Also, I forgot, but you should CC the EDK2 stewards (they're the ones that are going to add the Reviewed-by:). On Fri, Aug 19, 2022 at 4:54 PM Pedro Falcato wrote: > Hi Richard, > > What license is this code under? "Subject to AMI licensing agreement." > does not sound like a valid OSS license. > > Thanks, > Pedro > > On Fri, Aug 19, 2022 at 10:32 AM RichardHo [何明忠] via groups.io ami.com@groups.io> wrote: > >> UsbNetworkPkg provides network functions for USB ACM, USB NCM, >> and USB RNDIS network device. >> >> Signed-off-by: Richard Ho >> Reviewed-by: Tony Lo >> --- >> UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc | 9 + >> .../Config/UsbNetworkPkgComponentsDxe.inc.dsc | 20 + >> .../Config/UsbNetworkPkgComponentsDxe.inc.fdf | 21 + >> .../Config/UsbNetworkPkgDefines.inc.dsc | 23 + >> .../Include/Protocol/UsbEthernetProtocol.h | 872 +++++++++ >> UsbNetworkPkg/NetworkCommon/ComponentName.c | 264 +++ >> UsbNetworkPkg/NetworkCommon/DriverBinding.c | 583 ++++++ >> UsbNetworkPkg/NetworkCommon/DriverBinding.h | 263 +++ >> UsbNetworkPkg/NetworkCommon/NetworkCommon.inf | 43 + >> UsbNetworkPkg/NetworkCommon/PxeFunction.c | 1734 +++++++++++++++++ >> UsbNetworkPkg/ReadMe.md | 65 + >> UsbNetworkPkg/ReleaseNotes.md | 11 + >> UsbNetworkPkg/UsbCdcEcm/ComponentName.c | 170 ++ >> UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.c | 504 +++++ >> UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.h | 211 ++ >> UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf | 41 + >> UsbNetworkPkg/UsbCdcEcm/UsbEcmFunction.c | 861 ++++++++ >> UsbNetworkPkg/UsbCdcNcm/ComponentName.c | 170 ++ >> UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.c | 508 +++++ >> UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.h | 245 +++ >> UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf | 41 + >> UsbNetworkPkg/UsbCdcNcm/UsbNcmFunction.c | 946 +++++++++ >> UsbNetworkPkg/UsbNetworkPkg.dec | 32 + >> UsbNetworkPkg/UsbRndis/ComponentName.c | 172 ++ >> UsbNetworkPkg/UsbRndis/UsbRndis.c | 848 ++++++++ >> UsbNetworkPkg/UsbRndis/UsbRndis.h | 569 ++++++ >> UsbNetworkPkg/UsbRndis/UsbRndis.inf | 41 + >> UsbNetworkPkg/UsbRndis/UsbRndisFunction.c | 1587 +++++++++++++++ >> 28 files changed, 10854 insertions(+) >> create mode 100644 UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc >> create mode 100644 >> UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc >> create mode 100644 >> UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf >> create mode 100644 UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc >> create mode 100644 UsbNetworkPkg/Include/Protocol/UsbEthernetProtocol.h >> create mode 100644 UsbNetworkPkg/NetworkCommon/ComponentName.c >> create mode 100644 UsbNetworkPkg/NetworkCommon/DriverBinding.c >> create mode 100644 UsbNetworkPkg/NetworkCommon/DriverBinding.h >> create mode 100644 UsbNetworkPkg/NetworkCommon/NetworkCommon.inf >> create mode 100644 UsbNetworkPkg/NetworkCommon/PxeFunction.c >> create mode 100644 UsbNetworkPkg/ReadMe.md >> create mode 100644 UsbNetworkPkg/ReleaseNotes.md >> create mode 100644 UsbNetworkPkg/UsbCdcEcm/ComponentName.c >> create mode 100644 UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.c >> create mode 100644 UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.h >> create mode 100644 UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf >> create mode 100644 UsbNetworkPkg/UsbCdcEcm/UsbEcmFunction.c >> create mode 100644 UsbNetworkPkg/UsbCdcNcm/ComponentName.c >> create mode 100644 UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.c >> create mode 100644 UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.h >> create mode 100644 UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf >> create mode 100644 UsbNetworkPkg/UsbCdcNcm/UsbNcmFunction.c >> create mode 100644 UsbNetworkPkg/UsbNetworkPkg.dec >> create mode 100644 UsbNetworkPkg/UsbRndis/ComponentName.c >> create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndis.c >> create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndis.h >> create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndis.inf >> create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndisFunction.c >> >> diff --git a/UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc >> b/UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc >> new file mode 100644 >> index 0000000000..504680bc4b >> --- /dev/null >> +++ b/UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc >> @@ -0,0 +1,9 @@ >> +## @file >> +# Global DSC definitions to be included into project DSC file. >> +# >> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> +# Subject to AMI licensing agreement. >> +## >> + >> +[Components.X64] >> +!include UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc >> diff --git a/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc >> b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc >> new file mode 100644 >> index 0000000000..ae2727b68c >> --- /dev/null >> +++ b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc >> @@ -0,0 +1,20 @@ >> +## @file >> +# List of Core Components. >> +# >> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> +# Subject to AMI licensing agreement. >> +## >> + >> + UsbNetworkPkg/NetworkCommon/NetworkCommon.inf >> + >> +!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport >> + UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf >> +!endif >> + >> +!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport >> + UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf >> +!endif >> + >> +!if gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport >> + UsbNetworkPkg/UsbRndis/UsbRndis.inf >> +!endif >> diff --git a/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf >> b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf >> new file mode 100644 >> index 0000000000..6a611e359c >> --- /dev/null >> +++ b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf >> @@ -0,0 +1,21 @@ >> +## @file >> +# List of Core Components. >> +# >> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> +# Subject to AMI licensing agreement. >> +## >> + >> + INF UsbNetworkPkg/NetworkCommon/NetworkCommon.inf >> + >> +!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport >> + INF UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf >> +!endif >> + >> +!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport >> + INF UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf >> +!endif >> + >> +!if gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport >> + INF UsbNetworkPkg/UsbRndis/UsbRndis.inf >> +!endif >> + >> \ No newline at end of file >> diff --git a/UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc >> b/UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc >> new file mode 100644 >> index 0000000000..ef663bf253 >> --- /dev/null >> +++ b/UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc >> @@ -0,0 +1,23 @@ >> +## @file >> +# Global switches enable/disable project features. >> +# >> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> +# Subject to AMI licensing agreement. >> +## >> + >> +[Defines] >> +!if "IA32" in $(ARCH) && "X64" in $(ARCH) >> + DEFINE PEI=IA32 >> + DEFINE DXE=X64 >> +!else >> + DEFINE PEI=COMMON >> + DEFINE DXE=COMMON >> +!endif >> + >> +[Packages] >> + UsbNetworkPkg/UsbNetworkPkg.dec >> + >> +[PcdsFeatureFlag] >> + gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport|FALSE >> + gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport|FALSE >> + gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport|TRUE >> diff --git a/UsbNetworkPkg/Include/Protocol/UsbEthernetProtocol.h >> b/UsbNetworkPkg/Include/Protocol/UsbEthernetProtocol.h >> new file mode 100644 >> index 0000000000..d60e83f723 >> --- /dev/null >> +++ b/UsbNetworkPkg/Include/Protocol/UsbEthernetProtocol.h >> @@ -0,0 +1,872 @@ >> +/** @file >> >> + Header file contains code for USB Ethernet Protocol >> >> + definitions >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#ifndef _USB_ETHERNET_PROTOCOL_H >> >> +#define _USB_ETHERNET_PROTOCOL_H >> >> + >> >> +#define USB_ETHERNET_PROTOCOL_GUID \ >> >> + {0x8d8969cc, 0xfeb0, 0x4303, {0xb2, 0x1a, 0x1f, 0x11, 0x6f, 0x38, >> 0x56, 0x43}} >> >> + >> >> +typedef struct _USB_ETHERNET_PROTOCOL USB_ETHERNET_PROTOCOL; >> >> + >> >> +#define USB_CDC_CLASS 0x02 >> >> +#define USB_CDC_ACM_SUBCLASS 0x02 >> >> +#define USB_CDC_ECM_SUBCLASS 0x06 >> >> +#define USB_CDC_NCM_SUBCLASS 0x0D >> >> +#define USB_CDC_DATA_CLASS 0x0A >> >> +#define USB_CDC_DATA_SUBCLASS 0x00 >> >> +#define USB_NO_CLASS_PROTOCOL 0x00 >> >> +#define USB_NCM_NTB_PROTOCOL 0x01 >> >> +#define USB_VENDOR_PROTOCOL 0xFF >> >> + >> >> +// Type Values for the DescriptorType Field >> >> +#define CS_INTERFACE 0x24 >> >> +#define CS_ENDPOINT 0x25 >> >> + >> >> +// Descriptor SubType in Functional Descriptors >> >> +#define HEADER_FUN_DESCRIPTOR 0x00 >> >> +#define UNION_FUN_DESCRIPTOR 0x06 >> >> +#define ETHERNET_FUN_DESCRIPTOR 0x0F >> >> + >> >> +#define MAX_LAN_INTERFACE 0x10 >> >> + >> >> +// Table 20: Class-Specific Notification Codes >> >> +#define USB_CDC_NETWORK_CONNECTION 0x00 >> >> + >> >> +// 6.3.1 NetworkConnection >> >> +#define NETWORK_CONNECTED 0x01 >> >> +#define NETWORK_DISCONNECT 0x00 >> >> + >> >> +// USB Header functional Descriptor >> >> +typedef struct { >> >> + UINT8 FunctionLength; >> >> + UINT8 DescriptorType; >> >> + UINT8 DescriptorSubtype; >> >> + UINT16 BcdCdc; >> >> +} USB_HEADER_FUN_DESCRIPTOR; >> >> + >> >> +// USB Union Functional Descriptor >> >> +typedef struct { >> >> + UINT8 FunctionLength; >> >> + UINT8 DescriptorType; >> >> + UINT8 DescriptorSubtype; >> >> + UINT8 MasterInterface; >> >> + UINT8 SlaveInterface; >> >> +} USB_UNION_FUN_DESCRIPTOR; >> >> + >> >> +// USB Ethernet Functional Descriptor >> >> +typedef struct { >> >> + UINT8 FunctionLength; >> >> + UINT8 DescriptorType; >> >> + UINT8 DescriptorSubtype; >> >> + UINT8 MacAddress; >> >> + UINT32 EthernetStatistics; >> >> + UINT16 MaxSegmentSize; >> >> + UINT16 NumberMcFilters; >> >> + UINT8 NumberPowerFilters; >> >> +} USB_ETHERNET_FUN_DESCRIPTOR; >> >> + >> >> +typedef struct { >> >> + UINT32 UsBitRate; >> >> + UINT32 DsBitRate; >> >> +} USB_CONNECT_SPEED_CHANGE; >> >> + >> >> +// Request Type Codes for USB Ethernet >> >> +#define USB_ETHERNET_GET_REQ_TYPE 0xA1 >> >> +#define USB_ETHRTNET_SET_REQ_TYPE 0x21 >> >> + >> >> +// Class-Specific Request Codes for Ethernet subclass >> >> +// USB ECM 1.2 specification, Section 6.2 >> >> +#define SET_ETH_MULTICAST_FILTERS_REQ 0x40 >> >> +#define SET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ 0x41 >> >> +#define GET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ 0x42 >> >> +#define SET_ETH_PACKET_FILTER_REQ 0x43 >> >> +#define GET_ETH_STATISTIC_REQ 0x44 >> >> + >> >> +// USB ECM command request length >> >> +#define USB_ETH_POWER_FILTER_LENGTH 2 // Section 6.2.3 >> >> +#define USB_ETH_PACKET_FILTER_LENGTH 0 // Section 6.2.4 >> >> +#define USB_ETH_STATISTIC 4 // Section 6.2.5 >> >> + >> >> +// USB Ethernet Packet Filter Bitmap >> >> +// USB ECM 1.2 specification, Section 6.2.4 >> >> +#define USB_ETH_PACKET_TYPE_PROMISCUOUS BIT0 >> >> +#define USB_ETH_PACKET_TYPE_ALL_MULTICAST BIT1 >> >> +#define USB_ETH_PACKET_TYPE_DIRECTED BIT2 >> >> +#define USB_ETH_PACKET_TYPE_BROADCAST BIT3 >> >> +#define USB_ETH_PACKET_TYPE_MULTICAST BIT4 >> >> + >> >> +// USB Ethernet Statistics Feature Selector Codes >> >> +// USB ECM 1.2 specification, Section 6.2.5 >> >> +#define USB_ETH_XMIT_OK 0x01 >> >> +#define USB_ETH_RCV_OK 0x02 >> >> +#define USB_ETH_XMIT_ERROR 0x03 >> >> +#define USB_ETH_RCV_ERROR 0x04 >> >> +#define USB_ETH_RCV_NO_BUFFER 0x05 >> >> +#define USB_ETH_DIRECTED_BYTES_XMIT 0x06 >> >> +#define USB_ETH_DIRECTED_FRAMES_XMIT 0x07 >> >> +#define USB_ETH_MULTICAST_BYTES_XMIT 0x08 >> >> +#define USB_ETH_MULTICAST_FRAMES_XMIT 0x09 >> >> +#define USB_ETH_BROADCAST_BYTES_XMIT 0x0A >> >> +#define USB_ETH_BROADCAST_FRAMES_XMIT 0x0B >> >> +#define USB_ETH_DIRECTED_BYTES_RCV 0x0C >> >> +#define USB_ETH_DIRECTED_FRAMES_RCV 0x0D >> >> +#define USB_ETH_MULTICAST_BYTES_RCV 0x0E >> >> +#define USB_ETH_MULTICAST_FRAMES_RCV 0x0F >> >> +#define USB_ETH_BROADCAST_BYTES_RCV 0x10 >> >> +#define USB_ETH_BROADCAST_FRAMES_RCV 0x11 >> >> +#define USB_ETH_RCV_CRC_ERROR 0x12 >> >> +#define USB_ETH_TRANSMIT_QUEUE_LENGTH 0x13 >> >> +#define USB_ETH_RCV_ERROR_ALIGNMENT 0x14 >> >> +#define USB_ETH_XMIT_ONE_COLLISION 0x15 >> >> +#define USB_ETH_XMIT_MORE_COLLISIONS 0x16 >> >> +#define USB_ETH_XMIT_DEFERRED 0x17 >> >> +#define USB_ETH_XMIT_MAX_COLLISIONS 0x18 >> >> +#define USB_ETH_RCV_OVERRUN 0x19 >> >> +#define USB_ETH_XMIT_UNDERRUN 0x1A >> >> +#define USB_ETH_XMIT_HEARTBEAT_FAILURE 0x1B >> >> +#define USB_ETH_XMIT_TIMES_CRS_LOST 0x1C >> >> +#define USB_ETH_XMIT_LATE_COLLISIONS 0x1D >> >> + >> >> +// NIC Information >> >> +typedef struct { >> >> + UINT32 Signature; >> >> + USB_ETHERNET_PROTOCOL *UsbEth; >> >> + UINT16 InterrupOpFlag; >> >> + UINT64 MappedAddr; >> >> + PXE_MAC_ADDR McastList[MAX_MCAST_ADDRESS_CNT]; >> >> + UINT8 McastCount; >> >> + UINT64 MediaHeader[MAX_XMIT_BUFFERS]; >> >> + UINT8 TxBufferCount; >> >> + UINT16 State; >> >> + BOOLEAN CanTransmit; >> >> + BOOLEAN CanReceive; >> >> + UINT16 ReceiveStatus; >> >> + UINT8 RxFilter; >> >> + UINT32 RxFrame; >> >> + UINT32 TxFrame; >> >> + UINT16 NetworkConnect; >> >> + UINT8 CableDetect; >> >> + UINT16 MaxSegmentSize; >> >> + EFI_MAC_ADDRESS MacAddr; >> >> + PXE_CPB_START_31 PxeStart; >> >> + PXE_CPB_INITIALIZE PxeInit; >> >> + UINT8 PermNodeAddress[PXE_MAC_LENGTH]; >> >> + UINT8 CurrentNodeAddress[PXE_MAC_LENGTH]; >> >> + UINT8 BroadcastNodeAddress[PXE_MAC_LENGTH]; >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> +} NIC_DATA; >> >> + >> >> +#define NIC_DATA_SIGNATURE SIGNATURE_32('n', 'i', 'c', 'd') >> >> +#define NIC_DATA_FROM_USB_ETHERNET_PROTOCOL(a) CR (a, NIC_DATA, UsbEth, >> NIC_DATA_SIGNATURE) >> >> + >> >> +/** >> >> + This command is used to determine the operational state of the UNDI. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_GET_STATE)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command is used to change the UNDI operational state from stopped >> to started. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_START)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command is used to change the UNDI operational state from started >> to stopped. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_STOP)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command is used to retrieve initialization information that is >> >> + needed by drivers and applications to initialized UNDI. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_GET_INIT_INFO)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command is used to retrieve configuration information about >> >> + the NIC being controlled by the UNDI. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_GET_CONFIG_INFO)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command resets the network adapter and initializes UNDI using >> >> + the parameters supplied in the CPB. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_INITIALIZE)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command resets the network adapter and reinitializes the UNDI >> >> + with the same parameters provided in the Initialize command. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_RESET)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + The Shutdown command resets the network adapter and leaves it in a >> >> + safe state for another driver to initialize. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_SHUTDOWN)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + The Interrupt Enables command can be used to read and/or change >> >> + the current external interrupt enable settings. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_INTERRUPT_ENABLE)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command is used to read and change receive filters and, >> >> + if supported, read and change the multicast MAC address filter list. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_RECEIVE_FILTER)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command is used to get current station and broadcast MAC addresses >> >> + and, if supported, to change the current station MAC address. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_STATION_ADDRESS)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command is used to read and clear the NIC traffic statistics. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_STATISTICS)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + Translate a multicast IPv4 or IPv6 address to a multicast MAC address. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_MCAST_IPTOMAC)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command is used to read and write (if supported by NIC H/W) >> >> + nonvolatile storage on the NIC. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_NV_DATA)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command returns the current interrupt status and/or the >> >> + transmitted buffer addresses and the current media status. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_GET_STATUS)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command is used to fill the media header(s) in transmit packet(s). >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_FILL_HEADER)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + The Transmit command is used to place a packet into the transmit queue. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_TRANSMIT)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + When the network adapter has received a frame, this command is used >> >> + to copy the frame into driver/application storage. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_UNDI_RECEIVE)( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command resets the network adapter and initializes UNDI using >> >> + the parameters supplied in the CPB. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in, out] Nic A pointer to the Network interface controller >> data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_INITIALIZE)( >> >> + IN PXE_CDB *Cdb, >> >> + IN OUT NIC_DATA *Nic >> >> + ); >> >> + >> >> +/** >> >> + This command is used to read and clear the NIC traffic statistics. >> >> + >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + @param[in] DbAddr Data Block Address. >> >> + @param[in] DbSize Data Block Size. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_STATISTICS)( >> >> + IN NIC_DATA *Nic, >> >> + IN UINT64 DbAddr, >> >> + IN UINT16 DbSize >> >> + ); >> >> + >> >> +/** >> >> + This function is used to manage a USB device with the bulk transfer >> pipe. The endpoint is Bulk in. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor >> block. >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in, out] Packet A pointer to the buffer of data that >> will be transmitted to USB >> >> + device or received from USB device. >> >> + @param[in, out] PacketLength A pointer to the PacketLength. >> >> + >> >> + @retval EFI_SUCCESS The bulk transfer has been successfully >> executed. >> >> + @retval EFI_DEVICE_ERROR The transfer failed. The transfer status >> is returned in status. >> >> + @retval EFI_INVALID_PARAMETE One or more parameters are invalid. >> >> + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due >> to a lack of resources. >> >> + @retval EFI_TIMEOUT The control transfer fails due to >> timeout. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_RECEIVE)( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN OUT VOID *Packet, >> >> + IN OUT UINTN *PacketLength >> >> + ); >> >> + >> >> +/** >> >> + This function is used to manage a USB device with the bulk transfer >> pipe. The endpoint is Bulk out. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor >> block. >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in, out] Packet A pointer to the buffer of data that >> will be transmitted to USB >> >> + device or received from USB device. >> >> + @param[in, out] PacketLength A pointer to the PacketLength. >> >> + >> >> + @retval EFI_SUCCESS The bulk transfer has been successfully >> executed. >> >> + @retval EFI_DEVICE_ERROR The transfer failed. The transfer status >> is returned in status. >> >> + @retval EFI_INVALID_PARAMETE One or more parameters are invalid. >> >> + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due >> to a lack of resources. >> >> + @retval EFI_TIMEOUT The control transfer fails due to >> timeout. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_TRANSMIT)( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN OUT VOID *Packet, >> >> + IN OUT UINTN *PacketLength >> >> + ); >> >> + >> >> +/** >> >> + This function is used to manage a USB device with an interrupt >> transfer pipe. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in] IsNewTransfer If TRUE, a new transfer will be >> submitted to USB controller. If >> >> + FALSE, the interrupt transfer is deleted >> from the device's interrupt >> >> + transfer queue. >> >> + @param[in] PollingInterval Indicates the periodic rate, in >> milliseconds, that the transfer is to be >> >> + executed.This parameter is required when >> IsNewTransfer is TRUE. The >> >> + value must be between 1 to 255, >> otherwise EFI_INVALID_PARAMETER is returned. >> >> + The units are in milliseconds. >> >> + @param[in] Request A pointer to the EFI_USB_DEVICE_REQUEST >> data. >> >> + >> >> + @retval EFI_SUCCESS The asynchronous USB transfer request >> transfer has been successfully executed. >> >> + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request >> failed. >> >> + >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_INTERRUPT)( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN BOOLEAN IsNewTransfer, >> >> + IN UINTN PollingInterval, >> >> + IN EFI_USB_DEVICE_REQUEST *Request >> >> + ); >> >> + >> >> +/** >> >> + Retrieves the USB Ethernet Mac Address. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[out] MacAddress A pointer to the caller allocated USB >> Ethernet Mac Address. >> >> + >> >> + @retval EFI_SUCCESS The USB Header Functional descriptor was >> retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor was >> not found. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_GET_ETH_MAC_ADDRESS)( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT EFI_MAC_ADDRESS *MacAddress >> >> + ); >> >> + >> >> +/** >> >> + Retrieves the USB Ethernet Bulk transfer data size. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[out] BulkSize A pointer to the Bulk transfer data size. >> >> + >> >> + @retval EFI_SUCCESS The USB Header Functional descriptor was >> retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor was >> not found. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETH_MAX_BULK_SIZE)( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT UINTN *BulkSize >> >> + ); >> >> + >> >> +/** >> >> + Retrieves the USB Header functional Descriptor. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[out] UsbHeaderFunDescriptor A pointer to the caller allocated >> USB Header Functional Descriptor. >> >> + >> >> + @retval EFI_SUCCESS The USB Header Functional descriptor was >> retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor was >> not found. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_HEADER_FUNCTIONAL_DESCRIPTOR)( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor >> >> + ); >> >> + >> >> +/** >> >> + Retrieves the USB Union functional Descriptor. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[out] UsbUnionFunDescriptor A pointer to the caller allocated >> USB Union Functional Descriptor. >> >> + >> >> + @retval EFI_SUCCESS The USB Union Functional descriptor was >> retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbUnionFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Union Functional descriptor was >> not found. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_UNION_FUNCTIONAL_DESCRIPTOR)( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor >> >> + ); >> >> + >> >> +/** >> >> + Retrieves the USB Ethernet functional Descriptor. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[out] UsbEthFunDescriptor A pointer to the caller allocated >> USB Ethernet Functional Descriptor. >> >> + >> >> + @retval EFI_SUCCESS The USB Ethernet Functional descriptor >> was retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbEthFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Ethernet Functional descriptor >> was not found. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_FUNCTIONAL_DESCRIPTOR)( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor >> >> + ); >> >> + >> >> +/** >> >> + This request sets the Ethernet device multicast filters as specified >> in the >> >> + sequential list of 48 bit Ethernet multicast addresses. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] Value Number of filters. >> >> + @param[in] McastAddr A pointer to the value of the >> multicast addresses. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_SET_ETH_MULTICAST_FILTERS)( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN VOID *McastAddr >> >> + ); >> >> + >> >> +/** >> >> + This request sets up the specified Ethernet power management pattern >> filter as >> >> + described in the data structure. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] Value Number of filters. >> >> + @param[in] Length Size of the power management >> pattern filter data. >> >> + @param[in] PatternFilter A pointer to the power management >> pattern filter structure. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_SET_ETH_POWER_MANAGE_PATTERN_FILTER)( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN UINT16 Length, >> >> + IN VOID *PatternFilter >> >> + ); >> >> + >> >> +/** >> >> + This request retrieves the status of the specified Ethernet power >> management >> >> + pattern filter from the device. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] Value The filter number. >> >> + @param[out] PatternActive A pointer to the pattern active >> boolean. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_GET_ETH_POWER_MANAGE_PATTERN_FILTER)( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + OUT BOOLEAN *PatternActive >> >> + ); >> >> + >> >> +/** >> >> + This request is used to configure device Ethernet packet filter >> settings. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in] Value Packet Filter Bitmap. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_SET_ETH_PACKET_FILTER)( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value >> >> + ); >> >> + >> >> +/** >> >> + This request is used to retrieve a statistic based on the feature >> selector. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] FeatureSelector Value of the feature selector. >> >> + @param[out] Statistic A pointer to the 32 bit unsigned >> integer. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> +**/ >> >> +typedef >> >> +EFI_STATUS >> >> +(EFIAPI *USB_ETHERNET_GET_ETH_STATISTIC)( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 FeatureSelector, >> >> + OUT VOID *Statistic >> >> + ); >> >> + >> >> +typedef struct { >> >> + USB_ETHERNET_UNDI_GET_STATE UsbEthUndiGetState; >> >> + USB_ETHERNET_UNDI_START UsbEthUndiStart; >> >> + USB_ETHERNET_UNDI_STOP UsbEthUndiStop; >> >> + USB_ETHERNET_UNDI_GET_INIT_INFO UsbEthUndiGetInitInfo; >> >> + USB_ETHERNET_UNDI_GET_CONFIG_INFO UsbEthUndiGetConfigInfo; >> >> + USB_ETHERNET_UNDI_INITIALIZE UsbEthUndiInitialize; >> >> + USB_ETHERNET_UNDI_RESET UsbEthUndiReset; >> >> + USB_ETHERNET_UNDI_SHUTDOWN UsbEthUndiShutdown; >> >> + USB_ETHERNET_UNDI_INTERRUPT_ENABLE UsbEthUndiInterruptEnable; >> >> + USB_ETHERNET_UNDI_RECEIVE_FILTER UsbEthUndiReceiveFilter; >> >> + USB_ETHERNET_UNDI_STATION_ADDRESS UsbEthUndiStationAddress; >> >> + USB_ETHERNET_UNDI_STATISTICS UsbEthUndiStatistics; >> >> + USB_ETHERNET_UNDI_MCAST_IPTOMAC UsbEthUndiMcastIp2Mac; >> >> + USB_ETHERNET_UNDI_NV_DATA UsbEthUndiNvData; >> >> + USB_ETHERNET_UNDI_GET_STATUS UsbEthUndiGetStatus; >> >> + USB_ETHERNET_UNDI_FILL_HEADER UsbEthUndiFillHeader; >> >> + USB_ETHERNET_UNDI_TRANSMIT UsbEthUndiTransmit; >> >> + USB_ETHERNET_UNDI_RECEIVE UsbEthUndiReceive; >> >> +} USB_ETHERNET_UNDI; >> >> + >> >> +// The USB_ETHERNET_PROTOCOL provides some basic USB Ethernet device >> relevant >> >> +// descriptor and specific requests. >> >> +struct _USB_ETHERNET_PROTOCOL { >> >> + USB_ETHERNET_UNDI UsbEthUndi; >> >> + // for calling the UNDI child functions >> >> + USB_ETHERNET_INITIALIZE UsbEthInitialize; >> >> + USB_ETHERNET_STATISTICS UsbEthStatistics; >> >> + USB_ETHERNET_RECEIVE UsbEthReceive; >> >> + USB_ETHERNET_TRANSMIT UsbEthTransmit; >> >> + USB_ETHERNET_INTERRUPT UsbEthInterrupt; >> >> + USB_GET_ETH_MAC_ADDRESS UsbEthMacAddress; >> >> + USB_ETH_MAX_BULK_SIZE UsbEthMaxBulkSize; >> >> + USB_HEADER_FUNCTIONAL_DESCRIPTOR >> UsbHeaderFunDescriptor; >> >> + USB_UNION_FUNCTIONAL_DESCRIPTOR >> UsbUnionFunDescriptor; >> >> + USB_ETHERNET_FUNCTIONAL_DESCRIPTOR >> UsbEthFunDescriptor; >> >> + USB_ETHERNET_SET_ETH_MULTICAST_FILTERS >> SetUsbEthMcastFilter; >> >> + USB_ETHERNET_SET_ETH_POWER_MANAGE_PATTERN_FILTER >> SetUsbEthPowerPatternFilter; >> >> + USB_ETHERNET_GET_ETH_POWER_MANAGE_PATTERN_FILTER >> GetUsbEthPoewrPatternFilter; >> >> + USB_ETHERNET_SET_ETH_PACKET_FILTER >> SetUsbEthPacketFilter; >> >> + USB_ETHERNET_GET_ETH_STATISTIC GetUsbEthStatistic; >> >> +}; >> >> + >> >> +#endif >> >> diff --git a/UsbNetworkPkg/NetworkCommon/ComponentName.c >> b/UsbNetworkPkg/NetworkCommon/ComponentName.c >> new file mode 100644 >> index 0000000000..2697bf5083 >> --- /dev/null >> +++ b/UsbNetworkPkg/NetworkCommon/ComponentName.c >> @@ -0,0 +1,264 @@ >> +/** @file >> >> + This file contains code for USB network common driver >> >> + component name definitions >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#include "DriverBinding.h" >> >> + >> >> +extern EFI_DRIVER_BINDING_PROTOCOL gNetworkCommonDriverBinding; >> >> +extern EFI_GUID gUsbEthProtocolGuid; >> >> + >> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE >> gNetworkCommonDriverNameTable[] = { >> >> + { >> >> + "eng;en", >> >> + L"Network Common Driver" >> >> + }, >> >> + { >> >> + NULL, >> >> + NULL >> >> + } >> >> +}; >> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE >> *gNetworkCommonControllerNameTable = NULL; >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +NetworkCommonComponentNameGetDriverName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **DriverName >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +NetworkCommonComponentNameGetControllerName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN EFI_HANDLE Controller, >> >> + IN EFI_HANDLE ChildHandle OPTIONAL, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **ControllerName >> >> + ); >> >> + >> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL >> gNetworkCommonComponentName = { >> >> + NetworkCommonComponentNameGetDriverName, >> >> + NetworkCommonComponentNameGetControllerName, >> >> + "eng" >> >> +}; >> >> + >> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL >> gNetworkCommonComponentName2 = { >> >> + >> (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)NetworkCommonComponentNameGetDriverName, >> >> + >> (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)NetworkCommonComponentNameGetControllerName, >> >> + "en" >> >> +}; >> >> + >> >> +/** >> >> + Retrieves a Unicode string that is the user readable name of the >> driver. >> >> + >> >> + This function retrieves the user readable name of a driver in the form >> of a >> >> + Unicode string. If the driver specified by This has a user readable >> name in >> >> + the language specified by Language, then a pointer to the driver name >> is >> >> + returned in DriverName, and EFI_SUCCESS is returned. If the driver >> specified >> >> + by This does not support the language specified by Language, >> >> + then EFI_UNSUPPORTED is returned. >> >> + >> >> + @param[in] This A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >> >> + EFI_COMPONENT_NAME_PROTOCOL instance. >> >> + @param[in] Language A pointer to a Null-terminated ASCII >> string >> >> + array indicating the language. This is >> the >> >> + language of the driver name that the >> caller is >> >> + requesting, and it must match one of the >> >> + languages specified in >> SupportedLanguages. The >> >> + number of languages supported by a >> driver is up >> >> + to the driver writer. Language is >> specified >> >> + in RFC 4646 or ISO 639-2 language code >> format. >> >> + @param[out] DriverName A pointer to the Unicode string to >> return. >> >> + This Unicode string is the name of the >> >> + driver specified by This in the language >> >> + specified by Language. >> >> + >> >> + @retval EFI_SUCCESS The Unicode string for the Driver >> specified by >> >> + This and the language specified by >> Language was >> >> + returned in DriverName. >> >> + @retval EFI_INVALID_PARAMETER Language is NULL. >> >> + @retval EFI_INVALID_PARAMETER DriverName is NULL. >> >> + @retval EFI_UNSUPPORTED The driver specified by This does not >> support >> >> + the language specified by Language. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +NetworkCommonComponentNameGetDriverName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **DriverName >> >> + ) >> >> +{ >> >> + return LookupUnicodeString2 ( >> >> + Language, >> >> + This->SupportedLanguages, >> >> + gNetworkCommonDriverNameTable, >> >> + DriverName, >> >> + (BOOLEAN)(This == &gNetworkCommonComponentName) >> >> + ); >> >> +} >> >> + >> >> +/** >> >> + Retrieves a Unicode string that is the user readable name of the >> controller >> >> + that is being managed by a driver. >> >> + >> >> + This function retrieves the user readable name of the controller >> specified by >> >> + ControllerHandle and ChildHandle in the form of a Unicode string. If >> the >> >> + driver specified by This has a user readable name in the language >> specified by >> >> + Language, then a pointer to the controller name is returned in >> ControllerName, >> >> + and EFI_SUCCESS is returned. If the driver specified by This is not >> currently >> >> + managing the controller specified by ControllerHandle and ChildHandle, >> >> + then EFI_UNSUPPORTED is returned. If the driver specified by This >> does not >> >> + support the language specified by Language, then EFI_UNSUPPORTED is >> returned. >> >> + >> >> + @param[in] This A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >> >> + EFI_COMPONENT_NAME_PROTOCOL instance. >> >> + @param[in] Controller The handle of a controller that the >> driver >> >> + specified by This is managing. This >> handle >> >> + specifies the controller whose name is >> to be >> >> + returned. >> >> + @param[in] ChildHandle The handle of the child controller to >> retrieve >> >> + the name of. This is an optional >> parameter that >> >> + may be NULL. It will be NULL for device >> >> + drivers. It will also be NULL for a bus >> drivers >> >> + that wish to retrieve the name of the bus >> >> + controller. It will not be NULL for a >> bus >> >> + driver that wishes to retrieve the name >> of a >> >> + child controller. >> >> + @param[in] Language A pointer to a Null-terminated ASCII >> string >> >> + array indicating the language. This is >> the >> >> + language of the driver name that the >> caller is >> >> + requesting, and it must match one of the >> >> + languages specified in >> SupportedLanguages. The >> >> + number of languages supported by a >> driver is up >> >> + to the driver writer. Language is >> specified in >> >> + RFC 4646 or ISO 639-2 language code >> format. >> >> + @param[out] ControllerName A pointer to the Unicode string to >> return. >> >> + This Unicode string is the name of the >> >> + controller specified by ControllerHandle >> and >> >> + ChildHandle in the language specified by >> >> + Language from the point of view of the >> driver >> >> + specified by This. >> >> + >> >> + @retval EFI_SUCCESS The Unicode string for the user readable >> name in >> >> + the language specified by Language for >> the >> >> + driver specified by This was returned in >> >> + DriverName. >> >> + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid >> EFI_HANDLE. >> >> + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a >> valid >> >> + EFI_HANDLE. >> >> + @retval EFI_INVALID_PARAMETER Language is NULL. >> >> + @retval EFI_INVALID_PARAMETER ControllerName is NULL. >> >> + @retval EFI_UNSUPPORTED The driver specified by This is not >> currently >> >> + managing the controller specified by >> >> + ControllerHandle and ChildHandle. >> >> + @retval EFI_UNSUPPORTED The driver specified by This does not >> support >> >> + the language specified by Language. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +NetworkCommonComponentNameGetControllerName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN EFI_HANDLE Controller, >> >> + IN EFI_HANDLE ChildHandle OPTIONAL, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **ControllerName >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + CHAR16 *HandleName; >> >> + EFI_USB_IO_PROTOCOL *UsbIo = NULL; >> >> + EFI_USB_DEVICE_DESCRIPTOR DevDesc; >> >> + >> >> + if (!Language || !ControllerName) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + if (ChildHandle == NULL) { >> >> + return EFI_UNSUPPORTED; >> >> + } >> >> + >> >> + // >> >> + // Make sure this driver is currently managing ControllerHandle >> >> + // >> >> + Status = EfiTestManagedDevice ( >> >> + Controller, >> >> + gNetworkCommonDriverBinding.DriverBindingHandle, >> >> + &gUsbEthProtocolGuid >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + // >> >> + // Make sure this driver produced ChildHandle >> >> + // >> >> + Status = EfiTestChildHandle ( >> >> + Controller, >> >> + ChildHandle, >> >> + &gUsbEthProtocolGuid >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status = gBS->HandleProtocol (Controller, &gEfiUsbIoProtocolGuid, >> (VOID **)&UsbIo); >> >> + >> >> + if (!EFI_ERROR (Status)) { >> >> + Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status = UsbIo->UsbGetStringDescriptor (UsbIo, 0x409, >> DevDesc.StrManufacturer, &HandleName); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + *ControllerName = HandleName; >> >> + >> >> + if (gNetworkCommonControllerNameTable != NULL) { >> >> + FreeUnicodeStringTable (gNetworkCommonControllerNameTable); >> >> + gNetworkCommonControllerNameTable = NULL; >> >> + } >> >> + >> >> + Status = AddUnicodeString2 ( >> >> + "eng", >> >> + gNetworkCommonComponentName.SupportedLanguages, >> >> + &gNetworkCommonControllerNameTable, >> >> + HandleName, >> >> + TRUE >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status = AddUnicodeString2 ( >> >> + "en", >> >> + gNetworkCommonComponentName2.SupportedLanguages, >> >> + &gNetworkCommonControllerNameTable, >> >> + HandleName, >> >> + FALSE >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + return LookupUnicodeString2 ( >> >> + Language, >> >> + This->SupportedLanguages, >> >> + gNetworkCommonControllerNameTable, >> >> + ControllerName, >> >> + (BOOLEAN)(This == &gNetworkCommonComponentName) >> >> + ); >> >> + } >> >> + >> >> + return EFI_UNSUPPORTED; >> >> +} >> >> diff --git a/UsbNetworkPkg/NetworkCommon/DriverBinding.c >> b/UsbNetworkPkg/NetworkCommon/DriverBinding.c >> new file mode 100644 >> index 0000000000..18b2daa7a8 >> --- /dev/null >> +++ b/UsbNetworkPkg/NetworkCommon/DriverBinding.c >> @@ -0,0 +1,583 @@ >> +/** @file >> >> + This file contains code for USB network binding driver >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#include "DriverBinding.h" >> >> + >> >> +PXE_SW_UNDI *gPxe = NULL; >> >> +NIC_DEVICE *gLanDeviceList[MAX_LAN_INTERFACE]; >> >> + >> >> +EFI_GUID gUsbEthProtocolGuid = USB_ETHERNET_PROTOCOL_GUID; >> >> + >> >> +EFI_DRIVER_BINDING_PROTOCOL gNetworkCommonDriverBinding = { >> >> + NetworkCommonSupported, >> >> + NetworkCommonDriverStart, >> >> + NetworkCommonDriverStop, >> >> + NETWORK_COMMON_DRIVER_VERSION, >> >> + NULL, >> >> + NULL >> >> +}; >> >> + >> >> +/** >> >> + Create MAC Device Path >> >> + >> >> + @param[in, out] Dev A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> >> + @param[in] BaseDev A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> >> + @param[in] Nic A pointer to the Network interface >> controller data. >> >> + >> >> + @retval EFI_OUT_OF_RESOURCES The device path could not be created >> successfully due to a lack of resources. >> >> + @retval EFI_SUCCESS MAC device path created successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +CreateMacDevicePath ( >> >> + IN OUT EFI_DEVICE_PATH_PROTOCOL **Dev, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *BaseDev, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + MAC_ADDR_DEVICE_PATH MacAddrNode; >> >> + EFI_DEVICE_PATH_PROTOCOL *EndNode; >> >> + UINT8 *DevicePath; >> >> + UINT16 TotalLength; >> >> + UINT16 BaseLength; >> >> + >> >> + ZeroMem (&MacAddrNode, sizeof (MAC_ADDR_DEVICE_PATH)); >> >> + CopyMem (&MacAddrNode.MacAddress, &Nic->MacAddr, sizeof >> (EFI_MAC_ADDRESS)); >> >> + >> >> + MacAddrNode.Header.Type = MESSAGING_DEVICE_PATH; >> >> + MacAddrNode.Header.SubType = MSG_MAC_ADDR_DP; >> >> + MacAddrNode.Header.Length[0] = (UINT8)sizeof (MacAddrNode); >> >> + MacAddrNode.Header.Length[1] = 0; >> >> + >> >> + EndNode = BaseDev; >> >> + >> >> + while (!IsDevicePathEnd (EndNode)) { >> >> + EndNode = NextDevicePathNode (EndNode); >> >> + } >> >> + >> >> + BaseLength = (UINT16)((UINTN)(EndNode) - (UINTN)(BaseDev)); >> >> + TotalLength = (UINT16)(BaseLength + sizeof (MacAddrNode) + sizeof >> (EFI_DEVICE_PATH_PROTOCOL)); >> >> + >> >> + Status = gBS->AllocatePool (EfiBootServicesData, TotalLength, (VOID >> **)&DevicePath); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + *Dev = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath; >> >> + CopyMem (DevicePath, (CHAR8 *)BaseDev, BaseLength); >> >> + DevicePath += BaseLength; >> >> + CopyMem (DevicePath, (CHAR8 *)&MacAddrNode, sizeof (MacAddrNode)); >> >> + DevicePath += sizeof (MacAddrNode); >> >> + CopyMem (DevicePath, (CHAR8 *)EndNode, sizeof >> (EFI_DEVICE_PATH_PROTOCOL)); >> >> + >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + Network Common Driver Binding Support. >> >> + >> >> + @param[in] This Protocol instance pointer. >> >> + @param[in] ControllerHandle Handle of device to test. >> >> + @param[in] RemainingDevicePath Optional parameter use to pick a >> specific child >> >> + device to start. >> >> + >> >> + @retval EFI_SUCCESS This driver supports this device. >> >> + @retval EFI_ALREADY_STARTED This driver is already running on >> this device. >> >> + @retval other This driver does not support this >> device. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +NetworkCommonSupported ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_PROTOCOL *UsbEth; >> >> + >> >> + Status = gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + (VOID **)&UsbEth, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Network Common Driver Binding Start. >> >> + >> >> + @param[in] This Protocol instance pointer. >> >> + @param[in] ControllerHandle Handle of device to bind driver to. >> >> + @param[in] RemainingDevicePath Optional parameter use to pick a >> specific child >> >> + device to start. >> >> + >> >> + @retval EFI_SUCCESS This driver is added to >> ControllerHandle >> >> + @retval EFI_DEVICE_ERROR This driver could not be started >> due to a device error >> >> + @retval EFI_OUT_OF_RESOURCES The driver could not install >> successfully due to a lack of resources. >> >> + @retval other This driver does not support this >> device >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +NetworkCommonDriverStart ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_DEVICE_PATH_PROTOCOL *UsbEthPath; >> >> + USB_ETHERNET_PROTOCOL *UsbEth; >> >> + EFI_MAC_ADDRESS MacAddress; >> >> + UINTN BulkDataSize; >> >> + NIC_DEVICE *NicDevice; >> >> + UINT8 *TmpPxePointer = NULL; >> >> + >> >> + Status = gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + (VOID **)&UsbEth, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status = gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + (VOID **)&UsbEthPath, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> >> + ); >> >> + >> >> + if (EFI_ERROR (Status)) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return Status; >> >> + } >> >> + >> >> + ZeroMem (&MacAddress, sizeof (EFI_MAC_ADDRESS)); >> >> + >> >> + Status = UsbEth->UsbEthMacAddress (UsbEth, &MacAddress); >> >> + ASSERT_EFI_ERROR (Status); >> >> + Status = UsbEth->UsbEthMaxBulkSize (UsbEth, &BulkDataSize); >> >> + >> >> + if (EFI_ERROR (Status)) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return Status; >> >> + } >> >> + >> >> + NicDevice = AllocateZeroPool (sizeof (NIC_DEVICE)); >> >> + if (!NicDevice) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return EFI_OUT_OF_RESOURCES; >> >> + } >> >> + >> >> + // for alignment adjustment >> >> + if (gPxe == NULL) { >> >> + TmpPxePointer = AllocateZeroPool (sizeof (PXE_SW_UNDI) + 16); >> >> + if (!TmpPxePointer) { >> >> + if (NicDevice != NULL) { >> >> + gBS->FreePool (NicDevice); >> >> + } >> >> + >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + >> >> + return EFI_OUT_OF_RESOURCES; >> >> + } else { >> >> + // check for paragraph alignment here >> >> + if (((UINTN)TmpPxePointer & 0x0F) != 0) { >> >> + gPxe = (PXE_SW_UNDI *)(TmpPxePointer + 8); >> >> + } else { >> >> + gPxe = (PXE_SW_UNDI *)TmpPxePointer; >> >> + } >> >> + >> >> + if (!gPxe) { >> >> + if (NicDevice != NULL) { >> >> + gBS->FreePool (NicDevice); >> >> + } >> >> + >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return EFI_OUT_OF_RESOURCES; >> >> + } >> >> + >> >> + PxeStructInit (gPxe); >> >> + } >> >> + } >> >> + >> >> + NicDevice->NiiProtocol.Id = (UINT64)(UINTN)(gPxe); >> >> + NicDevice->NiiProtocol.IfNum = gPxe->IFcnt | gPxe->IFcntExt << 8; >> >> + >> >> + UpdateNicNum (&NicDevice->NicInfo, gPxe); >> >> + >> >> + NicDevice->NicInfo.Signature = NIC_DATA_SIGNATURE; >> >> + >> >> + NicDevice->NicInfo.UsbEth = UsbEth; >> >> + NicDevice->NicInfo.MaxSegmentSize = (UINT16)BulkDataSize; >> >> + NicDevice->NicInfo.CableDetect = 0; >> >> + >> >> + CopyMem ((CHAR8 *)&(NicDevice->NicInfo.MacAddr), (CHAR8 *)&MacAddress, >> sizeof (MacAddress)); >> >> + >> >> + NicDevice->NicInfo.TxBufferCount = 0; >> >> + >> >> + if (NicDevice->NiiProtocol.IfNum < MAX_LAN_INTERFACE) { >> >> + gLanDeviceList[NicDevice->NiiProtocol.IfNum] = NicDevice; >> >> + } else { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + >> >> + if (TmpPxePointer != NULL) { >> >> + gBS->FreePool (TmpPxePointer); >> >> + } >> >> + >> >> + if (NicDevice != NULL) { >> >> + gBS->FreePool (NicDevice); >> >> + } >> >> + >> >> + return EFI_DEVICE_ERROR; >> >> + } >> >> + >> >> + Status = CreateMacDevicePath ( >> >> + &NicDevice->DevPath, >> >> + UsbEthPath, >> >> + &NicDevice->NicInfo >> >> + ); >> >> + >> >> + if (EFI_ERROR (Status)) { >> >> + UpdateNicNum (NULL, gPxe); >> >> + if (TmpPxePointer != NULL) { >> >> + gBS->FreePool (TmpPxePointer); >> >> + } >> >> + } >> >> + >> >> + NicDevice->Signature = UNDI_DEV_SIGNATURE; >> >> + NicDevice->NiiProtocol.Revision = >> EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION; >> >> + NicDevice->NiiProtocol.Type = EfiNetworkInterfaceUndi; >> >> + NicDevice->NiiProtocol.MajorVer = PXE_ROMID_MAJORVER; >> >> + NicDevice->NiiProtocol.MinorVer = PXE_ROMID_MINORVER; >> >> + NicDevice->NiiProtocol.ImageSize = 0; >> >> + NicDevice->NiiProtocol.ImageAddr = 0; >> >> + NicDevice->NiiProtocol.Ipv6Supported = TRUE; >> >> + >> >> + NicDevice->NiiProtocol.StringId[0] = 'U'; >> >> + NicDevice->NiiProtocol.StringId[1] = 'N'; >> >> + NicDevice->NiiProtocol.StringId[2] = 'D'; >> >> + NicDevice->NiiProtocol.StringId[3] = 'I'; >> >> + NicDevice->DeviceHandle = NULL; >> >> + >> >> + ZeroMem (&NicDevice->NicInfo.Request, sizeof (EFI_USB_DEVICE_REQUEST)); >> >> + >> >> + Status = UsbEth->UsbEthInterrupt (UsbEth, TRUE, >> NETWORK_COMMON_POLLING_INTERVAL, &NicDevice->NicInfo.Request); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status = gBS->InstallMultipleProtocolInterfaces ( >> >> + &NicDevice->DeviceHandle, >> >> + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, >> >> + &NicDevice->NiiProtocol, >> >> + &gEfiDevicePathProtocolGuid, >> >> + NicDevice->DevPath, >> >> + NULL >> >> + ); >> >> + >> >> + if (EFI_ERROR (Status)) { >> >> + if (NicDevice->NiiProtocol.IfNum < MAX_LAN_INTERFACE) { >> >> + gLanDeviceList[NicDevice->NiiProtocol.IfNum] = NULL; >> >> + } >> >> + >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + >> >> + if (TmpPxePointer != NULL) { >> >> + gBS->FreePool (TmpPxePointer); >> >> + } >> >> + >> >> + if (NicDevice->DevPath != NULL) { >> >> + gBS->FreePool (NicDevice->DevPath); >> >> + } >> >> + >> >> + if (NicDevice != NULL) { >> >> + gBS->FreePool (NicDevice); >> >> + } >> >> + >> >> + return EFI_DEVICE_ERROR; >> >> + } >> >> + >> >> + Status = gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + (VOID **)&UsbEth, >> >> + This->DriverBindingHandle, >> >> + NicDevice->DeviceHandle, >> >> + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER >> >> + ); >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Network Common Driver Binding Stop. >> >> + >> >> + @param[in] This Protocol instance pointer. >> >> + @param[in] ControllerHandle Handle of device to stop driver on >> >> + @param[in] NumberOfChildren Number of Handles in >> ChildHandleBuffer. If number of >> >> + children is zero stop the entire bus >> driver. >> >> + @param[in] ChildHandleBuffer List of Child Handles to Stop. >> >> + >> >> + @retval EFI_SUCCESS This driver is removed >> ControllerHandle >> >> + @retval other This driver was not removed from >> this device >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +NetworkCommonDriverStop ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN UINTN NumberOfChildren, >> >> + IN EFI_HANDLE *ChildHandleBuffer >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + BOOLEAN AllChildrenStopped; >> >> + UINTN Index; >> >> + USB_ETHERNET_PROTOCOL *UsbEth; >> >> + NIC_DEVICE *NicDevice; >> >> + EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NiiProtocol; >> >> + >> >> + if (NumberOfChildren == 0) { >> >> + Status = gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, >> >> + (VOID **)&NiiProtocol, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >> >> + ); >> >> + >> >> + if (EFI_ERROR (Status)) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return EFI_SUCCESS; >> >> + } >> >> + >> >> + NicDevice = UNDI_DEV_FROM_THIS (NiiProtocol); >> >> + Status = gBS->UninstallMultipleProtocolInterfaces ( >> >> + ControllerHandle, >> >> + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, >> >> + &NicDevice->NiiProtocol, >> >> + &gEfiDevicePathProtocolGuid, >> >> + NicDevice->DevPath, >> >> + NULL >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + gBS->FreePool (NicDevice->DevPath); >> >> + gBS->FreePool (NicDevice); >> >> + >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return EFI_SUCCESS; >> >> + } >> >> + >> >> + AllChildrenStopped = TRUE; >> >> + >> >> + for (Index = 0; Index < NumberOfChildren; Index++) { >> >> + Status = gBS->OpenProtocol ( >> >> + ChildHandleBuffer[Index], >> >> + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, >> >> + (VOID **)&NiiProtocol, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + AllChildrenStopped = FALSE; >> >> + continue; >> >> + } >> >> + >> >> + NicDevice = UNDI_DEV_FROM_THIS (NiiProtocol); >> >> + >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ChildHandleBuffer[Index] >> >> + ); >> >> + >> >> + Status = gBS->UninstallMultipleProtocolInterfaces ( >> >> + ChildHandleBuffer[Index], >> >> + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, >> >> + &NicDevice->NiiProtocol, >> >> + &gEfiDevicePathProtocolGuid, >> >> + NicDevice->DevPath, >> >> + NULL >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + Status = gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + (VOID **)&UsbEth, >> >> + This->DriverBindingHandle, >> >> + ChildHandleBuffer[Index], >> >> + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER >> >> + ); >> >> + } else { >> >> + gBS->FreePool (NicDevice->DevPath); >> >> + gBS->FreePool (NicDevice); >> >> + } >> >> + } >> >> + >> >> + if (!AllChildrenStopped) { >> >> + return EFI_DEVICE_ERROR; >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Entrypoint of Network Common Driver. >> >> + >> >> + This function is the entrypoint of Network Common Driver. It installs >> Driver Binding >> >> + Protocols together with Component Name Protocols. >> >> + >> >> + @param[in] ImageHandle The firmware allocated handle for the >> EFI image. >> >> + @param[in] SystemTable A pointer to the EFI System Table. >> >> + >> >> + @retval EFI_SUCCESS The entry point is executed successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +NetworkCommonEntry ( >> >> + IN EFI_HANDLE ImageHandle, >> >> + IN EFI_SYSTEM_TABLE *SystemTable >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + >> >> + gNetworkCommonDriverBinding.DriverBindingHandle = ImageHandle; >> >> + gNetworkCommonDriverBinding.ImageHandle = ImageHandle; >> >> + >> >> + Status = gBS->InstallMultipleProtocolInterfaces ( >> >> + &gNetworkCommonDriverBinding.DriverBindingHandle, >> >> + &gEfiDriverBindingProtocolGuid, >> >> + &gNetworkCommonDriverBinding, >> >> + &gEfiComponentName2ProtocolGuid, >> >> + &gNetworkCommonComponentName2, >> >> + NULL >> >> + ); >> >> + return Status; >> >> +} >> >> diff --git a/UsbNetworkPkg/NetworkCommon/DriverBinding.h >> b/UsbNetworkPkg/NetworkCommon/DriverBinding.h >> new file mode 100644 >> index 0000000000..223e034f2f >> --- /dev/null >> +++ b/UsbNetworkPkg/NetworkCommon/DriverBinding.h >> @@ -0,0 +1,263 @@ >> +/** @file >> >> + Header file for for USB network common driver >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#ifndef _DRIVER_BINDING_H_ >> >> +#define _DRIVER_BINDING_H_ >> >> + >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> + >> >> +#define NETWORK_COMMON_DRIVER_VERSION 1 >> >> +#define NETWORK_COMMON_POLLING_INTERVAL 0x10 >> >> +#define RX_BUFFER_COUNT 32 >> >> +#define TX_BUFFER_COUNT 32 >> >> +#define MEMORY_REQUIRE 0 >> >> + >> >> +#define UNDI_DEV_SIGNATURE SIGNATURE_32('u','n','d','i') >> >> +#define UNDI_DEV_FROM_THIS(a) CR(a, NIC_DEVICE, NiiProtocol, >> UNDI_DEV_SIGNATURE) >> >> +#define UNDI_DEV_FROM_NIC(a) CR(a, NIC_DEVICE, NicInfo, >> UNDI_DEV_SIGNATURE) >> >> + >> >> +#pragma pack(1) >> >> +typedef struct { >> >> + UINT8 DestAddr[PXE_HWADDR_LEN_ETHER]; >> >> + UINT8 SrcAddr[PXE_HWADDR_LEN_ETHER]; >> >> + UINT16 Protocol; >> >> +} EthernetHeader; >> >> +#pragma pack() >> >> + >> >> +typedef struct { >> >> + UINTN Signature; >> >> + EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL NiiProtocol; >> >> + EFI_HANDLE DeviceHandle; >> >> + EFI_DEVICE_PATH_PROTOCOL *BaseDevPath; >> >> + EFI_DEVICE_PATH_PROTOCOL *DevPath; >> >> + NIC_DATA NicInfo; >> >> +} NIC_DEVICE; >> >> + >> >> +typedef VOID (*API_FUNC)( >> >> + PXE_CDB *, >> >> + NIC_DATA * >> >> + ); >> >> + >> >> +extern PXE_SW_UNDI *gPxe; >> >> +extern NIC_DEVICE *gLanDeviceList[MAX_LAN_INTERFACE]; >> >> +extern EFI_COMPONENT_NAME2_PROTOCOL gNetworkCommonComponentName2; >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +NetworkCommonSupported ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +NetworkCommonDriverStart ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +NetworkCommonDriverStop ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN UINTN NumberOfChildren, >> >> + IN EFI_HANDLE *ChildHandleBuffer >> >> + ); >> >> + >> >> +VOID >> >> +PxeStructInit ( >> >> + OUT PXE_SW_UNDI *PxeSw >> >> + ); >> >> + >> >> +VOID >> >> +UpdateNicNum ( >> >> + IN NIC_DATA *Nic, >> >> + IN OUT PXE_SW_UNDI *PxeSw >> >> + ); >> >> + >> >> +VOID >> >> +UndiApiEntry ( >> >> + IN UINT64 Cdb >> >> + ); >> >> + >> >> +UINTN >> >> +MapIt ( >> >> + IN NIC_DATA *Nic, >> >> + IN UINT64 MemAddr, >> >> + IN UINT32 Size, >> >> + IN UINT32 Direction, >> >> + OUT UINT64 MappedAddr >> >> + ); >> >> + >> >> +VOID >> >> +UnMapIt ( >> >> + IN NIC_DATA *Nic, >> >> + IN UINT64 MemAddr, >> >> + IN UINT32 Size, >> >> + IN UINT32 Direction, >> >> + IN UINT64 MappedAddr >> >> + ); >> >> + >> >> +VOID >> >> +UndiGetState ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiStart ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiStop ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiGetInitInfo ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiGetConfigInfo ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiInitialize ( >> >> + IN PXE_CDB *Cdb, >> >> + IN OUT NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiReset ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiShutdown ( >> >> + IN PXE_CDB *Cdb, >> >> + IN OUT NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiInterruptEnable ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiReceiveFilter ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiStationAddress ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiStatistics ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiMcastIp2Mac ( >> >> + IN OUT PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiNvData ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiGetStatus ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiFillHeader ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiTransmit ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +VOID >> >> +UndiReceive ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +UINT16 >> >> +Initialize ( >> >> + IN PXE_CDB *Cdb, >> >> + IN OUT NIC_DATA *Nic >> >> + ); >> >> + >> >> +UINT16 >> >> +Transmit ( >> >> + IN PXE_CDB *Cdb, >> >> + IN OUT NIC_DATA *Nic, >> >> + IN UINT64 CpbAddr, >> >> + IN UINT16 OpFlags >> >> + ); >> >> + >> >> +UINT16 >> >> +Receive ( >> >> + IN PXE_CDB *Cdb, >> >> + IN OUT NIC_DATA *Nic, >> >> + IN UINT64 CpbAddr, >> >> + IN OUT UINT64 DbAddr >> >> + ); >> >> + >> >> +UINT16 >> >> +Setfilter ( >> >> + IN NIC_DATA *Nic, >> >> + IN UINT16 SetFilter, >> >> + IN UINT64 CpbAddr, >> >> + IN UINT32 CpbSize >> >> + ); >> >> + >> >> +UINT16 >> >> +Statistics ( >> >> + IN NIC_DATA *Nic, >> >> + IN UINT64 DbAddr, >> >> + IN UINT16 DbSize >> >> + ); >> >> + >> >> +#endif >> >> diff --git a/UsbNetworkPkg/NetworkCommon/NetworkCommon.inf >> b/UsbNetworkPkg/NetworkCommon/NetworkCommon.inf >> new file mode 100644 >> index 0000000000..483df660f7 >> --- /dev/null >> +++ b/UsbNetworkPkg/NetworkCommon/NetworkCommon.inf >> @@ -0,0 +1,43 @@ >> +## @file >> +# This is Usb Network Common driver for DXE phase. >> +# >> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> +# Subject to AMI licensing agreement. >> +## >> + >> +[Defines] >> + INF_VERSION = 0x00010005 >> + BASE_NAME = NetworkCommon >> + FILE_GUID = ca6eb4f4-f1d6-4375-97d6-18856871e1bf >> + MODULE_TYPE = DXE_DRIVER >> + VERSION_STRING = 1.0 >> + ENTRY_POINT = NetworkCommonEntry >> + >> +[Sources] >> + DriverBinding.c >> + DriverBinding.h >> + ComponentName.c >> + PxeFunction.c >> + >> +[Packages] >> + MdePkg/MdePkg.dec >> + MdeModulePkg/MdeModulePkg.dec >> + UsbNetworkPkg/UsbNetworkPkg.dec >> + >> +[LibraryClasses] >> + UefiDriverEntryPoint >> + UefiBootServicesTableLib >> + UefiLib >> + DebugLib >> + UefiUsbLib >> + MemoryAllocationLib >> + BaseMemoryLib >> + >> +[Protocols] >> + gEfiNetworkInterfaceIdentifierProtocolGuid_31 >> + gEfiUsbIoProtocolGuid >> + gEfiDevicePathProtocolGuid >> + gEfiDriverBindingProtocolGuid >> + >> +[Depex] >> + TRUE >> diff --git a/UsbNetworkPkg/NetworkCommon/PxeFunction.c >> b/UsbNetworkPkg/NetworkCommon/PxeFunction.c >> new file mode 100644 >> index 0000000000..d34b61a69f >> --- /dev/null >> +++ b/UsbNetworkPkg/NetworkCommon/PxeFunction.c >> @@ -0,0 +1,1734 @@ >> +/** @file >> >> + This file contains code for UNDI command based on UEFI specification. >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#include "DriverBinding.h" >> >> + >> >> +// API table, defined in UEFI specification >> >> +API_FUNC gUndiApiTable[] = { >> >> + UndiGetState, >> >> + UndiStart, >> >> + UndiStop, >> >> + UndiGetInitInfo, >> >> + UndiGetConfigInfo, >> >> + UndiInitialize, >> >> + UndiReset, >> >> + UndiShutdown, >> >> + UndiInterruptEnable, >> >> + UndiReceiveFilter, >> >> + UndiStationAddress, >> >> + UndiStatistics, >> >> + UndiMcastIp2Mac, >> >> + UndiNvData, >> >> + UndiGetStatus, >> >> + UndiFillHeader, >> >> + UndiTransmit, >> >> + UndiReceive >> >> +}; >> >> + >> >> +/** >> >> + This command is used to determine the operational state of the UNDI. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiGetState ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode != PXE_OPCODE_GET_STATE) || >> >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) || >> >> + (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED) || >> >> + (Cdb->DBsize != PXE_DBSIZE_NOT_USED) || >> >> + (Cdb->DBaddr != PXE_DBADDR_NOT_USED) || >> >> + (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED)) >> >> + { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + Cdb->StatFlags = Cdb->StatFlags | Nic->State; >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetState != NULL) { >> >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiGetState (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This command is used to change the UNDI operational state from stopped >> to started. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiStart ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + PXE_CPB_START_31 *Cpb; >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode != PXE_OPCODE_START) || >> >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize != sizeof (PXE_CPB_START_31)) || >> >> + (Cdb->DBsize != PXE_DBSIZE_NOT_USED) || >> >> + (Cdb->DBaddr != PXE_DBADDR_NOT_USED) || >> >> + (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED)) >> >> + { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + if (Nic->State != PXE_STATFLAGS_GET_STATE_STOPPED) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_ALREADY_STARTED; >> >> + return; >> >> + } >> >> + >> >> + Cpb = (PXE_CPB_START_31 *)(UINTN)Cdb->CPBaddr; >> >> + >> >> + Nic->PxeStart.Delay = Cpb->Delay; >> >> + Nic->PxeStart.Virt2Phys = Cpb->Virt2Phys; >> >> + Nic->PxeStart.Block = Cpb->Block; >> >> + Nic->PxeStart.Map_Mem = 0; >> >> + Nic->PxeStart.UnMap_Mem = 0; >> >> + Nic->PxeStart.Sync_Mem = Cpb->Sync_Mem; >> >> + Nic->PxeStart.Unique_ID = Cpb->Unique_ID; >> >> + Nic->State = PXE_STATFLAGS_GET_STATE_STARTED; >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStart != NULL) { >> >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiStart (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This command is used to change the UNDI operational state from started >> to stopped. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiStop ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode != PXE_OPCODE_STOP) || >> >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) || >> >> + (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED) || >> >> + (Cdb->DBsize != PXE_DBSIZE_NOT_USED) || >> >> + (Cdb->DBaddr != PXE_DBADDR_NOT_USED) || >> >> + (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED)) >> >> + { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + if (Nic->State == PXE_STATFLAGS_GET_STATE_STOPPED) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_NOT_STARTED; >> >> + return; >> >> + } >> >> + >> >> + if (Nic->State == PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_NOT_SHUTDOWN; >> >> + return; >> >> + } >> >> + >> >> + Nic->PxeStart.Delay = 0; >> >> + Nic->PxeStart.Virt2Phys = 0; >> >> + Nic->PxeStart.Block = 0; >> >> + Nic->PxeStart.Map_Mem = 0; >> >> + Nic->PxeStart.UnMap_Mem = 0; >> >> + Nic->PxeStart.Sync_Mem = 0; >> >> + Nic->State = PXE_STATFLAGS_GET_STATE_STOPPED; >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStop != NULL) { >> >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiStop (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This command is used to retrieve initialization information that is >> >> + needed by drivers and applications to initialized UNDI. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiGetInitInfo ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + PXE_DB_GET_INIT_INFO *Db; >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode != PXE_OPCODE_GET_INIT_INFO) || >> >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) || >> >> + (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED) || >> >> + (Cdb->DBsize != sizeof (PXE_DB_GET_INIT_INFO)) || >> >> + (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED)) >> >> + { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + if (Nic->State == PXE_STATFLAGS_GET_STATE_STOPPED) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_NOT_STARTED; >> >> + return; >> >> + } >> >> + >> >> + Db = (PXE_DB_GET_INIT_INFO *)(UINTN)Cdb->DBaddr; >> >> + >> >> + Db->MemoryRequired = MEMORY_REQUIRE; >> >> + Db->FrameDataLen = PXE_MAX_TXRX_UNIT_ETHER; >> >> + Db->LinkSpeeds[0] = 10; >> >> + Db->LinkSpeeds[1] = 100; >> >> + Db->LinkSpeeds[2] = 1000; >> >> + Db->LinkSpeeds[3] = 0; >> >> + Db->MediaHeaderLen = PXE_MAC_HEADER_LEN_ETHER; >> >> + Db->HWaddrLen = PXE_HWADDR_LEN_ETHER; >> >> + Db->MCastFilterCnt = MAX_MCAST_ADDRESS_CNT; >> >> + Db->TxBufCnt = Nic->PxeInit.TxBufCnt; >> >> + Db->TxBufSize = Nic->PxeInit.TxBufSize; >> >> + Db->RxBufCnt = Nic->PxeInit.RxBufCnt; >> >> + Db->RxBufSize = Nic->PxeInit.RxBufSize; >> >> + Db->IFtype = PXE_IFTYPE_ETHERNET; >> >> + Db->SupportedDuplexModes = PXE_DUPLEX_DEFAULT; >> >> + Db->SupportedLoopBackModes = LOOPBACK_NORMAL; >> >> + >> >> + Cdb->StatFlags |= (PXE_STATFLAGS_CABLE_DETECT_SUPPORTED | >> >> + PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED); >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetInitInfo != NULL) { >> >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiGetInitInfo (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This command is used to retrieve configuration information about >> >> + the NIC being controlled by the UNDI. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiGetConfigInfo ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + PXE_DB_GET_CONFIG_INFO *Db; >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode != PXE_OPCODE_GET_CONFIG_INFO) || >> >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) || >> >> + (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED) || >> >> + (Cdb->DBsize != sizeof (PXE_DB_GET_CONFIG_INFO)) || >> >> + (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED)) >> >> + { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + if (Nic->State == PXE_STATFLAGS_GET_STATE_STOPPED) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_NOT_STARTED; >> >> + return; >> >> + } >> >> + >> >> + Db = (PXE_DB_GET_CONFIG_INFO *)(UINTN)Cdb->DBaddr; >> >> + >> >> + Db->pci.BusType = PXE_BUSTYPE_USB; >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetConfigInfo != NULL) { >> >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiGetConfigInfo (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This command resets the network adapter and initializes UNDI using >> >> + the parameters supplied in the CPB. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in, out] Nic A pointer to the Network interface controller >> data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiInitialize ( >> >> + IN PXE_CDB *Cdb, >> >> + IN OUT NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + PXE_CPB_INITIALIZE *Cpb; >> >> + PXE_DB_INITIALIZE *Db; >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode != PXE_OPCODE_INITIALIZE) || >> >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize != sizeof (PXE_CPB_INITIALIZE))) >> >> + { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + } >> >> + >> >> + if (Nic->State == PXE_STATFLAGS_GET_STATE_STOPPED) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_NOT_STARTED; >> >> + return; >> >> + } >> >> + >> >> + if ((Cdb->OpFlags != PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) && >> >> + (Cdb->OpFlags != PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE)) >> >> + { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } >> >> + >> >> + if (Nic->State == PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_ALREADY_INITIALIZED; >> >> + return; >> >> + } >> >> + >> >> + Cpb = (PXE_CPB_INITIALIZE *)(UINTN)Cdb->CPBaddr; >> >> + Db = (PXE_DB_INITIALIZE *)(UINTN)Cdb->DBaddr; >> >> + >> >> + Nic->PxeInit.LinkSpeed = Cpb->LinkSpeed; >> >> + Nic->PxeInit.DuplexMode = Cpb->DuplexMode; >> >> + Nic->PxeInit.LoopBackMode = Cpb->LoopBackMode; >> >> + Nic->PxeInit.MemoryAddr = Cpb->MemoryAddr; >> >> + Nic->PxeInit.MemoryLength = Cpb->MemoryLength; >> >> + Nic->PxeInit.TxBufCnt = TX_BUFFER_COUNT; >> >> + Nic->PxeInit.TxBufSize = Nic->MaxSegmentSize; >> >> + Nic->PxeInit.RxBufCnt = RX_BUFFER_COUNT; >> >> + Nic->PxeInit.RxBufSize = Nic->MaxSegmentSize; >> >> + >> >> + Cdb->StatCode = Initialize (Cdb, Nic); >> >> + >> >> + Db->MemoryUsed = MEMORY_REQUIRE; >> >> + Db->TxBufCnt = Nic->PxeInit.TxBufCnt; >> >> + Db->TxBufSize = Nic->PxeInit.TxBufSize; >> >> + Db->RxBufCnt = Nic->PxeInit.RxBufCnt; >> >> + Db->RxBufSize = Nic->PxeInit.RxBufSize; >> >> + >> >> + Nic->RxFilter = PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST; >> >> + Nic->CanReceive = FALSE; >> >> + Nic->CanTransmit = FALSE; >> >> + >> >> + if (Cdb->OpFlags == PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) { >> >> + if ((Nic->Request.Request == USB_CDC_NETWORK_CONNECTION) && >> (Nic->Request.Value == NETWORK_DISCONNECT)) { >> >> + Nic->CableDetect = 0; >> >> + } else if ((Nic->Request.Request == USB_CDC_NETWORK_CONNECTION) && >> (Nic->Request.Value == NETWORK_CONNECTED)) { >> >> + Nic->CableDetect = 1; >> >> + } >> >> + >> >> + if (Nic->CableDetect == 0) { >> >> + Cdb->StatFlags |= PXE_STATFLAGS_INITIALIZED_NO_MEDIA; >> >> + } >> >> + } >> >> + >> >> + if (Cdb->StatCode != PXE_STATCODE_SUCCESS) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + } else { >> >> + Nic->State = PXE_STATFLAGS_GET_STATE_INITIALIZED; >> >> + } >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiInitialize != NULL) { >> >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiInitialize (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + Initialize Network interface controller data. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in, out] Nic A pointer to the Network interface controller >> data. >> >> + >> >> + @retval Status A value of Pxe statcode. >> >> + >> >> +**/ >> >> +UINT16 >> >> +Initialize ( >> >> + IN PXE_CDB *Cdb, >> >> + IN OUT NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + UINTN Status; >> >> + UINT32 Index; >> >> + EFI_STATUS EfiStatus; >> >> + >> >> + Status = MapIt ( >> >> + Nic, >> >> + Nic->PxeInit.MemoryAddr, >> >> + Nic->PxeInit.MemoryLength, >> >> + TO_AND_FROM_DEVICE, >> >> + (UINT64)(UINTN)&Nic->MappedAddr >> >> + ); >> >> + >> >> + if (Status != 0) { >> >> + return (UINT16)Status; >> >> + } >> >> + >> >> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> >> + Nic->PermNodeAddress[Index] = Nic->MacAddr.Addr[Index]; >> >> + } >> >> + >> >> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> >> + Nic->CurrentNodeAddress[Index] = Nic->PermNodeAddress[Index]; >> >> + } >> >> + >> >> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> >> + Nic->BroadcastNodeAddress[Index] = 0xFF; >> >> + } >> >> + >> >> + for (Index = PXE_HWADDR_LEN_ETHER; Index < PXE_MAC_LENGTH; Index++) { >> >> + Nic->CurrentNodeAddress[Index] = 0; >> >> + Nic->PermNodeAddress[Index] = 0; >> >> + Nic->BroadcastNodeAddress[Index] = 0; >> >> + } >> >> + >> >> + if (Nic->UsbEth->UsbEthInitialize != NULL) { >> >> + EfiStatus = Nic->UsbEth->UsbEthInitialize (Cdb, Nic); >> >> + if (EFI_ERROR (EfiStatus)) { >> >> + return PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> + >> >> + return (UINT16)Status; >> >> +} >> >> + >> >> +/** >> >> + This command resets the network adapter and reinitializes the UNDI >> >> + with the same parameters provided in the Initialize command. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiReset ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode != PXE_OPCODE_RESET) || >> >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) || >> >> + (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED) || >> >> + (Cdb->DBsize != PXE_DBSIZE_NOT_USED) || >> >> + (Cdb->DBaddr != PXE_DBADDR_NOT_USED)) >> >> + { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> >> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED; >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + return; >> >> + } >> >> + >> >> + if ((Cdb->OpFlags != PXE_OPFLAGS_NOT_USED) && >> >> + (Cdb->OpFlags != PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS) && >> >> + (Cdb->OpFlags != PXE_OPFLAGS_RESET_DISABLE_FILTERS)) >> >> + { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } >> >> + >> >> + if ((Cdb->OpFlags & PXE_OPFLAGS_RESET_DISABLE_FILTERS) == 0) { >> >> + Nic->RxFilter = PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST; >> >> + } >> >> + >> >> + if ((Cdb->OpFlags & PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS) != 0) { >> >> + Nic->InterrupOpFlag = 0; >> >> + } >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiReset != NULL) { >> >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiReset (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + The Shutdown command resets the network adapter and leaves it in a >> >> + safe state for another driver to initialize. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in, out] Nic A pointer to the Network interface controller >> data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiShutdown ( >> >> + IN PXE_CDB *Cdb, >> >> + IN OUT NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode != PXE_OPCODE_SHUTDOWN) || >> >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) || >> >> + (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED) || >> >> + (Cdb->DBsize != PXE_DBSIZE_NOT_USED) || >> >> + (Cdb->DBaddr != PXE_DBADDR_NOT_USED) || >> >> + (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED)) >> >> + { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> >> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED; >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + return; >> >> + } >> >> + >> >> + Nic->CanReceive = FALSE; >> >> + Nic->CanTransmit = FALSE; >> >> + >> >> + Nic->State = PXE_STATFLAGS_GET_STATE_STARTED; >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiShutdown != NULL) { >> >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiShutdown (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED; >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + The Interrupt Enables command can be used to read and/or change >> >> + the current external interrupt enable settings. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiInterruptEnable ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + >> >> + Cdb->StatCode = PXE_STATCODE_UNSUPPORTED; >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiInterruptEnable != NULL) { >> >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiInterruptEnable (Cdb, >> Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + } else { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This command is used to read and change receive filters and, >> >> + if supported, read and change the multicast MAC address filter list. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiReceiveFilter ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + UINT16 NewFilter; >> >> + PXE_DB_RECEIVE_FILTERS *Db; >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode != PXE_OPCODE_RECEIVE_FILTERS) || >> >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8))) >> >> + { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> >> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED; >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + return; >> >> + } >> >> + >> >> + NewFilter = (UINT16)(Cdb->OpFlags & 0x1F); >> >> + >> >> + switch (Cdb->OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_OPMASK) { >> >> + case PXE_OPFLAGS_RECEIVE_FILTER_READ: >> >> + if (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> >> + } >> >> + >> >> + if ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) == >> 0) { >> >> + if ((Cdb->DBsize != 0)) { >> >> + Db = (PXE_DB_RECEIVE_FILTERS *)(UINTN)Cdb->DBaddr; >> >> + CopyMem (Db, &Nic->McastList, Nic->McastCount); >> >> + } >> >> + } >> >> + >> >> + break; >> >> + >> >> + case PXE_OPFLAGS_RECEIVE_FILTER_ENABLE: >> >> + if (NewFilter == 0) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + >> >> + if (Cdb->CPBsize != 0) { >> >> + if (((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) >> == 0) || >> >> + ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) >> != 0) || >> >> + ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) != >> 0) || >> >> + ((Cdb->CPBsize % sizeof (PXE_MAC_ADDR)) != 0)) >> >> + { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> + >> >> + if ((Cdb->OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) >> != 0) { >> >> + if (((Cdb->OpFlags & >> PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) != 0) || >> >> + ((Cdb->OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) >> != 0)) >> >> + { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + >> >> + if ((Cdb->CPBsize == 0)) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> + >> >> + Cdb->StatCode = Setfilter (Nic, NewFilter, Cdb->CPBaddr, >> Cdb->CPBsize); >> >> + break; >> >> + >> >> + case PXE_OPFLAGS_RECEIVE_FILTER_DISABLE: >> >> + if (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> >> + } >> >> + >> >> + Nic->CanReceive = TRUE; >> >> + break; >> >> + >> >> + default: >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> >> + } >> >> + >> >> + if (Nic->CanReceive) { >> >> + Cdb->StatFlags = (PXE_STATFLAGS)(Cdb->StatFlags | Nic->RxFilter); >> >> + } >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiReceiveFilter != NULL) { >> >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiReceiveFilter (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + Set PXE receive filter. >> >> + >> >> + @param[in] Nic A pointer to the Network interface controller >> data. >> >> + @param[in] SetFilter PXE receive filter >> >> + @param[in] CpbAddr Command Parameter Block Address >> >> + @param[in] CpbSize Command Parameter Block Size >> >> + >> >> +**/ >> >> +UINT16 >> >> +Setfilter ( >> >> + IN NIC_DATA *Nic, >> >> + IN UINT16 SetFilter, >> >> + IN UINT64 CpbAddr, >> >> + IN UINT32 CpbSize >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINT8 *McastList; >> >> + UINT8 Count = 0; >> >> + UINT8 Index1; >> >> + UINT8 Index2; >> >> + PXE_CPB_RECEIVE_FILTERS *Cpb = (PXE_CPB_RECEIVE_FILTERS >> *)(UINTN)CpbAddr; >> >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; >> >> + >> >> + // The Cpb could be NULL.(ref:PXE_CPBADDR_NOT_USED) >> >> + Nic->RxFilter = (UINT8)SetFilter; >> >> + >> >> + if (((SetFilter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) != 0) >> || (Cpb != NULL)) { >> >> + if (Cpb != NULL) { >> >> + Nic->McastCount = (UINT8)(CpbSize / PXE_MAC_LENGTH); >> >> + CopyMem (&Nic->McastList, Cpb, Nic->McastCount); >> >> + } >> >> + >> >> + if (Nic->CanReceive) { >> >> + Nic->CanReceive = FALSE; >> >> + } >> >> + >> >> + Nic->UsbEth->UsbEthFunDescriptor (Nic->UsbEth, &UsbEthFunDescriptor); >> >> + if ((UsbEthFunDescriptor.NumberMcFilters << 1) == 0) { >> >> + Nic->RxFilter |= PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST; >> >> + Nic->UsbEth->SetUsbEthPacketFilter (Nic->UsbEth, Nic->RxFilter); >> >> + } else { >> >> + Status = gBS->AllocatePool (EfiBootServicesData, Nic->McastCount * >> 6, (VOID **)&McastList); >> >> + if (EFI_ERROR (Status)) { >> >> + return PXE_STATCODE_INVALID_PARAMETER; >> >> + } >> >> + >> >> + if (Cpb != NULL) { >> >> + for (Index1 = 0; Index1 < Nic->McastCount; Index1++) { >> >> + for (Index2 = 0; Index2 < 6; Index2++) { >> >> + McastList[Count++] = Cpb->MCastList[Index1][Index2]; >> >> + } >> >> + } >> >> + } >> >> + >> >> + Nic->RxFilter |= PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST; >> >> + if (Cpb != NULL) { >> >> + Nic->UsbEth->SetUsbEthMcastFilter (Nic->UsbEth, Nic->McastCount, >> McastList); >> >> + } >> >> + >> >> + Nic->UsbEth->SetUsbEthPacketFilter (Nic->UsbEth, Nic->RxFilter); >> >> + gBS->FreePool (McastList); >> >> + } >> >> + } >> >> + >> >> + return PXE_STATCODE_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This command is used to get current station and broadcast MAC addresses >> >> + and, if supported, to change the current station MAC address. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiStationAddress ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + PXE_CPB_STATION_ADDRESS *Cpb; >> >> + PXE_DB_STATION_ADDRESS *Db; >> >> + UINT16 Index; >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode != PXE_OPCODE_STATION_ADDRESS) || >> >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->DBsize != sizeof (PXE_DB_STATION_ADDRESS))) >> >> + { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> >> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED; >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + return; >> >> + } >> >> + >> >> + if (Cdb->OpFlags == PXE_OPFLAGS_STATION_ADDRESS_RESET) { >> >> + if (CompareMem (&Nic->CurrentNodeAddress[0], >> &Nic->PermNodeAddress[0], PXE_MAC_LENGTH) != 0) { >> >> + for (Index = 0; Index < PXE_MAC_LENGTH; Index++) { >> >> + Nic->CurrentNodeAddress[Index] = Nic->PermNodeAddress[Index]; >> >> + } >> >> + } >> >> + } >> >> + >> >> + if (Cdb->CPBaddr != 0) { >> >> + Cpb = (PXE_CPB_STATION_ADDRESS *)(UINTN)Cdb->CPBaddr; >> >> + for (Index = 0; Index < PXE_MAC_LENGTH; Index++) { >> >> + Nic->CurrentNodeAddress[Index] = Cpb->StationAddr[Index]; >> >> + } >> >> + } >> >> + >> >> + if (Cdb->DBaddr != 0) { >> >> + Db = (PXE_DB_STATION_ADDRESS *)(UINTN)Cdb->DBaddr; >> >> + for (Index = 0; Index < PXE_MAC_LENGTH; Index++) { >> >> + Db->StationAddr[Index] = Nic->CurrentNodeAddress[Index]; >> >> + Db->BroadcastAddr[Index] = Nic->BroadcastNodeAddress[Index]; >> >> + Db->PermanentAddr[Index] = Nic->PermNodeAddress[Index]; >> >> + } >> >> + } >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStationAddress != NULL) { >> >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiStationAddress (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This command is used to read and clear the NIC traffic statistics. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiStatistics ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode != PXE_OPCODE_STATISTICS) || >> >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) || >> >> + (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED)) >> >> + { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + } >> >> + >> >> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> >> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED; >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + return; >> >> + } >> >> + >> >> + if ((Cdb->OpFlags != PXE_OPFLAGS_STATISTICS_RESET) && >> >> + (Cdb->OpFlags != PXE_OPFLAGS_STATISTICS_READ)) >> >> + { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } >> >> + >> >> + Cdb->StatCode = Statistics (Nic, Cdb->DBaddr, Cdb->DBsize); >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStatistics != NULL) { >> >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiStatistics (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + Return data for DB data. >> >> + >> >> + @param[in] Nic A pointer to the Network interface controller >> data. >> >> + @param[in] DbAddr Data Block Address. >> >> + @param[in] DbSize Data Block Size. >> >> + >> >> +**/ >> >> +UINT16 >> >> +Statistics ( >> >> + IN NIC_DATA *Nic, >> >> + IN UINT64 DbAddr, >> >> + IN UINT16 DbSize >> >> + ) >> >> +{ >> >> + PXE_DB_STATISTICS *DbStatistic; >> >> + EFI_STATUS Status; >> >> + >> >> + DbStatistic = (PXE_DB_STATISTICS *)(UINTN)DbAddr; >> >> + >> >> + if (DbSize == 0) { >> >> + return PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + DbStatistic->Supported = 0x802; >> >> + DbStatistic->Data[0x01] = Nic->RxFrame; >> >> + DbStatistic->Data[0x0B] = Nic->TxFrame; >> >> + >> >> + if (Nic->UsbEth->UsbEthStatistics != NULL) { >> >> + Status = Nic->UsbEth->UsbEthStatistics (Nic, DbAddr, DbSize); >> >> + if (EFI_ERROR (Status)) { >> >> + return PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> + >> >> + return PXE_STATCODE_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + Translate a multicast IPv4 or IPv6 address to a multicast MAC address. >> >> + >> >> + @param[in, out] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller >> data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiMcastIp2Mac ( >> >> + IN OUT PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + PXE_CPB_MCAST_IP_TO_MAC *Cpb; >> >> + PXE_DB_MCAST_IP_TO_MAC *Db; >> >> + UINT8 *Tmp; >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode != PXE_OPCODE_MCAST_IP_TO_MAC) || >> >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize != sizeof (PXE_CPB_MCAST_IP_TO_MAC)) || >> >> + (Cdb->DBsize != sizeof (PXE_DB_MCAST_IP_TO_MAC))) >> >> + { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> >> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED; >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + return; >> >> + } >> >> + >> >> + Cpb = (PXE_CPB_MCAST_IP_TO_MAC *)(UINTN)Cdb->CPBaddr; >> >> + Db = (PXE_DB_MCAST_IP_TO_MAC *)(UINTN)Cdb->DBaddr; >> >> + >> >> + if ((Cdb->OpFlags & PXE_OPFLAGS_MCAST_IPV6_TO_MAC) != 0) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_UNSUPPORTED; >> >> + return; >> >> + } >> >> + >> >> + Tmp = (UINT8 *)(&Cpb->IP.IPv4); >> >> + >> >> + if ((Tmp[0] & 0xF0) != 0xE0) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CPB; >> >> + } >> >> + >> >> + Db->MAC[0] = 0x01; >> >> + Db->MAC[1] = 0x00; >> >> + Db->MAC[2] = 0x5E; >> >> + Db->MAC[3] = Tmp[1] & 0x7F; >> >> + Db->MAC[4] = Tmp[2]; >> >> + Db->MAC[5] = Tmp[3]; >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiMcastIp2Mac != NULL) { >> >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiMcastIp2Mac (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This command is used to read and write (if supported by NIC H/W) >> >> + nonvolatile storage on the NIC. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiNvData ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + >> >> + Cdb->StatCode = PXE_STATCODE_UNSUPPORTED; >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiNvData != NULL) { >> >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiNvData (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + } else { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This command returns the current interrupt status and/or the >> >> + transmitted buffer addresses and the current media status. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiGetStatus ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + PXE_DB_GET_STATUS *Db; >> >> + PXE_DB_GET_STATUS TmpGetStatus; >> >> + UINT16 NumEntries; >> >> + UINTN Index; >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode != PXE_OPCODE_GET_STATUS) || >> >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) || >> >> + (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED)) >> >> + { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> >> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED; >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + return; >> >> + } >> >> + >> >> + TmpGetStatus.RxFrameLen = 0; >> >> + TmpGetStatus.reserved = 0; >> >> + Db = (PXE_DB_GET_STATUS *)(UINTN)Cdb->DBaddr; >> >> + >> >> + if ((Cdb->DBsize > 0) && (Cdb->DBsize < sizeof (UINT32) * 2)) { >> >> + CopyMem (Db, &TmpGetStatus, Cdb->DBsize); >> >> + } else { >> >> + CopyMem (Db, &TmpGetStatus, sizeof (UINT32) * 2); >> >> + } >> >> + >> >> + if ((Cdb->OpFlags & PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS) != 0) { >> >> + if (Cdb->DBsize == 0) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } >> >> + >> >> + NumEntries = Cdb->DBsize - sizeof (UINT64); >> >> + Cdb->DBsize = sizeof (UINT32) * 2; >> >> + >> >> + for (Index = 0; NumEntries >= sizeof (UINT64); Index++, NumEntries >> -= sizeof (UINT64)) { >> >> + if (Nic->TxBufferCount > 0) { >> >> + Nic->TxBufferCount--; >> >> + Db->TxBuffer[Index] = Nic->MediaHeader[Nic->TxBufferCount]; >> >> + } >> >> + } >> >> + } >> >> + >> >> + if ((Cdb->OpFlags & PXE_OPFLAGS_GET_INTERRUPT_STATUS) != 0) { >> >> + if (Nic->ReceiveStatus != 0) { >> >> + Cdb->StatFlags |= PXE_STATFLAGS_GET_STATUS_RECEIVE; >> >> + } >> >> + } >> >> + >> >> + if ((Nic->Request.Request == USB_CDC_NETWORK_CONNECTION) && >> (Nic->Request.Value == NETWORK_DISCONNECT)) { >> >> + Nic->CableDetect = 0; >> >> + } else if ((Nic->Request.Request == USB_CDC_NETWORK_CONNECTION) && >> (Nic->Request.Value == NETWORK_CONNECTED)) { >> >> + Nic->CableDetect = 1; >> >> + } >> >> + >> >> + if ((Cdb->OpFlags & PXE_OPFLAGS_GET_MEDIA_STATUS) != 0) { >> >> + if (Nic->CableDetect == 0) { >> >> + Cdb->StatFlags |= PXE_STATFLAGS_GET_STATUS_NO_MEDIA; >> >> + } >> >> + } >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetStatus != NULL) { >> >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiGetStatus (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This command is used to fill the media header(s) in transmit packet(s). >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiFillHeader ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + PXE_CPB_FILL_HEADER *CpbFillHeader; >> >> + PXE_CPB_FILL_HEADER_FRAGMENTED *CpbFill; >> >> + EthernetHeader *MacHeader; >> >> + UINTN Index; >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode != PXE_OPCODE_FILL_HEADER) || >> >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize != sizeof (PXE_CPB_FILL_HEADER_FRAGMENTED)) || >> >> + (Cdb->DBsize != PXE_DBSIZE_NOT_USED) || >> >> + (Cdb->DBaddr != PXE_DBADDR_NOT_USED)) >> >> + { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> >> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED; >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + return; >> >> + } >> >> + >> >> + if (Cdb->CPBsize == PXE_CPBSIZE_NOT_USED) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } >> >> + >> >> + if ((Cdb->OpFlags & PXE_OPFLAGS_FILL_HEADER_FRAGMENTED) != 0) { >> >> + CpbFill = (PXE_CPB_FILL_HEADER_FRAGMENTED *)(UINTN)Cdb->CPBaddr; >> >> + >> >> + if ((CpbFill->FragCnt == 0) || (CpbFill->FragDesc[0].FragLen < >> PXE_MAC_HEADER_LEN_ETHER)) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } >> >> + >> >> + MacHeader = (EthernetHeader >> *)(UINTN)CpbFill->FragDesc[0].FragAddr; >> >> + MacHeader->Protocol = CpbFill->Protocol; >> >> + >> >> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> >> + MacHeader->DestAddr[Index] = CpbFill->DestAddr[Index]; >> >> + MacHeader->SrcAddr[Index] = CpbFill->SrcAddr[Index]; >> >> + } >> >> + } else { >> >> + CpbFillHeader = (PXE_CPB_FILL_HEADER *)(UINTN)Cdb->CPBaddr; >> >> + >> >> + MacHeader = (EthernetHeader >> *)(UINTN)CpbFillHeader->MediaHeader; >> >> + MacHeader->Protocol = CpbFillHeader->Protocol; >> >> + >> >> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> >> + MacHeader->DestAddr[Index] = CpbFillHeader->DestAddr[Index]; >> >> + MacHeader->SrcAddr[Index] = CpbFillHeader->SrcAddr[Index]; >> >> + } >> >> + } >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiFillHeader != NULL) { >> >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiFillHeader (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + The Transmit command is used to place a packet into the transmit queue. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiTransmit ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode != PXE_OPCODE_TRANSMIT) || >> >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize != sizeof (PXE_CPB_TRANSMIT)) || >> >> + (Cdb->DBsize != PXE_DBSIZE_NOT_USED) || >> >> + (Cdb->DBaddr != PXE_DBADDR_NOT_USED)) >> >> + { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED; >> >> + return; >> >> + } >> >> + >> >> + if (Cdb->CPBsize == PXE_CPBSIZE_NOT_USED) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiTransmit != NULL) { >> >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiTransmit (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + >> >> + return; >> >> + } >> >> + >> >> + Cdb->StatCode = Transmit (Cdb, Nic, Cdb->CPBaddr, Cdb->OpFlags); >> >> + >> >> + if (Cdb->StatCode != PXE_STATCODE_SUCCESS) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> +} >> >> + >> >> +/** >> >> + Use USB Ethernet Protocol Bulk out command to transmit data. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in, out] Nic A pointer to the Network interface controller >> data. >> >> + @param[in] CpbAddr Command Parameter Block Address. >> >> + @param[in] OpFlags Operation Flags. >> >> + >> >> +**/ >> >> +UINT16 >> >> +Transmit ( >> >> + IN PXE_CDB *Cdb, >> >> + IN OUT NIC_DATA *Nic, >> >> + IN UINT64 CpbAddr, >> >> + IN UINT16 OpFlags >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + PXE_CPB_TRANSMIT *Cpb; >> >> + UINT64 BulkOutData = 0; >> >> + UINTN DataLength; >> >> + UINTN Map; >> >> + UINT32 Counter = 0; >> >> + UINT16 StatCode; >> >> + >> >> + Cpb = (PXE_CPB_TRANSMIT *)(UINTN)CpbAddr; >> >> + >> >> + if (Nic->CanTransmit) { >> >> + return PXE_STATCODE_BUSY; >> >> + } >> >> + >> >> + Nic->CanTransmit = TRUE; >> >> + >> >> + if ((OpFlags & PXE_OPFLAGS_TRANSMIT_FRAGMENTED) != 0) { >> >> + return PXE_STATCODE_INVALID_PARAMETER; >> >> + } >> >> + >> >> + Map = MapIt ( >> >> + Nic, >> >> + Cpb->FrameAddr, >> >> + Cpb->DataLen + (UINT32)Cpb->MediaheaderLen, >> >> + TO_DEVICE, >> >> + (UINT64)(UINTN)&BulkOutData >> >> + ); >> >> + >> >> + if (Map != 0) { >> >> + Nic->CanTransmit = FALSE; >> >> + return PXE_STATCODE_INVALID_PARAMETER; >> >> + } >> >> + >> >> + if (Nic->TxBufferCount < MAX_XMIT_BUFFERS) { >> >> + Nic->MediaHeader[Nic->TxBufferCount] = Cpb->FrameAddr; >> >> + Nic->TxBufferCount++; >> >> + } >> >> + >> >> + DataLength = (UINTN)(Cpb->DataLen + (UINT32)Cpb->MediaheaderLen); >> >> + >> >> + while (1) { >> >> + if (Counter >= 3) { >> >> + StatCode = PXE_STATCODE_BUSY; >> >> + break; >> >> + } >> >> + >> >> + Status = Nic->UsbEth->UsbEthTransmit (Cdb, Nic->UsbEth, (VOID >> *)(UINTN)BulkOutData, &DataLength); >> >> + if (EFI_ERROR (Status)) { >> >> + StatCode = PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + >> >> + if (Status == EFI_INVALID_PARAMETER) { >> >> + StatCode = PXE_STATCODE_INVALID_PARAMETER; >> >> + break; >> >> + } >> >> + >> >> + if (Status == EFI_DEVICE_ERROR) { >> >> + StatCode = PXE_STATCODE_DEVICE_FAILURE; >> >> + break; >> >> + } >> >> + >> >> + if (!EFI_ERROR (Status)) { >> >> + Nic->TxFrame++; >> >> + StatCode = PXE_STATCODE_SUCCESS; >> >> + break; >> >> + } >> >> + >> >> + Counter++; >> >> + } >> >> + >> >> + UnMapIt ( >> >> + Nic, >> >> + Cpb->FrameAddr, >> >> + Cpb->DataLen + (UINT32)Cpb->MediaheaderLen, >> >> + TO_DEVICE, >> >> + BulkOutData >> >> + ); >> >> + >> >> + Nic->CanTransmit = FALSE; >> >> + >> >> + return StatCode; >> >> +} >> >> + >> >> +/** >> >> + When the network adapter has received a frame, this command is used >> >> + to copy the frame into driver/application storage. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiReceive ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + >> >> + if ((Cdb->OpCode != PXE_OPCODE_RECEIVE) || >> >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> >> + (Cdb->CPBsize != sizeof (PXE_CPB_RECEIVE)) || >> >> + (Cdb->DBsize != sizeof (PXE_DB_RECEIVE)) || >> >> + (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED)) >> >> + { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> >> + return; >> >> + } else { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> >> + } >> >> + >> >> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED; >> >> + return; >> >> + } >> >> + >> >> + if (!Nic->CanReceive) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED; >> >> + return; >> >> + } >> >> + >> >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiReceive != NULL) { >> >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiReceive (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> + >> >> + return; >> >> + } >> >> + >> >> + Cdb->StatCode = Receive (Cdb, Nic, Cdb->CPBaddr, Cdb->DBaddr); >> >> + >> >> + if (Cdb->StatCode != PXE_STATCODE_SUCCESS) { >> >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> >> + } >> >> +} >> >> + >> >> +/** >> >> + Use USB Ethernet Protocol Bulk in command to receive data. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in, out] Nic A pointer to the Network interface controller >> data. >> >> + @param[in] CpbAddr Command Parameter Block Address. >> >> + @param[in, out] DbAddr Data Block Address. >> >> + >> >> +**/ >> >> +UINT16 >> >> +Receive ( >> >> + IN PXE_CDB *Cdb, >> >> + IN OUT NIC_DATA *Nic, >> >> + IN UINT64 CpbAddr, >> >> + IN OUT UINT64 DbAddr >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINTN Index; >> >> + UINT16 StatCode = PXE_STATCODE_NO_DATA; >> >> + PXE_FRAME_TYPE FrameType = PXE_FRAME_TYPE_NONE; >> >> + PXE_CPB_RECEIVE *Cpb; >> >> + PXE_DB_RECEIVE *Db; >> >> + UINT8 *BulkInData; >> >> + UINTN DataLength = (UINTN)Nic->MaxSegmentSize; >> >> + EthernetHeader *Header; >> >> + >> >> + Cpb = (PXE_CPB_RECEIVE *)(UINTN)CpbAddr; >> >> + Db = (PXE_DB_RECEIVE *)(UINTN)DbAddr; >> >> + >> >> + Status = gBS->AllocatePool (EfiBootServicesData, DataLength, (VOID >> **)&BulkInData); >> >> + if (EFI_ERROR (Status)) { >> >> + return PXE_STATCODE_INVALID_PARAMETER; >> >> + } >> >> + >> >> + while (1) { >> >> + Status = Nic->UsbEth->UsbEthReceive (Cdb, Nic->UsbEth, (VOID >> *)BulkInData, &DataLength); >> >> + if (EFI_ERROR (Status)) { >> >> + break; >> >> + } >> >> + >> >> + Nic->RxFrame++; >> >> + >> >> + if (DataLength != 0) { >> >> + if (DataLength > Cpb->BufferLen) { >> >> + DataLength = (UINTN)Cpb->BufferLen; >> >> + } >> >> + >> >> + CopyMem ((UINT8 *)(UINTN)Cpb->BufferAddr, (UINT8 *)BulkInData, >> DataLength); >> >> + >> >> + Header = (EthernetHeader *)BulkInData; >> >> + >> >> + Db->FrameLen = (UINT32)DataLength; >> >> + Db->MediaHeaderLen = PXE_MAC_HEADER_LEN_ETHER; >> >> + >> >> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> >> + if (Header->DestAddr[Index] != Nic->CurrentNodeAddress[Index]) { >> >> + break; >> >> + } >> >> + } >> >> + >> >> + if (Index >= PXE_HWADDR_LEN_ETHER) { >> >> + FrameType = PXE_FRAME_TYPE_UNICAST; >> >> + } else { >> >> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> >> + if (Header->DestAddr[Index] != >> Nic->BroadcastNodeAddress[Index]) { >> >> + break; >> >> + } >> >> + } >> >> + >> >> + if (Index >= PXE_HWADDR_LEN_ETHER) { >> >> + FrameType = PXE_FRAME_TYPE_BROADCAST; >> >> + } else { >> >> + if ((Header->DestAddr[0] & 1) == 1) { >> >> + FrameType = PXE_FRAME_TYPE_FILTERED_MULTICAST; >> >> + } else { >> >> + FrameType = PXE_FRAME_TYPE_PROMISCUOUS; >> >> + } >> >> + } >> >> + } >> >> + >> >> + Db->Type = FrameType; >> >> + Db->Protocol = Header->Protocol; >> >> + >> >> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> >> + Db->SrcAddr[Index] = Header->SrcAddr[Index]; >> >> + Db->DestAddr[Index] = Header->DestAddr[Index]; >> >> + } >> >> + >> >> + StatCode = PXE_STATCODE_SUCCESS; >> >> + break; >> >> + } >> >> + } >> >> + >> >> + if (FrameType == PXE_FRAME_TYPE_NONE) { >> >> + Nic->ReceiveStatus = 0; >> >> + } else { >> >> + Nic->ReceiveStatus = 1; >> >> + } >> >> + >> >> + gBS->FreePool (BulkInData); >> >> + >> >> + return StatCode; >> >> +} >> >> + >> >> +/** >> >> + Fill out PXE SW UNDI structure. >> >> + >> >> + @param[out] PxeSw A pointer to the PXE SW UNDI structure. >> >> + >> >> +**/ >> >> +VOID >> >> +PxeStructInit ( >> >> + OUT PXE_SW_UNDI *PxeSw >> >> + ) >> >> +{ >> >> + PxeSw->Signature = PXE_ROMID_SIGNATURE; >> >> + PxeSw->Len = (UINT8)sizeof (PXE_SW_UNDI); >> >> + PxeSw->Fudge = 0; >> >> + PxeSw->IFcnt = 0; >> >> + PxeSw->IFcntExt = 0; >> >> + PxeSw->Rev = PXE_ROMID_REV; >> >> + PxeSw->MajorVer = PXE_ROMID_MAJORVER; >> >> + PxeSw->MinorVer = PXE_ROMID_MINORVER; >> >> + PxeSw->reserved1 = 0; >> >> + >> >> + PxeSw->Implementation = PXE_ROMID_IMP_SW_VIRT_ADDR | >> >> + PXE_ROMID_IMP_FRAG_SUPPORTED | >> >> + PXE_ROMID_IMP_CMD_LINK_SUPPORTED | >> >> + PXE_ROMID_IMP_STATION_ADDR_SETTABLE | >> >> + >> PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED | >> >> + PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED | >> >> + PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED | >> >> + PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED; >> >> + >> >> + PxeSw->EntryPoint = (UINT64)(UINTN)UndiApiEntry; >> >> + PxeSw->reserved2[0] = 0; >> >> + PxeSw->reserved2[1] = 0; >> >> + PxeSw->reserved2[2] = 0; >> >> + PxeSw->BusCnt = 1; >> >> + PxeSw->BusType[0] = PXE_BUSTYPE_USB; >> >> + PxeSw->Fudge = PxeSw->Fudge - CalculateSum8 ((VOID *)PxeSw, >> PxeSw->Len); >> >> +} >> >> + >> >> +/** >> >> + Update NIC number. >> >> + >> >> + @param[in] Nic A pointer to the Network interface >> controller data. >> >> + @param[in, out] PxeSw A pointer to the PXE SW UNDI structure. >> >> + >> >> +**/ >> >> +VOID >> >> +UpdateNicNum ( >> >> + IN NIC_DATA *Nic, >> >> + IN OUT PXE_SW_UNDI *PxeSw >> >> + ) >> >> +{ >> >> + UINT16 NicNum; >> >> + >> >> + NicNum = (PxeSw->IFcnt | PxeSw->IFcntExt << 8); >> >> + >> >> + if (Nic == NULL) { >> >> + if (NicNum > 0) { >> >> + NicNum--; >> >> + } >> >> + >> >> + PxeSw->IFcnt = (UINT8)(NicNum & 0xFF); // Get lower byte >> >> + PxeSw->IFcntExt = (UINT8)((NicNum & 0xFF00) >> 8); // Get upper byte >> >> + PxeSw->Fudge = (UINT8)(PxeSw->Fudge - CalculateSum8 ((VOID >> *)PxeSw, PxeSw->Len)); >> >> + return; >> >> + } >> >> + >> >> + NicNum++; >> >> + >> >> + PxeSw->IFcnt = (UINT8)(NicNum & 0xFF); // Get lower byte >> >> + PxeSw->IFcntExt = (UINT8)((NicNum & 0xFF00) >> 8); // Get upper byte >> >> + PxeSw->Fudge = (UINT8)(PxeSw->Fudge - CalculateSum8 ((VOID *)PxeSw, >> PxeSw->Len)); >> >> +} >> >> + >> >> +/** >> >> + UNDI API table entry. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + >> >> +**/ >> >> +VOID >> >> +UndiApiEntry ( >> >> + IN UINT64 Cdb >> >> + ) >> >> +{ >> >> + PXE_CDB *CdbPtr; >> >> + NIC_DATA *Nic; >> >> + >> >> + if (Cdb == 0) { >> >> + return; >> >> + } >> >> + >> >> + CdbPtr = (PXE_CDB *)(UINTN)Cdb; >> >> + Nic = &(gLanDeviceList[CdbPtr->IFnum]->NicInfo); >> >> + gUndiApiTable[CdbPtr->OpCode](CdbPtr, Nic); >> >> +} >> >> + >> >> +/** >> >> + Map virtual memory address for DMA. This field can be set to >> >> + zero if there is no mapping service. >> >> + >> >> + @param[in] Nic A pointer to the Network interface >> controller data. >> >> + @param[in] MemAddr Virtual address to be mapped. >> >> + @param[in] Size Size of memory to be mapped. >> >> + @param[in] Direction Direction of data flow for this memory's >> usage: >> >> + cpu->device, device->cpu or both ways. >> >> + @param[out] MappedAddr Pointer to return the mapped device address. >> >> + >> >> +**/ >> >> +UINTN >> >> +MapIt ( >> >> + IN NIC_DATA *Nic, >> >> + IN UINT64 MemAddr, >> >> + IN UINT32 Size, >> >> + IN UINT32 Direction, >> >> + OUT UINT64 MappedAddr >> >> + ) >> >> +{ >> >> + UINT64 *PhyAddr; >> >> + >> >> + PhyAddr = (UINT64 *)(UINTN)MappedAddr; >> >> + >> >> + if (Nic->PxeStart.Map_Mem == 0) { >> >> + *PhyAddr = MemAddr; >> >> + } else { >> >> + ((void (*)(UINT64, UINT64, UINT32, UINT32, UINT64))(UINTN) >> Nic->PxeStart.Map_Mem)( >> >> + Nic->PxeStart.Unique_ID, >> >> + MemAddr, >> >> + Size, >> >> + Direction, >> >> + MappedAddr >> >> + ); >> >> + } >> >> + >> >> + return PXE_STATCODE_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + Un-map previously mapped virtual memory address. This field can be set >> >> + to zero only if the Map_Mem() service is also set to zero. >> >> + >> >> + @param[in] Nic A pointer to the Network interface >> controller data. >> >> + @param[in] MemAddr Virtual address to be mapped. >> >> + @param[in] Size Size of memory to be mapped. >> >> + @param[in] Direction Direction of data flow for this memory's >> usage: >> >> + cpu->device, device->cpu or both ways. >> >> + @param[in] MappedAddr Pointer to return the mapped device address. >> >> + >> >> +**/ >> >> +VOID >> >> +UnMapIt ( >> >> + IN NIC_DATA *Nic, >> >> + IN UINT64 MemAddr, >> >> + IN UINT32 Size, >> >> + IN UINT32 Direction, >> >> + IN UINT64 MappedAddr >> >> + ) >> >> +{ >> >> + if (Nic->PxeStart.UnMap_Mem != 0) { >> >> + ((void (*)(UINT64, UINT64, UINT32, UINT32, UINT64))(UINTN) >> Nic->PxeStart.UnMap_Mem)( >> >> + Nic->PxeStart.Unique_ID, >> >> + MemAddr, >> >> + Size, >> >> + Direction, >> >> + MappedAddr >> >> + ); >> >> + } >> >> + >> >> + return; >> >> +} >> >> diff --git a/UsbNetworkPkg/ReadMe.md b/UsbNetworkPkg/ReadMe.md >> new file mode 100644 >> index 0000000000..6dc0514ba7 >> --- /dev/null >> +++ b/UsbNetworkPkg/ReadMe.md >> @@ -0,0 +1,65 @@ >> +# UsbNetworkPkg >> + >> +This document is intend to provide package information, include the >> interface details. >> + >> +# INDEX >> + * [Introduction](#introduction) >> + * [Components](#components) >> + * [[NetworkCommon]](#networkcommon) >> + * [[UsbCdcEcm]](#usbcdcecm) >> + * [[UsbCdcNcm]](#usbcdcncm) >> + * [[UsbRndis]](#usbrndis) >> + >> +# Introduction >> +UsbNetworkPkg provides network functions for USB LAN devices. >> + >> +# Components >> +Below module is included in this package:
>> +- 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..39123994b2 >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbCdcEcm/ComponentName.c >> @@ -0,0 +1,170 @@ >> +/** @file >> >> + This file contains code for USB Ecm Driver Component Name definitions >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> +#include "UsbCdcEcm.h" >> >> + >> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE >> gUsbEcmDriverNameTable[] = { >> >> + { >> >> + "eng;en", >> >> + L"USB ECM Driver" >> >> + }, >> >> + { >> >> + NULL, >> >> + NULL >> >> + } >> >> +}; >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEcmComponentNameGetDriverName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **DriverName >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEcmComponentNameGetControllerName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN EFI_HANDLE Controller, >> >> + IN EFI_HANDLE ChildHandle OPTIONAL, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **ControllerName >> >> + ); >> >> + >> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL >> gUsbEcmComponentName = { >> >> + UsbEcmComponentNameGetDriverName, >> >> + UsbEcmComponentNameGetControllerName, >> >> + "eng" >> >> +}; >> >> + >> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL >> gUsbEcmComponentName2 = { >> >> + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)UsbEcmComponentNameGetDriverName, >> >> + >> (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)UsbEcmComponentNameGetControllerName, >> >> + "en" >> >> +}; >> >> + >> >> +/** >> >> + Retrieves a Unicode string that is the user readable name of the >> driver. >> >> + >> >> + This function retrieves the user readable name of a driver in the form >> of a >> >> + Unicode string. If the driver specified by This has a user readable >> name in >> >> + the language specified by Language, then a pointer to the driver name >> is >> >> + returned in DriverName, and EFI_SUCCESS is returned. If the driver >> specified >> >> + by This does not support the language specified by Language, >> >> + then EFI_UNSUPPORTED is returned. >> >> + >> >> + @param[in] This A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >> >> + EFI_COMPONENT_NAME_PROTOCOL instance. >> >> + @param[in] Language A pointer to a Null-terminated ASCII >> string >> >> + array indicating the language. This is >> the >> >> + language of the driver name that the >> caller is >> >> + requesting, and it must match one of the >> >> + languages specified in >> SupportedLanguages. The >> >> + number of languages supported by a >> driver is up >> >> + to the driver writer. Language is >> specified >> >> + in RFC 4646 or ISO 639-2 language code >> format. >> >> + @param[out] DriverName A pointer to the Unicode string to >> return. >> >> + This Unicode string is the name of the >> >> + driver specified by This in the language >> >> + specified by Language. >> >> + >> >> + @retval EFI_SUCCESS The Unicode string for the Driver >> specified by >> >> + This and the language specified by >> Language was >> >> + returned in DriverName. >> >> + @retval EFI_INVALID_PARAMETER Language is NULL. >> >> + @retval EFI_INVALID_PARAMETER DriverName is NULL. >> >> + @retval EFI_UNSUPPORTED The driver specified by This does not >> support >> >> + the language specified by Language. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEcmComponentNameGetDriverName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **DriverName >> >> + ) >> >> +{ >> >> + return LookupUnicodeString2 ( >> >> + Language, >> >> + This->SupportedLanguages, >> >> + gUsbEcmDriverNameTable, >> >> + DriverName, >> >> + (BOOLEAN)(This == &gUsbEcmComponentName) >> >> + ); >> >> +} >> >> + >> >> +/** >> >> + Retrieves a Unicode string that is the user readable name of the >> controller >> >> + that is being managed by a driver. >> >> + >> >> + This function retrieves the user readable name of the controller >> specified by >> >> + ControllerHandle and ChildHandle in the form of a Unicode string. If >> the >> >> + driver specified by This has a user readable name in the language >> specified by >> >> + Language, then a pointer to the controller name is returned in >> ControllerName, >> >> + and EFI_SUCCESS is returned. If the driver specified by This is not >> currently >> >> + managing the controller specified by ControllerHandle and ChildHandle, >> >> + then EFI_UNSUPPORTED is returned. If the driver specified by This >> does not >> >> + support the language specified by Language, then EFI_UNSUPPORTED is >> returned. >> >> + >> >> + @param[in] This A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >> >> + EFI_COMPONENT_NAME_PROTOCOL instance. >> >> + @param[in] Controller The handle of a controller that the >> driver >> >> + specified by This is managing. This >> handle >> >> + specifies the controller whose name is >> to be >> >> + returned. >> >> + @param[in] ChildHandle The handle of the child controller to >> retrieve >> >> + the name of. This is an optional >> parameter that >> >> + may be NULL. It will be NULL for device >> >> + drivers. It will also be NULL for a bus >> drivers >> >> + that wish to retrieve the name of the bus >> >> + controller. It will not be NULL for a >> bus >> >> + driver that wishes to retrieve the name >> of a >> >> + child controller. >> >> + @param[in] Language A pointer to a Null-terminated ASCII >> string >> >> + array indicating the language. This is >> the >> >> + language of the driver name that the >> caller is >> >> + requesting, and it must match one of the >> >> + languages specified in >> SupportedLanguages. The >> >> + number of languages supported by a >> driver is up >> >> + to the driver writer. Language is >> specified in >> >> + RFC 4646 or ISO 639-2 language code >> format. >> >> + @param[out] ControllerName A pointer to the Unicode string to >> return. >> >> + This Unicode string is the name of the >> >> + controller specified by ControllerHandle >> and >> >> + ChildHandle in the language specified by >> >> + Language from the point of view of the >> driver >> >> + specified by This. >> >> + >> >> + @retval EFI_SUCCESS The Unicode string for the user readable >> name in >> >> + the language specified by Language for >> the >> >> + driver specified by This was returned in >> >> + DriverName. >> >> + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid >> EFI_HANDLE. >> >> + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a >> valid >> >> + EFI_HANDLE. >> >> + @retval EFI_INVALID_PARAMETER Language is NULL. >> >> + @retval EFI_INVALID_PARAMETER ControllerName is NULL. >> >> + @retval EFI_UNSUPPORTED The driver specified by This is not >> currently >> >> + managing the controller specified by >> >> + ControllerHandle and ChildHandle. >> >> + @retval EFI_UNSUPPORTED The driver specified by This does not >> support >> >> + the language specified by Language. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEcmComponentNameGetControllerName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN EFI_HANDLE Controller, >> >> + IN EFI_HANDLE ChildHandle OPTIONAL, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **ControllerName >> >> + ) >> >> +{ >> >> + return EFI_UNSUPPORTED; >> >> +} >> >> diff --git a/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.c >> b/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.c >> new file mode 100644 >> index 0000000000..34f115f48d >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.c >> @@ -0,0 +1,504 @@ >> +/** @file >> >> + This file contains code for USB Ethernet Control Model >> >> + Driver >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> +#include "UsbCdcEcm.h" >> >> + >> >> +EFI_GUID gUsbEthProtocolGuid = USB_ETHERNET_PROTOCOL_GUID; >> >> + >> >> +EFI_DRIVER_BINDING_PROTOCOL gUsbEcmDriverBinding = { >> >> + UsbEcmDriverSupported, >> >> + UsbEcmDriverStart, >> >> + UsbEcmDriverStop, >> >> + USB_ECM_DRIVER_VERSION, >> >> + NULL, >> >> + NULL >> >> +}; >> >> + >> >> +/** >> >> + Check if this interface is USB ECM SubType >> >> + >> >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance. >> >> + >> >> + @retval TRUE USB ECM SubType. >> >> + @retval FALSE Not USB ECM SubType. >> >> + >> >> +**/ >> >> +BOOLEAN >> >> +IsSupportedDevice ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; >> >> + >> >> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, >> &InterfaceDescriptor); >> >> + if (EFI_ERROR (Status)) { >> >> + return FALSE; >> >> + } >> >> + >> >> + if ((InterfaceDescriptor.InterfaceClass == USB_CDC_CLASS) && >> >> + (InterfaceDescriptor.InterfaceSubClass == USB_CDC_ECM_SUBCLASS) && >> >> + (InterfaceDescriptor.InterfaceProtocol == USB_NO_CLASS_PROTOCOL)) >> >> + { >> >> + return TRUE; >> >> + } >> >> + >> >> + return FALSE; >> >> +} >> >> + >> >> +/** >> >> + USB ECM Driver Binding Support. >> >> + >> >> + @param[in] This Protocol instance pointer. >> >> + @param[in] ControllerHandle Handle of device to test. >> >> + @param[in] RemainingDevicePath Optional parameter use to pick a >> specific child >> >> + device to start. >> >> + >> >> + @retval EFI_SUCCESS This driver supports this device. >> >> + @retval EFI_ALREADY_STARTED This driver is already running on >> this device. >> >> + @retval other This driver does not support this >> device. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEcmDriverSupported ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_IO_PROTOCOL *UsbIo = NULL; >> >> + >> >> + Status = gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status = IsSupportedDevice (UsbIo) ? EFI_SUCCESS : EFI_UNSUPPORTED; >> >> + >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Check if the USB ECM and USB CDC Data interfaces are from the same >> device. >> >> + >> >> + @param[in] UsbEthPath A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> >> + @param[in] UsbCdcDataPath A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> >> + >> >> + @retval EFI_SUCCESS Is the same device. >> >> + @retval EFI_NOT_FOUND Is not the same device. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +IsSameDevice ( >> >> + IN EFI_DEVICE_PATH_PROTOCOL *UsbEthPath, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath >> >> + ) >> >> +{ >> >> + while (1) { >> >> + if ((UsbEthPath->Type == ACPI_DEVICE_PATH) && (UsbEthPath->SubType >> == ACPI_DP)) { >> >> + if (CompareMem ((ACPI_HID_DEVICE_PATH *)UsbCdcDataPath, >> (ACPI_HID_DEVICE_PATH *)UsbEthPath, sizeof (ACPI_HID_DEVICE_PATH))) { >> >> + return EFI_NOT_FOUND; >> >> + } >> >> + } >> >> + >> >> + if ((UsbEthPath->Type == HARDWARE_DEVICE_PATH) && >> (UsbEthPath->SubType == HW_PCI_DP)) { >> >> + if (CompareMem ((PCI_DEVICE_PATH *)UsbCdcDataPath, >> (PCI_DEVICE_PATH *)UsbEthPath, sizeof (PCI_DEVICE_PATH))) { >> >> + return EFI_NOT_FOUND; >> >> + } >> >> + } >> >> + >> >> + if ((UsbEthPath->Type == MESSAGING_DEVICE_PATH) && >> (UsbEthPath->SubType == MSG_USB_DP)) { >> >> + if (IsDevicePathEnd (NextDevicePathNode (UsbEthPath))) { >> >> + if (((USB_DEVICE_PATH *)UsbEthPath)->ParentPortNumber == >> >> + ((USB_DEVICE_PATH *)UsbCdcDataPath)->ParentPortNumber) >> >> + { >> >> + return EFI_SUCCESS; >> >> + } else { >> >> + return EFI_NOT_FOUND; >> >> + } >> >> + } else { >> >> + if (CompareMem ((USB_DEVICE_PATH *)UsbCdcDataPath, >> (USB_DEVICE_PATH *)UsbEthPath, sizeof (USB_DEVICE_PATH))) { >> >> + return EFI_NOT_FOUND; >> >> + } >> >> + } >> >> + } >> >> + >> >> + UsbEthPath = NextDevicePathNode (UsbEthPath); >> >> + UsbCdcDataPath = NextDevicePathNode (UsbCdcDataPath); >> >> + } >> >> +} >> >> + >> >> +/** >> >> + Check if the USB CDC Data(UsbIo) installed and return USB CDC Data >> Handle. >> >> + >> >> + @param[in] UsbEthPath A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> >> + @param[in, out] UsbCdcDataHandle A pointer to the EFI_HANDLE for >> USB CDC Data. >> >> + >> >> + @retval TRUE USB CDC Data(UsbIo) installed. >> >> + @retval FALSE USB CDC Data(UsbIo) did not installed. >> >> + >> >> +**/ >> >> +BOOLEAN >> >> +IsUsbCdcData ( >> >> + IN EFI_DEVICE_PATH_PROTOCOL *UsbEthPath, >> >> + IN OUT EFI_HANDLE *UsbCdcDataHandle >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINTN Index; >> >> + UINTN HandleCount; >> >> + EFI_HANDLE *HandleBuffer; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + EFI_USB_INTERFACE_DESCRIPTOR Interface; >> >> + EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath; >> >> + >> >> + Status = gBS->LocateHandleBuffer ( >> >> + ByProtocol, >> >> + &gEfiUsbIoProtocolGuid, >> >> + NULL, >> >> + &HandleCount, >> >> + &HandleBuffer >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return FALSE; >> >> + } >> >> + >> >> + for (Index = 0; Index < HandleCount; Index++) { >> >> + Status = gBS->HandleProtocol ( >> >> + HandleBuffer[Index], >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo >> >> + ); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + if ((Interface.InterfaceClass == USB_CDC_DATA_CLASS) && >> >> + (Interface.InterfaceSubClass == USB_CDC_DATA_SUBCLASS) && >> >> + (Interface.InterfaceProtocol == USB_NO_CLASS_PROTOCOL)) >> >> + { >> >> + Status = gBS->HandleProtocol ( >> >> + HandleBuffer[Index], >> >> + &gEfiDevicePathProtocolGuid, >> >> + (VOID **)&UsbCdcDataPath >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + continue; >> >> + } >> >> + >> >> + Status = IsSameDevice (UsbEthPath, UsbCdcDataPath); >> >> + if (!EFI_ERROR (Status)) { >> >> + CopyMem (UsbCdcDataHandle, &HandleBuffer[Index], sizeof >> (EFI_HANDLE)); >> >> + gBS->FreePool (HandleBuffer); >> >> + return TRUE; >> >> + } >> >> + } >> >> + } >> >> + >> >> + gBS->FreePool (HandleBuffer); >> >> + return FALSE; >> >> +} >> >> + >> >> +/** >> >> + Call Back Function. >> >> + >> >> + @param[in] Event Event whose notification function is being >> invoked. >> >> + @param[in] Context The pointer to the notification function's >> context, >> >> + which is implementation-dependent. >> >> + >> >> +**/ >> >> +VOID >> >> +EFIAPI >> >> +CallbackFunction ( >> >> + IN EFI_EVENT Event, >> >> + IN VOID *Context >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINTN Index; >> >> + UINTN HandleCount; >> >> + EFI_HANDLE *HandleBuffer; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + EFI_USB_INTERFACE_DESCRIPTOR Interface; >> >> + >> >> + Status = gBS->LocateHandleBuffer ( >> >> + ByProtocol, >> >> + &gEfiUsbIoProtocolGuid, >> >> + NULL, >> >> + &HandleCount, >> >> + &HandleBuffer >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return; >> >> + } >> >> + >> >> + for (Index = 0; Index < HandleCount; Index++) { >> >> + Status = gBS->HandleProtocol ( >> >> + HandleBuffer[Index], >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo >> >> + ); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + if ((Interface.InterfaceClass == USB_CDC_CLASS) && >> >> + (Interface.InterfaceSubClass == USB_CDC_ECM_SUBCLASS) && >> >> + (Interface.InterfaceProtocol == USB_NO_CLASS_PROTOCOL)) >> >> + { >> >> + gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE); >> >> + } >> >> + } >> >> + >> >> + gBS->FreePool (HandleBuffer); >> >> + gBS->CloseEvent (Event); >> >> +} >> >> + >> >> +/** >> >> + USB ECM Driver Binding Start. >> >> + >> >> + @param[in] This Protocol instance pointer. >> >> + @param[in] ControllerHandle Handle of device to bind driver to. >> >> + @param[in] RemainingDevicePath Optional parameter use to pick a >> specific child >> >> + device to start. >> >> + >> >> + @retval EFI_SUCCESS This driver is added to >> ControllerHandle >> >> + @retval EFI_DEVICE_ERROR This driver could not be started >> due to a device error >> >> + @retval EFI_OUT_OF_RESOURCES The driver could not install >> successfully due to a lack of resources. >> >> + @retval other This driver does not support this >> device >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEcmDriverStart ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + VOID *Reg; >> >> + EFI_EVENT Event; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + EFI_DEVICE_PATH_PROTOCOL *UsbEthPath; >> >> + EFI_HANDLE UsbCdcDataHandle; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + EFI_USB_INTERFACE_DESCRIPTOR Interface; >> >> + >> >> + Status = gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status = gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + (VOID **)&UsbEthPath, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return Status; >> >> + } >> >> + >> >> + Status = IsUsbCdcData (UsbEthPath, &UsbCdcDataHandle) ? EFI_SUCCESS : >> EFI_UNSUPPORTED; >> >> + if (EFI_ERROR (Status)) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + >> >> + Status = gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, >> CallbackFunction, NULL, &Event); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status = gBS->RegisterProtocolNotify (&gEfiUsbIoProtocolGuid, Event, >> &Reg); >> >> + return Status; >> >> + } >> >> + >> >> + UsbEthDriver = AllocateZeroPool (sizeof (USB_ETHERNET_DRIVER)); >> >> + if (!UsbEthDriver) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return EFI_OUT_OF_RESOURCES; >> >> + } >> >> + >> >> + Status = LoadAllDescriptor (UsbIo, &UsbEthDriver->Config); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + GetEndpoint (UsbIo, UsbEthDriver); >> >> + >> >> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + UsbEthDriver->Signature = >> USB_ETHERNET_SIGNATURE; >> >> + UsbEthDriver->NumOfInterface = >> Interface.InterfaceNumber; >> >> + UsbEthDriver->UsbCdcDataHandle = UsbCdcDataHandle; >> >> + UsbEthDriver->UsbIo = UsbIo; >> >> + UsbEthDriver->UsbEth.UsbEthReceive = UsbEthReceive; >> >> + UsbEthDriver->UsbEth.UsbEthTransmit = UsbEthTransmit; >> >> + UsbEthDriver->UsbEth.UsbEthInterrupt = UsbEthInterrupt; >> >> + UsbEthDriver->UsbEth.UsbEthMacAddress = GetUsbEthMacAddress; >> >> + UsbEthDriver->UsbEth.UsbEthMaxBulkSize = UsbEthBulkSize; >> >> + UsbEthDriver->UsbEth.UsbHeaderFunDescriptor = >> GetUsbHeaderFunDescriptor; >> >> + UsbEthDriver->UsbEth.UsbUnionFunDescriptor = >> GetUsbUnionFunDescriptor; >> >> + UsbEthDriver->UsbEth.UsbEthFunDescriptor = >> GetUsbEthFunDescriptor; >> >> + UsbEthDriver->UsbEth.SetUsbEthMcastFilter = >> SetUsbEthMcastFilter; >> >> + UsbEthDriver->UsbEth.SetUsbEthPowerPatternFilter = >> SetUsbEthPowerFilter; >> >> + UsbEthDriver->UsbEth.GetUsbEthPoewrPatternFilter = >> GetUsbEthPowerFilter; >> >> + UsbEthDriver->UsbEth.SetUsbEthPacketFilter = >> SetUsbEthPacketFilter; >> >> + UsbEthDriver->UsbEth.GetUsbEthStatistic = GetUsbEthStatistic; >> >> + >> >> + Status = gBS->InstallProtocolInterface ( >> >> + &ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + EFI_NATIVE_INTERFACE, >> >> + &(UsbEthDriver->UsbEth) >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + gBS->FreePool (UsbEthDriver); >> >> + return Status; >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + USB ECM Driver Binding Stop. >> >> + >> >> + @param[in] This Protocol instance pointer. >> >> + @param[in] ControllerHandle Handle of device to stop driver on >> >> + @param[in] NumberOfChildren Number of Handles in >> ChildHandleBuffer. If number of >> >> + children is zero stop the entire bus >> driver. >> >> + @param[in] ChildHandleBuffer List of Child Handles to Stop. >> >> + >> >> + @retval EFI_SUCCESS This driver is removed ControllerHandle >> >> + @retval other This driver was not removed from this >> device >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEcmDriverStop ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN UINTN NumberOfChildren, >> >> + IN EFI_HANDLE *ChildHandleBuffer >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_PROTOCOL *UsbEthProtocol; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + Status = gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + (VOID **)&UsbEthProtocol, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (UsbEthProtocol); >> >> + >> >> + Status = gBS->UninstallProtocolInterface ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + UsbEthProtocol >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status = gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + gBS->FreePool (UsbEthDriver->Config); >> >> + gBS->FreePool (UsbEthDriver); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Entrypoint of ECM Driver. >> >> + >> >> + This function is the entrypoint of ECM Driver. It installs Driver >> Binding >> >> + Protocols together with Component Name Protocols. >> >> + >> >> + @param[in] ImageHandle The firmware allocated handle for the >> EFI image. >> >> + @param[in] SystemTable A pointer to the EFI System Table. >> >> + >> >> + @retval EFI_SUCCESS The entry point is executed successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEcmEntry ( >> >> + IN EFI_HANDLE ImageHandle, >> >> + IN EFI_SYSTEM_TABLE *SystemTable >> >> + ) >> >> +{ >> >> + gUsbEcmDriverBinding.DriverBindingHandle = ImageHandle; >> >> + gUsbEcmDriverBinding.ImageHandle = ImageHandle; >> >> + >> >> + return gBS->InstallMultipleProtocolInterfaces ( >> >> + &gUsbEcmDriverBinding.DriverBindingHandle, >> >> + &gEfiDriverBindingProtocolGuid, >> >> + &gUsbEcmDriverBinding, >> >> + &gEfiComponentName2ProtocolGuid, >> >> + &gUsbEcmComponentName2, >> >> + NULL >> >> + ); >> >> +} >> >> diff --git a/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.h >> b/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.h >> new file mode 100644 >> index 0000000000..52a818466e >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.h >> @@ -0,0 +1,211 @@ >> +/** @file >> >> + Header file contains code for USB Ethernet Control Model >> >> + driver definitions >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#ifndef _USB_CDC_ECM_H_ >> >> +#define _USB_CDC_ECM_H_ >> >> + >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> + >> >> +typedef struct { >> >> + UINTN Signature; >> >> + USB_ETHERNET_PROTOCOL UsbEth; >> >> + EFI_HANDLE UsbCdcDataHandle; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + EFI_USB_CONFIG_DESCRIPTOR *Config; >> >> + UINT8 NumOfInterface; >> >> + UINT8 BulkInEndpoint; >> >> + UINT8 BulkOutEndpoint; >> >> + UINT8 InterruptEndpoint; >> >> + EFI_MAC_ADDRESS MacAddress; >> >> +} USB_ETHERNET_DRIVER; >> >> + >> >> +#define USB_ECM_DRIVER_VERSION 1 >> >> +#define USB_ETHERNET_BULK_TIMEOUT 1 >> >> +#define USB_ETHERNET_TRANSFER_TIMEOUT 200 >> >> + >> >> +#define USB_ETHERNET_SIGNATURE SIGNATURE_32('u', 'e', 't', 'h') >> >> +#define USB_ETHERNET_DEV_FROM_THIS(a) CR (a, USB_ETHERNET_DRIVER, >> UsbEth, USB_ETHERNET_SIGNATURE) >> >> + >> >> +typedef struct { >> >> + UINT16 Src; >> >> + UINT16 Dst; >> >> +} BIT_MAP; >> >> + >> >> +extern EFI_COMPONENT_NAME2_PROTOCOL gUsbEcmComponentName2; >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEcmDriverSupported ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEcmDriverStart ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEcmDriverStop ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN UINTN NumberOfChildren, >> >> + IN EFI_HANDLE *ChildHandleBuffer >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +LoadAllDescriptor ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> >> + OUT EFI_USB_CONFIG_DESCRIPTOR **ConfigDesc >> >> + ); >> >> + >> >> +BOOLEAN >> >> +NextDescriptor ( >> >> + IN EFI_USB_CONFIG_DESCRIPTOR *Desc, >> >> + IN OUT UINTN *Offset >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +GetFunctionalDescriptor ( >> >> + IN EFI_USB_CONFIG_DESCRIPTOR *Config, >> >> + IN UINT8 FunDescriptorType, >> >> + OUT VOID *DataBuffer >> >> + ); >> >> + >> >> +VOID >> >> +GetEndpoint ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> >> + IN OUT USB_ETHERNET_DRIVER *UsbEthDriver >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthReceive ( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN OUT VOID *Packet, >> >> + IN OUT UINTN *PacketLength >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthTransmit ( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN VOID *Packet, >> >> + IN OUT UINTN *PacketLength >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthInterrupt ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN BOOLEAN IsNewTransfer, >> >> + IN UINTN PollingInterval, >> >> + IN EFI_USB_DEVICE_REQUEST *Request >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +InterruptCallback ( >> >> + IN VOID *Data, >> >> + IN UINTN DataLength, >> >> + IN VOID *Context, >> >> + IN UINT32 Status >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthMacAddress ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT EFI_MAC_ADDRESS *MacAddress >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthBulkSize ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT UINTN *BulkSize >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbHeaderFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbUnionFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbEthMcastFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN VOID *McastAddr >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbEthPowerFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN UINT16 Length, >> >> + IN VOID *PatternFilter >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthPowerFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + OUT BOOLEAN *PatternActive >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbEthPacketFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthStatistic ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 FeatureSelector, >> >> + OUT VOID *Statistic >> >> + ); >> >> + >> >> +#endif >> >> diff --git a/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf >> b/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf >> new file mode 100644 >> index 0000000000..ed031864c6 >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf >> @@ -0,0 +1,41 @@ >> +## @file >> +# This is Usb Cdc Ecm driver for DXE phase. >> +# >> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> +# Subject to AMI licensing agreement. >> +## >> + >> +[Defines] >> + INF_VERSION = 0x00010005 >> + BASE_NAME = UsbCdcEcm >> + FILE_GUID = 07a84945-685d-48ec-a6a1-1b397579fa76 >> + MODULE_TYPE = DXE_DRIVER >> + VERSION_STRING = 1.0 >> + ENTRY_POINT = UsbEcmEntry >> + >> +[Sources] >> + UsbCdcEcm.c >> + UsbCdcEcm.h >> + UsbEcmFunction.c >> + ComponentName.c >> + >> +[Packages] >> + MdePkg/MdePkg.dec >> + UsbNetworkPkg/UsbNetworkPkg.dec >> + >> +[LibraryClasses] >> + UefiDriverEntryPoint >> + UefiBootServicesTableLib >> + UefiLib >> + DebugLib >> + UefiUsbLib >> + MemoryAllocationLib >> + BaseMemoryLib >> + >> +[Protocols] >> + gEfiUsbIoProtocolGuid >> + gEfiDevicePathProtocolGuid >> + gEfiDriverBindingProtocolGuid >> + >> +[Depex] >> + TRUE >> diff --git a/UsbNetworkPkg/UsbCdcEcm/UsbEcmFunction.c >> b/UsbNetworkPkg/UsbCdcEcm/UsbEcmFunction.c >> new file mode 100644 >> index 0000000000..175addddc6 >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbCdcEcm/UsbEcmFunction.c >> @@ -0,0 +1,861 @@ >> +/** @file >> >> + This file contains code for USB Ethernet descriptor >> >> + and specific requests implement. >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#include "UsbCdcEcm.h" >> >> + >> >> +/** >> >> + Load All of device descriptor. >> >> + >> >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL >> instance. >> >> + @param[out] ConfigDesc A pointer to the configuration >> descriptor. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_OUT_OF_RESOURCES The request could not be completed >> because the >> >> + buffer specified by DescriptorLength and >> Descriptor >> >> + is not large enough to hold the result >> of the request. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device >> error. The transfer >> >> + status is returned in Status. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +LoadAllDescriptor ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> >> + OUT EFI_USB_CONFIG_DESCRIPTOR **ConfigDesc >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINT32 TransStatus; >> >> + EFI_USB_CONFIG_DESCRIPTOR Tmp; >> >> + >> >> + Status = UsbIo->UsbGetConfigDescriptor (UsbIo, &Tmp); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status = gBS->AllocatePool (EfiBootServicesData, Tmp.TotalLength, >> (VOID **)ConfigDesc); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status = UsbGetDescriptor ( >> >> + UsbIo, >> >> + USB_DESC_TYPE_CONFIG << 8 | (Tmp.ConfigurationValue - 1), >> // zero based >> >> + 0, >> >> + Tmp.TotalLength, >> >> + *ConfigDesc, >> >> + &TransStatus >> >> + ); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Returns pointer to the next descriptor for the pack of USB descriptors >> >> + located in continues memory segment >> >> + >> >> + @param[in] Desc A pointer to the CONFIG_DESCRIPTOR instance. >> >> + @param[in, out] Offset A pointer to the sum of descriptor length. >> >> + >> >> + @retval TRUE The request executed successfully. >> >> + @retval FALSE No next descriptor. >> >> + >> >> +**/ >> >> +BOOLEAN >> >> +NextDescriptor ( >> >> + IN EFI_USB_CONFIG_DESCRIPTOR *Desc, >> >> + IN OUT UINTN *Offset >> >> + ) >> >> +{ >> >> + if ((Desc == NULL) || (*Offset >= Desc->TotalLength)) { >> >> + return FALSE; >> >> + } >> >> + >> >> + if (((EFI_USB_CONFIG_DESCRIPTOR *)((char *)Desc+*Offset))->Length == >> 0) { >> >> + return FALSE; >> >> + } >> >> + >> >> + *Offset += ((EFI_USB_CONFIG_DESCRIPTOR *)((char >> *)Desc+*Offset))->Length; >> >> + if ( *Offset >= Desc->TotalLength ) { >> >> + return FALSE; >> >> + } >> >> + >> >> + return TRUE; >> >> +} >> >> + >> >> +/** >> >> + Read Function descriptor >> >> + >> >> + @param[in] Config A pointer to all of configuration. >> >> + @param[in] FunDescriptorType USB CDC class descriptor SubType. >> >> + @param[out] DataBuffer A pointer to the Data of corresponding >> to device capability. >> >> + >> >> + @retval EFI_SUCCESS The device capability descriptor was >> retrieved >> >> + successfully. >> >> + @retval EFI_UNSUPPORTED No supported. >> >> + @retval EFI_NOT_FOUND The device capability descriptor was not >> found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +GetFunctionalDescriptor ( >> >> + IN EFI_USB_CONFIG_DESCRIPTOR *Config, >> >> + IN UINT8 FunDescriptorType, >> >> + OUT VOID *DataBuffer >> >> + ) >> >> +{ >> >> + EFI_STATUS Status = EFI_NOT_FOUND; >> >> + UINTN Offset; >> >> + EFI_USB_INTERFACE_DESCRIPTOR *Interface; >> >> + >> >> + for (Offset = 0; NextDescriptor (Config, &Offset);) { >> >> + Interface = (EFI_USB_INTERFACE_DESCRIPTOR *)((UINT8 *)Config + >> Offset); >> >> + if (Interface->DescriptorType == CS_INTERFACE) { >> >> + if (((USB_HEADER_FUN_DESCRIPTOR *)Interface)->DescriptorSubtype == >> FunDescriptorType) { >> >> + switch (FunDescriptorType) { >> >> + case HEADER_FUN_DESCRIPTOR: >> >> + CopyMem ( >> >> + DataBuffer, >> >> + (USB_HEADER_FUN_DESCRIPTOR *)Interface, >> >> + sizeof (USB_HEADER_FUN_DESCRIPTOR) >> >> + ); >> >> + return EFI_SUCCESS; >> >> + case UNION_FUN_DESCRIPTOR: >> >> + CopyMem ( >> >> + DataBuffer, >> >> + (USB_UNION_FUN_DESCRIPTOR *)Interface, >> >> + ((USB_UNION_FUN_DESCRIPTOR *)Interface)->FunctionLength >> >> + ); >> >> + return EFI_SUCCESS; >> >> + case ETHERNET_FUN_DESCRIPTOR: >> >> + CopyMem ( >> >> + DataBuffer, >> >> + (USB_ETHERNET_FUN_DESCRIPTOR *)Interface, >> >> + sizeof (USB_ETHERNET_FUN_DESCRIPTOR) >> >> + ); >> >> + return EFI_SUCCESS; >> >> + default: >> >> + Status = EFI_UNSUPPORTED; >> >> + break; >> >> + } >> >> + } >> >> + } >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Get USB Ethernet IO endpoint and USB CDC data IO endpoint. >> >> + >> >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL >> instance. >> >> + @param[in, out] UsbEthDriver A pointer to the USB_ETHERNET_DRIVER >> instance. >> >> + >> >> +**/ >> >> +VOID >> >> +GetEndpoint ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> >> + IN OUT USB_ETHERNET_DRIVER *UsbEthDriver >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINT8 Index; >> >> + UINT32 Result; >> >> + EFI_USB_INTERFACE_DESCRIPTOR Interface; >> >> + EFI_USB_ENDPOINT_DESCRIPTOR Endpoint; >> >> + >> >> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + if (Interface.NumEndpoints == 0) { >> >> + Status = UsbSetInterface (UsbIo, Interface.InterfaceNumber, 1, >> &Result); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> >> + ASSERT_EFI_ERROR (Status); >> >> + } >> >> + >> >> + for (Index = 0; Index < Interface.NumEndpoints; Index++) { >> >> + Status = UsbIo->UsbGetEndpointDescriptor (UsbIo, Index, &Endpoint); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + switch ((Endpoint.Attributes & (BIT0 | BIT1))) { >> >> + case USB_ENDPOINT_BULK: >> >> + if (Endpoint.EndpointAddress & BIT7) { >> >> + UsbEthDriver->BulkInEndpoint = Endpoint.EndpointAddress; >> >> + } else { >> >> + UsbEthDriver->BulkOutEndpoint = Endpoint.EndpointAddress; >> >> + } >> >> + >> >> + break; >> >> + case USB_ENDPOINT_INTERRUPT: >> >> + UsbEthDriver->InterruptEndpoint = Endpoint.EndpointAddress; >> >> + break; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This function is used to manage a USB device with the bulk transfer >> pipe. The endpoint is Bulk in. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor >> block. >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in, out] Packet A pointer to the buffer of data that >> will be transmitted to USB >> >> + device or received from USB device. >> >> + @param[in, out] PacketLength A pointer to the PacketLength. >> >> + >> >> + @retval EFI_SUCCESS The bulk transfer has been successfully >> executed. >> >> + @retval EFI_DEVICE_ERROR The transfer failed. The transfer status >> is returned in status. >> >> + @retval EFI_INVALID_PARAMETE One or more parameters are invalid. >> >> + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due >> to a lack of resources. >> >> + @retval EFI_TIMEOUT The control transfer fails due to >> timeout. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthReceive ( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN OUT VOID *Packet, >> >> + IN OUT UINTN *PacketLength >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + UINT32 TransStatus; >> >> + >> >> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + Status = gBS->HandleProtocol ( >> >> + UsbEthDriver->UsbCdcDataHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + if (UsbEthDriver->BulkInEndpoint == 0) { >> >> + GetEndpoint (UsbIo, UsbEthDriver); >> >> + } >> >> + >> >> + Status = UsbIo->UsbBulkTransfer ( >> >> + UsbIo, >> >> + UsbEthDriver->BulkInEndpoint, >> >> + Packet, >> >> + PacketLength, >> >> + USB_ETHERNET_BULK_TIMEOUT, >> >> + &TransStatus >> >> + ); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + This function is used to manage a USB device with the bulk transfer >> pipe. The endpoint is Bulk out. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor >> block. >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in] Packet A pointer to the buffer of data that >> will be transmitted to USB >> >> + device or received from USB device. >> >> + @param[in, out] PacketLength A pointer to the PacketLength. >> >> + >> >> + @retval EFI_SUCCESS The bulk transfer has been successfully >> executed. >> >> + @retval EFI_DEVICE_ERROR The transfer failed. The transfer status >> is returned in status. >> >> + @retval EFI_INVALID_PARAMETE One or more parameters are invalid. >> >> + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due >> to a lack of resources. >> >> + @retval EFI_TIMEOUT The control transfer fails due to >> timeout. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthTransmit ( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN VOID *Packet, >> >> + IN OUT UINTN *PacketLength >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + UINT32 TransStatus; >> >> + >> >> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + Status = gBS->HandleProtocol ( >> >> + UsbEthDriver->UsbCdcDataHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + if (UsbEthDriver->BulkOutEndpoint == 0) { >> >> + GetEndpoint (UsbIo, UsbEthDriver); >> >> + } >> >> + >> >> + Status = UsbIo->UsbBulkTransfer ( >> >> + UsbIo, >> >> + UsbEthDriver->BulkOutEndpoint, >> >> + Packet, >> >> + PacketLength, >> >> + USB_ETHERNET_BULK_TIMEOUT, >> >> + &TransStatus >> >> + ); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Async USB transfer callback routine. >> >> + >> >> + @param[in] Data Data received or sent via the USB >> Asynchronous Transfer, if the >> >> + transfer completed successfully. >> >> + @param[in] DataLength The length of Data received or sent via >> the Asynchronous >> >> + Transfer, if transfer successfully >> completes. >> >> + @param[in] Context Data passed from >> UsbAsyncInterruptTransfer() request. >> >> + @param[in] Status Indicates the result of the asynchronous >> transfer. >> >> + >> >> + @retval EFI_SUCCESS The asynchronous USB transfer request >> has been successfully executed. >> >> + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request >> failed. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +InterruptCallback ( >> >> + IN VOID *Data, >> >> + IN UINTN DataLength, >> >> + IN VOID *Context, >> >> + IN UINT32 Status >> >> + ) >> >> +{ >> >> + if (((EFI_USB_DEVICE_REQUEST *)Data)->Request == >> USB_CDC_NETWORK_CONNECTION) { >> >> + CopyMem ( >> >> + (EFI_USB_DEVICE_REQUEST *)Context, >> >> + (EFI_USB_DEVICE_REQUEST *)Data, >> >> + sizeof (EFI_USB_DEVICE_REQUEST) >> >> + ); >> >> + } >> >> + >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This function is used to manage a USB device with an interrupt >> transfer pipe. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in] IsNewTransfer If TRUE, a new transfer will be >> submitted to USB controller. If >> >> + FALSE, the interrupt transfer is deleted >> from the device's interrupt >> >> + transfer queue. >> >> + @param[in] PollingInterval Indicates the periodic rate, in >> milliseconds, that the transfer is to be >> >> + executed.This parameter is required when >> IsNewTransfer is TRUE. The >> >> + value must be between 1 to 255, >> otherwise EFI_INVALID_PARAMETER is returned. >> >> + The units are in milliseconds. >> >> + @param[in] Request A pointer to the EFI_USB_DEVICE_REQUEST >> data. >> >> + >> >> + @retval EFI_SUCCESS The asynchronous USB transfer request >> transfer has been successfully executed. >> >> + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request >> failed. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthInterrupt ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN BOOLEAN IsNewTransfer, >> >> + IN UINTN PollingInterval, >> >> + IN EFI_USB_DEVICE_REQUEST *Request >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + UINTN DataLength = 0; >> >> + >> >> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This); >> >> + if (IsNewTransfer == TRUE) { >> >> + DataLength = sizeof (EFI_USB_DEVICE_REQUEST) + sizeof >> (USB_CONNECT_SPEED_CHANGE); >> >> + Status = UsbEthDriver->UsbIo->UsbAsyncInterruptTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + UsbEthDriver->InterruptEndpoint, >> >> + IsNewTransfer, >> >> + PollingInterval, >> >> + DataLength, >> >> + >> (EFI_ASYNC_USB_TRANSFER_CALLBACK)InterruptCallback, >> >> + Request >> >> + ); >> >> + } else { >> >> + Status = UsbEthDriver->UsbIo->UsbAsyncInterruptTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + UsbEthDriver->InterruptEndpoint, >> >> + IsNewTransfer, >> >> + 0, >> >> + 0, >> >> + NULL, >> >> + NULL >> >> + ); >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Ethernet Mac Address. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[out] MacAddress A pointer to the caller allocated USB >> Ethernet Mac Address. >> >> + >> >> + @retval EFI_SUCCESS The USB Header Functional descriptor was >> retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor was >> not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthMacAddress ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT EFI_MAC_ADDRESS *MacAddress >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthDescriptor; >> >> + CHAR16 *Data; >> >> + CHAR16 *DataPtr; >> >> + CHAR16 TmpStr[1]; >> >> + UINT8 Index; >> >> + UINT8 Hi; >> >> + UINT8 Low; >> >> + >> >> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + Status = This->UsbEthFunDescriptor (This, &UsbEthDescriptor); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status = UsbEthDriver->UsbIo->UsbGetStringDescriptor ( >> >> + UsbEthDriver->UsbIo, >> >> + 0x409, // >> English-US Language ID >> >> + UsbEthDescriptor.MacAddress, >> >> + &Data >> >> + ); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + DataPtr = Data; >> >> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> >> + CopyMem (TmpStr, DataPtr, sizeof (CHAR16)); >> >> + DataPtr++; >> >> + Hi = (UINT8)StrHexToUintn (TmpStr); >> >> + CopyMem (TmpStr, DataPtr, sizeof (CHAR16)); >> >> + DataPtr++; >> >> + Low = (UINT8)StrHexToUintn (TmpStr); >> >> + MacAddress->Addr[Index] = (Hi << 4) | Low; >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Ethernet Bulk transfer data size. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[out] BulkSize A pointer to the Bulk transfer data size. >> >> + >> >> + @retval EFI_SUCCESS The bulk transfer data size was retrieved >> successfully. >> >> + @retval other Failed to retrieve the bulk transfer data >> size. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthBulkSize ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT UINTN *BulkSize >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; >> >> + >> >> + Status = This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + *BulkSize = (UINTN)UsbEthFunDescriptor.MaxSegmentSize; >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Header functional Descriptor. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[out] UsbHeaderFunDescriptor A pointer to the caller allocated >> USB Header Functional Descriptor. >> >> + >> >> + @retval EFI_SUCCESS The USB Header Functional descriptor was >> retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor was >> not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbHeaderFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + if (UsbHeaderFunDescriptor == NULL) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + Status = GetFunctionalDescriptor (UsbEthDriver->Config, >> HEADER_FUN_DESCRIPTOR, UsbHeaderFunDescriptor); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Union functional Descriptor. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[out] UsbUnionFunDescriptor A pointer to the caller allocated >> USB Union Functional Descriptor. >> >> + >> >> + @retval EFI_SUCCESS The USB Union Functional descriptor was >> retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbUnionFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Union Functional descriptor was >> not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbUnionFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + if (UsbUnionFunDescriptor == NULL) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + Status = GetFunctionalDescriptor (UsbEthDriver->Config, >> UNION_FUN_DESCRIPTOR, UsbUnionFunDescriptor); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Ethernet functional Descriptor. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[out] UsbEthFunDescriptor A pointer to the caller allocated >> USB Ethernet Functional Descriptor. >> >> + >> >> + @retval EFI_SUCCESS The USB Ethernet Functional descriptor >> was retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbEthFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Ethernet Functional descriptor >> was not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + if (UsbEthFunDescriptor == NULL) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + Status = GetFunctionalDescriptor (UsbEthDriver->Config, >> ETHERNET_FUN_DESCRIPTOR, UsbEthFunDescriptor); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + This request sets the Ethernet device multicast filters as specified >> in the >> >> + sequential list of 48 bit Ethernet multicast addresses. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] Value Number of filters. >> >> + @param[in] McastAddr A pointer to the value of the >> multicast addresses. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbEthMcastFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN VOID *McastAddr >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> + UINT32 TransStatus; >> >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + Status = This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + if ((UsbEthFunDescriptor.NumberMcFilters << 1) == 0) { >> >> + return EFI_UNSUPPORTED; >> >> + } >> >> + >> >> + Request.RequestType = USB_ETHRTNET_SET_REQ_TYPE; >> >> + Request.Request = SET_ETH_MULTICAST_FILTERS_REQ; >> >> + Request.Value = Value; >> >> + Request.Index = UsbEthDriver->NumOfInterface; >> >> + Request.Length = Value * 6; >> >> + >> >> + return UsbEthDriver->UsbIo->UsbControlTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + &Request, >> >> + EfiUsbDataOut, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + McastAddr, >> >> + Request.Length, >> >> + &TransStatus >> >> + ); >> >> +} >> >> + >> >> +/** >> >> + This request sets up the specified Ethernet power management pattern >> filter as >> >> + described in the data structure. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] Value Number of filters. >> >> + @param[in] Length Size of the power management pattern >> filter data. >> >> + @param[in] PatternFilter A pointer to the power management >> pattern filter structure. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbEthPowerFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN UINT16 Length, >> >> + IN VOID *PatternFilter >> >> + ) >> >> +{ >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> + UINT32 TransStatus; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + Request.RequestType = USB_ETHRTNET_SET_REQ_TYPE; >> >> + Request.Request = SET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ; >> >> + Request.Value = Value; >> >> + Request.Index = UsbEthDriver->NumOfInterface; >> >> + Request.Length = Length; >> >> + >> >> + return UsbEthDriver->UsbIo->UsbControlTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + &Request, >> >> + EfiUsbDataOut, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + PatternFilter, >> >> + Length, >> >> + &TransStatus >> >> + ); >> >> +} >> >> + >> >> +/** >> >> + This request retrieves the status of the specified Ethernet power >> management >> >> + pattern filter from the device. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] Value The filter number. >> >> + @param[out] PatternActive A pointer to the pattern active >> boolean. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthPowerFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + OUT BOOLEAN *PatternActive >> >> + ) >> >> +{ >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> + UINT32 TransStatus; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + Request.RequestType = USB_ETHERNET_GET_REQ_TYPE; >> >> + Request.Request = GET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ; >> >> + Request.Value = Value; >> >> + Request.Index = UsbEthDriver->NumOfInterface; >> >> + Request.Length = USB_ETH_POWER_FILTER_LENGTH; >> >> + >> >> + return UsbEthDriver->UsbIo->UsbControlTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + &Request, >> >> + EfiUsbDataIn, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + PatternActive, >> >> + USB_ETH_POWER_FILTER_LENGTH, >> >> + &TransStatus >> >> + ); >> >> +} >> >> + >> >> +BIT_MAP gTable[] = { >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_UNICAST, >> USB_ETH_PACKET_TYPE_DIRECTED }, >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST, >> USB_ETH_PACKET_TYPE_BROADCAST }, >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST, >> USB_ETH_PACKET_TYPE_MULTICAST }, >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS, >> USB_ETH_PACKET_TYPE_PROMISCUOUS }, >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST, >> USB_ETH_PACKET_TYPE_ALL_MULTICAST }, >> >> +}; >> >> + >> >> +/** >> >> + Convert value between PXE receive filter and USB ETH packet filter. >> >> + >> >> + @param[in] Value PXE filter data. >> >> + @param[out] CdcFilter A pointer to the Ethernet Packet Filter Bitmap >> value converted by PXE_OPFLAGS. >> >> + >> >> +**/ >> >> +VOID >> >> +ConvertFilter ( >> >> + IN UINT16 Value, >> >> + OUT UINT16 *CdcFilter >> >> + ) >> >> +{ >> >> + UINT32 Index; >> >> + UINT32 Count; >> >> + >> >> + Count = sizeof (gTable)/sizeof (gTable[0]); >> >> + >> >> + for (Index = 0; (gTable[Index].Src != 0) && (Index < Count); Index++) { >> >> + if (gTable[Index].Src & Value) { >> >> + *CdcFilter |= gTable[Index].Dst; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This request is used to configure device Ethernet packet filter >> settings. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in] Value Packet Filter Bitmap. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbEthPacketFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value >> >> + ) >> >> +{ >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> + UINT32 TransStatus; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + UINT16 CommandFilter = 0; >> >> + >> >> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + ConvertFilter (Value, &CommandFilter); >> >> + >> >> + Request.RequestType = USB_ETHRTNET_SET_REQ_TYPE; >> >> + Request.Request = SET_ETH_PACKET_FILTER_REQ; >> >> + Request.Value = CommandFilter; >> >> + Request.Index = UsbEthDriver->NumOfInterface; >> >> + Request.Length = USB_ETH_PACKET_FILTER_LENGTH; >> >> + >> >> + return UsbEthDriver->UsbIo->UsbControlTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + &Request, >> >> + EfiUsbNoData, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + NULL, >> >> + USB_ETH_PACKET_FILTER_LENGTH, >> >> + &TransStatus >> >> + ); >> >> +} >> >> + >> >> +/** >> >> + This request is used to retrieve a statistic based on the feature >> selector. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] FeatureSelector Value of the feature selector. >> >> + @param[out] Statistic A pointer to the 32 bit unsigned >> integer. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthStatistic ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 FeatureSelector, >> >> + OUT VOID *Statistic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> + UINT32 TransStatus; >> >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + Status = This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + if (UsbEthFunDescriptor.EthernetStatistics == 0) { >> >> + return EFI_UNSUPPORTED; >> >> + } >> >> + >> >> + Request.RequestType = USB_ETHERNET_GET_REQ_TYPE; >> >> + Request.Request = GET_ETH_STATISTIC_REQ; >> >> + Request.Value = FeatureSelector; >> >> + Request.Index = UsbEthDriver->NumOfInterface; >> >> + Request.Length = USB_ETH_STATISTIC; >> >> + >> >> + return UsbEthDriver->UsbIo->UsbControlTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + &Request, >> >> + EfiUsbDataIn, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + Statistic, >> >> + USB_ETH_STATISTIC, >> >> + &TransStatus >> >> + ); >> >> +} >> >> diff --git a/UsbNetworkPkg/UsbCdcNcm/ComponentName.c >> b/UsbNetworkPkg/UsbCdcNcm/ComponentName.c >> new file mode 100644 >> index 0000000000..36792b89c5 >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbCdcNcm/ComponentName.c >> @@ -0,0 +1,170 @@ >> +/** @file >> >> + This file contains code for USB Ncm Driver Component Name definitions >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> +#include "UsbCdcNcm.h" >> >> + >> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE >> gUsbNcmDriverNameTable[] = { >> >> + { >> >> + "eng;en", >> >> + L"USB NCM Driver" >> >> + }, >> >> + { >> >> + NULL, >> >> + NULL >> >> + } >> >> +}; >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbNcmComponentNameGetDriverName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **DriverName >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbNcmComponentNameGetControllerName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN EFI_HANDLE Controller, >> >> + IN EFI_HANDLE ChildHandle OPTIONAL, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **ControllerName >> >> + ); >> >> + >> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL >> gUsbNcmComponentName = { >> >> + UsbNcmComponentNameGetDriverName, >> >> + UsbNcmComponentNameGetControllerName, >> >> + "eng" >> >> +}; >> >> + >> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL >> gUsbNcmComponentName2 = { >> >> + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)UsbNcmComponentNameGetDriverName, >> >> + >> (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)UsbNcmComponentNameGetControllerName, >> >> + "en" >> >> +}; >> >> + >> >> +/** >> >> + Retrieves a Unicode string that is the user readable name of the >> driver. >> >> + >> >> + This function retrieves the user readable name of a driver in the form >> of a >> >> + Unicode string. If the driver specified by This has a user readable >> name in >> >> + the language specified by Language, then a pointer to the driver name >> is >> >> + returned in DriverName, and EFI_SUCCESS is returned. If the driver >> specified >> >> + by This does not support the language specified by Language, >> >> + then EFI_UNSUPPORTED is returned. >> >> + >> >> + @param[in] This A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >> >> + EFI_COMPONENT_NAME_PROTOCOL instance. >> >> + @param[in] Language A pointer to a Null-terminated ASCII >> string >> >> + array indicating the language. This is >> the >> >> + language of the driver name that the >> caller is >> >> + requesting, and it must match one of the >> >> + languages specified in >> SupportedLanguages. The >> >> + number of languages supported by a >> driver is up >> >> + to the driver writer. Language is >> specified >> >> + in RFC 4646 or ISO 639-2 language code >> format. >> >> + @param[out] DriverName A pointer to the Unicode string to >> return. >> >> + This Unicode string is the name of the >> >> + driver specified by This in the language >> >> + specified by Language. >> >> + >> >> + @retval EFI_SUCCESS The Unicode string for the Driver >> specified by >> >> + This and the language specified by >> Language was >> >> + returned in DriverName. >> >> + @retval EFI_INVALID_PARAMETER Language is NULL. >> >> + @retval EFI_INVALID_PARAMETER DriverName is NULL. >> >> + @retval EFI_UNSUPPORTED The driver specified by This does not >> support >> >> + the language specified by Language. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbNcmComponentNameGetDriverName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **DriverName >> >> + ) >> >> +{ >> >> + return LookupUnicodeString2 ( >> >> + Language, >> >> + This->SupportedLanguages, >> >> + gUsbNcmDriverNameTable, >> >> + DriverName, >> >> + (BOOLEAN)(This == &gUsbNcmComponentName) >> >> + ); >> >> +} >> >> + >> >> +/** >> >> + Retrieves a Unicode string that is the user readable name of the >> controller >> >> + that is being managed by a driver. >> >> + >> >> + This function retrieves the user readable name of the controller >> specified by >> >> + ControllerHandle and ChildHandle in the form of a Unicode string. If >> the >> >> + driver specified by This has a user readable name in the language >> specified by >> >> + Language, then a pointer to the controller name is returned in >> ControllerName, >> >> + and EFI_SUCCESS is returned. If the driver specified by This is not >> currently >> >> + managing the controller specified by ControllerHandle and ChildHandle, >> >> + then EFI_UNSUPPORTED is returned. If the driver specified by This >> does not >> >> + support the language specified by Language, then EFI_UNSUPPORTED is >> returned. >> >> + >> >> + @param[in] This A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >> >> + EFI_COMPONENT_NAME_PROTOCOL instance. >> >> + @param[in] Controller The handle of a controller that the >> driver >> >> + specified by This is managing. This >> handle >> >> + specifies the controller whose name is >> to be >> >> + returned. >> >> + @param[in] ChildHandle The handle of the child controller to >> retrieve >> >> + the name of. This is an optional >> parameter that >> >> + may be NULL. It will be NULL for device >> >> + drivers. It will also be NULL for a bus >> drivers >> >> + that wish to retrieve the name of the bus >> >> + controller. It will not be NULL for a >> bus >> >> + driver that wishes to retrieve the name >> of a >> >> + child controller. >> >> + @param[in] Language A pointer to a Null-terminated ASCII >> string >> >> + array indicating the language. This is >> the >> >> + language of the driver name that the >> caller is >> >> + requesting, and it must match one of the >> >> + languages specified in >> SupportedLanguages. The >> >> + number of languages supported by a >> driver is up >> >> + to the driver writer. Language is >> specified in >> >> + RFC 4646 or ISO 639-2 language code >> format. >> >> + @param[out] ControllerName A pointer to the Unicode string to >> return. >> >> + This Unicode string is the name of the >> >> + controller specified by ControllerHandle >> and >> >> + ChildHandle in the language specified by >> >> + Language from the point of view of the >> driver >> >> + specified by This. >> >> + >> >> + @retval EFI_SUCCESS The Unicode string for the user readable >> name in >> >> + the language specified by Language for >> the >> >> + driver specified by This was returned in >> >> + DriverName. >> >> + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid >> EFI_HANDLE. >> >> + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a >> valid >> >> + EFI_HANDLE. >> >> + @retval EFI_INVALID_PARAMETER Language is NULL. >> >> + @retval EFI_INVALID_PARAMETER ControllerName is NULL. >> >> + @retval EFI_UNSUPPORTED The driver specified by This is not >> currently >> >> + managing the controller specified by >> >> + ControllerHandle and ChildHandle. >> >> + @retval EFI_UNSUPPORTED The driver specified by This does not >> support >> >> + the language specified by Language. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbNcmComponentNameGetControllerName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN EFI_HANDLE Controller, >> >> + IN EFI_HANDLE ChildHandle OPTIONAL, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **ControllerName >> >> + ) >> >> +{ >> >> + return EFI_UNSUPPORTED; >> >> +} >> >> diff --git a/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.c >> b/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.c >> new file mode 100644 >> index 0000000000..fc7cbd8132 >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.c >> @@ -0,0 +1,508 @@ >> +/** @file >> >> + This file contains code for USB Network Control Model >> >> + binding driver >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#include "UsbCdcNcm.h" >> >> + >> >> +EFI_GUID gUsbEthProtocolGuid = USB_ETHERNET_PROTOCOL_GUID; >> >> + >> >> +EFI_DRIVER_BINDING_PROTOCOL gUsbNcmDriverBinding = { >> >> + UsbNcmDriverSupported, >> >> + UsbNcmDriverStart, >> >> + UsbNcmDriverStop, >> >> + USB_NCM_DRIVER_VERSION, >> >> + NULL, >> >> + NULL >> >> +}; >> >> + >> >> +/** >> >> + Check if this interface is USB NCM SubType >> >> + >> >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance. >> >> + >> >> + @retval TRUE USB NCM SubType. >> >> + @retval FALSE Not USB NCM SubType. >> >> + >> >> +**/ >> >> +BOOLEAN >> >> +IsSupportedDevice ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; >> >> + >> >> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, >> &InterfaceDescriptor); >> >> + if (EFI_ERROR (Status)) { >> >> + return FALSE; >> >> + } >> >> + >> >> + if ((InterfaceDescriptor.InterfaceClass == USB_CDC_CLASS) && >> >> + (InterfaceDescriptor.InterfaceSubClass == USB_CDC_NCM_SUBCLASS) && >> >> + (InterfaceDescriptor.InterfaceProtocol == USB_NO_CLASS_PROTOCOL)) >> >> + { >> >> + return TRUE; >> >> + } >> >> + >> >> + return FALSE; >> >> +} >> >> + >> >> +/** >> >> + USB NCM Driver Binding Support. >> >> + >> >> + @param[in] This Protocol instance pointer. >> >> + @param[in] ControllerHandle Handle of device to test. >> >> + @param[in] RemainingDevicePath Optional parameter use to pick a >> specific child >> >> + device to start. >> >> + >> >> + @retval EFI_SUCCESS This driver supports this device. >> >> + @retval EFI_ALREADY_STARTED This driver is already running on >> this device. >> >> + @retval other This driver does not support this >> device. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbNcmDriverSupported ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_IO_PROTOCOL *UsbIo = NULL; >> >> + >> >> + Status = gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status = IsSupportedDevice (UsbIo) ? EFI_SUCCESS : EFI_UNSUPPORTED; >> >> + >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Check if the USB NCM and USB CDC Data interfaces are from the same >> device. >> >> + >> >> + @param[in] UsbEthPath A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> >> + @param[in] UsbCdcDataPath A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> >> + >> >> + @retval EFI_SUCCESS Is the same device. >> >> + @retval EFI_NOT_FOUND Is not the same device. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +IsSameDevice ( >> >> + IN EFI_DEVICE_PATH_PROTOCOL *UsbEthPath, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath >> >> + ) >> >> +{ >> >> + while (1) { >> >> + if ((UsbEthPath->Type == ACPI_DEVICE_PATH) && (UsbEthPath->SubType >> == ACPI_DP)) { >> >> + if (CompareMem ((ACPI_HID_DEVICE_PATH *)UsbCdcDataPath, >> (ACPI_HID_DEVICE_PATH *)UsbEthPath, sizeof (ACPI_HID_DEVICE_PATH))) { >> >> + return EFI_NOT_FOUND; >> >> + } >> >> + } >> >> + >> >> + if ((UsbEthPath->Type == HARDWARE_DEVICE_PATH) && >> (UsbEthPath->SubType == HW_PCI_DP)) { >> >> + if (CompareMem ((PCI_DEVICE_PATH *)UsbCdcDataPath, >> (PCI_DEVICE_PATH *)UsbEthPath, sizeof (PCI_DEVICE_PATH))) { >> >> + return EFI_NOT_FOUND; >> >> + } >> >> + } >> >> + >> >> + if ((UsbEthPath->Type == MESSAGING_DEVICE_PATH) && >> (UsbEthPath->SubType == MSG_USB_DP)) { >> >> + if (IsDevicePathEnd (NextDevicePathNode (UsbEthPath))) { >> >> + if (((USB_DEVICE_PATH *)UsbEthPath)->ParentPortNumber == >> >> + ((USB_DEVICE_PATH *)UsbCdcDataPath)->ParentPortNumber) >> >> + { >> >> + return EFI_SUCCESS; >> >> + } else { >> >> + return EFI_NOT_FOUND; >> >> + } >> >> + } else { >> >> + if (CompareMem ((USB_DEVICE_PATH *)UsbCdcDataPath, >> (USB_DEVICE_PATH *)UsbEthPath, sizeof (USB_DEVICE_PATH))) { >> >> + return EFI_NOT_FOUND; >> >> + } >> >> + } >> >> + } >> >> + >> >> + UsbEthPath = NextDevicePathNode (UsbEthPath); >> >> + UsbCdcDataPath = NextDevicePathNode (UsbCdcDataPath); >> >> + } >> >> +} >> >> + >> >> +/** >> >> + Check if the USB CDC Data(UsbIo) installed and return USB CDC Data >> Handle. >> >> + >> >> + @param[in] UsbEthPath A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> >> + @param[in, out] UsbCdcDataHandle A pointer to the EFI_HANDLE for >> USB CDC Data. >> >> + >> >> + @retval TRUE USB CDC Data(UsbIo) installed. >> >> + @retval FALSE USB CDC Data(UsbIo) did not installed. >> >> + >> >> +**/ >> >> +BOOLEAN >> >> +IsUsbCdcData ( >> >> + IN EFI_DEVICE_PATH_PROTOCOL *UsbEthPath, >> >> + IN OUT EFI_HANDLE *UsbCdcDataHandle >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINTN Index; >> >> + UINTN HandleCount; >> >> + EFI_HANDLE *HandleBuffer; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + EFI_USB_INTERFACE_DESCRIPTOR Interface; >> >> + EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath; >> >> + >> >> + Status = gBS->LocateHandleBuffer ( >> >> + ByProtocol, >> >> + &gEfiUsbIoProtocolGuid, >> >> + NULL, >> >> + &HandleCount, >> >> + &HandleBuffer >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return FALSE; >> >> + } >> >> + >> >> + for (Index = 0; Index < HandleCount; Index++) { >> >> + Status = gBS->HandleProtocol ( >> >> + HandleBuffer[Index], >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo >> >> + ); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + if ((Interface.InterfaceClass == USB_CDC_DATA_CLASS) && >> >> + (Interface.InterfaceSubClass == USB_CDC_DATA_SUBCLASS) && >> >> + (Interface.InterfaceProtocol == USB_NCM_NTB_PROTOCOL)) >> >> + { >> >> + Status = gBS->HandleProtocol ( >> >> + HandleBuffer[Index], >> >> + &gEfiDevicePathProtocolGuid, >> >> + (VOID **)&UsbCdcDataPath >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + continue; >> >> + } >> >> + >> >> + Status = IsSameDevice (UsbEthPath, UsbCdcDataPath); >> >> + if (!EFI_ERROR (Status)) { >> >> + CopyMem (UsbCdcDataHandle, &HandleBuffer[Index], sizeof >> (EFI_HANDLE)); >> >> + gBS->FreePool (HandleBuffer); >> >> + return TRUE; >> >> + } >> >> + } >> >> + } >> >> + >> >> + gBS->FreePool (HandleBuffer); >> >> + return FALSE; >> >> +} >> >> + >> >> +/** >> >> + Call Back Function. >> >> + >> >> + @param[in] Event Event whose notification function is being >> invoked. >> >> + @param[in] Context The pointer to the notification function's >> context, >> >> + which is implementation-dependent. >> >> + >> >> +**/ >> >> +VOID >> >> +EFIAPI >> >> +CallbackFunction ( >> >> + IN EFI_EVENT Event, >> >> + IN VOID *Context >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINTN Index; >> >> + UINTN HandleCount; >> >> + EFI_HANDLE *HandleBuffer; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + EFI_USB_INTERFACE_DESCRIPTOR Interface; >> >> + >> >> + Status = gBS->LocateHandleBuffer ( >> >> + ByProtocol, >> >> + &gEfiUsbIoProtocolGuid, >> >> + NULL, >> >> + &HandleCount, >> >> + &HandleBuffer >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return; >> >> + } >> >> + >> >> + for (Index = 0; Index < HandleCount; Index++) { >> >> + Status = gBS->HandleProtocol ( >> >> + HandleBuffer[Index], >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo >> >> + ); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + if ((Interface.InterfaceClass == USB_CDC_CLASS) && >> >> + (Interface.InterfaceSubClass == USB_CDC_NCM_SUBCLASS) && >> >> + (Interface.InterfaceProtocol == USB_NO_CLASS_PROTOCOL)) >> >> + { >> >> + gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE); >> >> + } >> >> + } >> >> + >> >> + gBS->FreePool (HandleBuffer); >> >> + gBS->CloseEvent (Event); >> >> +} >> >> + >> >> +/** >> >> + USB NCM Driver Binding Start. >> >> + >> >> + @param[in] This Protocol instance pointer. >> >> + @param[in] ControllerHandle Handle of device to bind driver to. >> >> + @param[in] RemainingDevicePath Optional parameter use to pick a >> specific child >> >> + device to start. >> >> + >> >> + @retval EFI_SUCCESS This driver is added to >> ControllerHandle >> >> + @retval EFI_DEVICE_ERROR This driver could not be started >> due to a device error >> >> + @retval EFI_OUT_OF_RESOURCES The driver could not install >> successfully due to a lack of resources. >> >> + @retval other This driver does not support this >> device >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbNcmDriverStart ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + VOID *Reg; >> >> + EFI_EVENT Event; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + EFI_DEVICE_PATH_PROTOCOL *UsbEthPath; >> >> + EFI_HANDLE UsbCdcDataHandle; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + EFI_USB_INTERFACE_DESCRIPTOR Interface; >> >> + >> >> + Status = gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status = gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + (VOID **)&UsbEthPath, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return Status; >> >> + } >> >> + >> >> + Status = IsUsbCdcData (UsbEthPath, &UsbCdcDataHandle) ? EFI_SUCCESS : >> EFI_UNSUPPORTED; >> >> + if (EFI_ERROR (Status)) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + >> >> + Status = gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, >> CallbackFunction, NULL, &Event); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status = gBS->RegisterProtocolNotify (&gEfiUsbIoProtocolGuid, Event, >> &Reg); >> >> + return Status; >> >> + } >> >> + >> >> + UsbEthDriver = AllocateZeroPool (sizeof (USB_ETHERNET_DRIVER)); >> >> + if (!UsbEthDriver) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return EFI_OUT_OF_RESOURCES; >> >> + } >> >> + >> >> + Status = LoadAllDescriptor (UsbIo, &UsbEthDriver->Config); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + GetEndpoint (UsbIo, UsbEthDriver); >> >> + >> >> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + UsbEthDriver->Signature = >> USB_ETHERNET_SIGNATURE; >> >> + UsbEthDriver->NumOfInterface = >> Interface.InterfaceNumber; >> >> + UsbEthDriver->UsbCdcDataHandle = UsbCdcDataHandle; >> >> + UsbEthDriver->UsbIo = UsbIo; >> >> + UsbEthDriver->UsbEth.UsbEthReceive = UsbEthReceive; >> >> + UsbEthDriver->UsbEth.UsbEthTransmit = UsbEthTransmit; >> >> + UsbEthDriver->UsbEth.UsbEthInterrupt = UsbEthInterrupt; >> >> + UsbEthDriver->UsbEth.UsbEthMacAddress = GetUsbEthMacAddress; >> >> + UsbEthDriver->UsbEth.UsbEthMaxBulkSize = UsbEthBulkSize; >> >> + UsbEthDriver->UsbEth.UsbHeaderFunDescriptor = >> GetUsbHeaderFunDescriptor; >> >> + UsbEthDriver->UsbEth.UsbUnionFunDescriptor = >> GetUsbUnionFunDescriptor; >> >> + UsbEthDriver->UsbEth.UsbEthFunDescriptor = >> GetUsbEthFunDescriptor; >> >> + UsbEthDriver->UsbEth.SetUsbEthMcastFilter = >> SetUsbEthMcastFilter; >> >> + UsbEthDriver->UsbEth.SetUsbEthPowerPatternFilter = >> SetUsbEthPowerFilter; >> >> + UsbEthDriver->UsbEth.GetUsbEthPoewrPatternFilter = >> GetUsbEthPowerFilter; >> >> + UsbEthDriver->UsbEth.SetUsbEthPacketFilter = >> SetUsbEthPacketFilter; >> >> + UsbEthDriver->UsbEth.GetUsbEthStatistic = GetUsbEthStatistic; >> >> + >> >> + UsbEthDriver->BulkBuffer = AllocateZeroPool (USB_NCM_MAX_NTB_SIZE); >> >> + >> >> + Status = gBS->InstallProtocolInterface ( >> >> + &ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + EFI_NATIVE_INTERFACE, >> >> + &(UsbEthDriver->UsbEth) >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + gBS->FreePool (UsbEthDriver); >> >> + return Status; >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + USB NCM Driver Binding Stop. >> >> + >> >> + @param[in] This Protocol instance pointer. >> >> + @param[in] ControllerHandle Handle of device to stop driver on >> >> + @param[in] NumberOfChildren Number of Handles in >> ChildHandleBuffer. If number of >> >> + children is zero stop the entire bus >> driver. >> >> + @param[in] ChildHandleBuffer List of Child Handles to Stop. >> >> + >> >> + @retval EFI_SUCCESS This driver is removed >> ControllerHandle >> >> + @retval other This driver was not removed from >> this device >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbNcmDriverStop ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN UINTN NumberOfChildren, >> >> + IN EFI_HANDLE *ChildHandleBuffer >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_PROTOCOL *UsbEthProtocol; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + Status = gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + (VOID **)&UsbEthProtocol, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (UsbEthProtocol); >> >> + >> >> + Status = gBS->UninstallProtocolInterface ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + UsbEthProtocol >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status = gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + gBS->FreePool (UsbEthDriver->Config); >> >> + gBS->FreePool (UsbEthDriver->BulkBuffer); >> >> + gBS->FreePool (UsbEthDriver); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Entrypoint of NCM Driver. >> >> + >> >> + This function is the entrypoint of NCM Driver. It installs Driver >> Binding >> >> + Protocols together with Component Name Protocols. >> >> + >> >> + @param[in] ImageHandle The firmware allocated handle for the >> EFI image. >> >> + @param[in] SystemTable A pointer to the EFI System Table. >> >> + >> >> + @retval EFI_SUCCESS The entry point is executed successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbNcmEntry ( >> >> + IN EFI_HANDLE ImageHandle, >> >> + IN EFI_SYSTEM_TABLE *SystemTable >> >> + ) >> >> +{ >> >> + gUsbNcmDriverBinding.DriverBindingHandle = ImageHandle; >> >> + gUsbNcmDriverBinding.ImageHandle = ImageHandle; >> >> + >> >> + return gBS->InstallMultipleProtocolInterfaces ( >> >> + &gUsbNcmDriverBinding.DriverBindingHandle, >> >> + &gEfiDriverBindingProtocolGuid, >> >> + &gUsbNcmDriverBinding, >> >> + &gEfiComponentName2ProtocolGuid, >> >> + &gUsbNcmComponentName2, >> >> + NULL >> >> + ); >> >> +} >> >> diff --git a/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.h >> b/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.h >> new file mode 100644 >> index 0000000000..40b2671a1e >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.h >> @@ -0,0 +1,245 @@ >> +/** @file >> >> + Header file for USB Network Control Model driver >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#ifndef _USB_CDC_NCM_H_ >> >> +#define _USB_CDC_NCM_H_ >> >> + >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> + >> >> +typedef struct { >> >> + UINTN Signature; >> >> + USB_ETHERNET_PROTOCOL UsbEth; >> >> + EFI_HANDLE UsbCdcDataHandle; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + EFI_USB_CONFIG_DESCRIPTOR *Config; >> >> + UINT8 NumOfInterface; >> >> + UINT8 BulkInEndpoint; >> >> + UINT8 BulkOutEndpoint; >> >> + UINT8 InterruptEndpoint; >> >> + EFI_MAC_ADDRESS MacAddress; >> >> + UINT16 BulkOutSequence; >> >> + UINT8 *BulkBuffer; >> >> + UINT8 TotalDatagram; >> >> + UINT8 NowDatagram; >> >> +} USB_ETHERNET_DRIVER; >> >> + >> >> +#define USB_NCM_DRIVER_VERSION 1 >> >> +#define USB_ETHERNET_BULK_TIMEOUT 1 >> >> +#define USB_ETHERNET_TRANSFER_TIMEOUT 200 >> >> +#define USB_NCM_MAX_NTB_SIZE 0xFFFF >> >> +#define USB_ETH_FRAME_SIZE 0x5F2 // frome network stack snp >> >> + >> >> +// Defined in USB NCM 1.0 spec., section 3.2 and 3.3 >> >> +#define USB_NCM_NTH_SIGN_16 0x484D434E >> >> +#define USB_NCM_NDP_SIGN_16 0x304D434E >> >> +#define USB_NCM_NDP_SIGN_16_CRC 0x314D434E >> >> +#define USB_NCM_NTH_LENGTH 0x000C >> >> +#define USB_NCM_NDP_LENGTH 0x0010// at least 16 >> >> + >> >> +// USB NCM Transfer header structure - UINT16 >> >> +typedef struct { >> >> + UINT32 Signature; >> >> + UINT16 HeaderLength; >> >> + UINT16 Sequence; >> >> + UINT16 BlockLength; >> >> + UINT16 NdpIndex; >> >> +} USB_NCM_TRANSFER_HEADER_16; >> >> + >> >> +// USB NCM Datagram pointer structure - UINT16 >> >> +typedef struct { >> >> + UINT32 Signature; >> >> + UINT16 Length; >> >> + UINT16 NextNdpIndex; >> >> +} USB_NCM_DATAGRAM_POINTER_16; >> >> + >> >> +// USB NCM Datagram structure >> >> +typedef struct { >> >> + UINT16 DatagramIndex; >> >> + UINT16 DatagramLength; >> >> +} USB_NCM_DATA_GRAM; >> >> + >> >> +#define USB_ETHERNET_SIGNATURE SIGNATURE_32('u', 'e', 't', 'h') >> >> +#define USB_ETHERNET_DEV_FROM_THIS(a) CR (a, USB_ETHERNET_DRIVER, >> UsbEth, USB_ETHERNET_SIGNATURE) >> >> + >> >> +typedef struct { >> >> + UINT16 Src; >> >> + UINT16 Dst; >> >> +} BIT_MAP; >> >> + >> >> +extern EFI_COMPONENT_NAME2_PROTOCOL gUsbNcmComponentName2; >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbNcmDriverSupported ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbNcmDriverStart ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbNcmDriverStop ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN UINTN NumberOfChildren, >> >> + IN EFI_HANDLE *ChildHandleBuffer >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +LoadAllDescriptor ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> >> + OUT EFI_USB_CONFIG_DESCRIPTOR **ConfigDesc >> >> + ); >> >> + >> >> +BOOLEAN >> >> +NextDescriptor ( >> >> + IN EFI_USB_CONFIG_DESCRIPTOR *Desc, >> >> + IN OUT UINTN *Offset >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +GetFunctionalDescriptor ( >> >> + IN EFI_USB_CONFIG_DESCRIPTOR *Config, >> >> + IN UINT8 FunDescriptorType, >> >> + OUT VOID *DataBuffer >> >> + ); >> >> + >> >> +VOID >> >> +GetEndpoint ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> >> + IN OUT USB_ETHERNET_DRIVER *UsbEthDriver >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthReceive ( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN OUT VOID *Packet, >> >> + IN OUT UINTN *PacketLength >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthTransmit ( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN VOID *Packet, >> >> + IN OUT UINTN *PacketLength >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthInterrupt ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN BOOLEAN IsNewTransfer, >> >> + IN UINTN PollingInterval, >> >> + IN EFI_USB_DEVICE_REQUEST *Request >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +InterruptCallback ( >> >> + IN VOID *Data, >> >> + IN UINTN DataLength, >> >> + IN VOID *Context, >> >> + IN UINT32 Status >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthMacAddress ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT EFI_MAC_ADDRESS *MacAddress >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthBulkSize ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT UINTN *BulkSize >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbHeaderFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbUnionFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbEthMcastFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN VOID *McastAddr >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbEthPowerFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN UINT16 Length, >> >> + IN VOID *PatternFilter >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthPowerFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + OUT BOOLEAN *PatternActive >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbEthPacketFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthStatistic ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 FeatureSelector, >> >> + OUT VOID *Statistic >> >> + ); >> >> + >> >> +#endif >> >> diff --git a/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf >> b/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf >> new file mode 100644 >> index 0000000000..cfbf9ad720 >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf >> @@ -0,0 +1,41 @@ >> +## @file >> +# This is Usb Cdc Ncm driver for DXE phase. >> +# >> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> +# Subject to AMI licensing agreement. >> +## >> + >> +[Defines] >> + INF_VERSION = 0x00010005 >> + BASE_NAME = UsbCdcNcm >> + FILE_GUID = 52230d31-6c11-4442-b262-bec6bfe84efa >> + MODULE_TYPE = DXE_DRIVER >> + VERSION_STRING = 1.0 >> + ENTRY_POINT = UsbNcmEntry >> + >> +[Sources] >> + UsbCdcNcm.c >> + UsbCdcNcm.h >> + UsbNcmFunction.c >> + ComponentName.c >> + >> +[Packages] >> + MdePkg/MdePkg.dec >> + UsbNetworkPkg/UsbNetworkPkg.dec >> + >> +[LibraryClasses] >> + UefiDriverEntryPoint >> + UefiBootServicesTableLib >> + UefiLib >> + DebugLib >> + UefiUsbLib >> + MemoryAllocationLib >> + BaseMemoryLib >> + >> +[Protocols] >> + gEfiUsbIoProtocolGuid >> + gEfiDevicePathProtocolGuid >> + gEfiDriverBindingProtocolGuid >> + >> +[Depex] >> + TRUE >> \ No newline at end of file >> diff --git a/UsbNetworkPkg/UsbCdcNcm/UsbNcmFunction.c >> b/UsbNetworkPkg/UsbCdcNcm/UsbNcmFunction.c >> new file mode 100644 >> index 0000000000..98bcf6d6d5 >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbCdcNcm/UsbNcmFunction.c >> @@ -0,0 +1,946 @@ >> +/** @file >> >> + This file contains code for USB Ethernet descriptor >> >> + and specific requests implement. >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#include "UsbCdcNcm.h" >> >> + >> >> +/** >> >> + Load All of device descriptor. >> >> + >> >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL >> instance. >> >> + @param[out] ConfigDesc A pointer to the configuration >> descriptor. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_OUT_OF_RESOURCES The request could not be completed >> because the >> >> + buffer specified by DescriptorLength and >> Descriptor >> >> + is not large enough to hold the result >> of the request. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device >> error. The transfer >> >> + status is returned in Status. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +LoadAllDescriptor ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> >> + OUT EFI_USB_CONFIG_DESCRIPTOR **ConfigDesc >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINT32 TransStatus; >> >> + EFI_USB_CONFIG_DESCRIPTOR Tmp; >> >> + >> >> + Status = UsbIo->UsbGetConfigDescriptor (UsbIo, &Tmp); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status = gBS->AllocatePool (EfiBootServicesData, Tmp.TotalLength, >> (VOID **)ConfigDesc); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status = UsbGetDescriptor ( >> >> + UsbIo, >> >> + USB_DESC_TYPE_CONFIG << 8 | (Tmp.ConfigurationValue - 1), >> // zero based >> >> + 0, >> >> + Tmp.TotalLength, >> >> + *ConfigDesc, >> >> + &TransStatus >> >> + ); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Returns pointer to the next descriptor for the pack of USB descriptors >> >> + located in continues memory segment >> >> + >> >> + @param[in] Desc A pointer to the CONFIG_DESCRIPTOR instance. >> >> + @param[in, out] Offset A pointer to the sum of descriptor length. >> >> + >> >> + @retval TRUE The request executed successfully. >> >> + @retval FALSE No next descriptor. >> >> + >> >> +**/ >> >> +BOOLEAN >> >> +NextDescriptor ( >> >> + IN EFI_USB_CONFIG_DESCRIPTOR *Desc, >> >> + IN OUT UINTN *Offset >> >> + ) >> >> +{ >> >> + if ((Desc == NULL) || (*Offset >= Desc->TotalLength)) { >> >> + return FALSE; >> >> + } >> >> + >> >> + if (((EFI_USB_CONFIG_DESCRIPTOR *)((char *)Desc+*Offset))->Length == >> 0) { >> >> + return FALSE; >> >> + } >> >> + >> >> + *Offset += ((EFI_USB_CONFIG_DESCRIPTOR *)((char >> *)Desc+*Offset))->Length; >> >> + if ( *Offset >= Desc->TotalLength ) { >> >> + return FALSE; >> >> + } >> >> + >> >> + return TRUE; >> >> +} >> >> + >> >> +/** >> >> + Read Function descriptor >> >> + >> >> + @param[in] Config A pointer to all of configuration. >> >> + @param[in] FunDescriptorType USB CDC class descriptor SubType. >> >> + @param[out] DataBuffer A pointer to the Data of corresponding >> to device capability. >> >> + >> >> + @retval EFI_SUCCESS The device capability descriptor was >> retrieved >> >> + successfully. >> >> + @retval EFI_UNSUPPORTED No supported. >> >> + @retval EFI_NOT_FOUND The device capability descriptor was not >> found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +GetFunctionalDescriptor ( >> >> + IN EFI_USB_CONFIG_DESCRIPTOR *Config, >> >> + IN UINT8 FunDescriptorType, >> >> + OUT VOID *DataBuffer >> >> + ) >> >> +{ >> >> + EFI_STATUS Status = EFI_NOT_FOUND; >> >> + UINTN Offset; >> >> + EFI_USB_INTERFACE_DESCRIPTOR *Interface; >> >> + >> >> + for (Offset = 0; NextDescriptor (Config, &Offset);) { >> >> + Interface = (EFI_USB_INTERFACE_DESCRIPTOR *)((UINT8 *)Config + >> Offset); >> >> + if (Interface->DescriptorType == CS_INTERFACE) { >> >> + if (((USB_HEADER_FUN_DESCRIPTOR *)Interface)->DescriptorSubtype == >> FunDescriptorType) { >> >> + switch (FunDescriptorType) { >> >> + case HEADER_FUN_DESCRIPTOR: >> >> + CopyMem ( >> >> + DataBuffer, >> >> + (USB_HEADER_FUN_DESCRIPTOR *)Interface, >> >> + sizeof (USB_HEADER_FUN_DESCRIPTOR) >> >> + ); >> >> + return EFI_SUCCESS; >> >> + case UNION_FUN_DESCRIPTOR: >> >> + CopyMem ( >> >> + DataBuffer, >> >> + (USB_UNION_FUN_DESCRIPTOR *)Interface, >> >> + ((USB_UNION_FUN_DESCRIPTOR *)Interface)->FunctionLength >> >> + ); >> >> + return EFI_SUCCESS; >> >> + case ETHERNET_FUN_DESCRIPTOR: >> >> + CopyMem ( >> >> + DataBuffer, >> >> + (USB_ETHERNET_FUN_DESCRIPTOR *)Interface, >> >> + sizeof (USB_ETHERNET_FUN_DESCRIPTOR) >> >> + ); >> >> + return EFI_SUCCESS; >> >> + default: >> >> + Status = EFI_UNSUPPORTED; >> >> + break; >> >> + } >> >> + } >> >> + } >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Get USB Ethernet IO endpoint and USB CDC data IO endpoint. >> >> + >> >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL >> instance. >> >> + @param[in, out] UsbEthDriver A pointer to the USB_ETHERNET_DRIVER >> instance. >> >> + >> >> +**/ >> >> +VOID >> >> +GetEndpoint ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> >> + IN OUT USB_ETHERNET_DRIVER *UsbEthDriver >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINT8 Index; >> >> + UINT32 Result; >> >> + EFI_USB_INTERFACE_DESCRIPTOR Interface; >> >> + EFI_USB_ENDPOINT_DESCRIPTOR Endpoint; >> >> + >> >> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + if (Interface.NumEndpoints == 0) { >> >> + Status = UsbSetInterface (UsbIo, Interface.InterfaceNumber, 1, >> &Result); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> >> + ASSERT_EFI_ERROR (Status); >> >> + } >> >> + >> >> + for (Index = 0; Index < Interface.NumEndpoints; Index++) { >> >> + Status = UsbIo->UsbGetEndpointDescriptor (UsbIo, Index, &Endpoint); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + switch ((Endpoint.Attributes & (BIT0 | BIT1))) { >> >> + case USB_ENDPOINT_BULK: >> >> + if (Endpoint.EndpointAddress & BIT7) { >> >> + UsbEthDriver->BulkInEndpoint = Endpoint.EndpointAddress; >> >> + } else { >> >> + UsbEthDriver->BulkOutEndpoint = Endpoint.EndpointAddress; >> >> + } >> >> + >> >> + break; >> >> + case USB_ENDPOINT_INTERRUPT: >> >> + UsbEthDriver->InterruptEndpoint = Endpoint.EndpointAddress; >> >> + break; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This function is used to manage a USB device with the bulk transfer >> pipe. The endpoint is Bulk in. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor >> block. >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in, out] Packet A pointer to the buffer of data that >> will be transmitted to USB >> >> + device or received from USB device. >> >> + @param[in, out] PacketLength A pointer to the PacketLength. >> >> + >> >> + @retval EFI_SUCCESS The bulk transfer has been successfully >> executed. >> >> + @retval EFI_DEVICE_ERROR The transfer failed. The transfer status >> is returned in status. >> >> + @retval EFI_INVALID_PARAMETE One or more parameters are invalid. >> >> + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due >> to a lack of resources. >> >> + @retval EFI_TIMEOUT The control transfer fails due to >> timeout. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthReceive ( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN OUT VOID *Packet, >> >> + IN OUT UINTN *PacketLength >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + UINT32 TransStatus; >> >> + UINT8 Index; >> >> + UINTN BulkDataLenght; >> >> + UINTN TotalLength = 0; >> >> + USB_NCM_TRANSFER_HEADER_16 *Nth; >> >> + USB_NCM_DATAGRAM_POINTER_16 *Ndp; >> >> + USB_NCM_DATA_GRAM *Datagram; >> >> + >> >> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + if (UsbEthDriver->TotalDatagram == UsbEthDriver->NowDatagram) { >> >> + Status = gBS->HandleProtocol ( >> >> + UsbEthDriver->UsbCdcDataHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + if (UsbEthDriver->BulkInEndpoint == 0) { >> >> + GetEndpoint (UsbIo, UsbEthDriver); >> >> + } >> >> + >> >> + BulkDataLenght = USB_NCM_MAX_NTB_SIZE; >> >> + SetMem (UsbEthDriver->BulkBuffer, BulkDataLenght, 0); >> >> + UsbEthDriver->NowDatagram = 0; >> >> + UsbEthDriver->TotalDatagram = 0; >> >> + >> >> + Status = UsbIo->UsbBulkTransfer ( >> >> + UsbIo, >> >> + UsbEthDriver->BulkInEndpoint, >> >> + UsbEthDriver->BulkBuffer, >> >> + &BulkDataLenght, >> >> + USB_ETHERNET_BULK_TIMEOUT, >> >> + &TransStatus >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Nth = (USB_NCM_TRANSFER_HEADER_16 >> *)UsbEthDriver->BulkBuffer; >> >> + Ndp = (USB_NCM_DATAGRAM_POINTER_16 *)((UINT8 >> *)UsbEthDriver->BulkBuffer + Nth->NdpIndex); >> >> + Datagram = (USB_NCM_DATA_GRAM *)((UINT8 *)Ndp + >> sizeof (USB_NCM_DATAGRAM_POINTER_16)); >> >> + UsbEthDriver->TotalDatagram = (UINT8)((Ndp->Length - 8) / 4 - 1); >> >> + >> >> + for (Index = 0; Index < UsbEthDriver->TotalDatagram; Index++) { >> >> + TotalLength += Datagram->DatagramLength; >> >> + Datagram = (USB_NCM_DATA_GRAM *)((UINT8 *)Datagram + sizeof >> (USB_NCM_DATA_GRAM)); >> >> + } >> >> + >> >> + if (TotalLength < USB_ETH_FRAME_SIZE) { >> >> + Datagram = (USB_NCM_DATA_GRAM *)((UINT8 *)Ndp + sizeof >> (USB_NCM_DATAGRAM_POINTER_16)); >> >> + >> >> + TotalLength = 0; >> >> + for (Index = 0; Index < UsbEthDriver->TotalDatagram; Index++) { >> >> + CopyMem ((UINT8 *)Packet + TotalLength, (UINT8 >> *)UsbEthDriver->BulkBuffer + Datagram->DatagramIndex, >> Datagram->DatagramLength); >> >> + TotalLength += Datagram->DatagramLength; >> >> + Datagram = (USB_NCM_DATA_GRAM *)((UINT8 *)Datagram + sizeof >> (USB_NCM_DATA_GRAM)); >> >> + } >> >> + >> >> + *PacketLength = TotalLength; >> >> + UsbEthDriver->NowDatagram = UsbEthDriver->TotalDatagram; >> >> + } else { >> >> + UsbEthDriver->NowDatagram++; >> >> + >> >> + Datagram = (USB_NCM_DATA_GRAM *)((UINT8 *)Ndp + sizeof >> (USB_NCM_DATAGRAM_POINTER_16)); >> >> + CopyMem (Packet, (UINT8 *)UsbEthDriver->BulkBuffer + >> Datagram->DatagramIndex, Datagram->DatagramLength); >> >> + *PacketLength = Datagram->DatagramLength; >> >> + } >> >> + >> >> + return Status; >> >> + } else { >> >> + UsbEthDriver->NowDatagram++; >> >> + >> >> + Nth = (USB_NCM_TRANSFER_HEADER_16 *)UsbEthDriver->BulkBuffer; >> >> + Ndp = (USB_NCM_DATAGRAM_POINTER_16 *)((UINT8 >> *)UsbEthDriver->BulkBuffer + Nth->NdpIndex); >> >> + Datagram = (USB_NCM_DATA_GRAM *)((UINT8 *)Ndp + sizeof >> (USB_NCM_DATAGRAM_POINTER_16)); >> >> + Datagram = (USB_NCM_DATA_GRAM *)((UINT8 *)Datagram + sizeof >> (USB_NCM_DATA_GRAM) * (UsbEthDriver->NowDatagram - 1)); >> >> + >> >> + CopyMem (Packet, (UINT8 *)UsbEthDriver->BulkBuffer + >> Datagram->DatagramIndex, Datagram->DatagramLength); >> >> + *PacketLength = Datagram->DatagramLength; >> >> + >> >> + return EFI_SUCCESS; >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This function is used to manage a USB device with the bulk transfer >> pipe. The endpoint is Bulk out. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor >> block. >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in] Packet A pointer to the buffer of data that >> will be transmitted to USB >> >> + device or received from USB device. >> >> + @param[in, out] PacketLength A pointer to the PacketLength. >> >> + >> >> + @retval EFI_SUCCESS The bulk transfer has been successfully >> executed. >> >> + @retval EFI_DEVICE_ERROR The transfer failed. The transfer status >> is returned in status. >> >> + @retval EFI_INVALID_PARAMETE One or more parameters are invalid. >> >> + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due >> to a lack of resources. >> >> + @retval EFI_TIMEOUT The control transfer fails due to >> timeout. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthTransmit ( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN VOID *Packet, >> >> + IN OUT UINTN *PacketLength >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + UINT32 TransStatus; >> >> + USB_NCM_TRANSFER_HEADER_16 *Nth; >> >> + USB_NCM_DATAGRAM_POINTER_16 *Ndp; >> >> + USB_NCM_DATA_GRAM *Datagram; >> >> + UINT8 *TotalPacket; >> >> + UINTN TotalLength; >> >> + >> >> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + Status = gBS->HandleProtocol ( >> >> + UsbEthDriver->UsbCdcDataHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + if (UsbEthDriver->BulkOutEndpoint == 0) { >> >> + GetEndpoint (UsbIo, UsbEthDriver); >> >> + } >> >> + >> >> + TotalLength = (UINTN)(USB_NCM_NTH_LENGTH + USB_NCM_NDP_LENGTH + >> (*PacketLength)); >> >> + >> >> + Status = gBS->AllocatePool (EfiBootServicesData, TotalLength, (VOID >> **)&TotalPacket); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + SetMem (TotalPacket, TotalLength, 0); >> >> + >> >> + Nth = (USB_NCM_TRANSFER_HEADER_16 *)TotalPacket; >> >> + Nth->Signature = USB_NCM_NTH_SIGN_16; >> >> + Nth->HeaderLength = USB_NCM_NTH_LENGTH; >> >> + Nth->Sequence = UsbEthDriver->BulkOutSequence++; >> >> + Nth->BlockLength = (UINT16)TotalLength; >> >> + Nth->NdpIndex = Nth->HeaderLength; >> >> + >> >> + Ndp = (USB_NCM_DATAGRAM_POINTER_16 *)((UINT8 >> *)TotalPacket + Nth->NdpIndex); >> >> + Ndp->Signature = USB_NCM_NDP_SIGN_16; >> >> + Ndp->Length = USB_NCM_NDP_LENGTH; >> >> + Ndp->NextNdpIndex = 0x00; >> >> + >> >> + Datagram = (USB_NCM_DATA_GRAM *)((UINT8 *)Ndp + sizeof >> (USB_NCM_DATAGRAM_POINTER_16)); >> >> + Datagram->DatagramIndex = Nth->HeaderLength + Ndp->Length; >> >> + Datagram->DatagramLength = (UINT16)*PacketLength; >> >> + >> >> + CopyMem (TotalPacket + Datagram->DatagramIndex, Packet, *PacketLength); >> >> + >> >> + *PacketLength = TotalLength; >> >> + >> >> + Status = UsbIo->UsbBulkTransfer ( >> >> + UsbIo, >> >> + UsbEthDriver->BulkOutEndpoint, >> >> + TotalPacket, >> >> + PacketLength, >> >> + USB_ETHERNET_BULK_TIMEOUT, >> >> + &TransStatus >> >> + ); >> >> + gBS->FreePool (TotalPacket); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Async USB transfer callback routine. >> >> + >> >> + @param[in] Data Data received or sent via the USB >> Asynchronous Transfer, if the >> >> + transfer completed successfully. >> >> + @param[in] DataLength The length of Data received or sent via >> the Asynchronous >> >> + Transfer, if transfer successfully >> completes. >> >> + @param[in] Context Data passed from >> UsbAsyncInterruptTransfer() request. >> >> + @param[in] Status Indicates the result of the asynchronous >> transfer. >> >> + >> >> + @retval EFI_SUCCESS The asynchronous USB transfer request >> has been successfully executed. >> >> + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request >> failed. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +InterruptCallback ( >> >> + IN VOID *Data, >> >> + IN UINTN DataLength, >> >> + IN VOID *Context, >> >> + IN UINT32 Status >> >> + ) >> >> +{ >> >> + if (((EFI_USB_DEVICE_REQUEST *)Data)->Request == >> USB_CDC_NETWORK_CONNECTION) { >> >> + CopyMem ( >> >> + (EFI_USB_DEVICE_REQUEST *)Context, >> >> + (EFI_USB_DEVICE_REQUEST *)Data, >> >> + sizeof (EFI_USB_DEVICE_REQUEST) >> >> + ); >> >> + } >> >> + >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This function is used to manage a USB device with an interrupt >> transfer pipe. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in] IsNewTransfer If TRUE, a new transfer will be >> submitted to USB controller. If >> >> + FALSE, the interrupt transfer is deleted >> from the device's interrupt >> >> + transfer queue. >> >> + @param[in] PollingInterval Indicates the periodic rate, in >> milliseconds, that the transfer is to be >> >> + executed.This parameter is required when >> IsNewTransfer is TRUE. The >> >> + value must be between 1 to 255, >> otherwise EFI_INVALID_PARAMETER is returned. >> >> + The units are in milliseconds. >> >> + @param[in] Request A pointer to the EFI_USB_DEVICE_REQUEST >> data. >> >> + >> >> + @retval EFI_SUCCESS The asynchronous USB transfer request >> transfer has been successfully executed. >> >> + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request >> failed. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthInterrupt ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN BOOLEAN IsNewTransfer, >> >> + IN UINTN PollingInterval, >> >> + IN EFI_USB_DEVICE_REQUEST *Request >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + UINTN DataLength = 0; >> >> + >> >> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This); >> >> + if (IsNewTransfer == TRUE) { >> >> + DataLength = sizeof (EFI_USB_DEVICE_REQUEST) + sizeof >> (USB_CONNECT_SPEED_CHANGE); >> >> + Status = UsbEthDriver->UsbIo->UsbAsyncInterruptTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + UsbEthDriver->InterruptEndpoint, >> >> + IsNewTransfer, >> >> + PollingInterval, >> >> + DataLength, >> >> + >> (EFI_ASYNC_USB_TRANSFER_CALLBACK)InterruptCallback, >> >> + Request >> >> + ); >> >> + } else { >> >> + Status = UsbEthDriver->UsbIo->UsbAsyncInterruptTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + UsbEthDriver->InterruptEndpoint, >> >> + IsNewTransfer, >> >> + 0, >> >> + 0, >> >> + NULL, >> >> + NULL >> >> + ); >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Ethernet Mac Address. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[out] MacAddress A pointer to the caller allocated USB >> Ethernet Mac Address. >> >> + >> >> + @retval EFI_SUCCESS The USB Header Functional descriptor was >> retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor was >> not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthMacAddress ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT EFI_MAC_ADDRESS *MacAddress >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthDescriptor; >> >> + CHAR16 *Data; >> >> + CHAR16 *DataPtr; >> >> + CHAR16 TmpStr[1]; >> >> + UINT8 Index; >> >> + UINT8 Hi; >> >> + UINT8 Low; >> >> + >> >> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + Status = This->UsbEthFunDescriptor (This, &UsbEthDescriptor); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status = UsbEthDriver->UsbIo->UsbGetStringDescriptor ( >> >> + UsbEthDriver->UsbIo, >> >> + 0x409, // >> English-US Language ID >> >> + UsbEthDescriptor.MacAddress, >> >> + &Data >> >> + ); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + DataPtr = Data; >> >> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> >> + CopyMem (TmpStr, DataPtr, sizeof (CHAR16)); >> >> + DataPtr++; >> >> + Hi = (UINT8)StrHexToUintn (TmpStr); >> >> + CopyMem (TmpStr, DataPtr, sizeof (CHAR16)); >> >> + DataPtr++; >> >> + Low = (UINT8)StrHexToUintn (TmpStr); >> >> + MacAddress->Addr[Index] = (Hi << 4) | Low; >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Get the USB NCM max NTB size. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[out] BulkSize A pointer to the Bulk transfer data size. >> >> + >> >> + @retval EFI_SUCCESS Get the USB NCM max NTB size >> successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthBulkSize ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT UINTN *BulkSize >> >> + ) >> >> +{ >> >> + *BulkSize = USB_NCM_MAX_NTB_SIZE; >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Header functional Descriptor. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[out] UsbHeaderFunDescriptor A pointer to the caller allocated >> USB Header Functional Descriptor. >> >> + >> >> + @retval EFI_SUCCESS The USB Header Functional descriptor was >> retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor was >> not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbHeaderFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + if (UsbHeaderFunDescriptor == NULL) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + Status = GetFunctionalDescriptor (UsbEthDriver->Config, >> HEADER_FUN_DESCRIPTOR, UsbHeaderFunDescriptor); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Union functional Descriptor. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[out] UsbUnionFunDescriptor A pointer to the caller allocated >> USB Union Functional Descriptor. >> >> + >> >> + @retval EFI_SUCCESS The USB Union Functional descriptor was >> retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbUnionFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Union Functional descriptor was >> not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbUnionFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + if (UsbUnionFunDescriptor == NULL) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + Status = GetFunctionalDescriptor (UsbEthDriver->Config, >> UNION_FUN_DESCRIPTOR, UsbUnionFunDescriptor); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Ethernet functional Descriptor. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[out] UsbEthFunDescriptor A pointer to the caller allocated >> USB Ethernet Functional Descriptor. >> >> + >> >> + @retval EFI_SUCCESS The USB Ethernet Functional descriptor >> was retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbEthFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Ethernet Functional descriptor >> was not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + if (UsbEthFunDescriptor == NULL) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + Status = GetFunctionalDescriptor (UsbEthDriver->Config, >> ETHERNET_FUN_DESCRIPTOR, UsbEthFunDescriptor); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + This request sets the Ethernet device multicast filters as specified >> in the >> >> + sequential list of 48 bit Ethernet multicast addresses. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] Value Number of filters. >> >> + @param[in] McastAddr A pointer to the value of the >> multicast addresses. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbEthMcastFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN VOID *McastAddr >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> + UINT32 TransStatus; >> >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + Status = This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + if ((UsbEthFunDescriptor.NumberMcFilters << 1) == 0) { >> >> + return EFI_UNSUPPORTED; >> >> + } >> >> + >> >> + Request.RequestType = USB_ETHRTNET_SET_REQ_TYPE; >> >> + Request.Request = SET_ETH_MULTICAST_FILTERS_REQ; >> >> + Request.Value = Value; >> >> + Request.Index = UsbEthDriver->NumOfInterface; >> >> + Request.Length = Value * 6; >> >> + >> >> + return UsbEthDriver->UsbIo->UsbControlTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + &Request, >> >> + EfiUsbDataOut, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + McastAddr, >> >> + Request.Length, >> >> + &TransStatus >> >> + ); >> >> +} >> >> + >> >> +/** >> >> + This request sets up the specified Ethernet power management pattern >> filter as >> >> + described in the data structure. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] Value Number of filters. >> >> + @param[in] Length Size of the power management pattern >> filter data. >> >> + @param[in] PatternFilter A pointer to the power management >> pattern filter structure. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbEthPowerFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN UINT16 Length, >> >> + IN VOID *PatternFilter >> >> + ) >> >> +{ >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> + UINT32 TransStatus; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + Request.RequestType = USB_ETHRTNET_SET_REQ_TYPE; >> >> + Request.Request = SET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ; >> >> + Request.Value = Value; >> >> + Request.Index = UsbEthDriver->NumOfInterface; >> >> + Request.Length = Length; >> >> + >> >> + return UsbEthDriver->UsbIo->UsbControlTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + &Request, >> >> + EfiUsbDataOut, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + PatternFilter, >> >> + Length, >> >> + &TransStatus >> >> + ); >> >> +} >> >> + >> >> +/** >> >> + This request retrieves the status of the specified Ethernet power >> management >> >> + pattern filter from the device. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] Value The filter number. >> >> + @param[out] PatternActive A pointer to the pattern active >> boolean. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthPowerFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + OUT BOOLEAN *PatternActive >> >> + ) >> >> +{ >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> + UINT32 TransStatus; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + Request.RequestType = USB_ETHERNET_GET_REQ_TYPE; >> >> + Request.Request = GET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ; >> >> + Request.Value = Value; >> >> + Request.Index = UsbEthDriver->NumOfInterface; >> >> + Request.Length = USB_ETH_POWER_FILTER_LENGTH; >> >> + >> >> + return UsbEthDriver->UsbIo->UsbControlTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + &Request, >> >> + EfiUsbDataIn, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + PatternActive, >> >> + USB_ETH_POWER_FILTER_LENGTH, >> >> + &TransStatus >> >> + ); >> >> +} >> >> + >> >> +BIT_MAP gTable[] = { >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_UNICAST, >> USB_ETH_PACKET_TYPE_DIRECTED }, >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST, >> USB_ETH_PACKET_TYPE_BROADCAST }, >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST, >> USB_ETH_PACKET_TYPE_MULTICAST }, >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS, >> USB_ETH_PACKET_TYPE_PROMISCUOUS }, >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST, >> USB_ETH_PACKET_TYPE_ALL_MULTICAST }, >> >> +}; >> >> + >> >> +/** >> >> + Convert value between PXE receive filter and USB ETH packet filter. >> >> + >> >> + @param[in] Value PXE filter data. >> >> + @param[out] CdcFilter A pointer to the Ethernet Packet Filter Bitmap >> value converted by PXE_OPFLAGS. >> >> + >> >> +**/ >> >> +VOID >> >> +ConvertFilter ( >> >> + IN UINT16 Value, >> >> + OUT UINT16 *CdcFilter >> >> + ) >> >> +{ >> >> + UINT32 Index; >> >> + UINT32 Count; >> >> + >> >> + Count = sizeof (gTable)/sizeof (gTable[0]); >> >> + >> >> + for (Index = 0; (gTable[Index].Src != 0) && (Index < Count); Index++) { >> >> + if (gTable[Index].Src & Value) { >> >> + *CdcFilter |= gTable[Index].Dst; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + This request is used to configure device Ethernet packet filter >> settings. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in] Value Packet Filter Bitmap. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbEthPacketFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value >> >> + ) >> >> +{ >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> + UINT32 TransStatus; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + UINT16 CommandFilter = 0; >> >> + >> >> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + ConvertFilter (Value, &CommandFilter); >> >> + >> >> + Request.RequestType = USB_ETHRTNET_SET_REQ_TYPE; >> >> + Request.Request = SET_ETH_PACKET_FILTER_REQ; >> >> + Request.Value = CommandFilter; >> >> + Request.Index = UsbEthDriver->NumOfInterface; >> >> + Request.Length = USB_ETH_PACKET_FILTER_LENGTH; >> >> + >> >> + return UsbEthDriver->UsbIo->UsbControlTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + &Request, >> >> + EfiUsbNoData, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + NULL, >> >> + USB_ETH_PACKET_FILTER_LENGTH, >> >> + &TransStatus >> >> + ); >> >> +} >> >> + >> >> +/** >> >> + This request is used to retrieve a statistic based on the feature >> selector. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] FeatureSelector Value of the feature selector. >> >> + @param[out] Statistic A pointer to the 32 bit unsigned >> integer. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthStatistic ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 FeatureSelector, >> >> + OUT VOID *Statistic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> + UINT32 TransStatus; >> >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; >> >> + USB_ETHERNET_DRIVER *UsbEthDriver; >> >> + >> >> + UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This); >> >> + >> >> + Status = This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + if (UsbEthFunDescriptor.EthernetStatistics == 0) { >> >> + return EFI_UNSUPPORTED; >> >> + } >> >> + >> >> + Request.RequestType = USB_ETHERNET_GET_REQ_TYPE; >> >> + Request.Request = GET_ETH_STATISTIC_REQ; >> >> + Request.Value = FeatureSelector; >> >> + Request.Index = UsbEthDriver->NumOfInterface; >> >> + Request.Length = USB_ETH_STATISTIC; >> >> + >> >> + return UsbEthDriver->UsbIo->UsbControlTransfer ( >> >> + UsbEthDriver->UsbIo, >> >> + &Request, >> >> + EfiUsbDataIn, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + Statistic, >> >> + USB_ETH_STATISTIC, >> >> + &TransStatus >> >> + ); >> >> +} >> >> diff --git a/UsbNetworkPkg/UsbNetworkPkg.dec >> b/UsbNetworkPkg/UsbNetworkPkg.dec >> new file mode 100644 >> index 0000000000..4ffafd99ed >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbNetworkPkg.dec >> @@ -0,0 +1,32 @@ >> +## @file >> +# This package defines Usb network specific interfaces and library >> classes >> +# as well as configuration for standard edk2 packages. >> +# >> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> +# Subject to AMI licensing agreement. >> +## >> + >> +[Defines] >> + DEC_SPECIFICATION = 0x00010005 >> + PACKAGE_NAME = UsbNetworkPkg >> + PACKAGE_GUID = abfab91e-37ea-4cb4-80a6-563dbb0bcec6 >> + PACKAGE_VERSION = 0.1 >> + >> +[Includes] >> + Include >> + >> +[Guids] >> + ## Usb Network package token space GUID >> + gUsbNetworkPkgTokenSpaceGuid = { 0xA1231E82, 0x21B8, 0x4204, { 0x92, >> 0xBB, 0x37, 0x3A, 0xFB, 0x01, 0xC6, 0xA1 } } >> + >> +[PcdsFeatureFlag] >> + >> + ## Set the PCD 'UsbCdcEcmSupport' to 'TRUE' if 'Usb Cdc Ecm device' >> need to be enabled. >> + gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport|FALSE|BOOLEAN|0x00000001 >> + >> + ## Set the PCD 'UsbCdcNcmSupport' to 'TRUE' if 'Usb Cdc Ncm device' >> need to be enabled. >> + gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport|FALSE|BOOLEAN|0x00000002 >> + >> + ## Set the PCD 'UsbRndisSupport' to 'TRUE' if 'Usb Rndis device' need >> to be enabled. >> + gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport|TRUE|BOOLEAN|0x00000003 >> + >> diff --git a/UsbNetworkPkg/UsbRndis/ComponentName.c >> b/UsbNetworkPkg/UsbRndis/ComponentName.c >> new file mode 100644 >> index 0000000000..6b7891afd9 >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbRndis/ComponentName.c >> @@ -0,0 +1,172 @@ >> +/** @file >> >> + This file contains code for USB RNDIS Driver Component >> >> + Name definitions >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#include "UsbRndis.h" >> >> + >> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE >> gUsbRndisDriverNameTable[] = { >> >> + { >> >> + "eng;en", >> >> + L"USB RNDIS Driver" >> >> + }, >> >> + { >> >> + NULL, >> >> + NULL >> >> + } >> >> +}; >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbRndisComponentNameGetDriverName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **DriverName >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbRndisComponentNameGetControllerName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN EFI_HANDLE Controller, >> >> + IN EFI_HANDLE ChildHandle OPTIONAL, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **ControllerName >> >> + ); >> >> + >> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL >> gUsbRndisComponentName = { >> >> + UsbRndisComponentNameGetDriverName, >> >> + UsbRndisComponentNameGetControllerName, >> >> + "eng" >> >> +}; >> >> + >> >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL >> gUsbRndisComponentName2 = { >> >> + >> (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)UsbRndisComponentNameGetDriverName, >> >> + >> (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)UsbRndisComponentNameGetControllerName, >> >> + "en" >> >> +}; >> >> + >> >> +/** >> >> + Retrieves a Unicode string that is the user readable name of the >> driver. >> >> + >> >> + This function retrieves the user readable name of a driver in the form >> of a >> >> + Unicode string. If the driver specified by This has a user readable >> name in >> >> + the language specified by Language, then a pointer to the driver name >> is >> >> + returned in DriverName, and EFI_SUCCESS is returned. If the driver >> specified >> >> + by This does not support the language specified by Language, >> >> + then EFI_UNSUPPORTED is returned. >> >> + >> >> + @param[in] This A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >> >> + EFI_COMPONENT_NAME_PROTOCOL instance. >> >> + @param[in] Language A pointer to a Null-terminated ASCII >> string >> >> + array indicating the language. This is >> the >> >> + language of the driver name that the >> caller is >> >> + requesting, and it must match one of the >> >> + languages specified in >> SupportedLanguages. The >> >> + number of languages supported by a >> driver is up >> >> + to the driver writer. Language is >> specified >> >> + in RFC 4646 or ISO 639-2 language code >> format. >> >> + @param[out] DriverName A pointer to the Unicode string to >> return. >> >> + This Unicode string is the name of the >> >> + driver specified by This in the language >> >> + specified by Language. >> >> + >> >> + @retval EFI_SUCCESS The Unicode string for the Driver >> specified by >> >> + This and the language specified by >> Language was >> >> + returned in DriverName. >> >> + @retval EFI_INVALID_PARAMETER Language is NULL. >> >> + @retval EFI_INVALID_PARAMETER DriverName is NULL. >> >> + @retval EFI_UNSUPPORTED The driver specified by This does not >> support >> >> + the language specified by Language. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbRndisComponentNameGetDriverName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **DriverName >> >> + ) >> >> +{ >> >> + return LookupUnicodeString2 ( >> >> + Language, >> >> + This->SupportedLanguages, >> >> + gUsbRndisDriverNameTable, >> >> + DriverName, >> >> + (BOOLEAN)(This == &gUsbRndisComponentName) >> >> + ); >> >> +} >> >> + >> >> +/** >> >> + Retrieves a Unicode string that is the user readable name of the >> controller >> >> + that is being managed by a driver. >> >> + >> >> + This function retrieves the user readable name of the controller >> specified by >> >> + ControllerHandle and ChildHandle in the form of a Unicode string. If >> the >> >> + driver specified by This has a user readable name in the language >> specified by >> >> + Language, then a pointer to the controller name is returned in >> ControllerName, >> >> + and EFI_SUCCESS is returned. If the driver specified by This is not >> currently >> >> + managing the controller specified by ControllerHandle and ChildHandle, >> >> + then EFI_UNSUPPORTED is returned. If the driver specified by This >> does not >> >> + support the language specified by Language, then EFI_UNSUPPORTED is >> returned. >> >> + >> >> + @param[in] This A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >> >> + EFI_COMPONENT_NAME_PROTOCOL instance. >> >> + @param[in] Controller The handle of a controller that the >> driver >> >> + specified by This is managing. This >> handle >> >> + specifies the controller whose name is >> to be >> >> + returned. >> >> + @param[in] ChildHandle The handle of the child controller to >> retrieve >> >> + the name of. This is an optional >> parameter that >> >> + may be NULL. It will be NULL for device >> >> + drivers. It will also be NULL for a bus >> drivers >> >> + that wish to retrieve the name of the bus >> >> + controller. It will not be NULL for a >> bus >> >> + driver that wishes to retrieve the name >> of a >> >> + child controller. >> >> + @param[in] Language A pointer to a Null-terminated ASCII >> string >> >> + array indicating the language. This is >> the >> >> + language of the driver name that the >> caller is >> >> + requesting, and it must match one of the >> >> + languages specified in >> SupportedLanguages. The >> >> + number of languages supported by a >> driver is up >> >> + to the driver writer. Language is >> specified in >> >> + RFC 4646 or ISO 639-2 language code >> format. >> >> + @param[out] ControllerName A pointer to the Unicode string to >> return. >> >> + This Unicode string is the name of the >> >> + controller specified by ControllerHandle >> and >> >> + ChildHandle in the language specified by >> >> + Language from the point of view of the >> driver >> >> + specified by This. >> >> + >> >> + @retval EFI_SUCCESS The Unicode string for the user readable >> name in >> >> + the language specified by Language for >> the >> >> + driver specified by This was returned in >> >> + DriverName. >> >> + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid >> EFI_HANDLE. >> >> + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a >> valid >> >> + EFI_HANDLE. >> >> + @retval EFI_INVALID_PARAMETER Language is NULL. >> >> + @retval EFI_INVALID_PARAMETER ControllerName is NULL. >> >> + @retval EFI_UNSUPPORTED The driver specified by This is not >> currently >> >> + managing the controller specified by >> >> + ControllerHandle and ChildHandle. >> >> + @retval EFI_UNSUPPORTED The driver specified by This does not >> support >> >> + the language specified by Language. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbRndisComponentNameGetControllerName ( >> >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> >> + IN EFI_HANDLE Controller, >> >> + IN EFI_HANDLE ChildHandle OPTIONAL, >> >> + IN CHAR8 *Language, >> >> + OUT CHAR16 **ControllerName >> >> + ) >> >> +{ >> >> + return EFI_UNSUPPORTED; >> >> +} >> >> diff --git a/UsbNetworkPkg/UsbRndis/UsbRndis.c >> b/UsbNetworkPkg/UsbRndis/UsbRndis.c >> new file mode 100644 >> index 0000000000..a75355825b >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbRndis/UsbRndis.c >> @@ -0,0 +1,848 @@ >> +/** @file >> >> + This file contains code for USB Remote Network Driver >> >> + Interface Spec. Driver Binding >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#include "UsbRndis.h" >> >> + >> >> +EFI_GUID gUsbEthProtocolGuid = >> USB_ETHERNET_PROTOCOL_GUID; >> >> +extern EFI_COMPONENT_NAME2_PROTOCOL gUsbRndisComponentName2; >> >> + >> >> +EFI_DRIVER_BINDING_PROTOCOL gUsbRndisDriverBinding = { >> >> + UsbRndisDriverSupported, >> >> + UsbRndisDriverStart, >> >> + UsbRndisDriverStop, >> >> + USB_RNDIS_DRIVER_VERSION, >> >> + NULL, >> >> + NULL >> >> +}; >> >> + >> >> +/** >> >> + Check if this interface is USB Rndis SubType >> >> + >> >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance. >> >> + >> >> + @retval TRUE USB Rndis SubType. >> >> + @retval FALSE Not USB Rndis SubType. >> >> + >> >> +**/ >> >> +BOOLEAN >> >> +IsSupportedDevice ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; >> >> + >> >> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, >> &InterfaceDescriptor); >> >> + if (EFI_ERROR (Status)) { >> >> + return FALSE; >> >> + } >> >> + >> >> + // Check specific device/RNDIS and CDC-DATA >> >> + if (((InterfaceDescriptor.InterfaceClass == 0x2) && >> >> + (InterfaceDescriptor.InterfaceSubClass == 0x2) && >> >> + (InterfaceDescriptor.InterfaceProtocol == 0xFF)) || \ >> >> + ((InterfaceDescriptor.InterfaceClass == 0xEF) && >> >> + (InterfaceDescriptor.InterfaceSubClass == 0x4) && >> >> + (InterfaceDescriptor.InterfaceProtocol == 0x1)) || \ >> >> + ((InterfaceDescriptor.InterfaceClass == 0xA) && >> >> + (InterfaceDescriptor.InterfaceSubClass == 0x0) && >> >> + (InterfaceDescriptor.InterfaceProtocol == 0x00)) >> >> + ) >> >> + { >> >> + return TRUE; >> >> + } >> >> + >> >> + return FALSE; >> >> +} >> >> + >> >> +/** >> >> + Check if this interface is USB Rndis SubType but not CDC Data interface >> >> + >> >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance. >> >> + >> >> + @retval TRUE USB Rndis SubType. >> >> + @retval FALSE Not USB Rndis SubType. >> >> + >> >> +**/ >> >> +BOOLEAN >> >> +IsRndisInterface ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; >> >> + >> >> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, >> &InterfaceDescriptor); >> >> + if (EFI_ERROR (Status)) { >> >> + return FALSE; >> >> + } >> >> + >> >> + // Check for specific device/RNDIS and CDC-DATA >> >> + if (((InterfaceDescriptor.InterfaceClass == 0x2) && >> >> + (InterfaceDescriptor.InterfaceSubClass == 0x2) && >> >> + (InterfaceDescriptor.InterfaceProtocol == 0xFF)) || \ >> >> + ((InterfaceDescriptor.InterfaceClass == 0xEF) && >> >> + (InterfaceDescriptor.InterfaceSubClass == 0x4) && >> >> + (InterfaceDescriptor.InterfaceProtocol == 0x1)) >> >> + ) >> >> + { >> >> + return TRUE; >> >> + } >> >> + >> >> + return FALSE; >> >> +} >> >> + >> >> +/** >> >> + Check if the USB RNDIS and USB CDC Data interfaces are from the same >> device. >> >> + >> >> + @param[in] UsbRndisDataPath A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> >> + @param[in] UsbCdcDataPath A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> >> + >> >> + @retval EFI_SUCCESS Is the same device. >> >> + @retval EFI_UNSUPPORTED Is not the same device. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +IsSameDevice ( >> >> + IN EFI_DEVICE_PATH_PROTOCOL *UsbRndisDataPath, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath >> >> + ) >> >> +{ >> >> + DEBUG ((EFI_D_VERBOSE, "IsSameDevice Entry \n")); >> >> + while (1) { >> >> + if (IsDevicePathEnd (NextDevicePathNode (UsbRndisDataPath))) { >> >> + if (((USB_DEVICE_PATH *)UsbRndisDataPath)->ParentPortNumber == >> >> + ((USB_DEVICE_PATH *)UsbCdcDataPath)->ParentPortNumber) >> >> + { >> >> + return EFI_SUCCESS; >> >> + } else { >> >> + return EFI_UNSUPPORTED; >> >> + } >> >> + } else { >> >> + if (CompareMem (UsbCdcDataPath, UsbRndisDataPath, sizeof >> (EFI_DEVICE_PATH_PROTOCOL)) != 0) { >> >> + return EFI_UNSUPPORTED; >> >> + } >> >> + >> >> + UsbRndisDataPath = NextDevicePathNode (UsbRndisDataPath); >> >> + UsbCdcDataPath = NextDevicePathNode (UsbCdcDataPath); >> >> + } >> >> + } >> >> + >> >> + DEBUG ((EFI_D_VERBOSE, "IsSameDevice Exit \n")); >> >> +} >> >> + >> >> +/** >> >> + Check if the USB CDC Data(UsbIo) installed and return USB CDC Data >> Handle. >> >> + >> >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance. >> >> + >> >> + @retval TRUE USB CDC Data(UsbIo) installed. >> >> + @retval FALSE USB CDC Data(UsbIo) did not installed. >> >> + >> >> +**/ >> >> +BOOLEAN >> >> +IsUsbCdcData ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; >> >> + >> >> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, >> &InterfaceDescriptor); >> >> + if (EFI_ERROR (Status)) { >> >> + return FALSE; >> >> + } >> >> + >> >> + // Check for CDC-DATA >> >> + if ((InterfaceDescriptor.InterfaceClass == 0xA) && >> >> + (InterfaceDescriptor.InterfaceSubClass == 0x0) && >> >> + (InterfaceDescriptor.InterfaceProtocol == 0x0)) >> >> + { >> >> + return TRUE; >> >> + } >> >> + >> >> + return FALSE; >> >> +} >> >> + >> >> +/** >> >> + Check if the USB Rndis(UsbIo) installed >> >> + >> >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance. >> >> + >> >> + @retval TRUE USB Rndis(UsbIo) installed. >> >> + @retval FALSE USB Rndis(UsbIo) did not installed. >> >> + >> >> +**/ >> >> +BOOLEAN >> >> +IsUsbRndis ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; >> >> + >> >> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, >> &InterfaceDescriptor); >> >> + if (EFI_ERROR (Status)) { >> >> + return FALSE; >> >> + } >> >> + >> >> + // Check for Rndis >> >> + if ((InterfaceDescriptor.InterfaceClass == 0x2) && >> >> + (InterfaceDescriptor.InterfaceSubClass == 0x2) && >> >> + (InterfaceDescriptor.InterfaceProtocol == 0xFF)) >> >> + { >> >> + return TRUE; >> >> + } >> >> + >> >> + return FALSE; >> >> +} >> >> + >> >> +/** >> >> + Control comes here when a CDC device is found.Check if a RNDIS >> interface is already found for this device or not. >> >> + For one device two USBIO will be installed each for CDC and RNDIS >> interface. >> >> + >> >> + @param[in] UsbEthPath A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> >> + @param[out] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE Data. >> >> + >> >> + @retval EFI_SUCCESS The USB_RNDIS_DEVICE matching this CDC >> Data is found. >> >> + @retval EFI_NOT_FOUND The USB_RNDIS_DEVICE matching this CDC >> Data is not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +UpdateRndisDevice ( >> >> + IN EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath, >> >> + OUT USB_RNDIS_DEVICE **UsbRndisDevice >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINTN Index; >> >> + UINTN HandleCount; >> >> + EFI_HANDLE *HandleBuffer; >> >> + USB_ETHERNET_PROTOCOL *UsbEthDevice; >> >> + EFI_DEVICE_PATH_PROTOCOL *UsbRndisDataPath; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + BOOLEAN IsRndisInterfaceFlag = FALSE; >> >> + >> >> + Status = gBS->LocateHandleBuffer ( >> >> + ByProtocol, >> >> + &gUsbEthProtocolGuid, >> >> + NULL, >> >> + &HandleCount, >> >> + &HandleBuffer >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + for (Index = 0; Index < HandleCount; Index++) { >> >> + Status = gBS->HandleProtocol ( >> >> + HandleBuffer[Index], >> >> + &gUsbEthProtocolGuid, >> >> + (VOID **)&UsbEthDevice >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + continue; >> >> + } >> >> + >> >> + Status = gBS->HandleProtocol ( >> >> + HandleBuffer[Index], >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + continue; >> >> + } >> >> + >> >> + IsRndisInterfaceFlag = IsRndisInterface (UsbIo); >> >> + if (IsRndisInterfaceFlag == FALSE) { >> >> + continue; >> >> + } >> >> + >> >> + Status = gBS->HandleProtocol ( >> >> + HandleBuffer[Index], >> >> + &gEfiDevicePathProtocolGuid, >> >> + (VOID **)&UsbRndisDataPath >> >> + ); >> >> + Status = IsSameDevice (UsbRndisDataPath, UsbCdcDataPath); >> >> + >> >> + DEBUG ((EFI_D_VERBOSE, "Rndis IsSameDevice %r\n", Status)); >> >> + >> >> + if (!EFI_ERROR (Status)) { >> >> + *UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (UsbEthDevice); >> >> + gBS->FreePool (HandleBuffer); >> >> + return EFI_SUCCESS; >> >> + } >> >> + } // End of For loop >> >> + >> >> + gBS->FreePool (HandleBuffer); >> >> + return EFI_NOT_FOUND; >> >> +} >> >> + >> >> +/** >> >> + >> >> + For the given Rndis Device, find a matching CDC device already exists >> or not. If found update the handle >> >> + and UsbIO protocol. >> >> + >> >> + @param[in] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE >> data. >> >> + >> >> +**/ >> >> +VOID >> >> +FindMatchingCdcData ( >> >> + IN USB_RNDIS_DEVICE *UsbRndisDevice >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINTN Index; >> >> + UINTN HandleCount; >> >> + EFI_HANDLE *HandleBuffer; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + EFI_DEVICE_PATH_PROTOCOL *UsbRndisDataPath; >> >> + EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath; >> >> + >> >> + // Find the parent RNDIS and update the UsbIo for the CDC device >> >> + Status = gBS->HandleProtocol ( >> >> + UsbRndisDevice->UsbRndisHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + (VOID **)&UsbRndisDataPath >> >> + ); >> >> + >> >> + if (EFI_ERROR (Status)) { >> >> + return; >> >> + } >> >> + >> >> + Status = gBS->LocateHandleBuffer ( >> >> + ByProtocol, >> >> + &gEfiUsbIoProtocolGuid, >> >> + NULL, >> >> + &HandleCount, >> >> + &HandleBuffer >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return; >> >> + } >> >> + >> >> + for (Index = 0; Index < HandleCount; Index++) { >> >> + Status = gBS->HandleProtocol ( >> >> + HandleBuffer[Index], >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo >> >> + ); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + if (IsUsbCdcData (UsbIo)) { >> >> + DEBUG ((EFI_D_VERBOSE, "Rndis FindMatchingCdcData CDCData >> interface found\n")); >> >> + >> >> + Status = gBS->HandleProtocol ( >> >> + HandleBuffer[Index], >> >> + &gEfiDevicePathProtocolGuid, >> >> + (VOID **)&UsbCdcDataPath >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + DEBUG ((EFI_D_VERBOSE, "Rndis CDCData DevicePath not found\n")); >> >> + gBS->FreePool (HandleBuffer); >> >> + return; >> >> + } >> >> + >> >> + Status = IsSameDevice (UsbRndisDataPath, UsbCdcDataPath); >> >> + DEBUG ((EFI_D_VERBOSE, "Rndis IsSameDevice %r\n", Status)); >> >> + if (!EFI_ERROR (Status)) { >> >> + UsbRndisDevice->UsbCdcDataHandle = HandleBuffer[Index]; >> >> + UsbRndisDevice->UsbIoCdcData = UsbIo; >> >> + GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice); >> >> + gBS->FreePool (HandleBuffer); >> >> + return; >> >> + } >> >> + } >> >> + } // End of For loop >> >> + >> >> + gBS->FreePool (HandleBuffer); >> >> +} >> >> + >> >> +/** >> >> + >> >> + For the given UsbIo CdcData, find a matching RNDIS device already >> exists or not. >> >> + >> >> + @param[in] CdcHandle A pointer to the EFI_HANDLE for USB CDC >> Data. >> >> + @param[out] CdcUsbIo A pointer for retrieve the >> EFI_USB_IO_PROTOCOL instance. >> >> + @param[out] RndisHandle A pointer for retrieve the handle of RNDIS >> device. >> >> + >> >> + @retval EFI_SUCCESS The USB_RNDIS_DEVICE matching this CDC >> Data is found. >> >> + @retval EFI_NOT_FOUND The USB_RNDIS_DEVICE matching this CDC >> Data is not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +FindMatchingRndisDev ( >> >> + IN EFI_HANDLE CdcHandle, >> >> + OUT EFI_USB_IO_PROTOCOL **CdcUsbIo, >> >> + OUT EFI_HANDLE *RndisHandle >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINTN Index; >> >> + UINTN HandleCount; >> >> + EFI_HANDLE *HandleBuffer; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + EFI_DEVICE_PATH_PROTOCOL *UsbRndisDataPath; >> >> + EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath; >> >> + >> >> + // Find the parent RNDIS and update the UsbIo for the CDC device >> >> + Status = gBS->HandleProtocol ( >> >> + CdcHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + (VOID **)&UsbCdcDataPath >> >> + ); >> >> + >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status = gBS->LocateHandleBuffer ( >> >> + ByProtocol, >> >> + &gEfiUsbIoProtocolGuid, >> >> + NULL, >> >> + &HandleCount, >> >> + &HandleBuffer >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + for (Index = 0; Index < HandleCount; Index++) { >> >> + Status = gBS->HandleProtocol ( >> >> + HandleBuffer[Index], >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo >> >> + ); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + if (IsUsbRndis (UsbIo)) { >> >> + Status = gBS->HandleProtocol ( >> >> + HandleBuffer[Index], >> >> + &gEfiDevicePathProtocolGuid, >> >> + (VOID **)&UsbRndisDataPath >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + DEBUG ((EFI_D_ERROR, "Usb Rndis DevicePath not found\n")); >> >> + break; >> >> + } >> >> + >> >> + Status = IsSameDevice (UsbRndisDataPath, UsbCdcDataPath); >> >> + >> >> + if (!EFI_ERROR (Status)) { >> >> + *RndisHandle = HandleBuffer[Index]; >> >> + *CdcUsbIo = UsbIo; >> >> + gBS->FreePool (HandleBuffer); >> >> + return Status; >> >> + } >> >> + } >> >> + } // End of For loop >> >> + >> >> + gBS->FreePool (HandleBuffer); >> >> + >> >> + return EFI_NOT_FOUND; >> >> +} >> >> + >> >> +/** >> >> + USB Rndis Driver Binding Support. >> >> + >> >> + @param[in] This Protocol instance pointer. >> >> + @param[in] ControllerHandle Handle of device to test. >> >> + @param[in] RemainingDevicePath Optional parameter use to pick a >> specific child >> >> + device to start. >> >> + >> >> + @retval EFI_SUCCESS This driver supports this device. >> >> + @retval EFI_ALREADY_STARTED This driver is already running on >> this device. >> >> + @retval other This driver does not support this >> device. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbRndisDriverSupported ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_IO_PROTOCOL *UsbIo = NULL; >> >> + >> >> + Status = gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status = IsSupportedDevice (UsbIo) ? EFI_SUCCESS : EFI_UNSUPPORTED; >> >> + >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + USB RNDIS Driver Binding Start. >> >> + >> >> + @param[in] This Protocol instance pointer. >> >> + @param[in] ControllerHandle Handle of device to bind driver to. >> >> + @param[in] RemainingDevicePath Optional parameter use to pick a >> specific child >> >> + device to start. >> >> + >> >> + @retval EFI_SUCCESS This driver is added to >> ControllerHandle >> >> + @retval EFI_DEVICE_ERROR This driver could not be started >> due to a device error >> >> + @retval EFI_OUT_OF_RESOURCES The driver could not install >> successfully due to a lack of resources. >> >> + @retval other This driver does not support this >> device >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbRndisDriverStart ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> >> + EFI_DEVICE_PATH_PROTOCOL *UsbEthPath; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + EFI_USB_INTERFACE_DESCRIPTOR Interface; >> >> + EFI_HANDLE RndisHandle = ControllerHandle; >> >> + >> >> + Status = gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + Status = gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + (VOID **)&UsbEthPath, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return Status; >> >> + } >> >> + >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiDevicePathProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + >> >> + DEBUG ((EFI_D_ERROR, "UsbRndisDriverStart %x\n", ControllerHandle)); >> >> + >> >> + // Controls come here for RNDIS and CDC. If it is CDC, check whether >> RNDIS is present on the same controller or not. >> >> + if (IsUsbCdcData (UsbIo)) { >> >> + // Find the parent RNDIS and update the UsbIo for the CDC device >> >> + Status = UpdateRndisDevice (UsbEthPath, &UsbRndisDevice); >> >> + >> >> + if (!EFI_ERROR (Status)) { >> >> + DEBUG ((EFI_D_VERBOSE, "Rndis Matching interface found\n")); >> >> + UsbRndisDevice->UsbCdcDataHandle = ControllerHandle; >> >> + UsbRndisDevice->UsbIoCdcData = UsbIo; >> >> + GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice); >> >> + return Status; >> >> + } else { >> >> + // Check if RnDis exist >> >> + Status = FindMatchingRndisDev (ControllerHandle, &UsbIo, >> &RndisHandle); >> >> + >> >> + if (EFI_ERROR (Status)) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return Status; >> >> + } >> >> + } >> >> + } >> >> + >> >> + UsbRndisDevice = AllocateZeroPool (sizeof (USB_RNDIS_DEVICE)); >> >> + >> >> + if (!UsbRndisDevice) { >> >> + DEBUG ((EFI_D_ERROR, "AllocateZeroPool Fail\n")); >> >> + >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + return EFI_OUT_OF_RESOURCES; >> >> + } >> >> + >> >> + Status = LoadAllDescriptor (UsbIo, &UsbRndisDevice->Config); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + UsbRndisDevice->Signature = >> USB_RNDIS_SIGNATURE; >> >> + UsbRndisDevice->NumOfInterface = >> Interface.InterfaceNumber; >> >> + UsbRndisDevice->UsbRndisHandle = RndisHandle; >> >> + UsbRndisDevice->UsbCdcDataHandle = 0; >> >> + UsbRndisDevice->UsbIo = UsbIo; >> >> + UsbRndisDevice->UsbEth.UsbEthReceive = RndisUndiReceive; >> >> + UsbRndisDevice->UsbEth.UsbEthTransmit = RndisUndiTransmit; >> >> + UsbRndisDevice->UsbEth.UsbEthInterrupt = UsbRndisInterrupt; >> >> + UsbRndisDevice->UsbEth.UsbEthMacAddress = >> GetUsbEthMacAddress; >> >> + UsbRndisDevice->UsbEth.UsbEthMaxBulkSize = UsbEthBulkSize; >> >> + UsbRndisDevice->UsbEth.UsbHeaderFunDescriptor = >> GetUsbHeaderFunDescriptor; >> >> + UsbRndisDevice->UsbEth.UsbUnionFunDescriptor = >> GetUsbUnionFunDescriptor; >> >> + UsbRndisDevice->UsbEth.UsbEthFunDescriptor = >> GetUsbRndisFunDescriptor; >> >> + UsbRndisDevice->UsbEth.SetUsbEthMcastFilter = >> SetUsbRndisMcastFilter; >> >> + UsbRndisDevice->UsbEth.SetUsbEthPowerPatternFilter = >> SetUsbRndisPowerFilter; >> >> + UsbRndisDevice->UsbEth.GetUsbEthPoewrPatternFilter = >> GetUsbRndisPowerFilter; >> >> + UsbRndisDevice->UsbEth.SetUsbEthPacketFilter = >> SetUsbRndisPacketFilter; >> >> + UsbRndisDevice->UsbEth.GetUsbEthStatistic = GetRndisStatistic; >> >> + >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetState = >> RndisDummyReturn; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStart = >> RndisUndiStart; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStop = >> RndisUndiStop; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetInitInfo = >> RndisUndiGetInitInfo; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetConfigInfo = >> RndisUndiGetConfigInfo; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiInitialize = >> RndisUndiInitialize; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiReset = >> RndisUndiReset; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiShutdown = >> RndisUndiShutdown; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiInterruptEnable = >> RndisDummyReturn; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiReceiveFilter = >> RndisUndiReceiveFilter; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStationAddress = >> RndisDummyReturn; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStatistics = NULL; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiMcastIp2Mac = >> RndisDummyReturn; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiNvData = >> RndisDummyReturn; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetStatus = >> RndisUndiGetStatus; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiFillHeader = >> RndisDummyReturn; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiTransmit = NULL; >> >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiReceive = NULL; >> >> + >> >> + UsbRndisDevice->MaxTransferSize = RNDIS_MAX_TRANSFER_SIZE; >> >> + UsbRndisDevice->MaxPacketsPerTransfer = 1; >> >> + UsbRndisDevice->PacketAlignmentFactor = 0; >> >> + >> >> + InitializeListHead (&UsbRndisDevice->ReceivePacketList); >> >> + >> >> + // This is a RNDIS interface. See whether CDC-DATA interface has >> already been connected or not >> >> + FindMatchingCdcData (UsbRndisDevice); >> >> + >> >> + if (UsbRndisDevice->UsbIoCdcData) { >> >> + Status = gBS->InstallProtocolInterface ( >> >> + &ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + EFI_NATIVE_INTERFACE, >> >> + &(UsbRndisDevice->UsbEth) >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + >> >> + gBS->FreePool (UsbRndisDevice->Config); >> >> + gBS->FreePool (UsbRndisDevice); >> >> + return Status; >> >> + } >> >> + >> >> + GetEndpoint (UsbRndisDevice->UsbIo, UsbRndisDevice); >> >> + >> >> + DEBUG ((EFI_D_ERROR, "Rndis DeviceHandle %r\n", >> UsbRndisDevice->UsbRndisHandle)); >> >> + DEBUG ((EFI_D_ERROR, "CDC DeviceHandle %r\n", >> UsbRndisDevice->UsbCdcDataHandle)); >> >> + return EFI_SUCCESS; >> >> + } >> >> + >> >> + gBS->FreePool (UsbRndisDevice->Config); >> >> + gBS->FreePool (UsbRndisDevice); >> >> + >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + CheckandStopRndisDevice >> >> + >> >> + @param[in] This Protocol instance pointer. >> >> + @param[in] ControllerHandle Handle of device to bind driver to. >> >> + >> >> + @retval EFI_SUCCESS This driver is added to ControllerHandle >> >> + @retval EFI_DEVICE_ERROR This driver could not be started due to a >> device error >> >> + @retval other This driver does not support this device >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +CheckandStopRndisDevice ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + >> >> + Status = gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + (VOID **)&UsbIo, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + if (IsUsbRndis (UsbIo)) { >> >> + Status = gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + DEBUG ((EFI_D_ERROR, "Rndis ControllerHandle Stop %r\n", Status)); >> >> + return Status; >> >> + } >> >> + >> >> + return EFI_UNSUPPORTED; >> >> +} >> >> + >> >> +/** >> >> + USB Rndis Driver Binding Stop. >> >> + >> >> + @param[in] This Protocol instance pointer. >> >> + @param[in] ControllerHandle Handle of device to stop driver on >> >> + @param[in] NumberOfChildren Number of Handles in >> ChildHandleBuffer. If number of >> >> + children is zero stop the entire bus >> driver. >> >> + @param[in] ChildHandleBuffer List of Child Handles to Stop. >> >> + >> >> + @retval EFI_SUCCESS This driver is removed >> ControllerHandle >> >> + @retval other This driver was not removed from >> this device >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbRndisDriverStop ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN UINTN NumberOfChildren, >> >> + IN EFI_HANDLE *ChildHandleBuffer >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_PROTOCOL *UsbEthProtocol; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> >> + >> >> + DEBUG ((EFI_D_ERROR, "UsbRndisDriverStop ControllerHandle %lx\n", >> ControllerHandle)); >> >> + >> >> + Status = gBS->OpenProtocol ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + (VOID **)&UsbEthProtocol, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle, >> >> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + Status = CheckandStopRndisDevice (This, ControllerHandle); >> >> + >> >> + DEBUG ((EFI_D_ERROR, "CheckandStopRndisDevice %r\n", Status)); >> >> + >> >> + return Status; >> >> + } >> >> + >> >> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (UsbEthProtocol); >> >> + >> >> + Status = gBS->CloseProtocol ( >> >> + UsbRndisDevice->UsbCdcDataHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + UsbRndisDevice->UsbCdcDataHandle >> >> + ); >> >> + >> >> + Status = gBS->UninstallProtocolInterface ( >> >> + ControllerHandle, >> >> + &gUsbEthProtocolGuid, >> >> + UsbEthProtocol >> >> + ); >> >> + if (EFI_ERROR (Status)) { >> >> + DEBUG ((EFI_D_ERROR, "EFI_ERROR %r\n", Status)); >> >> + >> >> + return Status; >> >> + } >> >> + >> >> + Status = gBS->CloseProtocol ( >> >> + ControllerHandle, >> >> + &gEfiUsbIoProtocolGuid, >> >> + This->DriverBindingHandle, >> >> + ControllerHandle >> >> + ); >> >> + >> >> + gBS->FreePool (UsbRndisDevice->Config); >> >> + gBS->FreePool (UsbRndisDevice); >> >> + >> >> + DEBUG ((EFI_D_ERROR, "UsbRndisDriverStop %r\n", Status)); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Entrypoint of RNDIS Driver. >> >> + >> >> + This function is the entrypoint of RNDIS Driver. It installs Driver >> Binding >> >> + Protocols together with Component Name Protocols. >> >> + >> >> + @param[in] ImageHandle The firmware allocated handle for the >> EFI image. >> >> + @param[in] SystemTable A pointer to the EFI System Table. >> >> + >> >> + @retval EFI_SUCCESS The entry point is executed successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbRndisEntry ( >> >> + IN EFI_HANDLE ImageHandle, >> >> + IN EFI_SYSTEM_TABLE *SystemTable >> >> + ) >> >> +{ >> >> + gUsbRndisDriverBinding.DriverBindingHandle = ImageHandle; >> >> + gUsbRndisDriverBinding.ImageHandle = ImageHandle; >> >> + >> >> + return gBS->InstallMultipleProtocolInterfaces ( >> >> + &gUsbRndisDriverBinding.DriverBindingHandle, >> >> + &gEfiDriverBindingProtocolGuid, >> >> + &gUsbRndisDriverBinding, >> >> + &gEfiComponentName2ProtocolGuid, >> >> + &gUsbRndisComponentName2, >> >> + NULL >> >> + ); >> >> +} >> >> diff --git a/UsbNetworkPkg/UsbRndis/UsbRndis.h >> b/UsbNetworkPkg/UsbRndis/UsbRndis.h >> new file mode 100644 >> index 0000000000..680a9e67c9 >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbRndis/UsbRndis.h >> @@ -0,0 +1,569 @@ >> +/** @file >> >> + Header file for for USB Rndis driver >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#ifndef _USB_RNDIS_H_ >> >> +#define _USB_RNDIS_H_ >> >> + >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> +#include >> >> + >> >> +typedef struct _REMOTE_NDIS_MSG_HEADER REMOTE_NDIS_MSG_HEADER; >> >> + >> >> +typedef struct { >> >> + UINT32 Signature; >> >> + USB_ETHERNET_PROTOCOL UsbEth; >> >> + EFI_HANDLE UsbCdcDataHandle; >> >> + EFI_HANDLE UsbRndisHandle; >> >> + EFI_USB_IO_PROTOCOL *UsbIo; >> >> + EFI_USB_IO_PROTOCOL *UsbIoCdcData; >> >> + EFI_USB_CONFIG_DESCRIPTOR *Config; >> >> + UINT8 NumOfInterface; >> >> + UINT8 BulkInEndpoint; >> >> + UINT8 BulkOutEndpoint; >> >> + UINT8 InterrupEndpoint; >> >> + EFI_MAC_ADDRESS MacAddress; >> >> + UINT32 RequestId; >> >> + UINT32 Medium; >> >> + UINT32 MaxPacketsPerTransfer; >> >> + UINT32 MaxTransferSize; >> >> + UINT32 PacketAlignmentFactor; >> >> + LIST_ENTRY ReceivePacketList; >> >> +} USB_RNDIS_DEVICE; >> >> + >> >> +#define USB_RNDIS_DRIVER_VERSION 1 >> >> +#define USB_TX_ETHERNET_BULK_TIMEOUT 3000 >> >> +#define USB_RX_ETHERNET_BULK_TIMEOUT 3 >> >> +#define USB_ETHERNET_TRANSFER_TIMEOUT 200 >> >> + >> >> +#define LAN_BULKIN_CMD_CONTROL 1 >> >> +#define MAXIMUM_STOPBULKIN_CNT 300 // Indicating maximum >> counts for waiting bulk in command >> >> +#define MINIMUM_STOPBULKIN_CNT 3 // Indicating minimum >> counts for waiting bulk in command >> >> +#define BULKIN_CMD_POLLING_CNT 300 // Indicating the waiting >> counts for send bulk in command when system pending >> >> + >> >> +#define USB_RNDIS_SIGNATURE SIGNATURE_32('r', 'n', 'd', 's') >> >> +#define USB_RNDIS_DEVICE_FROM_THIS(a) CR (a, USB_RNDIS_DEVICE, UsbEth, >> USB_RNDIS_SIGNATURE) >> >> + >> >> +struct BIT_MAP { >> >> + unsigned int Src; >> >> + unsigned int Dst; >> >> +}; >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbRndisDriverSupported ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbRndisDriverStart ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbRndisDriverStop ( >> >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> >> + IN EFI_HANDLE ControllerHandle, >> >> + IN UINTN NumberOfChildren, >> >> + IN EFI_HANDLE *ChildHandleBuffer >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +LoadAllDescriptor ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> >> + OUT EFI_USB_CONFIG_DESCRIPTOR **ConfigDesc >> >> + ); >> >> + >> >> +BOOLEAN >> >> +NextDescriptor ( >> >> + IN EFI_USB_CONFIG_DESCRIPTOR *Desc, >> >> + IN OUT UINTN *Offset >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +GetFunctionalDescriptor ( >> >> + IN EFI_USB_CONFIG_DESCRIPTOR *Config, >> >> + IN UINT8 FunDescriptorType, >> >> + OUT VOID *DataBuffer >> >> + ); >> >> + >> >> +VOID >> >> +GetEndpoint ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> >> + IN OUT USB_RNDIS_DEVICE *UsbRndisDevice >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbRndisInterrupt ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN BOOLEAN IsNewTransfer, >> >> + IN UINTN PollingInterval, >> >> + IN EFI_USB_DEVICE_REQUEST *Requst >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +InterruptCallback ( >> >> + IN VOID *Data, >> >> + IN UINTN DataLength, >> >> + IN VOID *Context, >> >> + IN UINT32 Status >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthMacAddress ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT EFI_MAC_ADDRESS *MacAddress >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthBulkSize ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT UINTN *BulkSize >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisDummyReturn ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiStart ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiStop ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiGetInitInfo ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiGetConfigInfo ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiInitialize ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiTransmit ( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN VOID *BulkOutData, >> >> + IN OUT UINTN *DataLength >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiReceive ( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN OUT VOID *BulkInData, >> >> + IN OUT UINTN *DataLength >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiReset ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiShutdown ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiReceiveFilter ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiGetStatus ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbHeaderFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbUnionFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbRndisFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbRndisMcastFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN VOID *McastAddr >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbRndisPowerFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN UINT16 Length, >> >> + IN VOID *PatternFilter >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbRndisPowerFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN BOOLEAN *PatternActive >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbRndisPacketFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetRndisStatistic ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN VOID *Statistic >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +SendRndisSetMsg ( >> >> + IN USB_RNDIS_DEVICE *UsbRndisDevice, >> >> + UINT8 Oid, >> >> + UINT32 Length, >> >> + UINT8 *Buf >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +RndisControlMsg ( >> >> + IN USB_RNDIS_DEVICE *UsbRndisDevice, >> >> + IN REMOTE_NDIS_MSG_HEADER *RndisMsg, >> >> + OUT REMOTE_NDIS_MSG_HEADER *RndisMsgResponse >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +RndisTransmitDataMsg ( >> >> + IN USB_RNDIS_DEVICE *UsbRndisDevice, >> >> + IN REMOTE_NDIS_MSG_HEADER *RndisMsg, >> >> + UINTN *TransferLength >> >> + ); >> >> + >> >> +EFI_STATUS >> >> +RndisReceiveDataMsg ( >> >> + IN USB_RNDIS_DEVICE *UsbRndisDevice, >> >> + IN REMOTE_NDIS_MSG_HEADER *RndisMsg, >> >> + UINTN *TransferLength >> >> + ); >> >> + >> >> +VOID >> >> +PrintRndisMsg ( >> >> + IN REMOTE_NDIS_MSG_HEADER *RndisMsg >> >> + ); >> >> + >> >> +#define RNDIS_MAJOR_VERSION 0x00000001 >> >> +#define RNDIS_MINOR_VERSION 0x00000000 >> >> +#define RNDIS_MAX_TRANSFER_SIZE 0x4000 >> >> + >> >> +#define RNDIS_PACKET_MSG 0x00000001 >> >> +#define RNDIS_INITIALIZE_MSG 0x00000002 >> >> +#define RNDIS_INITIALIZE_CMPLT 0x80000002 >> >> +#define RNDIS_HLT_MSG 0x00000003 >> >> +#define RNDIS_QUERY_MSG 0x00000004 >> >> +#define RNDIS_QUERY_CMPLT 0x80000004 >> >> +#define RNDIS_SET_MSG 0x00000005 >> >> +#define RNDIS_SET_CMPLT 0x80000005 >> >> +#define RNDIS_RESET_MSG 0x00000006 >> >> +#define RNDIS_RESET_CMPLT 0x80000006 >> >> +#define RNDIS_INDICATE_STATUS_MSG 0x00000007 >> >> +#define RNDIS_KEEPALIVE_MSG 0x00000008 >> >> +#define RNDIS_KEEPALIVE_CMPLT 0x80000008 >> >> + >> >> +#define RNDIS_STATUS_SUCCESS 0x00000000 >> >> +#define RNDIS_STATUS_FAILURE 0xC0000001 >> >> +#define RNDIS_STATUS_INVALID_DATA 0xC0010015 >> >> +#define RNDIS_STATUS_NOT_SUPPORTED 0xC00000BB >> >> +#define RNDIS_STATUS_MEDIA_CONNECT 0x4001000B >> >> +#define RNDIS_STATUS_MEDIA_DISCONNECT 0x4001000C >> >> + >> >> +#define RNDIS_CONTROL_TIMEOUT 10000 // 10sec >> >> +#define RNDIS_KEEPALIVE_TIMEOUT 5000 // 5sec >> >> + >> >> +#define SEND_ENCAPSULATED_COMMAND 0x00000000 >> >> +#define GET_ENCAPSULATED_RESPONSE 0x00000001 >> >> + >> >> +// >> >> +// General Objects >> >> +// >> >> +// Taken from NTDDNDIS.H >> >> +#define OID_GEN_SUPPORTED_LIST 0x00010101 >> >> +#define OID_GEN_HARDWARE_STATUS 0x00010102 >> >> +#define OID_GEN_MEDIA_SUPPORTED 0x00010103 >> >> +#define OID_GEN_MEDIA_IN_USE 0x00010104 >> >> +#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 >> >> +#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 >> >> +#define OID_GEN_LINK_SPEED 0x00010107 >> >> +#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 >> >> +#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 >> >> +#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A >> >> +#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B >> >> +#define OID_GEN_VENDOR_ID 0x0001010C >> >> +#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D >> >> +#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E >> >> +#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F >> >> +#define OID_GEN_DRIVER_VERSION 0x00010110 >> >> +#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 >> >> +#define OID_GEN_PROTOCOL_OPTIONS 0x00010112 >> >> +#define OID_GEN_MAC_OPTIONS 0x00010113 >> >> +#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 >> >> +#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 >> >> +#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 >> >> + >> >> +#define OID_GEN_XMIT_OK 0x00020101 >> >> +#define OID_GEN_RCV_OK 0x00020102 >> >> +#define OID_GEN_XMIT_ERROR 0x00020103 >> >> +#define OID_GEN_RCV_ERROR 0x00020104 >> >> +#define OID_GEN_RCV_NO_BUFFER 0x00020105 >> >> + >> >> +#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 >> >> +#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 >> >> +#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 >> >> +#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 >> >> +#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 >> >> +#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 >> >> +#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 >> >> +#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 >> >> +#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 >> >> +#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A >> >> +#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B >> >> +#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C >> >> +#define OID_GEN_RCV_CRC_ERROR 0x0002020D >> >> +#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E >> >> + >> >> +// >> >> +// Ndis Packet Filter Bits (OID_GEN_CURRENT_PACKET_FILTER). >> >> +// >> >> +#define NDIS_PACKET_TYPE_DIRECTED 0x0001 >> >> +#define NDIS_PACKET_TYPE_MULTICAST 0x0002 >> >> +#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x0004 >> >> +#define NDIS_PACKET_TYPE_BROADCAST 0x0008 >> >> +#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x0010 >> >> +#define NDIS_PACKET_TYPE_PROMISCUOUS 0x0020 >> >> +#define NDIS_PACKET_TYPE_SMT 0x0040 >> >> +#define NDIS_PACKET_TYPE_ALL_LOCAL 0x0080 >> >> +#define NDIS_PACKET_TYPE_MAC_FRAME 0x8000 >> >> +#define NDIS_PACKET_TYPE_FUNCTIONAL 0x4000 >> >> +#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x2000 >> >> +#define NDIS_PACKET_TYPE_GROUP 0x1000 >> >> + >> >> +#pragma pack(1) >> >> + >> >> +typedef struct _REMOTE_NDIS_MSG_HEADER { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> +} REMOTE_NDIS_MSG_HEADER; >> >> + >> >> +typedef struct { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> + UINT32 RequestID; >> >> + UINT32 MajorVersion; >> >> + UINT32 MinorVersion; >> >> + UINT32 MaxTransferSize; >> >> +} REMOTE_NDIS_INITIALIZE_MSG; >> >> + >> >> +typedef struct { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> + UINT32 RequestID; >> >> +} REMOTE_NDIS_HALT_MSG; >> >> + >> >> +typedef struct { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> + UINT32 RequestID; >> >> + UINT32 Oid; >> >> + UINT32 InformationBufferLength; >> >> + UINT32 InformationBufferOffset; >> >> + UINT32 Reserved; >> >> +} REMOTE_NDIS_QUERY_MSG; >> >> + >> >> +typedef struct { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> + UINT32 RequestID; >> >> + UINT32 Oid; >> >> + UINT32 InformationBufferLength; >> >> + UINT32 InformationBufferOffset; >> >> + UINT32 Reserved; >> >> +} REMOTE_NDIS_SET_MSG; >> >> + >> >> +typedef struct { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> + UINT32 Reserved; >> >> +} REMOTE_NDIS_RESET_MSG; >> >> + >> >> +typedef struct { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> + UINT32 Status; >> >> + UINT32 StatusBufferLength; >> >> + UINT32 StatusBufferOffset; >> >> +} REMOTE_NDIS_INDICATE_STATUS_MSG; >> >> + >> >> +typedef struct { >> >> + UINT32 DiagStatus; >> >> + UINT32 ErrorOffset; >> >> +} RNDIS_DIAGNOSTIC_INFO; >> >> + >> >> +typedef struct { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> + UINT32 RequestID; >> >> +} REMOTE_NDIS_KEEPALIVE_MSG; >> >> + >> >> +typedef struct { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> + UINT32 RequestID; >> >> + UINT32 Status; >> >> + UINT32 MajorVersion; >> >> + UINT32 MinorVersion; >> >> + UINT32 DeviceFlags; >> >> + UINT32 Medium; >> >> + UINT32 MaxPacketsPerTransfer; >> >> + UINT32 MaxTransferSize; >> >> + UINT32 PacketAlignmentFactor; >> >> + UINT64 Reserved; >> >> +} REMOTE_NDIS_INITIALIZE_CMPLT; >> >> + >> >> +typedef struct { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> + UINT32 RequestID; >> >> + UINT32 Status; >> >> + UINT32 InformationBufferLength; >> >> + UINT32 InformationBufferOffset; >> >> +} REMOTE_NDIS_QUERY_CMPLT; >> >> + >> >> +typedef struct { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> + UINT32 RequestID; >> >> + UINT32 Status; >> >> +} REMOTE_NDIS_SET_CMPLT; >> >> + >> >> +typedef struct { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> + UINT32 Status; >> >> + UINT32 AddressingReset; >> >> +} REMOTE_NDIS_RESET_CMPLT; >> >> + >> >> +typedef struct { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> + UINT32 RequestID; >> >> + UINT32 Status; >> >> +} REMOTE_NDIS_KEEPALIVE_CMPLT; >> >> + >> >> +typedef struct { >> >> + UINT32 MessageType; >> >> + UINT32 MessageLength; >> >> + UINT32 DataOffset; >> >> + UINT32 DataLength; >> >> + UINT32 OutOfBandDataOffset; >> >> + UINT32 OutOfBandDataLength; >> >> + UINT32 NumOutOfBandDataElements; >> >> + UINT32 PerPacketInfoOffset; >> >> + UINT32 PerPacketInfoLength; >> >> + UINT32 Reserved1; >> >> + UINT32 Reserved2; >> >> +} REMOTE_NDIS_PACKET_MSG; >> >> + >> >> +typedef struct { >> >> + UINT32 Size; >> >> + UINT32 Type; >> >> + UINT32 ClassInformationOffset; >> >> +} OUT_OF_BAND_DATA_RECORD; >> >> + >> >> +typedef struct { >> >> + UINT32 Size; >> >> + UINT32 Type; >> >> + UINT32 ClassInformationOffset; >> >> +} PER_PACKET_INFO_DATA_RECORD; >> >> + >> >> +typedef struct { >> >> + LIST_ENTRY PacketList; >> >> + UINT8 *OrgBuffer; >> >> + UINTN RemainingLength; >> >> +} PACKET_LIST; >> >> + >> >> +#pragma pack() >> >> + >> >> +#endif >> >> diff --git a/UsbNetworkPkg/UsbRndis/UsbRndis.inf >> b/UsbNetworkPkg/UsbRndis/UsbRndis.inf >> new file mode 100644 >> index 0000000000..909b106059 >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbRndis/UsbRndis.inf >> @@ -0,0 +1,41 @@ >> +## @file >> +# This is Usb Rndis driver for DXE phase. >> +# >> +# Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> +# Subject to AMI licensing agreement. >> +## >> + >> +[Defines] >> + INF_VERSION = 0x00010005 >> + BASE_NAME = UsbRndis >> + FILE_GUID = 11E32C34-60B5-4991-8DEA-63D3E8C876DE >> + MODULE_TYPE = DXE_DRIVER >> + VERSION_STRING = 1.0 >> + ENTRY_POINT = UsbRndisEntry >> + >> +[Sources] >> + UsbRndis.c >> + UsbRndis.h >> + UsbRndisFunction.c >> + ComponentName.c >> + >> +[Packages] >> + MdePkg/MdePkg.dec >> + UsbNetworkPkg/UsbNetworkPkg.dec >> + >> +[LibraryClasses] >> + UefiDriverEntryPoint >> + UefiBootServicesTableLib >> + UefiLib >> + DebugLib >> + UefiUsbLib >> + MemoryAllocationLib >> + BaseMemoryLib >> + >> +[Protocols] >> + gEfiUsbIoProtocolGuid >> + gEfiDevicePathProtocolGuid >> + gEfiDriverBindingProtocolGuid >> + >> +[Depex] >> + TRUE >> diff --git a/UsbNetworkPkg/UsbRndis/UsbRndisFunction.c >> b/UsbNetworkPkg/UsbRndis/UsbRndisFunction.c >> new file mode 100644 >> index 0000000000..a9b7b54f6a >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbRndis/UsbRndisFunction.c >> @@ -0,0 +1,1587 @@ >> +/** @file >> >> + This file contains code for USB Ethernet descriptor >> >> + and specific requests implement. >> >> + >> >> + Copyright (c) 1985 - 2022, AMI. All rights reserved.
>> >> + Subject to AMI licensing agreement. >> >> +**/ >> >> + >> >> +#include "UsbRndis.h" >> >> + >> >> +UINT16 StopBulkInCnt = 0; >> >> +UINT16 BlockBulkInCnt = 0; >> >> + >> >> +/** >> >> + Load All of device descriptor. >> >> + >> >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL >> instance. >> >> + @param[out] ConfigDesc A pointer to the configuration >> descriptor. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_OUT_OF_RESOURCES The request could not be completed >> because the >> >> + buffer specified by DescriptorLength and >> Descriptor >> >> + is not large enough to hold the result >> of the request. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device >> error. The transfer >> >> + status is returned in Status. >> >> +**/ >> >> +EFI_STATUS >> >> +LoadAllDescriptor ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> >> + OUT EFI_USB_CONFIG_DESCRIPTOR **ConfigDesc >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINT32 TransStatus; >> >> + EFI_USB_CONFIG_DESCRIPTOR Tmp; >> >> + >> >> + Status = UsbIo->UsbGetConfigDescriptor (UsbIo, &Tmp); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status = gBS->AllocatePool ( >> >> + EfiBootServicesData, >> >> + Tmp.TotalLength, >> >> + (VOID **)ConfigDesc >> >> + ); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status = UsbGetDescriptor ( >> >> + UsbIo, >> >> + USB_DESC_TYPE_CONFIG << 8 | (Tmp.ConfigurationValue - 1), >> // zero based >> >> + 0, >> >> + Tmp.TotalLength, >> >> + *ConfigDesc, >> >> + &TransStatus >> >> + ); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Returns pointer to the next descriptor for the pack of USB descriptors >> >> + located in continues memory segment >> >> + >> >> + @param[in] Desc A pointer to the CONFIG_DESCRIPTOR instance. >> >> + @param[in, out] Offset A pointer to the sum of descriptor length. >> >> + >> >> + @retval TRUE The request executed successfully. >> >> + @retval FALSE No next descriptor. >> >> + >> >> +**/ >> >> +BOOLEAN >> >> +NextDescriptor ( >> >> + IN EFI_USB_CONFIG_DESCRIPTOR *Desc, >> >> + IN OUT UINTN *Offset >> >> + ) >> >> +{ >> >> + if ((Desc == NULL) || (*Offset >= Desc->TotalLength)) { >> >> + return FALSE; >> >> + } >> >> + >> >> + if (((EFI_USB_CONFIG_DESCRIPTOR *)((char *)Desc+*Offset))->Length == >> 0) { >> >> + return FALSE; >> >> + } >> >> + >> >> + *Offset += ((EFI_USB_CONFIG_DESCRIPTOR *)((char >> *)Desc+*Offset))->Length; >> >> + if ( *Offset >= Desc->TotalLength ) { >> >> + return FALSE; >> >> + } >> >> + >> >> + return TRUE; >> >> +} >> >> + >> >> +/** >> >> + Read Function descriptor >> >> + >> >> + @param[in] Config A pointer to all of configuration. >> >> + @param[in] FunDescriptorType USB CDC class descriptor SubType. >> >> + @param[out] DataBuffer A pointer to the Data of corresponding >> to device capability. >> >> + >> >> + @retval EFI_SUCCESS The device capability descriptor was >> retrieved >> >> + successfully. >> >> + @retval EFI_UNSUPPORTED No supported. >> >> + @retval EFI_NOT_FOUND The device capability descriptor was not >> found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +GetFunctionalDescriptor ( >> >> + IN EFI_USB_CONFIG_DESCRIPTOR *Config, >> >> + IN UINT8 FunDescriptorType, >> >> + OUT VOID *DataBuffer >> >> + ) >> >> +{ >> >> + EFI_STATUS Status = EFI_NOT_FOUND; >> >> + UINTN Offset; >> >> + EFI_USB_INTERFACE_DESCRIPTOR *Interface; >> >> + >> >> + for (Offset = 0; NextDescriptor (Config, &Offset);) { >> >> + Interface = (EFI_USB_INTERFACE_DESCRIPTOR *)((UINT8 *)Config + >> Offset); >> >> + if (Interface->DescriptorType == CS_INTERFACE) { >> >> + if (((USB_HEADER_FUN_DESCRIPTOR *)Interface)->DescriptorSubtype == >> FunDescriptorType) { >> >> + switch (FunDescriptorType) { >> >> + case HEADER_FUN_DESCRIPTOR: >> >> + CopyMem ( >> >> + DataBuffer, >> >> + (USB_HEADER_FUN_DESCRIPTOR *)Interface, >> >> + sizeof (USB_HEADER_FUN_DESCRIPTOR) >> >> + ); >> >> + return EFI_SUCCESS; >> >> + case UNION_FUN_DESCRIPTOR: >> >> + CopyMem ( >> >> + DataBuffer, >> >> + (USB_UNION_FUN_DESCRIPTOR *)Interface, >> >> + ((USB_UNION_FUN_DESCRIPTOR *)Interface)->FunctionLength >> >> + ); >> >> + return EFI_SUCCESS; >> >> + case ETHERNET_FUN_DESCRIPTOR: >> >> + CopyMem ( >> >> + DataBuffer, >> >> + (USB_ETHERNET_FUN_DESCRIPTOR *)Interface, >> >> + sizeof (USB_ETHERNET_FUN_DESCRIPTOR) >> >> + ); >> >> + return EFI_SUCCESS; >> >> + default: >> >> + Status = EFI_UNSUPPORTED; >> >> + break; >> >> + } >> >> + } >> >> + } >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Get USB Ethernet IO endpoint and USB CDC data IO endpoint. >> >> + >> >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL >> instance. >> >> + @param[in, out] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE >> instance. >> >> + >> >> +**/ >> >> +VOID >> >> +GetEndpoint ( >> >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> >> + IN OUT USB_RNDIS_DEVICE *UsbRndisDevice >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINT8 Index; >> >> + UINT32 Result; >> >> + EFI_USB_INTERFACE_DESCRIPTOR Interface; >> >> + EFI_USB_ENDPOINT_DESCRIPTOR Endpoint; >> >> + >> >> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + if (Interface.NumEndpoints == 0 ) { >> >> + Status = UsbSetInterface (UsbIo, 1, 0, &Result); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> >> + ASSERT_EFI_ERROR (Status); >> >> + } >> >> + >> >> + for (Index = 0; Index < Interface.NumEndpoints; Index++) { >> >> + Status = UsbIo->UsbGetEndpointDescriptor (UsbIo, Index, &Endpoint); >> >> + >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + switch ((Endpoint.Attributes & (BIT0 | BIT1))) { >> >> + case USB_ENDPOINT_BULK: >> >> + if (Endpoint.EndpointAddress & BIT7) { >> >> + UsbRndisDevice->BulkInEndpoint = Endpoint.EndpointAddress; >> >> + } else { >> >> + UsbRndisDevice->BulkOutEndpoint = Endpoint.EndpointAddress; >> >> + } >> >> + >> >> + break; >> >> + case USB_ENDPOINT_INTERRUPT: >> >> + UsbRndisDevice->InterrupEndpoint = Endpoint.EndpointAddress; >> >> + break; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + Async USB transfer callback routine. >> >> + >> >> + @param[in] Data Data received or sent via the USB >> Asynchronous Transfer, if the >> >> + transfer completed successfully. >> >> + @param[in] DataLength The length of Data received or sent via >> the Asynchronous >> >> + Transfer, if transfer successfully >> completes. >> >> + @param[in] Context Data passed from >> UsbAsyncInterruptTransfer() request. >> >> + @param[in] Status Indicates the result of the asynchronous >> transfer. >> >> + >> >> + @retval EFI_SUCCESS The asynchronous USB transfer request >> has been successfully executed. >> >> + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request >> failed. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +InterruptCallback ( >> >> + IN VOID *Data, >> >> + IN UINTN DataLength, >> >> + IN VOID *Context, >> >> + IN UINT32 Status >> >> + ) >> >> +{ >> >> + if (((EFI_USB_DEVICE_REQUEST *)Data)->Request == 0) { >> >> + CopyMem ( >> >> + (EFI_USB_DEVICE_REQUEST *)Context, >> >> + (EFI_USB_DEVICE_REQUEST *)Data, >> >> + sizeof (EFI_USB_DEVICE_REQUEST) >> >> + ); >> >> + } >> >> + >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This function is used to manage a USB device with an interrupt >> transfer pipe. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in] IsNewTransfer If TRUE, a new transfer will be >> submitted to USB controller. If >> >> + FALSE, the interrupt transfer is deleted >> from the device's interrupt >> >> + transfer queue. >> >> + @param[in] PollingInterval Indicates the periodic rate, in >> milliseconds, that the transfer is to be >> >> + executed.This parameter is required when >> IsNewTransfer is TRUE. The >> >> + value must be between 1 to 255, >> otherwise EFI_INVALID_PARAMETER is returned. >> >> + The units are in milliseconds. >> >> + @param[in] Request A pointer to the EFI_USB_DEVICE_REQUEST >> data. >> >> + >> >> + @retval EFI_SUCCESS The asynchronous USB transfer request >> transfer has been successfully executed. >> >> + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request >> failed. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbRndisInterrupt ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN BOOLEAN IsNewTransfer, >> >> + IN UINTN PollingInterval, >> >> + IN EFI_USB_DEVICE_REQUEST *Requst >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> >> + UINTN DataLength = 0; >> >> + >> >> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> >> + >> >> + if (IsNewTransfer == TRUE) { >> >> + DataLength = sizeof (EFI_USB_DEVICE_REQUEST) + sizeof >> (USB_CONNECT_SPEED_CHANGE); >> >> + Status = UsbRndisDevice->UsbIo->UsbAsyncInterruptTransfer ( >> >> + UsbRndisDevice->UsbIo, >> >> + >> UsbRndisDevice->InterrupEndpoint, >> >> + IsNewTransfer, >> >> + PollingInterval, >> >> + DataLength, >> >> + InterruptCallback, >> >> + Requst >> >> + ); >> >> + >> >> + if (Status == EFI_INVALID_PARAMETER) { >> >> + // Because of Stacked AsyncInterrupt request are not supported >> >> + Status = UsbRndisDevice->UsbIo->UsbAsyncInterruptTransfer ( >> >> + UsbRndisDevice->UsbIo, >> >> + UsbRndisDevice->InterrupEndpoint, >> >> + 0, >> >> + 0, >> >> + 0, >> >> + NULL, >> >> + NULL >> >> + ); >> >> + } >> >> + } else { >> >> + Status = UsbRndisDevice->UsbIo->UsbAsyncInterruptTransfer ( >> >> + UsbRndisDevice->UsbIo, >> >> + UsbRndisDevice->InterrupEndpoint, >> >> + IsNewTransfer, >> >> + 0, >> >> + 0, >> >> + NULL, >> >> + NULL >> >> + ); >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Ethernet Mac Address. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[out] MacAddress A pointer to the caller allocated USB >> Ethernet Mac Address. >> >> + >> >> + @retval EFI_SUCCESS The USB Header Functional descriptor was >> retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor was >> not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbEthMacAddress ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT EFI_MAC_ADDRESS *MacAddress >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthDescriptor; >> >> + CHAR16 *Data; >> >> + CHAR16 *DataPtr; >> >> + CHAR16 TmpStr[1]; >> >> + UINT8 Index; >> >> + UINT8 Hi; >> >> + UINT8 Low; >> >> + >> >> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> >> + >> >> + Status = This->UsbEthFunDescriptor (This, &UsbEthDescriptor); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + Status = UsbRndisDevice->UsbIo->UsbGetStringDescriptor ( >> >> + UsbRndisDevice->UsbIo, >> >> + 0x409, // >> English-US Language ID >> >> + UsbEthDescriptor.MacAddress, >> >> + &Data >> >> + ); >> >> + ASSERT_EFI_ERROR (Status); >> >> + >> >> + DataPtr = Data; >> >> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> >> + CopyMem (TmpStr, DataPtr, sizeof (CHAR16)); >> >> + DataPtr++; >> >> + Hi = (UINT8)StrHexToUintn (TmpStr); >> >> + CopyMem (TmpStr, DataPtr, sizeof (CHAR16)); >> >> + DataPtr++; >> >> + Low = (UINT8)StrHexToUintn (TmpStr); >> >> + MacAddress->Addr[Index] = (Hi << 4) | Low; >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Ethernet Bulk transfer data size. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[out] BulkSize A pointer to the Bulk transfer data size. >> >> + >> >> + @retval EFI_SUCCESS The bulk transfer data size was retrieved >> successfully. >> >> + @retval other Failed to retrieve the bulk transfer data >> size. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +UsbEthBulkSize ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT UINTN *BulkSize >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; >> >> + >> >> + Status = This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + *BulkSize = (UINTN)UsbEthFunDescriptor.MaxSegmentSize; >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Header functional Descriptor. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[out] UsbHeaderFunDescriptor A pointer to the caller allocated >> USB Header Functional Descriptor. >> >> + >> >> + @retval EFI_SUCCESS The USB Header Functional descriptor was >> retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor was >> not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbHeaderFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> >> + >> >> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> >> + >> >> + if (UsbHeaderFunDescriptor == NULL) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + Status = GetFunctionalDescriptor ( >> >> + UsbRndisDevice->Config, >> >> + HEADER_FUN_DESCRIPTOR, >> >> + UsbHeaderFunDescriptor >> >> + ); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Union functional Descriptor. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[out] UsbUnionFunDescriptor A pointer to the caller allocated >> USB Union Functional Descriptor. >> >> + >> >> + @retval EFI_SUCCESS The USB Union Functional descriptor was >> retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbUnionFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Union Functional descriptor was >> not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbUnionFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> >> + >> >> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> >> + >> >> + if (UsbUnionFunDescriptor == NULL) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + Status = GetFunctionalDescriptor ( >> >> + UsbRndisDevice->Config, >> >> + UNION_FUN_DESCRIPTOR, >> >> + UsbUnionFunDescriptor >> >> + ); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Retrieves the USB Ethernet functional Descriptor. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[out] UsbEthFunDescriptor A pointer to the caller allocated >> USB Ethernet Functional Descriptor. >> >> + >> >> + @retval EFI_SUCCESS The USB Ethernet Functional descriptor >> was retrieved successfully. >> >> + @retval EFI_INVALID_PARAMETER UsbEthFunDescriptor is NULL. >> >> + @retval EFI_NOT_FOUND The USB Ethernet Functional descriptor >> was not found. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbRndisFunDescriptor ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> >> + >> >> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> >> + >> >> + if (UsbEthFunDescriptor == NULL) { >> >> + return EFI_INVALID_PARAMETER; >> >> + } >> >> + >> >> + Status = GetFunctionalDescriptor ( >> >> + UsbRndisDevice->Config, >> >> + ETHERNET_FUN_DESCRIPTOR, >> >> + UsbEthFunDescriptor >> >> + ); >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + This request sets the Ethernet device multicast filters as specified >> in the >> >> + sequential list of 48 bit Ethernet multicast addresses. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] Value Number of filters. >> >> + @param[in] McastAddr A pointer to the value of the >> multicast addresses. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the >> request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device >> error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbRndisMcastFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN VOID *McastAddr >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> + UINT32 TransStatus; >> >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> >> + >> >> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> >> + >> >> + Status = This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor); >> >> + if (EFI_ERROR (Status)) { >> >> + return Status; >> >> + } >> >> + >> >> + if ((UsbEthFunDescriptor.NumberMcFilters << 1) == 0) { >> >> + return EFI_UNSUPPORTED; >> >> + } >> >> + >> >> + Request.RequestType = USB_ETHRTNET_SET_REQ_TYPE; >> >> + Request.Request = SET_ETH_MULTICAST_FILTERS_REQ; >> >> + Request.Value = Value; >> >> + Request.Index = UsbRndisDevice->NumOfInterface; >> >> + Request.Length = Value * 6; >> >> + >> >> + return UsbRndisDevice->UsbIo->UsbControlTransfer ( >> >> + UsbRndisDevice->UsbIo, >> >> + &Request, >> >> + EfiUsbDataOut, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + McastAddr, >> >> + Request.Length, >> >> + &TransStatus >> >> + ); >> >> +} >> >> + >> >> +/** >> >> + This request sets up the specified Ethernet power management pattern >> filter as >> >> + described in the data structure. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] Value Number of filters. >> >> + @param[in] Length Size of the power management pattern >> filter data. >> >> + @param[in] PatternFilter A pointer to the power management >> pattern filter structure. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the >> request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device >> error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbRndisPowerFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + IN UINT16 Length, >> >> + IN VOID *PatternFilter >> >> + ) >> >> +{ >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> + UINT32 TransStatus; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> >> + >> >> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> >> + >> >> + Request.RequestType = USB_ETHRTNET_SET_REQ_TYPE; >> >> + Request.Request = SET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ; >> >> + Request.Value = Value; >> >> + Request.Index = UsbRndisDevice->NumOfInterface; >> >> + Request.Length = Length; >> >> + >> >> + return UsbRndisDevice->UsbIo->UsbControlTransfer ( >> >> + UsbRndisDevice->UsbIo, >> >> + &Request, >> >> + EfiUsbDataOut, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + PatternFilter, >> >> + Length, >> >> + &TransStatus >> >> + ); >> >> +} >> >> + >> >> +/** >> >> + This request retrieves the status of the specified Ethernet power >> management >> >> + pattern filter from the device. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] Value The filter number. >> >> + @param[out] PatternActive A pointer to the pattern active >> boolean. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the >> request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device >> error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetUsbRndisPowerFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value, >> >> + OUT BOOLEAN *PatternActive >> >> + ) >> >> +{ >> >> + EFI_USB_DEVICE_REQUEST Request; >> >> + UINT32 TransStatus; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> >> + >> >> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> >> + >> >> + Request.RequestType = USB_ETHERNET_GET_REQ_TYPE; >> >> + Request.Request = GET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ; >> >> + Request.Value = Value; >> >> + Request.Index = UsbRndisDevice->NumOfInterface; >> >> + Request.Length = USB_ETH_POWER_FILTER_LENGTH; >> >> + >> >> + return UsbRndisDevice->UsbIo->UsbControlTransfer ( >> >> + UsbRndisDevice->UsbIo, >> >> + &Request, >> >> + EfiUsbDataIn, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + PatternActive, >> >> + USB_ETH_POWER_FILTER_LENGTH, >> >> + &TransStatus >> >> + ); >> >> +} >> >> + >> >> +/** >> >> + >> >> + Converts PXE filter settings to RNDIS values >> >> + >> >> + @param[in] Value PXE filter data. >> >> + @param[out] CdcFilter A pointer to the Ethernet Packet Filter Bitmap >> value converted by PXE_OPFLAGS. >> >> + >> >> +**/ >> >> +VOID >> >> +ConvertFilter ( >> >> + IN UINT16 Value, >> >> + OUT UINT16 *CdcFilter >> >> + ) >> >> +{ >> >> + UINT32 Index; >> >> + UINT32 Count; >> >> + static struct BIT_MAP Table[] = { >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_UNICAST, >> NDIS_PACKET_TYPE_DIRECTED }, >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST, >> NDIS_PACKET_TYPE_BROADCAST }, >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST, >> NDIS_PACKET_TYPE_MULTICAST }, >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS, >> NDIS_PACKET_TYPE_PROMISCUOUS }, >> >> + { PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST, >> NDIS_PACKET_TYPE_ALL_MULTICAST }, >> >> + }; >> >> + >> >> + Count = sizeof (Table)/sizeof (Table[0]); >> >> + >> >> + for (Index = 0; (Table[Index].Src != 0) && (Index < Count); Index++) { >> >> + if (Table[Index].Src & Value) { >> >> + *CdcFilter |= Table[Index].Dst; >> >> + } >> >> + } >> >> +} >> >> + >> >> +/** >> >> + >> >> + Updates Filter settings on the device. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_STATUS >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiReceiveFilter ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINT8 *McastList; >> >> + UINT8 Count = 0; >> >> + UINT8 Index1; >> >> + UINT8 Index2; >> >> + UINT64 CpbAddr = Cdb->CPBaddr; >> >> + UINT32 CpbSize = Cdb->CPBsize; >> >> + UINT16 SetFilter = (UINT16)(Cdb->OpFlags & 0x1F); >> >> + PXE_CPB_RECEIVE_FILTERS *Cpb = (PXE_CPB_RECEIVE_FILTERS >> *)(UINTN)CpbAddr; >> >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; >> >> + >> >> + // The Cpb could be NULL.(ref:PXE_CPBADDR_NOT_USED) >> >> + Nic->RxFilter = (UINT8)SetFilter; >> >> + >> >> + if (((SetFilter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) != 0) >> || (Cpb != NULL)) { >> >> + if (Cpb != NULL) { >> >> + Nic->McastCount = (UINT8)(CpbSize / PXE_MAC_LENGTH); >> >> + CopyMem (&Nic->McastList, Cpb, Nic->McastCount); >> >> + } else { >> >> + Nic->McastCount = 0; >> >> + } >> >> + >> >> + if (Nic->CanReceive) { >> >> + Nic->CanReceive = FALSE; >> >> + } >> >> + >> >> + Nic->UsbEth->UsbEthFunDescriptor (Nic->UsbEth, &UsbEthFunDescriptor); >> >> + if ((UsbEthFunDescriptor.NumberMcFilters << 1) == 0) { >> >> + Nic->RxFilter |= PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST; >> >> + DEBUG ((DEBUG_INFO, "SetUsbEthPacketFilter Nic %lx Nic->UsbEth %lx >> ", Nic, Nic->UsbEth)); >> >> + Nic->UsbEth->SetUsbEthPacketFilter (Nic->UsbEth, Nic->RxFilter); >> >> + } else { >> >> + Status = gBS->AllocatePool (EfiBootServicesData, Nic->McastCount * >> 6, (VOID **)&McastList); >> >> + if (EFI_ERROR (Status)) { >> >> + return PXE_STATCODE_INVALID_PARAMETER; >> >> + } >> >> + >> >> + if (Cpb != NULL) { >> >> + for (Index1 = 0; Index1 < Nic->McastCount; Index1++) { >> >> + for (Index2 = 0; Index2 < 6; Index2++) { >> >> + McastList[Count++] = Cpb->MCastList[Index1][Index2]; >> >> + } >> >> + } >> >> + } >> >> + >> >> + Nic->RxFilter |= PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST; >> >> + if (Cpb != NULL) { >> >> + Nic->UsbEth->SetUsbEthMcastFilter (Nic->UsbEth, Nic->McastCount, >> McastList); >> >> + } >> >> + >> >> + Nic->UsbEth->SetUsbEthPacketFilter (Nic->UsbEth, Nic->RxFilter); >> >> + gBS->FreePool (McastList); >> >> + } >> >> + } >> >> + >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This request is used to configure device Ethernet packet filter >> settings. >> >> + >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in] Value Packet Filter Bitmap. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +SetUsbRndisPacketFilter ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 Value >> >> + ) >> >> +{ >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This request is used to retrieve a statistic based on the feature >> selector. >> >> + >> >> + @param[in] This A pointer to the >> USB_ETHERNET_PROTOCOL instance. >> >> + @param[in] FeatureSelector Value of the feature selector. >> >> + @param[out] Statistic A pointer to the 32 bit unsigned >> integer. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +GetRndisStatistic ( >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN UINT16 FeatureSelector, >> >> + OUT VOID *Statistic >> >> + ) >> >> +{ >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This function is called when UndiStart is invoked. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiStart ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + >> >> + DEBUG ((DEBUG_INFO, "RndisUndiStart Nic %lx Cdb %lx Nic State %x\n", >> Nic, Cdb, Nic->State)); >> >> + >> >> + // Issue Rndis Reset and bring the device to RNDIS_BUS_INITIALIZED >> state >> >> + Status = RndisUndiReset (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + RndisUndiReset (Cdb, Nic); >> >> + } >> >> + >> >> + Status = RndisUndiInitialize (Cdb, Nic); >> >> + if (EFI_ERROR (Status)) { >> >> + RndisUndiInitialize (Cdb, Nic); >> >> + } >> >> + >> >> + RndisUndiShutdown (Cdb, Nic); >> >> + >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This function is called when Undistop is invoked. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiStop ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + DEBUG ((DEBUG_INFO, "RndisUndiStop State %x\n", Nic->State)); >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This function is called when UndiGetInitInfo is invoked. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiGetInitInfo ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + USB_ETHERNET_PROTOCOL *UsbEthDevice = Nic->UsbEth; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS >> (UsbEthDevice); >> >> + PXE_DB_GET_INIT_INFO *Db; >> >> + >> >> + DEBUG ((DEBUG_INFO, "RndisUndiGetInitInfo\n")); >> >> + >> >> + Db = (PXE_DB_GET_INIT_INFO *)(UINTN)Cdb->DBaddr; >> >> + >> >> + Db->FrameDataLen = UsbRndisDevice->MaxTransferSize - sizeof >> (REMOTE_NDIS_PACKET_MSG) - PXE_MAC_HEADER_LEN_ETHER; >> >> + // Limit Max MTU size to 1500 bytes as RNDIS spec. >> >> + if (Db->FrameDataLen > PXE_MAX_TXRX_UNIT_ETHER) { >> >> + Db->FrameDataLen = PXE_MAX_TXRX_UNIT_ETHER; >> >> + } >> >> + >> >> + DEBUG ((DEBUG_INFO, "Db->FrameDataLen %x\n", Db->FrameDataLen)); >> >> + >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This function is called when RndisUndiGetConfigInfo is invoked. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiGetConfigInfo ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + DEBUG ((DEBUG_INFO, "RndisUndiGetConfigInfo\n")); >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This function is called when UndiInitialize is invoked. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_UNSUPPORTED Not supported. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiInitialize ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + USB_ETHERNET_PROTOCOL *UsbEthDriver = Nic->UsbEth; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice = >> USB_RNDIS_DEVICE_FROM_THIS (UsbEthDriver); >> >> + REMOTE_NDIS_INITIALIZE_MSG RndisInitMsg; >> >> + REMOTE_NDIS_INITIALIZE_CMPLT RndisInitMsgCmplt; >> >> + EFI_STATUS Status; >> >> + >> >> + DEBUG ((DEBUG_INFO, "RndisUndiInitialize\n")); >> >> + >> >> + ZeroMem (&RndisInitMsg, sizeof (REMOTE_NDIS_INITIALIZE_MSG)); >> >> + ZeroMem (&RndisInitMsgCmplt, sizeof (REMOTE_NDIS_INITIALIZE_CMPLT)); >> >> + >> >> + RndisInitMsg.MessageType = RNDIS_INITIALIZE_MSG; >> >> + RndisInitMsg.MessageLength = sizeof (REMOTE_NDIS_INITIALIZE_MSG); >> >> + RndisInitMsg.RequestID = UsbRndisDevice->RequestId; >> >> + RndisInitMsg.MajorVersion = RNDIS_MAJOR_VERSION; >> >> + RndisInitMsg.MinorVersion = RNDIS_MINOR_VERSION; >> >> + RndisInitMsg.MaxTransferSize = RNDIS_MAX_TRANSFER_SIZE; >> >> + >> >> + RndisInitMsgCmplt.MessageType = RNDIS_INITIALIZE_CMPLT; >> >> + RndisInitMsgCmplt.MessageLength = sizeof >> (REMOTE_NDIS_INITIALIZE_CMPLT); >> >> + >> >> + Status = RndisControlMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_HEADER >> *)&RndisInitMsg, (REMOTE_NDIS_MSG_HEADER *)&RndisInitMsgCmplt); >> >> + >> >> + UsbRndisDevice->RequestId++; >> >> + >> >> + if (EFI_ERROR (Status) || (RndisInitMsgCmplt.Status & 0x80000000)) { >> >> + return Status; >> >> + } >> >> + >> >> + // Only Wired Medium is supported >> >> + if (RndisInitMsgCmplt.Medium) { >> >> + return EFI_UNSUPPORTED; >> >> + } >> >> + >> >> + UsbRndisDevice->Medium = RndisInitMsgCmplt.Medium; >> >> + UsbRndisDevice->MaxPacketsPerTransfer = >> RndisInitMsgCmplt.MaxPacketsPerTransfer; >> >> + UsbRndisDevice->MaxTransferSize = >> RndisInitMsgCmplt.MaxTransferSize; >> >> + UsbRndisDevice->PacketAlignmentFactor = >> RndisInitMsgCmplt.PacketAlignmentFactor; >> >> + >> >> + DEBUG ((DEBUG_INFO, "Medium : %x \n", RndisInitMsgCmplt.Medium)); >> >> + DEBUG ((DEBUG_INFO, "MaxPacketsPerTransfer : %x \n", >> RndisInitMsgCmplt.MaxPacketsPerTransfer)); >> >> + DEBUG ((DEBUG_INFO, "MaxTransferSize : %x\n", >> RndisInitMsgCmplt.MaxTransferSize)); >> >> + DEBUG ((DEBUG_INFO, "PacketAlignmentFactor : %x\n", >> RndisInitMsgCmplt.PacketAlignmentFactor)); >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + This function is called when UndiReset is invoked. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiReset ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + USB_ETHERNET_PROTOCOL *UsbEthDriver = Nic->UsbEth; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS >> (UsbEthDriver); >> >> + REMOTE_NDIS_RESET_MSG RndisResetMsg; >> >> + REMOTE_NDIS_RESET_CMPLT RndisResetCmplt; >> >> + EFI_STATUS Status; >> >> + >> >> + DEBUG ((DEBUG_INFO, "RndisUndiReset\n")); >> >> + >> >> + ZeroMem (&RndisResetMsg, sizeof (REMOTE_NDIS_RESET_MSG)); >> >> + ZeroMem (&RndisResetCmplt, sizeof (REMOTE_NDIS_RESET_CMPLT)); >> >> + >> >> + RndisResetMsg.MessageType = RNDIS_RESET_MSG; >> >> + RndisResetMsg.MessageLength = sizeof (REMOTE_NDIS_RESET_MSG); >> >> + >> >> + RndisResetCmplt.MessageType = RNDIS_RESET_CMPLT; >> >> + RndisResetCmplt.MessageLength = sizeof (REMOTE_NDIS_RESET_CMPLT); >> >> + >> >> + Status = RndisControlMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_HEADER >> *)&RndisResetMsg, (REMOTE_NDIS_MSG_HEADER *)&RndisResetCmplt); >> >> + >> >> + UsbRndisDevice->RequestId = 1; // Let's start with 1 >> >> + >> >> + if (EFI_ERROR (Status) || (RndisResetCmplt.Status & 0x80000000)) { >> >> + return EFI_DEVICE_ERROR; >> >> + } >> >> + >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This function is called when UndiShutdown is invoked. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiShutdown ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + USB_ETHERNET_PROTOCOL *UsbEthDriver = Nic->UsbEth; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS >> (UsbEthDriver); >> >> + REMOTE_NDIS_HALT_MSG RndisHltMsg; >> >> + EFI_STATUS Status; >> >> + >> >> + DEBUG ((DEBUG_INFO, "RndisUndiShutdown\n")); >> >> + >> >> + ZeroMem (&RndisHltMsg, sizeof (REMOTE_NDIS_HALT_MSG)); >> >> + >> >> + RndisHltMsg.MessageType = RNDIS_HLT_MSG; >> >> + RndisHltMsg.MessageLength = sizeof (REMOTE_NDIS_HALT_MSG); >> >> + >> >> + Status = RndisControlMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_HEADER >> *)&RndisHltMsg, NULL); >> >> + >> >> + if (Status == EFI_DEVICE_ERROR) { >> >> + Status = EFI_SUCCESS; >> >> + } >> >> + >> >> + UsbRndisDevice->RequestId = 1; >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Update the Media connection. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiGetStatus ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + Cdb->StatFlags &= ~(PXE_STATFLAGS_GET_STATUS_NO_MEDIA); >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + Transmit the data after appending RNDIS header. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor >> block. >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in] BulkOutData A pointer to the buffer of data that >> will be transmitted to USB >> >> + device or received from USB device. >> >> + @param[in, out] DataLength A pointer to the PacketLength. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiTransmit ( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN VOID *BulkOutData, >> >> + IN OUT UINTN *DataLength >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS >> (This); >> >> + REMOTE_NDIS_PACKET_MSG *RndisPacketMsg; >> >> + UINTN TransferLength; >> >> + >> >> + DEBUG ((DEBUG_INFO, "RndisUndiTransmit DataLength : %x\n", >> *DataLength)); >> >> + >> >> + Status = gBS->AllocatePool (EfiBootServicesData, sizeof >> (REMOTE_NDIS_PACKET_MSG) + *DataLength, (VOID **)&RndisPacketMsg); >> >> + >> >> + ZeroMem (RndisPacketMsg, sizeof (REMOTE_NDIS_PACKET_MSG)); >> >> + >> >> + RndisPacketMsg->MessageType = RNDIS_PACKET_MSG; >> >> + RndisPacketMsg->MessageLength = sizeof (REMOTE_NDIS_PACKET_MSG) + >> (UINT32)*DataLength; >> >> + RndisPacketMsg->DataOffset = sizeof (REMOTE_NDIS_PACKET_MSG) - 8; >> >> + RndisPacketMsg->DataLength = (UINT32)*DataLength; >> >> + >> >> + gBS->CopyMem (((UINT8 *)RndisPacketMsg) + sizeof >> (REMOTE_NDIS_PACKET_MSG), BulkOutData, *DataLength); >> >> + >> >> + TransferLength = RndisPacketMsg->MessageLength; >> >> + >> >> + Status = RndisTransmitDataMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_HEADER >> *)RndisPacketMsg, &TransferLength); >> >> + >> >> + DEBUG ((DEBUG_INFO, "\nRndisUndiTransmit TransferLength %lx\n", >> TransferLength)); >> >> + >> >> + gBS->FreePool (RndisPacketMsg); >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Receives and removes RNDIS header and returns the raw data. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor >> block. >> >> + @param[in] This A pointer to the USB_ETHERNET_PROTOCOL >> instance. >> >> + @param[in, out] BulkInData A pointer to the buffer of data that >> will be transmitted to USB >> >> + device or received from USB device. >> >> + @param[in, out] DataLength A pointer to the PacketLength. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + @retval EFI_BUFFER_TOO_SMALL The user provided buffer is too small >> >> + @retval EFI_NOT_FOUND No buffer was found in the list. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisUndiReceive ( >> >> + IN PXE_CDB *Cdb, >> >> + IN USB_ETHERNET_PROTOCOL *This, >> >> + IN OUT VOID *BulkInData, >> >> + IN OUT UINTN *DataLength >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + USB_RNDIS_DEVICE *UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS >> (This); >> >> + REMOTE_NDIS_PACKET_MSG *RndisPacketMsg; >> >> + UINTN TransferLength; >> >> + VOID *Buffer; >> >> + PACKET_LIST *HeadPacket = NULL; >> >> + PACKET_LIST *PacketList; >> >> + UINT32 ReceivedBytes = 0; >> >> + >> >> + // Check if there is any outstanding packet to receive >> >> + // The buffer allocated has a linked List followed by the packet. >> >> + do { >> >> + Status = gBS->AllocatePool (EfiBootServicesData, sizeof >> (PACKET_LIST) + sizeof (REMOTE_NDIS_PACKET_MSG) + >> UsbRndisDevice->MaxTransferSize, &Buffer); >> >> + RndisPacketMsg = (REMOTE_NDIS_PACKET_MSG *)(sizeof (PACKET_LIST) + >> (UINT8 *)Buffer); >> >> + PacketList = (PACKET_LIST *)Buffer; >> >> + // Save the original address for freeing it up >> >> + PacketList->OrgBuffer = Buffer; >> >> + PacketList->RemainingLength = UsbRndisDevice->MaxTransferSize; >> >> + >> >> + ZeroMem (RndisPacketMsg, sizeof (REMOTE_NDIS_PACKET_MSG)); >> >> + TransferLength = UsbRndisDevice->MaxTransferSize; >> >> + >> >> + Status = RndisReceiveDataMsg (UsbRndisDevice, >> (REMOTE_NDIS_MSG_HEADER *)RndisPacketMsg, &TransferLength); >> >> + >> >> + if (EFI_ERROR (Status) || (TransferLength == 0)) { >> >> + gBS->FreePool (Buffer); >> >> + break; >> >> + } >> >> + >> >> + // Handle Multiple packets >> >> + if ((RndisPacketMsg->MessageType == RNDIS_PACKET_MSG) && >> (RndisPacketMsg->DataOffset == sizeof (REMOTE_NDIS_PACKET_MSG) - 8)) { >> >> + // Insert Packet >> >> + InsertTailList (&UsbRndisDevice->ReceivePacketList, Buffer); >> >> + } >> >> + } while (1); >> >> + >> >> + // Check if they linked list has any received buffer. If yes report it. >> >> + if (IsListEmpty (&UsbRndisDevice->ReceivePacketList)) { >> >> + return EFI_NOT_FOUND; >> >> + } >> >> + >> >> + HeadPacket = (PACKET_LIST *)GetFirstNode >> (&UsbRndisDevice->ReceivePacketList); >> >> + >> >> + RndisPacketMsg = (REMOTE_NDIS_PACKET_MSG *)((UINT8 *)HeadPacket + >> sizeof (PACKET_LIST)); >> >> + >> >> + PrintRndisMsg ((REMOTE_NDIS_MSG_HEADER *)RndisPacketMsg); >> >> + >> >> + if ((RndisPacketMsg->MessageType == RNDIS_PACKET_MSG) && >> (RndisPacketMsg->DataOffset == sizeof (REMOTE_NDIS_PACKET_MSG) - 8)) { >> >> + if (*DataLength >= RndisPacketMsg->DataLength) { >> >> + gBS->CopyMem (BulkInData, (UINT8 *)RndisPacketMsg + >> RndisPacketMsg->DataOffset + 8, RndisPacketMsg->DataLength); >> >> + >> >> + ReceivedBytes += >> RndisPacketMsg->DataLength; >> >> + BulkInData = ((UINT8 >> *)BulkInData) + RndisPacketMsg->DataLength; >> >> + ((PACKET_LIST *)HeadPacket)->RemainingLength -= >> RndisPacketMsg->DataLength; >> >> + } else { >> >> + DEBUG ((EFI_D_ERROR, "RndisUndiReceive:Buffer too small %x\n", >> RndisPacketMsg->DataLength)); >> >> + *DataLength = RndisPacketMsg->DataLength; >> >> + return EFI_BUFFER_TOO_SMALL; >> >> + } >> >> + >> >> + // check if there this is a multi-packet message. If so update the >> pointer so that next Receive call will return that data. >> >> + RndisPacketMsg = (REMOTE_NDIS_PACKET_MSG *)((UINT8 *)RndisPacketMsg >> + RndisPacketMsg->DataLength); >> >> + PacketList = (PACKET_LIST *)((UINT8 *)RndisPacketMsg - sizeof >> (PACKET_LIST)); >> >> + >> >> + if ((HeadPacket->RemainingLength > sizeof (REMOTE_NDIS_PACKET_MSG)) >> && \ >> >> + (RndisPacketMsg->MessageType == RNDIS_PACKET_MSG) && \ >> >> + (RndisPacketMsg->DataOffset == sizeof (REMOTE_NDIS_PACKET_MSG) - >> 8)) >> >> + { >> >> + // Multi-Packet msg is found. Since the first packet is consumed, >> update the linked list to point this new packet. >> >> + PacketList->OrgBuffer = HeadPacket->OrgBuffer; >> >> + PacketList->RemainingLength = HeadPacket->RemainingLength; >> >> + RemoveEntryList (&HeadPacket->PacketList); >> >> + InsertHeadList (&UsbRndisDevice->ReceivePacketList, >> &(PacketList->PacketList)); >> >> + } else { >> >> + RemoveEntryList (&HeadPacket->PacketList); >> >> + gBS->FreePool ((PACKET_LIST *)HeadPacket->OrgBuffer); >> >> + } >> >> + } else { >> >> + // Packet doesn't contain valid header >> >> + DEBUG ((DEBUG_INFO, "RndisUndiReceive:Invalid RNDIS Packet >> received\n")); >> >> + RemoveEntryList (&(HeadPacket->PacketList)); >> >> + gBS->FreePool ((PACKET_LIST *)HeadPacket->OrgBuffer); >> >> + } >> >> + >> >> + if (ReceivedBytes) { >> >> + *DataLength = ReceivedBytes; >> >> + } >> >> + >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This is a dummy function which just returns. Unimplimented >> USB_ETHERNET_PROTOCOL functions >> >> + point to this function. >> >> + >> >> + @param[in] Cdb A pointer to the command descriptor block. >> >> + @param[in] Nic A pointer to the Network interface controller data. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +EFIAPI >> >> +RndisDummyReturn ( >> >> + IN PXE_CDB *Cdb, >> >> + IN NIC_DATA *Nic >> >> + ) >> >> +{ >> >> + DEBUG ((DEBUG_INFO, "RndisDummyReturn called\n")); >> >> + return EFI_SUCCESS; >> >> +} >> >> + >> >> +/** >> >> + This function sends the RNDIS SET_MSG cmd >> >> + >> >> + @param[in] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE instance. >> >> + @param[in] Oid Value of the OID. >> >> + @param[in] Length Length of the data buffer. >> >> + @param[in] Buf A pointer to the data buffer. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +SendRndisSetMsg ( >> >> + IN USB_RNDIS_DEVICE *UsbRndisDevice, >> >> + IN UINT8 Oid, >> >> + IN UINT32 Length, >> >> + IN UINT8 *Buf >> >> + ) >> >> +{ >> >> + REMOTE_NDIS_SET_MSG *RndisSetMsg; >> >> + EFI_STATUS Status; >> >> + >> >> + RndisSetMsg = AllocateZeroPool (sizeof (USB_RNDIS_DEVICE) + Length); >> >> + >> >> + RndisSetMsg->MessageType = RNDIS_SET_MSG; >> >> + RndisSetMsg->MessageLength = sizeof (REMOTE_NDIS_SET_MSG) + >> Length; >> >> + RndisSetMsg->RequestID = UsbRndisDevice->RequestId; >> >> + RndisSetMsg->Oid = Oid; >> >> + RndisSetMsg->InformationBufferLength = Length; >> >> + RndisSetMsg->InformationBufferOffset = sizeof (REMOTE_NDIS_SET_MSG) - >> 8; >> >> + >> >> + gBS->CopyMem (((UINT8 *)RndisSetMsg) + sizeof (REMOTE_NDIS_SET_MSG), >> Buf, Length); >> >> + >> >> + Status = RndisControlMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_HEADER >> *)RndisSetMsg, NULL); >> >> + >> >> + gBS->FreePool (RndisSetMsg); >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + This function send the RNDIS command through the device's control >> endpoint >> >> + >> >> + @param[in] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE >> instance. >> >> + @param[in] RndisMsg A pointer to the REMOTE_NDIS_MSG_HEADER >> data. >> >> + @param[out] RndisMsgResponse A pointer to the REMOTE_NDIS_MSG_HEADER >> data for getting responses. >> >> + >> >> + @retval EFI_SUCCESS The bulk transfer has been successfully >> executed. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +RndisControlMsg ( >> >> + IN USB_RNDIS_DEVICE *UsbRndisDevice, >> >> + IN REMOTE_NDIS_MSG_HEADER *RndisMsg, >> >> + OUT REMOTE_NDIS_MSG_HEADER *RndisMsgResponse >> >> + ) >> >> +{ >> >> + EFI_USB_IO_PROTOCOL *UsbIo = UsbRndisDevice->UsbIo; >> >> + EFI_USB_DEVICE_REQUEST DevReq; >> >> + UINT32 UsbStatus; >> >> + EFI_STATUS Status; >> >> + UINT32 SaveResponseType = 0; >> >> + UINT32 SaveResponseLength = 0; >> >> + UINT32 Index; >> >> + REMOTE_NDIS_INITIALIZE_CMPLT *RndisInitCmplt = >> (REMOTE_NDIS_INITIALIZE_CMPLT *)RndisMsgResponse; >> >> + >> >> + if (RndisMsgResponse) { >> >> + SaveResponseType = RndisMsgResponse->MessageType; >> >> + SaveResponseLength = RndisMsgResponse->MessageLength; >> >> + } >> >> + >> >> + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); >> >> + >> >> + DevReq.RequestType = USB_REQ_TYPE_CLASS | USB_TARGET_INTERFACE; >> >> + DevReq.Request = SEND_ENCAPSULATED_COMMAND; >> >> + DevReq.Value = 0; >> >> + DevReq.Index = 0; >> >> + DevReq.Length = (UINT16)RndisMsg->MessageLength; >> >> + >> >> + PrintRndisMsg (RndisMsg); >> >> + >> >> + Status = UsbIo->UsbControlTransfer ( >> >> + UsbIo, >> >> + &DevReq, >> >> + EfiUsbDataOut, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + RndisMsg, >> >> + RndisMsg->MessageLength, >> >> + &UsbStatus >> >> + ); >> >> + >> >> + DEBUG ((DEBUG_INFO, "RndisControlMsg: UsbStatus : %x Status : %r >> RndisMsgResponse : %lx\n", UsbStatus, Status, RndisMsgResponse)); >> >> + >> >> + // Error or no response expected >> >> + if ((EFI_ERROR (Status)) || (RndisMsgResponse == NULL)) { >> >> + DEBUG ((DEBUG_INFO, "RndisControlMsg: UsbStatus : %x Status : %r\n", >> UsbStatus, Status)); >> >> + return Status; >> >> + } >> >> + >> >> + for (Index = 0; Index < (RNDIS_CONTROL_TIMEOUT/100); Index++) { >> >> + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); >> >> + >> >> + DevReq.RequestType = USB_ENDPOINT_DIR_IN | USB_REQ_TYPE_CLASS | >> USB_TARGET_INTERFACE; >> >> + DevReq.Request = GET_ENCAPSULATED_RESPONSE; >> >> + DevReq.Value = 0; >> >> + DevReq.Index = 0; >> >> + DevReq.Length = (UINT16)RndisMsgResponse->MessageLength; >> >> + >> >> + Status = UsbIo->UsbControlTransfer ( >> >> + UsbIo, >> >> + &DevReq, >> >> + EfiUsbDataIn, >> >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> >> + RndisMsgResponse, >> >> + RndisMsgResponse->MessageLength, >> >> + &UsbStatus >> >> + ); >> >> + >> >> + DEBUG ((DEBUG_INFO, "RndisControlMsg Response: UsbStatus : %x Status >> : %r \n", UsbStatus, Status)); >> >> + >> >> + PrintRndisMsg (RndisMsgResponse); >> >> + >> >> + if (!EFI_ERROR (Status)) { >> >> + if ((RndisInitCmplt->RequestID != ((REMOTE_NDIS_INITIALIZE_CMPLT >> *)RndisMsg)->RequestID) || (RndisInitCmplt->MessageType != >> SaveResponseType)) { >> >> + DEBUG ((DEBUG_INFO, "Retry the response\n")); >> >> + continue; >> >> + } >> >> + >> >> + return Status; >> >> + } >> >> + >> >> + RndisMsgResponse->MessageType = SaveResponseType; >> >> + RndisMsgResponse->MessageLength = SaveResponseLength; >> >> + >> >> + gBS->Stall (100000); // 100msec >> >> + } >> >> + >> >> + DEBUG ((DEBUG_INFO, "RndisControlMsg: TimeOut\n")); >> >> + >> >> + return EFI_TIMEOUT; >> >> +} >> >> + >> >> +/** >> >> + This function send the RNDIS command through the device's Data endpoint >> >> + >> >> + @param[in] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE >> instance. >> >> + @param[in] RndisMsg A pointer to the >> REMOTE_NDIS_MSG_HEADER to send out. >> >> + @param[in, out] TransferLength The length of the RndisMsg data to >> transfer. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +RndisTransmitDataMsg ( >> >> + IN USB_RNDIS_DEVICE *UsbRndisDevice, >> >> + IN REMOTE_NDIS_MSG_HEADER *RndisMsg, >> >> + IN OUT UINTN *TransferLength >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINT32 UsbStatus; >> >> + >> >> + if (UsbRndisDevice->BulkInEndpoint == 0) { >> >> + GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice); >> >> + } >> >> + >> >> + PrintRndisMsg (RndisMsg); >> >> + >> >> + Status = UsbRndisDevice->UsbIoCdcData->UsbBulkTransfer ( >> >> + UsbRndisDevice->UsbIoCdcData, >> >> + >> UsbRndisDevice->BulkOutEndpoint, >> >> + RndisMsg, >> >> + TransferLength, >> >> + USB_TX_ETHERNET_BULK_TIMEOUT, >> >> + &UsbStatus >> >> + ); >> >> + >> >> + if (Status == EFI_SUCCESS) { >> >> + StopBulkInCnt = MAXIMUM_STOPBULKIN_CNT; // After sending cmd ,we >> will polling receive package for MAXIMUM_STOPBULKIN_CNT times >> >> + } >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + This function send the RNDIS command through the device's Data endpoint >> >> + >> >> + @param[in] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE >> instance. >> >> + @param[in, out] RndisMsg A pointer to the >> REMOTE_NDIS_MSG_HEADER to send out. >> >> + @param[in, out] TransferLength The length of the RndisMsg data to >> transfer. >> >> + >> >> + @retval EFI_SUCCESS The request executed successfully. >> >> + >> >> +**/ >> >> +EFI_STATUS >> >> +RndisReceiveDataMsg ( >> >> + IN USB_RNDIS_DEVICE *UsbRndisDevice, >> >> + IN OUT REMOTE_NDIS_MSG_HEADER *RndisMsg, >> >> + IN OUT UINTN *TransferLength >> >> + ) >> >> +{ >> >> + EFI_STATUS Status; >> >> + UINT32 UsbStatus = 0; >> >> + >> >> + if (UsbRndisDevice->BulkInEndpoint == 0) { >> >> + GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice); >> >> + } >> >> + >> >> + // Use StopBulkInCnt to stop BulkIn command >> >> + if (StopBulkInCnt || LAN_BULKIN_CMD_CONTROL) { >> >> + Status = UsbRndisDevice->UsbIoCdcData->UsbBulkTransfer ( >> >> + >> UsbRndisDevice->UsbIoCdcData, >> >> + >> UsbRndisDevice->BulkInEndpoint, >> >> + RndisMsg, >> >> + TransferLength, >> >> + >> USB_RX_ETHERNET_BULK_TIMEOUT, >> >> + &UsbStatus >> >> + ); >> >> + >> >> + if (!EFI_ERROR (Status)) { >> >> + StopBulkInCnt = MINIMUM_STOPBULKIN_CNT; >> >> + } else { >> >> + StopBulkInCnt--; >> >> + } >> >> + } else { >> >> + Status = EFI_TIMEOUT; >> >> + *TransferLength = 0; >> >> + BlockBulkInCnt++; >> >> + } >> >> + >> >> + if (BlockBulkInCnt > BULKIN_CMD_POLLING_CNT) { >> >> + StopBulkInCnt = MINIMUM_STOPBULKIN_CNT; >> >> + BlockBulkInCnt = 0; >> >> + } >> >> + >> >> + PrintRndisMsg (RndisMsg); >> >> + >> >> + return Status; >> >> +} >> >> + >> >> +/** >> >> + Prints RNDIS Header and Data >> >> + >> >> + @param[in] RndisMsg A pointer to the REMOTE_NDIS_MSG_HEADER data. >> >> + >> >> +**/ >> >> +VOID >> >> +PrintRndisMsg ( >> >> + IN REMOTE_NDIS_MSG_HEADER *RndisMsg >> >> + ) >> >> +{ >> >> + UINTN Length = 0; >> >> + >> >> + switch (RndisMsg->MessageType) { >> >> + case RNDIS_PACKET_MSG: >> >> + DEBUG ((DEBUG_INFO, "RNDIS_PACKET_MSG:\n")); >> >> + Length = sizeof (REMOTE_NDIS_PACKET_MSG) + 0x14; >> >> + break; >> >> + case RNDIS_INITIALIZE_MSG: >> >> + DEBUG ((DEBUG_INFO, "RNDIS_INITIALIZE_MSG:\n")); >> >> + Length = sizeof (REMOTE_NDIS_INITIALIZE_MSG); >> >> + break; >> >> + case RNDIS_INITIALIZE_CMPLT: >> >> + DEBUG ((DEBUG_INFO, "RNDIS_INITIALIZE_CMPLT:\n")); >> >> + Length = sizeof (REMOTE_NDIS_INITIALIZE_CMPLT); >> >> + break; >> >> + case RNDIS_HLT_MSG: >> >> + DEBUG ((DEBUG_INFO, "RNDIS_HLT_MSG:\n")); >> >> + Length = sizeof (REMOTE_NDIS_HALT_MSG); >> >> + break; >> >> + case RNDIS_QUERY_MSG: >> >> + DEBUG ((DEBUG_INFO, "RNDIS_QUERY_MSG:\n")); >> >> + Length = sizeof (REMOTE_NDIS_QUERY_MSG); >> >> + break; >> >> + case RNDIS_QUERY_CMPLT: >> >> + DEBUG ((DEBUG_INFO, "RNDIS_QUERY_CMPLT:\n")); >> >> + Length = sizeof (REMOTE_NDIS_QUERY_CMPLT); >> >> + break; >> >> + case RNDIS_SET_MSG: >> >> + DEBUG ((DEBUG_INFO, "RNDIS_SET_MSG:\n")); >> >> + Length = sizeof (REMOTE_NDIS_SET_MSG); >> >> + break; >> >> + case RNDIS_SET_CMPLT: >> >> + DEBUG ((DEBUG_INFO, "RNDIS_SET_CMPLT:\n")); >> >> + Length = sizeof (REMOTE_NDIS_SET_CMPLT); >> >> + break; >> >> + case RNDIS_RESET_MSG: >> >> + DEBUG ((DEBUG_INFO, "RNDIS_RESET_MSG:\n")); >> >> + Length = sizeof (REMOTE_NDIS_RESET_MSG); >> >> + break; >> >> + case RNDIS_RESET_CMPLT: >> >> + DEBUG ((DEBUG_INFO, "RNDIS_RESET_CMPLT:\n")); >> >> + Length = sizeof (REMOTE_NDIS_RESET_CMPLT); >> >> + break; >> >> + case RNDIS_INDICATE_STATUS_MSG: >> >> + DEBUG ((DEBUG_INFO, "RNDIS_INDICATE_STATUS_MSG:\n")); >> >> + Length = sizeof (REMOTE_NDIS_INDICATE_STATUS_MSG); >> >> + break; >> >> + case RNDIS_KEEPALIVE_MSG: >> >> + DEBUG ((DEBUG_INFO, "RNDIS_KEEPALIVE_MSG:\n")); >> >> + Length = sizeof (REMOTE_NDIS_KEEPALIVE_MSG); >> >> + break; >> >> + case RNDIS_KEEPALIVE_CMPLT: >> >> + DEBUG ((DEBUG_INFO, "RNDIS_KEEPALIVE_CMPLT:\n")); >> >> + Length = sizeof (REMOTE_NDIS_KEEPALIVE_CMPLT); >> >> + } >> >> + >> >> + if (Length) { >> >> + UINTN Index = 0; >> >> + for ( ; Length; Length -= 4, Index++) { >> >> + DEBUG ((DEBUG_INFO, "%8X\t", RndisMsg[Index])); >> >> + if (((Index % 4) == 3) && (Index != 0)) { >> >> + DEBUG ((DEBUG_INFO, "\n")); >> >> + } >> >> + } >> >> + >> >> + if (Index % 4) { >> >> + DEBUG ((DEBUG_INFO, "\n")); >> >> + } >> >> + } >> >> +} >> >> -- >> 2.35.1.windows.2 >> -The information contained in this message may be confidential and >> proprietary to American Megatrends (AMI). This communication is intended to >> be read only by the individual or entity to whom it is addressed or by >> their designee. If the reader of this message is not the intended >> recipient, you are on notice that any distribution of this message, in any >> form, is strictly prohibited. Please promptly notify the sender by reply >> e-mail or by telephone at 770-246-8600, and then delete or destroy all >> copies of the transmission. >> >> >> >> >> >> > > -- > Pedro Falcato > -- Pedro Falcato