From: "Pedro Falcato" <pedro.falcato@gmail.com>
To: edk2-devel-groups-io <devel@edk2.groups.io>, richardho@ami.com
Cc: "TonyLo [羅金松]" <TonyLo@ami.com>
Subject: Re: [edk2-devel] [PATCH] UsbNetworkPkg: add USB network devices support
Date: Fri, 19 Aug 2022 16:54:29 +0100 [thread overview]
Message-ID: <CAKbZUD0GH9KSY2AaPE=d=pFHynPNNQ2O=p6DjKPoZkoutb8V8Q@mail.gmail.com> (raw)
In-Reply-To: <20220819091703.247-1-richardho@ami.com>
[-- Attachment #1: Type: text/plain, Size: 435118 bytes --]
Hi Richard,
What license is this code under? "Subject to AMI licensing agreement." does
not sound like a valid OSS license.
Thanks,
Pedro
On Fri, Aug 19, 2022 at 10:32 AM RichardHo [何明忠] via groups.io <richardho=
ami.com@groups.io> wrote:
> UsbNetworkPkg provides network functions for USB ACM, USB NCM,
> and USB RNDIS network device.
>
> Signed-off-by: Richard Ho <richardho@ami.com>
> Reviewed-by: Tony Lo <tonylo@ami.com>
> ---
> UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc | 9 +
> .../Config/UsbNetworkPkgComponentsDxe.inc.dsc | 20 +
> .../Config/UsbNetworkPkgComponentsDxe.inc.fdf | 21 +
> .../Config/UsbNetworkPkgDefines.inc.dsc | 23 +
> .../Include/Protocol/UsbEthernetProtocol.h | 872 +++++++++
> UsbNetworkPkg/NetworkCommon/ComponentName.c | 264 +++
> UsbNetworkPkg/NetworkCommon/DriverBinding.c | 583 ++++++
> UsbNetworkPkg/NetworkCommon/DriverBinding.h | 263 +++
> UsbNetworkPkg/NetworkCommon/NetworkCommon.inf | 43 +
> UsbNetworkPkg/NetworkCommon/PxeFunction.c | 1734 +++++++++++++++++
> UsbNetworkPkg/ReadMe.md | 65 +
> UsbNetworkPkg/ReleaseNotes.md | 11 +
> UsbNetworkPkg/UsbCdcEcm/ComponentName.c | 170 ++
> UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.c | 504 +++++
> UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.h | 211 ++
> UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf | 41 +
> UsbNetworkPkg/UsbCdcEcm/UsbEcmFunction.c | 861 ++++++++
> UsbNetworkPkg/UsbCdcNcm/ComponentName.c | 170 ++
> UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.c | 508 +++++
> UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.h | 245 +++
> UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf | 41 +
> UsbNetworkPkg/UsbCdcNcm/UsbNcmFunction.c | 946 +++++++++
> UsbNetworkPkg/UsbNetworkPkg.dec | 32 +
> UsbNetworkPkg/UsbRndis/ComponentName.c | 172 ++
> UsbNetworkPkg/UsbRndis/UsbRndis.c | 848 ++++++++
> UsbNetworkPkg/UsbRndis/UsbRndis.h | 569 ++++++
> UsbNetworkPkg/UsbRndis/UsbRndis.inf | 41 +
> UsbNetworkPkg/UsbRndis/UsbRndisFunction.c | 1587 +++++++++++++++
> 28 files changed, 10854 insertions(+)
> create mode 100644 UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc
> create mode 100644 UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc
> create mode 100644 UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf
> create mode 100644 UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc
> create mode 100644 UsbNetworkPkg/Include/Protocol/UsbEthernetProtocol.h
> create mode 100644 UsbNetworkPkg/NetworkCommon/ComponentName.c
> create mode 100644 UsbNetworkPkg/NetworkCommon/DriverBinding.c
> create mode 100644 UsbNetworkPkg/NetworkCommon/DriverBinding.h
> create mode 100644 UsbNetworkPkg/NetworkCommon/NetworkCommon.inf
> create mode 100644 UsbNetworkPkg/NetworkCommon/PxeFunction.c
> create mode 100644 UsbNetworkPkg/ReadMe.md
> create mode 100644 UsbNetworkPkg/ReleaseNotes.md
> create mode 100644 UsbNetworkPkg/UsbCdcEcm/ComponentName.c
> create mode 100644 UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.c
> create mode 100644 UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.h
> create mode 100644 UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf
> create mode 100644 UsbNetworkPkg/UsbCdcEcm/UsbEcmFunction.c
> create mode 100644 UsbNetworkPkg/UsbCdcNcm/ComponentName.c
> create mode 100644 UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.c
> create mode 100644 UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.h
> create mode 100644 UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf
> create mode 100644 UsbNetworkPkg/UsbCdcNcm/UsbNcmFunction.c
> create mode 100644 UsbNetworkPkg/UsbNetworkPkg.dec
> create mode 100644 UsbNetworkPkg/UsbRndis/ComponentName.c
> create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndis.c
> create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndis.h
> create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndis.inf
> create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndisFunction.c
>
> diff --git a/UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc
> b/UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc
> new file mode 100644
> index 0000000000..504680bc4b
> --- /dev/null
> +++ b/UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc
> @@ -0,0 +1,9 @@
> +## @file
> +# Global DSC definitions to be included into project DSC file.
> +#
> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
> +# Subject to AMI licensing agreement.
> +##
> +
> +[Components.X64]
> +!include UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc
> diff --git a/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc
> b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc
> new file mode 100644
> index 0000000000..ae2727b68c
> --- /dev/null
> +++ b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc
> @@ -0,0 +1,20 @@
> +## @file
> +# List of Core Components.
> +#
> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
> +# Subject to AMI licensing agreement.
> +##
> +
> + UsbNetworkPkg/NetworkCommon/NetworkCommon.inf
> +
> +!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport
> + UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf
> +!endif
> +
> +!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport
> + UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf
> +!endif
> +
> +!if gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport
> + UsbNetworkPkg/UsbRndis/UsbRndis.inf
> +!endif
> diff --git a/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf
> b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf
> new file mode 100644
> index 0000000000..6a611e359c
> --- /dev/null
> +++ b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf
> @@ -0,0 +1,21 @@
> +## @file
> +# List of Core Components.
> +#
> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
> +# Subject to AMI licensing agreement.
> +##
> +
> + INF UsbNetworkPkg/NetworkCommon/NetworkCommon.inf
> +
> +!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport
> + INF UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf
> +!endif
> +
> +!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport
> + INF UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf
> +!endif
> +
> +!if gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport
> + INF UsbNetworkPkg/UsbRndis/UsbRndis.inf
> +!endif
> +
> \ No newline at end of file
> diff --git a/UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc
> b/UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc
> new file mode 100644
> index 0000000000..ef663bf253
> --- /dev/null
> +++ b/UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc
> @@ -0,0 +1,23 @@
> +## @file
> +# Global switches enable/disable project features.
> +#
> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
> +# Subject to AMI licensing agreement.
> +##
> +
> +[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/Include/Protocol/UsbEthernetProtocol.h
> b/UsbNetworkPkg/Include/Protocol/UsbEthernetProtocol.h
> new file mode 100644
> index 0000000000..d60e83f723
> --- /dev/null
> +++ b/UsbNetworkPkg/Include/Protocol/UsbEthernetProtocol.h
> @@ -0,0 +1,872 @@
> +/** @file
>
> + Header file contains code for USB Ethernet Protocol
>
> + definitions
>
> +
>
> + Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
>
> + Subject to AMI licensing agreement.
>
> +**/
>
> +
>
> +#ifndef _USB_ETHERNET_PROTOCOL_H
>
> +#define _USB_ETHERNET_PROTOCOL_H
>
> +
>
> +#define USB_ETHERNET_PROTOCOL_GUID \
>
> + {0x8d8969cc, 0xfeb0, 0x4303, {0xb2, 0x1a, 0x1f, 0x11, 0x6f, 0x38,
> 0x56, 0x43}}
>
> +
>
> +typedef struct _USB_ETHERNET_PROTOCOL USB_ETHERNET_PROTOCOL;
>
> +
>
> +#define USB_CDC_CLASS 0x02
>
> +#define USB_CDC_ACM_SUBCLASS 0x02
>
> +#define USB_CDC_ECM_SUBCLASS 0x06
>
> +#define USB_CDC_NCM_SUBCLASS 0x0D
>
> +#define USB_CDC_DATA_CLASS 0x0A
>
> +#define USB_CDC_DATA_SUBCLASS 0x00
>
> +#define USB_NO_CLASS_PROTOCOL 0x00
>
> +#define USB_NCM_NTB_PROTOCOL 0x01
>
> +#define USB_VENDOR_PROTOCOL 0xFF
>
> +
>
> +// Type Values for the DescriptorType Field
>
> +#define CS_INTERFACE 0x24
>
> +#define CS_ENDPOINT 0x25
>
> +
>
> +// Descriptor SubType in Functional Descriptors
>
> +#define HEADER_FUN_DESCRIPTOR 0x00
>
> +#define UNION_FUN_DESCRIPTOR 0x06
>
> +#define ETHERNET_FUN_DESCRIPTOR 0x0F
>
> +
>
> +#define MAX_LAN_INTERFACE 0x10
>
> +
>
> +// Table 20: Class-Specific Notification Codes
>
> +#define USB_CDC_NETWORK_CONNECTION 0x00
>
> +
>
> +// 6.3.1 NetworkConnection
>
> +#define NETWORK_CONNECTED 0x01
>
> +#define NETWORK_DISCONNECT 0x00
>
> +
>
> +// USB Header functional Descriptor
>
> +typedef struct {
>
> + UINT8 FunctionLength;
>
> + UINT8 DescriptorType;
>
> + UINT8 DescriptorSubtype;
>
> + UINT16 BcdCdc;
>
> +} USB_HEADER_FUN_DESCRIPTOR;
>
> +
>
> +// USB Union Functional Descriptor
>
> +typedef struct {
>
> + UINT8 FunctionLength;
>
> + UINT8 DescriptorType;
>
> + UINT8 DescriptorSubtype;
>
> + UINT8 MasterInterface;
>
> + UINT8 SlaveInterface;
>
> +} USB_UNION_FUN_DESCRIPTOR;
>
> +
>
> +// USB Ethernet Functional Descriptor
>
> +typedef struct {
>
> + UINT8 FunctionLength;
>
> + UINT8 DescriptorType;
>
> + UINT8 DescriptorSubtype;
>
> + UINT8 MacAddress;
>
> + UINT32 EthernetStatistics;
>
> + UINT16 MaxSegmentSize;
>
> + UINT16 NumberMcFilters;
>
> + UINT8 NumberPowerFilters;
>
> +} USB_ETHERNET_FUN_DESCRIPTOR;
>
> +
>
> +typedef struct {
>
> + UINT32 UsBitRate;
>
> + UINT32 DsBitRate;
>
> +} USB_CONNECT_SPEED_CHANGE;
>
> +
>
> +// Request Type Codes for USB Ethernet
>
> +#define USB_ETHERNET_GET_REQ_TYPE 0xA1
>
> +#define USB_ETHRTNET_SET_REQ_TYPE 0x21
>
> +
>
> +// Class-Specific Request Codes for Ethernet subclass
>
> +// USB ECM 1.2 specification, Section 6.2
>
> +#define SET_ETH_MULTICAST_FILTERS_REQ 0x40
>
> +#define SET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ 0x41
>
> +#define GET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ 0x42
>
> +#define SET_ETH_PACKET_FILTER_REQ 0x43
>
> +#define GET_ETH_STATISTIC_REQ 0x44
>
> +
>
> +// USB ECM command request length
>
> +#define USB_ETH_POWER_FILTER_LENGTH 2 // Section 6.2.3
>
> +#define USB_ETH_PACKET_FILTER_LENGTH 0 // Section 6.2.4
>
> +#define USB_ETH_STATISTIC 4 // Section 6.2.5
>
> +
>
> +// USB Ethernet Packet Filter Bitmap
>
> +// USB ECM 1.2 specification, Section 6.2.4
>
> +#define USB_ETH_PACKET_TYPE_PROMISCUOUS BIT0
>
> +#define USB_ETH_PACKET_TYPE_ALL_MULTICAST BIT1
>
> +#define USB_ETH_PACKET_TYPE_DIRECTED BIT2
>
> +#define USB_ETH_PACKET_TYPE_BROADCAST BIT3
>
> +#define USB_ETH_PACKET_TYPE_MULTICAST BIT4
>
> +
>
> +// USB Ethernet Statistics Feature Selector Codes
>
> +// USB ECM 1.2 specification, Section 6.2.5
>
> +#define USB_ETH_XMIT_OK 0x01
>
> +#define USB_ETH_RCV_OK 0x02
>
> +#define USB_ETH_XMIT_ERROR 0x03
>
> +#define USB_ETH_RCV_ERROR 0x04
>
> +#define USB_ETH_RCV_NO_BUFFER 0x05
>
> +#define USB_ETH_DIRECTED_BYTES_XMIT 0x06
>
> +#define USB_ETH_DIRECTED_FRAMES_XMIT 0x07
>
> +#define USB_ETH_MULTICAST_BYTES_XMIT 0x08
>
> +#define USB_ETH_MULTICAST_FRAMES_XMIT 0x09
>
> +#define USB_ETH_BROADCAST_BYTES_XMIT 0x0A
>
> +#define USB_ETH_BROADCAST_FRAMES_XMIT 0x0B
>
> +#define USB_ETH_DIRECTED_BYTES_RCV 0x0C
>
> +#define USB_ETH_DIRECTED_FRAMES_RCV 0x0D
>
> +#define USB_ETH_MULTICAST_BYTES_RCV 0x0E
>
> +#define USB_ETH_MULTICAST_FRAMES_RCV 0x0F
>
> +#define USB_ETH_BROADCAST_BYTES_RCV 0x10
>
> +#define USB_ETH_BROADCAST_FRAMES_RCV 0x11
>
> +#define USB_ETH_RCV_CRC_ERROR 0x12
>
> +#define USB_ETH_TRANSMIT_QUEUE_LENGTH 0x13
>
> +#define USB_ETH_RCV_ERROR_ALIGNMENT 0x14
>
> +#define USB_ETH_XMIT_ONE_COLLISION 0x15
>
> +#define USB_ETH_XMIT_MORE_COLLISIONS 0x16
>
> +#define USB_ETH_XMIT_DEFERRED 0x17
>
> +#define USB_ETH_XMIT_MAX_COLLISIONS 0x18
>
> +#define USB_ETH_RCV_OVERRUN 0x19
>
> +#define USB_ETH_XMIT_UNDERRUN 0x1A
>
> +#define USB_ETH_XMIT_HEARTBEAT_FAILURE 0x1B
>
> +#define USB_ETH_XMIT_TIMES_CRS_LOST 0x1C
>
> +#define USB_ETH_XMIT_LATE_COLLISIONS 0x1D
>
> +
>
> +// NIC Information
>
> +typedef struct {
>
> + UINT32 Signature;
>
> + USB_ETHERNET_PROTOCOL *UsbEth;
>
> + UINT16 InterrupOpFlag;
>
> + UINT64 MappedAddr;
>
> + PXE_MAC_ADDR McastList[MAX_MCAST_ADDRESS_CNT];
>
> + UINT8 McastCount;
>
> + UINT64 MediaHeader[MAX_XMIT_BUFFERS];
>
> + UINT8 TxBufferCount;
>
> + UINT16 State;
>
> + BOOLEAN CanTransmit;
>
> + BOOLEAN CanReceive;
>
> + UINT16 ReceiveStatus;
>
> + UINT8 RxFilter;
>
> + UINT32 RxFrame;
>
> + UINT32 TxFrame;
>
> + UINT16 NetworkConnect;
>
> + UINT8 CableDetect;
>
> + UINT16 MaxSegmentSize;
>
> + EFI_MAC_ADDRESS MacAddr;
>
> + PXE_CPB_START_31 PxeStart;
>
> + PXE_CPB_INITIALIZE PxeInit;
>
> + UINT8 PermNodeAddress[PXE_MAC_LENGTH];
>
> + UINT8 CurrentNodeAddress[PXE_MAC_LENGTH];
>
> + UINT8 BroadcastNodeAddress[PXE_MAC_LENGTH];
>
> + EFI_USB_DEVICE_REQUEST Request;
>
> +} NIC_DATA;
>
> +
>
> +#define NIC_DATA_SIGNATURE SIGNATURE_32('n', 'i', 'c', 'd')
>
> +#define NIC_DATA_FROM_USB_ETHERNET_PROTOCOL(a) CR (a, NIC_DATA, UsbEth,
> NIC_DATA_SIGNATURE)
>
> +
>
> +/**
>
> + This command is used to determine the operational state of the UNDI.
>
> +
>
> + @param[in] Cdb A pointer to the command descriptor block.
>
> + @param[in] Nic A pointer to the Network interface controller data.
>
> +
>
> + @retval EFI_SUCCESS The request executed successfully.
>
> + @retval EFI_TIMEOUT A timeout occurred executing the 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 *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 *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 *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 *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 *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 *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 *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 *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 *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 *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 *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 *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 *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 *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 *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 *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 *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 *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 *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 *USB_ETHERNET_STATISTICS)(
>
> + IN NIC_DATA *Nic,
>
> + IN UINT64 DbAddr,
>
> + IN UINT16 DbSize
>
> + );
>
> +
>
> +/**
>
> + This function is used to manage a USB device with the bulk transfer
> pipe. The endpoint is Bulk in.
>
> +
>
> + @param[in] Cdb A pointer to the command descriptor block.
>
> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL
> instance.
>
> + @param[in, out] Packet A pointer to the buffer of data that will
> be transmitted to USB
>
> + device or received from USB device.
>
> + @param[in, out] PacketLength A pointer to the PacketLength.
>
> +
>
> + @retval EFI_SUCCESS The bulk transfer has been successfully
> executed.
>
> + @retval EFI_DEVICE_ERROR The transfer failed. The transfer status
> is returned in status.
>
> + @retval EFI_INVALID_PARAMETE One or more parameters are invalid.
>
> + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due to
> a lack of resources.
>
> + @retval EFI_TIMEOUT The control transfer fails due to timeout.
>
> +**/
>
> +typedef
>
> +EFI_STATUS
>
> +(EFIAPI *USB_ETHERNET_RECEIVE)(
>
> + IN PXE_CDB *Cdb,
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN OUT VOID *Packet,
>
> + IN OUT UINTN *PacketLength
>
> + );
>
> +
>
> +/**
>
> + This function is used to manage a USB device with the bulk transfer
> pipe. The endpoint is Bulk out.
>
> +
>
> + @param[in] Cdb A pointer to the command descriptor block.
>
> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL
> instance.
>
> + @param[in, out] Packet A pointer to the buffer of data that will
> be transmitted to USB
>
> + device or received from USB device.
>
> + @param[in, out] PacketLength A pointer to the PacketLength.
>
> +
>
> + @retval EFI_SUCCESS The bulk transfer has been successfully
> executed.
>
> + @retval EFI_DEVICE_ERROR The transfer failed. The transfer status
> is returned in status.
>
> + @retval EFI_INVALID_PARAMETE One or more parameters are invalid.
>
> + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due to
> a lack of resources.
>
> + @retval EFI_TIMEOUT The control transfer fails due to timeout.
>
> +**/
>
> +typedef
>
> +EFI_STATUS
>
> +(EFIAPI *USB_ETHERNET_TRANSMIT)(
>
> + IN PXE_CDB *Cdb,
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN OUT VOID *Packet,
>
> + IN OUT UINTN *PacketLength
>
> + );
>
> +
>
> +/**
>
> + This function is used to manage a USB device with an interrupt transfer
> pipe.
>
> +
>
> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL
> instance.
>
> + @param[in] IsNewTransfer If TRUE, a new transfer will be submitted
> to USB controller. If
>
> + FALSE, the interrupt transfer is 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 *USB_ETHERNET_INTERRUPT)(
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN BOOLEAN IsNewTransfer,
>
> + IN UINTN PollingInterval,
>
> + IN EFI_USB_DEVICE_REQUEST *Request
>
> + );
>
> +
>
> +/**
>
> + Retrieves the USB Ethernet Mac Address.
>
> +
>
> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL
> instance.
>
> + @param[out] MacAddress A pointer to the caller allocated USB
> Ethernet Mac Address.
>
> +
>
> + @retval EFI_SUCCESS The USB Header Functional descriptor 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 *USB_GET_ETH_MAC_ADDRESS)(
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT EFI_MAC_ADDRESS *MacAddress
>
> + );
>
> +
>
> +/**
>
> + Retrieves the USB Ethernet Bulk transfer data size.
>
> +
>
> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL
> instance.
>
> + @param[out] BulkSize A pointer to the Bulk transfer data size.
>
> +
>
> + @retval EFI_SUCCESS The USB Header Functional descriptor 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 *USB_ETH_MAX_BULK_SIZE)(
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT UINTN *BulkSize
>
> + );
>
> +
>
> +/**
>
> + Retrieves the USB Header functional Descriptor.
>
> +
>
> + @param[in] This A pointer to the
> USB_ETHERNET_PROTOCOL instance.
>
> + @param[out] UsbHeaderFunDescriptor A pointer to the caller allocated
> USB Header Functional Descriptor.
>
> +
>
> + @retval EFI_SUCCESS The USB Header Functional descriptor 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 *USB_HEADER_FUNCTIONAL_DESCRIPTOR)(
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor
>
> + );
>
> +
>
> +/**
>
> + Retrieves the USB Union functional Descriptor.
>
> +
>
> + @param[in] This A pointer to the
> USB_ETHERNET_PROTOCOL instance.
>
> + @param[out] UsbUnionFunDescriptor A pointer to the caller allocated
> USB Union Functional Descriptor.
>
> +
>
> + @retval EFI_SUCCESS The USB Union Functional descriptor was
> retrieved successfully.
>
> + @retval EFI_INVALID_PARAMETER UsbUnionFunDescriptor is NULL.
>
> + @retval EFI_NOT_FOUND The USB Union Functional descriptor was
> not found.
>
> +**/
>
> +typedef
>
> +EFI_STATUS
>
> +(EFIAPI *USB_UNION_FUNCTIONAL_DESCRIPTOR)(
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor
>
> + );
>
> +
>
> +/**
>
> + Retrieves the USB Ethernet functional Descriptor.
>
> +
>
> + @param[in] This A pointer to the
> USB_ETHERNET_PROTOCOL instance.
>
> + @param[out] UsbEthFunDescriptor A pointer to the caller allocated
> USB Ethernet Functional Descriptor.
>
> +
>
> + @retval EFI_SUCCESS The USB Ethernet Functional descriptor
> was retrieved successfully.
>
> + @retval EFI_INVALID_PARAMETER UsbEthFunDescriptor is NULL.
>
> + @retval EFI_NOT_FOUND The USB Ethernet Functional descriptor
> was not found.
>
> +**/
>
> +typedef
>
> +EFI_STATUS
>
> +(EFIAPI *USB_ETHERNET_FUNCTIONAL_DESCRIPTOR)(
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor
>
> + );
>
> +
>
> +/**
>
> + This request sets the Ethernet device multicast filters as specified in
> the
>
> + sequential list of 48 bit Ethernet multicast addresses.
>
> +
>
> + @param[in] This A pointer to the
> USB_ETHERNET_PROTOCOL instance.
>
> + @param[in] Value Number of filters.
>
> + @param[in] McastAddr A pointer to the value of the
> multicast addresses.
>
> +
>
> + @retval EFI_SUCCESS The request executed successfully.
>
> + @retval EFI_TIMEOUT A timeout occurred executing the 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 *USB_ETHERNET_SET_ETH_MULTICAST_FILTERS)(
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value,
>
> + IN VOID *McastAddr
>
> + );
>
> +
>
> +/**
>
> + This request sets up the specified Ethernet power management pattern
> filter as
>
> + described in the data structure.
>
> +
>
> + @param[in] This A pointer to the
> USB_ETHERNET_PROTOCOL instance.
>
> + @param[in] Value Number of filters.
>
> + @param[in] Length Size of the power management pattern
> filter data.
>
> + @param[in] PatternFilter A pointer to the power management
> pattern filter structure.
>
> +
>
> + @retval EFI_SUCCESS The request executed successfully.
>
> + @retval EFI_TIMEOUT A timeout occurred executing the 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 *USB_ETHERNET_SET_ETH_POWER_MANAGE_PATTERN_FILTER)(
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value,
>
> + IN UINT16 Length,
>
> + IN VOID *PatternFilter
>
> + );
>
> +
>
> +/**
>
> + This request retrieves the status of the specified Ethernet power
> management
>
> + pattern filter from the device.
>
> +
>
> + @param[in] This A pointer to the
> USB_ETHERNET_PROTOCOL instance.
>
> + @param[in] Value The filter number.
>
> + @param[out] PatternActive A pointer to the pattern active
> boolean.
>
> +
>
> + @retval EFI_SUCCESS The request executed successfully.
>
> + @retval EFI_TIMEOUT A timeout occurred executing the 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 *USB_ETHERNET_GET_ETH_POWER_MANAGE_PATTERN_FILTER)(
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value,
>
> + OUT BOOLEAN *PatternActive
>
> + );
>
> +
>
> +/**
>
> + This request is used to configure device Ethernet packet filter
> settings.
>
> +
>
> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL
> instance.
>
> + @param[in] Value Packet Filter Bitmap.
>
> +
>
> + @retval EFI_SUCCESS The request executed successfully.
>
> + @retval EFI_TIMEOUT A timeout occurred executing the 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 *USB_ETHERNET_SET_ETH_PACKET_FILTER)(
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value
>
> + );
>
> +
>
> +/**
>
> + This request is used to retrieve a statistic based on the feature
> selector.
>
> +
>
> + @param[in] This A pointer to the
> USB_ETHERNET_PROTOCOL instance.
>
> + @param[in] FeatureSelector Value of the feature selector.
>
> + @param[out] Statistic A pointer to the 32 bit unsigned
> integer.
>
> +
>
> + @retval EFI_SUCCESS The request executed successfully.
>
> + @retval EFI_TIMEOUT A timeout occurred executing the 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 *USB_ETHERNET_GET_ETH_STATISTIC)(
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 FeatureSelector,
>
> + OUT VOID *Statistic
>
> + );
>
> +
>
> +typedef struct {
>
> + USB_ETHERNET_UNDI_GET_STATE UsbEthUndiGetState;
>
> + USB_ETHERNET_UNDI_START UsbEthUndiStart;
>
> + USB_ETHERNET_UNDI_STOP UsbEthUndiStop;
>
> + USB_ETHERNET_UNDI_GET_INIT_INFO UsbEthUndiGetInitInfo;
>
> + USB_ETHERNET_UNDI_GET_CONFIG_INFO UsbEthUndiGetConfigInfo;
>
> + USB_ETHERNET_UNDI_INITIALIZE UsbEthUndiInitialize;
>
> + USB_ETHERNET_UNDI_RESET UsbEthUndiReset;
>
> + USB_ETHERNET_UNDI_SHUTDOWN UsbEthUndiShutdown;
>
> + USB_ETHERNET_UNDI_INTERRUPT_ENABLE UsbEthUndiInterruptEnable;
>
> + USB_ETHERNET_UNDI_RECEIVE_FILTER UsbEthUndiReceiveFilter;
>
> + USB_ETHERNET_UNDI_STATION_ADDRESS UsbEthUndiStationAddress;
>
> + USB_ETHERNET_UNDI_STATISTICS UsbEthUndiStatistics;
>
> + USB_ETHERNET_UNDI_MCAST_IPTOMAC UsbEthUndiMcastIp2Mac;
>
> + USB_ETHERNET_UNDI_NV_DATA UsbEthUndiNvData;
>
> + USB_ETHERNET_UNDI_GET_STATUS UsbEthUndiGetStatus;
>
> + USB_ETHERNET_UNDI_FILL_HEADER UsbEthUndiFillHeader;
>
> + USB_ETHERNET_UNDI_TRANSMIT UsbEthUndiTransmit;
>
> + USB_ETHERNET_UNDI_RECEIVE UsbEthUndiReceive;
>
> +} USB_ETHERNET_UNDI;
>
> +
>
> +// The USB_ETHERNET_PROTOCOL provides some basic USB Ethernet device
> relevant
>
> +// descriptor and specific requests.
>
> +struct _USB_ETHERNET_PROTOCOL {
>
> + USB_ETHERNET_UNDI UsbEthUndi;
>
> + // for calling the UNDI child functions
>
> + USB_ETHERNET_INITIALIZE UsbEthInitialize;
>
> + USB_ETHERNET_STATISTICS UsbEthStatistics;
>
> + USB_ETHERNET_RECEIVE UsbEthReceive;
>
> + USB_ETHERNET_TRANSMIT UsbEthTransmit;
>
> + USB_ETHERNET_INTERRUPT UsbEthInterrupt;
>
> + USB_GET_ETH_MAC_ADDRESS UsbEthMacAddress;
>
> + USB_ETH_MAX_BULK_SIZE UsbEthMaxBulkSize;
>
> + USB_HEADER_FUNCTIONAL_DESCRIPTOR
> UsbHeaderFunDescriptor;
>
> + USB_UNION_FUNCTIONAL_DESCRIPTOR
> UsbUnionFunDescriptor;
>
> + USB_ETHERNET_FUNCTIONAL_DESCRIPTOR UsbEthFunDescriptor;
>
> + USB_ETHERNET_SET_ETH_MULTICAST_FILTERS
> SetUsbEthMcastFilter;
>
> + USB_ETHERNET_SET_ETH_POWER_MANAGE_PATTERN_FILTER
> SetUsbEthPowerPatternFilter;
>
> + USB_ETHERNET_GET_ETH_POWER_MANAGE_PATTERN_FILTER
> GetUsbEthPoewrPatternFilter;
>
> + USB_ETHERNET_SET_ETH_PACKET_FILTER
> SetUsbEthPacketFilter;
>
> + USB_ETHERNET_GET_ETH_STATISTIC GetUsbEthStatistic;
>
> +};
>
> +
>
> +#endif
>
> diff --git a/UsbNetworkPkg/NetworkCommon/ComponentName.c
> b/UsbNetworkPkg/NetworkCommon/ComponentName.c
> new file mode 100644
> index 0000000000..2697bf5083
> --- /dev/null
> +++ b/UsbNetworkPkg/NetworkCommon/ComponentName.c
> @@ -0,0 +1,264 @@
> +/** @file
>
> + This file contains code for USB network common driver
>
> + component name definitions
>
> +
>
> + Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
>
> + Subject to AMI licensing agreement.
>
> +**/
>
> +
>
> +#include "DriverBinding.h"
>
> +
>
> +extern EFI_DRIVER_BINDING_PROTOCOL gNetworkCommonDriverBinding;
>
> +extern EFI_GUID gUsbEthProtocolGuid;
>
> +
>
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE
> gNetworkCommonDriverNameTable[] = {
>
> + {
>
> + "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 = NULL;
>
> + 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,
>
> + &gUsbEthProtocolGuid
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + return Status;
>
> + }
>
> +
>
> + //
>
> + // Make sure this driver produced ChildHandle
>
> + //
>
> + Status = EfiTestChildHandle (
>
> + Controller,
>
> + ChildHandle,
>
> + &gUsbEthProtocolGuid
>
> + );
>
> + 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 0000000000..18b2daa7a8
> --- /dev/null
> +++ b/UsbNetworkPkg/NetworkCommon/DriverBinding.c
> @@ -0,0 +1,583 @@
> +/** @file
>
> + This file contains code for USB network binding driver
>
> +
>
> + Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
>
> + Subject to AMI licensing agreement.
>
> +**/
>
> +
>
> +#include "DriverBinding.h"
>
> +
>
> +PXE_SW_UNDI *gPxe = NULL;
>
> +NIC_DEVICE *gLanDeviceList[MAX_LAN_INTERFACE];
>
> +
>
> +EFI_GUID gUsbEthProtocolGuid = USB_ETHERNET_PROTOCOL_GUID;
>
> +
>
> +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;
>
> + USB_ETHERNET_PROTOCOL *UsbEth;
>
> +
>
> + Status = gBS->OpenProtocol (
>
> + ControllerHandle,
>
> + &gUsbEthProtocolGuid,
>
> + (VOID **)&UsbEth,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle,
>
> + EFI_OPEN_PROTOCOL_BY_DRIVER
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + return Status;
>
> + }
>
> +
>
> + gBS->CloseProtocol (
>
> + ControllerHandle,
>
> + &gUsbEthProtocolGuid,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle
>
> + );
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + Network Common Driver Binding Start.
>
> +
>
> + @param[in] This Protocol instance pointer.
>
> + @param[in] ControllerHandle Handle of device to bind driver 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;
>
> + USB_ETHERNET_PROTOCOL *UsbEth;
>
> + EFI_MAC_ADDRESS MacAddress;
>
> + UINTN BulkDataSize;
>
> + NIC_DEVICE *NicDevice;
>
> + UINT8 *TmpPxePointer = NULL;
>
> +
>
> + Status = gBS->OpenProtocol (
>
> + ControllerHandle,
>
> + &gUsbEthProtocolGuid,
>
> + (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,
>
> + &gUsbEthProtocolGuid,
>
> + 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,
>
> + &gUsbEthProtocolGuid,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle
>
> + );
>
> + return Status;
>
> + }
>
> +
>
> + NicDevice = AllocateZeroPool (sizeof (NIC_DEVICE));
>
> + if (!NicDevice) {
>
> + gBS->CloseProtocol (
>
> + ControllerHandle,
>
> + &gEfiDevicePathProtocolGuid,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle
>
> + );
>
> + gBS->CloseProtocol (
>
> + ControllerHandle,
>
> + &gUsbEthProtocolGuid,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle
>
> + );
>
> + return EFI_OUT_OF_RESOURCES;
>
> + }
>
> +
>
> + // for alignment adjustment
>
> + if (gPxe == NULL) {
>
> + TmpPxePointer = AllocateZeroPool (sizeof (PXE_SW_UNDI) + 16);
>
> + if (!TmpPxePointer) {
>
> + if (NicDevice != NULL) {
>
> + gBS->FreePool (NicDevice);
>
> + }
>
> +
>
> + gBS->CloseProtocol (
>
> + ControllerHandle,
>
> + &gEfiDevicePathProtocolGuid,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle
>
> + );
>
> + gBS->CloseProtocol (
>
> + ControllerHandle,
>
> + &gUsbEthProtocolGuid,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle
>
> + );
>
> +
>
> + return EFI_OUT_OF_RESOURCES;
>
> + } else {
>
> + // check for paragraph alignment here
>
> + if (((UINTN)TmpPxePointer & 0x0F) != 0) {
>
> + gPxe = (PXE_SW_UNDI *)(TmpPxePointer + 8);
>
> + } else {
>
> + gPxe = (PXE_SW_UNDI *)TmpPxePointer;
>
> + }
>
> +
>
> + if (!gPxe) {
>
> + if (NicDevice != NULL) {
>
> + gBS->FreePool (NicDevice);
>
> + }
>
> +
>
> + gBS->CloseProtocol (
>
> + ControllerHandle,
>
> + &gEfiDevicePathProtocolGuid,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle
>
> + );
>
> + gBS->CloseProtocol (
>
> + ControllerHandle,
>
> + &gUsbEthProtocolGuid,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle
>
> + );
>
> + return EFI_OUT_OF_RESOURCES;
>
> + }
>
> +
>
> + PxeStructInit (gPxe);
>
> + }
>
> + }
>
> +
>
> + NicDevice->NiiProtocol.Id = (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;
>
> +
>
> + 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,
>
> + &gUsbEthProtocolGuid,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle
>
> + );
>
> +
>
> + if (TmpPxePointer != NULL) {
>
> + gBS->FreePool (TmpPxePointer);
>
> + }
>
> +
>
> + if (NicDevice != NULL) {
>
> + gBS->FreePool (NicDevice);
>
> + }
>
> +
>
> + return EFI_DEVICE_ERROR;
>
> + }
>
> +
>
> + Status = CreateMacDevicePath (
>
> + &NicDevice->DevPath,
>
> + UsbEthPath,
>
> + &NicDevice->NicInfo
>
> + );
>
> +
>
> + if (EFI_ERROR (Status)) {
>
> + UpdateNicNum (NULL, gPxe);
>
> + if (TmpPxePointer != NULL) {
>
> + gBS->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;
>
> +
>
> + 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,
>
> + &gUsbEthProtocolGuid,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle
>
> + );
>
> +
>
> + if (TmpPxePointer != NULL) {
>
> + gBS->FreePool (TmpPxePointer);
>
> + }
>
> +
>
> + if (NicDevice->DevPath != NULL) {
>
> + gBS->FreePool (NicDevice->DevPath);
>
> + }
>
> +
>
> + if (NicDevice != NULL) {
>
> + gBS->FreePool (NicDevice);
>
> + }
>
> +
>
> + return EFI_DEVICE_ERROR;
>
> + }
>
> +
>
> + Status = gBS->OpenProtocol (
>
> + ControllerHandle,
>
> + &gUsbEthProtocolGuid,
>
> + (VOID **)&UsbEth,
>
> + This->DriverBindingHandle,
>
> + NicDevice->DeviceHandle,
>
> + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
>
> + );
>
> +
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + Network Common Driver Binding Stop.
>
> +
>
> + @param[in] This Protocol instance pointer.
>
> + @param[in] ControllerHandle Handle of device to stop driver on
>
> + @param[in] NumberOfChildren Number of Handles in
> ChildHandleBuffer. If number of
>
> + children is zero stop the entire 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;
>
> + 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,
>
> + &gUsbEthProtocolGuid,
>
> + 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;
>
> + }
>
> +
>
> + gBS->FreePool (NicDevice->DevPath);
>
> + gBS->FreePool (NicDevice);
>
> +
>
> + gBS->CloseProtocol (
>
> + ControllerHandle,
>
> + &gEfiDevicePathProtocolGuid,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle
>
> + );
>
> + gBS->CloseProtocol (
>
> + ControllerHandle,
>
> + &gUsbEthProtocolGuid,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle
>
> + );
>
> + return EFI_SUCCESS;
>
> + }
>
> +
>
> + AllChildrenStopped = 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,
>
> + &gUsbEthProtocolGuid,
>
> + 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,
>
> + &gUsbEthProtocolGuid,
>
> + (VOID **)&UsbEth,
>
> + This->DriverBindingHandle,
>
> + ChildHandleBuffer[Index],
>
> + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
>
> + );
>
> + } else {
>
> + gBS->FreePool (NicDevice->DevPath);
>
> + gBS->FreePool (NicDevice);
>
> + }
>
> + }
>
> +
>
> + if (!AllChildrenStopped) {
>
> + return EFI_DEVICE_ERROR;
>
> + }
>
> +
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + Entrypoint of Network Common Driver.
>
> +
>
> + This function is the entrypoint of Network Common Driver. It installs
> Driver Binding
>
> + Protocols together with Component Name Protocols.
>
> +
>
> + @param[in] ImageHandle The firmware allocated handle for the EFI
> image.
>
> + @param[in] SystemTable A pointer to the EFI System Table.
>
> +
>
> + @retval EFI_SUCCESS The entry point is executed successfully.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +NetworkCommonEntry (
>
> + IN EFI_HANDLE ImageHandle,
>
> + IN EFI_SYSTEM_TABLE *SystemTable
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> +
>
> + gNetworkCommonDriverBinding.DriverBindingHandle = ImageHandle;
>
> + gNetworkCommonDriverBinding.ImageHandle = ImageHandle;
>
> +
>
> + Status = gBS->InstallMultipleProtocolInterfaces (
>
> + &gNetworkCommonDriverBinding.DriverBindingHandle,
>
> + &gEfiDriverBindingProtocolGuid,
>
> + &gNetworkCommonDriverBinding,
>
> + &gEfiComponentName2ProtocolGuid,
>
> + &gNetworkCommonComponentName2,
>
> + NULL
>
> + );
>
> + return Status;
>
> +}
>
> diff --git a/UsbNetworkPkg/NetworkCommon/DriverBinding.h
> b/UsbNetworkPkg/NetworkCommon/DriverBinding.h
> new file mode 100644
> index 0000000000..223e034f2f
> --- /dev/null
> +++ b/UsbNetworkPkg/NetworkCommon/DriverBinding.h
> @@ -0,0 +1,263 @@
> +/** @file
>
> + Header file for for USB network common driver
>
> +
>
> + Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
>
> + Subject to AMI licensing agreement.
>
> +**/
>
> +
>
> +#ifndef _DRIVER_BINDING_H_
>
> +#define _DRIVER_BINDING_H_
>
> +
>
> +#include <Library/UefiDriverEntryPoint.h>
>
> +#include <Library/UefiBootServicesTableLib.h>
>
> +#include <Library/UefiLib.h>
>
> +#include <Library/DevicePathLib.h>
>
> +#include <Library/DebugLib.h>
>
> +#include <Library/MemoryAllocationLib.h>
>
> +#include <Library/BaseMemoryLib.h>
>
> +#include <Library/UefiUsbLib.h>
>
> +#include <Protocol/UsbIo.h>
>
> +#include <Protocol/NetworkInterfaceIdentifier.h>
>
> +#include <Protocol/UsbEthernetProtocol.h>
>
> +
>
> +#define NETWORK_COMMON_DRIVER_VERSION 1
>
> +#define NETWORK_COMMON_POLLING_INTERVAL 0x10
>
> +#define RX_BUFFER_COUNT 32
>
> +#define TX_BUFFER_COUNT 32
>
> +#define MEMORY_REQUIRE 0
>
> +
>
> +#define UNDI_DEV_SIGNATURE SIGNATURE_32('u','n','d','i')
>
> +#define UNDI_DEV_FROM_THIS(a) CR(a, NIC_DEVICE, NiiProtocol,
> UNDI_DEV_SIGNATURE)
>
> +#define UNDI_DEV_FROM_NIC(a) CR(a, NIC_DEVICE, NicInfo,
> UNDI_DEV_SIGNATURE)
>
> +
>
> +#pragma pack(1)
>
> +typedef struct {
>
> + UINT8 DestAddr[PXE_HWADDR_LEN_ETHER];
>
> + UINT8 SrcAddr[PXE_HWADDR_LEN_ETHER];
>
> + UINT16 Protocol;
>
> +} EthernetHeader;
>
> +#pragma pack()
>
> +
>
> +typedef struct {
>
> + UINTN Signature;
>
> + EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL NiiProtocol;
>
> + EFI_HANDLE DeviceHandle;
>
> + EFI_DEVICE_PATH_PROTOCOL *BaseDevPath;
>
> + EFI_DEVICE_PATH_PROTOCOL *DevPath;
>
> + NIC_DATA NicInfo;
>
> +} NIC_DEVICE;
>
> +
>
> +typedef VOID (*API_FUNC)(
>
> + PXE_CDB *,
>
> + NIC_DATA *
>
> + );
>
> +
>
> +extern PXE_SW_UNDI *gPxe;
>
> +extern NIC_DEVICE *gLanDeviceList[MAX_LAN_INTERFACE];
>
> +extern EFI_COMPONENT_NAME2_PROTOCOL gNetworkCommonComponentName2;
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +NetworkCommonSupported (
>
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
>
> + IN EFI_HANDLE ControllerHandle,
>
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +NetworkCommonDriverStart (
>
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
>
> + IN EFI_HANDLE ControllerHandle,
>
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +NetworkCommonDriverStop (
>
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
>
> + IN EFI_HANDLE ControllerHandle,
>
> + IN UINTN NumberOfChildren,
>
> + IN EFI_HANDLE *ChildHandleBuffer
>
> + );
>
> +
>
> +VOID
>
> +PxeStructInit (
>
> + OUT PXE_SW_UNDI *PxeSw
>
> + );
>
> +
>
> +VOID
>
> +UpdateNicNum (
>
> + IN NIC_DATA *Nic,
>
> + IN OUT PXE_SW_UNDI *PxeSw
>
> + );
>
> +
>
> +VOID
>
> +UndiApiEntry (
>
> + IN UINT64 Cdb
>
> + );
>
> +
>
> +UINTN
>
> +MapIt (
>
> + IN NIC_DATA *Nic,
>
> + IN UINT64 MemAddr,
>
> + IN UINT32 Size,
>
> + IN UINT32 Direction,
>
> + OUT UINT64 MappedAddr
>
> + );
>
> +
>
> +VOID
>
> +UnMapIt (
>
> + IN NIC_DATA *Nic,
>
> + IN UINT64 MemAddr,
>
> + IN UINT32 Size,
>
> + IN UINT32 Direction,
>
> + IN UINT64 MappedAddr
>
> + );
>
> +
>
> +VOID
>
> +UndiGetState (
>
> + IN PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + );
>
> +
>
> +VOID
>
> +UndiStart (
>
> + IN PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + );
>
> +
>
> +VOID
>
> +UndiStop (
>
> + IN PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + );
>
> +
>
> +VOID
>
> +UndiGetInitInfo (
>
> + IN PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + );
>
> +
>
> +VOID
>
> +UndiGetConfigInfo (
>
> + IN PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + );
>
> +
>
> +VOID
>
> +UndiInitialize (
>
> + IN PXE_CDB *Cdb,
>
> + IN OUT NIC_DATA *Nic
>
> + );
>
> +
>
> +VOID
>
> +UndiReset (
>
> + IN PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + );
>
> +
>
> +VOID
>
> +UndiShutdown (
>
> + IN PXE_CDB *Cdb,
>
> + IN OUT NIC_DATA *Nic
>
> + );
>
> +
>
> +VOID
>
> +UndiInterruptEnable (
>
> + IN PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + );
>
> +
>
> +VOID
>
> +UndiReceiveFilter (
>
> + IN PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + );
>
> +
>
> +VOID
>
> +UndiStationAddress (
>
> + IN PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + );
>
> +
>
> +VOID
>
> +UndiStatistics (
>
> + IN PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + );
>
> +
>
> +VOID
>
> +UndiMcastIp2Mac (
>
> + IN OUT PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + );
>
> +
>
> +VOID
>
> +UndiNvData (
>
> + IN PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + );
>
> +
>
> +VOID
>
> +UndiGetStatus (
>
> + IN PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + );
>
> +
>
> +VOID
>
> +UndiFillHeader (
>
> + IN PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + );
>
> +
>
> +VOID
>
> +UndiTransmit (
>
> + IN PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + );
>
> +
>
> +VOID
>
> +UndiReceive (
>
> + IN PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + );
>
> +
>
> +UINT16
>
> +Initialize (
>
> + IN PXE_CDB *Cdb,
>
> + IN OUT NIC_DATA *Nic
>
> + );
>
> +
>
> +UINT16
>
> +Transmit (
>
> + IN PXE_CDB *Cdb,
>
> + IN OUT NIC_DATA *Nic,
>
> + IN UINT64 CpbAddr,
>
> + IN UINT16 OpFlags
>
> + );
>
> +
>
> +UINT16
>
> +Receive (
>
> + IN PXE_CDB *Cdb,
>
> + IN OUT NIC_DATA *Nic,
>
> + IN UINT64 CpbAddr,
>
> + IN OUT UINT64 DbAddr
>
> + );
>
> +
>
> +UINT16
>
> +Setfilter (
>
> + IN NIC_DATA *Nic,
>
> + IN UINT16 SetFilter,
>
> + IN UINT64 CpbAddr,
>
> + IN UINT32 CpbSize
>
> + );
>
> +
>
> +UINT16
>
> +Statistics (
>
> + IN NIC_DATA *Nic,
>
> + IN UINT64 DbAddr,
>
> + IN UINT16 DbSize
>
> + );
>
> +
>
> +#endif
>
> diff --git a/UsbNetworkPkg/NetworkCommon/NetworkCommon.inf
> b/UsbNetworkPkg/NetworkCommon/NetworkCommon.inf
> new file mode 100644
> index 0000000000..483df660f7
> --- /dev/null
> +++ b/UsbNetworkPkg/NetworkCommon/NetworkCommon.inf
> @@ -0,0 +1,43 @@
> +## @file
> +# This is Usb Network Common driver for DXE phase.
> +#
> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
> +# Subject to AMI licensing agreement.
> +##
> +
> +[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
> +
> +[Depex]
> + TRUE
> diff --git a/UsbNetworkPkg/NetworkCommon/PxeFunction.c
> b/UsbNetworkPkg/NetworkCommon/PxeFunction.c
> new file mode 100644
> index 0000000000..d34b61a69f
> --- /dev/null
> +++ b/UsbNetworkPkg/NetworkCommon/PxeFunction.c
> @@ -0,0 +1,1734 @@
> +/** @file
>
> + This file contains code for UNDI command based on UEFI specification.
>
> +
>
> + Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
>
> + Subject to AMI licensing agreement.
>
> +**/
>
> +
>
> +#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
>
> +};
>
> +
>
> +/**
>
> + 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;
>
> +
>
> + 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;
>
> + } 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_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;
>
> + Nic->State = PXE_STATFLAGS_GET_STATE_STARTED;
>
> +
>
> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStart != NULL) {
>
> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiStart (Cdb, Nic);
>
> + if (EFI_ERROR (Status)) {
>
> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>
> + }
>
> + }
>
> +}
>
> +
>
> +/**
>
> + 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->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->CanReceive = FALSE;
>
> + 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->CanReceive = FALSE;
>
> + 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;
>
> + }
>
> +
>
> + Nic->CanReceive = TRUE;
>
> + break;
>
> +
>
> + default:
>
> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED;
>
> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB;
>
> + }
>
> +
>
> + if (Nic->CanReceive) {
>
> + 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 = 0;
>
> + UINT8 Index1;
>
> + UINT8 Index2;
>
> + PXE_CPB_RECEIVE_FILTERS *Cpb = (PXE_CPB_RECEIVE_FILTERS
> *)(UINTN)CpbAddr;
>
> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor;
>
> +
>
> + // 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);
>
> + }
>
> +
>
> + if (Nic->CanReceive) {
>
> + Nic->CanReceive = FALSE;
>
> + }
>
> +
>
> + 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);
>
> + gBS->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 = 0;
>
> + UINTN DataLength;
>
> + UINTN Map;
>
> + UINT32 Counter = 0;
>
> + UINT16 StatCode;
>
> +
>
> + 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;
>
> + }
>
> +
>
> + Status = Nic->UsbEth->UsbEthTransmit (Cdb, Nic->UsbEth, (VOID
> *)(UINTN)BulkOutData, &DataLength);
>
> + 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->CanReceive) {
>
> + 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;
>
> + UINT16 StatCode = PXE_STATCODE_NO_DATA;
>
> + PXE_FRAME_TYPE FrameType = PXE_FRAME_TYPE_NONE;
>
> + PXE_CPB_RECEIVE *Cpb;
>
> + PXE_DB_RECEIVE *Db;
>
> + UINT8 *BulkInData;
>
> + UINTN DataLength = (UINTN)Nic->MaxSegmentSize;
>
> + EthernetHeader *Header;
>
> +
>
> + Cpb = (PXE_CPB_RECEIVE *)(UINTN)CpbAddr;
>
> + Db = (PXE_DB_RECEIVE *)(UINTN)DbAddr;
>
> +
>
> + Status = gBS->AllocatePool (EfiBootServicesData, DataLength, (VOID
> **)&BulkInData);
>
> + if (EFI_ERROR (Status)) {
>
> + return PXE_STATCODE_INVALID_PARAMETER;
>
> + }
>
> +
>
> + while (1) {
>
> + Status = Nic->UsbEth->UsbEthReceive (Cdb, Nic->UsbEth, (VOID
> *)BulkInData, &DataLength);
>
> + if (EFI_ERROR (Status)) {
>
> + break;
>
> + }
>
> +
>
> + 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];
>
> + }
>
> +
>
> + StatCode = PXE_STATCODE_SUCCESS;
>
> + break;
>
> + }
>
> + }
>
> +
>
> + if (FrameType == PXE_FRAME_TYPE_NONE) {
>
> + Nic->ReceiveStatus = 0;
>
> + } else {
>
> + Nic->ReceiveStatus = 1;
>
> + }
>
> +
>
> + gBS->FreePool (BulkInData);
>
> +
>
> + return StatCode;
>
> +}
>
> +
>
> +/**
>
> + Fill out PXE SW UNDI structure.
>
> +
>
> + @param[out] PxeSw A pointer to the PXE SW UNDI structure.
>
> +
>
> +**/
>
> +VOID
>
> +PxeStructInit (
>
> + OUT PXE_SW_UNDI *PxeSw
>
> + )
>
> +{
>
> + PxeSw->Signature = 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.
>
> +
>
> +**/
>
> +VOID
>
> +UndiApiEntry (
>
> + IN UINT64 Cdb
>
> + )
>
> +{
>
> + PXE_CDB *CdbPtr;
>
> + NIC_DATA *Nic;
>
> +
>
> + if (Cdb == 0) {
>
> + return;
>
> + }
>
> +
>
> + CdbPtr = (PXE_CDB *)(UINTN)Cdb;
>
> + Nic = &(gLanDeviceList[CdbPtr->IFnum]->NicInfo);
>
> + gUndiApiTable[CdbPtr->OpCode](CdbPtr, Nic);
>
> +}
>
> +
>
> +/**
>
> + Map virtual memory address for DMA. This field can be set to
>
> + zero if there is no mapping service.
>
> +
>
> + @param[in] Nic A pointer to the Network interface controller
> data.
>
> + @param[in] MemAddr Virtual address to be mapped.
>
> + @param[in] Size Size of memory to be mapped.
>
> + @param[in] Direction Direction of data flow for this memory's
> usage:
>
> + cpu->device, device->cpu or both ways.
>
> + @param[out] MappedAddr Pointer to return the mapped device address.
>
> +
>
> +**/
>
> +UINTN
>
> +MapIt (
>
> + IN NIC_DATA *Nic,
>
> + IN UINT64 MemAddr,
>
> + IN UINT32 Size,
>
> + IN UINT32 Direction,
>
> + OUT UINT64 MappedAddr
>
> + )
>
> +{
>
> + UINT64 *PhyAddr;
>
> +
>
> + PhyAddr = (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/ReadMe.md b/UsbNetworkPkg/ReadMe.md
> new file mode 100644
> index 0000000000..6dc0514ba7
> --- /dev/null
> +++ b/UsbNetworkPkg/ReadMe.md
> @@ -0,0 +1,65 @@
> +# UsbNetworkPkg
> +
> +This document is intend to provide package information, include the
> interface details.
> +
> +# INDEX
> + * [Introduction](#introduction)
> + * [Components](#components)
> + * [[NetworkCommon]](#networkcommon)
> + * [[UsbCdcEcm]](#usbcdcecm)
> + * [[UsbCdcNcm]](#usbcdcncm)
> + * [[UsbRndis]](#usbrndis)
> +
> +# Introduction
> +UsbNetworkPkg provides network functions for USB LAN devices.
> +
> +# Components
> +Below module is included in this package:<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 0000000000..03912e7788
> --- /dev/null
> +++ b/UsbNetworkPkg/ReleaseNotes.md
> @@ -0,0 +1,11 @@
> +# UsbNetworkPkg Release Notes<!-- omit in toc -->
>
> +
>
> +# Release History<!-- omit in toc -->
>
> +- [1.00](#100)
>
> +
>
> +## 1.00
>
> +
>
> +**Release Date:** Mar 10, 2022
>
> +
>
> +**New Features**
>
> +- UsbNetworkPkg first release.
>
> diff --git a/UsbNetworkPkg/UsbCdcEcm/ComponentName.c
> b/UsbNetworkPkg/UsbCdcEcm/ComponentName.c
> new file mode 100644
> index 0000000000..39123994b2
> --- /dev/null
> +++ b/UsbNetworkPkg/UsbCdcEcm/ComponentName.c
> @@ -0,0 +1,170 @@
> +/** @file
>
> + This file contains code for USB Ecm Driver Component Name definitions
>
> +
>
> + Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
>
> + Subject to AMI licensing agreement.
>
> +**/
>
> +#include "UsbCdcEcm.h"
>
> +
>
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE
> gUsbEcmDriverNameTable[] = {
>
> + {
>
> + "eng;en",
>
> + L"USB ECM Driver"
>
> + },
>
> + {
>
> + NULL,
>
> + NULL
>
> + }
>
> +};
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbEcmComponentNameGetDriverName (
>
> + IN EFI_COMPONENT_NAME_PROTOCOL *This,
>
> + IN CHAR8 *Language,
>
> + OUT CHAR16 **DriverName
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbEcmComponentNameGetControllerName (
>
> + IN EFI_COMPONENT_NAME_PROTOCOL *This,
>
> + IN EFI_HANDLE Controller,
>
> + IN EFI_HANDLE ChildHandle OPTIONAL,
>
> + IN CHAR8 *Language,
>
> + OUT CHAR16 **ControllerName
>
> + );
>
> +
>
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL
> gUsbEcmComponentName = {
>
> + UsbEcmComponentNameGetDriverName,
>
> + UsbEcmComponentNameGetControllerName,
>
> + "eng"
>
> +};
>
> +
>
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL
> gUsbEcmComponentName2 = {
>
> + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)UsbEcmComponentNameGetDriverName,
>
> +
> (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)UsbEcmComponentNameGetControllerName,
>
> + "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
>
> +UsbEcmComponentNameGetDriverName (
>
> + IN EFI_COMPONENT_NAME_PROTOCOL *This,
>
> + IN CHAR8 *Language,
>
> + OUT CHAR16 **DriverName
>
> + )
>
> +{
>
> + return LookupUnicodeString2 (
>
> + Language,
>
> + This->SupportedLanguages,
>
> + gUsbEcmDriverNameTable,
>
> + DriverName,
>
> + (BOOLEAN)(This == &gUsbEcmComponentName)
>
> + );
>
> +}
>
> +
>
> +/**
>
> + Retrieves a Unicode string that is the user readable name of the
> controller
>
> + that is being managed by a driver.
>
> +
>
> + This function retrieves the user readable name of the controller
> specified by
>
> + ControllerHandle and ChildHandle in the form of a Unicode string. If the
>
> + driver specified by This has a user readable name in the language
> specified by
>
> + Language, then a pointer to the controller name is returned in
> ControllerName,
>
> + and EFI_SUCCESS is returned. If the driver specified by This is not
> currently
>
> + managing the controller specified by ControllerHandle and ChildHandle,
>
> + then EFI_UNSUPPORTED is returned. If the driver specified by This does
> not
>
> + support the language specified by Language, then EFI_UNSUPPORTED is
> returned.
>
> +
>
> + @param[in] This A pointer to the
> EFI_COMPONENT_NAME2_PROTOCOL or
>
> + EFI_COMPONENT_NAME_PROTOCOL instance.
>
> + @param[in] Controller The handle of a controller that the driver
>
> + specified by This is managing. This
> handle
>
> + specifies the controller whose name is to
> be
>
> + returned.
>
> + @param[in] ChildHandle The handle of the child controller to
> retrieve
>
> + the name of. This is an optional
> parameter that
>
> + may be NULL. It will be NULL for 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
>
> +UsbEcmComponentNameGetControllerName (
>
> + IN EFI_COMPONENT_NAME_PROTOCOL *This,
>
> + IN EFI_HANDLE Controller,
>
> + IN EFI_HANDLE ChildHandle OPTIONAL,
>
> + IN CHAR8 *Language,
>
> + OUT CHAR16 **ControllerName
>
> + )
>
> +{
>
> + return EFI_UNSUPPORTED;
>
> +}
>
> diff --git a/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.c
> b/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.c
> new file mode 100644
> index 0000000000..34f115f48d
> --- /dev/null
> +++ b/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.c
> @@ -0,0 +1,504 @@
> +/** @file
>
> + This file contains code for USB Ethernet Control Model
>
> + Driver
>
> +
>
> + Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
>
> + Subject to AMI licensing agreement.
>
> +**/
>
> +#include "UsbCdcEcm.h"
>
> +
>
> +EFI_GUID gUsbEthProtocolGuid = USB_ETHERNET_PROTOCOL_GUID;
>
> +
>
> +EFI_DRIVER_BINDING_PROTOCOL gUsbEcmDriverBinding = {
>
> + UsbEcmDriverSupported,
>
> + UsbEcmDriverStart,
>
> + UsbEcmDriverStop,
>
> + USB_ECM_DRIVER_VERSION,
>
> + NULL,
>
> + NULL
>
> +};
>
> +
>
> +/**
>
> + Check if this interface is USB ECM SubType
>
> +
>
> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance.
>
> +
>
> + @retval TRUE USB ECM SubType.
>
> + @retval FALSE Not USB ECM SubType.
>
> +
>
> +**/
>
> +BOOLEAN
>
> +IsSupportedDevice (
>
> + IN EFI_USB_IO_PROTOCOL *UsbIo
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
>
> +
>
> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &InterfaceDescriptor);
>
> + if (EFI_ERROR (Status)) {
>
> + return FALSE;
>
> + }
>
> +
>
> + if ((InterfaceDescriptor.InterfaceClass == USB_CDC_CLASS) &&
>
> + (InterfaceDescriptor.InterfaceSubClass == USB_CDC_ECM_SUBCLASS) &&
>
> + (InterfaceDescriptor.InterfaceProtocol == USB_NO_CLASS_PROTOCOL))
>
> + {
>
> + return TRUE;
>
> + }
>
> +
>
> + return FALSE;
>
> +}
>
> +
>
> +/**
>
> + USB ECM Driver Binding Support.
>
> +
>
> + @param[in] This Protocol instance pointer.
>
> + @param[in] ControllerHandle Handle of device to test.
>
> + @param[in] RemainingDevicePath Optional parameter use to pick a
> specific child
>
> + device to start.
>
> +
>
> + @retval EFI_SUCCESS This driver supports this device.
>
> + @retval EFI_ALREADY_STARTED This driver is already running on
> this device.
>
> + @retval other This driver does not support this
> device.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbEcmDriverSupported (
>
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
>
> + IN EFI_HANDLE ControllerHandle,
>
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + EFI_USB_IO_PROTOCOL *UsbIo = NULL;
>
> +
>
> + 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;
>
> +}
>
> +
>
> +/**
>
> + Check if the USB ECM and USB CDC Data interfaces are from the same
> device.
>
> +
>
> + @param[in] UsbEthPath A pointer to the
> EFI_DEVICE_PATH_PROTOCOL instance.
>
> + @param[in] UsbCdcDataPath A pointer to the
> EFI_DEVICE_PATH_PROTOCOL instance.
>
> +
>
> + @retval EFI_SUCCESS Is the same device.
>
> + @retval EFI_NOT_FOUND Is not the same device.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +IsSameDevice (
>
> + IN EFI_DEVICE_PATH_PROTOCOL *UsbEthPath,
>
> + IN EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath
>
> + )
>
> +{
>
> + while (1) {
>
> + if ((UsbEthPath->Type == ACPI_DEVICE_PATH) && (UsbEthPath->SubType ==
> ACPI_DP)) {
>
> + if (CompareMem ((ACPI_HID_DEVICE_PATH *)UsbCdcDataPath,
> (ACPI_HID_DEVICE_PATH *)UsbEthPath, sizeof (ACPI_HID_DEVICE_PATH))) {
>
> + return EFI_NOT_FOUND;
>
> + }
>
> + }
>
> +
>
> + if ((UsbEthPath->Type == HARDWARE_DEVICE_PATH) &&
> (UsbEthPath->SubType == HW_PCI_DP)) {
>
> + if (CompareMem ((PCI_DEVICE_PATH *)UsbCdcDataPath, (PCI_DEVICE_PATH
> *)UsbEthPath, sizeof (PCI_DEVICE_PATH))) {
>
> + return EFI_NOT_FOUND;
>
> + }
>
> + }
>
> +
>
> + if ((UsbEthPath->Type == MESSAGING_DEVICE_PATH) &&
> (UsbEthPath->SubType == MSG_USB_DP)) {
>
> + if (IsDevicePathEnd (NextDevicePathNode (UsbEthPath))) {
>
> + if (((USB_DEVICE_PATH *)UsbEthPath)->ParentPortNumber ==
>
> + ((USB_DEVICE_PATH *)UsbCdcDataPath)->ParentPortNumber)
>
> + {
>
> + return EFI_SUCCESS;
>
> + } else {
>
> + return EFI_NOT_FOUND;
>
> + }
>
> + } else {
>
> + if (CompareMem ((USB_DEVICE_PATH *)UsbCdcDataPath,
> (USB_DEVICE_PATH *)UsbEthPath, sizeof (USB_DEVICE_PATH))) {
>
> + return EFI_NOT_FOUND;
>
> + }
>
> + }
>
> + }
>
> +
>
> + UsbEthPath = NextDevicePathNode (UsbEthPath);
>
> + UsbCdcDataPath = NextDevicePathNode (UsbCdcDataPath);
>
> + }
>
> +}
>
> +
>
> +/**
>
> + Check if the USB CDC Data(UsbIo) installed and return USB CDC Data
> Handle.
>
> +
>
> + @param[in] UsbEthPath A pointer to the
> EFI_DEVICE_PATH_PROTOCOL instance.
>
> + @param[in, out] UsbCdcDataHandle A pointer to the EFI_HANDLE for USB
> CDC Data.
>
> +
>
> + @retval TRUE USB CDC Data(UsbIo) installed.
>
> + @retval FALSE USB CDC Data(UsbIo) did not installed.
>
> +
>
> +**/
>
> +BOOLEAN
>
> +IsUsbCdcData (
>
> + IN EFI_DEVICE_PATH_PROTOCOL *UsbEthPath,
>
> + IN OUT EFI_HANDLE *UsbCdcDataHandle
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN Index;
>
> + UINTN HandleCount;
>
> + EFI_HANDLE *HandleBuffer;
>
> + EFI_USB_IO_PROTOCOL *UsbIo;
>
> + EFI_USB_INTERFACE_DESCRIPTOR Interface;
>
> + EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath;
>
> +
>
> + Status = gBS->LocateHandleBuffer (
>
> + ByProtocol,
>
> + &gEfiUsbIoProtocolGuid,
>
> + NULL,
>
> + &HandleCount,
>
> + &HandleBuffer
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + return FALSE;
>
> + }
>
> +
>
> + for (Index = 0; Index < HandleCount; Index++) {
>
> + Status = gBS->HandleProtocol (
>
> + HandleBuffer[Index],
>
> + &gEfiUsbIoProtocolGuid,
>
> + (VOID **)&UsbIo
>
> + );
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + if ((Interface.InterfaceClass == USB_CDC_DATA_CLASS) &&
>
> + (Interface.InterfaceSubClass == USB_CDC_DATA_SUBCLASS) &&
>
> + (Interface.InterfaceProtocol == USB_NO_CLASS_PROTOCOL))
>
> + {
>
> + Status = gBS->HandleProtocol (
>
> + HandleBuffer[Index],
>
> + &gEfiDevicePathProtocolGuid,
>
> + (VOID **)&UsbCdcDataPath
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + continue;
>
> + }
>
> +
>
> + Status = IsSameDevice (UsbEthPath, UsbCdcDataPath);
>
> + if (!EFI_ERROR (Status)) {
>
> + CopyMem (UsbCdcDataHandle, &HandleBuffer[Index], sizeof
> (EFI_HANDLE));
>
> + gBS->FreePool (HandleBuffer);
>
> + return TRUE;
>
> + }
>
> + }
>
> + }
>
> +
>
> + gBS->FreePool (HandleBuffer);
>
> + return FALSE;
>
> +}
>
> +
>
> +/**
>
> + Call Back Function.
>
> +
>
> + @param[in] Event Event whose notification function is being
> invoked.
>
> + @param[in] Context The pointer to the notification function's
> context,
>
> + which is implementation-dependent.
>
> +
>
> +**/
>
> +VOID
>
> +EFIAPI
>
> +CallbackFunction (
>
> + IN EFI_EVENT Event,
>
> + IN VOID *Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN Index;
>
> + UINTN HandleCount;
>
> + EFI_HANDLE *HandleBuffer;
>
> + EFI_USB_IO_PROTOCOL *UsbIo;
>
> + EFI_USB_INTERFACE_DESCRIPTOR Interface;
>
> +
>
> + Status = 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);
>
> +
>
> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + if ((Interface.InterfaceClass == USB_CDC_CLASS) &&
>
> + (Interface.InterfaceSubClass == USB_CDC_ECM_SUBCLASS) &&
>
> + (Interface.InterfaceProtocol == USB_NO_CLASS_PROTOCOL))
>
> + {
>
> + gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
>
> + }
>
> + }
>
> +
>
> + gBS->FreePool (HandleBuffer);
>
> + gBS->CloseEvent (Event);
>
> +}
>
> +
>
> +/**
>
> + USB ECM Driver Binding Start.
>
> +
>
> + @param[in] This Protocol instance pointer.
>
> + @param[in] ControllerHandle Handle of device to bind driver 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
>
> +UsbEcmDriverStart (
>
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
>
> + IN EFI_HANDLE ControllerHandle,
>
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + VOID *Reg;
>
> + EFI_EVENT Event;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> + EFI_DEVICE_PATH_PROTOCOL *UsbEthPath;
>
> + EFI_HANDLE UsbCdcDataHandle;
>
> + EFI_USB_IO_PROTOCOL *UsbIo;
>
> + EFI_USB_INTERFACE_DESCRIPTOR Interface;
>
> +
>
> + Status = 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_GET_PROTOCOL
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + gBS->CloseProtocol (
>
> + ControllerHandle,
>
> + &gEfiUsbIoProtocolGuid,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle
>
> + );
>
> + return Status;
>
> + }
>
> +
>
> + Status = IsUsbCdcData (UsbEthPath, &UsbCdcDataHandle) ? EFI_SUCCESS :
> EFI_UNSUPPORTED;
>
> + if (EFI_ERROR (Status)) {
>
> + gBS->CloseProtocol (
>
> + ControllerHandle,
>
> + &gEfiUsbIoProtocolGuid,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle
>
> + );
>
> +
>
> + Status = gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
> CallbackFunction, NULL, &Event);
>
> + if (EFI_ERROR (Status)) {
>
> + return Status;
>
> + }
>
> +
>
> + Status = gBS->RegisterProtocolNotify (&gEfiUsbIoProtocolGuid, Event,
> &Reg);
>
> + return Status;
>
> + }
>
> +
>
> + UsbEthDriver = AllocateZeroPool (sizeof (USB_ETHERNET_DRIVER));
>
> + if (!UsbEthDriver) {
>
> + gBS->CloseProtocol (
>
> + ControllerHandle,
>
> + &gEfiUsbIoProtocolGuid,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle
>
> + );
>
> + return EFI_OUT_OF_RESOURCES;
>
> + }
>
> +
>
> + Status = LoadAllDescriptor (UsbIo, &UsbEthDriver->Config);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + GetEndpoint (UsbIo, UsbEthDriver);
>
> +
>
> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + UsbEthDriver->Signature =
> USB_ETHERNET_SIGNATURE;
>
> + UsbEthDriver->NumOfInterface =
> Interface.InterfaceNumber;
>
> + UsbEthDriver->UsbCdcDataHandle = UsbCdcDataHandle;
>
> + UsbEthDriver->UsbIo = UsbIo;
>
> + UsbEthDriver->UsbEth.UsbEthReceive = UsbEthReceive;
>
> + UsbEthDriver->UsbEth.UsbEthTransmit = UsbEthTransmit;
>
> + UsbEthDriver->UsbEth.UsbEthInterrupt = UsbEthInterrupt;
>
> + UsbEthDriver->UsbEth.UsbEthMacAddress = GetUsbEthMacAddress;
>
> + UsbEthDriver->UsbEth.UsbEthMaxBulkSize = UsbEthBulkSize;
>
> + UsbEthDriver->UsbEth.UsbHeaderFunDescriptor =
> GetUsbHeaderFunDescriptor;
>
> + UsbEthDriver->UsbEth.UsbUnionFunDescriptor =
> GetUsbUnionFunDescriptor;
>
> + UsbEthDriver->UsbEth.UsbEthFunDescriptor =
> GetUsbEthFunDescriptor;
>
> + UsbEthDriver->UsbEth.SetUsbEthMcastFilter = SetUsbEthMcastFilter;
>
> + UsbEthDriver->UsbEth.SetUsbEthPowerPatternFilter = SetUsbEthPowerFilter;
>
> + UsbEthDriver->UsbEth.GetUsbEthPoewrPatternFilter = GetUsbEthPowerFilter;
>
> + UsbEthDriver->UsbEth.SetUsbEthPacketFilter =
> SetUsbEthPacketFilter;
>
> + UsbEthDriver->UsbEth.GetUsbEthStatistic = GetUsbEthStatistic;
>
> +
>
> + Status = gBS->InstallProtocolInterface (
>
> + &ControllerHandle,
>
> + &gUsbEthProtocolGuid,
>
> + EFI_NATIVE_INTERFACE,
>
> + &(UsbEthDriver->UsbEth)
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + gBS->CloseProtocol (
>
> + ControllerHandle,
>
> + &gEfiUsbIoProtocolGuid,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle
>
> + );
>
> + gBS->FreePool (UsbEthDriver);
>
> + return Status;
>
> + }
>
> +
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + USB ECM Driver Binding Stop.
>
> +
>
> + @param[in] This Protocol instance pointer.
>
> + @param[in] ControllerHandle Handle of device to stop driver on
>
> + @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer.
> If number of
>
> + children is zero stop the entire bus
> driver.
>
> + @param[in] ChildHandleBuffer List of Child Handles to Stop.
>
> +
>
> + @retval EFI_SUCCESS This driver is removed ControllerHandle
>
> + @retval other This driver was not removed from this
> device
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbEcmDriverStop (
>
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
>
> + IN EFI_HANDLE ControllerHandle,
>
> + IN UINTN NumberOfChildren,
>
> + IN EFI_HANDLE *ChildHandleBuffer
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + USB_ETHERNET_PROTOCOL *UsbEthProtocol;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> +
>
> + Status = gBS->OpenProtocol (
>
> + ControllerHandle,
>
> + &gUsbEthProtocolGuid,
>
> + (VOID **)&UsbEthProtocol,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle,
>
> + EFI_OPEN_PROTOCOL_GET_PROTOCOL
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + return Status;
>
> + }
>
> +
>
> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (UsbEthProtocol);
>
> +
>
> + Status = gBS->UninstallProtocolInterface (
>
> + ControllerHandle,
>
> + &gUsbEthProtocolGuid,
>
> + UsbEthProtocol
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + return Status;
>
> + }
>
> +
>
> + Status = gBS->CloseProtocol (
>
> + ControllerHandle,
>
> + &gEfiUsbIoProtocolGuid,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle
>
> + );
>
> + gBS->FreePool (UsbEthDriver->Config);
>
> + gBS->FreePool (UsbEthDriver);
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + Entrypoint of ECM Driver.
>
> +
>
> + This function is the entrypoint of ECM Driver. It installs Driver
> Binding
>
> + Protocols together with Component Name Protocols.
>
> +
>
> + @param[in] ImageHandle The firmware allocated handle for the EFI
> image.
>
> + @param[in] SystemTable A pointer to the EFI System Table.
>
> +
>
> + @retval EFI_SUCCESS The entry point is executed successfully.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbEcmEntry (
>
> + IN EFI_HANDLE ImageHandle,
>
> + IN EFI_SYSTEM_TABLE *SystemTable
>
> + )
>
> +{
>
> + gUsbEcmDriverBinding.DriverBindingHandle = ImageHandle;
>
> + gUsbEcmDriverBinding.ImageHandle = ImageHandle;
>
> +
>
> + return gBS->InstallMultipleProtocolInterfaces (
>
> + &gUsbEcmDriverBinding.DriverBindingHandle,
>
> + &gEfiDriverBindingProtocolGuid,
>
> + &gUsbEcmDriverBinding,
>
> + &gEfiComponentName2ProtocolGuid,
>
> + &gUsbEcmComponentName2,
>
> + NULL
>
> + );
>
> +}
>
> diff --git a/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.h
> b/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.h
> new file mode 100644
> index 0000000000..52a818466e
> --- /dev/null
> +++ b/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.h
> @@ -0,0 +1,211 @@
> +/** @file
>
> + Header file contains code for USB Ethernet Control Model
>
> + driver definitions
>
> +
>
> + Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
>
> + Subject to AMI licensing agreement.
>
> +**/
>
> +
>
> +#ifndef _USB_CDC_ECM_H_
>
> +#define _USB_CDC_ECM_H_
>
> +
>
> +#include <Library/UefiDriverEntryPoint.h>
>
> +#include <Library/UefiBootServicesTableLib.h>
>
> +#include <Library/UefiLib.h>
>
> +#include <Library/DevicePathLib.h>
>
> +#include <Library/DebugLib.h>
>
> +#include <Library/MemoryAllocationLib.h>
>
> +#include <Library/BaseMemoryLib.h>
>
> +#include <Library/UefiUsbLib.h>
>
> +#include <Protocol/UsbIo.h>
>
> +#include <Protocol/UsbEthernetProtocol.h>
>
> +
>
> +typedef struct {
>
> + UINTN Signature;
>
> + USB_ETHERNET_PROTOCOL UsbEth;
>
> + EFI_HANDLE UsbCdcDataHandle;
>
> + EFI_USB_IO_PROTOCOL *UsbIo;
>
> + EFI_USB_CONFIG_DESCRIPTOR *Config;
>
> + UINT8 NumOfInterface;
>
> + UINT8 BulkInEndpoint;
>
> + UINT8 BulkOutEndpoint;
>
> + UINT8 InterruptEndpoint;
>
> + EFI_MAC_ADDRESS MacAddress;
>
> +} USB_ETHERNET_DRIVER;
>
> +
>
> +#define USB_ECM_DRIVER_VERSION 1
>
> +#define USB_ETHERNET_BULK_TIMEOUT 1
>
> +#define USB_ETHERNET_TRANSFER_TIMEOUT 200
>
> +
>
> +#define USB_ETHERNET_SIGNATURE SIGNATURE_32('u', 'e', 't', 'h')
>
> +#define USB_ETHERNET_DEV_FROM_THIS(a) CR (a, USB_ETHERNET_DRIVER,
> UsbEth, USB_ETHERNET_SIGNATURE)
>
> +
>
> +typedef struct {
>
> + UINT16 Src;
>
> + UINT16 Dst;
>
> +} BIT_MAP;
>
> +
>
> +extern EFI_COMPONENT_NAME2_PROTOCOL gUsbEcmComponentName2;
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbEcmDriverSupported (
>
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
>
> + IN EFI_HANDLE ControllerHandle,
>
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbEcmDriverStart (
>
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
>
> + IN EFI_HANDLE ControllerHandle,
>
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbEcmDriverStop (
>
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
>
> + IN EFI_HANDLE ControllerHandle,
>
> + IN UINTN NumberOfChildren,
>
> + IN EFI_HANDLE *ChildHandleBuffer
>
> + );
>
> +
>
> +EFI_STATUS
>
> +LoadAllDescriptor (
>
> + IN EFI_USB_IO_PROTOCOL *UsbIo,
>
> + OUT EFI_USB_CONFIG_DESCRIPTOR **ConfigDesc
>
> + );
>
> +
>
> +BOOLEAN
>
> +NextDescriptor (
>
> + IN EFI_USB_CONFIG_DESCRIPTOR *Desc,
>
> + IN OUT UINTN *Offset
>
> + );
>
> +
>
> +EFI_STATUS
>
> +GetFunctionalDescriptor (
>
> + IN EFI_USB_CONFIG_DESCRIPTOR *Config,
>
> + IN UINT8 FunDescriptorType,
>
> + OUT VOID *DataBuffer
>
> + );
>
> +
>
> +VOID
>
> +GetEndpoint (
>
> + IN EFI_USB_IO_PROTOCOL *UsbIo,
>
> + IN OUT USB_ETHERNET_DRIVER *UsbEthDriver
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbEthReceive (
>
> + IN PXE_CDB *Cdb,
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN OUT VOID *Packet,
>
> + IN OUT UINTN *PacketLength
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbEthTransmit (
>
> + IN PXE_CDB *Cdb,
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN VOID *Packet,
>
> + IN OUT UINTN *PacketLength
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbEthInterrupt (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN BOOLEAN IsNewTransfer,
>
> + IN UINTN PollingInterval,
>
> + IN EFI_USB_DEVICE_REQUEST *Request
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +InterruptCallback (
>
> + IN VOID *Data,
>
> + IN UINTN DataLength,
>
> + IN VOID *Context,
>
> + IN UINT32 Status
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetUsbEthMacAddress (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT EFI_MAC_ADDRESS *MacAddress
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbEthBulkSize (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT UINTN *BulkSize
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetUsbHeaderFunDescriptor (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetUsbUnionFunDescriptor (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetUsbEthFunDescriptor (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +SetUsbEthMcastFilter (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value,
>
> + IN VOID *McastAddr
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +SetUsbEthPowerFilter (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value,
>
> + IN UINT16 Length,
>
> + IN VOID *PatternFilter
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetUsbEthPowerFilter (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value,
>
> + OUT BOOLEAN *PatternActive
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +SetUsbEthPacketFilter (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetUsbEthStatistic (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 FeatureSelector,
>
> + OUT VOID *Statistic
>
> + );
>
> +
>
> +#endif
>
> diff --git a/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf
> b/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf
> new file mode 100644
> index 0000000000..ed031864c6
> --- /dev/null
> +++ b/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf
> @@ -0,0 +1,41 @@
> +## @file
> +# This is Usb Cdc Ecm driver for DXE phase.
> +#
> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
> +# Subject to AMI licensing agreement.
> +##
> +
> +[Defines]
> + INF_VERSION = 0x00010005
> + BASE_NAME = UsbCdcEcm
> + FILE_GUID = 07a84945-685d-48ec-a6a1-1b397579fa76
> + MODULE_TYPE = DXE_DRIVER
> + VERSION_STRING = 1.0
> + ENTRY_POINT = UsbEcmEntry
> +
> +[Sources]
> + UsbCdcEcm.c
> + UsbCdcEcm.h
> + UsbEcmFunction.c
> + ComponentName.c
> +
> +[Packages]
> + MdePkg/MdePkg.dec
> + UsbNetworkPkg/UsbNetworkPkg.dec
> +
> +[LibraryClasses]
> + UefiDriverEntryPoint
> + UefiBootServicesTableLib
> + UefiLib
> + DebugLib
> + UefiUsbLib
> + MemoryAllocationLib
> + BaseMemoryLib
> +
> +[Protocols]
> + gEfiUsbIoProtocolGuid
> + gEfiDevicePathProtocolGuid
> + gEfiDriverBindingProtocolGuid
> +
> +[Depex]
> + TRUE
> diff --git a/UsbNetworkPkg/UsbCdcEcm/UsbEcmFunction.c
> b/UsbNetworkPkg/UsbCdcEcm/UsbEcmFunction.c
> new file mode 100644
> index 0000000000..175addddc6
> --- /dev/null
> +++ b/UsbNetworkPkg/UsbCdcEcm/UsbEcmFunction.c
> @@ -0,0 +1,861 @@
> +/** @file
>
> + This file contains code for USB Ethernet descriptor
>
> + and specific requests implement.
>
> +
>
> + Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
>
> + Subject to AMI licensing agreement.
>
> +**/
>
> +
>
> +#include "UsbCdcEcm.h"
>
> +
>
> +/**
>
> + 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);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + Status = gBS->AllocatePool (EfiBootServicesData, Tmp.TotalLength, (VOID
> **)ConfigDesc);
>
> + ASSERT_EFI_ERROR (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 = EFI_NOT_FOUND;
>
> + UINTN Offset;
>
> + EFI_USB_INTERFACE_DESCRIPTOR *Interface;
>
> +
>
> + 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] UsbEthDriver A pointer to the USB_ETHERNET_DRIVER
> instance.
>
> +
>
> +**/
>
> +VOID
>
> +GetEndpoint (
>
> + IN EFI_USB_IO_PROTOCOL *UsbIo,
>
> + IN OUT USB_ETHERNET_DRIVER *UsbEthDriver
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINT8 Index;
>
> + UINT32 Result;
>
> + EFI_USB_INTERFACE_DESCRIPTOR Interface;
>
> + EFI_USB_ENDPOINT_DESCRIPTOR Endpoint;
>
> +
>
> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + if (Interface.NumEndpoints == 0) {
>
> + Status = UsbSetInterface (UsbIo, Interface.InterfaceNumber, 1,
> &Result);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
>
> + ASSERT_EFI_ERROR (Status);
>
> + }
>
> +
>
> + for (Index = 0; Index < Interface.NumEndpoints; Index++) {
>
> + Status = UsbIo->UsbGetEndpointDescriptor (UsbIo, Index, &Endpoint);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + switch ((Endpoint.Attributes & (BIT0 | BIT1))) {
>
> + case USB_ENDPOINT_BULK:
>
> + if (Endpoint.EndpointAddress & BIT7) {
>
> + UsbEthDriver->BulkInEndpoint = Endpoint.EndpointAddress;
>
> + } else {
>
> + UsbEthDriver->BulkOutEndpoint = Endpoint.EndpointAddress;
>
> + }
>
> +
>
> + break;
>
> + case USB_ENDPOINT_INTERRUPT:
>
> + UsbEthDriver->InterruptEndpoint = Endpoint.EndpointAddress;
>
> + break;
>
> + }
>
> + }
>
> +}
>
> +
>
> +/**
>
> + This function is used to manage a USB device with the bulk transfer
> pipe. The endpoint is Bulk in.
>
> +
>
> + @param[in] Cdb A pointer to the command descriptor block.
>
> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL
> instance.
>
> + @param[in, out] Packet A pointer to the buffer of data that will
> be transmitted to USB
>
> + device or received from USB device.
>
> + @param[in, out] PacketLength A pointer to the PacketLength.
>
> +
>
> + @retval EFI_SUCCESS The bulk transfer has been successfully
> executed.
>
> + @retval EFI_DEVICE_ERROR The transfer failed. The transfer status
> is returned in status.
>
> + @retval EFI_INVALID_PARAMETE One or more parameters are invalid.
>
> + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due to
> a lack of resources.
>
> + @retval EFI_TIMEOUT The control transfer fails due to timeout.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbEthReceive (
>
> + IN PXE_CDB *Cdb,
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN OUT VOID *Packet,
>
> + IN OUT UINTN *PacketLength
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> + EFI_USB_IO_PROTOCOL *UsbIo;
>
> + UINT32 TransStatus;
>
> +
>
> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
>
> +
>
> + Status = gBS->HandleProtocol (
>
> + UsbEthDriver->UsbCdcDataHandle,
>
> + &gEfiUsbIoProtocolGuid,
>
> + (VOID **)&UsbIo
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + return Status;
>
> + }
>
> +
>
> + if (UsbEthDriver->BulkInEndpoint == 0) {
>
> + GetEndpoint (UsbIo, UsbEthDriver);
>
> + }
>
> +
>
> + Status = UsbIo->UsbBulkTransfer (
>
> + UsbIo,
>
> + UsbEthDriver->BulkInEndpoint,
>
> + Packet,
>
> + PacketLength,
>
> + USB_ETHERNET_BULK_TIMEOUT,
>
> + &TransStatus
>
> + );
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + This function is used to manage a USB device with the bulk transfer
> pipe. The endpoint is Bulk out.
>
> +
>
> + @param[in] Cdb A pointer to the command descriptor block.
>
> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL
> instance.
>
> + @param[in] Packet A pointer to the buffer of data that will
> be transmitted to USB
>
> + device or received from USB device.
>
> + @param[in, out] PacketLength A pointer to the PacketLength.
>
> +
>
> + @retval EFI_SUCCESS The bulk transfer has been successfully
> executed.
>
> + @retval EFI_DEVICE_ERROR The transfer failed. The transfer status
> is returned in status.
>
> + @retval EFI_INVALID_PARAMETE One or more parameters are invalid.
>
> + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due to
> a lack of resources.
>
> + @retval EFI_TIMEOUT The control transfer fails due to timeout.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbEthTransmit (
>
> + IN PXE_CDB *Cdb,
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN VOID *Packet,
>
> + IN OUT UINTN *PacketLength
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> + EFI_USB_IO_PROTOCOL *UsbIo;
>
> + UINT32 TransStatus;
>
> +
>
> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
>
> +
>
> + Status = gBS->HandleProtocol (
>
> + UsbEthDriver->UsbCdcDataHandle,
>
> + &gEfiUsbIoProtocolGuid,
>
> + (VOID **)&UsbIo
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + return Status;
>
> + }
>
> +
>
> + if (UsbEthDriver->BulkOutEndpoint == 0) {
>
> + GetEndpoint (UsbIo, UsbEthDriver);
>
> + }
>
> +
>
> + Status = UsbIo->UsbBulkTransfer (
>
> + UsbIo,
>
> + UsbEthDriver->BulkOutEndpoint,
>
> + Packet,
>
> + PacketLength,
>
> + USB_ETHERNET_BULK_TIMEOUT,
>
> + &TransStatus
>
> + );
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + Async USB transfer callback routine.
>
> +
>
> + @param[in] Data Data received or sent via the USB
> Asynchronous Transfer, if the
>
> + transfer completed successfully.
>
> + @param[in] DataLength The length of Data received or sent via the
> Asynchronous
>
> + Transfer, if transfer successfully
> completes.
>
> + @param[in] Context Data passed from
> UsbAsyncInterruptTransfer() request.
>
> + @param[in] Status Indicates the result of the asynchronous
> transfer.
>
> +
>
> + @retval EFI_SUCCESS The asynchronous USB transfer request has
> been successfully executed.
>
> + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request
> failed.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +InterruptCallback (
>
> + IN VOID *Data,
>
> + IN UINTN DataLength,
>
> + IN VOID *Context,
>
> + IN UINT32 Status
>
> + )
>
> +{
>
> + if (((EFI_USB_DEVICE_REQUEST *)Data)->Request ==
> USB_CDC_NETWORK_CONNECTION) {
>
> + CopyMem (
>
> + (EFI_USB_DEVICE_REQUEST *)Context,
>
> + (EFI_USB_DEVICE_REQUEST *)Data,
>
> + sizeof (EFI_USB_DEVICE_REQUEST)
>
> + );
>
> + }
>
> +
>
> + return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> + This function is used to manage a USB device with an interrupt transfer
> pipe.
>
> +
>
> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL
> instance.
>
> + @param[in] IsNewTransfer If TRUE, a new transfer will be submitted
> to USB controller. If
>
> + FALSE, the interrupt transfer is 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
>
> +UsbEthInterrupt (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN BOOLEAN IsNewTransfer,
>
> + IN UINTN PollingInterval,
>
> + IN EFI_USB_DEVICE_REQUEST *Request
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> + UINTN DataLength = 0;
>
> +
>
> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
>
> + if (IsNewTransfer == TRUE) {
>
> + DataLength = sizeof (EFI_USB_DEVICE_REQUEST) + sizeof
> (USB_CONNECT_SPEED_CHANGE);
>
> + Status = UsbEthDriver->UsbIo->UsbAsyncInterruptTransfer (
>
> + UsbEthDriver->UsbIo,
>
> + UsbEthDriver->InterruptEndpoint,
>
> + IsNewTransfer,
>
> + PollingInterval,
>
> + DataLength,
>
> +
> (EFI_ASYNC_USB_TRANSFER_CALLBACK)InterruptCallback,
>
> + Request
>
> + );
>
> + } else {
>
> + Status = UsbEthDriver->UsbIo->UsbAsyncInterruptTransfer (
>
> + UsbEthDriver->UsbIo,
>
> + UsbEthDriver->InterruptEndpoint,
>
> + IsNewTransfer,
>
> + 0,
>
> + 0,
>
> + NULL,
>
> + NULL
>
> + );
>
> + }
>
> +
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + Retrieves the USB Ethernet Mac Address.
>
> +
>
> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL
> instance.
>
> + @param[out] MacAddress A pointer to the caller allocated USB
> Ethernet Mac Address.
>
> +
>
> + @retval EFI_SUCCESS The USB Header Functional descriptor 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 USB_ETHERNET_PROTOCOL *This,
>
> + OUT EFI_MAC_ADDRESS *MacAddress
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthDescriptor;
>
> + CHAR16 *Data;
>
> + CHAR16 *DataPtr;
>
> + CHAR16 TmpStr[1];
>
> + UINT8 Index;
>
> + UINT8 Hi;
>
> + UINT8 Low;
>
> +
>
> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
>
> +
>
> + Status = This->UsbEthFunDescriptor (This, &UsbEthDescriptor);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + Status = UsbEthDriver->UsbIo->UsbGetStringDescriptor (
>
> + UsbEthDriver->UsbIo,
>
> + 0x409, //
> English-US Language ID
>
> + UsbEthDescriptor.MacAddress,
>
> + &Data
>
> + );
>
> + ASSERT_EFI_ERROR (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 USB_ETHERNET_PROTOCOL
> instance.
>
> + @param[out] BulkSize A pointer to the Bulk transfer data size.
>
> +
>
> + @retval EFI_SUCCESS The bulk transfer data size was retrieved
> successfully.
>
> + @retval other Failed to retrieve the bulk transfer data
> size.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbEthBulkSize (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT UINTN *BulkSize
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor;
>
> +
>
> + Status = 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
> 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 USB_ETHERNET_PROTOCOL *This,
>
> + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> +
>
> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
>
> +
>
> + if (UsbHeaderFunDescriptor == NULL) {
>
> + return EFI_INVALID_PARAMETER;
>
> + }
>
> +
>
> + Status = GetFunctionalDescriptor (UsbEthDriver->Config,
> HEADER_FUN_DESCRIPTOR, UsbHeaderFunDescriptor);
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + Retrieves the USB Union functional Descriptor.
>
> +
>
> + @param[in] This A pointer to the
> USB_ETHERNET_PROTOCOL instance.
>
> + @param[out] UsbUnionFunDescriptor A pointer to the caller allocated
> USB Union Functional Descriptor.
>
> +
>
> + @retval EFI_SUCCESS The USB Union Functional descriptor was
> retrieved successfully.
>
> + @retval EFI_INVALID_PARAMETER UsbUnionFunDescriptor is NULL.
>
> + @retval EFI_NOT_FOUND The USB Union Functional descriptor was
> not found.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetUsbUnionFunDescriptor (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> +
>
> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
>
> +
>
> + if (UsbUnionFunDescriptor == NULL) {
>
> + return EFI_INVALID_PARAMETER;
>
> + }
>
> +
>
> + Status = GetFunctionalDescriptor (UsbEthDriver->Config,
> UNION_FUN_DESCRIPTOR, UsbUnionFunDescriptor);
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + Retrieves the USB Ethernet functional Descriptor.
>
> +
>
> + @param[in] This A pointer to the
> USB_ETHERNET_PROTOCOL instance.
>
> + @param[out] UsbEthFunDescriptor A pointer to the caller allocated
> USB Ethernet Functional Descriptor.
>
> +
>
> + @retval EFI_SUCCESS The USB Ethernet Functional descriptor
> was retrieved successfully.
>
> + @retval EFI_INVALID_PARAMETER UsbEthFunDescriptor is NULL.
>
> + @retval EFI_NOT_FOUND The USB Ethernet Functional descriptor
> was not found.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetUsbEthFunDescriptor (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> +
>
> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
>
> +
>
> + if (UsbEthFunDescriptor == NULL) {
>
> + return EFI_INVALID_PARAMETER;
>
> + }
>
> +
>
> + Status = GetFunctionalDescriptor (UsbEthDriver->Config,
> ETHERNET_FUN_DESCRIPTOR, UsbEthFunDescriptor);
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + This request sets the Ethernet device multicast filters as specified in
> the
>
> + sequential list of 48 bit Ethernet multicast addresses.
>
> +
>
> + @param[in] This A pointer to the
> USB_ETHERNET_PROTOCOL instance.
>
> + @param[in] Value Number of filters.
>
> + @param[in] McastAddr A pointer to the value of the
> multicast addresses.
>
> +
>
> + @retval EFI_SUCCESS The request executed successfully.
>
> + @retval EFI_TIMEOUT A timeout occurred executing the 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
>
> +SetUsbEthMcastFilter (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value,
>
> + IN VOID *McastAddr
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + EFI_USB_DEVICE_REQUEST Request;
>
> + UINT32 TransStatus;
>
> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> +
>
> + UsbEthDriver = USB_ETHERNET_DEV_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_ETHRTNET_SET_REQ_TYPE;
>
> + Request.Request = SET_ETH_MULTICAST_FILTERS_REQ;
>
> + Request.Value = Value;
>
> + Request.Index = UsbEthDriver->NumOfInterface;
>
> + Request.Length = Value * 6;
>
> +
>
> + return UsbEthDriver->UsbIo->UsbControlTransfer (
>
> + UsbEthDriver->UsbIo,
>
> + &Request,
>
> + EfiUsbDataOut,
>
> + USB_ETHERNET_TRANSFER_TIMEOUT,
>
> + McastAddr,
>
> + Request.Length,
>
> + &TransStatus
>
> + );
>
> +}
>
> +
>
> +/**
>
> + This request sets up the specified Ethernet power management pattern
> filter as
>
> + described in the data structure.
>
> +
>
> + @param[in] This A pointer to the
> USB_ETHERNET_PROTOCOL instance.
>
> + @param[in] Value Number of filters.
>
> + @param[in] Length Size of the power management 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
>
> +SetUsbEthPowerFilter (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value,
>
> + IN UINT16 Length,
>
> + IN VOID *PatternFilter
>
> + )
>
> +{
>
> + EFI_USB_DEVICE_REQUEST Request;
>
> + UINT32 TransStatus;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> +
>
> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
>
> +
>
> + Request.RequestType = USB_ETHRTNET_SET_REQ_TYPE;
>
> + Request.Request = SET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ;
>
> + Request.Value = Value;
>
> + Request.Index = UsbEthDriver->NumOfInterface;
>
> + Request.Length = Length;
>
> +
>
> + return UsbEthDriver->UsbIo->UsbControlTransfer (
>
> + UsbEthDriver->UsbIo,
>
> + &Request,
>
> + EfiUsbDataOut,
>
> + USB_ETHERNET_TRANSFER_TIMEOUT,
>
> + PatternFilter,
>
> + Length,
>
> + &TransStatus
>
> + );
>
> +}
>
> +
>
> +/**
>
> + This request retrieves the status of the specified Ethernet power
> management
>
> + pattern filter from the device.
>
> +
>
> + @param[in] This A pointer to the
> USB_ETHERNET_PROTOCOL instance.
>
> + @param[in] Value The filter number.
>
> + @param[out] PatternActive A pointer to the pattern active
> boolean.
>
> +
>
> + @retval EFI_SUCCESS The request executed successfully.
>
> + @retval EFI_TIMEOUT A timeout occurred executing the 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
>
> +GetUsbEthPowerFilter (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value,
>
> + OUT BOOLEAN *PatternActive
>
> + )
>
> +{
>
> + EFI_USB_DEVICE_REQUEST Request;
>
> + UINT32 TransStatus;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> +
>
> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
>
> +
>
> + Request.RequestType = USB_ETHERNET_GET_REQ_TYPE;
>
> + Request.Request = GET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ;
>
> + Request.Value = Value;
>
> + Request.Index = UsbEthDriver->NumOfInterface;
>
> + Request.Length = USB_ETH_POWER_FILTER_LENGTH;
>
> +
>
> + return UsbEthDriver->UsbIo->UsbControlTransfer (
>
> + UsbEthDriver->UsbIo,
>
> + &Request,
>
> + EfiUsbDataIn,
>
> + USB_ETHERNET_TRANSFER_TIMEOUT,
>
> + PatternActive,
>
> + USB_ETH_POWER_FILTER_LENGTH,
>
> + &TransStatus
>
> + );
>
> +}
>
> +
>
> +BIT_MAP gTable[] = {
>
> + { PXE_OPFLAGS_RECEIVE_FILTER_UNICAST,
> USB_ETH_PACKET_TYPE_DIRECTED },
>
> + { PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST,
> USB_ETH_PACKET_TYPE_BROADCAST },
>
> + { PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST,
> USB_ETH_PACKET_TYPE_MULTICAST },
>
> + { PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS,
> USB_ETH_PACKET_TYPE_PROMISCUOUS },
>
> + { PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST,
> USB_ETH_PACKET_TYPE_ALL_MULTICAST },
>
> +};
>
> +
>
> +/**
>
> + Convert value between PXE receive filter and USB ETH packet filter.
>
> +
>
> + @param[in] Value PXE filter data.
>
> + @param[out] CdcFilter A pointer to the Ethernet Packet Filter Bitmap
> value converted by PXE_OPFLAGS.
>
> +
>
> +**/
>
> +VOID
>
> +ConvertFilter (
>
> + IN UINT16 Value,
>
> + OUT UINT16 *CdcFilter
>
> + )
>
> +{
>
> + UINT32 Index;
>
> + UINT32 Count;
>
> +
>
> + Count = sizeof (gTable)/sizeof (gTable[0]);
>
> +
>
> + for (Index = 0; (gTable[Index].Src != 0) && (Index < Count); Index++) {
>
> + if (gTable[Index].Src & Value) {
>
> + *CdcFilter |= gTable[Index].Dst;
>
> + }
>
> + }
>
> +}
>
> +
>
> +/**
>
> + This request is used to configure device Ethernet packet filter
> settings.
>
> +
>
> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL
> instance.
>
> + @param[in] Value Packet Filter Bitmap.
>
> +
>
> + @retval EFI_SUCCESS The request executed successfully.
>
> + @retval EFI_TIMEOUT A timeout occurred executing the 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
>
> +SetUsbEthPacketFilter (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value
>
> + )
>
> +{
>
> + EFI_USB_DEVICE_REQUEST Request;
>
> + UINT32 TransStatus;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> + UINT16 CommandFilter = 0;
>
> +
>
> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
>
> +
>
> + ConvertFilter (Value, &CommandFilter);
>
> +
>
> + Request.RequestType = USB_ETHRTNET_SET_REQ_TYPE;
>
> + Request.Request = SET_ETH_PACKET_FILTER_REQ;
>
> + Request.Value = CommandFilter;
>
> + Request.Index = UsbEthDriver->NumOfInterface;
>
> + Request.Length = USB_ETH_PACKET_FILTER_LENGTH;
>
> +
>
> + return UsbEthDriver->UsbIo->UsbControlTransfer (
>
> + UsbEthDriver->UsbIo,
>
> + &Request,
>
> + EfiUsbNoData,
>
> + USB_ETHERNET_TRANSFER_TIMEOUT,
>
> + NULL,
>
> + USB_ETH_PACKET_FILTER_LENGTH,
>
> + &TransStatus
>
> + );
>
> +}
>
> +
>
> +/**
>
> + This request is used to retrieve a statistic based on the feature
> selector.
>
> +
>
> + @param[in] This A pointer to the
> USB_ETHERNET_PROTOCOL instance.
>
> + @param[in] FeatureSelector Value of the feature selector.
>
> + @param[out] Statistic A pointer to the 32 bit unsigned
> integer.
>
> +
>
> + @retval EFI_SUCCESS The request executed successfully.
>
> + @retval EFI_TIMEOUT A timeout occurred executing the 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
>
> +GetUsbEthStatistic (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 FeatureSelector,
>
> + OUT VOID *Statistic
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + EFI_USB_DEVICE_REQUEST Request;
>
> + UINT32 TransStatus;
>
> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> +
>
> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
>
> +
>
> + Status = This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor);
>
> + if (EFI_ERROR (Status)) {
>
> + return Status;
>
> + }
>
> +
>
> + if (UsbEthFunDescriptor.EthernetStatistics == 0) {
>
> + return EFI_UNSUPPORTED;
>
> + }
>
> +
>
> + Request.RequestType = USB_ETHERNET_GET_REQ_TYPE;
>
> + Request.Request = GET_ETH_STATISTIC_REQ;
>
> + Request.Value = FeatureSelector;
>
> + Request.Index = UsbEthDriver->NumOfInterface;
>
> + Request.Length = USB_ETH_STATISTIC;
>
> +
>
> + return UsbEthDriver->UsbIo->UsbControlTransfer (
>
> + UsbEthDriver->UsbIo,
>
> + &Request,
>
> + EfiUsbDataIn,
>
> + USB_ETHERNET_TRANSFER_TIMEOUT,
>
> + Statistic,
>
> + USB_ETH_STATISTIC,
>
> + &TransStatus
>
> + );
>
> +}
>
> diff --git a/UsbNetworkPkg/UsbCdcNcm/ComponentName.c
> b/UsbNetworkPkg/UsbCdcNcm/ComponentName.c
> new file mode 100644
> index 0000000000..36792b89c5
> --- /dev/null
> +++ b/UsbNetworkPkg/UsbCdcNcm/ComponentName.c
> @@ -0,0 +1,170 @@
> +/** @file
>
> + This file contains code for USB Ncm Driver Component Name definitions
>
> +
>
> + Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
>
> + Subject to AMI licensing agreement.
>
> +**/
>
> +#include "UsbCdcNcm.h"
>
> +
>
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE
> gUsbNcmDriverNameTable[] = {
>
> + {
>
> + "eng;en",
>
> + L"USB NCM Driver"
>
> + },
>
> + {
>
> + NULL,
>
> + NULL
>
> + }
>
> +};
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbNcmComponentNameGetDriverName (
>
> + IN EFI_COMPONENT_NAME_PROTOCOL *This,
>
> + IN CHAR8 *Language,
>
> + OUT CHAR16 **DriverName
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbNcmComponentNameGetControllerName (
>
> + IN EFI_COMPONENT_NAME_PROTOCOL *This,
>
> + IN EFI_HANDLE Controller,
>
> + IN EFI_HANDLE ChildHandle OPTIONAL,
>
> + IN CHAR8 *Language,
>
> + OUT CHAR16 **ControllerName
>
> + );
>
> +
>
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL
> gUsbNcmComponentName = {
>
> + UsbNcmComponentNameGetDriverName,
>
> + UsbNcmComponentNameGetControllerName,
>
> + "eng"
>
> +};
>
> +
>
> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL
> gUsbNcmComponentName2 = {
>
> + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)UsbNcmComponentNameGetDriverName,
>
> +
> (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)UsbNcmComponentNameGetControllerName,
>
> + "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
>
> +UsbNcmComponentNameGetDriverName (
>
> + IN EFI_COMPONENT_NAME_PROTOCOL *This,
>
> + IN CHAR8 *Language,
>
> + OUT CHAR16 **DriverName
>
> + )
>
> +{
>
> + return LookupUnicodeString2 (
>
> + Language,
>
> + This->SupportedLanguages,
>
> + gUsbNcmDriverNameTable,
>
> + DriverName,
>
> + (BOOLEAN)(This == &gUsbNcmComponentName)
>
> + );
>
> +}
>
> +
>
> +/**
>
> + Retrieves a Unicode string that is the user readable name of the
> controller
>
> + that is being managed by a driver.
>
> +
>
> + This function retrieves the user readable name of the controller
> specified by
>
> + ControllerHandle and ChildHandle in the form of a Unicode string. If the
>
> + driver specified by This has a user readable name in the language
> specified by
>
> + Language, then a pointer to the controller name is returned in
> ControllerName,
>
> + and EFI_SUCCESS is returned. If the driver specified by This is not
> currently
>
> + managing the controller specified by ControllerHandle and ChildHandle,
>
> + then EFI_UNSUPPORTED is returned. If the driver specified by This does
> not
>
> + support the language specified by Language, then EFI_UNSUPPORTED is
> returned.
>
> +
>
> + @param[in] This A pointer to the
> EFI_COMPONENT_NAME2_PROTOCOL or
>
> + EFI_COMPONENT_NAME_PROTOCOL instance.
>
> + @param[in] Controller The handle of a controller that the driver
>
> + specified by This is managing. This
> handle
>
> + specifies the controller whose name is to
> be
>
> + returned.
>
> + @param[in] ChildHandle The handle of the child controller to
> retrieve
>
> + the name of. This is an optional
> parameter that
>
> + may be NULL. It will be NULL for 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
>
> +UsbNcmComponentNameGetControllerName (
>
> + IN EFI_COMPONENT_NAME_PROTOCOL *This,
>
> + IN EFI_HANDLE Controller,
>
> + IN EFI_HANDLE ChildHandle OPTIONAL,
>
> + IN CHAR8 *Language,
>
> + OUT CHAR16 **ControllerName
>
> + )
>
> +{
>
> + return EFI_UNSUPPORTED;
>
> +}
>
> diff --git a/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.c
> b/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.c
> new file mode 100644
> index 0000000000..fc7cbd8132
> --- /dev/null
> +++ b/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.c
> @@ -0,0 +1,508 @@
> +/** @file
>
> + This file contains code for USB Network Control Model
>
> + binding driver
>
> +
>
> + Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
>
> + Subject to AMI licensing agreement.
>
> +**/
>
> +
>
> +#include "UsbCdcNcm.h"
>
> +
>
> +EFI_GUID gUsbEthProtocolGuid = USB_ETHERNET_PROTOCOL_GUID;
>
> +
>
> +EFI_DRIVER_BINDING_PROTOCOL gUsbNcmDriverBinding = {
>
> + UsbNcmDriverSupported,
>
> + UsbNcmDriverStart,
>
> + UsbNcmDriverStop,
>
> + USB_NCM_DRIVER_VERSION,
>
> + NULL,
>
> + NULL
>
> +};
>
> +
>
> +/**
>
> + Check if this interface is USB NCM SubType
>
> +
>
> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance.
>
> +
>
> + @retval TRUE USB NCM SubType.
>
> + @retval FALSE Not USB NCM SubType.
>
> +
>
> +**/
>
> +BOOLEAN
>
> +IsSupportedDevice (
>
> + IN EFI_USB_IO_PROTOCOL *UsbIo
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
>
> +
>
> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &InterfaceDescriptor);
>
> + if (EFI_ERROR (Status)) {
>
> + return FALSE;
>
> + }
>
> +
>
> + if ((InterfaceDescriptor.InterfaceClass == USB_CDC_CLASS) &&
>
> + (InterfaceDescriptor.InterfaceSubClass == USB_CDC_NCM_SUBCLASS) &&
>
> + (InterfaceDescriptor.InterfaceProtocol == USB_NO_CLASS_PROTOCOL))
>
> + {
>
> + return TRUE;
>
> + }
>
> +
>
> + return FALSE;
>
> +}
>
> +
>
> +/**
>
> + USB NCM Driver Binding Support.
>
> +
>
> + @param[in] This Protocol instance pointer.
>
> + @param[in] ControllerHandle Handle of device to test.
>
> + @param[in] RemainingDevicePath Optional parameter use to pick a
> specific child
>
> + device to start.
>
> +
>
> + @retval EFI_SUCCESS This driver supports this device.
>
> + @retval EFI_ALREADY_STARTED This driver is already running on
> this device.
>
> + @retval other This driver does not support this
> device.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbNcmDriverSupported (
>
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
>
> + IN EFI_HANDLE ControllerHandle,
>
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + EFI_USB_IO_PROTOCOL *UsbIo = NULL;
>
> +
>
> + 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;
>
> +}
>
> +
>
> +/**
>
> + Check if the USB NCM and USB CDC Data interfaces are from the same
> device.
>
> +
>
> + @param[in] UsbEthPath A pointer to the
> EFI_DEVICE_PATH_PROTOCOL instance.
>
> + @param[in] UsbCdcDataPath A pointer to the
> EFI_DEVICE_PATH_PROTOCOL instance.
>
> +
>
> + @retval EFI_SUCCESS Is the same device.
>
> + @retval EFI_NOT_FOUND Is not the same device.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +IsSameDevice (
>
> + IN EFI_DEVICE_PATH_PROTOCOL *UsbEthPath,
>
> + IN EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath
>
> + )
>
> +{
>
> + while (1) {
>
> + if ((UsbEthPath->Type == ACPI_DEVICE_PATH) && (UsbEthPath->SubType ==
> ACPI_DP)) {
>
> + if (CompareMem ((ACPI_HID_DEVICE_PATH *)UsbCdcDataPath,
> (ACPI_HID_DEVICE_PATH *)UsbEthPath, sizeof (ACPI_HID_DEVICE_PATH))) {
>
> + return EFI_NOT_FOUND;
>
> + }
>
> + }
>
> +
>
> + if ((UsbEthPath->Type == HARDWARE_DEVICE_PATH) &&
> (UsbEthPath->SubType == HW_PCI_DP)) {
>
> + if (CompareMem ((PCI_DEVICE_PATH *)UsbCdcDataPath, (PCI_DEVICE_PATH
> *)UsbEthPath, sizeof (PCI_DEVICE_PATH))) {
>
> + return EFI_NOT_FOUND;
>
> + }
>
> + }
>
> +
>
> + if ((UsbEthPath->Type == MESSAGING_DEVICE_PATH) &&
> (UsbEthPath->SubType == MSG_USB_DP)) {
>
> + if (IsDevicePathEnd (NextDevicePathNode (UsbEthPath))) {
>
> + if (((USB_DEVICE_PATH *)UsbEthPath)->ParentPortNumber ==
>
> + ((USB_DEVICE_PATH *)UsbCdcDataPath)->ParentPortNumber)
>
> + {
>
> + return EFI_SUCCESS;
>
> + } else {
>
> + return EFI_NOT_FOUND;
>
> + }
>
> + } else {
>
> + if (CompareMem ((USB_DEVICE_PATH *)UsbCdcDataPath,
> (USB_DEVICE_PATH *)UsbEthPath, sizeof (USB_DEVICE_PATH))) {
>
> + return EFI_NOT_FOUND;
>
> + }
>
> + }
>
> + }
>
> +
>
> + UsbEthPath = NextDevicePathNode (UsbEthPath);
>
> + UsbCdcDataPath = NextDevicePathNode (UsbCdcDataPath);
>
> + }
>
> +}
>
> +
>
> +/**
>
> + Check if the USB CDC Data(UsbIo) installed and return USB CDC Data
> Handle.
>
> +
>
> + @param[in] UsbEthPath A pointer to the
> EFI_DEVICE_PATH_PROTOCOL instance.
>
> + @param[in, out] UsbCdcDataHandle A pointer to the EFI_HANDLE for USB
> CDC Data.
>
> +
>
> + @retval TRUE USB CDC Data(UsbIo) installed.
>
> + @retval FALSE USB CDC Data(UsbIo) did not installed.
>
> +
>
> +**/
>
> +BOOLEAN
>
> +IsUsbCdcData (
>
> + IN EFI_DEVICE_PATH_PROTOCOL *UsbEthPath,
>
> + IN OUT EFI_HANDLE *UsbCdcDataHandle
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN Index;
>
> + UINTN HandleCount;
>
> + EFI_HANDLE *HandleBuffer;
>
> + EFI_USB_IO_PROTOCOL *UsbIo;
>
> + EFI_USB_INTERFACE_DESCRIPTOR Interface;
>
> + EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath;
>
> +
>
> + Status = gBS->LocateHandleBuffer (
>
> + ByProtocol,
>
> + &gEfiUsbIoProtocolGuid,
>
> + NULL,
>
> + &HandleCount,
>
> + &HandleBuffer
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + return FALSE;
>
> + }
>
> +
>
> + for (Index = 0; Index < HandleCount; Index++) {
>
> + Status = gBS->HandleProtocol (
>
> + HandleBuffer[Index],
>
> + &gEfiUsbIoProtocolGuid,
>
> + (VOID **)&UsbIo
>
> + );
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + if ((Interface.InterfaceClass == USB_CDC_DATA_CLASS) &&
>
> + (Interface.InterfaceSubClass == USB_CDC_DATA_SUBCLASS) &&
>
> + (Interface.InterfaceProtocol == USB_NCM_NTB_PROTOCOL))
>
> + {
>
> + Status = gBS->HandleProtocol (
>
> + HandleBuffer[Index],
>
> + &gEfiDevicePathProtocolGuid,
>
> + (VOID **)&UsbCdcDataPath
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + continue;
>
> + }
>
> +
>
> + Status = IsSameDevice (UsbEthPath, UsbCdcDataPath);
>
> + if (!EFI_ERROR (Status)) {
>
> + CopyMem (UsbCdcDataHandle, &HandleBuffer[Index], sizeof
> (EFI_HANDLE));
>
> + gBS->FreePool (HandleBuffer);
>
> + return TRUE;
>
> + }
>
> + }
>
> + }
>
> +
>
> + gBS->FreePool (HandleBuffer);
>
> + return FALSE;
>
> +}
>
> +
>
> +/**
>
> + Call Back Function.
>
> +
>
> + @param[in] Event Event whose notification function is being
> invoked.
>
> + @param[in] Context The pointer to the notification function's
> context,
>
> + which is implementation-dependent.
>
> +
>
> +**/
>
> +VOID
>
> +EFIAPI
>
> +CallbackFunction (
>
> + IN EFI_EVENT Event,
>
> + IN VOID *Context
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN Index;
>
> + UINTN HandleCount;
>
> + EFI_HANDLE *HandleBuffer;
>
> + EFI_USB_IO_PROTOCOL *UsbIo;
>
> + EFI_USB_INTERFACE_DESCRIPTOR Interface;
>
> +
>
> + Status = 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);
>
> +
>
> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + if ((Interface.InterfaceClass == USB_CDC_CLASS) &&
>
> + (Interface.InterfaceSubClass == USB_CDC_NCM_SUBCLASS) &&
>
> + (Interface.InterfaceProtocol == USB_NO_CLASS_PROTOCOL))
>
> + {
>
> + gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
>
> + }
>
> + }
>
> +
>
> + gBS->FreePool (HandleBuffer);
>
> + gBS->CloseEvent (Event);
>
> +}
>
> +
>
> +/**
>
> + USB NCM Driver Binding Start.
>
> +
>
> + @param[in] This Protocol instance pointer.
>
> + @param[in] ControllerHandle Handle of device to bind driver 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
>
> +UsbNcmDriverStart (
>
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
>
> + IN EFI_HANDLE ControllerHandle,
>
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + VOID *Reg;
>
> + EFI_EVENT Event;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> + EFI_DEVICE_PATH_PROTOCOL *UsbEthPath;
>
> + EFI_HANDLE UsbCdcDataHandle;
>
> + EFI_USB_IO_PROTOCOL *UsbIo;
>
> + EFI_USB_INTERFACE_DESCRIPTOR Interface;
>
> +
>
> + Status = 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_GET_PROTOCOL
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + gBS->CloseProtocol (
>
> + ControllerHandle,
>
> + &gEfiUsbIoProtocolGuid,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle
>
> + );
>
> + return Status;
>
> + }
>
> +
>
> + Status = IsUsbCdcData (UsbEthPath, &UsbCdcDataHandle) ? EFI_SUCCESS :
> EFI_UNSUPPORTED;
>
> + if (EFI_ERROR (Status)) {
>
> + gBS->CloseProtocol (
>
> + ControllerHandle,
>
> + &gEfiUsbIoProtocolGuid,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle
>
> + );
>
> +
>
> + Status = gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
> CallbackFunction, NULL, &Event);
>
> + if (EFI_ERROR (Status)) {
>
> + return Status;
>
> + }
>
> +
>
> + Status = gBS->RegisterProtocolNotify (&gEfiUsbIoProtocolGuid, Event,
> &Reg);
>
> + return Status;
>
> + }
>
> +
>
> + UsbEthDriver = AllocateZeroPool (sizeof (USB_ETHERNET_DRIVER));
>
> + if (!UsbEthDriver) {
>
> + gBS->CloseProtocol (
>
> + ControllerHandle,
>
> + &gEfiUsbIoProtocolGuid,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle
>
> + );
>
> + return EFI_OUT_OF_RESOURCES;
>
> + }
>
> +
>
> + Status = LoadAllDescriptor (UsbIo, &UsbEthDriver->Config);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + GetEndpoint (UsbIo, UsbEthDriver);
>
> +
>
> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + UsbEthDriver->Signature =
> USB_ETHERNET_SIGNATURE;
>
> + UsbEthDriver->NumOfInterface =
> Interface.InterfaceNumber;
>
> + UsbEthDriver->UsbCdcDataHandle = UsbCdcDataHandle;
>
> + UsbEthDriver->UsbIo = UsbIo;
>
> + UsbEthDriver->UsbEth.UsbEthReceive = UsbEthReceive;
>
> + UsbEthDriver->UsbEth.UsbEthTransmit = UsbEthTransmit;
>
> + UsbEthDriver->UsbEth.UsbEthInterrupt = UsbEthInterrupt;
>
> + UsbEthDriver->UsbEth.UsbEthMacAddress = GetUsbEthMacAddress;
>
> + UsbEthDriver->UsbEth.UsbEthMaxBulkSize = UsbEthBulkSize;
>
> + UsbEthDriver->UsbEth.UsbHeaderFunDescriptor =
> GetUsbHeaderFunDescriptor;
>
> + UsbEthDriver->UsbEth.UsbUnionFunDescriptor =
> GetUsbUnionFunDescriptor;
>
> + UsbEthDriver->UsbEth.UsbEthFunDescriptor =
> GetUsbEthFunDescriptor;
>
> + UsbEthDriver->UsbEth.SetUsbEthMcastFilter = SetUsbEthMcastFilter;
>
> + UsbEthDriver->UsbEth.SetUsbEthPowerPatternFilter = SetUsbEthPowerFilter;
>
> + UsbEthDriver->UsbEth.GetUsbEthPoewrPatternFilter = GetUsbEthPowerFilter;
>
> + UsbEthDriver->UsbEth.SetUsbEthPacketFilter =
> SetUsbEthPacketFilter;
>
> + UsbEthDriver->UsbEth.GetUsbEthStatistic = GetUsbEthStatistic;
>
> +
>
> + UsbEthDriver->BulkBuffer = AllocateZeroPool (USB_NCM_MAX_NTB_SIZE);
>
> +
>
> + Status = gBS->InstallProtocolInterface (
>
> + &ControllerHandle,
>
> + &gUsbEthProtocolGuid,
>
> + EFI_NATIVE_INTERFACE,
>
> + &(UsbEthDriver->UsbEth)
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + gBS->CloseProtocol (
>
> + ControllerHandle,
>
> + &gEfiUsbIoProtocolGuid,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle
>
> + );
>
> + gBS->FreePool (UsbEthDriver);
>
> + return Status;
>
> + }
>
> +
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + USB NCM Driver Binding Stop.
>
> +
>
> + @param[in] This Protocol instance pointer.
>
> + @param[in] ControllerHandle Handle of device to stop driver on
>
> + @param[in] NumberOfChildren Number of Handles in
> ChildHandleBuffer. If number of
>
> + children is zero stop the entire 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
>
> +UsbNcmDriverStop (
>
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
>
> + IN EFI_HANDLE ControllerHandle,
>
> + IN UINTN NumberOfChildren,
>
> + IN EFI_HANDLE *ChildHandleBuffer
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + USB_ETHERNET_PROTOCOL *UsbEthProtocol;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> +
>
> + Status = gBS->OpenProtocol (
>
> + ControllerHandle,
>
> + &gUsbEthProtocolGuid,
>
> + (VOID **)&UsbEthProtocol,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle,
>
> + EFI_OPEN_PROTOCOL_GET_PROTOCOL
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + return Status;
>
> + }
>
> +
>
> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (UsbEthProtocol);
>
> +
>
> + Status = gBS->UninstallProtocolInterface (
>
> + ControllerHandle,
>
> + &gUsbEthProtocolGuid,
>
> + UsbEthProtocol
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + return Status;
>
> + }
>
> +
>
> + Status = gBS->CloseProtocol (
>
> + ControllerHandle,
>
> + &gEfiUsbIoProtocolGuid,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle
>
> + );
>
> + gBS->FreePool (UsbEthDriver->Config);
>
> + gBS->FreePool (UsbEthDriver->BulkBuffer);
>
> + gBS->FreePool (UsbEthDriver);
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + Entrypoint of NCM Driver.
>
> +
>
> + This function is the entrypoint of NCM Driver. It installs Driver
> Binding
>
> + Protocols together with Component Name Protocols.
>
> +
>
> + @param[in] ImageHandle The firmware allocated handle for the EFI
> image.
>
> + @param[in] SystemTable A pointer to the EFI System Table.
>
> +
>
> + @retval EFI_SUCCESS The entry point is executed successfully.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbNcmEntry (
>
> + IN EFI_HANDLE ImageHandle,
>
> + IN EFI_SYSTEM_TABLE *SystemTable
>
> + )
>
> +{
>
> + gUsbNcmDriverBinding.DriverBindingHandle = ImageHandle;
>
> + gUsbNcmDriverBinding.ImageHandle = ImageHandle;
>
> +
>
> + return gBS->InstallMultipleProtocolInterfaces (
>
> + &gUsbNcmDriverBinding.DriverBindingHandle,
>
> + &gEfiDriverBindingProtocolGuid,
>
> + &gUsbNcmDriverBinding,
>
> + &gEfiComponentName2ProtocolGuid,
>
> + &gUsbNcmComponentName2,
>
> + NULL
>
> + );
>
> +}
>
> diff --git a/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.h
> b/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.h
> new file mode 100644
> index 0000000000..40b2671a1e
> --- /dev/null
> +++ b/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.h
> @@ -0,0 +1,245 @@
> +/** @file
>
> + Header file for USB Network Control Model driver
>
> +
>
> + Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
>
> + Subject to AMI licensing agreement.
>
> +**/
>
> +
>
> +#ifndef _USB_CDC_NCM_H_
>
> +#define _USB_CDC_NCM_H_
>
> +
>
> +#include <Library/UefiDriverEntryPoint.h>
>
> +#include <Library/UefiBootServicesTableLib.h>
>
> +#include <Library/UefiLib.h>
>
> +#include <Library/DevicePathLib.h>
>
> +#include <Library/DebugLib.h>
>
> +#include <Library/MemoryAllocationLib.h>
>
> +#include <Library/BaseMemoryLib.h>
>
> +#include <Library/UefiUsbLib.h>
>
> +#include <Protocol/UsbIo.h>
>
> +#include <Protocol/UsbEthernetProtocol.h>
>
> +
>
> +typedef struct {
>
> + UINTN Signature;
>
> + USB_ETHERNET_PROTOCOL UsbEth;
>
> + EFI_HANDLE UsbCdcDataHandle;
>
> + EFI_USB_IO_PROTOCOL *UsbIo;
>
> + EFI_USB_CONFIG_DESCRIPTOR *Config;
>
> + UINT8 NumOfInterface;
>
> + UINT8 BulkInEndpoint;
>
> + UINT8 BulkOutEndpoint;
>
> + UINT8 InterruptEndpoint;
>
> + EFI_MAC_ADDRESS MacAddress;
>
> + UINT16 BulkOutSequence;
>
> + UINT8 *BulkBuffer;
>
> + UINT8 TotalDatagram;
>
> + UINT8 NowDatagram;
>
> +} USB_ETHERNET_DRIVER;
>
> +
>
> +#define USB_NCM_DRIVER_VERSION 1
>
> +#define USB_ETHERNET_BULK_TIMEOUT 1
>
> +#define USB_ETHERNET_TRANSFER_TIMEOUT 200
>
> +#define USB_NCM_MAX_NTB_SIZE 0xFFFF
>
> +#define USB_ETH_FRAME_SIZE 0x5F2 // frome network stack snp
>
> +
>
> +// Defined in USB NCM 1.0 spec., section 3.2 and 3.3
>
> +#define USB_NCM_NTH_SIGN_16 0x484D434E
>
> +#define USB_NCM_NDP_SIGN_16 0x304D434E
>
> +#define USB_NCM_NDP_SIGN_16_CRC 0x314D434E
>
> +#define USB_NCM_NTH_LENGTH 0x000C
>
> +#define USB_NCM_NDP_LENGTH 0x0010// at least 16
>
> +
>
> +// USB NCM Transfer header structure - UINT16
>
> +typedef struct {
>
> + UINT32 Signature;
>
> + UINT16 HeaderLength;
>
> + UINT16 Sequence;
>
> + UINT16 BlockLength;
>
> + UINT16 NdpIndex;
>
> +} USB_NCM_TRANSFER_HEADER_16;
>
> +
>
> +// USB NCM Datagram pointer structure - UINT16
>
> +typedef struct {
>
> + UINT32 Signature;
>
> + UINT16 Length;
>
> + UINT16 NextNdpIndex;
>
> +} USB_NCM_DATAGRAM_POINTER_16;
>
> +
>
> +// USB NCM Datagram structure
>
> +typedef struct {
>
> + UINT16 DatagramIndex;
>
> + UINT16 DatagramLength;
>
> +} USB_NCM_DATA_GRAM;
>
> +
>
> +#define USB_ETHERNET_SIGNATURE SIGNATURE_32('u', 'e', 't', 'h')
>
> +#define USB_ETHERNET_DEV_FROM_THIS(a) CR (a, USB_ETHERNET_DRIVER,
> UsbEth, USB_ETHERNET_SIGNATURE)
>
> +
>
> +typedef struct {
>
> + UINT16 Src;
>
> + UINT16 Dst;
>
> +} BIT_MAP;
>
> +
>
> +extern EFI_COMPONENT_NAME2_PROTOCOL gUsbNcmComponentName2;
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbNcmDriverSupported (
>
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
>
> + IN EFI_HANDLE ControllerHandle,
>
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbNcmDriverStart (
>
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
>
> + IN EFI_HANDLE ControllerHandle,
>
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbNcmDriverStop (
>
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
>
> + IN EFI_HANDLE ControllerHandle,
>
> + IN UINTN NumberOfChildren,
>
> + IN EFI_HANDLE *ChildHandleBuffer
>
> + );
>
> +
>
> +EFI_STATUS
>
> +LoadAllDescriptor (
>
> + IN EFI_USB_IO_PROTOCOL *UsbIo,
>
> + OUT EFI_USB_CONFIG_DESCRIPTOR **ConfigDesc
>
> + );
>
> +
>
> +BOOLEAN
>
> +NextDescriptor (
>
> + IN EFI_USB_CONFIG_DESCRIPTOR *Desc,
>
> + IN OUT UINTN *Offset
>
> + );
>
> +
>
> +EFI_STATUS
>
> +GetFunctionalDescriptor (
>
> + IN EFI_USB_CONFIG_DESCRIPTOR *Config,
>
> + IN UINT8 FunDescriptorType,
>
> + OUT VOID *DataBuffer
>
> + );
>
> +
>
> +VOID
>
> +GetEndpoint (
>
> + IN EFI_USB_IO_PROTOCOL *UsbIo,
>
> + IN OUT USB_ETHERNET_DRIVER *UsbEthDriver
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbEthReceive (
>
> + IN PXE_CDB *Cdb,
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN OUT VOID *Packet,
>
> + IN OUT UINTN *PacketLength
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbEthTransmit (
>
> + IN PXE_CDB *Cdb,
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN VOID *Packet,
>
> + IN OUT UINTN *PacketLength
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbEthInterrupt (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN BOOLEAN IsNewTransfer,
>
> + IN UINTN PollingInterval,
>
> + IN EFI_USB_DEVICE_REQUEST *Request
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +InterruptCallback (
>
> + IN VOID *Data,
>
> + IN UINTN DataLength,
>
> + IN VOID *Context,
>
> + IN UINT32 Status
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetUsbEthMacAddress (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT EFI_MAC_ADDRESS *MacAddress
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbEthBulkSize (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT UINTN *BulkSize
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetUsbHeaderFunDescriptor (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetUsbUnionFunDescriptor (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetUsbEthFunDescriptor (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +SetUsbEthMcastFilter (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value,
>
> + IN VOID *McastAddr
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +SetUsbEthPowerFilter (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value,
>
> + IN UINT16 Length,
>
> + IN VOID *PatternFilter
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetUsbEthPowerFilter (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value,
>
> + OUT BOOLEAN *PatternActive
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +SetUsbEthPacketFilter (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetUsbEthStatistic (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 FeatureSelector,
>
> + OUT VOID *Statistic
>
> + );
>
> +
>
> +#endif
>
> diff --git a/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf
> b/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf
> new file mode 100644
> index 0000000000..cfbf9ad720
> --- /dev/null
> +++ b/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf
> @@ -0,0 +1,41 @@
> +## @file
> +# This is Usb Cdc Ncm driver for DXE phase.
> +#
> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
> +# Subject to AMI licensing agreement.
> +##
> +
> +[Defines]
> + INF_VERSION = 0x00010005
> + BASE_NAME = UsbCdcNcm
> + FILE_GUID = 52230d31-6c11-4442-b262-bec6bfe84efa
> + MODULE_TYPE = DXE_DRIVER
> + VERSION_STRING = 1.0
> + ENTRY_POINT = UsbNcmEntry
> +
> +[Sources]
> + UsbCdcNcm.c
> + UsbCdcNcm.h
> + UsbNcmFunction.c
> + ComponentName.c
> +
> +[Packages]
> + MdePkg/MdePkg.dec
> + UsbNetworkPkg/UsbNetworkPkg.dec
> +
> +[LibraryClasses]
> + UefiDriverEntryPoint
> + UefiBootServicesTableLib
> + UefiLib
> + DebugLib
> + UefiUsbLib
> + MemoryAllocationLib
> + BaseMemoryLib
> +
> +[Protocols]
> + gEfiUsbIoProtocolGuid
> + gEfiDevicePathProtocolGuid
> + gEfiDriverBindingProtocolGuid
> +
> +[Depex]
> + TRUE
> \ No newline at end of file
> diff --git a/UsbNetworkPkg/UsbCdcNcm/UsbNcmFunction.c
> b/UsbNetworkPkg/UsbCdcNcm/UsbNcmFunction.c
> new file mode 100644
> index 0000000000..98bcf6d6d5
> --- /dev/null
> +++ b/UsbNetworkPkg/UsbCdcNcm/UsbNcmFunction.c
> @@ -0,0 +1,946 @@
> +/** @file
>
> + This file contains code for USB Ethernet descriptor
>
> + and specific requests implement.
>
> +
>
> + Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
>
> + Subject to AMI licensing agreement.
>
> +**/
>
> +
>
> +#include "UsbCdcNcm.h"
>
> +
>
> +/**
>
> + 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);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + Status = gBS->AllocatePool (EfiBootServicesData, Tmp.TotalLength, (VOID
> **)ConfigDesc);
>
> + ASSERT_EFI_ERROR (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 = EFI_NOT_FOUND;
>
> + UINTN Offset;
>
> + EFI_USB_INTERFACE_DESCRIPTOR *Interface;
>
> +
>
> + 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] UsbEthDriver A pointer to the USB_ETHERNET_DRIVER
> instance.
>
> +
>
> +**/
>
> +VOID
>
> +GetEndpoint (
>
> + IN EFI_USB_IO_PROTOCOL *UsbIo,
>
> + IN OUT USB_ETHERNET_DRIVER *UsbEthDriver
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINT8 Index;
>
> + UINT32 Result;
>
> + EFI_USB_INTERFACE_DESCRIPTOR Interface;
>
> + EFI_USB_ENDPOINT_DESCRIPTOR Endpoint;
>
> +
>
> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + if (Interface.NumEndpoints == 0) {
>
> + Status = UsbSetInterface (UsbIo, Interface.InterfaceNumber, 1,
> &Result);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
>
> + ASSERT_EFI_ERROR (Status);
>
> + }
>
> +
>
> + for (Index = 0; Index < Interface.NumEndpoints; Index++) {
>
> + Status = UsbIo->UsbGetEndpointDescriptor (UsbIo, Index, &Endpoint);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + switch ((Endpoint.Attributes & (BIT0 | BIT1))) {
>
> + case USB_ENDPOINT_BULK:
>
> + if (Endpoint.EndpointAddress & BIT7) {
>
> + UsbEthDriver->BulkInEndpoint = Endpoint.EndpointAddress;
>
> + } else {
>
> + UsbEthDriver->BulkOutEndpoint = Endpoint.EndpointAddress;
>
> + }
>
> +
>
> + break;
>
> + case USB_ENDPOINT_INTERRUPT:
>
> + UsbEthDriver->InterruptEndpoint = Endpoint.EndpointAddress;
>
> + break;
>
> + }
>
> + }
>
> +}
>
> +
>
> +/**
>
> + This function is used to manage a USB device with the bulk transfer
> pipe. The endpoint is Bulk in.
>
> +
>
> + @param[in] Cdb A pointer to the command descriptor block.
>
> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL
> instance.
>
> + @param[in, out] Packet A pointer to the buffer of data that will
> be transmitted to USB
>
> + device or received from USB device.
>
> + @param[in, out] PacketLength A pointer to the PacketLength.
>
> +
>
> + @retval EFI_SUCCESS The bulk transfer has been successfully
> executed.
>
> + @retval EFI_DEVICE_ERROR The transfer failed. The transfer status
> is returned in status.
>
> + @retval EFI_INVALID_PARAMETE One or more parameters are invalid.
>
> + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due to
> a lack of resources.
>
> + @retval EFI_TIMEOUT The control transfer fails due to timeout.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbEthReceive (
>
> + IN PXE_CDB *Cdb,
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN OUT VOID *Packet,
>
> + IN OUT UINTN *PacketLength
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> + EFI_USB_IO_PROTOCOL *UsbIo;
>
> + UINT32 TransStatus;
>
> + UINT8 Index;
>
> + UINTN BulkDataLenght;
>
> + UINTN TotalLength = 0;
>
> + USB_NCM_TRANSFER_HEADER_16 *Nth;
>
> + USB_NCM_DATAGRAM_POINTER_16 *Ndp;
>
> + USB_NCM_DATA_GRAM *Datagram;
>
> +
>
> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
>
> +
>
> + if (UsbEthDriver->TotalDatagram == UsbEthDriver->NowDatagram) {
>
> + Status = gBS->HandleProtocol (
>
> + UsbEthDriver->UsbCdcDataHandle,
>
> + &gEfiUsbIoProtocolGuid,
>
> + (VOID **)&UsbIo
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + return Status;
>
> + }
>
> +
>
> + if (UsbEthDriver->BulkInEndpoint == 0) {
>
> + GetEndpoint (UsbIo, UsbEthDriver);
>
> + }
>
> +
>
> + BulkDataLenght = USB_NCM_MAX_NTB_SIZE;
>
> + SetMem (UsbEthDriver->BulkBuffer, BulkDataLenght, 0);
>
> + UsbEthDriver->NowDatagram = 0;
>
> + UsbEthDriver->TotalDatagram = 0;
>
> +
>
> + Status = UsbIo->UsbBulkTransfer (
>
> + UsbIo,
>
> + UsbEthDriver->BulkInEndpoint,
>
> + UsbEthDriver->BulkBuffer,
>
> + &BulkDataLenght,
>
> + USB_ETHERNET_BULK_TIMEOUT,
>
> + &TransStatus
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + return Status;
>
> + }
>
> +
>
> + Nth = (USB_NCM_TRANSFER_HEADER_16
> *)UsbEthDriver->BulkBuffer;
>
> + Ndp = (USB_NCM_DATAGRAM_POINTER_16 *)((UINT8
> *)UsbEthDriver->BulkBuffer + Nth->NdpIndex);
>
> + Datagram = (USB_NCM_DATA_GRAM *)((UINT8 *)Ndp +
> sizeof (USB_NCM_DATAGRAM_POINTER_16));
>
> + UsbEthDriver->TotalDatagram = (UINT8)((Ndp->Length - 8) / 4 - 1);
>
> +
>
> + for (Index = 0; Index < UsbEthDriver->TotalDatagram; Index++) {
>
> + TotalLength += Datagram->DatagramLength;
>
> + Datagram = (USB_NCM_DATA_GRAM *)((UINT8 *)Datagram + sizeof
> (USB_NCM_DATA_GRAM));
>
> + }
>
> +
>
> + if (TotalLength < USB_ETH_FRAME_SIZE) {
>
> + Datagram = (USB_NCM_DATA_GRAM *)((UINT8 *)Ndp + sizeof
> (USB_NCM_DATAGRAM_POINTER_16));
>
> +
>
> + TotalLength = 0;
>
> + for (Index = 0; Index < UsbEthDriver->TotalDatagram; Index++) {
>
> + CopyMem ((UINT8 *)Packet + TotalLength, (UINT8
> *)UsbEthDriver->BulkBuffer + Datagram->DatagramIndex,
> Datagram->DatagramLength);
>
> + TotalLength += Datagram->DatagramLength;
>
> + Datagram = (USB_NCM_DATA_GRAM *)((UINT8 *)Datagram + sizeof
> (USB_NCM_DATA_GRAM));
>
> + }
>
> +
>
> + *PacketLength = TotalLength;
>
> + UsbEthDriver->NowDatagram = UsbEthDriver->TotalDatagram;
>
> + } else {
>
> + UsbEthDriver->NowDatagram++;
>
> +
>
> + Datagram = (USB_NCM_DATA_GRAM *)((UINT8 *)Ndp + sizeof
> (USB_NCM_DATAGRAM_POINTER_16));
>
> + CopyMem (Packet, (UINT8 *)UsbEthDriver->BulkBuffer +
> Datagram->DatagramIndex, Datagram->DatagramLength);
>
> + *PacketLength = Datagram->DatagramLength;
>
> + }
>
> +
>
> + return Status;
>
> + } else {
>
> + UsbEthDriver->NowDatagram++;
>
> +
>
> + Nth = (USB_NCM_TRANSFER_HEADER_16 *)UsbEthDriver->BulkBuffer;
>
> + Ndp = (USB_NCM_DATAGRAM_POINTER_16 *)((UINT8
> *)UsbEthDriver->BulkBuffer + Nth->NdpIndex);
>
> + Datagram = (USB_NCM_DATA_GRAM *)((UINT8 *)Ndp + sizeof
> (USB_NCM_DATAGRAM_POINTER_16));
>
> + Datagram = (USB_NCM_DATA_GRAM *)((UINT8 *)Datagram + sizeof
> (USB_NCM_DATA_GRAM) * (UsbEthDriver->NowDatagram - 1));
>
> +
>
> + CopyMem (Packet, (UINT8 *)UsbEthDriver->BulkBuffer +
> Datagram->DatagramIndex, Datagram->DatagramLength);
>
> + *PacketLength = Datagram->DatagramLength;
>
> +
>
> + return EFI_SUCCESS;
>
> + }
>
> +}
>
> +
>
> +/**
>
> + This function is used to manage a USB device with the bulk transfer
> pipe. The endpoint is Bulk out.
>
> +
>
> + @param[in] Cdb A pointer to the command descriptor block.
>
> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL
> instance.
>
> + @param[in] Packet A pointer to the buffer of data that will
> be transmitted to USB
>
> + device or received from USB device.
>
> + @param[in, out] PacketLength A pointer to the PacketLength.
>
> +
>
> + @retval EFI_SUCCESS The bulk transfer has been successfully
> executed.
>
> + @retval EFI_DEVICE_ERROR The transfer failed. The transfer status
> is returned in status.
>
> + @retval EFI_INVALID_PARAMETE One or more parameters are invalid.
>
> + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due to
> a lack of resources.
>
> + @retval EFI_TIMEOUT The control transfer fails due to timeout.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbEthTransmit (
>
> + IN PXE_CDB *Cdb,
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN VOID *Packet,
>
> + IN OUT UINTN *PacketLength
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> + EFI_USB_IO_PROTOCOL *UsbIo;
>
> + UINT32 TransStatus;
>
> + USB_NCM_TRANSFER_HEADER_16 *Nth;
>
> + USB_NCM_DATAGRAM_POINTER_16 *Ndp;
>
> + USB_NCM_DATA_GRAM *Datagram;
>
> + UINT8 *TotalPacket;
>
> + UINTN TotalLength;
>
> +
>
> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
>
> +
>
> + Status = gBS->HandleProtocol (
>
> + UsbEthDriver->UsbCdcDataHandle,
>
> + &gEfiUsbIoProtocolGuid,
>
> + (VOID **)&UsbIo
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + return Status;
>
> + }
>
> +
>
> + if (UsbEthDriver->BulkOutEndpoint == 0) {
>
> + GetEndpoint (UsbIo, UsbEthDriver);
>
> + }
>
> +
>
> + TotalLength = (UINTN)(USB_NCM_NTH_LENGTH + USB_NCM_NDP_LENGTH +
> (*PacketLength));
>
> +
>
> + Status = gBS->AllocatePool (EfiBootServicesData, TotalLength, (VOID
> **)&TotalPacket);
>
> + if (EFI_ERROR (Status)) {
>
> + return Status;
>
> + }
>
> +
>
> + SetMem (TotalPacket, TotalLength, 0);
>
> +
>
> + Nth = (USB_NCM_TRANSFER_HEADER_16 *)TotalPacket;
>
> + Nth->Signature = USB_NCM_NTH_SIGN_16;
>
> + Nth->HeaderLength = USB_NCM_NTH_LENGTH;
>
> + Nth->Sequence = UsbEthDriver->BulkOutSequence++;
>
> + Nth->BlockLength = (UINT16)TotalLength;
>
> + Nth->NdpIndex = Nth->HeaderLength;
>
> +
>
> + Ndp = (USB_NCM_DATAGRAM_POINTER_16 *)((UINT8
> *)TotalPacket + Nth->NdpIndex);
>
> + Ndp->Signature = USB_NCM_NDP_SIGN_16;
>
> + Ndp->Length = USB_NCM_NDP_LENGTH;
>
> + Ndp->NextNdpIndex = 0x00;
>
> +
>
> + Datagram = (USB_NCM_DATA_GRAM *)((UINT8 *)Ndp + sizeof
> (USB_NCM_DATAGRAM_POINTER_16));
>
> + Datagram->DatagramIndex = Nth->HeaderLength + Ndp->Length;
>
> + Datagram->DatagramLength = (UINT16)*PacketLength;
>
> +
>
> + CopyMem (TotalPacket + Datagram->DatagramIndex, Packet, *PacketLength);
>
> +
>
> + *PacketLength = TotalLength;
>
> +
>
> + Status = UsbIo->UsbBulkTransfer (
>
> + UsbIo,
>
> + UsbEthDriver->BulkOutEndpoint,
>
> + TotalPacket,
>
> + PacketLength,
>
> + USB_ETHERNET_BULK_TIMEOUT,
>
> + &TransStatus
>
> + );
>
> + gBS->FreePool (TotalPacket);
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + Async USB transfer callback routine.
>
> +
>
> + @param[in] Data Data received or sent via the USB
> Asynchronous Transfer, if the
>
> + transfer completed successfully.
>
> + @param[in] DataLength The length of Data received or sent via the
> Asynchronous
>
> + Transfer, if transfer successfully
> completes.
>
> + @param[in] Context Data passed from
> UsbAsyncInterruptTransfer() request.
>
> + @param[in] Status Indicates the result of the asynchronous
> transfer.
>
> +
>
> + @retval EFI_SUCCESS The asynchronous USB transfer request has
> been successfully executed.
>
> + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request
> failed.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +InterruptCallback (
>
> + IN VOID *Data,
>
> + IN UINTN DataLength,
>
> + IN VOID *Context,
>
> + IN UINT32 Status
>
> + )
>
> +{
>
> + if (((EFI_USB_DEVICE_REQUEST *)Data)->Request ==
> USB_CDC_NETWORK_CONNECTION) {
>
> + CopyMem (
>
> + (EFI_USB_DEVICE_REQUEST *)Context,
>
> + (EFI_USB_DEVICE_REQUEST *)Data,
>
> + sizeof (EFI_USB_DEVICE_REQUEST)
>
> + );
>
> + }
>
> +
>
> + return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> + This function is used to manage a USB device with an interrupt transfer
> pipe.
>
> +
>
> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL
> instance.
>
> + @param[in] IsNewTransfer If TRUE, a new transfer will be submitted
> to USB controller. If
>
> + FALSE, the interrupt transfer is 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
>
> +UsbEthInterrupt (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN BOOLEAN IsNewTransfer,
>
> + IN UINTN PollingInterval,
>
> + IN EFI_USB_DEVICE_REQUEST *Request
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> + UINTN DataLength = 0;
>
> +
>
> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
>
> + if (IsNewTransfer == TRUE) {
>
> + DataLength = sizeof (EFI_USB_DEVICE_REQUEST) + sizeof
> (USB_CONNECT_SPEED_CHANGE);
>
> + Status = UsbEthDriver->UsbIo->UsbAsyncInterruptTransfer (
>
> + UsbEthDriver->UsbIo,
>
> + UsbEthDriver->InterruptEndpoint,
>
> + IsNewTransfer,
>
> + PollingInterval,
>
> + DataLength,
>
> +
> (EFI_ASYNC_USB_TRANSFER_CALLBACK)InterruptCallback,
>
> + Request
>
> + );
>
> + } else {
>
> + Status = UsbEthDriver->UsbIo->UsbAsyncInterruptTransfer (
>
> + UsbEthDriver->UsbIo,
>
> + UsbEthDriver->InterruptEndpoint,
>
> + IsNewTransfer,
>
> + 0,
>
> + 0,
>
> + NULL,
>
> + NULL
>
> + );
>
> + }
>
> +
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + Retrieves the USB Ethernet Mac Address.
>
> +
>
> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL
> instance.
>
> + @param[out] MacAddress A pointer to the caller allocated USB
> Ethernet Mac Address.
>
> +
>
> + @retval EFI_SUCCESS The USB Header Functional descriptor 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 USB_ETHERNET_PROTOCOL *This,
>
> + OUT EFI_MAC_ADDRESS *MacAddress
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthDescriptor;
>
> + CHAR16 *Data;
>
> + CHAR16 *DataPtr;
>
> + CHAR16 TmpStr[1];
>
> + UINT8 Index;
>
> + UINT8 Hi;
>
> + UINT8 Low;
>
> +
>
> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
>
> +
>
> + Status = This->UsbEthFunDescriptor (This, &UsbEthDescriptor);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + Status = UsbEthDriver->UsbIo->UsbGetStringDescriptor (
>
> + UsbEthDriver->UsbIo,
>
> + 0x409, //
> English-US Language ID
>
> + UsbEthDescriptor.MacAddress,
>
> + &Data
>
> + );
>
> + ASSERT_EFI_ERROR (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;
>
> +}
>
> +
>
> +/**
>
> + Get the USB NCM max NTB size.
>
> +
>
> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL
> instance.
>
> + @param[out] BulkSize A pointer to the Bulk transfer data size.
>
> +
>
> + @retval EFI_SUCCESS Get the USB NCM max NTB size successfully.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbEthBulkSize (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT UINTN *BulkSize
>
> + )
>
> +{
>
> + *BulkSize = USB_NCM_MAX_NTB_SIZE;
>
> + return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> + Retrieves the USB Header functional Descriptor.
>
> +
>
> + @param[in] This A pointer to the
> USB_ETHERNET_PROTOCOL instance.
>
> + @param[out] UsbHeaderFunDescriptor A pointer to the caller allocated
> USB Header Functional Descriptor.
>
> +
>
> + @retval EFI_SUCCESS The USB Header Functional descriptor 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 USB_ETHERNET_PROTOCOL *This,
>
> + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> +
>
> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
>
> +
>
> + if (UsbHeaderFunDescriptor == NULL) {
>
> + return EFI_INVALID_PARAMETER;
>
> + }
>
> +
>
> + Status = GetFunctionalDescriptor (UsbEthDriver->Config,
> HEADER_FUN_DESCRIPTOR, UsbHeaderFunDescriptor);
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + Retrieves the USB Union functional Descriptor.
>
> +
>
> + @param[in] This A pointer to the
> USB_ETHERNET_PROTOCOL instance.
>
> + @param[out] UsbUnionFunDescriptor A pointer to the caller allocated
> USB Union Functional Descriptor.
>
> +
>
> + @retval EFI_SUCCESS The USB Union Functional descriptor was
> retrieved successfully.
>
> + @retval EFI_INVALID_PARAMETER UsbUnionFunDescriptor is NULL.
>
> + @retval EFI_NOT_FOUND The USB Union Functional descriptor was
> not found.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetUsbUnionFunDescriptor (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> +
>
> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
>
> +
>
> + if (UsbUnionFunDescriptor == NULL) {
>
> + return EFI_INVALID_PARAMETER;
>
> + }
>
> +
>
> + Status = GetFunctionalDescriptor (UsbEthDriver->Config,
> UNION_FUN_DESCRIPTOR, UsbUnionFunDescriptor);
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + Retrieves the USB Ethernet functional Descriptor.
>
> +
>
> + @param[in] This A pointer to the
> USB_ETHERNET_PROTOCOL instance.
>
> + @param[out] UsbEthFunDescriptor A pointer to the caller allocated
> USB Ethernet Functional Descriptor.
>
> +
>
> + @retval EFI_SUCCESS The USB Ethernet Functional descriptor
> was retrieved successfully.
>
> + @retval EFI_INVALID_PARAMETER UsbEthFunDescriptor is NULL.
>
> + @retval EFI_NOT_FOUND The USB Ethernet Functional descriptor
> was not found.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetUsbEthFunDescriptor (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> +
>
> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
>
> +
>
> + if (UsbEthFunDescriptor == NULL) {
>
> + return EFI_INVALID_PARAMETER;
>
> + }
>
> +
>
> + Status = GetFunctionalDescriptor (UsbEthDriver->Config,
> ETHERNET_FUN_DESCRIPTOR, UsbEthFunDescriptor);
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + This request sets the Ethernet device multicast filters as specified in
> the
>
> + sequential list of 48 bit Ethernet multicast addresses.
>
> +
>
> + @param[in] This A pointer to the
> USB_ETHERNET_PROTOCOL instance.
>
> + @param[in] Value Number of filters.
>
> + @param[in] McastAddr A pointer to the value of the
> multicast addresses.
>
> +
>
> + @retval EFI_SUCCESS The request executed successfully.
>
> + @retval EFI_TIMEOUT A timeout occurred executing the 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
>
> +SetUsbEthMcastFilter (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value,
>
> + IN VOID *McastAddr
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + EFI_USB_DEVICE_REQUEST Request;
>
> + UINT32 TransStatus;
>
> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> +
>
> + UsbEthDriver = USB_ETHERNET_DEV_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_ETHRTNET_SET_REQ_TYPE;
>
> + Request.Request = SET_ETH_MULTICAST_FILTERS_REQ;
>
> + Request.Value = Value;
>
> + Request.Index = UsbEthDriver->NumOfInterface;
>
> + Request.Length = Value * 6;
>
> +
>
> + return UsbEthDriver->UsbIo->UsbControlTransfer (
>
> + UsbEthDriver->UsbIo,
>
> + &Request,
>
> + EfiUsbDataOut,
>
> + USB_ETHERNET_TRANSFER_TIMEOUT,
>
> + McastAddr,
>
> + Request.Length,
>
> + &TransStatus
>
> + );
>
> +}
>
> +
>
> +/**
>
> + This request sets up the specified Ethernet power management pattern
> filter as
>
> + described in the data structure.
>
> +
>
> + @param[in] This A pointer to the
> USB_ETHERNET_PROTOCOL instance.
>
> + @param[in] Value Number of filters.
>
> + @param[in] Length Size of the power management 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
>
> +SetUsbEthPowerFilter (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value,
>
> + IN UINT16 Length,
>
> + IN VOID *PatternFilter
>
> + )
>
> +{
>
> + EFI_USB_DEVICE_REQUEST Request;
>
> + UINT32 TransStatus;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> +
>
> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
>
> +
>
> + Request.RequestType = USB_ETHRTNET_SET_REQ_TYPE;
>
> + Request.Request = SET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ;
>
> + Request.Value = Value;
>
> + Request.Index = UsbEthDriver->NumOfInterface;
>
> + Request.Length = Length;
>
> +
>
> + return UsbEthDriver->UsbIo->UsbControlTransfer (
>
> + UsbEthDriver->UsbIo,
>
> + &Request,
>
> + EfiUsbDataOut,
>
> + USB_ETHERNET_TRANSFER_TIMEOUT,
>
> + PatternFilter,
>
> + Length,
>
> + &TransStatus
>
> + );
>
> +}
>
> +
>
> +/**
>
> + This request retrieves the status of the specified Ethernet power
> management
>
> + pattern filter from the device.
>
> +
>
> + @param[in] This A pointer to the
> USB_ETHERNET_PROTOCOL instance.
>
> + @param[in] Value The filter number.
>
> + @param[out] PatternActive A pointer to the pattern active
> boolean.
>
> +
>
> + @retval EFI_SUCCESS The request executed successfully.
>
> + @retval EFI_TIMEOUT A timeout occurred executing the 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
>
> +GetUsbEthPowerFilter (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value,
>
> + OUT BOOLEAN *PatternActive
>
> + )
>
> +{
>
> + EFI_USB_DEVICE_REQUEST Request;
>
> + UINT32 TransStatus;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> +
>
> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
>
> +
>
> + Request.RequestType = USB_ETHERNET_GET_REQ_TYPE;
>
> + Request.Request = GET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ;
>
> + Request.Value = Value;
>
> + Request.Index = UsbEthDriver->NumOfInterface;
>
> + Request.Length = USB_ETH_POWER_FILTER_LENGTH;
>
> +
>
> + return UsbEthDriver->UsbIo->UsbControlTransfer (
>
> + UsbEthDriver->UsbIo,
>
> + &Request,
>
> + EfiUsbDataIn,
>
> + USB_ETHERNET_TRANSFER_TIMEOUT,
>
> + PatternActive,
>
> + USB_ETH_POWER_FILTER_LENGTH,
>
> + &TransStatus
>
> + );
>
> +}
>
> +
>
> +BIT_MAP gTable[] = {
>
> + { PXE_OPFLAGS_RECEIVE_FILTER_UNICAST,
> USB_ETH_PACKET_TYPE_DIRECTED },
>
> + { PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST,
> USB_ETH_PACKET_TYPE_BROADCAST },
>
> + { PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST,
> USB_ETH_PACKET_TYPE_MULTICAST },
>
> + { PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS,
> USB_ETH_PACKET_TYPE_PROMISCUOUS },
>
> + { PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST,
> USB_ETH_PACKET_TYPE_ALL_MULTICAST },
>
> +};
>
> +
>
> +/**
>
> + Convert value between PXE receive filter and USB ETH packet filter.
>
> +
>
> + @param[in] Value PXE filter data.
>
> + @param[out] CdcFilter A pointer to the Ethernet Packet Filter Bitmap
> value converted by PXE_OPFLAGS.
>
> +
>
> +**/
>
> +VOID
>
> +ConvertFilter (
>
> + IN UINT16 Value,
>
> + OUT UINT16 *CdcFilter
>
> + )
>
> +{
>
> + UINT32 Index;
>
> + UINT32 Count;
>
> +
>
> + Count = sizeof (gTable)/sizeof (gTable[0]);
>
> +
>
> + for (Index = 0; (gTable[Index].Src != 0) && (Index < Count); Index++) {
>
> + if (gTable[Index].Src & Value) {
>
> + *CdcFilter |= gTable[Index].Dst;
>
> + }
>
> + }
>
> +}
>
> +
>
> +/**
>
> + This request is used to configure device Ethernet packet filter
> settings.
>
> +
>
> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL
> instance.
>
> + @param[in] Value Packet Filter Bitmap.
>
> +
>
> + @retval EFI_SUCCESS The request executed successfully.
>
> + @retval EFI_TIMEOUT A timeout occurred executing the 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
>
> +SetUsbEthPacketFilter (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value
>
> + )
>
> +{
>
> + EFI_USB_DEVICE_REQUEST Request;
>
> + UINT32 TransStatus;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> + UINT16 CommandFilter = 0;
>
> +
>
> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
>
> +
>
> + ConvertFilter (Value, &CommandFilter);
>
> +
>
> + Request.RequestType = USB_ETHRTNET_SET_REQ_TYPE;
>
> + Request.Request = SET_ETH_PACKET_FILTER_REQ;
>
> + Request.Value = CommandFilter;
>
> + Request.Index = UsbEthDriver->NumOfInterface;
>
> + Request.Length = USB_ETH_PACKET_FILTER_LENGTH;
>
> +
>
> + return UsbEthDriver->UsbIo->UsbControlTransfer (
>
> + UsbEthDriver->UsbIo,
>
> + &Request,
>
> + EfiUsbNoData,
>
> + USB_ETHERNET_TRANSFER_TIMEOUT,
>
> + NULL,
>
> + USB_ETH_PACKET_FILTER_LENGTH,
>
> + &TransStatus
>
> + );
>
> +}
>
> +
>
> +/**
>
> + This request is used to retrieve a statistic based on the feature
> selector.
>
> +
>
> + @param[in] This A pointer to the
> USB_ETHERNET_PROTOCOL instance.
>
> + @param[in] FeatureSelector Value of the feature selector.
>
> + @param[out] Statistic A pointer to the 32 bit unsigned
> integer.
>
> +
>
> + @retval EFI_SUCCESS The request executed successfully.
>
> + @retval EFI_TIMEOUT A timeout occurred executing the 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
>
> +GetUsbEthStatistic (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 FeatureSelector,
>
> + OUT VOID *Statistic
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + EFI_USB_DEVICE_REQUEST Request;
>
> + UINT32 TransStatus;
>
> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor;
>
> + USB_ETHERNET_DRIVER *UsbEthDriver;
>
> +
>
> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
>
> +
>
> + Status = This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor);
>
> + if (EFI_ERROR (Status)) {
>
> + return Status;
>
> + }
>
> +
>
> + if (UsbEthFunDescriptor.EthernetStatistics == 0) {
>
> + return EFI_UNSUPPORTED;
>
> + }
>
> +
>
> + Request.RequestType = USB_ETHERNET_GET_REQ_TYPE;
>
> + Request.Request = GET_ETH_STATISTIC_REQ;
>
> + Request.Value = FeatureSelector;
>
> + Request.Index = UsbEthDriver->NumOfInterface;
>
> + Request.Length = USB_ETH_STATISTIC;
>
> +
>
> + return UsbEthDriver->UsbIo->UsbControlTransfer (
>
> + UsbEthDriver->UsbIo,
>
> + &Request,
>
> + EfiUsbDataIn,
>
> + USB_ETHERNET_TRANSFER_TIMEOUT,
>
> + Statistic,
>
> + USB_ETH_STATISTIC,
>
> + &TransStatus
>
> + );
>
> +}
>
> diff --git a/UsbNetworkPkg/UsbNetworkPkg.dec
> b/UsbNetworkPkg/UsbNetworkPkg.dec
> new file mode 100644
> index 0000000000..4ffafd99ed
> --- /dev/null
> +++ b/UsbNetworkPkg/UsbNetworkPkg.dec
> @@ -0,0 +1,32 @@
> +## @file
> +# This package defines Usb network specific interfaces and library
> classes
> +# as well as configuration for standard edk2 packages.
> +#
> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
> +# Subject to AMI licensing agreement.
> +##
> +
> +[Defines]
> + DEC_SPECIFICATION = 0x00010005
> + PACKAGE_NAME = UsbNetworkPkg
> + PACKAGE_GUID = abfab91e-37ea-4cb4-80a6-563dbb0bcec6
> + PACKAGE_VERSION = 0.1
> +
> +[Includes]
> + Include
> +
> +[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
> +
> diff --git a/UsbNetworkPkg/UsbRndis/ComponentName.c
> b/UsbNetworkPkg/UsbRndis/ComponentName.c
> new file mode 100644
> index 0000000000..6b7891afd9
> --- /dev/null
> +++ b/UsbNetworkPkg/UsbRndis/ComponentName.c
> @@ -0,0 +1,172 @@
> +/** @file
>
> + This file contains code for USB RNDIS Driver Component
>
> + Name definitions
>
> +
>
> + Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
>
> + Subject to AMI licensing agreement.
>
> +**/
>
> +
>
> +#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 0000000000..a75355825b
> --- /dev/null
> +++ b/UsbNetworkPkg/UsbRndis/UsbRndis.c
> @@ -0,0 +1,848 @@
> +/** @file
>
> + This file contains code for USB Remote Network Driver
>
> + Interface Spec. Driver Binding
>
> +
>
> + Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
>
> + Subject to AMI licensing agreement.
>
> +**/
>
> +
>
> +#include "UsbRndis.h"
>
> +
>
> +EFI_GUID gUsbEthProtocolGuid =
> USB_ETHERNET_PROTOCOL_GUID;
>
> +extern EFI_COMPONENT_NAME2_PROTOCOL gUsbRndisComponentName2;
>
> +
>
> +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 ((EFI_D_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 ((EFI_D_VERBOSE, "IsSameDevice Exit \n"));
>
> +}
>
> +
>
> +/**
>
> + Check if the USB CDC Data(UsbIo) installed and return USB CDC Data
> Handle.
>
> +
>
> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance.
>
> +
>
> + @retval TRUE USB CDC Data(UsbIo) installed.
>
> + @retval FALSE USB CDC Data(UsbIo) did not installed.
>
> +
>
> +**/
>
> +BOOLEAN
>
> +IsUsbCdcData (
>
> + IN EFI_USB_IO_PROTOCOL *UsbIo
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
>
> +
>
> + Status = 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;
>
> + USB_ETHERNET_PROTOCOL *UsbEthDevice;
>
> + EFI_DEVICE_PATH_PROTOCOL *UsbRndisDataPath;
>
> + EFI_USB_IO_PROTOCOL *UsbIo;
>
> + BOOLEAN IsRndisInterfaceFlag = FALSE;
>
> +
>
> + Status = gBS->LocateHandleBuffer (
>
> + ByProtocol,
>
> + &gUsbEthProtocolGuid,
>
> + NULL,
>
> + &HandleCount,
>
> + &HandleBuffer
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + return Status;
>
> + }
>
> +
>
> + for (Index = 0; Index < HandleCount; Index++) {
>
> + Status = gBS->HandleProtocol (
>
> + HandleBuffer[Index],
>
> + &gUsbEthProtocolGuid,
>
> + (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
>
> + );
>
> + Status = IsSameDevice (UsbRndisDataPath, UsbCdcDataPath);
>
> +
>
> + DEBUG ((EFI_D_VERBOSE, "Rndis IsSameDevice %r\n", Status));
>
> +
>
> + if (!EFI_ERROR (Status)) {
>
> + *UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (UsbEthDevice);
>
> + gBS->FreePool (HandleBuffer);
>
> + return EFI_SUCCESS;
>
> + }
>
> + } // End of For loop
>
> +
>
> + gBS->FreePool (HandleBuffer);
>
> + return EFI_NOT_FOUND;
>
> +}
>
> +
>
> +/**
>
> +
>
> + For the given Rndis Device, find a matching CDC device already exists
> or not. If found update the handle
>
> + and UsbIO protocol.
>
> +
>
> + @param[in] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE
> data.
>
> +
>
> +**/
>
> +VOID
>
> +FindMatchingCdcData (
>
> + IN USB_RNDIS_DEVICE *UsbRndisDevice
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + UINTN Index;
>
> + UINTN HandleCount;
>
> + EFI_HANDLE *HandleBuffer;
>
> + EFI_USB_IO_PROTOCOL *UsbIo;
>
> + EFI_DEVICE_PATH_PROTOCOL *UsbRndisDataPath;
>
> + EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath;
>
> +
>
> + // Find the parent RNDIS and update the UsbIo for the CDC device
>
> + Status = 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 ((EFI_D_VERBOSE, "Rndis FindMatchingCdcData CDCData interface
> found\n"));
>
> +
>
> + Status = gBS->HandleProtocol (
>
> + HandleBuffer[Index],
>
> + &gEfiDevicePathProtocolGuid,
>
> + (VOID **)&UsbCdcDataPath
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + DEBUG ((EFI_D_VERBOSE, "Rndis CDCData DevicePath not found\n"));
>
> + gBS->FreePool (HandleBuffer);
>
> + return;
>
> + }
>
> +
>
> + Status = IsSameDevice (UsbRndisDataPath, UsbCdcDataPath);
>
> + DEBUG ((EFI_D_VERBOSE, "Rndis IsSameDevice %r\n", Status));
>
> + if (!EFI_ERROR (Status)) {
>
> + UsbRndisDevice->UsbCdcDataHandle = HandleBuffer[Index];
>
> + UsbRndisDevice->UsbIoCdcData = UsbIo;
>
> + GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice);
>
> + gBS->FreePool (HandleBuffer);
>
> + return;
>
> + }
>
> + }
>
> + } // End of For loop
>
> +
>
> + gBS->FreePool (HandleBuffer);
>
> +}
>
> +
>
> +/**
>
> +
>
> + For the given UsbIo CdcData, find a matching RNDIS device already
> exists or not.
>
> +
>
> + @param[in] CdcHandle A pointer to the EFI_HANDLE for USB CDC
> Data.
>
> + @param[out] CdcUsbIo A pointer for retrieve the
> EFI_USB_IO_PROTOCOL instance.
>
> + @param[out] RndisHandle A pointer for retrieve the handle of 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
>
> + );
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + if (IsUsbRndis (UsbIo)) {
>
> + Status = gBS->HandleProtocol (
>
> + HandleBuffer[Index],
>
> + &gEfiDevicePathProtocolGuid,
>
> + (VOID **)&UsbRndisDataPath
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + DEBUG ((EFI_D_ERROR, "Usb Rndis DevicePath not found\n"));
>
> + break;
>
> + }
>
> +
>
> + Status = IsSameDevice (UsbRndisDataPath, UsbCdcDataPath);
>
> +
>
> + if (!EFI_ERROR (Status)) {
>
> + *RndisHandle = HandleBuffer[Index];
>
> + *CdcUsbIo = UsbIo;
>
> + gBS->FreePool (HandleBuffer);
>
> + return Status;
>
> + }
>
> + }
>
> + } // End of For loop
>
> +
>
> + gBS->FreePool (HandleBuffer);
>
> +
>
> + return EFI_NOT_FOUND;
>
> +}
>
> +
>
> +/**
>
> + USB Rndis Driver Binding Support.
>
> +
>
> + @param[in] This Protocol instance pointer.
>
> + @param[in] ControllerHandle Handle of device to test.
>
> + @param[in] RemainingDevicePath Optional parameter use to pick a
> specific child
>
> + device to start.
>
> +
>
> + @retval EFI_SUCCESS This driver supports this device.
>
> + @retval EFI_ALREADY_STARTED This driver is already running on
> this device.
>
> + @retval other This driver does not support this
> device.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbRndisDriverSupported (
>
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
>
> + IN EFI_HANDLE ControllerHandle,
>
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + EFI_USB_IO_PROTOCOL *UsbIo = NULL;
>
> +
>
> + 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 = 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
>
> + );
>
> +
>
> + DEBUG ((EFI_D_ERROR, "UsbRndisDriverStart %x\n", ControllerHandle));
>
> +
>
> + // Controls come here for RNDIS and CDC. If it is CDC, check whether
> RNDIS is present on the same controller or not.
>
> + if (IsUsbCdcData (UsbIo)) {
>
> + // Find the parent RNDIS and update the UsbIo for the CDC device
>
> + Status = UpdateRndisDevice (UsbEthPath, &UsbRndisDevice);
>
> +
>
> + if (!EFI_ERROR (Status)) {
>
> + DEBUG ((EFI_D_VERBOSE, "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 ((EFI_D_ERROR, "AllocateZeroPool Fail\n"));
>
> +
>
> + gBS->CloseProtocol (
>
> + ControllerHandle,
>
> + &gEfiUsbIoProtocolGuid,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle
>
> + );
>
> + return EFI_OUT_OF_RESOURCES;
>
> + }
>
> +
>
> + Status = LoadAllDescriptor (UsbIo, &UsbRndisDevice->Config);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
>
> + ASSERT_EFI_ERROR (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.GetUsbEthPoewrPatternFilter =
> 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,
>
> + &gUsbEthProtocolGuid,
>
> + EFI_NATIVE_INTERFACE,
>
> + &(UsbRndisDevice->UsbEth)
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + gBS->CloseProtocol (
>
> + ControllerHandle,
>
> + &gEfiUsbIoProtocolGuid,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle
>
> + );
>
> +
>
> + gBS->FreePool (UsbRndisDevice->Config);
>
> + gBS->FreePool (UsbRndisDevice);
>
> + return Status;
>
> + }
>
> +
>
> + GetEndpoint (UsbRndisDevice->UsbIo, UsbRndisDevice);
>
> +
>
> + DEBUG ((EFI_D_ERROR, "Rndis DeviceHandle %r\n",
> UsbRndisDevice->UsbRndisHandle));
>
> + DEBUG ((EFI_D_ERROR, "CDC DeviceHandle %r\n",
> UsbRndisDevice->UsbCdcDataHandle));
>
> + return EFI_SUCCESS;
>
> + }
>
> +
>
> + gBS->FreePool (UsbRndisDevice->Config);
>
> + gBS->FreePool (UsbRndisDevice);
>
> +
>
> + return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> + CheckandStopRndisDevice
>
> +
>
> + @param[in] This Protocol instance pointer.
>
> + @param[in] ControllerHandle Handle of device to bind driver to.
>
> +
>
> + @retval EFI_SUCCESS This driver is added to ControllerHandle
>
> + @retval EFI_DEVICE_ERROR This driver could not be started due to a
> device error
>
> + @retval other This driver does not support this device
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +CheckandStopRndisDevice (
>
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
>
> + IN EFI_HANDLE ControllerHandle
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + EFI_USB_IO_PROTOCOL *UsbIo;
>
> +
>
> + Status = 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 ((EFI_D_ERROR, "Rndis ControllerHandle Stop %r\n", Status));
>
> + return Status;
>
> + }
>
> +
>
> + return EFI_UNSUPPORTED;
>
> +}
>
> +
>
> +/**
>
> + USB Rndis Driver Binding Stop.
>
> +
>
> + @param[in] This Protocol instance pointer.
>
> + @param[in] ControllerHandle Handle of device to stop driver on
>
> + @param[in] NumberOfChildren Number of Handles in
> ChildHandleBuffer. If number of
>
> + children is zero stop the entire 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;
>
> + USB_ETHERNET_PROTOCOL *UsbEthProtocol;
>
> + USB_RNDIS_DEVICE *UsbRndisDevice;
>
> +
>
> + DEBUG ((EFI_D_ERROR, "UsbRndisDriverStop ControllerHandle %lx\n",
> ControllerHandle));
>
> +
>
> + Status = gBS->OpenProtocol (
>
> + ControllerHandle,
>
> + &gUsbEthProtocolGuid,
>
> + (VOID **)&UsbEthProtocol,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle,
>
> + EFI_OPEN_PROTOCOL_GET_PROTOCOL
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + Status = CheckandStopRndisDevice (This, ControllerHandle);
>
> +
>
> + DEBUG ((EFI_D_ERROR, "CheckandStopRndisDevice %r\n", Status));
>
> +
>
> + return Status;
>
> + }
>
> +
>
> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (UsbEthProtocol);
>
> +
>
> + Status = gBS->CloseProtocol (
>
> + UsbRndisDevice->UsbCdcDataHandle,
>
> + &gEfiUsbIoProtocolGuid,
>
> + This->DriverBindingHandle,
>
> + UsbRndisDevice->UsbCdcDataHandle
>
> + );
>
> +
>
> + Status = gBS->UninstallProtocolInterface (
>
> + ControllerHandle,
>
> + &gUsbEthProtocolGuid,
>
> + UsbEthProtocol
>
> + );
>
> + if (EFI_ERROR (Status)) {
>
> + DEBUG ((EFI_D_ERROR, "EFI_ERROR %r\n", Status));
>
> +
>
> + return Status;
>
> + }
>
> +
>
> + Status = gBS->CloseProtocol (
>
> + ControllerHandle,
>
> + &gEfiUsbIoProtocolGuid,
>
> + This->DriverBindingHandle,
>
> + ControllerHandle
>
> + );
>
> +
>
> + gBS->FreePool (UsbRndisDevice->Config);
>
> + gBS->FreePool (UsbRndisDevice);
>
> +
>
> + DEBUG ((EFI_D_ERROR, "UsbRndisDriverStop %r\n", Status));
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + Entrypoint of RNDIS Driver.
>
> +
>
> + This function is the entrypoint of RNDIS Driver. It installs Driver
> Binding
>
> + Protocols together with Component Name Protocols.
>
> +
>
> + @param[in] ImageHandle The firmware allocated handle for the EFI
> image.
>
> + @param[in] SystemTable A pointer to the EFI System Table.
>
> +
>
> + @retval EFI_SUCCESS The entry point is executed 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/UsbRndis.h
> b/UsbNetworkPkg/UsbRndis/UsbRndis.h
> new file mode 100644
> index 0000000000..680a9e67c9
> --- /dev/null
> +++ b/UsbNetworkPkg/UsbRndis/UsbRndis.h
> @@ -0,0 +1,569 @@
> +/** @file
>
> + Header file for for USB Rndis driver
>
> +
>
> + Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
>
> + Subject to AMI licensing agreement.
>
> +**/
>
> +
>
> +#ifndef _USB_RNDIS_H_
>
> +#define _USB_RNDIS_H_
>
> +
>
> +#include <Library/UefiDriverEntryPoint.h>
>
> +#include <Library/UefiBootServicesTableLib.h>
>
> +#include <Library/UefiLib.h>
>
> +#include <Library/DevicePathLib.h>
>
> +#include <Library/DebugLib.h>
>
> +#include <Library/MemoryAllocationLib.h>
>
> +#include <Library/BaseMemoryLib.h>
>
> +#include <Library/UefiUsbLib.h>
>
> +#include <Protocol/UsbIo.h>
>
> +#include <Protocol/UsbEthernetProtocol.h>
>
> +
>
> +typedef struct _REMOTE_NDIS_MSG_HEADER REMOTE_NDIS_MSG_HEADER;
>
> +
>
> +typedef struct {
>
> + UINT32 Signature;
>
> + USB_ETHERNET_PROTOCOL UsbEth;
>
> + EFI_HANDLE UsbCdcDataHandle;
>
> + EFI_HANDLE UsbRndisHandle;
>
> + EFI_USB_IO_PROTOCOL *UsbIo;
>
> + EFI_USB_IO_PROTOCOL *UsbIoCdcData;
>
> + EFI_USB_CONFIG_DESCRIPTOR *Config;
>
> + UINT8 NumOfInterface;
>
> + UINT8 BulkInEndpoint;
>
> + UINT8 BulkOutEndpoint;
>
> + UINT8 InterrupEndpoint;
>
> + EFI_MAC_ADDRESS MacAddress;
>
> + UINT32 RequestId;
>
> + UINT32 Medium;
>
> + UINT32 MaxPacketsPerTransfer;
>
> + UINT32 MaxTransferSize;
>
> + UINT32 PacketAlignmentFactor;
>
> + LIST_ENTRY ReceivePacketList;
>
> +} USB_RNDIS_DEVICE;
>
> +
>
> +#define USB_RNDIS_DRIVER_VERSION 1
>
> +#define USB_TX_ETHERNET_BULK_TIMEOUT 3000
>
> +#define USB_RX_ETHERNET_BULK_TIMEOUT 3
>
> +#define USB_ETHERNET_TRANSFER_TIMEOUT 200
>
> +
>
> +#define LAN_BULKIN_CMD_CONTROL 1
>
> +#define MAXIMUM_STOPBULKIN_CNT 300 // Indicating maximum
> counts for waiting bulk in command
>
> +#define MINIMUM_STOPBULKIN_CNT 3 // Indicating minimum
> counts for waiting bulk in command
>
> +#define BULKIN_CMD_POLLING_CNT 300 // Indicating the waiting
> counts for send bulk in command when system pending
>
> +
>
> +#define USB_RNDIS_SIGNATURE SIGNATURE_32('r', 'n', 'd', 's')
>
> +#define USB_RNDIS_DEVICE_FROM_THIS(a) CR (a, USB_RNDIS_DEVICE, UsbEth,
> USB_RNDIS_SIGNATURE)
>
> +
>
> +struct BIT_MAP {
>
> + unsigned int Src;
>
> + unsigned int Dst;
>
> +};
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbRndisDriverSupported (
>
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
>
> + IN EFI_HANDLE ControllerHandle,
>
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbRndisDriverStart (
>
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
>
> + IN EFI_HANDLE ControllerHandle,
>
> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbRndisDriverStop (
>
> + IN EFI_DRIVER_BINDING_PROTOCOL *This,
>
> + IN EFI_HANDLE ControllerHandle,
>
> + IN UINTN NumberOfChildren,
>
> + IN EFI_HANDLE *ChildHandleBuffer
>
> + );
>
> +
>
> +EFI_STATUS
>
> +LoadAllDescriptor (
>
> + IN EFI_USB_IO_PROTOCOL *UsbIo,
>
> + OUT EFI_USB_CONFIG_DESCRIPTOR **ConfigDesc
>
> + );
>
> +
>
> +BOOLEAN
>
> +NextDescriptor (
>
> + IN EFI_USB_CONFIG_DESCRIPTOR *Desc,
>
> + IN OUT UINTN *Offset
>
> + );
>
> +
>
> +EFI_STATUS
>
> +GetFunctionalDescriptor (
>
> + IN EFI_USB_CONFIG_DESCRIPTOR *Config,
>
> + IN UINT8 FunDescriptorType,
>
> + OUT VOID *DataBuffer
>
> + );
>
> +
>
> +VOID
>
> +GetEndpoint (
>
> + IN EFI_USB_IO_PROTOCOL *UsbIo,
>
> + IN OUT USB_RNDIS_DEVICE *UsbRndisDevice
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbRndisInterrupt (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN BOOLEAN IsNewTransfer,
>
> + IN UINTN PollingInterval,
>
> + IN EFI_USB_DEVICE_REQUEST *Requst
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +InterruptCallback (
>
> + IN VOID *Data,
>
> + IN UINTN DataLength,
>
> + IN VOID *Context,
>
> + IN UINT32 Status
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetUsbEthMacAddress (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT EFI_MAC_ADDRESS *MacAddress
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbEthBulkSize (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT UINTN *BulkSize
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +RndisDummyReturn (
>
> + IN PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +RndisUndiStart (
>
> + IN PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +RndisUndiStop (
>
> + IN PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +RndisUndiGetInitInfo (
>
> + IN PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +RndisUndiGetConfigInfo (
>
> + IN PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +RndisUndiInitialize (
>
> + IN PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +RndisUndiTransmit (
>
> + IN PXE_CDB *Cdb,
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN VOID *BulkOutData,
>
> + IN OUT UINTN *DataLength
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +RndisUndiReceive (
>
> + IN PXE_CDB *Cdb,
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN OUT VOID *BulkInData,
>
> + IN OUT UINTN *DataLength
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +RndisUndiReset (
>
> + IN PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +RndisUndiShutdown (
>
> + IN PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +RndisUndiReceiveFilter (
>
> + IN PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +RndisUndiGetStatus (
>
> + IN PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetUsbHeaderFunDescriptor (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetUsbUnionFunDescriptor (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetUsbRndisFunDescriptor (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +SetUsbRndisMcastFilter (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value,
>
> + IN VOID *McastAddr
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +SetUsbRndisPowerFilter (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value,
>
> + IN UINT16 Length,
>
> + IN VOID *PatternFilter
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetUsbRndisPowerFilter (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value,
>
> + IN BOOLEAN *PatternActive
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +SetUsbRndisPacketFilter (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value
>
> + );
>
> +
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetRndisStatistic (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value,
>
> + IN VOID *Statistic
>
> + );
>
> +
>
> +EFI_STATUS
>
> +SendRndisSetMsg (
>
> + IN USB_RNDIS_DEVICE *UsbRndisDevice,
>
> + UINT8 Oid,
>
> + UINT32 Length,
>
> + UINT8 *Buf
>
> + );
>
> +
>
> +EFI_STATUS
>
> +RndisControlMsg (
>
> + IN USB_RNDIS_DEVICE *UsbRndisDevice,
>
> + IN REMOTE_NDIS_MSG_HEADER *RndisMsg,
>
> + OUT REMOTE_NDIS_MSG_HEADER *RndisMsgResponse
>
> + );
>
> +
>
> +EFI_STATUS
>
> +RndisTransmitDataMsg (
>
> + IN USB_RNDIS_DEVICE *UsbRndisDevice,
>
> + IN REMOTE_NDIS_MSG_HEADER *RndisMsg,
>
> + UINTN *TransferLength
>
> + );
>
> +
>
> +EFI_STATUS
>
> +RndisReceiveDataMsg (
>
> + IN USB_RNDIS_DEVICE *UsbRndisDevice,
>
> + IN REMOTE_NDIS_MSG_HEADER *RndisMsg,
>
> + UINTN *TransferLength
>
> + );
>
> +
>
> +VOID
>
> +PrintRndisMsg (
>
> + IN REMOTE_NDIS_MSG_HEADER *RndisMsg
>
> + );
>
> +
>
> +#define RNDIS_MAJOR_VERSION 0x00000001
>
> +#define RNDIS_MINOR_VERSION 0x00000000
>
> +#define RNDIS_MAX_TRANSFER_SIZE 0x4000
>
> +
>
> +#define RNDIS_PACKET_MSG 0x00000001
>
> +#define RNDIS_INITIALIZE_MSG 0x00000002
>
> +#define RNDIS_INITIALIZE_CMPLT 0x80000002
>
> +#define RNDIS_HLT_MSG 0x00000003
>
> +#define RNDIS_QUERY_MSG 0x00000004
>
> +#define RNDIS_QUERY_CMPLT 0x80000004
>
> +#define RNDIS_SET_MSG 0x00000005
>
> +#define RNDIS_SET_CMPLT 0x80000005
>
> +#define RNDIS_RESET_MSG 0x00000006
>
> +#define RNDIS_RESET_CMPLT 0x80000006
>
> +#define RNDIS_INDICATE_STATUS_MSG 0x00000007
>
> +#define RNDIS_KEEPALIVE_MSG 0x00000008
>
> +#define RNDIS_KEEPALIVE_CMPLT 0x80000008
>
> +
>
> +#define RNDIS_STATUS_SUCCESS 0x00000000
>
> +#define RNDIS_STATUS_FAILURE 0xC0000001
>
> +#define RNDIS_STATUS_INVALID_DATA 0xC0010015
>
> +#define RNDIS_STATUS_NOT_SUPPORTED 0xC00000BB
>
> +#define RNDIS_STATUS_MEDIA_CONNECT 0x4001000B
>
> +#define RNDIS_STATUS_MEDIA_DISCONNECT 0x4001000C
>
> +
>
> +#define RNDIS_CONTROL_TIMEOUT 10000 // 10sec
>
> +#define RNDIS_KEEPALIVE_TIMEOUT 5000 // 5sec
>
> +
>
> +#define SEND_ENCAPSULATED_COMMAND 0x00000000
>
> +#define GET_ENCAPSULATED_RESPONSE 0x00000001
>
> +
>
> +//
>
> +// General Objects
>
> +//
>
> +// Taken from NTDDNDIS.H
>
> +#define OID_GEN_SUPPORTED_LIST 0x00010101
>
> +#define OID_GEN_HARDWARE_STATUS 0x00010102
>
> +#define OID_GEN_MEDIA_SUPPORTED 0x00010103
>
> +#define OID_GEN_MEDIA_IN_USE 0x00010104
>
> +#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105
>
> +#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106
>
> +#define OID_GEN_LINK_SPEED 0x00010107
>
> +#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108
>
> +#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109
>
> +#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A
>
> +#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B
>
> +#define OID_GEN_VENDOR_ID 0x0001010C
>
> +#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D
>
> +#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E
>
> +#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F
>
> +#define OID_GEN_DRIVER_VERSION 0x00010110
>
> +#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111
>
> +#define OID_GEN_PROTOCOL_OPTIONS 0x00010112
>
> +#define OID_GEN_MAC_OPTIONS 0x00010113
>
> +#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114
>
> +#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115
>
> +#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116
>
> +
>
> +#define OID_GEN_XMIT_OK 0x00020101
>
> +#define OID_GEN_RCV_OK 0x00020102
>
> +#define OID_GEN_XMIT_ERROR 0x00020103
>
> +#define OID_GEN_RCV_ERROR 0x00020104
>
> +#define OID_GEN_RCV_NO_BUFFER 0x00020105
>
> +
>
> +#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201
>
> +#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202
>
> +#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203
>
> +#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204
>
> +#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205
>
> +#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206
>
> +#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207
>
> +#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208
>
> +#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209
>
> +#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A
>
> +#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B
>
> +#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C
>
> +#define OID_GEN_RCV_CRC_ERROR 0x0002020D
>
> +#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E
>
> +
>
> +//
>
> +// Ndis Packet Filter Bits (OID_GEN_CURRENT_PACKET_FILTER).
>
> +//
>
> +#define NDIS_PACKET_TYPE_DIRECTED 0x0001
>
> +#define NDIS_PACKET_TYPE_MULTICAST 0x0002
>
> +#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x0004
>
> +#define NDIS_PACKET_TYPE_BROADCAST 0x0008
>
> +#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x0010
>
> +#define NDIS_PACKET_TYPE_PROMISCUOUS 0x0020
>
> +#define NDIS_PACKET_TYPE_SMT 0x0040
>
> +#define NDIS_PACKET_TYPE_ALL_LOCAL 0x0080
>
> +#define NDIS_PACKET_TYPE_MAC_FRAME 0x8000
>
> +#define NDIS_PACKET_TYPE_FUNCTIONAL 0x4000
>
> +#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x2000
>
> +#define NDIS_PACKET_TYPE_GROUP 0x1000
>
> +
>
> +#pragma pack(1)
>
> +
>
> +typedef struct _REMOTE_NDIS_MSG_HEADER {
>
> + UINT32 MessageType;
>
> + UINT32 MessageLength;
>
> +} REMOTE_NDIS_MSG_HEADER;
>
> +
>
> +typedef struct {
>
> + UINT32 MessageType;
>
> + UINT32 MessageLength;
>
> + UINT32 RequestID;
>
> + UINT32 MajorVersion;
>
> + UINT32 MinorVersion;
>
> + UINT32 MaxTransferSize;
>
> +} REMOTE_NDIS_INITIALIZE_MSG;
>
> +
>
> +typedef struct {
>
> + UINT32 MessageType;
>
> + UINT32 MessageLength;
>
> + UINT32 RequestID;
>
> +} REMOTE_NDIS_HALT_MSG;
>
> +
>
> +typedef struct {
>
> + UINT32 MessageType;
>
> + UINT32 MessageLength;
>
> + UINT32 RequestID;
>
> + UINT32 Oid;
>
> + UINT32 InformationBufferLength;
>
> + UINT32 InformationBufferOffset;
>
> + UINT32 Reserved;
>
> +} REMOTE_NDIS_QUERY_MSG;
>
> +
>
> +typedef struct {
>
> + UINT32 MessageType;
>
> + UINT32 MessageLength;
>
> + UINT32 RequestID;
>
> + UINT32 Oid;
>
> + UINT32 InformationBufferLength;
>
> + UINT32 InformationBufferOffset;
>
> + UINT32 Reserved;
>
> +} REMOTE_NDIS_SET_MSG;
>
> +
>
> +typedef struct {
>
> + UINT32 MessageType;
>
> + UINT32 MessageLength;
>
> + UINT32 Reserved;
>
> +} REMOTE_NDIS_RESET_MSG;
>
> +
>
> +typedef struct {
>
> + UINT32 MessageType;
>
> + UINT32 MessageLength;
>
> + UINT32 Status;
>
> + UINT32 StatusBufferLength;
>
> + UINT32 StatusBufferOffset;
>
> +} REMOTE_NDIS_INDICATE_STATUS_MSG;
>
> +
>
> +typedef struct {
>
> + UINT32 DiagStatus;
>
> + UINT32 ErrorOffset;
>
> +} RNDIS_DIAGNOSTIC_INFO;
>
> +
>
> +typedef struct {
>
> + UINT32 MessageType;
>
> + UINT32 MessageLength;
>
> + UINT32 RequestID;
>
> +} REMOTE_NDIS_KEEPALIVE_MSG;
>
> +
>
> +typedef struct {
>
> + UINT32 MessageType;
>
> + UINT32 MessageLength;
>
> + UINT32 RequestID;
>
> + UINT32 Status;
>
> + UINT32 MajorVersion;
>
> + UINT32 MinorVersion;
>
> + UINT32 DeviceFlags;
>
> + UINT32 Medium;
>
> + UINT32 MaxPacketsPerTransfer;
>
> + UINT32 MaxTransferSize;
>
> + UINT32 PacketAlignmentFactor;
>
> + UINT64 Reserved;
>
> +} REMOTE_NDIS_INITIALIZE_CMPLT;
>
> +
>
> +typedef struct {
>
> + UINT32 MessageType;
>
> + UINT32 MessageLength;
>
> + UINT32 RequestID;
>
> + UINT32 Status;
>
> + UINT32 InformationBufferLength;
>
> + UINT32 InformationBufferOffset;
>
> +} REMOTE_NDIS_QUERY_CMPLT;
>
> +
>
> +typedef struct {
>
> + UINT32 MessageType;
>
> + UINT32 MessageLength;
>
> + UINT32 RequestID;
>
> + UINT32 Status;
>
> +} REMOTE_NDIS_SET_CMPLT;
>
> +
>
> +typedef struct {
>
> + UINT32 MessageType;
>
> + UINT32 MessageLength;
>
> + UINT32 Status;
>
> + UINT32 AddressingReset;
>
> +} REMOTE_NDIS_RESET_CMPLT;
>
> +
>
> +typedef struct {
>
> + UINT32 MessageType;
>
> + UINT32 MessageLength;
>
> + UINT32 RequestID;
>
> + UINT32 Status;
>
> +} REMOTE_NDIS_KEEPALIVE_CMPLT;
>
> +
>
> +typedef struct {
>
> + UINT32 MessageType;
>
> + UINT32 MessageLength;
>
> + UINT32 DataOffset;
>
> + UINT32 DataLength;
>
> + UINT32 OutOfBandDataOffset;
>
> + UINT32 OutOfBandDataLength;
>
> + UINT32 NumOutOfBandDataElements;
>
> + UINT32 PerPacketInfoOffset;
>
> + UINT32 PerPacketInfoLength;
>
> + UINT32 Reserved1;
>
> + UINT32 Reserved2;
>
> +} REMOTE_NDIS_PACKET_MSG;
>
> +
>
> +typedef struct {
>
> + UINT32 Size;
>
> + UINT32 Type;
>
> + UINT32 ClassInformationOffset;
>
> +} OUT_OF_BAND_DATA_RECORD;
>
> +
>
> +typedef struct {
>
> + UINT32 Size;
>
> + UINT32 Type;
>
> + UINT32 ClassInformationOffset;
>
> +} PER_PACKET_INFO_DATA_RECORD;
>
> +
>
> +typedef struct {
>
> + LIST_ENTRY PacketList;
>
> + UINT8 *OrgBuffer;
>
> + UINTN RemainingLength;
>
> +} PACKET_LIST;
>
> +
>
> +#pragma pack()
>
> +
>
> +#endif
>
> diff --git a/UsbNetworkPkg/UsbRndis/UsbRndis.inf
> b/UsbNetworkPkg/UsbRndis/UsbRndis.inf
> new file mode 100644
> index 0000000000..909b106059
> --- /dev/null
> +++ b/UsbNetworkPkg/UsbRndis/UsbRndis.inf
> @@ -0,0 +1,41 @@
> +## @file
> +# This is Usb Rndis driver for DXE phase.
> +#
> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
> +# Subject to AMI licensing agreement.
> +##
> +
> +[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
> +
> +[Depex]
> + TRUE
> diff --git a/UsbNetworkPkg/UsbRndis/UsbRndisFunction.c
> b/UsbNetworkPkg/UsbRndis/UsbRndisFunction.c
> new file mode 100644
> index 0000000000..a9b7b54f6a
> --- /dev/null
> +++ b/UsbNetworkPkg/UsbRndis/UsbRndisFunction.c
> @@ -0,0 +1,1587 @@
> +/** @file
>
> + This file contains code for USB Ethernet descriptor
>
> + and specific requests implement.
>
> +
>
> + Copyright (c) 1985 - 2022, AMI. All rights reserved.<BR>
>
> + Subject to AMI licensing agreement.
>
> +**/
>
> +
>
> +#include "UsbRndis.h"
>
> +
>
> +UINT16 StopBulkInCnt = 0;
>
> +UINT16 BlockBulkInCnt = 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);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + Status = gBS->AllocatePool (
>
> + EfiBootServicesData,
>
> + Tmp.TotalLength,
>
> + (VOID **)ConfigDesc
>
> + );
>
> + ASSERT_EFI_ERROR (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 = EFI_NOT_FOUND;
>
> + UINTN Offset;
>
> + EFI_USB_INTERFACE_DESCRIPTOR *Interface;
>
> +
>
> + 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);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + if (Interface.NumEndpoints == 0 ) {
>
> + Status = UsbSetInterface (UsbIo, 1, 0, &Result);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
>
> + ASSERT_EFI_ERROR (Status);
>
> + }
>
> +
>
> + for (Index = 0; Index < Interface.NumEndpoints; Index++) {
>
> + Status = UsbIo->UsbGetEndpointDescriptor (UsbIo, Index, &Endpoint);
>
> +
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + 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 (((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 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 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 = 0;
>
> +
>
> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This);
>
> +
>
> + 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;
>
> +}
>
> +
>
> +/**
>
> + Retrieves the USB Ethernet Mac Address.
>
> +
>
> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL
> instance.
>
> + @param[out] MacAddress A pointer to the caller allocated USB
> Ethernet Mac Address.
>
> +
>
> + @retval EFI_SUCCESS The USB Header Functional descriptor 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 USB_ETHERNET_PROTOCOL *This,
>
> + OUT EFI_MAC_ADDRESS *MacAddress
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + USB_RNDIS_DEVICE *UsbRndisDevice;
>
> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthDescriptor;
>
> + CHAR16 *Data;
>
> + CHAR16 *DataPtr;
>
> + CHAR16 TmpStr[1];
>
> + UINT8 Index;
>
> + UINT8 Hi;
>
> + UINT8 Low;
>
> +
>
> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This);
>
> +
>
> + Status = This->UsbEthFunDescriptor (This, &UsbEthDescriptor);
>
> + ASSERT_EFI_ERROR (Status);
>
> +
>
> + Status = UsbRndisDevice->UsbIo->UsbGetStringDescriptor (
>
> + UsbRndisDevice->UsbIo,
>
> + 0x409, //
> English-US Language ID
>
> + UsbEthDescriptor.MacAddress,
>
> + &Data
>
> + );
>
> + ASSERT_EFI_ERROR (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 USB_ETHERNET_PROTOCOL
> instance.
>
> + @param[out] BulkSize A pointer to the Bulk transfer data size.
>
> +
>
> + @retval EFI_SUCCESS The bulk transfer data size was retrieved
> successfully.
>
> + @retval other Failed to retrieve the bulk transfer data
> size.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +UsbEthBulkSize (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT UINTN *BulkSize
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor;
>
> +
>
> + Status = 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
> 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 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
> USB_ETHERNET_PROTOCOL instance.
>
> + @param[out] UsbUnionFunDescriptor A pointer to the caller allocated
> USB Union Functional Descriptor.
>
> +
>
> + @retval EFI_SUCCESS The USB Union Functional descriptor was
> retrieved successfully.
>
> + @retval EFI_INVALID_PARAMETER UsbUnionFunDescriptor is NULL.
>
> + @retval EFI_NOT_FOUND The USB Union Functional descriptor was
> not found.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetUsbUnionFunDescriptor (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + USB_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.
>
> +
>
> + @param[in] This A pointer to the
> USB_ETHERNET_PROTOCOL instance.
>
> + @param[out] UsbEthFunDescriptor A pointer to the caller allocated
> USB Ethernet Functional Descriptor.
>
> +
>
> + @retval EFI_SUCCESS The USB Ethernet Functional descriptor
> was retrieved successfully.
>
> + @retval EFI_INVALID_PARAMETER UsbEthFunDescriptor is NULL.
>
> + @retval EFI_NOT_FOUND The USB Ethernet Functional descriptor
> was not found.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetUsbRndisFunDescriptor (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + USB_RNDIS_DEVICE *UsbRndisDevice;
>
> +
>
> + UsbRndisDevice = 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
> USB_ETHERNET_PROTOCOL instance.
>
> + @param[in] Value Number of filters.
>
> + @param[in] McastAddr A pointer to the value of the
> multicast addresses.
>
> +
>
> + @retval EFI_SUCCESS The request executed successfully.
>
> + @retval EFI_TIMEOUT A timeout occurred executing the request.
>
> + @retval EFI_DEVICE_ERROR The request failed due to a device error.
>
> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid
> value.
>
> + @retval EFI_UNSUPPORTED Not supported.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +SetUsbRndisMcastFilter (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value,
>
> + IN VOID *McastAddr
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + EFI_USB_DEVICE_REQUEST Request;
>
> + UINT32 TransStatus;
>
> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor;
>
> + USB_RNDIS_DEVICE *UsbRndisDevice;
>
> +
>
> + UsbRndisDevice = 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_ETHRTNET_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
> 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 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_ETHRTNET_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
> USB_ETHERNET_PROTOCOL instance.
>
> + @param[in] Value The filter number.
>
> + @param[out] PatternActive A pointer to the pattern active
> boolean.
>
> +
>
> + @retval EFI_SUCCESS The request executed successfully.
>
> + @retval EFI_TIMEOUT A timeout occurred executing the request.
>
> + @retval EFI_DEVICE_ERROR The request failed due to a device error.
>
> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid
> value.
>
> + @retval EFI_UNSUPPORTED Not supported.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +GetUsbRndisPowerFilter (
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value,
>
> + OUT BOOLEAN *PatternActive
>
> + )
>
> +{
>
> + EFI_USB_DEVICE_REQUEST Request;
>
> + UINT32 TransStatus;
>
> + USB_RNDIS_DEVICE *UsbRndisDevice;
>
> +
>
> + UsbRndisDevice = 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 = 0;
>
> + UINT8 Index1;
>
> + UINT8 Index2;
>
> + UINT64 CpbAddr = Cdb->CPBaddr;
>
> + UINT32 CpbSize = Cdb->CPBsize;
>
> + UINT16 SetFilter = (UINT16)(Cdb->OpFlags & 0x1F);
>
> + PXE_CPB_RECEIVE_FILTERS *Cpb = (PXE_CPB_RECEIVE_FILTERS
> *)(UINTN)CpbAddr;
>
> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor;
>
> +
>
> + // 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;
>
> + }
>
> +
>
> + if (Nic->CanReceive) {
>
> + Nic->CanReceive = FALSE;
>
> + }
>
> +
>
> + 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);
>
> + gBS->FreePool (McastList);
>
> + }
>
> + }
>
> +
>
> + return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> + This request is used to configure device Ethernet packet filter
> settings.
>
> +
>
> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL
> instance.
>
> + @param[in] Value Packet Filter Bitmap.
>
> +
>
> + @retval EFI_SUCCESS The request executed successfully.
>
> + @retval EFI_TIMEOUT A timeout occurred executing the 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 USB_ETHERNET_PROTOCOL *This,
>
> + IN UINT16 Value
>
> + )
>
> +{
>
> + return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> + This request is used to retrieve a statistic based on the feature
> selector.
>
> +
>
> + @param[in] This A pointer to the
> USB_ETHERNET_PROTOCOL instance.
>
> + @param[in] FeatureSelector Value of the feature selector.
>
> + @param[out] Statistic A pointer to the 32 bit unsigned
> integer.
>
> +
>
> + @retval EFI_SUCCESS The request executed successfully.
>
> + @retval EFI_TIMEOUT A timeout occurred executing the 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 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
>
> + )
>
> +{
>
> + USB_ETHERNET_PROTOCOL *UsbEthDevice = Nic->UsbEth;
>
> + USB_RNDIS_DEVICE *UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS
> (UsbEthDevice);
>
> + PXE_DB_GET_INIT_INFO *Db;
>
> +
>
> + DEBUG ((DEBUG_INFO, "RndisUndiGetInitInfo\n"));
>
> +
>
> + 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
>
> + )
>
> +{
>
> + USB_ETHERNET_PROTOCOL *UsbEthDriver = Nic->UsbEth;
>
> + USB_RNDIS_DEVICE *UsbRndisDevice =
> USB_RNDIS_DEVICE_FROM_THIS (UsbEthDriver);
>
> + REMOTE_NDIS_INITIALIZE_MSG RndisInitMsg;
>
> + REMOTE_NDIS_INITIALIZE_CMPLT RndisInitMsgCmplt;
>
> + EFI_STATUS Status;
>
> +
>
> + DEBUG ((DEBUG_INFO, "RndisUndiInitialize\n"));
>
> +
>
> + ZeroMem (&RndisInitMsg, sizeof (REMOTE_NDIS_INITIALIZE_MSG));
>
> + ZeroMem (&RndisInitMsgCmplt, sizeof (REMOTE_NDIS_INITIALIZE_CMPLT));
>
> +
>
> + RndisInitMsg.MessageType = 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
>
> + )
>
> +{
>
> + USB_ETHERNET_PROTOCOL *UsbEthDriver = Nic->UsbEth;
>
> + USB_RNDIS_DEVICE *UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS
> (UsbEthDriver);
>
> + REMOTE_NDIS_RESET_MSG RndisResetMsg;
>
> + REMOTE_NDIS_RESET_CMPLT RndisResetCmplt;
>
> + EFI_STATUS Status;
>
> +
>
> + DEBUG ((DEBUG_INFO, "RndisUndiReset\n"));
>
> +
>
> + ZeroMem (&RndisResetMsg, sizeof (REMOTE_NDIS_RESET_MSG));
>
> + ZeroMem (&RndisResetCmplt, sizeof (REMOTE_NDIS_RESET_CMPLT));
>
> +
>
> + RndisResetMsg.MessageType = 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
>
> + )
>
> +{
>
> + USB_ETHERNET_PROTOCOL *UsbEthDriver = Nic->UsbEth;
>
> + USB_RNDIS_DEVICE *UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS
> (UsbEthDriver);
>
> + REMOTE_NDIS_HALT_MSG RndisHltMsg;
>
> + EFI_STATUS Status;
>
> +
>
> + DEBUG ((DEBUG_INFO, "RndisUndiShutdown\n"));
>
> +
>
> + ZeroMem (&RndisHltMsg, sizeof (REMOTE_NDIS_HALT_MSG));
>
> +
>
> + RndisHltMsg.MessageType = 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 USB_ETHERNET_PROTOCOL
> instance.
>
> + @param[in] BulkOutData A pointer to the buffer of data that will
> be transmitted to USB
>
> + device or received from USB device.
>
> + @param[in, out] DataLength A pointer to the PacketLength.
>
> +
>
> + @retval EFI_SUCCESS The request executed successfully.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +RndisUndiTransmit (
>
> + IN PXE_CDB *Cdb,
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN VOID *BulkOutData,
>
> + IN OUT UINTN *DataLength
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + USB_RNDIS_DEVICE *UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS
> (This);
>
> + REMOTE_NDIS_PACKET_MSG *RndisPacketMsg;
>
> + UINTN TransferLength;
>
> +
>
> + DEBUG ((DEBUG_INFO, "RndisUndiTransmit DataLength : %x\n",
> *DataLength));
>
> +
>
> + Status = gBS->AllocatePool (EfiBootServicesData, sizeof
> (REMOTE_NDIS_PACKET_MSG) + *DataLength, (VOID **)&RndisPacketMsg);
>
> +
>
> + ZeroMem (RndisPacketMsg, sizeof (REMOTE_NDIS_PACKET_MSG));
>
> +
>
> + 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;
>
> +
>
> + gBS->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));
>
> +
>
> + gBS->FreePool (RndisPacketMsg);
>
> +
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + Receives and removes RNDIS header and returns the raw data.
>
> +
>
> + @param[in] Cdb A pointer to the command descriptor block.
>
> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL
> instance.
>
> + @param[in, out] BulkInData A pointer to the buffer of data that will
> be transmitted to USB
>
> + device or received from USB device.
>
> + @param[in, out] DataLength A pointer to the PacketLength.
>
> +
>
> + @retval EFI_SUCCESS The request executed successfully.
>
> + @retval EFI_BUFFER_TOO_SMALL The user provided buffer is too small
>
> + @retval EFI_NOT_FOUND No buffer was found in the list.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +RndisUndiReceive (
>
> + IN PXE_CDB *Cdb,
>
> + IN USB_ETHERNET_PROTOCOL *This,
>
> + IN OUT VOID *BulkInData,
>
> + IN OUT UINTN *DataLength
>
> + )
>
> +{
>
> + EFI_STATUS Status;
>
> + USB_RNDIS_DEVICE *UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS
> (This);
>
> + REMOTE_NDIS_PACKET_MSG *RndisPacketMsg;
>
> + UINTN TransferLength;
>
> + VOID *Buffer;
>
> + PACKET_LIST *HeadPacket = NULL;
>
> + PACKET_LIST *PacketList;
>
> + UINT32 ReceivedBytes = 0;
>
> +
>
> + // Check if there is any outstanding packet to receive
>
> + // The buffer allocated has a linked List followed by the packet.
>
> + do {
>
> + Status = gBS->AllocatePool (EfiBootServicesData, sizeof
> (PACKET_LIST) + sizeof (REMOTE_NDIS_PACKET_MSG) +
> UsbRndisDevice->MaxTransferSize, &Buffer);
>
> + RndisPacketMsg = (REMOTE_NDIS_PACKET_MSG *)(sizeof (PACKET_LIST) +
> (UINT8 *)Buffer);
>
> + PacketList = (PACKET_LIST *)Buffer;
>
> + // Save the original address for freeing it up
>
> + PacketList->OrgBuffer = Buffer;
>
> + PacketList->RemainingLength = UsbRndisDevice->MaxTransferSize;
>
> +
>
> + ZeroMem (RndisPacketMsg, sizeof (REMOTE_NDIS_PACKET_MSG));
>
> + TransferLength = UsbRndisDevice->MaxTransferSize;
>
> +
>
> + Status = RndisReceiveDataMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_HEADER
> *)RndisPacketMsg, &TransferLength);
>
> +
>
> + if (EFI_ERROR (Status) || (TransferLength == 0)) {
>
> + gBS->FreePool (Buffer);
>
> + break;
>
> + }
>
> +
>
> + // Handle Multiple packets
>
> + if ((RndisPacketMsg->MessageType == RNDIS_PACKET_MSG) &&
> (RndisPacketMsg->DataOffset == sizeof (REMOTE_NDIS_PACKET_MSG) - 8)) {
>
> + // Insert Packet
>
> + InsertTailList (&UsbRndisDevice->ReceivePacketList, Buffer);
>
> + }
>
> + } while (1);
>
> +
>
> + // Check if they linked list has any received buffer. If yes report it.
>
> + if (IsListEmpty (&UsbRndisDevice->ReceivePacketList)) {
>
> + return EFI_NOT_FOUND;
>
> + }
>
> +
>
> + HeadPacket = (PACKET_LIST *)GetFirstNode
> (&UsbRndisDevice->ReceivePacketList);
>
> +
>
> + RndisPacketMsg = (REMOTE_NDIS_PACKET_MSG *)((UINT8 *)HeadPacket +
> sizeof (PACKET_LIST));
>
> +
>
> + PrintRndisMsg ((REMOTE_NDIS_MSG_HEADER *)RndisPacketMsg);
>
> +
>
> + if ((RndisPacketMsg->MessageType == RNDIS_PACKET_MSG) &&
> (RndisPacketMsg->DataOffset == sizeof (REMOTE_NDIS_PACKET_MSG) - 8)) {
>
> + if (*DataLength >= RndisPacketMsg->DataLength) {
>
> + gBS->CopyMem (BulkInData, (UINT8 *)RndisPacketMsg +
> RndisPacketMsg->DataOffset + 8, RndisPacketMsg->DataLength);
>
> +
>
> + ReceivedBytes +=
> RndisPacketMsg->DataLength;
>
> + BulkInData = ((UINT8
> *)BulkInData) + RndisPacketMsg->DataLength;
>
> + ((PACKET_LIST *)HeadPacket)->RemainingLength -=
> RndisPacketMsg->DataLength;
>
> + } else {
>
> + DEBUG ((EFI_D_ERROR, "RndisUndiReceive:Buffer too small %x\n",
> RndisPacketMsg->DataLength));
>
> + *DataLength = RndisPacketMsg->DataLength;
>
> + return EFI_BUFFER_TOO_SMALL;
>
> + }
>
> +
>
> + // check if there this is a multi-packet message. If so update the
> pointer so that next Receive call will return that data.
>
> + RndisPacketMsg = (REMOTE_NDIS_PACKET_MSG *)((UINT8 *)RndisPacketMsg +
> RndisPacketMsg->DataLength);
>
> + PacketList = (PACKET_LIST *)((UINT8 *)RndisPacketMsg - sizeof
> (PACKET_LIST));
>
> +
>
> + if ((HeadPacket->RemainingLength > sizeof (REMOTE_NDIS_PACKET_MSG))
> && \
>
> + (RndisPacketMsg->MessageType == RNDIS_PACKET_MSG) && \
>
> + (RndisPacketMsg->DataOffset == sizeof (REMOTE_NDIS_PACKET_MSG) -
> 8))
>
> + {
>
> + // Multi-Packet msg is found. Since the first packet is consumed,
> update the linked list to point this new packet.
>
> + PacketList->OrgBuffer = HeadPacket->OrgBuffer;
>
> + PacketList->RemainingLength = HeadPacket->RemainingLength;
>
> + RemoveEntryList (&HeadPacket->PacketList);
>
> + InsertHeadList (&UsbRndisDevice->ReceivePacketList,
> &(PacketList->PacketList));
>
> + } else {
>
> + RemoveEntryList (&HeadPacket->PacketList);
>
> + gBS->FreePool ((PACKET_LIST *)HeadPacket->OrgBuffer);
>
> + }
>
> + } else {
>
> + // Packet doesn't contain valid header
>
> + DEBUG ((DEBUG_INFO, "RndisUndiReceive:Invalid RNDIS Packet
> received\n"));
>
> + RemoveEntryList (&(HeadPacket->PacketList));
>
> + gBS->FreePool ((PACKET_LIST *)HeadPacket->OrgBuffer);
>
> + }
>
> +
>
> + if (ReceivedBytes) {
>
> + *DataLength = ReceivedBytes;
>
> + }
>
> +
>
> + return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> + This is a dummy function which just returns. Unimplimented
> USB_ETHERNET_PROTOCOL functions
>
> + point to this function.
>
> +
>
> + @param[in] Cdb A pointer to the command descriptor block.
>
> + @param[in] Nic A pointer to the Network interface controller data.
>
> +
>
> + @retval EFI_SUCCESS The request executed successfully.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +EFIAPI
>
> +RndisDummyReturn (
>
> + IN PXE_CDB *Cdb,
>
> + IN NIC_DATA *Nic
>
> + )
>
> +{
>
> + DEBUG ((DEBUG_INFO, "RndisDummyReturn called\n"));
>
> + return EFI_SUCCESS;
>
> +}
>
> +
>
> +/**
>
> + This function sends the RNDIS SET_MSG cmd
>
> +
>
> + @param[in] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE instance.
>
> + @param[in] Oid Value of the OID.
>
> + @param[in] Length Length of the data buffer.
>
> + @param[in] Buf A pointer to the data buffer.
>
> +
>
> + @retval EFI_SUCCESS The request executed successfully.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +SendRndisSetMsg (
>
> + IN USB_RNDIS_DEVICE *UsbRndisDevice,
>
> + IN UINT8 Oid,
>
> + IN UINT32 Length,
>
> + IN UINT8 *Buf
>
> + )
>
> +{
>
> + REMOTE_NDIS_SET_MSG *RndisSetMsg;
>
> + EFI_STATUS Status;
>
> +
>
> + RndisSetMsg = AllocateZeroPool (sizeof (USB_RNDIS_DEVICE) + Length);
>
> +
>
> + RndisSetMsg->MessageType = RNDIS_SET_MSG;
>
> + RndisSetMsg->MessageLength = sizeof (REMOTE_NDIS_SET_MSG) +
> Length;
>
> + RndisSetMsg->RequestID = UsbRndisDevice->RequestId;
>
> + RndisSetMsg->Oid = Oid;
>
> + RndisSetMsg->InformationBufferLength = Length;
>
> + RndisSetMsg->InformationBufferOffset = sizeof (REMOTE_NDIS_SET_MSG) - 8;
>
> +
>
> + gBS->CopyMem (((UINT8 *)RndisSetMsg) + sizeof (REMOTE_NDIS_SET_MSG),
> Buf, Length);
>
> +
>
> + Status = RndisControlMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_HEADER
> *)RndisSetMsg, NULL);
>
> +
>
> + gBS->FreePool (RndisSetMsg);
>
> +
>
> + return Status;
>
> +}
>
> +
>
> +/**
>
> + This function send the RNDIS command through the device's control
> endpoint
>
> +
>
> + @param[in] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE
> instance.
>
> + @param[in] RndisMsg A pointer to the REMOTE_NDIS_MSG_HEADER
> data.
>
> + @param[out] RndisMsgResponse A pointer to the REMOTE_NDIS_MSG_HEADER
> data for getting responses.
>
> +
>
> + @retval EFI_SUCCESS The bulk transfer has been successfully
> executed.
>
> +
>
> +**/
>
> +EFI_STATUS
>
> +RndisControlMsg (
>
> + IN USB_RNDIS_DEVICE *UsbRndisDevice,
>
> + IN REMOTE_NDIS_MSG_HEADER *RndisMsg,
>
> + OUT REMOTE_NDIS_MSG_HEADER *RndisMsgResponse
>
> + )
>
> +{
>
> + EFI_USB_IO_PROTOCOL *UsbIo = UsbRndisDevice->UsbIo;
>
> + EFI_USB_DEVICE_REQUEST DevReq;
>
> + UINT32 UsbStatus;
>
> + EFI_STATUS Status;
>
> + UINT32 SaveResponseType = 0;
>
> + UINT32 SaveResponseLength = 0;
>
> + UINT32 Index;
>
> + REMOTE_NDIS_INITIALIZE_CMPLT *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++) {
>
> + 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"));
>
> + continue;
>
> + }
>
> +
>
> + return Status;
>
> + }
>
> +
>
> + RndisMsgResponse->MessageType = SaveResponseType;
>
> + RndisMsgResponse->MessageLength = SaveResponseLength;
>
> +
>
> + gBS->Stall (100000); // 100msec
>
> + }
>
> +
>
> + DEBUG ((DEBUG_INFO, "RndisControlMsg: TimeOut\n"));
>
> +
>
> + return EFI_TIMEOUT;
>
> +}
>
> +
>
> +/**
>
> + This function send the RNDIS command through the device's Data 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) {
>
> + StopBulkInCnt = 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 = 0;
>
> +
>
> + if (UsbRndisDevice->BulkInEndpoint == 0) {
>
> + GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice);
>
> + }
>
> +
>
> + // Use StopBulkInCnt to stop BulkIn command
>
> + if (StopBulkInCnt || LAN_BULKIN_CMD_CONTROL) {
>
> + Status = UsbRndisDevice->UsbIoCdcData->UsbBulkTransfer (
>
> + UsbRndisDevice->UsbIoCdcData,
>
> +
> UsbRndisDevice->BulkInEndpoint,
>
> + RndisMsg,
>
> + TransferLength,
>
> + USB_RX_ETHERNET_BULK_TIMEOUT,
>
> + &UsbStatus
>
> + );
>
> +
>
> + if (!EFI_ERROR (Status)) {
>
> + StopBulkInCnt = MINIMUM_STOPBULKIN_CNT;
>
> + } else {
>
> + StopBulkInCnt--;
>
> + }
>
> + } else {
>
> + Status = EFI_TIMEOUT;
>
> + *TransferLength = 0;
>
> + BlockBulkInCnt++;
>
> + }
>
> +
>
> + if (BlockBulkInCnt > BULKIN_CMD_POLLING_CNT) {
>
> + StopBulkInCnt = MINIMUM_STOPBULKIN_CNT;
>
> + BlockBulkInCnt = 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 = 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"));
>
> + Length = sizeof (REMOTE_NDIS_QUERY_CMPLT);
>
> + 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", RndisMsg[Index]));
>
> + if (((Index % 4) == 3) && (Index != 0)) {
>
> + DEBUG ((DEBUG_INFO, "\n"));
>
> + }
>
> + }
>
> +
>
> + if (Index % 4) {
>
> + DEBUG ((DEBUG_INFO, "\n"));
>
> + }
>
> + }
>
> +}
>
> --
> 2.35.1.windows.2
> -The information contained in this message may be confidential and
> proprietary to American Megatrends (AMI). This communication is intended to
> be read only by the individual or entity to whom it is addressed or by
> their designee. If the reader of this message is not the intended
> recipient, you are on notice that any distribution of this message, in 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.
>
>
>
>
>
>
--
Pedro Falcato
[-- Attachment #2: Type: text/html, Size: 531866 bytes --]
next prev parent reply other threads:[~2022-08-19 15:54 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-08-19 9:17 [PATCH] UsbNetworkPkg: add USB network devices support richardho
2022-08-19 15:54 ` Pedro Falcato [this message]
2022-08-19 15:56 ` [edk2-devel] " Pedro Falcato
2022-08-29 10:57 ` RichardHo [何明忠]
-- strict thread matches above, loose matches on Subject: below --
2022-08-31 2:31 RichardHo [何明忠]
2022-08-31 12:15 ` [edk2-devel] " Rebecca Cran
2022-08-31 7:51 RichardHo [何明忠]
2022-08-31 13:28 ` [edk2-devel] " Rebecca Cran
2022-09-01 2:51 ` RichardHo [何明忠]
2022-09-01 9:05 ` Chang, Abner
2022-09-01 10:47 ` RichardHo [何明忠]
2022-09-01 12:38 ` Rebecca Cran
2022-09-02 5:24 RichardHo [何明忠]
2022-09-02 21:48 ` [edk2-devel] " Rebecca Cran
2022-09-09 7:06 ` Chang, Abner
2022-09-12 3:48 ` RichardHo [何明忠]
2022-09-12 7:55 ` Chang, Abner
2022-09-21 2:34 ` RichardHo [何明忠]
2022-09-22 12:52 ` Chang, Abner
2022-09-06 15:05 ` Rebecca Cran
2022-09-07 5:31 ` RichardHo [何明忠]
2022-09-07 17:46 ` Rebecca Cran
2022-11-26 18:56 ` Rebecca Cran
2022-11-28 5:24 ` RichardHo [何明忠]
2022-12-05 3:14 ` Rebecca Cran
2022-12-06 9:15 ` RichardHo [何明忠]
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='CAKbZUD0GH9KSY2AaPE=d=pFHynPNNQ2O=p6DjKPoZkoutb8V8Q@mail.gmail.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