From: "Rebecca Cran" <rebecca@bsdio.com>
To: devel@edk2.groups.io, tinhnguyen@os.amperecomputing.com,
"Richard Ho (何明忠)" <RichardHo@ami.com>
Cc: "Andrew Fish" <afish@apple.com>,
"Leif Lindholm" <quic_llindhol@quicinc.com>,
"Michael D Kinney" <michael.d.kinney@intel.com>,
"Michael Kubacki" <mikuback@linux.microsoft.com>,
"Zhiguang Liu" <zhiguang.liu@intel.com>,
"Liming Gao" <gaoliming@byosoft.com.cn>,
"Tony Lo (羅金松)" <TonyLo@ami.com>
Subject: Re: [edk2-devel] [PATCH v6 1/3] UsbNetworkPkg/UsbRndis: Add USB RNDIS devices support
Date: Mon, 27 Mar 2023 09:13:32 -0600 [thread overview]
Message-ID: <9c2f244b-280f-8eb8-c352-79dcb41fa4e1@bsdio.com> (raw)
In-Reply-To: <2a40d264-3446-a2b7-4a55-2f1455f4ee32@amperemail.onmicrosoft.com>
I'll review them later today.
--
Rebecca Cran
On 3/27/23 8:59 AM, Tinh Nguyen via groups.io wrote:
> Are there any plans for these patches? Could someone please assist in
> reviewing these?
>
> On 3/9/2023 2:51 PM, Richard Ho (何明忠) wrote:
>> This driver provides UEFI driver for USB RNDIS device
>>
>> Signed-off-by: Richard Ho <richardho@ami.com>
>> Cc: Andrew Fish <afish@apple.com>
>> Cc: Leif Lindholm <quic_llindhol@quicinc.com>
>> Cc: Michael D Kinney <michael.d.kinney@intel.com>
>> Cc: Michael Kubacki <mikuback@linux.microsoft.com>
>> Cc: Zhiguang Liu <zhiguang.liu@intel.com>
>> Cc: Liming Gao <gaoliming@byosoft.com.cn>
>> Cc: Rebecca Cran <rebecca@bsdio.com>
>> Tested-by: Tinh Nguyen <tinhnguyen@os.amperecomputing.com>
>> Reviewed-by: Tony Lo <tonylo@ami.com>
>> ---
>> UsbNetworkPkg/UsbNetworkPkg.dec | 46 +
>> UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc | 9 +
>> .../Config/UsbNetworkPkgComponentsDxe.inc.dsc | 20 +
>> .../Config/UsbNetworkPkgDefines.inc.dsc | 23 +
>> .../Config/UsbNetworkPkgComponentsDxe.inc.fdf | 20 +
>> UsbNetworkPkg/NetworkCommon/NetworkCommon.inf | 49 +
>> UsbNetworkPkg/UsbRndis/UsbRndis.inf | 42 +
>> .../Protocol/EdkIIUsbEthernetProtocol.h | 878 ++++++++
>> UsbNetworkPkg/NetworkCommon/DriverBinding.h | 266 +++
>> UsbNetworkPkg/UsbRndis/UsbRndis.h | 586 ++++++
>> UsbNetworkPkg/NetworkCommon/ComponentName.c | 263 +++
>> UsbNetworkPkg/NetworkCommon/DriverBinding.c | 595 ++++++
>> UsbNetworkPkg/NetworkCommon/PxeFunction.c | 1803 +++++++++++++++++
>> UsbNetworkPkg/UsbRndis/ComponentName.c | 172 ++
>> UsbNetworkPkg/UsbRndis/UsbRndis.c | 886 ++++++++
>> UsbNetworkPkg/UsbRndis/UsbRndisFunction.c | 1718 ++++++++++++++++
>> UsbNetworkPkg/ReadMe.md | 65 +
>> UsbNetworkPkg/ReleaseNotes.md | 11 +
>> 18 files changed, 7452 insertions(+)
>> create mode 100644 UsbNetworkPkg/UsbNetworkPkg.dec
>> create mode 100644 UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc
>> create mode 100644
>> UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc
>> create mode 100644 UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc
>> create mode 100644
>> UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf
>> create mode 100644 UsbNetworkPkg/NetworkCommon/NetworkCommon.inf
>> create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndis.inf
>> create mode 100644
>> UsbNetworkPkg/Include/Protocol/EdkIIUsbEthernetProtocol.h
>> create mode 100644 UsbNetworkPkg/NetworkCommon/DriverBinding.h
>> create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndis.h
>> create mode 100644 UsbNetworkPkg/NetworkCommon/ComponentName.c
>> create mode 100644 UsbNetworkPkg/NetworkCommon/DriverBinding.c
>> create mode 100644 UsbNetworkPkg/NetworkCommon/PxeFunction.c
>> create mode 100644 UsbNetworkPkg/UsbRndis/ComponentName.c
>> create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndis.c
>> create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndisFunction.c
>> create mode 100644 UsbNetworkPkg/ReadMe.md
>> create mode 100644 UsbNetworkPkg/ReleaseNotes.md
>>
>> diff --git a/UsbNetworkPkg/UsbNetworkPkg.dec
>> b/UsbNetworkPkg/UsbNetworkPkg.dec
>> new file mode 100644
>> index 000000000000..30e4e4c8aac7
>> --- /dev/null
>> +++ b/UsbNetworkPkg/UsbNetworkPkg.dec
>> @@ -0,0 +1,46 @@
>> +## @file
>> +# This package defines Usb network specific interfaces and library
>> classes
>> +# as well as configuration for standard edk2 packages.
>> +#
>> +# Copyright (c) 2023, American Megatrends International LLC. All
>> rights reserved.<BR>
>> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>> +##
>> +
>> +[Defines]
>> + DEC_SPECIFICATION = 0x00010005
>> + PACKAGE_NAME = UsbNetworkPkg
>> + PACKAGE_GUID = abfab91e-37ea-4cb4-80a6-563dbb0bcec6
>> + PACKAGE_VERSION = 0.1
>> +
>> +[Includes]
>> + Include
>> +
>> +[Protocols]
>> + ## Include/Protocol/EdkIIUsbEthernet.h
>> + gEdkIIUsbEthProtocolGuid = { 0x8d8969cc, 0xfeb0, 0x4303, { 0xb2,
>> 0x1a, 0x1f, 0x11, 0x6f, 0x38, 0x56, 0x43 } }
>> +
>> +[Guids]
>> + ## Usb Network package token space GUID
>> + gUsbNetworkPkgTokenSpaceGuid = { 0xA1231E82, 0x21B8, 0x4204, {
>> 0x92, 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|0x00000001
>> +
>> + ## Set the PCD 'UsbCdcNcmSupport' to 'TRUE' if 'Usb Cdc Ncm
>> device' need to be enabled.
>> + gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport|FALSE|BOOLEAN|0x00000002
>> +
>> + ## Set the PCD 'UsbRndisSupport' to 'TRUE' if 'Usb Rndis device'
>> need to be enabled.
>> + gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport|TRUE|BOOLEAN|0x00000003
>> +
>> +[PcdsFixedAtBuild, PcdsPatchableInModule]
>> + ## Support rate limiting
>> +
>> gUsbNetworkPkgTokenSpaceGuid.EnableRateLimiting|FALSE|BOOLEAN|0x00010001
>> +
>> + ## The rate limiting Credit value is check in rate limiter event.
>> + # It is to control the RateLimitingCreditCount max value.
>> + gUsbNetworkPkgTokenSpaceGuid.RateLimitingCredit|10|UINT32|0x00010002
>> +
>> + ## The value of rate limiter event for timeout check. Default
>> value is 100(unit 1ms).
>> + gUsbNetworkPkgTokenSpaceGuid.RateLimitingFactor|100|UINT32|0x00010003
>> diff --git a/UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc
>> b/UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc
>> new file mode 100644
>> index 000000000000..a3316b1d4a89
>> --- /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) 2023, American Megatrends International LLC. All
>> rights reserved.<BR>
>> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>> +##
>> +
>> +[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 000000000000..544df8404c64
>> --- /dev/null
>> +++ b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc
>> @@ -0,0 +1,20 @@
>> +## @file
>> +# List of Core Components.
>> +#
>> +# Copyright (c) 2023, American Megatrends International LLC. All
>> rights reserved.<BR>
>> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>> +##
>> +
>> + 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/UsbNetworkPkgDefines.inc.dsc
>> b/UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc
>> new file mode 100644
>> index 000000000000..85a309bcf567
>> --- /dev/null
>> +++ b/UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc
>> @@ -0,0 +1,23 @@
>> +## @file
>> +# Global switches enable/disable project features.
>> +#
>> +# Copyright (c) 2023, American Megatrends International LLC. All
>> rights reserved.<BR>
>> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>> +##
>> +
>> +[Defines]
>> +!if "IA32" in $(ARCH) && "X64" in $(ARCH)
>> + DEFINE PEI=IA32
>> + DEFINE DXE=X64
>> +!else
>> + DEFINE PEI=COMMON
>> + DEFINE DXE=COMMON
>> +!endif
>> +
>> +[Packages]
>> + UsbNetworkPkg/UsbNetworkPkg.dec
>> +
>> +[PcdsFeatureFlag]
>> + gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport|FALSE
>> + gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport|FALSE
>> + gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport|TRUE
>> diff --git a/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf
>> b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf
>> new file mode 100644
>> index 000000000000..10616d97edb4
>> --- /dev/null
>> +++ b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf
>> @@ -0,0 +1,20 @@
>> +## @file
>> +# List of Core Components.
>> +#
>> +# Copyright (c) 2023, American Megatrends International LLC. All
>> rights reserved.<BR>
>> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>> +##
>> +
>> + 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
>> diff --git a/UsbNetworkPkg/NetworkCommon/NetworkCommon.inf
>> b/UsbNetworkPkg/NetworkCommon/NetworkCommon.inf
>> new file mode 100644
>> index 000000000000..8923102bc350
>> --- /dev/null
>> +++ b/UsbNetworkPkg/NetworkCommon/NetworkCommon.inf
>> @@ -0,0 +1,49 @@
>> +## @file
>> +# This is Usb Network Common driver for DXE phase.
>> +#
>> +# Copyright (c) 2023, American Megatrends International LLC. All
>> rights reserved.<BR>
>> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>> +##
>> +
>> +[Defines]
>> + INF_VERSION = 0x00010005
>> + BASE_NAME = NetworkCommon
>> + FILE_GUID = ca6eb4f4-f1d6-4375-97d6-18856871e1bf
>> + MODULE_TYPE = DXE_DRIVER
>> + VERSION_STRING = 1.0
>> + ENTRY_POINT = 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
>> + gEdkIIUsbEthProtocolGuid
>> +
>> +[Pcd]
>> + gUsbNetworkPkgTokenSpaceGuid.EnableRateLimiting
>> + gUsbNetworkPkgTokenSpaceGuid.RateLimitingCredit
>> + gUsbNetworkPkgTokenSpaceGuid.RateLimitingFactor
>> +
>> +[Depex]
>> + TRUE
>> diff --git a/UsbNetworkPkg/UsbRndis/UsbRndis.inf
>> b/UsbNetworkPkg/UsbRndis/UsbRndis.inf
>> new file mode 100644
>> index 000000000000..64205e427745
>> --- /dev/null
>> +++ b/UsbNetworkPkg/UsbRndis/UsbRndis.inf
>> @@ -0,0 +1,42 @@
>> +## @file
>> +# This is Usb Rndis driver for DXE phase.
>> +#
>> +# Copyright (c) 2023, American Megatrends International LLC. All
>> rights reserved.<BR>
>> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>> +##
>> +
>> +[Defines]
>> + INF_VERSION = 0x00010005
>> + BASE_NAME = UsbRndis
>> + FILE_GUID = 11E32C34-60B5-4991-8DEA-63D3E8C876DE
>> + MODULE_TYPE = DXE_DRIVER
>> + VERSION_STRING = 1.0
>> + ENTRY_POINT = 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
>> + gEdkIIUsbEthProtocolGuid
>> +
>> +[Depex]
>> + TRUE
>> diff --git
>> a/UsbNetworkPkg/Include/Protocol/EdkIIUsbEthernetProtocol.h
>> b/UsbNetworkPkg/Include/Protocol/EdkIIUsbEthernetProtocol.h
>> new file mode 100644
>> index 000000000000..f54946c7aa69
>> --- /dev/null
>> +++ b/UsbNetworkPkg/Include/Protocol/EdkIIUsbEthernetProtocol.h
>> @@ -0,0 +1,878 @@
>> +/** @file
>> + Header file contains code for USB Ethernet Protocol
>> + definitions
>> +
>> + Copyright (c) 2023, American Megatrends International LLC. All
>> rights reserved.<BR>
>> + SPDX-License-Identifier: BSD-2-Clause-Patent
>> +**/
>> +
>> +#ifndef EDKII_USB_ETHERNET_PROTOCOL_H_
>> +#define EDKII_USB_ETHERNET_PROTOCOL_H_
>> +
>> +#define EDKII_USB_ETHERNET_PROTOCOL_GUID \
>> + {0x8d8969cc, 0xfeb0, 0x4303, {0xb2, 0x1a, 0x1f, 0x11, 0x6f,
>> 0x38, 0x56, 0x43}}
>> +
>> +typedef struct _EDKII_USB_ETHERNET_PROTOCOL
>> EDKII_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_ETHERNET_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;
>> + EDKII_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;
>> + 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;
>> + EFI_EVENT RateLimiter;
>> + UINT32 RateLimitingCredit;
>> + UINT32 RateLimitingCreditCount;
>> + UINT32 RateLimitingPollTimer;
>> + BOOLEAN RateLimitingEnable;
>> +} NIC_DATA;
>> +
>> +#define NIC_DATA_SIGNATURE SIGNATURE_32('n', 'i', 'c', 'd')
>> +#define NIC_DATA_FROM_EDKII_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
>> 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.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_GET_STATE)(
>> + IN PXE_CDB *Cdb,
>> + IN NIC_DATA *Nic
>> + );
>> +
>> +/**
>> + This command is used to change the UNDI operational state from
>> stopped 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
>> 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.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_START)(
>> + IN PXE_CDB *Cdb,
>> + IN NIC_DATA *Nic
>> + );
>> +
>> +/**
>> + This command is used to change the UNDI operational state from
>> started 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
>> 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.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_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
>> 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.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_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
>> 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.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_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
>> 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.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_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
>> 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.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_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
>> 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.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_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
>> 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.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_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
>> 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.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_RECEIVE_FILTER)(
>> + IN PXE_CDB *Cdb,
>> + IN NIC_DATA *Nic
>> + );
>> +
>> +/**
>> + This command is used to get current station and broadcast MAC
>> addresses
>> + 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
>> 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.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_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
>> 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.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_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
>> 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.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_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
>> 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.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_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
>> 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.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_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
>> 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.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_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
>> queue.
>> +
>> + @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
>> 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.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_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
>> 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.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_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
>> 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.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_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
>> data.
>> + @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
>> 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.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_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
>> EDKII_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
>> status is returned in status.
>> + @retval EFI_INVALID_PARAMETER 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 *EDKII_USB_ETHERNET_RECEIVE)(
>> + IN PXE_CDB *Cdb,
>> + IN EDKII_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
>> EDKII_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
>> status is returned in status.
>> + @retval EFI_INVALID_PARAMETER 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 *EDKII_USB_ETHERNET_TRANSMIT)(
>> + IN PXE_CDB *Cdb,
>> + IN EDKII_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
>> EDKII_USB_ETHERNET_PROTOCOL instance.
>> + @param[in] IsNewTransfer If TRUE, a new transfer will be
>> submitted to USB controller. If
>> + FALSE, the interrupt transfer is
>> deleted 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
>> when 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 *EDKII_USB_ETHERNET_INTERRUPT)(
>> + IN EDKII_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
>> EDKII_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
>> was retrieved successfully.
>> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL.
>> + @retval EFI_NOT_FOUND The USB Header Functional descriptor
>> was not found.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_USB_GET_ETH_MAC_ADDRESS)(
>> + IN EDKII_USB_ETHERNET_PROTOCOL *This,
>> + OUT EFI_MAC_ADDRESS *MacAddress
>> + );
>> +
>> +/**
>> + Retrieves the USB Ethernet Bulk transfer data size.
>> +
>> + @param[in] This A pointer to the
>> EDKII_USB_ETHERNET_PROTOCOL instance.
>> + @param[out] BulkSize A pointer to the Bulk transfer data size.
>> +
>> + @retval EFI_SUCCESS The USB Header Functional descriptor
>> was retrieved successfully.
>> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL.
>> + @retval EFI_NOT_FOUND The USB Header Functional descriptor
>> was not found.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_USB_ETH_MAX_BULK_SIZE)(
>> + IN EDKII_USB_ETHERNET_PROTOCOL *This,
>> + OUT UINTN *BulkSize
>> + );
>> +
>> +/**
>> + Retrieves the USB Header functional Descriptor.
>> +
>> + @param[in] This A pointer to the
>> EDKII_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
>> was retrieved successfully.
>> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL.
>> + @retval EFI_NOT_FOUND The USB Header Functional descriptor
>> was not found.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_USB_HEADER_FUNCTIONAL_DESCRIPTOR)(
>> + IN EDKII_USB_ETHERNET_PROTOCOL *This,
>> + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor
>> + );
>> +
>> +/**
>> + Retrieves the USB Union functional Descriptor.
>> +
>> + @param[in] This A pointer to the
>> EDKII_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 *EDKII_USB_UNION_FUNCTIONAL_DESCRIPTOR)(
>> + IN EDKII_USB_ETHERNET_PROTOCOL *This,
>> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor
>> + );
>> +
>> +/**
>> + Retrieves the USB Ethernet functional Descriptor.
>> +
>> + @param[in] This A pointer to the
>> EDKII_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 *EDKII_USB_ETHERNET_FUNCTIONAL_DESCRIPTOR)(
>> + IN EDKII_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
>> EDKII_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.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_USB_ETHERNET_SET_ETH_MULTICAST_FILTERS)(
>> + IN EDKII_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
>> EDKII_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
>> 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.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_USB_ETHERNET_SET_ETH_POWER_MANAGE_PATTERN_FILTER)(
>> + IN EDKII_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
>> EDKII_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.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_USB_ETHERNET_GET_ETH_POWER_MANAGE_PATTERN_FILTER)(
>> + IN EDKII_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
>> EDKII_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
>> 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.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_USB_ETHERNET_SET_ETH_PACKET_FILTER)(
>> + IN EDKII_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
>> EDKII_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
>> 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.
>> +**/
>> +typedef
>> +EFI_STATUS
>> +(EFIAPI *EDKII_USB_ETHERNET_GET_ETH_STATISTIC)(
>> + IN EDKII_USB_ETHERNET_PROTOCOL *This,
>> + IN UINT16 FeatureSelector,
>> + OUT VOID *Statistic
>> + );
>> +
>> +typedef struct {
>> + EDKII_USB_ETHERNET_UNDI_GET_STATE UsbEthUndiGetState;
>> + EDKII_USB_ETHERNET_UNDI_START UsbEthUndiStart;
>> + EDKII_USB_ETHERNET_UNDI_STOP UsbEthUndiStop;
>> + EDKII_USB_ETHERNET_UNDI_GET_INIT_INFO UsbEthUndiGetInitInfo;
>> + EDKII_USB_ETHERNET_UNDI_GET_CONFIG_INFO UsbEthUndiGetConfigInfo;
>> + EDKII_USB_ETHERNET_UNDI_INITIALIZE UsbEthUndiInitialize;
>> + EDKII_USB_ETHERNET_UNDI_RESET UsbEthUndiReset;
>> + EDKII_USB_ETHERNET_UNDI_SHUTDOWN UsbEthUndiShutdown;
>> + EDKII_USB_ETHERNET_UNDI_INTERRUPT_ENABLE UsbEthUndiInterruptEnable;
>> + EDKII_USB_ETHERNET_UNDI_RECEIVE_FILTER UsbEthUndiReceiveFilter;
>> + EDKII_USB_ETHERNET_UNDI_STATION_ADDRESS UsbEthUndiStationAddress;
>> + EDKII_USB_ETHERNET_UNDI_STATISTICS UsbEthUndiStatistics;
>> + EDKII_USB_ETHERNET_UNDI_MCAST_IPTOMAC UsbEthUndiMcastIp2Mac;
>> + EDKII_USB_ETHERNET_UNDI_NV_DATA UsbEthUndiNvData;
>> + EDKII_USB_ETHERNET_UNDI_GET_STATUS UsbEthUndiGetStatus;
>> + EDKII_USB_ETHERNET_UNDI_FILL_HEADER UsbEthUndiFillHeader;
>> + EDKII_USB_ETHERNET_UNDI_TRANSMIT UsbEthUndiTransmit;
>> + EDKII_USB_ETHERNET_UNDI_RECEIVE UsbEthUndiReceive;
>> +} EDKII_USB_ETHERNET_UNDI;
>> +
>> +// The EDKII_USB_ETHERNET_PROTOCOL provides some basic USB Ethernet
>> device relevant
>> +// descriptor and specific requests.
>> +struct _EDKII_USB_ETHERNET_PROTOCOL {
>> + EDKII_USB_ETHERNET_UNDI UsbEthUndi;
>> + // for calling the UNDI child functions
>> + EDKII_USB_ETHERNET_INITIALIZE UsbEthInitialize;
>> + EDKII_USB_ETHERNET_STATISTICS UsbEthStatistics;
>> + EDKII_USB_ETHERNET_RECEIVE UsbEthReceive;
>> + EDKII_USB_ETHERNET_TRANSMIT UsbEthTransmit;
>> + EDKII_USB_ETHERNET_INTERRUPT UsbEthInterrupt;
>> + EDKII_USB_GET_ETH_MAC_ADDRESS UsbEthMacAddress;
>> + EDKII_USB_ETH_MAX_BULK_SIZE UsbEthMaxBulkSize;
>> + EDKII_USB_HEADER_FUNCTIONAL_DESCRIPTOR UsbHeaderFunDescriptor;
>> + EDKII_USB_UNION_FUNCTIONAL_DESCRIPTOR UsbUnionFunDescriptor;
>> + EDKII_USB_ETHERNET_FUNCTIONAL_DESCRIPTOR UsbEthFunDescriptor;
>> + EDKII_USB_ETHERNET_SET_ETH_MULTICAST_FILTERS SetUsbEthMcastFilter;
>> + EDKII_USB_ETHERNET_SET_ETH_POWER_MANAGE_PATTERN_FILTER
>> SetUsbEthPowerPatternFilter;
>> + EDKII_USB_ETHERNET_GET_ETH_POWER_MANAGE_PATTERN_FILTER
>> GetUsbEthPowerPatternFilter;
>> + EDKII_USB_ETHERNET_SET_ETH_PACKET_FILTER SetUsbEthPacketFilter;
>> + EDKII_USB_ETHERNET_GET_ETH_STATISTIC GetUsbEthStatistic;
>> +};
>> +
>> +extern EFI_GUID gEdkIIUsbEthProtocolGuid;
>> +
>> +#endif
>> diff --git a/UsbNetworkPkg/NetworkCommon/DriverBinding.h
>> b/UsbNetworkPkg/NetworkCommon/DriverBinding.h
>> new file mode 100644
>> index 000000000000..0416ce132302
>> --- /dev/null
>> +++ b/UsbNetworkPkg/NetworkCommon/DriverBinding.h
>> @@ -0,0 +1,266 @@
>> +/** @file
>> + Header file for for USB network common driver
>> +
>> + Copyright (c) 2023, American Megatrends International LLC. All
>> rights reserved.<BR>
>> + SPDX-License-Identifier: BSD-2-Clause-Patent
>> +**/
>> +
>> +#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/PcdLib.h>
>> +#include <Library/BaseMemoryLib.h>
>> +#include <Library/UefiUsbLib.h>
>> +#include <Protocol/UsbIo.h>
>> +#include <Protocol/NetworkInterfaceIdentifier.h>
>> +#include <Protocol/EdkIIUsbEthernetProtocol.h>
>> +
>> +#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;
>> + VOID *ReceiveBuffer;
>> +} 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
>> + );
>> +
>> +EFI_STATUS
>> +EFIAPI
>> +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/UsbRndis/UsbRndis.h
>> b/UsbNetworkPkg/UsbRndis/UsbRndis.h
>> new file mode 100644
>> index 000000000000..775807042460
>> --- /dev/null
>> +++ b/UsbNetworkPkg/UsbRndis/UsbRndis.h
>> @@ -0,0 +1,586 @@
>> +/** @file
>> + Header file for for USB Rndis driver
>> +
>> + Copyright (c) 2023, American Megatrends International LLC. All
>> rights reserved.<BR>
>> + SPDX-License-Identifier: BSD-2-Clause-Patent
>> +**/
>> +
>> +#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/EdkIIUsbEthernetProtocol.h>
>> +
>> +typedef struct _REMOTE_NDIS_MSG_HEADER REMOTE_NDIS_MSG_HEADER;
>> +
>> +typedef struct {
>> + UINT32 Signature;
>> + EDKII_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
>> waiting counts for send bulk in command when system pending
>> +#define RNDIS_RESERVED_BYTE_LENGTH 8
>> +
>> +#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)
>> +
>> +extern EFI_COMPONENT_NAME2_PROTOCOL gUsbRndisComponentName2;
>> +
>> +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 EDKII_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 EDKII_USB_ETHERNET_PROTOCOL *This,
>> + OUT EFI_MAC_ADDRESS *MacAddress
>> + );
>> +
>> +EFI_STATUS
>> +EFIAPI
>> +UsbEthBulkSize (
>> + IN EDKII_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 EDKII_USB_ETHERNET_PROTOCOL *This,
>> + IN VOID *BulkOutData,
>> + IN OUT UINTN *DataLength
>> + );
>> +
>> +EFI_STATUS
>> +EFIAPI
>> +RndisUndiReceive (
>> + IN PXE_CDB *Cdb,
>> + IN EDKII_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 EDKII_USB_ETHERNET_PROTOCOL *This,
>> + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor
>> + );
>> +
>> +EFI_STATUS
>> +EFIAPI
>> +GetUsbUnionFunDescriptor (
>> + IN EDKII_USB_ETHERNET_PROTOCOL *This,
>> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor
>> + );
>> +
>> +EFI_STATUS
>> +EFIAPI
>> +GetUsbRndisFunDescriptor (
>> + IN EDKII_USB_ETHERNET_PROTOCOL *This,
>> + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor
>> + );
>> +
>> +EFI_STATUS
>> +EFIAPI
>> +SetUsbRndisMcastFilter (
>> + IN EDKII_USB_ETHERNET_PROTOCOL *This,
>> + IN UINT16 Value,
>> + IN VOID *McastAddr
>> + );
>> +
>> +EFI_STATUS
>> +EFIAPI
>> +SetUsbRndisPowerFilter (
>> + IN EDKII_USB_ETHERNET_PROTOCOL *This,
>> + IN UINT16 Value,
>> + IN UINT16 Length,
>> + IN VOID *PatternFilter
>> + );
>> +
>> +EFI_STATUS
>> +EFIAPI
>> +GetUsbRndisPowerFilter (
>> + IN EDKII_USB_ETHERNET_PROTOCOL *This,
>> + IN UINT16 Value,
>> + IN BOOLEAN *PatternActive
>> + );
>> +
>> +EFI_STATUS
>> +EFIAPI
>> +SetUsbRndisPacketFilter (
>> + IN EDKII_USB_ETHERNET_PROTOCOL *This,
>> + IN UINT16 Value
>> + );
>> +
>> +EFI_STATUS
>> +EFIAPI
>> +GetRndisStatistic (
>> + IN EDKII_USB_ETHERNET_PROTOCOL *This,
>> + IN UINT16 Value,
>> + IN VOID *Statistic
>> + );
>> +
>> +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
>> +
>> +#define OID_802_3_CURRENT_ADDRESS 0x01010102
>> +//
>> +// 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 {
>> + REMOTE_NDIS_QUERY_MSG QueryMsg;
>> + UINT8 Addr[6];
>> +} REMOTE_NDIS_QUERY_MAC_MSG;
>> +
>> +typedef struct {
>> + REMOTE_NDIS_QUERY_MSG QueryMsg;
>> + UINT32 MaxTotalSize;
>> +} REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_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 {
>> + REMOTE_NDIS_QUERY_CMPLT QueryCmplt;
>> + UINT8 Addr[6];
>> +} REMOTE_NDIS_QUERY_MAC_CMPLT;
>> +
>> +typedef struct {
>> + REMOTE_NDIS_QUERY_CMPLT QueryCmplt;
>> + UINT32 MaxTotalSize;
>> +} REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_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;
>> + UINT8 *PacketStartBuffer; // Variable size data to follow
>> +} PACKET_LIST;
>> +
>> +#pragma pack()
>> +
>> +#endif
>> diff --git a/UsbNetworkPkg/NetworkCommon/ComponentName.c
>> b/UsbNetworkPkg/NetworkCommon/ComponentName.c
>> new file mode 100644
>> index 000000000000..e83469e13079
>> --- /dev/null
>> +++ b/UsbNetworkPkg/NetworkCommon/ComponentName.c
>> @@ -0,0 +1,263 @@
>> +/** @file
>> + This file contains code for USB network common driver
>> + component name definitions
>> +
>> + Copyright (c) 2023, American Megatrends International LLC. All
>> rights reserved.<BR>
>> + SPDX-License-Identifier: BSD-2-Clause-Patent
>> +**/
>> +
>> +#include "DriverBinding.h"
>> +
>> +extern EFI_DRIVER_BINDING_PROTOCOL gNetworkCommonDriverBinding;
>> +
>> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE
>> gNetworkCommonDriverNameTable[] = {
>> + {
>> + "eng;en",
>> + L"Network Common Driver"
>> + },
>> + {
>> + NULL,
>> + NULL
>> + }
>> +};
>> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE
>> *gNetworkCommonControllerNameTable = 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 = {
>> + NetworkCommonComponentNameGetDriverName,
>> + NetworkCommonComponentNameGetControllerName,
>> + "eng"
>> +};
>> +
>> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL
>> gNetworkCommonComponentName2 = {
>> +
>> (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)NetworkCommonComponentNameGetDriverName,
>> +
>> (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)NetworkCommonComponentNameGetControllerName,
>> + "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
>> 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 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
>> the
>> + 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
>> language
>> + 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 == &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
>> device
>> + drivers. It will also be NULL for a
>> bus drivers
>> + that wish to retrieve the name of
>> the bus
>> + 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
>> the
>> + 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
>> ControllerHandle and
>> + ChildHandle in the language
>> specified by
>> + Language from the point of view of
>> the driver
>> + specified by This.
>> +
>> + @retval EFI_SUCCESS The Unicode string for the user
>> readable name in
>> + the language specified by Language
>> for the
>> + driver specified by This was
>> returned in
>> + 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;
>> + EFI_USB_DEVICE_DESCRIPTOR DevDesc;
>> +
>> + if (!Language || !ControllerName) {
>> + return EFI_INVALID_PARAMETER;
>> + }
>> +
>> + if (ChildHandle == NULL) {
>> + return EFI_UNSUPPORTED;
>> + }
>> +
>> + //
>> + // Make sure this driver is currently managing ControllerHandle
>> + //
>> + Status = EfiTestManagedDevice (
>> + Controller,
>> + gNetworkCommonDriverBinding.DriverBindingHandle,
>> + &gEdkIIUsbEthProtocolGuid
>> + );
>> + if (EFI_ERROR (Status)) {
>> + return Status;
>> + }
>> +
>> + //
>> + // Make sure this driver produced ChildHandle
>> + //
>> + Status = EfiTestChildHandle (
>> + Controller,
>> + ChildHandle,
>> + &gEdkIIUsbEthProtocolGuid
>> + );
>> + if (EFI_ERROR (Status)) {
>> + return Status;
>> + }
>> +
>> + Status = gBS->HandleProtocol (Controller, &gEfiUsbIoProtocolGuid,
>> (VOID **)&UsbIo);
>> +
>> + if (!EFI_ERROR (Status)) {
>> + Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);
>> + if (EFI_ERROR (Status)) {
>> + return Status;
>> + }
>> +
>> + Status = UsbIo->UsbGetStringDescriptor (UsbIo, 0x409,
>> DevDesc.StrManufacturer, &HandleName);
>> + if (EFI_ERROR (Status)) {
>> + return Status;
>> + }
>> +
>> + *ControllerName = HandleName;
>> +
>> + if (gNetworkCommonControllerNameTable != NULL) {
>> + FreeUnicodeStringTable (gNetworkCommonControllerNameTable);
>> + gNetworkCommonControllerNameTable = NULL;
>> + }
>> +
>> + Status = AddUnicodeString2 (
>> + "eng",
>> + gNetworkCommonComponentName.SupportedLanguages,
>> + &gNetworkCommonControllerNameTable,
>> + HandleName,
>> + TRUE
>> + );
>> + if (EFI_ERROR (Status)) {
>> + return Status;
>> + }
>> +
>> + Status = AddUnicodeString2 (
>> + "en",
>> + gNetworkCommonComponentName2.SupportedLanguages,
>> + &gNetworkCommonControllerNameTable,
>> + HandleName,
>> + FALSE
>> + );
>> + if (EFI_ERROR (Status)) {
>> + return Status;
>> + }
>> +
>> + return LookupUnicodeString2 (
>> + Language,
>> + This->SupportedLanguages,
>> + gNetworkCommonControllerNameTable,
>> + ControllerName,
>> + (BOOLEAN)(This == &gNetworkCommonComponentName)
>> + );
>> + }
>> +
>> + return EFI_UNSUPPORTED;
>> +}
>> diff --git a/UsbNetworkPkg/NetworkCommon/DriverBinding.c
>> b/UsbNetworkPkg/NetworkCommon/DriverBinding.c
>> new file mode 100644
>> index 000000000000..23b791362091
>> --- /dev/null
>> +++ b/UsbNetworkPkg/NetworkCommon/DriverBinding.c
>> @@ -0,0 +1,595 @@
>> +/** @file
>> + This file contains code for USB network binding driver
>> +
>> + Copyright (c) 2023, American Megatrends International LLC. All
>> rights reserved.<BR>
>> + SPDX-License-Identifier: BSD-2-Clause-Patent
>> +**/
>> +
>> +#include "DriverBinding.h"
>> +
>> +PXE_SW_UNDI *gPxe = NULL;
>> +NIC_DEVICE *gLanDeviceList[MAX_LAN_INTERFACE];
>> +UINT32 gRateLimitingCredit;
>> +UINT32 gRateLimitingPollTimer;
>> +BOOLEAN gRateLimitingEnable;
>> +
>> +EFI_DRIVER_BINDING_PROTOCOL gNetworkCommonDriverBinding = {
>> + 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 = MESSAGING_DEVICE_PATH;
>> + MacAddrNode.Header.SubType = MSG_MAC_ADDR_DP;
>> + MacAddrNode.Header.Length[0] = (UINT8)sizeof (MacAddrNode);
>> + MacAddrNode.Header.Length[1] = 0;
>> +
>> + EndNode = BaseDev;
>> +
>> + while (!IsDevicePathEnd (EndNode)) {
>> + EndNode = NextDevicePathNode (EndNode);
>> + }
>> +
>> + BaseLength = (UINT16)((UINTN)(EndNode) - (UINTN)(BaseDev));
>> + TotalLength = (UINT16)(BaseLength + sizeof (MacAddrNode) + sizeof
>> (EFI_DEVICE_PATH_PROTOCOL));
>> +
>> + Status = gBS->AllocatePool (EfiBootServicesData, TotalLength,
>> (VOID **)&DevicePath);
>> + if (EFI_ERROR (Status)) {
>> + return Status;
>> + }
>> +
>> + *Dev = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;
>> + CopyMem (DevicePath, (CHAR8 *)BaseDev, BaseLength);
>> + DevicePath += BaseLength;
>> + CopyMem (DevicePath, (CHAR8 *)&MacAddrNode, sizeof (MacAddrNode));
>> + DevicePath += 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;
>> + EDKII_USB_ETHERNET_PROTOCOL *UsbEth;
>> +
>> + Status = gBS->OpenProtocol (
>> + ControllerHandle,
>> + &gEdkIIUsbEthProtocolGuid,
>> + (VOID **)&UsbEth,
>> + This->DriverBindingHandle,
>> + ControllerHandle,
>> + EFI_OPEN_PROTOCOL_BY_DRIVER
>> + );
>> + if (EFI_ERROR (Status)) {
>> + return Status;
>> + }
>> +
>> + gBS->CloseProtocol (
>> + ControllerHandle,
>> + &gEdkIIUsbEthProtocolGuid,
>> + 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 to.
>> + @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;
>> + EDKII_USB_ETHERNET_PROTOCOL *UsbEth;
>> + EFI_MAC_ADDRESS MacAddress;
>> + UINTN BulkDataSize;
>> + NIC_DEVICE *NicDevice;
>> + UINT8 *TmpPxePointer;
>> +
>> + Status = gBS->OpenProtocol (
>> + ControllerHandle,
>> + &gEdkIIUsbEthProtocolGuid,
>> + (VOID **)&UsbEth,
>> + This->DriverBindingHandle,
>> + ControllerHandle,
>> + EFI_OPEN_PROTOCOL_BY_DRIVER
>> + );
>> + if (EFI_ERROR (Status)) {
>> + return Status;
>> + }
>> +
>> + Status = gBS->OpenProtocol (
>> + ControllerHandle,
>> + &gEfiDevicePathProtocolGuid,
>> + (VOID **)&UsbEthPath,
>> + This->DriverBindingHandle,
>> + ControllerHandle,
>> + EFI_OPEN_PROTOCOL_BY_DRIVER
>> + );
>> +
>> + if (EFI_ERROR (Status)) {
>> + gBS->CloseProtocol (
>> + ControllerHandle,
>> + &gEdkIIUsbEthProtocolGuid,
>> + This->DriverBindingHandle,
>> + ControllerHandle
>> + );
>> + return Status;
>> + }
>> +
>> + ZeroMem (&MacAddress, sizeof (EFI_MAC_ADDRESS));
>> +
>> + Status = UsbEth->UsbEthMacAddress (UsbEth, &MacAddress);
>> + ASSERT_EFI_ERROR (Status);
>> + Status = UsbEth->UsbEthMaxBulkSize (UsbEth, &BulkDataSize);
>> +
>> + if (EFI_ERROR (Status)) {
>> + gBS->CloseProtocol (
>> + ControllerHandle,
>> + &gEfiDevicePathProtocolGuid,
>> + This->DriverBindingHandle,
>> + ControllerHandle
>> + );
>> + gBS->CloseProtocol (
>> + ControllerHandle,
>> + &gEdkIIUsbEthProtocolGuid,
>> + This->DriverBindingHandle,
>> + ControllerHandle
>> + );
>> + return Status;
>> + }
>> +
>> + NicDevice = AllocateZeroPool (sizeof (NIC_DEVICE) + BulkDataSize +
>> 4096);
>> + if (!NicDevice) {
>> + gBS->CloseProtocol (
>> + ControllerHandle,
>> + &gEfiDevicePathProtocolGuid,
>> + This->DriverBindingHandle,
>> + ControllerHandle
>> + );
>> + gBS->CloseProtocol (
>> + ControllerHandle,
>> + &gEdkIIUsbEthProtocolGuid,
>> + This->DriverBindingHandle,
>> + ControllerHandle
>> + );
>> + return EFI_OUT_OF_RESOURCES;
>> + }
>> +
>> + // for alignment adjustment
>> + if (gPxe == NULL) {
>> + TmpPxePointer = NULL;
>> + TmpPxePointer = AllocateZeroPool (sizeof (PXE_SW_UNDI) + 16);
>> + if (!TmpPxePointer) {
>> + if (NicDevice != NULL) {
>> + FreePool (NicDevice);
>> + }
>> +
>> + gBS->CloseProtocol (
>> + ControllerHandle,
>> + &gEfiDevicePathProtocolGuid,
>> + This->DriverBindingHandle,
>> + ControllerHandle
>> + );
>> + gBS->CloseProtocol (
>> + ControllerHandle,
>> + &gEdkIIUsbEthProtocolGuid,
>> + This->DriverBindingHandle,
>> + ControllerHandle
>> + );
>> +
>> + return EFI_OUT_OF_RESOURCES;
>> + } else {
>> + // check for paragraph alignment here
>> + if (((UINTN)TmpPxePointer & 0x0F) != 0) {
>> + gPxe = (PXE_SW_UNDI *)(TmpPxePointer + 8);
>> + } else {
>> + gPxe = (PXE_SW_UNDI *)TmpPxePointer;
>> + }
>> +
>> + if (!gPxe) {
>> + if (NicDevice != NULL) {
>> + FreePool (NicDevice);
>> + }
>> +
>> + gBS->CloseProtocol (
>> + ControllerHandle,
>> + &gEfiDevicePathProtocolGuid,
>> + This->DriverBindingHandle,
>> + ControllerHandle
>> + );
>> + gBS->CloseProtocol (
>> + ControllerHandle,
>> + &gEdkIIUsbEthProtocolGuid,
>> + This->DriverBindingHandle,
>> + ControllerHandle
>> + );
>> + return EFI_OUT_OF_RESOURCES;
>> + }
>> +
>> + PxeStructInit (gPxe);
>> + }
>> + }
>> +
>> + NicDevice->NiiProtocol.Id = (UINT64)(UINTN)(gPxe);
>> + NicDevice->NiiProtocol.IfNum = gPxe->IFcnt | gPxe->IFcntExt << 8;
>> +
>> + UpdateNicNum (&NicDevice->NicInfo, gPxe);
>> +
>> + NicDevice->NicInfo.Signature = NIC_DATA_SIGNATURE;
>> +
>> + NicDevice->NicInfo.UsbEth = UsbEth;
>> + NicDevice->NicInfo.MaxSegmentSize = (UINT16)BulkDataSize;
>> + NicDevice->NicInfo.CableDetect = 0;
>> + NicDevice->ReceiveBuffer = ALIGN_POINTER ((VOID
>> *)NicDevice, 4096);
>> +
>> + CopyMem ((CHAR8 *)&(NicDevice->NicInfo.MacAddr), (CHAR8
>> *)&MacAddress, sizeof (MacAddress));
>> +
>> + NicDevice->NicInfo.TxBufferCount = 0;
>> +
>> + if (NicDevice->NiiProtocol.IfNum < MAX_LAN_INTERFACE) {
>> + gLanDeviceList[NicDevice->NiiProtocol.IfNum] = NicDevice;
>> + } else {
>> + gBS->CloseProtocol (
>> + ControllerHandle,
>> + &gEfiDevicePathProtocolGuid,
>> + This->DriverBindingHandle,
>> + ControllerHandle
>> + );
>> + gBS->CloseProtocol (
>> + ControllerHandle,
>> + &gEdkIIUsbEthProtocolGuid,
>> + This->DriverBindingHandle,
>> + ControllerHandle
>> + );
>> +
>> + if (TmpPxePointer != NULL) {
>> + FreePool (TmpPxePointer);
>> + }
>> +
>> + if (NicDevice != NULL) {
>> + FreePool (NicDevice);
>> + }
>> +
>> + return EFI_DEVICE_ERROR;
>> + }
>> +
>> + Status = CreateMacDevicePath (
>> + &NicDevice->DevPath,
>> + UsbEthPath,
>> + &NicDevice->NicInfo
>> + );
>> +
>> + if (EFI_ERROR (Status)) {
>> + UpdateNicNum (NULL, gPxe);
>> + if (TmpPxePointer != NULL) {
>> + FreePool (TmpPxePointer);
>> + }
>> + }
>> +
>> + NicDevice->Signature = UNDI_DEV_SIGNATURE;
>> + NicDevice->NiiProtocol.Revision =
>> EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION;
>> + NicDevice->NiiProtocol.Type = EfiNetworkInterfaceUndi;
>> + NicDevice->NiiProtocol.MajorVer = PXE_ROMID_MAJORVER;
>> + NicDevice->NiiProtocol.MinorVer = PXE_ROMID_MINORVER;
>> + NicDevice->NiiProtocol.ImageSize = 0;
>> + NicDevice->NiiProtocol.ImageAddr = 0;
>> + NicDevice->NiiProtocol.Ipv6Supported = TRUE;
>> +
>> + NicDevice->NiiProtocol.StringId[0] = 'U';
>> + NicDevice->NiiProtocol.StringId[1] = 'N';
>> + NicDevice->NiiProtocol.StringId[2] = 'D';
>> + NicDevice->NiiProtocol.StringId[3] = 'I';
>> + NicDevice->DeviceHandle = NULL;
>> +
>> + NicDevice->NicInfo.RateLimitingEnable = gRateLimitingEnable;
>> + NicDevice->NicInfo.RateLimitingCreditCount = 0;
>> + NicDevice->NicInfo.RateLimitingCredit = gRateLimitingCredit;
>> + NicDevice->NicInfo.RateLimitingPollTimer = gRateLimitingPollTimer;
>> + NicDevice->NicInfo.RateLimiter = NULL;
>> +
>> + ZeroMem (&NicDevice->NicInfo.Request, sizeof
>> (EFI_USB_DEVICE_REQUEST));
>> +
>> + Status = UsbEth->UsbEthInterrupt (UsbEth, TRUE,
>> NETWORK_COMMON_POLLING_INTERVAL, &NicDevice->NicInfo.Request);
>> + ASSERT_EFI_ERROR (Status);
>> +
>> + Status = 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] = NULL;
>> + }
>> +
>> + gBS->CloseProtocol (
>> + ControllerHandle,
>> + &gEfiDevicePathProtocolGuid,
>> + This->DriverBindingHandle,
>> + ControllerHandle
>> + );
>> + gBS->CloseProtocol (
>> + ControllerHandle,
>> + &gEdkIIUsbEthProtocolGuid,
>> + This->DriverBindingHandle,
>> + ControllerHandle
>> + );
>> +
>> + if (TmpPxePointer != NULL) {
>> + FreePool (TmpPxePointer);
>> + }
>> +
>> + if (NicDevice->DevPath != NULL) {
>> + FreePool (NicDevice->DevPath);
>> + }
>> +
>> + if (NicDevice != NULL) {
>> + FreePool (NicDevice);
>> + }
>> +
>> + return EFI_DEVICE_ERROR;
>> + }
>> +
>> + Status = gBS->OpenProtocol (
>> + ControllerHandle,
>> + &gEdkIIUsbEthProtocolGuid,
>> + (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
>> bus 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;
>> + EDKII_USB_ETHERNET_PROTOCOL *UsbEth;
>> + NIC_DEVICE *NicDevice;
>> + EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NiiProtocol;
>> +
>> + if (NumberOfChildren == 0) {
>> + Status = 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,
>> + &gEdkIIUsbEthProtocolGuid,
>> + This->DriverBindingHandle,
>> + ControllerHandle
>> + );
>> + return EFI_SUCCESS;
>> + }
>> +
>> + NicDevice = UNDI_DEV_FROM_THIS (NiiProtocol);
>> + Status = gBS->UninstallMultipleProtocolInterfaces (
>> + ControllerHandle,
>> + &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
>> + &NicDevice->NiiProtocol,
>> + &gEfiDevicePathProtocolGuid,
>> + NicDevice->DevPath,
>> + NULL
>> + );
>> + if (EFI_ERROR (Status)) {
>> + return Status;
>> + }
>> +
>> + FreePool (NicDevice->DevPath);
>> + FreePool (NicDevice);
>> +
>> + gBS->CloseProtocol (
>> + ControllerHandle,
>> + &gEfiDevicePathProtocolGuid,
>> + This->DriverBindingHandle,
>> + ControllerHandle
>> + );
>> + gBS->CloseProtocol (
>> + ControllerHandle,
>> + &gEdkIIUsbEthProtocolGuid,
>> + This->DriverBindingHandle,
>> + ControllerHandle
>> + );
>> + return EFI_SUCCESS;
>> + }
>> +
>> + AllChildrenStopped = TRUE;
>> +
>> + for (Index = 0; Index < NumberOfChildren; Index++) {
>> + Status = gBS->OpenProtocol (
>> + ChildHandleBuffer[Index],
>> + &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
>> + (VOID **)&NiiProtocol,
>> + This->DriverBindingHandle,
>> + ControllerHandle,
>> + EFI_OPEN_PROTOCOL_GET_PROTOCOL
>> + );
>> + if (EFI_ERROR (Status)) {
>> + AllChildrenStopped = FALSE;
>> + continue;
>> + }
>> +
>> + NicDevice = UNDI_DEV_FROM_THIS (NiiProtocol);
>> +
>> + gBS->CloseProtocol (
>> + ControllerHandle,
>> + &gEdkIIUsbEthProtocolGuid,
>> + This->DriverBindingHandle,
>> + ChildHandleBuffer[Index]
>> + );
>> +
>> + Status = gBS->UninstallMultipleProtocolInterfaces (
>> + ChildHandleBuffer[Index],
>> + &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
>> + &NicDevice->NiiProtocol,
>> + &gEfiDevicePathProtocolGuid,
>> + NicDevice->DevPath,
>> + NULL
>> + );
>> + if (EFI_ERROR (Status)) {
>> + Status = gBS->OpenProtocol (
>> + ControllerHandle,
>> + &gEdkIIUsbEthProtocolGuid,
>> + (VOID **)&UsbEth,
>> + This->DriverBindingHandle,
>> + ChildHandleBuffer[Index],
>> + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
>> + );
>> + } else {
>> + FreePool (NicDevice->DevPath);
>> + 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
>> successfully.
>> +
>> +**/
>> +EFI_STATUS
>> +EFIAPI
>> +NetworkCommonEntry (
>> + IN EFI_HANDLE ImageHandle,
>> + IN EFI_SYSTEM_TABLE *SystemTable
>> + )
>> +{
>> + EFI_STATUS Status;
>> +
>> + gNetworkCommonDriverBinding.DriverBindingHandle = ImageHandle;
>> + gNetworkCommonDriverBinding.ImageHandle = ImageHandle;
>> + gRateLimitingEnable = PcdGetBool
>> (EnableRateLimiting);
>> + gRateLimitingCredit = PcdGet32
>> (RateLimitingCredit);
>> + gRateLimitingPollTimer = PcdGet32
>> (RateLimitingFactor);
>> +
>> + Status = gBS->InstallMultipleProtocolInterfaces (
>> + &gNetworkCommonDriverBinding.DriverBindingHandle,
>> + &gEfiDriverBindingProtocolGuid,
>> + &gNetworkCommonDriverBinding,
>> + &gEfiComponentName2ProtocolGuid,
>> + &gNetworkCommonComponentName2,
>> + NULL
>> + );
>> + return Status;
>> +}
>> diff --git a/UsbNetworkPkg/NetworkCommon/PxeFunction.c
>> b/UsbNetworkPkg/NetworkCommon/PxeFunction.c
>> new file mode 100644
>> index 000000000000..687cabca4ce3
>> --- /dev/null
>> +++ b/UsbNetworkPkg/NetworkCommon/PxeFunction.c
>> @@ -0,0 +1,1803 @@
>> +/** @file
>> + This file contains code for UNDI command based on UEFI specification.
>> +
>> + Copyright (c) 2023, American Megatrends International LLC. All
>> rights reserved.<BR>
>> + SPDX-License-Identifier: BSD-2-Clause-Patent
>> +**/
>> +
>> +#include "DriverBinding.h"
>> +
>> +// API table, defined in UEFI specification
>> +API_FUNC gUndiApiTable[] = {
>> + UndiGetState,
>> + UndiStart,
>> + UndiStop,
>> + UndiGetInitInfo,
>> + UndiGetConfigInfo,
>> + UndiInitialize,
>> + UndiReset,
>> + UndiShutdown,
>> + UndiInterruptEnable,
>> + UndiReceiveFilter,
>> + UndiStationAddress,
>> + UndiStatistics,
>> + UndiMcastIp2Mac,
>> + UndiNvData,
>> + UndiGetStatus,
>> + UndiFillHeader,
>> + UndiTransmit,
>> + UndiReceive
>> +};
>> +
>> +/**
>> + Callback function for enable Rate Limiter
>> +
>> + @param[in] Event Event whose notification function is
>> being invoked
>> + @param[in] Context Pointer to the notification function's
>> context
>> +
>> +**/
>> +VOID
>> +EFIAPI
>> +UndiRateLimiterCallback (
>> + IN EFI_EVENT Event,
>> + IN VOID *Context
>> + )
>> +{
>> + NIC_DATA *Nic = Context;
>> +
>> + if (Nic->RateLimitingCreditCount < Nic->RateLimitingCredit) {
>> + Nic->RateLimitingCreditCount++;
>> + }
>> +}
>> +
>> +/**
>> + 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 != PXE_OPCODE_GET_STATE) ||
>> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) ||
>> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) ||
>> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) ||
>> + (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) ||
>> + (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED) ||
>> + (Cdb->DBsize != PXE_DBSIZE_NOT_USED) ||
>> + (Cdb->DBaddr != PXE_DBADDR_NOT_USED) ||
>> + (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED))
>> + {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>> + return;
>> + } else {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;
>> + Cdb->StatCode = PXE_STATCODE_SUCCESS;
>> + }
>> +
>> + Cdb->StatFlags = Cdb->StatFlags | Nic->State;
>> +
>> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetState != NULL) {
>> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiGetState (Cdb, Nic);
>> + if (EFI_ERROR (Status)) {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + }
>> + }
>> +}
>> +
>> +/**
>> + This command is used to change the UNDI operational state from
>> stopped 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;
>> + BOOLEAN EventError;
>> +
>> + if ((Cdb->OpCode != PXE_OPCODE_START) ||
>> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) ||
>> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) ||
>> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) ||
>> + (Cdb->CPBsize != sizeof (PXE_CPB_START_31)) ||
>> + (Cdb->DBsize != PXE_DBSIZE_NOT_USED) ||
>> + (Cdb->DBaddr != PXE_DBADDR_NOT_USED) ||
>> + (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED))
>> + {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>> + return;
>> + }
>> +
>> + if (Nic->State != PXE_STATFLAGS_GET_STATE_STOPPED) {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_ALREADY_STARTED;
>> + return;
>> + }
>> +
>> + Cpb = (PXE_CPB_START_31 *)(UINTN)Cdb->CPBaddr;
>> +
>> + Nic->PxeStart.Delay = Cpb->Delay;
>> + Nic->PxeStart.Virt2Phys = Cpb->Virt2Phys;
>> + Nic->PxeStart.Block = Cpb->Block;
>> + Nic->PxeStart.Map_Mem = 0;
>> + Nic->PxeStart.UnMap_Mem = 0;
>> + Nic->PxeStart.Sync_Mem = Cpb->Sync_Mem;
>> + Nic->PxeStart.Unique_ID = Cpb->Unique_ID;
>> + EventError = FALSE;
>> + Status = EFI_SUCCESS;
>> + if (Nic->RateLimitingEnable == TRUE) {
>> + Status = gBS->CreateEvent (
>> + EVT_TIMER | EVT_NOTIFY_SIGNAL,
>> + TPL_NOTIFY,
>> + UndiRateLimiterCallback,
>> + Nic,
>> + &Nic->RateLimiter
>> + );
>> + if (!EFI_ERROR (Status)) {
>> + Status = gBS->SetTimer (
>> + Nic->RateLimiter,
>> + TimerPeriodic,
>> + Nic->RateLimitingPollTimer * 10000
>> + );
>> + if (EFI_ERROR (Status)) {
>> + EventError = TRUE;
>> + }
>> + }
>> + }
>> +
>> + if ((Nic->UsbEth->UsbEthUndi.UsbEthUndiStart != NULL) &&
>> (EventError == FALSE)) {
>> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiStart (Cdb, Nic);
>> + }
>> +
>> + if (!EFI_ERROR (Status)) {
>> + // Initial the state for UNDI start.
>> + Nic->State = PXE_STATFLAGS_GET_STATE_STARTED;
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;
>> + Cdb->StatCode = PXE_STATCODE_SUCCESS;
>> + } else {
>> + if (Nic->RateLimitingEnable == TRUE) {
>> + if (!EventError) {
>> + gBS->SetTimer (&Nic->RateLimiter, TimerCancel, 0);
>> + }
>> +
>> + if (Nic->RateLimiter) {
>> + gBS->CloseEvent (&Nic->RateLimiter);
>> + Nic->RateLimiter = 0;
>> + }
>> + }
>> +
>> + // Initial the state when UNDI start is fail
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_DEVICE_FAILURE;
>> + }
>> +}
>> +
>> +/**
>> + This command is used to change the UNDI operational state from
>> started 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 != PXE_OPCODE_STOP) ||
>> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) ||
>> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) ||
>> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) ||
>> + (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) ||
>> + (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED) ||
>> + (Cdb->DBsize != PXE_DBSIZE_NOT_USED) ||
>> + (Cdb->DBaddr != PXE_DBADDR_NOT_USED) ||
>> + (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED))
>> + {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>> + return;
>> + } else {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;
>> + Cdb->StatCode = PXE_STATCODE_SUCCESS;
>> + }
>> +
>> + if (Nic->State == PXE_STATFLAGS_GET_STATE_STOPPED) {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_NOT_STARTED;
>> + return;
>> + }
>> +
>> + if (Nic->State == PXE_STATFLAGS_GET_STATE_INITIALIZED) {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_NOT_SHUTDOWN;
>> + return;
>> + }
>> +
>> + Nic->PxeStart.Delay = 0;
>> + Nic->PxeStart.Virt2Phys = 0;
>> + Nic->PxeStart.Block = 0;
>> + Nic->PxeStart.Map_Mem = 0;
>> + Nic->PxeStart.UnMap_Mem = 0;
>> + Nic->PxeStart.Sync_Mem = 0;
>> + Nic->State = PXE_STATFLAGS_GET_STATE_STOPPED;
>> +
>> + if (Nic->RateLimitingEnable == TRUE) {
>> + gBS->SetTimer (&Nic->RateLimiter, TimerCancel, 0);
>> + gBS->CloseEvent (&Nic->RateLimiter);
>> + }
>> +
>> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStop != NULL) {
>> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiStop (Cdb, Nic);
>> + if (EFI_ERROR (Status)) {
>> + Cdb->StatFlags = 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 != PXE_OPCODE_GET_INIT_INFO) ||
>> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) ||
>> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) ||
>> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) ||
>> + (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) ||
>> + (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED) ||
>> + (Cdb->DBsize != sizeof (PXE_DB_GET_INIT_INFO)) ||
>> + (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED))
>> + {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>> + return;
>> + } else {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;
>> + Cdb->StatCode = PXE_STATCODE_SUCCESS;
>> + }
>> +
>> + if (Nic->State == PXE_STATFLAGS_GET_STATE_STOPPED) {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_NOT_STARTED;
>> + return;
>> + }
>> +
>> + Db = (PXE_DB_GET_INIT_INFO *)(UINTN)Cdb->DBaddr;
>> +
>> + Db->MemoryRequired = MEMORY_REQUIRE;
>> + Db->FrameDataLen = PXE_MAX_TXRX_UNIT_ETHER;
>> + Db->LinkSpeeds[0] = 10;
>> + Db->LinkSpeeds[1] = 100;
>> + Db->LinkSpeeds[2] = 1000;
>> + Db->LinkSpeeds[3] = 0;
>> + Db->MediaHeaderLen = PXE_MAC_HEADER_LEN_ETHER;
>> + Db->HWaddrLen = PXE_HWADDR_LEN_ETHER;
>> + Db->MCastFilterCnt = MAX_MCAST_ADDRESS_CNT;
>> + Db->TxBufCnt = Nic->PxeInit.TxBufCnt;
>> + Db->TxBufSize = Nic->PxeInit.TxBufSize;
>> + Db->RxBufCnt = Nic->PxeInit.RxBufCnt;
>> + Db->RxBufSize = Nic->PxeInit.RxBufSize;
>> + Db->IFtype = PXE_IFTYPE_ETHERNET;
>> + Db->SupportedDuplexModes = PXE_DUPLEX_DEFAULT;
>> + Db->SupportedLoopBackModes = LOOPBACK_NORMAL;
>> +
>> + Cdb->StatFlags |= (PXE_STATFLAGS_CABLE_DETECT_SUPPORTED |
>> + PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED);
>> +
>> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetInitInfo != NULL) {
>> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiGetInitInfo (Cdb, Nic);
>> + if (EFI_ERROR (Status)) {
>> + Cdb->StatFlags = 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 != PXE_OPCODE_GET_CONFIG_INFO) ||
>> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) ||
>> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) ||
>> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) ||
>> + (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) ||
>> + (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED) ||
>> + (Cdb->DBsize != sizeof (PXE_DB_GET_CONFIG_INFO)) ||
>> + (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED))
>> + {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>> + return;
>> + } else {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;
>> + Cdb->StatCode = PXE_STATCODE_SUCCESS;
>> + }
>> +
>> + if (Nic->State == PXE_STATFLAGS_GET_STATE_STOPPED) {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_NOT_STARTED;
>> + return;
>> + }
>> +
>> + Db = (PXE_DB_GET_CONFIG_INFO *)(UINTN)Cdb->DBaddr;
>> +
>> + Db->pci.BusType = PXE_BUSTYPE_USB;
>> +
>> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetConfigInfo != NULL) {
>> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiGetConfigInfo (Cdb,
>> Nic);
>> + if (EFI_ERROR (Status)) {
>> + Cdb->StatFlags = 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 != PXE_OPCODE_INITIALIZE) ||
>> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) ||
>> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) ||
>> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) ||
>> + (Cdb->CPBsize != sizeof (PXE_CPB_INITIALIZE)))
>> + {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>> + return;
>> + } else {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;
>> + }
>> +
>> + if (Nic->State == PXE_STATFLAGS_GET_STATE_STOPPED) {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_NOT_STARTED;
>> + return;
>> + }
>> +
>> + if ((Cdb->OpFlags != PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) &&
>> + (Cdb->OpFlags != PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE))
>> + {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>> + return;
>> + }
>> +
>> + if (Nic->State == PXE_STATFLAGS_GET_STATE_INITIALIZED) {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_ALREADY_INITIALIZED;
>> + return;
>> + }
>> +
>> + Cpb = (PXE_CPB_INITIALIZE *)(UINTN)Cdb->CPBaddr;
>> + Db = (PXE_DB_INITIALIZE *)(UINTN)Cdb->DBaddr;
>> +
>> + Nic->PxeInit.LinkSpeed = Cpb->LinkSpeed;
>> + Nic->PxeInit.DuplexMode = Cpb->DuplexMode;
>> + Nic->PxeInit.LoopBackMode = Cpb->LoopBackMode;
>> + Nic->PxeInit.MemoryAddr = Cpb->MemoryAddr;
>> + Nic->PxeInit.MemoryLength = Cpb->MemoryLength;
>> + Nic->PxeInit.TxBufCnt = TX_BUFFER_COUNT;
>> + Nic->PxeInit.TxBufSize = Nic->MaxSegmentSize;
>> + Nic->PxeInit.RxBufCnt = RX_BUFFER_COUNT;
>> + Nic->PxeInit.RxBufSize = Nic->MaxSegmentSize;
>> +
>> + Cdb->StatCode = Initialize (Cdb, Nic);
>> +
>> + Db->MemoryUsed = MEMORY_REQUIRE;
>> + Db->TxBufCnt = Nic->PxeInit.TxBufCnt;
>> + Db->TxBufSize = Nic->PxeInit.TxBufSize;
>> + Db->RxBufCnt = Nic->PxeInit.RxBufCnt;
>> + Db->RxBufSize = Nic->PxeInit.RxBufSize;
>> +
>> + Nic->RxFilter = PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST;
>> + Nic->CanTransmit = FALSE;
>> +
>> + if (Cdb->OpFlags == PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) {
>> + if ((Nic->Request.Request == USB_CDC_NETWORK_CONNECTION) &&
>> (Nic->Request.Value == NETWORK_DISCONNECT)) {
>> + Nic->CableDetect = 0;
>> + } else if ((Nic->Request.Request == USB_CDC_NETWORK_CONNECTION)
>> && (Nic->Request.Value == NETWORK_CONNECTED)) {
>> + Nic->CableDetect = 1;
>> + }
>> +
>> + if (Nic->CableDetect == 0) {
>> + Cdb->StatFlags |= PXE_STATFLAGS_INITIALIZED_NO_MEDIA;
>> + }
>> + }
>> +
>> + if (Cdb->StatCode != PXE_STATCODE_SUCCESS) {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + } else {
>> + Nic->State = PXE_STATFLAGS_GET_STATE_INITIALIZED;
>> + }
>> +
>> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiInitialize != NULL) {
>> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiInitialize (Cdb, Nic);
>> + if (EFI_ERROR (Status)) {
>> + Cdb->StatFlags = 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 = MapIt (
>> + Nic,
>> + Nic->PxeInit.MemoryAddr,
>> + Nic->PxeInit.MemoryLength,
>> + TO_AND_FROM_DEVICE,
>> + (UINT64)(UINTN)&Nic->MappedAddr
>> + );
>> +
>> + if (Status != 0) {
>> + return (UINT16)Status;
>> + }
>> +
>> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {
>> + Nic->PermNodeAddress[Index] = Nic->MacAddr.Addr[Index];
>> + }
>> +
>> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {
>> + Nic->CurrentNodeAddress[Index] = Nic->PermNodeAddress[Index];
>> + }
>> +
>> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {
>> + Nic->BroadcastNodeAddress[Index] = 0xFF;
>> + }
>> +
>> + for (Index = PXE_HWADDR_LEN_ETHER; Index < PXE_MAC_LENGTH; Index++) {
>> + Nic->CurrentNodeAddress[Index] = 0;
>> + Nic->PermNodeAddress[Index] = 0;
>> + Nic->BroadcastNodeAddress[Index] = 0;
>> + }
>> +
>> + if (Nic->UsbEth->UsbEthInitialize != NULL) {
>> + EfiStatus = 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 != PXE_OPCODE_RESET) ||
>> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) ||
>> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) ||
>> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) ||
>> + (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) ||
>> + (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED) ||
>> + (Cdb->DBsize != PXE_DBSIZE_NOT_USED) ||
>> + (Cdb->DBaddr != PXE_DBADDR_NOT_USED))
>> + {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>> + return;
>> + } else {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;
>> + Cdb->StatCode = PXE_STATCODE_SUCCESS;
>> + }
>> +
>> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) {
>> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED;
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + return;
>> + }
>> +
>> + if ((Cdb->OpFlags != PXE_OPFLAGS_NOT_USED) &&
>> + (Cdb->OpFlags != PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS) &&
>> + (Cdb->OpFlags != PXE_OPFLAGS_RESET_DISABLE_FILTERS))
>> + {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>> + return;
>> + }
>> +
>> + if ((Cdb->OpFlags & PXE_OPFLAGS_RESET_DISABLE_FILTERS) == 0) {
>> + Nic->RxFilter = PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST;
>> + }
>> +
>> + if ((Cdb->OpFlags & PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS) != 0) {
>> + Nic->InterrupOpFlag = 0;
>> + }
>> +
>> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiReset != NULL) {
>> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiReset (Cdb, Nic);
>> + if (EFI_ERROR (Status)) {
>> + Cdb->StatFlags = 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 != PXE_OPCODE_SHUTDOWN) ||
>> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) ||
>> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) ||
>> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) ||
>> + (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) ||
>> + (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED) ||
>> + (Cdb->DBsize != PXE_DBSIZE_NOT_USED) ||
>> + (Cdb->DBaddr != PXE_DBADDR_NOT_USED) ||
>> + (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED))
>> + {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>> + return;
>> + } else {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;
>> + Cdb->StatCode = PXE_STATCODE_SUCCESS;
>> + }
>> +
>> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) {
>> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED;
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + return;
>> + }
>> +
>> + Nic->CanTransmit = FALSE;
>> +
>> + Nic->State = PXE_STATFLAGS_GET_STATE_STARTED;
>> +
>> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiShutdown != NULL) {
>> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiShutdown (Cdb, Nic);
>> + if (EFI_ERROR (Status)) {
>> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED;
>> + Cdb->StatFlags = 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 = PXE_STATCODE_UNSUPPORTED;
>> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiInterruptEnable != NULL) {
>> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiInterruptEnable (Cdb,
>> Nic);
>> + if (EFI_ERROR (Status)) {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + } else {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;
>> + Cdb->StatCode = 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 != PXE_OPCODE_RECEIVE_FILTERS) ||
>> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) ||
>> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) ||
>> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)))
>> + {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>> + return;
>> + } else {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;
>> + Cdb->StatCode = PXE_STATCODE_SUCCESS;
>> + }
>> +
>> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) {
>> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED;
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + return;
>> + }
>> +
>> + NewFilter = (UINT16)(Cdb->OpFlags & 0x1F);
>> +
>> + switch (Cdb->OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_OPMASK) {
>> + case PXE_OPFLAGS_RECEIVE_FILTER_READ:
>> + if (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>> + }
>> +
>> + if ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST)
>> == 0) {
>> + if ((Cdb->DBsize != 0)) {
>> + Db = (PXE_DB_RECEIVE_FILTERS *)(UINTN)Cdb->DBaddr;
>> + CopyMem (Db, &Nic->McastList, Nic->McastCount);
>> + }
>> + }
>> +
>> + break;
>> +
>> + case PXE_OPFLAGS_RECEIVE_FILTER_ENABLE:
>> + if (NewFilter == 0) {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + }
>> +
>> + if (Cdb->CPBsize != 0) {
>> + if (((NewFilter &
>> PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) == 0) ||
>> + ((NewFilter &
>> PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) != 0) ||
>> + ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST)
>> != 0) ||
>> + ((Cdb->CPBsize % sizeof (PXE_MAC_ADDR)) != 0))
>> + {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + }
>> + }
>> +
>> + if ((Cdb->OpFlags &
>> PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) != 0) {
>> + if (((Cdb->OpFlags &
>> PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) != 0) ||
>> + ((Cdb->OpFlags &
>> PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) != 0))
>> + {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + }
>> +
>> + if ((Cdb->CPBsize == 0)) {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + }
>> + }
>> +
>> + Cdb->StatCode = SetFilter (Nic, NewFilter, Cdb->CPBaddr,
>> Cdb->CPBsize);
>> + break;
>> +
>> + case PXE_OPFLAGS_RECEIVE_FILTER_DISABLE:
>> + if (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>> + }
>> +
>> + break;
>> +
>> + default:
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>> + }
>> +
>> + Cdb->StatFlags = (PXE_STATFLAGS)(Cdb->StatFlags | Nic->RxFilter);
>> +
>> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiReceiveFilter != NULL) {
>> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiReceiveFilter (Cdb,
>> Nic);
>> + if (EFI_ERROR (Status)) {
>> + Cdb->StatFlags = 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;
>> + UINT8 Index1;
>> + UINT8 Index2;
>> + PXE_CPB_RECEIVE_FILTERS *Cpb;
>> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor;
>> +
>> + Count = 0;
>> + Cpb = (PXE_CPB_RECEIVE_FILTERS *)(UINTN)CpbAddr;
>> +
>> + // The Cpb could be NULL.(ref:PXE_CPBADDR_NOT_USED)
>> + Nic->RxFilter = (UINT8)SetFilter;
>> +
>> + if (((SetFilter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST)
>> != 0) || (Cpb != NULL)) {
>> + if (Cpb != NULL) {
>> + Nic->McastCount = (UINT8)(CpbSize / PXE_MAC_LENGTH);
>> + CopyMem (&Nic->McastList, Cpb, Nic->McastCount);
>> + }
>> +
>> + Nic->UsbEth->UsbEthFunDescriptor (Nic->UsbEth,
>> &UsbEthFunDescriptor);
>> + if ((UsbEthFunDescriptor.NumberMcFilters << 1) == 0) {
>> + Nic->RxFilter |= PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST;
>> + Nic->UsbEth->SetUsbEthPacketFilter (Nic->UsbEth, Nic->RxFilter);
>> + } else {
>> + Status = gBS->AllocatePool (EfiBootServicesData,
>> Nic->McastCount * 6, (VOID **)&McastList);
>> + if (EFI_ERROR (Status)) {
>> + return PXE_STATCODE_INVALID_PARAMETER;
>> + }
>> +
>> + if (Cpb != NULL) {
>> + for (Index1 = 0; Index1 < Nic->McastCount; Index1++) {
>> + for (Index2 = 0; Index2 < 6; Index2++) {
>> + McastList[Count++] = Cpb->MCastList[Index1][Index2];
>> + }
>> + }
>> + }
>> +
>> + Nic->RxFilter |= PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST;
>> + if (Cpb != NULL) {
>> + Nic->UsbEth->SetUsbEthMcastFilter (Nic->UsbEth,
>> Nic->McastCount, McastList);
>> + }
>> +
>> + Nic->UsbEth->SetUsbEthPacketFilter (Nic->UsbEth, Nic->RxFilter);
>> + FreePool (McastList);
>> + }
>> + }
>> +
>> + return PXE_STATCODE_SUCCESS;
>> +}
>> +
>> +/**
>> + This command is used to get current station and broadcast MAC
>> addresses
>> + 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 != PXE_OPCODE_STATION_ADDRESS) ||
>> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) ||
>> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) ||
>> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) ||
>> + (Cdb->DBsize != sizeof (PXE_DB_STATION_ADDRESS)))
>> + {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>> + return;
>> + } else {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;
>> + Cdb->StatCode = PXE_STATCODE_SUCCESS;
>> + }
>> +
>> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) {
>> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED;
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + return;
>> + }
>> +
>> + if (Cdb->OpFlags == PXE_OPFLAGS_STATION_ADDRESS_RESET) {
>> + if (CompareMem (&Nic->CurrentNodeAddress[0],
>> &Nic->PermNodeAddress[0], PXE_MAC_LENGTH) != 0) {
>> + for (Index = 0; Index < PXE_MAC_LENGTH; Index++) {
>> + Nic->CurrentNodeAddress[Index] = Nic->PermNodeAddress[Index];
>> + }
>> + }
>> + }
>> +
>> + if (Cdb->CPBaddr != 0) {
>> + Cpb = (PXE_CPB_STATION_ADDRESS *)(UINTN)Cdb->CPBaddr;
>> + for (Index = 0; Index < PXE_MAC_LENGTH; Index++) {
>> + Nic->CurrentNodeAddress[Index] = Cpb->StationAddr[Index];
>> + }
>> + }
>> +
>> + if (Cdb->DBaddr != 0) {
>> + Db = (PXE_DB_STATION_ADDRESS *)(UINTN)Cdb->DBaddr;
>> + for (Index = 0; Index < PXE_MAC_LENGTH; Index++) {
>> + Db->StationAddr[Index] = Nic->CurrentNodeAddress[Index];
>> + Db->BroadcastAddr[Index] = Nic->BroadcastNodeAddress[Index];
>> + Db->PermanentAddr[Index] = Nic->PermNodeAddress[Index];
>> + }
>> + }
>> +
>> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStationAddress != NULL) {
>> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiStationAddress (Cdb,
>> Nic);
>> + if (EFI_ERROR (Status)) {
>> + Cdb->StatFlags = 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 != PXE_OPCODE_STATISTICS) ||
>> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) ||
>> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) ||
>> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) ||
>> + (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) ||
>> + (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED))
>> + {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>> + return;
>> + } else {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;
>> + }
>> +
>> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) {
>> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED;
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + return;
>> + }
>> +
>> + if ((Cdb->OpFlags != PXE_OPFLAGS_STATISTICS_RESET) &&
>> + (Cdb->OpFlags != PXE_OPFLAGS_STATISTICS_READ))
>> + {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>> + return;
>> + }
>> +
>> + Cdb->StatCode = Statistics (Nic, Cdb->DBaddr, Cdb->DBsize);
>> +
>> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStatistics != NULL) {
>> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiStatistics (Cdb, Nic);
>> + if (EFI_ERROR (Status)) {
>> + Cdb->StatFlags = 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 = (PXE_DB_STATISTICS *)(UINTN)DbAddr;
>> +
>> + if (DbSize == 0) {
>> + return PXE_STATCODE_SUCCESS;
>> + }
>> +
>> + DbStatistic->Supported = 0x802;
>> + DbStatistic->Data[0x01] = Nic->RxFrame;
>> + DbStatistic->Data[0x0B] = Nic->TxFrame;
>> +
>> + if (Nic->UsbEth->UsbEthStatistics != NULL) {
>> + Status = 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 != PXE_OPCODE_MCAST_IP_TO_MAC) ||
>> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) ||
>> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) ||
>> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) ||
>> + (Cdb->CPBsize != sizeof (PXE_CPB_MCAST_IP_TO_MAC)) ||
>> + (Cdb->DBsize != sizeof (PXE_DB_MCAST_IP_TO_MAC)))
>> + {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>> + return;
>> + } else {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;
>> + Cdb->StatCode = PXE_STATCODE_SUCCESS;
>> + }
>> +
>> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) {
>> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED;
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + return;
>> + }
>> +
>> + Cpb = (PXE_CPB_MCAST_IP_TO_MAC *)(UINTN)Cdb->CPBaddr;
>> + Db = (PXE_DB_MCAST_IP_TO_MAC *)(UINTN)Cdb->DBaddr;
>> +
>> + if ((Cdb->OpFlags & PXE_OPFLAGS_MCAST_IPV6_TO_MAC) != 0) {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_UNSUPPORTED;
>> + return;
>> + }
>> +
>> + Tmp = (UINT8 *)(&Cpb->IP.IPv4);
>> +
>> + if ((Tmp[0] & 0xF0) != 0xE0) {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CPB;
>> + }
>> +
>> + Db->MAC[0] = 0x01;
>> + Db->MAC[1] = 0x00;
>> + Db->MAC[2] = 0x5E;
>> + Db->MAC[3] = Tmp[1] & 0x7F;
>> + Db->MAC[4] = Tmp[2];
>> + Db->MAC[5] = Tmp[3];
>> +
>> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiMcastIp2Mac != NULL) {
>> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiMcastIp2Mac (Cdb, Nic);
>> + if (EFI_ERROR (Status)) {
>> + Cdb->StatFlags = 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 = PXE_STATCODE_UNSUPPORTED;
>> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiNvData != NULL) {
>> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiNvData (Cdb, Nic);
>> + if (EFI_ERROR (Status)) {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + } else {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;
>> + Cdb->StatCode = 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 != PXE_OPCODE_GET_STATUS) ||
>> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) ||
>> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) ||
>> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) ||
>> + (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) ||
>> + (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED))
>> + {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>> + return;
>> + } else {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;
>> + Cdb->StatCode = PXE_STATCODE_SUCCESS;
>> + }
>> +
>> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) {
>> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED;
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + return;
>> + }
>> +
>> + TmpGetStatus.RxFrameLen = 0;
>> + TmpGetStatus.reserved = 0;
>> + Db = (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) != 0) {
>> + if (Cdb->DBsize == 0) {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>> + return;
>> + }
>> +
>> + NumEntries = Cdb->DBsize - sizeof (UINT64);
>> + Cdb->DBsize = sizeof (UINT32) * 2;
>> +
>> + for (Index = 0; NumEntries >= sizeof (UINT64); Index++,
>> NumEntries -= sizeof (UINT64)) {
>> + if (Nic->TxBufferCount > 0) {
>> + Nic->TxBufferCount--;
>> + Db->TxBuffer[Index] = Nic->MediaHeader[Nic->TxBufferCount];
>> + }
>> + }
>> + }
>> +
>> + if ((Cdb->OpFlags & PXE_OPFLAGS_GET_INTERRUPT_STATUS) != 0) {
>> + if (Nic->ReceiveStatus != 0) {
>> + Cdb->StatFlags |= PXE_STATFLAGS_GET_STATUS_RECEIVE;
>> + }
>> + }
>> +
>> + if ((Nic->Request.Request == USB_CDC_NETWORK_CONNECTION) &&
>> (Nic->Request.Value == NETWORK_DISCONNECT)) {
>> + Nic->CableDetect = 0;
>> + } else if ((Nic->Request.Request == USB_CDC_NETWORK_CONNECTION) &&
>> (Nic->Request.Value == NETWORK_CONNECTED)) {
>> + Nic->CableDetect = 1;
>> + }
>> +
>> + if ((Cdb->OpFlags & PXE_OPFLAGS_GET_MEDIA_STATUS) != 0) {
>> + if (Nic->CableDetect == 0) {
>> + Cdb->StatFlags |= PXE_STATFLAGS_GET_STATUS_NO_MEDIA;
>> + }
>> + }
>> +
>> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetStatus != NULL) {
>> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiGetStatus (Cdb, Nic);
>> + if (EFI_ERROR (Status)) {
>> + Cdb->StatFlags = 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 != PXE_OPCODE_FILL_HEADER) ||
>> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) ||
>> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) ||
>> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) ||
>> + (Cdb->CPBsize != sizeof (PXE_CPB_FILL_HEADER_FRAGMENTED)) ||
>> + (Cdb->DBsize != PXE_DBSIZE_NOT_USED) ||
>> + (Cdb->DBaddr != PXE_DBADDR_NOT_USED))
>> + {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>> + return;
>> + } else {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;
>> + Cdb->StatCode = PXE_STATCODE_SUCCESS;
>> + }
>> +
>> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) {
>> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED;
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + return;
>> + }
>> +
>> + if (Cdb->CPBsize == PXE_CPBSIZE_NOT_USED) {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>> + return;
>> + }
>> +
>> + if ((Cdb->OpFlags & PXE_OPFLAGS_FILL_HEADER_FRAGMENTED) != 0) {
>> + CpbFill = (PXE_CPB_FILL_HEADER_FRAGMENTED *)(UINTN)Cdb->CPBaddr;
>> +
>> + if ((CpbFill->FragCnt == 0) || (CpbFill->FragDesc[0].FragLen <
>> PXE_MAC_HEADER_LEN_ETHER)) {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>> + return;
>> + }
>> +
>> + MacHeader = (EthernetHeader
>> *)(UINTN)CpbFill->FragDesc[0].FragAddr;
>> + MacHeader->Protocol = CpbFill->Protocol;
>> +
>> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {
>> + MacHeader->DestAddr[Index] = CpbFill->DestAddr[Index];
>> + MacHeader->SrcAddr[Index] = CpbFill->SrcAddr[Index];
>> + }
>> + } else {
>> + CpbFillHeader = (PXE_CPB_FILL_HEADER *)(UINTN)Cdb->CPBaddr;
>> +
>> + MacHeader = (EthernetHeader
>> *)(UINTN)CpbFillHeader->MediaHeader;
>> + MacHeader->Protocol = CpbFillHeader->Protocol;
>> +
>> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {
>> + MacHeader->DestAddr[Index] = CpbFillHeader->DestAddr[Index];
>> + MacHeader->SrcAddr[Index] = CpbFillHeader->SrcAddr[Index];
>> + }
>> + }
>> +
>> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiFillHeader != NULL) {
>> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiFillHeader (Cdb, Nic);
>> + if (EFI_ERROR (Status)) {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + }
>> + }
>> +}
>> +
>> +/**
>> + The Transmit command is used to place a packet into the transmit
>> queue.
>> +
>> + @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 != PXE_OPCODE_TRANSMIT) ||
>> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) ||
>> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) ||
>> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) ||
>> + (Cdb->CPBsize != sizeof (PXE_CPB_TRANSMIT)) ||
>> + (Cdb->DBsize != PXE_DBSIZE_NOT_USED) ||
>> + (Cdb->DBaddr != PXE_DBADDR_NOT_USED))
>> + {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>> + return;
>> + } else {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;
>> + Cdb->StatCode = PXE_STATCODE_SUCCESS;
>> + }
>> +
>> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED;
>> + return;
>> + }
>> +
>> + if (Cdb->CPBsize == PXE_CPBSIZE_NOT_USED) {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>> + return;
>> + }
>> +
>> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiTransmit != NULL) {
>> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiTransmit (Cdb, Nic);
>> + if (EFI_ERROR (Status)) {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + }
>> +
>> + return;
>> + }
>> +
>> + Cdb->StatCode = Transmit (Cdb, Nic, Cdb->CPBaddr, Cdb->OpFlags);
>> +
>> + if (Cdb->StatCode != PXE_STATCODE_SUCCESS) {
>> + Cdb->StatFlags = 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
>> controller 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;
>> + UINTN DataLength;
>> + UINTN TransmitLength;
>> + UINTN Map;
>> + UINT32 Counter;
>> + UINT16 StatCode;
>> +
>> + BulkOutData = 0;
>> + Counter = 0;
>> + Cpb = (PXE_CPB_TRANSMIT *)(UINTN)CpbAddr;
>> +
>> + if (Nic->CanTransmit) {
>> + return PXE_STATCODE_BUSY;
>> + }
>> +
>> + Nic->CanTransmit = TRUE;
>> +
>> + if ((OpFlags & PXE_OPFLAGS_TRANSMIT_FRAGMENTED) != 0) {
>> + return PXE_STATCODE_INVALID_PARAMETER;
>> + }
>> +
>> + Map = MapIt (
>> + Nic,
>> + Cpb->FrameAddr,
>> + Cpb->DataLen + (UINT32)Cpb->MediaheaderLen,
>> + TO_DEVICE,
>> + (UINT64)(UINTN)&BulkOutData
>> + );
>> +
>> + if (Map != 0) {
>> + Nic->CanTransmit = FALSE;
>> + return PXE_STATCODE_INVALID_PARAMETER;
>> + }
>> +
>> + if (Nic->TxBufferCount < MAX_XMIT_BUFFERS) {
>> + Nic->MediaHeader[Nic->TxBufferCount] = Cpb->FrameAddr;
>> + Nic->TxBufferCount++;
>> + }
>> +
>> + DataLength = (UINTN)(Cpb->DataLen + (UINT32)Cpb->MediaheaderLen);
>> +
>> + while (1) {
>> + if (Counter >= 3) {
>> + StatCode = PXE_STATCODE_BUSY;
>> + break;
>> + }
>> +
>> + TransmitLength = DataLength;
>> +
>> + Status = Nic->UsbEth->UsbEthTransmit (Cdb, Nic->UsbEth, (VOID
>> *)(UINTN)BulkOutData, &TransmitLength);
>> + if (EFI_ERROR (Status)) {
>> + StatCode = PXE_STATFLAGS_COMMAND_FAILED;
>> + }
>> +
>> + if (Status == EFI_INVALID_PARAMETER) {
>> + StatCode = PXE_STATCODE_INVALID_PARAMETER;
>> + break;
>> + }
>> +
>> + if (Status == EFI_DEVICE_ERROR) {
>> + StatCode = PXE_STATCODE_DEVICE_FAILURE;
>> + break;
>> + }
>> +
>> + if (!EFI_ERROR (Status)) {
>> + Nic->TxFrame++;
>> + StatCode = PXE_STATCODE_SUCCESS;
>> + break;
>> + }
>> +
>> + Counter++;
>> + }
>> +
>> + UnMapIt (
>> + Nic,
>> + Cpb->FrameAddr,
>> + Cpb->DataLen + (UINT32)Cpb->MediaheaderLen,
>> + TO_DEVICE,
>> + BulkOutData
>> + );
>> +
>> + Nic->CanTransmit = 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 != PXE_OPCODE_RECEIVE) ||
>> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) ||
>> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) ||
>> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) ||
>> + (Cdb->CPBsize != sizeof (PXE_CPB_RECEIVE)) ||
>> + (Cdb->DBsize != sizeof (PXE_DB_RECEIVE)) ||
>> + (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED))
>> + {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>> + return;
>> + } else {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE;
>> + Cdb->StatCode = PXE_STATCODE_SUCCESS;
>> + }
>> +
>> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED;
>> + return;
>> + }
>> +
>> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiReceive != NULL) {
>> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiReceive (Cdb, Nic);
>> + if (EFI_ERROR (Status)) {
>> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>> + }
>> +
>> + return;
>> + }
>> +
>> + Cdb->StatCode = Receive (Cdb, Nic, Cdb->CPBaddr, Cdb->DBaddr);
>> +
>> + if (Cdb->StatCode != PXE_STATCODE_SUCCESS) {
>> + Cdb->StatFlags = 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
>> controller 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;
>> + PXE_FRAME_TYPE FrameType;
>> + PXE_CPB_RECEIVE *Cpb;
>> + PXE_DB_RECEIVE *Db;
>> + NIC_DEVICE *NicDevice;
>> + UINT8 *BulkInData;
>> + UINTN DataLength;
>> + EthernetHeader *Header;
>> + EFI_TPL OriginalTpl;
>> +
>> + FrameType = PXE_FRAME_TYPE_NONE;
>> + NicDevice = UNDI_DEV_FROM_NIC (Nic);
>> + BulkInData = NicDevice->ReceiveBuffer;
>> + DataLength = (UINTN)Nic->MaxSegmentSize;
>> + Cpb = (PXE_CPB_RECEIVE *)(UINTN)CpbAddr;
>> + Db = (PXE_DB_RECEIVE *)(UINTN)DbAddr;
>> +
>> + if (!BulkInData) {
>> + return PXE_STATCODE_INVALID_PARAMETER;
>> + }
>> +
>> + if ((Nic->RateLimitingCreditCount == 0) &&
>> (Nic->RateLimitingEnable == TRUE)) {
>> + return PXE_STATCODE_NO_DATA;
>> + }
>> +
>> + Status = Nic->UsbEth->UsbEthReceive (Cdb, Nic->UsbEth, (VOID
>> *)BulkInData, &DataLength);
>> + if (EFI_ERROR (Status)) {
>> + Nic->ReceiveStatus = 0;
>> + if (Nic->RateLimitingEnable == TRUE) {
>> + OriginalTpl = gBS->RaiseTPL (TPL_NOTIFY);
>> + if (Nic->RateLimitingCreditCount != 0) {
>> + Nic->RateLimitingCreditCount--;
>> + }
>> +
>> + gBS->RestoreTPL (OriginalTpl);
>> + }
>> +
>> + return PXE_STATCODE_NO_DATA;
>> + }
>> +
>> + Nic->RxFrame++;
>> +
>> + if (DataLength != 0) {
>> + if (DataLength > Cpb->BufferLen) {
>> + DataLength = (UINTN)Cpb->BufferLen;
>> + }
>> +
>> + CopyMem ((UINT8 *)(UINTN)Cpb->BufferAddr, (UINT8 *)BulkInData,
>> DataLength);
>> +
>> + Header = (EthernetHeader *)BulkInData;
>> +
>> + Db->FrameLen = (UINT32)DataLength;
>> + Db->MediaHeaderLen = PXE_MAC_HEADER_LEN_ETHER;
>> +
>> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {
>> + if (Header->DestAddr[Index] != Nic->CurrentNodeAddress[Index]) {
>> + break;
>> + }
>> + }
>> +
>> + if (Index >= PXE_HWADDR_LEN_ETHER) {
>> + FrameType = PXE_FRAME_TYPE_UNICAST;
>> + } else {
>> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {
>> + if (Header->DestAddr[Index] !=
>> Nic->BroadcastNodeAddress[Index]) {
>> + break;
>> + }
>> + }
>> +
>> + if (Index >= PXE_HWADDR_LEN_ETHER) {
>> + FrameType = PXE_FRAME_TYPE_BROADCAST;
>> + } else {
>> + if ((Header->DestAddr[0] & 1) == 1) {
>> + FrameType = PXE_FRAME_TYPE_FILTERED_MULTICAST;
>> + } else {
>> + FrameType = PXE_FRAME_TYPE_PROMISCUOUS;
>> + }
>> + }
>> + }
>> +
>> + Db->Type = FrameType;
>> + Db->Protocol = Header->Protocol;
>> +
>> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {
>> + Db->SrcAddr[Index] = Header->SrcAddr[Index];
>> + Db->DestAddr[Index] = Header->DestAddr[Index];
>> + }
>> + }
>> +
>> + if (FrameType == PXE_FRAME_TYPE_NONE) {
>> + Nic->ReceiveStatus = 0;
>> + } else {
>> + Nic->ReceiveStatus = 1;
>> + }
>> +
>> + return PXE_STATCODE_SUCCESS;
>> +}
>> +
>> +/**
>> + 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 = PXE_ROMID_SIGNATURE;
>> + PxeSw->Len = (UINT8)sizeof (PXE_SW_UNDI);
>> + PxeSw->Fudge = 0;
>> + PxeSw->IFcnt = 0;
>> + PxeSw->IFcntExt = 0;
>> + PxeSw->Rev = PXE_ROMID_REV;
>> + PxeSw->MajorVer = PXE_ROMID_MAJORVER;
>> + PxeSw->MinorVer = PXE_ROMID_MINORVER;
>> + PxeSw->reserved1 = 0;
>> +
>> + PxeSw->Implementation = 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 = (UINT64)(UINTN)UndiApiEntry;
>> + PxeSw->reserved2[0] = 0;
>> + PxeSw->reserved2[1] = 0;
>> + PxeSw->reserved2[2] = 0;
>> + PxeSw->BusCnt = 1;
>> + PxeSw->BusType[0] = PXE_BUSTYPE_USB;
>> + PxeSw->Fudge = 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 = (PxeSw->IFcnt | PxeSw->IFcntExt << 8);
>> +
>> + if (Nic == NULL) {
>> + if (NicNum > 0) {
>> + NicNum--;
>> + }
>> +
>> + PxeSw->IFcnt = (UINT8)(NicNum & 0xFF); // Get lower byte
>> + PxeSw->IFcntExt = (UINT8)((NicNum & 0xFF00) >> 8); // Get upper
>> byte
>> + PxeSw->Fudge = (UINT8)(PxeSw->Fudge - CalculateSum8 ((VOID
>> *)PxeSw, PxeSw->Len));
>> + return;
>> + }
>> +
>> + NicNum++;
>> +
>> + PxeSw->IFcnt = (UINT8)(NicNum & 0xFF); // Get lower byte
>> + PxeSw->IFcntExt = (UINT8)((NicNum & 0xFF00) >> 8); // Get upper byte
>> + PxeSw->Fudge = (UINT8)(PxeSw->Fudge - CalculateSum8 ((VOID
>> *)PxeSw, PxeSw->Len));
>> +}
>> +
>> +/**
>> + UNDI API table entry.
>> +
>> + @param[in] Cdb A pointer to the command descriptor block.
>> +
>> +**/
>> +EFI_STATUS
>> +EFIAPI
>> +UndiApiEntry (
>> + IN UINT64 Cdb
>> + )
>> +{
>> + PXE_CDB *CdbPtr;
>> + NIC_DATA *Nic;
>> +
>> + if (Cdb == 0) {
>> + return EFI_INVALID_PARAMETER;
>> + }
>> +
>> + CdbPtr = (PXE_CDB *)(UINTN)Cdb;
>> + Nic = &(gLanDeviceList[CdbPtr->IFnum]->NicInfo);
>> + gUndiApiTable[CdbPtr->OpCode](CdbPtr, Nic);
>> + return EFI_SUCCESS;
>> +}
>> +
>> +/**
>> + 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 = (UINT64 *)(UINTN)MappedAddr;
>> +
>> + if (Nic->PxeStart.Map_Mem == 0) {
>> + *PhyAddr = 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
>> set
>> + 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 != 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/UsbRndis/ComponentName.c
>> b/UsbNetworkPkg/UsbRndis/ComponentName.c
>> new file mode 100644
>> index 000000000000..b9ba170c135b
>> --- /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) 2023, American Megatrends International LLC. All
>> rights reserved.<BR>
>> + SPDX-License-Identifier: BSD-2-Clause-Patent
>> +**/
>> +
>> +#include "UsbRndis.h"
>> +
>> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE
>> gUsbRndisDriverNameTable[] = {
>> + {
>> + "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 = {
>> + UsbRndisComponentNameGetDriverName,
>> + UsbRndisComponentNameGetControllerName,
>> + "eng"
>> +};
>> +
>> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL
>> gUsbRndisComponentName2 = {
>> +
>> (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)UsbRndisComponentNameGetDriverName,
>> +
>> (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)UsbRndisComponentNameGetControllerName,
>> + "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
>> 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 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
>> the
>> + 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
>> language
>> + 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 == &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
>> device
>> + drivers. It will also be NULL for a
>> bus drivers
>> + that wish to retrieve the name of
>> the bus
>> + 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
>> the
>> + 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
>> ControllerHandle and
>> + ChildHandle in the language
>> specified by
>> + Language from the point of view of
>> the driver
>> + specified by This.
>> +
>> + @retval EFI_SUCCESS The Unicode string for the user
>> readable name in
>> + the language specified by Language
>> for the
>> + driver specified by This was
>> returned in
>> + 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 000000000000..92830771e408
>> --- /dev/null
>> +++ b/UsbNetworkPkg/UsbRndis/UsbRndis.c
>> @@ -0,0 +1,886 @@
>> +/** @file
>> + This file contains code for USB Remote Network Driver
>> + Interface Spec. Driver Binding
>> +
>> + Copyright (c) 2023, American Megatrends International LLC. All
>> rights reserved.<BR>
>> + SPDX-License-Identifier: BSD-2-Clause-Patent
>> +**/
>> +
>> +#include "UsbRndis.h"
>> +
>> +EFI_DRIVER_BINDING_PROTOCOL gUsbRndisDriverBinding = {
>> + 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 = UsbIo->UsbGetInterfaceDescriptor (UsbIo,
>> &InterfaceDescriptor);
>> + if (EFI_ERROR (Status)) {
>> + return FALSE;
>> + }
>> +
>> + // Check specific device/RNDIS and CDC-DATA
>> + if (((InterfaceDescriptor.InterfaceClass == 0x2) &&
>> + (InterfaceDescriptor.InterfaceSubClass == 0x2) &&
>> + (InterfaceDescriptor.InterfaceProtocol == 0xFF)) || \
>> + ((InterfaceDescriptor.InterfaceClass == 0xEF) &&
>> + (InterfaceDescriptor.InterfaceSubClass == 0x4) &&
>> + (InterfaceDescriptor.InterfaceProtocol == 0x1)) || \
>> + ((InterfaceDescriptor.InterfaceClass == 0xA) &&
>> + (InterfaceDescriptor.InterfaceSubClass == 0x0) &&
>> + (InterfaceDescriptor.InterfaceProtocol == 0x00))
>> + )
>> + {
>> + return TRUE;
>> + }
>> +
>> + return FALSE;
>> +}
>> +
>> +/**
>> + Check if this interface is USB Rndis SubType but not CDC Data
>> interface
>> +
>> + @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 = UsbIo->UsbGetInterfaceDescriptor (UsbIo,
>> &InterfaceDescriptor);
>> + if (EFI_ERROR (Status)) {
>> + return FALSE;
>> + }
>> +
>> + // Check for specific device/RNDIS and CDC-DATA
>> + if (((InterfaceDescriptor.InterfaceClass == 0x2) &&
>> + (InterfaceDescriptor.InterfaceSubClass == 0x2) &&
>> + (InterfaceDescriptor.InterfaceProtocol == 0xFF)) || \
>> + ((InterfaceDescriptor.InterfaceClass == 0xEF) &&
>> + (InterfaceDescriptor.InterfaceSubClass == 0x4) &&
>> + (InterfaceDescriptor.InterfaceProtocol == 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 ((DEBUG_VERBOSE, "IsSameDevice Entry \n"));
>> + while (1) {
>> + if (IsDevicePathEnd (NextDevicePathNode (UsbRndisDataPath))) {
>> + if (((USB_DEVICE_PATH *)UsbRndisDataPath)->ParentPortNumber ==
>> + ((USB_DEVICE_PATH *)UsbCdcDataPath)->ParentPortNumber)
>> + {
>> + return EFI_SUCCESS;
>> + } else {
>> + return EFI_UNSUPPORTED;
>> + }
>> + } else {
>> + if (CompareMem (UsbCdcDataPath, UsbRndisDataPath, sizeof
>> (EFI_DEVICE_PATH_PROTOCOL)) != 0) {
>> + return EFI_UNSUPPORTED;
>> + }
>> +
>> + UsbRndisDataPath = NextDevicePathNode (UsbRndisDataPath);
>> + UsbCdcDataPath = NextDevicePathNode (UsbCdcDataPath);
>> + }
>> + }
>> +
>> + DEBUG ((DEBUG_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 = UsbIo->UsbGetInterfaceDescriptor (UsbIo,
>> &InterfaceDescriptor);
>> + if (EFI_ERROR (Status)) {
>> + return FALSE;
>> + }
>> +
>> + // Check for CDC-DATA
>> + if ((InterfaceDescriptor.InterfaceClass == 0xA) &&
>> + (InterfaceDescriptor.InterfaceSubClass == 0x0) &&
>> + (InterfaceDescriptor.InterfaceProtocol == 0x0))
>> + {
>> + return TRUE;
>> + }
>> +
>> + return FALSE;
>> +}
>> +
>> +/**
>> + Check if the USB Rndis(UsbIo) installed
>> +
>> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL
>> instance.
>> +
>> + @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 = UsbIo->UsbGetInterfaceDescriptor (UsbIo,
>> &InterfaceDescriptor);
>> + if (EFI_ERROR (Status)) {
>> + return FALSE;
>> + }
>> +
>> + // Check for Rndis
>> + if ((InterfaceDescriptor.InterfaceClass == 0x2) &&
>> + (InterfaceDescriptor.InterfaceSubClass == 0x2) &&
>> + (InterfaceDescriptor.InterfaceProtocol == 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
>> CDC Data is found.
>> + @retval EFI_NOT_FOUND The USB_RNDIS_DEVICE matching this
>> CDC 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;
>> + EDKII_USB_ETHERNET_PROTOCOL *UsbEthDevice;
>> + EFI_DEVICE_PATH_PROTOCOL *UsbRndisDataPath;
>> + EFI_USB_IO_PROTOCOL *UsbIo;
>> + BOOLEAN IsRndisInterfaceFlag;
>> +
>> + IsRndisInterfaceFlag = FALSE;
>> +
>> + Status = gBS->LocateHandleBuffer (
>> + ByProtocol,
>> + &gEdkIIUsbEthProtocolGuid,
>> + NULL,
>> + &HandleCount,
>> + &HandleBuffer
>> + );
>> + if (EFI_ERROR (Status)) {
>> + return Status;
>> + }
>> +
>> + for (Index = 0; Index < HandleCount; Index++) {
>> + Status = gBS->HandleProtocol (
>> + HandleBuffer[Index],
>> + &gEdkIIUsbEthProtocolGuid,
>> + (VOID **)&UsbEthDevice
>> + );
>> + if (EFI_ERROR (Status)) {
>> + continue;
>> + }
>> +
>> + Status = gBS->HandleProtocol (
>> + HandleBuffer[Index],
>> + &gEfiUsbIoProtocolGuid,
>> + (VOID **)&UsbIo
>> + );
>> + if (EFI_ERROR (Status)) {
>> + continue;
>> + }
>> +
>> + IsRndisInterfaceFlag = IsRndisInterface (UsbIo);
>> + if (IsRndisInterfaceFlag == FALSE) {
>> + continue;
>> + }
>> +
>> + Status = gBS->HandleProtocol (
>> + HandleBuffer[Index],
>> + &gEfiDevicePathProtocolGuid,
>> + (VOID **)&UsbRndisDataPath
>> + );
>> + if (EFI_ERROR (Status)) {
>> + continue;
>> + }
>> +
>> + Status = IsSameDevice (UsbRndisDataPath, UsbCdcDataPath);
>> +
>> + DEBUG ((DEBUG_VERBOSE, "Rndis IsSameDevice %r\n", Status));
>> +
>> + if (!EFI_ERROR (Status)) {
>> + *UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (UsbEthDevice);
>> + FreePool (HandleBuffer);
>> + return EFI_SUCCESS;
>> + }
>> + } // End of For loop
>> +
>> + 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 = gBS->HandleProtocol (
>> + UsbRndisDevice->UsbRndisHandle,
>> + &gEfiDevicePathProtocolGuid,
>> + (VOID **)&UsbRndisDataPath
>> + );
>> +
>> + if (EFI_ERROR (Status)) {
>> + return;
>> + }
>> +
>> + Status = gBS->LocateHandleBuffer (
>> + ByProtocol,
>> + &gEfiUsbIoProtocolGuid,
>> + NULL,
>> + &HandleCount,
>> + &HandleBuffer
>> + );
>> + if (EFI_ERROR (Status)) {
>> + return;
>> + }
>> +
>> + for (Index = 0; Index < HandleCount; Index++) {
>> + Status = gBS->HandleProtocol (
>> + HandleBuffer[Index],
>> + &gEfiUsbIoProtocolGuid,
>> + (VOID **)&UsbIo
>> + );
>> + ASSERT_EFI_ERROR (Status);
>> +
>> + if (IsUsbCdcData (UsbIo)) {
>> + DEBUG ((DEBUG_VERBOSE, "Rndis FindMatchingCdcData CDCData
>> interface found\n"));
>> +
>> + Status = gBS->HandleProtocol (
>> + HandleBuffer[Index],
>> + &gEfiDevicePathProtocolGuid,
>> + (VOID **)&UsbCdcDataPath
>> + );
>> + if (EFI_ERROR (Status)) {
>> + DEBUG ((DEBUG_VERBOSE, "Rndis CDCData DevicePath not
>> found\n"));
>> + FreePool (HandleBuffer);
>> + return;
>> + }
>> +
>> + Status = IsSameDevice (UsbRndisDataPath, UsbCdcDataPath);
>> + DEBUG ((DEBUG_VERBOSE, "Rndis IsSameDevice %r\n", Status));
>> + if (!EFI_ERROR (Status)) {
>> + UsbRndisDevice->UsbCdcDataHandle = HandleBuffer[Index];
>> + UsbRndisDevice->UsbIoCdcData = UsbIo;
>> + GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice);
>> + FreePool (HandleBuffer);
>> + return;
>> + }
>> + }
>> + } // End of For loop
>> +
>> + 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
>> RNDIS device.
>> +
>> + @retval EFI_SUCCESS The USB_RNDIS_DEVICE matching this
>> CDC Data is found.
>> + @retval EFI_NOT_FOUND The USB_RNDIS_DEVICE matching this
>> CDC 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 = gBS->HandleProtocol (
>> + CdcHandle,
>> + &gEfiDevicePathProtocolGuid,
>> + (VOID **)&UsbCdcDataPath
>> + );
>> +
>> + if (EFI_ERROR (Status)) {
>> + return Status;
>> + }
>> +
>> + Status = gBS->LocateHandleBuffer (
>> + ByProtocol,
>> + &gEfiUsbIoProtocolGuid,
>> + NULL,
>> + &HandleCount,
>> + &HandleBuffer
>> + );
>> + if (EFI_ERROR (Status)) {
>> + return Status;
>> + }
>> +
>> + for (Index = 0; Index < HandleCount; Index++) {
>> + Status = gBS->HandleProtocol (
>> + HandleBuffer[Index],
>> + &gEfiUsbIoProtocolGuid,
>> + (VOID **)&UsbIo
>> + );
>> + if (EFI_ERROR (Status)) {
>> + return Status;
>> + }
>> +
>> + if (IsUsbRndis (UsbIo)) {
>> + Status = gBS->HandleProtocol (
>> + HandleBuffer[Index],
>> + &gEfiDevicePathProtocolGuid,
>> + (VOID **)&UsbRndisDataPath
>> + );
>> + if (EFI_ERROR (Status)) {
>> + DEBUG ((DEBUG_ERROR, "Usb Rndis DevicePath not found\n"));
>> + break;
>> + }
>> +
>> + Status = IsSameDevice (UsbRndisDataPath, UsbCdcDataPath);
>> +
>> + if (!EFI_ERROR (Status)) {
>> + *RndisHandle = HandleBuffer[Index];
>> + *CdcUsbIo = UsbIo;
>> + FreePool (HandleBuffer);
>> + return Status;
>> + }
>> + }
>> + } // End of For loop
>> +
>> + 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;
>> +
>> + Status = gBS->OpenProtocol (
>> + ControllerHandle,
>> + &gEfiUsbIoProtocolGuid,
>> + (VOID **)&UsbIo,
>> + This->DriverBindingHandle,
>> + ControllerHandle,
>> + EFI_OPEN_PROTOCOL_BY_DRIVER
>> + );
>> + if (EFI_ERROR (Status)) {
>> + return Status;
>> + }
>> +
>> + Status = 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 to.
>> + @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;
>> +
>> + RndisHandle = ControllerHandle;
>> +
>> + Status = gBS->OpenProtocol (
>> + ControllerHandle,
>> + &gEfiUsbIoProtocolGuid,
>> + (VOID **)&UsbIo,
>> + This->DriverBindingHandle,
>> + ControllerHandle,
>> + EFI_OPEN_PROTOCOL_BY_DRIVER
>> + );
>> + if (EFI_ERROR (Status)) {
>> + return Status;
>> + }
>> +
>> + Status = 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
>> + );
>> +
>> + // 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)) {
>> + DEBUG ((DEBUG_INFO, "Rndis CDCData interface found\n"));
>> +
>> + // Find the parent RNDIS and update the UsbIo for the CDC device
>> + Status = UpdateRndisDevice (
>> + UsbEthPath,
>> + &UsbRndisDevice
>> + );
>> +
>> + if (!EFI_ERROR (Status)) {
>> + DEBUG ((DEBUG_INFO, "Rndis Matching interface found\n"));
>> + UsbRndisDevice->UsbCdcDataHandle = ControllerHandle;
>> + UsbRndisDevice->UsbIoCdcData = UsbIo;
>> + GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice);
>> + return Status;
>> + } else {
>> + // Check if RnDis exist
>> + Status = FindMatchingRndisDev (
>> + ControllerHandle,
>> + &UsbIo,
>> + &RndisHandle
>> + );
>> +
>> + if (EFI_ERROR (Status)) {
>> + gBS->CloseProtocol (
>> + ControllerHandle,
>> + &gEfiUsbIoProtocolGuid,
>> + This->DriverBindingHandle,
>> + ControllerHandle
>> + );
>> + return Status;
>> + }
>> + }
>> + }
>> +
>> + UsbRndisDevice = AllocateZeroPool (sizeof (USB_RNDIS_DEVICE));
>> +
>> + if (!UsbRndisDevice) {
>> + DEBUG ((DEBUG_ERROR, "AllocateZeroPool Fail\n"));
>> +
>> + gBS->CloseProtocol (
>> + ControllerHandle,
>> + &gEfiUsbIoProtocolGuid,
>> + This->DriverBindingHandle,
>> + ControllerHandle
>> + );
>> + return EFI_OUT_OF_RESOURCES;
>> + }
>> +
>> + Status = LoadAllDescriptor (
>> + UsbIo,
>> + &UsbRndisDevice->Config
>> + );
>> + if (EFI_ERROR (Status)) {
>> + DEBUG ((DEBUG_ERROR, "%a:LoadAllDescriptor status = %r\n",
>> __FUNCTION__, Status));
>> + gBS->CloseProtocol (
>> + ControllerHandle,
>> + &gEfiUsbIoProtocolGuid,
>> + This->DriverBindingHandle,
>> + ControllerHandle
>> + );
>> + FreePool (UsbRndisDevice);
>> + return Status;
>> + }
>> +
>> + Status = UsbIo->UsbGetInterfaceDescriptor (
>> + UsbIo,
>> + &Interface
>> + );
>> + if (EFI_ERROR (Status)) {
>> + DEBUG ((DEBUG_ERROR, "%a:UsbGetInterfaceDescriptor status =
>> %r\n", __FUNCTION__, Status));
>> + gBS->CloseProtocol (
>> + ControllerHandle,
>> + &gEfiUsbIoProtocolGuid,
>> + This->DriverBindingHandle,
>> + ControllerHandle
>> + );
>> + FreePool (UsbRndisDevice->Config);
>> + FreePool (UsbRndisDevice);
>> + return Status;
>> + }
>> +
>> + UsbRndisDevice->Signature =
>> USB_RNDIS_SIGNATURE;
>> + UsbRndisDevice->NumOfInterface =
>> Interface.InterfaceNumber;
>> + UsbRndisDevice->UsbRndisHandle = RndisHandle;
>> + UsbRndisDevice->UsbCdcDataHandle = 0;
>> + UsbRndisDevice->UsbIo = UsbIo;
>> + UsbRndisDevice->UsbEth.UsbEthReceive =
>> RndisUndiReceive;
>> + UsbRndisDevice->UsbEth.UsbEthTransmit =
>> RndisUndiTransmit;
>> + UsbRndisDevice->UsbEth.UsbEthInterrupt =
>> UsbRndisInterrupt;
>> + UsbRndisDevice->UsbEth.UsbEthMacAddress =
>> GetUsbEthMacAddress;
>> + UsbRndisDevice->UsbEth.UsbEthMaxBulkSize = UsbEthBulkSize;
>> + UsbRndisDevice->UsbEth.UsbHeaderFunDescriptor =
>> GetUsbHeaderFunDescriptor;
>> + UsbRndisDevice->UsbEth.UsbUnionFunDescriptor =
>> GetUsbUnionFunDescriptor;
>> + UsbRndisDevice->UsbEth.UsbEthFunDescriptor =
>> GetUsbRndisFunDescriptor;
>> + UsbRndisDevice->UsbEth.SetUsbEthMcastFilter =
>> SetUsbRndisMcastFilter;
>> + UsbRndisDevice->UsbEth.SetUsbEthPowerPatternFilter =
>> SetUsbRndisPowerFilter;
>> + UsbRndisDevice->UsbEth.GetUsbEthPowerPatternFilter =
>> GetUsbRndisPowerFilter;
>> + UsbRndisDevice->UsbEth.SetUsbEthPacketFilter =
>> SetUsbRndisPacketFilter;
>> + UsbRndisDevice->UsbEth.GetUsbEthStatistic =
>> GetRndisStatistic;
>> +
>> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetState =
>> RndisDummyReturn;
>> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStart =
>> RndisUndiStart;
>> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStop =
>> RndisUndiStop;
>> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetInitInfo =
>> RndisUndiGetInitInfo;
>> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetConfigInfo =
>> RndisUndiGetConfigInfo;
>> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiInitialize =
>> RndisUndiInitialize;
>> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiReset =
>> RndisUndiReset;
>> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiShutdown =
>> RndisUndiShutdown;
>> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiInterruptEnable =
>> RndisDummyReturn;
>> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiReceiveFilter =
>> RndisUndiReceiveFilter;
>> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStationAddress =
>> RndisDummyReturn;
>> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStatistics = NULL;
>> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiMcastIp2Mac =
>> RndisDummyReturn;
>> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiNvData =
>> RndisDummyReturn;
>> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetStatus =
>> RndisUndiGetStatus;
>> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiFillHeader =
>> RndisDummyReturn;
>> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiTransmit = NULL;
>> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiReceive = NULL;
>> +
>> + UsbRndisDevice->MaxTransferSize = RNDIS_MAX_TRANSFER_SIZE;
>> + UsbRndisDevice->MaxPacketsPerTransfer = 1;
>> + UsbRndisDevice->PacketAlignmentFactor = 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 = gBS->InstallProtocolInterface (
>> + &ControllerHandle,
>> + &gEdkIIUsbEthProtocolGuid,
>> + EFI_NATIVE_INTERFACE,
>> + &(UsbRndisDevice->UsbEth)
>> + );
>> + if (EFI_ERROR (Status)) {
>> + gBS->CloseProtocol (
>> + ControllerHandle,
>> + &gEfiUsbIoProtocolGuid,
>> + This->DriverBindingHandle,
>> + ControllerHandle
>> + );
>> +
>> + FreePool (UsbRndisDevice->Config);
>> + FreePool (UsbRndisDevice);
>> + return Status;
>> + }
>> +
>> + GetEndpoint (UsbRndisDevice->UsbIo, UsbRndisDevice);
>> +
>> + DEBUG ((DEBUG_INFO, "Rndis DeviceHandle %r\n",
>> UsbRndisDevice->UsbRndisHandle));
>> + DEBUG ((DEBUG_INFO, "CDC DeviceHandle %r\n",
>> UsbRndisDevice->UsbCdcDataHandle));
>> + return EFI_SUCCESS;
>> + }
>> +
>> + FreePool (UsbRndisDevice->Config);
>> + 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 = gBS->OpenProtocol (
>> + ControllerHandle,
>> + &gEfiUsbIoProtocolGuid,
>> + (VOID **)&UsbIo,
>> + This->DriverBindingHandle,
>> + ControllerHandle,
>> + EFI_OPEN_PROTOCOL_GET_PROTOCOL
>> + );
>> + if (EFI_ERROR (Status)) {
>> + return Status;
>> + }
>> +
>> + if (IsUsbRndis (UsbIo)) {
>> + Status = gBS->CloseProtocol (
>> + ControllerHandle,
>> + &gEfiUsbIoProtocolGuid,
>> + This->DriverBindingHandle,
>> + ControllerHandle
>> + );
>> + DEBUG ((DEBUG_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
>> bus 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;
>> + EDKII_USB_ETHERNET_PROTOCOL *UsbEthProtocol;
>> + USB_RNDIS_DEVICE *UsbRndisDevice;
>> +
>> + DEBUG ((DEBUG_INFO, "UsbRndisDriverStop ControllerHandle %lx\n",
>> ControllerHandle));
>> +
>> + Status = gBS->OpenProtocol (
>> + ControllerHandle,
>> + &gEdkIIUsbEthProtocolGuid,
>> + (VOID **)&UsbEthProtocol,
>> + This->DriverBindingHandle,
>> + ControllerHandle,
>> + EFI_OPEN_PROTOCOL_GET_PROTOCOL
>> + );
>> + if (EFI_ERROR (Status)) {
>> + Status = CheckandStopRndisDevice (This, ControllerHandle);
>> + return Status;
>> + }
>> +
>> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (UsbEthProtocol);
>> +
>> + Status = gBS->CloseProtocol (
>> + UsbRndisDevice->UsbCdcDataHandle,
>> + &gEfiUsbIoProtocolGuid,
>> + This->DriverBindingHandle,
>> + UsbRndisDevice->UsbCdcDataHandle
>> + );
>> + if (EFI_ERROR (Status)) {
>> + DEBUG ((DEBUG_ERROR, "%a:CloseProtocol status = %r\n",
>> __FUNCTION__, Status));
>> + }
>> +
>> + Status = gBS->UninstallProtocolInterface (
>> + ControllerHandle,
>> + &gEdkIIUsbEthProtocolGuid,
>> + UsbEthProtocol
>> + );
>> + if (EFI_ERROR (Status)) {
>> + return Status;
>> + }
>> +
>> + Status = gBS->CloseProtocol (
>> + ControllerHandle,
>> + &gEfiUsbIoProtocolGuid,
>> + This->DriverBindingHandle,
>> + ControllerHandle
>> + );
>> +
>> + FreePool (UsbRndisDevice->Config);
>> + FreePool (UsbRndisDevice);
>> +
>> + DEBUG ((DEBUG_INFO, "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
>> successfully.
>> +
>> +**/
>> +EFI_STATUS
>> +EFIAPI
>> +UsbRndisEntry (
>> + IN EFI_HANDLE ImageHandle,
>> + IN EFI_SYSTEM_TABLE *SystemTable
>> + )
>> +{
>> + gUsbRndisDriverBinding.DriverBindingHandle = ImageHandle;
>> + gUsbRndisDriverBinding.ImageHandle = ImageHandle;
>> +
>> + return gBS->InstallMultipleProtocolInterfaces (
>> + &gUsbRndisDriverBinding.DriverBindingHandle,
>> + &gEfiDriverBindingProtocolGuid,
>> + &gUsbRndisDriverBinding,
>> + &gEfiComponentName2ProtocolGuid,
>> + &gUsbRndisComponentName2,
>> + NULL
>> + );
>> +}
>> diff --git a/UsbNetworkPkg/UsbRndis/UsbRndisFunction.c
>> b/UsbNetworkPkg/UsbRndis/UsbRndisFunction.c
>> new file mode 100644
>> index 000000000000..e3fe737cdef1
>> --- /dev/null
>> +++ b/UsbNetworkPkg/UsbRndis/UsbRndisFunction.c
>> @@ -0,0 +1,1718 @@
>> +/** @file
>> + This file contains code for USB Ethernet descriptor
>> + and specific requests implement.
>> +
>> + Copyright (c) 2023, American Megatrends International LLC. All
>> rights reserved.<BR>
>> + SPDX-License-Identifier: BSD-2-Clause-Patent
>> +**/
>> +
>> +#include "UsbRndis.h"
>> +
>> +UINT16 gStopBulkInCnt = 0;
>> +UINT16 gBlockBulkInCnt = 0;
>> +
>> +/**
>> + Load All of device descriptor.
>> +
>> + @param[in] UsbIo A pointer to the
>> EFI_USB_IO_PROTOCOL 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
>> and Descriptor
>> + is not large enough to hold the
>> result of the request.
>> + @retval EFI_TIMEOUT A timeout occurred executing the
>> request.
>> + @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 = UsbIo->UsbGetConfigDescriptor (UsbIo, &Tmp);
>> + if (EFI_ERROR (Status)) {
>> + DEBUG ((DEBUG_ERROR, "%a:UsbGetConfigDescriptor status = %r\n",
>> __FUNCTION__, Status));
>> + return Status;
>> + }
>> +
>> + Status = gBS->AllocatePool (
>> + EfiBootServicesData,
>> + Tmp.TotalLength,
>> + (VOID **)ConfigDesc
>> + );
>> + if (EFI_ERROR (Status)) {
>> + DEBUG ((DEBUG_ERROR, "%a: AllocatePool status = %r\n",
>> __FUNCTION__, Status));
>> + return Status;
>> + }
>> +
>> + Status = 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
>> descriptors
>> + 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 == NULL) || (*Offset >= Desc->TotalLength)) {
>> + return FALSE;
>> + }
>> +
>> + if (((EFI_USB_CONFIG_DESCRIPTOR *)((char *)Desc+*Offset))->Length
>> == 0) {
>> + return FALSE;
>> + }
>> +
>> + *Offset += ((EFI_USB_CONFIG_DESCRIPTOR *)((char
>> *)Desc+*Offset))->Length;
>> + if ( *Offset >= 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;
>> + UINTN Offset;
>> + EFI_USB_INTERFACE_DESCRIPTOR *Interface;
>> +
>> + Status = EFI_NOT_FOUND;
>> +
>> + for (Offset = 0; NextDescriptor (Config, &Offset);) {
>> + Interface = (EFI_USB_INTERFACE_DESCRIPTOR *)((UINT8 *)Config +
>> Offset);
>> + if (Interface->DescriptorType == CS_INTERFACE) {
>> + if (((USB_HEADER_FUN_DESCRIPTOR
>> *)Interface)->DescriptorSubtype == 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 = 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 = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
>> + if (EFI_ERROR (Status)) {
>> + DEBUG ((DEBUG_ERROR, "%a:UsbGetInterfaceDescriptor status =
>> %r\n", __FUNCTION__, Status));
>> + return;
>> + }
>> +
>> + if (Interface.NumEndpoints == 0 ) {
>> + Status = UsbSetInterface (UsbIo, 1, 0, &Result);
>> + if (EFI_ERROR (Status)) {
>> + DEBUG ((DEBUG_ERROR, "%a:UsbSetInterface status = %r\n",
>> __FUNCTION__, Status));
>> + return;
>> + }
>> +
>> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
>> + if (EFI_ERROR (Status)) {
>> + DEBUG ((DEBUG_ERROR, "%a:UsbGetInterfaceDescriptor status =
>> %r\n", __FUNCTION__, Status));
>> + return;
>> + }
>> + }
>> +
>> + for (Index = 0; Index < Interface.NumEndpoints; Index++) {
>> + Status = UsbIo->UsbGetEndpointDescriptor (UsbIo, Index, &Endpoint);
>> + if (EFI_ERROR (Status)) {
>> + DEBUG ((DEBUG_ERROR, "%a:UsbGetEndpointDescriptor status =
>> %r\n", __FUNCTION__, Status));
>> + return;
>> + }
>> +
>> + switch ((Endpoint.Attributes & (BIT0 | BIT1))) {
>> + case USB_ENDPOINT_BULK:
>> + if (Endpoint.EndpointAddress & BIT7) {
>> + UsbRndisDevice->BulkInEndpoint = Endpoint.EndpointAddress;
>> + } else {
>> + UsbRndisDevice->BulkOutEndpoint = Endpoint.EndpointAddress;
>> + }
>> +
>> + break;
>> + case USB_ENDPOINT_INTERRUPT:
>> + UsbRndisDevice->InterrupEndpoint = 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 ((Data == NULL) || (Context == NULL)) {
>> + return EFI_INVALID_PARAMETER;
>> + }
>> +
>> + if (((EFI_USB_DEVICE_REQUEST *)Data)->Request == 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
>> EDKII_USB_ETHERNET_PROTOCOL instance.
>> + @param[in] IsNewTransfer If TRUE, a new transfer will be
>> submitted to USB controller. If
>> + FALSE, the interrupt transfer is
>> deleted 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
>> when 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 EDKII_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;
>> +
>> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This);
>> + DataLength = 0;
>> +
>> + if (IsNewTransfer == TRUE) {
>> + DataLength = sizeof (EFI_USB_DEVICE_REQUEST) + sizeof
>> (USB_CONNECT_SPEED_CHANGE);
>> + Status = UsbRndisDevice->UsbIo->UsbAsyncInterruptTransfer (
>> + UsbRndisDevice->UsbIo,
>> + UsbRndisDevice->InterrupEndpoint,
>> + IsNewTransfer,
>> + PollingInterval,
>> + DataLength,
>> + InterruptCallback,
>> + Requst
>> + );
>> +
>> + if (Status == EFI_INVALID_PARAMETER) {
>> + // Because of Stacked AsyncInterrupt request are not supported
>> + Status = UsbRndisDevice->UsbIo->UsbAsyncInterruptTransfer (
>> + UsbRndisDevice->UsbIo,
>> + UsbRndisDevice->InterrupEndpoint,
>> + 0,
>> + 0,
>> + 0,
>> + NULL,
>> + NULL
>> + );
>> + }
>> + } else {
>> + Status = UsbRndisDevice->UsbIo->UsbAsyncInterruptTransfer (
>> + UsbRndisDevice->UsbIo,
>> + UsbRndisDevice->InterrupEndpoint,
>> + IsNewTransfer,
>> + 0,
>> + 0,
>> + NULL,
>> + NULL
>> + );
>> + }
>> +
>> + return Status;
>> +}
>> +
>> +/**
>> + This function is used to read USB interrupt transfer before the
>> response RNDIS message.
>> +
>> + @param[in] This A pointer to the USB_RNDIS_DEVICE
>> instance.
>> +
>> + @retval EFI_SUCCESS The USB interrupt transfer has been
>> successfully executed.
>> + @retval EFI_DEVICE_ERROR The USB interrupt transfer failed.
>> +
>> +**/
>> +EFI_STATUS
>> +EFIAPI
>> +ReadRndisResponseInterrupt (
>> + IN USB_RNDIS_DEVICE *UsbRndisDevice
>> + )
>> +{
>> + EFI_STATUS Status;
>> + UINT32 Data[2];
>> + UINT32 UsbStatus;
>> + UINTN DataLength;
>> +
>> + DataLength = 8;
>> +
>> + ZeroMem (Data, sizeof (Data));
>> +
>> + Status = UsbRndisDevice->UsbIo->UsbSyncInterruptTransfer (
>> + UsbRndisDevice->UsbIo,
>> + UsbRndisDevice->InterrupEndpoint,
>> + &Data,
>> + &DataLength,
>> + 0x20,
>> + &UsbStatus
>> + );
>> +
>> + return Status;
>> +}
>> +
>> +/**
>> + Retrieves the USB Ethernet Mac Address.
>> +
>> + @param[in] This A pointer to the
>> EDKII_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
>> was retrieved successfully.
>> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL.
>> + @retval EFI_NOT_FOUND The USB Header Functional descriptor
>> was not found.
>> +
>> +**/
>> +EFI_STATUS
>> +EFIAPI
>> +GetUsbEthMacAddress (
>> + IN EDKII_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;
>> +
>> + REMOTE_NDIS_QUERY_MAC_MSG RndisQueryMsg;
>> + REMOTE_NDIS_QUERY_MAC_CMPLT RndisQueryMsgCmplt;
>> +
>> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This);
>> +
>> + ZeroMem (&RndisQueryMsg, sizeof (REMOTE_NDIS_QUERY_MAC_MSG));
>> + ZeroMem (&RndisQueryMsgCmplt, sizeof (REMOTE_NDIS_QUERY_MAC_CMPLT));
>> +
>> + RndisQueryMsg.QueryMsg.MessageType = RNDIS_QUERY_MSG;
>> + RndisQueryMsg.QueryMsg.MessageLength = sizeof
>> (REMOTE_NDIS_QUERY_MAC_MSG);
>> + RndisQueryMsg.QueryMsg.RequestID = UsbRndisDevice->RequestId;
>> + RndisQueryMsg.QueryMsg.Oid = OID_802_3_CURRENT_ADDRESS;
>> +
>> + RndisQueryMsgCmplt.QueryCmplt.MessageType = RNDIS_QUERY_CMPLT;
>> + RndisQueryMsgCmplt.QueryCmplt.MessageLength = sizeof
>> (REMOTE_NDIS_QUERY_MAC_CMPLT);
>> +
>> + Status = RndisControlMsg (
>> + UsbRndisDevice,
>> + (REMOTE_NDIS_MSG_HEADER *)&RndisQueryMsg,
>> + (REMOTE_NDIS_MSG_HEADER *)&RndisQueryMsgCmplt
>> + );
>> + if (!EFI_ERROR (Status)) {
>> + DEBUG ((DEBUG_INFO, "Success to get Mac address from RNDIS
>> message.\n"));
>> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {
>> + MacAddress->Addr[Index] = RndisQueryMsgCmplt.Addr[Index];
>> + }
>> +
>> + UsbRndisDevice->RequestId++;
>> + return Status;
>> + }
>> +
>> + // If it is not support the OID_802_3_CURRENT_ADDRESS.
>> + // To check USB Ethernet functional Descriptor
>> + Status = This->UsbEthFunDescriptor (This, &UsbEthDescriptor);
>> + if (EFI_ERROR (Status)) {
>> + DEBUG ((DEBUG_ERROR, "%a:UsbEthFunDescriptor status = %r\n",
>> __FUNCTION__, Status));
>> + return Status;
>> + }
>> +
>> + Status = UsbRndisDevice->UsbIo->UsbGetStringDescriptor (
>> + UsbRndisDevice->UsbIo,
>> + 0x409, // English-US Language ID
>> + UsbEthDescriptor.MacAddress,
>> + &Data
>> + );
>> + if (EFI_ERROR (Status)) {
>> + DEBUG ((DEBUG_ERROR, "%a:UsbGetStringDescriptor status = %r\n",
>> __FUNCTION__, Status));
>> + return Status;
>> + }
>> +
>> + DataPtr = Data;
>> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) {
>> + CopyMem (TmpStr, DataPtr, sizeof (CHAR16));
>> + DataPtr++;
>> + Hi = (UINT8)StrHexToUintn (TmpStr);
>> + CopyMem (TmpStr, DataPtr, sizeof (CHAR16));
>> + DataPtr++;
>> + Low = (UINT8)StrHexToUintn (TmpStr);
>> + MacAddress->Addr[Index] = (Hi << 4) | Low;
>> + }
>> +
>> + return Status;
>> +}
>> +
>> +/**
>> + Retrieves the USB Ethernet Bulk transfer data size.
>> +
>> + @param[in] This A pointer to the
>> EDKII_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 EDKII_USB_ETHERNET_PROTOCOL *This,
>> + OUT UINTN *BulkSize
>> + )
>> +{
>> + EFI_STATUS Status;
>> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor;
>> + USB_RNDIS_DEVICE *UsbRndisDevice;
>> +
>> + REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_MSG RndisQueryMsg;
>> + REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_CMPLT RndisQueryMsgCmplt;
>> +
>> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This);
>> +
>> + ZeroMem (&RndisQueryMsg, sizeof
>> (REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_MSG));
>> + ZeroMem (&RndisQueryMsgCmplt, sizeof
>> (REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_CMPLT));
>> +
>> + RndisQueryMsg.QueryMsg.MessageType = RNDIS_QUERY_MSG;
>> + RndisQueryMsg.QueryMsg.MessageLength = sizeof
>> (REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_MSG);
>> + RndisQueryMsg.QueryMsg.RequestID = UsbRndisDevice->RequestId;
>> + RndisQueryMsg.QueryMsg.Oid = OID_GEN_MAXIMUM_TOTAL_SIZE;
>> +
>> + RndisQueryMsgCmplt.QueryCmplt.MessageType = RNDIS_QUERY_CMPLT;
>> + RndisQueryMsgCmplt.QueryCmplt.MessageLength = sizeof
>> (REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_CMPLT);
>> +
>> + Status = RndisControlMsg (
>> + UsbRndisDevice,
>> + (REMOTE_NDIS_MSG_HEADER *)&RndisQueryMsg,
>> + (REMOTE_NDIS_MSG_HEADER *)&RndisQueryMsgCmplt
>> + );
>> + if (!EFI_ERROR (Status)) {
>> + DEBUG ((DEBUG_INFO, "Success to get Max Total size : %X \n",
>> RndisQueryMsgCmplt.MaxTotalSize));
>> + *BulkSize = RndisQueryMsgCmplt.MaxTotalSize;
>> + UsbRndisDevice->RequestId++;
>> + return Status;
>> + }
>> +
>> + Status = This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor);
>> + if (EFI_ERROR (Status)) {
>> + return Status;
>> + }
>> +
>> + *BulkSize = (UINTN)UsbEthFunDescriptor.MaxSegmentSize;
>> + return Status;
>> +}
>> +
>> +/**
>> + Retrieves the USB Header functional Descriptor.
>> +
>> + @param[in] This A pointer to the
>> EDKII_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
>> was retrieved successfully.
>> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL.
>> + @retval EFI_NOT_FOUND The USB Header Functional descriptor
>> was not found.
>> +
>> +**/
>> +EFI_STATUS
>> +EFIAPI
>> +GetUsbHeaderFunDescriptor (
>> + IN EDKII_USB_ETHERNET_PROTOCOL *This,
>> + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor
>> + )
>> +{
>> + EFI_STATUS Status;
>> + USB_RNDIS_DEVICE *UsbRndisDevice;
>> +
>> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This);
>> +
>> + if (UsbHeaderFunDescriptor == NULL) {
>> + return EFI_INVALID_PARAMETER;
>> + }
>> +
>> + Status = GetFunctionalDescriptor (
>> + UsbRndisDevice->Config,
>> + HEADER_FUN_DESCRIPTOR,
>> + UsbHeaderFunDescriptor
>> + );
>> + return Status;
>> +}
>> +
>> +/**
>> + Retrieves the USB Union functional Descriptor.
>> +
>> + @param[in] This A pointer to the
>> EDKII_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 EDKII_USB_ETHERNET_PROTOCOL *This,
>> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor
>> + )
>> +{
>> + EFI_STATUS Status;
>> + USB_RNDIS_DEVICE *UsbRndisDevice;
>> +
>> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This);
>> +
>> + if (UsbUnionFunDescriptor == NULL) {
>> + return EFI_INVALID_PARAMETER;
>> + }
>> +
>> + Status = GetFunctionalDescriptor (
>> + UsbRndisDevice->Config,
>> + UNION_FUN_DESCRIPTOR,
>> + UsbUnionFunDescriptor
>> + );
>> + return Status;
>> +}
>> +
>> +/**
>> + Retrieves the USB Ethernet functional Descriptor.
>> +
>> + This function get the Mac Address, Ethernet statistics, maximum
>> segment size,
>> + number of multicast filters, and number of pattern filters from
>> Ethernet
>> + functional Descriptor.
>> +
>> + @param[in] This A pointer to the
>> EDKII_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 EDKII_USB_ETHERNET_PROTOCOL *This,
>> + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor
>> + )
>> +{
>> + EFI_STATUS Status;
>> + USB_RNDIS_DEVICE *UsbRndisDevice;
>> +
>> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This);
>> +
>> + if (UsbEthFunDescriptor == NULL) {
>> + return EFI_INVALID_PARAMETER;
>> + }
>> +
>> + Status = 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
>> EDKII_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 EDKII_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 = USB_RNDIS_DEVICE_FROM_THIS (This);
>> +
>> + Status = This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor);
>> + if (EFI_ERROR (Status)) {
>> + return Status;
>> + }
>> +
>> + if ((UsbEthFunDescriptor.NumberMcFilters << 1) == 0) {
>> + return EFI_UNSUPPORTED;
>> + }
>> +
>> + Request.RequestType = USB_ETHERNET_SET_REQ_TYPE;
>> + Request.Request = SET_ETH_MULTICAST_FILTERS_REQ;
>> + Request.Value = Value;
>> + Request.Index = UsbRndisDevice->NumOfInterface;
>> + Request.Length = 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
>> EDKII_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
>> 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 EDKII_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 = USB_RNDIS_DEVICE_FROM_THIS (This);
>> +
>> + Request.RequestType = USB_ETHERNET_SET_REQ_TYPE;
>> + Request.Request = SET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ;
>> + Request.Value = Value;
>> + Request.Index = UsbRndisDevice->NumOfInterface;
>> + Request.Length = 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
>> EDKII_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 EDKII_USB_ETHERNET_PROTOCOL *This,
>> + IN UINT16 Value,
>> + OUT BOOLEAN *PatternActive
>> + )
>> +{
>> + EFI_USB_DEVICE_REQUEST Request;
>> + UINT32 TransStatus;
>> + USB_RNDIS_DEVICE *UsbRndisDevice;
>> +
>> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This);
>> +
>> + Request.RequestType = USB_ETHERNET_GET_REQ_TYPE;
>> + Request.Request = GET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ;
>> + Request.Value = Value;
>> + Request.Index = UsbRndisDevice->NumOfInterface;
>> + Request.Length = 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[] = {
>> + { 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 = sizeof (Table)/sizeof (Table[0]);
>> +
>> + for (Index = 0; (Table[Index].Src != 0) && (Index < Count);
>> Index++) {
>> + if (Table[Index].Src & Value) {
>> + *CdcFilter |= 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;
>> + UINT8 Index1;
>> + UINT8 Index2;
>> + UINT64 CpbAddr;
>> + UINT32 CpbSize;
>> + UINT16 SetFilter;
>> + PXE_CPB_RECEIVE_FILTERS *Cpb;
>> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor;
>> +
>> + Count = 0;
>> + CpbAddr = Cdb->CPBaddr;
>> + CpbSize = Cdb->CPBsize;
>> + SetFilter = (UINT16)(Cdb->OpFlags & 0x1F);
>> + Cpb = (PXE_CPB_RECEIVE_FILTERS *)(UINTN)CpbAddr;
>> +
>> + // The Cpb could be NULL.(ref:PXE_CPBADDR_NOT_USED)
>> + Nic->RxFilter = (UINT8)SetFilter;
>> +
>> + if (((SetFilter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST)
>> != 0) || (Cpb != NULL)) {
>> + if (Cpb != NULL) {
>> + Nic->McastCount = (UINT8)(CpbSize / PXE_MAC_LENGTH);
>> + CopyMem (&Nic->McastList, Cpb, Nic->McastCount);
>> + } else {
>> + Nic->McastCount = 0;
>> + }
>> +
>> + Nic->UsbEth->UsbEthFunDescriptor (Nic->UsbEth,
>> &UsbEthFunDescriptor);
>> + if ((UsbEthFunDescriptor.NumberMcFilters << 1) == 0) {
>> + Nic->RxFilter |= PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST;
>> + DEBUG ((DEBUG_INFO, "SetUsbEthPacketFilter Nic %lx Nic->UsbEth
>> %lx ", Nic, Nic->UsbEth));
>> + Nic->UsbEth->SetUsbEthPacketFilter (Nic->UsbEth, Nic->RxFilter);
>> + } else {
>> + Status = gBS->AllocatePool (EfiBootServicesData,
>> Nic->McastCount * 6, (VOID **)&McastList);
>> + if (EFI_ERROR (Status)) {
>> + return PXE_STATCODE_INVALID_PARAMETER;
>> + }
>> +
>> + if (Cpb != NULL) {
>> + for (Index1 = 0; Index1 < Nic->McastCount; Index1++) {
>> + for (Index2 = 0; Index2 < 6; Index2++) {
>> + McastList[Count++] = Cpb->MCastList[Index1][Index2];
>> + }
>> + }
>> + }
>> +
>> + Nic->RxFilter |= PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST;
>> + if (Cpb != NULL) {
>> + Nic->UsbEth->SetUsbEthMcastFilter (Nic->UsbEth,
>> Nic->McastCount, McastList);
>> + }
>> +
>> + Nic->UsbEth->SetUsbEthPacketFilter (Nic->UsbEth, Nic->RxFilter);
>> + FreePool (McastList);
>> + }
>> + }
>> +
>> + return EFI_SUCCESS;
>> +}
>> +
>> +/**
>> + This request is used to configure device Ethernet packet filter
>> settings.
>> +
>> + @param[in] This A pointer to the
>> EDKII_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
>> 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
>> +SetUsbRndisPacketFilter (
>> + IN EDKII_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
>> EDKII_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
>> 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
>> +GetRndisStatistic (
>> + IN EDKII_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 = RndisUndiReset (Cdb, Nic);
>> + if (EFI_ERROR (Status)) {
>> + RndisUndiReset (Cdb, Nic);
>> + }
>> +
>> + Status = 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
>> + )
>> +{
>> + EDKII_USB_ETHERNET_PROTOCOL *UsbEthDevice;
>> + USB_RNDIS_DEVICE *UsbRndisDevice;
>> + PXE_DB_GET_INIT_INFO *Db;
>> +
>> + DEBUG ((DEBUG_INFO, "RndisUndiGetInitInfo\n"));
>> +
>> + UsbEthDevice = Nic->UsbEth;
>> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (UsbEthDevice);
>> +
>> + Db = (PXE_DB_GET_INIT_INFO *)(UINTN)Cdb->DBaddr;
>> +
>> + Db->FrameDataLen = 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 = 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
>> + )
>> +{
>> + EDKII_USB_ETHERNET_PROTOCOL *UsbEthDriver;
>> + USB_RNDIS_DEVICE *UsbRndisDevice;
>> + REMOTE_NDIS_INITIALIZE_MSG RndisInitMsg;
>> + REMOTE_NDIS_INITIALIZE_CMPLT RndisInitMsgCmplt;
>> + EFI_STATUS Status;
>> +
>> + DEBUG ((DEBUG_INFO, "RndisUndiInitialize\n"));
>> +
>> + UsbEthDriver = Nic->UsbEth;
>> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (UsbEthDriver);
>> +
>> + ZeroMem (&RndisInitMsg, sizeof (REMOTE_NDIS_INITIALIZE_MSG));
>> + ZeroMem (&RndisInitMsgCmplt, sizeof (REMOTE_NDIS_INITIALIZE_CMPLT));
>> +
>> + RndisInitMsg.MessageType = RNDIS_INITIALIZE_MSG;
>> + RndisInitMsg.MessageLength = sizeof (REMOTE_NDIS_INITIALIZE_MSG);
>> + RndisInitMsg.RequestID = UsbRndisDevice->RequestId;
>> + RndisInitMsg.MajorVersion = RNDIS_MAJOR_VERSION;
>> + RndisInitMsg.MinorVersion = RNDIS_MINOR_VERSION;
>> + RndisInitMsg.MaxTransferSize = RNDIS_MAX_TRANSFER_SIZE;
>> +
>> + RndisInitMsgCmplt.MessageType = RNDIS_INITIALIZE_CMPLT;
>> + RndisInitMsgCmplt.MessageLength = sizeof
>> (REMOTE_NDIS_INITIALIZE_CMPLT);
>> +
>> + Status = 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 = RndisInitMsgCmplt.Medium;
>> + UsbRndisDevice->MaxPacketsPerTransfer =
>> RndisInitMsgCmplt.MaxPacketsPerTransfer;
>> + UsbRndisDevice->MaxTransferSize =
>> RndisInitMsgCmplt.MaxTransferSize;
>> + UsbRndisDevice->PacketAlignmentFactor =
>> 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
>> error.
>> +
>> +**/
>> +EFI_STATUS
>> +EFIAPI
>> +RndisUndiReset (
>> + IN PXE_CDB *Cdb,
>> + IN NIC_DATA *Nic
>> + )
>> +{
>> + EDKII_USB_ETHERNET_PROTOCOL *UsbEthDriver;
>> + USB_RNDIS_DEVICE *UsbRndisDevice;
>> + REMOTE_NDIS_RESET_MSG RndisResetMsg;
>> + REMOTE_NDIS_RESET_CMPLT RndisResetCmplt;
>> + EFI_STATUS Status;
>> +
>> + DEBUG ((DEBUG_INFO, "RndisUndiReset\n"));
>> +
>> + UsbEthDriver = Nic->UsbEth;
>> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (UsbEthDriver);
>> +
>> + ZeroMem (&RndisResetMsg, sizeof (REMOTE_NDIS_RESET_MSG));
>> + ZeroMem (&RndisResetCmplt, sizeof (REMOTE_NDIS_RESET_CMPLT));
>> +
>> + RndisResetMsg.MessageType = RNDIS_RESET_MSG;
>> + RndisResetMsg.MessageLength = sizeof (REMOTE_NDIS_RESET_MSG);
>> +
>> + RndisResetCmplt.MessageType = RNDIS_RESET_CMPLT;
>> + RndisResetCmplt.MessageLength = sizeof (REMOTE_NDIS_RESET_CMPLT);
>> +
>> + Status = RndisControlMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_HEADER
>> *)&RndisResetMsg, (REMOTE_NDIS_MSG_HEADER *)&RndisResetCmplt);
>> +
>> + UsbRndisDevice->RequestId = 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
>> + )
>> +{
>> + EDKII_USB_ETHERNET_PROTOCOL *UsbEthDriver;
>> + USB_RNDIS_DEVICE *UsbRndisDevice;
>> + REMOTE_NDIS_HALT_MSG RndisHltMsg;
>> + EFI_STATUS Status;
>> +
>> + DEBUG ((DEBUG_INFO, "RndisUndiShutdown\n"));
>> +
>> + UsbEthDriver = Nic->UsbEth;
>> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (UsbEthDriver);
>> +
>> + ZeroMem (&RndisHltMsg, sizeof (REMOTE_NDIS_HALT_MSG));
>> +
>> + RndisHltMsg.MessageType = RNDIS_HLT_MSG;
>> + RndisHltMsg.MessageLength = sizeof (REMOTE_NDIS_HALT_MSG);
>> +
>> + Status = RndisControlMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_HEADER
>> *)&RndisHltMsg, NULL);
>> +
>> + if (Status == EFI_DEVICE_ERROR) {
>> + Status = EFI_SUCCESS;
>> + }
>> +
>> + UsbRndisDevice->RequestId = 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 &= ~(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
>> EDKII_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 EDKII_USB_ETHERNET_PROTOCOL *This,
>> + IN VOID *BulkOutData,
>> + IN OUT UINTN *DataLength
>> + )
>> +{
>> + EFI_STATUS Status;
>> + USB_RNDIS_DEVICE *UsbRndisDevice;
>> + REMOTE_NDIS_PACKET_MSG *RndisPacketMsg;
>> + UINTN TransferLength;
>> +
>> + DEBUG ((DEBUG_INFO, "RndisUndiTransmit DataLength : %x\n",
>> *DataLength));
>> +
>> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This);
>> +
>> + RndisPacketMsg = AllocateZeroPool (sizeof (REMOTE_NDIS_PACKET_MSG)
>> + *DataLength);
>> + if (RndisPacketMsg == NULL) {
>> + return EFI_OUT_OF_RESOURCES;
>> + }
>> +
>> + RndisPacketMsg->MessageType = RNDIS_PACKET_MSG;
>> + RndisPacketMsg->MessageLength = sizeof (REMOTE_NDIS_PACKET_MSG) +
>> (UINT32)*DataLength;
>> + RndisPacketMsg->DataOffset = sizeof (REMOTE_NDIS_PACKET_MSG) - 8;
>> + RndisPacketMsg->DataLength = (UINT32)*DataLength;
>> +
>> + CopyMem (
>> + ((UINT8 *)RndisPacketMsg) + sizeof (REMOTE_NDIS_PACKET_MSG),
>> + BulkOutData,
>> + *DataLength
>> + );
>> +
>> + TransferLength = RndisPacketMsg->MessageLength;
>> +
>> + Status = RndisTransmitDataMsg (
>> + UsbRndisDevice,
>> + (REMOTE_NDIS_MSG_HEADER *)RndisPacketMsg,
>> + &TransferLength
>> + );
>> +
>> + DEBUG ((DEBUG_INFO, "\nRndisUndiTransmit TransferLength %lx\n",
>> TransferLength));
>> +
>> + 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
>> EDKII_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 EDKII_USB_ETHERNET_PROTOCOL *This,
>> + IN OUT VOID *BulkInData,
>> + IN OUT UINTN *DataLength
>> + )
>> +{
>> + EFI_STATUS Status;
>> + USB_RNDIS_DEVICE *UsbRndisDevice;
>> + REMOTE_NDIS_PACKET_MSG *RndisPacketMsg;
>> + UINTN TransferLength;
>> + VOID *Buffer;
>> + PACKET_LIST *HeadPacket;
>> + PACKET_LIST *PacketList;
>> +
>> + // Check if there is any outstanding packet to receive
>> + // The buffer allocated has a linked List followed by the packet.
>> +
>> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This);
>> + Buffer = NULL;
>> + HeadPacket = NULL;
>> +
>> + while (1) {
>> + Buffer = AllocateZeroPool (sizeof (PACKET_LIST) + sizeof
>> (REMOTE_NDIS_PACKET_MSG) + UsbRndisDevice->MaxTransferSize);
>> + if (Buffer == NULL) {
>> + return EFI_OUT_OF_RESOURCES;
>> + }
>> +
>> + RndisPacketMsg = (REMOTE_NDIS_PACKET_MSG
>> *)(sizeof (PACKET_LIST) + (UINT8 *)Buffer);
>> + PacketList = (PACKET_LIST *)Buffer;
>> + PacketList->PacketStartBuffer = (UINT8 *)Buffer + sizeof
>> (PACKET_LIST);
>> + // Save the original address for freeing it up
>> + PacketList->OrgBuffer = (UINT8 *)Buffer;
>> + TransferLength = UsbRndisDevice->MaxTransferSize;
>> +
>> + Status = RndisReceiveDataMsg (
>> + UsbRndisDevice,
>> + (REMOTE_NDIS_MSG_HEADER *)RndisPacketMsg,
>> + &TransferLength
>> + );
>> +
>> + if (EFI_ERROR (Status) || (TransferLength == 0)) {
>> + FreePool (Buffer);
>> + break;
>> + }
>> +
>> + // Collect all the RNDIS packet in Linked list.
>> + if ((RndisPacketMsg->MessageType == RNDIS_PACKET_MSG) &&
>> + (RndisPacketMsg->DataOffset == sizeof
>> (REMOTE_NDIS_PACKET_MSG) - RNDIS_RESERVED_BYTE_LENGTH) &&
>> + (TransferLength >= RndisPacketMsg->MessageLength))
>> + {
>> + // Insert Packet
>> + PacketList->RemainingLength = TransferLength;
>> + InsertTailList (&UsbRndisDevice->ReceivePacketList, Buffer);
>> + } else {
>> + FreePool (Buffer);
>> + }
>> + }
>> +
>> + while (!IsListEmpty (&UsbRndisDevice->ReceivePacketList)) {
>> + HeadPacket = (PACKET_LIST *)GetFirstNode
>> (&UsbRndisDevice->ReceivePacketList);
>> +
>> + RndisPacketMsg = (REMOTE_NDIS_PACKET_MSG *)(UINT8
>> *)HeadPacket->PacketStartBuffer;
>> +
>> + PrintRndisMsg ((REMOTE_NDIS_MSG_HEADER *)RndisPacketMsg);
>> +
>> + // Check whether the packet is valid RNDIS packet.
>> + if ((HeadPacket->RemainingLength > sizeof
>> (REMOTE_NDIS_PACKET_MSG)) && (RndisPacketMsg->MessageType ==
>> RNDIS_PACKET_MSG) &&
>> + (RndisPacketMsg->DataOffset == (sizeof
>> (REMOTE_NDIS_PACKET_MSG) - RNDIS_RESERVED_BYTE_LENGTH)) &&
>> + (HeadPacket->RemainingLength >= RndisPacketMsg->MessageLength))
>> + {
>> + if (*DataLength >= RndisPacketMsg->DataLength) {
>> + CopyMem (
>> + BulkInData,
>> + (UINT8 *)RndisPacketMsg + (RndisPacketMsg->DataOffset +
>> RNDIS_RESERVED_BYTE_LENGTH),
>> + RndisPacketMsg->DataLength
>> + );
>> +
>> + *DataLength = RndisPacketMsg->DataLength;
>> +
>> + HeadPacket->RemainingLength = HeadPacket->RemainingLength
>> - RndisPacketMsg->MessageLength;
>> + HeadPacket->PacketStartBuffer = (UINT8 *)RndisPacketMsg +
>> RndisPacketMsg->MessageLength;
>> +
>> + return EFI_SUCCESS;
>> + } else {
>> + *DataLength = RndisPacketMsg->DataLength;
>> + return EFI_BUFFER_TOO_SMALL;
>> + }
>> + }
>> +
>> + RemoveEntryList (&HeadPacket->PacketList);
>> + FreePool ((PACKET_LIST *)HeadPacket->OrgBuffer);
>> + }
>> +
>> + return EFI_NOT_FOUND;
>> +}
>> +
>> +/**
>> + This is a dummy function which just returns. Unimplemented
>> EDKII_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 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 = UsbRndisDevice->UsbIo;
>> + EFI_USB_DEVICE_REQUEST DevReq;
>> + UINT32 UsbStatus;
>> + EFI_STATUS Status;
>> + UINT32 SaveResponseType;
>> + UINT32 SaveResponseLength;
>> + UINT32 Index;
>> + REMOTE_NDIS_INITIALIZE_CMPLT *RndisInitCmplt;
>> +
>> + SaveResponseType = 0;
>> + SaveResponseLength = 0;
>> + RndisInitCmplt = (REMOTE_NDIS_INITIALIZE_CMPLT
>> *)RndisMsgResponse;
>> +
>> + if (RndisMsgResponse) {
>> + SaveResponseType = RndisMsgResponse->MessageType;
>> + SaveResponseLength = RndisMsgResponse->MessageLength;
>> + }
>> +
>> + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
>> +
>> + DevReq.RequestType = USB_REQ_TYPE_CLASS | USB_TARGET_INTERFACE;
>> + DevReq.Request = SEND_ENCAPSULATED_COMMAND;
>> + DevReq.Value = 0;
>> + DevReq.Index = 0;
>> + DevReq.Length = (UINT16)RndisMsg->MessageLength;
>> +
>> + PrintRndisMsg (RndisMsg);
>> +
>> + Status = 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 == NULL)) {
>> + DEBUG ((DEBUG_INFO, "RndisControlMsg: UsbStatus : %x Status :
>> %r\n", UsbStatus, Status));
>> + return Status;
>> + }
>> +
>> + for (Index = 0; Index < (RNDIS_CONTROL_TIMEOUT/100); Index++) {
>> + ReadRndisResponseInterrupt (UsbRndisDevice);
>> + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST));
>> +
>> + DevReq.RequestType = USB_ENDPOINT_DIR_IN | USB_REQ_TYPE_CLASS |
>> USB_TARGET_INTERFACE;
>> + DevReq.Request = GET_ENCAPSULATED_RESPONSE;
>> + DevReq.Value = 0;
>> + DevReq.Index = 0;
>> + DevReq.Length = (UINT16)RndisMsgResponse->MessageLength;
>> +
>> + Status = UsbIo->UsbControlTransfer (
>> + UsbIo,
>> + &DevReq,
>> + EfiUsbDataIn,
>> + USB_ETHERNET_TRANSFER_TIMEOUT,
>> + RndisMsgResponse,
>> + RndisMsgResponse->MessageLength,
>> + &UsbStatus
>> + );
>> +
>> + DEBUG ((DEBUG_INFO, "RndisControlMsg Response: UsbStatus : %x
>> Status : %r \n", UsbStatus, Status));
>> +
>> + PrintRndisMsg (RndisMsgResponse);
>> +
>> + if (!EFI_ERROR (Status)) {
>> + if ((RndisInitCmplt->RequestID !=
>> ((REMOTE_NDIS_INITIALIZE_CMPLT *)RndisMsg)->RequestID) ||
>> (RndisInitCmplt->MessageType != SaveResponseType)) {
>> + DEBUG ((DEBUG_INFO, "Retry the response\n"));
>> +
>> + RndisMsgResponse->MessageType = SaveResponseType;
>> + RndisMsgResponse->MessageLength = SaveResponseLength;
>> + continue;
>> + }
>> + }
>> +
>> + return Status;
>> + }
>> +
>> + DEBUG ((DEBUG_INFO, "RndisControlMsg: TimeOut\n"));
>> +
>> + return EFI_TIMEOUT;
>> +}
>> +
>> +/**
>> + This function send the RNDIS command through the device's Data
>> endpoint
>> +
>> + @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 == 0) {
>> + GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice);
>> + }
>> +
>> + PrintRndisMsg (RndisMsg);
>> +
>> + Status = UsbRndisDevice->UsbIoCdcData->UsbBulkTransfer (
>> + UsbRndisDevice->UsbIoCdcData,
>> + UsbRndisDevice->BulkOutEndpoint,
>> + RndisMsg,
>> + TransferLength,
>> + USB_TX_ETHERNET_BULK_TIMEOUT,
>> + &UsbStatus
>> + );
>> +
>> + if (Status == EFI_SUCCESS) {
>> + gStopBulkInCnt = 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
>> endpoint
>> +
>> + @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;
>> +
>> + UsbStatus = 0;
>> +
>> + if (UsbRndisDevice->BulkInEndpoint == 0) {
>> + GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice);
>> + }
>> +
>> + // Use gStopBulkInCnt to stop BulkIn command
>> + if (gStopBulkInCnt || LAN_BULKIN_CMD_CONTROL) {
>> + Status = UsbRndisDevice->UsbIoCdcData->UsbBulkTransfer (
>> + UsbRndisDevice->UsbIoCdcData,
>> + UsbRndisDevice->BulkInEndpoint,
>> + RndisMsg,
>> + TransferLength,
>> + USB_RX_ETHERNET_BULK_TIMEOUT,
>> + &UsbStatus
>> + );
>> +
>> + if (!EFI_ERROR (Status)) {
>> + gStopBulkInCnt = MINIMUM_STOPBULKIN_CNT;
>> + } else {
>> + gStopBulkInCnt--;
>> + }
>> + } else {
>> + Status = EFI_TIMEOUT;
>> + *TransferLength = 0;
>> + gBlockBulkInCnt++;
>> + }
>> +
>> + if (gBlockBulkInCnt > BULKIN_CMD_POLLING_CNT) {
>> + gStopBulkInCnt = MINIMUM_STOPBULKIN_CNT;
>> + gBlockBulkInCnt = 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;
>> + REMOTE_NDIS_QUERY_CMPLT *RndisQueryCmplt;
>> +
>> + Length = 0;
>> +
>> + switch (RndisMsg->MessageType) {
>> + case RNDIS_PACKET_MSG:
>> + DEBUG ((DEBUG_INFO, "RNDIS_PACKET_MSG:\n"));
>> + Length = sizeof (REMOTE_NDIS_PACKET_MSG) + 0x14;
>> + break;
>> + case RNDIS_INITIALIZE_MSG:
>> + DEBUG ((DEBUG_INFO, "RNDIS_INITIALIZE_MSG:\n"));
>> + Length = sizeof (REMOTE_NDIS_INITIALIZE_MSG);
>> + break;
>> + case RNDIS_INITIALIZE_CMPLT:
>> + DEBUG ((DEBUG_INFO, "RNDIS_INITIALIZE_CMPLT:\n"));
>> + Length = sizeof (REMOTE_NDIS_INITIALIZE_CMPLT);
>> + break;
>> + case RNDIS_HLT_MSG:
>> + DEBUG ((DEBUG_INFO, "RNDIS_HLT_MSG:\n"));
>> + Length = sizeof (REMOTE_NDIS_HALT_MSG);
>> + break;
>> + case RNDIS_QUERY_MSG:
>> + DEBUG ((DEBUG_INFO, "RNDIS_QUERY_MSG:\n"));
>> + Length = sizeof (REMOTE_NDIS_QUERY_MSG);
>> + break;
>> + case RNDIS_QUERY_CMPLT:
>> + DEBUG ((DEBUG_INFO, "RNDIS_QUERY_CMPLT:\n"));
>> + RndisQueryCmplt = (REMOTE_NDIS_QUERY_CMPLT *)RndisMsg;
>> + Length = sizeof (REMOTE_NDIS_QUERY_CMPLT) +
>> RndisQueryCmplt->InformationBufferLength;
>> + break;
>> + case RNDIS_SET_MSG:
>> + DEBUG ((DEBUG_INFO, "RNDIS_SET_MSG:\n"));
>> + Length = sizeof (REMOTE_NDIS_SET_MSG);
>> + break;
>> + case RNDIS_SET_CMPLT:
>> + DEBUG ((DEBUG_INFO, "RNDIS_SET_CMPLT:\n"));
>> + Length = sizeof (REMOTE_NDIS_SET_CMPLT);
>> + break;
>> + case RNDIS_RESET_MSG:
>> + DEBUG ((DEBUG_INFO, "RNDIS_RESET_MSG:\n"));
>> + Length = sizeof (REMOTE_NDIS_RESET_MSG);
>> + break;
>> + case RNDIS_RESET_CMPLT:
>> + DEBUG ((DEBUG_INFO, "RNDIS_RESET_CMPLT:\n"));
>> + Length = sizeof (REMOTE_NDIS_RESET_CMPLT);
>> + break;
>> + case RNDIS_INDICATE_STATUS_MSG:
>> + DEBUG ((DEBUG_INFO, "RNDIS_INDICATE_STATUS_MSG:\n"));
>> + Length = sizeof (REMOTE_NDIS_INDICATE_STATUS_MSG);
>> + break;
>> + case RNDIS_KEEPALIVE_MSG:
>> + DEBUG ((DEBUG_INFO, "RNDIS_KEEPALIVE_MSG:\n"));
>> + Length = sizeof (REMOTE_NDIS_KEEPALIVE_MSG);
>> + break;
>> + case RNDIS_KEEPALIVE_CMPLT:
>> + DEBUG ((DEBUG_INFO, "RNDIS_KEEPALIVE_CMPLT:\n"));
>> + Length = sizeof (REMOTE_NDIS_KEEPALIVE_CMPLT);
>> + }
>> +
>> + if (Length) {
>> + UINTN Index = 0;
>> + for ( ; Length; Length -= 4, Index++) {
>> + DEBUG ((DEBUG_INFO, "%8X\t", *((UINT32 *)RndisMsg + Index)));
>> + if (((Index % 4) == 3) && (Index != 0)) {
>> + DEBUG ((DEBUG_INFO, "\n"));
>> + }
>> +
>> + if ((Length < 8) && (Length > 4)) {
>> + UINT32 Data32;
>> + Index++;
>> + Data32 = *((UINT32 *)RndisMsg + Index);
>> + DEBUG ((DEBUG_INFO, "%8X\t", Data32));
>> + break;
>> + }
>> + }
>> +
>> + if (Index % 4) {
>> + DEBUG ((DEBUG_INFO, "\n"));
>> + }
>> + }
>> +}
>> diff --git a/UsbNetworkPkg/ReadMe.md b/UsbNetworkPkg/ReadMe.md
>> new file mode 100644
>> index 000000000000..cb70684f0bf1
>> --- /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:<br>
>> +- NetworkCommon
>> +- UsbCdcEcm
>> +- UsbCdcNcm
>> +- UsbRndis
>> +
>> +## [NetworkCommon]
>> +Provides a LAN driver based on UEFI specification(UNDI). It supports
>> USB 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 with 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 with 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 000000000000..f8ccccdb0830
>> --- /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.
>> --
>> 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 any 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.
>
>
>
>
>
next prev parent reply other threads:[~2023-03-27 15:13 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-03-09 7:51 [PATCH v6 1/3] UsbNetworkPkg/UsbRndis: Add USB RNDIS devices support RichardHo [何明忠]
2023-03-09 7:51 ` [PATCH v6 2/3] UsbNetworkPkg/UsbCdcEcm: Add USB Cdc ECM " RichardHo [何明忠]
2023-03-09 7:51 ` [PATCH v6 3/3] UsbNetworkPkg/UsbCdcNcm: Add USB Cdc NCM " RichardHo [何明忠]
2023-03-27 14:59 ` [PATCH v6 1/3] UsbNetworkPkg/UsbRndis: Add USB RNDIS " Tinh Nguyen
2023-03-27 15:13 ` Rebecca Cran [this message]
2023-03-28 11:40 ` Rebecca Cran
2023-03-29 2:11 ` RichardHo [何明忠]
2023-04-07 1:57 ` Rebecca Cran
2023-04-07 2:49 ` RichardHo [何明忠]
2023-04-07 2:52 ` [edk2-devel] " Rebecca Cran
2023-04-07 11:47 ` Rebecca Cran
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=9c2f244b-280f-8eb8-c352-79dcb41fa4e1@bsdio.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox