From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-vk1-f178.google.com (mail-vk1-f178.google.com [209.85.221.178]) by mx.groups.io with SMTP id smtpd.web10.4777.1660924581504960059 for ; Fri, 19 Aug 2022 08:56:22 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@gmail.com header.s=20210112 header.b=OMLU4/kb; spf=pass (domain: gmail.com, ip: 209.85.221.178, mailfrom: pedro.falcato@gmail.com) Received: by mail-vk1-f178.google.com with SMTP id j11so2432871vkk.11 for ; Fri, 19 Aug 2022 08:56:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc; bh=vCJDZa8Y/doQ6yEPPezxb49xkMWJ8fZNeQgzeUlmHtQ=; b=OMLU4/kbXg5pY/nvD5d9bE+fseGzn8l0+axeILazP38F0aOPaVmq0rZ05nCjM/k4GH R2gkjxfq3QYjgBXOvk2IGQltEXx9V+rLnAFirdI1A2lSo1N4e2UBVTqNyHJ0LwsEPvse f96IjLIyO9Jsqte1iZMtbyo0Z6VPa5izTQoVbCw0IgxnJk5AZVLJt1gxtDjd0FgJWUhW O3hNIlr6RrgSDiW7LsC5u2B3HMx8naN1MCQCd8QbJNm0zuSoXgLCMJd1nln6thMm/bdQ /ihvs2mXKmg1zyqtRCr+vupfZoynuSF9swIO58P7EQ8H/j5TsKyEhEUIlGGs0v7VbGK7 Vgjg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc; bh=vCJDZa8Y/doQ6yEPPezxb49xkMWJ8fZNeQgzeUlmHtQ=; b=hWFFR4mWAIa+sk5u6MfCaf+m46QzpFV67/m99KMsjmeQLXdUl6EKBy9gZzm63zsxPo zZFaWk8SuRElJobwZBfsi/fFLehIQSd7IQ04cMcjdqEw2HziIssN2AnlKEIEgXVJlba7 B6lw4ezDFpZQCXrYQAXH4XiWduQ0xF2NkdRHAZSTdBJAKudlXjtRfBiUE05HXyHCPaHz w/XBbcoksQIZNgWQtR9RuAhz05EJTstpvdrxxR54ZhnAfA1RvJNOPDkJU3qVMOc1LJPN vdL6lr+9Hv28SX65gFk5qpq3C3PAGMLfEsdSO1TRVoL+O3Rr5Hvy8jSHNGOgLCIb81q0 IgbQ== X-Gm-Message-State: ACgBeo3zrFdI6JYSNB8P3Qd7BXmtyvgqpESU3iMAw4U3xJFouWBCOPYN zhFTvO7U+cBtQxr4Z2D7fKleVZTeiCcPk0coBs/svp/OYHo= X-Google-Smtp-Source: AA6agR7LWHAw4F6734xJi+REvqV9fl/ZtnRJc5Hp2OrozPKCtCT2/6HY1PLYmE74qYmqqAB8O7/gqmiuXeep38OzGoo= X-Received: by 2002:a1f:2b47:0:b0:380:59c5:8b8f with SMTP id r68-20020a1f2b47000000b0038059c58b8fmr3397574vkr.20.1660924579772; Fri, 19 Aug 2022 08:56:19 -0700 (PDT) MIME-Version: 1.0 References: <20220819091703.247-1-richardho@ami.com> In-Reply-To: From: "Pedro Falcato" Date: Fri, 19 Aug 2022 16:56:05 +0100 Message-ID: Subject: Re: [edk2-devel] [PATCH] UsbNetworkPkg: add USB network devices support To: edk2-devel-groups-io , richardho@ami.com Cc: =?UTF-8?B?VG9ueUxvIFvnvoXph5Hmnb5d?= Content-Type: multipart/alternative; boundary="000000000000937e2e05e69a233a" --000000000000937e2e05e69a233a Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Also, I forgot, but you should CC the EDK2 stewards (they're the ones that are going to add the Reviewed-by:). On Fri, Aug 19, 2022 at 4:54 PM Pedro Falcato wrote: > Hi Richard, > > What license is this code under? "Subject to AMI licensing agreement." > does not sound like a valid OSS license. > > Thanks, > Pedro > > On Fri, Aug 19, 2022 at 10:32 AM RichardHo [=E4=BD=95=E6=98=8E=E5=BF=A0] = via groups.io ami.com@groups.io> wrote: > >> UsbNetworkPkg provides network functions for USB ACM, USB NCM, >> and USB RNDIS network device. >> >> Signed-off-by: Richard Ho >> Reviewed-by: Tony Lo >> --- >> UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc | 9 + >> .../Config/UsbNetworkPkgComponentsDxe.inc.dsc | 20 + >> .../Config/UsbNetworkPkgComponentsDxe.inc.fdf | 21 + >> .../Config/UsbNetworkPkgDefines.inc.dsc | 23 + >> .../Include/Protocol/UsbEthernetProtocol.h | 872 +++++++++ >> UsbNetworkPkg/NetworkCommon/ComponentName.c | 264 +++ >> UsbNetworkPkg/NetworkCommon/DriverBinding.c | 583 ++++++ >> UsbNetworkPkg/NetworkCommon/DriverBinding.h | 263 +++ >> UsbNetworkPkg/NetworkCommon/NetworkCommon.inf | 43 + >> UsbNetworkPkg/NetworkCommon/PxeFunction.c | 1734 +++++++++++++++++ >> UsbNetworkPkg/ReadMe.md | 65 + >> UsbNetworkPkg/ReleaseNotes.md | 11 + >> UsbNetworkPkg/UsbCdcEcm/ComponentName.c | 170 ++ >> UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.c | 504 +++++ >> UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.h | 211 ++ >> UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf | 41 + >> UsbNetworkPkg/UsbCdcEcm/UsbEcmFunction.c | 861 ++++++++ >> UsbNetworkPkg/UsbCdcNcm/ComponentName.c | 170 ++ >> UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.c | 508 +++++ >> UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.h | 245 +++ >> UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf | 41 + >> UsbNetworkPkg/UsbCdcNcm/UsbNcmFunction.c | 946 +++++++++ >> UsbNetworkPkg/UsbNetworkPkg.dec | 32 + >> UsbNetworkPkg/UsbRndis/ComponentName.c | 172 ++ >> UsbNetworkPkg/UsbRndis/UsbRndis.c | 848 ++++++++ >> UsbNetworkPkg/UsbRndis/UsbRndis.h | 569 ++++++ >> UsbNetworkPkg/UsbRndis/UsbRndis.inf | 41 + >> UsbNetworkPkg/UsbRndis/UsbRndisFunction.c | 1587 +++++++++++++++ >> 28 files changed, 10854 insertions(+) >> create mode 100644 UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc >> create mode 100644 >> UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc >> create mode 100644 >> UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf >> create mode 100644 UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc >> create mode 100644 UsbNetworkPkg/Include/Protocol/UsbEthernetProtocol.h >> create mode 100644 UsbNetworkPkg/NetworkCommon/ComponentName.c >> create mode 100644 UsbNetworkPkg/NetworkCommon/DriverBinding.c >> create mode 100644 UsbNetworkPkg/NetworkCommon/DriverBinding.h >> create mode 100644 UsbNetworkPkg/NetworkCommon/NetworkCommon.inf >> create mode 100644 UsbNetworkPkg/NetworkCommon/PxeFunction.c >> create mode 100644 UsbNetworkPkg/ReadMe.md >> create mode 100644 UsbNetworkPkg/ReleaseNotes.md >> create mode 100644 UsbNetworkPkg/UsbCdcEcm/ComponentName.c >> create mode 100644 UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.c >> create mode 100644 UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.h >> create mode 100644 UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf >> create mode 100644 UsbNetworkPkg/UsbCdcEcm/UsbEcmFunction.c >> create mode 100644 UsbNetworkPkg/UsbCdcNcm/ComponentName.c >> create mode 100644 UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.c >> create mode 100644 UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.h >> create mode 100644 UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf >> create mode 100644 UsbNetworkPkg/UsbCdcNcm/UsbNcmFunction.c >> create mode 100644 UsbNetworkPkg/UsbNetworkPkg.dec >> create mode 100644 UsbNetworkPkg/UsbRndis/ComponentName.c >> create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndis.c >> create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndis.h >> create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndis.inf >> create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndisFunction.c >> >> diff --git a/UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc >> b/UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc >> new file mode 100644 >> index 0000000000..504680bc4b >> --- /dev/null >> +++ b/UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc >> @@ -0,0 +1,9 @@ >> +## @file >> +# Global DSC definitions to be included into project DSC file. >> +# >> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> +# Subject to AMI licensing agreement. >> +## >> + >> +[Components.X64] >> +!include UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc >> diff --git a/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc >> b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc >> new file mode 100644 >> index 0000000000..ae2727b68c >> --- /dev/null >> +++ b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc >> @@ -0,0 +1,20 @@ >> +## @file >> +# List of Core Components. >> +# >> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> +# Subject to AMI licensing agreement. >> +## >> + >> + UsbNetworkPkg/NetworkCommon/NetworkCommon.inf >> + >> +!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport >> + UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf >> +!endif >> + >> +!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport >> + UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf >> +!endif >> + >> +!if gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport >> + UsbNetworkPkg/UsbRndis/UsbRndis.inf >> +!endif >> diff --git a/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf >> b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf >> new file mode 100644 >> index 0000000000..6a611e359c >> --- /dev/null >> +++ b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf >> @@ -0,0 +1,21 @@ >> +## @file >> +# List of Core Components. >> +# >> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> +# Subject to AMI licensing agreement. >> +## >> + >> + INF UsbNetworkPkg/NetworkCommon/NetworkCommon.inf >> + >> +!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport >> + INF UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf >> +!endif >> + >> +!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport >> + INF UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf >> +!endif >> + >> +!if gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport >> + INF UsbNetworkPkg/UsbRndis/UsbRndis.inf >> +!endif >> + >> \ No newline at end of file >> diff --git a/UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc >> b/UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc >> new file mode 100644 >> index 0000000000..ef663bf253 >> --- /dev/null >> +++ b/UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc >> @@ -0,0 +1,23 @@ >> +## @file >> +# Global switches enable/disable project features. >> +# >> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> +# Subject to AMI licensing agreement. >> +## >> + >> +[Defines] >> +!if "IA32" in $(ARCH) && "X64" in $(ARCH) >> + DEFINE PEI=3DIA32 >> + DEFINE DXE=3DX64 >> +!else >> + DEFINE PEI=3DCOMMON >> + DEFINE DXE=3DCOMMON >> +!endif >> + >> +[Packages] >> + UsbNetworkPkg/UsbNetworkPkg.dec >> + >> +[PcdsFeatureFlag] >> + gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport|FALSE >> + gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport|FALSE >> + gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport|TRUE >> diff --git a/UsbNetworkPkg/Include/Protocol/UsbEthernetProtocol.h >> b/UsbNetworkPkg/Include/Protocol/UsbEthernetProtocol.h >> new file mode 100644 >> index 0000000000..d60e83f723 >> --- /dev/null >> +++ b/UsbNetworkPkg/Include/Protocol/UsbEthernetProtocol.h >> @@ -0,0 +1,872 @@ >> +/** @file >> >> + Header file contains code for USB Ethernet Protocol >> >> + definitions >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#ifndef _USB_ETHERNET_PROTOCOL_H >> >> +#define _USB_ETHERNET_PROTOCOL_H >> >> + >> >> +#define USB_ETHERNET_PROTOCOL_GUID \ >> >> + {0x8d8969cc, 0xfeb0, 0x4303, {0xb2, 0x1a, 0x1f, 0x11, 0x6f, 0x38, >> 0x56, 0x43}} >> >> + >> >> +typedef struct _USB_ETHERNET_PROTOCOL USB_ETHERNET_PROTOCOL; >> >> + >> >> +#define USB_CDC_CLASS 0x02 >> >> +#define USB_CDC_ACM_SUBCLASS 0x02 >> >> +#define USB_CDC_ECM_SUBCLASS 0x06 >> >> +#define USB_CDC_NCM_SUBCLASS 0x0D >> >> +#define USB_CDC_DATA_CLASS 0x0A >> >> +#define USB_CDC_DATA_SUBCLASS 0x00 >> >> +#define USB_NO_CLASS_PROTOCOL 0x00 >> >> +#define USB_NCM_NTB_PROTOCOL 0x01 >> >> +#define USB_VENDOR_PROTOCOL 0xFF >> >> + >> >> +// Type Values for the DescriptorType Field >> >> +#define CS_INTERFACE 0x24 >> >> +#define CS_ENDPOINT 0x25 >> >> + >> >> +// Descriptor SubType in Functional Descriptors >> >> +#define HEADER_FUN_DESCRIPTOR 0x00 >> >> +#define UNION_FUN_DESCRIPTOR 0x06 >> >> +#define ETHERNET_FUN_DESCRIPTOR 0x0F >> >> + >> >> +#define MAX_LAN_INTERFACE 0x10 >> >> + >> >> +// Table 20: Class-Specific Notification Codes >> >> +#define USB_CDC_NETWORK_CONNECTION 0x00 >> >> + >> >> +// 6.3.1 NetworkConnection >> >> +#define NETWORK_CONNECTED 0x01 >> >> +#define NETWORK_DISCONNECT 0x00 >> >> + >> >> +// USB Header functional Descriptor >> >> +typedef struct { >> >> + UINT8 FunctionLength; >> >> + UINT8 DescriptorType; >> >> + UINT8 DescriptorSubtype; >> >> + UINT16 BcdCdc; >> >> +} USB_HEADER_FUN_DESCRIPTOR; >> >> + >> >> +// USB Union Functional Descriptor >> >> +typedef struct { >> >> + UINT8 FunctionLength; >> >> + UINT8 DescriptorType; >> >> + UINT8 DescriptorSubtype; >> >> + UINT8 MasterInterface; >> >> + UINT8 SlaveInterface; >> >> +} USB_UNION_FUN_DESCRIPTOR; >> >> + >> >> +// USB Ethernet Functional Descriptor >> >> +typedef struct { >> >> + UINT8 FunctionLength; >> >> + UINT8 DescriptorType; >> >> + UINT8 DescriptorSubtype; >> >> + UINT8 MacAddress; >> >> + UINT32 EthernetStatistics; >> >> + UINT16 MaxSegmentSize; >> >> + UINT16 NumberMcFilters; >> >> + UINT8 NumberPowerFilters; >> >> +} USB_ETHERNET_FUN_DESCRIPTOR; >> >> + >> >> +typedef struct { >> >> + UINT32 UsBitRate; >> >> + UINT32 DsBitRate; >> >> +} USB_CONNECT_SPEED_CHANGE; >> >> + >> >> +// Request Type Codes for USB Ethernet >> >> +#define USB_ETHERNET_GET_REQ_TYPE 0xA1 >> >> +#define USB_ETHRTNET_SET_REQ_TYPE 0x21 >> >> + >> >> +// Class-Specific Request Codes for Ethernet subclass >> >> +// USB ECM 1.2 specification, Section 6.2 >> >> +#define SET_ETH_MULTICAST_FILTERS_REQ 0x40 >> >> +#define SET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ 0x41 >> >> +#define GET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ 0x42 >> >> +#define SET_ETH_PACKET_FILTER_REQ 0x43 >> >> +#define GET_ETH_STATISTIC_REQ 0x44 >> >> + >> >> +// USB ECM command request length >> >> +#define USB_ETH_POWER_FILTER_LENGTH 2 // Section 6.2.3 >> >> +#define USB_ETH_PACKET_FILTER_LENGTH 0 // Section 6.2.4 >> >> +#define USB_ETH_STATISTIC 4 // Section 6.2.5 >> >> + >> >> +// USB Ethernet Packet Filter Bitmap >> >> +// USB ECM 1.2 specification, Section 6.2.4 >> >> +#define USB_ETH_PACKET_TYPE_PROMISCUOUS BIT0 >> >> +#define USB_ETH_PACKET_TYPE_ALL_MULTICAST BIT1 >> >> +#define USB_ETH_PACKET_TYPE_DIRECTED BIT2 >> >> +#define USB_ETH_PACKET_TYPE_BROADCAST BIT3 >> >> +#define USB_ETH_PACKET_TYPE_MULTICAST BIT4 >> >> + >> >> +// USB Ethernet Statistics Feature Selector Codes >> >> +// USB ECM 1.2 specification, Section 6.2.5 >> >> +#define USB_ETH_XMIT_OK 0x01 >> >> +#define USB_ETH_RCV_OK 0x02 >> >> +#define USB_ETH_XMIT_ERROR 0x03 >> >> +#define USB_ETH_RCV_ERROR 0x04 >> >> +#define USB_ETH_RCV_NO_BUFFER 0x05 >> >> +#define USB_ETH_DIRECTED_BYTES_XMIT 0x06 >> >> +#define USB_ETH_DIRECTED_FRAMES_XMIT 0x07 >> >> +#define USB_ETH_MULTICAST_BYTES_XMIT 0x08 >> >> +#define USB_ETH_MULTICAST_FRAMES_XMIT 0x09 >> >> +#define USB_ETH_BROADCAST_BYTES_XMIT 0x0A >> >> +#define USB_ETH_BROADCAST_FRAMES_XMIT 0x0B >> >> +#define USB_ETH_DIRECTED_BYTES_RCV 0x0C >> >> +#define USB_ETH_DIRECTED_FRAMES_RCV 0x0D >> >> +#define USB_ETH_MULTICAST_BYTES_RCV 0x0E >> >> +#define USB_ETH_MULTICAST_FRAMES_RCV 0x0F >> >> +#define USB_ETH_BROADCAST_BYTES_RCV 0x10 >> >> +#define USB_ETH_BROADCAST_FRAMES_RCV 0x11 >> >> +#define USB_ETH_RCV_CRC_ERROR 0x12 >> >> +#define USB_ETH_TRANSMIT_QUEUE_LENGTH 0x13 >> >> +#define USB_ETH_RCV_ERROR_ALIGNMENT 0x14 >> >> +#define USB_ETH_XMIT_ONE_COLLISION 0x15 >> >> +#define USB_ETH_XMIT_MORE_COLLISIONS 0x16 >> >> +#define USB_ETH_XMIT_DEFERRED 0x17 >> >> +#define USB_ETH_XMIT_MAX_COLLISIONS 0x18 >> >> +#define USB_ETH_RCV_OVERRUN 0x19 >> >> +#define USB_ETH_XMIT_UNDERRUN 0x1A >> >> +#define USB_ETH_XMIT_HEARTBEAT_FAILURE 0x1B >> >> +#define USB_ETH_XMIT_TIMES_CRS_LOST 0x1C >> >> +#define USB_ETH_XMIT_LATE_COLLISIONS 0x1D >> >> + >> >> +// NIC Information >> >> +typedef struct { >> >> + UINT32 Signature; >> >> + USB_ETHERNET_PROTOCOL *UsbEth; >> >> + UINT16 InterrupOpFlag; >> >> + UINT64 MappedAddr; >> >> + PXE_MAC_ADDR McastList[MAX_MCAST_ADDRESS_CNT]; >> >> + UINT8 McastCount; >> >> + UINT64 MediaHeader[MAX_XMIT_BUFFERS]; >> >> + UINT8 TxBufferCount; >> >> + UINT16 State; >> >> + BOOLEAN CanTransmit; >> >> + BOOLEAN CanReceive; >> >> + UINT16 ReceiveStatus; >> >> + UINT8 RxFilter; >> >> + UINT32 RxFrame; >> >> + UINT32 TxFrame; >> >> + UINT16 NetworkConnect; >> >> + UINT8 CableDetect; >> >> + UINT16 MaxSegmentSize; >> >> + EFI_MAC_ADDRESS MacAddr; >> >> + PXE_CPB_START_31 PxeStart; >> >> + PXE_CPB_INITIALIZE PxeInit; >> >> + UINT8 PermNodeAddress[PXE_MAC_LENGTH]; >> >> + UINT8 CurrentNodeAddress[PXE_MAC_LENGTH]; >> >> + UINT8 BroadcastNodeAddress[PXE_MAC_LENGTH]; >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> +} NIC_DATA; >> >> + >> >> +#define NIC_DATA_SIGNATURE SIGNATURE_32('n', 'i', 'c', 'd') >> >> +#define NIC_DATA_FROM_USB_ETHERNET_PROTOCOL(a) CR (a, NIC_DATA, UsbEth= , >> NIC_DATA_SIGNATURE) >> >> + >> >> +/** >> >> + This command is used to determine the operational state of the UNDI. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_GET_STATE)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command is used to change the UNDI operational state from stoppe= d >> to started. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_START)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command is used to change the UNDI operational state from starte= d >> to stopped. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_STOP)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command is used to retrieve initialization information that is >> >> + needed by drivers and applications to initialized UNDI. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_GET_INIT_INFO)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command is used to retrieve configuration information about >> >> + the NIC being controlled by the UNDI. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_GET_CONFIG_INFO)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command resets the network adapter and initializes UNDI using >> >> + the parameters supplied in the CPB. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_INITIALIZE)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command resets the network adapter and reinitializes the UNDI >> >> + with the same parameters provided in the Initialize command. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_RESET)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + The Shutdown command resets the network adapter and leaves it in a >> >> + safe state for another driver to initialize. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_SHUTDOWN)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + The Interrupt Enables command can be used to read and/or change >> >> + the current external interrupt enable settings. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_INTERRUPT_ENABLE)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command is used to read and change receive filters and, >> >> + if supported, read and change the multicast MAC address filter list. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_RECEIVE_FILTER)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command is used to get current station and broadcast MAC address= es >> >> + and, if supported, to change the current station MAC address. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_STATION_ADDRESS)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command is used to read and clear the NIC traffic statistics. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_STATISTICS)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + Translate a multicast IPv4 or IPv6 address to a multicast MAC address= . >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_MCAST_IPTOMAC)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command is used to read and write (if supported by NIC H/W) >> >> + nonvolatile storage on the NIC. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_NV_DATA)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command returns the current interrupt status and/or the >> >> + transmitted buffer addresses and the current media status. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_GET_STATUS)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command is used to fill the media header(s) in transmit packet(s= ). >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_FILL_HEADER)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + The Transmit command is used to place a packet into the transmit queu= e. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_TRANSMIT)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + When the network adapter has received a frame, this command is used >> >> + to copy the frame into driver/application storage. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_RECEIVE)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command resets the network adapter and initializes UNDI using >> >> + the parameters supplied in the CPB. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in, out] Nic A pointer to the Network interface controller >> data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_INITIALIZE)( >> >> + IN PXE_CDB *Cdb, >> >> + IN OUT NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command is used to read and clear the NIC traffic statistics. >> >> + >> >> + @param[in] Nic A pointer to the Network interface controller dat= a. >> >> + @param[in] DbAddr Data Block Address. >> >> + @param[in] DbSize Data Block Size. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_STATISTICS)( >> >> + IN NIC_DATA *Nic, >> >> + IN UINT64 DbAddr, >> >> + IN UINT16 DbSize >> >> + ); >> >> + >> >> +/** >> >> + This function is used to manage a USB device with the bulk transfer >> pipe. The endpoint is Bulk in. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor >> block. >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in, out] Packet A pointer to the buffer of data that >> will be transmitted to USB >> >> + device or received from USB device. >> >> + @param[in, out] PacketLength A pointer to the PacketLength. >> >> + >> >> + @retval EFI_SUCCESS The bulk transfer has been successfully >> executed. >> >> + @retval EFI_DEVICE_ERROR The transfer failed. The transfer statu= s >> is returned in status. >> >> + @retval EFI_INVALID_PARAMETE One or more parameters are invalid. >> >> + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due >> to a lack of resources. >> >> + @retval EFI_TIMEOUT The control transfer fails due to >> timeout. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_RECEIVE)( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN OUT VOID *Packet, >> >> + IN OUT UINTN *PacketLength >> >> + ); >> >> + >> >> +/** >> >> + This function is used to manage a USB device with the bulk transfer >> pipe. The endpoint is Bulk out. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor >> block. >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in, out] Packet A pointer to the buffer of data that >> will be transmitted to USB >> >> + device or received from USB device. >> >> + @param[in, out] PacketLength A pointer to the PacketLength. >> >> + >> >> + @retval EFI_SUCCESS The bulk transfer has been successfully >> executed. >> >> + @retval EFI_DEVICE_ERROR The transfer failed. The transfer statu= s >> is returned in status. >> >> + @retval EFI_INVALID_PARAMETE One or more parameters are invalid. >> >> + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due >> to a lack of resources. >> >> + @retval EFI_TIMEOUT The control transfer fails due to >> timeout. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_TRANSMIT)( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN OUT VOID *Packet, >> >> + IN OUT UINTN *PacketLength >> >> + ); >> >> + >> >> +/** >> >> + This function is used to manage a USB device with an interrupt >> transfer pipe. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in] IsNewTransfer If TRUE, a new transfer will be >> submitted to USB controller. If >> >> + FALSE, the interrupt transfer is delete= d >> from the device's interrupt >> >> + transfer queue. >> >> + @param[in] PollingInterval Indicates the periodic rate, in >> milliseconds, that the transfer is to be >> >> + executed.This parameter is required whe= n >> IsNewTransfer is TRUE. The >> >> + value must be between 1 to 255, >> otherwise EFI_INVALID_PARAMETER is returned. >> >> + The units are in milliseconds. >> >> + @param[in] Request A pointer to the EFI_USB_DEVICE_REQUEST >> data. >> >> + >> >> + @retval EFI_SUCCESS The asynchronous USB transfer request >> transfer has been successfully executed. >> >> + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request >> failed. >> >> + >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_INTERRUPT)( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN BOOLEAN IsNewTransfer, >> >> + IN UINTN PollingInterval, >> >> + IN EFI_USB_DEVICE_REQUEST *Request >> >> + ); >> >> + >> >> +/** >> >> + Retrieves the USB Ethernet Mac Address. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[out] MacAddress A pointer to the caller allocated USB >> Ethernet Mac Address. >> >> + >> >> + @retval EFI_SUCCESS The USB Header Functional descriptor wa= s >> retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor wa= s >> not found. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_GET_ETH_MAC_ADDRESS)( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT EFI_MAC_ADDRESS *MacAddress >> >> + ); >> >> + >> >> +/** >> >> + Retrieves the USB Ethernet Bulk transfer data size. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[out] BulkSize A pointer to the Bulk transfer data size. >> >> + >> >> + @retval EFI_SUCCESS The USB Header Functional descriptor wa= s >> retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor wa= s >> not found. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETH_MAX_BULK_SIZE)( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT UINTN *BulkSize >> >> + ); >> >> + >> >> +/** >> >> + Retrieves the USB Header functional Descriptor. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[out] UsbHeaderFunDescriptor A pointer to the caller allocated >> USB Header Functional Descriptor. >> >> + >> >> + @retval EFI_SUCCESS The USB Header Functional descriptor wa= s >> retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor wa= s >> not found. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_HEADER_FUNCTIONAL_DESCRIPTOR)( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor >> >> + ); >> >> + >> >> +/** >> >> + Retrieves the USB Union functional Descriptor. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[out] UsbUnionFunDescriptor A pointer to the caller allocated >> USB Union Functional Descriptor. >> >> + >> >> + @retval EFI_SUCCESS The USB Union Functional descriptor was >> retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbUnionFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Union Functional descriptor was >> not found. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_UNION_FUNCTIONAL_DESCRIPTOR)( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor >> >> + ); >> >> + >> >> +/** >> >> + Retrieves the USB Ethernet functional Descriptor. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[out] UsbEthFunDescriptor A pointer to the caller allocated >> USB Ethernet Functional Descriptor. >> >> + >> >> + @retval EFI_SUCCESS The USB Ethernet Functional descriptor >> was retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbEthFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Ethernet Functional descriptor >> was not found. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_FUNCTIONAL_DESCRIPTOR)( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor >> >> + ); >> >> + >> >> +/** >> >> + This request sets the Ethernet device multicast filters as specified >> in the >> >> + sequential list of 48 bit Ethernet multicast addresses. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] Value Number of filters. >> >> + @param[in] McastAddr A pointer to the value of the >> multicast addresses. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_SET_ETH_MULTICAST_FILTERS)( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN VOID *McastAddr >> >> + ); >> >> + >> >> +/** >> >> + This request sets up the specified Ethernet power management pattern >> filter as >> >> + described in the data structure. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] Value Number of filters. >> >> + @param[in] Length Size of the power management >> pattern filter data. >> >> + @param[in] PatternFilter A pointer to the power management >> pattern filter structure. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_SET_ETH_POWER_MANAGE_PATTERN_FILTER)( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN UINT16 Length, >> >> + IN VOID *PatternFilter >> >> + ); >> >> + >> >> +/** >> >> + This request retrieves the status of the specified Ethernet power >> management >> >> + pattern filter from the device. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] Value The filter number. >> >> + @param[out] PatternActive A pointer to the pattern active >> boolean. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_GET_ETH_POWER_MANAGE_PATTERN_FILTER)( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + OUT BOOLEAN *PatternActive >> >> + ); >> >> + >> >> +/** >> >> + This request is used to configure device Ethernet packet filter >> settings. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in] Value Packet Filter Bitmap. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_SET_ETH_PACKET_FILTER)( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value >> >> + ); >> >> + >> >> +/** >> >> + This request is used to retrieve a statistic based on the feature >> selector. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] FeatureSelector Value of the feature selector. >> >> + @param[out] Statistic A pointer to the 32 bit unsigned >> integer. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_GET_ETH_STATISTIC)( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 FeatureSelector, >> >> + OUT VOID *Statistic >> >> + ); >> >> + >> >> +typedef struct { >> >> + USB_ETHERNET_UNDI_GET_STATE UsbEthUndiGetState; >> >> + USB_ETHERNET_UNDI_START UsbEthUndiStart; >> >> + USB_ETHERNET_UNDI_STOP UsbEthUndiStop; >> >> + USB_ETHERNET_UNDI_GET_INIT_INFO UsbEthUndiGetInitInfo; >> >> + USB_ETHERNET_UNDI_GET_CONFIG_INFO UsbEthUndiGetConfigInfo; >> >> + USB_ETHERNET_UNDI_INITIALIZE UsbEthUndiInitialize; >> >> + USB_ETHERNET_UNDI_RESET UsbEthUndiReset; >> >> + USB_ETHERNET_UNDI_SHUTDOWN UsbEthUndiShutdown; >> >> + USB_ETHERNET_UNDI_INTERRUPT_ENABLE UsbEthUndiInterruptEnable; >> >> + USB_ETHERNET_UNDI_RECEIVE_FILTER UsbEthUndiReceiveFilter; >> >> + USB_ETHERNET_UNDI_STATION_ADDRESS UsbEthUndiStationAddress; >> >> + USB_ETHERNET_UNDI_STATISTICS UsbEthUndiStatistics; >> >> + USB_ETHERNET_UNDI_MCAST_IPTOMAC UsbEthUndiMcastIp2Mac; >> >> + USB_ETHERNET_UNDI_NV_DATA UsbEthUndiNvData; >> >> + USB_ETHERNET_UNDI_GET_STATUS UsbEthUndiGetStatus; >> >> + USB_ETHERNET_UNDI_FILL_HEADER UsbEthUndiFillHeader; >> >> + USB_ETHERNET_UNDI_TRANSMIT UsbEthUndiTransmit; >> >> + USB_ETHERNET_UNDI_RECEIVE UsbEthUndiReceive; >> >> +} USB_ETHERNET_UNDI; >> >> + >> >> +// The USB_ETHERNET_PROTOCOL provides some basic USB Ethernet device >> relevant >> >> +// descriptor and specific requests. >> >> +struct _USB_ETHERNET_PROTOCOL { >> >> + USB_ETHERNET_UNDI UsbEthUndi; >> >> + // for calling the UNDI child functions >> >> + USB_ETHERNET_INITIALIZE UsbEthInitialize; >> >> + USB_ETHERNET_STATISTICS UsbEthStatistics; >> >> + USB_ETHERNET_RECEIVE UsbEthReceive; >> >> + USB_ETHERNET_TRANSMIT UsbEthTransmit; >> >> + USB_ETHERNET_INTERRUPT UsbEthInterrupt; >> >> + USB_GET_ETH_MAC_ADDRESS UsbEthMacAddress; >> >> + USB_ETH_MAX_BULK_SIZE UsbEthMaxBulkSize= ; >> >> + USB_HEADER_FUNCTIONAL_DESCRIPTOR >> UsbHeaderFunDescriptor; >> >> + USB_UNION_FUNCTIONAL_DESCRIPTOR >> UsbUnionFunDescriptor; >> >> + USB_ETHERNET_FUNCTIONAL_DESCRIPTOR >> UsbEthFunDescriptor; >> >> + USB_ETHERNET_SET_ETH_MULTICAST_FILTERS >> SetUsbEthMcastFilter; >> >> + USB_ETHERNET_SET_ETH_POWER_MANAGE_PATTERN_FILTER >> SetUsbEthPowerPatternFilter; >> >> + USB_ETHERNET_GET_ETH_POWER_MANAGE_PATTERN_FILTER >> GetUsbEthPoewrPatternFilter; >> >> + USB_ETHERNET_SET_ETH_PACKET_FILTER >> SetUsbEthPacketFilter; >> >> + USB_ETHERNET_GET_ETH_STATISTIC GetUsbEthStatisti= c; >> >> +}; >> >> + >> >> +#endif >> >> diff --git a/UsbNetworkPkg/NetworkCommon/ComponentName.c >> b/UsbNetworkPkg/NetworkCommon/ComponentName.c >> new file mode 100644 >> index 0000000000..2697bf5083 >> --- /dev/null >> +++ b/UsbNetworkPkg/NetworkCommon/ComponentName.c >> @@ -0,0 +1,264 @@ >> +/** @file >> >> + This file contains code for USB network common driver >> >> + component name definitions >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#include "DriverBinding.h" >> >> + >> >> +extern EFI_DRIVER_BINDING_PROTOCOL gNetworkCommonDriverBinding; >> >> +extern EFI_GUID gUsbEthProtocolGuid; >> >> + >> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE >> gNetworkCommonDriverNameTable[] =3D { >> >> + { >> >> + "eng;en", >> >> + L"Network Common Driver" >> >> + }, >> >> + { >> >> + NULL, >> >> + NULL >> >> + } >> >> +}; >> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE >> *gNetworkCommonControllerNameTable =3D NULL; >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +NetworkCommonComponentNameGetDriverName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **DriverName >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +NetworkCommonComponentNameGetControllerName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN EFI_HANDLE Controller, >> >> + IN EFI_HANDLE ChildHandle OPTIONAL, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **ControllerName >> >> + ); >> >> + >> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL >> gNetworkCommonComponentName =3D { >> >> + NetworkCommonComponentNameGetDriverName, >> >> + NetworkCommonComponentNameGetControllerName, >> >> + "eng" >> >> +}; >> >> + >> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL >> gNetworkCommonComponentName2 =3D { >> >> + >> (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)NetworkCommonComponentNameGetDriver= Name, >> >> + >> (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)NetworkCommonComponentNameGetCo= ntrollerName, >> >> + "en" >> >> +}; >> >> + >> >> +/** >> >> + Retrieves a Unicode string that is the user readable name of the >> driver. >> >> + >> >> + This function retrieves the user readable name of a driver in the for= m >> of a >> >> + Unicode string. If the driver specified by This has a user readable >> name in >> >> + the language specified by Language, then a pointer to the driver name >> is >> >> + returned in DriverName, and EFI_SUCCESS is returned. If the driver >> specified >> >> + by This does not support the language specified by Language, >> >> + then EFI_UNSUPPORTED is returned. >> >> + >> >> + @param[in] This A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >> >> + EFI_COMPONENT_NAME_PROTOCOL instance. >> >> + @param[in] Language A pointer to a Null-terminated ASCII >> string >> >> + array indicating the language. This is >> the >> >> + language of the driver name that the >> caller is >> >> + requesting, and it must match one of th= e >> >> + languages specified in >> SupportedLanguages. The >> >> + number of languages supported by a >> driver is up >> >> + to the driver writer. Language is >> specified >> >> + in RFC 4646 or ISO 639-2 language code >> format. >> >> + @param[out] DriverName A pointer to the Unicode string to >> return. >> >> + This Unicode string is the name of the >> >> + driver specified by This in the languag= e >> >> + specified by Language. >> >> + >> >> + @retval EFI_SUCCESS The Unicode string for the Driver >> specified by >> >> + This and the language specified by >> Language was >> >> + returned in DriverName. >> >> + @retval EFI_INVALID_PARAMETER Language is NULL. >> >> + @retval EFI_INVALID_PARAMETER DriverName is NULL. >> >> + @retval EFI_UNSUPPORTED The driver specified by This does not >> support >> >> + the language specified by Language. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +NetworkCommonComponentNameGetDriverName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **DriverName >> >> + ) >> >> +{ >> >> + return LookupUnicodeString2 ( >> >> + Language, >> >> + This->SupportedLanguages, >> >> + gNetworkCommonDriverNameTable, >> >> + DriverName, >> >> + (BOOLEAN)(This =3D=3D &gNetworkCommonComponentName) >> >> + ); >> >> +} >> >> + >> >> +/** >> >> + Retrieves a Unicode string that is the user readable name of the >> controller >> >> + that is being managed by a driver. >> >> + >> >> + This function retrieves the user readable name of the controller >> specified by >> >> + ControllerHandle and ChildHandle in the form of a Unicode string. If >> the >> >> + driver specified by This has a user readable name in the language >> specified by >> >> + Language, then a pointer to the controller name is returned in >> ControllerName, >> >> + and EFI_SUCCESS is returned. If the driver specified by This is not >> currently >> >> + managing the controller specified by ControllerHandle and ChildHandle= , >> >> + then EFI_UNSUPPORTED is returned. If the driver specified by This >> does not >> >> + support the language specified by Language, then EFI_UNSUPPORTED is >> returned. >> >> + >> >> + @param[in] This A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >> >> + EFI_COMPONENT_NAME_PROTOCOL instance. >> >> + @param[in] Controller The handle of a controller that the >> driver >> >> + specified by This is managing. This >> handle >> >> + specifies the controller whose name is >> to be >> >> + returned. >> >> + @param[in] ChildHandle The handle of the child controller to >> retrieve >> >> + the name of. This is an optional >> parameter that >> >> + may be NULL. It will be NULL for devic= e >> >> + drivers. It will also be NULL for a bu= s >> drivers >> >> + that wish to retrieve the name of the b= us >> >> + controller. It will not be NULL for a >> bus >> >> + driver that wishes to retrieve the name >> of a >> >> + child controller. >> >> + @param[in] Language A pointer to a Null-terminated ASCII >> string >> >> + array indicating the language. This is >> the >> >> + language of the driver name that the >> caller is >> >> + requesting, and it must match one of th= e >> >> + languages specified in >> SupportedLanguages. The >> >> + number of languages supported by a >> driver is up >> >> + to the driver writer. Language is >> specified in >> >> + RFC 4646 or ISO 639-2 language code >> format. >> >> + @param[out] ControllerName A pointer to the Unicode string to >> return. >> >> + This Unicode string is the name of the >> >> + controller specified by ControllerHandl= e >> and >> >> + ChildHandle in the language specified b= y >> >> + Language from the point of view of the >> driver >> >> + specified by This. >> >> + >> >> + @retval EFI_SUCCESS The Unicode string for the user readabl= e >> name in >> >> + the language specified by Language for >> the >> >> + driver specified by This was returned i= n >> >> + DriverName. >> >> + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid >> EFI_HANDLE. >> >> + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a >> valid >> >> + EFI_HANDLE. >> >> + @retval EFI_INVALID_PARAMETER Language is NULL. >> >> + @retval EFI_INVALID_PARAMETER ControllerName is NULL. >> >> + @retval EFI_UNSUPPORTED The driver specified by This is not >> currently >> >> + managing the controller specified by >> >> + ControllerHandle and ChildHandle. >> >> + @retval EFI_UNSUPPORTED The driver specified by This does not >> support >> >> + the language specified by Language. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +NetworkCommonComponentNameGetControllerName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN EFI_HANDLE Controller, >> >> + IN EFI_HANDLE ChildHandle OPTIONAL, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **ControllerName >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + CHAR16 *HandleName; >> >> + EFI_USB_IO_PROTOCOL *UsbIo =3D NULL; >> >> + EFI_USB_DEVICE_DESCRIPTOR DevDesc; >> >> + >> >> + if (!Language || !ControllerName) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + if (ChildHandle =3D=3D NULL) { >> >> + return EFI_UNSUPPORTED; >> >> + } >> >> + >> >> + // >> >> + // Make sure this driver is currently managing ControllerHandle >> >> + // >> >> + Status =3D EfiTestManagedDevice ( >> >> + Controller, >> >> + gNetworkCommonDriverBinding.DriverBindingHandle, >> >> + &gUsbEthProtocolGuid >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + // >> >> + // Make sure this driver produced ChildHandle >> >> + // >> >> + Status =3D EfiTestChildHandle ( >> >> + Controller, >> >> + ChildHandle, >> >> + &gUsbEthProtocolGuid >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status =3D gBS->HandleProtocol (Controller, &gEfiUsbIoProtocolGuid, >> (VOID **)&UsbIo); >> >> + >> >> + if (!EFI_ERROR (Status)) { >> >> + Status =3D UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status =3D UsbIo->UsbGetStringDescriptor (UsbIo, 0x409, >> DevDesc.StrManufacturer, &HandleName); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + *ControllerName =3D HandleName; >> >> + >> >> + if (gNetworkCommonControllerNameTable !=3D NULL) { >> >> + FreeUnicodeStringTable (gNetworkCommonControllerNameTable); >> >> + gNetworkCommonControllerNameTable =3D NULL; >> >> + } >> >> + >> >> + Status =3D AddUnicodeString2 ( >> >> + "eng", >> >> + gNetworkCommonComponentName.SupportedLanguages, >> >> + &gNetworkCommonControllerNameTable, >> >> + HandleName, >> >> + TRUE >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status =3D AddUnicodeString2 ( >> >> + "en", >> >> + gNetworkCommonComponentName2.SupportedLanguages, >> >> + &gNetworkCommonControllerNameTable, >> >> + HandleName, >> >> + FALSE >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + return LookupUnicodeString2 ( >> >> + Language, >> >> + This->SupportedLanguages, >> >> + gNetworkCommonControllerNameTable, >> >> + ControllerName, >> >> + (BOOLEAN)(This =3D=3D &gNetworkCommonComponentName) >> >> + ); >> >> + } >> >> + >> >> + return EFI_UNSUPPORTED; >> >> +} >> >> diff --git a/UsbNetworkPkg/NetworkCommon/DriverBinding.c >> b/UsbNetworkPkg/NetworkCommon/DriverBinding.c >> new file mode 100644 >> index 0000000000..18b2daa7a8 >> --- /dev/null >> +++ b/UsbNetworkPkg/NetworkCommon/DriverBinding.c >> @@ -0,0 +1,583 @@ >> +/** @file >> >> + This file contains code for USB network binding driver >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#include "DriverBinding.h" >> >> + >> >> +PXE_SW_UNDI *gPxe =3D NULL; >> >> +NIC_DEVICE *gLanDeviceList[MAX_LAN_INTERFACE]; >> >> + >> >> +EFI_GUID gUsbEthProtocolGuid =3D USB_ETHERNET_PROTOCOL_GUID; >> >> + >> >> +EFI_DRIVER_BINDING_PROTOCOL gNetworkCommonDriverBinding =3D { >> >> + NetworkCommonSupported, >> >> + NetworkCommonDriverStart, >> >> + NetworkCommonDriverStop, >> >> + NETWORK_COMMON_DRIVER_VERSION, >> >> + NULL, >> >> + NULL >> >> +}; >> >> + >> >> +/** >> >> + Create MAC Device Path >> >> + >> >> + @param[in, out] Dev A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> >> + @param[in] BaseDev A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> >> + @param[in] Nic A pointer to the Network interface >> controller data. >> >> + >> >> + @retval EFI_OUT_OF_RESOURCES The device path could not be created >> successfully due to a lack of resources. >> >> + @retval EFI_SUCCESS MAC device path created successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +CreateMacDevicePath ( >> >> + IN OUT EFI_DEVICE_PATH_PROTOCOL **Dev, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *BaseDev, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + MAC_ADDR_DEVICE_PATH MacAddrNode; >> >> + EFI_DEVICE_PATH_PROTOCOL *EndNode; >> >> + UINT8 *DevicePath; >> >> + UINT16 TotalLength; >> >> + UINT16 BaseLength; >> >> + >> >> + ZeroMem (&MacAddrNode, sizeof (MAC_ADDR_DEVICE_PATH)); >> >> + CopyMem (&MacAddrNode.MacAddress, &Nic->MacAddr, sizeof >> (EFI_MAC_ADDRESS)); >> >> + >> >> + MacAddrNode.Header.Type =3D MESSAGING_DEVICE_PATH; >> >> + MacAddrNode.Header.SubType =3D MSG_MAC_ADDR_DP; >> >> + MacAddrNode.Header.Length[0] =3D (UINT8)sizeof (MacAddrNode); >> >> + MacAddrNode.Header.Length[1] =3D 0; >> >> + >> >> + EndNode =3D BaseDev; >> >> + >> >> + while (!IsDevicePathEnd (EndNode)) { >> >> + EndNode =3D NextDevicePathNode (EndNode); >> >> + } >> >> + >> >> + BaseLength =3D (UINT16)((UINTN)(EndNode) - (UINTN)(BaseDev)); >> >> + TotalLength =3D (UINT16)(BaseLength + sizeof (MacAddrNode) + sizeof >> (EFI_DEVICE_PATH_PROTOCOL)); >> >> + >> >> + Status =3D gBS->AllocatePool (EfiBootServicesData, TotalLength, (VOID >> **)&DevicePath); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + *Dev =3D (EFI_DEVICE_PATH_PROTOCOL *)DevicePath; >> >> + CopyMem (DevicePath, (CHAR8 *)BaseDev, BaseLength); >> >> + DevicePath +=3D BaseLength; >> >> + CopyMem (DevicePath, (CHAR8 *)&MacAddrNode, sizeof (MacAddrNode)); >> >> + DevicePath +=3D sizeof (MacAddrNode); >> >> + CopyMem (DevicePath, (CHAR8 *)EndNode, sizeof >> (EFI_DEVICE_PATH_PROTOCOL)); >> >> + >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + Network Common Driver Binding Support. >> >> + >> >> + @param[in] This Protocol instance pointer. >> >> + @param[in] ControllerHandle Handle of device to test. >> >> + @param[in] RemainingDevicePath Optional parameter use to pick a >> specific child >> >> + device to start. >> >> + >> >> + @retval EFI_SUCCESS This driver supports this device. >> >> + @retval EFI_ALREADY_STARTED This driver is already running on >> this device. >> >> + @retval other This driver does not support this >> device. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +NetworkCommonSupported ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_PROTOCOL *UsbEth; >> >> + >> >> + Status =3D gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + (VOID **)&UsbEth, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Network Common Driver Binding Start. >> >> + >> >> + @param[in] This Protocol instance pointer. >> >> + @param[in] ControllerHandle Handle of device to bind driver t= o. >> >> + @param[in] RemainingDevicePath Optional parameter use to pick a >> specific child >> >> + device to start. >> >> + >> >> + @retval EFI_SUCCESS This driver is added to >> ControllerHandle >> >> + @retval EFI_DEVICE_ERROR This driver could not be started >> due to a device error >> >> + @retval EFI_OUT_OF_RESOURCES The driver could not install >> successfully due to a lack of resources. >> >> + @retval other This driver does not support this >> device >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +NetworkCommonDriverStart ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_DEVICE_PATH_PROTOCOL *UsbEthPath; >> >> + USB_ETHERNET_PROTOCOL *UsbEth; >> >> + EFI_MAC_ADDRESS MacAddress; >> >> + UINTN BulkDataSize; >> >> + NIC_DEVICE *NicDevice; >> >> + UINT8 *TmpPxePointer =3D NULL; >> >> + >> >> + Status =3D gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + (VOID **)&UsbEth, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status =3D gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + (VOID **)&UsbEthPath, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> >> + ); >> >> + >> >> + if (EFI_ERROR (Status)) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return Status; >> >> + } >> >> + >> >> + ZeroMem (&MacAddress, sizeof (EFI_MAC_ADDRESS)); >> >> + >> >> + Status =3D UsbEth->UsbEthMacAddress (UsbEth, &MacAddress); >> >> + ASSERT_EFI_ERROR (Status); >> >> + Status =3D UsbEth->UsbEthMaxBulkSize (UsbEth, &BulkDataSize); >> >> + >> >> + if (EFI_ERROR (Status)) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return Status; >> >> + } >> >> + >> >> + NicDevice =3D AllocateZeroPool (sizeof (NIC_DEVICE)); >> >> + if (!NicDevice) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return EFI_OUT_OF_RESOURCES; >> >> + } >> >> + >> >> + // for alignment adjustment >> >> + if (gPxe =3D=3D NULL) { >> >> + TmpPxePointer =3D AllocateZeroPool (sizeof (PXE_SW_UNDI) + 16); >> >> + if (!TmpPxePointer) { >> >> + if (NicDevice !=3D NULL) { >> >> + gBS->FreePool (NicDevice); >> >> + } >> >> + >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + >> >> + return EFI_OUT_OF_RESOURCES; >> >> + } else { >> >> + // check for paragraph alignment here >> >> + if (((UINTN)TmpPxePointer & 0x0F) !=3D 0) { >> >> + gPxe =3D (PXE_SW_UNDI *)(TmpPxePointer + 8); >> >> + } else { >> >> + gPxe =3D (PXE_SW_UNDI *)TmpPxePointer; >> >> + } >> >> + >> >> + if (!gPxe) { >> >> + if (NicDevice !=3D NULL) { >> >> + gBS->FreePool (NicDevice); >> >> + } >> >> + >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return EFI_OUT_OF_RESOURCES; >> >> + } >> >> + >> >> + PxeStructInit (gPxe); >> >> + } >> >> + } >> >> + >> >> + NicDevice->NiiProtocol.Id =3D (UINT64)(UINTN)(gPxe); >> >> + NicDevice->NiiProtocol.IfNum =3D gPxe->IFcnt | gPxe->IFcntExt << 8; >> >> + >> >> + UpdateNicNum (&NicDevice->NicInfo, gPxe); >> >> + >> >> + NicDevice->NicInfo.Signature =3D NIC_DATA_SIGNATURE; >> >> + >> >> + NicDevice->NicInfo.UsbEth =3D UsbEth; >> >> + NicDevice->NicInfo.MaxSegmentSize =3D (UINT16)BulkDataSize; >> >> + NicDevice->NicInfo.CableDetect =3D 0; >> >> + >> >> + CopyMem ((CHAR8 *)&(NicDevice->NicInfo.MacAddr), (CHAR8 *)&MacAddress= , >> sizeof (MacAddress)); >> >> + >> >> + NicDevice->NicInfo.TxBufferCount =3D 0; >> >> + >> >> + if (NicDevice->NiiProtocol.IfNum < MAX_LAN_INTERFACE) { >> >> + gLanDeviceList[NicDevice->NiiProtocol.IfNum] =3D NicDevice; >> >> + } else { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + >> >> + if (TmpPxePointer !=3D NULL) { >> >> + gBS->FreePool (TmpPxePointer); >> >> + } >> >> + >> >> + if (NicDevice !=3D NULL) { >> >> + gBS->FreePool (NicDevice); >> >> + } >> >> + >> >> + return EFI_DEVICE_ERROR; >> >> + } >> >> + >> >> + Status =3D CreateMacDevicePath ( >> >> + &NicDevice->DevPath, >> >> + UsbEthPath, >> >> + &NicDevice->NicInfo >> >> + ); >> >> + >> >> + if (EFI_ERROR (Status)) { >> >> + UpdateNicNum (NULL, gPxe); >> >> + if (TmpPxePointer !=3D NULL) { >> >> + gBS->FreePool (TmpPxePointer); >> >> + } >> >> + } >> >> + >> >> + NicDevice->Signature =3D UNDI_DEV_SIGNATURE; >> >> + NicDevice->NiiProtocol.Revision =3D >> EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION; >> >> + NicDevice->NiiProtocol.Type =3D EfiNetworkInterfaceUndi; >> >> + NicDevice->NiiProtocol.MajorVer =3D PXE_ROMID_MAJORVER; >> >> + NicDevice->NiiProtocol.MinorVer =3D PXE_ROMID_MINORVER; >> >> + NicDevice->NiiProtocol.ImageSize =3D 0; >> >> + NicDevice->NiiProtocol.ImageAddr =3D 0; >> >> + NicDevice->NiiProtocol.Ipv6Supported =3D TRUE; >> >> + >> >> + NicDevice->NiiProtocol.StringId[0] =3D 'U'; >> >> + NicDevice->NiiProtocol.StringId[1] =3D 'N'; >> >> + NicDevice->NiiProtocol.StringId[2] =3D 'D'; >> >> + NicDevice->NiiProtocol.StringId[3] =3D 'I'; >> >> + NicDevice->DeviceHandle =3D NULL; >> >> + >> >> + ZeroMem (&NicDevice->NicInfo.Request, sizeof (EFI_USB_DEVICE_REQUEST)= ); >> >> + >> >> + Status =3D UsbEth->UsbEthInterrupt (UsbEth, TRUE, >> NETWORK_COMMON_POLLING_INTERVAL, &NicDevice->NicInfo.Request); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status =3D gBS->InstallMultipleProtocolInterfaces ( >> >> + &NicDevice->DeviceHandle, >> >> + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, >> >> + &NicDevice->NiiProtocol, >> >> + &gEfiDevicePathProtocolGuid, >> >> + NicDevice->DevPath, >> >> + NULL >> >> + ); >> >> + >> >> + if (EFI_ERROR (Status)) { >> >> + if (NicDevice->NiiProtocol.IfNum < MAX_LAN_INTERFACE) { >> >> + gLanDeviceList[NicDevice->NiiProtocol.IfNum] =3D NULL; >> >> + } >> >> + >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + >> >> + if (TmpPxePointer !=3D NULL) { >> >> + gBS->FreePool (TmpPxePointer); >> >> + } >> >> + >> >> + if (NicDevice->DevPath !=3D NULL) { >> >> + gBS->FreePool (NicDevice->DevPath); >> >> + } >> >> + >> >> + if (NicDevice !=3D NULL) { >> >> + gBS->FreePool (NicDevice); >> >> + } >> >> + >> >> + return EFI_DEVICE_ERROR; >> >> + } >> >> + >> >> + Status =3D gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + (VOID **)&UsbEth, >> >> + This->DriverBindingHandle, >> >> + NicDevice->DeviceHandle, >> >> + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER >> >> + ); >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Network Common Driver Binding Stop. >> >> + >> >> + @param[in] This Protocol instance pointer. >> >> + @param[in] ControllerHandle Handle of device to stop driver on >> >> + @param[in] NumberOfChildren Number of Handles in >> ChildHandleBuffer. If number of >> >> + children is zero stop the entire bu= s >> driver. >> >> + @param[in] ChildHandleBuffer List of Child Handles to Stop. >> >> + >> >> + @retval EFI_SUCCESS This driver is removed >> ControllerHandle >> >> + @retval other This driver was not removed from >> this device >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +NetworkCommonDriverStop ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN UINTN NumberOfChildren, >> >> + IN EFI_HANDLE *ChildHandleBuffer >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + BOOLEAN AllChildrenStopped; >> >> + UINTN Index; >> >> + USB_ETHERNET_PROTOCOL *UsbEth; >> >> + NIC_DEVICE *NicDevice; >> >> + EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NiiProtocol; >> >> + >> >> + if (NumberOfChildren =3D=3D 0) { >> >> + Status =3D gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, >> >> + (VOID **)&NiiProtocol, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >> >> + ); >> >> + >> >> + if (EFI_ERROR (Status)) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return EFI_SUCCESS; >> >> + } >> >> + >> >> + NicDevice =3D UNDI_DEV_FROM_THIS (NiiProtocol); >> >> + Status =3D gBS->UninstallMultipleProtocolInterfaces ( >> >> + ControllerHandle, >> >> + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, >> >> + &NicDevice->NiiProtocol, >> >> + &gEfiDevicePathProtocolGuid, >> >> + NicDevice->DevPath, >> >> + NULL >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + gBS->FreePool (NicDevice->DevPath); >> >> + gBS->FreePool (NicDevice); >> >> + >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return EFI_SUCCESS; >> >> + } >> >> + >> >> + AllChildrenStopped =3D TRUE; >> >> + >> >> + for (Index =3D 0; Index < NumberOfChildren; Index++) { >> >> + Status =3D gBS->OpenProtocol ( >> >> + ChildHandleBuffer[Index], >> >> + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, >> >> + (VOID **)&NiiProtocol, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + AllChildrenStopped =3D FALSE; >> >> + continue; >> >> + } >> >> + >> >> + NicDevice =3D UNDI_DEV_FROM_THIS (NiiProtocol); >> >> + >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ChildHandleBuffer[Index] >> >> + ); >> >> + >> >> + Status =3D gBS->UninstallMultipleProtocolInterfaces ( >> >> + ChildHandleBuffer[Index], >> >> + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, >> >> + &NicDevice->NiiProtocol, >> >> + &gEfiDevicePathProtocolGuid, >> >> + NicDevice->DevPath, >> >> + NULL >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + Status =3D gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + (VOID **)&UsbEth, >> >> + This->DriverBindingHandle, >> >> + ChildHandleBuffer[Index], >> >> + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER >> >> + ); >> >> + } else { >> >> + gBS->FreePool (NicDevice->DevPath); >> >> + gBS->FreePool (NicDevice); >> >> + } >> >> + } >> >> + >> >> + if (!AllChildrenStopped) { >> >> + return EFI_DEVICE_ERROR; >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Entrypoint of Network Common Driver. >> >> + >> >> + This function is the entrypoint of Network Common Driver. It installs >> Driver Binding >> >> + Protocols together with Component Name Protocols. >> >> + >> >> + @param[in] ImageHandle The firmware allocated handle for the >> EFI image. >> >> + @param[in] SystemTable A pointer to the EFI System Table. >> >> + >> >> + @retval EFI_SUCCESS The entry point is executed successfull= y. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +NetworkCommonEntry ( >> >> + IN EFI_HANDLE ImageHandle, >> >> + IN EFI_SYSTEM_TABLE *SystemTable >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + >> >> + gNetworkCommonDriverBinding.DriverBindingHandle =3D ImageHandle; >> >> + gNetworkCommonDriverBinding.ImageHandle =3D ImageHandle; >> >> + >> >> + Status =3D gBS->InstallMultipleProtocolInterfaces ( >> >> + &gNetworkCommonDriverBinding.DriverBindingHandle, >> >> + &gEfiDriverBindingProtocolGuid, >> >> + &gNetworkCommonDriverBinding, >> >> + &gEfiComponentName2ProtocolGuid, >> >> + &gNetworkCommonComponentName2, >> >> + NULL >> >> + ); >> >> + return Status; >> >> +} >> >> diff --git a/UsbNetworkPkg/NetworkCommon/DriverBinding.h >> b/UsbNetworkPkg/NetworkCommon/DriverBinding.h >> new file mode 100644 >> index 0000000000..223e034f2f >> --- /dev/null >> +++ b/UsbNetworkPkg/NetworkCommon/DriverBinding.h >> @@ -0,0 +1,263 @@ >> +/** @file >> >> + Header file for for USB network common driver >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#ifndef _DRIVER_BINDING_H_ >> >> +#define _DRIVER_BINDING_H_ >> >> + >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> + >> >> +#define NETWORK_COMMON_DRIVER_VERSION 1 >> >> +#define NETWORK_COMMON_POLLING_INTERVAL 0x10 >> >> +#define RX_BUFFER_COUNT 32 >> >> +#define TX_BUFFER_COUNT 32 >> >> +#define MEMORY_REQUIRE 0 >> >> + >> >> +#define UNDI_DEV_SIGNATURE SIGNATURE_32('u','n','d','i') >> >> +#define UNDI_DEV_FROM_THIS(a) CR(a, NIC_DEVICE, NiiProtocol, >> UNDI_DEV_SIGNATURE) >> >> +#define UNDI_DEV_FROM_NIC(a) CR(a, NIC_DEVICE, NicInfo, >> UNDI_DEV_SIGNATURE) >> >> + >> >> +#pragma pack(1) >> >> +typedef struct { >> >> + UINT8 DestAddr[PXE_HWADDR_LEN_ETHER]; >> >> + UINT8 SrcAddr[PXE_HWADDR_LEN_ETHER]; >> >> + UINT16 Protocol; >> >> +} EthernetHeader; >> >> +#pragma pack() >> >> + >> >> +typedef struct { >> >> + UINTN Signature; >> >> + EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL NiiProtocol; >> >> + EFI_HANDLE DeviceHandle; >> >> + EFI_DEVICE_PATH_PROTOCOL *BaseDevPath; >> >> + EFI_DEVICE_PATH_PROTOCOL *DevPath; >> >> + NIC_DATA NicInfo; >> >> +} NIC_DEVICE; >> >> + >> >> +typedef VOID (*API_FUNC)( >> >> + PXE_CDB *, >> >> + NIC_DATA * >> >> + ); >> >> + >> >> +extern PXE_SW_UNDI *gPxe; >> >> +extern NIC_DEVICE *gLanDeviceList[MAX_LAN_INTERFACE]= ; >> >> +extern EFI_COMPONENT_NAME2_PROTOCOL gNetworkCommonComponentName2; >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +NetworkCommonSupported ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +NetworkCommonDriverStart ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +NetworkCommonDriverStop ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN UINTN NumberOfChildren, >> >> + IN EFI_HANDLE *ChildHandleBuffer >> >> + ); >> >> + >> >> +VOID >> >> +PxeStructInit ( >> >> + OUT PXE_SW_UNDI *PxeSw >> >> + ); >> >> + >> >> +VOID >> >> +UpdateNicNum ( >> >> + IN NIC_DATA *Nic, >> >> + IN OUT PXE_SW_UNDI *PxeSw >> >> + ); >> >> + >> >> +VOID >> >> +UndiApiEntry ( >> >> + IN UINT64 Cdb >> >> + ); >> >> + >> >> +UINTN >> >> +MapIt ( >> >> + IN NIC_DATA *Nic, >> >> + IN UINT64 MemAddr, >> >> + IN UINT32 Size, >> >> + IN UINT32 Direction, >> >> + OUT UINT64 MappedAddr >> >> + ); >> >> + >> >> +VOID >> >> +UnMapIt ( >> >> + IN NIC_DATA *Nic, >> >> + IN UINT64 MemAddr, >> >> + IN UINT32 Size, >> >> + IN UINT32 Direction, >> >> + IN UINT64 MappedAddr >> >> + ); >> >> + >> >> +VOID >> >> +UndiGetState ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiStart ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiStop ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiGetInitInfo ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiGetConfigInfo ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiInitialize ( >> >> + IN PXE_CDB *Cdb, >> >> + IN OUT NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiReset ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiShutdown ( >> >> + IN PXE_CDB *Cdb, >> >> + IN OUT NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiInterruptEnable ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiReceiveFilter ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiStationAddress ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiStatistics ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiMcastIp2Mac ( >> >> + IN OUT PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiNvData ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiGetStatus ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiFillHeader ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiTransmit ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiReceive ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +UINT16 >> >> +Initialize ( >> >> + IN PXE_CDB *Cdb, >> >> + IN OUT NIC_DATA *Nic >> >> + ); >> >> + >> >> +UINT16 >> >> +Transmit ( >> >> + IN PXE_CDB *Cdb, >> >> + IN OUT NIC_DATA *Nic, >> >> + IN UINT64 CpbAddr, >> >> + IN UINT16 OpFlags >> >> + ); >> >> + >> >> +UINT16 >> >> +Receive ( >> >> + IN PXE_CDB *Cdb, >> >> + IN OUT NIC_DATA *Nic, >> >> + IN UINT64 CpbAddr, >> >> + IN OUT UINT64 DbAddr >> >> + ); >> >> + >> >> +UINT16 >> >> +Setfilter ( >> >> + IN NIC_DATA *Nic, >> >> + IN UINT16 SetFilter, >> >> + IN UINT64 CpbAddr, >> >> + IN UINT32 CpbSize >> >> + ); >> >> + >> >> +UINT16 >> >> +Statistics ( >> >> + IN NIC_DATA *Nic, >> >> + IN UINT64 DbAddr, >> >> + IN UINT16 DbSize >> >> + ); >> >> + >> >> +#endif >> >> diff --git a/UsbNetworkPkg/NetworkCommon/NetworkCommon.inf >> b/UsbNetworkPkg/NetworkCommon/NetworkCommon.inf >> new file mode 100644 >> index 0000000000..483df660f7 >> --- /dev/null >> +++ b/UsbNetworkPkg/NetworkCommon/NetworkCommon.inf >> @@ -0,0 +1,43 @@ >> +## @file >> +# This is Usb Network Common driver for DXE phase. >> +# >> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> +# Subject to AMI licensing agreement. >> +## >> + >> +[Defines] >> + INF_VERSION =3D 0x00010005 >> + BASE_NAME =3D NetworkCommon >> + FILE_GUID =3D ca6eb4f4-f1d6-4375-97d6-18856871e1= bf >> + MODULE_TYPE =3D DXE_DRIVER >> + VERSION_STRING =3D 1.0 >> + ENTRY_POINT =3D NetworkCommonEntry >> + >> +[Sources] >> + DriverBinding.c >> + DriverBinding.h >> + ComponentName.c >> + PxeFunction.c >> + >> +[Packages] >> + MdePkg/MdePkg.dec >> + MdeModulePkg/MdeModulePkg.dec >> + UsbNetworkPkg/UsbNetworkPkg.dec >> + >> +[LibraryClasses] >> + UefiDriverEntryPoint >> + UefiBootServicesTableLib >> + UefiLib >> + DebugLib >> + UefiUsbLib >> + MemoryAllocationLib >> + BaseMemoryLib >> + >> +[Protocols] >> + gEfiNetworkInterfaceIdentifierProtocolGuid_31 >> + gEfiUsbIoProtocolGuid >> + gEfiDevicePathProtocolGuid >> + gEfiDriverBindingProtocolGuid >> + >> +[Depex] >> + TRUE >> diff --git a/UsbNetworkPkg/NetworkCommon/PxeFunction.c >> b/UsbNetworkPkg/NetworkCommon/PxeFunction.c >> new file mode 100644 >> index 0000000000..d34b61a69f >> --- /dev/null >> +++ b/UsbNetworkPkg/NetworkCommon/PxeFunction.c >> @@ -0,0 +1,1734 @@ >> +/** @file >> >> + This file contains code for UNDI command based on UEFI specification. >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#include "DriverBinding.h" >> >> + >> >> +// API table, defined in UEFI specification >> >> +API_FUNC gUndiApiTable[] =3D { >> >> + UndiGetState, >> >> + UndiStart, >> >> + UndiStop, >> >> + UndiGetInitInfo, >> >> + UndiGetConfigInfo, >> >> + UndiInitialize, >> >> + UndiReset, >> >> + UndiShutdown, >> >> + UndiInterruptEnable, >> >> + UndiReceiveFilter, >> >> + UndiStationAddress, >> >> + UndiStatistics, >> >> + UndiMcastIp2Mac, >> >> + UndiNvData, >> >> + UndiGetStatus, >> >> + UndiFillHeader, >> >> + UndiTransmit, >> >> + UndiReceive >> >> +}; >> >> + >> >> +/** >> >> + This command is used to determine the operational state of the UNDI. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiGetState ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode !=3D PXE_OPCODE_GET_STATE) || >> >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) || >> >> + (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED) || >> >> + (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) || >> >> + (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED) || >> >> + (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED)) >> >> + { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + Cdb->StatFlags =3D Cdb->StatFlags | Nic->State; >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetState !=3D NULL) { >> >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiGetState (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This command is used to change the UNDI operational state from stoppe= d >> to started. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiStart ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + PXE_CPB_START_31 *Cpb; >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode !=3D PXE_OPCODE_START) || >> >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize !=3D sizeof (PXE_CPB_START_31)) || >> >> + (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) || >> >> + (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED) || >> >> + (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED)) >> >> + { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_STOPPED) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_ALREADY_STARTED; >> >> + return; >> >> + } >> >> + >> >> + Cpb =3D (PXE_CPB_START_31 *)(UINTN)Cdb->CPBaddr; >> >> + >> >> + Nic->PxeStart.Delay =3D Cpb->Delay; >> >> + Nic->PxeStart.Virt2Phys =3D Cpb->Virt2Phys; >> >> + Nic->PxeStart.Block =3D Cpb->Block; >> >> + Nic->PxeStart.Map_Mem =3D 0; >> >> + Nic->PxeStart.UnMap_Mem =3D 0; >> >> + Nic->PxeStart.Sync_Mem =3D Cpb->Sync_Mem; >> >> + Nic->PxeStart.Unique_ID =3D Cpb->Unique_ID; >> >> + Nic->State =3D PXE_STATFLAGS_GET_STATE_STARTED; >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStart !=3D NULL) { >> >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiStart (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This command is used to change the UNDI operational state from starte= d >> to stopped. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiStop ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode !=3D PXE_OPCODE_STOP) || >> >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) || >> >> + (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED) || >> >> + (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) || >> >> + (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED) || >> >> + (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED)) >> >> + { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + if (Nic->State =3D=3D PXE_STATFLAGS_GET_STATE_STOPPED) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_NOT_STARTED; >> >> + return; >> >> + } >> >> + >> >> + if (Nic->State =3D=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_NOT_SHUTDOWN; >> >> + return; >> >> + } >> >> + >> >> + Nic->PxeStart.Delay =3D 0; >> >> + Nic->PxeStart.Virt2Phys =3D 0; >> >> + Nic->PxeStart.Block =3D 0; >> >> + Nic->PxeStart.Map_Mem =3D 0; >> >> + Nic->PxeStart.UnMap_Mem =3D 0; >> >> + Nic->PxeStart.Sync_Mem =3D 0; >> >> + Nic->State =3D PXE_STATFLAGS_GET_STATE_STOPPED; >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStop !=3D NULL) { >> >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiStop (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This command is used to retrieve initialization information that is >> >> + needed by drivers and applications to initialized UNDI. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiGetInitInfo ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + PXE_DB_GET_INIT_INFO *Db; >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode !=3D PXE_OPCODE_GET_INIT_INFO) || >> >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) || >> >> + (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED) || >> >> + (Cdb->DBsize !=3D sizeof (PXE_DB_GET_INIT_INFO)) || >> >> + (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED)) >> >> + { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + if (Nic->State =3D=3D PXE_STATFLAGS_GET_STATE_STOPPED) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_NOT_STARTED; >> >> + return; >> >> + } >> >> + >> >> + Db =3D (PXE_DB_GET_INIT_INFO *)(UINTN)Cdb->DBaddr; >> >> + >> >> + Db->MemoryRequired =3D MEMORY_REQUIRE; >> >> + Db->FrameDataLen =3D PXE_MAX_TXRX_UNIT_ETHER; >> >> + Db->LinkSpeeds[0] =3D 10; >> >> + Db->LinkSpeeds[1] =3D 100; >> >> + Db->LinkSpeeds[2] =3D 1000; >> >> + Db->LinkSpeeds[3] =3D 0; >> >> + Db->MediaHeaderLen =3D PXE_MAC_HEADER_LEN_ETHER; >> >> + Db->HWaddrLen =3D PXE_HWADDR_LEN_ETHER; >> >> + Db->MCastFilterCnt =3D MAX_MCAST_ADDRESS_CNT; >> >> + Db->TxBufCnt =3D Nic->PxeInit.TxBufCnt; >> >> + Db->TxBufSize =3D Nic->PxeInit.TxBufSize; >> >> + Db->RxBufCnt =3D Nic->PxeInit.RxBufCnt; >> >> + Db->RxBufSize =3D Nic->PxeInit.RxBufSize; >> >> + Db->IFtype =3D PXE_IFTYPE_ETHERNET; >> >> + Db->SupportedDuplexModes =3D PXE_DUPLEX_DEFAULT; >> >> + Db->SupportedLoopBackModes =3D LOOPBACK_NORMAL; >> >> + >> >> + Cdb->StatFlags |=3D (PXE_STATFLAGS_CABLE_DETECT_SUPPORTED | >> >> + PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED); >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetInitInfo !=3D NULL) { >> >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiGetInitInfo (Cdb, Nic)= ; >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This command is used to retrieve configuration information about >> >> + the NIC being controlled by the UNDI. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiGetConfigInfo ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + PXE_DB_GET_CONFIG_INFO *Db; >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode !=3D PXE_OPCODE_GET_CONFIG_INFO) || >> >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) || >> >> + (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED) || >> >> + (Cdb->DBsize !=3D sizeof (PXE_DB_GET_CONFIG_INFO)) || >> >> + (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED)) >> >> + { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + if (Nic->State =3D=3D PXE_STATFLAGS_GET_STATE_STOPPED) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_NOT_STARTED; >> >> + return; >> >> + } >> >> + >> >> + Db =3D (PXE_DB_GET_CONFIG_INFO *)(UINTN)Cdb->DBaddr; >> >> + >> >> + Db->pci.BusType =3D PXE_BUSTYPE_USB; >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetConfigInfo !=3D NULL) { >> >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiGetConfigInfo (Cdb, Ni= c); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This command resets the network adapter and initializes UNDI using >> >> + the parameters supplied in the CPB. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in, out] Nic A pointer to the Network interface controller >> data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiInitialize ( >> >> + IN PXE_CDB *Cdb, >> >> + IN OUT NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + PXE_CPB_INITIALIZE *Cpb; >> >> + PXE_DB_INITIALIZE *Db; >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode !=3D PXE_OPCODE_INITIALIZE) || >> >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize !=3D sizeof (PXE_CPB_INITIALIZE))) >> >> + { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + } >> >> + >> >> + if (Nic->State =3D=3D PXE_STATFLAGS_GET_STATE_STOPPED) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_NOT_STARTED; >> >> + return; >> >> + } >> >> + >> >> + if ((Cdb->OpFlags !=3D PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) && >> >> + (Cdb->OpFlags !=3D PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE)) >> >> + { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } >> >> + >> >> + if (Nic->State =3D=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_ALREADY_INITIALIZED; >> >> + return; >> >> + } >> >> + >> >> + Cpb =3D (PXE_CPB_INITIALIZE *)(UINTN)Cdb->CPBaddr; >> >> + Db =3D (PXE_DB_INITIALIZE *)(UINTN)Cdb->DBaddr; >> >> + >> >> + Nic->PxeInit.LinkSpeed =3D Cpb->LinkSpeed; >> >> + Nic->PxeInit.DuplexMode =3D Cpb->DuplexMode; >> >> + Nic->PxeInit.LoopBackMode =3D Cpb->LoopBackMode; >> >> + Nic->PxeInit.MemoryAddr =3D Cpb->MemoryAddr; >> >> + Nic->PxeInit.MemoryLength =3D Cpb->MemoryLength; >> >> + Nic->PxeInit.TxBufCnt =3D TX_BUFFER_COUNT; >> >> + Nic->PxeInit.TxBufSize =3D Nic->MaxSegmentSize; >> >> + Nic->PxeInit.RxBufCnt =3D RX_BUFFER_COUNT; >> >> + Nic->PxeInit.RxBufSize =3D Nic->MaxSegmentSize; >> >> + >> >> + Cdb->StatCode =3D Initialize (Cdb, Nic); >> >> + >> >> + Db->MemoryUsed =3D MEMORY_REQUIRE; >> >> + Db->TxBufCnt =3D Nic->PxeInit.TxBufCnt; >> >> + Db->TxBufSize =3D Nic->PxeInit.TxBufSize; >> >> + Db->RxBufCnt =3D Nic->PxeInit.RxBufCnt; >> >> + Db->RxBufSize =3D Nic->PxeInit.RxBufSize; >> >> + >> >> + Nic->RxFilter =3D PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST; >> >> + Nic->CanReceive =3D FALSE; >> >> + Nic->CanTransmit =3D FALSE; >> >> + >> >> + if (Cdb->OpFlags =3D=3D PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) { >> >> + if ((Nic->Request.Request =3D=3D USB_CDC_NETWORK_CONNECTION) && >> (Nic->Request.Value =3D=3D NETWORK_DISCONNECT)) { >> >> + Nic->CableDetect =3D 0; >> >> + } else if ((Nic->Request.Request =3D=3D USB_CDC_NETWORK_CONNECTION)= && >> (Nic->Request.Value =3D=3D NETWORK_CONNECTED)) { >> >> + Nic->CableDetect =3D 1; >> >> + } >> >> + >> >> + if (Nic->CableDetect =3D=3D 0) { >> >> + Cdb->StatFlags |=3D PXE_STATFLAGS_INITIALIZED_NO_MEDIA; >> >> + } >> >> + } >> >> + >> >> + if (Cdb->StatCode !=3D PXE_STATCODE_SUCCESS) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + } else { >> >> + Nic->State =3D PXE_STATFLAGS_GET_STATE_INITIALIZED; >> >> + } >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiInitialize !=3D NULL) { >> >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiInitialize (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + Initialize Network interface controller data. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in, out] Nic A pointer to the Network interface controller >> data. >> >> + >> >> + @retval Status A value of Pxe statcode. >> >> + >> >> +**/ >> >> +UINT16 >> >> +Initialize ( >> >> + IN PXE_CDB *Cdb, >> >> + IN OUT NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + UINTN Status; >> >> + UINT32 Index; >> >> + EFI_STATUS EfiStatus; >> >> + >> >> + Status =3D MapIt ( >> >> + Nic, >> >> + Nic->PxeInit.MemoryAddr, >> >> + Nic->PxeInit.MemoryLength, >> >> + TO_AND_FROM_DEVICE, >> >> + (UINT64)(UINTN)&Nic->MappedAddr >> >> + ); >> >> + >> >> + if (Status !=3D 0) { >> >> + return (UINT16)Status; >> >> + } >> >> + >> >> + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> >> + Nic->PermNodeAddress[Index] =3D Nic->MacAddr.Addr[Index]; >> >> + } >> >> + >> >> + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> >> + Nic->CurrentNodeAddress[Index] =3D Nic->PermNodeAddress[Index]; >> >> + } >> >> + >> >> + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> >> + Nic->BroadcastNodeAddress[Index] =3D 0xFF; >> >> + } >> >> + >> >> + for (Index =3D PXE_HWADDR_LEN_ETHER; Index < PXE_MAC_LENGTH; Index++)= { >> >> + Nic->CurrentNodeAddress[Index] =3D 0; >> >> + Nic->PermNodeAddress[Index] =3D 0; >> >> + Nic->BroadcastNodeAddress[Index] =3D 0; >> >> + } >> >> + >> >> + if (Nic->UsbEth->UsbEthInitialize !=3D NULL) { >> >> + EfiStatus =3D Nic->UsbEth->UsbEthInitialize (Cdb, Nic); >> >> + if (EFI_ERROR (EfiStatus)) { >> >> + return PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> + >> >> + return (UINT16)Status; >> >> +} >> >> + >> >> +/** >> >> + This command resets the network adapter and reinitializes the UNDI >> >> + with the same parameters provided in the Initialize command. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiReset ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode !=3D PXE_OPCODE_RESET) || >> >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) || >> >> + (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED) || >> >> + (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) || >> >> + (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED)) >> >> + { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> >> + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + return; >> >> + } >> >> + >> >> + if ((Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED) && >> >> + (Cdb->OpFlags !=3D PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS) && >> >> + (Cdb->OpFlags !=3D PXE_OPFLAGS_RESET_DISABLE_FILTERS)) >> >> + { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } >> >> + >> >> + if ((Cdb->OpFlags & PXE_OPFLAGS_RESET_DISABLE_FILTERS) =3D=3D 0) { >> >> + Nic->RxFilter =3D PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST; >> >> + } >> >> + >> >> + if ((Cdb->OpFlags & PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS) !=3D 0) { >> >> + Nic->InterrupOpFlag =3D 0; >> >> + } >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiReset !=3D NULL) { >> >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiReset (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + The Shutdown command resets the network adapter and leaves it in a >> >> + safe state for another driver to initialize. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in, out] Nic A pointer to the Network interface controller >> data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiShutdown ( >> >> + IN PXE_CDB *Cdb, >> >> + IN OUT NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode !=3D PXE_OPCODE_SHUTDOWN) || >> >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) || >> >> + (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED) || >> >> + (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) || >> >> + (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED) || >> >> + (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED)) >> >> + { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> >> + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + return; >> >> + } >> >> + >> >> + Nic->CanReceive =3D FALSE; >> >> + Nic->CanTransmit =3D FALSE; >> >> + >> >> + Nic->State =3D PXE_STATFLAGS_GET_STATE_STARTED; >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiShutdown !=3D NULL) { >> >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiShutdown (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + The Interrupt Enables command can be used to read and/or change >> >> + the current external interrupt enable settings. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiInterruptEnable ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + >> >> + Cdb->StatCode =3D PXE_STATCODE_UNSUPPORTED; >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiInterruptEnable !=3D NULL) { >> >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiInterruptEnable (Cdb, >> Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + } else { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This command is used to read and change receive filters and, >> >> + if supported, read and change the multicast MAC address filter list. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiReceiveFilter ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + UINT16 NewFilter; >> >> + PXE_DB_RECEIVE_FILTERS *Db; >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode !=3D PXE_OPCODE_RECEIVE_FILTERS) || >> >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8))) >> >> + { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> >> + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + return; >> >> + } >> >> + >> >> + NewFilter =3D (UINT16)(Cdb->OpFlags & 0x1F); >> >> + >> >> + switch (Cdb->OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_OPMASK) { >> >> + case PXE_OPFLAGS_RECEIVE_FILTER_READ: >> >> + if (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> >> + } >> >> + >> >> + if ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) =3D= =3D >> 0) { >> >> + if ((Cdb->DBsize !=3D 0)) { >> >> + Db =3D (PXE_DB_RECEIVE_FILTERS *)(UINTN)Cdb->DBaddr; >> >> + CopyMem (Db, &Nic->McastList, Nic->McastCount); >> >> + } >> >> + } >> >> + >> >> + break; >> >> + >> >> + case PXE_OPFLAGS_RECEIVE_FILTER_ENABLE: >> >> + if (NewFilter =3D=3D 0) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + >> >> + if (Cdb->CPBsize !=3D 0) { >> >> + if (((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST= ) >> =3D=3D 0) || >> >> + ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) >> !=3D 0) || >> >> + ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) != =3D >> 0) || >> >> + ((Cdb->CPBsize % sizeof (PXE_MAC_ADDR)) !=3D 0)) >> >> + { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> + >> >> + if ((Cdb->OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST= ) >> !=3D 0) { >> >> + if (((Cdb->OpFlags & >> PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) !=3D 0) || >> >> + ((Cdb->OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) >> !=3D 0)) >> >> + { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + >> >> + if ((Cdb->CPBsize =3D=3D 0)) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> + >> >> + Cdb->StatCode =3D Setfilter (Nic, NewFilter, Cdb->CPBaddr, >> Cdb->CPBsize); >> >> + break; >> >> + >> >> + case PXE_OPFLAGS_RECEIVE_FILTER_DISABLE: >> >> + if (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> >> + } >> >> + >> >> + Nic->CanReceive =3D TRUE; >> >> + break; >> >> + >> >> + default: >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> >> + } >> >> + >> >> + if (Nic->CanReceive) { >> >> + Cdb->StatFlags =3D (PXE_STATFLAGS)(Cdb->StatFlags | Nic->RxFilter); >> >> + } >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiReceiveFilter !=3D NULL) { >> >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiReceiveFilter (Cdb, Ni= c); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + Set PXE receive filter. >> >> + >> >> + @param[in] Nic A pointer to the Network interface controller >> data. >> >> + @param[in] SetFilter PXE receive filter >> >> + @param[in] CpbAddr Command Parameter Block Address >> >> + @param[in] CpbSize Command Parameter Block Size >> >> + >> >> +**/ >> >> +UINT16 >> >> +Setfilter ( >> >> + IN NIC_DATA *Nic, >> >> + IN UINT16 SetFilter, >> >> + IN UINT64 CpbAddr, >> >> + IN UINT32 CpbSize >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINT8 *McastList; >> >> + UINT8 Count =3D 0; >> >> + UINT8 Index1; >> >> + UINT8 Index2; >> >> + PXE_CPB_RECEIVE_FILTERS *Cpb =3D (PXE_CPB_RECEIVE_FILTERS >> *)(UINTN)CpbAddr; >> >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; >> >> + >> >> + // The Cpb could be NULL.(ref:PXE_CPBADDR_NOT_USED) >> >> + Nic->RxFilter =3D (UINT8)SetFilter; >> >> + >> >> + if (((SetFilter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) !=3D= 0) >> || (Cpb !=3D NULL)) { >> >> + if (Cpb !=3D NULL) { >> >> + Nic->McastCount =3D (UINT8)(CpbSize / PXE_MAC_LENGTH); >> >> + CopyMem (&Nic->McastList, Cpb, Nic->McastCount); >> >> + } >> >> + >> >> + if (Nic->CanReceive) { >> >> + Nic->CanReceive =3D FALSE; >> >> + } >> >> + >> >> + Nic->UsbEth->UsbEthFunDescriptor (Nic->UsbEth, &UsbEthFunDescriptor= ); >> >> + if ((UsbEthFunDescriptor.NumberMcFilters << 1) =3D=3D 0) { >> >> + Nic->RxFilter |=3D PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST; >> >> + Nic->UsbEth->SetUsbEthPacketFilter (Nic->UsbEth, Nic->RxFilter); >> >> + } else { >> >> + Status =3D gBS->AllocatePool (EfiBootServicesData, Nic->McastCoun= t * >> 6, (VOID **)&McastList); >> >> + if (EFI_ERROR (Status)) { >> >> + return PXE_STATCODE_INVALID_PARAMETER; >> >> + } >> >> + >> >> + if (Cpb !=3D NULL) { >> >> + for (Index1 =3D 0; Index1 < Nic->McastCount; Index1++) { >> >> + for (Index2 =3D 0; Index2 < 6; Index2++) { >> >> + McastList[Count++] =3D Cpb->MCastList[Index1][Index2]; >> >> + } >> >> + } >> >> + } >> >> + >> >> + Nic->RxFilter |=3D PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST; >> >> + if (Cpb !=3D NULL) { >> >> + Nic->UsbEth->SetUsbEthMcastFilter (Nic->UsbEth, Nic->McastCount= , >> McastList); >> >> + } >> >> + >> >> + Nic->UsbEth->SetUsbEthPacketFilter (Nic->UsbEth, Nic->RxFilter); >> >> + gBS->FreePool (McastList); >> >> + } >> >> + } >> >> + >> >> + return PXE_STATCODE_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This command is used to get current station and broadcast MAC address= es >> >> + and, if supported, to change the current station MAC address. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiStationAddress ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + PXE_CPB_STATION_ADDRESS *Cpb; >> >> + PXE_DB_STATION_ADDRESS *Db; >> >> + UINT16 Index; >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode !=3D PXE_OPCODE_STATION_ADDRESS) || >> >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->DBsize !=3D sizeof (PXE_DB_STATION_ADDRESS))) >> >> + { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> >> + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + return; >> >> + } >> >> + >> >> + if (Cdb->OpFlags =3D=3D PXE_OPFLAGS_STATION_ADDRESS_RESET) { >> >> + if (CompareMem (&Nic->CurrentNodeAddress[0], >> &Nic->PermNodeAddress[0], PXE_MAC_LENGTH) !=3D 0) { >> >> + for (Index =3D 0; Index < PXE_MAC_LENGTH; Index++) { >> >> + Nic->CurrentNodeAddress[Index] =3D Nic->PermNodeAddress[Index]; >> >> + } >> >> + } >> >> + } >> >> + >> >> + if (Cdb->CPBaddr !=3D 0) { >> >> + Cpb =3D (PXE_CPB_STATION_ADDRESS *)(UINTN)Cdb->CPBaddr; >> >> + for (Index =3D 0; Index < PXE_MAC_LENGTH; Index++) { >> >> + Nic->CurrentNodeAddress[Index] =3D Cpb->StationAddr[Index]; >> >> + } >> >> + } >> >> + >> >> + if (Cdb->DBaddr !=3D 0) { >> >> + Db =3D (PXE_DB_STATION_ADDRESS *)(UINTN)Cdb->DBaddr; >> >> + for (Index =3D 0; Index < PXE_MAC_LENGTH; Index++) { >> >> + Db->StationAddr[Index] =3D Nic->CurrentNodeAddress[Index]; >> >> + Db->BroadcastAddr[Index] =3D Nic->BroadcastNodeAddress[Index]; >> >> + Db->PermanentAddr[Index] =3D Nic->PermNodeAddress[Index]; >> >> + } >> >> + } >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStationAddress !=3D NULL) { >> >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiStationAddress (Cdb, N= ic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This command is used to read and clear the NIC traffic statistics. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiStatistics ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode !=3D PXE_OPCODE_STATISTICS) || >> >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) || >> >> + (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED)) >> >> + { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + } >> >> + >> >> + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> >> + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + return; >> >> + } >> >> + >> >> + if ((Cdb->OpFlags !=3D PXE_OPFLAGS_STATISTICS_RESET) && >> >> + (Cdb->OpFlags !=3D PXE_OPFLAGS_STATISTICS_READ)) >> >> + { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } >> >> + >> >> + Cdb->StatCode =3D Statistics (Nic, Cdb->DBaddr, Cdb->DBsize); >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStatistics !=3D NULL) { >> >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiStatistics (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + Return data for DB data. >> >> + >> >> + @param[in] Nic A pointer to the Network interface controller >> data. >> >> + @param[in] DbAddr Data Block Address. >> >> + @param[in] DbSize Data Block Size. >> >> + >> >> +**/ >> >> +UINT16 >> >> +Statistics ( >> >> + IN NIC_DATA *Nic, >> >> + IN UINT64 DbAddr, >> >> + IN UINT16 DbSize >> >> + ) >> >> +{ >> >> + PXE_DB_STATISTICS *DbStatistic; >> >> + EFI_STATUS Status; >> >> + >> >> + DbStatistic =3D (PXE_DB_STATISTICS *)(UINTN)DbAddr; >> >> + >> >> + if (DbSize =3D=3D 0) { >> >> + return PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + DbStatistic->Supported =3D 0x802; >> >> + DbStatistic->Data[0x01] =3D Nic->RxFrame; >> >> + DbStatistic->Data[0x0B] =3D Nic->TxFrame; >> >> + >> >> + if (Nic->UsbEth->UsbEthStatistics !=3D NULL) { >> >> + Status =3D Nic->UsbEth->UsbEthStatistics (Nic, DbAddr, DbSize); >> >> + if (EFI_ERROR (Status)) { >> >> + return PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> + >> >> + return PXE_STATCODE_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + Translate a multicast IPv4 or IPv6 address to a multicast MAC address= . >> >> + >> >> + @param[in, out] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller >> data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiMcastIp2Mac ( >> >> + IN OUT PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + PXE_CPB_MCAST_IP_TO_MAC *Cpb; >> >> + PXE_DB_MCAST_IP_TO_MAC *Db; >> >> + UINT8 *Tmp; >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode !=3D PXE_OPCODE_MCAST_IP_TO_MAC) || >> >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize !=3D sizeof (PXE_CPB_MCAST_IP_TO_MAC)) || >> >> + (Cdb->DBsize !=3D sizeof (PXE_DB_MCAST_IP_TO_MAC))) >> >> + { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> >> + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + return; >> >> + } >> >> + >> >> + Cpb =3D (PXE_CPB_MCAST_IP_TO_MAC *)(UINTN)Cdb->CPBaddr; >> >> + Db =3D (PXE_DB_MCAST_IP_TO_MAC *)(UINTN)Cdb->DBaddr; >> >> + >> >> + if ((Cdb->OpFlags & PXE_OPFLAGS_MCAST_IPV6_TO_MAC) !=3D 0) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_UNSUPPORTED; >> >> + return; >> >> + } >> >> + >> >> + Tmp =3D (UINT8 *)(&Cpb->IP.IPv4); >> >> + >> >> + if ((Tmp[0] & 0xF0) !=3D 0xE0) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CPB; >> >> + } >> >> + >> >> + Db->MAC[0] =3D 0x01; >> >> + Db->MAC[1] =3D 0x00; >> >> + Db->MAC[2] =3D 0x5E; >> >> + Db->MAC[3] =3D Tmp[1] & 0x7F; >> >> + Db->MAC[4] =3D Tmp[2]; >> >> + Db->MAC[5] =3D Tmp[3]; >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiMcastIp2Mac !=3D NULL) { >> >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiMcastIp2Mac (Cdb, Nic)= ; >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This command is used to read and write (if supported by NIC H/W) >> >> + nonvolatile storage on the NIC. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiNvData ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + >> >> + Cdb->StatCode =3D PXE_STATCODE_UNSUPPORTED; >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiNvData !=3D NULL) { >> >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiNvData (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + } else { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This command returns the current interrupt status and/or the >> >> + transmitted buffer addresses and the current media status. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiGetStatus ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + PXE_DB_GET_STATUS *Db; >> >> + PXE_DB_GET_STATUS TmpGetStatus; >> >> + UINT16 NumEntries; >> >> + UINTN Index; >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode !=3D PXE_OPCODE_GET_STATUS) || >> >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) || >> >> + (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED)) >> >> + { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> >> + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + return; >> >> + } >> >> + >> >> + TmpGetStatus.RxFrameLen =3D 0; >> >> + TmpGetStatus.reserved =3D 0; >> >> + Db =3D (PXE_DB_GET_STATUS *)(UINTN)Cdb->DBaddr; >> >> + >> >> + if ((Cdb->DBsize > 0) && (Cdb->DBsize < sizeof (UINT32) * 2)) { >> >> + CopyMem (Db, &TmpGetStatus, Cdb->DBsize); >> >> + } else { >> >> + CopyMem (Db, &TmpGetStatus, sizeof (UINT32) * 2); >> >> + } >> >> + >> >> + if ((Cdb->OpFlags & PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS) !=3D 0) { >> >> + if (Cdb->DBsize =3D=3D 0) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } >> >> + >> >> + NumEntries =3D Cdb->DBsize - sizeof (UINT64); >> >> + Cdb->DBsize =3D sizeof (UINT32) * 2; >> >> + >> >> + for (Index =3D 0; NumEntries >=3D sizeof (UINT64); Index++, NumEntr= ies >> -=3D sizeof (UINT64)) { >> >> + if (Nic->TxBufferCount > 0) { >> >> + Nic->TxBufferCount--; >> >> + Db->TxBuffer[Index] =3D Nic->MediaHeader[Nic->TxBufferCount]; >> >> + } >> >> + } >> >> + } >> >> + >> >> + if ((Cdb->OpFlags & PXE_OPFLAGS_GET_INTERRUPT_STATUS) !=3D 0) { >> >> + if (Nic->ReceiveStatus !=3D 0) { >> >> + Cdb->StatFlags |=3D PXE_STATFLAGS_GET_STATUS_RECEIVE; >> >> + } >> >> + } >> >> + >> >> + if ((Nic->Request.Request =3D=3D USB_CDC_NETWORK_CONNECTION) && >> (Nic->Request.Value =3D=3D NETWORK_DISCONNECT)) { >> >> + Nic->CableDetect =3D 0; >> >> + } else if ((Nic->Request.Request =3D=3D USB_CDC_NETWORK_CONNECTION) &= & >> (Nic->Request.Value =3D=3D NETWORK_CONNECTED)) { >> >> + Nic->CableDetect =3D 1; >> >> + } >> >> + >> >> + if ((Cdb->OpFlags & PXE_OPFLAGS_GET_MEDIA_STATUS) !=3D 0) { >> >> + if (Nic->CableDetect =3D=3D 0) { >> >> + Cdb->StatFlags |=3D PXE_STATFLAGS_GET_STATUS_NO_MEDIA; >> >> + } >> >> + } >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetStatus !=3D NULL) { >> >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiGetStatus (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This command is used to fill the media header(s) in transmit packet(s= ). >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiFillHeader ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + PXE_CPB_FILL_HEADER *CpbFillHeader; >> >> + PXE_CPB_FILL_HEADER_FRAGMENTED *CpbFill; >> >> + EthernetHeader *MacHeader; >> >> + UINTN Index; >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode !=3D PXE_OPCODE_FILL_HEADER) || >> >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize !=3D sizeof (PXE_CPB_FILL_HEADER_FRAGMENTED)) || >> >> + (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) || >> >> + (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED)) >> >> + { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> >> + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + return; >> >> + } >> >> + >> >> + if (Cdb->CPBsize =3D=3D PXE_CPBSIZE_NOT_USED) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } >> >> + >> >> + if ((Cdb->OpFlags & PXE_OPFLAGS_FILL_HEADER_FRAGMENTED) !=3D 0) { >> >> + CpbFill =3D (PXE_CPB_FILL_HEADER_FRAGMENTED *)(UINTN)Cdb->CPBaddr; >> >> + >> >> + if ((CpbFill->FragCnt =3D=3D 0) || (CpbFill->FragDesc[0].FragLen < >> PXE_MAC_HEADER_LEN_ETHER)) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } >> >> + >> >> + MacHeader =3D (EthernetHeader >> *)(UINTN)CpbFill->FragDesc[0].FragAddr; >> >> + MacHeader->Protocol =3D CpbFill->Protocol; >> >> + >> >> + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> >> + MacHeader->DestAddr[Index] =3D CpbFill->DestAddr[Index]; >> >> + MacHeader->SrcAddr[Index] =3D CpbFill->SrcAddr[Index]; >> >> + } >> >> + } else { >> >> + CpbFillHeader =3D (PXE_CPB_FILL_HEADER *)(UINTN)Cdb->CPBaddr; >> >> + >> >> + MacHeader =3D (EthernetHeader >> *)(UINTN)CpbFillHeader->MediaHeader; >> >> + MacHeader->Protocol =3D CpbFillHeader->Protocol; >> >> + >> >> + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> >> + MacHeader->DestAddr[Index] =3D CpbFillHeader->DestAddr[Index]; >> >> + MacHeader->SrcAddr[Index] =3D CpbFillHeader->SrcAddr[Index]; >> >> + } >> >> + } >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiFillHeader !=3D NULL) { >> >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiFillHeader (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + The Transmit command is used to place a packet into the transmit queu= e. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiTransmit ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode !=3D PXE_OPCODE_TRANSMIT) || >> >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize !=3D sizeof (PXE_CPB_TRANSMIT)) || >> >> + (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) || >> >> + (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED)) >> >> + { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; >> >> + return; >> >> + } >> >> + >> >> + if (Cdb->CPBsize =3D=3D PXE_CPBSIZE_NOT_USED) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiTransmit !=3D NULL) { >> >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiTransmit (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + >> >> + return; >> >> + } >> >> + >> >> + Cdb->StatCode =3D Transmit (Cdb, Nic, Cdb->CPBaddr, Cdb->OpFlags); >> >> + >> >> + if (Cdb->StatCode !=3D PXE_STATCODE_SUCCESS) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> +} >> >> + >> >> +/** >> >> + Use USB Ethernet Protocol Bulk out command to transmit data. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in, out] Nic A pointer to the Network interface controlle= r >> data. >> >> + @param[in] CpbAddr Command Parameter Block Address. >> >> + @param[in] OpFlags Operation Flags. >> >> + >> >> +**/ >> >> +UINT16 >> >> +Transmit ( >> >> + IN PXE_CDB *Cdb, >> >> + IN OUT NIC_DATA *Nic, >> >> + IN UINT64 CpbAddr, >> >> + IN UINT16 OpFlags >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + PXE_CPB_TRANSMIT *Cpb; >> >> + UINT64 BulkOutData =3D 0; >> >> + UINTN DataLength; >> >> + UINTN Map; >> >> + UINT32 Counter =3D 0; >> >> + UINT16 StatCode; >> >> + >> >> + Cpb =3D (PXE_CPB_TRANSMIT *)(UINTN)CpbAddr; >> >> + >> >> + if (Nic->CanTransmit) { >> >> + return PXE_STATCODE_BUSY; >> >> + } >> >> + >> >> + Nic->CanTransmit =3D TRUE; >> >> + >> >> + if ((OpFlags & PXE_OPFLAGS_TRANSMIT_FRAGMENTED) !=3D 0) { >> >> + return PXE_STATCODE_INVALID_PARAMETER; >> >> + } >> >> + >> >> + Map =3D MapIt ( >> >> + Nic, >> >> + Cpb->FrameAddr, >> >> + Cpb->DataLen + (UINT32)Cpb->MediaheaderLen, >> >> + TO_DEVICE, >> >> + (UINT64)(UINTN)&BulkOutData >> >> + ); >> >> + >> >> + if (Map !=3D 0) { >> >> + Nic->CanTransmit =3D FALSE; >> >> + return PXE_STATCODE_INVALID_PARAMETER; >> >> + } >> >> + >> >> + if (Nic->TxBufferCount < MAX_XMIT_BUFFERS) { >> >> + Nic->MediaHeader[Nic->TxBufferCount] =3D Cpb->FrameAddr; >> >> + Nic->TxBufferCount++; >> >> + } >> >> + >> >> + DataLength =3D (UINTN)(Cpb->DataLen + (UINT32)Cpb->MediaheaderLen); >> >> + >> >> + while (1) { >> >> + if (Counter >=3D 3) { >> >> + StatCode =3D PXE_STATCODE_BUSY; >> >> + break; >> >> + } >> >> + >> >> + Status =3D Nic->UsbEth->UsbEthTransmit (Cdb, Nic->UsbEth, (VOID >> *)(UINTN)BulkOutData, &DataLength); >> >> + if (EFI_ERROR (Status)) { >> >> + StatCode =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + >> >> + if (Status =3D=3D EFI_INVALID_PARAMETER) { >> >> + StatCode =3D PXE_STATCODE_INVALID_PARAMETER; >> >> + break; >> >> + } >> >> + >> >> + if (Status =3D=3D EFI_DEVICE_ERROR) { >> >> + StatCode =3D PXE_STATCODE_DEVICE_FAILURE; >> >> + break; >> >> + } >> >> + >> >> + if (!EFI_ERROR (Status)) { >> >> + Nic->TxFrame++; >> >> + StatCode =3D PXE_STATCODE_SUCCESS; >> >> + break; >> >> + } >> >> + >> >> + Counter++; >> >> + } >> >> + >> >> + UnMapIt ( >> >> + Nic, >> >> + Cpb->FrameAddr, >> >> + Cpb->DataLen + (UINT32)Cpb->MediaheaderLen, >> >> + TO_DEVICE, >> >> + BulkOutData >> >> + ); >> >> + >> >> + Nic->CanTransmit =3D FALSE; >> >> + >> >> + return StatCode; >> >> +} >> >> + >> >> +/** >> >> + When the network adapter has received a frame, this command is used >> >> + to copy the frame into driver/application storage. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiReceive ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode !=3D PXE_OPCODE_RECEIVE) || >> >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize !=3D sizeof (PXE_CPB_RECEIVE)) || >> >> + (Cdb->DBsize !=3D sizeof (PXE_DB_RECEIVE)) || >> >> + (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED)) >> >> + { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; >> >> + return; >> >> + } >> >> + >> >> + if (!Nic->CanReceive) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; >> >> + return; >> >> + } >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiReceive !=3D NULL) { >> >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiReceive (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + >> >> + return; >> >> + } >> >> + >> >> + Cdb->StatCode =3D Receive (Cdb, Nic, Cdb->CPBaddr, Cdb->DBaddr); >> >> + >> >> + if (Cdb->StatCode !=3D PXE_STATCODE_SUCCESS) { >> >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> +} >> >> + >> >> +/** >> >> + Use USB Ethernet Protocol Bulk in command to receive data. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in, out] Nic A pointer to the Network interface controlle= r >> data. >> >> + @param[in] CpbAddr Command Parameter Block Address. >> >> + @param[in, out] DbAddr Data Block Address. >> >> + >> >> +**/ >> >> +UINT16 >> >> +Receive ( >> >> + IN PXE_CDB *Cdb, >> >> + IN OUT NIC_DATA *Nic, >> >> + IN UINT64 CpbAddr, >> >> + IN OUT UINT64 DbAddr >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINTN Index; >> >> + UINT16 StatCode =3D PXE_STATCODE_NO_DATA; >> >> + PXE_FRAME_TYPE FrameType =3D PXE_FRAME_TYPE_NONE; >> >> + PXE_CPB_RECEIVE *Cpb; >> >> + PXE_DB_RECEIVE *Db; >> >> + UINT8 *BulkInData; >> >> + UINTN DataLength =3D (UINTN)Nic->MaxSegmentSize; >> >> + EthernetHeader *Header; >> >> + >> >> + Cpb =3D (PXE_CPB_RECEIVE *)(UINTN)CpbAddr; >> >> + Db =3D (PXE_DB_RECEIVE *)(UINTN)DbAddr; >> >> + >> >> + Status =3D gBS->AllocatePool (EfiBootServicesData, DataLength, (VOID >> **)&BulkInData); >> >> + if (EFI_ERROR (Status)) { >> >> + return PXE_STATCODE_INVALID_PARAMETER; >> >> + } >> >> + >> >> + while (1) { >> >> + Status =3D Nic->UsbEth->UsbEthReceive (Cdb, Nic->UsbEth, (VOID >> *)BulkInData, &DataLength); >> >> + if (EFI_ERROR (Status)) { >> >> + break; >> >> + } >> >> + >> >> + Nic->RxFrame++; >> >> + >> >> + if (DataLength !=3D 0) { >> >> + if (DataLength > Cpb->BufferLen) { >> >> + DataLength =3D (UINTN)Cpb->BufferLen; >> >> + } >> >> + >> >> + CopyMem ((UINT8 *)(UINTN)Cpb->BufferAddr, (UINT8 *)BulkInData, >> DataLength); >> >> + >> >> + Header =3D (EthernetHeader *)BulkInData; >> >> + >> >> + Db->FrameLen =3D (UINT32)DataLength; >> >> + Db->MediaHeaderLen =3D PXE_MAC_HEADER_LEN_ETHER; >> >> + >> >> + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> >> + if (Header->DestAddr[Index] !=3D Nic->CurrentNodeAddress[Index]= ) { >> >> + break; >> >> + } >> >> + } >> >> + >> >> + if (Index >=3D PXE_HWADDR_LEN_ETHER) { >> >> + FrameType =3D PXE_FRAME_TYPE_UNICAST; >> >> + } else { >> >> + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> >> + if (Header->DestAddr[Index] !=3D >> Nic->BroadcastNodeAddress[Index]) { >> >> + break; >> >> + } >> >> + } >> >> + >> >> + if (Index >=3D PXE_HWADDR_LEN_ETHER) { >> >> + FrameType =3D PXE_FRAME_TYPE_BROADCAST; >> >> + } else { >> >> + if ((Header->DestAddr[0] & 1) =3D=3D 1) { >> >> + FrameType =3D PXE_FRAME_TYPE_FILTERED_MULTICAST; >> >> + } else { >> >> + FrameType =3D PXE_FRAME_TYPE_PROMISCUOUS; >> >> + } >> >> + } >> >> + } >> >> + >> >> + Db->Type =3D FrameType; >> >> + Db->Protocol =3D Header->Protocol; >> >> + >> >> + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> >> + Db->SrcAddr[Index] =3D Header->SrcAddr[Index]; >> >> + Db->DestAddr[Index] =3D Header->DestAddr[Index]; >> >> + } >> >> + >> >> + StatCode =3D PXE_STATCODE_SUCCESS; >> >> + break; >> >> + } >> >> + } >> >> + >> >> + if (FrameType =3D=3D PXE_FRAME_TYPE_NONE) { >> >> + Nic->ReceiveStatus =3D 0; >> >> + } else { >> >> + Nic->ReceiveStatus =3D 1; >> >> + } >> >> + >> >> + gBS->FreePool (BulkInData); >> >> + >> >> + return StatCode; >> >> +} >> >> + >> >> +/** >> >> + Fill out PXE SW UNDI structure. >> >> + >> >> + @param[out] PxeSw A pointer to the PXE SW UNDI structure. >> >> + >> >> +**/ >> >> +VOID >> >> +PxeStructInit ( >> >> + OUT PXE_SW_UNDI *PxeSw >> >> + ) >> >> +{ >> >> + PxeSw->Signature =3D PXE_ROMID_SIGNATURE; >> >> + PxeSw->Len =3D (UINT8)sizeof (PXE_SW_UNDI); >> >> + PxeSw->Fudge =3D 0; >> >> + PxeSw->IFcnt =3D 0; >> >> + PxeSw->IFcntExt =3D 0; >> >> + PxeSw->Rev =3D PXE_ROMID_REV; >> >> + PxeSw->MajorVer =3D PXE_ROMID_MAJORVER; >> >> + PxeSw->MinorVer =3D PXE_ROMID_MINORVER; >> >> + PxeSw->reserved1 =3D 0; >> >> + >> >> + PxeSw->Implementation =3D PXE_ROMID_IMP_SW_VIRT_ADDR | >> >> + PXE_ROMID_IMP_FRAG_SUPPORTED | >> >> + PXE_ROMID_IMP_CMD_LINK_SUPPORTED | >> >> + PXE_ROMID_IMP_STATION_ADDR_SETTABLE | >> >> + >> PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED | >> >> + PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED | >> >> + PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED | >> >> + PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED= ; >> >> + >> >> + PxeSw->EntryPoint =3D (UINT64)(UINTN)UndiApiEntry; >> >> + PxeSw->reserved2[0] =3D 0; >> >> + PxeSw->reserved2[1] =3D 0; >> >> + PxeSw->reserved2[2] =3D 0; >> >> + PxeSw->BusCnt =3D 1; >> >> + PxeSw->BusType[0] =3D PXE_BUSTYPE_USB; >> >> + PxeSw->Fudge =3D PxeSw->Fudge - CalculateSum8 ((VOID *)PxeSw, >> PxeSw->Len); >> >> +} >> >> + >> >> +/** >> >> + Update NIC number. >> >> + >> >> + @param[in] Nic A pointer to the Network interface >> controller data. >> >> + @param[in, out] PxeSw A pointer to the PXE SW UNDI structure. >> >> + >> >> +**/ >> >> +VOID >> >> +UpdateNicNum ( >> >> + IN NIC_DATA *Nic, >> >> + IN OUT PXE_SW_UNDI *PxeSw >> >> + ) >> >> +{ >> >> + UINT16 NicNum; >> >> + >> >> + NicNum =3D (PxeSw->IFcnt | PxeSw->IFcntExt << 8); >> >> + >> >> + if (Nic =3D=3D NULL) { >> >> + if (NicNum > 0) { >> >> + NicNum--; >> >> + } >> >> + >> >> + PxeSw->IFcnt =3D (UINT8)(NicNum & 0xFF); // Get lower b= yte >> >> + PxeSw->IFcntExt =3D (UINT8)((NicNum & 0xFF00) >> 8); // Get upper b= yte >> >> + PxeSw->Fudge =3D (UINT8)(PxeSw->Fudge - CalculateSum8 ((VOID >> *)PxeSw, PxeSw->Len)); >> >> + return; >> >> + } >> >> + >> >> + NicNum++; >> >> + >> >> + PxeSw->IFcnt =3D (UINT8)(NicNum & 0xFF); // Get lower byt= e >> >> + PxeSw->IFcntExt =3D (UINT8)((NicNum & 0xFF00) >> 8); // Get upper byt= e >> >> + PxeSw->Fudge =3D (UINT8)(PxeSw->Fudge - CalculateSum8 ((VOID *)Pxe= Sw, >> PxeSw->Len)); >> >> +} >> >> + >> >> +/** >> >> + UNDI API table entry. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiApiEntry ( >> >> + IN UINT64 Cdb >> >> + ) >> >> +{ >> >> + PXE_CDB *CdbPtr; >> >> + NIC_DATA *Nic; >> >> + >> >> + if (Cdb =3D=3D 0) { >> >> + return; >> >> + } >> >> + >> >> + CdbPtr =3D (PXE_CDB *)(UINTN)Cdb; >> >> + Nic =3D &(gLanDeviceList[CdbPtr->IFnum]->NicInfo); >> >> + gUndiApiTable[CdbPtr->OpCode](CdbPtr, Nic); >> >> +} >> >> + >> >> +/** >> >> + Map virtual memory address for DMA. This field can be set to >> >> + zero if there is no mapping service. >> >> + >> >> + @param[in] Nic A pointer to the Network interface >> controller data. >> >> + @param[in] MemAddr Virtual address to be mapped. >> >> + @param[in] Size Size of memory to be mapped. >> >> + @param[in] Direction Direction of data flow for this memory's >> usage: >> >> + cpu->device, device->cpu or both ways. >> >> + @param[out] MappedAddr Pointer to return the mapped device address= . >> >> + >> >> +**/ >> >> +UINTN >> >> +MapIt ( >> >> + IN NIC_DATA *Nic, >> >> + IN UINT64 MemAddr, >> >> + IN UINT32 Size, >> >> + IN UINT32 Direction, >> >> + OUT UINT64 MappedAddr >> >> + ) >> >> +{ >> >> + UINT64 *PhyAddr; >> >> + >> >> + PhyAddr =3D (UINT64 *)(UINTN)MappedAddr; >> >> + >> >> + if (Nic->PxeStart.Map_Mem =3D=3D 0) { >> >> + *PhyAddr =3D MemAddr; >> >> + } else { >> >> + ((void (*)(UINT64, UINT64, UINT32, UINT32, UINT64))(UINTN) >> Nic->PxeStart.Map_Mem)( >> >> + Nic->PxeStart.Unique_ID, >> >> + MemAddr, >> >> + Size, >> >> + Direction, >> >> + MappedAddr >> >> + ); >> >> + } >> >> + >> >> + return PXE_STATCODE_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + Un-map previously mapped virtual memory address. This field can be se= t >> >> + to zero only if the Map_Mem() service is also set to zero. >> >> + >> >> + @param[in] Nic A pointer to the Network interface >> controller data. >> >> + @param[in] MemAddr Virtual address to be mapped. >> >> + @param[in] Size Size of memory to be mapped. >> >> + @param[in] Direction Direction of data flow for this memory's >> usage: >> >> + cpu->device, device->cpu or both ways. >> >> + @param[in] MappedAddr Pointer to return the mapped device address= . >> >> + >> >> +**/ >> >> +VOID >> >> +UnMapIt ( >> >> + IN NIC_DATA *Nic, >> >> + IN UINT64 MemAddr, >> >> + IN UINT32 Size, >> >> + IN UINT32 Direction, >> >> + IN UINT64 MappedAddr >> >> + ) >> >> +{ >> >> + if (Nic->PxeStart.UnMap_Mem !=3D 0) { >> >> + ((void (*)(UINT64, UINT64, UINT32, UINT32, UINT64))(UINTN) >> Nic->PxeStart.UnMap_Mem)( >> >> + Nic->PxeStart.Unique_ID, >> >> + MemAddr, >> >> + Size, >> >> + Direction, >> >> + MappedAddr >> >> + ); >> >> + } >> >> + >> >> + return; >> >> +} >> >> diff --git a/UsbNetworkPkg/ReadMe.md b/UsbNetworkPkg/ReadMe.md >> new file mode 100644 >> index 0000000000..6dc0514ba7 >> --- /dev/null >> +++ b/UsbNetworkPkg/ReadMe.md >> @@ -0,0 +1,65 @@ >> +# UsbNetworkPkg >> + >> +This document is intend to provide package information, include the >> interface details. >> + >> +# INDEX >> + * [Introduction](#introduction) >> + * [Components](#components) >> + * [[NetworkCommon]](#networkcommon) >> + * [[UsbCdcEcm]](#usbcdcecm) >> + * [[UsbCdcNcm]](#usbcdcncm) >> + * [[UsbRndis]](#usbrndis) >> + >> +# Introduction >> +UsbNetworkPkg provides network functions for USB LAN devices. >> + >> +# Components >> +Below module is included in this package:
>> +- NetworkCommon >> +- UsbCdcEcm >> +- UsbCdcNcm >> +- UsbRndis >> + >> +## [NetworkCommon] >> +Provides a LAN driver based on UEFI specification(UNDI). It supports US= B >> communication class subclass devices and USB Rndis devices, depending on >> the UsbEthernetProtocol. >> + >> +## Required Components >> +- NetworkPkg >> + >> +## [UsbCdcEcm] >> +This driver provides a communication interface for USB Ethernet devices >> that follows the ECM protocol. The driver installs UsbEthernetProtocol w= ith >> ECM functions which are consumed by the NetworkCommon driver. >> + >> +The driver is compatible with the following USB class codes: >> +|Class Code|SubClass Code|Protocol Code| >> +|:--------:|:-----------:|:-----------:| >> +|0x02|0x06|0x00| >> + >> +## Required Components >> +- NetworkCommon >> +- MdeModulePkg(USB bus driver) >> + >> +## [UsbCdcNcm] >> +This driver provides a communication interface for USB Ethernet devices >> that follows the NCM protocol. The driver installs UsbEthernetProtocol w= ith >> NCM functions which are consumed by the NetworkCommon driver. >> + >> +The driver is compatible with the following USB class codes: >> +|Class Code|SubClass Code|Protocol Code| >> +|:--------:|:-----------:|:-----------:| >> +|0x02|0x0D|0x00| >> + >> +## Required Components >> +- NetworkCommon >> +- MdeModulePkg(USB bus driver) >> + >> +## [UsbRndis] >> +This driver provides a communication interface for USB Ethernet devices >> that follows the RNDIS protocol. The driver installs UsbEthernetProtocol >> with RNDIS functions which are consumed by the NetworkCommon driver. >> + >> +The driver is compatible with the following USB class codes: >> +|Class Code|SubClass Code|Protocol Code| >> +|:--------:|:-----------:|:-----------:| >> +|0x02|0x02|0xFF| >> +|0xEF|0x04|0x01| >> + >> +## Required Components >> +- NetworkCommon >> +- MdeModulePkg(USB bus driver) >> + >> diff --git a/UsbNetworkPkg/ReleaseNotes.md b/UsbNetworkPkg/ReleaseNotes.= md >> new file mode 100644 >> index 0000000000..03912e7788 >> --- /dev/null >> +++ b/UsbNetworkPkg/ReleaseNotes.md >> @@ -0,0 +1,11 @@ >> +# UsbNetworkPkg Release Notes >> >> + >> >> +# Release History >> >> +- [1.00](#100) >> >> + >> >> +## 1.00 >> >> + >> >> +**Release Date:** Mar 10, 2022 >> >> + >> >> +**New Features** >> >> +- UsbNetworkPkg first release. >> >> diff --git a/UsbNetworkPkg/UsbCdcEcm/ComponentName.c >> b/UsbNetworkPkg/UsbCdcEcm/ComponentName.c >> new file mode 100644 >> index 0000000000..39123994b2 >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbCdcEcm/ComponentName.c >> @@ -0,0 +1,170 @@ >> +/** @file >> >> + This file contains code for USB Ecm Driver Component Name definitions >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> +#include "UsbCdcEcm.h" >> >> + >> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE >> gUsbEcmDriverNameTable[] =3D { >> >> + { >> >> + "eng;en", >> >> + L"USB ECM Driver" >> >> + }, >> >> + { >> >> + NULL, >> >> + NULL >> >> + } >> >> +}; >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEcmComponentNameGetDriverName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **DriverName >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEcmComponentNameGetControllerName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN EFI_HANDLE Controller, >> >> + IN EFI_HANDLE ChildHandle OPTIONAL, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **ControllerName >> >> + ); >> >> + >> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL >> gUsbEcmComponentName =3D { >> >> + UsbEcmComponentNameGetDriverName, >> >> + UsbEcmComponentNameGetControllerName, >> >> + "eng" >> >> +}; >> >> + >> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL >> gUsbEcmComponentName2 =3D { >> >> + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)UsbEcmComponentNameGetDriverName= , >> >> + >> (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)UsbEcmComponentNameGetControlle= rName, >> >> + "en" >> >> +}; >> >> + >> >> +/** >> >> + Retrieves a Unicode string that is the user readable name of the >> driver. >> >> + >> >> + This function retrieves the user readable name of a driver in the for= m >> of a >> >> + Unicode string. If the driver specified by This has a user readable >> name in >> >> + the language specified by Language, then a pointer to the driver name >> is >> >> + returned in DriverName, and EFI_SUCCESS is returned. If the driver >> specified >> >> + by This does not support the language specified by Language, >> >> + then EFI_UNSUPPORTED is returned. >> >> + >> >> + @param[in] This A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >> >> + EFI_COMPONENT_NAME_PROTOCOL instance. >> >> + @param[in] Language A pointer to a Null-terminated ASCII >> string >> >> + array indicating the language. This is >> the >> >> + language of the driver name that the >> caller is >> >> + requesting, and it must match one of th= e >> >> + languages specified in >> SupportedLanguages. The >> >> + number of languages supported by a >> driver is up >> >> + to the driver writer. Language is >> specified >> >> + in RFC 4646 or ISO 639-2 language code >> format. >> >> + @param[out] DriverName A pointer to the Unicode string to >> return. >> >> + This Unicode string is the name of the >> >> + driver specified by This in the languag= e >> >> + specified by Language. >> >> + >> >> + @retval EFI_SUCCESS The Unicode string for the Driver >> specified by >> >> + This and the language specified by >> Language was >> >> + returned in DriverName. >> >> + @retval EFI_INVALID_PARAMETER Language is NULL. >> >> + @retval EFI_INVALID_PARAMETER DriverName is NULL. >> >> + @retval EFI_UNSUPPORTED The driver specified by This does not >> support >> >> + the language specified by Language. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEcmComponentNameGetDriverName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **DriverName >> >> + ) >> >> +{ >> >> + return LookupUnicodeString2 ( >> >> + Language, >> >> + This->SupportedLanguages, >> >> + gUsbEcmDriverNameTable, >> >> + DriverName, >> >> + (BOOLEAN)(This =3D=3D &gUsbEcmComponentName) >> >> + ); >> >> +} >> >> + >> >> +/** >> >> + Retrieves a Unicode string that is the user readable name of the >> controller >> >> + that is being managed by a driver. >> >> + >> >> + This function retrieves the user readable name of the controller >> specified by >> >> + ControllerHandle and ChildHandle in the form of a Unicode string. If >> the >> >> + driver specified by This has a user readable name in the language >> specified by >> >> + Language, then a pointer to the controller name is returned in >> ControllerName, >> >> + and EFI_SUCCESS is returned. If the driver specified by This is not >> currently >> >> + managing the controller specified by ControllerHandle and ChildHandle= , >> >> + then EFI_UNSUPPORTED is returned. If the driver specified by This >> does not >> >> + support the language specified by Language, then EFI_UNSUPPORTED is >> returned. >> >> + >> >> + @param[in] This A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >> >> + EFI_COMPONENT_NAME_PROTOCOL instance. >> >> + @param[in] Controller The handle of a controller that the >> driver >> >> + specified by This is managing. This >> handle >> >> + specifies the controller whose name is >> to be >> >> + returned. >> >> + @param[in] ChildHandle The handle of the child controller to >> retrieve >> >> + the name of. This is an optional >> parameter that >> >> + may be NULL. It will be NULL for devic= e >> >> + drivers. It will also be NULL for a bu= s >> drivers >> >> + that wish to retrieve the name of the b= us >> >> + controller. It will not be NULL for a >> bus >> >> + driver that wishes to retrieve the name >> of a >> >> + child controller. >> >> + @param[in] Language A pointer to a Null-terminated ASCII >> string >> >> + array indicating the language. This is >> the >> >> + language of the driver name that the >> caller is >> >> + requesting, and it must match one of th= e >> >> + languages specified in >> SupportedLanguages. The >> >> + number of languages supported by a >> driver is up >> >> + to the driver writer. Language is >> specified in >> >> + RFC 4646 or ISO 639-2 language code >> format. >> >> + @param[out] ControllerName A pointer to the Unicode string to >> return. >> >> + This Unicode string is the name of the >> >> + controller specified by ControllerHandl= e >> and >> >> + ChildHandle in the language specified b= y >> >> + Language from the point of view of the >> driver >> >> + specified by This. >> >> + >> >> + @retval EFI_SUCCESS The Unicode string for the user readabl= e >> name in >> >> + the language specified by Language for >> the >> >> + driver specified by This was returned i= n >> >> + DriverName. >> >> + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid >> EFI_HANDLE. >> >> + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a >> valid >> >> + EFI_HANDLE. >> >> + @retval EFI_INVALID_PARAMETER Language is NULL. >> >> + @retval EFI_INVALID_PARAMETER ControllerName is NULL. >> >> + @retval EFI_UNSUPPORTED The driver specified by This is not >> currently >> >> + managing the controller specified by >> >> + ControllerHandle and ChildHandle. >> >> + @retval EFI_UNSUPPORTED The driver specified by This does not >> support >> >> + the language specified by Language. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEcmComponentNameGetControllerName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN EFI_HANDLE Controller, >> >> + IN EFI_HANDLE ChildHandle OPTIONAL, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **ControllerName >> >> + ) >> >> +{ >> >> + return EFI_UNSUPPORTED; >> >> +} >> >> diff --git a/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.c >> b/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.c >> new file mode 100644 >> index 0000000000..34f115f48d >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.c >> @@ -0,0 +1,504 @@ >> +/** @file >> >> + This file contains code for USB Ethernet Control Model >> >> + Driver >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> +#include "UsbCdcEcm.h" >> >> + >> >> +EFI_GUID gUsbEthProtocolGuid =3D USB_ETHERNET_PROTOCOL_GUID; >> >> + >> >> +EFI_DRIVER_BINDING_PROTOCOL gUsbEcmDriverBinding =3D { >> >> + UsbEcmDriverSupported, >> >> + UsbEcmDriverStart, >> >> + UsbEcmDriverStop, >> >> + USB_ECM_DRIVER_VERSION, >> >> + NULL, >> >> + NULL >> >> +}; >> >> + >> >> +/** >> >> + Check if this interface is USB ECM SubType >> >> + >> >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance. >> >> + >> >> + @retval TRUE USB ECM SubType. >> >> + @retval FALSE Not USB ECM SubType. >> >> + >> >> +**/ >> >> +BOOLEAN >> >> +IsSupportedDevice ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; >> >> + >> >> + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, >> &InterfaceDescriptor); >> >> + if (EFI_ERROR (Status)) { >> >> + return FALSE; >> >> + } >> >> + >> >> + if ((InterfaceDescriptor.InterfaceClass =3D=3D USB_CDC_CLASS) && >> >> + (InterfaceDescriptor.InterfaceSubClass =3D=3D USB_CDC_ECM_SUBCLAS= S) && >> >> + (InterfaceDescriptor.InterfaceProtocol =3D=3D USB_NO_CLASS_PROTOC= OL)) >> >> + { >> >> + return TRUE; >> >> + } >> >> + >> >> + return FALSE; >> >> +} >> >> + >> >> +/** >> >> + USB ECM Driver Binding Support. >> >> + >> >> + @param[in] This Protocol instance pointer. >> >> + @param[in] ControllerHandle Handle of device to test. >> >> + @param[in] RemainingDevicePath Optional parameter use to pick a >> specific child >> >> + device to start. >> >> + >> >> + @retval EFI_SUCCESS This driver supports this device. >> >> + @retval EFI_ALREADY_STARTED This driver is already running on >> this device. >> >> + @retval other This driver does not support this >> device. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEcmDriverSupported ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_IO_PROTOCOL *UsbIo =3D NULL; >> >> + >> >> + Status =3D gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status =3D IsSupportedDevice (UsbIo) ? EFI_SUCCESS : EFI_UNSUPPORTED; >> >> + >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Check if the USB ECM and USB CDC Data interfaces are from the same >> device. >> >> + >> >> + @param[in] UsbEthPath A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> >> + @param[in] UsbCdcDataPath A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> >> + >> >> + @retval EFI_SUCCESS Is the same device. >> >> + @retval EFI_NOT_FOUND Is not the same device. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +IsSameDevice ( >> >> + IN EFI_DEVICE_PATH_PROTOCOL *UsbEthPath, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath >> >> + ) >> >> +{ >> >> + while (1) { >> >> + if ((UsbEthPath->Type =3D=3D ACPI_DEVICE_PATH) && (UsbEthPath->SubT= ype >> =3D=3D ACPI_DP)) { >> >> + if (CompareMem ((ACPI_HID_DEVICE_PATH *)UsbCdcDataPath, >> (ACPI_HID_DEVICE_PATH *)UsbEthPath, sizeof (ACPI_HID_DEVICE_PATH))) { >> >> + return EFI_NOT_FOUND; >> >> + } >> >> + } >> >> + >> >> + if ((UsbEthPath->Type =3D=3D HARDWARE_DEVICE_PATH) && >> (UsbEthPath->SubType =3D=3D HW_PCI_DP)) { >> >> + if (CompareMem ((PCI_DEVICE_PATH *)UsbCdcDataPath, >> (PCI_DEVICE_PATH *)UsbEthPath, sizeof (PCI_DEVICE_PATH))) { >> >> + return EFI_NOT_FOUND; >> >> + } >> >> + } >> >> + >> >> + if ((UsbEthPath->Type =3D=3D MESSAGING_DEVICE_PATH) && >> (UsbEthPath->SubType =3D=3D MSG_USB_DP)) { >> >> + if (IsDevicePathEnd (NextDevicePathNode (UsbEthPath))) { >> >> + if (((USB_DEVICE_PATH *)UsbEthPath)->ParentPortNumber =3D=3D >> >> + ((USB_DEVICE_PATH *)UsbCdcDataPath)->ParentPortNumber) >> >> + { >> >> + return EFI_SUCCESS; >> >> + } else { >> >> + return EFI_NOT_FOUND; >> >> + } >> >> + } else { >> >> + if (CompareMem ((USB_DEVICE_PATH *)UsbCdcDataPath, >> (USB_DEVICE_PATH *)UsbEthPath, sizeof (USB_DEVICE_PATH))) { >> >> + return EFI_NOT_FOUND; >> >> + } >> >> + } >> >> + } >> >> + >> >> + UsbEthPath =3D NextDevicePathNode (UsbEthPath); >> >> + UsbCdcDataPath =3D NextDevicePathNode (UsbCdcDataPath); >> >> + } >> >> +} >> >> + >> >> +/** >> >> + Check if the USB CDC Data(UsbIo) installed and return USB CDC Data >> Handle. >> >> + >> >> + @param[in] UsbEthPath A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> >> + @param[in, out] UsbCdcDataHandle A pointer to the EFI_HANDLE for >> USB CDC Data. >> >> + >> >> + @retval TRUE USB CDC Data(UsbIo) installed. >> >> + @retval FALSE USB CDC Data(UsbIo) did not installed. >> >> + >> >> +**/ >> >> +BOOLEAN >> >> +IsUsbCdcData ( >> >> + IN EFI_DEVICE_PATH_PROTOCOL *UsbEthPath, >> >> + IN OUT EFI_HANDLE *UsbCdcDataHandle >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINTN Index; >> >> + UINTN HandleCount; >> >> + EFI_HANDLE *HandleBuffer; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + EFI_USB_INTERFACE_DESCRIPTOR Interface; >> >> + EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath; >> >> + >> >> + Status =3D gBS->LocateHandleBuffer ( >> >> + ByProtocol, >> >> + &gEfiUsbIoProtocolGuid, >> >> + NULL, >> >> + &HandleCount, >> >> + &HandleBuffer >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return FALSE; >> >> + } >> >> + >> >> + for (Index =3D 0; Index < HandleCount; Index++) { >> >> + Status =3D gBS->HandleProtocol ( >> >> + HandleBuffer[Index], >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo >> >> + ); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + if ((Interface.InterfaceClass =3D=3D USB_CDC_DATA_CLASS) && >> >> + (Interface.InterfaceSubClass =3D=3D USB_CDC_DATA_SUBCLASS) && >> >> + (Interface.InterfaceProtocol =3D=3D USB_NO_CLASS_PROTOCOL)) >> >> + { >> >> + Status =3D gBS->HandleProtocol ( >> >> + HandleBuffer[Index], >> >> + &gEfiDevicePathProtocolGuid, >> >> + (VOID **)&UsbCdcDataPath >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + continue; >> >> + } >> >> + >> >> + Status =3D IsSameDevice (UsbEthPath, UsbCdcDataPath); >> >> + if (!EFI_ERROR (Status)) { >> >> + CopyMem (UsbCdcDataHandle, &HandleBuffer[Index], sizeof >> (EFI_HANDLE)); >> >> + gBS->FreePool (HandleBuffer); >> >> + return TRUE; >> >> + } >> >> + } >> >> + } >> >> + >> >> + gBS->FreePool (HandleBuffer); >> >> + return FALSE; >> >> +} >> >> + >> >> +/** >> >> + Call Back Function. >> >> + >> >> + @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 >> >> +CallbackFunction ( >> >> + IN EFI_EVENT Event, >> >> + IN VOID *Context >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINTN Index; >> >> + UINTN HandleCount; >> >> + EFI_HANDLE *HandleBuffer; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + EFI_USB_INTERFACE_DESCRIPTOR Interface; >> >> + >> >> + Status =3D gBS->LocateHandleBuffer ( >> >> + ByProtocol, >> >> + &gEfiUsbIoProtocolGuid, >> >> + NULL, >> >> + &HandleCount, >> >> + &HandleBuffer >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return; >> >> + } >> >> + >> >> + for (Index =3D 0; Index < HandleCount; Index++) { >> >> + Status =3D gBS->HandleProtocol ( >> >> + HandleBuffer[Index], >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo >> >> + ); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + if ((Interface.InterfaceClass =3D=3D USB_CDC_CLASS) && >> >> + (Interface.InterfaceSubClass =3D=3D USB_CDC_ECM_SUBCLASS) && >> >> + (Interface.InterfaceProtocol =3D=3D USB_NO_CLASS_PROTOCOL)) >> >> + { >> >> + gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE); >> >> + } >> >> + } >> >> + >> >> + gBS->FreePool (HandleBuffer); >> >> + gBS->CloseEvent (Event); >> >> +} >> >> + >> >> +/** >> >> + USB ECM Driver Binding Start. >> >> + >> >> + @param[in] This Protocol instance pointer. >> >> + @param[in] ControllerHandle Handle of device to bind driver t= o. >> >> + @param[in] RemainingDevicePath Optional parameter use to pick a >> specific child >> >> + device to start. >> >> + >> >> + @retval EFI_SUCCESS This driver is added to >> ControllerHandle >> >> + @retval EFI_DEVICE_ERROR This driver could not be started >> due to a device error >> >> + @retval EFI_OUT_OF_RESOURCES The driver could not install >> successfully due to a lack of resources. >> >> + @retval other This driver does not support this >> device >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEcmDriverStart ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + VOID *Reg; >> >> + EFI_EVENT Event; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + EFI_DEVICE_PATH_PROTOCOL *UsbEthPath; >> >> + EFI_HANDLE UsbCdcDataHandle; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + EFI_USB_INTERFACE_DESCRIPTOR Interface; >> >> + >> >> + Status =3D gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status =3D gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + (VOID **)&UsbEthPath, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return Status; >> >> + } >> >> + >> >> + Status =3D IsUsbCdcData (UsbEthPath, &UsbCdcDataHandle) ? EFI_SUCCESS= : >> EFI_UNSUPPORTED; >> >> + if (EFI_ERROR (Status)) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + >> >> + Status =3D gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, >> CallbackFunction, NULL, &Event); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status =3D gBS->RegisterProtocolNotify (&gEfiUsbIoProtocolGuid, Eve= nt, >> &Reg); >> >> + return Status; >> >> + } >> >> + >> >> + UsbEthDriver =3D AllocateZeroPool (sizeof (USB_ETHERNET_DRIVER)); >> >> + if (!UsbEthDriver) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return EFI_OUT_OF_RESOURCES; >> >> + } >> >> + >> >> + Status =3D LoadAllDescriptor (UsbIo, &UsbEthDriver->Config); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + GetEndpoint (UsbIo, UsbEthDriver); >> >> + >> >> + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + UsbEthDriver->Signature =3D >> USB_ETHERNET_SIGNATURE; >> >> + UsbEthDriver->NumOfInterface =3D >> Interface.InterfaceNumber; >> >> + UsbEthDriver->UsbCdcDataHandle =3D UsbCdcDataHandle= ; >> >> + UsbEthDriver->UsbIo =3D UsbIo; >> >> + UsbEthDriver->UsbEth.UsbEthReceive =3D UsbEthReceive; >> >> + UsbEthDriver->UsbEth.UsbEthTransmit =3D UsbEthTransmit; >> >> + UsbEthDriver->UsbEth.UsbEthInterrupt =3D UsbEthInterrupt; >> >> + UsbEthDriver->UsbEth.UsbEthMacAddress =3D GetUsbEthMacAddr= ess; >> >> + UsbEthDriver->UsbEth.UsbEthMaxBulkSize =3D UsbEthBulkSize; >> >> + UsbEthDriver->UsbEth.UsbHeaderFunDescriptor =3D >> GetUsbHeaderFunDescriptor; >> >> + UsbEthDriver->UsbEth.UsbUnionFunDescriptor =3D >> GetUsbUnionFunDescriptor; >> >> + UsbEthDriver->UsbEth.UsbEthFunDescriptor =3D >> GetUsbEthFunDescriptor; >> >> + UsbEthDriver->UsbEth.SetUsbEthMcastFilter =3D >> SetUsbEthMcastFilter; >> >> + UsbEthDriver->UsbEth.SetUsbEthPowerPatternFilter =3D >> SetUsbEthPowerFilter; >> >> + UsbEthDriver->UsbEth.GetUsbEthPoewrPatternFilter =3D >> GetUsbEthPowerFilter; >> >> + UsbEthDriver->UsbEth.SetUsbEthPacketFilter =3D >> SetUsbEthPacketFilter; >> >> + UsbEthDriver->UsbEth.GetUsbEthStatistic =3D GetUsbEthStatist= ic; >> >> + >> >> + Status =3D gBS->InstallProtocolInterface ( >> >> + &ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + EFI_NATIVE_INTERFACE, >> >> + &(UsbEthDriver->UsbEth) >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + gBS->FreePool (UsbEthDriver); >> >> + return Status; >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + USB ECM Driver Binding Stop. >> >> + >> >> + @param[in] This Protocol instance pointer. >> >> + @param[in] ControllerHandle Handle of device to stop driver on >> >> + @param[in] NumberOfChildren Number of Handles in >> ChildHandleBuffer. If number of >> >> + children is zero stop the entire bus >> driver. >> >> + @param[in] ChildHandleBuffer List of Child Handles to Stop. >> >> + >> >> + @retval EFI_SUCCESS This driver is removed ControllerHand= le >> >> + @retval other This driver was not removed from this >> device >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEcmDriverStop ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN UINTN NumberOfChildren, >> >> + IN EFI_HANDLE *ChildHandleBuffer >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_PROTOCOL *UsbEthProtocol; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + Status =3D gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + (VOID **)&UsbEthProtocol, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (UsbEthProtocol); >> >> + >> >> + Status =3D gBS->UninstallProtocolInterface ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + UsbEthProtocol >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status =3D gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + gBS->FreePool (UsbEthDriver->Config); >> >> + gBS->FreePool (UsbEthDriver); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Entrypoint of ECM Driver. >> >> + >> >> + This function is the entrypoint of ECM Driver. It installs Driver >> Binding >> >> + Protocols together with Component Name Protocols. >> >> + >> >> + @param[in] ImageHandle The firmware allocated handle for the >> EFI image. >> >> + @param[in] SystemTable A pointer to the EFI System Table. >> >> + >> >> + @retval EFI_SUCCESS The entry point is executed successfull= y. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEcmEntry ( >> >> + IN EFI_HANDLE ImageHandle, >> >> + IN EFI_SYSTEM_TABLE *SystemTable >> >> + ) >> >> +{ >> >> + gUsbEcmDriverBinding.DriverBindingHandle =3D ImageHandle; >> >> + gUsbEcmDriverBinding.ImageHandle =3D ImageHandle; >> >> + >> >> + return gBS->InstallMultipleProtocolInterfaces ( >> >> + &gUsbEcmDriverBinding.DriverBindingHandle, >> >> + &gEfiDriverBindingProtocolGuid, >> >> + &gUsbEcmDriverBinding, >> >> + &gEfiComponentName2ProtocolGuid, >> >> + &gUsbEcmComponentName2, >> >> + NULL >> >> + ); >> >> +} >> >> diff --git a/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.h >> b/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.h >> new file mode 100644 >> index 0000000000..52a818466e >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.h >> @@ -0,0 +1,211 @@ >> +/** @file >> >> + Header file contains code for USB Ethernet Control Model >> >> + driver definitions >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#ifndef _USB_CDC_ECM_H_ >> >> +#define _USB_CDC_ECM_H_ >> >> + >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> + >> >> +typedef struct { >> >> + UINTN Signature; >> >> + USB_ETHERNET_PROTOCOL UsbEth; >> >> + EFI_HANDLE UsbCdcDataHandle; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + EFI_USB_CONFIG_DESCRIPTOR *Config; >> >> + UINT8 NumOfInterface; >> >> + UINT8 BulkInEndpoint; >> >> + UINT8 BulkOutEndpoint; >> >> + UINT8 InterruptEndpoint; >> >> + EFI_MAC_ADDRESS MacAddress; >> >> +} USB_ETHERNET_DRIVER; >> >> + >> >> +#define USB_ECM_DRIVER_VERSION 1 >> >> +#define USB_ETHERNET_BULK_TIMEOUT 1 >> >> +#define USB_ETHERNET_TRANSFER_TIMEOUT 200 >> >> + >> >> +#define USB_ETHERNET_SIGNATURE SIGNATURE_32('u', 'e', 't', 'h') >> >> +#define USB_ETHERNET_DEV_FROM_THIS(a) CR (a, USB_ETHERNET_DRIVER, >> UsbEth, USB_ETHERNET_SIGNATURE) >> >> + >> >> +typedef struct { >> >> + UINT16 Src; >> >> + UINT16 Dst; >> >> +} BIT_MAP; >> >> + >> >> +extern EFI_COMPONENT_NAME2_PROTOCOL gUsbEcmComponentName2; >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEcmDriverSupported ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEcmDriverStart ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEcmDriverStop ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN UINTN NumberOfChildren, >> >> + IN EFI_HANDLE *ChildHandleBuffer >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +LoadAllDescriptor ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> >> + OUT EFI_USB_CONFIG_DESCRIPTOR **ConfigDesc >> >> + ); >> >> + >> >> +BOOLEAN >> >> +NextDescriptor ( >> >> + IN EFI_USB_CONFIG_DESCRIPTOR *Desc, >> >> + IN OUT UINTN *Offset >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +GetFunctionalDescriptor ( >> >> + IN EFI_USB_CONFIG_DESCRIPTOR *Config, >> >> + IN UINT8 FunDescriptorType, >> >> + OUT VOID *DataBuffer >> >> + ); >> >> + >> >> +VOID >> >> +GetEndpoint ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> >> + IN OUT USB_ETHERNET_DRIVER *UsbEthDriver >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthReceive ( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN OUT VOID *Packet, >> >> + IN OUT UINTN *PacketLength >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthTransmit ( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN VOID *Packet, >> >> + IN OUT UINTN *PacketLength >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthInterrupt ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN BOOLEAN IsNewTransfer, >> >> + IN UINTN PollingInterval, >> >> + IN EFI_USB_DEVICE_REQUEST *Request >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +InterruptCallback ( >> >> + IN VOID *Data, >> >> + IN UINTN DataLength, >> >> + IN VOID *Context, >> >> + IN UINT32 Status >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthMacAddress ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT EFI_MAC_ADDRESS *MacAddress >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthBulkSize ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT UINTN *BulkSize >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbHeaderFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbUnionFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbEthMcastFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN VOID *McastAddr >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbEthPowerFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN UINT16 Length, >> >> + IN VOID *PatternFilter >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthPowerFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + OUT BOOLEAN *PatternActive >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbEthPacketFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthStatistic ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 FeatureSelector, >> >> + OUT VOID *Statistic >> >> + ); >> >> + >> >> +#endif >> >> diff --git a/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf >> b/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf >> new file mode 100644 >> index 0000000000..ed031864c6 >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf >> @@ -0,0 +1,41 @@ >> +## @file >> +# This is Usb Cdc Ecm driver for DXE phase. >> +# >> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> +# Subject to AMI licensing agreement. >> +## >> + >> +[Defines] >> + INF_VERSION =3D 0x00010005 >> + BASE_NAME =3D UsbCdcEcm >> + FILE_GUID =3D 07a84945-685d-48ec-a6a1-1b397579fa= 76 >> + MODULE_TYPE =3D DXE_DRIVER >> + VERSION_STRING =3D 1.0 >> + ENTRY_POINT =3D UsbEcmEntry >> + >> +[Sources] >> + UsbCdcEcm.c >> + UsbCdcEcm.h >> + UsbEcmFunction.c >> + ComponentName.c >> + >> +[Packages] >> + MdePkg/MdePkg.dec >> + UsbNetworkPkg/UsbNetworkPkg.dec >> + >> +[LibraryClasses] >> + UefiDriverEntryPoint >> + UefiBootServicesTableLib >> + UefiLib >> + DebugLib >> + UefiUsbLib >> + MemoryAllocationLib >> + BaseMemoryLib >> + >> +[Protocols] >> + gEfiUsbIoProtocolGuid >> + gEfiDevicePathProtocolGuid >> + gEfiDriverBindingProtocolGuid >> + >> +[Depex] >> + TRUE >> diff --git a/UsbNetworkPkg/UsbCdcEcm/UsbEcmFunction.c >> b/UsbNetworkPkg/UsbCdcEcm/UsbEcmFunction.c >> new file mode 100644 >> index 0000000000..175addddc6 >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbCdcEcm/UsbEcmFunction.c >> @@ -0,0 +1,861 @@ >> +/** @file >> >> + This file contains code for USB Ethernet descriptor >> >> + and specific requests implement. >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#include "UsbCdcEcm.h" >> >> + >> >> +/** >> >> + Load All of device descriptor. >> >> + >> >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCO= L >> instance. >> >> + @param[out] ConfigDesc A pointer to the configuration >> descriptor. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_OUT_OF_RESOURCES The request could not be completed >> because the >> >> + buffer specified by DescriptorLength an= d >> Descriptor >> >> + is not large enough to hold the result >> of the request. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device >> error. The transfer >> >> + status is returned in Status. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +LoadAllDescriptor ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> >> + OUT EFI_USB_CONFIG_DESCRIPTOR **ConfigDesc >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINT32 TransStatus; >> >> + EFI_USB_CONFIG_DESCRIPTOR Tmp; >> >> + >> >> + Status =3D UsbIo->UsbGetConfigDescriptor (UsbIo, &Tmp); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status =3D gBS->AllocatePool (EfiBootServicesData, Tmp.TotalLength, >> (VOID **)ConfigDesc); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status =3D UsbGetDescriptor ( >> >> + UsbIo, >> >> + USB_DESC_TYPE_CONFIG << 8 | (Tmp.ConfigurationValue - 1), >> // zero based >> >> + 0, >> >> + Tmp.TotalLength, >> >> + *ConfigDesc, >> >> + &TransStatus >> >> + ); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Returns pointer to the next descriptor for the pack of USB descriptor= s >> >> + located in continues memory segment >> >> + >> >> + @param[in] Desc A pointer to the CONFIG_DESCRIPTOR instance. >> >> + @param[in, out] Offset A pointer to the sum of descriptor length. >> >> + >> >> + @retval TRUE The request executed successfully. >> >> + @retval FALSE No next descriptor. >> >> + >> >> +**/ >> >> +BOOLEAN >> >> +NextDescriptor ( >> >> + IN EFI_USB_CONFIG_DESCRIPTOR *Desc, >> >> + IN OUT UINTN *Offset >> >> + ) >> >> +{ >> >> + if ((Desc =3D=3D NULL) || (*Offset >=3D Desc->TotalLength)) { >> >> + return FALSE; >> >> + } >> >> + >> >> + if (((EFI_USB_CONFIG_DESCRIPTOR *)((char *)Desc+*Offset))->Length =3D= =3D >> 0) { >> >> + return FALSE; >> >> + } >> >> + >> >> + *Offset +=3D ((EFI_USB_CONFIG_DESCRIPTOR *)((char >> *)Desc+*Offset))->Length; >> >> + if ( *Offset >=3D Desc->TotalLength ) { >> >> + return FALSE; >> >> + } >> >> + >> >> + return TRUE; >> >> +} >> >> + >> >> +/** >> >> + Read Function descriptor >> >> + >> >> + @param[in] Config A pointer to all of configuration. >> >> + @param[in] FunDescriptorType USB CDC class descriptor SubType. >> >> + @param[out] DataBuffer A pointer to the Data of corresponding >> to device capability. >> >> + >> >> + @retval EFI_SUCCESS The device capability descriptor was >> retrieved >> >> + successfully. >> >> + @retval EFI_UNSUPPORTED No supported. >> >> + @retval EFI_NOT_FOUND The device capability descriptor was not >> found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +GetFunctionalDescriptor ( >> >> + IN EFI_USB_CONFIG_DESCRIPTOR *Config, >> >> + IN UINT8 FunDescriptorType, >> >> + OUT VOID *DataBuffer >> >> + ) >> >> +{ >> >> + EFI_STATUS Status =3D EFI_NOT_FOUND; >> >> + UINTN Offset; >> >> + EFI_USB_INTERFACE_DESCRIPTOR *Interface; >> >> + >> >> + for (Offset =3D 0; NextDescriptor (Config, &Offset);) { >> >> + Interface =3D (EFI_USB_INTERFACE_DESCRIPTOR *)((UINT8 *)Config + >> Offset); >> >> + if (Interface->DescriptorType =3D=3D CS_INTERFACE) { >> >> + if (((USB_HEADER_FUN_DESCRIPTOR *)Interface)->DescriptorSubtype = =3D=3D >> FunDescriptorType) { >> >> + switch (FunDescriptorType) { >> >> + case HEADER_FUN_DESCRIPTOR: >> >> + CopyMem ( >> >> + DataBuffer, >> >> + (USB_HEADER_FUN_DESCRIPTOR *)Interface, >> >> + sizeof (USB_HEADER_FUN_DESCRIPTOR) >> >> + ); >> >> + return EFI_SUCCESS; >> >> + case UNION_FUN_DESCRIPTOR: >> >> + CopyMem ( >> >> + DataBuffer, >> >> + (USB_UNION_FUN_DESCRIPTOR *)Interface, >> >> + ((USB_UNION_FUN_DESCRIPTOR *)Interface)->FunctionLength >> >> + ); >> >> + return EFI_SUCCESS; >> >> + case ETHERNET_FUN_DESCRIPTOR: >> >> + CopyMem ( >> >> + DataBuffer, >> >> + (USB_ETHERNET_FUN_DESCRIPTOR *)Interface, >> >> + sizeof (USB_ETHERNET_FUN_DESCRIPTOR) >> >> + ); >> >> + return EFI_SUCCESS; >> >> + default: >> >> + Status =3D EFI_UNSUPPORTED; >> >> + break; >> >> + } >> >> + } >> >> + } >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Get USB Ethernet IO endpoint and USB CDC data IO endpoint. >> >> + >> >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL >> instance. >> >> + @param[in, out] UsbEthDriver A pointer to the USB_ETHERNET_DRIVER >> instance. >> >> + >> >> +**/ >> >> +VOID >> >> +GetEndpoint ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> >> + IN OUT USB_ETHERNET_DRIVER *UsbEthDriver >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINT8 Index; >> >> + UINT32 Result; >> >> + EFI_USB_INTERFACE_DESCRIPTOR Interface; >> >> + EFI_USB_ENDPOINT_DESCRIPTOR Endpoint; >> >> + >> >> + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + if (Interface.NumEndpoints =3D=3D 0) { >> >> + Status =3D UsbSetInterface (UsbIo, Interface.InterfaceNumber, 1, >> &Result); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> >> + ASSERT_EFI_ERROR (Status); >> >> + } >> >> + >> >> + for (Index =3D 0; Index < Interface.NumEndpoints; Index++) { >> >> + Status =3D UsbIo->UsbGetEndpointDescriptor (UsbIo, Index, &Endpoint= ); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + switch ((Endpoint.Attributes & (BIT0 | BIT1))) { >> >> + case USB_ENDPOINT_BULK: >> >> + if (Endpoint.EndpointAddress & BIT7) { >> >> + UsbEthDriver->BulkInEndpoint =3D Endpoint.EndpointAddress; >> >> + } else { >> >> + UsbEthDriver->BulkOutEndpoint =3D Endpoint.EndpointAddress; >> >> + } >> >> + >> >> + break; >> >> + case USB_ENDPOINT_INTERRUPT: >> >> + UsbEthDriver->InterruptEndpoint =3D Endpoint.EndpointAddress; >> >> + break; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This function is used to manage a USB device with the bulk transfer >> pipe. The endpoint is Bulk in. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor >> block. >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in, out] Packet A pointer to the buffer of data that >> will be transmitted to USB >> >> + device or received from USB device. >> >> + @param[in, out] PacketLength A pointer to the PacketLength. >> >> + >> >> + @retval EFI_SUCCESS The bulk transfer has been successfully >> executed. >> >> + @retval EFI_DEVICE_ERROR The transfer failed. The transfer statu= s >> is returned in status. >> >> + @retval EFI_INVALID_PARAMETE One or more parameters are invalid. >> >> + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due >> to a lack of resources. >> >> + @retval EFI_TIMEOUT The control transfer fails due to >> timeout. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthReceive ( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN OUT VOID *Packet, >> >> + IN OUT UINTN *PacketLength >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + UINT32 TransStatus; >> >> + >> >> + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + Status =3D gBS->HandleProtocol ( >> >> + UsbEthDriver->UsbCdcDataHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + if (UsbEthDriver->BulkInEndpoint =3D=3D 0) { >> >> + GetEndpoint (UsbIo, UsbEthDriver); >> >> + } >> >> + >> >> + Status =3D UsbIo->UsbBulkTransfer ( >> >> + UsbIo, >> >> + UsbEthDriver->BulkInEndpoint, >> >> + Packet, >> >> + PacketLength, >> >> + USB_ETHERNET_BULK_TIMEOUT, >> >> + &TransStatus >> >> + ); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + This function is used to manage a USB device with the bulk transfer >> pipe. The endpoint is Bulk out. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor >> block. >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in] Packet A pointer to the buffer of data that >> will be transmitted to USB >> >> + device or received from USB device. >> >> + @param[in, out] PacketLength A pointer to the PacketLength. >> >> + >> >> + @retval EFI_SUCCESS The bulk transfer has been successfully >> executed. >> >> + @retval EFI_DEVICE_ERROR The transfer failed. The transfer statu= s >> is returned in status. >> >> + @retval EFI_INVALID_PARAMETE One or more parameters are invalid. >> >> + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due >> to a lack of resources. >> >> + @retval EFI_TIMEOUT The control transfer fails due to >> timeout. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthTransmit ( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN VOID *Packet, >> >> + IN OUT UINTN *PacketLength >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + UINT32 TransStatus; >> >> + >> >> + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + Status =3D gBS->HandleProtocol ( >> >> + UsbEthDriver->UsbCdcDataHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + if (UsbEthDriver->BulkOutEndpoint =3D=3D 0) { >> >> + GetEndpoint (UsbIo, UsbEthDriver); >> >> + } >> >> + >> >> + Status =3D UsbIo->UsbBulkTransfer ( >> >> + UsbIo, >> >> + UsbEthDriver->BulkOutEndpoint, >> >> + Packet, >> >> + PacketLength, >> >> + USB_ETHERNET_BULK_TIMEOUT, >> >> + &TransStatus >> >> + ); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Async USB transfer callback routine. >> >> + >> >> + @param[in] Data Data received or sent via the USB >> Asynchronous Transfer, if the >> >> + transfer completed successfully. >> >> + @param[in] DataLength The length of Data received or sent via >> the Asynchronous >> >> + Transfer, if transfer successfully >> completes. >> >> + @param[in] Context Data passed from >> UsbAsyncInterruptTransfer() request. >> >> + @param[in] Status Indicates the result of the asynchronous >> transfer. >> >> + >> >> + @retval EFI_SUCCESS The asynchronous USB transfer request >> has been successfully executed. >> >> + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request >> failed. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +InterruptCallback ( >> >> + IN VOID *Data, >> >> + IN UINTN DataLength, >> >> + IN VOID *Context, >> >> + IN UINT32 Status >> >> + ) >> >> +{ >> >> + if (((EFI_USB_DEVICE_REQUEST *)Data)->Request =3D=3D >> USB_CDC_NETWORK_CONNECTION) { >> >> + CopyMem ( >> >> + (EFI_USB_DEVICE_REQUEST *)Context, >> >> + (EFI_USB_DEVICE_REQUEST *)Data, >> >> + sizeof (EFI_USB_DEVICE_REQUEST) >> >> + ); >> >> + } >> >> + >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This function is used to manage a USB device with an interrupt >> transfer pipe. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in] IsNewTransfer If TRUE, a new transfer will be >> submitted to USB controller. If >> >> + FALSE, the interrupt transfer is delete= d >> from the device's interrupt >> >> + transfer queue. >> >> + @param[in] PollingInterval Indicates the periodic rate, in >> milliseconds, that the transfer is to be >> >> + executed.This parameter is required whe= n >> IsNewTransfer is TRUE. The >> >> + value must be between 1 to 255, >> otherwise EFI_INVALID_PARAMETER is returned. >> >> + The units are in milliseconds. >> >> + @param[in] Request A pointer to the EFI_USB_DEVICE_REQUEST >> data. >> >> + >> >> + @retval EFI_SUCCESS The asynchronous USB transfer request >> transfer has been successfully executed. >> >> + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request >> failed. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthInterrupt ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN BOOLEAN IsNewTransfer, >> >> + IN UINTN PollingInterval, >> >> + IN EFI_USB_DEVICE_REQUEST *Request >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + UINTN DataLength =3D 0; >> >> + >> >> + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); >> >> + if (IsNewTransfer =3D=3D TRUE) { >> >> + DataLength =3D sizeof (EFI_USB_DEVICE_REQUEST) + sizeof >> (USB_CONNECT_SPEED_CHANGE); >> >> + Status =3D UsbEthDriver->UsbIo->UsbAsyncInterruptTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + UsbEthDriver->InterruptEndpoint= , >> >> + IsNewTransfer, >> >> + PollingInterval, >> >> + DataLength, >> >> + >> (EFI_ASYNC_USB_TRANSFER_CALLBACK)InterruptCallback, >> >> + Request >> >> + ); >> >> + } else { >> >> + Status =3D UsbEthDriver->UsbIo->UsbAsyncInterruptTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + UsbEthDriver->InterruptEndpoint, >> >> + IsNewTransfer, >> >> + 0, >> >> + 0, >> >> + NULL, >> >> + NULL >> >> + ); >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Ethernet Mac Address. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[out] MacAddress A pointer to the caller allocated USB >> Ethernet Mac Address. >> >> + >> >> + @retval EFI_SUCCESS The USB Header Functional descriptor wa= s >> retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor wa= s >> not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthMacAddress ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT EFI_MAC_ADDRESS *MacAddress >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthDescriptor; >> >> + CHAR16 *Data; >> >> + CHAR16 *DataPtr; >> >> + CHAR16 TmpStr[1]; >> >> + UINT8 Index; >> >> + UINT8 Hi; >> >> + UINT8 Low; >> >> + >> >> + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + Status =3D This->UsbEthFunDescriptor (This, &UsbEthDescriptor); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status =3D UsbEthDriver->UsbIo->UsbGetStringDescriptor ( >> >> + UsbEthDriver->UsbIo, >> >> + 0x409, // >> English-US Language ID >> >> + UsbEthDescriptor.MacAddress, >> >> + &Data >> >> + ); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + DataPtr =3D Data; >> >> + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> >> + CopyMem (TmpStr, DataPtr, sizeof (CHAR16)); >> >> + DataPtr++; >> >> + Hi =3D (UINT8)StrHexToUintn (TmpStr); >> >> + CopyMem (TmpStr, DataPtr, sizeof (CHAR16)); >> >> + DataPtr++; >> >> + Low =3D (UINT8)StrHexToUintn (TmpStr); >> >> + MacAddress->Addr[Index] =3D (Hi << 4) | Low; >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Ethernet Bulk transfer data size. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[out] BulkSize A pointer to the Bulk transfer data size. >> >> + >> >> + @retval EFI_SUCCESS The bulk transfer data size was retrieved >> successfully. >> >> + @retval other Failed to retrieve the bulk transfer data >> size. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthBulkSize ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT UINTN *BulkSize >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; >> >> + >> >> + Status =3D This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + *BulkSize =3D (UINTN)UsbEthFunDescriptor.MaxSegmentSize; >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Header functional Descriptor. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[out] UsbHeaderFunDescriptor A pointer to the caller allocated >> USB Header Functional Descriptor. >> >> + >> >> + @retval EFI_SUCCESS The USB Header Functional descriptor wa= s >> retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor wa= s >> not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbHeaderFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + if (UsbHeaderFunDescriptor =3D=3D NULL) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + Status =3D GetFunctionalDescriptor (UsbEthDriver->Config, >> HEADER_FUN_DESCRIPTOR, UsbHeaderFunDescriptor); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Union functional Descriptor. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[out] UsbUnionFunDescriptor A pointer to the caller allocated >> USB Union Functional Descriptor. >> >> + >> >> + @retval EFI_SUCCESS The USB Union Functional descriptor was >> retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbUnionFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Union Functional descriptor was >> not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbUnionFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + if (UsbUnionFunDescriptor =3D=3D NULL) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + Status =3D GetFunctionalDescriptor (UsbEthDriver->Config, >> UNION_FUN_DESCRIPTOR, UsbUnionFunDescriptor); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Ethernet functional Descriptor. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[out] UsbEthFunDescriptor A pointer to the caller allocated >> USB Ethernet Functional Descriptor. >> >> + >> >> + @retval EFI_SUCCESS The USB Ethernet Functional descriptor >> was retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbEthFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Ethernet Functional descriptor >> was not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + if (UsbEthFunDescriptor =3D=3D NULL) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + Status =3D GetFunctionalDescriptor (UsbEthDriver->Config, >> ETHERNET_FUN_DESCRIPTOR, UsbEthFunDescriptor); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + This request sets the Ethernet device multicast filters as specified >> in the >> >> + sequential list of 48 bit Ethernet multicast addresses. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] Value Number of filters. >> >> + @param[in] McastAddr A pointer to the value of the >> multicast addresses. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbEthMcastFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN VOID *McastAddr >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> + UINT32 TransStatus; >> >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + Status =3D This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + if ((UsbEthFunDescriptor.NumberMcFilters << 1) =3D=3D 0) { >> >> + return EFI_UNSUPPORTED; >> >> + } >> >> + >> >> + Request.RequestType =3D USB_ETHRTNET_SET_REQ_TYPE; >> >> + Request.Request =3D SET_ETH_MULTICAST_FILTERS_REQ; >> >> + Request.Value =3D Value; >> >> + Request.Index =3D UsbEthDriver->NumOfInterface; >> >> + Request.Length =3D Value * 6; >> >> + >> >> + return UsbEthDriver->UsbIo->UsbControlTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + &Request, >> >> + EfiUsbDataOut, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + McastAddr, >> >> + Request.Length, >> >> + &TransStatus >> >> + ); >> >> +} >> >> + >> >> +/** >> >> + This request sets up the specified Ethernet power management pattern >> filter as >> >> + described in the data structure. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] Value Number of filters. >> >> + @param[in] Length Size of the power management patter= n >> filter data. >> >> + @param[in] PatternFilter A pointer to the power management >> pattern filter structure. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbEthPowerFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN UINT16 Length, >> >> + IN VOID *PatternFilter >> >> + ) >> >> +{ >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> + UINT32 TransStatus; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + Request.RequestType =3D USB_ETHRTNET_SET_REQ_TYPE; >> >> + Request.Request =3D SET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ; >> >> + Request.Value =3D Value; >> >> + Request.Index =3D UsbEthDriver->NumOfInterface; >> >> + Request.Length =3D Length; >> >> + >> >> + return UsbEthDriver->UsbIo->UsbControlTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + &Request, >> >> + EfiUsbDataOut, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + PatternFilter, >> >> + Length, >> >> + &TransStatus >> >> + ); >> >> +} >> >> + >> >> +/** >> >> + This request retrieves the status of the specified Ethernet power >> management >> >> + pattern filter from the device. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] Value The filter number. >> >> + @param[out] PatternActive A pointer to the pattern active >> boolean. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthPowerFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + OUT BOOLEAN *PatternActive >> >> + ) >> >> +{ >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> + UINT32 TransStatus; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + Request.RequestType =3D USB_ETHERNET_GET_REQ_TYPE; >> >> + Request.Request =3D GET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ; >> >> + Request.Value =3D Value; >> >> + Request.Index =3D UsbEthDriver->NumOfInterface; >> >> + Request.Length =3D USB_ETH_POWER_FILTER_LENGTH; >> >> + >> >> + return UsbEthDriver->UsbIo->UsbControlTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + &Request, >> >> + EfiUsbDataIn, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + PatternActive, >> >> + USB_ETH_POWER_FILTER_LENGTH, >> >> + &TransStatus >> >> + ); >> >> +} >> >> + >> >> +BIT_MAP gTable[] =3D { >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_UNICAST, >> USB_ETH_PACKET_TYPE_DIRECTED }, >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST, >> USB_ETH_PACKET_TYPE_BROADCAST }, >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST, >> USB_ETH_PACKET_TYPE_MULTICAST }, >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS, >> USB_ETH_PACKET_TYPE_PROMISCUOUS }, >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST, >> USB_ETH_PACKET_TYPE_ALL_MULTICAST }, >> >> +}; >> >> + >> >> +/** >> >> + Convert value between PXE receive filter and USB ETH packet filter. >> >> + >> >> + @param[in] Value PXE filter data. >> >> + @param[out] CdcFilter A pointer to the Ethernet Packet Filter Bitmap >> value converted by PXE_OPFLAGS. >> >> + >> >> +**/ >> >> +VOID >> >> +ConvertFilter ( >> >> + IN UINT16 Value, >> >> + OUT UINT16 *CdcFilter >> >> + ) >> >> +{ >> >> + UINT32 Index; >> >> + UINT32 Count; >> >> + >> >> + Count =3D sizeof (gTable)/sizeof (gTable[0]); >> >> + >> >> + for (Index =3D 0; (gTable[Index].Src !=3D 0) && (Index < Count); Inde= x++) { >> >> + if (gTable[Index].Src & Value) { >> >> + *CdcFilter |=3D gTable[Index].Dst; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This request is used to configure device Ethernet packet filter >> settings. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in] Value Packet Filter Bitmap. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbEthPacketFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value >> >> + ) >> >> +{ >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> + UINT32 TransStatus; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + UINT16 CommandFilter =3D 0; >> >> + >> >> + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + ConvertFilter (Value, &CommandFilter); >> >> + >> >> + Request.RequestType =3D USB_ETHRTNET_SET_REQ_TYPE; >> >> + Request.Request =3D SET_ETH_PACKET_FILTER_REQ; >> >> + Request.Value =3D CommandFilter; >> >> + Request.Index =3D UsbEthDriver->NumOfInterface; >> >> + Request.Length =3D USB_ETH_PACKET_FILTER_LENGTH; >> >> + >> >> + return UsbEthDriver->UsbIo->UsbControlTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + &Request, >> >> + EfiUsbNoData, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + NULL, >> >> + USB_ETH_PACKET_FILTER_LENGTH, >> >> + &TransStatus >> >> + ); >> >> +} >> >> + >> >> +/** >> >> + This request is used to retrieve a statistic based on the feature >> selector. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] FeatureSelector Value of the feature selector. >> >> + @param[out] Statistic A pointer to the 32 bit unsigned >> integer. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthStatistic ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 FeatureSelector, >> >> + OUT VOID *Statistic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> + UINT32 TransStatus; >> >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + Status =3D This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + if (UsbEthFunDescriptor.EthernetStatistics =3D=3D 0) { >> >> + return EFI_UNSUPPORTED; >> >> + } >> >> + >> >> + Request.RequestType =3D USB_ETHERNET_GET_REQ_TYPE; >> >> + Request.Request =3D GET_ETH_STATISTIC_REQ; >> >> + Request.Value =3D FeatureSelector; >> >> + Request.Index =3D UsbEthDriver->NumOfInterface; >> >> + Request.Length =3D USB_ETH_STATISTIC; >> >> + >> >> + return UsbEthDriver->UsbIo->UsbControlTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + &Request, >> >> + EfiUsbDataIn, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + Statistic, >> >> + USB_ETH_STATISTIC, >> >> + &TransStatus >> >> + ); >> >> +} >> >> diff --git a/UsbNetworkPkg/UsbCdcNcm/ComponentName.c >> b/UsbNetworkPkg/UsbCdcNcm/ComponentName.c >> new file mode 100644 >> index 0000000000..36792b89c5 >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbCdcNcm/ComponentName.c >> @@ -0,0 +1,170 @@ >> +/** @file >> >> + This file contains code for USB Ncm Driver Component Name definitions >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> +#include "UsbCdcNcm.h" >> >> + >> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE >> gUsbNcmDriverNameTable[] =3D { >> >> + { >> >> + "eng;en", >> >> + L"USB NCM Driver" >> >> + }, >> >> + { >> >> + NULL, >> >> + NULL >> >> + } >> >> +}; >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbNcmComponentNameGetDriverName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **DriverName >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbNcmComponentNameGetControllerName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN EFI_HANDLE Controller, >> >> + IN EFI_HANDLE ChildHandle OPTIONAL, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **ControllerName >> >> + ); >> >> + >> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL >> gUsbNcmComponentName =3D { >> >> + UsbNcmComponentNameGetDriverName, >> >> + UsbNcmComponentNameGetControllerName, >> >> + "eng" >> >> +}; >> >> + >> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL >> gUsbNcmComponentName2 =3D { >> >> + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)UsbNcmComponentNameGetDriverName= , >> >> + >> (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)UsbNcmComponentNameGetControlle= rName, >> >> + "en" >> >> +}; >> >> + >> >> +/** >> >> + Retrieves a Unicode string that is the user readable name of the >> driver. >> >> + >> >> + This function retrieves the user readable name of a driver in the for= m >> of a >> >> + Unicode string. If the driver specified by This has a user readable >> name in >> >> + the language specified by Language, then a pointer to the driver name >> is >> >> + returned in DriverName, and EFI_SUCCESS is returned. If the driver >> specified >> >> + by This does not support the language specified by Language, >> >> + then EFI_UNSUPPORTED is returned. >> >> + >> >> + @param[in] This A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >> >> + EFI_COMPONENT_NAME_PROTOCOL instance. >> >> + @param[in] Language A pointer to a Null-terminated ASCII >> string >> >> + array indicating the language. This is >> the >> >> + language of the driver name that the >> caller is >> >> + requesting, and it must match one of th= e >> >> + languages specified in >> SupportedLanguages. The >> >> + number of languages supported by a >> driver is up >> >> + to the driver writer. Language is >> specified >> >> + in RFC 4646 or ISO 639-2 language code >> format. >> >> + @param[out] DriverName A pointer to the Unicode string to >> return. >> >> + This Unicode string is the name of the >> >> + driver specified by This in the languag= e >> >> + specified by Language. >> >> + >> >> + @retval EFI_SUCCESS The Unicode string for the Driver >> specified by >> >> + This and the language specified by >> Language was >> >> + returned in DriverName. >> >> + @retval EFI_INVALID_PARAMETER Language is NULL. >> >> + @retval EFI_INVALID_PARAMETER DriverName is NULL. >> >> + @retval EFI_UNSUPPORTED The driver specified by This does not >> support >> >> + the language specified by Language. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbNcmComponentNameGetDriverName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **DriverName >> >> + ) >> >> +{ >> >> + return LookupUnicodeString2 ( >> >> + Language, >> >> + This->SupportedLanguages, >> >> + gUsbNcmDriverNameTable, >> >> + DriverName, >> >> + (BOOLEAN)(This =3D=3D &gUsbNcmComponentName) >> >> + ); >> >> +} >> >> + >> >> +/** >> >> + Retrieves a Unicode string that is the user readable name of the >> controller >> >> + that is being managed by a driver. >> >> + >> >> + This function retrieves the user readable name of the controller >> specified by >> >> + ControllerHandle and ChildHandle in the form of a Unicode string. If >> the >> >> + driver specified by This has a user readable name in the language >> specified by >> >> + Language, then a pointer to the controller name is returned in >> ControllerName, >> >> + and EFI_SUCCESS is returned. If the driver specified by This is not >> currently >> >> + managing the controller specified by ControllerHandle and ChildHandle= , >> >> + then EFI_UNSUPPORTED is returned. If the driver specified by This >> does not >> >> + support the language specified by Language, then EFI_UNSUPPORTED is >> returned. >> >> + >> >> + @param[in] This A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >> >> + EFI_COMPONENT_NAME_PROTOCOL instance. >> >> + @param[in] Controller The handle of a controller that the >> driver >> >> + specified by This is managing. This >> handle >> >> + specifies the controller whose name is >> to be >> >> + returned. >> >> + @param[in] ChildHandle The handle of the child controller to >> retrieve >> >> + the name of. This is an optional >> parameter that >> >> + may be NULL. It will be NULL for devic= e >> >> + drivers. It will also be NULL for a bu= s >> drivers >> >> + that wish to retrieve the name of the b= us >> >> + controller. It will not be NULL for a >> bus >> >> + driver that wishes to retrieve the name >> of a >> >> + child controller. >> >> + @param[in] Language A pointer to a Null-terminated ASCII >> string >> >> + array indicating the language. This is >> the >> >> + language of the driver name that the >> caller is >> >> + requesting, and it must match one of th= e >> >> + languages specified in >> SupportedLanguages. The >> >> + number of languages supported by a >> driver is up >> >> + to the driver writer. Language is >> specified in >> >> + RFC 4646 or ISO 639-2 language code >> format. >> >> + @param[out] ControllerName A pointer to the Unicode string to >> return. >> >> + This Unicode string is the name of the >> >> + controller specified by ControllerHandl= e >> and >> >> + ChildHandle in the language specified b= y >> >> + Language from the point of view of the >> driver >> >> + specified by This. >> >> + >> >> + @retval EFI_SUCCESS The Unicode string for the user readabl= e >> name in >> >> + the language specified by Language for >> the >> >> + driver specified by This was returned i= n >> >> + DriverName. >> >> + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid >> EFI_HANDLE. >> >> + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a >> valid >> >> + EFI_HANDLE. >> >> + @retval EFI_INVALID_PARAMETER Language is NULL. >> >> + @retval EFI_INVALID_PARAMETER ControllerName is NULL. >> >> + @retval EFI_UNSUPPORTED The driver specified by This is not >> currently >> >> + managing the controller specified by >> >> + ControllerHandle and ChildHandle. >> >> + @retval EFI_UNSUPPORTED The driver specified by This does not >> support >> >> + the language specified by Language. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbNcmComponentNameGetControllerName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN EFI_HANDLE Controller, >> >> + IN EFI_HANDLE ChildHandle OPTIONAL, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **ControllerName >> >> + ) >> >> +{ >> >> + return EFI_UNSUPPORTED; >> >> +} >> >> diff --git a/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.c >> b/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.c >> new file mode 100644 >> index 0000000000..fc7cbd8132 >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.c >> @@ -0,0 +1,508 @@ >> +/** @file >> >> + This file contains code for USB Network Control Model >> >> + binding driver >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#include "UsbCdcNcm.h" >> >> + >> >> +EFI_GUID gUsbEthProtocolGuid =3D USB_ETHERNET_PROTOCOL_GUID; >> >> + >> >> +EFI_DRIVER_BINDING_PROTOCOL gUsbNcmDriverBinding =3D { >> >> + UsbNcmDriverSupported, >> >> + UsbNcmDriverStart, >> >> + UsbNcmDriverStop, >> >> + USB_NCM_DRIVER_VERSION, >> >> + NULL, >> >> + NULL >> >> +}; >> >> + >> >> +/** >> >> + Check if this interface is USB NCM SubType >> >> + >> >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance. >> >> + >> >> + @retval TRUE USB NCM SubType. >> >> + @retval FALSE Not USB NCM SubType. >> >> + >> >> +**/ >> >> +BOOLEAN >> >> +IsSupportedDevice ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; >> >> + >> >> + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, >> &InterfaceDescriptor); >> >> + if (EFI_ERROR (Status)) { >> >> + return FALSE; >> >> + } >> >> + >> >> + if ((InterfaceDescriptor.InterfaceClass =3D=3D USB_CDC_CLASS) && >> >> + (InterfaceDescriptor.InterfaceSubClass =3D=3D USB_CDC_NCM_SUBCLAS= S) && >> >> + (InterfaceDescriptor.InterfaceProtocol =3D=3D USB_NO_CLASS_PROTOC= OL)) >> >> + { >> >> + return TRUE; >> >> + } >> >> + >> >> + return FALSE; >> >> +} >> >> + >> >> +/** >> >> + USB NCM Driver Binding Support. >> >> + >> >> + @param[in] This Protocol instance pointer. >> >> + @param[in] ControllerHandle Handle of device to test. >> >> + @param[in] RemainingDevicePath Optional parameter use to pick a >> specific child >> >> + device to start. >> >> + >> >> + @retval EFI_SUCCESS This driver supports this device. >> >> + @retval EFI_ALREADY_STARTED This driver is already running on >> this device. >> >> + @retval other This driver does not support this >> device. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbNcmDriverSupported ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_IO_PROTOCOL *UsbIo =3D NULL; >> >> + >> >> + Status =3D gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status =3D IsSupportedDevice (UsbIo) ? EFI_SUCCESS : EFI_UNSUPPORTED; >> >> + >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Check if the USB NCM and USB CDC Data interfaces are from the same >> device. >> >> + >> >> + @param[in] UsbEthPath A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> >> + @param[in] UsbCdcDataPath A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> >> + >> >> + @retval EFI_SUCCESS Is the same device. >> >> + @retval EFI_NOT_FOUND Is not the same device. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +IsSameDevice ( >> >> + IN EFI_DEVICE_PATH_PROTOCOL *UsbEthPath, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath >> >> + ) >> >> +{ >> >> + while (1) { >> >> + if ((UsbEthPath->Type =3D=3D ACPI_DEVICE_PATH) && (UsbEthPath->SubT= ype >> =3D=3D ACPI_DP)) { >> >> + if (CompareMem ((ACPI_HID_DEVICE_PATH *)UsbCdcDataPath, >> (ACPI_HID_DEVICE_PATH *)UsbEthPath, sizeof (ACPI_HID_DEVICE_PATH))) { >> >> + return EFI_NOT_FOUND; >> >> + } >> >> + } >> >> + >> >> + if ((UsbEthPath->Type =3D=3D HARDWARE_DEVICE_PATH) && >> (UsbEthPath->SubType =3D=3D HW_PCI_DP)) { >> >> + if (CompareMem ((PCI_DEVICE_PATH *)UsbCdcDataPath, >> (PCI_DEVICE_PATH *)UsbEthPath, sizeof (PCI_DEVICE_PATH))) { >> >> + return EFI_NOT_FOUND; >> >> + } >> >> + } >> >> + >> >> + if ((UsbEthPath->Type =3D=3D MESSAGING_DEVICE_PATH) && >> (UsbEthPath->SubType =3D=3D MSG_USB_DP)) { >> >> + if (IsDevicePathEnd (NextDevicePathNode (UsbEthPath))) { >> >> + if (((USB_DEVICE_PATH *)UsbEthPath)->ParentPortNumber =3D=3D >> >> + ((USB_DEVICE_PATH *)UsbCdcDataPath)->ParentPortNumber) >> >> + { >> >> + return EFI_SUCCESS; >> >> + } else { >> >> + return EFI_NOT_FOUND; >> >> + } >> >> + } else { >> >> + if (CompareMem ((USB_DEVICE_PATH *)UsbCdcDataPath, >> (USB_DEVICE_PATH *)UsbEthPath, sizeof (USB_DEVICE_PATH))) { >> >> + return EFI_NOT_FOUND; >> >> + } >> >> + } >> >> + } >> >> + >> >> + UsbEthPath =3D NextDevicePathNode (UsbEthPath); >> >> + UsbCdcDataPath =3D NextDevicePathNode (UsbCdcDataPath); >> >> + } >> >> +} >> >> + >> >> +/** >> >> + Check if the USB CDC Data(UsbIo) installed and return USB CDC Data >> Handle. >> >> + >> >> + @param[in] UsbEthPath A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> >> + @param[in, out] UsbCdcDataHandle A pointer to the EFI_HANDLE for >> USB CDC Data. >> >> + >> >> + @retval TRUE USB CDC Data(UsbIo) installed. >> >> + @retval FALSE USB CDC Data(UsbIo) did not installed. >> >> + >> >> +**/ >> >> +BOOLEAN >> >> +IsUsbCdcData ( >> >> + IN EFI_DEVICE_PATH_PROTOCOL *UsbEthPath, >> >> + IN OUT EFI_HANDLE *UsbCdcDataHandle >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINTN Index; >> >> + UINTN HandleCount; >> >> + EFI_HANDLE *HandleBuffer; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + EFI_USB_INTERFACE_DESCRIPTOR Interface; >> >> + EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath; >> >> + >> >> + Status =3D gBS->LocateHandleBuffer ( >> >> + ByProtocol, >> >> + &gEfiUsbIoProtocolGuid, >> >> + NULL, >> >> + &HandleCount, >> >> + &HandleBuffer >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return FALSE; >> >> + } >> >> + >> >> + for (Index =3D 0; Index < HandleCount; Index++) { >> >> + Status =3D gBS->HandleProtocol ( >> >> + HandleBuffer[Index], >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo >> >> + ); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + if ((Interface.InterfaceClass =3D=3D USB_CDC_DATA_CLASS) && >> >> + (Interface.InterfaceSubClass =3D=3D USB_CDC_DATA_SUBCLASS) && >> >> + (Interface.InterfaceProtocol =3D=3D USB_NCM_NTB_PROTOCOL)) >> >> + { >> >> + Status =3D gBS->HandleProtocol ( >> >> + HandleBuffer[Index], >> >> + &gEfiDevicePathProtocolGuid, >> >> + (VOID **)&UsbCdcDataPath >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + continue; >> >> + } >> >> + >> >> + Status =3D IsSameDevice (UsbEthPath, UsbCdcDataPath); >> >> + if (!EFI_ERROR (Status)) { >> >> + CopyMem (UsbCdcDataHandle, &HandleBuffer[Index], sizeof >> (EFI_HANDLE)); >> >> + gBS->FreePool (HandleBuffer); >> >> + return TRUE; >> >> + } >> >> + } >> >> + } >> >> + >> >> + gBS->FreePool (HandleBuffer); >> >> + return FALSE; >> >> +} >> >> + >> >> +/** >> >> + Call Back Function. >> >> + >> >> + @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 >> >> +CallbackFunction ( >> >> + IN EFI_EVENT Event, >> >> + IN VOID *Context >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINTN Index; >> >> + UINTN HandleCount; >> >> + EFI_HANDLE *HandleBuffer; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + EFI_USB_INTERFACE_DESCRIPTOR Interface; >> >> + >> >> + Status =3D gBS->LocateHandleBuffer ( >> >> + ByProtocol, >> >> + &gEfiUsbIoProtocolGuid, >> >> + NULL, >> >> + &HandleCount, >> >> + &HandleBuffer >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return; >> >> + } >> >> + >> >> + for (Index =3D 0; Index < HandleCount; Index++) { >> >> + Status =3D gBS->HandleProtocol ( >> >> + HandleBuffer[Index], >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo >> >> + ); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + if ((Interface.InterfaceClass =3D=3D USB_CDC_CLASS) && >> >> + (Interface.InterfaceSubClass =3D=3D USB_CDC_NCM_SUBCLASS) && >> >> + (Interface.InterfaceProtocol =3D=3D USB_NO_CLASS_PROTOCOL)) >> >> + { >> >> + gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE); >> >> + } >> >> + } >> >> + >> >> + gBS->FreePool (HandleBuffer); >> >> + gBS->CloseEvent (Event); >> >> +} >> >> + >> >> +/** >> >> + USB NCM Driver Binding Start. >> >> + >> >> + @param[in] This Protocol instance pointer. >> >> + @param[in] ControllerHandle Handle of device to bind driver t= o. >> >> + @param[in] RemainingDevicePath Optional parameter use to pick a >> specific child >> >> + device to start. >> >> + >> >> + @retval EFI_SUCCESS This driver is added to >> ControllerHandle >> >> + @retval EFI_DEVICE_ERROR This driver could not be started >> due to a device error >> >> + @retval EFI_OUT_OF_RESOURCES The driver could not install >> successfully due to a lack of resources. >> >> + @retval other This driver does not support this >> device >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbNcmDriverStart ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + VOID *Reg; >> >> + EFI_EVENT Event; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + EFI_DEVICE_PATH_PROTOCOL *UsbEthPath; >> >> + EFI_HANDLE UsbCdcDataHandle; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + EFI_USB_INTERFACE_DESCRIPTOR Interface; >> >> + >> >> + Status =3D gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status =3D gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + (VOID **)&UsbEthPath, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return Status; >> >> + } >> >> + >> >> + Status =3D IsUsbCdcData (UsbEthPath, &UsbCdcDataHandle) ? EFI_SUCCESS= : >> EFI_UNSUPPORTED; >> >> + if (EFI_ERROR (Status)) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + >> >> + Status =3D gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, >> CallbackFunction, NULL, &Event); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status =3D gBS->RegisterProtocolNotify (&gEfiUsbIoProtocolGuid, Eve= nt, >> &Reg); >> >> + return Status; >> >> + } >> >> + >> >> + UsbEthDriver =3D AllocateZeroPool (sizeof (USB_ETHERNET_DRIVER)); >> >> + if (!UsbEthDriver) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return EFI_OUT_OF_RESOURCES; >> >> + } >> >> + >> >> + Status =3D LoadAllDescriptor (UsbIo, &UsbEthDriver->Config); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + GetEndpoint (UsbIo, UsbEthDriver); >> >> + >> >> + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + UsbEthDriver->Signature =3D >> USB_ETHERNET_SIGNATURE; >> >> + UsbEthDriver->NumOfInterface =3D >> Interface.InterfaceNumber; >> >> + UsbEthDriver->UsbCdcDataHandle =3D UsbCdcDataHandle= ; >> >> + UsbEthDriver->UsbIo =3D UsbIo; >> >> + UsbEthDriver->UsbEth.UsbEthReceive =3D UsbEthReceive; >> >> + UsbEthDriver->UsbEth.UsbEthTransmit =3D UsbEthTransmit; >> >> + UsbEthDriver->UsbEth.UsbEthInterrupt =3D UsbEthInterrupt; >> >> + UsbEthDriver->UsbEth.UsbEthMacAddress =3D GetUsbEthMacAddr= ess; >> >> + UsbEthDriver->UsbEth.UsbEthMaxBulkSize =3D UsbEthBulkSize; >> >> + UsbEthDriver->UsbEth.UsbHeaderFunDescriptor =3D >> GetUsbHeaderFunDescriptor; >> >> + UsbEthDriver->UsbEth.UsbUnionFunDescriptor =3D >> GetUsbUnionFunDescriptor; >> >> + UsbEthDriver->UsbEth.UsbEthFunDescriptor =3D >> GetUsbEthFunDescriptor; >> >> + UsbEthDriver->UsbEth.SetUsbEthMcastFilter =3D >> SetUsbEthMcastFilter; >> >> + UsbEthDriver->UsbEth.SetUsbEthPowerPatternFilter =3D >> SetUsbEthPowerFilter; >> >> + UsbEthDriver->UsbEth.GetUsbEthPoewrPatternFilter =3D >> GetUsbEthPowerFilter; >> >> + UsbEthDriver->UsbEth.SetUsbEthPacketFilter =3D >> SetUsbEthPacketFilter; >> >> + UsbEthDriver->UsbEth.GetUsbEthStatistic =3D GetUsbEthStatist= ic; >> >> + >> >> + UsbEthDriver->BulkBuffer =3D AllocateZeroPool (USB_NCM_MAX_NTB_SIZE); >> >> + >> >> + Status =3D gBS->InstallProtocolInterface ( >> >> + &ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + EFI_NATIVE_INTERFACE, >> >> + &(UsbEthDriver->UsbEth) >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + gBS->FreePool (UsbEthDriver); >> >> + return Status; >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + USB NCM Driver Binding Stop. >> >> + >> >> + @param[in] This Protocol instance pointer. >> >> + @param[in] ControllerHandle Handle of device to stop driver on >> >> + @param[in] NumberOfChildren Number of Handles in >> ChildHandleBuffer. If number of >> >> + children is zero stop the entire bu= s >> driver. >> >> + @param[in] ChildHandleBuffer List of Child Handles to Stop. >> >> + >> >> + @retval EFI_SUCCESS This driver is removed >> ControllerHandle >> >> + @retval other This driver was not removed from >> this device >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbNcmDriverStop ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN UINTN NumberOfChildren, >> >> + IN EFI_HANDLE *ChildHandleBuffer >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_PROTOCOL *UsbEthProtocol; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + Status =3D gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + (VOID **)&UsbEthProtocol, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (UsbEthProtocol); >> >> + >> >> + Status =3D gBS->UninstallProtocolInterface ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + UsbEthProtocol >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status =3D gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + gBS->FreePool (UsbEthDriver->Config); >> >> + gBS->FreePool (UsbEthDriver->BulkBuffer); >> >> + gBS->FreePool (UsbEthDriver); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Entrypoint of NCM Driver. >> >> + >> >> + This function is the entrypoint of NCM Driver. It installs Driver >> Binding >> >> + Protocols together with Component Name Protocols. >> >> + >> >> + @param[in] ImageHandle The firmware allocated handle for the >> EFI image. >> >> + @param[in] SystemTable A pointer to the EFI System Table. >> >> + >> >> + @retval EFI_SUCCESS The entry point is executed successfull= y. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbNcmEntry ( >> >> + IN EFI_HANDLE ImageHandle, >> >> + IN EFI_SYSTEM_TABLE *SystemTable >> >> + ) >> >> +{ >> >> + gUsbNcmDriverBinding.DriverBindingHandle =3D ImageHandle; >> >> + gUsbNcmDriverBinding.ImageHandle =3D ImageHandle; >> >> + >> >> + return gBS->InstallMultipleProtocolInterfaces ( >> >> + &gUsbNcmDriverBinding.DriverBindingHandle, >> >> + &gEfiDriverBindingProtocolGuid, >> >> + &gUsbNcmDriverBinding, >> >> + &gEfiComponentName2ProtocolGuid, >> >> + &gUsbNcmComponentName2, >> >> + NULL >> >> + ); >> >> +} >> >> diff --git a/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.h >> b/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.h >> new file mode 100644 >> index 0000000000..40b2671a1e >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.h >> @@ -0,0 +1,245 @@ >> +/** @file >> >> + Header file for USB Network Control Model driver >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#ifndef _USB_CDC_NCM_H_ >> >> +#define _USB_CDC_NCM_H_ >> >> + >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> + >> >> +typedef struct { >> >> + UINTN Signature; >> >> + USB_ETHERNET_PROTOCOL UsbEth; >> >> + EFI_HANDLE UsbCdcDataHandle; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + EFI_USB_CONFIG_DESCRIPTOR *Config; >> >> + UINT8 NumOfInterface; >> >> + UINT8 BulkInEndpoint; >> >> + UINT8 BulkOutEndpoint; >> >> + UINT8 InterruptEndpoint; >> >> + EFI_MAC_ADDRESS MacAddress; >> >> + UINT16 BulkOutSequence; >> >> + UINT8 *BulkBuffer; >> >> + UINT8 TotalDatagram; >> >> + UINT8 NowDatagram; >> >> +} USB_ETHERNET_DRIVER; >> >> + >> >> +#define USB_NCM_DRIVER_VERSION 1 >> >> +#define USB_ETHERNET_BULK_TIMEOUT 1 >> >> +#define USB_ETHERNET_TRANSFER_TIMEOUT 200 >> >> +#define USB_NCM_MAX_NTB_SIZE 0xFFFF >> >> +#define USB_ETH_FRAME_SIZE 0x5F2 // frome network stack sn= p >> >> + >> >> +// Defined in USB NCM 1.0 spec., section 3.2 and 3.3 >> >> +#define USB_NCM_NTH_SIGN_16 0x484D434E >> >> +#define USB_NCM_NDP_SIGN_16 0x304D434E >> >> +#define USB_NCM_NDP_SIGN_16_CRC 0x314D434E >> >> +#define USB_NCM_NTH_LENGTH 0x000C >> >> +#define USB_NCM_NDP_LENGTH 0x0010// at least 16 >> >> + >> >> +// USB NCM Transfer header structure - UINT16 >> >> +typedef struct { >> >> + UINT32 Signature; >> >> + UINT16 HeaderLength; >> >> + UINT16 Sequence; >> >> + UINT16 BlockLength; >> >> + UINT16 NdpIndex; >> >> +} USB_NCM_TRANSFER_HEADER_16; >> >> + >> >> +// USB NCM Datagram pointer structure - UINT16 >> >> +typedef struct { >> >> + UINT32 Signature; >> >> + UINT16 Length; >> >> + UINT16 NextNdpIndex; >> >> +} USB_NCM_DATAGRAM_POINTER_16; >> >> + >> >> +// USB NCM Datagram structure >> >> +typedef struct { >> >> + UINT16 DatagramIndex; >> >> + UINT16 DatagramLength; >> >> +} USB_NCM_DATA_GRAM; >> >> + >> >> +#define USB_ETHERNET_SIGNATURE SIGNATURE_32('u', 'e', 't', 'h') >> >> +#define USB_ETHERNET_DEV_FROM_THIS(a) CR (a, USB_ETHERNET_DRIVER, >> UsbEth, USB_ETHERNET_SIGNATURE) >> >> + >> >> +typedef struct { >> >> + UINT16 Src; >> >> + UINT16 Dst; >> >> +} BIT_MAP; >> >> + >> >> +extern EFI_COMPONENT_NAME2_PROTOCOL gUsbNcmComponentName2; >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbNcmDriverSupported ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbNcmDriverStart ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbNcmDriverStop ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN UINTN NumberOfChildren, >> >> + IN EFI_HANDLE *ChildHandleBuffer >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +LoadAllDescriptor ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> >> + OUT EFI_USB_CONFIG_DESCRIPTOR **ConfigDesc >> >> + ); >> >> + >> >> +BOOLEAN >> >> +NextDescriptor ( >> >> + IN EFI_USB_CONFIG_DESCRIPTOR *Desc, >> >> + IN OUT UINTN *Offset >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +GetFunctionalDescriptor ( >> >> + IN EFI_USB_CONFIG_DESCRIPTOR *Config, >> >> + IN UINT8 FunDescriptorType, >> >> + OUT VOID *DataBuffer >> >> + ); >> >> + >> >> +VOID >> >> +GetEndpoint ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> >> + IN OUT USB_ETHERNET_DRIVER *UsbEthDriver >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthReceive ( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN OUT VOID *Packet, >> >> + IN OUT UINTN *PacketLength >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthTransmit ( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN VOID *Packet, >> >> + IN OUT UINTN *PacketLength >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthInterrupt ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN BOOLEAN IsNewTransfer, >> >> + IN UINTN PollingInterval, >> >> + IN EFI_USB_DEVICE_REQUEST *Request >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +InterruptCallback ( >> >> + IN VOID *Data, >> >> + IN UINTN DataLength, >> >> + IN VOID *Context, >> >> + IN UINT32 Status >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthMacAddress ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT EFI_MAC_ADDRESS *MacAddress >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthBulkSize ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT UINTN *BulkSize >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbHeaderFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbUnionFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbEthMcastFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN VOID *McastAddr >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbEthPowerFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN UINT16 Length, >> >> + IN VOID *PatternFilter >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthPowerFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + OUT BOOLEAN *PatternActive >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbEthPacketFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthStatistic ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 FeatureSelector, >> >> + OUT VOID *Statistic >> >> + ); >> >> + >> >> +#endif >> >> diff --git a/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf >> b/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf >> new file mode 100644 >> index 0000000000..cfbf9ad720 >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf >> @@ -0,0 +1,41 @@ >> +## @file >> +# This is Usb Cdc Ncm driver for DXE phase. >> +# >> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> +# Subject to AMI licensing agreement. >> +## >> + >> +[Defines] >> + INF_VERSION =3D 0x00010005 >> + BASE_NAME =3D UsbCdcNcm >> + FILE_GUID =3D 52230d31-6c11-4442-b262-bec6bfe84e= fa >> + MODULE_TYPE =3D DXE_DRIVER >> + VERSION_STRING =3D 1.0 >> + ENTRY_POINT =3D UsbNcmEntry >> + >> +[Sources] >> + UsbCdcNcm.c >> + UsbCdcNcm.h >> + UsbNcmFunction.c >> + ComponentName.c >> + >> +[Packages] >> + MdePkg/MdePkg.dec >> + UsbNetworkPkg/UsbNetworkPkg.dec >> + >> +[LibraryClasses] >> + UefiDriverEntryPoint >> + UefiBootServicesTableLib >> + UefiLib >> + DebugLib >> + UefiUsbLib >> + MemoryAllocationLib >> + BaseMemoryLib >> + >> +[Protocols] >> + gEfiUsbIoProtocolGuid >> + gEfiDevicePathProtocolGuid >> + gEfiDriverBindingProtocolGuid >> + >> +[Depex] >> + TRUE >> \ No newline at end of file >> diff --git a/UsbNetworkPkg/UsbCdcNcm/UsbNcmFunction.c >> b/UsbNetworkPkg/UsbCdcNcm/UsbNcmFunction.c >> new file mode 100644 >> index 0000000000..98bcf6d6d5 >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbCdcNcm/UsbNcmFunction.c >> @@ -0,0 +1,946 @@ >> +/** @file >> >> + This file contains code for USB Ethernet descriptor >> >> + and specific requests implement. >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#include "UsbCdcNcm.h" >> >> + >> >> +/** >> >> + Load All of device descriptor. >> >> + >> >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCO= L >> instance. >> >> + @param[out] ConfigDesc A pointer to the configuration >> descriptor. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_OUT_OF_RESOURCES The request could not be completed >> because the >> >> + buffer specified by DescriptorLength an= d >> Descriptor >> >> + is not large enough to hold the result >> of the request. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device >> error. The transfer >> >> + status is returned in Status. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +LoadAllDescriptor ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> >> + OUT EFI_USB_CONFIG_DESCRIPTOR **ConfigDesc >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINT32 TransStatus; >> >> + EFI_USB_CONFIG_DESCRIPTOR Tmp; >> >> + >> >> + Status =3D UsbIo->UsbGetConfigDescriptor (UsbIo, &Tmp); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status =3D gBS->AllocatePool (EfiBootServicesData, Tmp.TotalLength, >> (VOID **)ConfigDesc); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status =3D UsbGetDescriptor ( >> >> + UsbIo, >> >> + USB_DESC_TYPE_CONFIG << 8 | (Tmp.ConfigurationValue - 1), >> // zero based >> >> + 0, >> >> + Tmp.TotalLength, >> >> + *ConfigDesc, >> >> + &TransStatus >> >> + ); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Returns pointer to the next descriptor for the pack of USB descriptor= s >> >> + located in continues memory segment >> >> + >> >> + @param[in] Desc A pointer to the CONFIG_DESCRIPTOR instance. >> >> + @param[in, out] Offset A pointer to the sum of descriptor length. >> >> + >> >> + @retval TRUE The request executed successfully. >> >> + @retval FALSE No next descriptor. >> >> + >> >> +**/ >> >> +BOOLEAN >> >> +NextDescriptor ( >> >> + IN EFI_USB_CONFIG_DESCRIPTOR *Desc, >> >> + IN OUT UINTN *Offset >> >> + ) >> >> +{ >> >> + if ((Desc =3D=3D NULL) || (*Offset >=3D Desc->TotalLength)) { >> >> + return FALSE; >> >> + } >> >> + >> >> + if (((EFI_USB_CONFIG_DESCRIPTOR *)((char *)Desc+*Offset))->Length =3D= =3D >> 0) { >> >> + return FALSE; >> >> + } >> >> + >> >> + *Offset +=3D ((EFI_USB_CONFIG_DESCRIPTOR *)((char >> *)Desc+*Offset))->Length; >> >> + if ( *Offset >=3D Desc->TotalLength ) { >> >> + return FALSE; >> >> + } >> >> + >> >> + return TRUE; >> >> +} >> >> + >> >> +/** >> >> + Read Function descriptor >> >> + >> >> + @param[in] Config A pointer to all of configuration. >> >> + @param[in] FunDescriptorType USB CDC class descriptor SubType. >> >> + @param[out] DataBuffer A pointer to the Data of corresponding >> to device capability. >> >> + >> >> + @retval EFI_SUCCESS The device capability descriptor was >> retrieved >> >> + successfully. >> >> + @retval EFI_UNSUPPORTED No supported. >> >> + @retval EFI_NOT_FOUND The device capability descriptor was not >> found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +GetFunctionalDescriptor ( >> >> + IN EFI_USB_CONFIG_DESCRIPTOR *Config, >> >> + IN UINT8 FunDescriptorType, >> >> + OUT VOID *DataBuffer >> >> + ) >> >> +{ >> >> + EFI_STATUS Status =3D EFI_NOT_FOUND; >> >> + UINTN Offset; >> >> + EFI_USB_INTERFACE_DESCRIPTOR *Interface; >> >> + >> >> + for (Offset =3D 0; NextDescriptor (Config, &Offset);) { >> >> + Interface =3D (EFI_USB_INTERFACE_DESCRIPTOR *)((UINT8 *)Config + >> Offset); >> >> + if (Interface->DescriptorType =3D=3D CS_INTERFACE) { >> >> + if (((USB_HEADER_FUN_DESCRIPTOR *)Interface)->DescriptorSubtype = =3D=3D >> FunDescriptorType) { >> >> + switch (FunDescriptorType) { >> >> + case HEADER_FUN_DESCRIPTOR: >> >> + CopyMem ( >> >> + DataBuffer, >> >> + (USB_HEADER_FUN_DESCRIPTOR *)Interface, >> >> + sizeof (USB_HEADER_FUN_DESCRIPTOR) >> >> + ); >> >> + return EFI_SUCCESS; >> >> + case UNION_FUN_DESCRIPTOR: >> >> + CopyMem ( >> >> + DataBuffer, >> >> + (USB_UNION_FUN_DESCRIPTOR *)Interface, >> >> + ((USB_UNION_FUN_DESCRIPTOR *)Interface)->FunctionLength >> >> + ); >> >> + return EFI_SUCCESS; >> >> + case ETHERNET_FUN_DESCRIPTOR: >> >> + CopyMem ( >> >> + DataBuffer, >> >> + (USB_ETHERNET_FUN_DESCRIPTOR *)Interface, >> >> + sizeof (USB_ETHERNET_FUN_DESCRIPTOR) >> >> + ); >> >> + return EFI_SUCCESS; >> >> + default: >> >> + Status =3D EFI_UNSUPPORTED; >> >> + break; >> >> + } >> >> + } >> >> + } >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Get USB Ethernet IO endpoint and USB CDC data IO endpoint. >> >> + >> >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL >> instance. >> >> + @param[in, out] UsbEthDriver A pointer to the USB_ETHERNET_DRIVER >> instance. >> >> + >> >> +**/ >> >> +VOID >> >> +GetEndpoint ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> >> + IN OUT USB_ETHERNET_DRIVER *UsbEthDriver >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINT8 Index; >> >> + UINT32 Result; >> >> + EFI_USB_INTERFACE_DESCRIPTOR Interface; >> >> + EFI_USB_ENDPOINT_DESCRIPTOR Endpoint; >> >> + >> >> + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + if (Interface.NumEndpoints =3D=3D 0) { >> >> + Status =3D UsbSetInterface (UsbIo, Interface.InterfaceNumber, 1, >> &Result); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> >> + ASSERT_EFI_ERROR (Status); >> >> + } >> >> + >> >> + for (Index =3D 0; Index < Interface.NumEndpoints; Index++) { >> >> + Status =3D UsbIo->UsbGetEndpointDescriptor (UsbIo, Index, &Endpoint= ); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + switch ((Endpoint.Attributes & (BIT0 | BIT1))) { >> >> + case USB_ENDPOINT_BULK: >> >> + if (Endpoint.EndpointAddress & BIT7) { >> >> + UsbEthDriver->BulkInEndpoint =3D Endpoint.EndpointAddress; >> >> + } else { >> >> + UsbEthDriver->BulkOutEndpoint =3D Endpoint.EndpointAddress; >> >> + } >> >> + >> >> + break; >> >> + case USB_ENDPOINT_INTERRUPT: >> >> + UsbEthDriver->InterruptEndpoint =3D Endpoint.EndpointAddress; >> >> + break; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This function is used to manage a USB device with the bulk transfer >> pipe. The endpoint is Bulk in. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor >> block. >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in, out] Packet A pointer to the buffer of data that >> will be transmitted to USB >> >> + device or received from USB device. >> >> + @param[in, out] PacketLength A pointer to the PacketLength. >> >> + >> >> + @retval EFI_SUCCESS The bulk transfer has been successfully >> executed. >> >> + @retval EFI_DEVICE_ERROR The transfer failed. The transfer statu= s >> is returned in status. >> >> + @retval EFI_INVALID_PARAMETE One or more parameters are invalid. >> >> + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due >> to a lack of resources. >> >> + @retval EFI_TIMEOUT The control transfer fails due to >> timeout. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthReceive ( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN OUT VOID *Packet, >> >> + IN OUT UINTN *PacketLength >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + UINT32 TransStatus; >> >> + UINT8 Index; >> >> + UINTN BulkDataLenght; >> >> + UINTN TotalLength =3D 0; >> >> + USB_NCM_TRANSFER_HEADER_16 *Nth; >> >> + USB_NCM_DATAGRAM_POINTER_16 *Ndp; >> >> + USB_NCM_DATA_GRAM *Datagram; >> >> + >> >> + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + if (UsbEthDriver->TotalDatagram =3D=3D UsbEthDriver->NowDatagram) { >> >> + Status =3D gBS->HandleProtocol ( >> >> + UsbEthDriver->UsbCdcDataHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + if (UsbEthDriver->BulkInEndpoint =3D=3D 0) { >> >> + GetEndpoint (UsbIo, UsbEthDriver); >> >> + } >> >> + >> >> + BulkDataLenght =3D USB_NCM_MAX_NTB_SIZE; >> >> + SetMem (UsbEthDriver->BulkBuffer, BulkDataLenght, 0); >> >> + UsbEthDriver->NowDatagram =3D 0; >> >> + UsbEthDriver->TotalDatagram =3D 0; >> >> + >> >> + Status =3D UsbIo->UsbBulkTransfer ( >> >> + UsbIo, >> >> + UsbEthDriver->BulkInEndpoint, >> >> + UsbEthDriver->BulkBuffer, >> >> + &BulkDataLenght, >> >> + USB_ETHERNET_BULK_TIMEOUT, >> >> + &TransStatus >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Nth =3D (USB_NCM_TRANSFER_HEADER_16 >> *)UsbEthDriver->BulkBuffer; >> >> + Ndp =3D (USB_NCM_DATAGRAM_POINTER_16 *)((UI= NT8 >> *)UsbEthDriver->BulkBuffer + Nth->NdpIndex); >> >> + Datagram =3D (USB_NCM_DATA_GRAM *)((UINT8 *)Ndp = + >> sizeof (USB_NCM_DATAGRAM_POINTER_16)); >> >> + UsbEthDriver->TotalDatagram =3D (UINT8)((Ndp->Length - 8) / 4 - 1); >> >> + >> >> + for (Index =3D 0; Index < UsbEthDriver->TotalDatagram; Index++) { >> >> + TotalLength +=3D Datagram->DatagramLength; >> >> + Datagram =3D (USB_NCM_DATA_GRAM *)((UINT8 *)Datagram + sizeof >> (USB_NCM_DATA_GRAM)); >> >> + } >> >> + >> >> + if (TotalLength < USB_ETH_FRAME_SIZE) { >> >> + Datagram =3D (USB_NCM_DATA_GRAM *)((UINT8 *)Ndp + sizeof >> (USB_NCM_DATAGRAM_POINTER_16)); >> >> + >> >> + TotalLength =3D 0; >> >> + for (Index =3D 0; Index < UsbEthDriver->TotalDatagram; Index++) { >> >> + CopyMem ((UINT8 *)Packet + TotalLength, (UINT8 >> *)UsbEthDriver->BulkBuffer + Datagram->DatagramIndex, >> Datagram->DatagramLength); >> >> + TotalLength +=3D Datagram->DatagramLength; >> >> + Datagram =3D (USB_NCM_DATA_GRAM *)((UINT8 *)Datagram + size= of >> (USB_NCM_DATA_GRAM)); >> >> + } >> >> + >> >> + *PacketLength =3D TotalLength; >> >> + UsbEthDriver->NowDatagram =3D UsbEthDriver->TotalDatagram; >> >> + } else { >> >> + UsbEthDriver->NowDatagram++; >> >> + >> >> + Datagram =3D (USB_NCM_DATA_GRAM *)((UINT8 *)Ndp + sizeof >> (USB_NCM_DATAGRAM_POINTER_16)); >> >> + CopyMem (Packet, (UINT8 *)UsbEthDriver->BulkBuffer + >> Datagram->DatagramIndex, Datagram->DatagramLength); >> >> + *PacketLength =3D Datagram->DatagramLength; >> >> + } >> >> + >> >> + return Status; >> >> + } else { >> >> + UsbEthDriver->NowDatagram++; >> >> + >> >> + Nth =3D (USB_NCM_TRANSFER_HEADER_16 *)UsbEthDriver->BulkBuffer= ; >> >> + Ndp =3D (USB_NCM_DATAGRAM_POINTER_16 *)((UINT8 >> *)UsbEthDriver->BulkBuffer + Nth->NdpIndex); >> >> + Datagram =3D (USB_NCM_DATA_GRAM *)((UINT8 *)Ndp + sizeof >> (USB_NCM_DATAGRAM_POINTER_16)); >> >> + Datagram =3D (USB_NCM_DATA_GRAM *)((UINT8 *)Datagram + sizeof >> (USB_NCM_DATA_GRAM) * (UsbEthDriver->NowDatagram - 1)); >> >> + >> >> + CopyMem (Packet, (UINT8 *)UsbEthDriver->BulkBuffer + >> Datagram->DatagramIndex, Datagram->DatagramLength); >> >> + *PacketLength =3D Datagram->DatagramLength; >> >> + >> >> + return EFI_SUCCESS; >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This function is used to manage a USB device with the bulk transfer >> pipe. The endpoint is Bulk out. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor >> block. >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in] Packet A pointer to the buffer of data that >> will be transmitted to USB >> >> + device or received from USB device. >> >> + @param[in, out] PacketLength A pointer to the PacketLength. >> >> + >> >> + @retval EFI_SUCCESS The bulk transfer has been successfully >> executed. >> >> + @retval EFI_DEVICE_ERROR The transfer failed. The transfer statu= s >> is returned in status. >> >> + @retval EFI_INVALID_PARAMETE One or more parameters are invalid. >> >> + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due >> to a lack of resources. >> >> + @retval EFI_TIMEOUT The control transfer fails due to >> timeout. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthTransmit ( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN VOID *Packet, >> >> + IN OUT UINTN *PacketLength >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + UINT32 TransStatus; >> >> + USB_NCM_TRANSFER_HEADER_16 *Nth; >> >> + USB_NCM_DATAGRAM_POINTER_16 *Ndp; >> >> + USB_NCM_DATA_GRAM *Datagram; >> >> + UINT8 *TotalPacket; >> >> + UINTN TotalLength; >> >> + >> >> + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + Status =3D gBS->HandleProtocol ( >> >> + UsbEthDriver->UsbCdcDataHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + if (UsbEthDriver->BulkOutEndpoint =3D=3D 0) { >> >> + GetEndpoint (UsbIo, UsbEthDriver); >> >> + } >> >> + >> >> + TotalLength =3D (UINTN)(USB_NCM_NTH_LENGTH + USB_NCM_NDP_LENGTH + >> (*PacketLength)); >> >> + >> >> + Status =3D gBS->AllocatePool (EfiBootServicesData, TotalLength, (VOID >> **)&TotalPacket); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + SetMem (TotalPacket, TotalLength, 0); >> >> + >> >> + Nth =3D (USB_NCM_TRANSFER_HEADER_16 *)TotalPacket; >> >> + Nth->Signature =3D USB_NCM_NTH_SIGN_16; >> >> + Nth->HeaderLength =3D USB_NCM_NTH_LENGTH; >> >> + Nth->Sequence =3D UsbEthDriver->BulkOutSequence++; >> >> + Nth->BlockLength =3D (UINT16)TotalLength; >> >> + Nth->NdpIndex =3D Nth->HeaderLength; >> >> + >> >> + Ndp =3D (USB_NCM_DATAGRAM_POINTER_16 *)((UINT8 >> *)TotalPacket + Nth->NdpIndex); >> >> + Ndp->Signature =3D USB_NCM_NDP_SIGN_16; >> >> + Ndp->Length =3D USB_NCM_NDP_LENGTH; >> >> + Ndp->NextNdpIndex =3D 0x00; >> >> + >> >> + Datagram =3D (USB_NCM_DATA_GRAM *)((UINT8 *)Ndp + siz= eof >> (USB_NCM_DATAGRAM_POINTER_16)); >> >> + Datagram->DatagramIndex =3D Nth->HeaderLength + Ndp->Length; >> >> + Datagram->DatagramLength =3D (UINT16)*PacketLength; >> >> + >> >> + CopyMem (TotalPacket + Datagram->DatagramIndex, Packet, *PacketLength= ); >> >> + >> >> + *PacketLength =3D TotalLength; >> >> + >> >> + Status =3D UsbIo->UsbBulkTransfer ( >> >> + UsbIo, >> >> + UsbEthDriver->BulkOutEndpoint, >> >> + TotalPacket, >> >> + PacketLength, >> >> + USB_ETHERNET_BULK_TIMEOUT, >> >> + &TransStatus >> >> + ); >> >> + gBS->FreePool (TotalPacket); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Async USB transfer callback routine. >> >> + >> >> + @param[in] Data Data received or sent via the USB >> Asynchronous Transfer, if the >> >> + transfer completed successfully. >> >> + @param[in] DataLength The length of Data received or sent via >> the Asynchronous >> >> + Transfer, if transfer successfully >> completes. >> >> + @param[in] Context Data passed from >> UsbAsyncInterruptTransfer() request. >> >> + @param[in] Status Indicates the result of the asynchronous >> transfer. >> >> + >> >> + @retval EFI_SUCCESS The asynchronous USB transfer request >> has been successfully executed. >> >> + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request >> failed. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +InterruptCallback ( >> >> + IN VOID *Data, >> >> + IN UINTN DataLength, >> >> + IN VOID *Context, >> >> + IN UINT32 Status >> >> + ) >> >> +{ >> >> + if (((EFI_USB_DEVICE_REQUEST *)Data)->Request =3D=3D >> USB_CDC_NETWORK_CONNECTION) { >> >> + CopyMem ( >> >> + (EFI_USB_DEVICE_REQUEST *)Context, >> >> + (EFI_USB_DEVICE_REQUEST *)Data, >> >> + sizeof (EFI_USB_DEVICE_REQUEST) >> >> + ); >> >> + } >> >> + >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This function is used to manage a USB device with an interrupt >> transfer pipe. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in] IsNewTransfer If TRUE, a new transfer will be >> submitted to USB controller. If >> >> + FALSE, the interrupt transfer is delete= d >> from the device's interrupt >> >> + transfer queue. >> >> + @param[in] PollingInterval Indicates the periodic rate, in >> milliseconds, that the transfer is to be >> >> + executed.This parameter is required whe= n >> IsNewTransfer is TRUE. The >> >> + value must be between 1 to 255, >> otherwise EFI_INVALID_PARAMETER is returned. >> >> + The units are in milliseconds. >> >> + @param[in] Request A pointer to the EFI_USB_DEVICE_REQUEST >> data. >> >> + >> >> + @retval EFI_SUCCESS The asynchronous USB transfer request >> transfer has been successfully executed. >> >> + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request >> failed. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthInterrupt ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN BOOLEAN IsNewTransfer, >> >> + IN UINTN PollingInterval, >> >> + IN EFI_USB_DEVICE_REQUEST *Request >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + UINTN DataLength =3D 0; >> >> + >> >> + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); >> >> + if (IsNewTransfer =3D=3D TRUE) { >> >> + DataLength =3D sizeof (EFI_USB_DEVICE_REQUEST) + sizeof >> (USB_CONNECT_SPEED_CHANGE); >> >> + Status =3D UsbEthDriver->UsbIo->UsbAsyncInterruptTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + UsbEthDriver->InterruptEndpoint= , >> >> + IsNewTransfer, >> >> + PollingInterval, >> >> + DataLength, >> >> + >> (EFI_ASYNC_USB_TRANSFER_CALLBACK)InterruptCallback, >> >> + Request >> >> + ); >> >> + } else { >> >> + Status =3D UsbEthDriver->UsbIo->UsbAsyncInterruptTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + UsbEthDriver->InterruptEndpoint, >> >> + IsNewTransfer, >> >> + 0, >> >> + 0, >> >> + NULL, >> >> + NULL >> >> + ); >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Ethernet Mac Address. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[out] MacAddress A pointer to the caller allocated USB >> Ethernet Mac Address. >> >> + >> >> + @retval EFI_SUCCESS The USB Header Functional descriptor wa= s >> retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor wa= s >> not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthMacAddress ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT EFI_MAC_ADDRESS *MacAddress >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthDescriptor; >> >> + CHAR16 *Data; >> >> + CHAR16 *DataPtr; >> >> + CHAR16 TmpStr[1]; >> >> + UINT8 Index; >> >> + UINT8 Hi; >> >> + UINT8 Low; >> >> + >> >> + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + Status =3D This->UsbEthFunDescriptor (This, &UsbEthDescriptor); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status =3D UsbEthDriver->UsbIo->UsbGetStringDescriptor ( >> >> + UsbEthDriver->UsbIo, >> >> + 0x409, // >> English-US Language ID >> >> + UsbEthDescriptor.MacAddress, >> >> + &Data >> >> + ); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + DataPtr =3D Data; >> >> + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> >> + CopyMem (TmpStr, DataPtr, sizeof (CHAR16)); >> >> + DataPtr++; >> >> + Hi =3D (UINT8)StrHexToUintn (TmpStr); >> >> + CopyMem (TmpStr, DataPtr, sizeof (CHAR16)); >> >> + DataPtr++; >> >> + Low =3D (UINT8)StrHexToUintn (TmpStr); >> >> + MacAddress->Addr[Index] =3D (Hi << 4) | Low; >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Get the USB NCM max NTB size. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[out] BulkSize A pointer to the Bulk transfer data size. >> >> + >> >> + @retval EFI_SUCCESS Get the USB NCM max NTB size >> successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthBulkSize ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT UINTN *BulkSize >> >> + ) >> >> +{ >> >> + *BulkSize =3D USB_NCM_MAX_NTB_SIZE; >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Header functional Descriptor. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[out] UsbHeaderFunDescriptor A pointer to the caller allocated >> USB Header Functional Descriptor. >> >> + >> >> + @retval EFI_SUCCESS The USB Header Functional descriptor wa= s >> retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor wa= s >> not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbHeaderFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + if (UsbHeaderFunDescriptor =3D=3D NULL) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + Status =3D GetFunctionalDescriptor (UsbEthDriver->Config, >> HEADER_FUN_DESCRIPTOR, UsbHeaderFunDescriptor); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Union functional Descriptor. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[out] UsbUnionFunDescriptor A pointer to the caller allocated >> USB Union Functional Descriptor. >> >> + >> >> + @retval EFI_SUCCESS The USB Union Functional descriptor was >> retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbUnionFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Union Functional descriptor was >> not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbUnionFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + if (UsbUnionFunDescriptor =3D=3D NULL) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + Status =3D GetFunctionalDescriptor (UsbEthDriver->Config, >> UNION_FUN_DESCRIPTOR, UsbUnionFunDescriptor); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Ethernet functional Descriptor. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[out] UsbEthFunDescriptor A pointer to the caller allocated >> USB Ethernet Functional Descriptor. >> >> + >> >> + @retval EFI_SUCCESS The USB Ethernet Functional descriptor >> was retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbEthFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Ethernet Functional descriptor >> was not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + if (UsbEthFunDescriptor =3D=3D NULL) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + Status =3D GetFunctionalDescriptor (UsbEthDriver->Config, >> ETHERNET_FUN_DESCRIPTOR, UsbEthFunDescriptor); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + This request sets the Ethernet device multicast filters as specified >> in the >> >> + sequential list of 48 bit Ethernet multicast addresses. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] Value Number of filters. >> >> + @param[in] McastAddr A pointer to the value of the >> multicast addresses. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbEthMcastFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN VOID *McastAddr >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> + UINT32 TransStatus; >> >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + Status =3D This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + if ((UsbEthFunDescriptor.NumberMcFilters << 1) =3D=3D 0) { >> >> + return EFI_UNSUPPORTED; >> >> + } >> >> + >> >> + Request.RequestType =3D USB_ETHRTNET_SET_REQ_TYPE; >> >> + Request.Request =3D SET_ETH_MULTICAST_FILTERS_REQ; >> >> + Request.Value =3D Value; >> >> + Request.Index =3D UsbEthDriver->NumOfInterface; >> >> + Request.Length =3D Value * 6; >> >> + >> >> + return UsbEthDriver->UsbIo->UsbControlTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + &Request, >> >> + EfiUsbDataOut, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + McastAddr, >> >> + Request.Length, >> >> + &TransStatus >> >> + ); >> >> +} >> >> + >> >> +/** >> >> + This request sets up the specified Ethernet power management pattern >> filter as >> >> + described in the data structure. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] Value Number of filters. >> >> + @param[in] Length Size of the power management patter= n >> filter data. >> >> + @param[in] PatternFilter A pointer to the power management >> pattern filter structure. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbEthPowerFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN UINT16 Length, >> >> + IN VOID *PatternFilter >> >> + ) >> >> +{ >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> + UINT32 TransStatus; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + Request.RequestType =3D USB_ETHRTNET_SET_REQ_TYPE; >> >> + Request.Request =3D SET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ; >> >> + Request.Value =3D Value; >> >> + Request.Index =3D UsbEthDriver->NumOfInterface; >> >> + Request.Length =3D Length; >> >> + >> >> + return UsbEthDriver->UsbIo->UsbControlTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + &Request, >> >> + EfiUsbDataOut, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + PatternFilter, >> >> + Length, >> >> + &TransStatus >> >> + ); >> >> +} >> >> + >> >> +/** >> >> + This request retrieves the status of the specified Ethernet power >> management >> >> + pattern filter from the device. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] Value The filter number. >> >> + @param[out] PatternActive A pointer to the pattern active >> boolean. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthPowerFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + OUT BOOLEAN *PatternActive >> >> + ) >> >> +{ >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> + UINT32 TransStatus; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + Request.RequestType =3D USB_ETHERNET_GET_REQ_TYPE; >> >> + Request.Request =3D GET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ; >> >> + Request.Value =3D Value; >> >> + Request.Index =3D UsbEthDriver->NumOfInterface; >> >> + Request.Length =3D USB_ETH_POWER_FILTER_LENGTH; >> >> + >> >> + return UsbEthDriver->UsbIo->UsbControlTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + &Request, >> >> + EfiUsbDataIn, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + PatternActive, >> >> + USB_ETH_POWER_FILTER_LENGTH, >> >> + &TransStatus >> >> + ); >> >> +} >> >> + >> >> +BIT_MAP gTable[] =3D { >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_UNICAST, >> USB_ETH_PACKET_TYPE_DIRECTED }, >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST, >> USB_ETH_PACKET_TYPE_BROADCAST }, >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST, >> USB_ETH_PACKET_TYPE_MULTICAST }, >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS, >> USB_ETH_PACKET_TYPE_PROMISCUOUS }, >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST, >> USB_ETH_PACKET_TYPE_ALL_MULTICAST }, >> >> +}; >> >> + >> >> +/** >> >> + Convert value between PXE receive filter and USB ETH packet filter. >> >> + >> >> + @param[in] Value PXE filter data. >> >> + @param[out] CdcFilter A pointer to the Ethernet Packet Filter Bitmap >> value converted by PXE_OPFLAGS. >> >> + >> >> +**/ >> >> +VOID >> >> +ConvertFilter ( >> >> + IN UINT16 Value, >> >> + OUT UINT16 *CdcFilter >> >> + ) >> >> +{ >> >> + UINT32 Index; >> >> + UINT32 Count; >> >> + >> >> + Count =3D sizeof (gTable)/sizeof (gTable[0]); >> >> + >> >> + for (Index =3D 0; (gTable[Index].Src !=3D 0) && (Index < Count); Inde= x++) { >> >> + if (gTable[Index].Src & Value) { >> >> + *CdcFilter |=3D gTable[Index].Dst; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This request is used to configure device Ethernet packet filter >> settings. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in] Value Packet Filter Bitmap. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbEthPacketFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value >> >> + ) >> >> +{ >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> + UINT32 TransStatus; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + UINT16 CommandFilter =3D 0; >> >> + >> >> + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + ConvertFilter (Value, &CommandFilter); >> >> + >> >> + Request.RequestType =3D USB_ETHRTNET_SET_REQ_TYPE; >> >> + Request.Request =3D SET_ETH_PACKET_FILTER_REQ; >> >> + Request.Value =3D CommandFilter; >> >> + Request.Index =3D UsbEthDriver->NumOfInterface; >> >> + Request.Length =3D USB_ETH_PACKET_FILTER_LENGTH; >> >> + >> >> + return UsbEthDriver->UsbIo->UsbControlTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + &Request, >> >> + EfiUsbNoData, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + NULL, >> >> + USB_ETH_PACKET_FILTER_LENGTH, >> >> + &TransStatus >> >> + ); >> >> +} >> >> + >> >> +/** >> >> + This request is used to retrieve a statistic based on the feature >> selector. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] FeatureSelector Value of the feature selector. >> >> + @param[out] Statistic A pointer to the 32 bit unsigned >> integer. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthStatistic ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 FeatureSelector, >> >> + OUT VOID *Statistic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> + UINT32 TransStatus; >> >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + Status =3D This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + if (UsbEthFunDescriptor.EthernetStatistics =3D=3D 0) { >> >> + return EFI_UNSUPPORTED; >> >> + } >> >> + >> >> + Request.RequestType =3D USB_ETHERNET_GET_REQ_TYPE; >> >> + Request.Request =3D GET_ETH_STATISTIC_REQ; >> >> + Request.Value =3D FeatureSelector; >> >> + Request.Index =3D UsbEthDriver->NumOfInterface; >> >> + Request.Length =3D USB_ETH_STATISTIC; >> >> + >> >> + return UsbEthDriver->UsbIo->UsbControlTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + &Request, >> >> + EfiUsbDataIn, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + Statistic, >> >> + USB_ETH_STATISTIC, >> >> + &TransStatus >> >> + ); >> >> +} >> >> diff --git a/UsbNetworkPkg/UsbNetworkPkg.dec >> b/UsbNetworkPkg/UsbNetworkPkg.dec >> new file mode 100644 >> index 0000000000..4ffafd99ed >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbNetworkPkg.dec >> @@ -0,0 +1,32 @@ >> +## @file >> +# This package defines Usb network specific interfaces and library >> classes >> +# as well as configuration for standard edk2 packages. >> +# >> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> +# Subject to AMI licensing agreement. >> +## >> + >> +[Defines] >> + DEC_SPECIFICATION =3D 0x00010005 >> + PACKAGE_NAME =3D UsbNetworkPkg >> + PACKAGE_GUID =3D abfab91e-37ea-4cb4-80a6-563dbb0bce= c6 >> + PACKAGE_VERSION =3D 0.1 >> + >> +[Includes] >> + Include >> + >> +[Guids] >> + ## Usb Network package token space GUID >> + gUsbNetworkPkgTokenSpaceGuid =3D { 0xA1231E82, 0x21B8, 0x4204, { 0x9= 2, >> 0xBB, 0x37, 0x3A, 0xFB, 0x01, 0xC6, 0xA1 } } >> + >> +[PcdsFeatureFlag] >> + >> + ## Set the PCD 'UsbCdcEcmSupport' to 'TRUE' if 'Usb Cdc Ecm device' >> need to be enabled. >> + gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport|FALSE|BOOLEAN|0x0000000= 1 >> + >> + ## Set the PCD 'UsbCdcNcmSupport' to 'TRUE' if 'Usb Cdc Ncm device' >> need to be enabled. >> + gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport|FALSE|BOOLEAN|0x0000000= 2 >> + >> + ## Set the PCD 'UsbRndisSupport' to 'TRUE' if 'Usb Rndis device' need >> to be enabled. >> + gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport|TRUE|BOOLEAN|0x00000003 >> + >> diff --git a/UsbNetworkPkg/UsbRndis/ComponentName.c >> b/UsbNetworkPkg/UsbRndis/ComponentName.c >> new file mode 100644 >> index 0000000000..6b7891afd9 >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbRndis/ComponentName.c >> @@ -0,0 +1,172 @@ >> +/** @file >> >> + This file contains code for USB RNDIS Driver Component >> >> + Name definitions >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#include "UsbRndis.h" >> >> + >> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE >> gUsbRndisDriverNameTable[] =3D { >> >> + { >> >> + "eng;en", >> >> + L"USB RNDIS Driver" >> >> + }, >> >> + { >> >> + NULL, >> >> + NULL >> >> + } >> >> +}; >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbRndisComponentNameGetDriverName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **DriverName >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbRndisComponentNameGetControllerName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN EFI_HANDLE Controller, >> >> + IN EFI_HANDLE ChildHandle OPTIONAL, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **ControllerName >> >> + ); >> >> + >> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL >> gUsbRndisComponentName =3D { >> >> + UsbRndisComponentNameGetDriverName, >> >> + UsbRndisComponentNameGetControllerName, >> >> + "eng" >> >> +}; >> >> + >> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL >> gUsbRndisComponentName2 =3D { >> >> + >> (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)UsbRndisComponentNameGetDriverName, >> >> + >> (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)UsbRndisComponentNameGetControl= lerName, >> >> + "en" >> >> +}; >> >> + >> >> +/** >> >> + Retrieves a Unicode string that is the user readable name of the >> driver. >> >> + >> >> + This function retrieves the user readable name of a driver in the for= m >> of a >> >> + Unicode string. If the driver specified by This has a user readable >> name in >> >> + the language specified by Language, then a pointer to the driver name >> is >> >> + returned in DriverName, and EFI_SUCCESS is returned. If the driver >> specified >> >> + by This does not support the language specified by Language, >> >> + then EFI_UNSUPPORTED is returned. >> >> + >> >> + @param[in] This A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >> >> + EFI_COMPONENT_NAME_PROTOCOL instance. >> >> + @param[in] Language A pointer to a Null-terminated ASCII >> string >> >> + array indicating the language. This is >> the >> >> + language of the driver name that the >> caller is >> >> + requesting, and it must match one of th= e >> >> + languages specified in >> SupportedLanguages. The >> >> + number of languages supported by a >> driver is up >> >> + to the driver writer. Language is >> specified >> >> + in RFC 4646 or ISO 639-2 language code >> format. >> >> + @param[out] DriverName A pointer to the Unicode string to >> return. >> >> + This Unicode string is the name of the >> >> + driver specified by This in the languag= e >> >> + specified by Language. >> >> + >> >> + @retval EFI_SUCCESS The Unicode string for the Driver >> specified by >> >> + This and the language specified by >> Language was >> >> + returned in DriverName. >> >> + @retval EFI_INVALID_PARAMETER Language is NULL. >> >> + @retval EFI_INVALID_PARAMETER DriverName is NULL. >> >> + @retval EFI_UNSUPPORTED The driver specified by This does not >> support >> >> + the language specified by Language. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbRndisComponentNameGetDriverName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **DriverName >> >> + ) >> >> +{ >> >> + return LookupUnicodeString2 ( >> >> + Language, >> >> + This->SupportedLanguages, >> >> + gUsbRndisDriverNameTable, >> >> + DriverName, >> >> + (BOOLEAN)(This =3D=3D &gUsbRndisComponentName) >> >> + ); >> >> +} >> >> + >> >> +/** >> >> + Retrieves a Unicode string that is the user readable name of the >> controller >> >> + that is being managed by a driver. >> >> + >> >> + This function retrieves the user readable name of the controller >> specified by >> >> + ControllerHandle and ChildHandle in the form of a Unicode string. If >> the >> >> + driver specified by This has a user readable name in the language >> specified by >> >> + Language, then a pointer to the controller name is returned in >> ControllerName, >> >> + and EFI_SUCCESS is returned. If the driver specified by This is not >> currently >> >> + managing the controller specified by ControllerHandle and ChildHandle= , >> >> + then EFI_UNSUPPORTED is returned. If the driver specified by This >> does not >> >> + support the language specified by Language, then EFI_UNSUPPORTED is >> returned. >> >> + >> >> + @param[in] This A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >> >> + EFI_COMPONENT_NAME_PROTOCOL instance. >> >> + @param[in] Controller The handle of a controller that the >> driver >> >> + specified by This is managing. This >> handle >> >> + specifies the controller whose name is >> to be >> >> + returned. >> >> + @param[in] ChildHandle The handle of the child controller to >> retrieve >> >> + the name of. This is an optional >> parameter that >> >> + may be NULL. It will be NULL for devic= e >> >> + drivers. It will also be NULL for a bu= s >> drivers >> >> + that wish to retrieve the name of the b= us >> >> + controller. It will not be NULL for a >> bus >> >> + driver that wishes to retrieve the name >> of a >> >> + child controller. >> >> + @param[in] Language A pointer to a Null-terminated ASCII >> string >> >> + array indicating the language. This is >> the >> >> + language of the driver name that the >> caller is >> >> + requesting, and it must match one of th= e >> >> + languages specified in >> SupportedLanguages. The >> >> + number of languages supported by a >> driver is up >> >> + to the driver writer. Language is >> specified in >> >> + RFC 4646 or ISO 639-2 language code >> format. >> >> + @param[out] ControllerName A pointer to the Unicode string to >> return. >> >> + This Unicode string is the name of the >> >> + controller specified by ControllerHandl= e >> and >> >> + ChildHandle in the language specified b= y >> >> + Language from the point of view of the >> driver >> >> + specified by This. >> >> + >> >> + @retval EFI_SUCCESS The Unicode string for the user readabl= e >> name in >> >> + the language specified by Language for >> the >> >> + driver specified by This was returned i= n >> >> + DriverName. >> >> + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid >> EFI_HANDLE. >> >> + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a >> valid >> >> + EFI_HANDLE. >> >> + @retval EFI_INVALID_PARAMETER Language is NULL. >> >> + @retval EFI_INVALID_PARAMETER ControllerName is NULL. >> >> + @retval EFI_UNSUPPORTED The driver specified by This is not >> currently >> >> + managing the controller specified by >> >> + ControllerHandle and ChildHandle. >> >> + @retval EFI_UNSUPPORTED The driver specified by This does not >> support >> >> + the language specified by Language. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbRndisComponentNameGetControllerName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN EFI_HANDLE Controller, >> >> + IN EFI_HANDLE ChildHandle OPTIONAL, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **ControllerName >> >> + ) >> >> +{ >> >> + return EFI_UNSUPPORTED; >> >> +} >> >> diff --git a/UsbNetworkPkg/UsbRndis/UsbRndis.c >> b/UsbNetworkPkg/UsbRndis/UsbRndis.c >> new file mode 100644 >> index 0000000000..a75355825b >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbRndis/UsbRndis.c >> @@ -0,0 +1,848 @@ >> +/** @file >> >> + This file contains code for USB Remote Network Driver >> >> + Interface Spec. Driver Binding >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#include "UsbRndis.h" >> >> + >> >> +EFI_GUID gUsbEthProtocolGuid =3D >> USB_ETHERNET_PROTOCOL_GUID; >> >> +extern EFI_COMPONENT_NAME2_PROTOCOL gUsbRndisComponentName2; >> >> + >> >> +EFI_DRIVER_BINDING_PROTOCOL gUsbRndisDriverBinding =3D { >> >> + UsbRndisDriverSupported, >> >> + UsbRndisDriverStart, >> >> + UsbRndisDriverStop, >> >> + USB_RNDIS_DRIVER_VERSION, >> >> + NULL, >> >> + NULL >> >> +}; >> >> + >> >> +/** >> >> + Check if this interface is USB Rndis SubType >> >> + >> >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance. >> >> + >> >> + @retval TRUE USB Rndis SubType. >> >> + @retval FALSE Not USB Rndis SubType. >> >> + >> >> +**/ >> >> +BOOLEAN >> >> +IsSupportedDevice ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; >> >> + >> >> + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, >> &InterfaceDescriptor); >> >> + if (EFI_ERROR (Status)) { >> >> + return FALSE; >> >> + } >> >> + >> >> + // Check specific device/RNDIS and CDC-DATA >> >> + if (((InterfaceDescriptor.InterfaceClass =3D=3D 0x2) && >> >> + (InterfaceDescriptor.InterfaceSubClass =3D=3D 0x2) && >> >> + (InterfaceDescriptor.InterfaceProtocol =3D=3D 0xFF)) || \ >> >> + ((InterfaceDescriptor.InterfaceClass =3D=3D 0xEF) && >> >> + (InterfaceDescriptor.InterfaceSubClass =3D=3D 0x4) && >> >> + (InterfaceDescriptor.InterfaceProtocol =3D=3D 0x1)) || \ >> >> + ((InterfaceDescriptor.InterfaceClass =3D=3D 0xA) && >> >> + (InterfaceDescriptor.InterfaceSubClass =3D=3D 0x0) && >> >> + (InterfaceDescriptor.InterfaceProtocol =3D=3D 0x00)) >> >> + ) >> >> + { >> >> + return TRUE; >> >> + } >> >> + >> >> + return FALSE; >> >> +} >> >> + >> >> +/** >> >> + Check if this interface is USB Rndis SubType but not CDC Data interfa= ce >> >> + >> >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance. >> >> + >> >> + @retval TRUE USB Rndis SubType. >> >> + @retval FALSE Not USB Rndis SubType. >> >> + >> >> +**/ >> >> +BOOLEAN >> >> +IsRndisInterface ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; >> >> + >> >> + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, >> &InterfaceDescriptor); >> >> + if (EFI_ERROR (Status)) { >> >> + return FALSE; >> >> + } >> >> + >> >> + // Check for specific device/RNDIS and CDC-DATA >> >> + if (((InterfaceDescriptor.InterfaceClass =3D=3D 0x2) && >> >> + (InterfaceDescriptor.InterfaceSubClass =3D=3D 0x2) && >> >> + (InterfaceDescriptor.InterfaceProtocol =3D=3D 0xFF)) || \ >> >> + ((InterfaceDescriptor.InterfaceClass =3D=3D 0xEF) && >> >> + (InterfaceDescriptor.InterfaceSubClass =3D=3D 0x4) && >> >> + (InterfaceDescriptor.InterfaceProtocol =3D=3D 0x1)) >> >> + ) >> >> + { >> >> + return TRUE; >> >> + } >> >> + >> >> + return FALSE; >> >> +} >> >> + >> >> +/** >> >> + Check if the USB RNDIS and USB CDC Data interfaces are from the same >> device. >> >> + >> >> + @param[in] UsbRndisDataPath A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> >> + @param[in] UsbCdcDataPath A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> >> + >> >> + @retval EFI_SUCCESS Is the same device. >> >> + @retval EFI_UNSUPPORTED Is not the same device. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +IsSameDevice ( >> >> + IN EFI_DEVICE_PATH_PROTOCOL *UsbRndisDataPath, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath >> >> + ) >> >> +{ >> >> + DEBUG ((EFI_D_VERBOSE, "IsSameDevice Entry \n")); >> >> + while (1) { >> >> + if (IsDevicePathEnd (NextDevicePathNode (UsbRndisDataPath))) { >> >> + if (((USB_DEVICE_PATH *)UsbRndisDataPath)->ParentPortNumber =3D= =3D >> >> + ((USB_DEVICE_PATH *)UsbCdcDataPath)->ParentPortNumber) >> >> + { >> >> + return EFI_SUCCESS; >> >> + } else { >> >> + return EFI_UNSUPPORTED; >> >> + } >> >> + } else { >> >> + if (CompareMem (UsbCdcDataPath, UsbRndisDataPath, sizeof >> (EFI_DEVICE_PATH_PROTOCOL)) !=3D 0) { >> >> + return EFI_UNSUPPORTED; >> >> + } >> >> + >> >> + UsbRndisDataPath =3D NextDevicePathNode (UsbRndisDataPath); >> >> + UsbCdcDataPath =3D NextDevicePathNode (UsbCdcDataPath); >> >> + } >> >> + } >> >> + >> >> + DEBUG ((EFI_D_VERBOSE, "IsSameDevice Exit \n")); >> >> +} >> >> + >> >> +/** >> >> + Check if the USB CDC Data(UsbIo) installed and return USB CDC Data >> Handle. >> >> + >> >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance. >> >> + >> >> + @retval TRUE USB CDC Data(UsbIo) installed. >> >> + @retval FALSE USB CDC Data(UsbIo) did not installed. >> >> + >> >> +**/ >> >> +BOOLEAN >> >> +IsUsbCdcData ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; >> >> + >> >> + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, >> &InterfaceDescriptor); >> >> + if (EFI_ERROR (Status)) { >> >> + return FALSE; >> >> + } >> >> + >> >> + // Check for CDC-DATA >> >> + if ((InterfaceDescriptor.InterfaceClass =3D=3D 0xA) && >> >> + (InterfaceDescriptor.InterfaceSubClass =3D=3D 0x0) && >> >> + (InterfaceDescriptor.InterfaceProtocol =3D=3D 0x0)) >> >> + { >> >> + return TRUE; >> >> + } >> >> + >> >> + return FALSE; >> >> +} >> >> + >> >> +/** >> >> + Check if the USB Rndis(UsbIo) installed >> >> + >> >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instanc= e. >> >> + >> >> + @retval TRUE USB Rndis(UsbIo) installed. >> >> + @retval FALSE USB Rndis(UsbIo) did not installed. >> >> + >> >> +**/ >> >> +BOOLEAN >> >> +IsUsbRndis ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; >> >> + >> >> + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, >> &InterfaceDescriptor); >> >> + if (EFI_ERROR (Status)) { >> >> + return FALSE; >> >> + } >> >> + >> >> + // Check for Rndis >> >> + if ((InterfaceDescriptor.InterfaceClass =3D=3D 0x2) && >> >> + (InterfaceDescriptor.InterfaceSubClass =3D=3D 0x2) && >> >> + (InterfaceDescriptor.InterfaceProtocol =3D=3D 0xFF)) >> >> + { >> >> + return TRUE; >> >> + } >> >> + >> >> + return FALSE; >> >> +} >> >> + >> >> +/** >> >> + Control comes here when a CDC device is found.Check if a RNDIS >> interface is already found for this device or not. >> >> + For one device two USBIO will be installed each for CDC and RNDIS >> interface. >> >> + >> >> + @param[in] UsbEthPath A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> >> + @param[out] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE Data. >> >> + >> >> + @retval EFI_SUCCESS The USB_RNDIS_DEVICE matching this CD= C >> Data is found. >> >> + @retval EFI_NOT_FOUND The USB_RNDIS_DEVICE matching this CD= C >> Data is not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +UpdateRndisDevice ( >> >> + IN EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath, >> >> + OUT USB_RNDIS_DEVICE **UsbRndisDevice >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINTN Index; >> >> + UINTN HandleCount; >> >> + EFI_HANDLE *HandleBuffer; >> >> + USB_ETHERNET_PROTOCOL *UsbEthDevice; >> >> + EFI_DEVICE_PATH_PROTOCOL *UsbRndisDataPath; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + BOOLEAN IsRndisInterfaceFlag =3D FALSE; >> >> + >> >> + Status =3D gBS->LocateHandleBuffer ( >> >> + ByProtocol, >> >> + &gUsbEthProtocolGuid, >> >> + NULL, >> >> + &HandleCount, >> >> + &HandleBuffer >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + for (Index =3D 0; Index < HandleCount; Index++) { >> >> + Status =3D gBS->HandleProtocol ( >> >> + HandleBuffer[Index], >> >> + &gUsbEthProtocolGuid, >> >> + (VOID **)&UsbEthDevice >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + continue; >> >> + } >> >> + >> >> + Status =3D gBS->HandleProtocol ( >> >> + HandleBuffer[Index], >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + continue; >> >> + } >> >> + >> >> + IsRndisInterfaceFlag =3D IsRndisInterface (UsbIo); >> >> + if (IsRndisInterfaceFlag =3D=3D FALSE) { >> >> + continue; >> >> + } >> >> + >> >> + Status =3D gBS->HandleProtocol ( >> >> + HandleBuffer[Index], >> >> + &gEfiDevicePathProtocolGuid, >> >> + (VOID **)&UsbRndisDataPath >> >> + ); >> >> + Status =3D IsSameDevice (UsbRndisDataPath, UsbCdcDataPath); >> >> + >> >> + DEBUG ((EFI_D_VERBOSE, "Rndis IsSameDevice %r\n", Status)); >> >> + >> >> + if (!EFI_ERROR (Status)) { >> >> + *UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (UsbEthDevice); >> >> + gBS->FreePool (HandleBuffer); >> >> + return EFI_SUCCESS; >> >> + } >> >> + } // End of For loop >> >> + >> >> + gBS->FreePool (HandleBuffer); >> >> + return EFI_NOT_FOUND; >> >> +} >> >> + >> >> +/** >> >> + >> >> + For the given Rndis Device, find a matching CDC device already exists >> or not. If found update the handle >> >> + and UsbIO protocol. >> >> + >> >> + @param[in] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE >> data. >> >> + >> >> +**/ >> >> +VOID >> >> +FindMatchingCdcData ( >> >> + IN USB_RNDIS_DEVICE *UsbRndisDevice >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINTN Index; >> >> + UINTN HandleCount; >> >> + EFI_HANDLE *HandleBuffer; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + EFI_DEVICE_PATH_PROTOCOL *UsbRndisDataPath; >> >> + EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath; >> >> + >> >> + // Find the parent RNDIS and update the UsbIo for the CDC device >> >> + Status =3D gBS->HandleProtocol ( >> >> + UsbRndisDevice->UsbRndisHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + (VOID **)&UsbRndisDataPath >> >> + ); >> >> + >> >> + if (EFI_ERROR (Status)) { >> >> + return; >> >> + } >> >> + >> >> + Status =3D gBS->LocateHandleBuffer ( >> >> + ByProtocol, >> >> + &gEfiUsbIoProtocolGuid, >> >> + NULL, >> >> + &HandleCount, >> >> + &HandleBuffer >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return; >> >> + } >> >> + >> >> + for (Index =3D 0; Index < HandleCount; Index++) { >> >> + Status =3D gBS->HandleProtocol ( >> >> + HandleBuffer[Index], >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo >> >> + ); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + if (IsUsbCdcData (UsbIo)) { >> >> + DEBUG ((EFI_D_VERBOSE, "Rndis FindMatchingCdcData CDCData >> interface found\n")); >> >> + >> >> + Status =3D gBS->HandleProtocol ( >> >> + HandleBuffer[Index], >> >> + &gEfiDevicePathProtocolGuid, >> >> + (VOID **)&UsbCdcDataPath >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + DEBUG ((EFI_D_VERBOSE, "Rndis CDCData DevicePath not found\n"))= ; >> >> + gBS->FreePool (HandleBuffer); >> >> + return; >> >> + } >> >> + >> >> + Status =3D IsSameDevice (UsbRndisDataPath, UsbCdcDataPath); >> >> + DEBUG ((EFI_D_VERBOSE, "Rndis IsSameDevice %r\n", Status)); >> >> + if (!EFI_ERROR (Status)) { >> >> + UsbRndisDevice->UsbCdcDataHandle =3D HandleBuffer[Index]; >> >> + UsbRndisDevice->UsbIoCdcData =3D UsbIo; >> >> + GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice); >> >> + gBS->FreePool (HandleBuffer); >> >> + return; >> >> + } >> >> + } >> >> + } // End of For loop >> >> + >> >> + gBS->FreePool (HandleBuffer); >> >> +} >> >> + >> >> +/** >> >> + >> >> + For the given UsbIo CdcData, find a matching RNDIS device already >> exists or not. >> >> + >> >> + @param[in] CdcHandle A pointer to the EFI_HANDLE for USB CDC >> Data. >> >> + @param[out] CdcUsbIo A pointer for retrieve the >> EFI_USB_IO_PROTOCOL instance. >> >> + @param[out] RndisHandle A pointer for retrieve the handle of RNDI= S >> device. >> >> + >> >> + @retval EFI_SUCCESS The USB_RNDIS_DEVICE matching this CD= C >> Data is found. >> >> + @retval EFI_NOT_FOUND The USB_RNDIS_DEVICE matching this CD= C >> Data is not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +FindMatchingRndisDev ( >> >> + IN EFI_HANDLE CdcHandle, >> >> + OUT EFI_USB_IO_PROTOCOL **CdcUsbIo, >> >> + OUT EFI_HANDLE *RndisHandle >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINTN Index; >> >> + UINTN HandleCount; >> >> + EFI_HANDLE *HandleBuffer; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + EFI_DEVICE_PATH_PROTOCOL *UsbRndisDataPath; >> >> + EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath; >> >> + >> >> + // Find the parent RNDIS and update the UsbIo for the CDC device >> >> + Status =3D gBS->HandleProtocol ( >> >> + CdcHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + (VOID **)&UsbCdcDataPath >> >> + ); >> >> + >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status =3D gBS->LocateHandleBuffer ( >> >> + ByProtocol, >> >> + &gEfiUsbIoProtocolGuid, >> >> + NULL, >> >> + &HandleCount, >> >> + &HandleBuffer >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + for (Index =3D 0; Index < HandleCount; Index++) { >> >> + Status =3D gBS->HandleProtocol ( >> >> + HandleBuffer[Index], >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo >> >> + ); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + if (IsUsbRndis (UsbIo)) { >> >> + Status =3D gBS->HandleProtocol ( >> >> + HandleBuffer[Index], >> >> + &gEfiDevicePathProtocolGuid, >> >> + (VOID **)&UsbRndisDataPath >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + DEBUG ((EFI_D_ERROR, "Usb Rndis DevicePath not found\n")); >> >> + break; >> >> + } >> >> + >> >> + Status =3D IsSameDevice (UsbRndisDataPath, UsbCdcDataPath); >> >> + >> >> + if (!EFI_ERROR (Status)) { >> >> + *RndisHandle =3D HandleBuffer[Index]; >> >> + *CdcUsbIo =3D UsbIo; >> >> + gBS->FreePool (HandleBuffer); >> >> + return Status; >> >> + } >> >> + } >> >> + } // End of For loop >> >> + >> >> + gBS->FreePool (HandleBuffer); >> >> + >> >> + return EFI_NOT_FOUND; >> >> +} >> >> + >> >> +/** >> >> + USB Rndis Driver Binding Support. >> >> + >> >> + @param[in] This Protocol instance pointer. >> >> + @param[in] ControllerHandle Handle of device to test. >> >> + @param[in] RemainingDevicePath Optional parameter use to pick a >> specific child >> >> + device to start. >> >> + >> >> + @retval EFI_SUCCESS This driver supports this device. >> >> + @retval EFI_ALREADY_STARTED This driver is already running on >> this device. >> >> + @retval other This driver does not support this >> device. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbRndisDriverSupported ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_IO_PROTOCOL *UsbIo =3D NULL; >> >> + >> >> + Status =3D gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status =3D IsSupportedDevice (UsbIo) ? EFI_SUCCESS : EFI_UNSUPPORTED; >> >> + >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + USB RNDIS Driver Binding Start. >> >> + >> >> + @param[in] This Protocol instance pointer. >> >> + @param[in] ControllerHandle Handle of device to bind driver t= o. >> >> + @param[in] RemainingDevicePath Optional parameter use to pick a >> specific child >> >> + device to start. >> >> + >> >> + @retval EFI_SUCCESS This driver is added to >> ControllerHandle >> >> + @retval EFI_DEVICE_ERROR This driver could not be started >> due to a device error >> >> + @retval EFI_OUT_OF_RESOURCES The driver could not install >> successfully due to a lack of resources. >> >> + @retval other This driver does not support this >> device >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbRndisDriverStart ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> >> + EFI_DEVICE_PATH_PROTOCOL *UsbEthPath; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + EFI_USB_INTERFACE_DESCRIPTOR Interface; >> >> + EFI_HANDLE RndisHandle =3D ControllerHandle; >> >> + >> >> + Status =3D gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status =3D gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + (VOID **)&UsbEthPath, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return Status; >> >> + } >> >> + >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + >> >> + DEBUG ((EFI_D_ERROR, "UsbRndisDriverStart %x\n", ControllerHandle)); >> >> + >> >> + // Controls come here for RNDIS and CDC. If it is CDC, check whether >> RNDIS is present on the same controller or not. >> >> + if (IsUsbCdcData (UsbIo)) { >> >> + // Find the parent RNDIS and update the UsbIo for the CDC device >> >> + Status =3D UpdateRndisDevice (UsbEthPath, &UsbRndisDevice); >> >> + >> >> + if (!EFI_ERROR (Status)) { >> >> + DEBUG ((EFI_D_VERBOSE, "Rndis Matching interface found\n")); >> >> + UsbRndisDevice->UsbCdcDataHandle =3D ControllerHandle; >> >> + UsbRndisDevice->UsbIoCdcData =3D UsbIo; >> >> + GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice); >> >> + return Status; >> >> + } else { >> >> + // Check if RnDis exist >> >> + Status =3D FindMatchingRndisDev (ControllerHandle, &UsbIo, >> &RndisHandle); >> >> + >> >> + if (EFI_ERROR (Status)) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return Status; >> >> + } >> >> + } >> >> + } >> >> + >> >> + UsbRndisDevice =3D AllocateZeroPool (sizeof (USB_RNDIS_DEVICE)); >> >> + >> >> + if (!UsbRndisDevice) { >> >> + DEBUG ((EFI_D_ERROR, "AllocateZeroPool Fail\n")); >> >> + >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return EFI_OUT_OF_RESOURCES; >> >> + } >> >> + >> >> + Status =3D LoadAllDescriptor (UsbIo, &UsbRndisDevice->Config); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + UsbRndisDevice->Signature =3D >> USB_RNDIS_SIGNATURE; >> >> + UsbRndisDevice->NumOfInterface =3D >> Interface.InterfaceNumber; >> >> + UsbRndisDevice->UsbRndisHandle =3D RndisHandle; >> >> + UsbRndisDevice->UsbCdcDataHandle =3D 0; >> >> + UsbRndisDevice->UsbIo =3D UsbIo; >> >> + UsbRndisDevice->UsbEth.UsbEthReceive =3D RndisUndiRecei= ve; >> >> + UsbRndisDevice->UsbEth.UsbEthTransmit =3D RndisUndiTrans= mit; >> >> + UsbRndisDevice->UsbEth.UsbEthInterrupt =3D UsbRndisInterr= upt; >> >> + UsbRndisDevice->UsbEth.UsbEthMacAddress =3D >> GetUsbEthMacAddress; >> >> + UsbRndisDevice->UsbEth.UsbEthMaxBulkSize =3D UsbEthBulkSize= ; >> >> + UsbRndisDevice->UsbEth.UsbHeaderFunDescriptor =3D >> GetUsbHeaderFunDescriptor; >> >> + UsbRndisDevice->UsbEth.UsbUnionFunDescriptor =3D >> GetUsbUnionFunDescriptor; >> >> + UsbRndisDevice->UsbEth.UsbEthFunDescriptor =3D >> GetUsbRndisFunDescriptor; >> >> + UsbRndisDevice->UsbEth.SetUsbEthMcastFilter =3D >> SetUsbRndisMcastFilter; >> >> + UsbRndisDevice->UsbEth.SetUsbEthPowerPatternFilter =3D >> SetUsbRndisPowerFilter; >> >> + UsbRndisDevice->UsbEth.GetUsbEthPoewrPatternFilter =3D >> GetUsbRndisPowerFilter; >> >> + UsbRndisDevice->UsbEth.SetUsbEthPacketFilter =3D >> SetUsbRndisPacketFilter; >> >> + UsbRndisDevice->UsbEth.GetUsbEthStatistic =3D GetRndisStatis= tic; >> >> + >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetState =3D >> RndisDummyReturn; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStart =3D >> RndisUndiStart; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStop =3D >> RndisUndiStop; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetInitInfo =3D >> RndisUndiGetInitInfo; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetConfigInfo =3D >> RndisUndiGetConfigInfo; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiInitialize =3D >> RndisUndiInitialize; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiReset =3D >> RndisUndiReset; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiShutdown =3D >> RndisUndiShutdown; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiInterruptEnable =3D >> RndisDummyReturn; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiReceiveFilter =3D >> RndisUndiReceiveFilter; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStationAddress =3D >> RndisDummyReturn; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStatistics =3D NULL; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiMcastIp2Mac =3D >> RndisDummyReturn; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiNvData =3D >> RndisDummyReturn; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetStatus =3D >> RndisUndiGetStatus; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiFillHeader =3D >> RndisDummyReturn; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiTransmit =3D NULL; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiReceive =3D NULL; >> >> + >> >> + UsbRndisDevice->MaxTransferSize =3D RNDIS_MAX_TRANSFER_SIZE; >> >> + UsbRndisDevice->MaxPacketsPerTransfer =3D 1; >> >> + UsbRndisDevice->PacketAlignmentFactor =3D 0; >> >> + >> >> + InitializeListHead (&UsbRndisDevice->ReceivePacketList); >> >> + >> >> + // This is a RNDIS interface. See whether CDC-DATA interface has >> already been connected or not >> >> + FindMatchingCdcData (UsbRndisDevice); >> >> + >> >> + if (UsbRndisDevice->UsbIoCdcData) { >> >> + Status =3D gBS->InstallProtocolInterface ( >> >> + &ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + EFI_NATIVE_INTERFACE, >> >> + &(UsbRndisDevice->UsbEth) >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + >> >> + gBS->FreePool (UsbRndisDevice->Config); >> >> + gBS->FreePool (UsbRndisDevice); >> >> + return Status; >> >> + } >> >> + >> >> + GetEndpoint (UsbRndisDevice->UsbIo, UsbRndisDevice); >> >> + >> >> + DEBUG ((EFI_D_ERROR, "Rndis DeviceHandle %r\n", >> UsbRndisDevice->UsbRndisHandle)); >> >> + DEBUG ((EFI_D_ERROR, "CDC DeviceHandle %r\n", >> UsbRndisDevice->UsbCdcDataHandle)); >> >> + return EFI_SUCCESS; >> >> + } >> >> + >> >> + gBS->FreePool (UsbRndisDevice->Config); >> >> + gBS->FreePool (UsbRndisDevice); >> >> + >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + CheckandStopRndisDevice >> >> + >> >> + @param[in] This Protocol instance pointer. >> >> + @param[in] ControllerHandle Handle of device to bind driver to. >> >> + >> >> + @retval EFI_SUCCESS This driver is added to ControllerHandle >> >> + @retval EFI_DEVICE_ERROR This driver could not be started due to = a >> device error >> >> + @retval other This driver does not support this device >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +CheckandStopRndisDevice ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + >> >> + Status =3D gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + if (IsUsbRndis (UsbIo)) { >> >> + Status =3D gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + DEBUG ((EFI_D_ERROR, "Rndis ControllerHandle Stop %r\n", Status)); >> >> + return Status; >> >> + } >> >> + >> >> + return EFI_UNSUPPORTED; >> >> +} >> >> + >> >> +/** >> >> + USB Rndis Driver Binding Stop. >> >> + >> >> + @param[in] This Protocol instance pointer. >> >> + @param[in] ControllerHandle Handle of device to stop driver on >> >> + @param[in] NumberOfChildren Number of Handles in >> ChildHandleBuffer. If number of >> >> + children is zero stop the entire bu= s >> driver. >> >> + @param[in] ChildHandleBuffer List of Child Handles to Stop. >> >> + >> >> + @retval EFI_SUCCESS This driver is removed >> ControllerHandle >> >> + @retval other This driver was not removed from >> this device >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbRndisDriverStop ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN UINTN NumberOfChildren, >> >> + IN EFI_HANDLE *ChildHandleBuffer >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_PROTOCOL *UsbEthProtocol; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> >> + >> >> + DEBUG ((EFI_D_ERROR, "UsbRndisDriverStop ControllerHandle %lx\n", >> ControllerHandle)); >> >> + >> >> + Status =3D gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + (VOID **)&UsbEthProtocol, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + Status =3D CheckandStopRndisDevice (This, ControllerHandle); >> >> + >> >> + DEBUG ((EFI_D_ERROR, "CheckandStopRndisDevice %r\n", Status)); >> >> + >> >> + return Status; >> >> + } >> >> + >> >> + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (UsbEthProtocol); >> >> + >> >> + Status =3D gBS->CloseProtocol ( >> >> + UsbRndisDevice->UsbCdcDataHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + UsbRndisDevice->UsbCdcDataHandle >> >> + ); >> >> + >> >> + Status =3D gBS->UninstallProtocolInterface ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + UsbEthProtocol >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + DEBUG ((EFI_D_ERROR, "EFI_ERROR %r\n", Status)); >> >> + >> >> + return Status; >> >> + } >> >> + >> >> + Status =3D gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + >> >> + gBS->FreePool (UsbRndisDevice->Config); >> >> + gBS->FreePool (UsbRndisDevice); >> >> + >> >> + DEBUG ((EFI_D_ERROR, "UsbRndisDriverStop %r\n", Status)); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Entrypoint of RNDIS Driver. >> >> + >> >> + This function is the entrypoint of RNDIS Driver. It installs Driver >> Binding >> >> + Protocols together with Component Name Protocols. >> >> + >> >> + @param[in] ImageHandle The firmware allocated handle for the >> EFI image. >> >> + @param[in] SystemTable A pointer to the EFI System Table. >> >> + >> >> + @retval EFI_SUCCESS The entry point is executed successfull= y. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbRndisEntry ( >> >> + IN EFI_HANDLE ImageHandle, >> >> + IN EFI_SYSTEM_TABLE *SystemTable >> >> + ) >> >> +{ >> >> + gUsbRndisDriverBinding.DriverBindingHandle =3D ImageHandle; >> >> + gUsbRndisDriverBinding.ImageHandle =3D ImageHandle; >> >> + >> >> + return gBS->InstallMultipleProtocolInterfaces ( >> >> + &gUsbRndisDriverBinding.DriverBindingHandle, >> >> + &gEfiDriverBindingProtocolGuid, >> >> + &gUsbRndisDriverBinding, >> >> + &gEfiComponentName2ProtocolGuid, >> >> + &gUsbRndisComponentName2, >> >> + NULL >> >> + ); >> >> +} >> >> diff --git a/UsbNetworkPkg/UsbRndis/UsbRndis.h >> b/UsbNetworkPkg/UsbRndis/UsbRndis.h >> new file mode 100644 >> index 0000000000..680a9e67c9 >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbRndis/UsbRndis.h >> @@ -0,0 +1,569 @@ >> +/** @file >> >> + Header file for for USB Rndis driver >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#ifndef _USB_RNDIS_H_ >> >> +#define _USB_RNDIS_H_ >> >> + >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> + >> >> +typedef struct _REMOTE_NDIS_MSG_HEADER REMOTE_NDIS_MSG_HEADER; >> >> + >> >> +typedef struct { >> >> + UINT32 Signature; >> >> + USB_ETHERNET_PROTOCOL UsbEth; >> >> + EFI_HANDLE UsbCdcDataHandle; >> >> + EFI_HANDLE UsbRndisHandle; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + EFI_USB_IO_PROTOCOL *UsbIoCdcData; >> >> + EFI_USB_CONFIG_DESCRIPTOR *Config; >> >> + UINT8 NumOfInterface; >> >> + UINT8 BulkInEndpoint; >> >> + UINT8 BulkOutEndpoint; >> >> + UINT8 InterrupEndpoint; >> >> + EFI_MAC_ADDRESS MacAddress; >> >> + UINT32 RequestId; >> >> + UINT32 Medium; >> >> + UINT32 MaxPacketsPerTransfer; >> >> + UINT32 MaxTransferSize; >> >> + UINT32 PacketAlignmentFactor; >> >> + LIST_ENTRY ReceivePacketList; >> >> +} USB_RNDIS_DEVICE; >> >> + >> >> +#define USB_RNDIS_DRIVER_VERSION 1 >> >> +#define USB_TX_ETHERNET_BULK_TIMEOUT 3000 >> >> +#define USB_RX_ETHERNET_BULK_TIMEOUT 3 >> >> +#define USB_ETHERNET_TRANSFER_TIMEOUT 200 >> >> + >> >> +#define LAN_BULKIN_CMD_CONTROL 1 >> >> +#define MAXIMUM_STOPBULKIN_CNT 300 // Indicating maximum >> counts for waiting bulk in command >> >> +#define MINIMUM_STOPBULKIN_CNT 3 // Indicating minimum >> counts for waiting bulk in command >> >> +#define BULKIN_CMD_POLLING_CNT 300 // Indicating the waitin= g >> counts for send bulk in command when system pending >> >> + >> >> +#define USB_RNDIS_SIGNATURE SIGNATURE_32('r', 'n', 'd', 's') >> >> +#define USB_RNDIS_DEVICE_FROM_THIS(a) CR (a, USB_RNDIS_DEVICE, UsbEth, >> USB_RNDIS_SIGNATURE) >> >> + >> >> +struct BIT_MAP { >> >> + unsigned int Src; >> >> + unsigned int Dst; >> >> +}; >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbRndisDriverSupported ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbRndisDriverStart ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbRndisDriverStop ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN UINTN NumberOfChildren, >> >> + IN EFI_HANDLE *ChildHandleBuffer >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +LoadAllDescriptor ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> >> + OUT EFI_USB_CONFIG_DESCRIPTOR **ConfigDesc >> >> + ); >> >> + >> >> +BOOLEAN >> >> +NextDescriptor ( >> >> + IN EFI_USB_CONFIG_DESCRIPTOR *Desc, >> >> + IN OUT UINTN *Offset >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +GetFunctionalDescriptor ( >> >> + IN EFI_USB_CONFIG_DESCRIPTOR *Config, >> >> + IN UINT8 FunDescriptorType, >> >> + OUT VOID *DataBuffer >> >> + ); >> >> + >> >> +VOID >> >> +GetEndpoint ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> >> + IN OUT USB_RNDIS_DEVICE *UsbRndisDevice >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbRndisInterrupt ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN BOOLEAN IsNewTransfer, >> >> + IN UINTN PollingInterval, >> >> + IN EFI_USB_DEVICE_REQUEST *Requst >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +InterruptCallback ( >> >> + IN VOID *Data, >> >> + IN UINTN DataLength, >> >> + IN VOID *Context, >> >> + IN UINT32 Status >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthMacAddress ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT EFI_MAC_ADDRESS *MacAddress >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthBulkSize ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT UINTN *BulkSize >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisDummyReturn ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiStart ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiStop ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiGetInitInfo ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiGetConfigInfo ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiInitialize ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiTransmit ( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN VOID *BulkOutData, >> >> + IN OUT UINTN *DataLength >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiReceive ( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN OUT VOID *BulkInData, >> >> + IN OUT UINTN *DataLength >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiReset ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiShutdown ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiReceiveFilter ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiGetStatus ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbHeaderFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbUnionFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbRndisFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbRndisMcastFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN VOID *McastAddr >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbRndisPowerFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN UINT16 Length, >> >> + IN VOID *PatternFilter >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbRndisPowerFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN BOOLEAN *PatternActive >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbRndisPacketFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetRndisStatistic ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN VOID *Statistic >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +SendRndisSetMsg ( >> >> + IN USB_RNDIS_DEVICE *UsbRndisDevice, >> >> + UINT8 Oid, >> >> + UINT32 Length, >> >> + UINT8 *Buf >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +RndisControlMsg ( >> >> + IN USB_RNDIS_DEVICE *UsbRndisDevice, >> >> + IN REMOTE_NDIS_MSG_HEADER *RndisMsg, >> >> + OUT REMOTE_NDIS_MSG_HEADER *RndisMsgResponse >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +RndisTransmitDataMsg ( >> >> + IN USB_RNDIS_DEVICE *UsbRndisDevice, >> >> + IN REMOTE_NDIS_MSG_HEADER *RndisMsg, >> >> + UINTN *TransferLength >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +RndisReceiveDataMsg ( >> >> + IN USB_RNDIS_DEVICE *UsbRndisDevice, >> >> + IN REMOTE_NDIS_MSG_HEADER *RndisMsg, >> >> + UINTN *TransferLength >> >> + ); >> >> + >> >> +VOID >> >> +PrintRndisMsg ( >> >> + IN REMOTE_NDIS_MSG_HEADER *RndisMsg >> >> + ); >> >> + >> >> +#define RNDIS_MAJOR_VERSION 0x00000001 >> >> +#define RNDIS_MINOR_VERSION 0x00000000 >> >> +#define RNDIS_MAX_TRANSFER_SIZE 0x4000 >> >> + >> >> +#define RNDIS_PACKET_MSG 0x00000001 >> >> +#define RNDIS_INITIALIZE_MSG 0x00000002 >> >> +#define RNDIS_INITIALIZE_CMPLT 0x80000002 >> >> +#define RNDIS_HLT_MSG 0x00000003 >> >> +#define RNDIS_QUERY_MSG 0x00000004 >> >> +#define RNDIS_QUERY_CMPLT 0x80000004 >> >> +#define RNDIS_SET_MSG 0x00000005 >> >> +#define RNDIS_SET_CMPLT 0x80000005 >> >> +#define RNDIS_RESET_MSG 0x00000006 >> >> +#define RNDIS_RESET_CMPLT 0x80000006 >> >> +#define RNDIS_INDICATE_STATUS_MSG 0x00000007 >> >> +#define RNDIS_KEEPALIVE_MSG 0x00000008 >> >> +#define RNDIS_KEEPALIVE_CMPLT 0x80000008 >> >> + >> >> +#define RNDIS_STATUS_SUCCESS 0x00000000 >> >> +#define RNDIS_STATUS_FAILURE 0xC0000001 >> >> +#define RNDIS_STATUS_INVALID_DATA 0xC0010015 >> >> +#define RNDIS_STATUS_NOT_SUPPORTED 0xC00000BB >> >> +#define RNDIS_STATUS_MEDIA_CONNECT 0x4001000B >> >> +#define RNDIS_STATUS_MEDIA_DISCONNECT 0x4001000C >> >> + >> >> +#define RNDIS_CONTROL_TIMEOUT 10000 // 10sec >> >> +#define RNDIS_KEEPALIVE_TIMEOUT 5000 // 5sec >> >> + >> >> +#define SEND_ENCAPSULATED_COMMAND 0x00000000 >> >> +#define GET_ENCAPSULATED_RESPONSE 0x00000001 >> >> + >> >> +// >> >> +// General Objects >> >> +// >> >> +// Taken from NTDDNDIS.H >> >> +#define OID_GEN_SUPPORTED_LIST 0x00010101 >> >> +#define OID_GEN_HARDWARE_STATUS 0x00010102 >> >> +#define OID_GEN_MEDIA_SUPPORTED 0x00010103 >> >> +#define OID_GEN_MEDIA_IN_USE 0x00010104 >> >> +#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 >> >> +#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 >> >> +#define OID_GEN_LINK_SPEED 0x00010107 >> >> +#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 >> >> +#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 >> >> +#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A >> >> +#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B >> >> +#define OID_GEN_VENDOR_ID 0x0001010C >> >> +#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D >> >> +#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E >> >> +#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F >> >> +#define OID_GEN_DRIVER_VERSION 0x00010110 >> >> +#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 >> >> +#define OID_GEN_PROTOCOL_OPTIONS 0x00010112 >> >> +#define OID_GEN_MAC_OPTIONS 0x00010113 >> >> +#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 >> >> +#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 >> >> +#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 >> >> + >> >> +#define OID_GEN_XMIT_OK 0x00020101 >> >> +#define OID_GEN_RCV_OK 0x00020102 >> >> +#define OID_GEN_XMIT_ERROR 0x00020103 >> >> +#define OID_GEN_RCV_ERROR 0x00020104 >> >> +#define OID_GEN_RCV_NO_BUFFER 0x00020105 >> >> + >> >> +#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 >> >> +#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 >> >> +#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 >> >> +#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 >> >> +#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 >> >> +#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 >> >> +#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 >> >> +#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 >> >> +#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 >> >> +#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A >> >> +#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B >> >> +#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C >> >> +#define OID_GEN_RCV_CRC_ERROR 0x0002020D >> >> +#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E >> >> + >> >> +// >> >> +// Ndis Packet Filter Bits (OID_GEN_CURRENT_PACKET_FILTER). >> >> +// >> >> +#define NDIS_PACKET_TYPE_DIRECTED 0x0001 >> >> +#define NDIS_PACKET_TYPE_MULTICAST 0x0002 >> >> +#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x0004 >> >> +#define NDIS_PACKET_TYPE_BROADCAST 0x0008 >> >> +#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x0010 >> >> +#define NDIS_PACKET_TYPE_PROMISCUOUS 0x0020 >> >> +#define NDIS_PACKET_TYPE_SMT 0x0040 >> >> +#define NDIS_PACKET_TYPE_ALL_LOCAL 0x0080 >> >> +#define NDIS_PACKET_TYPE_MAC_FRAME 0x8000 >> >> +#define NDIS_PACKET_TYPE_FUNCTIONAL 0x4000 >> >> +#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x2000 >> >> +#define NDIS_PACKET_TYPE_GROUP 0x1000 >> >> + >> >> +#pragma pack(1) >> >> + >> >> +typedef struct _REMOTE_NDIS_MSG_HEADER { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> +} REMOTE_NDIS_MSG_HEADER; >> >> + >> >> +typedef struct { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> + UINT32 RequestID; >> >> + UINT32 MajorVersion; >> >> + UINT32 MinorVersion; >> >> + UINT32 MaxTransferSize; >> >> +} REMOTE_NDIS_INITIALIZE_MSG; >> >> + >> >> +typedef struct { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> + UINT32 RequestID; >> >> +} REMOTE_NDIS_HALT_MSG; >> >> + >> >> +typedef struct { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> + UINT32 RequestID; >> >> + UINT32 Oid; >> >> + UINT32 InformationBufferLength; >> >> + UINT32 InformationBufferOffset; >> >> + UINT32 Reserved; >> >> +} REMOTE_NDIS_QUERY_MSG; >> >> + >> >> +typedef struct { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> + UINT32 RequestID; >> >> + UINT32 Oid; >> >> + UINT32 InformationBufferLength; >> >> + UINT32 InformationBufferOffset; >> >> + UINT32 Reserved; >> >> +} REMOTE_NDIS_SET_MSG; >> >> + >> >> +typedef struct { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> + UINT32 Reserved; >> >> +} REMOTE_NDIS_RESET_MSG; >> >> + >> >> +typedef struct { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> + UINT32 Status; >> >> + UINT32 StatusBufferLength; >> >> + UINT32 StatusBufferOffset; >> >> +} REMOTE_NDIS_INDICATE_STATUS_MSG; >> >> + >> >> +typedef struct { >> >> + UINT32 DiagStatus; >> >> + UINT32 ErrorOffset; >> >> +} RNDIS_DIAGNOSTIC_INFO; >> >> + >> >> +typedef struct { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> + UINT32 RequestID; >> >> +} REMOTE_NDIS_KEEPALIVE_MSG; >> >> + >> >> +typedef struct { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> + UINT32 RequestID; >> >> + UINT32 Status; >> >> + UINT32 MajorVersion; >> >> + UINT32 MinorVersion; >> >> + UINT32 DeviceFlags; >> >> + UINT32 Medium; >> >> + UINT32 MaxPacketsPerTransfer; >> >> + UINT32 MaxTransferSize; >> >> + UINT32 PacketAlignmentFactor; >> >> + UINT64 Reserved; >> >> +} REMOTE_NDIS_INITIALIZE_CMPLT; >> >> + >> >> +typedef struct { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> + UINT32 RequestID; >> >> + UINT32 Status; >> >> + UINT32 InformationBufferLength; >> >> + UINT32 InformationBufferOffset; >> >> +} REMOTE_NDIS_QUERY_CMPLT; >> >> + >> >> +typedef struct { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> + UINT32 RequestID; >> >> + UINT32 Status; >> >> +} REMOTE_NDIS_SET_CMPLT; >> >> + >> >> +typedef struct { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> + UINT32 Status; >> >> + UINT32 AddressingReset; >> >> +} REMOTE_NDIS_RESET_CMPLT; >> >> + >> >> +typedef struct { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> + UINT32 RequestID; >> >> + UINT32 Status; >> >> +} REMOTE_NDIS_KEEPALIVE_CMPLT; >> >> + >> >> +typedef struct { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> + UINT32 DataOffset; >> >> + UINT32 DataLength; >> >> + UINT32 OutOfBandDataOffset; >> >> + UINT32 OutOfBandDataLength; >> >> + UINT32 NumOutOfBandDataElements; >> >> + UINT32 PerPacketInfoOffset; >> >> + UINT32 PerPacketInfoLength; >> >> + UINT32 Reserved1; >> >> + UINT32 Reserved2; >> >> +} REMOTE_NDIS_PACKET_MSG; >> >> + >> >> +typedef struct { >> >> + UINT32 Size; >> >> + UINT32 Type; >> >> + UINT32 ClassInformationOffset; >> >> +} OUT_OF_BAND_DATA_RECORD; >> >> + >> >> +typedef struct { >> >> + UINT32 Size; >> >> + UINT32 Type; >> >> + UINT32 ClassInformationOffset; >> >> +} PER_PACKET_INFO_DATA_RECORD; >> >> + >> >> +typedef struct { >> >> + LIST_ENTRY PacketList; >> >> + UINT8 *OrgBuffer; >> >> + UINTN RemainingLength; >> >> +} PACKET_LIST; >> >> + >> >> +#pragma pack() >> >> + >> >> +#endif >> >> diff --git a/UsbNetworkPkg/UsbRndis/UsbRndis.inf >> b/UsbNetworkPkg/UsbRndis/UsbRndis.inf >> new file mode 100644 >> index 0000000000..909b106059 >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbRndis/UsbRndis.inf >> @@ -0,0 +1,41 @@ >> +## @file >> +# This is Usb Rndis driver for DXE phase. >> +# >> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> +# Subject to AMI licensing agreement. >> +## >> + >> +[Defines] >> + INF_VERSION =3D 0x00010005 >> + BASE_NAME =3D UsbRndis >> + FILE_GUID =3D 11E32C34-60B5-4991-8DEA-63D3E8C876= DE >> + MODULE_TYPE =3D DXE_DRIVER >> + VERSION_STRING =3D 1.0 >> + ENTRY_POINT =3D UsbRndisEntry >> + >> +[Sources] >> + UsbRndis.c >> + UsbRndis.h >> + UsbRndisFunction.c >> + ComponentName.c >> + >> +[Packages] >> + MdePkg/MdePkg.dec >> + UsbNetworkPkg/UsbNetworkPkg.dec >> + >> +[LibraryClasses] >> + UefiDriverEntryPoint >> + UefiBootServicesTableLib >> + UefiLib >> + DebugLib >> + UefiUsbLib >> + MemoryAllocationLib >> + BaseMemoryLib >> + >> +[Protocols] >> + gEfiUsbIoProtocolGuid >> + gEfiDevicePathProtocolGuid >> + gEfiDriverBindingProtocolGuid >> + >> +[Depex] >> + TRUE >> diff --git a/UsbNetworkPkg/UsbRndis/UsbRndisFunction.c >> b/UsbNetworkPkg/UsbRndis/UsbRndisFunction.c >> new file mode 100644 >> index 0000000000..a9b7b54f6a >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbRndis/UsbRndisFunction.c >> @@ -0,0 +1,1587 @@ >> +/** @file >> >> + This file contains code for USB Ethernet descriptor >> >> + and specific requests implement. >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#include "UsbRndis.h" >> >> + >> >> +UINT16 StopBulkInCnt =3D 0; >> >> +UINT16 BlockBulkInCnt =3D 0; >> >> + >> >> +/** >> >> + Load All of device descriptor. >> >> + >> >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCO= L >> instance. >> >> + @param[out] ConfigDesc A pointer to the configuration >> descriptor. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_OUT_OF_RESOURCES The request could not be completed >> because the >> >> + buffer specified by DescriptorLength an= d >> Descriptor >> >> + is not large enough to hold the result >> of the request. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device >> error. The transfer >> >> + status is returned in Status. >> >> +**/ >> >> +EFI_STATUS >> >> +LoadAllDescriptor ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> >> + OUT EFI_USB_CONFIG_DESCRIPTOR **ConfigDesc >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINT32 TransStatus; >> >> + EFI_USB_CONFIG_DESCRIPTOR Tmp; >> >> + >> >> + Status =3D UsbIo->UsbGetConfigDescriptor (UsbIo, &Tmp); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status =3D gBS->AllocatePool ( >> >> + EfiBootServicesData, >> >> + Tmp.TotalLength, >> >> + (VOID **)ConfigDesc >> >> + ); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status =3D UsbGetDescriptor ( >> >> + UsbIo, >> >> + USB_DESC_TYPE_CONFIG << 8 | (Tmp.ConfigurationValue - 1), >> // zero based >> >> + 0, >> >> + Tmp.TotalLength, >> >> + *ConfigDesc, >> >> + &TransStatus >> >> + ); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Returns pointer to the next descriptor for the pack of USB descriptor= s >> >> + located in continues memory segment >> >> + >> >> + @param[in] Desc A pointer to the CONFIG_DESCRIPTOR instance. >> >> + @param[in, out] Offset A pointer to the sum of descriptor length. >> >> + >> >> + @retval TRUE The request executed successfully. >> >> + @retval FALSE No next descriptor. >> >> + >> >> +**/ >> >> +BOOLEAN >> >> +NextDescriptor ( >> >> + IN EFI_USB_CONFIG_DESCRIPTOR *Desc, >> >> + IN OUT UINTN *Offset >> >> + ) >> >> +{ >> >> + if ((Desc =3D=3D NULL) || (*Offset >=3D Desc->TotalLength)) { >> >> + return FALSE; >> >> + } >> >> + >> >> + if (((EFI_USB_CONFIG_DESCRIPTOR *)((char *)Desc+*Offset))->Length =3D= =3D >> 0) { >> >> + return FALSE; >> >> + } >> >> + >> >> + *Offset +=3D ((EFI_USB_CONFIG_DESCRIPTOR *)((char >> *)Desc+*Offset))->Length; >> >> + if ( *Offset >=3D Desc->TotalLength ) { >> >> + return FALSE; >> >> + } >> >> + >> >> + return TRUE; >> >> +} >> >> + >> >> +/** >> >> + Read Function descriptor >> >> + >> >> + @param[in] Config A pointer to all of configuration. >> >> + @param[in] FunDescriptorType USB CDC class descriptor SubType. >> >> + @param[out] DataBuffer A pointer to the Data of corresponding >> to device capability. >> >> + >> >> + @retval EFI_SUCCESS The device capability descriptor was >> retrieved >> >> + successfully. >> >> + @retval EFI_UNSUPPORTED No supported. >> >> + @retval EFI_NOT_FOUND The device capability descriptor was not >> found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +GetFunctionalDescriptor ( >> >> + IN EFI_USB_CONFIG_DESCRIPTOR *Config, >> >> + IN UINT8 FunDescriptorType, >> >> + OUT VOID *DataBuffer >> >> + ) >> >> +{ >> >> + EFI_STATUS Status =3D EFI_NOT_FOUND; >> >> + UINTN Offset; >> >> + EFI_USB_INTERFACE_DESCRIPTOR *Interface; >> >> + >> >> + for (Offset =3D 0; NextDescriptor (Config, &Offset);) { >> >> + Interface =3D (EFI_USB_INTERFACE_DESCRIPTOR *)((UINT8 *)Config + >> Offset); >> >> + if (Interface->DescriptorType =3D=3D CS_INTERFACE) { >> >> + if (((USB_HEADER_FUN_DESCRIPTOR *)Interface)->DescriptorSubtype = =3D=3D >> FunDescriptorType) { >> >> + switch (FunDescriptorType) { >> >> + case HEADER_FUN_DESCRIPTOR: >> >> + CopyMem ( >> >> + DataBuffer, >> >> + (USB_HEADER_FUN_DESCRIPTOR *)Interface, >> >> + sizeof (USB_HEADER_FUN_DESCRIPTOR) >> >> + ); >> >> + return EFI_SUCCESS; >> >> + case UNION_FUN_DESCRIPTOR: >> >> + CopyMem ( >> >> + DataBuffer, >> >> + (USB_UNION_FUN_DESCRIPTOR *)Interface, >> >> + ((USB_UNION_FUN_DESCRIPTOR *)Interface)->FunctionLength >> >> + ); >> >> + return EFI_SUCCESS; >> >> + case ETHERNET_FUN_DESCRIPTOR: >> >> + CopyMem ( >> >> + DataBuffer, >> >> + (USB_ETHERNET_FUN_DESCRIPTOR *)Interface, >> >> + sizeof (USB_ETHERNET_FUN_DESCRIPTOR) >> >> + ); >> >> + return EFI_SUCCESS; >> >> + default: >> >> + Status =3D EFI_UNSUPPORTED; >> >> + break; >> >> + } >> >> + } >> >> + } >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Get USB Ethernet IO endpoint and USB CDC data IO endpoint. >> >> + >> >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL >> instance. >> >> + @param[in, out] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE >> instance. >> >> + >> >> +**/ >> >> +VOID >> >> +GetEndpoint ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> >> + IN OUT USB_RNDIS_DEVICE *UsbRndisDevice >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINT8 Index; >> >> + UINT32 Result; >> >> + EFI_USB_INTERFACE_DESCRIPTOR Interface; >> >> + EFI_USB_ENDPOINT_DESCRIPTOR Endpoint; >> >> + >> >> + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + if (Interface.NumEndpoints =3D=3D 0 ) { >> >> + Status =3D UsbSetInterface (UsbIo, 1, 0, &Result); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> >> + ASSERT_EFI_ERROR (Status); >> >> + } >> >> + >> >> + for (Index =3D 0; Index < Interface.NumEndpoints; Index++) { >> >> + Status =3D UsbIo->UsbGetEndpointDescriptor (UsbIo, Index, &Endpoint= ); >> >> + >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + switch ((Endpoint.Attributes & (BIT0 | BIT1))) { >> >> + case USB_ENDPOINT_BULK: >> >> + if (Endpoint.EndpointAddress & BIT7) { >> >> + UsbRndisDevice->BulkInEndpoint =3D Endpoint.EndpointAddress; >> >> + } else { >> >> + UsbRndisDevice->BulkOutEndpoint =3D Endpoint.EndpointAddress; >> >> + } >> >> + >> >> + break; >> >> + case USB_ENDPOINT_INTERRUPT: >> >> + UsbRndisDevice->InterrupEndpoint =3D Endpoint.EndpointAddress; >> >> + break; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + Async USB transfer callback routine. >> >> + >> >> + @param[in] Data Data received or sent via the USB >> Asynchronous Transfer, if the >> >> + transfer completed successfully. >> >> + @param[in] DataLength The length of Data received or sent via >> the Asynchronous >> >> + Transfer, if transfer successfully >> completes. >> >> + @param[in] Context Data passed from >> UsbAsyncInterruptTransfer() request. >> >> + @param[in] Status Indicates the result of the asynchronous >> transfer. >> >> + >> >> + @retval EFI_SUCCESS The asynchronous USB transfer request >> has been successfully executed. >> >> + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request >> failed. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +InterruptCallback ( >> >> + IN VOID *Data, >> >> + IN UINTN DataLength, >> >> + IN VOID *Context, >> >> + IN UINT32 Status >> >> + ) >> >> +{ >> >> + if (((EFI_USB_DEVICE_REQUEST *)Data)->Request =3D=3D 0) { >> >> + CopyMem ( >> >> + (EFI_USB_DEVICE_REQUEST *)Context, >> >> + (EFI_USB_DEVICE_REQUEST *)Data, >> >> + sizeof (EFI_USB_DEVICE_REQUEST) >> >> + ); >> >> + } >> >> + >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This function is used to manage a USB device with an interrupt >> transfer pipe. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in] IsNewTransfer If TRUE, a new transfer will be >> submitted to USB controller. If >> >> + FALSE, the interrupt transfer is delete= d >> from the device's interrupt >> >> + transfer queue. >> >> + @param[in] PollingInterval Indicates the periodic rate, in >> milliseconds, that the transfer is to be >> >> + executed.This parameter is required whe= n >> IsNewTransfer is TRUE. The >> >> + value must be between 1 to 255, >> otherwise EFI_INVALID_PARAMETER is returned. >> >> + The units are in milliseconds. >> >> + @param[in] Request A pointer to the EFI_USB_DEVICE_REQUEST >> data. >> >> + >> >> + @retval EFI_SUCCESS The asynchronous USB transfer request >> transfer has been successfully executed. >> >> + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request >> failed. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbRndisInterrupt ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN BOOLEAN IsNewTransfer, >> >> + IN UINTN PollingInterval, >> >> + IN EFI_USB_DEVICE_REQUEST *Requst >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> >> + UINTN DataLength =3D 0; >> >> + >> >> + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This); >> >> + >> >> + if (IsNewTransfer =3D=3D TRUE) { >> >> + DataLength =3D sizeof (EFI_USB_DEVICE_REQUEST) + sizeof >> (USB_CONNECT_SPEED_CHANGE); >> >> + Status =3D UsbRndisDevice->UsbIo->UsbAsyncInterruptTransfer ( >> >> + UsbRndisDevice->UsbIo, >> >> + >> UsbRndisDevice->InterrupEndpoint, >> >> + IsNewTransfer, >> >> + PollingInterval, >> >> + DataLength, >> >> + InterruptCallback, >> >> + Requst >> >> + ); >> >> + >> >> + if (Status =3D=3D EFI_INVALID_PARAMETER) { >> >> + // Because of Stacked AsyncInterrupt request are not supported >> >> + Status =3D UsbRndisDevice->UsbIo->UsbAsyncInterruptTransfer ( >> >> + UsbRndisDevice->UsbIo, >> >> + UsbRndisDevice->InterrupEndpoin= t, >> >> + 0, >> >> + 0, >> >> + 0, >> >> + NULL, >> >> + NULL >> >> + ); >> >> + } >> >> + } else { >> >> + Status =3D UsbRndisDevice->UsbIo->UsbAsyncInterruptTransfer ( >> >> + UsbRndisDevice->UsbIo, >> >> + UsbRndisDevice->InterrupEndpoint, >> >> + IsNewTransfer, >> >> + 0, >> >> + 0, >> >> + NULL, >> >> + NULL >> >> + ); >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Ethernet Mac Address. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[out] MacAddress A pointer to the caller allocated USB >> Ethernet Mac Address. >> >> + >> >> + @retval EFI_SUCCESS The USB Header Functional descriptor wa= s >> retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor wa= s >> not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthMacAddress ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT EFI_MAC_ADDRESS *MacAddress >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthDescriptor; >> >> + CHAR16 *Data; >> >> + CHAR16 *DataPtr; >> >> + CHAR16 TmpStr[1]; >> >> + UINT8 Index; >> >> + UINT8 Hi; >> >> + UINT8 Low; >> >> + >> >> + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This); >> >> + >> >> + Status =3D This->UsbEthFunDescriptor (This, &UsbEthDescriptor); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status =3D UsbRndisDevice->UsbIo->UsbGetStringDescriptor ( >> >> + UsbRndisDevice->UsbIo, >> >> + 0x409, // >> English-US Language ID >> >> + UsbEthDescriptor.MacAddress, >> >> + &Data >> >> + ); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + DataPtr =3D Data; >> >> + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> >> + CopyMem (TmpStr, DataPtr, sizeof (CHAR16)); >> >> + DataPtr++; >> >> + Hi =3D (UINT8)StrHexToUintn (TmpStr); >> >> + CopyMem (TmpStr, DataPtr, sizeof (CHAR16)); >> >> + DataPtr++; >> >> + Low =3D (UINT8)StrHexToUintn (TmpStr); >> >> + MacAddress->Addr[Index] =3D (Hi << 4) | Low; >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Ethernet Bulk transfer data size. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[out] BulkSize A pointer to the Bulk transfer data size. >> >> + >> >> + @retval EFI_SUCCESS The bulk transfer data size was retrieved >> successfully. >> >> + @retval other Failed to retrieve the bulk transfer data >> size. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthBulkSize ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT UINTN *BulkSize >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; >> >> + >> >> + Status =3D This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + *BulkSize =3D (UINTN)UsbEthFunDescriptor.MaxSegmentSize; >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Header functional Descriptor. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[out] UsbHeaderFunDescriptor A pointer to the caller allocated >> USB Header Functional Descriptor. >> >> + >> >> + @retval EFI_SUCCESS The USB Header Functional descriptor wa= s >> retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor wa= s >> not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbHeaderFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> >> + >> >> + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This); >> >> + >> >> + if (UsbHeaderFunDescriptor =3D=3D NULL) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + Status =3D GetFunctionalDescriptor ( >> >> + UsbRndisDevice->Config, >> >> + HEADER_FUN_DESCRIPTOR, >> >> + UsbHeaderFunDescriptor >> >> + ); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Union functional Descriptor. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[out] UsbUnionFunDescriptor A pointer to the caller allocated >> USB Union Functional Descriptor. >> >> + >> >> + @retval EFI_SUCCESS The USB Union Functional descriptor wa= s >> retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbUnionFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Union Functional descriptor wa= s >> not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbUnionFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> >> + >> >> + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This); >> >> + >> >> + if (UsbUnionFunDescriptor =3D=3D NULL) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + Status =3D GetFunctionalDescriptor ( >> >> + UsbRndisDevice->Config, >> >> + UNION_FUN_DESCRIPTOR, >> >> + UsbUnionFunDescriptor >> >> + ); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Ethernet functional Descriptor. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[out] UsbEthFunDescriptor A pointer to the caller allocated >> USB Ethernet Functional Descriptor. >> >> + >> >> + @retval EFI_SUCCESS The USB Ethernet Functional descriptor >> was retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbEthFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Ethernet Functional descriptor >> was not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbRndisFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> >> + >> >> + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This); >> >> + >> >> + if (UsbEthFunDescriptor =3D=3D NULL) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + Status =3D GetFunctionalDescriptor ( >> >> + UsbRndisDevice->Config, >> >> + ETHERNET_FUN_DESCRIPTOR, >> >> + UsbEthFunDescriptor >> >> + ); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + This request sets the Ethernet device multicast filters as specified >> in the >> >> + sequential list of 48 bit Ethernet multicast addresses. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] Value Number of filters. >> >> + @param[in] McastAddr A pointer to the value of the >> multicast addresses. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the >> request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device >> error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbRndisMcastFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN VOID *McastAddr >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> + UINT32 TransStatus; >> >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> >> + >> >> + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This); >> >> + >> >> + Status =3D This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + if ((UsbEthFunDescriptor.NumberMcFilters << 1) =3D=3D 0) { >> >> + return EFI_UNSUPPORTED; >> >> + } >> >> + >> >> + Request.RequestType =3D USB_ETHRTNET_SET_REQ_TYPE; >> >> + Request.Request =3D SET_ETH_MULTICAST_FILTERS_REQ; >> >> + Request.Value =3D Value; >> >> + Request.Index =3D UsbRndisDevice->NumOfInterface; >> >> + Request.Length =3D Value * 6; >> >> + >> >> + return UsbRndisDevice->UsbIo->UsbControlTransfer ( >> >> + UsbRndisDevice->UsbIo, >> >> + &Request, >> >> + EfiUsbDataOut, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + McastAddr, >> >> + Request.Length, >> >> + &TransStatus >> >> + ); >> >> +} >> >> + >> >> +/** >> >> + This request sets up the specified Ethernet power management pattern >> filter as >> >> + described in the data structure. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] Value Number of filters. >> >> + @param[in] Length Size of the power management patter= n >> filter data. >> >> + @param[in] PatternFilter A pointer to the power management >> pattern filter structure. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the >> request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device >> error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbRndisPowerFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN UINT16 Length, >> >> + IN VOID *PatternFilter >> >> + ) >> >> +{ >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> + UINT32 TransStatus; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> >> + >> >> + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This); >> >> + >> >> + Request.RequestType =3D USB_ETHRTNET_SET_REQ_TYPE; >> >> + Request.Request =3D SET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ; >> >> + Request.Value =3D Value; >> >> + Request.Index =3D UsbRndisDevice->NumOfInterface; >> >> + Request.Length =3D Length; >> >> + >> >> + return UsbRndisDevice->UsbIo->UsbControlTransfer ( >> >> + UsbRndisDevice->UsbIo, >> >> + &Request, >> >> + EfiUsbDataOut, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + PatternFilter, >> >> + Length, >> >> + &TransStatus >> >> + ); >> >> +} >> >> + >> >> +/** >> >> + This request retrieves the status of the specified Ethernet power >> management >> >> + pattern filter from the device. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] Value The filter number. >> >> + @param[out] PatternActive A pointer to the pattern active >> boolean. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the >> request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device >> error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbRndisPowerFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + OUT BOOLEAN *PatternActive >> >> + ) >> >> +{ >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> + UINT32 TransStatus; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> >> + >> >> + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This); >> >> + >> >> + Request.RequestType =3D USB_ETHERNET_GET_REQ_TYPE; >> >> + Request.Request =3D GET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ; >> >> + Request.Value =3D Value; >> >> + Request.Index =3D UsbRndisDevice->NumOfInterface; >> >> + Request.Length =3D USB_ETH_POWER_FILTER_LENGTH; >> >> + >> >> + return UsbRndisDevice->UsbIo->UsbControlTransfer ( >> >> + UsbRndisDevice->UsbIo, >> >> + &Request, >> >> + EfiUsbDataIn, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + PatternActive, >> >> + USB_ETH_POWER_FILTER_LENGTH, >> >> + &TransStatus >> >> + ); >> >> +} >> >> + >> >> +/** >> >> + >> >> + Converts PXE filter settings to RNDIS values >> >> + >> >> + @param[in] Value PXE filter data. >> >> + @param[out] CdcFilter A pointer to the Ethernet Packet Filter Bitmap >> value converted by PXE_OPFLAGS. >> >> + >> >> +**/ >> >> +VOID >> >> +ConvertFilter ( >> >> + IN UINT16 Value, >> >> + OUT UINT16 *CdcFilter >> >> + ) >> >> +{ >> >> + UINT32 Index; >> >> + UINT32 Count; >> >> + static struct BIT_MAP Table[] =3D { >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_UNICAST, >> NDIS_PACKET_TYPE_DIRECTED }, >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST, >> NDIS_PACKET_TYPE_BROADCAST }, >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST, >> NDIS_PACKET_TYPE_MULTICAST }, >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS, >> NDIS_PACKET_TYPE_PROMISCUOUS }, >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST, >> NDIS_PACKET_TYPE_ALL_MULTICAST }, >> >> + }; >> >> + >> >> + Count =3D sizeof (Table)/sizeof (Table[0]); >> >> + >> >> + for (Index =3D 0; (Table[Index].Src !=3D 0) && (Index < Count); Index= ++) { >> >> + if (Table[Index].Src & Value) { >> >> + *CdcFilter |=3D Table[Index].Dst; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + >> >> + Updates Filter settings on the device. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_STATUS >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiReceiveFilter ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINT8 *McastList; >> >> + UINT8 Count =3D 0; >> >> + UINT8 Index1; >> >> + UINT8 Index2; >> >> + UINT64 CpbAddr =3D Cdb->CPBaddr; >> >> + UINT32 CpbSize =3D Cdb->CPBsize; >> >> + UINT16 SetFilter =3D (UINT16)(Cdb->OpFlags & 0x= 1F); >> >> + PXE_CPB_RECEIVE_FILTERS *Cpb =3D (PXE_CPB_RECEIVE_FILTERS >> *)(UINTN)CpbAddr; >> >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; >> >> + >> >> + // The Cpb could be NULL.(ref:PXE_CPBADDR_NOT_USED) >> >> + Nic->RxFilter =3D (UINT8)SetFilter; >> >> + >> >> + if (((SetFilter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) !=3D= 0) >> || (Cpb !=3D NULL)) { >> >> + if (Cpb !=3D NULL) { >> >> + Nic->McastCount =3D (UINT8)(CpbSize / PXE_MAC_LENGTH); >> >> + CopyMem (&Nic->McastList, Cpb, Nic->McastCount); >> >> + } else { >> >> + Nic->McastCount =3D 0; >> >> + } >> >> + >> >> + if (Nic->CanReceive) { >> >> + Nic->CanReceive =3D FALSE; >> >> + } >> >> + >> >> + Nic->UsbEth->UsbEthFunDescriptor (Nic->UsbEth, &UsbEthFunDescriptor= ); >> >> + if ((UsbEthFunDescriptor.NumberMcFilters << 1) =3D=3D 0) { >> >> + Nic->RxFilter |=3D PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST; >> >> + DEBUG ((DEBUG_INFO, "SetUsbEthPacketFilter Nic %lx Nic->UsbEth %l= x >> ", Nic, Nic->UsbEth)); >> >> + Nic->UsbEth->SetUsbEthPacketFilter (Nic->UsbEth, Nic->RxFilter); >> >> + } else { >> >> + Status =3D gBS->AllocatePool (EfiBootServicesData, Nic->McastCoun= t * >> 6, (VOID **)&McastList); >> >> + if (EFI_ERROR (Status)) { >> >> + return PXE_STATCODE_INVALID_PARAMETER; >> >> + } >> >> + >> >> + if (Cpb !=3D NULL) { >> >> + for (Index1 =3D 0; Index1 < Nic->McastCount; Index1++) { >> >> + for (Index2 =3D 0; Index2 < 6; Index2++) { >> >> + McastList[Count++] =3D Cpb->MCastList[Index1][Index2]; >> >> + } >> >> + } >> >> + } >> >> + >> >> + Nic->RxFilter |=3D PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST; >> >> + if (Cpb !=3D NULL) { >> >> + Nic->UsbEth->SetUsbEthMcastFilter (Nic->UsbEth, Nic->McastCount= , >> McastList); >> >> + } >> >> + >> >> + Nic->UsbEth->SetUsbEthPacketFilter (Nic->UsbEth, Nic->RxFilter); >> >> + gBS->FreePool (McastList); >> >> + } >> >> + } >> >> + >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This request is used to configure device Ethernet packet filter >> settings. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in] Value Packet Filter Bitmap. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbRndisPacketFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value >> >> + ) >> >> +{ >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This request is used to retrieve a statistic based on the feature >> selector. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] FeatureSelector Value of the feature selector. >> >> + @param[out] Statistic A pointer to the 32 bit unsigned >> integer. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetRndisStatistic ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 FeatureSelector, >> >> + OUT VOID *Statistic >> >> + ) >> >> +{ >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This function is called when UndiStart is invoked. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiStart ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + >> >> + DEBUG ((DEBUG_INFO, "RndisUndiStart Nic %lx Cdb %lx Nic State %x\n", >> Nic, Cdb, Nic->State)); >> >> + >> >> + // Issue Rndis Reset and bring the device to RNDIS_BUS_INITIALIZED >> state >> >> + Status =3D RndisUndiReset (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + RndisUndiReset (Cdb, Nic); >> >> + } >> >> + >> >> + Status =3D RndisUndiInitialize (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + RndisUndiInitialize (Cdb, Nic); >> >> + } >> >> + >> >> + RndisUndiShutdown (Cdb, Nic); >> >> + >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This function is called when Undistop is invoked. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiStop ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + DEBUG ((DEBUG_INFO, "RndisUndiStop State %x\n", Nic->State)); >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This function is called when UndiGetInitInfo is invoked. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiGetInitInfo ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + USB_ETHERNET_PROTOCOL *UsbEthDevice =3D Nic->UsbEth; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS >> (UsbEthDevice); >> >> + PXE_DB_GET_INIT_INFO *Db; >> >> + >> >> + DEBUG ((DEBUG_INFO, "RndisUndiGetInitInfo\n")); >> >> + >> >> + Db =3D (PXE_DB_GET_INIT_INFO *)(UINTN)Cdb->DBaddr; >> >> + >> >> + Db->FrameDataLen =3D UsbRndisDevice->MaxTransferSize - sizeof >> (REMOTE_NDIS_PACKET_MSG) - PXE_MAC_HEADER_LEN_ETHER; >> >> + // Limit Max MTU size to 1500 bytes as RNDIS spec. >> >> + if (Db->FrameDataLen > PXE_MAX_TXRX_UNIT_ETHER) { >> >> + Db->FrameDataLen =3D PXE_MAX_TXRX_UNIT_ETHER; >> >> + } >> >> + >> >> + DEBUG ((DEBUG_INFO, "Db->FrameDataLen %x\n", Db->FrameDataLen)); >> >> + >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This function is called when RndisUndiGetConfigInfo is invoked. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiGetConfigInfo ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + DEBUG ((DEBUG_INFO, "RndisUndiGetConfigInfo\n")); >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This function is called when UndiInitialize is invoked. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiInitialize ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + USB_ETHERNET_PROTOCOL *UsbEthDriver =3D Nic->UsbEth; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice =3D >> USB_RNDIS_DEVICE_FROM_THIS (UsbEthDriver); >> >> + REMOTE_NDIS_INITIALIZE_MSG RndisInitMsg; >> >> + REMOTE_NDIS_INITIALIZE_CMPLT RndisInitMsgCmplt; >> >> + EFI_STATUS Status; >> >> + >> >> + DEBUG ((DEBUG_INFO, "RndisUndiInitialize\n")); >> >> + >> >> + ZeroMem (&RndisInitMsg, sizeof (REMOTE_NDIS_INITIALIZE_MSG)); >> >> + ZeroMem (&RndisInitMsgCmplt, sizeof (REMOTE_NDIS_INITIALIZE_CMPLT)); >> >> + >> >> + RndisInitMsg.MessageType =3D RNDIS_INITIALIZE_MSG; >> >> + RndisInitMsg.MessageLength =3D sizeof (REMOTE_NDIS_INITIALIZE_MSG); >> >> + RndisInitMsg.RequestID =3D UsbRndisDevice->RequestId; >> >> + RndisInitMsg.MajorVersion =3D RNDIS_MAJOR_VERSION; >> >> + RndisInitMsg.MinorVersion =3D RNDIS_MINOR_VERSION; >> >> + RndisInitMsg.MaxTransferSize =3D RNDIS_MAX_TRANSFER_SIZE; >> >> + >> >> + RndisInitMsgCmplt.MessageType =3D RNDIS_INITIALIZE_CMPLT; >> >> + RndisInitMsgCmplt.MessageLength =3D sizeof >> (REMOTE_NDIS_INITIALIZE_CMPLT); >> >> + >> >> + Status =3D RndisControlMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_HEADER >> *)&RndisInitMsg, (REMOTE_NDIS_MSG_HEADER *)&RndisInitMsgCmplt); >> >> + >> >> + UsbRndisDevice->RequestId++; >> >> + >> >> + if (EFI_ERROR (Status) || (RndisInitMsgCmplt.Status & 0x80000000)) { >> >> + return Status; >> >> + } >> >> + >> >> + // Only Wired Medium is supported >> >> + if (RndisInitMsgCmplt.Medium) { >> >> + return EFI_UNSUPPORTED; >> >> + } >> >> + >> >> + UsbRndisDevice->Medium =3D RndisInitMsgCmplt.Medium; >> >> + UsbRndisDevice->MaxPacketsPerTransfer =3D >> RndisInitMsgCmplt.MaxPacketsPerTransfer; >> >> + UsbRndisDevice->MaxTransferSize =3D >> RndisInitMsgCmplt.MaxTransferSize; >> >> + UsbRndisDevice->PacketAlignmentFactor =3D >> RndisInitMsgCmplt.PacketAlignmentFactor; >> >> + >> >> + DEBUG ((DEBUG_INFO, "Medium : %x \n", RndisInitMsgCmplt.Medium)); >> >> + DEBUG ((DEBUG_INFO, "MaxPacketsPerTransfer : %x \n", >> RndisInitMsgCmplt.MaxPacketsPerTransfer)); >> >> + DEBUG ((DEBUG_INFO, "MaxTransferSize : %x\n", >> RndisInitMsgCmplt.MaxTransferSize)); >> >> + DEBUG ((DEBUG_INFO, "PacketAlignmentFactor : %x\n", >> RndisInitMsgCmplt.PacketAlignmentFactor)); >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + This function is called when UndiReset is invoked. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiReset ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + USB_ETHERNET_PROTOCOL *UsbEthDriver =3D Nic->UsbEth; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_TH= IS >> (UsbEthDriver); >> >> + REMOTE_NDIS_RESET_MSG RndisResetMsg; >> >> + REMOTE_NDIS_RESET_CMPLT RndisResetCmplt; >> >> + EFI_STATUS Status; >> >> + >> >> + DEBUG ((DEBUG_INFO, "RndisUndiReset\n")); >> >> + >> >> + ZeroMem (&RndisResetMsg, sizeof (REMOTE_NDIS_RESET_MSG)); >> >> + ZeroMem (&RndisResetCmplt, sizeof (REMOTE_NDIS_RESET_CMPLT)); >> >> + >> >> + RndisResetMsg.MessageType =3D RNDIS_RESET_MSG; >> >> + RndisResetMsg.MessageLength =3D sizeof (REMOTE_NDIS_RESET_MSG); >> >> + >> >> + RndisResetCmplt.MessageType =3D RNDIS_RESET_CMPLT; >> >> + RndisResetCmplt.MessageLength =3D sizeof (REMOTE_NDIS_RESET_CMPLT); >> >> + >> >> + Status =3D RndisControlMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_HEADER >> *)&RndisResetMsg, (REMOTE_NDIS_MSG_HEADER *)&RndisResetCmplt); >> >> + >> >> + UsbRndisDevice->RequestId =3D 1; // Let's start with 1 >> >> + >> >> + if (EFI_ERROR (Status) || (RndisResetCmplt.Status & 0x80000000)) { >> >> + return EFI_DEVICE_ERROR; >> >> + } >> >> + >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This function is called when UndiShutdown is invoked. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiShutdown ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + USB_ETHERNET_PROTOCOL *UsbEthDriver =3D Nic->UsbEth; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS >> (UsbEthDriver); >> >> + REMOTE_NDIS_HALT_MSG RndisHltMsg; >> >> + EFI_STATUS Status; >> >> + >> >> + DEBUG ((DEBUG_INFO, "RndisUndiShutdown\n")); >> >> + >> >> + ZeroMem (&RndisHltMsg, sizeof (REMOTE_NDIS_HALT_MSG)); >> >> + >> >> + RndisHltMsg.MessageType =3D RNDIS_HLT_MSG; >> >> + RndisHltMsg.MessageLength =3D sizeof (REMOTE_NDIS_HALT_MSG); >> >> + >> >> + Status =3D RndisControlMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_HEADER >> *)&RndisHltMsg, NULL); >> >> + >> >> + if (Status =3D=3D EFI_DEVICE_ERROR) { >> >> + Status =3D EFI_SUCCESS; >> >> + } >> >> + >> >> + UsbRndisDevice->RequestId =3D 1; >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Update the Media connection. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiGetStatus ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + Cdb->StatFlags &=3D ~(PXE_STATFLAGS_GET_STATUS_NO_MEDIA); >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + Transmit the data after appending RNDIS header. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor >> block. >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in] BulkOutData A pointer to the buffer of data that >> will be transmitted to USB >> >> + device or received from USB device. >> >> + @param[in, out] DataLength A pointer to the PacketLength. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiTransmit ( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN VOID *BulkOutData, >> >> + IN OUT UINTN *DataLength >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THI= S >> (This); >> >> + REMOTE_NDIS_PACKET_MSG *RndisPacketMsg; >> >> + UINTN TransferLength; >> >> + >> >> + DEBUG ((DEBUG_INFO, "RndisUndiTransmit DataLength : %x\n", >> *DataLength)); >> >> + >> >> + Status =3D gBS->AllocatePool (EfiBootServicesData, sizeof >> (REMOTE_NDIS_PACKET_MSG) + *DataLength, (VOID **)&RndisPacketMsg); >> >> + >> >> + ZeroMem (RndisPacketMsg, sizeof (REMOTE_NDIS_PACKET_MSG)); >> >> + >> >> + RndisPacketMsg->MessageType =3D RNDIS_PACKET_MSG; >> >> + RndisPacketMsg->MessageLength =3D sizeof (REMOTE_NDIS_PACKET_MSG) + >> (UINT32)*DataLength; >> >> + RndisPacketMsg->DataOffset =3D sizeof (REMOTE_NDIS_PACKET_MSG) - 8= ; >> >> + RndisPacketMsg->DataLength =3D (UINT32)*DataLength; >> >> + >> >> + gBS->CopyMem (((UINT8 *)RndisPacketMsg) + sizeof >> (REMOTE_NDIS_PACKET_MSG), BulkOutData, *DataLength); >> >> + >> >> + TransferLength =3D RndisPacketMsg->MessageLength; >> >> + >> >> + Status =3D RndisTransmitDataMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_HEA= DER >> *)RndisPacketMsg, &TransferLength); >> >> + >> >> + DEBUG ((DEBUG_INFO, "\nRndisUndiTransmit TransferLength %lx\n", >> TransferLength)); >> >> + >> >> + gBS->FreePool (RndisPacketMsg); >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Receives and removes RNDIS header and returns the raw data. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor >> block. >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in, out] BulkInData A pointer to the buffer of data that >> will be transmitted to USB >> >> + device or received from USB device. >> >> + @param[in, out] DataLength A pointer to the PacketLength. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_BUFFER_TOO_SMALL The user provided buffer is too small >> >> + @retval EFI_NOT_FOUND No buffer was found in the list. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiReceive ( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN OUT VOID *BulkInData, >> >> + IN OUT UINTN *DataLength >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THI= S >> (This); >> >> + REMOTE_NDIS_PACKET_MSG *RndisPacketMsg; >> >> + UINTN TransferLength; >> >> + VOID *Buffer; >> >> + PACKET_LIST *HeadPacket =3D NULL; >> >> + PACKET_LIST *PacketList; >> >> + UINT32 ReceivedBytes =3D 0; >> >> + >> >> + // Check if there is any outstanding packet to receive >> >> + // The buffer allocated has a linked List followed by the packet. >> >> + do { >> >> + Status =3D gBS->AllocatePool (EfiBootServicesData, sizeof >> (PACKET_LIST) + sizeof (REMOTE_NDIS_PACKET_MSG) + >> UsbRndisDevice->MaxTransferSize, &Buffer); >> >> + RndisPacketMsg =3D (REMOTE_NDIS_PACKET_MSG *)(sizeof (PACKET_LIST) = + >> (UINT8 *)Buffer); >> >> + PacketList =3D (PACKET_LIST *)Buffer; >> >> + // Save the original address for freeing it up >> >> + PacketList->OrgBuffer =3D Buffer; >> >> + PacketList->RemainingLength =3D UsbRndisDevice->MaxTransferSize; >> >> + >> >> + ZeroMem (RndisPacketMsg, sizeof (REMOTE_NDIS_PACKET_MSG)); >> >> + TransferLength =3D UsbRndisDevice->MaxTransferSize; >> >> + >> >> + Status =3D RndisReceiveDataMsg (UsbRndisDevice, >> (REMOTE_NDIS_MSG_HEADER *)RndisPacketMsg, &TransferLength); >> >> + >> >> + if (EFI_ERROR (Status) || (TransferLength =3D=3D 0)) { >> >> + gBS->FreePool (Buffer); >> >> + break; >> >> + } >> >> + >> >> + // Handle Multiple packets >> >> + if ((RndisPacketMsg->MessageType =3D=3D RNDIS_PACKET_MSG) && >> (RndisPacketMsg->DataOffset =3D=3D sizeof (REMOTE_NDIS_PACKET_MSG) - 8))= { >> >> + // Insert Packet >> >> + InsertTailList (&UsbRndisDevice->ReceivePacketList, Buffer); >> >> + } >> >> + } while (1); >> >> + >> >> + // Check if they linked list has any received buffer. If yes report i= t. >> >> + if (IsListEmpty (&UsbRndisDevice->ReceivePacketList)) { >> >> + return EFI_NOT_FOUND; >> >> + } >> >> + >> >> + HeadPacket =3D (PACKET_LIST *)GetFirstNode >> (&UsbRndisDevice->ReceivePacketList); >> >> + >> >> + RndisPacketMsg =3D (REMOTE_NDIS_PACKET_MSG *)((UINT8 *)HeadPacket + >> sizeof (PACKET_LIST)); >> >> + >> >> + PrintRndisMsg ((REMOTE_NDIS_MSG_HEADER *)RndisPacketMsg); >> >> + >> >> + if ((RndisPacketMsg->MessageType =3D=3D RNDIS_PACKET_MSG) && >> (RndisPacketMsg->DataOffset =3D=3D sizeof (REMOTE_NDIS_PACKET_MSG) - 8))= { >> >> + if (*DataLength >=3D RndisPacketMsg->DataLength) { >> >> + gBS->CopyMem (BulkInData, (UINT8 *)RndisPacketMsg + >> RndisPacketMsg->DataOffset + 8, RndisPacketMsg->DataLength); >> >> + >> >> + ReceivedBytes +=3D >> RndisPacketMsg->DataLength; >> >> + BulkInData =3D ((UINT8 >> *)BulkInData) + RndisPacketMsg->DataLength; >> >> + ((PACKET_LIST *)HeadPacket)->RemainingLength -=3D >> RndisPacketMsg->DataLength; >> >> + } else { >> >> + DEBUG ((EFI_D_ERROR, "RndisUndiReceive:Buffer too small %x\n", >> RndisPacketMsg->DataLength)); >> >> + *DataLength =3D RndisPacketMsg->DataLength; >> >> + return EFI_BUFFER_TOO_SMALL; >> >> + } >> >> + >> >> + // check if there this is a multi-packet message. If so update the >> pointer so that next Receive call will return that data. >> >> + RndisPacketMsg =3D (REMOTE_NDIS_PACKET_MSG *)((UINT8 *)RndisPacketM= sg >> + RndisPacketMsg->DataLength); >> >> + PacketList =3D (PACKET_LIST *)((UINT8 *)RndisPacketMsg - sizeof >> (PACKET_LIST)); >> >> + >> >> + if ((HeadPacket->RemainingLength > sizeof (REMOTE_NDIS_PACKET_MSG)) >> && \ >> >> + (RndisPacketMsg->MessageType =3D=3D RNDIS_PACKET_MSG) && \ >> >> + (RndisPacketMsg->DataOffset =3D=3D sizeof (REMOTE_NDIS_PACKET_M= SG) - >> 8)) >> >> + { >> >> + // Multi-Packet msg is found. Since the first packet is consumed, >> update the linked list to point this new packet. >> >> + PacketList->OrgBuffer =3D HeadPacket->OrgBuffer; >> >> + PacketList->RemainingLength =3D HeadPacket->RemainingLength; >> >> + RemoveEntryList (&HeadPacket->PacketList); >> >> + InsertHeadList (&UsbRndisDevice->ReceivePacketList, >> &(PacketList->PacketList)); >> >> + } else { >> >> + RemoveEntryList (&HeadPacket->PacketList); >> >> + gBS->FreePool ((PACKET_LIST *)HeadPacket->OrgBuffer); >> >> + } >> >> + } else { >> >> + // Packet doesn't contain valid header >> >> + DEBUG ((DEBUG_INFO, "RndisUndiReceive:Invalid RNDIS Packet >> received\n")); >> >> + RemoveEntryList (&(HeadPacket->PacketList)); >> >> + gBS->FreePool ((PACKET_LIST *)HeadPacket->OrgBuffer); >> >> + } >> >> + >> >> + if (ReceivedBytes) { >> >> + *DataLength =3D ReceivedBytes; >> >> + } >> >> + >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This is a dummy function which just returns. Unimplimented >> USB_ETHERNET_PROTOCOL functions >> >> + point to this function. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisDummyReturn ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + DEBUG ((DEBUG_INFO, "RndisDummyReturn called\n")); >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This function sends the RNDIS SET_MSG cmd >> >> + >> >> + @param[in] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE instanc= e. >> >> + @param[in] Oid Value of the OID. >> >> + @param[in] Length Length of the data buffer. >> >> + @param[in] Buf A pointer to the data buffer. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +SendRndisSetMsg ( >> >> + IN USB_RNDIS_DEVICE *UsbRndisDevice, >> >> + IN UINT8 Oid, >> >> + IN UINT32 Length, >> >> + IN UINT8 *Buf >> >> + ) >> >> +{ >> >> + REMOTE_NDIS_SET_MSG *RndisSetMsg; >> >> + EFI_STATUS Status; >> >> + >> >> + RndisSetMsg =3D AllocateZeroPool (sizeof (USB_RNDIS_DEVICE) + Length)= ; >> >> + >> >> + RndisSetMsg->MessageType =3D RNDIS_SET_MSG; >> >> + RndisSetMsg->MessageLength =3D sizeof (REMOTE_NDIS_SET_MSG)= + >> Length; >> >> + RndisSetMsg->RequestID =3D UsbRndisDevice->RequestId; >> >> + RndisSetMsg->Oid =3D Oid; >> >> + RndisSetMsg->InformationBufferLength =3D Length; >> >> + RndisSetMsg->InformationBufferOffset =3D sizeof (REMOTE_NDIS_SET_MSG)= - >> 8; >> >> + >> >> + gBS->CopyMem (((UINT8 *)RndisSetMsg) + sizeof (REMOTE_NDIS_SET_MSG), >> Buf, Length); >> >> + >> >> + Status =3D RndisControlMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_HEADER >> *)RndisSetMsg, NULL); >> >> + >> >> + gBS->FreePool (RndisSetMsg); >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + This function send the RNDIS command through the device's control >> endpoint >> >> + >> >> + @param[in] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE >> instance. >> >> + @param[in] RndisMsg A pointer to the REMOTE_NDIS_MSG_HEADER >> data. >> >> + @param[out] RndisMsgResponse A pointer to the REMOTE_NDIS_MSG_HEADER >> data for getting responses. >> >> + >> >> + @retval EFI_SUCCESS The bulk transfer has been successfully >> executed. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +RndisControlMsg ( >> >> + IN USB_RNDIS_DEVICE *UsbRndisDevice, >> >> + IN REMOTE_NDIS_MSG_HEADER *RndisMsg, >> >> + OUT REMOTE_NDIS_MSG_HEADER *RndisMsgResponse >> >> + ) >> >> +{ >> >> + EFI_USB_IO_PROTOCOL *UsbIo =3D UsbRndisDevice->UsbIo; >> >> + EFI_USB_DEVICE_REQUEST DevReq; >> >> + UINT32 UsbStatus; >> >> + EFI_STATUS Status; >> >> + UINT32 SaveResponseType =3D 0; >> >> + UINT32 SaveResponseLength =3D 0; >> >> + UINT32 Index; >> >> + REMOTE_NDIS_INITIALIZE_CMPLT *RndisInitCmplt =3D >> (REMOTE_NDIS_INITIALIZE_CMPLT *)RndisMsgResponse; >> >> + >> >> + if (RndisMsgResponse) { >> >> + SaveResponseType =3D RndisMsgResponse->MessageType; >> >> + SaveResponseLength =3D RndisMsgResponse->MessageLength; >> >> + } >> >> + >> >> + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); >> >> + >> >> + DevReq.RequestType =3D USB_REQ_TYPE_CLASS | USB_TARGET_INTERFACE; >> >> + DevReq.Request =3D SEND_ENCAPSULATED_COMMAND; >> >> + DevReq.Value =3D 0; >> >> + DevReq.Index =3D 0; >> >> + DevReq.Length =3D (UINT16)RndisMsg->MessageLength; >> >> + >> >> + PrintRndisMsg (RndisMsg); >> >> + >> >> + Status =3D UsbIo->UsbControlTransfer ( >> >> + UsbIo, >> >> + &DevReq, >> >> + EfiUsbDataOut, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + RndisMsg, >> >> + RndisMsg->MessageLength, >> >> + &UsbStatus >> >> + ); >> >> + >> >> + DEBUG ((DEBUG_INFO, "RndisControlMsg: UsbStatus : %x Status : %r >> RndisMsgResponse : %lx\n", UsbStatus, Status, RndisMsgResponse)); >> >> + >> >> + // Error or no response expected >> >> + if ((EFI_ERROR (Status)) || (RndisMsgResponse =3D=3D NULL)) { >> >> + DEBUG ((DEBUG_INFO, "RndisControlMsg: UsbStatus : %x Status : %r\n"= , >> UsbStatus, Status)); >> >> + return Status; >> >> + } >> >> + >> >> + for (Index =3D 0; Index < (RNDIS_CONTROL_TIMEOUT/100); Index++) { >> >> + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); >> >> + >> >> + DevReq.RequestType =3D USB_ENDPOINT_DIR_IN | USB_REQ_TYPE_CLASS | >> USB_TARGET_INTERFACE; >> >> + DevReq.Request =3D GET_ENCAPSULATED_RESPONSE; >> >> + DevReq.Value =3D 0; >> >> + DevReq.Index =3D 0; >> >> + DevReq.Length =3D (UINT16)RndisMsgResponse->MessageLength; >> >> + >> >> + Status =3D UsbIo->UsbControlTransfer ( >> >> + UsbIo, >> >> + &DevReq, >> >> + EfiUsbDataIn, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + RndisMsgResponse, >> >> + RndisMsgResponse->MessageLength, >> >> + &UsbStatus >> >> + ); >> >> + >> >> + DEBUG ((DEBUG_INFO, "RndisControlMsg Response: UsbStatus : %x Statu= s >> : %r \n", UsbStatus, Status)); >> >> + >> >> + PrintRndisMsg (RndisMsgResponse); >> >> + >> >> + if (!EFI_ERROR (Status)) { >> >> + if ((RndisInitCmplt->RequestID !=3D ((REMOTE_NDIS_INITIALIZE_CMPL= T >> *)RndisMsg)->RequestID) || (RndisInitCmplt->MessageType !=3D >> SaveResponseType)) { >> >> + DEBUG ((DEBUG_INFO, "Retry the response\n")); >> >> + continue; >> >> + } >> >> + >> >> + return Status; >> >> + } >> >> + >> >> + RndisMsgResponse->MessageType =3D SaveResponseType; >> >> + RndisMsgResponse->MessageLength =3D SaveResponseLength; >> >> + >> >> + gBS->Stall (100000); // 100msec >> >> + } >> >> + >> >> + DEBUG ((DEBUG_INFO, "RndisControlMsg: TimeOut\n")); >> >> + >> >> + return EFI_TIMEOUT; >> >> +} >> >> + >> >> +/** >> >> + This function send the RNDIS command through the device's Data endpoi= nt >> >> + >> >> + @param[in] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE >> instance. >> >> + @param[in] RndisMsg A pointer to the >> REMOTE_NDIS_MSG_HEADER to send out. >> >> + @param[in, out] TransferLength The length of the RndisMsg data to >> transfer. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +RndisTransmitDataMsg ( >> >> + IN USB_RNDIS_DEVICE *UsbRndisDevice, >> >> + IN REMOTE_NDIS_MSG_HEADER *RndisMsg, >> >> + IN OUT UINTN *TransferLength >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINT32 UsbStatus; >> >> + >> >> + if (UsbRndisDevice->BulkInEndpoint =3D=3D 0) { >> >> + GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice); >> >> + } >> >> + >> >> + PrintRndisMsg (RndisMsg); >> >> + >> >> + Status =3D UsbRndisDevice->UsbIoCdcData->UsbBulkTransfer ( >> >> + UsbRndisDevice->UsbIoCdcData= , >> >> + >> UsbRndisDevice->BulkOutEndpoint, >> >> + RndisMsg, >> >> + TransferLength, >> >> + USB_TX_ETHERNET_BULK_TIMEOUT= , >> >> + &UsbStatus >> >> + ); >> >> + >> >> + if (Status =3D=3D EFI_SUCCESS) { >> >> + StopBulkInCnt =3D MAXIMUM_STOPBULKIN_CNT; // After sending cmd = ,we >> will polling receive package for MAXIMUM_STOPBULKIN_CNT times >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + This function send the RNDIS command through the device's Data endpoi= nt >> >> + >> >> + @param[in] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE >> instance. >> >> + @param[in, out] RndisMsg A pointer to the >> REMOTE_NDIS_MSG_HEADER to send out. >> >> + @param[in, out] TransferLength The length of the RndisMsg data to >> transfer. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +RndisReceiveDataMsg ( >> >> + IN USB_RNDIS_DEVICE *UsbRndisDevice, >> >> + IN OUT REMOTE_NDIS_MSG_HEADER *RndisMsg, >> >> + IN OUT UINTN *TransferLength >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINT32 UsbStatus =3D 0; >> >> + >> >> + if (UsbRndisDevice->BulkInEndpoint =3D=3D 0) { >> >> + GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice); >> >> + } >> >> + >> >> + // Use StopBulkInCnt to stop BulkIn command >> >> + if (StopBulkInCnt || LAN_BULKIN_CMD_CONTROL) { >> >> + Status =3D UsbRndisDevice->UsbIoCdcData->UsbBulkTransfer ( >> >> + >> UsbRndisDevice->UsbIoCdcData, >> >> + >> UsbRndisDevice->BulkInEndpoint, >> >> + RndisMsg, >> >> + TransferLength, >> >> + >> USB_RX_ETHERNET_BULK_TIMEOUT, >> >> + &UsbStatus >> >> + ); >> >> + >> >> + if (!EFI_ERROR (Status)) { >> >> + StopBulkInCnt =3D MINIMUM_STOPBULKIN_CNT; >> >> + } else { >> >> + StopBulkInCnt--; >> >> + } >> >> + } else { >> >> + Status =3D EFI_TIMEOUT; >> >> + *TransferLength =3D 0; >> >> + BlockBulkInCnt++; >> >> + } >> >> + >> >> + if (BlockBulkInCnt > BULKIN_CMD_POLLING_CNT) { >> >> + StopBulkInCnt =3D MINIMUM_STOPBULKIN_CNT; >> >> + BlockBulkInCnt =3D 0; >> >> + } >> >> + >> >> + PrintRndisMsg (RndisMsg); >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Prints RNDIS Header and Data >> >> + >> >> + @param[in] RndisMsg A pointer to the REMOTE_NDIS_MSG_HEADER data. >> >> + >> >> +**/ >> >> +VOID >> >> +PrintRndisMsg ( >> >> + IN REMOTE_NDIS_MSG_HEADER *RndisMsg >> >> + ) >> >> +{ >> >> + UINTN Length =3D 0; >> >> + >> >> + switch (RndisMsg->MessageType) { >> >> + case RNDIS_PACKET_MSG: >> >> + DEBUG ((DEBUG_INFO, "RNDIS_PACKET_MSG:\n")); >> >> + Length =3D sizeof (REMOTE_NDIS_PACKET_MSG) + 0x14; >> >> + break; >> >> + case RNDIS_INITIALIZE_MSG: >> >> + DEBUG ((DEBUG_INFO, "RNDIS_INITIALIZE_MSG:\n")); >> >> + Length =3D sizeof (REMOTE_NDIS_INITIALIZE_MSG); >> >> + break; >> >> + case RNDIS_INITIALIZE_CMPLT: >> >> + DEBUG ((DEBUG_INFO, "RNDIS_INITIALIZE_CMPLT:\n")); >> >> + Length =3D sizeof (REMOTE_NDIS_INITIALIZE_CMPLT); >> >> + break; >> >> + case RNDIS_HLT_MSG: >> >> + DEBUG ((DEBUG_INFO, "RNDIS_HLT_MSG:\n")); >> >> + Length =3D sizeof (REMOTE_NDIS_HALT_MSG); >> >> + break; >> >> + case RNDIS_QUERY_MSG: >> >> + DEBUG ((DEBUG_INFO, "RNDIS_QUERY_MSG:\n")); >> >> + Length =3D sizeof (REMOTE_NDIS_QUERY_MSG); >> >> + break; >> >> + case RNDIS_QUERY_CMPLT: >> >> + DEBUG ((DEBUG_INFO, "RNDIS_QUERY_CMPLT:\n")); >> >> + Length =3D sizeof (REMOTE_NDIS_QUERY_CMPLT); >> >> + break; >> >> + case RNDIS_SET_MSG: >> >> + DEBUG ((DEBUG_INFO, "RNDIS_SET_MSG:\n")); >> >> + Length =3D sizeof (REMOTE_NDIS_SET_MSG); >> >> + break; >> >> + case RNDIS_SET_CMPLT: >> >> + DEBUG ((DEBUG_INFO, "RNDIS_SET_CMPLT:\n")); >> >> + Length =3D sizeof (REMOTE_NDIS_SET_CMPLT); >> >> + break; >> >> + case RNDIS_RESET_MSG: >> >> + DEBUG ((DEBUG_INFO, "RNDIS_RESET_MSG:\n")); >> >> + Length =3D sizeof (REMOTE_NDIS_RESET_MSG); >> >> + break; >> >> + case RNDIS_RESET_CMPLT: >> >> + DEBUG ((DEBUG_INFO, "RNDIS_RESET_CMPLT:\n")); >> >> + Length =3D sizeof (REMOTE_NDIS_RESET_CMPLT); >> >> + break; >> >> + case RNDIS_INDICATE_STATUS_MSG: >> >> + DEBUG ((DEBUG_INFO, "RNDIS_INDICATE_STATUS_MSG:\n")); >> >> + Length =3D sizeof (REMOTE_NDIS_INDICATE_STATUS_MSG); >> >> + break; >> >> + case RNDIS_KEEPALIVE_MSG: >> >> + DEBUG ((DEBUG_INFO, "RNDIS_KEEPALIVE_MSG:\n")); >> >> + Length =3D sizeof (REMOTE_NDIS_KEEPALIVE_MSG); >> >> + break; >> >> + case RNDIS_KEEPALIVE_CMPLT: >> >> + DEBUG ((DEBUG_INFO, "RNDIS_KEEPALIVE_CMPLT:\n")); >> >> + Length =3D sizeof (REMOTE_NDIS_KEEPALIVE_CMPLT); >> >> + } >> >> + >> >> + if (Length) { >> >> + UINTN Index =3D 0; >> >> + for ( ; Length; Length -=3D 4, Index++) { >> >> + DEBUG ((DEBUG_INFO, "%8X\t", RndisMsg[Index])); >> >> + if (((Index % 4) =3D=3D 3) && (Index !=3D 0)) { >> >> + DEBUG ((DEBUG_INFO, "\n")); >> >> + } >> >> + } >> >> + >> >> + if (Index % 4) { >> >> + DEBUG ((DEBUG_INFO, "\n")); >> >> + } >> >> + } >> >> +} >> >> -- >> 2.35.1.windows.2 >> -The information contained in this message may be confidential and >> proprietary to American Megatrends (AMI). This communication is intended= to >> be read only by the individual or entity to whom it is addressed or by >> their designee. If the reader of this message is not the intended >> recipient, you are on notice that any distribution of this message, in a= ny >> form, is strictly prohibited. Please promptly notify the sender by reply >> e-mail or by telephone at 770-246-8600, and then delete or destroy all >> copies of the transmission. >> >> >>=20 >> >> >> > > -- > Pedro Falcato > --=20 Pedro Falcato --000000000000937e2e05e69a233a Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Also, I forgot, but you should CC the EDK2 stewards (they&= #39;re the ones that are going to add the Reviewed-by:).

On Fri, Aug 19, 202= 2 at 4:54 PM Pedro Falcato <p= edro.falcato@gmail.com> wrote:
Hi Richard,

What = license is this code under? "Subject to AMI licensing agreement."= does not sound like a valid OSS license.

Thanks,<= /div>
Pedro

On Fri, Aug 19, 2022 at 10:32 AM RichardHo [=E4=BD=95= =E6=98=8E=E5=BF=A0] via grou= ps.io <richardho=3Dami.com@groups.io> wrote:
UsbNetworkPkg provides network functions for USB ACM= , USB NCM,
and USB RNDIS network device.

Signed-off-by: Richard Ho <richardho@ami.com>
Reviewed-by: Tony Lo <tonylo@ami.com>
---
=C2=A0UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc=C2=A0 =C2=A0 |=C2=A0 =C2= =A0 9 +
=C2=A0.../Config/UsbNetworkPkgComponentsDxe.inc.dsc |=C2=A0 =C2=A020 +
=C2=A0.../Config/UsbNetworkPkgComponentsDxe.inc.fdf |=C2=A0 =C2=A021 +
=C2=A0.../Config/UsbNetworkPkgDefines.inc.dsc=C2=A0 =C2=A0 =C2=A0 =C2=A0|= =C2=A0 =C2=A023 +
=C2=A0.../Include/Protocol/UsbEthernetProtocol.h=C2=A0 =C2=A0 |=C2=A0 872 += ++++++++
=C2=A0UsbNetworkPkg/NetworkCommon/ComponentName.c=C2=A0 =C2=A0|=C2=A0 264 += ++
=C2=A0UsbNetworkPkg/NetworkCommon/DriverBinding.c=C2=A0 =C2=A0|=C2=A0 583 += +++++
=C2=A0UsbNetworkPkg/NetworkCommon/DriverBinding.h=C2=A0 =C2=A0|=C2=A0 263 += ++
=C2=A0UsbNetworkPkg/NetworkCommon/NetworkCommon.inf |=C2=A0 =C2=A043 +
=C2=A0UsbNetworkPkg/NetworkCommon/PxeFunction.c=C2=A0 =C2=A0 =C2=A0| 1734 += ++++++++++++++++
=C2=A0UsbNetworkPkg/ReadMe.md=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0|=C2=A0 =C2=A065 +
=C2=A0UsbNetworkPkg/ReleaseNotes.md=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0|=C2=A0 =C2=A011 +
=C2=A0UsbNetworkPkg/UsbCdcEcm/ComponentName.c=C2=A0 =C2=A0 =C2=A0 =C2=A0|= =C2=A0 170 ++
=C2=A0UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.c=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0|=C2=A0 504 +++++
=C2=A0UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.h=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0|=C2=A0 211 ++
=C2=A0UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0|=C2=A0 =C2=A041 +
=C2=A0UsbNetworkPkg/UsbCdcEcm/UsbEcmFunction.c=C2=A0 =C2=A0 =C2=A0 |=C2=A0 = 861 ++++++++
=C2=A0UsbNetworkPkg/UsbCdcNcm/ComponentName.c=C2=A0 =C2=A0 =C2=A0 =C2=A0|= =C2=A0 170 ++
=C2=A0UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.c=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0|=C2=A0 508 +++++
=C2=A0UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.h=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0|=C2=A0 245 +++
=C2=A0UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0|=C2=A0 =C2=A041 +
=C2=A0UsbNetworkPkg/UsbCdcNcm/UsbNcmFunction.c=C2=A0 =C2=A0 =C2=A0 |=C2=A0 = 946 +++++++++
=C2=A0UsbNetworkPkg/UsbNetworkPkg.dec=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0|=C2=A0 =C2=A032 +
=C2=A0UsbNetworkPkg/UsbRndis/ComponentName.c=C2=A0 =C2=A0 =C2=A0 =C2=A0 |= =C2=A0 172 ++
=C2=A0UsbNetworkPkg/UsbRndis/UsbRndis.c=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0|=C2=A0 848 ++++++++
=C2=A0UsbNetworkPkg/UsbRndis/UsbRndis.h=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0|=C2=A0 569 ++++++
=C2=A0UsbNetworkPkg/UsbRndis/UsbRndis.inf=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0|=C2=A0 =C2=A041 +
=C2=A0UsbNetworkPkg/UsbRndis/UsbRndisFunction.c=C2=A0 =C2=A0 =C2=A0| 1587 += ++++++++++++++
=C2=A028 files changed, 10854 insertions(+)
=C2=A0create mode 100644 UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc
=C2=A0create mode 100644 UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.in= c.dsc
=C2=A0create mode 100644 UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.in= c.fdf
=C2=A0create mode 100644 UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc<= br> =C2=A0create mode 100644 UsbNetworkPkg/Include/Protocol/UsbEthernetProtocol= .h
=C2=A0create mode 100644 UsbNetworkPkg/NetworkCommon/ComponentName.c
=C2=A0create mode 100644 UsbNetworkPkg/NetworkCommon/DriverBinding.c
=C2=A0create mode 100644 UsbNetworkPkg/NetworkCommon/DriverBinding.h
=C2=A0create mode 100644 UsbNetworkPkg/NetworkCommon/NetworkCommon.inf
=C2=A0create mode 100644 UsbNetworkPkg/NetworkCommon/PxeFunction.c
=C2=A0create mode 100644 UsbNetworkPkg/ReadMe.md
=C2=A0create mode 100644 UsbNetworkPkg/ReleaseNotes.md
=C2=A0create mode 100644 UsbNetworkPkg/UsbCdcEcm/ComponentName.c
=C2=A0create mode 100644 UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.c
=C2=A0create mode 100644 UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.h
=C2=A0create mode 100644 UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf
=C2=A0create mode 100644 UsbNetworkPkg/UsbCdcEcm/UsbEcmFunction.c
=C2=A0create mode 100644 UsbNetworkPkg/UsbCdcNcm/ComponentName.c
=C2=A0create mode 100644 UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.c
=C2=A0create mode 100644 UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.h
=C2=A0create mode 100644 UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf
=C2=A0create mode 100644 UsbNetworkPkg/UsbCdcNcm/UsbNcmFunction.c
=C2=A0create mode 100644 UsbNetworkPkg/UsbNetworkPkg.dec
=C2=A0create mode 100644 UsbNetworkPkg/UsbRndis/ComponentName.c
=C2=A0create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndis.c
=C2=A0create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndis.h
=C2=A0create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndis.inf
=C2=A0create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndisFunction.c

diff --git a/UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc b/UsbNetworkPkg/Con= fig/UsbNetworkPkg.inc.dsc
new file mode 100644
index 0000000000..504680bc4b
--- /dev/null
+++ b/UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc
@@ -0,0 +1,9 @@
+## @file
+# Global DSC definitions to be included into project DSC file.
+#
+# Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
+# Subject to AMI licensing agreement.
+##
+
+[Components.X64]
+!include UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc
diff --git a/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc b/UsbN= etworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc
new file mode 100644
index 0000000000..ae2727b68c
--- /dev/null
+++ b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc
@@ -0,0 +1,20 @@
+## @file
+# List of Core Components.
+#
+# Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
+# Subject to AMI licensing agreement.
+##
+
+=C2=A0 UsbNetworkPkg/NetworkCommon/NetworkCommon.inf
+
+!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport
+=C2=A0 UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf
+!endif
+
+!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport
+=C2=A0 UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf
+!endif
+
+!if gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport
+=C2=A0 UsbNetworkPkg/UsbRndis/UsbRndis.inf
+!endif
diff --git a/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf b/UsbN= etworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf
new file mode 100644
index 0000000000..6a611e359c
--- /dev/null
+++ b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf
@@ -0,0 +1,21 @@
+## @file
+# List of Core Components.
+#
+# Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
+# Subject to AMI licensing agreement.
+##
+
+=C2=A0 INF UsbNetworkPkg/NetworkCommon/NetworkCommon.inf
+
+!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport
+=C2=A0 INF UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf
+!endif
+
+!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport
+=C2=A0 INF UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf
+!endif
+
+!if gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport
+=C2=A0 INF UsbNetworkPkg/UsbRndis/UsbRndis.inf
+!endif
+
\ No newline at end of file
diff --git a/UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc b/UsbNetwork= Pkg/Config/UsbNetworkPkgDefines.inc.dsc
new file mode 100644
index 0000000000..ef663bf253
--- /dev/null
+++ b/UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc
@@ -0,0 +1,23 @@
+## @file
+# Global switches enable/disable project features.
+#
+# Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
+# Subject to AMI licensing agreement.
+##
+
+[Defines]
+!if "IA32" in $(ARCH) && "X64" in $(ARCH)
+=C2=A0 DEFINE PEI=3DIA32
+=C2=A0 DEFINE DXE=3DX64
+!else
+=C2=A0 DEFINE PEI=3DCOMMON
+=C2=A0 DEFINE DXE=3DCOMMON
+!endif
+
+[Packages]
+=C2=A0 UsbNetworkPkg/UsbNetworkPkg.dec
+
+[PcdsFeatureFlag]
+=C2=A0 gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport|FALSE
+=C2=A0 gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport|FALSE
+=C2=A0 gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport|TRUE
diff --git a/UsbNetworkPkg/Include/Protocol/UsbEthernetProtocol.h b/UsbNetw= orkPkg/Include/Protocol/UsbEthernetProtocol.h
new file mode 100644
index 0000000000..d60e83f723
--- /dev/null
+++ b/UsbNetworkPkg/Include/Protocol/UsbEthernetProtocol.h
@@ -0,0 +1,872 @@
+/** @file

+=C2=A0 Header file contains code for USB Ethernet Protocol

+=C2=A0 definitions

+

+=C2=A0 Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+=C2=A0 Subject to AMI licensing agreement.

+**/

+

+#ifndef _USB_ETHERNET_PROTOCOL_H

+#define _USB_ETHERNET_PROTOCOL_H

+

+#define USB_ETHERNET_PROTOCOL_GUID \

+=C2=A0 =C2=A0 {0x8d8969cc, 0xfeb0, 0x4303, {0xb2, 0x1a, 0x1f, 0x11, 0x6f, = 0x38, 0x56, 0x43}}

+

+typedef struct _USB_ETHERNET_PROTOCOL USB_ETHERNET_PROTOCOL;

+

+#define USB_CDC_CLASS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x02

+#define USB_CDC_ACM_SUBCLASS=C2=A0 =C2=A00x02

+#define USB_CDC_ECM_SUBCLASS=C2=A0 =C2=A00x06

+#define USB_CDC_NCM_SUBCLASS=C2=A0 =C2=A00x0D

+#define USB_CDC_DATA_CLASS=C2=A0 =C2=A0 =C2=A00x0A

+#define USB_CDC_DATA_SUBCLASS=C2=A0 0x00

+#define USB_NO_CLASS_PROTOCOL=C2=A0 0x00

+#define USB_NCM_NTB_PROTOCOL=C2=A0 =C2=A00x01

+#define USB_VENDOR_PROTOCOL=C2=A0 =C2=A0 0xFF

+

+// Type Values for the DescriptorType Field

+#define CS_INTERFACE=C2=A0 0x24

+#define CS_ENDPOINT=C2=A0 =C2=A00x25

+

+// Descriptor SubType in Functional Descriptors

+#define HEADER_FUN_DESCRIPTOR=C2=A0 =C2=A0 0x00

+#define UNION_FUN_DESCRIPTOR=C2=A0 =C2=A0 =C2=A00x06

+#define ETHERNET_FUN_DESCRIPTOR=C2=A0 0x0F

+

+#define MAX_LAN_INTERFACE=C2=A0 0x10

+

+// Table 20: Class-Specific Notification Codes

+#define USB_CDC_NETWORK_CONNECTION=C2=A0 0x00

+

+// 6.3.1 NetworkConnection

+#define NETWORK_CONNECTED=C2=A0 =C2=A00x01

+#define NETWORK_DISCONNECT=C2=A0 0x00

+

+// USB Header functional Descriptor

+typedef struct {

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0FunctionLength;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0DescriptorType;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0DescriptorSubtype;

+=C2=A0 UINT16=C2=A0 =C2=A0 BcdCdc;

+} USB_HEADER_FUN_DESCRIPTOR;

+

+// USB Union Functional Descriptor

+typedef struct {

+=C2=A0 UINT8=C2=A0 =C2=A0 FunctionLength;

+=C2=A0 UINT8=C2=A0 =C2=A0 DescriptorType;

+=C2=A0 UINT8=C2=A0 =C2=A0 DescriptorSubtype;

+=C2=A0 UINT8=C2=A0 =C2=A0 MasterInterface;

+=C2=A0 UINT8=C2=A0 =C2=A0 SlaveInterface;

+} USB_UNION_FUN_DESCRIPTOR;

+

+// USB Ethernet Functional Descriptor

+typedef struct {

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0FunctionLength;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0DescriptorType;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0DescriptorSubtype;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0MacAddress;

+=C2=A0 UINT32=C2=A0 =C2=A0 EthernetStatistics;

+=C2=A0 UINT16=C2=A0 =C2=A0 MaxSegmentSize;

+=C2=A0 UINT16=C2=A0 =C2=A0 NumberMcFilters;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0NumberPowerFilters;

+} USB_ETHERNET_FUN_DESCRIPTOR;

+

+typedef struct {

+=C2=A0 UINT32=C2=A0 =C2=A0 UsBitRate;

+=C2=A0 UINT32=C2=A0 =C2=A0 DsBitRate;

+} USB_CONNECT_SPEED_CHANGE;

+

+// Request Type Codes for USB Ethernet

+#define USB_ETHERNET_GET_REQ_TYPE=C2=A0 0xA1

+#define USB_ETHRTNET_SET_REQ_TYPE=C2=A0 0x21

+

+// Class-Specific Request Codes for Ethernet subclass

+// USB ECM 1.2 specification, Section 6.2

+#define SET_ETH_MULTICAST_FILTERS_REQ=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 0x40

+#define SET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ=C2=A0 0x41

+#define GET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ=C2=A0 0x42

+#define SET_ETH_PACKET_FILTER_REQ=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x43

+#define GET_ETH_STATISTIC_REQ=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x44

+

+// USB ECM command request length

+#define USB_ETH_POWER_FILTER_LENGTH=C2=A0 =C2=A02 // Section 6.2.3

+#define USB_ETH_PACKET_FILTER_LENGTH=C2=A0 0 // Section 6.2.4

+#define USB_ETH_STATISTIC=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A04= // Section 6.2.5

+

+// USB Ethernet Packet Filter Bitmap

+// USB ECM 1.2 specification, Section 6.2.4

+#define USB_ETH_PACKET_TYPE_PROMISCUOUS=C2=A0 =C2=A0 BIT0

+#define USB_ETH_PACKET_TYPE_ALL_MULTICAST=C2=A0 BIT1

+#define USB_ETH_PACKET_TYPE_DIRECTED=C2=A0 =C2=A0 =C2=A0 =C2=A0BIT2

+#define USB_ETH_PACKET_TYPE_BROADCAST=C2=A0 =C2=A0 =C2=A0 BIT3

+#define USB_ETH_PACKET_TYPE_MULTICAST=C2=A0 =C2=A0 =C2=A0 BIT4

+

+// USB Ethernet Statistics Feature Selector Codes

+// USB ECM 1.2 specification, Section 6.2.5

+#define USB_ETH_XMIT_OK=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A00x01

+#define USB_ETH_RCV_OK=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 0x02

+#define USB_ETH_XMIT_ERROR=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= 0x03

+#define USB_ETH_RCV_ERROR=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A00x04

+#define USB_ETH_RCV_NO_BUFFER=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x05=

+#define USB_ETH_DIRECTED_BYTES_XMIT=C2=A0 =C2=A0 =C2=A00x06

+#define USB_ETH_DIRECTED_FRAMES_XMIT=C2=A0 =C2=A0 0x07

+#define USB_ETH_MULTICAST_BYTES_XMIT=C2=A0 =C2=A0 0x08

+#define USB_ETH_MULTICAST_FRAMES_XMIT=C2=A0 =C2=A00x09

+#define USB_ETH_BROADCAST_BYTES_XMIT=C2=A0 =C2=A0 0x0A

+#define USB_ETH_BROADCAST_FRAMES_XMIT=C2=A0 =C2=A00x0B

+#define USB_ETH_DIRECTED_BYTES_RCV=C2=A0 =C2=A0 =C2=A0 0x0C

+#define USB_ETH_DIRECTED_FRAMES_RCV=C2=A0 =C2=A0 =C2=A00x0D

+#define USB_ETH_MULTICAST_BYTES_RCV=C2=A0 =C2=A0 =C2=A00x0E

+#define USB_ETH_MULTICAST_FRAMES_RCV=C2=A0 =C2=A0 0x0F

+#define USB_ETH_BROADCAST_BYTES_RCV=C2=A0 =C2=A0 =C2=A00x10

+#define USB_ETH_BROADCAST_FRAMES_RCV=C2=A0 =C2=A0 0x11

+#define USB_ETH_RCV_CRC_ERROR=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x12=

+#define USB_ETH_TRANSMIT_QUEUE_LENGTH=C2=A0 =C2=A00x13

+#define USB_ETH_RCV_ERROR_ALIGNMENT=C2=A0 =C2=A0 =C2=A00x14

+#define USB_ETH_XMIT_ONE_COLLISION=C2=A0 =C2=A0 =C2=A0 0x15

+#define USB_ETH_XMIT_MORE_COLLISIONS=C2=A0 =C2=A0 0x16

+#define USB_ETH_XMIT_DEFERRED=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x17=

+#define USB_ETH_XMIT_MAX_COLLISIONS=C2=A0 =C2=A0 =C2=A00x18

+#define USB_ETH_RCV_OVERRUN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A00x19

+#define USB_ETH_XMIT_UNDERRUN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x1A=

+#define USB_ETH_XMIT_HEARTBEAT_FAILURE=C2=A0 0x1B

+#define USB_ETH_XMIT_TIMES_CRS_LOST=C2=A0 =C2=A0 =C2=A00x1C

+#define USB_ETH_XMIT_LATE_COLLISIONS=C2=A0 =C2=A0 0x1D

+

+// NIC Information

+typedef struct {

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 Signature;

+=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0*UsbEth;

+=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 InterrupOpFlag;

+=C2=A0 UINT64=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 MappedAddr;

+=C2=A0 PXE_MAC_ADDR=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 McastL= ist[MAX_MCAST_ADDRESS_CNT];

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0McastCount;

+=C2=A0 UINT64=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 MediaHeader[MAX_XMIT_BUFFERS];

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0TxBufferCount;

+=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 State;

+=C2=A0 BOOLEAN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0CanTransmit;

+=C2=A0 BOOLEAN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0CanReceive;

+=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 ReceiveStatus;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0RxFilter;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 RxFrame;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 TxFrame;

+=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 NetworkConnect;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0CableDetect;

+=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 MaxSegmentSize;

+=C2=A0 EFI_MAC_ADDRESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0MacAddr;
+=C2=A0 PXE_CPB_START_31=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 PxeStart;

+=C2=A0 PXE_CPB_INITIALIZE=C2=A0 =C2=A0 =C2=A0 =C2=A0 PxeInit;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0PermNodeAddress[PXE_MAC_LENGTH];

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0CurrentNodeAddress[PXE_MAC_LENGTH];

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0BroadcastNodeAddress[PXE_MAC_LENGTH];

+=C2=A0 EFI_USB_DEVICE_REQUEST=C2=A0 =C2=A0 Request;

+} NIC_DATA;

+

+#define NIC_DATA_SIGNATURE=C2=A0 SIGNATURE_32('n', 'i', &#= 39;c', 'd')

+#define NIC_DATA_FROM_USB_ETHERNET_PROTOCOL(a)=C2=A0 CR (a, NIC_DATA, UsbE= th, NIC_DATA_SIGNATURE)

+

+/**

+=C2=A0 This command is used to determine the operational state of the UNDI= .

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_UNDI_GET_STATE)(

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 =C2=A0 *Nic

+=C2=A0 );

+

+/**

+=C2=A0 This command is used to change the UNDI operational state from stop= ped to started.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_UNDI_START)(

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 =C2=A0 *Nic

+=C2=A0 );

+

+/**

+=C2=A0 This command is used to change the UNDI operational state from star= ted to stopped.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_UNDI_STOP)(

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 =C2=A0 *Nic

+=C2=A0 );

+

+/**

+=C2=A0 This command is used to retrieve initialization information that is=

+=C2=A0 needed by drivers and applications to initialized UNDI.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_UNDI_GET_INIT_INFO)(

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 =C2=A0 *Nic

+=C2=A0 );

+

+/**

+=C2=A0 This command is used to retrieve configuration information about
+=C2=A0 the NIC being controlled by the UNDI.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_UNDI_GET_CONFIG_INFO)(

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 =C2=A0 *Nic

+=C2=A0 );

+

+/**

+=C2=A0 This command resets the network adapter and initializes UNDI using<= br>
+=C2=A0 the parameters supplied in the CPB.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_UNDI_INITIALIZE)(

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+/**

+=C2=A0 This command resets the network adapter and reinitializes the UNDI<= br>
+=C2=A0 with the same parameters provided in the Initialize command.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_UNDI_RESET)(

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 =C2=A0 *Nic

+=C2=A0 );

+

+/**

+=C2=A0 The Shutdown command resets the network adapter and leaves it in a<= br>
+=C2=A0 safe state for another driver to initialize.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_UNDI_SHUTDOWN)(

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 =C2=A0 *Nic

+=C2=A0 );

+

+/**

+=C2=A0 The Interrupt Enables command can be used to read and/or change

+=C2=A0 the current external interrupt enable settings.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_UNDI_INTERRUPT_ENABLE)(

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 =C2=A0 *Nic

+=C2=A0 );

+

+/**

+=C2=A0 This command is used to read and change receive filters and,

+=C2=A0 if supported, read and change the multicast MAC address filter list= .

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_UNDI_RECEIVE_FILTER)(

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 =C2=A0 *Nic

+=C2=A0 );

+

+/**

+=C2=A0 This command is used to get current station and broadcast MAC addre= sses

+=C2=A0 and, if supported, to change the current station MAC address.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_UNDI_STATION_ADDRESS)(

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 =C2=A0 *Nic

+=C2=A0 );

+

+/**

+=C2=A0 This command is used to read and clear the NIC traffic statistics.<= br>
+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_UNDI_STATISTICS)(

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 =C2=A0 *Nic

+=C2=A0 );

+

+/**

+=C2=A0 Translate a multicast IPv4 or IPv6 address to a multicast MAC addre= ss.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_UNDI_MCAST_IPTOMAC)(

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 =C2=A0 *Nic

+=C2=A0 );

+

+/**

+=C2=A0 This command is used to read and write (if supported by NIC H/W)
+=C2=A0 nonvolatile storage on the NIC.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_UNDI_NV_DATA)(

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 =C2=A0 *Nic

+=C2=A0 );

+

+/**

+=C2=A0 This command returns the current interrupt status and/or the

+=C2=A0 transmitted buffer addresses and the current media status.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_UNDI_GET_STATUS)(

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 =C2=A0 *Nic

+=C2=A0 );

+

+/**

+=C2=A0 This command is used to fill the media header(s) in transmit packet= (s).

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_UNDI_FILL_HEADER)(

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 =C2=A0 *Nic

+=C2=A0 );

+

+/**

+=C2=A0 The Transmit command is used to place a packet into the transmit qu= eue.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_UNDI_TRANSMIT)(

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 =C2=A0 *Nic

+=C2=A0 );

+

+/**

+=C2=A0 When the network adapter has received a frame, this command is used=

+=C2=A0 to copy the frame into driver/application storage.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_UNDI_RECEIVE)(

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 =C2=A0 *Nic

+=C2=A0 );

+

+/**

+=C2=A0 This command resets the network adapter and initializes UNDI using<= br>
+=C2=A0 the parameters supplied in the CPB.

+

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 Cdb=C2=A0 A pointer to the command d= escriptor block.

+=C2=A0 @param[in, out] Nic=C2=A0 A pointer to the Network interface contro= ller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_INITIALIZE)(

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN OUT=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+/**

+=C2=A0 This command is used to read and clear the NIC traffic statistics.<= br>
+

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 =C2=A0 =C2=A0A pointer to the Network in= terface controller data.

+=C2=A0 @param[in]=C2=A0 DbAddr=C2=A0 Data Block Address.

+=C2=A0 @param[in]=C2=A0 DbSize=C2=A0 Data Block Size.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_STATISTICS)(

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 =C2=A0 *Nic,

+=C2=A0 IN=C2=A0 UINT64=C2=A0 =C2=A0 =C2=A0 DbAddr,

+=C2=A0 IN=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 DbSize

+=C2=A0 );

+

+/**

+=C2=A0 This function is used to manage a USB device with the bulk transfer= pipe. The endpoint is Bulk in.

+

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 Cdb=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0A pointer to the command descriptor block.

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 A pointer to the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[in, out] Packet=C2=A0 =C2=A0 =C2=A0 =C2=A0 A pointer to the = buffer of data that will be transmitted to USB

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 device or received from USB device.<= br>
+=C2=A0 @param[in, out] PacketLength=C2=A0 A pointer to the PacketLength.
+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The bul= k transfer has been successfully executed.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The transfer failed. T= he transfer status is returned in status.

+=C2=A0 @retval EFI_INVALID_PARAMETE=C2=A0 One or more parameters are inval= id.

+=C2=A0 @retval EFI_OUT_OF_RESOURCES=C2=A0 The request could not be submitt= ed due to a lack of resources.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The con= trol transfer fails due to timeout.

+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_RECEIVE)(

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0PXE_CDB=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0USB_ETHERNET_PROTOCOL *This,

+=C2=A0 IN OUT VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 *Packet,

+=C2=A0 IN OUT UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0*PacketLength

+=C2=A0 );

+

+/**

+=C2=A0 This function is used to manage a USB device with the bulk transfer= pipe. The endpoint is Bulk out.

+

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 Cdb=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0A pointer to the command descriptor block.

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 A pointer to the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[in, out] Packet=C2=A0 =C2=A0 =C2=A0 =C2=A0 A pointer to the = buffer of data that will be transmitted to USB

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 device or received from USB device.<= br>
+=C2=A0 @param[in, out] PacketLength=C2=A0 A pointer to the PacketLength.
+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The bul= k transfer has been successfully executed.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The transfer failed. T= he transfer status is returned in status.

+=C2=A0 @retval EFI_INVALID_PARAMETE=C2=A0 One or more parameters are inval= id.

+=C2=A0 @retval EFI_OUT_OF_RESOURCES=C2=A0 The request could not be submitt= ed due to a lack of resources.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The con= trol transfer fails due to timeout.

+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_TRANSMIT)(

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0PXE_CDB=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0USB_ETHERNET_PROTOCOL *This,

+=C2=A0 IN OUT VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 *Packet,

+=C2=A0 IN OUT UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0*PacketLength

+=C2=A0 );

+

+/**

+=C2=A0 This function is used to manage a USB device with an interrupt tran= sfer pipe.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 A pointer to the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[in]=C2=A0 IsNewTransfer=C2=A0 =C2=A0 =C2=A0If TRUE, a new tr= ansfer will be submitted to USB controller. If

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 FALSE, the interrupt transfer is del= eted from the device's interrupt

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 transfer queue.

+=C2=A0 @param[in]=C2=A0 PollingInterval=C2=A0 =C2=A0Indicates the periodic= rate, in milliseconds, that the transfer is to be

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 executed.This parameter is required = when IsNewTransfer is TRUE. The

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 value must be between 1 to 255, othe= rwise EFI_INVALID_PARAMETER is returned.

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 The units are in milliseconds.

+=C2=A0 @param[in]=C2=A0 Request=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A = pointer to the EFI_USB_DEVICE_REQUEST data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The asy= nchronous USB transfer request transfer has been successfully executed.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The asynchronous USB t= ransfer request failed.

+

+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_INTERRUPT)(

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0*This,

+=C2=A0 IN BOOLEAN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0IsNewTransfer,

+=C2=A0 IN UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0PollingInterval,

+=C2=A0 IN EFI_USB_DEVICE_REQUEST=C2=A0 *Request

+=C2=A0 );

+

+/**

+=C2=A0 Retrieves the USB Ethernet Mac Address.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A pointer t= o the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[out] MacAddress=C2=A0 =C2=A0 A pointer to the caller allocat= ed USB Ethernet Mac Address.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB= Header Functional descriptor was retrieved successfully.

+=C2=A0 @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL.

+=C2=A0 @retval EFI_NOT_FOUND=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB Head= er Functional descriptor was not found.

+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_GET_ETH_MAC_ADDRESS)(

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL *This,

+=C2=A0 OUT EFI_MAC_ADDRESS=C2=A0 =C2=A0 =C2=A0 =C2=A0*MacAddress

+=C2=A0 );

+

+/**

+=C2=A0 Retrieves the USB Ethernet Bulk transfer data size.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A pointer t= o the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[out] BulkSize=C2=A0 =C2=A0 =C2=A0 A pointer to the Bulk tran= sfer data size.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB= Header Functional descriptor was retrieved successfully.

+=C2=A0 @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL.

+=C2=A0 @retval EFI_NOT_FOUND=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB Head= er Functional descriptor was not found.

+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETH_MAX_BULK_SIZE)(

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL *This,

+=C2=A0 OUT UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0*BulkSize

+=C2=A0 );

+

+/**

+=C2=A0 Retrieves the USB Header functional Descriptor.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0A pointer to the USB_ETHERNET_PROTOCOL instance.
+=C2=A0 @param[out] UsbHeaderFunDescriptor A pointer to the caller allocate= d USB Header Functional Descriptor.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB= Header Functional descriptor was retrieved successfully.

+=C2=A0 @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL.

+=C2=A0 @retval EFI_NOT_FOUND=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB Head= er Functional descriptor was not found.

+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_HEADER_FUNCTIONAL_DESCRIPTOR)(

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0 *This,

+=C2=A0 OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor

+=C2=A0 );

+

+/**

+=C2=A0 Retrieves the USB Union functional Descriptor.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0A pointer to the USB_ETHERNET_PROTOCOL instance.
+=C2=A0 @param[out] UsbUnionFunDescriptor=C2=A0 A pointer to the caller all= ocated USB Union Functional Descriptor.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB= Union Functional descriptor was retrieved successfully.

+=C2=A0 @retval EFI_INVALID_PARAMETER UsbUnionFunDescriptor is NULL.

+=C2=A0 @retval EFI_NOT_FOUND=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB Unio= n Functional descriptor was not found.

+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_UNION_FUNCTIONAL_DESCRIPTOR)(

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0*This,

+=C2=A0 OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor

+=C2=A0 );

+

+/**

+=C2=A0 Retrieves the USB Ethernet functional Descriptor.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0A pointer to the USB_ETHERNET_PROTOCOL instance.
+=C2=A0 @param[out] UsbEthFunDescriptor=C2=A0 =C2=A0 A pointer to the calle= r allocated USB Ethernet Functional Descriptor.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB= Ethernet Functional descriptor was retrieved successfully.

+=C2=A0 @retval EFI_INVALID_PARAMETER UsbEthFunDescriptor is NULL.

+=C2=A0 @retval EFI_NOT_FOUND=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB Ethe= rnet Functional descriptor was not found.

+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_FUNCTIONAL_DESCRIPTOR)(

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 *This,

+=C2=A0 OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor

+=C2=A0 );

+

+/**

+=C2=A0 This request sets the Ethernet device multicast filters as specifie= d in the

+=C2=A0 sequential list of 48 bit Ethernet multicast addresses.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0A pointer to the USB_ETHERNET_PROTOCOL instance.
+=C2=A0 @param[in]=C2=A0 Value=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 Number of filters.

+=C2=A0 @param[in]=C2=A0 McastAddr=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 A pointer to the value of the multicast addresses.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_SET_ETH_MULTICAST_FILTERS)(

+=C2=A0 IN USB_ETHERNET_PROTOCOL *This,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Va= lue,

+=C2=A0 IN VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 *McastAddr

+=C2=A0 );

+

+/**

+=C2=A0 This request sets up the specified Ethernet power management patter= n filter as

+=C2=A0 described in the data structure.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0A pointer to the USB_ETHERNET_PROTOCOL instance.
+=C2=A0 @param[in]=C2=A0 Value=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 Number of filters.

+=C2=A0 @param[in]=C2=A0 Length=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0Size of the power management pattern filter data.

+=C2=A0 @param[in]=C2=A0 PatternFilter=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A = pointer to the power management pattern filter structure.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_SET_ETH_POWER_MANAGE_PATTERN_FILTER)(

+=C2=A0 IN USB_ETHERNET_PROTOCOL *This,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Va= lue,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Le= ngth,

+=C2=A0 IN VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 *PatternFilter

+=C2=A0 );

+

+/**

+=C2=A0 This request retrieves the status of the specified Ethernet power m= anagement

+=C2=A0 pattern filter from the device.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0A pointer to the USB_ETHERNET_PROTOCOL instance.
+=C2=A0 @param[in]=C2=A0 Value=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 The filter number.

+=C2=A0 @param[out] PatternActive=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A point= er to the pattern active boolean.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_GET_ETH_POWER_MANAGE_PATTERN_FILTER)(

+=C2=A0 IN=C2=A0 =C2=A0USB_ETHERNET_PROTOCOL *This,

+=C2=A0 IN=C2=A0 =C2=A0UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 Value,

+=C2=A0 OUT=C2=A0 BOOLEAN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0*PatternActive

+=C2=A0 );

+

+/**

+=C2=A0 This request is used to configure device Ethernet packet filter set= tings.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 A pointer to the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[in]=C2=A0 Value=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0Packet Filter Bitmap.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_SET_ETH_PACKET_FILTER)(

+=C2=A0 IN USB_ETHERNET_PROTOCOL *This,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Va= lue

+=C2=A0 );

+

+/**

+=C2=A0 This request is used to retrieve a statistic based on the feature s= elector.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 A pointer to the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[in]=C2=A0 FeatureSelector=C2=A0 =C2=A0 =C2=A0 =C2=A0Value of= the feature selector.

+=C2=A0 @param[out] Statistic=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0A pointer to the 32 bit unsigned integer.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+**/

+typedef

+EFI_STATUS

+(EFIAPI *USB_ETHERNET_GET_ETH_STATISTIC)(

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0FeatureSelector,

+=C2=A0 OUT VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0*Statistic

+=C2=A0 );

+

+typedef struct {

+=C2=A0 USB_ETHERNET_UNDI_GET_STATE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0UsbEthUndiGetState;

+=C2=A0 USB_ETHERNET_UNDI_START=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0UsbEthUndiStart;

+=C2=A0 USB_ETHERNET_UNDI_STOP=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 UsbEthUndiStop;

+=C2=A0 USB_ETHERNET_UNDI_GET_INIT_INFO=C2=A0 =C2=A0 =C2=A0 =C2=A0UsbEthUnd= iGetInitInfo;

+=C2=A0 USB_ETHERNET_UNDI_GET_CONFIG_INFO=C2=A0 =C2=A0 =C2=A0UsbEthUndiGetC= onfigInfo;

+=C2=A0 USB_ETHERNET_UNDI_INITIALIZE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbE= thUndiInitialize;

+=C2=A0 USB_ETHERNET_UNDI_RESET=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0UsbEthUndiReset;

+=C2=A0 USB_ETHERNET_UNDI_SHUTDOWN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= UsbEthUndiShutdown;

+=C2=A0 USB_ETHERNET_UNDI_INTERRUPT_ENABLE=C2=A0 =C2=A0 UsbEthUndiInterrupt= Enable;

+=C2=A0 USB_ETHERNET_UNDI_RECEIVE_FILTER=C2=A0 =C2=A0 =C2=A0 UsbEthUndiRece= iveFilter;

+=C2=A0 USB_ETHERNET_UNDI_STATION_ADDRESS=C2=A0 =C2=A0 =C2=A0UsbEthUndiStat= ionAddress;

+=C2=A0 USB_ETHERNET_UNDI_STATISTICS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbE= thUndiStatistics;

+=C2=A0 USB_ETHERNET_UNDI_MCAST_IPTOMAC=C2=A0 =C2=A0 =C2=A0 =C2=A0UsbEthUnd= iMcastIp2Mac;

+=C2=A0 USB_ETHERNET_UNDI_NV_DATA=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0UsbEthUndiNvData;

+=C2=A0 USB_ETHERNET_UNDI_GET_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbE= thUndiGetStatus;

+=C2=A0 USB_ETHERNET_UNDI_FILL_HEADER=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0UsbE= thUndiFillHeader;

+=C2=A0 USB_ETHERNET_UNDI_TRANSMIT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= UsbEthUndiTransmit;

+=C2=A0 USB_ETHERNET_UNDI_RECEIVE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0UsbEthUndiReceive;

+} USB_ETHERNET_UNDI;

+

+// The USB_ETHERNET_PROTOCOL provides some basic USB Ethernet device relev= ant

+// descriptor and specific requests.

+struct _USB_ETHERNET_PROTOCOL {

+=C2=A0 USB_ETHERNET_UNDI=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0UsbEthUndi;

+=C2=A0 // for calling the UNDI child functions

+=C2=A0 USB_ETHERNET_INITIALIZE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0UsbEthInitial= ize;

+=C2=A0 USB_ETHERNET_STATISTICS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0UsbEthStatist= ics;

+=C2=A0 USB_ETHERNET_RECEIVE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthRe= ceive;

+=C2=A0 USB_ETHERNET_TRANSMIT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0UsbEthTra= nsmit;

+=C2=A0 USB_ETHERNET_INTERRUPT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthInterrupt= ;

+=C2=A0 USB_GET_ETH_MAC_ADDRESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0UsbEthMacAddr= ess;

+=C2=A0 USB_ETH_MAX_BULK_SIZE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0UsbEthMax= BulkSize;

+=C2=A0 USB_HEADER_FUNCTIONAL_DESCRIPTOR=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbHeaderFunDescriptor;

+=C2=A0 USB_UNION_FUNCTIONAL_DESCRIPTOR=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0UsbUnionFunDescriptor;

+=C2=A0 USB_ETHERNET_FUNCTIONAL_DESCRIPTOR=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthFunDescriptor;

+=C2=A0 USB_ETHERNET_SET_ETH_MULTICAST_FILTERS=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 SetUsbEthMcastFilter;

+=C2=A0 USB_ETHERNET_SET_ETH_POWER_MANAGE_PATTERN_FILTER=C2=A0 =C2=A0 SetUs= bEthPowerPatternFilter;

+=C2=A0 USB_ETHERNET_GET_ETH_POWER_MANAGE_PATTERN_FILTER=C2=A0 =C2=A0 GetUs= bEthPoewrPatternFilter;

+=C2=A0 USB_ETHERNET_SET_ETH_PACKET_FILTER=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 SetUsbEthPacketFilter;

+=C2=A0 USB_ETHERNET_GET_ETH_STATISTIC=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 GetUsbEthStatistic;

+};

+

+#endif

diff --git a/UsbNetworkPkg/NetworkCommon/ComponentName.c b/UsbNetworkPkg/Ne= tworkCommon/ComponentName.c
new file mode 100644
index 0000000000..2697bf5083
--- /dev/null
+++ b/UsbNetworkPkg/NetworkCommon/ComponentName.c
@@ -0,0 +1,264 @@
+/** @file

+=C2=A0 This file contains code for USB network common driver

+=C2=A0 component name definitions

+

+=C2=A0 Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+=C2=A0 Subject to AMI licensing agreement.

+**/

+

+#include "DriverBinding.h"

+

+extern EFI_DRIVER_BINDING_PROTOCOL=C2=A0 gNetworkCommonDriverBinding;

+extern EFI_GUID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0gUsbEthProtocolGuid;

+

+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE=C2=A0 gNetworkCommo= nDriverNameTable[] =3D {

+=C2=A0 {

+=C2=A0 =C2=A0 "eng;en",

+=C2=A0 =C2=A0 L"Network Common Driver"

+=C2=A0 },

+=C2=A0 {

+=C2=A0 =C2=A0 NULL,

+=C2=A0 =C2=A0 NULL

+=C2=A0 }

+};

+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE=C2=A0 *gNetworkComm= onControllerNameTable =3D NULL;

+

+EFI_STATUS

+EFIAPI

+NetworkCommonComponentNameGetDriverName (

+=C2=A0 IN=C2=A0 EFI_COMPONENT_NAME_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 CHAR8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *Language,

+=C2=A0 OUT CHAR16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0**DriverName

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+NetworkCommonComponentNameGetControllerName (

+=C2=A0 IN EFI_COMPONENT_NAME_PROTOCOL=C2=A0 *This,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0Controller,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0ChildHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0 OPTIONAL,

+=C2=A0 IN CHAR8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 *Language,

+=C2=A0 OUT CHAR16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 **ControllerName

+=C2=A0 );

+

+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL=C2=A0 gNetworkCo= mmonComponentName =3D {

+=C2=A0 NetworkCommonComponentNameGetDriverName,

+=C2=A0 NetworkCommonComponentNameGetControllerName,

+=C2=A0 "eng"

+};

+

+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL=C2=A0 gNetworkC= ommonComponentName2 =3D {

+=C2=A0 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)NetworkCommonComponentNameGetD= riverName,

+=C2=A0 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)NetworkCommonComponentName= GetControllerName,

+=C2=A0 "en"

+};

+

+/**

+=C2=A0 Retrieves a Unicode string that is the user readable name of the dr= iver.

+

+=C2=A0 This function retrieves the user readable name of a driver in the f= orm of a

+=C2=A0 Unicode string. If the driver specified by This has a user readable= name in

+=C2=A0 the language specified by Language, then a pointer to the driver na= me is

+=C2=A0 returned in DriverName, and EFI_SUCCESS is returned. If the driver = specified

+=C2=A0 by This does not support the language specified by Language,

+=C2=A0 then EFI_UNSUPPORTED is returned.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_COMPONENT_NAME_PROTOCOL instance= .

+=C2=A0 @param[in]=C2=A0 Language=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A point= er to a Null-terminated ASCII string

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 array indicating the language. This = is the

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 language of the driver name that the= caller is

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 requesting, and it must match one of= the

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 languages specified in SupportedLang= uages. The

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 number of languages supported by a d= river is up

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 to the driver writer. Language is sp= ecified

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 in RFC 4646 or ISO 639-2 language co= de format.

+=C2=A0 @param[out] DriverName=C2=A0 =C2=A0 =C2=A0 =C2=A0 A pointer to the = Unicode string to return.

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This Unicode string is the name of t= he

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 driver specified by This in the lang= uage

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 specified by Language.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The Uni= code string for the Driver specified by

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This and the language specified by L= anguage was

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 returned in DriverName.

+=C2=A0 @retval EFI_INVALID_PARAMETER Language is NULL.

+=C2=A0 @retval EFI_INVALID_PARAMETER DriverName is NULL.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0The driver specif= ied by This does not support

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 the language specified by Language.<= br>
+

+**/

+EFI_STATUS

+EFIAPI

+NetworkCommonComponentNameGetDriverName (

+=C2=A0 IN=C2=A0 EFI_COMPONENT_NAME_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 CHAR8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *Language,

+=C2=A0 OUT CHAR16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0**DriverName

+=C2=A0 )

+{

+=C2=A0 return LookupUnicodeString2 (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Language,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->SupportedLanguages,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0gNetworkCommonDriverNameTable,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0DriverName,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(BOOLEAN)(This =3D=3D &gNetwo= rkCommonComponentName)

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+}

+

+/**

+=C2=A0 Retrieves a Unicode string that is the user readable name of the co= ntroller

+=C2=A0 that is being managed by a driver.

+

+=C2=A0 This function retrieves the user readable name of the controller sp= ecified by

+=C2=A0 ControllerHandle and ChildHandle in the form of a Unicode string. I= f the

+=C2=A0 driver specified by This has a user readable name in the language s= pecified by

+=C2=A0 Language, then a pointer to the controller name is returned in Cont= rollerName,

+=C2=A0 and EFI_SUCCESS is returned.=C2=A0 If the driver specified by This = is not currently

+=C2=A0 managing the controller specified by ControllerHandle and ChildHand= le,

+=C2=A0 then EFI_UNSUPPORTED is returned.=C2=A0 If the driver specified by = This does not

+=C2=A0 support the language specified by Language, then EFI_UNSUPPORTED is= returned.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_COMPONENT_NAME_PROTOCOL instance= .

+=C2=A0 @param[in]=C2=A0 Controller=C2=A0 =C2=A0 =C2=A0 =C2=A0 The handle o= f a controller that the driver

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 specified by This is managing.=C2=A0= This handle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 specifies the controller whose name = is to be

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 returned.

+=C2=A0 @param[in]=C2=A0 ChildHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0The handle o= f the child controller to retrieve

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 the name of.=C2=A0 This is an option= al parameter that

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 may be NULL.=C2=A0 It will be NULL f= or device

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 drivers.=C2=A0 It will also be NULL = for a bus drivers

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 that wish to retrieve the name of th= e bus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 controller.=C2=A0 It will not be NUL= L for a bus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 driver that wishes to retrieve the n= ame of a

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 child controller.

+=C2=A0 @param[in]=C2=A0 Language=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A point= er to a Null-terminated ASCII string

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 array indicating the language.=C2=A0= This is the

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 language of the driver name that the= caller is

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 requesting, and it must match one of= the

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 languages specified in SupportedLang= uages. The

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 number of languages supported by a d= river is up

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 to the driver writer. Language is sp= ecified in

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 RFC 4646 or ISO 639-2 language code = format.

+=C2=A0 @param[out] ControllerName=C2=A0 =C2=A0 A pointer to the Unicode st= ring to return.

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This Unicode string is the name of t= he

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 controller specified by ControllerHa= ndle and

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ChildHandle in the language specifie= d by

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Language from the point of view of t= he driver

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 specified by This.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The Uni= code string for the user readable name in

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 the language specified by Language f= or the

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 driver specified by This was returne= d in

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 DriverName.

+=C2=A0 @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_H= ANDLE.

+=C2=A0 @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not= a valid

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_HANDLE.

+=C2=A0 @retval EFI_INVALID_PARAMETER Language is NULL.

+=C2=A0 @retval EFI_INVALID_PARAMETER ControllerName is NULL.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0The driver specif= ied by This is not currently

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 managing the controller specified by=

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerHandle and ChildHandle.
+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0The driver specif= ied by This does not support

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 the language specified by Language.<= br>
+

+**/

+EFI_STATUS

+EFIAPI

+NetworkCommonComponentNameGetControllerName (

+=C2=A0 IN=C2=A0 EFI_COMPONENT_NAME_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0Controller,

+=C2=A0 IN=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0ChildHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0 OPTIONAL,

+=C2=A0 IN=C2=A0 CHAR8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *Language,

+=C2=A0 OUT CHAR16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0**ControllerName

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Status;

+=C2=A0 CHAR16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0*HandleName;

+=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbIo =3D NULL;

+=C2=A0 EFI_USB_DEVICE_DESCRIPTOR=C2=A0 DevDesc;

+

+=C2=A0 if (!Language || !ControllerName) {

+=C2=A0 =C2=A0 return EFI_INVALID_PARAMETER;

+=C2=A0 }

+

+=C2=A0 if (ChildHandle =3D=3D NULL) {

+=C2=A0 =C2=A0 return EFI_UNSUPPORTED;

+=C2=A0 }

+

+=C2=A0 //

+=C2=A0 // Make sure this driver is currently managing ControllerHandle

+=C2=A0 //

+=C2=A0 Status =3D EfiTestManagedDevice (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Controller,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0gNetworkCommonDriverBindin= g.DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gUsbEthProtocolGuid
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 //

+=C2=A0 // Make sure this driver produced ChildHandle

+=C2=A0 //

+=C2=A0 Status =3D EfiTestChildHandle (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Controller,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ChildHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gUsbEthProtocolGuid
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 Status =3D gBS->HandleProtocol (Controller, &gEfiUsbIoProtoc= olGuid, (VOID **)&UsbIo);

+

+=C2=A0 if (!EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 Status =3D UsbIo->UsbGetDeviceDescriptor (UsbIo, &Dev= Desc);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 return Status;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 Status =3D UsbIo->UsbGetStringDescriptor (UsbIo, 0x409, D= evDesc.StrManufacturer, &HandleName);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 return Status;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 *ControllerName =3D HandleName;

+

+=C2=A0 =C2=A0 if (gNetworkCommonControllerNameTable !=3D NULL) {

+=C2=A0 =C2=A0 =C2=A0 FreeUnicodeStringTable (gNetworkCommonControllerNameT= able);

+=C2=A0 =C2=A0 =C2=A0 gNetworkCommonControllerNameTable =3D NULL;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 Status =3D AddUnicodeString2 (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0"eng",
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0gNetworkCommonCompo= nentName.SupportedLanguages,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gNetworkCommon= ControllerNameTable,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0HandleName,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0TRUE

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 return Status;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 Status =3D AddUnicodeString2 (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0"en",

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0gNetworkCommonCompo= nentName2.SupportedLanguages,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gNetworkCommon= ControllerNameTable,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0HandleName,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0FALSE

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 return Status;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 return LookupUnicodeString2 (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Language,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->SupportedLanguage= s,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0gNetworkCommonControllerNa= meTable,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerName,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(BOOLEAN)(This =3D=3D &= ;gNetworkCommonComponentName)

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 }

+

+=C2=A0 return EFI_UNSUPPORTED;

+}

diff --git a/UsbNetworkPkg/NetworkCommon/DriverBinding.c b/UsbNetworkPkg/Ne= tworkCommon/DriverBinding.c
new file mode 100644
index 0000000000..18b2daa7a8
--- /dev/null
+++ b/UsbNetworkPkg/NetworkCommon/DriverBinding.c
@@ -0,0 +1,583 @@
+/** @file

+=C2=A0 This file contains code for USB network binding driver

+

+=C2=A0 Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+=C2=A0 Subject to AMI licensing agreement.

+**/

+

+#include "DriverBinding.h"

+

+PXE_SW_UNDI=C2=A0 *gPxe =3D NULL;

+NIC_DEVICE=C2=A0 =C2=A0*gLanDeviceList[MAX_LAN_INTERFACE];

+

+EFI_GUID=C2=A0 gUsbEthProtocolGuid =3D USB_ETHERNET_PROTOCOL_GUID;

+

+EFI_DRIVER_BINDING_PROTOCOL=C2=A0 gNetworkCommonDriverBinding =3D {

+=C2=A0 NetworkCommonSupported,

+=C2=A0 NetworkCommonDriverStart,

+=C2=A0 NetworkCommonDriverStop,

+=C2=A0 NETWORK_COMMON_DRIVER_VERSION,

+=C2=A0 NULL,

+=C2=A0 NULL

+};

+

+/**

+=C2=A0 Create MAC Device Path

+

+=C2=A0 @param[in, out] Dev=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= A pointer to the EFI_DEVICE_PATH_PROTOCOL instance.

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 BaseDev=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0A pointer to the EFI_DEVICE_PATH_PROTOCOL instance.

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 Nic=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0A pointer to the Network interface controller data.

+

+=C2=A0 @retval EFI_OUT_OF_RESOURCES=C2=A0 =C2=A0 The device path could not= be created successfully due to a lack of resources.

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= MAC device path created successfully.

+

+**/

+EFI_STATUS

+CreateMacDevicePath (

+=C2=A0 IN OUT=C2=A0 EFI_DEVICE_PATH_PROTOCOL=C2=A0 **Dev,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 EFI_DEVICE_PATH_PROTOCOL=C2=A0 *BaseDev,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 NIC_DATA=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 S= tatus;

+=C2=A0 MAC_ADDR_DEVICE_PATH=C2=A0 =C2=A0 =C2=A0 MacAddrNode;

+=C2=A0 EFI_DEVICE_PATH_PROTOCOL=C2=A0 *EndNode;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0*DevicePath;

+=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 TotalLength;

+=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 BaseLength;

+

+=C2=A0 ZeroMem (&MacAddrNode, sizeof (MAC_ADDR_DEVICE_PATH));

+=C2=A0 CopyMem (&MacAddrNode.MacAddress, &Nic->MacAddr, sizeof = (EFI_MAC_ADDRESS));

+

+=C2=A0 MacAddrNode.Header.Type=C2=A0 =C2=A0 =C2=A0 =3D MESSAGING_DEVICE_PA= TH;

+=C2=A0 MacAddrNode.Header.SubType=C2=A0 =C2=A0=3D MSG_MAC_ADDR_DP;

+=C2=A0 MacAddrNode.Header.Length[0] =3D (UINT8)sizeof (MacAddrNode);

+=C2=A0 MacAddrNode.Header.Length[1] =3D 0;

+

+=C2=A0 EndNode =3D BaseDev;

+

+=C2=A0 while (!IsDevicePathEnd (EndNode)) {

+=C2=A0 =C2=A0 EndNode =3D NextDevicePathNode (EndNode);

+=C2=A0 }

+

+=C2=A0 BaseLength=C2=A0 =3D (UINT16)((UINTN)(EndNode) - (UINTN)(BaseDev));=

+=C2=A0 TotalLength =3D (UINT16)(BaseLength + sizeof (MacAddrNode) + sizeof= (EFI_DEVICE_PATH_PROTOCOL));

+

+=C2=A0 Status =3D gBS->AllocatePool (EfiBootServicesData, TotalLength, = (VOID **)&DevicePath);

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 *Dev =3D (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;

+=C2=A0 CopyMem (DevicePath, (CHAR8 *)BaseDev, BaseLength);

+=C2=A0 DevicePath +=3D BaseLength;

+=C2=A0 CopyMem (DevicePath, (CHAR8 *)&MacAddrNode, sizeof (MacAddrNode= ));

+=C2=A0 DevicePath +=3D sizeof (MacAddrNode);

+=C2=A0 CopyMem (DevicePath, (CHAR8 *)EndNode, sizeof (EFI_DEVICE_PATH_PROT= OCOL));

+

+=C2=A0 return EFI_SUCCESS;

+}

+

+/**

+=C2=A0 Network Common Driver Binding Support.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 Protocol instance pointer.

+=C2=A0 @param[in]=C2=A0 ControllerHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0 Handle= of device to test.

+=C2=A0 @param[in]=C2=A0 RemainingDevicePath=C2=A0 =C2=A0 =C2=A0Optional pa= rameter use to pick a specific child

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 device to start= .

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0This driver supports this device.

+=C2=A0 @retval EFI_ALREADY_STARTED=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This d= river is already running on this device.

+=C2=A0 @retval other=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This driver does not support this device.
+

+**/

+EFI_STATUS

+EFIAPI

+NetworkCommonSupported (

+=C2=A0 IN EFI_DRIVER_BINDING_PROTOCOL=C2=A0 *This,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 IN EFI_DEVICE_PATH_PROTOCOL=C2=A0 =C2=A0 =C2=A0*RemainingDevicePath=

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Status;
+=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *UsbEth;

+

+=C2=A0 Status =3D gBS->OpenProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gUsbEt= hProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOID **)&a= mp;UsbEth,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This->Dr= iverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_OPEN_PR= OTOCOL_BY_DRIVER

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gUsbEthProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Network Common Driver Binding Start.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 Protocol instance pointer.

+=C2=A0 @param[in]=C2=A0 ControllerHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0 Handle= of device to bind driver to.

+=C2=A0 @param[in]=C2=A0 RemainingDevicePath=C2=A0 =C2=A0 =C2=A0Optional pa= rameter use to pick a specific child

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 device to start= .

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0This driver is added to ControllerHandle

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 T= his driver could not be started due to a device error

+=C2=A0 @retval EFI_OUT_OF_RESOURCES=C2=A0 =C2=A0 =C2=A0 =C2=A0 The driver = could not install successfully due to a lack of resources.

+=C2=A0 @retval other=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This driver does not support this device

+

+**/

+EFI_STATUS

+EFIAPI

+NetworkCommonDriverStart (

+=C2=A0 IN EFI_DRIVER_BINDING_PROTOCOL=C2=A0 *This,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 IN EFI_DEVICE_PATH_PROTOCOL=C2=A0 =C2=A0 =C2=A0*RemainingDevicePath=

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 S= tatus;

+=C2=A0 EFI_DEVICE_PATH_PROTOCOL=C2=A0 *UsbEthPath;

+=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0*UsbEth;

+=C2=A0 EFI_MAC_ADDRESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0MacAddress;=

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0BulkDataSize;

+=C2=A0 NIC_DEVICE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *= NicDevice;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0*TmpPxePointer =3D NULL;

+

+=C2=A0 Status =3D gBS->OpenProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gUsbEt= hProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOID **)&a= mp;UsbEth,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This->Dr= iverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_OPEN_PR= OTOCOL_BY_DRIVER

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 Status =3D gBS->OpenProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiDe= vicePathProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOID **)&a= mp;UsbEthPath,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This->Dr= iverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_OPEN_PR= OTOCOL_BY_DRIVER

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gUsbEthProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 ZeroMem (&MacAddress, sizeof (EFI_MAC_ADDRESS));

+

+=C2=A0 Status =3D UsbEth->UsbEthMacAddress (UsbEth, &MacAddress);
+=C2=A0 ASSERT_EFI_ERROR (Status);

+=C2=A0 Status =3D UsbEth->UsbEthMaxBulkSize (UsbEth, &BulkDataSize)= ;

+

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gEfiDevicePathProtocolGuid,<= br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gUsbEthProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 NicDevice =3D AllocateZeroPool (sizeof (NIC_DEVICE));

+=C2=A0 if (!NicDevice) {

+=C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gEfiDevicePathProtocolGuid,<= br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gUsbEthProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 =C2=A0 return EFI_OUT_OF_RESOURCES;

+=C2=A0 }

+

+=C2=A0 // for alignment adjustment

+=C2=A0 if (gPxe =3D=3D NULL) {

+=C2=A0 =C2=A0 TmpPxePointer =3D AllocateZeroPool (sizeof (PXE_SW_UNDI) + 1= 6);

+=C2=A0 =C2=A0 if (!TmpPxePointer) {

+=C2=A0 =C2=A0 =C2=A0 if (NicDevice !=3D NULL) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 gBS->FreePool (NicDevice);

+=C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gEfiDevicePathProtoco= lGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHand= le,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 =C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gUsbEthProtocolGuid,<= br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHand= le,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+

+=C2=A0 =C2=A0 =C2=A0 return EFI_OUT_OF_RESOURCES;

+=C2=A0 =C2=A0 } else {

+=C2=A0 =C2=A0 =C2=A0 // check for paragraph alignment here

+=C2=A0 =C2=A0 =C2=A0 if (((UINTN)TmpPxePointer & 0x0F) !=3D 0) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 gPxe =3D (PXE_SW_UNDI *)(TmpPxePointer + 8);
+=C2=A0 =C2=A0 =C2=A0 } else {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 gPxe =3D (PXE_SW_UNDI *)TmpPxePointer;

+=C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 if (!gPxe) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (NicDevice !=3D NULL) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 gBS->FreePool (NicDevice);

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gEfiDevicePath= ProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBind= ingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gUsbEthProtoco= lGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBind= ingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return EFI_OUT_OF_RESOURCES;

+=C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 PxeStructInit (gPxe);

+=C2=A0 =C2=A0 }

+=C2=A0 }

+

+=C2=A0 NicDevice->NiiProtocol.Id=C2=A0 =C2=A0 =3D (UINT64)(UINTN)(gPxe)= ;

+=C2=A0 NicDevice->NiiProtocol.IfNum =3D gPxe->IFcnt | gPxe->IFcnt= Ext << 8;

+

+=C2=A0 UpdateNicNum (&NicDevice->NicInfo, gPxe);

+

+=C2=A0 NicDevice->NicInfo.Signature =3D NIC_DATA_SIGNATURE;

+

+=C2=A0 NicDevice->NicInfo.UsbEth=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D U= sbEth;

+=C2=A0 NicDevice->NicInfo.MaxSegmentSize =3D (UINT16)BulkDataSize;

+=C2=A0 NicDevice->NicInfo.CableDetect=C2=A0 =C2=A0 =3D 0;

+

+=C2=A0 CopyMem ((CHAR8 *)&(NicDevice->NicInfo.MacAddr), (CHAR8 *)&a= mp;MacAddress, sizeof (MacAddress));

+

+=C2=A0 NicDevice->NicInfo.TxBufferCount =3D 0;

+

+=C2=A0 if (NicDevice->NiiProtocol.IfNum < MAX_LAN_INTERFACE) {

+=C2=A0 =C2=A0 gLanDeviceList[NicDevice->NiiProtocol.IfNum] =3D NicDevic= e;

+=C2=A0 } else {

+=C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gEfiDevicePathProtocolGuid,<= br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gUsbEthProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+

+=C2=A0 =C2=A0 if (TmpPxePointer !=3D NULL) {

+=C2=A0 =C2=A0 =C2=A0 gBS->FreePool (TmpPxePointer);

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 if (NicDevice !=3D NULL) {

+=C2=A0 =C2=A0 =C2=A0 gBS->FreePool (NicDevice);

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 return EFI_DEVICE_ERROR;

+=C2=A0 }

+

+=C2=A0 Status =3D CreateMacDevicePath (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&NicDevice->DevPath= ,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0UsbEthPath,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&NicDevice->NicInfo=

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 UpdateNicNum (NULL, gPxe);

+=C2=A0 =C2=A0 if (TmpPxePointer !=3D NULL) {

+=C2=A0 =C2=A0 =C2=A0 gBS->FreePool (TmpPxePointer);

+=C2=A0 =C2=A0 }

+=C2=A0 }

+

+=C2=A0 NicDevice->Signature=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0=3D UNDI_DEV_SIGNATURE;

+=C2=A0 NicDevice->NiiProtocol.Revision=C2=A0 =C2=A0 =C2=A0 =3D EFI_NETW= ORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION;

+=C2=A0 NicDevice->NiiProtocol.Type=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =3D EfiNetworkInterfaceUndi;

+=C2=A0 NicDevice->NiiProtocol.MajorVer=C2=A0 =C2=A0 =C2=A0 =3D PXE_ROMI= D_MAJORVER;

+=C2=A0 NicDevice->NiiProtocol.MinorVer=C2=A0 =C2=A0 =C2=A0 =3D PXE_ROMI= D_MINORVER;

+=C2=A0 NicDevice->NiiProtocol.ImageSize=C2=A0 =C2=A0 =C2=A0=3D 0;

+=C2=A0 NicDevice->NiiProtocol.ImageAddr=C2=A0 =C2=A0 =C2=A0=3D 0;

+=C2=A0 NicDevice->NiiProtocol.Ipv6Supported =3D TRUE;

+

+=C2=A0 NicDevice->NiiProtocol.StringId[0] =3D 'U';

+=C2=A0 NicDevice->NiiProtocol.StringId[1] =3D 'N';

+=C2=A0 NicDevice->NiiProtocol.StringId[2] =3D 'D';

+=C2=A0 NicDevice->NiiProtocol.StringId[3] =3D 'I';

+=C2=A0 NicDevice->DeviceHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =3D NULL;

+

+=C2=A0 ZeroMem (&NicDevice->NicInfo.Request, sizeof (EFI_USB_DEVICE= _REQUEST));

+

+=C2=A0 Status =3D UsbEth->UsbEthInterrupt (UsbEth, TRUE, NETWORK_COMMON= _POLLING_INTERVAL, &NicDevice->NicInfo.Request);

+=C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 Status =3D gBS->InstallMultipleProtocolInterfaces (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &NicDev= ice->DeviceHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiNe= tworkInterfaceIdentifierProtocolGuid_31,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &NicDev= ice->NiiProtocol,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiDe= vicePathProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NicDevice-&= gt;DevPath,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NULL

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 if (NicDevice->NiiProtocol.IfNum < MAX_LAN_INTERFACE) = {

+=C2=A0 =C2=A0 =C2=A0 gLanDeviceList[NicDevice->NiiProtocol.IfNum] =3D N= ULL;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gEfiDevicePathProtocolGuid,<= br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gUsbEthProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+

+=C2=A0 =C2=A0 if (TmpPxePointer !=3D NULL) {

+=C2=A0 =C2=A0 =C2=A0 gBS->FreePool (TmpPxePointer);

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 if (NicDevice->DevPath !=3D NULL) {

+=C2=A0 =C2=A0 =C2=A0 gBS->FreePool (NicDevice->DevPath);

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 if (NicDevice !=3D NULL) {

+=C2=A0 =C2=A0 =C2=A0 gBS->FreePool (NicDevice);

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 return EFI_DEVICE_ERROR;

+=C2=A0 }

+

+=C2=A0 Status =3D gBS->OpenProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gUsbEt= hProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOID **)&a= mp;UsbEth,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This->Dr= iverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NicDevice-&= gt;DeviceHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_OPEN_PR= OTOCOL_BY_CHILD_CONTROLLER

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Network Common Driver Binding Stop.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 Protocol instance pointer.

+=C2=A0 @param[in]=C2=A0 ControllerHandle=C2=A0 =C2=A0 =C2=A0 Handle of dev= ice to stop driver on

+=C2=A0 @param[in]=C2=A0 NumberOfChildren=C2=A0 =C2=A0 =C2=A0 Number of Han= dles in ChildHandleBuffer. If number of

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 children is zero stop = the entire bus driver.

+=C2=A0 @param[in]=C2=A0 ChildHandleBuffer=C2=A0 =C2=A0 =C2=A0List of Child= Handles to Stop.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0This driver is removed ControllerHandle

+=C2=A0 @retval other=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0This driver was not removed from this device

+

+**/

+EFI_STATUS

+EFIAPI

+NetworkCommonDriverStop (

+=C2=A0 IN=C2=A0 EFI_DRIVER_BINDING_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 IN=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NumberOfChildren,

+=C2=A0 IN=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0*ChildHandleBuffer

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Status;

+=C2=A0 BOOLEAN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 AllChild= renStopped;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Inde= x;

+=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbEth;

+=C2=A0 NIC_DEVICE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*NicDevice;
+=C2=A0 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL=C2=A0 *NiiProtocol;

+

+=C2=A0 if (NumberOfChildren =3D=3D 0) {

+=C2=A0 =C2=A0 Status =3D gBS->OpenProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Cont= rollerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &= ;gEfiNetworkInterfaceIdentifierProtocolGuid_31,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOI= D **)&NiiProtocol,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This= ->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Cont= rollerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_= OPEN_PROTOCOL_GET_PROTOCOL

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );
+

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gEfiDevicePathProtoco= lGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHand= le,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 =C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gUsbEthProtocolGuid,<= br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHand= le,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 =C2=A0 =C2=A0 return EFI_SUCCESS;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 NicDevice =3D UNDI_DEV_FROM_THIS (NiiProtocol);

+=C2=A0 =C2=A0 Status=C2=A0 =C2=A0 =3D gBS->UninstallMultipleProtocolInt= erfaces (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0&gEfiNetworkInterfaceIdentifierProtocolGuid_31,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0&NicDevice->NiiProtocol,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0&gEfiDevicePathProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0NicDevice->DevPath,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0NULL

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 return Status;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 gBS->FreePool (NicDevice->DevPath);

+=C2=A0 =C2=A0 gBS->FreePool (NicDevice);

+

+=C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gEfiDevicePathProtocolGuid,<= br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gUsbEthProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 =C2=A0 return EFI_SUCCESS;

+=C2=A0 }

+

+=C2=A0 AllChildrenStopped =3D TRUE;

+

+=C2=A0 for (Index =3D 0; Index < NumberOfChildren; Index++) {

+=C2=A0 =C2=A0 Status =3D gBS->OpenProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Chil= dHandleBuffer[Index],

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &= ;gEfiNetworkInterfaceIdentifierProtocolGuid_31,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOI= D **)&NiiProtocol,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This= ->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Cont= rollerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_= OPEN_PROTOCOL_GET_PROTOCOL

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );
+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 AllChildrenStopped =3D FALSE;

+=C2=A0 =C2=A0 =C2=A0 continue;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 NicDevice =3D UNDI_DEV_FROM_THIS (NiiProtocol);

+

+=C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gUsbEthProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ChildHandleBuffer[Index]

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+

+=C2=A0 =C2=A0 Status =3D gBS->UninstallMultipleProtocolInterfaces (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Chil= dHandleBuffer[Index],

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &= ;gEfiNetworkInterfaceIdentifierProtocolGuid_31,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &= ;NicDevice->NiiProtocol,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &= ;gEfiDevicePathProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NicD= evice->DevPath,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NULL=

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );
+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 Status =3D gBS->OpenProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 &gUsbEthProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 (VOID **)&UsbEth,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 ChildHandleBuffer[Index],

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 );

+=C2=A0 =C2=A0 } else {

+=C2=A0 =C2=A0 =C2=A0 gBS->FreePool (NicDevice->DevPath);

+=C2=A0 =C2=A0 =C2=A0 gBS->FreePool (NicDevice);

+=C2=A0 =C2=A0 }

+=C2=A0 }

+

+=C2=A0 if (!AllChildrenStopped) {

+=C2=A0 =C2=A0 return EFI_DEVICE_ERROR;

+=C2=A0 }

+

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Entrypoint of Network Common Driver.

+

+=C2=A0 This function is the entrypoint of Network Common Driver. It instal= ls Driver Binding

+=C2=A0 Protocols together with Component Name Protocols.

+

+=C2=A0 @param[in]=C2=A0 ImageHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0The firmware= allocated handle for the EFI image.

+=C2=A0 @param[in]=C2=A0 SystemTable=C2=A0 =C2=A0 =C2=A0 =C2=A0A pointer to= the EFI System Table.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The ent= ry point is executed successfully.

+

+**/

+EFI_STATUS

+EFIAPI

+NetworkCommonEntry (

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 ImageHandle,

+=C2=A0 IN EFI_SYSTEM_TABLE=C2=A0 *SystemTable

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 Status;

+

+=C2=A0 gNetworkCommonDriverBinding.DriverBindingHandle =3D ImageHandle;
+=C2=A0 gNetworkCommonDriverBinding.ImageHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0=3D ImageHandle;

+

+=C2=A0 Status =3D gBS->InstallMultipleProtocolInterfaces (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gNetwo= rkCommonDriverBinding.DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiDr= iverBindingProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gNetwo= rkCommonDriverBinding,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiCo= mponentName2ProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gNetwo= rkCommonComponentName2,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NULL

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 return Status;

+}

diff --git a/UsbNetworkPkg/NetworkCommon/DriverBinding.h b/UsbNetworkPkg/Ne= tworkCommon/DriverBinding.h
new file mode 100644
index 0000000000..223e034f2f
--- /dev/null
+++ b/UsbNetworkPkg/NetworkCommon/DriverBinding.h
@@ -0,0 +1,263 @@
+/** @file

+=C2=A0 Header file for for USB network common driver

+

+=C2=A0 Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+=C2=A0 Subject to AMI licensing agreement.

+**/

+

+#ifndef _DRIVER_BINDING_H_

+#define _DRIVER_BINDING_H_

+

+#include <Library/UefiDriverEntryPoint.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <Library/UefiLib.h>

+#include <Library/DevicePathLib.h>

+#include <Library/DebugLib.h>

+#include <Library/MemoryAllocationLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/UefiUsbLib.h>

+#include <Protocol/UsbIo.h>

+#include <Protocol/NetworkInterfaceIdentifier.h>

+#include <Protocol/UsbEthernetProtocol.h>

+

+#define NETWORK_COMMON_DRIVER_VERSION=C2=A0 =C2=A0 1

+#define NETWORK_COMMON_POLLING_INTERVAL=C2=A0 0x10

+#define RX_BUFFER_COUNT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 32

+#define TX_BUFFER_COUNT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 32

+#define MEMORY_REQUIRE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A00

+

+#define UNDI_DEV_SIGNATURE=C2=A0 SIGNATURE_32('u','n','= ;d','i')

+#define UNDI_DEV_FROM_THIS(a)=C2=A0 CR(a, NIC_DEVICE, NiiProtocol, UNDI_DE= V_SIGNATURE)

+#define UNDI_DEV_FROM_NIC(a)=C2=A0 =C2=A0CR(a, NIC_DEVICE, NicInfo, UNDI_D= EV_SIGNATURE)

+

+#pragma pack(1)

+typedef struct {

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0DestAddr[PXE_HWADDR_LEN_ETHER];

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0SrcAddr[PXE_HWADDR_LEN_ETHER];

+=C2=A0 UINT16=C2=A0 =C2=A0 Protocol;

+} EthernetHeader;

+#pragma pack()

+

+typedef struct {

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 Signature;

+=C2=A0 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL=C2=A0 =C2=A0 NiiProtocol;=

+=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Device= Handle;

+=C2=A0 EFI_DEVICE_PATH_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*BaseDevPath;

+=C2=A0 EFI_DEVICE_PATH_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*DevPath;

+=C2=A0 NIC_DATA=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Ni= cInfo;

+} NIC_DEVICE;

+

+typedef VOID (*API_FUNC)(

+=C2=A0 PXE_CDB *,

+=C2=A0 NIC_DATA *

+=C2=A0 );

+

+extern PXE_SW_UNDI=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0*gPxe;

+extern NIC_DEVICE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 *gLanDeviceList[MAX_LAN_INTERFACE];

+extern EFI_COMPONENT_NAME2_PROTOCOL=C2=A0 gNetworkCommonComponentName2;
+

+EFI_STATUS

+EFIAPI

+NetworkCommonSupported (

+=C2=A0 IN EFI_DRIVER_BINDING_PROTOCOL=C2=A0 *This,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 IN EFI_DEVICE_PATH_PROTOCOL=C2=A0 =C2=A0 =C2=A0*RemainingDevicePath=

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+NetworkCommonDriverStart (

+=C2=A0 IN EFI_DRIVER_BINDING_PROTOCOL=C2=A0 *This,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 IN EFI_DEVICE_PATH_PROTOCOL=C2=A0 =C2=A0 =C2=A0*RemainingDevicePath=

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+NetworkCommonDriverStop (

+=C2=A0 IN=C2=A0 EFI_DRIVER_BINDING_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 IN=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NumberOfChildren,

+=C2=A0 IN=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0*ChildHandleBuffer

+=C2=A0 );

+

+VOID

+PxeStructInit (

+=C2=A0 OUT PXE_SW_UNDI=C2=A0 *PxeSw

+=C2=A0 );

+

+VOID

+UpdateNicNum (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 NIC_DATA=C2=A0 =C2=A0 =C2=A0*Nic,

+=C2=A0 IN OUT=C2=A0 PXE_SW_UNDI=C2=A0 *PxeSw

+=C2=A0 );

+

+VOID

+UndiApiEntry (

+=C2=A0 IN=C2=A0 UINT64=C2=A0 Cdb

+=C2=A0 );

+

+UINTN

+MapIt (

+=C2=A0 IN NIC_DATA=C2=A0 *Nic,

+=C2=A0 IN UINT64=C2=A0 =C2=A0 MemAddr,

+=C2=A0 IN UINT32=C2=A0 =C2=A0 Size,

+=C2=A0 IN UINT32=C2=A0 =C2=A0 Direction,

+=C2=A0 OUT UINT64=C2=A0 =C2=A0MappedAddr

+=C2=A0 );

+

+VOID

+UnMapIt (

+=C2=A0 IN NIC_DATA=C2=A0 *Nic,

+=C2=A0 IN UINT64=C2=A0 =C2=A0 MemAddr,

+=C2=A0 IN UINT32=C2=A0 =C2=A0 Size,

+=C2=A0 IN UINT32=C2=A0 =C2=A0 Direction,

+=C2=A0 IN UINT64=C2=A0 =C2=A0 MappedAddr

+=C2=A0 );

+

+VOID

+UndiGetState (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+VOID

+UndiStart (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+VOID

+UndiStop (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+VOID

+UndiGetInitInfo (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+VOID

+UndiGetConfigInfo (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+VOID

+UndiInitialize (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN OUT=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+VOID

+UndiReset (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+VOID

+UndiShutdown (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN OUT=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+VOID

+UndiInterruptEnable (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+VOID

+UndiReceiveFilter (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+VOID

+UndiStationAddress (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+VOID

+UndiStatistics (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+VOID

+UndiMcastIp2Mac (

+=C2=A0 IN OUT=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+VOID

+UndiNvData (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+VOID

+UndiGetStatus (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+VOID

+UndiFillHeader (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+VOID

+UndiTransmit (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+VOID

+UndiReceive (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+UINT16

+Initialize (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN OUT=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+UINT16

+Transmit (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN OUT=C2=A0 NIC_DATA=C2=A0 *Nic,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 UINT64=C2=A0 =C2=A0 CpbAddr,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 UINT16=C2=A0 =C2=A0 OpFlags

+=C2=A0 );

+

+UINT16

+Receive (

+=C2=A0 IN PXE_CDB=C2=A0 =C2=A0 =C2=A0 =C2=A0*Cdb,

+=C2=A0 IN OUT NIC_DATA=C2=A0 *Nic,

+=C2=A0 IN UINT64=C2=A0 =C2=A0 =C2=A0 =C2=A0 CpbAddr,

+=C2=A0 IN OUT UINT64=C2=A0 =C2=A0 DbAddr

+=C2=A0 );

+

+UINT16

+Setfilter (

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic,

+=C2=A0 IN=C2=A0 UINT16=C2=A0 =C2=A0 SetFilter,

+=C2=A0 IN=C2=A0 UINT64=C2=A0 =C2=A0 CpbAddr,

+=C2=A0 IN=C2=A0 UINT32=C2=A0 =C2=A0 CpbSize

+=C2=A0 );

+

+UINT16

+Statistics (

+=C2=A0 IN NIC_DATA=C2=A0 *Nic,

+=C2=A0 IN UINT64=C2=A0 =C2=A0 DbAddr,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 DbSize

+=C2=A0 );

+

+#endif

diff --git a/UsbNetworkPkg/NetworkCommon/NetworkCommon.inf b/UsbNetworkPkg/= NetworkCommon/NetworkCommon.inf
new file mode 100644
index 0000000000..483df660f7
--- /dev/null
+++ b/UsbNetworkPkg/NetworkCommon/NetworkCommon.inf
@@ -0,0 +1,43 @@
+## @file
+#=C2=A0 =C2=A0This is Usb Network Common driver for DXE phase.
+#
+# Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
+# Subject to AMI licensing agreement.
+##
+
+[Defines]
+=C2=A0 INF_VERSION=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =3D 0x00010005
+=C2=A0 BASE_NAME=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =3D NetworkCommon
+=C2=A0 FILE_GUID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =3D ca6eb4f4-f1d6-4375-97d6-18856871e1bf
+=C2=A0 MODULE_TYPE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =3D DXE_DRIVER
+=C2=A0 VERSION_STRING=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0=3D 1.0
+=C2=A0 ENTRY_POINT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =3D NetworkCommonEntry
+
+[Sources]
+=C2=A0 DriverBinding.c
+=C2=A0 DriverBinding.h
+=C2=A0 ComponentName.c
+=C2=A0 PxeFunction.c
+
+[Packages]
+=C2=A0 MdePkg/MdePkg.dec
+=C2=A0 MdeModulePkg/MdeModulePkg.dec
+=C2=A0 UsbNetworkPkg/UsbNetworkPkg.dec
+
+[LibraryClasses]
+=C2=A0 UefiDriverEntryPoint
+=C2=A0 UefiBootServicesTableLib
+=C2=A0 UefiLib
+=C2=A0 DebugLib
+=C2=A0 UefiUsbLib
+=C2=A0 MemoryAllocationLib
+=C2=A0 BaseMemoryLib
+
+[Protocols]
+=C2=A0 gEfiNetworkInterfaceIdentifierProtocolGuid_31
+=C2=A0 gEfiUsbIoProtocolGuid
+=C2=A0 gEfiDevicePathProtocolGuid
+=C2=A0 gEfiDriverBindingProtocolGuid
+
+[Depex]
+=C2=A0 TRUE
diff --git a/UsbNetworkPkg/NetworkCommon/PxeFunction.c b/UsbNetworkPkg/Netw= orkCommon/PxeFunction.c
new file mode 100644
index 0000000000..d34b61a69f
--- /dev/null
+++ b/UsbNetworkPkg/NetworkCommon/PxeFunction.c
@@ -0,0 +1,1734 @@
+/** @file

+=C2=A0 This file contains code for UNDI command based on UEFI specificatio= n.

+

+=C2=A0 Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+=C2=A0 Subject to AMI licensing agreement.

+**/

+

+#include "DriverBinding.h"

+

+// API table, defined in UEFI specification

+API_FUNC=C2=A0 gUndiApiTable[] =3D {

+=C2=A0 UndiGetState,

+=C2=A0 UndiStart,

+=C2=A0 UndiStop,

+=C2=A0 UndiGetInitInfo,

+=C2=A0 UndiGetConfigInfo,

+=C2=A0 UndiInitialize,

+=C2=A0 UndiReset,

+=C2=A0 UndiShutdown,

+=C2=A0 UndiInterruptEnable,

+=C2=A0 UndiReceiveFilter,

+=C2=A0 UndiStationAddress,

+=C2=A0 UndiStatistics,

+=C2=A0 UndiMcastIp2Mac,

+=C2=A0 UndiNvData,

+=C2=A0 UndiGetStatus,

+=C2=A0 UndiFillHeader,

+=C2=A0 UndiTransmit,

+=C2=A0 UndiReceive

+};

+

+/**

+=C2=A0 This command is used to determine the operational state of the UNDI= .

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+**/

+VOID

+UndiGetState (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 Status;

+

+=C2=A0 if ((Cdb->OpCode !=3D PXE_OPCODE_GET_STATE) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) ||
+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) ||<= br>
+=C2=A0 =C2=A0 =C2=A0 (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFc= ntExt << 8)) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED))

+=C2=A0 {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALID_CDB;

+=C2=A0 =C2=A0 return;

+=C2=A0 } else {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_SUCCESS;

+=C2=A0 }

+

+=C2=A0 Cdb->StatFlags =3D Cdb->StatFlags | Nic->State;

+

+=C2=A0 if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetState !=3D NULL) {
+=C2=A0 =C2=A0 Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiGetState = (Cdb, Nic);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;
+=C2=A0 =C2=A0 }

+=C2=A0 }

+}

+

+/**

+=C2=A0 This command is used to change the UNDI operational state from stop= ped to started.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+**/

+VOID

+UndiStart (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 PXE_CPB_START_31=C2=A0 *Cpb;

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 Status;

+

+=C2=A0 if ((Cdb->OpCode !=3D PXE_OPCODE_START) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) ||
+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) ||<= br>
+=C2=A0 =C2=A0 =C2=A0 (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFc= ntExt << 8)) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->CPBsize !=3D sizeof (PXE_CPB_START_31)) ||
+=C2=A0 =C2=A0 =C2=A0 (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED))

+=C2=A0 {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALID_CDB;

+=C2=A0 =C2=A0 return;

+=C2=A0 } else {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_SUCCESS;

+=C2=A0 }

+

+=C2=A0 if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_STOPPED) {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_ALREADY_STARTED;

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 Cpb =3D (PXE_CPB_START_31 *)(UINTN)Cdb->CPBaddr;

+

+=C2=A0 Nic->PxeStart.Delay=C2=A0 =C2=A0 =C2=A0=3D Cpb->Delay;

+=C2=A0 Nic->PxeStart.Virt2Phys =3D Cpb->Virt2Phys;

+=C2=A0 Nic->PxeStart.Block=C2=A0 =C2=A0 =C2=A0=3D Cpb->Block;

+=C2=A0 Nic->PxeStart.Map_Mem=C2=A0 =C2=A0=3D 0;

+=C2=A0 Nic->PxeStart.UnMap_Mem =3D 0;

+=C2=A0 Nic->PxeStart.Sync_Mem=C2=A0 =3D Cpb->Sync_Mem;

+=C2=A0 Nic->PxeStart.Unique_ID =3D Cpb->Unique_ID;

+=C2=A0 Nic->State=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =3D P= XE_STATFLAGS_GET_STATE_STARTED;

+

+=C2=A0 if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStart !=3D NULL) {

+=C2=A0 =C2=A0 Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiStart (Cd= b, Nic);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;
+=C2=A0 =C2=A0 }

+=C2=A0 }

+}

+

+/**

+=C2=A0 This command is used to change the UNDI operational state from star= ted to stopped.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+**/

+VOID

+UndiStop (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 Status;

+

+=C2=A0 if ((Cdb->OpCode !=3D PXE_OPCODE_STOP) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) ||
+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) ||<= br>
+=C2=A0 =C2=A0 =C2=A0 (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFc= ntExt << 8)) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED))

+=C2=A0 {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALID_CDB;

+=C2=A0 =C2=A0 return;

+=C2=A0 } else {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_SUCCESS;

+=C2=A0 }

+

+=C2=A0 if (Nic->State =3D=3D PXE_STATFLAGS_GET_STATE_STOPPED) {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_NOT_STARTED;

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 if (Nic->State =3D=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_NOT_SHUTDOWN;

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 Nic->PxeStart.Delay=C2=A0 =C2=A0 =C2=A0=3D 0;

+=C2=A0 Nic->PxeStart.Virt2Phys =3D 0;

+=C2=A0 Nic->PxeStart.Block=C2=A0 =C2=A0 =C2=A0=3D 0;

+=C2=A0 Nic->PxeStart.Map_Mem=C2=A0 =C2=A0=3D 0;

+=C2=A0 Nic->PxeStart.UnMap_Mem =3D 0;

+=C2=A0 Nic->PxeStart.Sync_Mem=C2=A0 =3D 0;

+=C2=A0 Nic->State=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =3D P= XE_STATFLAGS_GET_STATE_STOPPED;

+

+=C2=A0 if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStop !=3D NULL) {

+=C2=A0 =C2=A0 Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiStop (Cdb= , Nic);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;
+=C2=A0 =C2=A0 }

+=C2=A0 }

+}

+

+/**

+=C2=A0 This command is used to retrieve initialization information that is=

+=C2=A0 needed by drivers and applications to initialized UNDI.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+**/

+VOID

+UndiGetInitInfo (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 PXE_DB_GET_INIT_INFO=C2=A0 *Db;

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Status;

+

+=C2=A0 if ((Cdb->OpCode !=3D PXE_OPCODE_GET_INIT_INFO) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) ||
+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) ||<= br>
+=C2=A0 =C2=A0 =C2=A0 (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFc= ntExt << 8)) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->DBsize !=3D sizeof (PXE_DB_GET_INIT_INFO)) |= |

+=C2=A0 =C2=A0 =C2=A0 (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED))

+=C2=A0 {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALID_CDB;

+=C2=A0 =C2=A0 return;

+=C2=A0 } else {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_SUCCESS;

+=C2=A0 }

+

+=C2=A0 if (Nic->State =3D=3D PXE_STATFLAGS_GET_STATE_STOPPED) {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_NOT_STARTED;

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 Db =3D (PXE_DB_GET_INIT_INFO *)(UINTN)Cdb->DBaddr;

+

+=C2=A0 Db->MemoryRequired=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D MEMORY_R= EQUIRE;

+=C2=A0 Db->FrameDataLen=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D PXE= _MAX_TXRX_UNIT_ETHER;

+=C2=A0 Db->LinkSpeeds[0]=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =3D 10;

+=C2=A0 Db->LinkSpeeds[1]=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =3D 100;

+=C2=A0 Db->LinkSpeeds[2]=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =3D 1000;
+=C2=A0 Db->LinkSpeeds[3]=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =3D 0;

+=C2=A0 Db->MediaHeaderLen=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D PXE_MAC_= HEADER_LEN_ETHER;

+=C2=A0 Db->HWaddrLen=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =3D PXE_HWADDR_LEN_ETHER;

+=C2=A0 Db->MCastFilterCnt=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D MAX_MCAS= T_ADDRESS_CNT;

+=C2=A0 Db->TxBufCnt=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0=3D Nic->PxeInit.TxBufCnt;

+=C2=A0 Db->TxBufSize=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =3D Nic->PxeInit.TxBufSize;

+=C2=A0 Db->RxBufCnt=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0=3D Nic->PxeInit.RxBufCnt;

+=C2=A0 Db->RxBufSize=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =3D Nic->PxeInit.RxBufSize;

+=C2=A0 Db->IFtype=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0=3D PXE_IFTYPE_ETHERNET;

+=C2=A0 Db->SupportedDuplexModes=C2=A0 =C2=A0=3D PXE_DUPLEX_DEFAULT;

+=C2=A0 Db->SupportedLoopBackModes =3D LOOPBACK_NORMAL;

+

+=C2=A0 Cdb->StatFlags |=3D (PXE_STATFLAGS_CABLE_DETECT_SUPPORTED |

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED);

+

+=C2=A0 if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetInitInfo !=3D NULL) = {

+=C2=A0 =C2=A0 Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiGetInitIn= fo (Cdb, Nic);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;
+=C2=A0 =C2=A0 }

+=C2=A0 }

+}

+

+/**

+=C2=A0 This command is used to retrieve configuration information about
+=C2=A0 the NIC being controlled by the UNDI.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+**/

+VOID

+UndiGetConfigInfo (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 PXE_DB_GET_CONFIG_INFO=C2=A0 *Db;

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Status;<= br>
+

+=C2=A0 if ((Cdb->OpCode !=3D PXE_OPCODE_GET_CONFIG_INFO) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) ||
+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) ||<= br>
+=C2=A0 =C2=A0 =C2=A0 (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFc= ntExt << 8)) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->DBsize !=3D sizeof (PXE_DB_GET_CONFIG_INFO))= ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED))

+=C2=A0 {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALID_CDB;

+=C2=A0 =C2=A0 return;

+=C2=A0 } else {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_SUCCESS;

+=C2=A0 }

+

+=C2=A0 if (Nic->State =3D=3D PXE_STATFLAGS_GET_STATE_STOPPED) {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_NOT_STARTED;

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 Db =3D (PXE_DB_GET_CONFIG_INFO *)(UINTN)Cdb->DBaddr;

+

+=C2=A0 Db->pci.BusType =3D PXE_BUSTYPE_USB;

+

+=C2=A0 if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetConfigInfo !=3D NULL= ) {

+=C2=A0 =C2=A0 Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiGetConfig= Info (Cdb, Nic);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;
+=C2=A0 =C2=A0 }

+=C2=A0 }

+}

+

+/**

+=C2=A0 This command resets the network adapter and initializes UNDI using<= br>
+=C2=A0 the parameters supplied in the CPB.

+

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 Cdb=C2=A0 A pointer to the command d= escriptor block.

+=C2=A0 @param[in, out] Nic=C2=A0 A pointer to the Network interface contro= ller data.

+

+**/

+VOID

+UndiInitialize (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN OUT=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 PXE_CPB_INITIALIZE=C2=A0 *Cpb;

+=C2=A0 PXE_DB_INITIALIZE=C2=A0 =C2=A0*Db;

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Status;

+

+=C2=A0 if ((Cdb->OpCode !=3D PXE_OPCODE_INITIALIZE) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) ||
+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) ||<= br>
+=C2=A0 =C2=A0 =C2=A0 (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFc= ntExt << 8)) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->CPBsize !=3D sizeof (PXE_CPB_INITIALIZE)))
+=C2=A0 {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALID_CDB;

+=C2=A0 =C2=A0 return;

+=C2=A0 } else {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE;

+=C2=A0 }

+

+=C2=A0 if (Nic->State =3D=3D PXE_STATFLAGS_GET_STATE_STOPPED) {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_NOT_STARTED;

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 if ((Cdb->OpFlags !=3D PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) &= ;&

+=C2=A0 =C2=A0 =C2=A0 (Cdb->OpFlags !=3D PXE_OPFLAGS_INITIALIZE_DO_NOT_D= ETECT_CABLE))

+=C2=A0 {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALID_CDB;

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 if (Nic->State =3D=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_ALREADY_INITIALIZED;=

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 Cpb =3D (PXE_CPB_INITIALIZE *)(UINTN)Cdb->CPBaddr;

+=C2=A0 Db=C2=A0 =3D (PXE_DB_INITIALIZE *)(UINTN)Cdb->DBaddr;

+

+=C2=A0 Nic->PxeInit.LinkSpeed=C2=A0 =C2=A0 =3D Cpb->LinkSpeed;

+=C2=A0 Nic->PxeInit.DuplexMode=C2=A0 =C2=A0=3D Cpb->DuplexMode;

+=C2=A0 Nic->PxeInit.LoopBackMode =3D Cpb->LoopBackMode;

+=C2=A0 Nic->PxeInit.MemoryAddr=C2=A0 =C2=A0=3D Cpb->MemoryAddr;

+=C2=A0 Nic->PxeInit.MemoryLength =3D Cpb->MemoryLength;

+=C2=A0 Nic->PxeInit.TxBufCnt=C2=A0 =C2=A0 =C2=A0=3D TX_BUFFER_COUNT;
+=C2=A0 Nic->PxeInit.TxBufSize=C2=A0 =C2=A0 =3D Nic->MaxSegmentSize;<= br>
+=C2=A0 Nic->PxeInit.RxBufCnt=C2=A0 =C2=A0 =C2=A0=3D RX_BUFFER_COUNT;
+=C2=A0 Nic->PxeInit.RxBufSize=C2=A0 =C2=A0 =3D Nic->MaxSegmentSize;<= br>
+

+=C2=A0 Cdb->StatCode =3D Initialize (Cdb, Nic);

+

+=C2=A0 Db->MemoryUsed =3D MEMORY_REQUIRE;

+=C2=A0 Db->TxBufCnt=C2=A0 =C2=A0=3D Nic->PxeInit.TxBufCnt;

+=C2=A0 Db->TxBufSize=C2=A0 =3D Nic->PxeInit.TxBufSize;

+=C2=A0 Db->RxBufCnt=C2=A0 =C2=A0=3D Nic->PxeInit.RxBufCnt;

+=C2=A0 Db->RxBufSize=C2=A0 =3D Nic->PxeInit.RxBufSize;

+

+=C2=A0 Nic->RxFilter=C2=A0 =C2=A0 =3D PXE_OPFLAGS_RECEIVE_FILTER_BROADC= AST;

+=C2=A0 Nic->CanReceive=C2=A0 =3D FALSE;

+=C2=A0 Nic->CanTransmit =3D FALSE;

+

+=C2=A0 if (Cdb->OpFlags =3D=3D PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) {
+=C2=A0 =C2=A0 if ((Nic->Request.Request =3D=3D USB_CDC_NETWORK_CONNECTI= ON) && (Nic->Request.Value =3D=3D NETWORK_DISCONNECT)) {

+=C2=A0 =C2=A0 =C2=A0 Nic->CableDetect =3D 0;

+=C2=A0 =C2=A0 } else if ((Nic->Request.Request =3D=3D USB_CDC_NETWORK_C= ONNECTION) && (Nic->Request.Value =3D=3D NETWORK_CONNECTED)) {
+=C2=A0 =C2=A0 =C2=A0 Nic->CableDetect =3D 1;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 if (Nic->CableDetect =3D=3D 0) {

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags |=3D PXE_STATFLAGS_INITIALIZED_NO_M= EDIA;

+=C2=A0 =C2=A0 }

+=C2=A0 }

+

+=C2=A0 if (Cdb->StatCode !=3D PXE_STATCODE_SUCCESS) {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 } else {

+=C2=A0 =C2=A0 Nic->State =3D PXE_STATFLAGS_GET_STATE_INITIALIZED;

+=C2=A0 }

+

+=C2=A0 if (Nic->UsbEth->UsbEthUndi.UsbEthUndiInitialize !=3D NULL) {=

+=C2=A0 =C2=A0 Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiInitializ= e (Cdb, Nic);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;
+=C2=A0 =C2=A0 }

+=C2=A0 }

+}

+

+/**

+=C2=A0 Initialize Network interface controller data.

+

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 Cdb=C2=A0 =C2=A0 =C2=A0A pointer to = the command descriptor block.

+=C2=A0 @param[in, out] Nic=C2=A0 =C2=A0 =C2=A0A pointer to the Network int= erface controller data.

+

+=C2=A0 @retval Status=C2=A0 A value of Pxe statcode.

+

+**/

+UINT16

+Initialize (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN OUT=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0Status;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 Index;

+=C2=A0 EFI_STATUS=C2=A0 EfiStatus;

+

+=C2=A0 Status =3D MapIt (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Nic,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Nic->PxeInit.MemoryAddr= ,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Nic->PxeInit.MemoryLeng= th,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0TO_AND_FROM_DEVICE,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(UINT64)(UINTN)&Nic-&g= t;MappedAddr

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+

+=C2=A0 if (Status !=3D 0) {

+=C2=A0 =C2=A0 return (UINT16)Status;

+=C2=A0 }

+

+=C2=A0 for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {

+=C2=A0 =C2=A0 Nic->PermNodeAddress[Index] =3D Nic->MacAddr.Addr[Inde= x];

+=C2=A0 }

+

+=C2=A0 for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {

+=C2=A0 =C2=A0 Nic->CurrentNodeAddress[Index] =3D Nic->PermNodeAddres= s[Index];

+=C2=A0 }

+

+=C2=A0 for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {

+=C2=A0 =C2=A0 Nic->BroadcastNodeAddress[Index] =3D 0xFF;

+=C2=A0 }

+

+=C2=A0 for (Index =3D PXE_HWADDR_LEN_ETHER; Index < PXE_MAC_LENGTH; Ind= ex++) {

+=C2=A0 =C2=A0 Nic->CurrentNodeAddress[Index]=C2=A0 =C2=A0=3D 0;

+=C2=A0 =C2=A0 Nic->PermNodeAddress[Index]=C2=A0 =C2=A0 =C2=A0 =3D 0;
+=C2=A0 =C2=A0 Nic->BroadcastNodeAddress[Index] =3D 0;

+=C2=A0 }

+

+=C2=A0 if (Nic->UsbEth->UsbEthInitialize !=3D NULL) {

+=C2=A0 =C2=A0 EfiStatus =3D Nic->UsbEth->UsbEthInitialize (Cdb, Nic)= ;

+=C2=A0 =C2=A0 if (EFI_ERROR (EfiStatus)) {

+=C2=A0 =C2=A0 =C2=A0 return PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 }

+=C2=A0 }

+

+=C2=A0 return (UINT16)Status;

+}

+

+/**

+=C2=A0 This command resets the network adapter and reinitializes the UNDI<= br>
+=C2=A0 with the same parameters provided in the Initialize command.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+**/

+VOID

+UndiReset (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 Status;

+

+=C2=A0 if ((Cdb->OpCode !=3D PXE_OPCODE_RESET) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) ||
+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) ||<= br>
+=C2=A0 =C2=A0 =C2=A0 (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFc= ntExt << 8)) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED))

+=C2=A0 {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALID_CDB;

+=C2=A0 =C2=A0 return;

+=C2=A0 } else {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_SUCCESS;

+=C2=A0 }

+

+=C2=A0 if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) {

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_NOT_INITIALIZED;

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 if ((Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED) &&

+=C2=A0 =C2=A0 =C2=A0 (Cdb->OpFlags !=3D PXE_OPFLAGS_RESET_DISABLE_INTER= RUPTS) &&

+=C2=A0 =C2=A0 =C2=A0 (Cdb->OpFlags !=3D PXE_OPFLAGS_RESET_DISABLE_FILTE= RS))

+=C2=A0 {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALID_CDB;

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 if ((Cdb->OpFlags & PXE_OPFLAGS_RESET_DISABLE_FILTERS) =3D= =3D 0) {

+=C2=A0 =C2=A0 Nic->RxFilter =3D PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST;
+=C2=A0 }

+

+=C2=A0 if ((Cdb->OpFlags & PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS) != =3D 0) {

+=C2=A0 =C2=A0 Nic->InterrupOpFlag =3D 0;

+=C2=A0 }

+

+=C2=A0 if (Nic->UsbEth->UsbEthUndi.UsbEthUndiReset !=3D NULL) {

+=C2=A0 =C2=A0 Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiReset (Cd= b, Nic);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;
+=C2=A0 =C2=A0 }

+=C2=A0 }

+}

+

+/**

+=C2=A0 The Shutdown command resets the network adapter and leaves it in a<= br>
+=C2=A0 safe state for another driver to initialize.

+

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 Cdb=C2=A0 A pointer to the command d= escriptor block.

+=C2=A0 @param[in, out] Nic=C2=A0 A pointer to the Network interface contro= ller data.

+

+**/

+VOID

+UndiShutdown (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN OUT=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 Status;

+

+=C2=A0 if ((Cdb->OpCode !=3D PXE_OPCODE_SHUTDOWN) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) ||
+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) ||<= br>
+=C2=A0 =C2=A0 =C2=A0 (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFc= ntExt << 8)) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED))

+=C2=A0 {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALID_CDB;

+=C2=A0 =C2=A0 return;

+=C2=A0 } else {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_SUCCESS;

+=C2=A0 }

+

+=C2=A0 if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) {

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_NOT_INITIALIZED;

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 Nic->CanReceive=C2=A0 =3D FALSE;

+=C2=A0 Nic->CanTransmit =3D FALSE;

+

+=C2=A0 Nic->State =3D PXE_STATFLAGS_GET_STATE_STARTED;

+

+=C2=A0 if (Nic->UsbEth->UsbEthUndi.UsbEthUndiShutdown !=3D NULL) {
+=C2=A0 =C2=A0 Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiShutdown = (Cdb, Nic);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_NOT_INITIALIZ= ED;

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;
+=C2=A0 =C2=A0 }

+=C2=A0 }

+}

+

+/**

+=C2=A0 The Interrupt Enables command can be used to read and/or change

+=C2=A0 the current external interrupt enable settings.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+**/

+VOID

+UndiInterruptEnable (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 Status;

+

+=C2=A0 Cdb->StatCode =3D PXE_STATCODE_UNSUPPORTED;

+=C2=A0 if (Nic->UsbEth->UsbEthUndi.UsbEthUndiInterruptEnable !=3D NU= LL) {

+=C2=A0 =C2=A0 Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiInterrupt= Enable (Cdb, Nic);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;
+=C2=A0 =C2=A0 } else {

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE;=

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_SUCCESS;

+=C2=A0 =C2=A0 }

+=C2=A0 }

+}

+

+/**

+=C2=A0 This command is used to read and change receive filters and,

+=C2=A0 if supported, read and change the multicast MAC address filter list= .

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+**/

+VOID

+UndiReceiveFilter (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 NewFilter;

+=C2=A0 PXE_DB_RECEIVE_FILTERS=C2=A0 *Db;

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Status;<= br>
+

+=C2=A0 if ((Cdb->OpCode !=3D PXE_OPCODE_RECEIVE_FILTERS) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) ||
+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) ||<= br>
+=C2=A0 =C2=A0 =C2=A0 (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFc= ntExt << 8)))

+=C2=A0 {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALID_CDB;

+=C2=A0 =C2=A0 return;

+=C2=A0 } else {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_SUCCESS;

+=C2=A0 }

+

+=C2=A0 if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) {

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_NOT_INITIALIZED;

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 NewFilter =3D (UINT16)(Cdb->OpFlags & 0x1F);

+

+=C2=A0 switch (Cdb->OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_OPMASK) {<= br>
+=C2=A0 =C2=A0 case PXE_OPFLAGS_RECEIVE_FILTER_READ:

+=C2=A0 =C2=A0 =C2=A0 if (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FA= ILED;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALI= D_CDB;

+=C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 if ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_RESET= _MCAST_LIST) =3D=3D 0) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 if ((Cdb->DBsize !=3D 0)) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Db =3D (PXE_DB_RECEIVE_FILTERS *)(UINTN= )Cdb->DBaddr;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 CopyMem (Db, &Nic->McastList, Ni= c->McastCount);

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 break;

+

+=C2=A0 =C2=A0 case PXE_OPFLAGS_RECEIVE_FILTER_ENABLE:

+=C2=A0 =C2=A0 =C2=A0 if (NewFilter =3D=3D 0) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FA= ILED;

+=C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 if (Cdb->CPBsize !=3D 0) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (((NewFilter & PXE_OPFLAGS_RECEIVE_FILT= ER_FILTERED_MULTICAST) =3D=3D 0) ||

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ((NewFilter & PXE_OPFLAGS_RE= CEIVE_FILTER_RESET_MCAST_LIST) !=3D 0) ||

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ((NewFilter & PXE_OPFLAGS_RE= CEIVE_FILTER_ALL_MULTICAST) !=3D 0) ||

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ((Cdb->CPBsize % sizeof (PXE_= MAC_ADDR)) !=3D 0))

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COM= MAND_FAILED;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 if ((Cdb->OpFlags & PXE_OPFLAGS_RECEIVE_FILTER= _FILTERED_MULTICAST) !=3D 0) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (((Cdb->OpFlags & PXE_OPFLAGS_RECEIV= E_FILTER_RESET_MCAST_LIST) !=3D 0) ||

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ((Cdb->OpFlags & PXE_OPFL= AGS_RECEIVE_FILTER_ALL_MULTICAST) !=3D 0))

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COM= MAND_FAILED;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 if ((Cdb->CPBsize =3D=3D 0)) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COM= MAND_FAILED;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatCode =3D Setfilter (Nic, NewFilter, Cdb-&= gt;CPBaddr, Cdb->CPBsize);

+=C2=A0 =C2=A0 =C2=A0 break;

+

+=C2=A0 =C2=A0 case PXE_OPFLAGS_RECEIVE_FILTER_DISABLE:

+=C2=A0 =C2=A0 =C2=A0 if (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FA= ILED;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALI= D_CDB;

+=C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 Nic->CanReceive =3D TRUE;

+=C2=A0 =C2=A0 =C2=A0 break;

+

+=C2=A0 =C2=A0 default:

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;
+=C2=A0 =C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALID_CDB;<= br>
+=C2=A0 }

+

+=C2=A0 if (Nic->CanReceive) {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D (PXE_STATFLAGS)(Cdb->StatFlags | Ni= c->RxFilter);

+=C2=A0 }

+

+=C2=A0 if (Nic->UsbEth->UsbEthUndi.UsbEthUndiReceiveFilter !=3D NULL= ) {

+=C2=A0 =C2=A0 Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiReceiveFi= lter (Cdb, Nic);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;
+=C2=A0 =C2=A0 }

+=C2=A0 }

+}

+

+/**

+=C2=A0 Set PXE receive filter.

+

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A pointer to = the Network interface controller data.

+=C2=A0 @param[in]=C2=A0 SetFilter=C2=A0 =C2=A0PXE receive filter

+=C2=A0 @param[in]=C2=A0 CpbAddr=C2=A0 =C2=A0 =C2=A0Command Parameter Block= Address

+=C2=A0 @param[in]=C2=A0 CpbSize=C2=A0 =C2=A0 =C2=A0Command Parameter Block= Size

+

+**/

+UINT16

+Setfilter (

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic,

+=C2=A0 IN=C2=A0 UINT16=C2=A0 =C2=A0 SetFilter,

+=C2=A0 IN=C2=A0 UINT64=C2=A0 =C2=A0 CpbAddr,

+=C2=A0 IN=C2=A0 UINT32=C2=A0 =C2=A0 CpbSize

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0Status;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 *McastList;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 Count =3D 0;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 Index1;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 Index2;

+=C2=A0 PXE_CPB_RECEIVE_FILTERS=C2=A0 =C2=A0 =C2=A0 *Cpb =3D (PXE_CPB_RECEI= VE_FILTERS *)(UINTN)CpbAddr;

+=C2=A0 USB_ETHERNET_FUN_DESCRIPTOR=C2=A0 UsbEthFunDescriptor;

+

+=C2=A0 // The Cpb could be NULL.(ref:PXE_CPBADDR_NOT_USED)

+=C2=A0 Nic->RxFilter =3D (UINT8)SetFilter;

+

+=C2=A0 if (((SetFilter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST= ) !=3D 0) || (Cpb !=3D NULL)) {

+=C2=A0 =C2=A0 if (Cpb !=3D NULL) {

+=C2=A0 =C2=A0 =C2=A0 Nic->McastCount =3D (UINT8)(CpbSize / PXE_MAC_LENG= TH);

+=C2=A0 =C2=A0 =C2=A0 CopyMem (&Nic->McastList, Cpb, Nic->McastCo= unt);

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 if (Nic->CanReceive) {

+=C2=A0 =C2=A0 =C2=A0 Nic->CanReceive =3D FALSE;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 Nic->UsbEth->UsbEthFunDescriptor (Nic->UsbEth, &= ;UsbEthFunDescriptor);

+=C2=A0 =C2=A0 if ((UsbEthFunDescriptor.NumberMcFilters << 1) =3D=3D = 0) {

+=C2=A0 =C2=A0 =C2=A0 Nic->RxFilter |=3D PXE_OPFLAGS_RECEIVE_FILTER_ALL_= MULTICAST;

+=C2=A0 =C2=A0 =C2=A0 Nic->UsbEth->SetUsbEthPacketFilter (Nic->Usb= Eth, Nic->RxFilter);

+=C2=A0 =C2=A0 } else {

+=C2=A0 =C2=A0 =C2=A0 Status =3D gBS->AllocatePool (EfiBootServicesData,= Nic->McastCount * 6, (VOID **)&McastList);

+=C2=A0 =C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return PXE_STATCODE_INVALID_PARAMETER;

+=C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 if (Cpb !=3D NULL) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 for (Index1 =3D 0; Index1 < Nic->McastCo= unt; Index1++) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 for (Index2 =3D 0; Index2 < 6; Index= 2++) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 McastList[Count++] =3D Cpb->M= CastList[Index1][Index2];

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 Nic->RxFilter |=3D PXE_OPFLAGS_RECEIVE_FILTER_FILT= ERED_MULTICAST;

+=C2=A0 =C2=A0 =C2=A0 if (Cpb !=3D NULL) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 Nic->UsbEth->SetUsbEthMcastFilter (Nic-&= gt;UsbEth, Nic->McastCount, McastList);

+=C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 Nic->UsbEth->SetUsbEthPacketFilter (Nic->Usb= Eth, Nic->RxFilter);

+=C2=A0 =C2=A0 =C2=A0 gBS->FreePool (McastList);

+=C2=A0 =C2=A0 }

+=C2=A0 }

+

+=C2=A0 return PXE_STATCODE_SUCCESS;

+}

+

+/**

+=C2=A0 This command is used to get current station and broadcast MAC addre= sses

+=C2=A0 and, if supported, to change the current station MAC address.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+**/

+VOID

+UndiStationAddress (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 PXE_CPB_STATION_ADDRESS=C2=A0 *Cpb;

+=C2=A0 PXE_DB_STATION_ADDRESS=C2=A0 =C2=A0*Db;

+=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0Index;

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0St= atus;

+

+=C2=A0 if ((Cdb->OpCode !=3D PXE_OPCODE_STATION_ADDRESS) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) ||
+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) ||<= br>
+=C2=A0 =C2=A0 =C2=A0 (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFc= ntExt << 8)) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->DBsize !=3D sizeof (PXE_DB_STATION_ADDRESS))= )

+=C2=A0 {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALID_CDB;

+=C2=A0 =C2=A0 return;

+=C2=A0 } else {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_SUCCESS;

+=C2=A0 }

+

+=C2=A0 if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) {

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_NOT_INITIALIZED;

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 if (Cdb->OpFlags =3D=3D PXE_OPFLAGS_STATION_ADDRESS_RESET) {

+=C2=A0 =C2=A0 if (CompareMem (&Nic->CurrentNodeAddress[0], &Nic= ->PermNodeAddress[0], PXE_MAC_LENGTH) !=3D 0) {

+=C2=A0 =C2=A0 =C2=A0 for (Index =3D 0; Index < PXE_MAC_LENGTH; Index++)= {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 Nic->CurrentNodeAddress[Index] =3D Nic->= PermNodeAddress[Index];

+=C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 }

+=C2=A0 }

+

+=C2=A0 if (Cdb->CPBaddr !=3D 0) {

+=C2=A0 =C2=A0 Cpb =3D (PXE_CPB_STATION_ADDRESS *)(UINTN)Cdb->CPBaddr;
+=C2=A0 =C2=A0 for (Index =3D 0; Index < PXE_MAC_LENGTH; Index++) {

+=C2=A0 =C2=A0 =C2=A0 Nic->CurrentNodeAddress[Index] =3D Cpb->Station= Addr[Index];

+=C2=A0 =C2=A0 }

+=C2=A0 }

+

+=C2=A0 if (Cdb->DBaddr !=3D 0) {

+=C2=A0 =C2=A0 Db =3D (PXE_DB_STATION_ADDRESS *)(UINTN)Cdb->DBaddr;

+=C2=A0 =C2=A0 for (Index =3D 0; Index < PXE_MAC_LENGTH; Index++) {

+=C2=A0 =C2=A0 =C2=A0 Db->StationAddr[Index]=C2=A0 =C2=A0=3D Nic->Cur= rentNodeAddress[Index];

+=C2=A0 =C2=A0 =C2=A0 Db->BroadcastAddr[Index] =3D Nic->BroadcastNode= Address[Index];

+=C2=A0 =C2=A0 =C2=A0 Db->PermanentAddr[Index] =3D Nic->PermNodeAddre= ss[Index];

+=C2=A0 =C2=A0 }

+=C2=A0 }

+

+=C2=A0 if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStationAddress !=3D NUL= L) {

+=C2=A0 =C2=A0 Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiStationAd= dress (Cdb, Nic);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;
+=C2=A0 =C2=A0 }

+=C2=A0 }

+}

+

+/**

+=C2=A0 This command is used to read and clear the NIC traffic statistics.<= br>
+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+**/

+VOID

+UndiStatistics (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 Status;

+

+=C2=A0 if ((Cdb->OpCode !=3D PXE_OPCODE_STATISTICS) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) ||
+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) ||<= br>
+=C2=A0 =C2=A0 =C2=A0 (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFc= ntExt << 8)) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED))

+=C2=A0 {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALID_CDB;

+=C2=A0 =C2=A0 return;

+=C2=A0 } else {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE;

+=C2=A0 }

+

+=C2=A0 if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) {

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_NOT_INITIALIZED;

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 if ((Cdb->OpFlags !=3D PXE_OPFLAGS_STATISTICS_RESET) &&<= br>
+=C2=A0 =C2=A0 =C2=A0 (Cdb->OpFlags !=3D PXE_OPFLAGS_STATISTICS_READ))
+=C2=A0 {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALID_CDB;

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 Cdb->StatCode =3D Statistics (Nic, Cdb->DBaddr, Cdb->DBsiz= e);

+

+=C2=A0 if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStatistics !=3D NULL) {=

+=C2=A0 =C2=A0 Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiStatistic= s (Cdb, Nic);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;
+=C2=A0 =C2=A0 }

+=C2=A0 }

+}

+

+/**

+=C2=A0 Return data for DB data.

+

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 =C2=A0 =C2=A0 A pointer to the Network i= nterface controller data.

+=C2=A0 @param[in]=C2=A0 DbAddr=C2=A0 =C2=A0Data Block Address.

+=C2=A0 @param[in]=C2=A0 DbSize=C2=A0 =C2=A0Data Block Size.

+

+**/

+UINT16

+Statistics (

+=C2=A0 IN NIC_DATA=C2=A0 *Nic,

+=C2=A0 IN UINT64=C2=A0 =C2=A0 DbAddr,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 DbSize

+=C2=A0 )

+{

+=C2=A0 PXE_DB_STATISTICS=C2=A0 *DbStatistic;

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Status;

+

+=C2=A0 DbStatistic =3D (PXE_DB_STATISTICS *)(UINTN)DbAddr;

+

+=C2=A0 if (DbSize =3D=3D 0) {

+=C2=A0 =C2=A0 return PXE_STATCODE_SUCCESS;

+=C2=A0 }

+

+=C2=A0 DbStatistic->Supported=C2=A0 =3D 0x802;

+=C2=A0 DbStatistic->Data[0x01] =3D Nic->RxFrame;

+=C2=A0 DbStatistic->Data[0x0B] =3D Nic->TxFrame;

+

+=C2=A0 if (Nic->UsbEth->UsbEthStatistics !=3D NULL) {

+=C2=A0 =C2=A0 Status =3D Nic->UsbEth->UsbEthStatistics (Nic, DbAddr,= DbSize);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 return PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 }

+=C2=A0 }

+

+=C2=A0 return PXE_STATCODE_SUCCESS;

+}

+

+/**

+=C2=A0 Translate a multicast IPv4 or IPv6 address to a multicast MAC addre= ss.

+

+=C2=A0 @param[in, out] Cdb=C2=A0 A pointer to the command descriptor block= .

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 Nic=C2=A0 A pointer to the Network i= nterface controller data.

+

+**/

+VOID

+UndiMcastIp2Mac (

+=C2=A0 IN OUT=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 PXE_CPB_MCAST_IP_TO_MAC=C2=A0 *Cpb;

+=C2=A0 PXE_DB_MCAST_IP_TO_MAC=C2=A0 =C2=A0*Db;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 *Tmp;

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0St= atus;

+

+=C2=A0 if ((Cdb->OpCode !=3D PXE_OPCODE_MCAST_IP_TO_MAC) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) ||
+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) ||<= br>
+=C2=A0 =C2=A0 =C2=A0 (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFc= ntExt << 8)) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->CPBsize !=3D sizeof (PXE_CPB_MCAST_IP_TO_MAC= )) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->DBsize !=3D sizeof (PXE_DB_MCAST_IP_TO_MAC))= )

+=C2=A0 {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALID_CDB;

+=C2=A0 =C2=A0 return;

+=C2=A0 } else {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_SUCCESS;

+=C2=A0 }

+

+=C2=A0 if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) {

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_NOT_INITIALIZED;

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 Cpb =3D (PXE_CPB_MCAST_IP_TO_MAC *)(UINTN)Cdb->CPBaddr;

+=C2=A0 Db=C2=A0 =3D (PXE_DB_MCAST_IP_TO_MAC *)(UINTN)Cdb->DBaddr;

+

+=C2=A0 if ((Cdb->OpFlags & PXE_OPFLAGS_MCAST_IPV6_TO_MAC) !=3D 0) {=

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_UNSUPPORTED;

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 Tmp =3D (UINT8 *)(&Cpb->IP.IPv4);

+

+=C2=A0 if ((Tmp[0] & 0xF0) !=3D 0xE0) {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALID_CPB;

+=C2=A0 }

+

+=C2=A0 Db->MAC[0] =3D 0x01;

+=C2=A0 Db->MAC[1] =3D 0x00;

+=C2=A0 Db->MAC[2] =3D 0x5E;

+=C2=A0 Db->MAC[3] =3D Tmp[1] & 0x7F;

+=C2=A0 Db->MAC[4] =3D Tmp[2];

+=C2=A0 Db->MAC[5] =3D Tmp[3];

+

+=C2=A0 if (Nic->UsbEth->UsbEthUndi.UsbEthUndiMcastIp2Mac !=3D NULL) = {

+=C2=A0 =C2=A0 Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiMcastIp2M= ac (Cdb, Nic);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;
+=C2=A0 =C2=A0 }

+=C2=A0 }

+}

+

+/**

+=C2=A0 This command is used to read and write (if supported by NIC H/W)
+=C2=A0 nonvolatile storage on the NIC.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+**/

+VOID

+UndiNvData (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 Status;

+

+=C2=A0 Cdb->StatCode =3D PXE_STATCODE_UNSUPPORTED;

+=C2=A0 if (Nic->UsbEth->UsbEthUndi.UsbEthUndiNvData !=3D NULL) {

+=C2=A0 =C2=A0 Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiNvData (C= db, Nic);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;
+=C2=A0 =C2=A0 } else {

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE;=

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_SUCCESS;

+=C2=A0 =C2=A0 }

+=C2=A0 }

+}

+

+/**

+=C2=A0 This command returns the current interrupt status and/or the

+=C2=A0 transmitted buffer addresses and the current media status.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+**/

+VOID

+UndiGetStatus (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 PXE_DB_GET_STATUS=C2=A0 *Db;

+=C2=A0 PXE_DB_GET_STATUS=C2=A0 TmpGetStatus;

+=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0NumEntries;
+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Index;

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Status;

+

+=C2=A0 if ((Cdb->OpCode !=3D PXE_OPCODE_GET_STATUS) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) ||
+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) ||<= br>
+=C2=A0 =C2=A0 =C2=A0 (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFc= ntExt << 8)) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED))

+=C2=A0 {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALID_CDB;

+=C2=A0 =C2=A0 return;

+=C2=A0 } else {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_SUCCESS;

+=C2=A0 }

+

+=C2=A0 if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) {

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_NOT_INITIALIZED;

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 TmpGetStatus.RxFrameLen =3D 0;

+=C2=A0 TmpGetStatus.reserved=C2=A0 =C2=A0=3D 0;

+=C2=A0 Db=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =3D (PXE_DB_GET_STATUS *)(UINTN)Cdb->DBaddr;

+

+=C2=A0 if ((Cdb->DBsize > 0) && (Cdb->DBsize < sizeof = (UINT32) * 2)) {

+=C2=A0 =C2=A0 CopyMem (Db, &TmpGetStatus, Cdb->DBsize);

+=C2=A0 } else {

+=C2=A0 =C2=A0 CopyMem (Db, &TmpGetStatus, sizeof (UINT32) * 2);

+=C2=A0 }

+

+=C2=A0 if ((Cdb->OpFlags & PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS) != =3D 0) {

+=C2=A0 =C2=A0 if (Cdb->DBsize =3D=3D 0) {

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;
+=C2=A0 =C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALID_CDB;<= br>
+=C2=A0 =C2=A0 =C2=A0 return;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 NumEntries=C2=A0 =3D Cdb->DBsize - sizeof (UINT64);

+=C2=A0 =C2=A0 Cdb->DBsize =3D sizeof (UINT32) * 2;

+

+=C2=A0 =C2=A0 for (Index =3D 0; NumEntries >=3D sizeof (UINT64); Index+= +, NumEntries -=3D sizeof (UINT64)) {

+=C2=A0 =C2=A0 =C2=A0 if (Nic->TxBufferCount > 0) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 Nic->TxBufferCount--;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 Db->TxBuffer[Index] =3D Nic->MediaHeader= [Nic->TxBufferCount];

+=C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 }

+=C2=A0 }

+

+=C2=A0 if ((Cdb->OpFlags & PXE_OPFLAGS_GET_INTERRUPT_STATUS) !=3D 0= ) {

+=C2=A0 =C2=A0 if (Nic->ReceiveStatus !=3D 0) {

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags |=3D PXE_STATFLAGS_GET_STATUS_RECEI= VE;

+=C2=A0 =C2=A0 }

+=C2=A0 }

+

+=C2=A0 if ((Nic->Request.Request =3D=3D USB_CDC_NETWORK_CONNECTION) &am= p;& (Nic->Request.Value =3D=3D NETWORK_DISCONNECT)) {

+=C2=A0 =C2=A0 Nic->CableDetect =3D 0;

+=C2=A0 } else if ((Nic->Request.Request =3D=3D USB_CDC_NETWORK_CONNECTI= ON) && (Nic->Request.Value =3D=3D NETWORK_CONNECTED)) {

+=C2=A0 =C2=A0 Nic->CableDetect =3D 1;

+=C2=A0 }

+

+=C2=A0 if ((Cdb->OpFlags & PXE_OPFLAGS_GET_MEDIA_STATUS) !=3D 0) {<= br>
+=C2=A0 =C2=A0 if (Nic->CableDetect =3D=3D 0) {

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags |=3D PXE_STATFLAGS_GET_STATUS_NO_ME= DIA;

+=C2=A0 =C2=A0 }

+=C2=A0 }

+

+=C2=A0 if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetStatus !=3D NULL) {<= br>
+=C2=A0 =C2=A0 Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiGetStatus= (Cdb, Nic);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;
+=C2=A0 =C2=A0 }

+=C2=A0 }

+}

+

+/**

+=C2=A0 This command is used to fill the media header(s) in transmit packet= (s).

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+**/

+VOID

+UndiFillHeader (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 PXE_CPB_FILL_HEADER=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= *CpbFillHeader;

+=C2=A0 PXE_CPB_FILL_HEADER_FRAGMENTED=C2=A0 *CpbFill;

+=C2=A0 EthernetHeader=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 *MacHeader;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Index;

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 Status;

+

+=C2=A0 if ((Cdb->OpCode !=3D PXE_OPCODE_FILL_HEADER) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) ||
+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) ||<= br>
+=C2=A0 =C2=A0 =C2=A0 (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFc= ntExt << 8)) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->CPBsize !=3D sizeof (PXE_CPB_FILL_HEADER_FRA= GMENTED)) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED))

+=C2=A0 {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALID_CDB;

+=C2=A0 =C2=A0 return;

+=C2=A0 } else {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_SUCCESS;

+=C2=A0 }

+

+=C2=A0 if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) {

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_NOT_INITIALIZED;

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 if (Cdb->CPBsize =3D=3D PXE_CPBSIZE_NOT_USED) {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALID_CDB;

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 if ((Cdb->OpFlags & PXE_OPFLAGS_FILL_HEADER_FRAGMENTED) !=3D= 0) {

+=C2=A0 =C2=A0 CpbFill =3D (PXE_CPB_FILL_HEADER_FRAGMENTED *)(UINTN)Cdb->= ;CPBaddr;

+

+=C2=A0 =C2=A0 if ((CpbFill->FragCnt =3D=3D 0) || (CpbFill->FragDesc[= 0].FragLen < PXE_MAC_HEADER_LEN_ETHER)) {

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;
+=C2=A0 =C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALID_CDB;<= br>
+=C2=A0 =C2=A0 =C2=A0 return;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 MacHeader=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D (Ether= netHeader *)(UINTN)CpbFill->FragDesc[0].FragAddr;

+=C2=A0 =C2=A0 MacHeader->Protocol =3D CpbFill->Protocol;

+

+=C2=A0 =C2=A0 for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) = {

+=C2=A0 =C2=A0 =C2=A0 MacHeader->DestAddr[Index] =3D CpbFill->DestAdd= r[Index];

+=C2=A0 =C2=A0 =C2=A0 MacHeader->SrcAddr[Index]=C2=A0 =3D CpbFill->Sr= cAddr[Index];

+=C2=A0 =C2=A0 }

+=C2=A0 } else {

+=C2=A0 =C2=A0 CpbFillHeader =3D (PXE_CPB_FILL_HEADER *)(UINTN)Cdb->CPBa= ddr;

+

+=C2=A0 =C2=A0 MacHeader=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D (Ether= netHeader *)(UINTN)CpbFillHeader->MediaHeader;

+=C2=A0 =C2=A0 MacHeader->Protocol =3D CpbFillHeader->Protocol;

+

+=C2=A0 =C2=A0 for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) = {

+=C2=A0 =C2=A0 =C2=A0 MacHeader->DestAddr[Index] =3D CpbFillHeader->D= estAddr[Index];

+=C2=A0 =C2=A0 =C2=A0 MacHeader->SrcAddr[Index]=C2=A0 =3D CpbFillHeader-= >SrcAddr[Index];

+=C2=A0 =C2=A0 }

+=C2=A0 }

+

+=C2=A0 if (Nic->UsbEth->UsbEthUndi.UsbEthUndiFillHeader !=3D NULL) {=

+=C2=A0 =C2=A0 Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiFillHeade= r (Cdb, Nic);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;
+=C2=A0 =C2=A0 }

+=C2=A0 }

+}

+

+/**

+=C2=A0 The Transmit command is used to place a packet into the transmit qu= eue.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+**/

+VOID

+UndiTransmit (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 Status;

+

+=C2=A0 if ((Cdb->OpCode !=3D PXE_OPCODE_TRANSMIT) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) ||
+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) ||<= br>
+=C2=A0 =C2=A0 =C2=A0 (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFc= ntExt << 8)) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->CPBsize !=3D sizeof (PXE_CPB_TRANSMIT)) ||
+=C2=A0 =C2=A0 =C2=A0 (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED))

+=C2=A0 {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALID_CDB;

+=C2=A0 =C2=A0 return;

+=C2=A0 } else {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_SUCCESS;

+=C2=A0 }

+

+=C2=A0 if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_NOT_INITIALIZED;

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 if (Cdb->CPBsize =3D=3D PXE_CPBSIZE_NOT_USED) {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALID_CDB;

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 if (Nic->UsbEth->UsbEthUndi.UsbEthUndiTransmit !=3D NULL) {
+=C2=A0 =C2=A0 Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiTransmit = (Cdb, Nic);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;
+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 Cdb->StatCode =3D Transmit (Cdb, Nic, Cdb->CPBaddr, Cdb->O= pFlags);

+

+=C2=A0 if (Cdb->StatCode !=3D PXE_STATCODE_SUCCESS) {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 }

+}

+

+/**

+=C2=A0 Use USB Ethernet Protocol Bulk out command to transmit data.

+

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 Cdb=C2=A0 =C2=A0 =C2=A0 A pointer to= the command descriptor block.

+=C2=A0 @param[in, out] Nic=C2=A0 =C2=A0 =C2=A0 A pointer to the Network in= terface controller data.

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 CpbAddr=C2=A0 Command Parameter Bloc= k Address.

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 OpFlags=C2=A0 Operation Flags.

+

+**/

+UINT16

+Transmit (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN OUT=C2=A0 NIC_DATA=C2=A0 *Nic,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 UINT64=C2=A0 =C2=A0 CpbAddr,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 UINT16=C2=A0 =C2=A0 OpFlags

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 Status;

+=C2=A0 PXE_CPB_TRANSMIT=C2=A0 *Cpb;

+=C2=A0 UINT64=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 BulkOutData =3D 0;<= br>
+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0DataLength;
+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Map;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Counter =3D 0;

+=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 StatCode;

+

+=C2=A0 Cpb =3D (PXE_CPB_TRANSMIT *)(UINTN)CpbAddr;

+

+=C2=A0 if (Nic->CanTransmit) {

+=C2=A0 =C2=A0 return PXE_STATCODE_BUSY;

+=C2=A0 }

+

+=C2=A0 Nic->CanTransmit =3D TRUE;

+

+=C2=A0 if ((OpFlags & PXE_OPFLAGS_TRANSMIT_FRAGMENTED) !=3D 0) {

+=C2=A0 =C2=A0 return PXE_STATCODE_INVALID_PARAMETER;

+=C2=A0 }

+

+=C2=A0 Map =3D MapIt (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Nic,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Cpb->FrameAddr,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Cpb->DataLen + (UINT32)Cpb->Media= headerLen,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 TO_DEVICE,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (UINT64)(UINTN)&BulkOutData

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+

+=C2=A0 if (Map !=3D 0) {

+=C2=A0 =C2=A0 Nic->CanTransmit =3D FALSE;

+=C2=A0 =C2=A0 return PXE_STATCODE_INVALID_PARAMETER;

+=C2=A0 }

+

+=C2=A0 if (Nic->TxBufferCount < MAX_XMIT_BUFFERS) {

+=C2=A0 =C2=A0 Nic->MediaHeader[Nic->TxBufferCount] =3D Cpb->Frame= Addr;

+=C2=A0 =C2=A0 Nic->TxBufferCount++;

+=C2=A0 }

+

+=C2=A0 DataLength =3D (UINTN)(Cpb->DataLen + (UINT32)Cpb->Mediaheade= rLen);

+

+=C2=A0 while (1) {

+=C2=A0 =C2=A0 if (Counter >=3D 3) {

+=C2=A0 =C2=A0 =C2=A0 StatCode =3D PXE_STATCODE_BUSY;

+=C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 Status =3D Nic->UsbEth->UsbEthTransmit (Cdb, Nic->U= sbEth, (VOID *)(UINTN)BulkOutData, &DataLength);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 StatCode =3D=C2=A0 PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 if (Status =3D=3D EFI_INVALID_PARAMETER) {

+=C2=A0 =C2=A0 =C2=A0 StatCode =3D PXE_STATCODE_INVALID_PARAMETER;

+=C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 if (Status =3D=3D EFI_DEVICE_ERROR) {

+=C2=A0 =C2=A0 =C2=A0 StatCode =3D PXE_STATCODE_DEVICE_FAILURE;

+=C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 if (!EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 Nic->TxFrame++;

+=C2=A0 =C2=A0 =C2=A0 StatCode =3D PXE_STATCODE_SUCCESS;

+=C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 Counter++;

+=C2=A0 }

+

+=C2=A0 UnMapIt (

+=C2=A0 =C2=A0 Nic,

+=C2=A0 =C2=A0 Cpb->FrameAddr,

+=C2=A0 =C2=A0 Cpb->DataLen + (UINT32)Cpb->MediaheaderLen,

+=C2=A0 =C2=A0 TO_DEVICE,

+=C2=A0 =C2=A0 BulkOutData

+=C2=A0 =C2=A0 );

+

+=C2=A0 Nic->CanTransmit =3D FALSE;

+

+=C2=A0 return StatCode;

+}

+

+/**

+=C2=A0 When the network adapter has received a frame, this command is used=

+=C2=A0 to copy the frame into driver/application storage.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+**/

+VOID

+UndiReceive (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 Status;

+

+=C2=A0 if ((Cdb->OpCode !=3D PXE_OPCODE_RECEIVE) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) ||
+=C2=A0 =C2=A0 =C2=A0 (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) ||<= br>
+=C2=A0 =C2=A0 =C2=A0 (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFc= ntExt << 8)) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->CPBsize !=3D sizeof (PXE_CPB_RECEIVE)) ||
+=C2=A0 =C2=A0 =C2=A0 (Cdb->DBsize !=3D sizeof (PXE_DB_RECEIVE)) ||

+=C2=A0 =C2=A0 =C2=A0 (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED))

+=C2=A0 {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_INVALID_CDB;

+=C2=A0 =C2=A0 return;

+=C2=A0 } else {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_SUCCESS;

+=C2=A0 }

+

+=C2=A0 if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_NOT_INITIALIZED;

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 if (!Nic->CanReceive) {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 =C2=A0 Cdb->StatCode=C2=A0 =3D PXE_STATCODE_NOT_INITIALIZED;

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 if (Nic->UsbEth->UsbEthUndi.UsbEthUndiReceive !=3D NULL) {
+=C2=A0 =C2=A0 Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiReceive (= Cdb, Nic);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;
+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 Cdb->StatCode =3D Receive (Cdb, Nic, Cdb->CPBaddr, Cdb->DB= addr);

+

+=C2=A0 if (Cdb->StatCode !=3D PXE_STATCODE_SUCCESS) {

+=C2=A0 =C2=A0 Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED;

+=C2=A0 }

+}

+

+/**

+=C2=A0 Use USB Ethernet Protocol Bulk in command to receive data.

+

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 Cdb=C2=A0 =C2=A0 =C2=A0 A pointer to= the command descriptor block.

+=C2=A0 @param[in, out] Nic=C2=A0 =C2=A0 =C2=A0 A pointer to the Network in= terface controller data.

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 CpbAddr=C2=A0 Command Parameter Bloc= k Address.

+=C2=A0 @param[in, out] DbAddr=C2=A0 =C2=A0Data Block Address.

+

+**/

+UINT16

+Receive (

+=C2=A0 IN PXE_CDB=C2=A0 =C2=A0 =C2=A0 =C2=A0*Cdb,

+=C2=A0 IN OUT NIC_DATA=C2=A0 *Nic,

+=C2=A0 IN UINT64=C2=A0 =C2=A0 =C2=A0 =C2=A0 CpbAddr,

+=C2=A0 IN OUT UINT64=C2=A0 =C2=A0 DbAddr

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0Status;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Index;

+=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0StatCode=C2=A0 =3D P= XE_STATCODE_NO_DATA;

+=C2=A0 PXE_FRAME_TYPE=C2=A0 =C2=A0FrameType =3D PXE_FRAME_TYPE_NONE;

+=C2=A0 PXE_CPB_RECEIVE=C2=A0 *Cpb;

+=C2=A0 PXE_DB_RECEIVE=C2=A0 =C2=A0*Db;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *BulkInData;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 DataLength =3D (UINT= N)Nic->MaxSegmentSize;

+=C2=A0 EthernetHeader=C2=A0 =C2=A0*Header;

+

+=C2=A0 Cpb =3D (PXE_CPB_RECEIVE *)(UINTN)CpbAddr;

+=C2=A0 Db=C2=A0 =3D (PXE_DB_RECEIVE *)(UINTN)DbAddr;

+

+=C2=A0 Status =3D gBS->AllocatePool (EfiBootServicesData, DataLength, (= VOID **)&BulkInData);

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return PXE_STATCODE_INVALID_PARAMETER;

+=C2=A0 }

+

+=C2=A0 while (1) {

+=C2=A0 =C2=A0 Status =3D Nic->UsbEth->UsbEthReceive (Cdb, Nic->Us= bEth, (VOID *)BulkInData, &DataLength);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 Nic->RxFrame++;

+

+=C2=A0 =C2=A0 if (DataLength !=3D 0) {

+=C2=A0 =C2=A0 =C2=A0 if (DataLength > Cpb->BufferLen) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 DataLength =3D (UINTN)Cpb->BufferLen;

+=C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 CopyMem ((UINT8 *)(UINTN)Cpb->BufferAddr, (UINT8 *= )BulkInData, DataLength);

+

+=C2=A0 =C2=A0 =C2=A0 Header =3D (EthernetHeader *)BulkInData;

+

+=C2=A0 =C2=A0 =C2=A0 Db->FrameLen=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D (UINT32= )DataLength;

+=C2=A0 =C2=A0 =C2=A0 Db->MediaHeaderLen =3D PXE_MAC_HEADER_LEN_ETHER;
+

+=C2=A0 =C2=A0 =C2=A0 for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; In= dex++) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (Header->DestAddr[Index] !=3D Nic->Cu= rrentNodeAddress[Index]) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 if (Index >=3D PXE_HWADDR_LEN_ETHER) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 FrameType =3D PXE_FRAME_TYPE_UNICAST;

+=C2=A0 =C2=A0 =C2=A0 } else {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 for (Index =3D 0; Index < PXE_HWADDR_LEN_ET= HER; Index++) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (Header->DestAddr[Index] !=3D Nic= ->BroadcastNodeAddress[Index]) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (Index >=3D PXE_HWADDR_LEN_ETHER) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 FrameType =3D PXE_FRAME_TYPE_BROADCAST;=

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 } else {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if ((Header->DestAddr[0] & 1) = =3D=3D 1) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 FrameType =3D PXE_FRAME_TYPE_FIL= TERED_MULTICAST;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 } else {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 FrameType =3D PXE_FRAME_TYPE_PRO= MISCUOUS;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 Db->Type=C2=A0 =C2=A0 =C2=A0=3D FrameType;

+=C2=A0 =C2=A0 =C2=A0 Db->Protocol =3D Header->Protocol;

+

+=C2=A0 =C2=A0 =C2=A0 for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; In= dex++) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 Db->SrcAddr[Index]=C2=A0 =3D Header->Src= Addr[Index];

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 Db->DestAddr[Index] =3D Header->DestAddr= [Index];

+=C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 StatCode =3D PXE_STATCODE_SUCCESS;

+=C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 }

+=C2=A0 }

+

+=C2=A0 if (FrameType =3D=3D PXE_FRAME_TYPE_NONE) {

+=C2=A0 =C2=A0 Nic->ReceiveStatus =3D 0;

+=C2=A0 } else {

+=C2=A0 =C2=A0 Nic->ReceiveStatus =3D 1;

+=C2=A0 }

+

+=C2=A0 gBS->FreePool (BulkInData);

+

+=C2=A0 return StatCode;

+}

+

+/**

+=C2=A0 Fill out PXE SW UNDI structure.

+

+=C2=A0 @param[out]=C2=A0 PxeSw=C2=A0 =C2=A0 =C2=A0 A pointer to the PXE SW= UNDI structure.

+

+**/

+VOID

+PxeStructInit (

+=C2=A0 OUT PXE_SW_UNDI=C2=A0 *PxeSw

+=C2=A0 )

+{

+=C2=A0 PxeSw->Signature =3D PXE_ROMID_SIGNATURE;

+=C2=A0 PxeSw->Len=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D (UINT8)sizeof (PXE_SW_U= NDI);

+=C2=A0 PxeSw->Fudge=C2=A0 =C2=A0 =C2=A0=3D 0;

+=C2=A0 PxeSw->IFcnt=C2=A0 =C2=A0 =C2=A0=3D 0;

+=C2=A0 PxeSw->IFcntExt=C2=A0 =3D 0;

+=C2=A0 PxeSw->Rev=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D PXE_ROMID_REV;

+=C2=A0 PxeSw->MajorVer=C2=A0 =3D PXE_ROMID_MAJORVER;

+=C2=A0 PxeSw->MinorVer=C2=A0 =3D PXE_ROMID_MINORVER;

+=C2=A0 PxeSw->reserved1 =3D 0;

+

+=C2=A0 PxeSw->Implementation =3D PXE_ROMID_IMP_SW_VIRT_ADDR |

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 PXE_ROMID_IMP_FRAG_SUPPORTED |

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 PXE_ROMID_IMP_CMD_LINK_SUPPORTED |

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 PXE_ROMID_IMP_STATION_ADDR_SETTABLE |

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED |

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED |

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED |

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED;

+

+=C2=A0 PxeSw->EntryPoint=C2=A0 =C2=A0=3D (UINT64)(UINTN)UndiApiEntry;
+=C2=A0 PxeSw->reserved2[0] =3D 0;

+=C2=A0 PxeSw->reserved2[1] =3D 0;

+=C2=A0 PxeSw->reserved2[2] =3D 0;

+=C2=A0 PxeSw->BusCnt=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D 1;

+=C2=A0 PxeSw->BusType[0]=C2=A0 =C2=A0=3D PXE_BUSTYPE_USB;

+=C2=A0 PxeSw->Fudge=C2=A0 =C2=A0 =C2=A0 =C2=A0 =3D PxeSw->Fudge - Ca= lculateSum8 ((VOID *)PxeSw, PxeSw->Len);

+}

+

+/**

+=C2=A0 Update NIC number.

+

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 Nic=C2=A0 =C2=A0 =C2=A0 =C2=A0A poin= ter to the Network interface controller data.

+=C2=A0 @param[in, out] PxeSw=C2=A0 =C2=A0 =C2=A0A pointer to the PXE SW UN= DI structure.

+

+**/

+VOID

+UpdateNicNum (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 NIC_DATA=C2=A0 =C2=A0 =C2=A0*Nic,

+=C2=A0 IN OUT=C2=A0 PXE_SW_UNDI=C2=A0 *PxeSw

+=C2=A0 )

+{

+=C2=A0 UINT16=C2=A0 NicNum;

+

+=C2=A0 NicNum =3D (PxeSw->IFcnt | PxeSw->IFcntExt << 8);

+

+=C2=A0 if (Nic =3D=3D NULL) {

+=C2=A0 =C2=A0 if (NicNum > 0) {

+=C2=A0 =C2=A0 =C2=A0 NicNum--;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 PxeSw->IFcnt=C2=A0 =C2=A0 =3D (UINT8)(NicNum & 0xFF);= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 // Get lower byte

+=C2=A0 =C2=A0 PxeSw->IFcntExt =3D (UINT8)((NicNum & 0xFF00) >>= ; 8); // Get upper byte

+=C2=A0 =C2=A0 PxeSw->Fudge=C2=A0 =C2=A0 =3D (UINT8)(PxeSw->Fudge - C= alculateSum8 ((VOID *)PxeSw, PxeSw->Len));

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 NicNum++;

+

+=C2=A0 PxeSw->IFcnt=C2=A0 =C2=A0 =3D (UINT8)(NicNum & 0xFF);=C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 // Get lower byte

+=C2=A0 PxeSw->IFcntExt =3D (UINT8)((NicNum & 0xFF00) >> 8); /= / Get upper byte

+=C2=A0 PxeSw->Fudge=C2=A0 =C2=A0 =3D (UINT8)(PxeSw->Fudge - Calculat= eSum8 ((VOID *)PxeSw, PxeSw->Len));

+}

+

+/**

+=C2=A0 UNDI API table entry.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+

+**/

+VOID

+UndiApiEntry (

+=C2=A0 IN=C2=A0 UINT64=C2=A0 Cdb

+=C2=A0 )

+{

+=C2=A0 PXE_CDB=C2=A0 =C2=A0*CdbPtr;

+=C2=A0 NIC_DATA=C2=A0 *Nic;

+

+=C2=A0 if (Cdb =3D=3D 0) {

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 CdbPtr =3D (PXE_CDB *)(UINTN)Cdb;

+=C2=A0 Nic=C2=A0 =C2=A0 =3D &(gLanDeviceList[CdbPtr->IFnum]->Nic= Info);

+=C2=A0 gUndiApiTable[CdbPtr->OpCode](CdbPtr, Nic);

+}

+

+/**

+=C2=A0 Map virtual memory address for DMA. This field can be set to

+=C2=A0 zero if there is no mapping service.

+

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A poin= ter to the Network interface controller data.

+=C2=A0 @param[in]=C2=A0 MemAddr=C2=A0 =C2=A0 =C2=A0 =C2=A0Virtual address = to be mapped.

+=C2=A0 @param[in]=C2=A0 Size=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Size of mem= ory to be mapped.

+=C2=A0 @param[in]=C2=A0 Direction=C2=A0 =C2=A0 =C2=A0Direction of data flo= w for this memory's usage:

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 cpu->device, device->cpu or both ways.

+=C2=A0 @param[out] MappedAddr=C2=A0 =C2=A0 Pointer to return the mapped de= vice address.

+

+**/

+UINTN

+MapIt (

+=C2=A0 IN NIC_DATA=C2=A0 *Nic,

+=C2=A0 IN UINT64=C2=A0 =C2=A0 MemAddr,

+=C2=A0 IN UINT32=C2=A0 =C2=A0 Size,

+=C2=A0 IN UINT32=C2=A0 =C2=A0 Direction,

+=C2=A0 OUT UINT64=C2=A0 =C2=A0MappedAddr

+=C2=A0 )

+{

+=C2=A0 UINT64=C2=A0 *PhyAddr;

+

+=C2=A0 PhyAddr =3D (UINT64 *)(UINTN)MappedAddr;

+

+=C2=A0 if (Nic->PxeStart.Map_Mem =3D=3D 0) {

+=C2=A0 =C2=A0 *PhyAddr =3D MemAddr;

+=C2=A0 } else {

+=C2=A0 =C2=A0 ((void (*)(UINT64, UINT64, UINT32, UINT32, UINT64))(UINTN) N= ic->PxeStart.Map_Mem)(

+=C2=A0 Nic->PxeStart.Unique_ID,

+=C2=A0 MemAddr,

+=C2=A0 Size,

+=C2=A0 Direction,

+=C2=A0 MappedAddr

+=C2=A0 );

+=C2=A0 }

+

+=C2=A0 return PXE_STATCODE_SUCCESS;

+}

+

+/**

+=C2=A0 Un-map previously mapped virtual memory address. This field can be = set

+=C2=A0 to zero only if the Map_Mem() service is also set to zero.

+

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A poin= ter to the Network interface controller data.

+=C2=A0 @param[in]=C2=A0 MemAddr=C2=A0 =C2=A0 =C2=A0 =C2=A0Virtual address = to be mapped.

+=C2=A0 @param[in]=C2=A0 Size=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Size of mem= ory to be mapped.

+=C2=A0 @param[in]=C2=A0 Direction=C2=A0 =C2=A0 =C2=A0Direction of data flo= w for this memory's usage:

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 cpu->device, device->cpu or both ways.

+=C2=A0 @param[in]=C2=A0 MappedAddr=C2=A0 =C2=A0 Pointer to return the mapp= ed device address.

+

+**/

+VOID

+UnMapIt (

+=C2=A0 IN NIC_DATA=C2=A0 *Nic,

+=C2=A0 IN UINT64=C2=A0 =C2=A0 MemAddr,

+=C2=A0 IN UINT32=C2=A0 =C2=A0 Size,

+=C2=A0 IN UINT32=C2=A0 =C2=A0 Direction,

+=C2=A0 IN UINT64=C2=A0 =C2=A0 MappedAddr

+=C2=A0 )

+{

+=C2=A0 if (Nic->PxeStart.UnMap_Mem !=3D 0) {

+=C2=A0 =C2=A0 ((void (*)(UINT64, UINT64, UINT32, UINT32, UINT64))(UINTN) N= ic->PxeStart.UnMap_Mem)(

+=C2=A0 Nic->PxeStart.Unique_ID,

+=C2=A0 MemAddr,

+=C2=A0 Size,

+=C2=A0 Direction,

+=C2=A0 MappedAddr

+=C2=A0 );

+=C2=A0 }

+

+=C2=A0 return;

+}

diff --git a/UsbNetworkPkg/ReadMe.md b/UsbNetworkPkg/ReadMe.md
new file mode 100644
index 0000000000..6dc0514ba7
--- /dev/null
+++ b/UsbNetworkPkg/ReadMe.md
@@ -0,0 +1,65 @@
+# UsbNetworkPkg
+
+This document is intend to provide package information, include the interf= ace details.
+
+# INDEX
+=C2=A0 * [Introduction](#introduction)
+=C2=A0 * [Components](#components)
+=C2=A0 =C2=A0 * [[NetworkCommon]](#networkcommon)
+=C2=A0 =C2=A0 * [[UsbCdcEcm]](#usbcdcecm)
+=C2=A0 =C2=A0 * [[UsbCdcNcm]](#usbcdcncm)
+=C2=A0 =C2=A0 * [[UsbRndis]](#usbrndis)
+
+#=C2=A0 Introduction
+UsbNetworkPkg provides network functions for USB LAN devices.
+
+# Components
+Below module is included in this package:<br>
+- NetworkCommon
+- UsbCdcEcm
+- UsbCdcNcm
+- UsbRndis
+
+## [NetworkCommon]
+Provides a LAN driver based on UEFI specification(UNDI). It supports USB c= ommunication class subclass devices and USB Rndis devices, depending on the= UsbEthernetProtocol.
+
+## Required Components
+- NetworkPkg
+
+## [UsbCdcEcm]
+This driver provides a communication interface for USB Ethernet devices th= at follows the ECM protocol. The driver installs UsbEthernetProtocol with E= CM functions which are consumed by the NetworkCommon driver.
+
+The driver is compatible with the following USB class codes:
+|Class Code|SubClass Code|Protocol Code|
+|:--------:|:-----------:|:-----------:|
+|0x02|0x06|0x00|
+
+## Required Components
+- NetworkCommon
+- MdeModulePkg(USB bus driver)
+
+## [UsbCdcNcm]
+This driver provides a communication interface for USB Ethernet devices th= at follows the NCM protocol. The driver installs UsbEthernetProtocol with N= CM functions which are consumed by the NetworkCommon driver.
+
+The driver is compatible with the following USB class codes:
+|Class Code|SubClass Code|Protocol Code|
+|:--------:|:-----------:|:-----------:|
+|0x02|0x0D|0x00|
+
+## Required Components
+- NetworkCommon
+- MdeModulePkg(USB bus driver)
+
+## [UsbRndis]
+This driver provides a communication interface for USB Ethernet devices th= at follows the RNDIS protocol. The driver installs UsbEthernetProtocol with= RNDIS functions which are consumed by the NetworkCommon driver.
+
+The driver is compatible with the following USB class codes:
+|Class Code|SubClass Code|Protocol Code|
+|:--------:|:-----------:|:-----------:|
+|0x02|0x02|0xFF|
+|0xEF|0x04|0x01|
+
+## Required Components
+- NetworkCommon
+- MdeModulePkg(USB bus driver)
+
diff --git a/UsbNetworkPkg/ReleaseNotes.md b/UsbNetworkPkg/ReleaseNotes.md<= br> new file mode 100644
index 0000000000..03912e7788
--- /dev/null
+++ b/UsbNetworkPkg/ReleaseNotes.md
@@ -0,0 +1,11 @@
+# UsbNetworkPkg Release Notes<!-- omit in toc -->

+

+# Release History<!-- omit in toc -->

+- [1.00](#100)

+

+## 1.00

+

+**Release Date:** Mar 10, 2022

+

+**New Features**

+- UsbNetworkPkg first release.

diff --git a/UsbNetworkPkg/UsbCdcEcm/ComponentName.c b/UsbNetworkPkg/UsbCdc= Ecm/ComponentName.c
new file mode 100644
index 0000000000..39123994b2
--- /dev/null
+++ b/UsbNetworkPkg/UsbCdcEcm/ComponentName.c
@@ -0,0 +1,170 @@
+/** @file

+=C2=A0 This file contains code for USB Ecm Driver Component Name definitio= ns

+

+=C2=A0 Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+=C2=A0 Subject to AMI licensing agreement.

+**/

+#include "UsbCdcEcm.h"

+

+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE=C2=A0 gUsbEcmDriver= NameTable[] =3D {

+=C2=A0 {

+=C2=A0 =C2=A0 "eng;en",

+=C2=A0 =C2=A0 L"USB ECM Driver"

+=C2=A0 },

+=C2=A0 {

+=C2=A0 =C2=A0 NULL,

+=C2=A0 =C2=A0 NULL

+=C2=A0 }

+};

+

+EFI_STATUS

+EFIAPI

+UsbEcmComponentNameGetDriverName (

+=C2=A0 IN=C2=A0 EFI_COMPONENT_NAME_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 CHAR8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *Language,

+=C2=A0 OUT CHAR16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0**DriverName

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+UsbEcmComponentNameGetControllerName (

+=C2=A0 IN EFI_COMPONENT_NAME_PROTOCOL=C2=A0 *This,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0Controller,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0ChildHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0 OPTIONAL,

+=C2=A0 IN CHAR8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 *Language,

+=C2=A0 OUT CHAR16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 **ControllerName

+=C2=A0 );

+

+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL=C2=A0 gUsbEcmCom= ponentName =3D {

+=C2=A0 UsbEcmComponentNameGetDriverName,

+=C2=A0 UsbEcmComponentNameGetControllerName,

+=C2=A0 "eng"

+};

+

+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL=C2=A0 gUsbEcmCo= mponentName2 =3D {

+=C2=A0 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)UsbEcmComponentNameGetDriverNa= me,

+=C2=A0 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)UsbEcmComponentNameGetCont= rollerName,

+=C2=A0 "en"

+};

+

+/**

+=C2=A0 Retrieves a Unicode string that is the user readable name of the dr= iver.

+

+=C2=A0 This function retrieves the user readable name of a driver in the f= orm of a

+=C2=A0 Unicode string. If the driver specified by This has a user readable= name in

+=C2=A0 the language specified by Language, then a pointer to the driver na= me is

+=C2=A0 returned in DriverName, and EFI_SUCCESS is returned. If the driver = specified

+=C2=A0 by This does not support the language specified by Language,

+=C2=A0 then EFI_UNSUPPORTED is returned.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_COMPONENT_NAME_PROTOCOL instance= .

+=C2=A0 @param[in]=C2=A0 Language=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A point= er to a Null-terminated ASCII string

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 array indicating the language. This = is the

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 language of the driver name that the= caller is

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 requesting, and it must match one of= the

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 languages specified in SupportedLang= uages. The

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 number of languages supported by a d= river is up

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 to the driver writer. Language is sp= ecified

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 in RFC 4646 or ISO 639-2 language co= de format.

+=C2=A0 @param[out] DriverName=C2=A0 =C2=A0 =C2=A0 =C2=A0 A pointer to the = Unicode string to return.

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This Unicode string is the name of t= he

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 driver specified by This in the lang= uage

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 specified by Language.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The Uni= code string for the Driver specified by

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This and the language specified by L= anguage was

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 returned in DriverName.

+=C2=A0 @retval EFI_INVALID_PARAMETER Language is NULL.

+=C2=A0 @retval EFI_INVALID_PARAMETER DriverName is NULL.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0The driver specif= ied by This does not support

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 the language specified by Language.<= br>
+

+**/

+EFI_STATUS

+EFIAPI

+UsbEcmComponentNameGetDriverName (

+=C2=A0 IN=C2=A0 EFI_COMPONENT_NAME_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 CHAR8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *Language,

+=C2=A0 OUT CHAR16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0**DriverName

+=C2=A0 )

+{

+=C2=A0 return LookupUnicodeString2 (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Language,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->SupportedLanguages,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0gUsbEcmDriverNameTable,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0DriverName,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(BOOLEAN)(This =3D=3D &gUsbEc= mComponentName)

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+}

+

+/**

+=C2=A0 Retrieves a Unicode string that is the user readable name of the co= ntroller

+=C2=A0 that is being managed by a driver.

+

+=C2=A0 This function retrieves the user readable name of the controller sp= ecified by

+=C2=A0 ControllerHandle and ChildHandle in the form of a Unicode string. I= f the

+=C2=A0 driver specified by This has a user readable name in the language s= pecified by

+=C2=A0 Language, then a pointer to the controller name is returned in Cont= rollerName,

+=C2=A0 and EFI_SUCCESS is returned.=C2=A0 If the driver specified by This = is not currently

+=C2=A0 managing the controller specified by ControllerHandle and ChildHand= le,

+=C2=A0 then EFI_UNSUPPORTED is returned.=C2=A0 If the driver specified by = This does not

+=C2=A0 support the language specified by Language, then EFI_UNSUPPORTED is= returned.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_COMPONENT_NAME_PROTOCOL instance= .

+=C2=A0 @param[in]=C2=A0 Controller=C2=A0 =C2=A0 =C2=A0 =C2=A0 The handle o= f a controller that the driver

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 specified by This is managing.=C2=A0= This handle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 specifies the controller whose name = is to be

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 returned.

+=C2=A0 @param[in]=C2=A0 ChildHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0The handle o= f the child controller to retrieve

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 the name of.=C2=A0 This is an option= al parameter that

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 may be NULL.=C2=A0 It will be NULL f= or device

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 drivers.=C2=A0 It will also be NULL = for a bus drivers

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 that wish to retrieve the name of th= e bus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 controller.=C2=A0 It will not be NUL= L for a bus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 driver that wishes to retrieve the n= ame of a

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 child controller.

+=C2=A0 @param[in]=C2=A0 Language=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A point= er to a Null-terminated ASCII string

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 array indicating the language.=C2=A0= This is the

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 language of the driver name that the= caller is

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 requesting, and it must match one of= the

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 languages specified in SupportedLang= uages. The

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 number of languages supported by a d= river is up

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 to the driver writer. Language is sp= ecified in

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 RFC 4646 or ISO 639-2 language code = format.

+=C2=A0 @param[out] ControllerName=C2=A0 =C2=A0 A pointer to the Unicode st= ring to return.

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This Unicode string is the name of t= he

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 controller specified by ControllerHa= ndle and

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ChildHandle in the language specifie= d by

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Language from the point of view of t= he driver

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 specified by This.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The Uni= code string for the user readable name in

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 the language specified by Language f= or the

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 driver specified by This was returne= d in

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 DriverName.

+=C2=A0 @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_H= ANDLE.

+=C2=A0 @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not= a valid

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_HANDLE.

+=C2=A0 @retval EFI_INVALID_PARAMETER Language is NULL.

+=C2=A0 @retval EFI_INVALID_PARAMETER ControllerName is NULL.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0The driver specif= ied by This is not currently

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 managing the controller specified by=

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerHandle and ChildHandle.
+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0The driver specif= ied by This does not support

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 the language specified by Language.<= br>
+

+**/

+EFI_STATUS

+EFIAPI

+UsbEcmComponentNameGetControllerName (

+=C2=A0 IN EFI_COMPONENT_NAME_PROTOCOL=C2=A0 *This,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0Controller,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0ChildHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0 OPTIONAL,

+=C2=A0 IN CHAR8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 *Language,

+=C2=A0 OUT CHAR16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 **ControllerName

+=C2=A0 )

+{

+=C2=A0 return EFI_UNSUPPORTED;

+}

diff --git a/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.c b/UsbNetworkPkg/UsbCdcEcm/= UsbCdcEcm.c
new file mode 100644
index 0000000000..34f115f48d
--- /dev/null
+++ b/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.c
@@ -0,0 +1,504 @@
+/** @file

+=C2=A0 This file contains code for USB Ethernet Control Model

+=C2=A0 Driver

+

+=C2=A0 Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+=C2=A0 Subject to AMI licensing agreement.

+**/

+#include "UsbCdcEcm.h"

+

+EFI_GUID=C2=A0 gUsbEthProtocolGuid =3D USB_ETHERNET_PROTOCOL_GUID;

+

+EFI_DRIVER_BINDING_PROTOCOL=C2=A0 gUsbEcmDriverBinding =3D {

+=C2=A0 UsbEcmDriverSupported,

+=C2=A0 UsbEcmDriverStart,

+=C2=A0 UsbEcmDriverStop,

+=C2=A0 USB_ECM_DRIVER_VERSION,

+=C2=A0 NULL,

+=C2=A0 NULL

+};

+

+/**

+=C2=A0 Check if this interface is USB ECM SubType

+

+=C2=A0 @param[in]=C2=A0 UsbIo=C2=A0 =C2=A0 =C2=A0A pointer to the EFI_USB_= IO_PROTOCOL instance.

+

+=C2=A0 @retval TRUE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB ECM SubType.

+=C2=A0 @retval FALSE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Not USB ECM SubType.=

+

+**/

+BOOLEAN

+IsSupportedDevice (

+=C2=A0 IN EFI_USB_IO_PROTOCOL=C2=A0 *UsbIo

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 Status;

+=C2=A0 EFI_USB_INTERFACE_DESCRIPTOR=C2=A0 InterfaceDescriptor;

+

+=C2=A0 Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interfa= ceDescriptor);

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return FALSE;

+=C2=A0 }

+

+=C2=A0 if ((InterfaceDescriptor.InterfaceClass =3D=3D USB_CDC_CLASS) &= &

+=C2=A0 =C2=A0 =C2=A0 (InterfaceDescriptor.InterfaceSubClass =3D=3D USB_CDC= _ECM_SUBCLASS) &&

+=C2=A0 =C2=A0 =C2=A0 (InterfaceDescriptor.InterfaceProtocol =3D=3D USB_NO_= CLASS_PROTOCOL))

+=C2=A0 {

+=C2=A0 =C2=A0 return TRUE;

+=C2=A0 }

+

+=C2=A0 return FALSE;

+}

+

+/**

+=C2=A0 USB ECM Driver Binding Support.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 Protocol instance pointer.

+=C2=A0 @param[in]=C2=A0 ControllerHandle=C2=A0 =C2=A0 =C2=A0 Handle of dev= ice to test.

+=C2=A0 @param[in]=C2=A0 RemainingDevicePath=C2=A0 =C2=A0Optional parameter= use to pick a specific child

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 device to start.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0This driver supports this device.

+=C2=A0 @retval EFI_ALREADY_STARTED=C2=A0 =C2=A0 =C2=A0 =C2=A0This driver i= s already running on this device.

+=C2=A0 @retval other=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0This driver does not support this device.

+

+**/

+EFI_STATUS

+EFIAPI

+UsbEcmDriverSupported (

+=C2=A0 IN EFI_DRIVER_BINDING_PROTOCOL=C2=A0 *This,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 IN EFI_DEVICE_PATH_PROTOCOL=C2=A0 =C2=A0 =C2=A0*RemainingDevicePath=

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Status;

+=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 *UsbIo =3D NULL;

+

+=C2=A0 Status =3D gBS->OpenProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiUs= bIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOID **)&a= mp;UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This->Dr= iverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_OPEN_PR= OTOCOL_BY_DRIVER

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 Status =3D IsSupportedDevice (UsbIo) ? EFI_SUCCESS : EFI_UNSUPPORTE= D;

+

+=C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gEfiUsbIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Check if the USB ECM and USB CDC Data interfaces are from the same = device.

+

+=C2=A0 @param[in]=C2=A0 UsbEthPath=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 A pointer to the EFI_DEVICE_PATH_PROTOCOL instance= .

+=C2=A0 @param[in]=C2=A0 UsbCdcDataPath=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 A pointer to the EFI_DEVICE_PATH_PROTOCOL instance.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0Is the same device.

+=C2=A0 @retval EFI_NOT_FOUND=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0Is not the same device.

+

+**/

+EFI_STATUS

+IsSameDevice (

+=C2=A0 IN=C2=A0 EFI_DEVICE_PATH_PROTOCOL=C2=A0 *UsbEthPath,

+=C2=A0 IN=C2=A0 EFI_DEVICE_PATH_PROTOCOL=C2=A0 *UsbCdcDataPath

+=C2=A0 )

+{

+=C2=A0 while (1) {

+=C2=A0 =C2=A0 if ((UsbEthPath->Type =3D=3D ACPI_DEVICE_PATH) &&= (UsbEthPath->SubType =3D=3D ACPI_DP)) {

+=C2=A0 =C2=A0 =C2=A0 if (CompareMem ((ACPI_HID_DEVICE_PATH *)UsbCdcDataPat= h, (ACPI_HID_DEVICE_PATH *)UsbEthPath, sizeof (ACPI_HID_DEVICE_PATH))) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return EFI_NOT_FOUND;

+=C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 if ((UsbEthPath->Type =3D=3D HARDWARE_DEVICE_PATH) &&= amp; (UsbEthPath->SubType =3D=3D HW_PCI_DP)) {

+=C2=A0 =C2=A0 =C2=A0 if (CompareMem ((PCI_DEVICE_PATH *)UsbCdcDataPath, (P= CI_DEVICE_PATH *)UsbEthPath, sizeof (PCI_DEVICE_PATH))) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return EFI_NOT_FOUND;

+=C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 if ((UsbEthPath->Type =3D=3D MESSAGING_DEVICE_PATH) &= & (UsbEthPath->SubType =3D=3D MSG_USB_DP)) {

+=C2=A0 =C2=A0 =C2=A0 if (IsDevicePathEnd (NextDevicePathNode (UsbEthPath))= ) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (((USB_DEVICE_PATH *)UsbEthPath)->Parent= PortNumber =3D=3D

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ((USB_DEVICE_PATH *)UsbCdcDataPa= th)->ParentPortNumber)

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return EFI_SUCCESS;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 } else {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return EFI_NOT_FOUND;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 =C2=A0 } else {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (CompareMem ((USB_DEVICE_PATH *)UsbCdcDataP= ath, (USB_DEVICE_PATH *)UsbEthPath, sizeof (USB_DEVICE_PATH))) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return EFI_NOT_FOUND;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 UsbEthPath=C2=A0 =C2=A0 =C2=A0=3D NextDevicePathNode (UsbEth= Path);

+=C2=A0 =C2=A0 UsbCdcDataPath =3D NextDevicePathNode (UsbCdcDataPath);

+=C2=A0 }

+}

+

+/**

+=C2=A0 Check if the USB CDC Data(UsbIo) installed and return USB CDC Data = Handle.

+

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 UsbEthPath=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 A pointer to the EFI_DEVICE_PATH_PROTOCOL instance.

+=C2=A0 @param[in, out] UsbCdcDataHandle=C2=A0 =C2=A0 A pointer to the EFI_= HANDLE for USB CDC Data.

+

+=C2=A0 @retval TRUE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= USB CDC Data(UsbIo) installed.

+=C2=A0 @retval FALSE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0USB CDC Data(UsbIo) did not installed.

+

+**/

+BOOLEAN

+IsUsbCdcData (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 EFI_DEVICE_PATH_PROTOCOL=C2=A0 *UsbEthPath,<= br>
+=C2=A0 IN OUT=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 *UsbCdcDataHandle

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 Status;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0Index;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0HandleCount;

+=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 *HandleBuffer;

+=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*UsbIo;=

+=C2=A0 EFI_USB_INTERFACE_DESCRIPTOR=C2=A0 Interface;

+=C2=A0 EFI_DEVICE_PATH_PROTOCOL=C2=A0 =C2=A0 =C2=A0 *UsbCdcDataPath;

+

+=C2=A0 Status =3D gBS->LocateHandleBuffer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ByProtocol,=

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiUs= bIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NULL,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Handle= Count,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Handle= Buffer

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return FALSE;

+=C2=A0 }

+

+=C2=A0 for (Index =3D 0; Index < HandleCount; Index++) {

+=C2=A0 =C2=A0 Status =3D gBS->HandleProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Hand= leBuffer[Index],

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &= ;gEfiUsbIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOI= D **)&UsbIo

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );
+=C2=A0 =C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 =C2=A0 Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &= Interface);

+=C2=A0 =C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 =C2=A0 if ((Interface.InterfaceClass =3D=3D USB_CDC_DATA_CLASS) &am= p;&

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 (Interface.InterfaceSubClass =3D=3D USB_CDC_DA= TA_SUBCLASS) &&

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 (Interface.InterfaceProtocol =3D=3D USB_NO_CLA= SS_PROTOCOL))

+=C2=A0 =C2=A0 {

+=C2=A0 =C2=A0 =C2=A0 Status =3D gBS->HandleProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 HandleBuffer[Index],

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 &gEfiDevicePathProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 (VOID **)&UsbCdcDataPath

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 );

+=C2=A0 =C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 continue;

+=C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 Status =3D IsSameDevice (UsbEthPath, UsbCdcDataPath);=

+=C2=A0 =C2=A0 =C2=A0 if (!EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 CopyMem (UsbCdcDataHandle, &HandleBuffer[I= ndex], sizeof (EFI_HANDLE));

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 gBS->FreePool (HandleBuffer);

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return TRUE;

+=C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 }

+=C2=A0 }

+

+=C2=A0 gBS->FreePool (HandleBuffer);

+=C2=A0 return FALSE;

+}

+

+/**

+=C2=A0 Call Back Function.

+

+=C2=A0 @param[in]=C2=A0 Event=C2=A0 =C2=A0 =C2=A0 =C2=A0Event whose notifi= cation function is being invoked.

+=C2=A0 @param[in]=C2=A0 Context=C2=A0 =C2=A0 =C2=A0The pointer to the noti= fication function's context,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 which is implementation-dependent.

+

+**/

+VOID

+EFIAPI

+CallbackFunction (

+=C2=A0 IN EFI_EVENT=C2=A0 Event,

+=C2=A0 IN VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0*Context

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 Status;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0Index;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0HandleCount;

+=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 *HandleBuffer;

+=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*UsbIo;=

+=C2=A0 EFI_USB_INTERFACE_DESCRIPTOR=C2=A0 Interface;

+

+=C2=A0 Status =3D gBS->LocateHandleBuffer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ByProtocol,=

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiUs= bIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NULL,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Handle= Count,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Handle= Buffer

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 for (Index =3D 0; Index < HandleCount; Index++) {

+=C2=A0 =C2=A0 Status =3D gBS->HandleProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Hand= leBuffer[Index],

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &= ;gEfiUsbIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOI= D **)&UsbIo

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );
+=C2=A0 =C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 =C2=A0 Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &= Interface);

+=C2=A0 =C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 =C2=A0 if ((Interface.InterfaceClass =3D=3D USB_CDC_CLASS) &&am= p;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 (Interface.InterfaceSubClass =3D=3D USB_CDC_EC= M_SUBCLASS) &&

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 (Interface.InterfaceProtocol =3D=3D USB_NO_CLA= SS_PROTOCOL))

+=C2=A0 =C2=A0 {

+=C2=A0 =C2=A0 =C2=A0 gBS->ConnectController (HandleBuffer[Index], NULL,= NULL, TRUE);

+=C2=A0 =C2=A0 }

+=C2=A0 }

+

+=C2=A0 gBS->FreePool (HandleBuffer);

+=C2=A0 gBS->CloseEvent (Event);

+}

+

+/**

+=C2=A0 USB ECM Driver Binding Start.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 Protocol instance pointer.

+=C2=A0 @param[in]=C2=A0 ControllerHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0 Handle= of device to bind driver to.

+=C2=A0 @param[in]=C2=A0 RemainingDevicePath=C2=A0 =C2=A0 =C2=A0Optional pa= rameter use to pick a specific child

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 device to start= .

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0This driver is added to ControllerHandle

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 T= his driver could not be started due to a device error

+=C2=A0 @retval EFI_OUT_OF_RESOURCES=C2=A0 =C2=A0 =C2=A0 =C2=A0 The driver = could not install successfully due to a lack of resources.

+=C2=A0 @retval other=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This driver does not support this device

+

+**/

+EFI_STATUS

+EFIAPI

+UsbEcmDriverStart (

+=C2=A0 IN EFI_DRIVER_BINDING_PROTOCOL=C2=A0 *This,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 IN EFI_DEVICE_PATH_PROTOCOL=C2=A0 =C2=A0 =C2=A0*RemainingDevicePath=

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 Status;

+=C2=A0 VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 *Reg;

+=C2=A0 EFI_EVENT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0Event;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*UsbEth= Driver;

+=C2=A0 EFI_DEVICE_PATH_PROTOCOL=C2=A0 =C2=A0 =C2=A0 *UsbEthPath;

+=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 UsbCdcDataHandle;

+=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*UsbIo;=

+=C2=A0 EFI_USB_INTERFACE_DESCRIPTOR=C2=A0 Interface;

+

+=C2=A0 Status =3D gBS->OpenProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiUs= bIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOID **)&a= mp;UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This->Dr= iverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_OPEN_PR= OTOCOL_BY_DRIVER

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 Status =3D gBS->OpenProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiDe= vicePathProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOID **)&a= mp;UsbEthPath,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This->Dr= iverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_OPEN_PR= OTOCOL_GET_PROTOCOL

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gEfiUsbIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 Status =3D IsUsbCdcData (UsbEthPath, &UsbCdcDataHandle) ? EFI_S= UCCESS : EFI_UNSUPPORTED;

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gEfiUsbIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+

+=C2=A0 =C2=A0 Status =3D gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLB= ACK, CallbackFunction, NULL, &Event);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 return Status;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 Status =3D gBS->RegisterProtocolNotify (&gEfiUsbIoPro= tocolGuid, Event, &Reg);

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 UsbEthDriver =3D AllocateZeroPool (sizeof (USB_ETHERNET_DRIVER));
+=C2=A0 if (!UsbEthDriver) {

+=C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gEfiUsbIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 =C2=A0 return EFI_OUT_OF_RESOURCES;

+=C2=A0 }

+

+=C2=A0 Status =3D LoadAllDescriptor (UsbIo, &UsbEthDriver->Config);=

+=C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 GetEndpoint (UsbIo, UsbEthDriver);

+

+=C2=A0 Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interfa= ce);

+=C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 UsbEthDriver->Signature=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =3D USB_ETHERNET_SIGNATUR= E;

+=C2=A0 UsbEthDriver->NumOfInterface=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D Interface.InterfaceNumber;

+=C2=A0 UsbEthDriver->UsbCdcDataHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D UsbCdcDataHandle;

+=C2=A0 UsbEthDriver->UsbIo=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =3D UsbIo;

+=C2=A0 UsbEthDriver->UsbEth.UsbEthReceive=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D UsbEthReceive;

+=C2=A0 UsbEthDriver->UsbEth.UsbEthTransmit=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =3D UsbEthTransmit;

+=C2=A0 UsbEthDriver->UsbEth.UsbEthInterrupt=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0=3D UsbEthInterrupt;

+=C2=A0 UsbEthDriver->UsbEth.UsbEthMacAddress=C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =3D GetUsbEthMacAddress;

+=C2=A0 UsbEthDriver->UsbEth.UsbEthMaxBulkSize=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0=3D UsbEthBulkSize;

+=C2=A0 UsbEthDriver->UsbEth.UsbHeaderFunDescriptor=C2=A0 =C2=A0 =C2=A0 = =3D GetUsbHeaderFunDescriptor;

+=C2=A0 UsbEthDriver->UsbEth.UsbUnionFunDescriptor=C2=A0 =C2=A0 =C2=A0 = =C2=A0=3D GetUsbUnionFunDescriptor;

+=C2=A0 UsbEthDriver->UsbEth.UsbEthFunDescriptor=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0=3D GetUsbEthFunDescriptor;

+=C2=A0 UsbEthDriver->UsbEth.SetUsbEthMcastFilter=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =3D SetUsbEthMcastFilter;

+=C2=A0 UsbEthDriver->UsbEth.SetUsbEthPowerPatternFilter =3D SetUsbEthPo= werFilter;

+=C2=A0 UsbEthDriver->UsbEth.GetUsbEthPoewrPatternFilter =3D GetUsbEthPo= werFilter;

+=C2=A0 UsbEthDriver->UsbEth.SetUsbEthPacketFilter=C2=A0 =C2=A0 =C2=A0 = =C2=A0=3D SetUsbEthPacketFilter;

+=C2=A0 UsbEthDriver->UsbEth.GetUsbEthStatistic=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =3D GetUsbEthStatistic;

+

+=C2=A0 Status =3D gBS->InstallProtocolInterface (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Contro= llerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gUsbEt= hProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_NATIVE_= INTERFACE,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &(UsbEt= hDriver->UsbEth)

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gEfiUsbIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 =C2=A0 gBS->FreePool (UsbEthDriver);

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 USB ECM Driver Binding Stop.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 Protocol instance pointer.

+=C2=A0 @param[in]=C2=A0 ControllerHandle=C2=A0 =C2=A0 Handle of device to = stop driver on

+=C2=A0 @param[in]=C2=A0 NumberOfChildren=C2=A0 =C2=A0 Number of Handles in= ChildHandleBuffer. If number of

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 children is zero stop the ent= ire bus driver.

+=C2=A0 @param[in]=C2=A0 ChildHandleBuffer=C2=A0 =C2=A0List of Child Handle= s to Stop.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= This driver is removed ControllerHandle

+=C2=A0 @retval other=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0This driver was not removed from this device

+

+**/

+EFI_STATUS

+EFIAPI

+UsbEcmDriverStop (

+=C2=A0 IN=C2=A0 EFI_DRIVER_BINDING_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 IN=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NumberOfChildren,

+=C2=A0 IN=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0*ChildHandleBuffer

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Status;
+=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *UsbEthProtocol;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 =C2=A0 *UsbEthDriver;

+

+=C2=A0 Status =3D gBS->OpenProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gUsbEt= hProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOID **)&a= mp;UsbEthProtocol,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This->Dr= iverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_OPEN_PR= OTOCOL_GET_PROTOCOL

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (UsbEthProtocol);

+

+=C2=A0 Status =3D gBS->UninstallProtocolInterface (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gUsbEt= hProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthProto= col

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 Status =3D gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiUs= bIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This->Dr= iverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 gBS->FreePool (UsbEthDriver->Config);

+=C2=A0 gBS->FreePool (UsbEthDriver);

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Entrypoint of ECM Driver.

+

+=C2=A0 This function is the entrypoint of ECM Driver. It installs Driver B= inding

+=C2=A0 Protocols together with Component Name Protocols.

+

+=C2=A0 @param[in]=C2=A0 ImageHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0The firmware= allocated handle for the EFI image.

+=C2=A0 @param[in]=C2=A0 SystemTable=C2=A0 =C2=A0 =C2=A0 =C2=A0A pointer to= the EFI System Table.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The ent= ry point is executed successfully.

+

+**/

+EFI_STATUS

+EFIAPI

+UsbEcmEntry (

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 ImageHandle,

+=C2=A0 IN EFI_SYSTEM_TABLE=C2=A0 *SystemTable

+=C2=A0 )

+{

+=C2=A0 gUsbEcmDriverBinding.DriverBindingHandle =3D ImageHandle;

+=C2=A0 gUsbEcmDriverBinding.ImageHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =3D ImageHandle;

+

+=C2=A0 return gBS->InstallMultipleProtocolInterfaces (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gUsbEcmDriver= Binding.DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiDriverBin= dingProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gUsbEcmDriver= Binding,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiComponent= Name2ProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gUsbEcmCompon= entName2,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NULL

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+}

diff --git a/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.h b/UsbNetworkPkg/UsbCdcEcm/= UsbCdcEcm.h
new file mode 100644
index 0000000000..52a818466e
--- /dev/null
+++ b/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.h
@@ -0,0 +1,211 @@
+/** @file

+=C2=A0 Header file contains code for USB Ethernet Control Model

+=C2=A0 driver definitions

+

+=C2=A0 Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+=C2=A0 Subject to AMI licensing agreement.

+**/

+

+#ifndef _USB_CDC_ECM_H_

+#define _USB_CDC_ECM_H_

+

+#include <Library/UefiDriverEntryPoint.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <Library/UefiLib.h>

+#include <Library/DevicePathLib.h>

+#include <Library/DebugLib.h>

+#include <Library/MemoryAllocationLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/UefiUsbLib.h>

+#include <Protocol/UsbIo.h>

+#include <Protocol/UsbEthernetProtocol.h>

+

+typedef struct {

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 Signature;

+=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEth;

+=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0UsbCdcDataHandle;

+=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbIo;

+=C2=A0 EFI_USB_CONFIG_DESCRIPTOR=C2=A0 =C2=A0 *Config;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 NumOfInterface;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 BulkInEndpoint;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 BulkOutEndpoint;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 InterruptEndpoint;

+=C2=A0 EFI_MAC_ADDRESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Mac= Address;

+} USB_ETHERNET_DRIVER;

+

+#define USB_ECM_DRIVER_VERSION=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A01

+#define USB_ETHERNET_BULK_TIMEOUT=C2=A0 =C2=A0 =C2=A0 1

+#define USB_ETHERNET_TRANSFER_TIMEOUT=C2=A0 200

+

+#define USB_ETHERNET_SIGNATURE=C2=A0 SIGNATURE_32('u', 'e'= , 't', 'h')

+#define USB_ETHERNET_DEV_FROM_THIS(a)=C2=A0 CR (a, USB_ETHERNET_DRIVER, Us= bEth, USB_ETHERNET_SIGNATURE)

+

+typedef struct {

+=C2=A0 UINT16=C2=A0 =C2=A0 Src;

+=C2=A0 UINT16=C2=A0 =C2=A0 Dst;

+} BIT_MAP;

+

+extern EFI_COMPONENT_NAME2_PROTOCOL=C2=A0 gUsbEcmComponentName2;

+

+EFI_STATUS

+EFIAPI

+UsbEcmDriverSupported (

+=C2=A0 IN EFI_DRIVER_BINDING_PROTOCOL=C2=A0 *This,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 IN EFI_DEVICE_PATH_PROTOCOL=C2=A0 =C2=A0 =C2=A0*RemainingDevicePath=

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+UsbEcmDriverStart (

+=C2=A0 IN EFI_DRIVER_BINDING_PROTOCOL=C2=A0 *This,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 IN EFI_DEVICE_PATH_PROTOCOL=C2=A0 =C2=A0 =C2=A0*RemainingDevicePath=

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+UsbEcmDriverStop (

+=C2=A0 IN=C2=A0 EFI_DRIVER_BINDING_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 IN=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NumberOfChildren,

+=C2=A0 IN=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0*ChildHandleBuffer

+=C2=A0 );

+

+EFI_STATUS

+LoadAllDescriptor (

+=C2=A0 IN=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbIo,

+=C2=A0 OUT EFI_USB_CONFIG_DESCRIPTOR=C2=A0 **ConfigDesc

+=C2=A0 );

+

+BOOLEAN

+NextDescriptor (

+=C2=A0 IN EFI_USB_CONFIG_DESCRIPTOR=C2=A0 *Desc,

+=C2=A0 IN OUT UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 *Offset

+=C2=A0 );

+

+EFI_STATUS

+GetFunctionalDescriptor (

+=C2=A0 IN=C2=A0 EFI_USB_CONFIG_DESCRIPTOR=C2=A0 *Config,

+=C2=A0 IN=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 FunDescriptorType,

+=C2=A0 OUT VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0*DataBuffer

+=C2=A0 );

+

+VOID

+GetEndpoint (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 *UsbIo,

+=C2=A0 IN OUT=C2=A0 USB_ETHERNET_DRIVER=C2=A0 *UsbEthDriver

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+UsbEthReceive (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0PXE_CDB=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 *Cdb,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN OUT VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0*Packet,

+=C2=A0 IN OUT UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 *PacketLength

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+UsbEthTransmit (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 PXE_CDB=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 *Cdb,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*Packet,

+=C2=A0 IN OUT=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 *PacketLength

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+UsbEthInterrupt (

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0*This,

+=C2=A0 IN BOOLEAN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0IsNewTransfer,

+=C2=A0 IN UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0PollingInterval,

+=C2=A0 IN EFI_USB_DEVICE_REQUEST=C2=A0 *Request

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+InterruptCallback (

+=C2=A0 IN=C2=A0 VOID=C2=A0 =C2=A0 *Data,

+=C2=A0 IN=C2=A0 UINTN=C2=A0 =C2=A0DataLength,

+=C2=A0 IN=C2=A0 VOID=C2=A0 =C2=A0 *Context,

+=C2=A0 IN=C2=A0 UINT32=C2=A0 Status

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+GetUsbEthMacAddress (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 OUT EFI_MAC_ADDRESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 *MacAddress

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+UsbEthBulkSize (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 OUT UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 *BulkSize

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+GetUsbHeaderFunDescriptor (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0 *This,

+=C2=A0 OUT USB_HEADER_FUN_DESCRIPTOR=C2=A0 *UsbHeaderFunDescriptor

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+GetUsbUnionFunDescriptor (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0*This,

+=C2=A0 OUT USB_UNION_FUN_DESCRIPTOR=C2=A0 *UsbUnionFunDescriptor

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+GetUsbEthFunDescriptor (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 *This,
+=C2=A0 OUT USB_ETHERNET_FUN_DESCRIPTOR=C2=A0 *UsbEthFunDescriptor

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+SetUsbEthMcastFilter (

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Value,

+=C2=A0 IN VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0*McastAddr

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+SetUsbEthPowerFilter (

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Value,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Length,

+=C2=A0 IN VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0*PatternFilter

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+GetUsbEthPowerFilter (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0Value,

+=C2=A0 OUT BOOLEAN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = *PatternActive

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+SetUsbEthPacketFilter (

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Value

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+GetUsbEthStatistic (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0FeatureSelector,

+=C2=A0 OUT VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0*Statistic

+=C2=A0 );

+

+#endif

diff --git a/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf b/UsbNetworkPkg/UsbCdcEc= m/UsbCdcEcm.inf
new file mode 100644
index 0000000000..ed031864c6
--- /dev/null
+++ b/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf
@@ -0,0 +1,41 @@
+## @file
+#=C2=A0 =C2=A0This is Usb Cdc Ecm driver for DXE phase.
+#
+# Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
+# Subject to AMI licensing agreement.
+##
+
+[Defines]
+=C2=A0 INF_VERSION=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =3D 0x00010005
+=C2=A0 BASE_NAME=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =3D UsbCdcEcm
+=C2=A0 FILE_GUID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =3D 07a84945-685d-48ec-a6a1-1b397579fa76
+=C2=A0 MODULE_TYPE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =3D DXE_DRIVER
+=C2=A0 VERSION_STRING=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0=3D 1.0
+=C2=A0 ENTRY_POINT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =3D UsbEcmEntry
+
+[Sources]
+=C2=A0 UsbCdcEcm.c
+=C2=A0 UsbCdcEcm.h
+=C2=A0 UsbEcmFunction.c
+=C2=A0 ComponentName.c
+
+[Packages]
+=C2=A0 MdePkg/MdePkg.dec
+=C2=A0 UsbNetworkPkg/UsbNetworkPkg.dec
+
+[LibraryClasses]
+=C2=A0 UefiDriverEntryPoint
+=C2=A0 UefiBootServicesTableLib
+=C2=A0 UefiLib
+=C2=A0 DebugLib
+=C2=A0 UefiUsbLib
+=C2=A0 MemoryAllocationLib
+=C2=A0 BaseMemoryLib
+
+[Protocols]
+=C2=A0 gEfiUsbIoProtocolGuid
+=C2=A0 gEfiDevicePathProtocolGuid
+=C2=A0 gEfiDriverBindingProtocolGuid
+
+[Depex]
+=C2=A0 TRUE
diff --git a/UsbNetworkPkg/UsbCdcEcm/UsbEcmFunction.c b/UsbNetworkPkg/UsbCd= cEcm/UsbEcmFunction.c
new file mode 100644
index 0000000000..175addddc6
--- /dev/null
+++ b/UsbNetworkPkg/UsbCdcEcm/UsbEcmFunction.c
@@ -0,0 +1,861 @@
+/** @file

+=C2=A0 This file contains code for USB Ethernet descriptor

+=C2=A0 and specific requests implement.

+

+=C2=A0 Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+=C2=A0 Subject to AMI licensing agreement.

+**/

+

+#include "UsbCdcEcm.h"

+

+/**

+=C2=A0 Load All of device descriptor.

+

+=C2=A0 @param[in]=C2=A0 UsbIo=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0A pointer to the EFI_USB_IO_PROTOCOL instance.

+=C2=A0 @param[out] ConfigDesc=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A p= ointer to the configuration descriptor.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_OUT_OF_RESOURCES=C2=A0 The request could not be complet= ed because the

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 buffer specified by DescriptorLength= and Descriptor

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 is not large enough to hold the resu= lt of the request.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error. The transfer

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 status is returned in Status.

+

+**/

+EFI_STATUS

+LoadAllDescriptor (

+=C2=A0 IN=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbIo,

+=C2=A0 OUT EFI_USB_CONFIG_DESCRIPTOR=C2=A0 **ConfigDesc

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Status;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0TransStatus;

+=C2=A0 EFI_USB_CONFIG_DESCRIPTOR=C2=A0 Tmp;

+

+=C2=A0 Status =3D UsbIo->UsbGetConfigDescriptor (UsbIo, &Tmp);

+=C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 Status =3D gBS->AllocatePool (EfiBootServicesData, Tmp.TotalLeng= th, (VOID **)ConfigDesc);

+=C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 Status =3D UsbGetDescriptor (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0USB_DESC_TYPE_CONFIG <&= lt; 8 | (Tmp.ConfigurationValue - 1),=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0// zero based

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Tmp.TotalLength,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*ConfigDesc,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&TransStatus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Returns pointer to the next descriptor for the pack of USB descript= ors

+=C2=A0 located in continues memory segment

+

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 Desc=C2=A0 =C2=A0A pointer to the CO= NFIG_DESCRIPTOR instance.

+=C2=A0 @param[in, out] Offset A pointer to the sum of descriptor length.
+

+=C2=A0 @retval TRUE=C2=A0 =C2=A0The request executed successfully.

+=C2=A0 @retval FALSE=C2=A0 No next descriptor.

+

+**/

+BOOLEAN

+NextDescriptor (

+=C2=A0 IN EFI_USB_CONFIG_DESCRIPTOR=C2=A0 *Desc,

+=C2=A0 IN OUT UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 *Offset

+=C2=A0 )

+{

+=C2=A0 if ((Desc =3D=3D NULL) || (*Offset >=3D Desc->TotalLength)) {=

+=C2=A0 =C2=A0 return FALSE;

+=C2=A0 }

+

+=C2=A0 if (((EFI_USB_CONFIG_DESCRIPTOR *)((char *)Desc+*Offset))->Lengt= h =3D=3D 0) {

+=C2=A0 =C2=A0 return FALSE;

+=C2=A0 }

+

+=C2=A0 *Offset +=3D ((EFI_USB_CONFIG_DESCRIPTOR *)((char *)Desc+*Offset))-= >Length;

+=C2=A0 if ( *Offset >=3D Desc->TotalLength ) {

+=C2=A0 =C2=A0 return FALSE;

+=C2=A0 }

+

+=C2=A0 return TRUE;

+}

+

+/**

+=C2=A0 Read Function descriptor

+

+=C2=A0 @param[in]=C2=A0 Config=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0A pointer to all of configuration.

+=C2=A0 @param[in]=C2=A0 FunDescriptorType=C2=A0 USB CDC class descriptor S= ubType.

+=C2=A0 @param[out] DataBuffer=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A pointer t= o the Data of corresponding to device capability.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 The device capabilit= y descriptor was retrieved

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0successfully.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 No supported.

+=C2=A0 @retval EFI_NOT_FOUND=C2=A0 =C2=A0 =C2=A0 The device capability des= criptor was not found.

+

+**/

+EFI_STATUS

+GetFunctionalDescriptor (

+=C2=A0 IN=C2=A0 EFI_USB_CONFIG_DESCRIPTOR=C2=A0 *Config,

+=C2=A0 IN=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 FunDescriptorType,

+=C2=A0 OUT VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0*DataBuffer

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 Status =3D EFI_NOT_FOUND;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0Offset;

+=C2=A0 EFI_USB_INTERFACE_DESCRIPTOR=C2=A0 *Interface;

+

+=C2=A0 for (Offset =3D 0; NextDescriptor (Config, &Offset);) {

+=C2=A0 =C2=A0 Interface =3D (EFI_USB_INTERFACE_DESCRIPTOR *)((UINT8 *)Conf= ig + Offset);

+=C2=A0 =C2=A0 if (Interface->DescriptorType =3D=3D CS_INTERFACE) {

+=C2=A0 =C2=A0 =C2=A0 if (((USB_HEADER_FUN_DESCRIPTOR *)Interface)->Desc= riptorSubtype =3D=3D FunDescriptorType) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 switch (FunDescriptorType) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 case HEADER_FUN_DESCRIPTOR:

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 CopyMem (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 DataBuffer,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (USB_HEADER_FUN_DESCRIPTO= R *)Interface,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 sizeof (USB_HEADER_FUN_DE= SCRIPTOR)

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return EFI_SUCCESS;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 case UNION_FUN_DESCRIPTOR:

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 CopyMem (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 DataBuffer,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (USB_UNION_FUN_DESCRIPTOR= *)Interface,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ((USB_UNION_FUN_DESCRIPTO= R *)Interface)->FunctionLength

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return EFI_SUCCESS;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 case ETHERNET_FUN_DESCRIPTOR:

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 CopyMem (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 DataBuffer,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (USB_ETHERNET_FUN_DESCRIP= TOR *)Interface,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 sizeof (USB_ETHERNET_FUN_= DESCRIPTOR)

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return EFI_SUCCESS;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 default:

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Status =3D EFI_UNSUPPORTED;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 }

+=C2=A0 }

+

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Get USB Ethernet IO endpoint and USB CDC data IO endpoint.

+

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 UsbIo=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0A pointer to the EFI_USB_IO_PROTOCOL instance.

+=C2=A0 @param[in, out] UsbEthDriver=C2=A0 A pointer to the USB_ETHERNET_DR= IVER instance.

+

+**/

+VOID

+GetEndpoint (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 *UsbIo,

+=C2=A0 IN OUT=C2=A0 USB_ETHERNET_DRIVER=C2=A0 *UsbEthDriver

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 Status;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0Index;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 Result;

+=C2=A0 EFI_USB_INTERFACE_DESCRIPTOR=C2=A0 Interface;

+=C2=A0 EFI_USB_ENDPOINT_DESCRIPTOR=C2=A0 =C2=A0Endpoint;

+

+=C2=A0 Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interfa= ce);

+=C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 if (Interface.NumEndpoints =3D=3D 0) {

+=C2=A0 =C2=A0 Status =3D UsbSetInterface (UsbIo, Interface.InterfaceNumber= , 1, &Result);

+=C2=A0 =C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 =C2=A0 Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &= Interface);

+=C2=A0 =C2=A0 ASSERT_EFI_ERROR (Status);

+=C2=A0 }

+

+=C2=A0 for (Index =3D 0; Index < Interface.NumEndpoints; Index++) {

+=C2=A0 =C2=A0 Status =3D UsbIo->UsbGetEndpointDescriptor (UsbIo, Index,= &Endpoint);

+=C2=A0 =C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 =C2=A0 switch ((Endpoint.Attributes & (BIT0 | BIT1))) {

+=C2=A0 =C2=A0 =C2=A0 case USB_ENDPOINT_BULK:

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (Endpoint.EndpointAddress & BIT7) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDriver->BulkInEndpoint =3D End= point.EndpointAddress;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 } else {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDriver->BulkOutEndpoint =3D En= dpoint.EndpointAddress;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 =C2=A0 case USB_ENDPOINT_INTERRUPT:

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDriver->InterruptEndpoint =3D Endpoin= t.EndpointAddress;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 }

+=C2=A0 }

+}

+

+/**

+=C2=A0 This function is used to manage a USB device with the bulk transfer= pipe. The endpoint is Bulk in.

+

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 Cdb=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0A pointer to the command descriptor block.

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 A pointer to the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[in, out] Packet=C2=A0 =C2=A0 =C2=A0 =C2=A0 A pointer to the = buffer of data that will be transmitted to USB

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 device or received from USB device.<= br>
+=C2=A0 @param[in, out] PacketLength=C2=A0 A pointer to the PacketLength.
+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The bul= k transfer has been successfully executed.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The transfer failed. T= he transfer status is returned in status.

+=C2=A0 @retval EFI_INVALID_PARAMETE=C2=A0 One or more parameters are inval= id.

+=C2=A0 @retval EFI_OUT_OF_RESOURCES=C2=A0 The request could not be submitt= ed due to a lack of resources.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The con= trol transfer fails due to timeout.

+

+**/

+EFI_STATUS

+EFIAPI

+UsbEthReceive (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0PXE_CDB=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 *Cdb,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN OUT VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0*Packet,

+=C2=A0 IN OUT UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 *PacketLength

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Status;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 *UsbEthDriver;

+=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 *UsbIo;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0TransS= tatus;

+

+=C2=A0 UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This);

+

+=C2=A0 Status =3D gBS->HandleProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDrive= r->UsbCdcDataHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiUs= bIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOID **)&a= mp;UsbIo

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 if (UsbEthDriver->BulkInEndpoint =3D=3D 0) {

+=C2=A0 =C2=A0 GetEndpoint (UsbIo, UsbEthDriver);

+=C2=A0 }

+

+=C2=A0 Status =3D UsbIo->UsbBulkTransfer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbI= o,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbE= thDriver->BulkInEndpoint,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Pack= et,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Pack= etLength,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB_= ETHERNET_BULK_TIMEOUT,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &= ;TransStatus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );
+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 This function is used to manage a USB device with the bulk transfer= pipe. The endpoint is Bulk out.

+

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 Cdb=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0A pointer to the command descriptor block.

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 A pointer to the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 Packet=C2=A0 =C2=A0 =C2=A0 =C2=A0 A = pointer to the buffer of data that will be transmitted to USB

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 device or received from USB device.<= br>
+=C2=A0 @param[in, out] PacketLength=C2=A0 A pointer to the PacketLength.
+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The bul= k transfer has been successfully executed.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The transfer failed. T= he transfer status is returned in status.

+=C2=A0 @retval EFI_INVALID_PARAMETE=C2=A0 One or more parameters are inval= id.

+=C2=A0 @retval EFI_OUT_OF_RESOURCES=C2=A0 The request could not be submitt= ed due to a lack of resources.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The con= trol transfer fails due to timeout.

+

+**/

+EFI_STATUS

+EFIAPI

+UsbEthTransmit (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 PXE_CDB=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 *Cdb,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*Packet,

+=C2=A0 IN OUT=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 *PacketLength

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Status;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 *UsbEthDriver;

+=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 *UsbIo;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0TransS= tatus;

+

+=C2=A0 UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This);

+

+=C2=A0 Status =3D gBS->HandleProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDrive= r->UsbCdcDataHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiUs= bIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOID **)&a= mp;UsbIo

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 if (UsbEthDriver->BulkOutEndpoint =3D=3D 0) {

+=C2=A0 =C2=A0 GetEndpoint (UsbIo, UsbEthDriver);

+=C2=A0 }

+

+=C2=A0 Status =3D UsbIo->UsbBulkTransfer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbI= o,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbE= thDriver->BulkOutEndpoint,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Pack= et,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Pack= etLength,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB_= ETHERNET_BULK_TIMEOUT,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &= ;TransStatus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );
+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Async USB transfer callback routine.

+

+=C2=A0 @param[in]=C2=A0 Data=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Data= received or sent via the USB Asynchronous Transfer, if the

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 transfer completed successfully.

+=C2=A0 @param[in]=C2=A0 DataLength=C2=A0 =C2=A0 =C2=A0 The length of Data = received or sent via the Asynchronous

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Transfer, if transfer successfully complete= s.

+=C2=A0 @param[in]=C2=A0 Context=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Data pass= ed from UsbAsyncInterruptTransfer() request.

+=C2=A0 @param[in]=C2=A0 Status=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Indicates= the result of the asynchronous transfer.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The asy= nchronous USB transfer request has been successfully executed.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The asynchronous USB t= ransfer request failed.

+

+**/

+EFI_STATUS

+EFIAPI

+InterruptCallback (

+=C2=A0 IN=C2=A0 VOID=C2=A0 =C2=A0 *Data,

+=C2=A0 IN=C2=A0 UINTN=C2=A0 =C2=A0DataLength,

+=C2=A0 IN=C2=A0 VOID=C2=A0 =C2=A0 *Context,

+=C2=A0 IN=C2=A0 UINT32=C2=A0 Status

+=C2=A0 )

+{

+=C2=A0 if (((EFI_USB_DEVICE_REQUEST *)Data)->Request =3D=3D USB_CDC_NET= WORK_CONNECTION) {

+=C2=A0 =C2=A0 CopyMem (

+=C2=A0 =C2=A0 =C2=A0 (EFI_USB_DEVICE_REQUEST *)Context,

+=C2=A0 =C2=A0 =C2=A0 (EFI_USB_DEVICE_REQUEST *)Data,

+=C2=A0 =C2=A0 =C2=A0 sizeof (EFI_USB_DEVICE_REQUEST)

+=C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 }

+

+=C2=A0 return EFI_SUCCESS;

+}

+

+/**

+=C2=A0 This function is used to manage a USB device with an interrupt tran= sfer pipe.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 A pointer to the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[in]=C2=A0 IsNewTransfer=C2=A0 =C2=A0 =C2=A0If TRUE, a new tr= ansfer will be submitted to USB controller. If

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 FALSE, the interrupt transfer is del= eted from the device's interrupt

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 transfer queue.

+=C2=A0 @param[in]=C2=A0 PollingInterval=C2=A0 =C2=A0Indicates the periodic= rate, in milliseconds, that the transfer is to be

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 executed.This parameter is required = when IsNewTransfer is TRUE. The

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 value must be between 1 to 255, othe= rwise EFI_INVALID_PARAMETER is returned.

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 The units are in milliseconds.

+=C2=A0 @param[in]=C2=A0 Request=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A = pointer to the EFI_USB_DEVICE_REQUEST data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The asy= nchronous USB transfer request transfer has been successfully executed.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The asynchronous USB t= ransfer request failed.

+

+**/

+EFI_STATUS

+EFIAPI

+UsbEthInterrupt (

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0*This,

+=C2=A0 IN BOOLEAN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0IsNewTransfer,

+=C2=A0 IN UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0PollingInterval,

+=C2=A0 IN EFI_USB_DEVICE_REQUEST=C2=A0 *Request

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Status;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 *UsbEthDriver;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 DataLe= ngth =3D 0;

+

+=C2=A0 UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This);

+=C2=A0 if (IsNewTransfer =3D=3D TRUE) {

+=C2=A0 =C2=A0 DataLength =3D sizeof (EFI_USB_DEVICE_REQUEST) + sizeof (USB= _CONNECT_SPEED_CHANGE);

+=C2=A0 =C2=A0 Status=C2=A0 =C2=A0 =C2=A0=3D UsbEthDriver->UsbIo->Usb= AsyncInterruptTransfer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDr= iver->UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDr= iver->InterruptEndpoint,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 IsNewTra= nsfer,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 PollingI= nterval,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 DataLeng= th,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (EFI_ASY= NC_USB_TRANSFER_CALLBACK)InterruptCallback,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Request<= br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 } else {

+=C2=A0 =C2=A0 Status =3D UsbEthDriver->UsbIo->UsbAsyncInterruptTrans= fer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDriver->UsbIo= ,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDriver->Inter= ruptEndpoint,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 IsNewTransfer,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NULL,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NULL

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 }

+

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Retrieves the USB Ethernet Mac Address.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A pointer t= o the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[out] MacAddress=C2=A0 =C2=A0 A pointer to the caller allocat= ed USB Ethernet Mac Address.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB= Header Functional descriptor was retrieved successfully.

+=C2=A0 @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL.

+=C2=A0 @retval EFI_NOT_FOUND=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB Head= er Functional descriptor was not found.

+

+**/

+EFI_STATUS

+EFIAPI

+GetUsbEthMacAddress (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 OUT EFI_MAC_ADDRESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 *MacAddress

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0Status;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbEthDriver= ;

+=C2=A0 USB_ETHERNET_FUN_DESCRIPTOR=C2=A0 UsbEthDescriptor;

+=C2=A0 CHAR16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0*Data;

+=C2=A0 CHAR16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0*DataPtr;

+=C2=A0 CHAR16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0TmpStr[1];

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 Index;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 Hi;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 Low;

+

+=C2=A0 UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This);

+

+=C2=A0 Status =3D This->UsbEthFunDescriptor (This, &UsbEthDescripto= r);

+=C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 Status =3D UsbEthDriver->UsbIo->UsbGetStringDescriptor (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDriver->UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x409,=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 // English-U= S Language ID

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDescriptor.MacAddress,<= br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Data

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 DataPtr =3D Data;

+=C2=A0 for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {

+=C2=A0 =C2=A0 CopyMem (TmpStr, DataPtr, sizeof (CHAR16));

+=C2=A0 =C2=A0 DataPtr++;

+=C2=A0 =C2=A0 Hi =3D (UINT8)StrHexToUintn (TmpStr);

+=C2=A0 =C2=A0 CopyMem (TmpStr, DataPtr, sizeof (CHAR16));

+=C2=A0 =C2=A0 DataPtr++;

+=C2=A0 =C2=A0 Low=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0=3D (UINT8)StrHexToUintn (TmpStr);

+=C2=A0 =C2=A0 MacAddress->Addr[Index] =3D (Hi << 4) | Low;

+=C2=A0 }

+

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Retrieves the USB Ethernet Bulk transfer data size.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A pointer t= o the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[out] BulkSize=C2=A0 =C2=A0 =C2=A0 A pointer to the Bulk tran= sfer data size.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0The bulk transfer dat= a size was retrieved successfully.

+=C2=A0 @retval other=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Failed= to retrieve the bulk transfer data size.

+

+**/

+EFI_STATUS

+EFIAPI

+UsbEthBulkSize (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 OUT UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 *BulkSize

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0Status;

+=C2=A0 USB_ETHERNET_FUN_DESCRIPTOR=C2=A0 UsbEthFunDescriptor;

+

+=C2=A0 Status =3D This->UsbEthFunDescriptor (This, &UsbEthFunDescri= ptor);

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 *BulkSize =3D (UINTN)UsbEthFunDescriptor.MaxSegmentSize;

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Retrieves the USB Header functional Descriptor.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0A pointer to the USB_ETHERNET_PROTOCOL instance.
+=C2=A0 @param[out] UsbHeaderFunDescriptor A pointer to the caller allocate= d USB Header Functional Descriptor.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB= Header Functional descriptor was retrieved successfully.

+=C2=A0 @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL.

+=C2=A0 @retval EFI_NOT_FOUND=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB Head= er Functional descriptor was not found.

+

+**/

+EFI_STATUS

+EFIAPI

+GetUsbHeaderFunDescriptor (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0 *This,

+=C2=A0 OUT USB_HEADER_FUN_DESCRIPTOR=C2=A0 *UsbHeaderFunDescriptor

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Status;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 *UsbEthDriver;

+

+=C2=A0 UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This);

+

+=C2=A0 if (UsbHeaderFunDescriptor =3D=3D NULL) {

+=C2=A0 =C2=A0 return EFI_INVALID_PARAMETER;

+=C2=A0 }

+

+=C2=A0 Status =3D GetFunctionalDescriptor (UsbEthDriver->Config, HEADER= _FUN_DESCRIPTOR, UsbHeaderFunDescriptor);

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Retrieves the USB Union functional Descriptor.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0A pointer to the USB_ETHERNET_PROTOCOL instance.
+=C2=A0 @param[out] UsbUnionFunDescriptor=C2=A0 A pointer to the caller all= ocated USB Union Functional Descriptor.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB= Union Functional descriptor was retrieved successfully.

+=C2=A0 @retval EFI_INVALID_PARAMETER UsbUnionFunDescriptor is NULL.

+=C2=A0 @retval EFI_NOT_FOUND=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB Unio= n Functional descriptor was not found.

+

+**/

+EFI_STATUS

+EFIAPI

+GetUsbUnionFunDescriptor (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0*This,

+=C2=A0 OUT USB_UNION_FUN_DESCRIPTOR=C2=A0 *UsbUnionFunDescriptor

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Status;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 *UsbEthDriver;

+

+=C2=A0 UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This);

+

+=C2=A0 if (UsbUnionFunDescriptor =3D=3D NULL) {

+=C2=A0 =C2=A0 return EFI_INVALID_PARAMETER;

+=C2=A0 }

+

+=C2=A0 Status =3D GetFunctionalDescriptor (UsbEthDriver->Config, UNION_= FUN_DESCRIPTOR, UsbUnionFunDescriptor);

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Retrieves the USB Ethernet functional Descriptor.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0A pointer to the USB_ETHERNET_PROTOCOL instance.
+=C2=A0 @param[out] UsbEthFunDescriptor=C2=A0 =C2=A0 A pointer to the calle= r allocated USB Ethernet Functional Descriptor.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB= Ethernet Functional descriptor was retrieved successfully.

+=C2=A0 @retval EFI_INVALID_PARAMETER UsbEthFunDescriptor is NULL.

+=C2=A0 @retval EFI_NOT_FOUND=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB Ethe= rnet Functional descriptor was not found.

+

+**/

+EFI_STATUS

+EFIAPI

+GetUsbEthFunDescriptor (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 *This,
+=C2=A0 OUT USB_ETHERNET_FUN_DESCRIPTOR=C2=A0 *UsbEthFunDescriptor

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Status;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 *UsbEthDriver;

+

+=C2=A0 UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This);

+

+=C2=A0 if (UsbEthFunDescriptor =3D=3D NULL) {

+=C2=A0 =C2=A0 return EFI_INVALID_PARAMETER;

+=C2=A0 }

+

+=C2=A0 Status =3D GetFunctionalDescriptor (UsbEthDriver->Config, ETHERN= ET_FUN_DESCRIPTOR, UsbEthFunDescriptor);

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 This request sets the Ethernet device multicast filters as specifie= d in the

+=C2=A0 sequential list of 48 bit Ethernet multicast addresses.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0A pointer to the USB_ETHERNET_PROTOCOL instance.
+=C2=A0 @param[in]=C2=A0 Value=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 Number of filters.

+=C2=A0 @param[in]=C2=A0 McastAddr=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 A pointer to the value of the multicast addresses.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+

+**/

+EFI_STATUS

+EFIAPI

+SetUsbEthMcastFilter (

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Value,

+=C2=A0 IN VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0*McastAddr

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0Status;

+=C2=A0 EFI_USB_DEVICE_REQUEST=C2=A0 =C2=A0 =C2=A0 =C2=A0Request;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0TransStatus;

+=C2=A0 USB_ETHERNET_FUN_DESCRIPTOR=C2=A0 UsbEthFunDescriptor;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbEthDriver= ;

+

+=C2=A0 UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This);

+

+=C2=A0 Status =3D This->UsbEthFunDescriptor (This, &UsbEthFunDescri= ptor);

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 if ((UsbEthFunDescriptor.NumberMcFilters << 1) =3D=3D 0) {
+=C2=A0 =C2=A0 return EFI_UNSUPPORTED;

+=C2=A0 }

+

+=C2=A0 Request.RequestType =3D USB_ETHRTNET_SET_REQ_TYPE;

+=C2=A0 Request.Request=C2=A0 =C2=A0 =C2=A0=3D SET_ETH_MULTICAST_FILTERS_RE= Q;

+=C2=A0 Request.Value=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D Value;

+=C2=A0 Request.Index=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D UsbEthDriver->NumOfI= nterface;

+=C2=A0 Request.Length=C2=A0 =C2=A0 =C2=A0 =3D Value * 6;

+

+=C2=A0 return UsbEthDriver->UsbIo->UsbControlTransfer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDriver->UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Request,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EfiUsbDataOut,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB_ETHERNET_TRANSFER_TIMEOUT,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 McastAddr,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Request.Length,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &TransStatus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+}

+

+/**

+=C2=A0 This request sets up the specified Ethernet power management patter= n filter as

+=C2=A0 described in the data structure.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 A pointer to the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[in]=C2=A0 Value=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0Number of filters.

+=C2=A0 @param[in]=C2=A0 Length=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 Size of the power management pattern filter data.

+=C2=A0 @param[in]=C2=A0 PatternFilter=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A p= ointer to the power management pattern filter structure.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+

+**/

+EFI_STATUS

+EFIAPI

+SetUsbEthPowerFilter (

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Value,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Length,

+=C2=A0 IN VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0*PatternFilter

+=C2=A0 )

+{

+=C2=A0 EFI_USB_DEVICE_REQUEST=C2=A0 Request;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 TransStatus;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 =C2=A0 =C2=A0*UsbEthDriver;

+

+=C2=A0 UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This);

+

+=C2=A0 Request.RequestType =3D USB_ETHRTNET_SET_REQ_TYPE;

+=C2=A0 Request.Request=C2=A0 =C2=A0 =C2=A0=3D SET_ETH_POWER_MANAGEMENT_PAT= TERN_FILTER_REQ;

+=C2=A0 Request.Value=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D Value;

+=C2=A0 Request.Index=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D UsbEthDriver->NumOfI= nterface;

+=C2=A0 Request.Length=C2=A0 =C2=A0 =C2=A0 =3D Length;

+

+=C2=A0 return UsbEthDriver->UsbIo->UsbControlTransfer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDriver->UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Request,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EfiUsbDataOut,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB_ETHERNET_TRANSFER_TIMEOUT,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 PatternFilter,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Length,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &TransStatus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+}

+

+/**

+=C2=A0 This request retrieves the status of the specified Ethernet power m= anagement

+=C2=A0 pattern filter from the device.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0A pointer to the USB_ETHERNET_PROTOCOL instance.
+=C2=A0 @param[in]=C2=A0 Value=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 The filter number.

+=C2=A0 @param[out] PatternActive=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A point= er to the pattern active boolean.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+

+**/

+EFI_STATUS

+EFIAPI

+GetUsbEthPowerFilter (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0Value,

+=C2=A0 OUT BOOLEAN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = *PatternActive

+=C2=A0 )

+{

+=C2=A0 EFI_USB_DEVICE_REQUEST=C2=A0 Request;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 TransStatus;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 =C2=A0 =C2=A0*UsbEthDriver;

+

+=C2=A0 UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This);

+

+=C2=A0 Request.RequestType =3D USB_ETHERNET_GET_REQ_TYPE;

+=C2=A0 Request.Request=C2=A0 =C2=A0 =C2=A0=3D GET_ETH_POWER_MANAGEMENT_PAT= TERN_FILTER_REQ;

+=C2=A0 Request.Value=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D Value;

+=C2=A0 Request.Index=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D UsbEthDriver->NumOfI= nterface;

+=C2=A0 Request.Length=C2=A0 =C2=A0 =C2=A0 =3D USB_ETH_POWER_FILTER_LENGTH;=

+

+=C2=A0 return UsbEthDriver->UsbIo->UsbControlTransfer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDriver->UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Request,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EfiUsbDataIn,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB_ETHERNET_TRANSFER_TIMEOUT,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 PatternActive,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB_ETH_POWER_FILTER_LENGTH,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &TransStatus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+}

+

+BIT_MAP=C2=A0 gTable[] =3D {

+=C2=A0 { PXE_OPFLAGS_RECEIVE_FILTER_UNICAST,=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 USB_ETH_PACKET_TYPE_DIRECTED=C2=A0 =C2=A0 =C2=A0 },

+=C2=A0 { PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST,=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 USB_ETH_PACKET_TYPE_BROADCAST=C2=A0 =C2=A0 =C2=A0},

+=C2=A0 { PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST, USB_ETH_PACKET_TYP= E_MULTICAST=C2=A0 =C2=A0 =C2=A0},

+=C2=A0 { PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS,=C2=A0 =C2=A0 =C2=A0 =C2= =A0 USB_ETH_PACKET_TYPE_PROMISCUOUS=C2=A0 =C2=A0},

+=C2=A0 { PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST,=C2=A0 =C2=A0 =C2=A0 USB= _ETH_PACKET_TYPE_ALL_MULTICAST },

+};

+

+/**

+=C2=A0 Convert value between PXE receive filter and USB ETH packet filter.=

+

+=C2=A0 @param[in]=C2=A0 Value=C2=A0 =C2=A0 =C2=A0 PXE filter data.

+=C2=A0 @param[out] CdcFilter=C2=A0 A pointer to the Ethernet Packet Filter= Bitmap value converted by PXE_OPFLAGS.

+

+**/

+VOID

+ConvertFilter (

+=C2=A0 IN=C2=A0 UINT16=C2=A0 Value,

+=C2=A0 OUT UINT16=C2=A0 *CdcFilter

+=C2=A0 )

+{

+=C2=A0 UINT32=C2=A0 Index;

+=C2=A0 UINT32=C2=A0 Count;

+

+=C2=A0 Count =3D sizeof (gTable)/sizeof (gTable[0]);

+

+=C2=A0 for (Index =3D 0; (gTable[Index].Src !=3D 0) && (Index <= Count); Index++) {

+=C2=A0 =C2=A0 if (gTable[Index].Src & Value) {

+=C2=A0 =C2=A0 =C2=A0 *CdcFilter |=3D gTable[Index].Dst;

+=C2=A0 =C2=A0 }

+=C2=A0 }

+}

+

+/**

+=C2=A0 This request is used to configure device Ethernet packet filter set= tings.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 A pointer to the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[in]=C2=A0 Value=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0Packet Filter Bitmap.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+

+**/

+EFI_STATUS

+EFIAPI

+SetUsbEthPacketFilter (

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Value

+=C2=A0 )

+{

+=C2=A0 EFI_USB_DEVICE_REQUEST=C2=A0 Request;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 TransStatus;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 =C2=A0 =C2=A0*UsbEthDriver;

+=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 CommandFilter =3D 0;

+

+=C2=A0 UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This);

+

+=C2=A0 ConvertFilter (Value, &CommandFilter);

+

+=C2=A0 Request.RequestType =3D USB_ETHRTNET_SET_REQ_TYPE;

+=C2=A0 Request.Request=C2=A0 =C2=A0 =C2=A0=3D SET_ETH_PACKET_FILTER_REQ;
+=C2=A0 Request.Value=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D CommandFilter;

+=C2=A0 Request.Index=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D UsbEthDriver->NumOfI= nterface;

+=C2=A0 Request.Length=C2=A0 =C2=A0 =C2=A0 =3D USB_ETH_PACKET_FILTER_LENGTH= ;

+

+=C2=A0 return UsbEthDriver->UsbIo->UsbControlTransfer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDriver->UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Request,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EfiUsbNoData,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB_ETHERNET_TRANSFER_TIMEOUT,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NULL,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB_ETH_PACKET_FILTER_LENGTH,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &TransStatus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+}

+

+/**

+=C2=A0 This request is used to retrieve a statistic based on the feature s= elector.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 A pointer to the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[in]=C2=A0 FeatureSelector=C2=A0 =C2=A0 =C2=A0 =C2=A0Value of= the feature selector.

+=C2=A0 @param[out] Statistic=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0A pointer to the 32 bit unsigned integer.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+

+**/

+EFI_STATUS

+EFIAPI

+GetUsbEthStatistic (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0FeatureSelector,

+=C2=A0 OUT VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0*Statistic

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0Status;

+=C2=A0 EFI_USB_DEVICE_REQUEST=C2=A0 =C2=A0 =C2=A0 =C2=A0Request;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0TransStatus;

+=C2=A0 USB_ETHERNET_FUN_DESCRIPTOR=C2=A0 UsbEthFunDescriptor;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbEthDriver= ;

+

+=C2=A0 UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This);

+

+=C2=A0 Status =3D This->UsbEthFunDescriptor (This, &UsbEthFunDescri= ptor);

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 if (UsbEthFunDescriptor.EthernetStatistics =3D=3D 0) {

+=C2=A0 =C2=A0 return EFI_UNSUPPORTED;

+=C2=A0 }

+

+=C2=A0 Request.RequestType =3D USB_ETHERNET_GET_REQ_TYPE;

+=C2=A0 Request.Request=C2=A0 =C2=A0 =C2=A0=3D GET_ETH_STATISTIC_REQ;

+=C2=A0 Request.Value=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D FeatureSelector;

+=C2=A0 Request.Index=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D UsbEthDriver->NumOfI= nterface;

+=C2=A0 Request.Length=C2=A0 =C2=A0 =C2=A0 =3D USB_ETH_STATISTIC;

+

+=C2=A0 return UsbEthDriver->UsbIo->UsbControlTransfer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDriver->UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Request,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EfiUsbDataIn,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB_ETHERNET_TRANSFER_TIMEOUT,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Statistic,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB_ETH_STATISTIC,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &TransStatus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+}

diff --git a/UsbNetworkPkg/UsbCdcNcm/ComponentName.c b/UsbNetworkPkg/UsbCdc= Ncm/ComponentName.c
new file mode 100644
index 0000000000..36792b89c5
--- /dev/null
+++ b/UsbNetworkPkg/UsbCdcNcm/ComponentName.c
@@ -0,0 +1,170 @@
+/** @file

+=C2=A0 This file contains code for USB Ncm Driver Component Name definitio= ns

+

+=C2=A0 Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+=C2=A0 Subject to AMI licensing agreement.

+**/

+#include "UsbCdcNcm.h"

+

+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE=C2=A0 gUsbNcmDriver= NameTable[] =3D {

+=C2=A0 {

+=C2=A0 =C2=A0 "eng;en",

+=C2=A0 =C2=A0 L"USB NCM Driver"

+=C2=A0 },

+=C2=A0 {

+=C2=A0 =C2=A0 NULL,

+=C2=A0 =C2=A0 NULL

+=C2=A0 }

+};

+

+EFI_STATUS

+EFIAPI

+UsbNcmComponentNameGetDriverName (

+=C2=A0 IN=C2=A0 EFI_COMPONENT_NAME_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 CHAR8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *Language,

+=C2=A0 OUT CHAR16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0**DriverName

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+UsbNcmComponentNameGetControllerName (

+=C2=A0 IN EFI_COMPONENT_NAME_PROTOCOL=C2=A0 *This,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0Controller,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0ChildHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0 OPTIONAL,

+=C2=A0 IN CHAR8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 *Language,

+=C2=A0 OUT CHAR16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 **ControllerName

+=C2=A0 );

+

+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL=C2=A0 gUsbNcmCom= ponentName =3D {

+=C2=A0 UsbNcmComponentNameGetDriverName,

+=C2=A0 UsbNcmComponentNameGetControllerName,

+=C2=A0 "eng"

+};

+

+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL=C2=A0 gUsbNcmCo= mponentName2 =3D {

+=C2=A0 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)UsbNcmComponentNameGetDriverNa= me,

+=C2=A0 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)UsbNcmComponentNameGetCont= rollerName,

+=C2=A0 "en"

+};

+

+/**

+=C2=A0 Retrieves a Unicode string that is the user readable name of the dr= iver.

+

+=C2=A0 This function retrieves the user readable name of a driver in the f= orm of a

+=C2=A0 Unicode string. If the driver specified by This has a user readable= name in

+=C2=A0 the language specified by Language, then a pointer to the driver na= me is

+=C2=A0 returned in DriverName, and EFI_SUCCESS is returned. If the driver = specified

+=C2=A0 by This does not support the language specified by Language,

+=C2=A0 then EFI_UNSUPPORTED is returned.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_COMPONENT_NAME_PROTOCOL instance= .

+=C2=A0 @param[in]=C2=A0 Language=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A point= er to a Null-terminated ASCII string

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 array indicating the language. This = is the

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 language of the driver name that the= caller is

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 requesting, and it must match one of= the

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 languages specified in SupportedLang= uages. The

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 number of languages supported by a d= river is up

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 to the driver writer. Language is sp= ecified

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 in RFC 4646 or ISO 639-2 language co= de format.

+=C2=A0 @param[out] DriverName=C2=A0 =C2=A0 =C2=A0 =C2=A0 A pointer to the = Unicode string to return.

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This Unicode string is the name of t= he

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 driver specified by This in the lang= uage

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 specified by Language.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The Uni= code string for the Driver specified by

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This and the language specified by L= anguage was

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 returned in DriverName.

+=C2=A0 @retval EFI_INVALID_PARAMETER Language is NULL.

+=C2=A0 @retval EFI_INVALID_PARAMETER DriverName is NULL.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0The driver specif= ied by This does not support

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 the language specified by Language.<= br>
+

+**/

+EFI_STATUS

+EFIAPI

+UsbNcmComponentNameGetDriverName (

+=C2=A0 IN=C2=A0 EFI_COMPONENT_NAME_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 CHAR8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *Language,

+=C2=A0 OUT CHAR16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0**DriverName

+=C2=A0 )

+{

+=C2=A0 return LookupUnicodeString2 (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Language,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->SupportedLanguages,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0gUsbNcmDriverNameTable,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0DriverName,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(BOOLEAN)(This =3D=3D &gUsbNc= mComponentName)

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+}

+

+/**

+=C2=A0 Retrieves a Unicode string that is the user readable name of the co= ntroller

+=C2=A0 that is being managed by a driver.

+

+=C2=A0 This function retrieves the user readable name of the controller sp= ecified by

+=C2=A0 ControllerHandle and ChildHandle in the form of a Unicode string. I= f the

+=C2=A0 driver specified by This has a user readable name in the language s= pecified by

+=C2=A0 Language, then a pointer to the controller name is returned in Cont= rollerName,

+=C2=A0 and EFI_SUCCESS is returned.=C2=A0 If the driver specified by This = is not currently

+=C2=A0 managing the controller specified by ControllerHandle and ChildHand= le,

+=C2=A0 then EFI_UNSUPPORTED is returned.=C2=A0 If the driver specified by = This does not

+=C2=A0 support the language specified by Language, then EFI_UNSUPPORTED is= returned.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_COMPONENT_NAME_PROTOCOL instance= .

+=C2=A0 @param[in]=C2=A0 Controller=C2=A0 =C2=A0 =C2=A0 =C2=A0 The handle o= f a controller that the driver

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 specified by This is managing.=C2=A0= This handle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 specifies the controller whose name = is to be

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 returned.

+=C2=A0 @param[in]=C2=A0 ChildHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0The handle o= f the child controller to retrieve

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 the name of.=C2=A0 This is an option= al parameter that

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 may be NULL.=C2=A0 It will be NULL f= or device

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 drivers.=C2=A0 It will also be NULL = for a bus drivers

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 that wish to retrieve the name of th= e bus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 controller.=C2=A0 It will not be NUL= L for a bus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 driver that wishes to retrieve the n= ame of a

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 child controller.

+=C2=A0 @param[in]=C2=A0 Language=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A point= er to a Null-terminated ASCII string

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 array indicating the language.=C2=A0= This is the

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 language of the driver name that the= caller is

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 requesting, and it must match one of= the

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 languages specified in SupportedLang= uages. The

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 number of languages supported by a d= river is up

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 to the driver writer. Language is sp= ecified in

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 RFC 4646 or ISO 639-2 language code = format.

+=C2=A0 @param[out] ControllerName=C2=A0 =C2=A0 A pointer to the Unicode st= ring to return.

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This Unicode string is the name of t= he

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 controller specified by ControllerHa= ndle and

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ChildHandle in the language specifie= d by

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Language from the point of view of t= he driver

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 specified by This.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The Uni= code string for the user readable name in

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 the language specified by Language f= or the

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 driver specified by This was returne= d in

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 DriverName.

+=C2=A0 @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_H= ANDLE.

+=C2=A0 @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not= a valid

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_HANDLE.

+=C2=A0 @retval EFI_INVALID_PARAMETER Language is NULL.

+=C2=A0 @retval EFI_INVALID_PARAMETER ControllerName is NULL.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0The driver specif= ied by This is not currently

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 managing the controller specified by=

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerHandle and ChildHandle.
+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0The driver specif= ied by This does not support

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 the language specified by Language.<= br>
+

+**/

+EFI_STATUS

+EFIAPI

+UsbNcmComponentNameGetControllerName (

+=C2=A0 IN EFI_COMPONENT_NAME_PROTOCOL=C2=A0 *This,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0Controller,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0ChildHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0 OPTIONAL,

+=C2=A0 IN CHAR8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 *Language,

+=C2=A0 OUT CHAR16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 **ControllerName

+=C2=A0 )

+{

+=C2=A0 return EFI_UNSUPPORTED;

+}

diff --git a/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.c b/UsbNetworkPkg/UsbCdcNcm/= UsbCdcNcm.c
new file mode 100644
index 0000000000..fc7cbd8132
--- /dev/null
+++ b/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.c
@@ -0,0 +1,508 @@
+/** @file

+=C2=A0 This file contains code for USB Network Control Model

+=C2=A0 binding driver

+

+=C2=A0 Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+=C2=A0 Subject to AMI licensing agreement.

+**/

+

+#include "UsbCdcNcm.h"

+

+EFI_GUID=C2=A0 gUsbEthProtocolGuid =3D USB_ETHERNET_PROTOCOL_GUID;

+

+EFI_DRIVER_BINDING_PROTOCOL=C2=A0 gUsbNcmDriverBinding =3D {

+=C2=A0 UsbNcmDriverSupported,

+=C2=A0 UsbNcmDriverStart,

+=C2=A0 UsbNcmDriverStop,

+=C2=A0 USB_NCM_DRIVER_VERSION,

+=C2=A0 NULL,

+=C2=A0 NULL

+};

+

+/**

+=C2=A0 Check if this interface is USB NCM SubType

+

+=C2=A0 @param[in]=C2=A0 UsbIo=C2=A0 =C2=A0A pointer to the EFI_USB_IO_PROT= OCOL instance.

+

+=C2=A0 @retval TRUE=C2=A0 =C2=A0 =C2=A0 =C2=A0 USB NCM SubType.

+=C2=A0 @retval FALSE=C2=A0 =C2=A0 =C2=A0 =C2=A0Not USB NCM SubType.

+

+**/

+BOOLEAN

+IsSupportedDevice (

+=C2=A0 IN EFI_USB_IO_PROTOCOL=C2=A0 *UsbIo

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 Status;

+=C2=A0 EFI_USB_INTERFACE_DESCRIPTOR=C2=A0 InterfaceDescriptor;

+

+=C2=A0 Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interfa= ceDescriptor);

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return FALSE;

+=C2=A0 }

+

+=C2=A0 if ((InterfaceDescriptor.InterfaceClass =3D=3D USB_CDC_CLASS) &= &

+=C2=A0 =C2=A0 =C2=A0 (InterfaceDescriptor.InterfaceSubClass =3D=3D USB_CDC= _NCM_SUBCLASS) &&

+=C2=A0 =C2=A0 =C2=A0 (InterfaceDescriptor.InterfaceProtocol =3D=3D USB_NO_= CLASS_PROTOCOL))

+=C2=A0 {

+=C2=A0 =C2=A0 return TRUE;

+=C2=A0 }

+

+=C2=A0 return FALSE;

+}

+

+/**

+=C2=A0 USB NCM Driver Binding Support.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 Protocol instance pointer.

+=C2=A0 @param[in]=C2=A0 ControllerHandle=C2=A0 =C2=A0 =C2=A0 Handle of dev= ice to test.

+=C2=A0 @param[in]=C2=A0 RemainingDevicePath=C2=A0 =C2=A0Optional parameter= use to pick a specific child

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 device to start.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0This driver supports this device.

+=C2=A0 @retval EFI_ALREADY_STARTED=C2=A0 =C2=A0 =C2=A0 =C2=A0This driver i= s already running on this device.

+=C2=A0 @retval other=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0This driver does not support this device.

+

+**/

+EFI_STATUS

+EFIAPI

+UsbNcmDriverSupported (

+=C2=A0 IN EFI_DRIVER_BINDING_PROTOCOL=C2=A0 *This,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 IN EFI_DEVICE_PATH_PROTOCOL=C2=A0 =C2=A0 =C2=A0*RemainingDevicePath=

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Status;

+=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 *UsbIo =3D NULL;

+

+=C2=A0 Status =3D gBS->OpenProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiUs= bIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOID **)&a= mp;UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This->Dr= iverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_OPEN_PR= OTOCOL_BY_DRIVER

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 Status =3D IsSupportedDevice (UsbIo) ? EFI_SUCCESS : EFI_UNSUPPORTE= D;

+

+=C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gEfiUsbIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Check if the USB NCM and USB CDC Data interfaces are from the same = device.

+

+=C2=A0 @param[in]=C2=A0 UsbEthPath=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 A pointer to the EFI_DEVICE_PATH_PROTOCOL instance= .

+=C2=A0 @param[in]=C2=A0 UsbCdcDataPath=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 A pointer to the EFI_DEVICE_PATH_PROTOCOL instance.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0Is the same device.

+=C2=A0 @retval EFI_NOT_FOUND=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0Is not the same device.

+

+**/

+EFI_STATUS

+IsSameDevice (

+=C2=A0 IN=C2=A0 EFI_DEVICE_PATH_PROTOCOL=C2=A0 *UsbEthPath,

+=C2=A0 IN=C2=A0 EFI_DEVICE_PATH_PROTOCOL=C2=A0 *UsbCdcDataPath

+=C2=A0 )

+{

+=C2=A0 while (1) {

+=C2=A0 =C2=A0 if ((UsbEthPath->Type =3D=3D ACPI_DEVICE_PATH) &&= (UsbEthPath->SubType =3D=3D ACPI_DP)) {

+=C2=A0 =C2=A0 =C2=A0 if (CompareMem ((ACPI_HID_DEVICE_PATH *)UsbCdcDataPat= h, (ACPI_HID_DEVICE_PATH *)UsbEthPath, sizeof (ACPI_HID_DEVICE_PATH))) {
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return EFI_NOT_FOUND;

+=C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 if ((UsbEthPath->Type =3D=3D HARDWARE_DEVICE_PATH) &&= amp; (UsbEthPath->SubType =3D=3D HW_PCI_DP)) {

+=C2=A0 =C2=A0 =C2=A0 if (CompareMem ((PCI_DEVICE_PATH *)UsbCdcDataPath, (P= CI_DEVICE_PATH *)UsbEthPath, sizeof (PCI_DEVICE_PATH))) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return EFI_NOT_FOUND;

+=C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 if ((UsbEthPath->Type =3D=3D MESSAGING_DEVICE_PATH) &= & (UsbEthPath->SubType =3D=3D MSG_USB_DP)) {

+=C2=A0 =C2=A0 =C2=A0 if (IsDevicePathEnd (NextDevicePathNode (UsbEthPath))= ) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (((USB_DEVICE_PATH *)UsbEthPath)->Parent= PortNumber =3D=3D

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ((USB_DEVICE_PATH *)UsbCdcDataPa= th)->ParentPortNumber)

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return EFI_SUCCESS;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 } else {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return EFI_NOT_FOUND;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 =C2=A0 } else {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (CompareMem ((USB_DEVICE_PATH *)UsbCdcDataP= ath, (USB_DEVICE_PATH *)UsbEthPath, sizeof (USB_DEVICE_PATH))) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return EFI_NOT_FOUND;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 UsbEthPath=C2=A0 =C2=A0 =C2=A0=3D NextDevicePathNode (UsbEth= Path);

+=C2=A0 =C2=A0 UsbCdcDataPath =3D NextDevicePathNode (UsbCdcDataPath);

+=C2=A0 }

+}

+

+/**

+=C2=A0 Check if the USB CDC Data(UsbIo) installed and return USB CDC Data = Handle.

+

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 UsbEthPath=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 A pointer to the EFI_DEVICE_PATH_PROTOCOL instance.

+=C2=A0 @param[in, out] UsbCdcDataHandle=C2=A0 =C2=A0 A pointer to the EFI_= HANDLE for USB CDC Data.

+

+=C2=A0 @retval TRUE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= USB CDC Data(UsbIo) installed.

+=C2=A0 @retval FALSE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0USB CDC Data(UsbIo) did not installed.

+

+**/

+BOOLEAN

+IsUsbCdcData (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 EFI_DEVICE_PATH_PROTOCOL=C2=A0 *UsbEthPath,<= br>
+=C2=A0 IN OUT=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 *UsbCdcDataHandle

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 Status;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0Index;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0HandleCount;

+=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 *HandleBuffer;

+=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*UsbIo;=

+=C2=A0 EFI_USB_INTERFACE_DESCRIPTOR=C2=A0 Interface;

+=C2=A0 EFI_DEVICE_PATH_PROTOCOL=C2=A0 =C2=A0 =C2=A0 *UsbCdcDataPath;

+

+=C2=A0 Status =3D gBS->LocateHandleBuffer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ByProtocol,=

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiUs= bIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NULL,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Handle= Count,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Handle= Buffer

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return FALSE;

+=C2=A0 }

+

+=C2=A0 for (Index =3D 0; Index < HandleCount; Index++) {

+=C2=A0 =C2=A0 Status =3D gBS->HandleProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Hand= leBuffer[Index],

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &= ;gEfiUsbIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOI= D **)&UsbIo

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );
+=C2=A0 =C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 =C2=A0 Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &= Interface);

+=C2=A0 =C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 =C2=A0 if ((Interface.InterfaceClass =3D=3D USB_CDC_DATA_CLASS) &am= p;&

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 (Interface.InterfaceSubClass =3D=3D USB_CDC_DA= TA_SUBCLASS) &&

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 (Interface.InterfaceProtocol =3D=3D USB_NCM_NT= B_PROTOCOL))

+=C2=A0 =C2=A0 {

+=C2=A0 =C2=A0 =C2=A0 Status =3D gBS->HandleProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 HandleBuffer[Index],

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 &gEfiDevicePathProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 (VOID **)&UsbCdcDataPath

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 );

+=C2=A0 =C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 continue;

+=C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 Status =3D IsSameDevice (UsbEthPath, UsbCdcDataPath);=

+=C2=A0 =C2=A0 =C2=A0 if (!EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 CopyMem (UsbCdcDataHandle, &HandleBuffer[I= ndex], sizeof (EFI_HANDLE));

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 gBS->FreePool (HandleBuffer);

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return TRUE;

+=C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 }

+=C2=A0 }

+

+=C2=A0 gBS->FreePool (HandleBuffer);

+=C2=A0 return FALSE;

+}

+

+/**

+=C2=A0 Call Back Function.

+

+=C2=A0 @param[in]=C2=A0 Event=C2=A0 =C2=A0 =C2=A0 =C2=A0Event whose notifi= cation function is being invoked.

+=C2=A0 @param[in]=C2=A0 Context=C2=A0 =C2=A0 =C2=A0The pointer to the noti= fication function's context,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 which is implementation-dependent.

+

+**/

+VOID

+EFIAPI

+CallbackFunction (

+=C2=A0 IN EFI_EVENT=C2=A0 Event,

+=C2=A0 IN VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0*Context

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 Status;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0Index;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0HandleCount;

+=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 *HandleBuffer;

+=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*UsbIo;=

+=C2=A0 EFI_USB_INTERFACE_DESCRIPTOR=C2=A0 Interface;

+

+=C2=A0 Status =3D gBS->LocateHandleBuffer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ByProtocol,=

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiUs= bIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NULL,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Handle= Count,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Handle= Buffer

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 for (Index =3D 0; Index < HandleCount; Index++) {

+=C2=A0 =C2=A0 Status =3D gBS->HandleProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Hand= leBuffer[Index],

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &= ;gEfiUsbIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOI= D **)&UsbIo

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );
+=C2=A0 =C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 =C2=A0 Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &= Interface);

+=C2=A0 =C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 =C2=A0 if ((Interface.InterfaceClass =3D=3D USB_CDC_CLASS) &&am= p;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 (Interface.InterfaceSubClass =3D=3D USB_CDC_NC= M_SUBCLASS) &&

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 (Interface.InterfaceProtocol =3D=3D USB_NO_CLA= SS_PROTOCOL))

+=C2=A0 =C2=A0 {

+=C2=A0 =C2=A0 =C2=A0 gBS->ConnectController (HandleBuffer[Index], NULL,= NULL, TRUE);

+=C2=A0 =C2=A0 }

+=C2=A0 }

+

+=C2=A0 gBS->FreePool (HandleBuffer);

+=C2=A0 gBS->CloseEvent (Event);

+}

+

+/**

+=C2=A0 USB NCM Driver Binding Start.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 Protocol instance pointer.

+=C2=A0 @param[in]=C2=A0 ControllerHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0 Handle= of device to bind driver to.

+=C2=A0 @param[in]=C2=A0 RemainingDevicePath=C2=A0 =C2=A0 =C2=A0Optional pa= rameter use to pick a specific child

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 device to start= .

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0This driver is added to ControllerHandle

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 T= his driver could not be started due to a device error

+=C2=A0 @retval EFI_OUT_OF_RESOURCES=C2=A0 =C2=A0 =C2=A0 =C2=A0 The driver = could not install successfully due to a lack of resources.

+=C2=A0 @retval other=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This driver does not support this device

+

+**/

+EFI_STATUS

+EFIAPI

+UsbNcmDriverStart (

+=C2=A0 IN EFI_DRIVER_BINDING_PROTOCOL=C2=A0 *This,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 IN EFI_DEVICE_PATH_PROTOCOL=C2=A0 =C2=A0 =C2=A0*RemainingDevicePath=

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 Status;

+=C2=A0 VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 *Reg;

+=C2=A0 EFI_EVENT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0Event;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*UsbEth= Driver;

+=C2=A0 EFI_DEVICE_PATH_PROTOCOL=C2=A0 =C2=A0 =C2=A0 *UsbEthPath;

+=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 UsbCdcDataHandle;

+=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*UsbIo;=

+=C2=A0 EFI_USB_INTERFACE_DESCRIPTOR=C2=A0 Interface;

+

+=C2=A0 Status =3D gBS->OpenProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiUs= bIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOID **)&a= mp;UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This->Dr= iverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_OPEN_PR= OTOCOL_BY_DRIVER

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 Status =3D gBS->OpenProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiDe= vicePathProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOID **)&a= mp;UsbEthPath,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This->Dr= iverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_OPEN_PR= OTOCOL_GET_PROTOCOL

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gEfiUsbIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 Status =3D IsUsbCdcData (UsbEthPath, &UsbCdcDataHandle) ? EFI_S= UCCESS : EFI_UNSUPPORTED;

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gEfiUsbIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+

+=C2=A0 =C2=A0 Status =3D gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLB= ACK, CallbackFunction, NULL, &Event);

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 return Status;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 Status =3D gBS->RegisterProtocolNotify (&gEfiUsbIoPro= tocolGuid, Event, &Reg);

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 UsbEthDriver =3D AllocateZeroPool (sizeof (USB_ETHERNET_DRIVER));
+=C2=A0 if (!UsbEthDriver) {

+=C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gEfiUsbIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 =C2=A0 return EFI_OUT_OF_RESOURCES;

+=C2=A0 }

+

+=C2=A0 Status =3D LoadAllDescriptor (UsbIo, &UsbEthDriver->Config);=

+=C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 GetEndpoint (UsbIo, UsbEthDriver);

+

+=C2=A0 Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interfa= ce);

+=C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 UsbEthDriver->Signature=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =3D USB_ETHERNET_SIGNATUR= E;

+=C2=A0 UsbEthDriver->NumOfInterface=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D Interface.InterfaceNumber;

+=C2=A0 UsbEthDriver->UsbCdcDataHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D UsbCdcDataHandle;

+=C2=A0 UsbEthDriver->UsbIo=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =3D UsbIo;

+=C2=A0 UsbEthDriver->UsbEth.UsbEthReceive=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D UsbEthReceive;

+=C2=A0 UsbEthDriver->UsbEth.UsbEthTransmit=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =3D UsbEthTransmit;

+=C2=A0 UsbEthDriver->UsbEth.UsbEthInterrupt=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0=3D UsbEthInterrupt;

+=C2=A0 UsbEthDriver->UsbEth.UsbEthMacAddress=C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =3D GetUsbEthMacAddress;

+=C2=A0 UsbEthDriver->UsbEth.UsbEthMaxBulkSize=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0=3D UsbEthBulkSize;

+=C2=A0 UsbEthDriver->UsbEth.UsbHeaderFunDescriptor=C2=A0 =C2=A0 =C2=A0 = =3D GetUsbHeaderFunDescriptor;

+=C2=A0 UsbEthDriver->UsbEth.UsbUnionFunDescriptor=C2=A0 =C2=A0 =C2=A0 = =C2=A0=3D GetUsbUnionFunDescriptor;

+=C2=A0 UsbEthDriver->UsbEth.UsbEthFunDescriptor=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0=3D GetUsbEthFunDescriptor;

+=C2=A0 UsbEthDriver->UsbEth.SetUsbEthMcastFilter=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =3D SetUsbEthMcastFilter;

+=C2=A0 UsbEthDriver->UsbEth.SetUsbEthPowerPatternFilter =3D SetUsbEthPo= werFilter;

+=C2=A0 UsbEthDriver->UsbEth.GetUsbEthPoewrPatternFilter =3D GetUsbEthPo= werFilter;

+=C2=A0 UsbEthDriver->UsbEth.SetUsbEthPacketFilter=C2=A0 =C2=A0 =C2=A0 = =C2=A0=3D SetUsbEthPacketFilter;

+=C2=A0 UsbEthDriver->UsbEth.GetUsbEthStatistic=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =3D GetUsbEthStatistic;

+

+=C2=A0 UsbEthDriver->BulkBuffer =3D AllocateZeroPool (USB_NCM_MAX_NTB_S= IZE);

+

+=C2=A0 Status =3D gBS->InstallProtocolInterface (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Contro= llerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gUsbEt= hProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_NATIVE_= INTERFACE,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &(UsbEt= hDriver->UsbEth)

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gEfiUsbIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 =C2=A0 gBS->FreePool (UsbEthDriver);

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 USB NCM Driver Binding Stop.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 Protocol instance pointer.

+=C2=A0 @param[in]=C2=A0 ControllerHandle=C2=A0 =C2=A0 =C2=A0 Handle of dev= ice to stop driver on

+=C2=A0 @param[in]=C2=A0 NumberOfChildren=C2=A0 =C2=A0 =C2=A0 Number of Han= dles in ChildHandleBuffer. If number of

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 children is zero stop = the entire bus driver.

+=C2=A0 @param[in]=C2=A0 ChildHandleBuffer=C2=A0 =C2=A0 =C2=A0List of Child= Handles to Stop.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0This driver is removed ControllerHandle

+=C2=A0 @retval other=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0This driver was not removed from this device

+

+**/

+EFI_STATUS

+EFIAPI

+UsbNcmDriverStop (

+=C2=A0 IN=C2=A0 EFI_DRIVER_BINDING_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 IN=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NumberOfChildren,

+=C2=A0 IN=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0*ChildHandleBuffer

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Status;
+=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *UsbEthProtocol;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 =C2=A0 *UsbEthDriver;

+

+=C2=A0 Status =3D gBS->OpenProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gUsbEt= hProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOID **)&a= mp;UsbEthProtocol,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This->Dr= iverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_OPEN_PR= OTOCOL_GET_PROTOCOL

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (UsbEthProtocol);

+

+=C2=A0 Status =3D gBS->UninstallProtocolInterface (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gUsbEt= hProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthProto= col

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 Status =3D gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiUs= bIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This->Dr= iverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 gBS->FreePool (UsbEthDriver->Config);

+=C2=A0 gBS->FreePool (UsbEthDriver->BulkBuffer);

+=C2=A0 gBS->FreePool (UsbEthDriver);

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Entrypoint of NCM Driver.

+

+=C2=A0 This function is the entrypoint of NCM Driver. It installs Driver B= inding

+=C2=A0 Protocols together with Component Name Protocols.

+

+=C2=A0 @param[in]=C2=A0 ImageHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0The firmware= allocated handle for the EFI image.

+=C2=A0 @param[in]=C2=A0 SystemTable=C2=A0 =C2=A0 =C2=A0 =C2=A0A pointer to= the EFI System Table.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The ent= ry point is executed successfully.

+

+**/

+EFI_STATUS

+EFIAPI

+UsbNcmEntry (

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 ImageHandle,

+=C2=A0 IN EFI_SYSTEM_TABLE=C2=A0 *SystemTable

+=C2=A0 )

+{

+=C2=A0 gUsbNcmDriverBinding.DriverBindingHandle =3D ImageHandle;

+=C2=A0 gUsbNcmDriverBinding.ImageHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =3D ImageHandle;

+

+=C2=A0 return gBS->InstallMultipleProtocolInterfaces (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gUsbNcmDriver= Binding.DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiDriverBin= dingProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gUsbNcmDriver= Binding,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiComponent= Name2ProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gUsbNcmCompon= entName2,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NULL

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+}

diff --git a/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.h b/UsbNetworkPkg/UsbCdcNcm/= UsbCdcNcm.h
new file mode 100644
index 0000000000..40b2671a1e
--- /dev/null
+++ b/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.h
@@ -0,0 +1,245 @@
+/** @file

+=C2=A0 Header file for USB Network Control Model driver

+

+=C2=A0 Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+=C2=A0 Subject to AMI licensing agreement.

+**/

+

+#ifndef _USB_CDC_NCM_H_

+#define _USB_CDC_NCM_H_

+

+#include <Library/UefiDriverEntryPoint.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <Library/UefiLib.h>

+#include <Library/DevicePathLib.h>

+#include <Library/DebugLib.h>

+#include <Library/MemoryAllocationLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/UefiUsbLib.h>

+#include <Protocol/UsbIo.h>

+#include <Protocol/UsbEthernetProtocol.h>

+

+typedef struct {

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 Signature;

+=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEth;

+=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0UsbCdcDataHandle;

+=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbIo;

+=C2=A0 EFI_USB_CONFIG_DESCRIPTOR=C2=A0 =C2=A0 *Config;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 NumOfInterface;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 BulkInEndpoint;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 BulkOutEndpoint;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 InterruptEndpoint;

+=C2=A0 EFI_MAC_ADDRESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Mac= Address;

+=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0BulkOutSequence;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 *BulkBuffer;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 TotalDatagram;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 NowDatagram;

+} USB_ETHERNET_DRIVER;

+

+#define USB_NCM_DRIVER_VERSION=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A01

+#define USB_ETHERNET_BULK_TIMEOUT=C2=A0 =C2=A0 =C2=A0 1

+#define USB_ETHERNET_TRANSFER_TIMEOUT=C2=A0 200

+#define USB_NCM_MAX_NTB_SIZE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00xFFF= F

+#define USB_ETH_FRAME_SIZE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= 0x5F2=C2=A0 // frome network stack snp

+

+// Defined in USB NCM 1.0 spec., section 3.2 and 3.3

+#define USB_NCM_NTH_SIGN_16=C2=A0 =C2=A0 =C2=A0 0x484D434E

+#define USB_NCM_NDP_SIGN_16=C2=A0 =C2=A0 =C2=A0 0x304D434E

+#define USB_NCM_NDP_SIGN_16_CRC=C2=A0 0x314D434E

+#define USB_NCM_NTH_LENGTH=C2=A0 =C2=A0 =C2=A0 =C2=A00x000C

+#define USB_NCM_NDP_LENGTH=C2=A0 =C2=A0 =C2=A0 =C2=A00x0010// at least 16<= br>
+

+// USB NCM Transfer header structure - UINT16

+typedef struct {

+=C2=A0 UINT32=C2=A0 =C2=A0 Signature;

+=C2=A0 UINT16=C2=A0 =C2=A0 HeaderLength;

+=C2=A0 UINT16=C2=A0 =C2=A0 Sequence;

+=C2=A0 UINT16=C2=A0 =C2=A0 BlockLength;

+=C2=A0 UINT16=C2=A0 =C2=A0 NdpIndex;

+} USB_NCM_TRANSFER_HEADER_16;

+

+// USB NCM Datagram pointer structure - UINT16

+typedef struct {

+=C2=A0 UINT32=C2=A0 =C2=A0 Signature;

+=C2=A0 UINT16=C2=A0 =C2=A0 Length;

+=C2=A0 UINT16=C2=A0 =C2=A0 NextNdpIndex;

+} USB_NCM_DATAGRAM_POINTER_16;

+

+// USB NCM Datagram structure

+typedef struct {

+=C2=A0 UINT16=C2=A0 =C2=A0 DatagramIndex;

+=C2=A0 UINT16=C2=A0 =C2=A0 DatagramLength;

+} USB_NCM_DATA_GRAM;

+

+#define USB_ETHERNET_SIGNATURE=C2=A0 SIGNATURE_32('u', 'e'= , 't', 'h')

+#define USB_ETHERNET_DEV_FROM_THIS(a)=C2=A0 CR (a, USB_ETHERNET_DRIVER, Us= bEth, USB_ETHERNET_SIGNATURE)

+

+typedef struct {

+=C2=A0 UINT16=C2=A0 =C2=A0 Src;

+=C2=A0 UINT16=C2=A0 =C2=A0 Dst;

+} BIT_MAP;

+

+extern EFI_COMPONENT_NAME2_PROTOCOL=C2=A0 gUsbNcmComponentName2;

+

+EFI_STATUS

+EFIAPI

+UsbNcmDriverSupported (

+=C2=A0 IN EFI_DRIVER_BINDING_PROTOCOL=C2=A0 *This,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 IN EFI_DEVICE_PATH_PROTOCOL=C2=A0 =C2=A0 =C2=A0*RemainingDevicePath=

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+UsbNcmDriverStart (

+=C2=A0 IN EFI_DRIVER_BINDING_PROTOCOL=C2=A0 *This,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 IN EFI_DEVICE_PATH_PROTOCOL=C2=A0 =C2=A0 =C2=A0*RemainingDevicePath=

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+UsbNcmDriverStop (

+=C2=A0 IN=C2=A0 EFI_DRIVER_BINDING_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 IN=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NumberOfChildren,

+=C2=A0 IN=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0*ChildHandleBuffer

+=C2=A0 );

+

+EFI_STATUS

+LoadAllDescriptor (

+=C2=A0 IN=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbIo,

+=C2=A0 OUT EFI_USB_CONFIG_DESCRIPTOR=C2=A0 **ConfigDesc

+=C2=A0 );

+

+BOOLEAN

+NextDescriptor (

+=C2=A0 IN EFI_USB_CONFIG_DESCRIPTOR=C2=A0 *Desc,

+=C2=A0 IN OUT UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 *Offset

+=C2=A0 );

+

+EFI_STATUS

+GetFunctionalDescriptor (

+=C2=A0 IN=C2=A0 EFI_USB_CONFIG_DESCRIPTOR=C2=A0 *Config,

+=C2=A0 IN=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 FunDescriptorType,

+=C2=A0 OUT VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0*DataBuffer

+=C2=A0 );

+

+VOID

+GetEndpoint (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 *UsbIo,

+=C2=A0 IN OUT=C2=A0 USB_ETHERNET_DRIVER=C2=A0 *UsbEthDriver

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+UsbEthReceive (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0PXE_CDB=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 *Cdb,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN OUT VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0*Packet,

+=C2=A0 IN OUT UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 *PacketLength

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+UsbEthTransmit (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 PXE_CDB=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 *Cdb,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*Packet,

+=C2=A0 IN OUT=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 *PacketLength

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+UsbEthInterrupt (

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0*This,

+=C2=A0 IN BOOLEAN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0IsNewTransfer,

+=C2=A0 IN UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0PollingInterval,

+=C2=A0 IN EFI_USB_DEVICE_REQUEST=C2=A0 *Request

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+InterruptCallback (

+=C2=A0 IN=C2=A0 VOID=C2=A0 =C2=A0 *Data,

+=C2=A0 IN=C2=A0 UINTN=C2=A0 =C2=A0DataLength,

+=C2=A0 IN=C2=A0 VOID=C2=A0 =C2=A0 *Context,

+=C2=A0 IN=C2=A0 UINT32=C2=A0 Status

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+GetUsbEthMacAddress (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 OUT EFI_MAC_ADDRESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 *MacAddress

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+UsbEthBulkSize (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 OUT UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 *BulkSize

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+GetUsbHeaderFunDescriptor (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0 *This,

+=C2=A0 OUT USB_HEADER_FUN_DESCRIPTOR=C2=A0 *UsbHeaderFunDescriptor

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+GetUsbUnionFunDescriptor (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0*This,

+=C2=A0 OUT USB_UNION_FUN_DESCRIPTOR=C2=A0 *UsbUnionFunDescriptor

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+GetUsbEthFunDescriptor (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 *This,
+=C2=A0 OUT USB_ETHERNET_FUN_DESCRIPTOR=C2=A0 *UsbEthFunDescriptor

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+SetUsbEthMcastFilter (

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Value,

+=C2=A0 IN VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0*McastAddr

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+SetUsbEthPowerFilter (

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Value,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Length,

+=C2=A0 IN VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0*PatternFilter

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+GetUsbEthPowerFilter (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0Value,

+=C2=A0 OUT BOOLEAN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = *PatternActive

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+SetUsbEthPacketFilter (

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Value

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+GetUsbEthStatistic (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0FeatureSelector,

+=C2=A0 OUT VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0*Statistic

+=C2=A0 );

+

+#endif

diff --git a/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf b/UsbNetworkPkg/UsbCdcNc= m/UsbCdcNcm.inf
new file mode 100644
index 0000000000..cfbf9ad720
--- /dev/null
+++ b/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf
@@ -0,0 +1,41 @@
+## @file
+#=C2=A0 =C2=A0This is Usb Cdc Ncm driver for DXE phase.
+#
+# Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
+# Subject to AMI licensing agreement.
+##
+
+[Defines]
+=C2=A0 INF_VERSION=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =3D 0x00010005
+=C2=A0 BASE_NAME=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =3D UsbCdcNcm
+=C2=A0 FILE_GUID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =3D 52230d31-6c11-4442-b262-bec6bfe84efa
+=C2=A0 MODULE_TYPE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =3D DXE_DRIVER
+=C2=A0 VERSION_STRING=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0=3D 1.0
+=C2=A0 ENTRY_POINT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =3D UsbNcmEntry
+
+[Sources]
+=C2=A0 UsbCdcNcm.c
+=C2=A0 UsbCdcNcm.h
+=C2=A0 UsbNcmFunction.c
+=C2=A0 ComponentName.c
+
+[Packages]
+=C2=A0 MdePkg/MdePkg.dec
+=C2=A0 UsbNetworkPkg/UsbNetworkPkg.dec
+
+[LibraryClasses]
+=C2=A0 UefiDriverEntryPoint
+=C2=A0 UefiBootServicesTableLib
+=C2=A0 UefiLib
+=C2=A0 DebugLib
+=C2=A0 UefiUsbLib
+=C2=A0 MemoryAllocationLib
+=C2=A0 BaseMemoryLib
+
+[Protocols]
+=C2=A0 gEfiUsbIoProtocolGuid
+=C2=A0 gEfiDevicePathProtocolGuid
+=C2=A0 gEfiDriverBindingProtocolGuid
+
+[Depex]
+=C2=A0 TRUE
\ No newline at end of file
diff --git a/UsbNetworkPkg/UsbCdcNcm/UsbNcmFunction.c b/UsbNetworkPkg/UsbCd= cNcm/UsbNcmFunction.c
new file mode 100644
index 0000000000..98bcf6d6d5
--- /dev/null
+++ b/UsbNetworkPkg/UsbCdcNcm/UsbNcmFunction.c
@@ -0,0 +1,946 @@
+/** @file

+=C2=A0 This file contains code for USB Ethernet descriptor

+=C2=A0 and specific requests implement.

+

+=C2=A0 Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+=C2=A0 Subject to AMI licensing agreement.

+**/

+

+#include "UsbCdcNcm.h"

+

+/**

+=C2=A0 Load All of device descriptor.

+

+=C2=A0 @param[in]=C2=A0 UsbIo=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0A pointer to the EFI_USB_IO_PROTOCOL instance.

+=C2=A0 @param[out] ConfigDesc=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A p= ointer to the configuration descriptor.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_OUT_OF_RESOURCES=C2=A0 The request could not be complet= ed because the

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 buffer specified by DescriptorLength= and Descriptor

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 is not large enough to hold the resu= lt of the request.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error. The transfer

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 status is returned in Status.

+

+**/

+EFI_STATUS

+LoadAllDescriptor (

+=C2=A0 IN=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbIo,

+=C2=A0 OUT EFI_USB_CONFIG_DESCRIPTOR=C2=A0 **ConfigDesc

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Status;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0TransStatus;

+=C2=A0 EFI_USB_CONFIG_DESCRIPTOR=C2=A0 Tmp;

+

+=C2=A0 Status =3D UsbIo->UsbGetConfigDescriptor (UsbIo, &Tmp);

+=C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 Status =3D gBS->AllocatePool (EfiBootServicesData, Tmp.TotalLeng= th, (VOID **)ConfigDesc);

+=C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 Status =3D UsbGetDescriptor (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0USB_DESC_TYPE_CONFIG <&= lt; 8 | (Tmp.ConfigurationValue - 1),=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0// zero based

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Tmp.TotalLength,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*ConfigDesc,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&TransStatus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Returns pointer to the next descriptor for the pack of USB descript= ors

+=C2=A0 located in continues memory segment

+

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 Desc=C2=A0 =C2=A0A pointer to the CO= NFIG_DESCRIPTOR instance.

+=C2=A0 @param[in, out] Offset A pointer to the sum of descriptor length.
+

+=C2=A0 @retval TRUE=C2=A0 =C2=A0The request executed successfully.

+=C2=A0 @retval FALSE=C2=A0 No next descriptor.

+

+**/

+BOOLEAN

+NextDescriptor (

+=C2=A0 IN EFI_USB_CONFIG_DESCRIPTOR=C2=A0 *Desc,

+=C2=A0 IN OUT UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 *Offset

+=C2=A0 )

+{

+=C2=A0 if ((Desc =3D=3D NULL) || (*Offset >=3D Desc->TotalLength)) {=

+=C2=A0 =C2=A0 return FALSE;

+=C2=A0 }

+

+=C2=A0 if (((EFI_USB_CONFIG_DESCRIPTOR *)((char *)Desc+*Offset))->Lengt= h =3D=3D 0) {

+=C2=A0 =C2=A0 return FALSE;

+=C2=A0 }

+

+=C2=A0 *Offset +=3D ((EFI_USB_CONFIG_DESCRIPTOR *)((char *)Desc+*Offset))-= >Length;

+=C2=A0 if ( *Offset >=3D Desc->TotalLength ) {

+=C2=A0 =C2=A0 return FALSE;

+=C2=A0 }

+

+=C2=A0 return TRUE;

+}

+

+/**

+=C2=A0 Read Function descriptor

+

+=C2=A0 @param[in]=C2=A0 Config=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0A pointer to all of configuration.

+=C2=A0 @param[in]=C2=A0 FunDescriptorType=C2=A0 USB CDC class descriptor S= ubType.

+=C2=A0 @param[out] DataBuffer=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A pointer t= o the Data of corresponding to device capability.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 The device capabilit= y descriptor was retrieved

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0successfully.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 No supported.

+=C2=A0 @retval EFI_NOT_FOUND=C2=A0 =C2=A0 =C2=A0 The device capability des= criptor was not found.

+

+**/

+EFI_STATUS

+GetFunctionalDescriptor (

+=C2=A0 IN=C2=A0 EFI_USB_CONFIG_DESCRIPTOR=C2=A0 *Config,

+=C2=A0 IN=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 FunDescriptorType,

+=C2=A0 OUT VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0*DataBuffer

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 Status =3D EFI_NOT_FOUND;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0Offset;

+=C2=A0 EFI_USB_INTERFACE_DESCRIPTOR=C2=A0 *Interface;

+

+=C2=A0 for (Offset =3D 0; NextDescriptor (Config, &Offset);) {

+=C2=A0 =C2=A0 Interface =3D (EFI_USB_INTERFACE_DESCRIPTOR *)((UINT8 *)Conf= ig + Offset);

+=C2=A0 =C2=A0 if (Interface->DescriptorType =3D=3D CS_INTERFACE) {

+=C2=A0 =C2=A0 =C2=A0 if (((USB_HEADER_FUN_DESCRIPTOR *)Interface)->Desc= riptorSubtype =3D=3D FunDescriptorType) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 switch (FunDescriptorType) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 case HEADER_FUN_DESCRIPTOR:

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 CopyMem (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 DataBuffer,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (USB_HEADER_FUN_DESCRIPTO= R *)Interface,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 sizeof (USB_HEADER_FUN_DE= SCRIPTOR)

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return EFI_SUCCESS;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 case UNION_FUN_DESCRIPTOR:

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 CopyMem (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 DataBuffer,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (USB_UNION_FUN_DESCRIPTOR= *)Interface,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ((USB_UNION_FUN_DESCRIPTO= R *)Interface)->FunctionLength

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return EFI_SUCCESS;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 case ETHERNET_FUN_DESCRIPTOR:

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 CopyMem (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 DataBuffer,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (USB_ETHERNET_FUN_DESCRIP= TOR *)Interface,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 sizeof (USB_ETHERNET_FUN_= DESCRIPTOR)

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return EFI_SUCCESS;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 default:

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Status =3D EFI_UNSUPPORTED;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 }

+=C2=A0 }

+

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Get USB Ethernet IO endpoint and USB CDC data IO endpoint.

+

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 UsbIo=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0A pointer to the EFI_USB_IO_PROTOCOL instance.

+=C2=A0 @param[in, out] UsbEthDriver=C2=A0 A pointer to the USB_ETHERNET_DR= IVER instance.

+

+**/

+VOID

+GetEndpoint (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 *UsbIo,

+=C2=A0 IN OUT=C2=A0 USB_ETHERNET_DRIVER=C2=A0 *UsbEthDriver

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 Status;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0Index;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 Result;

+=C2=A0 EFI_USB_INTERFACE_DESCRIPTOR=C2=A0 Interface;

+=C2=A0 EFI_USB_ENDPOINT_DESCRIPTOR=C2=A0 =C2=A0Endpoint;

+

+=C2=A0 Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interfa= ce);

+=C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 if (Interface.NumEndpoints =3D=3D 0) {

+=C2=A0 =C2=A0 Status =3D UsbSetInterface (UsbIo, Interface.InterfaceNumber= , 1, &Result);

+=C2=A0 =C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 =C2=A0 Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &= Interface);

+=C2=A0 =C2=A0 ASSERT_EFI_ERROR (Status);

+=C2=A0 }

+

+=C2=A0 for (Index =3D 0; Index < Interface.NumEndpoints; Index++) {

+=C2=A0 =C2=A0 Status =3D UsbIo->UsbGetEndpointDescriptor (UsbIo, Index,= &Endpoint);

+=C2=A0 =C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 =C2=A0 switch ((Endpoint.Attributes & (BIT0 | BIT1))) {

+=C2=A0 =C2=A0 =C2=A0 case USB_ENDPOINT_BULK:

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (Endpoint.EndpointAddress & BIT7) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDriver->BulkInEndpoint =3D End= point.EndpointAddress;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 } else {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDriver->BulkOutEndpoint =3D En= dpoint.EndpointAddress;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 =C2=A0 case USB_ENDPOINT_INTERRUPT:

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDriver->InterruptEndpoint =3D Endpoin= t.EndpointAddress;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 }

+=C2=A0 }

+}

+

+/**

+=C2=A0 This function is used to manage a USB device with the bulk transfer= pipe. The endpoint is Bulk in.

+

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 Cdb=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0A pointer to the command descriptor block.

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 A pointer to the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[in, out] Packet=C2=A0 =C2=A0 =C2=A0 =C2=A0 A pointer to the = buffer of data that will be transmitted to USB

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 device or received from USB device.<= br>
+=C2=A0 @param[in, out] PacketLength=C2=A0 A pointer to the PacketLength.
+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The bul= k transfer has been successfully executed.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The transfer failed. T= he transfer status is returned in status.

+=C2=A0 @retval EFI_INVALID_PARAMETE=C2=A0 One or more parameters are inval= id.

+=C2=A0 @retval EFI_OUT_OF_RESOURCES=C2=A0 The request could not be submitt= ed due to a lack of resources.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The con= trol transfer fails due to timeout.

+

+**/

+EFI_STATUS

+EFIAPI

+UsbEthReceive (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0PXE_CDB=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 *Cdb,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN OUT VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0*Packet,

+=C2=A0 IN OUT UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 *PacketLength

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0Status;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbEthDriver= ;

+=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbIo;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0TransStatus;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 Index;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 BulkDataLenght;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 TotalLength =3D 0;

+=C2=A0 USB_NCM_TRANSFER_HEADER_16=C2=A0 =C2=A0*Nth;

+=C2=A0 USB_NCM_DATAGRAM_POINTER_16=C2=A0 *Ndp;

+=C2=A0 USB_NCM_DATA_GRAM=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *Datagra= m;

+

+=C2=A0 UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This);

+

+=C2=A0 if (UsbEthDriver->TotalDatagram =3D=3D UsbEthDriver->NowDatag= ram) {

+=C2=A0 =C2=A0 Status =3D gBS->HandleProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbE= thDriver->UsbCdcDataHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &= ;gEfiUsbIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOI= D **)&UsbIo

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );
+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 return Status;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 if (UsbEthDriver->BulkInEndpoint =3D=3D 0) {

+=C2=A0 =C2=A0 =C2=A0 GetEndpoint (UsbIo, UsbEthDriver);

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 BulkDataLenght =3D USB_NCM_MAX_NTB_SIZE;

+=C2=A0 =C2=A0 SetMem (UsbEthDriver->BulkBuffer, BulkDataLenght, 0);

+=C2=A0 =C2=A0 UsbEthDriver->NowDatagram=C2=A0 =C2=A0=3D 0;

+=C2=A0 =C2=A0 UsbEthDriver->TotalDatagram =3D 0;

+

+=C2=A0 =C2=A0 Status =3D UsbIo->UsbBulkTransfer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 UsbEthDriver->BulkInEndpoint,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 UsbEthDriver->BulkBuffer,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 &BulkDataLenght,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 USB_ETHERNET_BULK_TIMEOUT,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 &TransStatus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 );

+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 return Status;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 Nth=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D (USB_NCM_TRANSFER_HEADER_16 *)UsbEthD= river->BulkBuffer;

+=C2=A0 =C2=A0 Ndp=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D (USB_NCM_DATAGRAM_POINTER_16 *)((UINT= 8 *)UsbEthDriver->BulkBuffer + Nth->NdpIndex);

+=C2=A0 =C2=A0 Datagram=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =3D (USB_NCM_DATA_GRAM *)((UINT8 *)Ndp + sizeof (USB_NCM_= DATAGRAM_POINTER_16));

+=C2=A0 =C2=A0 UsbEthDriver->TotalDatagram =3D (UINT8)((Ndp->Length -= 8) / 4 - 1);

+

+=C2=A0 =C2=A0 for (Index =3D 0; Index < UsbEthDriver->TotalDatagram;= Index++) {

+=C2=A0 =C2=A0 =C2=A0 TotalLength +=3D Datagram->DatagramLength;

+=C2=A0 =C2=A0 =C2=A0 Datagram=C2=A0 =C2=A0 =C2=A0=3D (USB_NCM_DATA_GRAM *)= ((UINT8 *)Datagram + sizeof (USB_NCM_DATA_GRAM));

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 if (TotalLength < USB_ETH_FRAME_SIZE) {

+=C2=A0 =C2=A0 =C2=A0 Datagram =3D (USB_NCM_DATA_GRAM *)((UINT8 *)Ndp + siz= eof (USB_NCM_DATAGRAM_POINTER_16));

+

+=C2=A0 =C2=A0 =C2=A0 TotalLength =3D 0;

+=C2=A0 =C2=A0 =C2=A0 for (Index =3D 0; Index < UsbEthDriver->TotalDa= tagram; Index++) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 CopyMem ((UINT8 *)Packet + TotalLength, (UINT8= *)UsbEthDriver->BulkBuffer + Datagram->DatagramIndex, Datagram->D= atagramLength);

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 TotalLength +=3D Datagram->DatagramLength;<= br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 Datagram=C2=A0 =C2=A0 =C2=A0=3D (USB_NCM_DATA_= GRAM *)((UINT8 *)Datagram + sizeof (USB_NCM_DATA_GRAM));

+=C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 *PacketLength=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0=3D TotalLength;

+=C2=A0 =C2=A0 =C2=A0 UsbEthDriver->NowDatagram =3D UsbEthDriver->Tot= alDatagram;

+=C2=A0 =C2=A0 } else {

+=C2=A0 =C2=A0 =C2=A0 UsbEthDriver->NowDatagram++;

+

+=C2=A0 =C2=A0 =C2=A0 Datagram =3D (USB_NCM_DATA_GRAM *)((UINT8 *)Ndp + siz= eof (USB_NCM_DATAGRAM_POINTER_16));

+=C2=A0 =C2=A0 =C2=A0 CopyMem (Packet, (UINT8 *)UsbEthDriver->BulkBuffer= + Datagram->DatagramIndex, Datagram->DatagramLength);

+=C2=A0 =C2=A0 =C2=A0 *PacketLength =3D Datagram->DatagramLength;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 return Status;

+=C2=A0 } else {

+=C2=A0 =C2=A0 UsbEthDriver->NowDatagram++;

+

+=C2=A0 =C2=A0 Nth=C2=A0 =C2=A0 =C2=A0 =3D (USB_NCM_TRANSFER_HEADER_16 *)Us= bEthDriver->BulkBuffer;

+=C2=A0 =C2=A0 Ndp=C2=A0 =C2=A0 =C2=A0 =3D (USB_NCM_DATAGRAM_POINTER_16 *)(= (UINT8 *)UsbEthDriver->BulkBuffer + Nth->NdpIndex);

+=C2=A0 =C2=A0 Datagram =3D (USB_NCM_DATA_GRAM *)((UINT8 *)Ndp + sizeof (US= B_NCM_DATAGRAM_POINTER_16));

+=C2=A0 =C2=A0 Datagram =3D (USB_NCM_DATA_GRAM *)((UINT8 *)Datagram + sizeo= f (USB_NCM_DATA_GRAM) * (UsbEthDriver->NowDatagram - 1));

+

+=C2=A0 =C2=A0 CopyMem (Packet, (UINT8 *)UsbEthDriver->BulkBuffer + Data= gram->DatagramIndex, Datagram->DatagramLength);

+=C2=A0 =C2=A0 *PacketLength =3D Datagram->DatagramLength;

+

+=C2=A0 =C2=A0 return EFI_SUCCESS;

+=C2=A0 }

+}

+

+/**

+=C2=A0 This function is used to manage a USB device with the bulk transfer= pipe. The endpoint is Bulk out.

+

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 Cdb=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0A pointer to the command descriptor block.

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 A pointer to the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 Packet=C2=A0 =C2=A0 =C2=A0 =C2=A0 A = pointer to the buffer of data that will be transmitted to USB

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 device or received from USB device.<= br>
+=C2=A0 @param[in, out] PacketLength=C2=A0 A pointer to the PacketLength.
+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The bul= k transfer has been successfully executed.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The transfer failed. T= he transfer status is returned in status.

+=C2=A0 @retval EFI_INVALID_PARAMETE=C2=A0 One or more parameters are inval= id.

+=C2=A0 @retval EFI_OUT_OF_RESOURCES=C2=A0 The request could not be submitt= ed due to a lack of resources.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The con= trol transfer fails due to timeout.

+

+**/

+EFI_STATUS

+EFIAPI

+UsbEthTransmit (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 PXE_CDB=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 *Cdb,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*Packet,

+=C2=A0 IN OUT=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 *PacketLength

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0Status;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbEthDriver= ;

+=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbIo;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0TransStatus;

+=C2=A0 USB_NCM_TRANSFER_HEADER_16=C2=A0 =C2=A0*Nth;

+=C2=A0 USB_NCM_DATAGRAM_POINTER_16=C2=A0 *Ndp;

+=C2=A0 USB_NCM_DATA_GRAM=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *Datagra= m;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 *TotalPacket;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 TotalLength;

+

+=C2=A0 UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This);

+

+=C2=A0 Status =3D gBS->HandleProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDrive= r->UsbCdcDataHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiUs= bIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOID **)&a= mp;UsbIo

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 if (UsbEthDriver->BulkOutEndpoint =3D=3D 0) {

+=C2=A0 =C2=A0 GetEndpoint (UsbIo, UsbEthDriver);

+=C2=A0 }

+

+=C2=A0 TotalLength =3D (UINTN)(USB_NCM_NTH_LENGTH + USB_NCM_NDP_LENGTH + (= *PacketLength));

+

+=C2=A0 Status =3D gBS->AllocatePool (EfiBootServicesData, TotalLength, = (VOID **)&TotalPacket);

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 SetMem (TotalPacket, TotalLength, 0);

+

+=C2=A0 Nth=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D (USB_= NCM_TRANSFER_HEADER_16 *)TotalPacket;

+=C2=A0 Nth->Signature=C2=A0 =C2=A0 =3D USB_NCM_NTH_SIGN_16;

+=C2=A0 Nth->HeaderLength =3D USB_NCM_NTH_LENGTH;

+=C2=A0 Nth->Sequence=C2=A0 =C2=A0 =C2=A0=3D UsbEthDriver->BulkOutSeq= uence++;

+=C2=A0 Nth->BlockLength=C2=A0 =3D (UINT16)TotalLength;

+=C2=A0 Nth->NdpIndex=C2=A0 =C2=A0 =C2=A0=3D Nth->HeaderLength;

+

+=C2=A0 Ndp=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D (USB_= NCM_DATAGRAM_POINTER_16 *)((UINT8 *)TotalPacket + Nth->NdpIndex);

+=C2=A0 Ndp->Signature=C2=A0 =C2=A0 =3D USB_NCM_NDP_SIGN_16;

+=C2=A0 Ndp->Length=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D USB_NCM_NDP_LENGTH;
+=C2=A0 Ndp->NextNdpIndex =3D 0x00;

+

+=C2=A0 Datagram=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0=3D (USB_NCM_DATA_GRAM *)((UINT8 *)Ndp + sizeof (USB_NCM_DATAGRAM_POINTE= R_16));

+=C2=A0 Datagram->DatagramIndex=C2=A0 =3D Nth->HeaderLength + Ndp->= ;Length;

+=C2=A0 Datagram->DatagramLength =3D (UINT16)*PacketLength;

+

+=C2=A0 CopyMem (TotalPacket + Datagram->DatagramIndex, Packet, *PacketL= ength);

+

+=C2=A0 *PacketLength =3D TotalLength;

+

+=C2=A0 Status =3D UsbIo->UsbBulkTransfer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbI= o,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbE= thDriver->BulkOutEndpoint,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Tota= lPacket,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Pack= etLength,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB_= ETHERNET_BULK_TIMEOUT,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &= ;TransStatus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );
+=C2=A0 gBS->FreePool (TotalPacket);

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Async USB transfer callback routine.

+

+=C2=A0 @param[in]=C2=A0 Data=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Data= received or sent via the USB Asynchronous Transfer, if the

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 transfer completed successfully.

+=C2=A0 @param[in]=C2=A0 DataLength=C2=A0 =C2=A0 =C2=A0 The length of Data = received or sent via the Asynchronous

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Transfer, if transfer successfully complete= s.

+=C2=A0 @param[in]=C2=A0 Context=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Data pass= ed from UsbAsyncInterruptTransfer() request.

+=C2=A0 @param[in]=C2=A0 Status=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Indicates= the result of the asynchronous transfer.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The asy= nchronous USB transfer request has been successfully executed.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The asynchronous USB t= ransfer request failed.

+

+**/

+EFI_STATUS

+EFIAPI

+InterruptCallback (

+=C2=A0 IN=C2=A0 VOID=C2=A0 =C2=A0 *Data,

+=C2=A0 IN=C2=A0 UINTN=C2=A0 =C2=A0DataLength,

+=C2=A0 IN=C2=A0 VOID=C2=A0 =C2=A0 *Context,

+=C2=A0 IN=C2=A0 UINT32=C2=A0 Status

+=C2=A0 )

+{

+=C2=A0 if (((EFI_USB_DEVICE_REQUEST *)Data)->Request =3D=3D USB_CDC_NET= WORK_CONNECTION) {

+=C2=A0 =C2=A0 CopyMem (

+=C2=A0 =C2=A0 =C2=A0 (EFI_USB_DEVICE_REQUEST *)Context,

+=C2=A0 =C2=A0 =C2=A0 (EFI_USB_DEVICE_REQUEST *)Data,

+=C2=A0 =C2=A0 =C2=A0 sizeof (EFI_USB_DEVICE_REQUEST)

+=C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 }

+

+=C2=A0 return EFI_SUCCESS;

+}

+

+/**

+=C2=A0 This function is used to manage a USB device with an interrupt tran= sfer pipe.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 A pointer to the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[in]=C2=A0 IsNewTransfer=C2=A0 =C2=A0 =C2=A0If TRUE, a new tr= ansfer will be submitted to USB controller. If

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 FALSE, the interrupt transfer is del= eted from the device's interrupt

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 transfer queue.

+=C2=A0 @param[in]=C2=A0 PollingInterval=C2=A0 =C2=A0Indicates the periodic= rate, in milliseconds, that the transfer is to be

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 executed.This parameter is required = when IsNewTransfer is TRUE. The

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 value must be between 1 to 255, othe= rwise EFI_INVALID_PARAMETER is returned.

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 The units are in milliseconds.

+=C2=A0 @param[in]=C2=A0 Request=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A = pointer to the EFI_USB_DEVICE_REQUEST data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The asy= nchronous USB transfer request transfer has been successfully executed.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The asynchronous USB t= ransfer request failed.

+

+**/

+EFI_STATUS

+EFIAPI

+UsbEthInterrupt (

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0*This,

+=C2=A0 IN BOOLEAN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0IsNewTransfer,

+=C2=A0 IN UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0PollingInterval,

+=C2=A0 IN EFI_USB_DEVICE_REQUEST=C2=A0 *Request

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Status;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 *UsbEthDriver;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 DataLe= ngth =3D 0;

+

+=C2=A0 UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This);

+=C2=A0 if (IsNewTransfer =3D=3D TRUE) {

+=C2=A0 =C2=A0 DataLength =3D sizeof (EFI_USB_DEVICE_REQUEST) + sizeof (USB= _CONNECT_SPEED_CHANGE);

+=C2=A0 =C2=A0 Status=C2=A0 =C2=A0 =C2=A0=3D UsbEthDriver->UsbIo->Usb= AsyncInterruptTransfer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDr= iver->UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDr= iver->InterruptEndpoint,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 IsNewTra= nsfer,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 PollingI= nterval,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 DataLeng= th,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (EFI_ASY= NC_USB_TRANSFER_CALLBACK)InterruptCallback,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Request<= br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 } else {

+=C2=A0 =C2=A0 Status =3D UsbEthDriver->UsbIo->UsbAsyncInterruptTrans= fer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDriver->UsbIo= ,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDriver->Inter= ruptEndpoint,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 IsNewTransfer,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NULL,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NULL

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 }

+

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Retrieves the USB Ethernet Mac Address.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A pointer t= o the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[out] MacAddress=C2=A0 =C2=A0 A pointer to the caller allocat= ed USB Ethernet Mac Address.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB= Header Functional descriptor was retrieved successfully.

+=C2=A0 @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL.

+=C2=A0 @retval EFI_NOT_FOUND=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB Head= er Functional descriptor was not found.

+

+**/

+EFI_STATUS

+EFIAPI

+GetUsbEthMacAddress (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 OUT EFI_MAC_ADDRESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 *MacAddress

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0Status;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbEthDriver= ;

+=C2=A0 USB_ETHERNET_FUN_DESCRIPTOR=C2=A0 UsbEthDescriptor;

+=C2=A0 CHAR16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0*Data;

+=C2=A0 CHAR16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0*DataPtr;

+=C2=A0 CHAR16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0TmpStr[1];

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 Index;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 Hi;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 Low;

+

+=C2=A0 UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This);

+

+=C2=A0 Status =3D This->UsbEthFunDescriptor (This, &UsbEthDescripto= r);

+=C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 Status =3D UsbEthDriver->UsbIo->UsbGetStringDescriptor (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDriver->UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x409,=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 // English-U= S Language ID

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDescriptor.MacAddress,<= br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Data

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 DataPtr =3D Data;

+=C2=A0 for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {

+=C2=A0 =C2=A0 CopyMem (TmpStr, DataPtr, sizeof (CHAR16));

+=C2=A0 =C2=A0 DataPtr++;

+=C2=A0 =C2=A0 Hi =3D (UINT8)StrHexToUintn (TmpStr);

+=C2=A0 =C2=A0 CopyMem (TmpStr, DataPtr, sizeof (CHAR16));

+=C2=A0 =C2=A0 DataPtr++;

+=C2=A0 =C2=A0 Low=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0=3D (UINT8)StrHexToUintn (TmpStr);

+=C2=A0 =C2=A0 MacAddress->Addr[Index] =3D (Hi << 4) | Low;

+=C2=A0 }

+

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Get the USB NCM max NTB size.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A pointer t= o the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[out] BulkSize=C2=A0 =C2=A0 =C2=A0 A pointer to the Bulk tran= sfer data size.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Get the= USB NCM max NTB size successfully.

+

+**/

+EFI_STATUS

+EFIAPI

+UsbEthBulkSize (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 OUT UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 *BulkSize

+=C2=A0 )

+{

+=C2=A0 *BulkSize =3D USB_NCM_MAX_NTB_SIZE;

+=C2=A0 return EFI_SUCCESS;

+}

+

+/**

+=C2=A0 Retrieves the USB Header functional Descriptor.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0A pointer to the USB_ETHERNET_PROTOCOL instance.
+=C2=A0 @param[out] UsbHeaderFunDescriptor A pointer to the caller allocate= d USB Header Functional Descriptor.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB= Header Functional descriptor was retrieved successfully.

+=C2=A0 @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL.

+=C2=A0 @retval EFI_NOT_FOUND=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB Head= er Functional descriptor was not found.

+

+**/

+EFI_STATUS

+EFIAPI

+GetUsbHeaderFunDescriptor (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0 *This,

+=C2=A0 OUT USB_HEADER_FUN_DESCRIPTOR=C2=A0 *UsbHeaderFunDescriptor

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Status;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 *UsbEthDriver;

+

+=C2=A0 UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This);

+

+=C2=A0 if (UsbHeaderFunDescriptor =3D=3D NULL) {

+=C2=A0 =C2=A0 return EFI_INVALID_PARAMETER;

+=C2=A0 }

+

+=C2=A0 Status =3D GetFunctionalDescriptor (UsbEthDriver->Config, HEADER= _FUN_DESCRIPTOR, UsbHeaderFunDescriptor);

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Retrieves the USB Union functional Descriptor.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0A pointer to the USB_ETHERNET_PROTOCOL instance.
+=C2=A0 @param[out] UsbUnionFunDescriptor=C2=A0 A pointer to the caller all= ocated USB Union Functional Descriptor.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB= Union Functional descriptor was retrieved successfully.

+=C2=A0 @retval EFI_INVALID_PARAMETER UsbUnionFunDescriptor is NULL.

+=C2=A0 @retval EFI_NOT_FOUND=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB Unio= n Functional descriptor was not found.

+

+**/

+EFI_STATUS

+EFIAPI

+GetUsbUnionFunDescriptor (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0*This,

+=C2=A0 OUT USB_UNION_FUN_DESCRIPTOR=C2=A0 *UsbUnionFunDescriptor

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Status;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 *UsbEthDriver;

+

+=C2=A0 UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This);

+

+=C2=A0 if (UsbUnionFunDescriptor =3D=3D NULL) {

+=C2=A0 =C2=A0 return EFI_INVALID_PARAMETER;

+=C2=A0 }

+

+=C2=A0 Status =3D GetFunctionalDescriptor (UsbEthDriver->Config, UNION_= FUN_DESCRIPTOR, UsbUnionFunDescriptor);

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Retrieves the USB Ethernet functional Descriptor.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0A pointer to the USB_ETHERNET_PROTOCOL instance.
+=C2=A0 @param[out] UsbEthFunDescriptor=C2=A0 =C2=A0 A pointer to the calle= r allocated USB Ethernet Functional Descriptor.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB= Ethernet Functional descriptor was retrieved successfully.

+=C2=A0 @retval EFI_INVALID_PARAMETER UsbEthFunDescriptor is NULL.

+=C2=A0 @retval EFI_NOT_FOUND=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB Ethe= rnet Functional descriptor was not found.

+

+**/

+EFI_STATUS

+EFIAPI

+GetUsbEthFunDescriptor (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 *This,
+=C2=A0 OUT USB_ETHERNET_FUN_DESCRIPTOR=C2=A0 *UsbEthFunDescriptor

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Status;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 *UsbEthDriver;

+

+=C2=A0 UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This);

+

+=C2=A0 if (UsbEthFunDescriptor =3D=3D NULL) {

+=C2=A0 =C2=A0 return EFI_INVALID_PARAMETER;

+=C2=A0 }

+

+=C2=A0 Status =3D GetFunctionalDescriptor (UsbEthDriver->Config, ETHERN= ET_FUN_DESCRIPTOR, UsbEthFunDescriptor);

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 This request sets the Ethernet device multicast filters as specifie= d in the

+=C2=A0 sequential list of 48 bit Ethernet multicast addresses.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0A pointer to the USB_ETHERNET_PROTOCOL instance.
+=C2=A0 @param[in]=C2=A0 Value=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 Number of filters.

+=C2=A0 @param[in]=C2=A0 McastAddr=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 A pointer to the value of the multicast addresses.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+

+**/

+EFI_STATUS

+EFIAPI

+SetUsbEthMcastFilter (

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Value,

+=C2=A0 IN VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0*McastAddr

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0Status;

+=C2=A0 EFI_USB_DEVICE_REQUEST=C2=A0 =C2=A0 =C2=A0 =C2=A0Request;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0TransStatus;

+=C2=A0 USB_ETHERNET_FUN_DESCRIPTOR=C2=A0 UsbEthFunDescriptor;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbEthDriver= ;

+

+=C2=A0 UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This);

+

+=C2=A0 Status =3D This->UsbEthFunDescriptor (This, &UsbEthFunDescri= ptor);

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 if ((UsbEthFunDescriptor.NumberMcFilters << 1) =3D=3D 0) {
+=C2=A0 =C2=A0 return EFI_UNSUPPORTED;

+=C2=A0 }

+

+=C2=A0 Request.RequestType =3D USB_ETHRTNET_SET_REQ_TYPE;

+=C2=A0 Request.Request=C2=A0 =C2=A0 =C2=A0=3D SET_ETH_MULTICAST_FILTERS_RE= Q;

+=C2=A0 Request.Value=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D Value;

+=C2=A0 Request.Index=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D UsbEthDriver->NumOfI= nterface;

+=C2=A0 Request.Length=C2=A0 =C2=A0 =C2=A0 =3D Value * 6;

+

+=C2=A0 return UsbEthDriver->UsbIo->UsbControlTransfer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDriver->UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Request,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EfiUsbDataOut,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB_ETHERNET_TRANSFER_TIMEOUT,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 McastAddr,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Request.Length,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &TransStatus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+}

+

+/**

+=C2=A0 This request sets up the specified Ethernet power management patter= n filter as

+=C2=A0 described in the data structure.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 A pointer to the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[in]=C2=A0 Value=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0Number of filters.

+=C2=A0 @param[in]=C2=A0 Length=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 Size of the power management pattern filter data.

+=C2=A0 @param[in]=C2=A0 PatternFilter=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A p= ointer to the power management pattern filter structure.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+

+**/

+EFI_STATUS

+EFIAPI

+SetUsbEthPowerFilter (

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Value,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Length,

+=C2=A0 IN VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0*PatternFilter

+=C2=A0 )

+{

+=C2=A0 EFI_USB_DEVICE_REQUEST=C2=A0 Request;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 TransStatus;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 =C2=A0 =C2=A0*UsbEthDriver;

+

+=C2=A0 UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This);

+

+=C2=A0 Request.RequestType =3D USB_ETHRTNET_SET_REQ_TYPE;

+=C2=A0 Request.Request=C2=A0 =C2=A0 =C2=A0=3D SET_ETH_POWER_MANAGEMENT_PAT= TERN_FILTER_REQ;

+=C2=A0 Request.Value=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D Value;

+=C2=A0 Request.Index=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D UsbEthDriver->NumOfI= nterface;

+=C2=A0 Request.Length=C2=A0 =C2=A0 =C2=A0 =3D Length;

+

+=C2=A0 return UsbEthDriver->UsbIo->UsbControlTransfer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDriver->UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Request,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EfiUsbDataOut,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB_ETHERNET_TRANSFER_TIMEOUT,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 PatternFilter,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Length,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &TransStatus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+}

+

+/**

+=C2=A0 This request retrieves the status of the specified Ethernet power m= anagement

+=C2=A0 pattern filter from the device.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0A pointer to the USB_ETHERNET_PROTOCOL instance.
+=C2=A0 @param[in]=C2=A0 Value=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 The filter number.

+=C2=A0 @param[out] PatternActive=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A point= er to the pattern active boolean.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+

+**/

+EFI_STATUS

+EFIAPI

+GetUsbEthPowerFilter (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0Value,

+=C2=A0 OUT BOOLEAN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = *PatternActive

+=C2=A0 )

+{

+=C2=A0 EFI_USB_DEVICE_REQUEST=C2=A0 Request;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 TransStatus;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 =C2=A0 =C2=A0*UsbEthDriver;

+

+=C2=A0 UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This);

+

+=C2=A0 Request.RequestType =3D USB_ETHERNET_GET_REQ_TYPE;

+=C2=A0 Request.Request=C2=A0 =C2=A0 =C2=A0=3D GET_ETH_POWER_MANAGEMENT_PAT= TERN_FILTER_REQ;

+=C2=A0 Request.Value=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D Value;

+=C2=A0 Request.Index=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D UsbEthDriver->NumOfI= nterface;

+=C2=A0 Request.Length=C2=A0 =C2=A0 =C2=A0 =3D USB_ETH_POWER_FILTER_LENGTH;=

+

+=C2=A0 return UsbEthDriver->UsbIo->UsbControlTransfer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDriver->UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Request,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EfiUsbDataIn,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB_ETHERNET_TRANSFER_TIMEOUT,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 PatternActive,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB_ETH_POWER_FILTER_LENGTH,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &TransStatus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+}

+

+BIT_MAP=C2=A0 gTable[] =3D {

+=C2=A0 { PXE_OPFLAGS_RECEIVE_FILTER_UNICAST,=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 USB_ETH_PACKET_TYPE_DIRECTED=C2=A0 =C2=A0 =C2=A0 },

+=C2=A0 { PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST,=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 USB_ETH_PACKET_TYPE_BROADCAST=C2=A0 =C2=A0 =C2=A0},

+=C2=A0 { PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST, USB_ETH_PACKET_TYP= E_MULTICAST=C2=A0 =C2=A0 =C2=A0},

+=C2=A0 { PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS,=C2=A0 =C2=A0 =C2=A0 =C2= =A0 USB_ETH_PACKET_TYPE_PROMISCUOUS=C2=A0 =C2=A0},

+=C2=A0 { PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST,=C2=A0 =C2=A0 =C2=A0 USB= _ETH_PACKET_TYPE_ALL_MULTICAST },

+};

+

+/**

+=C2=A0 Convert value between PXE receive filter and USB ETH packet filter.=

+

+=C2=A0 @param[in]=C2=A0 Value=C2=A0 =C2=A0 =C2=A0 PXE filter data.

+=C2=A0 @param[out] CdcFilter=C2=A0 A pointer to the Ethernet Packet Filter= Bitmap value converted by PXE_OPFLAGS.

+

+**/

+VOID

+ConvertFilter (

+=C2=A0 IN=C2=A0 UINT16=C2=A0 Value,

+=C2=A0 OUT UINT16=C2=A0 *CdcFilter

+=C2=A0 )

+{

+=C2=A0 UINT32=C2=A0 Index;

+=C2=A0 UINT32=C2=A0 Count;

+

+=C2=A0 Count =3D sizeof (gTable)/sizeof (gTable[0]);

+

+=C2=A0 for (Index =3D 0; (gTable[Index].Src !=3D 0) && (Index <= Count); Index++) {

+=C2=A0 =C2=A0 if (gTable[Index].Src & Value) {

+=C2=A0 =C2=A0 =C2=A0 *CdcFilter |=3D gTable[Index].Dst;

+=C2=A0 =C2=A0 }

+=C2=A0 }

+}

+

+/**

+=C2=A0 This request is used to configure device Ethernet packet filter set= tings.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 A pointer to the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[in]=C2=A0 Value=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0Packet Filter Bitmap.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+

+**/

+EFI_STATUS

+EFIAPI

+SetUsbEthPacketFilter (

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Value

+=C2=A0 )

+{

+=C2=A0 EFI_USB_DEVICE_REQUEST=C2=A0 Request;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 TransStatus;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 =C2=A0 =C2=A0*UsbEthDriver;

+=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 CommandFilter =3D 0;

+

+=C2=A0 UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This);

+

+=C2=A0 ConvertFilter (Value, &CommandFilter);

+

+=C2=A0 Request.RequestType =3D USB_ETHRTNET_SET_REQ_TYPE;

+=C2=A0 Request.Request=C2=A0 =C2=A0 =C2=A0=3D SET_ETH_PACKET_FILTER_REQ;
+=C2=A0 Request.Value=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D CommandFilter;

+=C2=A0 Request.Index=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D UsbEthDriver->NumOfI= nterface;

+=C2=A0 Request.Length=C2=A0 =C2=A0 =C2=A0 =3D USB_ETH_PACKET_FILTER_LENGTH= ;

+

+=C2=A0 return UsbEthDriver->UsbIo->UsbControlTransfer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDriver->UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Request,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EfiUsbNoData,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB_ETHERNET_TRANSFER_TIMEOUT,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NULL,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB_ETH_PACKET_FILTER_LENGTH,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &TransStatus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+}

+

+/**

+=C2=A0 This request is used to retrieve a statistic based on the feature s= elector.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 A pointer to the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[in]=C2=A0 FeatureSelector=C2=A0 =C2=A0 =C2=A0 =C2=A0Value of= the feature selector.

+=C2=A0 @param[out] Statistic=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0A pointer to the 32 bit unsigned integer.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+

+**/

+EFI_STATUS

+EFIAPI

+GetUsbEthStatistic (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0FeatureSelector,

+=C2=A0 OUT VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0*Statistic

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0Status;

+=C2=A0 EFI_USB_DEVICE_REQUEST=C2=A0 =C2=A0 =C2=A0 =C2=A0Request;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0TransStatus;

+=C2=A0 USB_ETHERNET_FUN_DESCRIPTOR=C2=A0 UsbEthFunDescriptor;

+=C2=A0 USB_ETHERNET_DRIVER=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbEthDriver= ;

+

+=C2=A0 UsbEthDriver =3D USB_ETHERNET_DEV_FROM_THIS (This);

+

+=C2=A0 Status =3D This->UsbEthFunDescriptor (This, &UsbEthFunDescri= ptor);

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 if (UsbEthFunDescriptor.EthernetStatistics =3D=3D 0) {

+=C2=A0 =C2=A0 return EFI_UNSUPPORTED;

+=C2=A0 }

+

+=C2=A0 Request.RequestType =3D USB_ETHERNET_GET_REQ_TYPE;

+=C2=A0 Request.Request=C2=A0 =C2=A0 =C2=A0=3D GET_ETH_STATISTIC_REQ;

+=C2=A0 Request.Value=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D FeatureSelector;

+=C2=A0 Request.Index=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D UsbEthDriver->NumOfI= nterface;

+=C2=A0 Request.Length=C2=A0 =C2=A0 =C2=A0 =3D USB_ETH_STATISTIC;

+

+=C2=A0 return UsbEthDriver->UsbIo->UsbControlTransfer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDriver->UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Request,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EfiUsbDataIn,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB_ETHERNET_TRANSFER_TIMEOUT,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Statistic,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB_ETH_STATISTIC,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &TransStatus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+}

diff --git a/UsbNetworkPkg/UsbNetworkPkg.dec b/UsbNetworkPkg/UsbNetworkPkg.= dec
new file mode 100644
index 0000000000..4ffafd99ed
--- /dev/null
+++ b/UsbNetworkPkg/UsbNetworkPkg.dec
@@ -0,0 +1,32 @@
+## @file
+#=C2=A0 This package defines Usb network specific interfaces and library c= lasses
+#=C2=A0 as well as configuration for standard edk2 packages.
+#
+#=C2=A0 Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
+#=C2=A0 Subject to AMI licensing agreement.
+##
+
+[Defines]
+=C2=A0 DEC_SPECIFICATION=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =3D 0x00010005
+=C2=A0 PACKAGE_NAME=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0=3D UsbNetworkPkg
+=C2=A0 PACKAGE_GUID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0=3D abfab91e-37ea-4cb4-80a6-563dbb0bcec6
+=C2=A0 PACKAGE_VERSION=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =3D 0.1
+
+[Includes]
+=C2=A0 Include
+
+[Guids]
+=C2=A0 ## Usb Network package token space GUID
+=C2=A0 gUsbNetworkPkgTokenSpaceGuid=C2=A0 =3D { 0xA1231E82, 0x21B8, 0x4204= , { 0x92, 0xBB, 0x37, 0x3A, 0xFB, 0x01, 0xC6, 0xA1 } }
+
+[PcdsFeatureFlag]
+
+=C2=A0 ## Set the PCD 'UsbCdcEcmSupport' to 'TRUE' if '= ;Usb Cdc Ecm device' need to be enabled.
+=C2=A0 gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport|FALSE|BOOLEAN|0x00000= 001
+
+=C2=A0 ## Set the PCD 'UsbCdcNcmSupport' to 'TRUE' if '= ;Usb Cdc Ncm device' need to be enabled.
+=C2=A0 gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport|FALSE|BOOLEAN|0x00000= 002
+
+=C2=A0 ## Set the PCD 'UsbRndisSupport' to 'TRUE' if '= Usb Rndis device' need to be enabled.
+=C2=A0 gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport|TRUE|BOOLEAN|0x0000000= 3
+
diff --git a/UsbNetworkPkg/UsbRndis/ComponentName.c b/UsbNetworkPkg/UsbRndi= s/ComponentName.c
new file mode 100644
index 0000000000..6b7891afd9
--- /dev/null
+++ b/UsbNetworkPkg/UsbRndis/ComponentName.c
@@ -0,0 +1,172 @@
+/** @file

+=C2=A0 This file contains code for USB RNDIS Driver Component

+=C2=A0 Name definitions

+

+=C2=A0 Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+=C2=A0 Subject to AMI licensing agreement.

+**/

+

+#include "UsbRndis.h"

+

+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE=C2=A0 gUsbRndisDriv= erNameTable[] =3D {

+=C2=A0 {

+=C2=A0 =C2=A0 "eng;en",

+=C2=A0 =C2=A0 L"USB RNDIS Driver"

+=C2=A0 },

+=C2=A0 {

+=C2=A0 =C2=A0 NULL,

+=C2=A0 =C2=A0 NULL

+=C2=A0 }

+};

+

+EFI_STATUS

+EFIAPI

+UsbRndisComponentNameGetDriverName (

+=C2=A0 IN=C2=A0 EFI_COMPONENT_NAME_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 CHAR8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *Language,

+=C2=A0 OUT CHAR16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0**DriverName

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+UsbRndisComponentNameGetControllerName (

+=C2=A0 IN EFI_COMPONENT_NAME_PROTOCOL=C2=A0 *This,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0Controller,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0ChildHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0 OPTIONAL,

+=C2=A0 IN CHAR8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 *Language,

+=C2=A0 OUT CHAR16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 **ControllerName

+=C2=A0 );

+

+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL=C2=A0 gUsbRndisC= omponentName =3D {

+=C2=A0 UsbRndisComponentNameGetDriverName,

+=C2=A0 UsbRndisComponentNameGetControllerName,

+=C2=A0 "eng"

+};

+

+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL=C2=A0 gUsbRndis= ComponentName2 =3D {

+=C2=A0 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)UsbRndisComponentNameGetDriver= Name,

+=C2=A0 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)UsbRndisComponentNameGetCo= ntrollerName,

+=C2=A0 "en"

+};

+

+/**

+=C2=A0 Retrieves a Unicode string that is the user readable name of the dr= iver.

+

+=C2=A0 This function retrieves the user readable name of a driver in the f= orm of a

+=C2=A0 Unicode string. If the driver specified by This has a user readable= name in

+=C2=A0 the language specified by Language, then a pointer to the driver na= me is

+=C2=A0 returned in DriverName, and EFI_SUCCESS is returned. If the driver = specified

+=C2=A0 by This does not support the language specified by Language,

+=C2=A0 then EFI_UNSUPPORTED is returned.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_COMPONENT_NAME_PROTOCOL instance= .

+=C2=A0 @param[in]=C2=A0 Language=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A point= er to a Null-terminated ASCII string

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 array indicating the language. This = is the

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 language of the driver name that the= caller is

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 requesting, and it must match one of= the

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 languages specified in SupportedLang= uages. The

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 number of languages supported by a d= river is up

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 to the driver writer. Language is sp= ecified

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 in RFC 4646 or ISO 639-2 language co= de format.

+=C2=A0 @param[out] DriverName=C2=A0 =C2=A0 =C2=A0 =C2=A0 A pointer to the = Unicode string to return.

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This Unicode string is the name of t= he

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 driver specified by This in the lang= uage

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 specified by Language.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The Uni= code string for the Driver specified by

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This and the language specified by L= anguage was

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 returned in DriverName.

+=C2=A0 @retval EFI_INVALID_PARAMETER Language is NULL.

+=C2=A0 @retval EFI_INVALID_PARAMETER DriverName is NULL.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0The driver specif= ied by This does not support

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 the language specified by Language.<= br>
+

+**/

+EFI_STATUS

+EFIAPI

+UsbRndisComponentNameGetDriverName (

+=C2=A0 IN=C2=A0 EFI_COMPONENT_NAME_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 CHAR8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *Language,

+=C2=A0 OUT CHAR16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0**DriverName

+=C2=A0 )

+{

+=C2=A0 return LookupUnicodeString2 (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Language,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->SupportedLanguages,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0gUsbRndisDriverNameTable,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0DriverName,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(BOOLEAN)(This =3D=3D &gUsbRn= disComponentName)

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+}

+

+/**

+=C2=A0 Retrieves a Unicode string that is the user readable name of the co= ntroller

+=C2=A0 that is being managed by a driver.

+

+=C2=A0 This function retrieves the user readable name of the controller sp= ecified by

+=C2=A0 ControllerHandle and ChildHandle in the form of a Unicode string. I= f the

+=C2=A0 driver specified by This has a user readable name in the language s= pecified by

+=C2=A0 Language, then a pointer to the controller name is returned in Cont= rollerName,

+=C2=A0 and EFI_SUCCESS is returned.=C2=A0 If the driver specified by This = is not currently

+=C2=A0 managing the controller specified by ControllerHandle and ChildHand= le,

+=C2=A0 then EFI_UNSUPPORTED is returned.=C2=A0 If the driver specified by = This does not

+=C2=A0 support the language specified by Language, then EFI_UNSUPPORTED is= returned.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_COMPONENT_NAME_PROTOCOL instance= .

+=C2=A0 @param[in]=C2=A0 Controller=C2=A0 =C2=A0 =C2=A0 =C2=A0 The handle o= f a controller that the driver

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 specified by This is managing.=C2=A0= This handle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 specifies the controller whose name = is to be

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 returned.

+=C2=A0 @param[in]=C2=A0 ChildHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0The handle o= f the child controller to retrieve

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 the name of.=C2=A0 This is an option= al parameter that

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 may be NULL.=C2=A0 It will be NULL f= or device

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 drivers.=C2=A0 It will also be NULL = for a bus drivers

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 that wish to retrieve the name of th= e bus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 controller.=C2=A0 It will not be NUL= L for a bus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 driver that wishes to retrieve the n= ame of a

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 child controller.

+=C2=A0 @param[in]=C2=A0 Language=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A point= er to a Null-terminated ASCII string

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 array indicating the language.=C2=A0= This is the

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 language of the driver name that the= caller is

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 requesting, and it must match one of= the

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 languages specified in SupportedLang= uages. The

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 number of languages supported by a d= river is up

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 to the driver writer. Language is sp= ecified in

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 RFC 4646 or ISO 639-2 language code = format.

+=C2=A0 @param[out] ControllerName=C2=A0 =C2=A0 A pointer to the Unicode st= ring to return.

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This Unicode string is the name of t= he

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 controller specified by ControllerHa= ndle and

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ChildHandle in the language specifie= d by

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Language from the point of view of t= he driver

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 specified by This.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The Uni= code string for the user readable name in

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 the language specified by Language f= or the

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 driver specified by This was returne= d in

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 DriverName.

+=C2=A0 @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_H= ANDLE.

+=C2=A0 @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not= a valid

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_HANDLE.

+=C2=A0 @retval EFI_INVALID_PARAMETER Language is NULL.

+=C2=A0 @retval EFI_INVALID_PARAMETER ControllerName is NULL.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0The driver specif= ied by This is not currently

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 managing the controller specified by=

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerHandle and ChildHandle.
+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0The driver specif= ied by This does not support

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 the language specified by Language.<= br>
+

+**/

+EFI_STATUS

+EFIAPI

+UsbRndisComponentNameGetControllerName (

+=C2=A0 IN EFI_COMPONENT_NAME_PROTOCOL=C2=A0 *This,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0Controller,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0ChildHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0 OPTIONAL,

+=C2=A0 IN CHAR8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 *Language,

+=C2=A0 OUT CHAR16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 **ControllerName

+=C2=A0 )

+{

+=C2=A0 return EFI_UNSUPPORTED;

+}

diff --git a/UsbNetworkPkg/UsbRndis/UsbRndis.c b/UsbNetworkPkg/UsbRndis/Usb= Rndis.c
new file mode 100644
index 0000000000..a75355825b
--- /dev/null
+++ b/UsbNetworkPkg/UsbRndis/UsbRndis.c
@@ -0,0 +1,848 @@
+/** @file

+=C2=A0 This file contains code for USB Remote Network Driver

+=C2=A0 Interface Spec. Driver Binding

+

+=C2=A0 Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+=C2=A0 Subject to AMI licensing agreement.

+**/

+

+#include "UsbRndis.h"

+

+EFI_GUID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0gUsbEthProtocolGuid =3D USB_ETHERNET_= PROTOCOL_GUID;

+extern EFI_COMPONENT_NAME2_PROTOCOL=C2=A0 gUsbRndisComponentName2;

+

+EFI_DRIVER_BINDING_PROTOCOL=C2=A0 gUsbRndisDriverBinding =3D {

+=C2=A0 UsbRndisDriverSupported,

+=C2=A0 UsbRndisDriverStart,

+=C2=A0 UsbRndisDriverStop,

+=C2=A0 USB_RNDIS_DRIVER_VERSION,

+=C2=A0 NULL,

+=C2=A0 NULL

+};

+

+/**

+=C2=A0 Check if this interface is USB Rndis SubType

+

+=C2=A0 @param[in]=C2=A0 UsbIo=C2=A0 A pointer to the EFI_USB_IO_PROTOCOL i= nstance.

+

+=C2=A0 @retval TRUE=C2=A0 =C2=A0USB Rndis SubType.

+=C2=A0 @retval FALSE=C2=A0 Not USB Rndis SubType.

+

+**/

+BOOLEAN

+IsSupportedDevice (

+=C2=A0 IN EFI_USB_IO_PROTOCOL=C2=A0 *UsbIo

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 Status;

+=C2=A0 EFI_USB_INTERFACE_DESCRIPTOR=C2=A0 InterfaceDescriptor;

+

+=C2=A0 Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interfa= ceDescriptor);

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return FALSE;

+=C2=A0 }

+

+=C2=A0 // Check specific device/RNDIS and CDC-DATA

+=C2=A0 if (((InterfaceDescriptor.InterfaceClass =3D=3D 0x2) &&

+=C2=A0 =C2=A0 =C2=A0 =C2=A0(InterfaceDescriptor.InterfaceSubClass =3D=3D 0= x2) &&

+=C2=A0 =C2=A0 =C2=A0 =C2=A0(InterfaceDescriptor.InterfaceProtocol =3D=3D 0= xFF)) || \

+=C2=A0 =C2=A0 =C2=A0 ((InterfaceDescriptor.InterfaceClass =3D=3D 0xEF) &am= p;&

+=C2=A0 =C2=A0 =C2=A0 =C2=A0(InterfaceDescriptor.InterfaceSubClass =3D=3D 0= x4) &&

+=C2=A0 =C2=A0 =C2=A0 =C2=A0(InterfaceDescriptor.InterfaceProtocol =3D=3D 0= x1)) || \

+=C2=A0 =C2=A0 =C2=A0 ((InterfaceDescriptor.InterfaceClass =3D=3D 0xA) &= ;&

+=C2=A0 =C2=A0 =C2=A0 =C2=A0(InterfaceDescriptor.InterfaceSubClass =3D=3D 0= x0) &&

+=C2=A0 =C2=A0 =C2=A0 =C2=A0(InterfaceDescriptor.InterfaceProtocol =3D=3D 0= x00))

+=C2=A0 =C2=A0 =C2=A0 )

+=C2=A0 {

+=C2=A0 =C2=A0 return TRUE;

+=C2=A0 }

+

+=C2=A0 return FALSE;

+}

+

+/**

+=C2=A0 Check if this interface is USB Rndis SubType but not CDC Data inter= face

+

+=C2=A0 @param[in]=C2=A0 UsbIo=C2=A0 A pointer to the EFI_USB_IO_PROTOCOL i= nstance.

+

+=C2=A0 @retval TRUE=C2=A0 =C2=A0USB Rndis SubType.

+=C2=A0 @retval FALSE=C2=A0 Not USB Rndis SubType.

+

+**/

+BOOLEAN

+IsRndisInterface (

+=C2=A0 IN EFI_USB_IO_PROTOCOL=C2=A0 *UsbIo

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 Status;

+=C2=A0 EFI_USB_INTERFACE_DESCRIPTOR=C2=A0 InterfaceDescriptor;

+

+=C2=A0 Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interfa= ceDescriptor);

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return FALSE;

+=C2=A0 }

+

+=C2=A0 // Check for specific device/RNDIS and CDC-DATA

+=C2=A0 if (((InterfaceDescriptor.InterfaceClass =3D=3D 0x2) &&

+=C2=A0 =C2=A0 =C2=A0 =C2=A0(InterfaceDescriptor.InterfaceSubClass =3D=3D 0= x2) &&

+=C2=A0 =C2=A0 =C2=A0 =C2=A0(InterfaceDescriptor.InterfaceProtocol =3D=3D 0= xFF)) || \

+=C2=A0 =C2=A0 =C2=A0 ((InterfaceDescriptor.InterfaceClass =3D=3D 0xEF) &am= p;&

+=C2=A0 =C2=A0 =C2=A0 =C2=A0(InterfaceDescriptor.InterfaceSubClass =3D=3D 0= x4) &&

+=C2=A0 =C2=A0 =C2=A0 =C2=A0(InterfaceDescriptor.InterfaceProtocol =3D=3D 0= x1))

+=C2=A0 =C2=A0 =C2=A0 )

+=C2=A0 {

+=C2=A0 =C2=A0 return TRUE;

+=C2=A0 }

+

+=C2=A0 return FALSE;

+}

+

+/**

+=C2=A0 Check if the USB RNDIS and USB CDC Data interfaces are from the sam= e device.

+

+=C2=A0 @param[in]=C2=A0 UsbRndisDataPath=C2=A0 A pointer to the EFI_DEVICE= _PATH_PROTOCOL instance.

+=C2=A0 @param[in]=C2=A0 UsbCdcDataPath=C2=A0 =C2=A0 A pointer to the EFI_D= EVICE_PATH_PROTOCOL instance.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Is the = same device.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Is not the same d= evice.

+

+**/

+EFI_STATUS

+IsSameDevice (

+=C2=A0 IN=C2=A0 EFI_DEVICE_PATH_PROTOCOL=C2=A0 *UsbRndisDataPath,

+=C2=A0 IN=C2=A0 EFI_DEVICE_PATH_PROTOCOL=C2=A0 *UsbCdcDataPath

+=C2=A0 )

+{

+=C2=A0 DEBUG ((EFI_D_VERBOSE, "IsSameDevice Entry \n"));

+=C2=A0 while (1) {

+=C2=A0 =C2=A0 if (IsDevicePathEnd (NextDevicePathNode (UsbRndisDataPath)))= {

+=C2=A0 =C2=A0 =C2=A0 if (((USB_DEVICE_PATH *)UsbRndisDataPath)->ParentP= ortNumber =3D=3D

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ((USB_DEVICE_PATH *)UsbCdcDataPath)->= ;ParentPortNumber)

+=C2=A0 =C2=A0 =C2=A0 {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return EFI_SUCCESS;

+=C2=A0 =C2=A0 =C2=A0 } else {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return EFI_UNSUPPORTED;

+=C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 } else {

+=C2=A0 =C2=A0 =C2=A0 if (CompareMem (UsbCdcDataPath, UsbRndisDataPath, siz= eof (EFI_DEVICE_PATH_PROTOCOL)) !=3D 0) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return EFI_UNSUPPORTED;

+=C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 UsbRndisDataPath =3D NextDevicePathNode (UsbRndisData= Path);

+=C2=A0 =C2=A0 =C2=A0 UsbCdcDataPath=C2=A0 =C2=A0=3D NextDevicePathNode (Us= bCdcDataPath);

+=C2=A0 =C2=A0 }

+=C2=A0 }

+

+=C2=A0 DEBUG ((EFI_D_VERBOSE, "IsSameDevice Exit \n"));

+}

+

+/**

+=C2=A0 Check if the USB CDC Data(UsbIo) installed and return USB CDC Data = Handle.

+

+=C2=A0 @param[in]=C2=A0 UsbIo=C2=A0 A pointer to the EFI_USB_IO_PROTOCOL i= nstance.

+

+=C2=A0 @retval TRUE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB CD= C Data(UsbIo) installed.

+=C2=A0 @retval FALSE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0USB CD= C Data(UsbIo) did not installed.

+

+**/

+BOOLEAN

+IsUsbCdcData (

+=C2=A0 IN EFI_USB_IO_PROTOCOL=C2=A0 *UsbIo

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 Status;

+=C2=A0 EFI_USB_INTERFACE_DESCRIPTOR=C2=A0 InterfaceDescriptor;

+

+=C2=A0 Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interfa= ceDescriptor);

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return FALSE;

+=C2=A0 }

+

+=C2=A0 // Check for CDC-DATA

+=C2=A0 if ((InterfaceDescriptor.InterfaceClass =3D=3D 0xA) &&

+=C2=A0 =C2=A0 =C2=A0 (InterfaceDescriptor.InterfaceSubClass =3D=3D 0x0) &a= mp;&

+=C2=A0 =C2=A0 =C2=A0 (InterfaceDescriptor.InterfaceProtocol =3D=3D 0x0))
+=C2=A0 {

+=C2=A0 =C2=A0 return TRUE;

+=C2=A0 }

+

+=C2=A0 return FALSE;

+}

+

+/**

+=C2=A0 Check if the USB Rndis(UsbIo) installed

+

+=C2=A0 @param[in]=C2=A0 UsbIo=C2=A0 =C2=A0 =C2=A0 =C2=A0 A pointer to the = EFI_USB_IO_PROTOCOL instance.

+

+=C2=A0 @retval TRUE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB Rn= dis(UsbIo) installed.

+=C2=A0 @retval FALSE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0USB Rn= dis(UsbIo) did not installed.

+

+**/

+BOOLEAN

+IsUsbRndis (

+=C2=A0 IN EFI_USB_IO_PROTOCOL=C2=A0 *UsbIo

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 Status;

+=C2=A0 EFI_USB_INTERFACE_DESCRIPTOR=C2=A0 InterfaceDescriptor;

+

+=C2=A0 Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interfa= ceDescriptor);

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return FALSE;

+=C2=A0 }

+

+=C2=A0 // Check for Rndis

+=C2=A0 if ((InterfaceDescriptor.InterfaceClass =3D=3D 0x2) &&

+=C2=A0 =C2=A0 =C2=A0 (InterfaceDescriptor.InterfaceSubClass =3D=3D 0x2) &a= mp;&

+=C2=A0 =C2=A0 =C2=A0 (InterfaceDescriptor.InterfaceProtocol =3D=3D 0xFF))<= br>
+=C2=A0 {

+=C2=A0 =C2=A0 return TRUE;

+=C2=A0 }

+

+=C2=A0 return FALSE;

+}

+

+/**

+=C2=A0 Control comes here when a CDC device is found.Check if a RNDIS inte= rface is already found for this device or not.

+=C2=A0 For one device two USBIO will be installed each for CDC and RNDIS i= nterface.

+

+=C2=A0 @param[in]=C2=A0 UsbEthPath=C2=A0 =C2=A0 =C2=A0 =C2=A0 A pointer to= the EFI_DEVICE_PATH_PROTOCOL instance.

+=C2=A0 @param[out] UsbRndisDevice=C2=A0 =C2=A0 A pointer to the USB_RNDIS_= DEVICE Data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= The USB_RNDIS_DEVICE matching this CDC Data is found.

+=C2=A0 @retval EFI_NOT_FOUND=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The U= SB_RNDIS_DEVICE matching this CDC Data is not found.

+

+**/

+EFI_STATUS

+UpdateRndisDevice (

+=C2=A0 IN=C2=A0 EFI_DEVICE_PATH_PROTOCOL=C2=A0 *UsbCdcDataPath,

+=C2=A0 OUT USB_RNDIS_DEVICE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 **UsbRndisDe= vice

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 S= tatus;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0Index;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0HandleCount;

+=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *= HandleBuffer;

+=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0*UsbEthDevice;

+=C2=A0 EFI_DEVICE_PATH_PROTOCOL=C2=A0 *UsbRndisDataPath;

+=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0*UsbIo;

+=C2=A0 BOOLEAN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0IsRndisInterfaceFlag =3D FALSE;

+

+=C2=A0 Status =3D gBS->LocateHandleBuffer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ByProtocol,=

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gUsbEt= hProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NULL,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Handle= Count,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Handle= Buffer

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 for (Index =3D 0; Index < HandleCount; Index++) {

+=C2=A0 =C2=A0 Status =3D gBS->HandleProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Hand= leBuffer[Index],

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &= ;gUsbEthProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOI= D **)&UsbEthDevice

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );
+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 continue;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 Status =3D gBS->HandleProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Hand= leBuffer[Index],

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &= ;gEfiUsbIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOI= D **)&UsbIo

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );
+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 continue;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 IsRndisInterfaceFlag =3D IsRndisInterface (UsbIo);

+=C2=A0 =C2=A0 if (IsRndisInterfaceFlag =3D=3D FALSE) {

+=C2=A0 =C2=A0 =C2=A0 continue;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 Status =3D gBS->HandleProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Hand= leBuffer[Index],

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &= ;gEfiDevicePathProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOI= D **)&UsbRndisDataPath

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );
+=C2=A0 =C2=A0 Status =3D IsSameDevice (UsbRndisDataPath, UsbCdcDataPath);<= br>
+

+=C2=A0 =C2=A0 DEBUG ((EFI_D_VERBOSE, "Rndis IsSameDevice %r\n", = Status));

+

+=C2=A0 =C2=A0 if (!EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 *UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (UsbEt= hDevice);

+=C2=A0 =C2=A0 =C2=A0 gBS->FreePool (HandleBuffer);

+=C2=A0 =C2=A0 =C2=A0 return EFI_SUCCESS;

+=C2=A0 =C2=A0 }

+=C2=A0 }=C2=A0 =C2=A0// End of For loop

+

+=C2=A0 gBS->FreePool (HandleBuffer);

+=C2=A0 return EFI_NOT_FOUND;

+}

+

+/**

+

+=C2=A0 For the given Rndis Device, find a matching CDC device already exis= ts or not. If found update the handle

+=C2=A0 and UsbIO protocol.

+

+=C2=A0 @param[in]=C2=A0 UsbRndisDevice=C2=A0 =C2=A0 =C2=A0 =C2=A0 A pointe= r to the USB_RNDIS_DEVICE data.

+

+**/

+VOID

+FindMatchingCdcData (

+=C2=A0 IN USB_RNDIS_DEVICE=C2=A0 *UsbRndisDevice

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 S= tatus;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0Index;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0HandleCount;

+=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *= HandleBuffer;

+=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0*UsbIo;

+=C2=A0 EFI_DEVICE_PATH_PROTOCOL=C2=A0 *UsbRndisDataPath;

+=C2=A0 EFI_DEVICE_PATH_PROTOCOL=C2=A0 *UsbCdcDataPath;

+

+=C2=A0 // Find the parent RNDIS and update the UsbIo for the CDC device
+=C2=A0 Status =3D gBS->HandleProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbRndisDev= ice->UsbRndisHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiDe= vicePathProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOID **)&a= mp;UsbRndisDataPath

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 Status =3D gBS->LocateHandleBuffer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ByProtocol,=

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiUs= bIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NULL,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Handle= Count,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Handle= Buffer

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return;

+=C2=A0 }

+

+=C2=A0 for (Index =3D 0; Index < HandleCount; Index++) {

+=C2=A0 =C2=A0 Status =3D gBS->HandleProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Hand= leBuffer[Index],

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &= ;gEfiUsbIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOI= D **)&UsbIo

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );
+=C2=A0 =C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 =C2=A0 if (IsUsbCdcData (UsbIo)) {

+=C2=A0 =C2=A0 =C2=A0 DEBUG ((EFI_D_VERBOSE, "Rndis FindMatchingCdcDat= a CDCData interface found\n"));

+

+=C2=A0 =C2=A0 =C2=A0 Status =3D gBS->HandleProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 HandleBuffer[Index],

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 &gEfiDevicePathProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 (VOID **)&UsbCdcDataPath

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 );

+=C2=A0 =C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 DEBUG ((EFI_D_VERBOSE, "Rndis CDCData Dev= icePath not found\n"));

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 gBS->FreePool (HandleBuffer);

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return;

+=C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 Status =3D IsSameDevice (UsbRndisDataPath, UsbCdcData= Path);

+=C2=A0 =C2=A0 =C2=A0 DEBUG ((EFI_D_VERBOSE, "Rndis IsSameDevice %r\n&= quot;, Status));

+=C2=A0 =C2=A0 =C2=A0 if (!EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbRndisDevice->UsbCdcDataHandle =3D Handle= Buffer[Index];

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbRndisDevice->UsbIoCdcData=C2=A0 =C2=A0 = =C2=A0=3D UsbIo;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 GetEndpoint (UsbRndisDevice->UsbIoCdcData, = UsbRndisDevice);

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 gBS->FreePool (HandleBuffer);

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return;

+=C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 }

+=C2=A0 }=C2=A0 =C2=A0// End of For loop

+

+=C2=A0 gBS->FreePool (HandleBuffer);

+}

+

+/**

+

+=C2=A0 For the given UsbIo CdcData, find a matching RNDIS device already e= xists or not.

+

+=C2=A0 @param[in]=C2=A0 CdcHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0A pointer to t= he EFI_HANDLE for USB CDC Data.

+=C2=A0 @param[out] CdcUsbIo=C2=A0 =C2=A0 =C2=A0 =C2=A0 A pointer for retri= eve the EFI_USB_IO_PROTOCOL instance.

+=C2=A0 @param[out] RndisHandle=C2=A0 =C2=A0 =C2=A0A pointer for retrieve t= he handle of RNDIS device.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= The USB_RNDIS_DEVICE matching this CDC Data is found.

+=C2=A0 @retval EFI_NOT_FOUND=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The U= SB_RNDIS_DEVICE matching this CDC Data is not found.

+

+**/

+EFI_STATUS

+EFIAPI

+FindMatchingRndisDev (

+=C2=A0 IN=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0CdcHand= le,

+=C2=A0 OUT EFI_USB_IO_PROTOCOL=C2=A0 **CdcUsbIo,

+=C2=A0 OUT EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*RndisHandle=

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 S= tatus;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0Index;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0HandleCount;

+=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *= HandleBuffer;

+=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0*UsbIo;

+=C2=A0 EFI_DEVICE_PATH_PROTOCOL=C2=A0 *UsbRndisDataPath;

+=C2=A0 EFI_DEVICE_PATH_PROTOCOL=C2=A0 *UsbCdcDataPath;

+

+=C2=A0 // Find the parent RNDIS and update the UsbIo for the CDC device
+=C2=A0 Status =3D gBS->HandleProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 CdcHandle,<= br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiDe= vicePathProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOID **)&a= mp;UsbCdcDataPath

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 Status =3D gBS->LocateHandleBuffer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ByProtocol,=

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiUs= bIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NULL,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Handle= Count,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Handle= Buffer

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 for (Index =3D 0; Index < HandleCount; Index++) {

+=C2=A0 =C2=A0 Status =3D gBS->HandleProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Hand= leBuffer[Index],

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &= ;gEfiUsbIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOI= D **)&UsbIo

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );
+=C2=A0 =C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 =C2=A0 if (IsUsbRndis (UsbIo)) {

+=C2=A0 =C2=A0 =C2=A0 Status =3D gBS->HandleProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 HandleBuffer[Index],

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 &gEfiDevicePathProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 (VOID **)&UsbRndisDataPath

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 );

+=C2=A0 =C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 DEBUG ((EFI_D_ERROR, "Usb Rndis DevicePat= h not found\n"));

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 Status =3D IsSameDevice (UsbRndisDataPath, UsbCdcData= Path);

+

+=C2=A0 =C2=A0 =C2=A0 if (!EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 *RndisHandle =3D HandleBuffer[Index];

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 *CdcUsbIo=C2=A0 =C2=A0 =3D UsbIo;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 gBS->FreePool (HandleBuffer);

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return Status;

+=C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 }

+=C2=A0 }=C2=A0 =C2=A0// End of For loop

+

+=C2=A0 gBS->FreePool (HandleBuffer);

+

+=C2=A0 return EFI_NOT_FOUND;

+}

+

+/**

+=C2=A0 USB Rndis Driver Binding Support.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 Protocol instance pointer.

+=C2=A0 @param[in]=C2=A0 ControllerHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0 Handle= of device to test.

+=C2=A0 @param[in]=C2=A0 RemainingDevicePath=C2=A0 =C2=A0 =C2=A0Optional pa= rameter use to pick a specific child

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 device to start= .

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0This driver supports this device.

+=C2=A0 @retval EFI_ALREADY_STARTED=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This d= river is already running on this device.

+=C2=A0 @retval other=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This driver does not support this device.
+

+**/

+EFI_STATUS

+EFIAPI

+UsbRndisDriverSupported (

+=C2=A0 IN EFI_DRIVER_BINDING_PROTOCOL=C2=A0 *This,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 IN EFI_DEVICE_PATH_PROTOCOL=C2=A0 =C2=A0 =C2=A0*RemainingDevicePath=

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Status;

+=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 *UsbIo =3D NULL;

+

+=C2=A0 Status =3D gBS->OpenProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiUs= bIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOID **)&a= mp;UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This->Dr= iverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_OPEN_PR= OTOCOL_BY_DRIVER

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 Status =3D IsSupportedDevice (UsbIo) ? EFI_SUCCESS : EFI_UNSUPPORTE= D;

+

+=C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gEfiUsbIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 USB RNDIS Driver Binding Start.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 Protocol instance pointer.

+=C2=A0 @param[in]=C2=A0 ControllerHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0 Handle= of device to bind driver to.

+=C2=A0 @param[in]=C2=A0 RemainingDevicePath=C2=A0 =C2=A0 =C2=A0Optional pa= rameter use to pick a specific child

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 device to start= .

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0This driver is added to ControllerHandle

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 T= his driver could not be started due to a device error

+=C2=A0 @retval EFI_OUT_OF_RESOURCES=C2=A0 =C2=A0 =C2=A0 =C2=A0 The driver = could not install successfully due to a lack of resources.

+=C2=A0 @retval other=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This driver does not support this device

+

+**/

+EFI_STATUS

+EFIAPI

+UsbRndisDriverStart (

+=C2=A0 IN EFI_DRIVER_BINDING_PROTOCOL=C2=A0 *This,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 IN EFI_DEVICE_PATH_PROTOCOL=C2=A0 =C2=A0 =C2=A0*RemainingDevicePath=

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 Status;

+=C2=A0 USB_RNDIS_DEVICE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *U= sbRndisDevice;

+=C2=A0 EFI_DEVICE_PATH_PROTOCOL=C2=A0 =C2=A0 =C2=A0 *UsbEthPath;

+=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*UsbIo;=

+=C2=A0 EFI_USB_INTERFACE_DESCRIPTOR=C2=A0 Interface;

+=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 RndisHandle =3D ControllerHandle;

+

+=C2=A0 Status =3D gBS->OpenProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiUs= bIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOID **)&a= mp;UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This->Dr= iverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_OPEN_PR= OTOCOL_BY_DRIVER

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 Status =3D gBS->OpenProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiDe= vicePathProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOID **)&a= mp;UsbEthPath,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This->Dr= iverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_OPEN_PR= OTOCOL_BY_DRIVER

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gEfiUsbIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gEfiDevicePathProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+

+=C2=A0 DEBUG ((EFI_D_ERROR, "UsbRndisDriverStart %x\n", Controll= erHandle));

+

+=C2=A0 // Controls come here for RNDIS and CDC. If it is CDC, check whethe= r RNDIS is present on the same controller or not.

+=C2=A0 if (IsUsbCdcData (UsbIo)) {

+=C2=A0 =C2=A0 // Find the parent RNDIS and update the UsbIo for the CDC de= vice

+=C2=A0 =C2=A0 Status =3D UpdateRndisDevice (UsbEthPath, &UsbRndisDevic= e);

+

+=C2=A0 =C2=A0 if (!EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 DEBUG ((EFI_D_VERBOSE, "Rndis Matching interface= found\n"));

+=C2=A0 =C2=A0 =C2=A0 UsbRndisDevice->UsbCdcDataHandle =3D ControllerHan= dle;

+=C2=A0 =C2=A0 =C2=A0 UsbRndisDevice->UsbIoCdcData=C2=A0 =C2=A0 =C2=A0= =3D UsbIo;

+=C2=A0 =C2=A0 =C2=A0 GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndi= sDevice);

+=C2=A0 =C2=A0 =C2=A0 return Status;

+=C2=A0 =C2=A0 } else {

+=C2=A0 =C2=A0 =C2=A0 // Check if RnDis exist

+=C2=A0 =C2=A0 =C2=A0 Status =3D FindMatchingRndisDev (ControllerHandle, &a= mp;UsbIo, &RndisHandle);

+

+=C2=A0 =C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gEfiUsbIoProto= colGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBind= ingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return Status;

+=C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 }

+=C2=A0 }

+

+=C2=A0 UsbRndisDevice =3D AllocateZeroPool (sizeof (USB_RNDIS_DEVICE));
+

+=C2=A0 if (!UsbRndisDevice) {

+=C2=A0 =C2=A0 DEBUG ((EFI_D_ERROR, "AllocateZeroPool Fail\n"));<= br>
+

+=C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gEfiUsbIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 =C2=A0 return EFI_OUT_OF_RESOURCES;

+=C2=A0 }

+

+=C2=A0 Status =3D LoadAllDescriptor (UsbIo, &UsbRndisDevice->Config= );

+=C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interfa= ce);

+=C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 UsbRndisDevice->Signature=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =3D USB_RNDIS_SIGNATUR= E;

+=C2=A0 UsbRndisDevice->NumOfInterface=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D Interface.InterfaceNumber;
+=C2=A0 UsbRndisDevice->UsbRndisHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D RndisHandle;

+=C2=A0 UsbRndisDevice->UsbCdcDataHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D 0;

+=C2=A0 UsbRndisDevice->UsbIo=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =3D UsbIo;
+=C2=A0 UsbRndisDevice->UsbEth.UsbEthReceive=C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D RndisUndiReceive;

+=C2=A0 UsbRndisDevice->UsbEth.UsbEthTransmit=C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =3D RndisUndiTransmit;

+=C2=A0 UsbRndisDevice->UsbEth.UsbEthInterrupt=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0=3D UsbRndisInterrupt;

+=C2=A0 UsbRndisDevice->UsbEth.UsbEthMacAddress=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =3D GetUsbEthMacAddress;

+=C2=A0 UsbRndisDevice->UsbEth.UsbEthMaxBulkSize=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0=3D UsbEthBulkSize;

+=C2=A0 UsbRndisDevice->UsbEth.UsbHeaderFunDescriptor=C2=A0 =C2=A0 =C2= =A0 =3D GetUsbHeaderFunDescriptor;

+=C2=A0 UsbRndisDevice->UsbEth.UsbUnionFunDescriptor=C2=A0 =C2=A0 =C2=A0= =C2=A0=3D GetUsbUnionFunDescriptor;

+=C2=A0 UsbRndisDevice->UsbEth.UsbEthFunDescriptor=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0=3D GetUsbRndisFunDescriptor;

+=C2=A0 UsbRndisDevice->UsbEth.SetUsbEthMcastFilter=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =3D SetUsbRndisMcastFilter;

+=C2=A0 UsbRndisDevice->UsbEth.SetUsbEthPowerPatternFilter =3D SetUsbRnd= isPowerFilter;

+=C2=A0 UsbRndisDevice->UsbEth.GetUsbEthPoewrPatternFilter =3D GetUsbRnd= isPowerFilter;

+=C2=A0 UsbRndisDevice->UsbEth.SetUsbEthPacketFilter=C2=A0 =C2=A0 =C2=A0= =C2=A0=3D SetUsbRndisPacketFilter;

+=C2=A0 UsbRndisDevice->UsbEth.GetUsbEthStatistic=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =3D GetRndisStatistic;

+

+=C2=A0 UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetState=C2=A0 =C2= =A0 =C2=A0 =C2=A0 =3D RndisDummyReturn;

+=C2=A0 UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStart=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D RndisUndiStart;

+=C2=A0 UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStop=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =3D RndisUndiStop;

+=C2=A0 UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetInitInfo=C2=A0 = =C2=A0 =C2=A0=3D RndisUndiGetInitInfo;

+=C2=A0 UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetConfigInfo=C2=A0 = =C2=A0=3D RndisUndiGetConfigInfo;

+=C2=A0 UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiInitialize=C2=A0 =C2= =A0 =C2=A0 =3D RndisUndiInitialize;

+=C2=A0 UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiReset=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D RndisUndiReset;

+=C2=A0 UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiShutdown=C2=A0 =C2= =A0 =C2=A0 =C2=A0 =3D RndisUndiShutdown;

+=C2=A0 UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiInterruptEnable =3D = RndisDummyReturn;

+=C2=A0 UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiReceiveFilter=C2=A0 = =C2=A0=3D RndisUndiReceiveFilter;

+=C2=A0 UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStationAddress=C2=A0= =3D RndisDummyReturn;

+=C2=A0 UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStatistics=C2=A0 =C2= =A0 =C2=A0 =3D NULL;

+=C2=A0 UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiMcastIp2Mac=C2=A0 = =C2=A0 =C2=A0=3D RndisDummyReturn;

+=C2=A0 UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiNvData=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =3D RndisDummyReturn;

+=C2=A0 UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetStatus=C2=A0 =C2= =A0 =C2=A0 =C2=A0=3D RndisUndiGetStatus;

+=C2=A0 UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiFillHeader=C2=A0 =C2= =A0 =C2=A0 =3D RndisDummyReturn;

+=C2=A0 UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiTransmit=C2=A0 =C2= =A0 =C2=A0 =C2=A0 =3D NULL;

+=C2=A0 UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiReceive=C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0=3D NULL;

+

+=C2=A0 UsbRndisDevice->MaxTransferSize=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D RN= DIS_MAX_TRANSFER_SIZE;

+=C2=A0 UsbRndisDevice->MaxPacketsPerTransfer =3D 1;

+=C2=A0 UsbRndisDevice->PacketAlignmentFactor =3D 0;

+

+=C2=A0 InitializeListHead (&UsbRndisDevice->ReceivePacketList);

+

+=C2=A0 // This is a RNDIS interface. See whether CDC-DATA interface has al= ready been connected or not

+=C2=A0 FindMatchingCdcData (UsbRndisDevice);

+

+=C2=A0 if (UsbRndisDevice->UsbIoCdcData) {

+=C2=A0 =C2=A0 Status =3D gBS->InstallProtocolInterface (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &= ;ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &= ;gUsbEthProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_= NATIVE_INTERFACE,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &= ;(UsbRndisDevice->UsbEth)

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );
+=C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&gEfiUsbIoProtocolGuid= ,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0This->DriverBindingHand= le,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+

+=C2=A0 =C2=A0 =C2=A0 gBS->FreePool (UsbRndisDevice->Config);

+=C2=A0 =C2=A0 =C2=A0 gBS->FreePool (UsbRndisDevice);

+=C2=A0 =C2=A0 =C2=A0 return Status;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 GetEndpoint (UsbRndisDevice->UsbIo, UsbRndisDevice);

+

+=C2=A0 =C2=A0 DEBUG ((EFI_D_ERROR, "Rndis DeviceHandle %r\n", Us= bRndisDevice->UsbRndisHandle));

+=C2=A0 =C2=A0 DEBUG ((EFI_D_ERROR, "CDC DeviceHandle %r\n", UsbR= ndisDevice->UsbCdcDataHandle));

+=C2=A0 =C2=A0 return EFI_SUCCESS;

+=C2=A0 }

+

+=C2=A0 gBS->FreePool (UsbRndisDevice->Config);

+=C2=A0 gBS->FreePool (UsbRndisDevice);

+

+=C2=A0 return EFI_SUCCESS;

+}

+

+/**

+=C2=A0 CheckandStopRndisDevice

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0Protocol instance pointer.

+=C2=A0 @param[in]=C2=A0 ControllerHandle=C2=A0 =C2=A0 =C2=A0Handle of devi= ce to bind driver to.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This driver i= s added to ControllerHandle

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0This driver could not b= e started due to a device error

+=C2=A0 @retval other=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 This driver does not support this device

+

+**/

+EFI_STATUS

+EFIAPI

+CheckandStopRndisDevice (

+=C2=A0 IN=C2=A0 EFI_DRIVER_BINDING_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0ControllerHandle

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Status;

+=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 *UsbIo;

+

+=C2=A0 Status =3D gBS->OpenProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiUs= bIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOID **)&a= mp;UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This->Dr= iverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_OPEN_PR= OTOCOL_GET_PROTOCOL

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 if (IsUsbRndis (UsbIo)) {

+=C2=A0 =C2=A0 Status =3D gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Cont= rollerHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &= ;gEfiUsbIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This= ->DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Cont= rollerHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );
+=C2=A0 =C2=A0 DEBUG ((EFI_D_ERROR, "Rndis ControllerHandle Stop %r\n&= quot;, Status));

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 return EFI_UNSUPPORTED;

+}

+

+/**

+=C2=A0 USB Rndis Driver Binding Stop.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 Protocol instance pointer.

+=C2=A0 @param[in]=C2=A0 ControllerHandle=C2=A0 =C2=A0 =C2=A0 Handle of dev= ice to stop driver on

+=C2=A0 @param[in]=C2=A0 NumberOfChildren=C2=A0 =C2=A0 =C2=A0 Number of Han= dles in ChildHandleBuffer. If number of

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 children is zero stop = the entire bus driver.

+=C2=A0 @param[in]=C2=A0 ChildHandleBuffer=C2=A0 =C2=A0 =C2=A0List of Child= Handles to Stop.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0This driver is removed ControllerHandle

+=C2=A0 @retval other=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0This driver was not removed from this device

+

+**/

+EFI_STATUS

+EFIAPI

+UsbRndisDriverStop (

+=C2=A0 IN=C2=A0 EFI_DRIVER_BINDING_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 IN=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NumberOfChildren,

+=C2=A0 IN=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0*ChildHandleBuffer

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Status;
+=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *UsbEthProtocol;

+=C2=A0 USB_RNDIS_DEVICE=C2=A0 =C2=A0 =C2=A0 =C2=A0*UsbRndisDevice;

+

+=C2=A0 DEBUG ((EFI_D_ERROR, "UsbRndisDriverStop ControllerHandle %lx\= n", ControllerHandle));

+

+=C2=A0 Status =3D gBS->OpenProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gUsbEt= hProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOID **)&a= mp;UsbEthProtocol,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This->Dr= iverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EFI_OPEN_PR= OTOCOL_GET_PROTOCOL

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 Status =3D CheckandStopRndisDevice (This, ControllerHandle);=

+

+=C2=A0 =C2=A0 DEBUG ((EFI_D_ERROR, "CheckandStopRndisDevice %r\n"= ;, Status));

+

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (UsbEthProtocol);

+

+=C2=A0 Status =3D gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbRndisDev= ice->UsbCdcDataHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiUs= bIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This->Dr= iverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbRndisDev= ice->UsbCdcDataHandle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+

+=C2=A0 Status =3D gBS->UninstallProtocolInterface (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gUsbEt= hProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthProto= col

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 DEBUG ((EFI_D_ERROR, "EFI_ERROR %r\n", Status));
+

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 Status =3D gBS->CloseProtocol (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiUs= bIoProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 This->Dr= iverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ControllerH= andle

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+

+=C2=A0 gBS->FreePool (UsbRndisDevice->Config);

+=C2=A0 gBS->FreePool (UsbRndisDevice);

+

+=C2=A0 DEBUG ((EFI_D_ERROR, "UsbRndisDriverStop %r\n", Status));=

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Entrypoint of RNDIS Driver.

+

+=C2=A0 This function is the entrypoint of RNDIS Driver. It installs Driver= Binding

+=C2=A0 Protocols together with Component Name Protocols.

+

+=C2=A0 @param[in]=C2=A0 ImageHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0The firmware= allocated handle for the EFI image.

+=C2=A0 @param[in]=C2=A0 SystemTable=C2=A0 =C2=A0 =C2=A0 =C2=A0A pointer to= the EFI System Table.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The ent= ry point is executed successfully.

+

+**/

+EFI_STATUS

+EFIAPI

+UsbRndisEntry (

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 ImageHandle,

+=C2=A0 IN EFI_SYSTEM_TABLE=C2=A0 *SystemTable

+=C2=A0 )

+{

+=C2=A0 gUsbRndisDriverBinding.DriverBindingHandle =3D ImageHandle;

+=C2=A0 gUsbRndisDriverBinding.ImageHandle=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0=3D ImageHandle;

+

+=C2=A0 return gBS->InstallMultipleProtocolInterfaces (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gUsbRndisDriv= erBinding.DriverBindingHandle,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiDriverBin= dingProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gUsbRndisDriv= erBinding,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gEfiComponent= Name2ProtocolGuid,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &gUsbRndisComp= onentName2,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NULL

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+}

diff --git a/UsbNetworkPkg/UsbRndis/UsbRndis.h b/UsbNetworkPkg/UsbRndis/Usb= Rndis.h
new file mode 100644
index 0000000000..680a9e67c9
--- /dev/null
+++ b/UsbNetworkPkg/UsbRndis/UsbRndis.h
@@ -0,0 +1,569 @@
+/** @file

+=C2=A0 Header file for for USB Rndis driver

+

+=C2=A0 Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+=C2=A0 Subject to AMI licensing agreement.

+**/

+

+#ifndef _USB_RNDIS_H_

+#define _USB_RNDIS_H_

+

+#include <Library/UefiDriverEntryPoint.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <Library/UefiLib.h>

+#include <Library/DevicePathLib.h>

+#include <Library/DebugLib.h>

+#include <Library/MemoryAllocationLib.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/UefiUsbLib.h>

+#include <Protocol/UsbIo.h>

+#include <Protocol/UsbEthernetProtocol.h>

+

+typedef struct _REMOTE_NDIS_MSG_HEADER REMOTE_NDIS_MSG_HEADER;

+

+typedef struct {

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0Signature;

+=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEth;

+=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0UsbCdcDataHandle;

+=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0UsbRndisHandle;

+=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbIo;

+=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbIoCdcData= ;

+=C2=A0 EFI_USB_CONFIG_DESCRIPTOR=C2=A0 =C2=A0 *Config;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 NumOfInterface;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 BulkInEndpoint;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 BulkOutEndpoint;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 InterrupEndpoint;

+=C2=A0 EFI_MAC_ADDRESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Mac= Address;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0RequestId;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0Medium;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0MaxPacketsPerTransfer;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0MaxTransferSize;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0PacketAlignmentFactor;

+=C2=A0 LIST_ENTRY=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0ReceivePacketList;

+} USB_RNDIS_DEVICE;

+

+#define USB_RNDIS_DRIVER_VERSION=C2=A0 =C2=A0 =C2=A0 =C2=A01

+#define USB_TX_ETHERNET_BULK_TIMEOUT=C2=A0 =C2=A03000

+#define USB_RX_ETHERNET_BULK_TIMEOUT=C2=A0 =C2=A03

+#define USB_ETHERNET_TRANSFER_TIMEOUT=C2=A0 200

+

+#define LAN_BULKIN_CMD_CONTROL=C2=A0 1

+#define MAXIMUM_STOPBULKIN_CNT=C2=A0 300=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 // Indicating maximum counts for waiting bulk in command

+#define MINIMUM_STOPBULKIN_CNT=C2=A0 3=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 // Indicating minimum counts for waiting bulk in command

+#define BULKIN_CMD_POLLING_CNT=C2=A0 300=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 // Indicating the waiting counts for send bulk in command when syst= em pending

+

+#define USB_RNDIS_SIGNATURE=C2=A0 SIGNATURE_32('r', 'n', &= #39;d', 's')

+#define USB_RNDIS_DEVICE_FROM_THIS(a)=C2=A0 CR (a, USB_RNDIS_DEVICE, UsbEt= h, USB_RNDIS_SIGNATURE)

+

+struct BIT_MAP {

+=C2=A0 unsigned int=C2=A0 =C2=A0 Src;

+=C2=A0 unsigned int=C2=A0 =C2=A0 Dst;

+};

+

+EFI_STATUS

+EFIAPI

+UsbRndisDriverSupported (

+=C2=A0 IN EFI_DRIVER_BINDING_PROTOCOL=C2=A0 *This,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 IN EFI_DEVICE_PATH_PROTOCOL=C2=A0 =C2=A0 =C2=A0*RemainingDevicePath=

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+UsbRndisDriverStart (

+=C2=A0 IN EFI_DRIVER_BINDING_PROTOCOL=C2=A0 *This,

+=C2=A0 IN EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 IN EFI_DEVICE_PATH_PROTOCOL=C2=A0 =C2=A0 =C2=A0*RemainingDevicePath=

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+UsbRndisDriverStop (

+=C2=A0 IN=C2=A0 EFI_DRIVER_BINDING_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0ControllerHandle,

+=C2=A0 IN=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NumberOfChildren,

+=C2=A0 IN=C2=A0 EFI_HANDLE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0*ChildHandleBuffer

+=C2=A0 );

+

+EFI_STATUS

+LoadAllDescriptor (

+=C2=A0 IN=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbIo,

+=C2=A0 OUT EFI_USB_CONFIG_DESCRIPTOR=C2=A0 **ConfigDesc

+=C2=A0 );

+

+BOOLEAN

+NextDescriptor (

+=C2=A0 IN EFI_USB_CONFIG_DESCRIPTOR=C2=A0 *Desc,

+=C2=A0 IN OUT UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 *Offset

+=C2=A0 );

+

+EFI_STATUS

+GetFunctionalDescriptor (

+=C2=A0 IN=C2=A0 EFI_USB_CONFIG_DESCRIPTOR=C2=A0 *Config,

+=C2=A0 IN=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 FunDescriptorType,

+=C2=A0 OUT VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0*DataBuffer

+=C2=A0 );

+

+VOID

+GetEndpoint (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 *UsbIo,

+=C2=A0 IN OUT=C2=A0 USB_RNDIS_DEVICE=C2=A0 =C2=A0 =C2=A0*UsbRndisDevice
+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+UsbRndisInterrupt (

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0*This,

+=C2=A0 IN BOOLEAN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0IsNewTransfer,

+=C2=A0 IN UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0PollingInterval,

+=C2=A0 IN EFI_USB_DEVICE_REQUEST=C2=A0 *Requst

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+InterruptCallback (

+=C2=A0 IN=C2=A0 VOID=C2=A0 =C2=A0 *Data,

+=C2=A0 IN=C2=A0 UINTN=C2=A0 =C2=A0DataLength,

+=C2=A0 IN=C2=A0 VOID=C2=A0 =C2=A0 *Context,

+=C2=A0 IN=C2=A0 UINT32=C2=A0 Status

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+GetUsbEthMacAddress (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 OUT EFI_MAC_ADDRESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 *MacAddress

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+UsbEthBulkSize (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 OUT UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 *BulkSize

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+RndisDummyReturn (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+RndisUndiStart (

+=C2=A0 IN PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+RndisUndiStop (

+=C2=A0 IN PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+RndisUndiGetInitInfo (

+=C2=A0 IN PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+RndisUndiGetConfigInfo (

+=C2=A0 IN PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+RndisUndiInitialize (

+=C2=A0 IN PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+RndisUndiTransmit (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 PXE_CDB=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 *Cdb,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*BulkOutData,

+=C2=A0 IN OUT=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 *DataLength

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+RndisUndiReceive (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0PXE_CDB=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 *Cdb,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN OUT VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0*BulkInData,

+=C2=A0 IN OUT UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 *DataLength

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+RndisUndiReset (

+=C2=A0 IN PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+RndisUndiShutdown (

+=C2=A0 IN PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+RndisUndiReceiveFilter (

+=C2=A0 IN PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+RndisUndiGetStatus (

+=C2=A0 IN PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN NIC_DATA=C2=A0 *Nic

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+GetUsbHeaderFunDescriptor (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0 *This,

+=C2=A0 OUT USB_HEADER_FUN_DESCRIPTOR=C2=A0 *UsbHeaderFunDescriptor

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+GetUsbUnionFunDescriptor (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0*This,

+=C2=A0 OUT USB_UNION_FUN_DESCRIPTOR=C2=A0 *UsbUnionFunDescriptor

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+GetUsbRndisFunDescriptor (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 *This,
+=C2=A0 OUT USB_ETHERNET_FUN_DESCRIPTOR=C2=A0 *UsbEthFunDescriptor

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+SetUsbRndisMcastFilter (

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Value,

+=C2=A0 IN VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0*McastAddr

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+SetUsbRndisPowerFilter (

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Value,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Length,

+=C2=A0 IN VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0*PatternFilter

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+GetUsbRndisPowerFilter (

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Value,

+=C2=A0 IN BOOLEAN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *= PatternActive

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+SetUsbRndisPacketFilter (

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Value

+=C2=A0 );

+

+EFI_STATUS

+EFIAPI

+GetRndisStatistic (

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Value,

+=C2=A0 IN VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0*Statistic

+=C2=A0 );

+

+EFI_STATUS

+SendRndisSetMsg (

+=C2=A0 IN=C2=A0 USB_RNDIS_DEVICE=C2=A0 *UsbRndisDevice,

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= Oid,

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Lengt= h,

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= *Buf

+=C2=A0 );

+

+EFI_STATUS

+RndisControlMsg (

+=C2=A0 IN=C2=A0 USB_RNDIS_DEVICE=C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbRndisDevic= e,

+=C2=A0 IN=C2=A0 REMOTE_NDIS_MSG_HEADER=C2=A0 *RndisMsg,

+=C2=A0 OUT REMOTE_NDIS_MSG_HEADER=C2=A0 *RndisMsgResponse

+=C2=A0 );

+

+EFI_STATUS

+RndisTransmitDataMsg (

+=C2=A0 IN=C2=A0 USB_RNDIS_DEVICE=C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbRndisDevic= e,

+=C2=A0 IN=C2=A0 REMOTE_NDIS_MSG_HEADER=C2=A0 *RndisMsg,

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0*TransferLength

+=C2=A0 );

+

+EFI_STATUS

+RndisReceiveDataMsg (

+=C2=A0 IN=C2=A0 USB_RNDIS_DEVICE=C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbRndisDevic= e,

+=C2=A0 IN=C2=A0 REMOTE_NDIS_MSG_HEADER=C2=A0 *RndisMsg,

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0*TransferLength

+=C2=A0 );

+

+VOID

+PrintRndisMsg (

+=C2=A0 IN=C2=A0 REMOTE_NDIS_MSG_HEADER=C2=A0 *RndisMsg

+=C2=A0 );

+

+#define RNDIS_MAJOR_VERSION=C2=A0 =C2=A0 =C2=A0 0x00000001

+#define RNDIS_MINOR_VERSION=C2=A0 =C2=A0 =C2=A0 0x00000000

+#define RNDIS_MAX_TRANSFER_SIZE=C2=A0 0x4000

+

+#define RNDIS_PACKET_MSG=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x0000000= 1

+#define RNDIS_INITIALIZE_MSG=C2=A0 =C2=A0 =C2=A0 =C2=A00x00000002

+#define RNDIS_INITIALIZE_CMPLT=C2=A0 =C2=A0 =C2=A00x80000002

+#define RNDIS_HLT_MSG=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x00= 000003

+#define RNDIS_QUERY_MSG=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x0000000= 4

+#define RNDIS_QUERY_CMPLT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x80000004

+#define RNDIS_SET_MSG=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x00= 000005

+#define RNDIS_SET_CMPLT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x8000000= 5

+#define RNDIS_RESET_MSG=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x0000000= 6

+#define RNDIS_RESET_CMPLT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x80000006

+#define RNDIS_INDICATE_STATUS_MSG=C2=A0 0x00000007

+#define RNDIS_KEEPALIVE_MSG=C2=A0 =C2=A0 =C2=A0 =C2=A0 0x00000008

+#define RNDIS_KEEPALIVE_CMPLT=C2=A0 =C2=A0 =C2=A0 0x80000008

+

+#define RNDIS_STATUS_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x000= 00000

+#define RNDIS_STATUS_FAILURE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00xC00= 00001

+#define RNDIS_STATUS_INVALID_DATA=C2=A0 =C2=A0 =C2=A0 0xC0010015

+#define RNDIS_STATUS_NOT_SUPPORTED=C2=A0 =C2=A0 =C2=A00xC00000BB

+#define RNDIS_STATUS_MEDIA_CONNECT=C2=A0 =C2=A0 =C2=A00x4001000B

+#define RNDIS_STATUS_MEDIA_DISCONNECT=C2=A0 0x4001000C

+

+#define RNDIS_CONTROL_TIMEOUT=C2=A0 =C2=A0 10000=C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 // 10sec

+#define RNDIS_KEEPALIVE_TIMEOUT=C2=A0 5000=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0// 5sec

+

+#define SEND_ENCAPSULATED_COMMAND=C2=A0 0x00000000

+#define GET_ENCAPSULATED_RESPONSE=C2=A0 0x00000001

+

+//

+// General Objects

+//

+// Taken from NTDDNDIS.H

+#define OID_GEN_SUPPORTED_LIST=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x00010101=

+#define OID_GEN_HARDWARE_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 0x00010102

+#define OID_GEN_MEDIA_SUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0 0x00010103

+#define OID_GEN_MEDIA_IN_USE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x000= 10104

+#define OID_GEN_MAXIMUM_LOOKAHEAD=C2=A0 =C2=A0 =C2=A0 0x00010105

+#define OID_GEN_MAXIMUM_FRAME_SIZE=C2=A0 =C2=A0 =C2=A00x00010106

+#define OID_GEN_LINK_SPEED=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= 0x00010107

+#define OID_GEN_TRANSMIT_BUFFER_SPACE=C2=A0 0x00010108

+#define OID_GEN_RECEIVE_BUFFER_SPACE=C2=A0 =C2=A00x00010109

+#define OID_GEN_TRANSMIT_BLOCK_SIZE=C2=A0 =C2=A0 0x0001010A

+#define OID_GEN_RECEIVE_BLOCK_SIZE=C2=A0 =C2=A0 =C2=A00x0001010B

+#define OID_GEN_VENDOR_ID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = 0x0001010C

+#define OID_GEN_VENDOR_DESCRIPTION=C2=A0 =C2=A0 =C2=A00x0001010D

+#define OID_GEN_CURRENT_PACKET_FILTER=C2=A0 0x0001010E

+#define OID_GEN_CURRENT_LOOKAHEAD=C2=A0 =C2=A0 =C2=A0 0x0001010F

+#define OID_GEN_DRIVER_VERSION=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x00010110=

+#define OID_GEN_MAXIMUM_TOTAL_SIZE=C2=A0 =C2=A0 =C2=A00x00010111

+#define OID_GEN_PROTOCOL_OPTIONS=C2=A0 =C2=A0 =C2=A0 =C2=A00x00010112

+#define OID_GEN_MAC_OPTIONS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x000= 10113

+#define OID_GEN_MEDIA_CONNECT_STATUS=C2=A0 =C2=A00x00010114

+#define OID_GEN_MAXIMUM_SEND_PACKETS=C2=A0 =C2=A00x00010115

+#define OID_GEN_VENDOR_DRIVER_VERSION=C2=A0 0x00010116

+

+#define OID_GEN_XMIT_OK=C2=A0 =C2=A0 =C2=A0 =C2=A0 0x00020101

+#define OID_GEN_RCV_OK=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x00020102

+#define OID_GEN_XMIT_ERROR=C2=A0 =C2=A0 =C2=A00x00020103

+#define OID_GEN_RCV_ERROR=C2=A0 =C2=A0 =C2=A0 0x00020104

+#define OID_GEN_RCV_NO_BUFFER=C2=A0 0x00020105

+

+#define OID_GEN_DIRECTED_BYTES_XMIT=C2=A0 =C2=A0 0x00020201

+#define OID_GEN_DIRECTED_FRAMES_XMIT=C2=A0 =C2=A00x00020202

+#define OID_GEN_MULTICAST_BYTES_XMIT=C2=A0 =C2=A00x00020203

+#define OID_GEN_MULTICAST_FRAMES_XMIT=C2=A0 0x00020204

+#define OID_GEN_BROADCAST_BYTES_XMIT=C2=A0 =C2=A00x00020205

+#define OID_GEN_BROADCAST_FRAMES_XMIT=C2=A0 0x00020206

+#define OID_GEN_DIRECTED_BYTES_RCV=C2=A0 =C2=A0 =C2=A00x00020207

+#define OID_GEN_DIRECTED_FRAMES_RCV=C2=A0 =C2=A0 0x00020208

+#define OID_GEN_MULTICAST_BYTES_RCV=C2=A0 =C2=A0 0x00020209

+#define OID_GEN_MULTICAST_FRAMES_RCV=C2=A0 =C2=A00x0002020A

+#define OID_GEN_BROADCAST_BYTES_RCV=C2=A0 =C2=A0 0x0002020B

+#define OID_GEN_BROADCAST_FRAMES_RCV=C2=A0 =C2=A00x0002020C

+#define OID_GEN_RCV_CRC_ERROR=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x0002020D=

+#define OID_GEN_TRANSMIT_QUEUE_LENGTH=C2=A0 0x0002020E

+

+//

+// Ndis Packet Filter Bits (OID_GEN_CURRENT_PACKET_FILTER).

+//

+#define NDIS_PACKET_TYPE_DIRECTED=C2=A0 =C2=A0 =C2=A0 =C2=A0 0x0001

+#define NDIS_PACKET_TYPE_MULTICAST=C2=A0 =C2=A0 =C2=A0 =C2=A00x0002

+#define NDIS_PACKET_TYPE_ALL_MULTICAST=C2=A0 =C2=A00x0004

+#define NDIS_PACKET_TYPE_BROADCAST=C2=A0 =C2=A0 =C2=A0 =C2=A00x0008

+#define NDIS_PACKET_TYPE_SOURCE_ROUTING=C2=A0 0x0010

+#define NDIS_PACKET_TYPE_PROMISCUOUS=C2=A0 =C2=A0 =C2=A00x0020

+#define NDIS_PACKET_TYPE_SMT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A00x0040

+#define NDIS_PACKET_TYPE_ALL_LOCAL=C2=A0 =C2=A0 =C2=A0 =C2=A00x0080

+#define NDIS_PACKET_TYPE_MAC_FRAME=C2=A0 =C2=A0 =C2=A0 =C2=A00x8000

+#define NDIS_PACKET_TYPE_FUNCTIONAL=C2=A0 =C2=A0 =C2=A0 0x4000

+#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL=C2=A0 0x2000

+#define NDIS_PACKET_TYPE_GROUP=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00x1= 000

+

+#pragma pack(1)

+

+typedef struct _REMOTE_NDIS_MSG_HEADER {

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageType;

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageLength;

+} REMOTE_NDIS_MSG_HEADER;

+

+typedef struct {

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageType;

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageLength;

+=C2=A0 UINT32=C2=A0 =C2=A0 RequestID;

+=C2=A0 UINT32=C2=A0 =C2=A0 MajorVersion;

+=C2=A0 UINT32=C2=A0 =C2=A0 MinorVersion;

+=C2=A0 UINT32=C2=A0 =C2=A0 MaxTransferSize;

+} REMOTE_NDIS_INITIALIZE_MSG;

+

+typedef struct {

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageType;

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageLength;

+=C2=A0 UINT32=C2=A0 =C2=A0 RequestID;

+} REMOTE_NDIS_HALT_MSG;

+

+typedef struct {

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageType;

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageLength;

+=C2=A0 UINT32=C2=A0 =C2=A0 RequestID;

+=C2=A0 UINT32=C2=A0 =C2=A0 Oid;

+=C2=A0 UINT32=C2=A0 =C2=A0 InformationBufferLength;

+=C2=A0 UINT32=C2=A0 =C2=A0 InformationBufferOffset;

+=C2=A0 UINT32=C2=A0 =C2=A0 Reserved;

+} REMOTE_NDIS_QUERY_MSG;

+

+typedef struct {

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageType;

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageLength;

+=C2=A0 UINT32=C2=A0 =C2=A0 RequestID;

+=C2=A0 UINT32=C2=A0 =C2=A0 Oid;

+=C2=A0 UINT32=C2=A0 =C2=A0 InformationBufferLength;

+=C2=A0 UINT32=C2=A0 =C2=A0 InformationBufferOffset;

+=C2=A0 UINT32=C2=A0 =C2=A0 Reserved;

+} REMOTE_NDIS_SET_MSG;

+

+typedef struct {

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageType;

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageLength;

+=C2=A0 UINT32=C2=A0 =C2=A0 Reserved;

+} REMOTE_NDIS_RESET_MSG;

+

+typedef struct {

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageType;

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageLength;

+=C2=A0 UINT32=C2=A0 =C2=A0 Status;

+=C2=A0 UINT32=C2=A0 =C2=A0 StatusBufferLength;

+=C2=A0 UINT32=C2=A0 =C2=A0 StatusBufferOffset;

+} REMOTE_NDIS_INDICATE_STATUS_MSG;

+

+typedef struct {

+=C2=A0 UINT32=C2=A0 =C2=A0 DiagStatus;

+=C2=A0 UINT32=C2=A0 =C2=A0 ErrorOffset;

+} RNDIS_DIAGNOSTIC_INFO;

+

+typedef struct {

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageType;

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageLength;

+=C2=A0 UINT32=C2=A0 =C2=A0 RequestID;

+} REMOTE_NDIS_KEEPALIVE_MSG;

+

+typedef struct {

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageType;

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageLength;

+=C2=A0 UINT32=C2=A0 =C2=A0 RequestID;

+=C2=A0 UINT32=C2=A0 =C2=A0 Status;

+=C2=A0 UINT32=C2=A0 =C2=A0 MajorVersion;

+=C2=A0 UINT32=C2=A0 =C2=A0 MinorVersion;

+=C2=A0 UINT32=C2=A0 =C2=A0 DeviceFlags;

+=C2=A0 UINT32=C2=A0 =C2=A0 Medium;

+=C2=A0 UINT32=C2=A0 =C2=A0 MaxPacketsPerTransfer;

+=C2=A0 UINT32=C2=A0 =C2=A0 MaxTransferSize;

+=C2=A0 UINT32=C2=A0 =C2=A0 PacketAlignmentFactor;

+=C2=A0 UINT64=C2=A0 =C2=A0 Reserved;

+} REMOTE_NDIS_INITIALIZE_CMPLT;

+

+typedef struct {

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageType;

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageLength;

+=C2=A0 UINT32=C2=A0 =C2=A0 RequestID;

+=C2=A0 UINT32=C2=A0 =C2=A0 Status;

+=C2=A0 UINT32=C2=A0 =C2=A0 InformationBufferLength;

+=C2=A0 UINT32=C2=A0 =C2=A0 InformationBufferOffset;

+} REMOTE_NDIS_QUERY_CMPLT;

+

+typedef struct {

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageType;

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageLength;

+=C2=A0 UINT32=C2=A0 =C2=A0 RequestID;

+=C2=A0 UINT32=C2=A0 =C2=A0 Status;

+} REMOTE_NDIS_SET_CMPLT;

+

+typedef struct {

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageType;

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageLength;

+=C2=A0 UINT32=C2=A0 =C2=A0 Status;

+=C2=A0 UINT32=C2=A0 =C2=A0 AddressingReset;

+} REMOTE_NDIS_RESET_CMPLT;

+

+typedef struct {

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageType;

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageLength;

+=C2=A0 UINT32=C2=A0 =C2=A0 RequestID;

+=C2=A0 UINT32=C2=A0 =C2=A0 Status;

+} REMOTE_NDIS_KEEPALIVE_CMPLT;

+

+typedef struct {

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageType;

+=C2=A0 UINT32=C2=A0 =C2=A0 MessageLength;

+=C2=A0 UINT32=C2=A0 =C2=A0 DataOffset;

+=C2=A0 UINT32=C2=A0 =C2=A0 DataLength;

+=C2=A0 UINT32=C2=A0 =C2=A0 OutOfBandDataOffset;

+=C2=A0 UINT32=C2=A0 =C2=A0 OutOfBandDataLength;

+=C2=A0 UINT32=C2=A0 =C2=A0 NumOutOfBandDataElements;

+=C2=A0 UINT32=C2=A0 =C2=A0 PerPacketInfoOffset;

+=C2=A0 UINT32=C2=A0 =C2=A0 PerPacketInfoLength;

+=C2=A0 UINT32=C2=A0 =C2=A0 Reserved1;

+=C2=A0 UINT32=C2=A0 =C2=A0 Reserved2;

+} REMOTE_NDIS_PACKET_MSG;

+

+typedef struct {

+=C2=A0 UINT32=C2=A0 =C2=A0 Size;

+=C2=A0 UINT32=C2=A0 =C2=A0 Type;

+=C2=A0 UINT32=C2=A0 =C2=A0 ClassInformationOffset;

+} OUT_OF_BAND_DATA_RECORD;

+

+typedef struct {

+=C2=A0 UINT32=C2=A0 =C2=A0 Size;

+=C2=A0 UINT32=C2=A0 =C2=A0 Type;

+=C2=A0 UINT32=C2=A0 =C2=A0 ClassInformationOffset;

+} PER_PACKET_INFO_DATA_RECORD;

+

+typedef struct {

+=C2=A0 LIST_ENTRY=C2=A0 =C2=A0 PacketList;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*OrgBuffer;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0RemainingLength;

+} PACKET_LIST;

+

+#pragma pack()

+

+#endif

diff --git a/UsbNetworkPkg/UsbRndis/UsbRndis.inf b/UsbNetworkPkg/UsbRndis/U= sbRndis.inf
new file mode 100644
index 0000000000..909b106059
--- /dev/null
+++ b/UsbNetworkPkg/UsbRndis/UsbRndis.inf
@@ -0,0 +1,41 @@
+## @file
+#=C2=A0 =C2=A0This is Usb Rndis driver for DXE phase.
+#
+# Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
+# Subject to AMI licensing agreement.
+##
+
+[Defines]
+=C2=A0 INF_VERSION=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =3D 0x00010005
+=C2=A0 BASE_NAME=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =3D UsbRndis
+=C2=A0 FILE_GUID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =3D 11E32C34-60B5-4991-8DEA-63D3E8C876DE
+=C2=A0 MODULE_TYPE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =3D DXE_DRIVER
+=C2=A0 VERSION_STRING=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0=3D 1.0
+=C2=A0 ENTRY_POINT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =3D UsbRndisEntry
+
+[Sources]
+=C2=A0 UsbRndis.c
+=C2=A0 UsbRndis.h
+=C2=A0 UsbRndisFunction.c
+=C2=A0 ComponentName.c
+
+[Packages]
+=C2=A0 MdePkg/MdePkg.dec
+=C2=A0 UsbNetworkPkg/UsbNetworkPkg.dec
+
+[LibraryClasses]
+=C2=A0 UefiDriverEntryPoint
+=C2=A0 UefiBootServicesTableLib
+=C2=A0 UefiLib
+=C2=A0 DebugLib
+=C2=A0 UefiUsbLib
+=C2=A0 MemoryAllocationLib
+=C2=A0 BaseMemoryLib
+
+[Protocols]
+=C2=A0 gEfiUsbIoProtocolGuid
+=C2=A0 gEfiDevicePathProtocolGuid
+=C2=A0 gEfiDriverBindingProtocolGuid
+
+[Depex]
+=C2=A0 TRUE
diff --git a/UsbNetworkPkg/UsbRndis/UsbRndisFunction.c b/UsbNetworkPkg/UsbR= ndis/UsbRndisFunction.c
new file mode 100644
index 0000000000..a9b7b54f6a
--- /dev/null
+++ b/UsbNetworkPkg/UsbRndis/UsbRndisFunction.c
@@ -0,0 +1,1587 @@
+/** @file

+=C2=A0 This file contains code for USB Ethernet descriptor

+=C2=A0 and specific requests implement.

+

+=C2=A0 Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>

+=C2=A0 Subject to AMI licensing agreement.

+**/

+

+#include "UsbRndis.h"

+

+UINT16=C2=A0 StopBulkInCnt=C2=A0 =3D 0;

+UINT16=C2=A0 BlockBulkInCnt =3D 0;

+

+/**

+=C2=A0 Load All of device descriptor.

+

+=C2=A0 @param[in]=C2=A0 UsbIo=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0A pointer to the EFI_USB_IO_PROTOCOL instance.

+=C2=A0 @param[out] ConfigDesc=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A p= ointer to the configuration descriptor.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_OUT_OF_RESOURCES=C2=A0 The request could not be complet= ed because the

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 buffer specified by DescriptorLength= and Descriptor

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 is not large enough to hold the resu= lt of the request.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error. The transfer

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 status is returned in Status.

+**/

+EFI_STATUS

+LoadAllDescriptor (

+=C2=A0 IN=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbIo,

+=C2=A0 OUT EFI_USB_CONFIG_DESCRIPTOR=C2=A0 **ConfigDesc

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Status;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0TransStatus;

+=C2=A0 EFI_USB_CONFIG_DESCRIPTOR=C2=A0 Tmp;

+

+=C2=A0 Status =3D UsbIo->UsbGetConfigDescriptor (UsbIo, &Tmp);

+=C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 Status =3D gBS->AllocatePool (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EfiBootServ= icesData,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Tmp.TotalLe= ngth,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (VOID **)Co= nfigDesc

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 Status =3D UsbGetDescriptor (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0USB_DESC_TYPE_CONFIG <&= lt; 8 | (Tmp.ConfigurationValue - 1),=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0// zero based

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A00,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Tmp.TotalLength,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*ConfigDesc,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0&TransStatus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Returns pointer to the next descriptor for the pack of USB descript= ors

+=C2=A0 located in continues memory segment

+

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 Desc=C2=A0 =C2=A0A pointer to the CO= NFIG_DESCRIPTOR instance.

+=C2=A0 @param[in, out] Offset A pointer to the sum of descriptor length.
+

+=C2=A0 @retval TRUE=C2=A0 =C2=A0The request executed successfully.

+=C2=A0 @retval FALSE=C2=A0 No next descriptor.

+

+**/

+BOOLEAN

+NextDescriptor (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 EFI_USB_CONFIG_DESCRIPTOR=C2=A0 *Desc,

+=C2=A0 IN OUT=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 *Offset

+=C2=A0 )

+{

+=C2=A0 if ((Desc =3D=3D NULL) || (*Offset >=3D Desc->TotalLength)) {=

+=C2=A0 =C2=A0 return FALSE;

+=C2=A0 }

+

+=C2=A0 if (((EFI_USB_CONFIG_DESCRIPTOR *)((char *)Desc+*Offset))->Lengt= h =3D=3D 0) {

+=C2=A0 =C2=A0 return FALSE;

+=C2=A0 }

+

+=C2=A0 *Offset +=3D ((EFI_USB_CONFIG_DESCRIPTOR *)((char *)Desc+*Offset))-= >Length;

+=C2=A0 if ( *Offset >=3D Desc->TotalLength ) {

+=C2=A0 =C2=A0 return FALSE;

+=C2=A0 }

+

+=C2=A0 return TRUE;

+}

+

+/**

+=C2=A0 Read Function descriptor

+

+=C2=A0 @param[in]=C2=A0 Config=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0A pointer to all of configuration.

+=C2=A0 @param[in]=C2=A0 FunDescriptorType=C2=A0 USB CDC class descriptor S= ubType.

+=C2=A0 @param[out] DataBuffer=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A pointer t= o the Data of corresponding to device capability.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 The device capabilit= y descriptor was retrieved

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0successfully.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 No supported.

+=C2=A0 @retval EFI_NOT_FOUND=C2=A0 =C2=A0 =C2=A0 The device capability des= criptor was not found.

+

+**/

+EFI_STATUS

+GetFunctionalDescriptor (

+=C2=A0 IN=C2=A0 EFI_USB_CONFIG_DESCRIPTOR=C2=A0 *Config,

+=C2=A0 IN=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 FunDescriptorType,

+=C2=A0 OUT VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0*DataBuffer

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 Status =3D EFI_NOT_FOUND;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0Offset;

+=C2=A0 EFI_USB_INTERFACE_DESCRIPTOR=C2=A0 *Interface;

+

+=C2=A0 for (Offset =3D 0; NextDescriptor (Config, &Offset);) {

+=C2=A0 =C2=A0 Interface =3D (EFI_USB_INTERFACE_DESCRIPTOR *)((UINT8 *)Conf= ig + Offset);

+=C2=A0 =C2=A0 if (Interface->DescriptorType =3D=3D CS_INTERFACE) {

+=C2=A0 =C2=A0 =C2=A0 if (((USB_HEADER_FUN_DESCRIPTOR *)Interface)->Desc= riptorSubtype =3D=3D FunDescriptorType) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 switch (FunDescriptorType) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 case HEADER_FUN_DESCRIPTOR:

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 CopyMem (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 DataBuffer,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (USB_HEADER_FUN_DESCRIPTO= R *)Interface,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 sizeof (USB_HEADER_FUN_DE= SCRIPTOR)

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return EFI_SUCCESS;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 case UNION_FUN_DESCRIPTOR:

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 CopyMem (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 DataBuffer,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (USB_UNION_FUN_DESCRIPTOR= *)Interface,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ((USB_UNION_FUN_DESCRIPTO= R *)Interface)->FunctionLength

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return EFI_SUCCESS;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 case ETHERNET_FUN_DESCRIPTOR:

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 CopyMem (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 DataBuffer,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (USB_ETHERNET_FUN_DESCRIP= TOR *)Interface,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 sizeof (USB_ETHERNET_FUN_= DESCRIPTOR)

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return EFI_SUCCESS;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 default:

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Status =3D EFI_UNSUPPORTED;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 }

+=C2=A0 }

+

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Get USB Ethernet IO endpoint and USB CDC data IO endpoint.

+

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 UsbIo=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0A pointer to the EFI_USB_IO_PROTOCOL instance.

+=C2=A0 @param[in, out] UsbRndisDevice=C2=A0 A pointer to the USB_RNDIS_DEV= ICE instance.

+

+**/

+VOID

+GetEndpoint (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 *UsbIo,

+=C2=A0 IN OUT=C2=A0 USB_RNDIS_DEVICE=C2=A0 =C2=A0 =C2=A0*UsbRndisDevice
+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 Status;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0Index;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 Result;

+=C2=A0 EFI_USB_INTERFACE_DESCRIPTOR=C2=A0 Interface;

+=C2=A0 EFI_USB_ENDPOINT_DESCRIPTOR=C2=A0 =C2=A0Endpoint;

+

+=C2=A0 Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interfa= ce);

+=C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 if (Interface.NumEndpoints =3D=3D 0 ) {

+=C2=A0 =C2=A0 Status =3D UsbSetInterface (UsbIo, 1, 0, &Result);

+=C2=A0 =C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 =C2=A0 Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &= Interface);

+=C2=A0 =C2=A0 ASSERT_EFI_ERROR (Status);

+=C2=A0 }

+

+=C2=A0 for (Index =3D 0; Index < Interface.NumEndpoints; Index++) {

+=C2=A0 =C2=A0 Status =3D UsbIo->UsbGetEndpointDescriptor (UsbIo, Index,= &Endpoint);

+

+=C2=A0 =C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 =C2=A0 switch ((Endpoint.Attributes & (BIT0 | BIT1))) {

+=C2=A0 =C2=A0 =C2=A0 case USB_ENDPOINT_BULK:

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (Endpoint.EndpointAddress & BIT7) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbRndisDevice->BulkInEndpoint =3D E= ndpoint.EndpointAddress;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 } else {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbRndisDevice->BulkOutEndpoint =3D = Endpoint.EndpointAddress;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 =C2=A0 case USB_ENDPOINT_INTERRUPT:

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbRndisDevice->InterrupEndpoint =3D Endpoi= nt.EndpointAddress;

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 }

+=C2=A0 }

+}

+

+/**

+=C2=A0 Async USB transfer callback routine.

+

+=C2=A0 @param[in]=C2=A0 Data=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Data= received or sent via the USB Asynchronous Transfer, if the

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 transfer completed successfully.

+=C2=A0 @param[in]=C2=A0 DataLength=C2=A0 =C2=A0 =C2=A0 The length of Data = received or sent via the Asynchronous

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Transfer, if transfer successfully complete= s.

+=C2=A0 @param[in]=C2=A0 Context=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Data pass= ed from UsbAsyncInterruptTransfer() request.

+=C2=A0 @param[in]=C2=A0 Status=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Indicates= the result of the asynchronous transfer.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The asy= nchronous USB transfer request has been successfully executed.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The asynchronous USB t= ransfer request failed.

+

+**/

+EFI_STATUS

+EFIAPI

+InterruptCallback (

+=C2=A0 IN=C2=A0 VOID=C2=A0 =C2=A0 *Data,

+=C2=A0 IN=C2=A0 UINTN=C2=A0 =C2=A0DataLength,

+=C2=A0 IN=C2=A0 VOID=C2=A0 =C2=A0 *Context,

+=C2=A0 IN=C2=A0 UINT32=C2=A0 Status

+=C2=A0 )

+{

+=C2=A0 if (((EFI_USB_DEVICE_REQUEST *)Data)->Request =3D=3D 0) {

+=C2=A0 =C2=A0 CopyMem (

+=C2=A0 =C2=A0 =C2=A0 (EFI_USB_DEVICE_REQUEST *)Context,

+=C2=A0 =C2=A0 =C2=A0 (EFI_USB_DEVICE_REQUEST *)Data,

+=C2=A0 =C2=A0 =C2=A0 sizeof (EFI_USB_DEVICE_REQUEST)

+=C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 }

+

+=C2=A0 return EFI_SUCCESS;

+}

+

+/**

+=C2=A0 This function is used to manage a USB device with an interrupt tran= sfer pipe.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 A pointer to the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[in]=C2=A0 IsNewTransfer=C2=A0 =C2=A0 =C2=A0If TRUE, a new tr= ansfer will be submitted to USB controller. If

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 FALSE, the interrupt transfer is del= eted from the device's interrupt

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 transfer queue.

+=C2=A0 @param[in]=C2=A0 PollingInterval=C2=A0 =C2=A0Indicates the periodic= rate, in milliseconds, that the transfer is to be

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 executed.This parameter is required = when IsNewTransfer is TRUE. The

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 value must be between 1 to 255, othe= rwise EFI_INVALID_PARAMETER is returned.

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 The units are in milliseconds.

+=C2=A0 @param[in]=C2=A0 Request=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A = pointer to the EFI_USB_DEVICE_REQUEST data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The asy= nchronous USB transfer request transfer has been successfully executed.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The asynchronous USB t= ransfer request failed.

+

+**/

+EFI_STATUS

+EFIAPI

+UsbRndisInterrupt (

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0*This,

+=C2=A0 IN BOOLEAN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0IsNewTransfer,

+=C2=A0 IN UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0PollingInterval,

+=C2=A0 IN EFI_USB_DEVICE_REQUEST=C2=A0 *Requst

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 Status;

+=C2=A0 USB_RNDIS_DEVICE=C2=A0 *UsbRndisDevice;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0DataLength =3D= 0;

+

+=C2=A0 UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This);

+

+=C2=A0 if (IsNewTransfer =3D=3D TRUE) {

+=C2=A0 =C2=A0 DataLength =3D sizeof (EFI_USB_DEVICE_REQUEST) + sizeof (USB= _CONNECT_SPEED_CHANGE);

+=C2=A0 =C2=A0 Status=C2=A0 =C2=A0 =C2=A0=3D UsbRndisDevice->UsbIo->U= sbAsyncInterruptTransfer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 U= sbRndisDevice->UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 U= sbRndisDevice->InterrupEndpoint,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 I= sNewTransfer,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 P= ollingInterval,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 D= ataLength,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 I= nterruptCallback,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 R= equst

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 )= ;

+

+=C2=A0 =C2=A0 if (Status =3D=3D EFI_INVALID_PARAMETER) {

+=C2=A0 =C2=A0 =C2=A0 // Because of Stacked AsyncInterrupt request are not = supported

+=C2=A0 =C2=A0 =C2=A0 Status =3D UsbRndisDevice->UsbIo->UsbAsyncInter= ruptTransfer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbRndis= Device->UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbRndis= Device->InterrupEndpoint,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NULL,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NULL

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 =C2=A0 }

+=C2=A0 } else {

+=C2=A0 =C2=A0 Status =3D UsbRndisDevice->UsbIo->UsbAsyncInterruptTra= nsfer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbRndisDevice-= >UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbRndisDevice-= >InterrupEndpoint,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 IsNewTransfer,<= br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NULL,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 NULL

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 }

+

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Retrieves the USB Ethernet Mac Address.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A pointer t= o the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[out] MacAddress=C2=A0 =C2=A0 A pointer to the caller allocat= ed USB Ethernet Mac Address.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB= Header Functional descriptor was retrieved successfully.

+=C2=A0 @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL.

+=C2=A0 @retval EFI_NOT_FOUND=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB Head= er Functional descriptor was not found.

+

+**/

+EFI_STATUS

+EFIAPI

+GetUsbEthMacAddress (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 OUT EFI_MAC_ADDRESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 *MacAddress

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0Status;

+=C2=A0 USB_RNDIS_DEVICE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*Us= bRndisDevice;

+=C2=A0 USB_ETHERNET_FUN_DESCRIPTOR=C2=A0 UsbEthDescriptor;

+=C2=A0 CHAR16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0*Data;

+=C2=A0 CHAR16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0*DataPtr;

+=C2=A0 CHAR16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0TmpStr[1];

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 Index;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 Hi;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 Low;

+

+=C2=A0 UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This);

+

+=C2=A0 Status =3D This->UsbEthFunDescriptor (This, &UsbEthDescripto= r);

+=C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 Status =3D UsbRndisDevice->UsbIo->UsbGetStringDescriptor (
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbRndisDevice->Usb= Io,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 0x409,=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0// Eng= lish-US Language ID

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbEthDescriptor.MacAd= dress,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Data

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+=C2=A0 ASSERT_EFI_ERROR (Status);

+

+=C2=A0 DataPtr =3D Data;

+=C2=A0 for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {

+=C2=A0 =C2=A0 CopyMem (TmpStr, DataPtr, sizeof (CHAR16));

+=C2=A0 =C2=A0 DataPtr++;

+=C2=A0 =C2=A0 Hi =3D (UINT8)StrHexToUintn (TmpStr);

+=C2=A0 =C2=A0 CopyMem (TmpStr, DataPtr, sizeof (CHAR16));

+=C2=A0 =C2=A0 DataPtr++;

+=C2=A0 =C2=A0 Low=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0=3D (UINT8)StrHexToUintn (TmpStr);

+=C2=A0 =C2=A0 MacAddress->Addr[Index] =3D (Hi << 4) | Low;

+=C2=A0 }

+

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Retrieves the USB Ethernet Bulk transfer data size.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A pointer t= o the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[out] BulkSize=C2=A0 =C2=A0 =C2=A0 A pointer to the Bulk tran= sfer data size.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0The bulk transfer dat= a size was retrieved successfully.

+=C2=A0 @retval other=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Failed= to retrieve the bulk transfer data size.

+

+**/

+EFI_STATUS

+EFIAPI

+UsbEthBulkSize (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 OUT UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 *BulkSize

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0Status;

+=C2=A0 USB_ETHERNET_FUN_DESCRIPTOR=C2=A0 UsbEthFunDescriptor;

+

+=C2=A0 Status =3D This->UsbEthFunDescriptor (This, &UsbEthFunDescri= ptor);

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 *BulkSize =3D (UINTN)UsbEthFunDescriptor.MaxSegmentSize;

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Retrieves the USB Header functional Descriptor.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0A pointer to the USB_ETHERNET_PROTOCOL instance.
+=C2=A0 @param[out] UsbHeaderFunDescriptor A pointer to the caller allocate= d USB Header Functional Descriptor.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB= Header Functional descriptor was retrieved successfully.

+=C2=A0 @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL.

+=C2=A0 @retval EFI_NOT_FOUND=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The USB Head= er Functional descriptor was not found.

+

+**/

+EFI_STATUS

+EFIAPI

+GetUsbHeaderFunDescriptor (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0 *This,

+=C2=A0 OUT USB_HEADER_FUN_DESCRIPTOR=C2=A0 *UsbHeaderFunDescriptor

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 Status;

+=C2=A0 USB_RNDIS_DEVICE=C2=A0 *UsbRndisDevice;

+

+=C2=A0 UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This);

+

+=C2=A0 if (UsbHeaderFunDescriptor =3D=3D NULL) {

+=C2=A0 =C2=A0 return EFI_INVALID_PARAMETER;

+=C2=A0 }

+

+=C2=A0 Status =3D GetFunctionalDescriptor (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0UsbRndisDevice->Config,=

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0HEADER_FUN_DESCRIPTOR,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0UsbHeaderFunDescriptor

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Retrieves the USB Union functional Descriptor.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0A pointer to the USB_ETHERNET_PROTOCOL instance.
+=C2=A0 @param[out] UsbUnionFunDescriptor=C2=A0 A pointer to the caller all= ocated USB Union Functional Descriptor.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 The US= B Union Functional descriptor was retrieved successfully.

+=C2=A0 @retval EFI_INVALID_PARAMETER=C2=A0 UsbUnionFunDescriptor is NULL.<= br>
+=C2=A0 @retval EFI_NOT_FOUND=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 The USB Uni= on Functional descriptor was not found.

+

+**/

+EFI_STATUS

+EFIAPI

+GetUsbUnionFunDescriptor (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0*This,

+=C2=A0 OUT USB_UNION_FUN_DESCRIPTOR=C2=A0 *UsbUnionFunDescriptor

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 Status;

+=C2=A0 USB_RNDIS_DEVICE=C2=A0 *UsbRndisDevice;

+

+=C2=A0 UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This);

+

+=C2=A0 if (UsbUnionFunDescriptor =3D=3D NULL) {

+=C2=A0 =C2=A0 return EFI_INVALID_PARAMETER;

+=C2=A0 }

+

+=C2=A0 Status =3D GetFunctionalDescriptor (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0UsbRndisDevice->Config,=

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0UNION_FUN_DESCRIPTOR,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0UsbUnionFunDescriptor

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Retrieves the USB Ethernet functional Descriptor.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0A pointer to the USB_ETHERNET_PROTOCOL instance.
+=C2=A0 @param[out] UsbEthFunDescriptor=C2=A0 =C2=A0 A pointer to the calle= r allocated USB Ethernet Functional Descriptor.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 The US= B Ethernet Functional descriptor was retrieved successfully.

+=C2=A0 @retval EFI_INVALID_PARAMETER=C2=A0 UsbEthFunDescriptor is NULL.
+=C2=A0 @retval EFI_NOT_FOUND=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 The USB Eth= ernet Functional descriptor was not found.

+

+**/

+EFI_STATUS

+EFIAPI

+GetUsbRndisFunDescriptor (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 *This,
+=C2=A0 OUT USB_ETHERNET_FUN_DESCRIPTOR=C2=A0 *UsbEthFunDescriptor

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 Status;

+=C2=A0 USB_RNDIS_DEVICE=C2=A0 *UsbRndisDevice;

+

+=C2=A0 UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This);

+

+=C2=A0 if (UsbEthFunDescriptor =3D=3D NULL) {

+=C2=A0 =C2=A0 return EFI_INVALID_PARAMETER;

+=C2=A0 }

+

+=C2=A0 Status =3D GetFunctionalDescriptor (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0UsbRndisDevice->Config,=

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ETHERNET_FUN_DESCRIPTOR,
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0UsbEthFunDescriptor

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0);

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 This request sets the Ethernet device multicast filters as specifie= d in the

+=C2=A0 sequential list of 48 bit Ethernet multicast addresses.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0A pointer to the USB_ETHERNET_PROTOCOL instance.
+=C2=A0 @param[in]=C2=A0 Value=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 Number of filters.

+=C2=A0 @param[in]=C2=A0 McastAddr=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 A pointer to the value of the multicast addresses.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 The re= quest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A time= out occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 =C2=A0The request fail= ed due to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER=C2=A0 One of the parameters has an in= valid value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0 Not supported.
+

+**/

+EFI_STATUS

+EFIAPI

+SetUsbRndisMcastFilter (

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Value,

+=C2=A0 IN VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0*McastAddr

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0Status;

+=C2=A0 EFI_USB_DEVICE_REQUEST=C2=A0 =C2=A0 =C2=A0 =C2=A0Request;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0TransStatus;

+=C2=A0 USB_ETHERNET_FUN_DESCRIPTOR=C2=A0 UsbEthFunDescriptor;

+=C2=A0 USB_RNDIS_DEVICE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*Us= bRndisDevice;

+

+=C2=A0 UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This);

+

+=C2=A0 Status =3D This->UsbEthFunDescriptor (This, &UsbEthFunDescri= ptor);

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 if ((UsbEthFunDescriptor.NumberMcFilters << 1) =3D=3D 0) {
+=C2=A0 =C2=A0 return EFI_UNSUPPORTED;

+=C2=A0 }

+

+=C2=A0 Request.RequestType =3D USB_ETHRTNET_SET_REQ_TYPE;

+=C2=A0 Request.Request=C2=A0 =C2=A0 =C2=A0=3D SET_ETH_MULTICAST_FILTERS_RE= Q;

+=C2=A0 Request.Value=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D Value;

+=C2=A0 Request.Index=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D UsbRndisDevice->NumO= fInterface;

+=C2=A0 Request.Length=C2=A0 =C2=A0 =C2=A0 =3D Value * 6;

+

+=C2=A0 return UsbRndisDevice->UsbIo->UsbControlTransfer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbRndisDevice->UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Request,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EfiUsbDataOut,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB_ETHERNET_TRANSFER_TIMEOUT= ,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 McastAddr,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Request.Length,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &TransStatus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+}

+

+/**

+=C2=A0 This request sets up the specified Ethernet power management patter= n filter as

+=C2=A0 described in the data structure.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 A pointer to the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[in]=C2=A0 Value=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0Number of filters.

+=C2=A0 @param[in]=C2=A0 Length=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 Size of the power management pattern filter data.

+=C2=A0 @param[in]=C2=A0 PatternFilter=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A p= ointer to the power management pattern filter structure.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 The re= quest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A time= out occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 =C2=A0The request fail= ed due to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER=C2=A0 One of the parameters has an in= valid value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0 Not supported.
+

+**/

+EFI_STATUS

+EFIAPI

+SetUsbRndisPowerFilter (

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Value,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Length,

+=C2=A0 IN VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0*PatternFilter

+=C2=A0 )

+{

+=C2=A0 EFI_USB_DEVICE_REQUEST=C2=A0 Request;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 TransStatus;

+=C2=A0 USB_RNDIS_DEVICE=C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbRndisDevice;

+

+=C2=A0 UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This);

+

+=C2=A0 Request.RequestType =3D USB_ETHRTNET_SET_REQ_TYPE;

+=C2=A0 Request.Request=C2=A0 =C2=A0 =C2=A0=3D SET_ETH_POWER_MANAGEMENT_PAT= TERN_FILTER_REQ;

+=C2=A0 Request.Value=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D Value;

+=C2=A0 Request.Index=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D UsbRndisDevice->NumO= fInterface;

+=C2=A0 Request.Length=C2=A0 =C2=A0 =C2=A0 =3D Length;

+

+=C2=A0 return UsbRndisDevice->UsbIo->UsbControlTransfer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbRndisDevice->UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Request,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EfiUsbDataOut,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB_ETHERNET_TRANSFER_TIMEOUT= ,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 PatternFilter,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Length,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &TransStatus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+}

+

+/**

+=C2=A0 This request retrieves the status of the specified Ethernet power m= anagement

+=C2=A0 pattern filter from the device.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0A pointer to the USB_ETHERNET_PROTOCOL instance.
+=C2=A0 @param[in]=C2=A0 Value=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 The filter number.

+=C2=A0 @param[out] PatternActive=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A point= er to the pattern active boolean.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 The re= quest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A time= out occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 =C2=A0The request fail= ed due to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER=C2=A0 One of the parameters has an in= valid value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0 Not supported.
+

+**/

+EFI_STATUS

+EFIAPI

+GetUsbRndisPowerFilter (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0Value,

+=C2=A0 OUT BOOLEAN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = *PatternActive

+=C2=A0 )

+{

+=C2=A0 EFI_USB_DEVICE_REQUEST=C2=A0 Request;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 TransStatus;

+=C2=A0 USB_RNDIS_DEVICE=C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbRndisDevice;

+

+=C2=A0 UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This);

+

+=C2=A0 Request.RequestType =3D USB_ETHERNET_GET_REQ_TYPE;

+=C2=A0 Request.Request=C2=A0 =C2=A0 =C2=A0=3D GET_ETH_POWER_MANAGEMENT_PAT= TERN_FILTER_REQ;

+=C2=A0 Request.Value=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D Value;

+=C2=A0 Request.Index=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D UsbRndisDevice->NumO= fInterface;

+=C2=A0 Request.Length=C2=A0 =C2=A0 =C2=A0 =3D USB_ETH_POWER_FILTER_LENGTH;=

+

+=C2=A0 return UsbRndisDevice->UsbIo->UsbControlTransfer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbRndisDevice->UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &Request,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EfiUsbDataIn,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB_ETHERNET_TRANSFER_TIMEOUT= ,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 PatternActive,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB_ETH_POWER_FILTER_LENGTH,<= br>
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &TransStatus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );

+}

+

+/**

+

+=C2=A0 Converts PXE filter settings to RNDIS values

+

+=C2=A0 @param[in]=C2=A0 Value=C2=A0 =C2=A0 =C2=A0 PXE filter data.

+=C2=A0 @param[out] CdcFilter=C2=A0 A pointer to the Ethernet Packet Filter= Bitmap value converted by PXE_OPFLAGS.

+

+**/

+VOID

+ConvertFilter (

+=C2=A0 IN=C2=A0 UINT16=C2=A0 Value,

+=C2=A0 OUT UINT16=C2=A0 *CdcFilter

+=C2=A0 )

+{

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0Index;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0Count;

+=C2=A0 static struct BIT_MAP=C2=A0 Table[] =3D {

+=C2=A0 =C2=A0 { PXE_OPFLAGS_RECEIVE_FILTER_UNICAST,=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 NDIS_PACKET_TYPE_DIRECTED=C2=A0 =C2=A0 =C2=A0 },

+=C2=A0 =C2=A0 { PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST,=C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 NDIS_PACKET_TYPE_BROADCAST=C2=A0 =C2=A0 =C2=A0},

+=C2=A0 =C2=A0 { PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST, NDIS_PACKET= _TYPE_MULTICAST=C2=A0 =C2=A0 =C2=A0},

+=C2=A0 =C2=A0 { PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS,=C2=A0 =C2=A0 =C2= =A0 =C2=A0 NDIS_PACKET_TYPE_PROMISCUOUS=C2=A0 =C2=A0},

+=C2=A0 =C2=A0 { PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST,=C2=A0 =C2=A0 =C2= =A0 NDIS_PACKET_TYPE_ALL_MULTICAST },

+=C2=A0 };

+

+=C2=A0 Count =3D sizeof (Table)/sizeof (Table[0]);

+

+=C2=A0 for (Index =3D 0; (Table[Index].Src !=3D 0) && (Index < = Count); Index++) {

+=C2=A0 =C2=A0 if (Table[Index].Src & Value) {

+=C2=A0 =C2=A0 =C2=A0 *CdcFilter |=3D Table[Index].Dst;

+=C2=A0 =C2=A0 }

+=C2=A0 }

+}

+

+/**

+

+=C2=A0 Updates Filter settings on the device.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_STATUS

+

+**/

+EFI_STATUS

+EFIAPI

+RndisUndiReceiveFilter (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0Status;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 *McastList;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 Count =3D 0;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 Index1;

+=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 Index2;

+=C2=A0 UINT64=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0CpbAddr=C2=A0 =C2=A0=3D Cdb->CPBaddr;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0CpbSize=C2=A0 =C2=A0=3D Cdb->CPBsize;

+=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0SetFilter =3D (UINT16)(Cdb->OpFlags & 0x1F);=

+=C2=A0 PXE_CPB_RECEIVE_FILTERS=C2=A0 =C2=A0 =C2=A0 *Cpb=C2=A0 =C2=A0 =C2= =A0 =3D (PXE_CPB_RECEIVE_FILTERS *)(UINTN)CpbAddr;

+=C2=A0 USB_ETHERNET_FUN_DESCRIPTOR=C2=A0 UsbEthFunDescriptor;

+

+=C2=A0 // The Cpb could be NULL.(ref:PXE_CPBADDR_NOT_USED)

+=C2=A0 Nic->RxFilter =3D (UINT8)SetFilter;

+

+=C2=A0 if (((SetFilter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST= ) !=3D 0) || (Cpb !=3D NULL)) {

+=C2=A0 =C2=A0 if (Cpb !=3D NULL) {

+=C2=A0 =C2=A0 =C2=A0 Nic->McastCount =3D (UINT8)(CpbSize / PXE_MAC_LENG= TH);

+=C2=A0 =C2=A0 =C2=A0 CopyMem (&Nic->McastList, Cpb, Nic->McastCo= unt);

+=C2=A0 =C2=A0 } else {

+=C2=A0 =C2=A0 =C2=A0 Nic->McastCount =3D 0;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 if (Nic->CanReceive) {

+=C2=A0 =C2=A0 =C2=A0 Nic->CanReceive =3D FALSE;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 Nic->UsbEth->UsbEthFunDescriptor (Nic->UsbEth, &= ;UsbEthFunDescriptor);

+=C2=A0 =C2=A0 if ((UsbEthFunDescriptor.NumberMcFilters << 1) =3D=3D = 0) {

+=C2=A0 =C2=A0 =C2=A0 Nic->RxFilter |=3D PXE_OPFLAGS_RECEIVE_FILTER_ALL_= MULTICAST;

+=C2=A0 =C2=A0 =C2=A0 DEBUG ((DEBUG_INFO, "SetUsbEthPacketFilter Nic %= lx Nic->UsbEth %lx ", Nic, Nic->UsbEth));

+=C2=A0 =C2=A0 =C2=A0 Nic->UsbEth->SetUsbEthPacketFilter (Nic->Usb= Eth, Nic->RxFilter);

+=C2=A0 =C2=A0 } else {

+=C2=A0 =C2=A0 =C2=A0 Status =3D gBS->AllocatePool (EfiBootServicesData,= Nic->McastCount * 6, (VOID **)&McastList);

+=C2=A0 =C2=A0 =C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 return PXE_STATCODE_INVALID_PARAMETER;

+=C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 if (Cpb !=3D NULL) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 for (Index1 =3D 0; Index1 < Nic->McastCo= unt; Index1++) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 for (Index2 =3D 0; Index2 < 6; Index= 2++) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 McastList[Count++] =3D Cpb->M= CastList[Index1][Index2];

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 Nic->RxFilter |=3D PXE_OPFLAGS_RECEIVE_FILTER_FILT= ERED_MULTICAST;

+=C2=A0 =C2=A0 =C2=A0 if (Cpb !=3D NULL) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 Nic->UsbEth->SetUsbEthMcastFilter (Nic-&= gt;UsbEth, Nic->McastCount, McastList);

+=C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 Nic->UsbEth->SetUsbEthPacketFilter (Nic->Usb= Eth, Nic->RxFilter);

+=C2=A0 =C2=A0 =C2=A0 gBS->FreePool (McastList);

+=C2=A0 =C2=A0 }

+=C2=A0 }

+

+=C2=A0 return EFI_SUCCESS;

+}

+

+/**

+=C2=A0 This request is used to configure device Ethernet packet filter set= tings.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 A pointer to the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[in]=C2=A0 Value=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0Packet Filter Bitmap.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+

+**/

+EFI_STATUS

+EFIAPI

+SetUsbRndisPacketFilter (

+=C2=A0 IN USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0Value

+=C2=A0 )

+{

+=C2=A0 return EFI_SUCCESS;

+}

+

+/**

+=C2=A0 This request is used to retrieve a statistic based on the feature s= elector.

+

+=C2=A0 @param[in]=C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 A pointer to the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[in]=C2=A0 FeatureSelector=C2=A0 =C2=A0 =C2=A0 =C2=A0Value of= the feature selector.

+=C2=A0 @param[out] Statistic=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0A pointer to the 32 bit unsigned integer.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_TIMEOUT=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0A timeo= ut occurred executing the request.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+=C2=A0 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid = value.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+

+**/

+EFI_STATUS

+EFIAPI

+GetRndisStatistic (

+=C2=A0 IN=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 UINT16=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0FeatureSelector,

+=C2=A0 OUT VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0*Statistic

+=C2=A0 )

+{

+=C2=A0 return EFI_SUCCESS;

+}

+

+/**

+=C2=A0 This function is called when UndiStart is invoked.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0The request executed success= fully.

+

+**/

+EFI_STATUS

+EFIAPI

+RndisUndiStart (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 Status;

+

+=C2=A0 DEBUG ((DEBUG_INFO, "RndisUndiStart Nic %lx Cdb %lx Nic State = %x\n", Nic, Cdb, Nic->State));

+

+=C2=A0 // Issue Rndis Reset and bring the device to RNDIS_BUS_INITIALIZED = state

+=C2=A0 Status =3D RndisUndiReset (Cdb, Nic);

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 RndisUndiReset (Cdb, Nic);

+=C2=A0 }

+

+=C2=A0 Status =3D RndisUndiInitialize (Cdb, Nic);

+=C2=A0 if (EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 RndisUndiInitialize (Cdb, Nic);

+=C2=A0 }

+

+=C2=A0 RndisUndiShutdown (Cdb, Nic);

+

+=C2=A0 return EFI_SUCCESS;

+}

+

+/**

+=C2=A0 This function is called when Undistop is invoked.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0The request executed success= fully.

+**/

+EFI_STATUS

+EFIAPI

+RndisUndiStop (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 DEBUG ((DEBUG_INFO, "RndisUndiStop State %x\n", Nic->S= tate));

+=C2=A0 return EFI_SUCCESS;

+}

+

+/**

+=C2=A0 This function is called when UndiGetInitInfo is invoked.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0The request executed success= fully.

+

+**/

+EFI_STATUS

+EFIAPI

+RndisUndiGetInitInfo (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *UsbEthDevice=C2=A0 =C2=A0=3D Nic->U= sbEth;

+=C2=A0 USB_RNDIS_DEVICE=C2=A0 =C2=A0 =C2=A0 =C2=A0*UsbRndisDevice =3D USB_= RNDIS_DEVICE_FROM_THIS (UsbEthDevice);

+=C2=A0 PXE_DB_GET_INIT_INFO=C2=A0 =C2=A0*Db;

+

+=C2=A0 DEBUG ((DEBUG_INFO, "RndisUndiGetInitInfo\n"));

+

+=C2=A0 Db =3D (PXE_DB_GET_INIT_INFO *)(UINTN)Cdb->DBaddr;

+

+=C2=A0 Db->FrameDataLen =3D UsbRndisDevice->MaxTransferSize - sizeof= (REMOTE_NDIS_PACKET_MSG) - PXE_MAC_HEADER_LEN_ETHER;

+=C2=A0 // Limit Max MTU size to 1500 bytes as RNDIS spec.

+=C2=A0 if (Db->FrameDataLen > PXE_MAX_TXRX_UNIT_ETHER) {

+=C2=A0 =C2=A0 Db->FrameDataLen =3D PXE_MAX_TXRX_UNIT_ETHER;

+=C2=A0 }

+

+=C2=A0 DEBUG ((DEBUG_INFO, "Db->FrameDataLen %x\n", Db->Fr= ameDataLen));

+

+=C2=A0 return EFI_SUCCESS;

+}

+

+/**

+=C2=A0 This function is called when RndisUndiGetConfigInfo is invoked.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0The request executed success= fully.

+

+**/

+EFI_STATUS

+EFIAPI

+RndisUndiGetConfigInfo (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 DEBUG ((DEBUG_INFO, "RndisUndiGetConfigInfo\n"));

+=C2=A0 return EFI_SUCCESS;

+}

+

+/**

+=C2=A0 This function is called when UndiInitialize is invoked.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_UNSUPPORTED=C2=A0 =C2=A0 =C2=A0 =C2=A0Not supported.
+

+**/

+EFI_STATUS

+EFIAPI

+RndisUndiInitialize (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*UsbEthDrive= r=C2=A0 =C2=A0=3D Nic->UsbEth;

+=C2=A0 USB_RNDIS_DEVICE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 *U= sbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (UsbEthDriver);

+=C2=A0 REMOTE_NDIS_INITIALIZE_MSG=C2=A0 =C2=A0 RndisInitMsg;

+=C2=A0 REMOTE_NDIS_INITIALIZE_CMPLT=C2=A0 RndisInitMsgCmplt;

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 Status;

+

+=C2=A0 DEBUG ((DEBUG_INFO, "RndisUndiInitialize\n"));

+

+=C2=A0 ZeroMem (&RndisInitMsg, sizeof (REMOTE_NDIS_INITIALIZE_MSG));
+=C2=A0 ZeroMem (&RndisInitMsgCmplt, sizeof (REMOTE_NDIS_INITIALIZE_CMP= LT));

+

+=C2=A0 RndisInitMsg.MessageType=C2=A0 =C2=A0 =C2=A0=3D RNDIS_INITIALIZE_MS= G;

+=C2=A0 RndisInitMsg.MessageLength=C2=A0 =C2=A0=3D sizeof (REMOTE_NDIS_INIT= IALIZE_MSG);

+=C2=A0 RndisInitMsg.RequestID=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D UsbRndisDevice= ->RequestId;

+=C2=A0 RndisInitMsg.MajorVersion=C2=A0 =C2=A0 =3D RNDIS_MAJOR_VERSION;

+=C2=A0 RndisInitMsg.MinorVersion=C2=A0 =C2=A0 =3D RNDIS_MINOR_VERSION;

+=C2=A0 RndisInitMsg.MaxTransferSize =3D RNDIS_MAX_TRANSFER_SIZE;

+

+=C2=A0 RndisInitMsgCmplt.MessageType=C2=A0 =C2=A0=3D RNDIS_INITIALIZE_CMPL= T;

+=C2=A0 RndisInitMsgCmplt.MessageLength =3D sizeof (REMOTE_NDIS_INITIALIZE_= CMPLT);

+

+=C2=A0 Status =3D RndisControlMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_HEADER= *)&RndisInitMsg, (REMOTE_NDIS_MSG_HEADER *)&RndisInitMsgCmplt);
+

+=C2=A0 UsbRndisDevice->RequestId++;

+

+=C2=A0 if (EFI_ERROR (Status) || (RndisInitMsgCmplt.Status & 0x8000000= 0)) {

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 // Only Wired Medium is supported

+=C2=A0 if (RndisInitMsgCmplt.Medium) {

+=C2=A0 =C2=A0 return EFI_UNSUPPORTED;

+=C2=A0 }

+

+=C2=A0 UsbRndisDevice->Medium=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =3D RndisInitMsgCmplt.Medium;

+=C2=A0 UsbRndisDevice->MaxPacketsPerTransfer =3D RndisInitMsgCmplt.MaxP= acketsPerTransfer;

+=C2=A0 UsbRndisDevice->MaxTransferSize=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D Rn= disInitMsgCmplt.MaxTransferSize;

+=C2=A0 UsbRndisDevice->PacketAlignmentFactor =3D RndisInitMsgCmplt.Pack= etAlignmentFactor;

+

+=C2=A0 DEBUG ((DEBUG_INFO, "Medium : %x \n", RndisInitMsgCmplt.M= edium));

+=C2=A0 DEBUG ((DEBUG_INFO, "MaxPacketsPerTransfer : %x \n", Rndi= sInitMsgCmplt.MaxPacketsPerTransfer));

+=C2=A0 DEBUG ((DEBUG_INFO, "MaxTransferSize : %x\n", RndisInitMs= gCmplt.MaxTransferSize));

+=C2=A0 DEBUG ((DEBUG_INFO, "PacketAlignmentFactor : %x\n", Rndis= InitMsgCmplt.PacketAlignmentFactor));

+

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 This function is called when UndiReset is invoked.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_DEVICE_ERROR=C2=A0 =C2=A0 =C2=A0 The request failed due= to a device error.

+

+**/

+EFI_STATUS

+EFIAPI

+RndisUndiReset (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 =C2=A0 *UsbEthDriver=C2=A0 =C2=A0=3D Ni= c->UsbEth;

+=C2=A0 USB_RNDIS_DEVICE=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*UsbRndisDevice = =3D USB_RNDIS_DEVICE_FROM_THIS (UsbEthDriver);

+=C2=A0 REMOTE_NDIS_RESET_MSG=C2=A0 =C2=A0 RndisResetMsg;

+=C2=A0 REMOTE_NDIS_RESET_CMPLT=C2=A0 RndisResetCmplt;

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0St= atus;

+

+=C2=A0 DEBUG ((DEBUG_INFO, "RndisUndiReset\n"));

+

+=C2=A0 ZeroMem (&RndisResetMsg, sizeof (REMOTE_NDIS_RESET_MSG));

+=C2=A0 ZeroMem (&RndisResetCmplt, sizeof (REMOTE_NDIS_RESET_CMPLT));
+

+=C2=A0 RndisResetMsg.MessageType=C2=A0 =C2=A0=3D RNDIS_RESET_MSG;

+=C2=A0 RndisResetMsg.MessageLength =3D sizeof (REMOTE_NDIS_RESET_MSG);

+

+=C2=A0 RndisResetCmplt.MessageType=C2=A0 =C2=A0=3D RNDIS_RESET_CMPLT;

+=C2=A0 RndisResetCmplt.MessageLength =3D sizeof (REMOTE_NDIS_RESET_CMPLT);=

+

+=C2=A0 Status =3D RndisControlMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_HEADER= *)&RndisResetMsg, (REMOTE_NDIS_MSG_HEADER *)&RndisResetCmplt);

+

+=C2=A0 UsbRndisDevice->RequestId =3D 1;=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 // Let's start with 1

+

+=C2=A0 if (EFI_ERROR (Status) || (RndisResetCmplt.Status & 0x80000000)= ) {

+=C2=A0 =C2=A0 return EFI_DEVICE_ERROR;

+=C2=A0 }

+

+=C2=A0 return EFI_SUCCESS;

+}

+

+/**

+=C2=A0 This function is called when UndiShutdown is invoked.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0The request executed success= fully.

+

+**/

+EFI_STATUS

+EFIAPI

+RndisUndiShutdown (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *UsbEthDriver=C2=A0 =C2=A0=3D Nic->U= sbEth;

+=C2=A0 USB_RNDIS_DEVICE=C2=A0 =C2=A0 =C2=A0 =C2=A0*UsbRndisDevice =3D USB_= RNDIS_DEVICE_FROM_THIS (UsbEthDriver);

+=C2=A0 REMOTE_NDIS_HALT_MSG=C2=A0 =C2=A0RndisHltMsg;

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Status;
+

+=C2=A0 DEBUG ((DEBUG_INFO, "RndisUndiShutdown\n"));

+

+=C2=A0 ZeroMem (&RndisHltMsg, sizeof (REMOTE_NDIS_HALT_MSG));

+

+=C2=A0 RndisHltMsg.MessageType=C2=A0 =C2=A0=3D RNDIS_HLT_MSG;

+=C2=A0 RndisHltMsg.MessageLength =3D sizeof (REMOTE_NDIS_HALT_MSG);

+

+=C2=A0 Status =3D RndisControlMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_HEADER= *)&RndisHltMsg, NULL);

+

+=C2=A0 if (Status =3D=3D EFI_DEVICE_ERROR) {

+=C2=A0 =C2=A0 Status =3D EFI_SUCCESS;

+=C2=A0 }

+

+=C2=A0 UsbRndisDevice->RequestId =3D 1;

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Update the Media connection.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0The request executed success= fully.

+

+**/

+EFI_STATUS

+EFIAPI

+RndisUndiGetStatus (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 Cdb->StatFlags &=3D ~(PXE_STATFLAGS_GET_STATUS_NO_MEDIA);
+=C2=A0 return EFI_SUCCESS;

+}

+

+/**

+=C2=A0 Transmit the data after appending RNDIS header.

+

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 Cdb=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0A pointer to the command descriptor block.

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 A pointer to the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 BulkOutData=C2=A0 =C2=A0A pointer to= the buffer of data that will be transmitted to USB

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 device or received from USB device.<= br>
+=C2=A0 @param[in, out] DataLength=C2=A0 =C2=A0 A pointer to the PacketLeng= th.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0The request executed success= fully.

+

+**/

+EFI_STATUS

+EFIAPI

+RndisUndiTransmit (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 PXE_CDB=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 *Cdb,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*BulkOutData,

+=C2=A0 IN OUT=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 *DataLength

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Status;<= br>
+=C2=A0 USB_RNDIS_DEVICE=C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbRndisDevice =3D USB= _RNDIS_DEVICE_FROM_THIS (This);

+=C2=A0 REMOTE_NDIS_PACKET_MSG=C2=A0 *RndisPacketMsg;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0TransferLength;

+

+=C2=A0 DEBUG ((DEBUG_INFO, "RndisUndiTransmit DataLength : %x\n"= , *DataLength));

+

+=C2=A0 Status =3D gBS->AllocatePool (EfiBootServicesData, sizeof (REMOT= E_NDIS_PACKET_MSG) + *DataLength, (VOID **)&RndisPacketMsg);

+

+=C2=A0 ZeroMem (RndisPacketMsg, sizeof (REMOTE_NDIS_PACKET_MSG));

+

+=C2=A0 RndisPacketMsg->MessageType=C2=A0 =C2=A0=3D RNDIS_PACKET_MSG;
+=C2=A0 RndisPacketMsg->MessageLength =3D sizeof (REMOTE_NDIS_PACKET_MSG= ) + (UINT32)*DataLength;

+=C2=A0 RndisPacketMsg->DataOffset=C2=A0 =C2=A0 =3D sizeof (REMOTE_NDIS_= PACKET_MSG) - 8;

+=C2=A0 RndisPacketMsg->DataLength=C2=A0 =C2=A0 =3D (UINT32)*DataLength;=

+

+=C2=A0 gBS->CopyMem (((UINT8 *)RndisPacketMsg) + sizeof (REMOTE_NDIS_PA= CKET_MSG), BulkOutData, *DataLength);

+

+=C2=A0 TransferLength =3D RndisPacketMsg->MessageLength;

+

+=C2=A0 Status =3D RndisTransmitDataMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_H= EADER *)RndisPacketMsg, &TransferLength);

+

+=C2=A0 DEBUG ((DEBUG_INFO, "\nRndisUndiTransmit TransferLength %lx\n&= quot;, TransferLength));

+

+=C2=A0 gBS->FreePool (RndisPacketMsg);

+

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Receives and removes RNDIS header and returns the raw data.

+

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 Cdb=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0A pointer to the command descriptor block.

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 This=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 A pointer to the USB_ETHERNET_PROTOCOL instance.

+=C2=A0 @param[in, out] BulkInData=C2=A0 =C2=A0 A pointer to the buffer of = data that will be transmitted to USB

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 device or received from USB device.<= br>
+=C2=A0 @param[in, out] DataLength=C2=A0 =C2=A0 A pointer to the PacketLeng= th.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The req= uest executed successfully.

+=C2=A0 @retval EFI_BUFFER_TOO_SMALL=C2=A0 The user provided buffer is too = small

+=C2=A0 @retval EFI_NOT_FOUND=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0No buffer wa= s found in the list.

+

+**/

+EFI_STATUS

+EFIAPI

+RndisUndiReceive (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0PXE_CDB=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 *Cdb,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0USB_ETHERNET_PROTOCOL=C2=A0 *This,

+=C2=A0 IN OUT VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0*BulkInData,

+=C2=A0 IN OUT UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 *DataLength

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Status;<= br>
+=C2=A0 USB_RNDIS_DEVICE=C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbRndisDevice =3D USB= _RNDIS_DEVICE_FROM_THIS (This);

+=C2=A0 REMOTE_NDIS_PACKET_MSG=C2=A0 *RndisPacketMsg;

+=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0TransferLength;

+=C2=A0 VOID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 *Buffer;

+=C2=A0 PACKET_LIST=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*HeadPac= ket =3D NULL;

+=C2=A0 PACKET_LIST=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*PacketL= ist;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 ReceivedBytes =3D 0;

+

+=C2=A0 // Check if there is any outstanding packet to receive

+=C2=A0 // The buffer allocated has a linked List followed by the packet.
+=C2=A0 do {

+=C2=A0 =C2=A0 Status=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D gBS->Allocate= Pool (EfiBootServicesData, sizeof (PACKET_LIST) + sizeof (REMOTE_NDIS_PACKE= T_MSG) + UsbRndisDevice->MaxTransferSize, &Buffer);

+=C2=A0 =C2=A0 RndisPacketMsg =3D (REMOTE_NDIS_PACKET_MSG *)(sizeof (PACKET= _LIST) + (UINT8 *)Buffer);

+=C2=A0 =C2=A0 PacketList=C2=A0 =C2=A0 =C2=A0=3D (PACKET_LIST *)Buffer;

+=C2=A0 =C2=A0 // Save the original address for freeing it up

+=C2=A0 =C2=A0 PacketList->OrgBuffer=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D Buffe= r;

+=C2=A0 =C2=A0 PacketList->RemainingLength =3D UsbRndisDevice->MaxTra= nsferSize;

+

+=C2=A0 =C2=A0 ZeroMem (RndisPacketMsg, sizeof (REMOTE_NDIS_PACKET_MSG));
+=C2=A0 =C2=A0 TransferLength =3D UsbRndisDevice->MaxTransferSize;

+

+=C2=A0 =C2=A0 Status =3D RndisReceiveDataMsg (UsbRndisDevice, (REMOTE_NDIS= _MSG_HEADER *)RndisPacketMsg, &TransferLength);

+

+=C2=A0 =C2=A0 if (EFI_ERROR (Status) || (TransferLength =3D=3D 0)) {

+=C2=A0 =C2=A0 =C2=A0 gBS->FreePool (Buffer);

+=C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 // Handle Multiple packets

+=C2=A0 =C2=A0 if ((RndisPacketMsg->MessageType =3D=3D RNDIS_PACKET_MSG)= && (RndisPacketMsg->DataOffset =3D=3D sizeof (REMOTE_NDIS_PACKE= T_MSG) - 8)) {

+=C2=A0 =C2=A0 =C2=A0 // Insert Packet

+=C2=A0 =C2=A0 =C2=A0 InsertTailList (&UsbRndisDevice->ReceivePacket= List, Buffer);

+=C2=A0 =C2=A0 }

+=C2=A0 } while (1);

+

+=C2=A0 // Check if they linked list has any received buffer. If yes report= it.

+=C2=A0 if (IsListEmpty (&UsbRndisDevice->ReceivePacketList)) {

+=C2=A0 =C2=A0 return EFI_NOT_FOUND;

+=C2=A0 }

+

+=C2=A0 HeadPacket =3D (PACKET_LIST *)GetFirstNode (&UsbRndisDevice->= ;ReceivePacketList);

+

+=C2=A0 RndisPacketMsg =3D (REMOTE_NDIS_PACKET_MSG *)((UINT8 *)HeadPacket += sizeof (PACKET_LIST));

+

+=C2=A0 PrintRndisMsg ((REMOTE_NDIS_MSG_HEADER *)RndisPacketMsg);

+

+=C2=A0 if ((RndisPacketMsg->MessageType =3D=3D RNDIS_PACKET_MSG) &&= amp; (RndisPacketMsg->DataOffset =3D=3D sizeof (REMOTE_NDIS_PACKET_MSG) = - 8)) {

+=C2=A0 =C2=A0 if (*DataLength >=3D RndisPacketMsg->DataLength) {

+=C2=A0 =C2=A0 =C2=A0 gBS->CopyMem (BulkInData, (UINT8 *)RndisPacketMsg = + RndisPacketMsg->DataOffset + 8, RndisPacketMsg->DataLength);

+

+=C2=A0 =C2=A0 =C2=A0 ReceivedBytes=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 += =3D RndisPacketMsg->DataLength;

+=C2=A0 =C2=A0 =C2=A0 BulkInData=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =3D ((UINT8 *)BulkInData) + RndisPacketMsg->DataLength;

+=C2=A0 =C2=A0 =C2=A0 ((PACKET_LIST *)HeadPacket)->RemainingLength -=3D = RndisPacketMsg->DataLength;

+=C2=A0 =C2=A0 } else {

+=C2=A0 =C2=A0 =C2=A0 DEBUG ((EFI_D_ERROR, "RndisUndiReceive:Buffer to= o small %x\n", RndisPacketMsg->DataLength));

+=C2=A0 =C2=A0 =C2=A0 *DataLength =3D RndisPacketMsg->DataLength;

+=C2=A0 =C2=A0 =C2=A0 return EFI_BUFFER_TOO_SMALL;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 // check if there this is a multi-packet message. If so upda= te the pointer so that next Receive call will return that data.

+=C2=A0 =C2=A0 RndisPacketMsg =3D (REMOTE_NDIS_PACKET_MSG *)((UINT8 *)Rndis= PacketMsg + RndisPacketMsg->DataLength);

+=C2=A0 =C2=A0 PacketList=C2=A0 =C2=A0 =C2=A0=3D (PACKET_LIST *)((UINT8 *)R= ndisPacketMsg - sizeof (PACKET_LIST));

+

+=C2=A0 =C2=A0 if ((HeadPacket->RemainingLength > sizeof (REMOTE_NDIS= _PACKET_MSG)) && \

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 (RndisPacketMsg->MessageType =3D=3D RNDIS_P= ACKET_MSG) && \

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 (RndisPacketMsg->DataOffset =3D=3D sizeof (= REMOTE_NDIS_PACKET_MSG) - 8))

+=C2=A0 =C2=A0 {

+=C2=A0 =C2=A0 =C2=A0 // Multi-Packet msg is found. Since the first packet = is consumed, update the linked list to point this new packet.

+=C2=A0 =C2=A0 =C2=A0 PacketList->OrgBuffer=C2=A0 =C2=A0 =C2=A0 =C2=A0= =3D HeadPacket->OrgBuffer;

+=C2=A0 =C2=A0 =C2=A0 PacketList->RemainingLength =3D HeadPacket->Rem= ainingLength;

+=C2=A0 =C2=A0 =C2=A0 RemoveEntryList (&HeadPacket->PacketList);

+=C2=A0 =C2=A0 =C2=A0 InsertHeadList (&UsbRndisDevice->ReceivePacket= List, &(PacketList->PacketList));

+=C2=A0 =C2=A0 } else {

+=C2=A0 =C2=A0 =C2=A0 RemoveEntryList (&HeadPacket->PacketList);

+=C2=A0 =C2=A0 =C2=A0 gBS->FreePool ((PACKET_LIST *)HeadPacket->OrgBu= ffer);

+=C2=A0 =C2=A0 }

+=C2=A0 } else {

+=C2=A0 =C2=A0 // Packet doesn't contain valid header

+=C2=A0 =C2=A0 DEBUG ((DEBUG_INFO, "RndisUndiReceive:Invalid RNDIS Pac= ket received\n"));

+=C2=A0 =C2=A0 RemoveEntryList (&(HeadPacket->PacketList));

+=C2=A0 =C2=A0 gBS->FreePool ((PACKET_LIST *)HeadPacket->OrgBuffer);<= br>
+=C2=A0 }

+

+=C2=A0 if (ReceivedBytes) {

+=C2=A0 =C2=A0 *DataLength =3D ReceivedBytes;

+=C2=A0 }

+

+=C2=A0 return EFI_SUCCESS;

+}

+

+/**

+=C2=A0 This is a dummy function which just returns. Unimplimented USB_ETHE= RNET_PROTOCOL functions

+=C2=A0 point to this function.

+

+=C2=A0 @param[in]=C2=A0 Cdb=C2=A0 A pointer to the command descriptor bloc= k.

+=C2=A0 @param[in]=C2=A0 Nic=C2=A0 A pointer to the Network interface contr= oller data.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0The request executed success= fully.

+

+**/

+EFI_STATUS

+EFIAPI

+RndisDummyReturn (

+=C2=A0 IN=C2=A0 PXE_CDB=C2=A0 =C2=A0*Cdb,

+=C2=A0 IN=C2=A0 NIC_DATA=C2=A0 *Nic

+=C2=A0 )

+{

+=C2=A0 DEBUG ((DEBUG_INFO, "RndisDummyReturn called\n"));

+=C2=A0 return EFI_SUCCESS;

+}

+

+/**

+=C2=A0 This function sends the RNDIS SET_MSG cmd

+

+=C2=A0 @param[in]=C2=A0 UsbRndisDevice=C2=A0 A pointer to the USB_RNDIS_DE= VICE instance.

+=C2=A0 @param[in]=C2=A0 Oid=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0Value of the OID.

+=C2=A0 @param[in]=C2=A0 Length=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Length of= the data buffer.

+=C2=A0 @param[in]=C2=A0 Buf=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0A pointer to the data buffer.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The request ex= ecuted successfully.

+

+**/

+EFI_STATUS

+SendRndisSetMsg (

+=C2=A0 IN=C2=A0 USB_RNDIS_DEVICE=C2=A0 *UsbRndisDevice,

+=C2=A0 IN=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Oid,<= br>
+=C2=A0 IN=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Length,
+=C2=A0 IN=C2=A0 UINT8=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*Buf<= br>
+=C2=A0 )

+{

+=C2=A0 REMOTE_NDIS_SET_MSG=C2=A0 *RndisSetMsg;

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0Status;

+

+=C2=A0 RndisSetMsg =3D AllocateZeroPool (sizeof (USB_RNDIS_DEVICE) + Lengt= h);

+

+=C2=A0 RndisSetMsg->MessageType=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0=3D RNDIS_SET_MSG;

+=C2=A0 RndisSetMsg->MessageLength=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0=3D sizeof (REMOTE_NDIS_SET_MSG) + Length;

+=C2=A0 RndisSetMsg->RequestID=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0=3D UsbRndisDevice->RequestId;

+=C2=A0 RndisSetMsg->Oid=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0=3D Oid;

+=C2=A0 RndisSetMsg->InformationBufferLength =3D Length;

+=C2=A0 RndisSetMsg->InformationBufferOffset =3D sizeof (REMOTE_NDIS_SET= _MSG) - 8;

+

+=C2=A0 gBS->CopyMem (((UINT8 *)RndisSetMsg) + sizeof (REMOTE_NDIS_SET_M= SG), Buf, Length);

+

+=C2=A0 Status =3D RndisControlMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_HEADER= *)RndisSetMsg, NULL);

+

+=C2=A0 gBS->FreePool (RndisSetMsg);

+

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 This function send the RNDIS command through the device's contr= ol endpoint

+

+=C2=A0 @param[in]=C2=A0 UsbRndisDevice=C2=A0 =C2=A0 A pointer to the USB_R= NDIS_DEVICE instance.

+=C2=A0 @param[in]=C2=A0 RndisMsg=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A point= er to the REMOTE_NDIS_MSG_HEADER data.

+=C2=A0 @param[out] RndisMsgResponse=C2=A0 A pointer to the REMOTE_NDIS_MSG= _HEADER data for getting responses.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0The bul= k transfer has been successfully executed.

+

+**/

+EFI_STATUS

+RndisControlMsg (

+=C2=A0 IN=C2=A0 USB_RNDIS_DEVICE=C2=A0 =C2=A0 =C2=A0 =C2=A0 *UsbRndisDevic= e,

+=C2=A0 IN=C2=A0 REMOTE_NDIS_MSG_HEADER=C2=A0 *RndisMsg,

+=C2=A0 OUT REMOTE_NDIS_MSG_HEADER=C2=A0 *RndisMsgResponse

+=C2=A0 )

+{

+=C2=A0 EFI_USB_IO_PROTOCOL=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0*UsbIo = =3D UsbRndisDevice->UsbIo;

+=C2=A0 EFI_USB_DEVICE_REQUEST=C2=A0 =C2=A0 =C2=A0 =C2=A0 DevReq;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 UsbStatus;

+=C2=A0 EFI_STATUS=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 Status;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 SaveResponseType=C2=A0 =C2=A0=3D 0;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 SaveResponseLength =3D 0;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 Index;

+=C2=A0 REMOTE_NDIS_INITIALIZE_CMPLT=C2=A0 *RndisInitCmplt =3D (REMOTE_NDIS= _INITIALIZE_CMPLT *)RndisMsgResponse;

+

+=C2=A0 if (RndisMsgResponse) {

+=C2=A0 =C2=A0 SaveResponseType=C2=A0 =C2=A0=3D RndisMsgResponse->Messag= eType;

+=C2=A0 =C2=A0 SaveResponseLength =3D RndisMsgResponse->MessageLength;
+=C2=A0 }

+

+=C2=A0 ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));

+

+=C2=A0 DevReq.RequestType =3D USB_REQ_TYPE_CLASS | USB_TARGET_INTERFACE;
+=C2=A0 DevReq.Request=C2=A0 =C2=A0 =C2=A0=3D SEND_ENCAPSULATED_COMMAND;
+=C2=A0 DevReq.Value=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D 0;

+=C2=A0 DevReq.Index=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D 0;

+=C2=A0 DevReq.Length=C2=A0 =C2=A0 =C2=A0 =3D (UINT16)RndisMsg->MessageL= ength;

+

+=C2=A0 PrintRndisMsg (RndisMsg);

+

+=C2=A0 Status =3D UsbIo->UsbControlTransfer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 UsbI= o,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &= ;DevReq,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 EfiU= sbDataOut,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 USB_= ETHERNET_TRANSFER_TIMEOUT,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Rndi= sMsg,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 Rndi= sMsg->MessageLength,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 &= ;UsbStatus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 );
+

+=C2=A0 DEBUG ((DEBUG_INFO, "RndisControlMsg: UsbStatus : %x Status : = %r RndisMsgResponse : %lx\n", UsbStatus, Status, RndisMsgResponse));
+

+=C2=A0 // Error or no response expected

+=C2=A0 if ((EFI_ERROR (Status)) || (RndisMsgResponse =3D=3D NULL)) {

+=C2=A0 =C2=A0 DEBUG ((DEBUG_INFO, "RndisControlMsg: UsbStatus : %x St= atus : %r\n", UsbStatus, Status));

+=C2=A0 =C2=A0 return Status;

+=C2=A0 }

+

+=C2=A0 for (Index =3D 0; Index < (RNDIS_CONTROL_TIMEOUT/100); Index++) = {

+=C2=A0 =C2=A0 ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));

+

+=C2=A0 =C2=A0 DevReq.RequestType =3D USB_ENDPOINT_DIR_IN | USB_REQ_TYPE_CL= ASS | USB_TARGET_INTERFACE;

+=C2=A0 =C2=A0 DevReq.Request=C2=A0 =C2=A0 =C2=A0=3D GET_ENCAPSULATED_RESPO= NSE;

+=C2=A0 =C2=A0 DevReq.Value=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D 0;

+=C2=A0 =C2=A0 DevReq.Index=C2=A0 =C2=A0 =C2=A0 =C2=A0=3D 0;

+=C2=A0 =C2=A0 DevReq.Length=C2=A0 =C2=A0 =C2=A0 =3D (UINT16)RndisMsgRespon= se->MessageLength;

+

+=C2=A0 =C2=A0 Status =3D UsbIo->UsbControlTransfer (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 UsbIo,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 &DevReq,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 EfiUsbDataIn,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 USB_ETHERNET_TRANSFER_TIMEOUT,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 RndisMsgResponse,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 RndisMsgResponse->MessageLength,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 &UsbStatus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 );

+

+=C2=A0 =C2=A0 DEBUG ((DEBUG_INFO, "RndisControlMsg Response: UsbStatu= s : %x Status : %r \n", UsbStatus, Status));

+

+=C2=A0 =C2=A0 PrintRndisMsg (RndisMsgResponse);

+

+=C2=A0 =C2=A0 if (!EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 if ((RndisInitCmplt->RequestID !=3D ((REMOTE_NDIS_= INITIALIZE_CMPLT *)RndisMsg)->RequestID) || (RndisInitCmplt->MessageT= ype !=3D SaveResponseType)) {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 DEBUG ((DEBUG_INFO, "Retry the response\n= "));

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 continue;

+=C2=A0 =C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 =C2=A0 return Status;

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 RndisMsgResponse->MessageType=C2=A0 =C2=A0=3D SaveRespons= eType;

+=C2=A0 =C2=A0 RndisMsgResponse->MessageLength =3D SaveResponseLength;
+

+=C2=A0 =C2=A0 gBS->Stall (100000);=C2=A0 =C2=A0 // 100msec

+=C2=A0 }

+

+=C2=A0 DEBUG ((DEBUG_INFO, "RndisControlMsg: TimeOut\n"));

+

+=C2=A0 return EFI_TIMEOUT;

+}

+

+/**

+=C2=A0 This function send the RNDIS command through the device's Data = endpoint

+

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 UsbRndisDevice=C2=A0 A pointer to th= e USB_RNDIS_DEVICE instance.

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 RndisMsg=C2=A0 =C2=A0 =C2=A0 =C2=A0 = A pointer to the REMOTE_NDIS_MSG_HEADER to send out.

+=C2=A0 @param[in, out] TransferLength=C2=A0 The length of the RndisMsg dat= a to transfer.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0The request executed success= fully.

+

+**/

+EFI_STATUS

+RndisTransmitDataMsg (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 USB_RNDIS_DEVICE=C2=A0 =C2=A0 =C2=A0 =C2=A0 = *UsbRndisDevice,

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 REMOTE_NDIS_MSG_HEADER=C2=A0 *RndisMsg,

+=C2=A0 IN OUT=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0*TransferLength

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 Status;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 UsbStatus;

+

+=C2=A0 if (UsbRndisDevice->BulkInEndpoint =3D=3D 0) {

+=C2=A0 =C2=A0 GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice= );

+=C2=A0 }

+

+=C2=A0 PrintRndisMsg (RndisMsg);

+

+=C2=A0 Status =3D UsbRndisDevice->UsbIoCdcData->UsbBulkTransfer (
+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0UsbRndisDevice->UsbIoCdcData,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0UsbRndisDevice->BulkOutEndpoint,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0RndisMsg,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0TransferLength,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0USB_TX_ETHERNET_BULK_TIMEOUT,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0&UsbStatus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0);

+

+=C2=A0 if (Status =3D=3D EFI_SUCCESS) {

+=C2=A0 =C2=A0 StopBulkInCnt =3D MAXIMUM_STOPBULKIN_CNT;=C2=A0 =C2=A0 =C2= =A0// After sending cmd ,we will polling receive package for MAXIMUM_STOPBU= LKIN_CNT times

+=C2=A0 }

+

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 This function send the RNDIS command through the device's Data = endpoint

+

+=C2=A0 @param[in]=C2=A0 =C2=A0 =C2=A0 UsbRndisDevice=C2=A0 =C2=A0 A pointe= r to the USB_RNDIS_DEVICE instance.

+=C2=A0 @param[in, out] RndisMsg=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 A pointe= r to the REMOTE_NDIS_MSG_HEADER to send out.

+=C2=A0 @param[in, out] TransferLength=C2=A0 =C2=A0 The length of the Rndis= Msg data to transfer.

+

+=C2=A0 @retval EFI_SUCCESS=C2=A0 =C2=A0 =C2=A0The request executed success= fully.

+

+**/

+EFI_STATUS

+RndisReceiveDataMsg (

+=C2=A0 IN=C2=A0 =C2=A0 =C2=A0 USB_RNDIS_DEVICE=C2=A0 =C2=A0 =C2=A0 =C2=A0 = *UsbRndisDevice,

+=C2=A0 IN OUT=C2=A0 REMOTE_NDIS_MSG_HEADER=C2=A0 *RndisMsg,

+=C2=A0 IN OUT=C2=A0 UINTN=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0*TransferLength

+=C2=A0 )

+{

+=C2=A0 EFI_STATUS=C2=A0 Status;

+=C2=A0 UINT32=C2=A0 =C2=A0 =C2=A0 UsbStatus =3D 0;

+

+=C2=A0 if (UsbRndisDevice->BulkInEndpoint =3D=3D 0) {

+=C2=A0 =C2=A0 GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice= );

+=C2=A0 }

+

+=C2=A0 // Use StopBulkInCnt to stop BulkIn command

+=C2=A0 if (StopBulkInCnt || LAN_BULKIN_CMD_CONTROL) {

+=C2=A0 =C2=A0 Status =3D UsbRndisDevice->UsbIoCdcData->UsbBulkTransf= er (

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0UsbRndisDevice->UsbIoCdcData,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0UsbRndisDevice->BulkInEndpoint,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0RndisMsg,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0TransferLength,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0USB_RX_ETHERNET_BULK_TIMEOUT,

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0&UsbStatus

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0);

+

+=C2=A0 =C2=A0 if (!EFI_ERROR (Status)) {

+=C2=A0 =C2=A0 =C2=A0 StopBulkInCnt =3D MINIMUM_STOPBULKIN_CNT;

+=C2=A0 =C2=A0 } else {

+=C2=A0 =C2=A0 =C2=A0 StopBulkInCnt--;

+=C2=A0 =C2=A0 }

+=C2=A0 } else {

+=C2=A0 =C2=A0 Status=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =3D EFI_TIMEOUT;
+=C2=A0 =C2=A0 *TransferLength =3D 0;

+=C2=A0 =C2=A0 BlockBulkInCnt++;

+=C2=A0 }

+

+=C2=A0 if (BlockBulkInCnt > BULKIN_CMD_POLLING_CNT) {

+=C2=A0 =C2=A0 StopBulkInCnt=C2=A0 =3D MINIMUM_STOPBULKIN_CNT;

+=C2=A0 =C2=A0 BlockBulkInCnt =3D 0;

+=C2=A0 }

+

+=C2=A0 PrintRndisMsg (RndisMsg);

+

+=C2=A0 return Status;

+}

+

+/**

+=C2=A0 Prints RNDIS Header and Data

+

+=C2=A0 @param[in] RndisMsg=C2=A0 =C2=A0 A pointer to the REMOTE_NDIS_MSG_H= EADER data.

+

+**/

+VOID

+PrintRndisMsg (

+=C2=A0 IN=C2=A0 REMOTE_NDIS_MSG_HEADER=C2=A0 *RndisMsg

+=C2=A0 )

+{

+=C2=A0 UINTN=C2=A0 Length =3D 0;

+

+=C2=A0 switch (RndisMsg->MessageType) {

+=C2=A0 =C2=A0 case RNDIS_PACKET_MSG:

+=C2=A0 =C2=A0 =C2=A0 DEBUG ((DEBUG_INFO, "RNDIS_PACKET_MSG:\n"))= ;

+=C2=A0 =C2=A0 =C2=A0 Length =3D sizeof (REMOTE_NDIS_PACKET_MSG) + 0x14;
+=C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 case RNDIS_INITIALIZE_MSG:

+=C2=A0 =C2=A0 =C2=A0 DEBUG ((DEBUG_INFO, "RNDIS_INITIALIZE_MSG:\n&quo= t;));

+=C2=A0 =C2=A0 =C2=A0 Length =3D sizeof (REMOTE_NDIS_INITIALIZE_MSG);

+=C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 case RNDIS_INITIALIZE_CMPLT:

+=C2=A0 =C2=A0 =C2=A0 DEBUG ((DEBUG_INFO, "RNDIS_INITIALIZE_CMPLT:\n&q= uot;));

+=C2=A0 =C2=A0 =C2=A0 Length =3D sizeof (REMOTE_NDIS_INITIALIZE_CMPLT);

+=C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 case RNDIS_HLT_MSG:

+=C2=A0 =C2=A0 =C2=A0 DEBUG ((DEBUG_INFO, "RNDIS_HLT_MSG:\n"));
+=C2=A0 =C2=A0 =C2=A0 Length =3D sizeof (REMOTE_NDIS_HALT_MSG);

+=C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 case RNDIS_QUERY_MSG:

+=C2=A0 =C2=A0 =C2=A0 DEBUG ((DEBUG_INFO, "RNDIS_QUERY_MSG:\n"));=

+=C2=A0 =C2=A0 =C2=A0 Length =3D sizeof (REMOTE_NDIS_QUERY_MSG);

+=C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 case RNDIS_QUERY_CMPLT:

+=C2=A0 =C2=A0 =C2=A0 DEBUG ((DEBUG_INFO, "RNDIS_QUERY_CMPLT:\n")= );

+=C2=A0 =C2=A0 =C2=A0 Length =3D sizeof (REMOTE_NDIS_QUERY_CMPLT);

+=C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 case RNDIS_SET_MSG:

+=C2=A0 =C2=A0 =C2=A0 DEBUG ((DEBUG_INFO, "RNDIS_SET_MSG:\n"));
+=C2=A0 =C2=A0 =C2=A0 Length =3D sizeof (REMOTE_NDIS_SET_MSG);

+=C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 case RNDIS_SET_CMPLT:

+=C2=A0 =C2=A0 =C2=A0 DEBUG ((DEBUG_INFO, "RNDIS_SET_CMPLT:\n"));=

+=C2=A0 =C2=A0 =C2=A0 Length =3D sizeof (REMOTE_NDIS_SET_CMPLT);

+=C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 case RNDIS_RESET_MSG:

+=C2=A0 =C2=A0 =C2=A0 DEBUG ((DEBUG_INFO, "RNDIS_RESET_MSG:\n"));=

+=C2=A0 =C2=A0 =C2=A0 Length =3D sizeof (REMOTE_NDIS_RESET_MSG);

+=C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 case RNDIS_RESET_CMPLT:

+=C2=A0 =C2=A0 =C2=A0 DEBUG ((DEBUG_INFO, "RNDIS_RESET_CMPLT:\n")= );

+=C2=A0 =C2=A0 =C2=A0 Length =3D sizeof (REMOTE_NDIS_RESET_CMPLT);

+=C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 case RNDIS_INDICATE_STATUS_MSG:

+=C2=A0 =C2=A0 =C2=A0 DEBUG ((DEBUG_INFO, "RNDIS_INDICATE_STATUS_MSG:\= n"));

+=C2=A0 =C2=A0 =C2=A0 Length =3D sizeof (REMOTE_NDIS_INDICATE_STATUS_MSG);<= br>
+=C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 case RNDIS_KEEPALIVE_MSG:

+=C2=A0 =C2=A0 =C2=A0 DEBUG ((DEBUG_INFO, "RNDIS_KEEPALIVE_MSG:\n"= ;));

+=C2=A0 =C2=A0 =C2=A0 Length =3D sizeof (REMOTE_NDIS_KEEPALIVE_MSG);

+=C2=A0 =C2=A0 =C2=A0 break;

+=C2=A0 =C2=A0 case RNDIS_KEEPALIVE_CMPLT:

+=C2=A0 =C2=A0 =C2=A0 DEBUG ((DEBUG_INFO, "RNDIS_KEEPALIVE_CMPLT:\n&qu= ot;));

+=C2=A0 =C2=A0 =C2=A0 Length =3D sizeof (REMOTE_NDIS_KEEPALIVE_CMPLT);

+=C2=A0 }

+

+=C2=A0 if (Length) {

+=C2=A0 =C2=A0 UINTN=C2=A0 Index =3D 0;

+=C2=A0 =C2=A0 for ( ; Length; Length -=3D 4, Index++) {

+=C2=A0 =C2=A0 =C2=A0 DEBUG ((DEBUG_INFO, "%8X\t", RndisMsg[Index= ]));

+=C2=A0 =C2=A0 =C2=A0 if (((Index % 4) =3D=3D 3) && (Index !=3D 0))= {

+=C2=A0 =C2=A0 =C2=A0 =C2=A0 DEBUG ((DEBUG_INFO, "\n"));

+=C2=A0 =C2=A0 =C2=A0 }

+=C2=A0 =C2=A0 }

+

+=C2=A0 =C2=A0 if (Index % 4) {

+=C2=A0 =C2=A0 =C2=A0 DEBUG ((DEBUG_INFO, "\n"));

+=C2=A0 =C2=A0 }

+=C2=A0 }

+}

--
2.35.1.windows.2
-The information contained in this message may be confidential and propriet= ary to American Megatrends (AMI). This communication is intended to be read= only by the individual or entity to whom it is addressed or by their desig= nee. If the reader of this message is not the intended recipient, you are o= n notice that any distribution of this message, in any form, is strictly pr= ohibited. Please promptly notify the sender by reply e-mail or by telephone= at 770-246-8600, and then delete or destroy all copies of the transmission= .







--
Pedro Falcato


--
Pedro Falcato
--000000000000937e2e05e69a233a--