Sorry, I do not remember reviewing this patch. Could you please remove the below information in the commit log message "Reviewed-by: Hao A Wu " Thanks in advance. Best Regards, Hao Wu > -----Original Message----- > From: RichardHo [ºÎÃ÷ÖÒ] > Sent: Wednesday, August 31, 2022 10:31 AM > To: devel@edk2.groups.io > Cc: Andrew Fish ; Leif Lindholm > ; Kinney, Michael D > ; Kubacki, Michael > ; Leif Lindholm ; Liu, > Zhiguang ; Gao, Liming > ; Wu, Hao A ; Ni, Ray > ; TonyLo [Á_½ðËÉ] > Subject: [PATCH] UsbNetworkPkg: add USB network devices support > > UsbNetworkPkg provides network functions for USB ACM, USB NCM, > and USB RNDIS network device. > > Signed-off-by: Richard Ho > Cc: Andrew Fish > Cc: Leif Lindholm > Cc: Michael D Kinney > Cc: Michael Kubacki > Cc: Leif Lindholm > Cc: Zhiguang Liu > Acked-by: Michael D Kinney > Acked-by: Liming Gao > Acked-by: Leif Lindholm > Reviewed-by: Hao A Wu > Reviewed-by: Ray Ni > Reviewed-by: Tony Lo > --- > UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc | 9 + > .../Config/UsbNetworkPkgComponentsDxe.inc.dsc | 20 + > .../Config/UsbNetworkPkgComponentsDxe.inc.fdf | 21 + > .../Config/UsbNetworkPkgDefines.inc.dsc | 23 + > .../Include/Protocol/UsbEthernetProtocol.h | 872 +++++++++ > UsbNetworkPkg/NetworkCommon/ComponentName.c | 264 +++ > UsbNetworkPkg/NetworkCommon/DriverBinding.c | 583 ++++++ > UsbNetworkPkg/NetworkCommon/DriverBinding.h | 263 +++ > UsbNetworkPkg/NetworkCommon/NetworkCommon.inf | 43 + > UsbNetworkPkg/NetworkCommon/PxeFunction.c | 1734 > +++++++++++++++++ > UsbNetworkPkg/ReadMe.md | 65 + > UsbNetworkPkg/ReleaseNotes.md | 11 + > UsbNetworkPkg/UsbCdcEcm/ComponentName.c | 170 ++ > UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.c | 504 +++++ > UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.h | 211 ++ > UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf | 41 + > UsbNetworkPkg/UsbCdcEcm/UsbEcmFunction.c | 861 ++++++++ > UsbNetworkPkg/UsbCdcNcm/ComponentName.c | 170 ++ > UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.c | 508 +++++ > UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.h | 245 +++ > UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf | 41 + > UsbNetworkPkg/UsbCdcNcm/UsbNcmFunction.c | 946 +++++++++ > UsbNetworkPkg/UsbNetworkPkg.dec | 32 + > UsbNetworkPkg/UsbRndis/ComponentName.c | 172 ++ > UsbNetworkPkg/UsbRndis/UsbRndis.c | 848 ++++++++ > UsbNetworkPkg/UsbRndis/UsbRndis.h | 569 ++++++ > UsbNetworkPkg/UsbRndis/UsbRndis.inf | 41 + > UsbNetworkPkg/UsbRndis/UsbRndisFunction.c | 1587 +++++++++++++++ > 28 files changed, 10854 insertions(+) > create mode 100644 UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc > create mode 100644 > UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc > create mode 100644 > UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf > create mode 100644 > UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc > create mode 100644 > UsbNetworkPkg/Include/Protocol/UsbEthernetProtocol.h > create mode 100644 > UsbNetworkPkg/NetworkCommon/ComponentName.c > create mode 100644 UsbNetworkPkg/NetworkCommon/DriverBinding.c > create mode 100644 UsbNetworkPkg/NetworkCommon/DriverBinding.h > create mode 100644 > UsbNetworkPkg/NetworkCommon/NetworkCommon.inf > create mode 100644 UsbNetworkPkg/NetworkCommon/PxeFunction.c > create mode 100644 UsbNetworkPkg/ReadMe.md > create mode 100644 UsbNetworkPkg/ReleaseNotes.md > create mode 100644 UsbNetworkPkg/UsbCdcEcm/ComponentName.c > create mode 100644 UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.c > create mode 100644 UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.h > create mode 100644 UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf > create mode 100644 UsbNetworkPkg/UsbCdcEcm/UsbEcmFunction.c > create mode 100644 UsbNetworkPkg/UsbCdcNcm/ComponentName.c > create mode 100644 UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.c > create mode 100644 UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.h > create mode 100644 UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf > create mode 100644 UsbNetworkPkg/UsbCdcNcm/UsbNcmFunction.c > create mode 100644 UsbNetworkPkg/UsbNetworkPkg.dec > create mode 100644 UsbNetworkPkg/UsbRndis/ComponentName.c > create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndis.c > create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndis.h > create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndis.inf > create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndisFunction.c > > diff --git a/UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc > b/UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc > new file mode 100644 > index 0000000000..db2cc7a3fb > --- /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) 2022, American Megatrends International LLC. All rights > reserved.
> +# SPDX-License-Identifier: BSD-2-Clause-Patent > +## > + > +[Components.X64] > +!include UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc > diff --git a/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc > b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc > new file mode 100644 > index 0000000000..1fb7337d38 > --- /dev/null > +++ b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc > @@ -0,0 +1,20 @@ > +## @file > +# List of Core Components. > +# > +# Copyright (c) 2022, American Megatrends International LLC. All rights > reserved.
> +# SPDX-License-Identifier: BSD-2-Clause-Patent > +## > + > + UsbNetworkPkg/NetworkCommon/NetworkCommon.inf > + > +!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport > + UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf > +!endif > + > +!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport > + UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf > +!endif > + > +!if gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport > + UsbNetworkPkg/UsbRndis/UsbRndis.inf > +!endif > diff --git a/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf > b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf > new file mode 100644 > index 0000000000..c094e28950 > --- /dev/null > +++ b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf > @@ -0,0 +1,21 @@ > +## @file > +# List of Core Components. > +# > +# Copyright (c) 2022, American Megatrends International LLC. All rights > reserved.
> +# SPDX-License-Identifier: BSD-2-Clause-Patent > +## > + > + INF UsbNetworkPkg/NetworkCommon/NetworkCommon.inf > + > +!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport > + INF UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf > +!endif > + > +!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport > + INF UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf > +!endif > + > +!if gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport > + INF UsbNetworkPkg/UsbRndis/UsbRndis.inf > +!endif > + > \ 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..8f5a56f93e > --- /dev/null > +++ b/UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc > @@ -0,0 +1,23 @@ > +## @file > +# Global switches enable/disable project features. > +# > +# Copyright (c) 2022, American Megatrends International LLC. All rights > reserved.
> +# SPDX-License-Identifier: BSD-2-Clause-Patent > +## > + > +[Defines] > +!if "IA32" in $(ARCH) && "X64" in $(ARCH) > + DEFINE PEI=IA32 > + DEFINE DXE=X64 > +!else > + DEFINE PEI=COMMON > + DEFINE DXE=COMMON > +!endif > + > +[Packages] > + UsbNetworkPkg/UsbNetworkPkg.dec > + > +[PcdsFeatureFlag] > + gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport|FALSE > + gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport|FALSE > + gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport|TRUE > diff --git a/UsbNetworkPkg/Include/Protocol/UsbEthernetProtocol.h > b/UsbNetworkPkg/Include/Protocol/UsbEthernetProtocol.h > new file mode 100644 > index 0000000000..1c1a450920 > --- /dev/null > +++ b/UsbNetworkPkg/Include/Protocol/UsbEthernetProtocol.h > @@ -0,0 +1,872 @@ > +/** @file > > + Header file contains code for USB Ethernet Protocol > > + definitions > > + > > + Copyright (c) 2022, American Megatrends International LLC. All rights > reserved.
> > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > + > > +#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..680d64f47f > --- /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) 2022, American Megatrends International LLC. All rights > reserved.
> > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > + > > +#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)NetworkCommonCompon > entNameGetDriverName, > > + > (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)NetworkCommonCo > mponentNameGetControllerName, > > + "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..f960d6ebad > --- /dev/null > +++ b/UsbNetworkPkg/NetworkCommon/DriverBinding.c > @@ -0,0 +1,583 @@ > +/** @file > > + This file contains code for USB network binding driver > > + > > + Copyright (c) 2022, American Megatrends International LLC. All rights > reserved.
> > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > + > > +#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..5f72cca198 > --- /dev/null > +++ b/UsbNetworkPkg/NetworkCommon/DriverBinding.h > @@ -0,0 +1,263 @@ > +/** @file > > + Header file for for USB network common driver > > + > > + Copyright (c) 2022, American Megatrends International LLC. All rights > reserved.
> > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > + > > +#ifndef _DRIVER_BINDING_H_ > > +#define _DRIVER_BINDING_H_ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +#define NETWORK_COMMON_DRIVER_VERSION 1 > > +#define NETWORK_COMMON_POLLING_INTERVAL 0x10 > > +#define RX_BUFFER_COUNT 32 > > +#define TX_BUFFER_COUNT 32 > > +#define MEMORY_REQUIRE 0 > > + > > +#define UNDI_DEV_SIGNATURE SIGNATURE_32('u','n','d','i') > > +#define UNDI_DEV_FROM_THIS(a) CR(a, NIC_DEVICE, NiiProtocol, > UNDI_DEV_SIGNATURE) > > +#define UNDI_DEV_FROM_NIC(a) CR(a, NIC_DEVICE, NicInfo, > UNDI_DEV_SIGNATURE) > > + > > +#pragma pack(1) > > +typedef struct { > > + UINT8 DestAddr[PXE_HWADDR_LEN_ETHER]; > > + UINT8 SrcAddr[PXE_HWADDR_LEN_ETHER]; > > + UINT16 Protocol; > > +} EthernetHeader; > > +#pragma pack() > > + > > +typedef struct { > > + UINTN Signature; > > + EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL NiiProtocol; > > + EFI_HANDLE DeviceHandle; > > + EFI_DEVICE_PATH_PROTOCOL *BaseDevPath; > > + EFI_DEVICE_PATH_PROTOCOL *DevPath; > > + NIC_DATA NicInfo; > > +} NIC_DEVICE; > > + > > +typedef VOID (*API_FUNC)( > > + PXE_CDB *, > > + NIC_DATA * > > + ); > > + > > +extern PXE_SW_UNDI *gPxe; > > +extern NIC_DEVICE *gLanDeviceList[MAX_LAN_INTERFACE]; > > +extern EFI_COMPONENT_NAME2_PROTOCOL > gNetworkCommonComponentName2; > > + > > +EFI_STATUS > > +EFIAPI > > +NetworkCommonSupported ( > > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > > + IN EFI_HANDLE ControllerHandle, > > + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath > > + ); > > + > > +EFI_STATUS > > +EFIAPI > > +NetworkCommonDriverStart ( > > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > > + IN EFI_HANDLE ControllerHandle, > > + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath > > + ); > > + > > +EFI_STATUS > > +EFIAPI > > +NetworkCommonDriverStop ( > > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > > + IN EFI_HANDLE ControllerHandle, > > + IN UINTN NumberOfChildren, > > + IN EFI_HANDLE *ChildHandleBuffer > > + ); > > + > > +VOID > > +PxeStructInit ( > > + OUT PXE_SW_UNDI *PxeSw > > + ); > > + > > +VOID > > +UpdateNicNum ( > > + IN NIC_DATA *Nic, > > + IN OUT PXE_SW_UNDI *PxeSw > > + ); > > + > > +VOID > > +UndiApiEntry ( > > + IN UINT64 Cdb > > + ); > > + > > +UINTN > > +MapIt ( > > + IN NIC_DATA *Nic, > > + IN UINT64 MemAddr, > > + IN UINT32 Size, > > + IN UINT32 Direction, > > + OUT UINT64 MappedAddr > > + ); > > + > > +VOID > > +UnMapIt ( > > + IN NIC_DATA *Nic, > > + IN UINT64 MemAddr, > > + IN UINT32 Size, > > + IN UINT32 Direction, > > + IN UINT64 MappedAddr > > + ); > > + > > +VOID > > +UndiGetState ( > > + IN PXE_CDB *Cdb, > > + IN NIC_DATA *Nic > > + ); > > + > > +VOID > > +UndiStart ( > > + IN PXE_CDB *Cdb, > > + IN NIC_DATA *Nic > > + ); > > + > > +VOID > > +UndiStop ( > > + IN PXE_CDB *Cdb, > > + IN NIC_DATA *Nic > > + ); > > + > > +VOID > > +UndiGetInitInfo ( > > + IN PXE_CDB *Cdb, > > + IN NIC_DATA *Nic > > + ); > > + > > +VOID > > +UndiGetConfigInfo ( > > + IN PXE_CDB *Cdb, > > + IN NIC_DATA *Nic > > + ); > > + > > +VOID > > +UndiInitialize ( > > + IN PXE_CDB *Cdb, > > + IN OUT NIC_DATA *Nic > > + ); > > + > > +VOID > > +UndiReset ( > > + IN PXE_CDB *Cdb, > > + IN NIC_DATA *Nic > > + ); > > + > > +VOID > > +UndiShutdown ( > > + IN PXE_CDB *Cdb, > > + IN OUT NIC_DATA *Nic > > + ); > > + > > +VOID > > +UndiInterruptEnable ( > > + IN PXE_CDB *Cdb, > > + IN NIC_DATA *Nic > > + ); > > + > > +VOID > > +UndiReceiveFilter ( > > + IN PXE_CDB *Cdb, > > + IN NIC_DATA *Nic > > + ); > > + > > +VOID > > +UndiStationAddress ( > > + IN PXE_CDB *Cdb, > > + IN NIC_DATA *Nic > > + ); > > + > > +VOID > > +UndiStatistics ( > > + IN PXE_CDB *Cdb, > > + IN NIC_DATA *Nic > > + ); > > + > > +VOID > > +UndiMcastIp2Mac ( > > + IN OUT PXE_CDB *Cdb, > > + IN NIC_DATA *Nic > > + ); > > + > > +VOID > > +UndiNvData ( > > + IN PXE_CDB *Cdb, > > + IN NIC_DATA *Nic > > + ); > > + > > +VOID > > +UndiGetStatus ( > > + IN PXE_CDB *Cdb, > > + IN NIC_DATA *Nic > > + ); > > + > > +VOID > > +UndiFillHeader ( > > + IN PXE_CDB *Cdb, > > + IN NIC_DATA *Nic > > + ); > > + > > +VOID > > +UndiTransmit ( > > + IN PXE_CDB *Cdb, > > + IN NIC_DATA *Nic > > + ); > > + > > +VOID > > +UndiReceive ( > > + IN PXE_CDB *Cdb, > > + IN NIC_DATA *Nic > > + ); > > + > > +UINT16 > > +Initialize ( > > + IN PXE_CDB *Cdb, > > + IN OUT NIC_DATA *Nic > > + ); > > + > > +UINT16 > > +Transmit ( > > + IN PXE_CDB *Cdb, > > + IN OUT NIC_DATA *Nic, > > + IN UINT64 CpbAddr, > > + IN UINT16 OpFlags > > + ); > > + > > +UINT16 > > +Receive ( > > + IN PXE_CDB *Cdb, > > + IN OUT NIC_DATA *Nic, > > + IN UINT64 CpbAddr, > > + IN OUT UINT64 DbAddr > > + ); > > + > > +UINT16 > > +Setfilter ( > > + IN NIC_DATA *Nic, > > + IN UINT16 SetFilter, > > + IN UINT64 CpbAddr, > > + IN UINT32 CpbSize > > + ); > > + > > +UINT16 > > +Statistics ( > > + IN NIC_DATA *Nic, > > + IN UINT64 DbAddr, > > + IN UINT16 DbSize > > + ); > > + > > +#endif > > diff --git a/UsbNetworkPkg/NetworkCommon/NetworkCommon.inf > b/UsbNetworkPkg/NetworkCommon/NetworkCommon.inf > new file mode 100644 > index 0000000000..7fa4bb3a44 > --- /dev/null > +++ b/UsbNetworkPkg/NetworkCommon/NetworkCommon.inf > @@ -0,0 +1,43 @@ > +## @file > +# This is Usb Network Common driver for DXE phase. > +# > +# Copyright (c) 2022, American Megatrends International LLC. All rights > reserved.
> +# SPDX-License-Identifier: BSD-2-Clause-Patent > +## > + > +[Defines] > + INF_VERSION = 0x00010005 > + BASE_NAME = NetworkCommon > + FILE_GUID = ca6eb4f4-f1d6-4375-97d6-18856871e1bf > + MODULE_TYPE = DXE_DRIVER > + VERSION_STRING = 1.0 > + ENTRY_POINT = NetworkCommonEntry > + > +[Sources] > + DriverBinding.c > + DriverBinding.h > + ComponentName.c > + PxeFunction.c > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + UsbNetworkPkg/UsbNetworkPkg.dec > + > +[LibraryClasses] > + UefiDriverEntryPoint > + UefiBootServicesTableLib > + UefiLib > + DebugLib > + UefiUsbLib > + MemoryAllocationLib > + BaseMemoryLib > + > +[Protocols] > + gEfiNetworkInterfaceIdentifierProtocolGuid_31 > + gEfiUsbIoProtocolGuid > + gEfiDevicePathProtocolGuid > + gEfiDriverBindingProtocolGuid > + > +[Depex] > + TRUE > diff --git a/UsbNetworkPkg/NetworkCommon/PxeFunction.c > b/UsbNetworkPkg/NetworkCommon/PxeFunction.c > new file mode 100644 > index 0000000000..f6505f7018 > --- /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) 2022, American Megatrends International LLC. All rights > reserved.
> > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > + > > +#include "DriverBinding.h" > > + > > +// API table, defined in UEFI specification > > +API_FUNC gUndiApiTable[] = { > > + UndiGetState, > > + UndiStart, > > + UndiStop, > > + UndiGetInitInfo, > > + UndiGetConfigInfo, > > + UndiInitialize, > > + UndiReset, > > + UndiShutdown, > > + UndiInterruptEnable, > > + UndiReceiveFilter, > > + UndiStationAddress, > > + UndiStatistics, > > + UndiMcastIp2Mac, > > + UndiNvData, > > + UndiGetStatus, > > + UndiFillHeader, > > + UndiTransmit, > > + UndiReceive > > +}; > > + > > +/** > > + 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:
> +- 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 > > + > > +# Release History > > +- [1.00](#100) > > + > > +## 1.00 > > + > > +**Release Date:** Mar 10, 2022 > > + > > +**New Features** > > +- UsbNetworkPkg first release. > > diff --git a/UsbNetworkPkg/UsbCdcEcm/ComponentName.c > b/UsbNetworkPkg/UsbCdcEcm/ComponentName.c > new file mode 100644 > index 0000000000..684a08730a > --- /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) 2022, American Megatrends International LLC. All rights > reserved.
> > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > +#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)UsbEcmComponentName > GetDriverName, > > + > (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)UsbEcmComponent > NameGetControllerName, > > + "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..7e241b440d > --- /dev/null > +++ b/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.c > @@ -0,0 +1,504 @@ > +/** @file > > + This file contains code for USB Ethernet Control Model > > + Driver > > + > > + Copyright (c) 2022, American Megatrends International LLC. All rights > reserved.
> > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > +#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..46158aecc5 > --- /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) 2022, American Megatrends International LLC. All rights > reserved.
> > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > + > > +#ifndef _USB_CDC_ECM_H_ > > +#define _USB_CDC_ECM_H_ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +typedef struct { > > + UINTN Signature; > > + USB_ETHERNET_PROTOCOL UsbEth; > > + EFI_HANDLE UsbCdcDataHandle; > > + EFI_USB_IO_PROTOCOL *UsbIo; > > + EFI_USB_CONFIG_DESCRIPTOR *Config; > > + UINT8 NumOfInterface; > > + UINT8 BulkInEndpoint; > > + UINT8 BulkOutEndpoint; > > + UINT8 InterruptEndpoint; > > + EFI_MAC_ADDRESS MacAddress; > > +} USB_ETHERNET_DRIVER; > > + > > +#define USB_ECM_DRIVER_VERSION 1 > > +#define USB_ETHERNET_BULK_TIMEOUT 1 > > +#define USB_ETHERNET_TRANSFER_TIMEOUT 200 > > + > > +#define USB_ETHERNET_SIGNATURE SIGNATURE_32('u', 'e', 't', 'h') > > +#define USB_ETHERNET_DEV_FROM_THIS(a) CR (a, > USB_ETHERNET_DRIVER, UsbEth, USB_ETHERNET_SIGNATURE) > > + > > +typedef struct { > > + UINT16 Src; > > + UINT16 Dst; > > +} BIT_MAP; > > + > > +extern EFI_COMPONENT_NAME2_PROTOCOL gUsbEcmComponentName2; > > + > > +EFI_STATUS > > +EFIAPI > > +UsbEcmDriverSupported ( > > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > > + IN EFI_HANDLE ControllerHandle, > > + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath > > + ); > > + > > +EFI_STATUS > > +EFIAPI > > +UsbEcmDriverStart ( > > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > > + IN EFI_HANDLE ControllerHandle, > > + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath > > + ); > > + > > +EFI_STATUS > > +EFIAPI > > +UsbEcmDriverStop ( > > + IN EFI_DRIVER_BINDING_PROTOCOL *This, > > + IN EFI_HANDLE ControllerHandle, > > + IN UINTN NumberOfChildren, > > + IN EFI_HANDLE *ChildHandleBuffer > > + ); > > + > > +EFI_STATUS > > +LoadAllDescriptor ( > > + IN EFI_USB_IO_PROTOCOL *UsbIo, > > + OUT EFI_USB_CONFIG_DESCRIPTOR **ConfigDesc > > + ); > > + > > +BOOLEAN > > +NextDescriptor ( > > + IN EFI_USB_CONFIG_DESCRIPTOR *Desc, > > + IN OUT UINTN *Offset > > + ); > > + > > +EFI_STATUS > > +GetFunctionalDescriptor ( > > + IN EFI_USB_CONFIG_DESCRIPTOR *Config, > > + IN UINT8 FunDescriptorType, > > + OUT VOID *DataBuffer > > + ); > > + > > +VOID > > +GetEndpoint ( > > + IN EFI_USB_IO_PROTOCOL *UsbIo, > > + IN OUT USB_ETHERNET_DRIVER *UsbEthDriver > > + ); > > + > > +EFI_STATUS > > +EFIAPI > > +UsbEthReceive ( > > + IN PXE_CDB *Cdb, > > + IN USB_ETHERNET_PROTOCOL *This, > > + IN OUT VOID *Packet, > > + IN OUT UINTN *PacketLength > > + ); > > + > > +EFI_STATUS > > +EFIAPI > > +UsbEthTransmit ( > > + IN PXE_CDB *Cdb, > > + IN USB_ETHERNET_PROTOCOL *This, > > + IN VOID *Packet, > > + IN OUT UINTN *PacketLength > > + ); > > + > > +EFI_STATUS > > +EFIAPI > > +UsbEthInterrupt ( > > + IN USB_ETHERNET_PROTOCOL *This, > > + IN BOOLEAN IsNewTransfer, > > + IN UINTN PollingInterval, > > + IN EFI_USB_DEVICE_REQUEST *Request > > + ); > > + > > +EFI_STATUS > > +EFIAPI > > +InterruptCallback ( > > + IN VOID *Data, > > + IN UINTN DataLength, > > + IN VOID *Context, > > + IN UINT32 Status > > + ); > > + > > +EFI_STATUS > > +EFIAPI > > +GetUsbEthMacAddress ( > > + IN USB_ETHERNET_PROTOCOL *This, > > + OUT EFI_MAC_ADDRESS *MacAddress > > + ); > > + > > +EFI_STATUS > > +EFIAPI > > +UsbEthBulkSize ( > > + IN USB_ETHERNET_PROTOCOL *This, > > + OUT UINTN *BulkSize > > + ); > > + > > +EFI_STATUS > > +EFIAPI > > +GetUsbHeaderFunDescriptor ( > > + IN USB_ETHERNET_PROTOCOL *This, > > + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor > > + ); > > + > > +EFI_STATUS > > +EFIAPI > > +GetUsbUnionFunDescriptor ( > > + IN USB_ETHERNET_PROTOCOL *This, > > + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor > > + ); > > + > > +EFI_STATUS > > +EFIAPI > > +GetUsbEthFunDescriptor ( > > + IN USB_ETHERNET_PROTOCOL *This, > > + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor > > + ); > > + > > +EFI_STATUS > > +EFIAPI > > +SetUsbEthMcastFilter ( > > + IN USB_ETHERNET_PROTOCOL *This, > > + IN UINT16 Value, > > + IN VOID *McastAddr > > + ); > > + > > +EFI_STATUS > > +EFIAPI > > +SetUsbEthPowerFilter ( > > + IN USB_ETHERNET_PROTOCOL *This, > > + IN UINT16 Value, > > + IN UINT16 Length, > > + IN VOID *PatternFilter > > + ); > > + > > +EFI_STATUS > > +EFIAPI > > +GetUsbEthPowerFilter ( > > + IN USB_ETHERNET_PROTOCOL *This, > > + IN UINT16 Value, > > + OUT BOOLEAN *PatternActive > > + ); > > + > > +EFI_STATUS > > +EFIAPI > > +SetUsbEthPacketFilter ( > > + IN USB_ETHERNET_PROTOCOL *This, > > + IN UINT16 Value > > + ); > > + > > +EFI_STATUS > > +EFIAPI > > +GetUsbEthStatistic ( > > + IN USB_ETHERNET_PROTOCOL *This, > > + IN UINT16 FeatureSelector, > > + OUT VOID *Statistic > > + ); > > + > > +#endif > > diff --git a/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf > b/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf > new file mode 100644 > index 0000000000..3b7d511940 > --- /dev/null > +++ b/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf > @@ -0,0 +1,41 @@ > +## @file > +# This is Usb Cdc Ecm driver for DXE phase. > +# > +# Copyright (c) 2022, American Megatrends International LLC. All rights > reserved.
> +# SPDX-License-Identifier: BSD-2-Clause-Patent > +## > + > +[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..7d2a58ea57 > --- /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) 2022, American Megatrends International LLC. All rights > reserved.
> > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > + > > +#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..3db1dc6933 > --- /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) 2022, American Megatrends International LLC. All rights > reserved.
> > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > +#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)UsbNcmComponentName > GetDriverName, > > + > (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)UsbNcmComponent > NameGetControllerName, > > + "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..0f1786da83 > --- /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) 2022, American Megatrends International LLC. All rights > reserved.
> > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > + > > +#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..ea7f8af388 > --- /dev/null > +++ b/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.h > @@ -0,0 +1,245 @@ > +/** @file > > + Header file for USB Network Control Model driver > > + > > + Copyright (c) 2022, American Megatrends International LLC. All rights > reserved.
> > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > + > > +#ifndef _USB_CDC_NCM_H_ > > +#define _USB_CDC_NCM_H_ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +typedef struct { > > + UINTN Signature; > > + USB_ETHERNET_PROTOCOL UsbEth; > > + EFI_HANDLE UsbCdcDataHandle; > > + EFI_USB_IO_PROTOCOL *UsbIo; > > + EFI_USB_CONFIG_DESCRIPTOR *Config; > > + UINT8 NumOfInterface; > > + UINT8 BulkInEndpoint; > > + UINT8 BulkOutEndpoint; > > + UINT8 InterruptEndpoint; > > + EFI_MAC_ADDRESS MacAddress; > > + UINT16 BulkOutSequence; > > + UINT8 *BulkBuffer; > > + UINT8 TotalDatagram; > > + UINT8 NowDatagram; > > +} USB_ETHERNET_DRIVER; > > + > > +#define USB_NCM_DRIVER_VERSION 1 > > +#define USB_ETHERNET_BULK_TIMEOUT 1 > > +#define USB_ETHERNET_TRANSFER_TIMEOUT 200 > > +#define USB_NCM_MAX_NTB_SIZE 0xFFFF > > +#define USB_ETH_FRAME_SIZE 0x5F2 // frome network stack 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..a81bbd2e9d > --- /dev/null > +++ b/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf > @@ -0,0 +1,41 @@ > +## @file > +# This is Usb Cdc Ncm driver for DXE phase. > +# > +# Copyright (c) 2022, American Megatrends International LLC. All rights > reserved.
> +# SPDX-License-Identifier: BSD-2-Clause-Patent > +## > + > +[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..429fb5f834 > --- /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) 2022, American Megatrends International LLC. All rights > reserved.
> > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > + > > +#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..f39a3523a6 > --- /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) 2022, American Megatrends International LLC. All rights > reserved.
> +# SPDX-License-Identifier: BSD-2-Clause-Patent > +## > + > +[Defines] > + DEC_SPECIFICATION = 0x00010005 > + PACKAGE_NAME = UsbNetworkPkg > + PACKAGE_GUID = abfab91e-37ea-4cb4-80a6-563dbb0bcec6 > + PACKAGE_VERSION = 0.1 > + > +[Includes] > + Include > + > +[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|0x > 00000001 > + > + ## Set the PCD 'UsbCdcNcmSupport' to 'TRUE' if 'Usb Cdc Ncm device' > need to be enabled. > + > gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport|FALSE|BOOLEAN|0x > 00000002 > + > + ## Set the PCD 'UsbRndisSupport' to 'TRUE' if 'Usb Rndis device' need to be > enabled. > + > gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport|TRUE|BOOLEAN|0x000 > 00003 > + > diff --git a/UsbNetworkPkg/UsbRndis/ComponentName.c > b/UsbNetworkPkg/UsbRndis/ComponentName.c > new file mode 100644 > index 0000000000..437d776b17 > --- /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) 2022, American Megatrends International LLC. All rights > reserved.
> > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > + > > +#include "UsbRndis.h" > > + > > +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE > gUsbRndisDriverNameTable[] = { > > + { > > + "eng;en", > > + L"USB RNDIS Driver" > > + }, > > + { > > + NULL, > > + NULL > > + } > > +}; > > + > > +EFI_STATUS > > +EFIAPI > > +UsbRndisComponentNameGetDriverName ( > > + IN EFI_COMPONENT_NAME_PROTOCOL *This, > > + IN CHAR8 *Language, > > + OUT CHAR16 **DriverName > > + ); > > + > > +EFI_STATUS > > +EFIAPI > > +UsbRndisComponentNameGetControllerName ( > > + IN EFI_COMPONENT_NAME_PROTOCOL *This, > > + IN EFI_HANDLE Controller, > > + IN EFI_HANDLE ChildHandle OPTIONAL, > > + IN CHAR8 *Language, > > + OUT CHAR16 **ControllerName > > + ); > > + > > +GLOBAL_REMOVE_IF_UNREFERENCED > EFI_COMPONENT_NAME_PROTOCOL gUsbRndisComponentName = { > > + UsbRndisComponentNameGetDriverName, > > + UsbRndisComponentNameGetControllerName, > > + "eng" > > +}; > > + > > +GLOBAL_REMOVE_IF_UNREFERENCED > EFI_COMPONENT_NAME2_PROTOCOL gUsbRndisComponentName2 = { > > + > (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)UsbRndisComponentNam > eGetDriverName, > > + > (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)UsbRndisComponent > NameGetControllerName, > > + "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..26728d7333 > --- /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) 2022, American Megatrends International LLC. All rights > reserved.
> > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > + > > +#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..d963a2744f > --- /dev/null > +++ b/UsbNetworkPkg/UsbRndis/UsbRndis.h > @@ -0,0 +1,569 @@ > +/** @file > > + Header file for for USB Rndis driver > > + > > + Copyright (c) 2022, American Megatrends International LLC. All rights > reserved.
> > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > + > > +#ifndef _USB_RNDIS_H_ > > +#define _USB_RNDIS_H_ > > + > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > +#include > > + > > +typedef struct _REMOTE_NDIS_MSG_HEADER > REMOTE_NDIS_MSG_HEADER; > > + > > +typedef struct { > > + UINT32 Signature; > > + USB_ETHERNET_PROTOCOL UsbEth; > > + EFI_HANDLE UsbCdcDataHandle; > > + EFI_HANDLE UsbRndisHandle; > > + EFI_USB_IO_PROTOCOL *UsbIo; > > + EFI_USB_IO_PROTOCOL *UsbIoCdcData; > > + EFI_USB_CONFIG_DESCRIPTOR *Config; > > + UINT8 NumOfInterface; > > + UINT8 BulkInEndpoint; > > + UINT8 BulkOutEndpoint; > > + UINT8 InterrupEndpoint; > > + EFI_MAC_ADDRESS MacAddress; > > + UINT32 RequestId; > > + UINT32 Medium; > > + UINT32 MaxPacketsPerTransfer; > > + UINT32 MaxTransferSize; > > + UINT32 PacketAlignmentFactor; > > + LIST_ENTRY ReceivePacketList; > > +} USB_RNDIS_DEVICE; > > + > > +#define USB_RNDIS_DRIVER_VERSION 1 > > +#define USB_TX_ETHERNET_BULK_TIMEOUT 3000 > > +#define USB_RX_ETHERNET_BULK_TIMEOUT 3 > > +#define USB_ETHERNET_TRANSFER_TIMEOUT 200 > > + > > +#define LAN_BULKIN_CMD_CONTROL 1 > > +#define MAXIMUM_STOPBULKIN_CNT 300 // Indicating maximum > counts for waiting bulk in command > > +#define MINIMUM_STOPBULKIN_CNT 3 // Indicating minimum > counts for waiting bulk in command > > +#define BULKIN_CMD_POLLING_CNT 300 // Indicating the 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..71c724a916 > --- /dev/null > +++ b/UsbNetworkPkg/UsbRndis/UsbRndis.inf > @@ -0,0 +1,41 @@ > +## @file > +# This is Usb Rndis driver for DXE phase. > +# > +# Copyright (c) 2022, American Megatrends International LLC. All rights > reserved.
> +# SPDX-License-Identifier: BSD-2-Clause-Patent > +## > + > +[Defines] > + INF_VERSION = 0x00010005 > + BASE_NAME = UsbRndis > + FILE_GUID = 11E32C34-60B5-4991-8DEA-63D3E8C876DE > + MODULE_TYPE = DXE_DRIVER > + VERSION_STRING = 1.0 > + ENTRY_POINT = UsbRndisEntry > + > +[Sources] > + UsbRndis.c > + UsbRndis.h > + UsbRndisFunction.c > + ComponentName.c > + > +[Packages] > + MdePkg/MdePkg.dec > + UsbNetworkPkg/UsbNetworkPkg.dec > + > +[LibraryClasses] > + UefiDriverEntryPoint > + UefiBootServicesTableLib > + UefiLib > + DebugLib > + UefiUsbLib > + MemoryAllocationLib > + BaseMemoryLib > + > +[Protocols] > + gEfiUsbIoProtocolGuid > + gEfiDevicePathProtocolGuid > + gEfiDriverBindingProtocolGuid > + > +[Depex] > + TRUE > diff --git a/UsbNetworkPkg/UsbRndis/UsbRndisFunction.c > b/UsbNetworkPkg/UsbRndis/UsbRndisFunction.c > new file mode 100644 > index 0000000000..a0e4c9ee5e > --- /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) 2022, American Megatrends International LLC. All rights > reserved.
> > + SPDX-License-Identifier: BSD-2-Clause-Patent > > +**/ > > + > > +#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.