From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from out5-smtp.messagingengine.com (out5-smtp.messagingengine.com [66.111.4.29]) by mx.groups.io with SMTP id smtpd.web10.37942.1679930017444341326 for ; Mon, 27 Mar 2023 08:13:38 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="signature has expired" header.i=@bsdio.com header.s=fm3 header.b=NLteiczL; spf=pass (domain: bsdio.com, ip: 66.111.4.29, mailfrom: rebecca@bsdio.com) Received: from compute2.internal (compute2.nyi.internal [10.202.2.46]) by mailout.nyi.internal (Postfix) with ESMTP id ACA235C00B3; Mon, 27 Mar 2023 11:13:36 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute2.internal (MEProxy); Mon, 27 Mar 2023 11:13:36 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bsdio.com; h=cc :cc:content-transfer-encoding:content-type:content-type:date :date:from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:sender:subject:subject:to:to; s=fm3; t= 1679930016; x=1680016416; bh=F6yAomfj/4X7VRLFUH75u8Suhz+SdvILyP6 7kLo4ok4=; b=NLteiczLHvtPKab8y7QCnHyneg6mJLaEVybtPtG8Z+RUlP1dr3E N/w2kjycInjo3u+cN7ymQb7jajmtRtPU/lPn2Sx9s/pGfA7Ya4DI/VzuVuRiUADq mbjR3hOmsLrcU4Yrb4NUDFU7EHhwytPbQM5jye34zJ/u8a0cNGNidGOEtABTiJPm jLQC3fhjK5qgUfGIIh8c1hh3oc//JJF1K9btj3jemvesFgW+j76ngDftHbS9dZq4 jUcLxxcRJ3goQxywz90q5Az0GcLxsL88kY6SPBOJiP+kGLvB6RdzjfAEX+jXuXK5 FREy6agGKbBu8K6z4/Vu4GCzjgsKL8rrIew== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-transfer-encoding :content-type:content-type:date:date:feedback-id:feedback-id :from:from:in-reply-to:in-reply-to:message-id:mime-version :references:reply-to:sender:subject:subject:to:to:x-me-proxy :x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s=fm2; t= 1679930016; x=1680016416; bh=F6yAomfj/4X7VRLFUH75u8Suhz+SdvILyP6 7kLo4ok4=; b=hm9dMnUDs3cYqTSnuYIXRtp1CCXew4QZ5hBkHloQOovkLeah9dW iMA0k9tlvt9NxgxJg95J2cRpALd6CeyV6XpaKdBGc69mJvGfX+tU180ZeK85Verb 1CAIU3SyiQdCHLbSVPIJtczW1U7Uf3HVes3taXpEmRtAKVi3nf7hSFsRpGpOKMdL PbbJfj/6M5rnmG50FECnhy59gVydtvlNKYL7rRkhr9MFfPHIhjaKVH17hGMXvBaQ Ov7rqxIzeZInDYh4t9FhxwippNxJO0oso6zbrqZN2DE/thuGizUjiaQJPy2UEKvx LF14fiXIGraf5eXWdrk066dx1mkHPGLXYMg== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvhedrvdehvddgkeeiucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepkfffgggfuffvvehfhfgjtgfgsehtkeertddtfeejnecuhfhrohhmpeftvggs vggttggrucevrhgrnhcuoehrvggsvggttggrsegsshguihhordgtohhmqeenucggtffrrg htthgvrhhnpeegfeegveduheejgfduffefhfehleehiefghfetvdejvdelhfeukefhhfdv geehveenucevlhhushhtvghrufhiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpe hrvggsvggttggrsegsshguihhordgtohhm X-ME-Proxy: Feedback-ID: i5b994698:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Mon, 27 Mar 2023 11:13:33 -0400 (EDT) Message-ID: <9c2f244b-280f-8eb8-c352-79dcb41fa4e1@bsdio.com> Date: Mon, 27 Mar 2023 09:13:32 -0600 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:102.0) Gecko/20100101 Thunderbird/102.9.0 Subject: Re: [edk2-devel] [PATCH v6 1/3] UsbNetworkPkg/UsbRndis: Add USB RNDIS devices support To: devel@edk2.groups.io, tinhnguyen@os.amperecomputing.com, =?UTF-8?B?UmljaGFyZCBIbyAo5L2V5piO5b+gKQ==?= Cc: Andrew Fish , Leif Lindholm , Michael D Kinney , Michael Kubacki , Zhiguang Liu , Liming Gao , =?UTF-8?B?VG9ueSBMbyAo576F6YeR5p2+KQ==?= References: <20230309075134.864-1-richardho@ami.com> <2a40d264-3446-a2b7-4a55-2f1455f4ee32@amperemail.onmicrosoft.com> From: "Rebecca Cran" In-Reply-To: <2a40d264-3446-a2b7-4a55-2f1455f4ee32@amperemail.onmicrosoft.com> Content-Language: en-US Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit I'll review them later today. -- Rebecca Cran On 3/27/23 8:59 AM, Tinh Nguyen via groups.io wrote: > Are there any plans for these patches? Could someone please assist in > reviewing these? > > On 3/9/2023 2:51 PM, Richard Ho (何明忠) wrote: >> This driver provides UEFI driver for USB RNDIS device >> >> Signed-off-by: Richard Ho >> Cc: Andrew Fish >> Cc: Leif Lindholm >> Cc: Michael D Kinney >> Cc: Michael Kubacki >> Cc: Zhiguang Liu >> Cc: Liming Gao >> Cc: Rebecca Cran >> Tested-by: Tinh Nguyen >> Reviewed-by: Tony Lo >> --- >>   UsbNetworkPkg/UsbNetworkPkg.dec               |   46 + >>   UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc    |    9 + >>   .../Config/UsbNetworkPkgComponentsDxe.inc.dsc |   20 + >>   .../Config/UsbNetworkPkgDefines.inc.dsc       |   23 + >>   .../Config/UsbNetworkPkgComponentsDxe.inc.fdf |   20 + >>   UsbNetworkPkg/NetworkCommon/NetworkCommon.inf |   49 + >>   UsbNetworkPkg/UsbRndis/UsbRndis.inf           |   42 + >>   .../Protocol/EdkIIUsbEthernetProtocol.h       |  878 ++++++++ >>   UsbNetworkPkg/NetworkCommon/DriverBinding.h   |  266 +++ >>   UsbNetworkPkg/UsbRndis/UsbRndis.h             |  586 ++++++ >>   UsbNetworkPkg/NetworkCommon/ComponentName.c   |  263 +++ >>   UsbNetworkPkg/NetworkCommon/DriverBinding.c   |  595 ++++++ >>   UsbNetworkPkg/NetworkCommon/PxeFunction.c     | 1803 +++++++++++++++++ >>   UsbNetworkPkg/UsbRndis/ComponentName.c        |  172 ++ >>   UsbNetworkPkg/UsbRndis/UsbRndis.c             |  886 ++++++++ >>   UsbNetworkPkg/UsbRndis/UsbRndisFunction.c     | 1718 ++++++++++++++++ >>   UsbNetworkPkg/ReadMe.md                       |   65 + >>   UsbNetworkPkg/ReleaseNotes.md                 |   11 + >>   18 files changed, 7452 insertions(+) >>   create mode 100644 UsbNetworkPkg/UsbNetworkPkg.dec >>   create mode 100644 UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc >>   create mode 100644 >> UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc >>   create mode 100644 UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc >>   create mode 100644 >> UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf >>   create mode 100644 UsbNetworkPkg/NetworkCommon/NetworkCommon.inf >>   create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndis.inf >>   create mode 100644 >> UsbNetworkPkg/Include/Protocol/EdkIIUsbEthernetProtocol.h >>   create mode 100644 UsbNetworkPkg/NetworkCommon/DriverBinding.h >>   create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndis.h >>   create mode 100644 UsbNetworkPkg/NetworkCommon/ComponentName.c >>   create mode 100644 UsbNetworkPkg/NetworkCommon/DriverBinding.c >>   create mode 100644 UsbNetworkPkg/NetworkCommon/PxeFunction.c >>   create mode 100644 UsbNetworkPkg/UsbRndis/ComponentName.c >>   create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndis.c >>   create mode 100644 UsbNetworkPkg/UsbRndis/UsbRndisFunction.c >>   create mode 100644 UsbNetworkPkg/ReadMe.md >>   create mode 100644 UsbNetworkPkg/ReleaseNotes.md >> >> diff --git a/UsbNetworkPkg/UsbNetworkPkg.dec >> b/UsbNetworkPkg/UsbNetworkPkg.dec >> new file mode 100644 >> index 000000000000..30e4e4c8aac7 >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbNetworkPkg.dec >> @@ -0,0 +1,46 @@ >> +## @file >> +#  This package defines Usb network specific interfaces and library >> classes >> +#  as well as configuration for standard edk2 packages. >> +# >> +# Copyright (c) 2023, American Megatrends International LLC. All >> rights reserved.
>> +# SPDX-License-Identifier: BSD-2-Clause-Patent >> +## >> + >> +[Defines] >> +  DEC_SPECIFICATION              = 0x00010005 >> +  PACKAGE_NAME                   = UsbNetworkPkg >> +  PACKAGE_GUID                   = abfab91e-37ea-4cb4-80a6-563dbb0bcec6 >> +  PACKAGE_VERSION                = 0.1 >> + >> +[Includes] >> +  Include >> + >> +[Protocols] >> +  ## Include/Protocol/EdkIIUsbEthernet.h >> +  gEdkIIUsbEthProtocolGuid = { 0x8d8969cc, 0xfeb0, 0x4303, { 0xb2, >> 0x1a, 0x1f, 0x11, 0x6f, 0x38, 0x56, 0x43 } } >> + >> +[Guids] >> +  ## Usb Network package token space GUID >> +  gUsbNetworkPkgTokenSpaceGuid  = { 0xA1231E82, 0x21B8, 0x4204, { >> 0x92, 0xBB, 0x37, 0x3A, 0xFB, 0x01, 0xC6, 0xA1 } } >> + >> +[PcdsFeatureFlag] >> + >> +  ## Set the PCD 'UsbCdcEcmSupport' to 'TRUE' if 'Usb Cdc Ecm >> device' need to be enabled. >> + gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport|FALSE|BOOLEAN|0x00000001 >> + >> +  ## Set the PCD 'UsbCdcNcmSupport' to 'TRUE' if 'Usb Cdc Ncm >> device' need to be enabled. >> + gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport|FALSE|BOOLEAN|0x00000002 >> + >> +  ## Set the PCD 'UsbRndisSupport' to 'TRUE' if 'Usb Rndis device' >> need to be enabled. >> + gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport|TRUE|BOOLEAN|0x00000003 >> + >> +[PcdsFixedAtBuild, PcdsPatchableInModule] >> +  ## Support rate limiting >> + >> gUsbNetworkPkgTokenSpaceGuid.EnableRateLimiting|FALSE|BOOLEAN|0x00010001 >> + >> +  ## The rate limiting Credit value is check in rate limiter event. >> +  #  It is to control the RateLimitingCreditCount max value. >> + gUsbNetworkPkgTokenSpaceGuid.RateLimitingCredit|10|UINT32|0x00010002 >> + >> +  ## The value of rate limiter event for timeout check. Default >> value is 100(unit 1ms). >> + gUsbNetworkPkgTokenSpaceGuid.RateLimitingFactor|100|UINT32|0x00010003 >> diff --git a/UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc >> b/UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc >> new file mode 100644 >> index 000000000000..a3316b1d4a89 >> --- /dev/null >> +++ b/UsbNetworkPkg/Config/UsbNetworkPkg.inc.dsc >> @@ -0,0 +1,9 @@ >> +## @file >> +# Global DSC definitions to be included into project DSC file. >> +# >> +# Copyright (c) 2023, American Megatrends International LLC. All >> rights reserved.
>> +# SPDX-License-Identifier: BSD-2-Clause-Patent >> +## >> + >> +[Components.X64] >> +!include UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc >> diff --git a/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc >> b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc >> new file mode 100644 >> index 000000000000..544df8404c64 >> --- /dev/null >> +++ b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.dsc >> @@ -0,0 +1,20 @@ >> +## @file >> +# List of Core Components. >> +# >> +# Copyright (c) 2023, American Megatrends International LLC. All >> rights reserved.
>> +# SPDX-License-Identifier: BSD-2-Clause-Patent >> +## >> + >> +  UsbNetworkPkg/NetworkCommon/NetworkCommon.inf >> + >> +!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport >> +  UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf >> +!endif >> + >> +!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport >> +  UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf >> +!endif >> + >> +!if gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport >> +  UsbNetworkPkg/UsbRndis/UsbRndis.inf >> +!endif >> diff --git a/UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc >> b/UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc >> new file mode 100644 >> index 000000000000..85a309bcf567 >> --- /dev/null >> +++ b/UsbNetworkPkg/Config/UsbNetworkPkgDefines.inc.dsc >> @@ -0,0 +1,23 @@ >> +## @file >> +# Global switches enable/disable project features. >> +# >> +# Copyright (c) 2023, American Megatrends International LLC. All >> rights reserved.
>> +# SPDX-License-Identifier: BSD-2-Clause-Patent >> +## >> + >> +[Defines] >> +!if "IA32" in $(ARCH) && "X64" in $(ARCH) >> +  DEFINE PEI=IA32 >> +  DEFINE DXE=X64 >> +!else >> +  DEFINE PEI=COMMON >> +  DEFINE DXE=COMMON >> +!endif >> + >> +[Packages] >> +  UsbNetworkPkg/UsbNetworkPkg.dec >> + >> +[PcdsFeatureFlag] >> +  gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport|FALSE >> +  gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport|FALSE >> +  gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport|TRUE >> diff --git a/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf >> b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf >> new file mode 100644 >> index 000000000000..10616d97edb4 >> --- /dev/null >> +++ b/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf >> @@ -0,0 +1,20 @@ >> +## @file >> +# List of Core Components. >> +# >> +# Copyright (c) 2023, American Megatrends International LLC. All >> rights reserved.
>> +# SPDX-License-Identifier: BSD-2-Clause-Patent >> +## >> + >> +  INF UsbNetworkPkg/NetworkCommon/NetworkCommon.inf >> + >> +!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport >> +  INF UsbNetworkPkg/UsbCdcEcm/UsbCdcEcm.inf >> +!endif >> + >> +!if gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport >> +  INF UsbNetworkPkg/UsbCdcNcm/UsbCdcNcm.inf >> +!endif >> + >> +!if gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport >> +  INF UsbNetworkPkg/UsbRndis/UsbRndis.inf >> +!endif >> diff --git a/UsbNetworkPkg/NetworkCommon/NetworkCommon.inf >> b/UsbNetworkPkg/NetworkCommon/NetworkCommon.inf >> new file mode 100644 >> index 000000000000..8923102bc350 >> --- /dev/null >> +++ b/UsbNetworkPkg/NetworkCommon/NetworkCommon.inf >> @@ -0,0 +1,49 @@ >> +## @file >> +#   This is Usb Network Common driver for DXE phase. >> +# >> +# Copyright (c) 2023, American Megatrends International LLC. All >> rights reserved.
>> +# SPDX-License-Identifier: BSD-2-Clause-Patent >> +## >> + >> +[Defines] >> +  INF_VERSION                    = 0x00010005 >> +  BASE_NAME                      = NetworkCommon >> +  FILE_GUID                      = ca6eb4f4-f1d6-4375-97d6-18856871e1bf >> +  MODULE_TYPE                    = DXE_DRIVER >> +  VERSION_STRING                 = 1.0 >> +  ENTRY_POINT                    = NetworkCommonEntry >> + >> +[Sources] >> +  DriverBinding.c >> +  DriverBinding.h >> +  ComponentName.c >> +  PxeFunction.c >> + >> +[Packages] >> +  MdePkg/MdePkg.dec >> +  MdeModulePkg/MdeModulePkg.dec >> +  UsbNetworkPkg/UsbNetworkPkg.dec >> + >> +[LibraryClasses] >> +  UefiDriverEntryPoint >> +  UefiBootServicesTableLib >> +  UefiLib >> +  DebugLib >> +  UefiUsbLib >> +  MemoryAllocationLib >> +  BaseMemoryLib >> + >> +[Protocols] >> +  gEfiNetworkInterfaceIdentifierProtocolGuid_31 >> +  gEfiUsbIoProtocolGuid >> +  gEfiDevicePathProtocolGuid >> +  gEfiDriverBindingProtocolGuid >> +  gEdkIIUsbEthProtocolGuid >> + >> +[Pcd] >> +  gUsbNetworkPkgTokenSpaceGuid.EnableRateLimiting >> +  gUsbNetworkPkgTokenSpaceGuid.RateLimitingCredit >> +  gUsbNetworkPkgTokenSpaceGuid.RateLimitingFactor >> + >> +[Depex] >> +  TRUE >> diff --git a/UsbNetworkPkg/UsbRndis/UsbRndis.inf >> b/UsbNetworkPkg/UsbRndis/UsbRndis.inf >> new file mode 100644 >> index 000000000000..64205e427745 >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbRndis/UsbRndis.inf >> @@ -0,0 +1,42 @@ >> +## @file >> +#   This is Usb Rndis driver for DXE phase. >> +# >> +# Copyright (c) 2023, American Megatrends International LLC. All >> rights reserved.
>> +# SPDX-License-Identifier: BSD-2-Clause-Patent >> +## >> + >> +[Defines] >> +  INF_VERSION                    = 0x00010005 >> +  BASE_NAME                      = UsbRndis >> +  FILE_GUID                      = 11E32C34-60B5-4991-8DEA-63D3E8C876DE >> +  MODULE_TYPE                    = DXE_DRIVER >> +  VERSION_STRING                 = 1.0 >> +  ENTRY_POINT                    = UsbRndisEntry >> + >> +[Sources] >> +  UsbRndis.c >> +  UsbRndis.h >> +  UsbRndisFunction.c >> +  ComponentName.c >> + >> +[Packages] >> +  MdePkg/MdePkg.dec >> +  UsbNetworkPkg/UsbNetworkPkg.dec >> + >> +[LibraryClasses] >> +  UefiDriverEntryPoint >> +  UefiBootServicesTableLib >> +  UefiLib >> +  DebugLib >> +  UefiUsbLib >> +  MemoryAllocationLib >> +  BaseMemoryLib >> + >> +[Protocols] >> +  gEfiUsbIoProtocolGuid >> +  gEfiDevicePathProtocolGuid >> +  gEfiDriverBindingProtocolGuid >> +  gEdkIIUsbEthProtocolGuid >> + >> +[Depex] >> +  TRUE >> diff --git >> a/UsbNetworkPkg/Include/Protocol/EdkIIUsbEthernetProtocol.h >> b/UsbNetworkPkg/Include/Protocol/EdkIIUsbEthernetProtocol.h >> new file mode 100644 >> index 000000000000..f54946c7aa69 >> --- /dev/null >> +++ b/UsbNetworkPkg/Include/Protocol/EdkIIUsbEthernetProtocol.h >> @@ -0,0 +1,878 @@ >> +/** @file >> +  Header file contains code for USB Ethernet Protocol >> +  definitions >> + >> +  Copyright (c) 2023, American Megatrends International LLC. All >> rights reserved.
>> +  SPDX-License-Identifier: BSD-2-Clause-Patent >> +**/ >> + >> +#ifndef EDKII_USB_ETHERNET_PROTOCOL_H_ >> +#define EDKII_USB_ETHERNET_PROTOCOL_H_ >> + >> +#define EDKII_USB_ETHERNET_PROTOCOL_GUID \ >> +    {0x8d8969cc, 0xfeb0, 0x4303, {0xb2, 0x1a, 0x1f, 0x11, 0x6f, >> 0x38, 0x56, 0x43}} >> + >> +typedef struct _EDKII_USB_ETHERNET_PROTOCOL >> EDKII_USB_ETHERNET_PROTOCOL; >> + >> +#define USB_CDC_CLASS          0x02 >> +#define USB_CDC_ACM_SUBCLASS   0x02 >> +#define USB_CDC_ECM_SUBCLASS   0x06 >> +#define USB_CDC_NCM_SUBCLASS   0x0D >> +#define USB_CDC_DATA_CLASS     0x0A >> +#define USB_CDC_DATA_SUBCLASS  0x00 >> +#define USB_NO_CLASS_PROTOCOL  0x00 >> +#define USB_NCM_NTB_PROTOCOL   0x01 >> +#define USB_VENDOR_PROTOCOL    0xFF >> + >> +// Type Values for the DescriptorType Field >> +#define CS_INTERFACE  0x24 >> +#define CS_ENDPOINT   0x25 >> + >> +// Descriptor SubType in Functional Descriptors >> +#define HEADER_FUN_DESCRIPTOR    0x00 >> +#define UNION_FUN_DESCRIPTOR     0x06 >> +#define ETHERNET_FUN_DESCRIPTOR  0x0F >> + >> +#define MAX_LAN_INTERFACE  0x10 >> + >> +// Table 20: Class-Specific Notification Codes >> +#define USB_CDC_NETWORK_CONNECTION  0x00 >> + >> +// 6.3.1 NetworkConnection >> +#define NETWORK_CONNECTED   0x01 >> +#define NETWORK_DISCONNECT  0x00 >> + >> +// USB Header functional Descriptor >> +typedef struct { >> +  UINT8     FunctionLength; >> +  UINT8     DescriptorType; >> +  UINT8     DescriptorSubtype; >> +  UINT16    BcdCdc; >> +} USB_HEADER_FUN_DESCRIPTOR; >> + >> +// USB Union Functional Descriptor >> +typedef struct { >> +  UINT8    FunctionLength; >> +  UINT8    DescriptorType; >> +  UINT8    DescriptorSubtype; >> +  UINT8    MasterInterface; >> +  UINT8    SlaveInterface; >> +} USB_UNION_FUN_DESCRIPTOR; >> + >> +// USB Ethernet Functional Descriptor >> +typedef struct { >> +  UINT8     FunctionLength; >> +  UINT8     DescriptorType; >> +  UINT8     DescriptorSubtype; >> +  UINT8     MacAddress; >> +  UINT32    EthernetStatistics; >> +  UINT16    MaxSegmentSize; >> +  UINT16    NumberMcFilters; >> +  UINT8     NumberPowerFilters; >> +} USB_ETHERNET_FUN_DESCRIPTOR; >> + >> +typedef struct { >> +  UINT32    UsBitRate; >> +  UINT32    DsBitRate; >> +} USB_CONNECT_SPEED_CHANGE; >> + >> +// Request Type Codes for USB Ethernet >> +#define USB_ETHERNET_GET_REQ_TYPE  0xA1 >> +#define USB_ETHERNET_SET_REQ_TYPE  0x21 >> + >> +// Class-Specific Request Codes for Ethernet subclass >> +// USB ECM 1.2 specification, Section 6.2 >> +#define SET_ETH_MULTICAST_FILTERS_REQ                0x40 >> +#define SET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ  0x41 >> +#define GET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ  0x42 >> +#define SET_ETH_PACKET_FILTER_REQ                    0x43 >> +#define GET_ETH_STATISTIC_REQ                        0x44 >> + >> +// USB ECM command request length >> +#define USB_ETH_POWER_FILTER_LENGTH   2 // Section 6.2.3 >> +#define USB_ETH_PACKET_FILTER_LENGTH  0 // Section 6.2.4 >> +#define USB_ETH_STATISTIC             4 // Section 6.2.5 >> + >> +// USB Ethernet Packet Filter Bitmap >> +// USB ECM 1.2 specification, Section 6.2.4 >> +#define USB_ETH_PACKET_TYPE_PROMISCUOUS    BIT0 >> +#define USB_ETH_PACKET_TYPE_ALL_MULTICAST  BIT1 >> +#define USB_ETH_PACKET_TYPE_DIRECTED       BIT2 >> +#define USB_ETH_PACKET_TYPE_BROADCAST      BIT3 >> +#define USB_ETH_PACKET_TYPE_MULTICAST      BIT4 >> + >> +// USB Ethernet Statistics Feature Selector Codes >> +// USB ECM 1.2 specification, Section 6.2.5 >> +#define USB_ETH_XMIT_OK                 0x01 >> +#define USB_ETH_RCV_OK                  0x02 >> +#define USB_ETH_XMIT_ERROR              0x03 >> +#define USB_ETH_RCV_ERROR               0x04 >> +#define USB_ETH_RCV_NO_BUFFER           0x05 >> +#define USB_ETH_DIRECTED_BYTES_XMIT     0x06 >> +#define USB_ETH_DIRECTED_FRAMES_XMIT    0x07 >> +#define USB_ETH_MULTICAST_BYTES_XMIT    0x08 >> +#define USB_ETH_MULTICAST_FRAMES_XMIT   0x09 >> +#define USB_ETH_BROADCAST_BYTES_XMIT    0x0A >> +#define USB_ETH_BROADCAST_FRAMES_XMIT   0x0B >> +#define USB_ETH_DIRECTED_BYTES_RCV      0x0C >> +#define USB_ETH_DIRECTED_FRAMES_RCV     0x0D >> +#define USB_ETH_MULTICAST_BYTES_RCV     0x0E >> +#define USB_ETH_MULTICAST_FRAMES_RCV    0x0F >> +#define USB_ETH_BROADCAST_BYTES_RCV     0x10 >> +#define USB_ETH_BROADCAST_FRAMES_RCV    0x11 >> +#define USB_ETH_RCV_CRC_ERROR           0x12 >> +#define USB_ETH_TRANSMIT_QUEUE_LENGTH   0x13 >> +#define USB_ETH_RCV_ERROR_ALIGNMENT     0x14 >> +#define USB_ETH_XMIT_ONE_COLLISION      0x15 >> +#define USB_ETH_XMIT_MORE_COLLISIONS    0x16 >> +#define USB_ETH_XMIT_DEFERRED           0x17 >> +#define USB_ETH_XMIT_MAX_COLLISIONS     0x18 >> +#define USB_ETH_RCV_OVERRUN             0x19 >> +#define USB_ETH_XMIT_UNDERRUN           0x1A >> +#define USB_ETH_XMIT_HEARTBEAT_FAILURE  0x1B >> +#define USB_ETH_XMIT_TIMES_CRS_LOST     0x1C >> +#define USB_ETH_XMIT_LATE_COLLISIONS    0x1D >> + >> +// NIC Information >> +typedef struct { >> +  UINT32                         Signature; >> +  EDKII_USB_ETHERNET_PROTOCOL    *UsbEth; >> +  UINT16                         InterrupOpFlag; >> +  UINT64                         MappedAddr; >> +  PXE_MAC_ADDR McastList[MAX_MCAST_ADDRESS_CNT]; >> +  UINT8                          McastCount; >> +  UINT64                         MediaHeader[MAX_XMIT_BUFFERS]; >> +  UINT8                          TxBufferCount; >> +  UINT16                         State; >> +  BOOLEAN                        CanTransmit; >> +  UINT16                         ReceiveStatus; >> +  UINT8                          RxFilter; >> +  UINT32                         RxFrame; >> +  UINT32                         TxFrame; >> +  UINT16                         NetworkConnect; >> +  UINT8                          CableDetect; >> +  UINT16                         MaxSegmentSize; >> +  EFI_MAC_ADDRESS                MacAddr; >> +  PXE_CPB_START_31               PxeStart; >> +  PXE_CPB_INITIALIZE             PxeInit; >> +  UINT8 PermNodeAddress[PXE_MAC_LENGTH]; >> +  UINT8 CurrentNodeAddress[PXE_MAC_LENGTH]; >> +  UINT8 BroadcastNodeAddress[PXE_MAC_LENGTH]; >> +  EFI_USB_DEVICE_REQUEST         Request; >> +  EFI_EVENT                      RateLimiter; >> +  UINT32                         RateLimitingCredit; >> +  UINT32                         RateLimitingCreditCount; >> +  UINT32                         RateLimitingPollTimer; >> +  BOOLEAN                        RateLimitingEnable; >> +} NIC_DATA; >> + >> +#define NIC_DATA_SIGNATURE  SIGNATURE_32('n', 'i', 'c', 'd') >> +#define NIC_DATA_FROM_EDKII_USB_ETHERNET_PROTOCOL(a)  CR (a, >> NIC_DATA, UsbEth, NIC_DATA_SIGNATURE) >> + >> +/** >> +  This command is used to determine the operational state of the UNDI. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_GET_STATE)( >> +  IN  PXE_CDB     *Cdb, >> +  IN  NIC_DATA    *Nic >> +  ); >> + >> +/** >> +  This command is used to change the UNDI operational state from >> stopped to started. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_START)( >> +  IN  PXE_CDB     *Cdb, >> +  IN  NIC_DATA    *Nic >> +  ); >> + >> +/** >> +  This command is used to change the UNDI operational state from >> started to stopped. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_STOP)( >> +  IN  PXE_CDB     *Cdb, >> +  IN  NIC_DATA    *Nic >> +  ); >> + >> +/** >> +  This command is used to retrieve initialization information that is >> +  needed by drivers and applications to initialized UNDI. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_GET_INIT_INFO)( >> +  IN  PXE_CDB     *Cdb, >> +  IN  NIC_DATA    *Nic >> +  ); >> + >> +/** >> +  This command is used to retrieve configuration information about >> +  the NIC being controlled by the UNDI. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_GET_CONFIG_INFO)( >> +  IN  PXE_CDB     *Cdb, >> +  IN  NIC_DATA    *Nic >> +  ); >> + >> +/** >> +  This command resets the network adapter and initializes UNDI using >> +  the parameters supplied in the CPB. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_INITIALIZE)( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ); >> + >> +/** >> +  This command resets the network adapter and reinitializes the UNDI >> +  with the same parameters provided in the Initialize command. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_RESET)( >> +  IN  PXE_CDB     *Cdb, >> +  IN  NIC_DATA    *Nic >> +  ); >> + >> +/** >> +  The Shutdown command resets the network adapter and leaves it in a >> +  safe state for another driver to initialize. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_SHUTDOWN)( >> +  IN  PXE_CDB     *Cdb, >> +  IN  NIC_DATA    *Nic >> +  ); >> + >> +/** >> +  The Interrupt Enables command can be used to read and/or change >> +  the current external interrupt enable settings. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_INTERRUPT_ENABLE)( >> +  IN  PXE_CDB     *Cdb, >> +  IN  NIC_DATA    *Nic >> +  ); >> + >> +/** >> +  This command is used to read and change receive filters and, >> +  if supported, read and change the multicast MAC address filter list. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_RECEIVE_FILTER)( >> +  IN  PXE_CDB     *Cdb, >> +  IN  NIC_DATA    *Nic >> +  ); >> + >> +/** >> +  This command is used to get current station and broadcast MAC >> addresses >> +  and, if supported, to change the current station MAC address. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_STATION_ADDRESS)( >> +  IN  PXE_CDB     *Cdb, >> +  IN  NIC_DATA    *Nic >> +  ); >> + >> +/** >> +  This command is used to read and clear the NIC traffic statistics. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_STATISTICS)( >> +  IN  PXE_CDB     *Cdb, >> +  IN  NIC_DATA    *Nic >> +  ); >> + >> +/** >> +  Translate a multicast IPv4 or IPv6 address to a multicast MAC >> address. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_MCAST_IPTOMAC)( >> +  IN  PXE_CDB     *Cdb, >> +  IN  NIC_DATA    *Nic >> +  ); >> + >> +/** >> +  This command is used to read and write (if supported by NIC H/W) >> +  nonvolatile storage on the NIC. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_NV_DATA)( >> +  IN  PXE_CDB     *Cdb, >> +  IN  NIC_DATA    *Nic >> +  ); >> + >> +/** >> +  This command returns the current interrupt status and/or the >> +  transmitted buffer addresses and the current media status. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_GET_STATUS)( >> +  IN  PXE_CDB     *Cdb, >> +  IN  NIC_DATA    *Nic >> +  ); >> + >> +/** >> +  This command is used to fill the media header(s) in transmit >> packet(s). >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_FILL_HEADER)( >> +  IN  PXE_CDB     *Cdb, >> +  IN  NIC_DATA    *Nic >> +  ); >> + >> +/** >> +  The Transmit command is used to place a packet into the transmit >> queue. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_TRANSMIT)( >> +  IN  PXE_CDB     *Cdb, >> +  IN  NIC_DATA    *Nic >> +  ); >> + >> +/** >> +  When the network adapter has received a frame, this command is used >> +  to copy the frame into driver/application storage. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_RECEIVE)( >> +  IN  PXE_CDB     *Cdb, >> +  IN  NIC_DATA    *Nic >> +  ); >> + >> +/** >> +  This command resets the network adapter and initializes UNDI using >> +  the parameters supplied in the CPB. >> + >> +  @param[in]      Cdb  A pointer to the command descriptor block. >> +  @param[in, out] Nic  A pointer to the Network interface controller >> data. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_INITIALIZE)( >> +  IN      PXE_CDB   *Cdb, >> +  IN OUT  NIC_DATA  *Nic >> +  ); >> + >> +/** >> +  This command is used to read and clear the NIC traffic statistics. >> + >> +  @param[in]  Nic     A pointer to the Network interface controller >> data. >> +  @param[in]  DbAddr  Data Block Address. >> +  @param[in]  DbSize  Data Block Size. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_STATISTICS)( >> +  IN  NIC_DATA    *Nic, >> +  IN  UINT64      DbAddr, >> +  IN  UINT16      DbSize >> +  ); >> + >> +/** >> +  This function is used to manage a USB device with the bulk >> transfer pipe. The endpoint is Bulk in. >> + >> +  @param[in]      Cdb           A pointer to the command descriptor >> block. >> +  @param[in]      This          A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> +  @param[in, out] Packet        A pointer to the buffer of data that >> will be transmitted to USB >> +                                device or received from USB device. >> +  @param[in, out] PacketLength  A pointer to the PacketLength. >> + >> +  @retval EFI_SUCCESS           The bulk transfer has been >> successfully executed. >> +  @retval EFI_DEVICE_ERROR      The transfer failed. The transfer >> status is returned in status. >> +  @retval EFI_INVALID_PARAMETER One or more parameters are invalid. >> +  @retval EFI_OUT_OF_RESOURCES  The request could not be submitted >> due to a lack of resources. >> +  @retval EFI_TIMEOUT           The control transfer fails due to >> timeout. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_RECEIVE)( >> +  IN     PXE_CDB               *Cdb, >> +  IN     EDKII_USB_ETHERNET_PROTOCOL *This, >> +  IN OUT VOID                  *Packet, >> +  IN OUT UINTN                 *PacketLength >> +  ); >> + >> +/** >> +  This function is used to manage a USB device with the bulk >> transfer pipe. The endpoint is Bulk out. >> + >> +  @param[in]      Cdb           A pointer to the command descriptor >> block. >> +  @param[in]      This          A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> +  @param[in, out] Packet        A pointer to the buffer of data that >> will be transmitted to USB >> +                                device or received from USB device. >> +  @param[in, out] PacketLength  A pointer to the PacketLength. >> + >> +  @retval EFI_SUCCESS           The bulk transfer has been >> successfully executed. >> +  @retval EFI_DEVICE_ERROR      The transfer failed. The transfer >> status is returned in status. >> +  @retval EFI_INVALID_PARAMETER One or more parameters are invalid. >> +  @retval EFI_OUT_OF_RESOURCES  The request could not be submitted >> due to a lack of resources. >> +  @retval EFI_TIMEOUT           The control transfer fails due to >> timeout. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_TRANSMIT)( >> +  IN     PXE_CDB               *Cdb, >> +  IN     EDKII_USB_ETHERNET_PROTOCOL *This, >> +  IN OUT VOID                  *Packet, >> +  IN OUT UINTN                 *PacketLength >> +  ); >> + >> +/** >> +  This function is used to manage a USB device with an interrupt >> transfer pipe. >> + >> +  @param[in]  This              A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> +  @param[in]  IsNewTransfer     If TRUE, a new transfer will be >> submitted to USB controller. If >> +                                FALSE, the interrupt transfer is >> deleted from the device's interrupt >> +                                transfer queue. >> +  @param[in]  PollingInterval   Indicates the periodic rate, in >> milliseconds, that the transfer is to be >> +                                executed.This parameter is required >> when IsNewTransfer is TRUE. The >> +                                value must be between 1 to 255, >> otherwise EFI_INVALID_PARAMETER is returned. >> +                                The units are in milliseconds. >> +  @param[in]  Request           A pointer to the >> EFI_USB_DEVICE_REQUEST data. >> + >> +  @retval EFI_SUCCESS           The asynchronous USB transfer >> request transfer has been successfully executed. >> +  @retval EFI_DEVICE_ERROR      The asynchronous USB transfer >> request failed. >> + >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_INTERRUPT)( >> +  IN EDKII_USB_ETHERNET_PROTOCOL   *This, >> +  IN BOOLEAN                 IsNewTransfer, >> +  IN UINTN                   PollingInterval, >> +  IN EFI_USB_DEVICE_REQUEST  *Request >> +  ); >> + >> +/** >> +  Retrieves the USB Ethernet Mac Address. >> + >> +  @param[in]  This          A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> +  @param[out] MacAddress    A pointer to the caller allocated USB >> Ethernet Mac Address. >> + >> +  @retval EFI_SUCCESS           The USB Header Functional descriptor >> was retrieved successfully. >> +  @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> +  @retval EFI_NOT_FOUND         The USB Header Functional descriptor >> was not found. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_GET_ETH_MAC_ADDRESS)( >> +  IN  EDKII_USB_ETHERNET_PROTOCOL *This, >> +  OUT EFI_MAC_ADDRESS       *MacAddress >> +  ); >> + >> +/** >> +  Retrieves the USB Ethernet Bulk transfer data size. >> + >> +  @param[in]  This          A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> +  @param[out] BulkSize      A pointer to the Bulk transfer data size. >> + >> +  @retval EFI_SUCCESS           The USB Header Functional descriptor >> was retrieved successfully. >> +  @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> +  @retval EFI_NOT_FOUND         The USB Header Functional descriptor >> was not found. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETH_MAX_BULK_SIZE)( >> +  IN  EDKII_USB_ETHERNET_PROTOCOL *This, >> +  OUT UINTN                 *BulkSize >> +  ); >> + >> +/** >> +  Retrieves the USB Header functional Descriptor. >> + >> +  @param[in]  This                   A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> +  @param[out] UsbHeaderFunDescriptor A pointer to the caller >> allocated USB Header Functional Descriptor. >> + >> +  @retval EFI_SUCCESS           The USB Header Functional descriptor >> was retrieved successfully. >> +  @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> +  @retval EFI_NOT_FOUND         The USB Header Functional descriptor >> was not found. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_HEADER_FUNCTIONAL_DESCRIPTOR)( >> +  IN EDKII_USB_ETHERNET_PROTOCOL      *This, >> +  OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor >> +  ); >> + >> +/** >> +  Retrieves the USB Union functional Descriptor. >> + >> +  @param[in]  This                   A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> +  @param[out] UsbUnionFunDescriptor  A pointer to the caller >> allocated USB Union Functional Descriptor. >> + >> +  @retval EFI_SUCCESS           The USB Union Functional descriptor >> was retrieved successfully. >> +  @retval EFI_INVALID_PARAMETER UsbUnionFunDescriptor is NULL. >> +  @retval EFI_NOT_FOUND         The USB Union Functional descriptor >> was not found. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_UNION_FUNCTIONAL_DESCRIPTOR)( >> +  IN EDKII_USB_ETHERNET_PROTOCOL     *This, >> +  OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor >> +  ); >> + >> +/** >> +  Retrieves the USB Ethernet functional Descriptor. >> + >> +  @param[in]  This                   A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> +  @param[out] UsbEthFunDescriptor    A pointer to the caller >> allocated USB Ethernet Functional Descriptor. >> + >> +  @retval EFI_SUCCESS           The USB Ethernet Functional >> descriptor was retrieved successfully. >> +  @retval EFI_INVALID_PARAMETER UsbEthFunDescriptor is NULL. >> +  @retval EFI_NOT_FOUND         The USB Ethernet Functional >> descriptor was not found. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_FUNCTIONAL_DESCRIPTOR)( >> +  IN EDKII_USB_ETHERNET_PROTOCOL        *This, >> +  OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor >> +  ); >> + >> +/** >> +  This request sets the Ethernet device multicast filters as >> specified in the >> +  sequential list of 48 bit Ethernet multicast addresses. >> + >> +  @param[in]  This                   A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> +  @param[in]  Value                  Number of filters. >> +  @param[in]  McastAddr              A pointer to the value of the >> multicast addresses. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_SET_ETH_MULTICAST_FILTERS)( >> +  IN EDKII_USB_ETHERNET_PROTOCOL *This, >> +  IN UINT16                Value, >> +  IN VOID                  *McastAddr >> +  ); >> + >> +/** >> +  This request sets up the specified Ethernet power management >> pattern filter as >> +  described in the data structure. >> + >> +  @param[in]  This                   A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> +  @param[in]  Value                  Number of filters. >> +  @param[in]  Length                 Size of the power management >> pattern filter data. >> +  @param[in]  PatternFilter          A pointer to the power >> management pattern filter structure. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_SET_ETH_POWER_MANAGE_PATTERN_FILTER)( >> +  IN EDKII_USB_ETHERNET_PROTOCOL *This, >> +  IN UINT16                Value, >> +  IN UINT16                Length, >> +  IN VOID                  *PatternFilter >> +  ); >> + >> +/** >> +  This request retrieves the status of the specified Ethernet power >> management >> +  pattern filter from the device. >> + >> +  @param[in]  This                   A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> +  @param[in]  Value                  The filter number. >> +  @param[out] PatternActive          A pointer to the pattern active >> boolean. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_GET_ETH_POWER_MANAGE_PATTERN_FILTER)( >> +  IN   EDKII_USB_ETHERNET_PROTOCOL *This, >> +  IN   UINT16                Value, >> +  OUT  BOOLEAN               *PatternActive >> +  ); >> + >> +/** >> +  This request is used to configure device Ethernet packet filter >> settings. >> + >> +  @param[in]  This              A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> +  @param[in]  Value             Packet Filter Bitmap. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_SET_ETH_PACKET_FILTER)( >> +  IN EDKII_USB_ETHERNET_PROTOCOL *This, >> +  IN UINT16                Value >> +  ); >> + >> +/** >> +  This request is used to retrieve a statistic based on the feature >> selector. >> + >> +  @param[in]  This                  A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> +  @param[in]  FeatureSelector       Value of the feature selector. >> +  @param[out] Statistic             A pointer to the 32 bit unsigned >> integer. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_GET_ETH_STATISTIC)( >> +  IN  EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  IN  UINT16                 FeatureSelector, >> +  OUT VOID                   *Statistic >> +  ); >> + >> +typedef struct { >> +  EDKII_USB_ETHERNET_UNDI_GET_STATE UsbEthUndiGetState; >> +  EDKII_USB_ETHERNET_UNDI_START               UsbEthUndiStart; >> +  EDKII_USB_ETHERNET_UNDI_STOP                UsbEthUndiStop; >> +  EDKII_USB_ETHERNET_UNDI_GET_INIT_INFO UsbEthUndiGetInitInfo; >> +  EDKII_USB_ETHERNET_UNDI_GET_CONFIG_INFO UsbEthUndiGetConfigInfo; >> +  EDKII_USB_ETHERNET_UNDI_INITIALIZE UsbEthUndiInitialize; >> +  EDKII_USB_ETHERNET_UNDI_RESET               UsbEthUndiReset; >> +  EDKII_USB_ETHERNET_UNDI_SHUTDOWN UsbEthUndiShutdown; >> +  EDKII_USB_ETHERNET_UNDI_INTERRUPT_ENABLE UsbEthUndiInterruptEnable; >> +  EDKII_USB_ETHERNET_UNDI_RECEIVE_FILTER UsbEthUndiReceiveFilter; >> +  EDKII_USB_ETHERNET_UNDI_STATION_ADDRESS UsbEthUndiStationAddress; >> +  EDKII_USB_ETHERNET_UNDI_STATISTICS UsbEthUndiStatistics; >> +  EDKII_USB_ETHERNET_UNDI_MCAST_IPTOMAC UsbEthUndiMcastIp2Mac; >> +  EDKII_USB_ETHERNET_UNDI_NV_DATA             UsbEthUndiNvData; >> +  EDKII_USB_ETHERNET_UNDI_GET_STATUS UsbEthUndiGetStatus; >> +  EDKII_USB_ETHERNET_UNDI_FILL_HEADER UsbEthUndiFillHeader; >> +  EDKII_USB_ETHERNET_UNDI_TRANSMIT UsbEthUndiTransmit; >> +  EDKII_USB_ETHERNET_UNDI_RECEIVE UsbEthUndiReceive; >> +} EDKII_USB_ETHERNET_UNDI; >> + >> +// The EDKII_USB_ETHERNET_PROTOCOL provides some basic USB Ethernet >> device relevant >> +// descriptor and specific requests. >> +struct _EDKII_USB_ETHERNET_PROTOCOL { >> +  EDKII_USB_ETHERNET_UNDI UsbEthUndi; >> +  // for calling the UNDI child functions >> +  EDKII_USB_ETHERNET_INITIALIZE UsbEthInitialize; >> +  EDKII_USB_ETHERNET_STATISTICS UsbEthStatistics; >> +  EDKII_USB_ETHERNET_RECEIVE UsbEthReceive; >> +  EDKII_USB_ETHERNET_TRANSMIT UsbEthTransmit; >> +  EDKII_USB_ETHERNET_INTERRUPT UsbEthInterrupt; >> +  EDKII_USB_GET_ETH_MAC_ADDRESS UsbEthMacAddress; >> +  EDKII_USB_ETH_MAX_BULK_SIZE UsbEthMaxBulkSize; >> +  EDKII_USB_HEADER_FUNCTIONAL_DESCRIPTOR UsbHeaderFunDescriptor; >> +  EDKII_USB_UNION_FUNCTIONAL_DESCRIPTOR UsbUnionFunDescriptor; >> +  EDKII_USB_ETHERNET_FUNCTIONAL_DESCRIPTOR UsbEthFunDescriptor; >> +  EDKII_USB_ETHERNET_SET_ETH_MULTICAST_FILTERS SetUsbEthMcastFilter; >> +  EDKII_USB_ETHERNET_SET_ETH_POWER_MANAGE_PATTERN_FILTER >> SetUsbEthPowerPatternFilter; >> +  EDKII_USB_ETHERNET_GET_ETH_POWER_MANAGE_PATTERN_FILTER >> GetUsbEthPowerPatternFilter; >> +  EDKII_USB_ETHERNET_SET_ETH_PACKET_FILTER SetUsbEthPacketFilter; >> +  EDKII_USB_ETHERNET_GET_ETH_STATISTIC GetUsbEthStatistic; >> +}; >> + >> +extern EFI_GUID  gEdkIIUsbEthProtocolGuid; >> + >> +#endif >> diff --git a/UsbNetworkPkg/NetworkCommon/DriverBinding.h >> b/UsbNetworkPkg/NetworkCommon/DriverBinding.h >> new file mode 100644 >> index 000000000000..0416ce132302 >> --- /dev/null >> +++ b/UsbNetworkPkg/NetworkCommon/DriverBinding.h >> @@ -0,0 +1,266 @@ >> +/** @file >> +  Header file for for USB network common driver >> + >> +  Copyright (c) 2023, American Megatrends International LLC. All >> rights reserved.
>> +  SPDX-License-Identifier: BSD-2-Clause-Patent >> +**/ >> + >> +#ifndef _DRIVER_BINDING_H_ >> +#define _DRIVER_BINDING_H_ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#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; >> +  VOID                                         *ReceiveBuffer; >> +} NIC_DEVICE; >> + >> +typedef VOID (*API_FUNC)( >> +  PXE_CDB *, >> +  NIC_DATA * >> +  ); >> + >> +extern PXE_SW_UNDI                   *gPxe; >> +extern NIC_DEVICE *gLanDeviceList[MAX_LAN_INTERFACE]; >> +extern EFI_COMPONENT_NAME2_PROTOCOL gNetworkCommonComponentName2; >> + >> +EFI_STATUS >> +EFIAPI >> +NetworkCommonSupported ( >> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This, >> +  IN EFI_HANDLE                   ControllerHandle, >> +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +NetworkCommonDriverStart ( >> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This, >> +  IN EFI_HANDLE                   ControllerHandle, >> +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +NetworkCommonDriverStop ( >> +  IN  EFI_DRIVER_BINDING_PROTOCOL  *This, >> +  IN  EFI_HANDLE                   ControllerHandle, >> +  IN  UINTN                        NumberOfChildren, >> +  IN  EFI_HANDLE                   *ChildHandleBuffer >> +  ); >> + >> +VOID >> +PxeStructInit ( >> +  OUT PXE_SW_UNDI  *PxeSw >> +  ); >> + >> +VOID >> +UpdateNicNum ( >> +  IN      NIC_DATA     *Nic, >> +  IN OUT  PXE_SW_UNDI  *PxeSw >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +UndiApiEntry ( >> +  IN  UINT64  Cdb >> +  ); >> + >> +UINTN >> +MapIt ( >> +  IN NIC_DATA  *Nic, >> +  IN UINT64    MemAddr, >> +  IN UINT32    Size, >> +  IN UINT32    Direction, >> +  OUT UINT64   MappedAddr >> +  ); >> + >> +VOID >> +UnMapIt ( >> +  IN NIC_DATA  *Nic, >> +  IN UINT64    MemAddr, >> +  IN UINT32    Size, >> +  IN UINT32    Direction, >> +  IN UINT64    MappedAddr >> +  ); >> + >> +VOID >> +UndiGetState ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ); >> + >> +VOID >> +UndiStart ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ); >> + >> +VOID >> +UndiStop ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ); >> + >> +VOID >> +UndiGetInitInfo ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ); >> + >> +VOID >> +UndiGetConfigInfo ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ); >> + >> +VOID >> +UndiInitialize ( >> +  IN      PXE_CDB   *Cdb, >> +  IN OUT  NIC_DATA  *Nic >> +  ); >> + >> +VOID >> +UndiReset ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ); >> + >> +VOID >> +UndiShutdown ( >> +  IN      PXE_CDB   *Cdb, >> +  IN OUT  NIC_DATA  *Nic >> +  ); >> + >> +VOID >> +UndiInterruptEnable ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ); >> + >> +VOID >> +UndiReceiveFilter ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ); >> + >> +VOID >> +UndiStationAddress ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ); >> + >> +VOID >> +UndiStatistics ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ); >> + >> +VOID >> +UndiMcastIp2Mac ( >> +  IN OUT  PXE_CDB   *Cdb, >> +  IN      NIC_DATA  *Nic >> +  ); >> + >> +VOID >> +UndiNvData ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ); >> + >> +VOID >> +UndiGetStatus ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ); >> + >> +VOID >> +UndiFillHeader ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ); >> + >> +VOID >> +UndiTransmit ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ); >> + >> +VOID >> +UndiReceive ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ); >> + >> +UINT16 >> +Initialize ( >> +  IN      PXE_CDB   *Cdb, >> +  IN OUT  NIC_DATA  *Nic >> +  ); >> + >> +UINT16 >> +Transmit ( >> +  IN      PXE_CDB   *Cdb, >> +  IN OUT  NIC_DATA  *Nic, >> +  IN      UINT64    CpbAddr, >> +  IN      UINT16    OpFlags >> +  ); >> + >> +UINT16 >> +Receive ( >> +  IN PXE_CDB       *Cdb, >> +  IN OUT NIC_DATA  *Nic, >> +  IN UINT64        CpbAddr, >> +  IN OUT UINT64    DbAddr >> +  ); >> + >> +UINT16 >> +SetFilter ( >> +  IN  NIC_DATA  *Nic, >> +  IN  UINT16    SetFilter, >> +  IN  UINT64    CpbAddr, >> +  IN  UINT32    CpbSize >> +  ); >> + >> +UINT16 >> +Statistics ( >> +  IN NIC_DATA  *Nic, >> +  IN UINT64    DbAddr, >> +  IN UINT16    DbSize >> +  ); >> + >> +#endif >> diff --git a/UsbNetworkPkg/UsbRndis/UsbRndis.h >> b/UsbNetworkPkg/UsbRndis/UsbRndis.h >> new file mode 100644 >> index 000000000000..775807042460 >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbRndis/UsbRndis.h >> @@ -0,0 +1,586 @@ >> +/** @file >> +  Header file for for USB Rndis driver >> + >> +  Copyright (c) 2023, American Megatrends International LLC. All >> rights reserved.
>> +  SPDX-License-Identifier: BSD-2-Clause-Patent >> +**/ >> + >> +#ifndef _USB_RNDIS_H_ >> +#define _USB_RNDIS_H_ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +typedef struct _REMOTE_NDIS_MSG_HEADER REMOTE_NDIS_MSG_HEADER; >> + >> +typedef struct { >> +  UINT32                         Signature; >> +  EDKII_USB_ETHERNET_PROTOCOL    UsbEth; >> +  EFI_HANDLE                     UsbCdcDataHandle; >> +  EFI_HANDLE                     UsbRndisHandle; >> +  EFI_USB_IO_PROTOCOL            *UsbIo; >> +  EFI_USB_IO_PROTOCOL            *UsbIoCdcData; >> +  EFI_USB_CONFIG_DESCRIPTOR      *Config; >> +  UINT8                          NumOfInterface; >> +  UINT8                          BulkInEndpoint; >> +  UINT8                          BulkOutEndpoint; >> +  UINT8                          InterrupEndpoint; >> +  EFI_MAC_ADDRESS                MacAddress; >> +  UINT32                         RequestId; >> +  UINT32                         Medium; >> +  UINT32                         MaxPacketsPerTransfer; >> +  UINT32                         MaxTransferSize; >> +  UINT32                         PacketAlignmentFactor; >> +  LIST_ENTRY                     ReceivePacketList; >> +} USB_RNDIS_DEVICE; >> + >> +#define USB_RNDIS_DRIVER_VERSION       1 >> +#define USB_TX_ETHERNET_BULK_TIMEOUT   3000 >> +#define USB_RX_ETHERNET_BULK_TIMEOUT   3 >> +#define USB_ETHERNET_TRANSFER_TIMEOUT  200 >> + >> +#define LAN_BULKIN_CMD_CONTROL      1 >> +#define MAXIMUM_STOPBULKIN_CNT      300        // Indicating maximum >> counts for waiting bulk in command >> +#define MINIMUM_STOPBULKIN_CNT      3          // Indicating minimum >> counts for waiting bulk in command >> +#define BULKIN_CMD_POLLING_CNT      300        // Indicating the >> waiting counts for send bulk in command when system pending >> +#define RNDIS_RESERVED_BYTE_LENGTH  8 >> + >> +#define USB_RNDIS_SIGNATURE  SIGNATURE_32('r', 'n', 'd', 's') >> +#define USB_RNDIS_DEVICE_FROM_THIS(a)  CR (a, USB_RNDIS_DEVICE, >> UsbEth, USB_RNDIS_SIGNATURE) >> + >> +extern EFI_COMPONENT_NAME2_PROTOCOL  gUsbRndisComponentName2; >> + >> +struct BIT_MAP { >> +  unsigned int    Src; >> +  unsigned int    Dst; >> +}; >> + >> +EFI_STATUS >> +EFIAPI >> +UsbRndisDriverSupported ( >> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This, >> +  IN EFI_HANDLE                   ControllerHandle, >> +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +UsbRndisDriverStart ( >> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This, >> +  IN EFI_HANDLE                   ControllerHandle, >> +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +UsbRndisDriverStop ( >> +  IN  EFI_DRIVER_BINDING_PROTOCOL  *This, >> +  IN  EFI_HANDLE                   ControllerHandle, >> +  IN  UINTN                        NumberOfChildren, >> +  IN  EFI_HANDLE                   *ChildHandleBuffer >> +  ); >> + >> +EFI_STATUS >> +LoadAllDescriptor ( >> +  IN  EFI_USB_IO_PROTOCOL        *UsbIo, >> +  OUT EFI_USB_CONFIG_DESCRIPTOR  **ConfigDesc >> +  ); >> + >> +BOOLEAN >> +NextDescriptor ( >> +  IN EFI_USB_CONFIG_DESCRIPTOR  *Desc, >> +  IN OUT UINTN                  *Offset >> +  ); >> + >> +EFI_STATUS >> +GetFunctionalDescriptor ( >> +  IN  EFI_USB_CONFIG_DESCRIPTOR  *Config, >> +  IN  UINT8                      FunDescriptorType, >> +  OUT VOID                       *DataBuffer >> +  ); >> + >> +VOID >> +GetEndpoint ( >> +  IN      EFI_USB_IO_PROTOCOL  *UsbIo, >> +  IN OUT  USB_RNDIS_DEVICE     *UsbRndisDevice >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +UsbRndisInterrupt ( >> +  IN EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  IN BOOLEAN                      IsNewTransfer, >> +  IN UINTN                        PollingInterval, >> +  IN EFI_USB_DEVICE_REQUEST       *Requst >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +InterruptCallback ( >> +  IN  VOID    *Data, >> +  IN  UINTN   DataLength, >> +  IN  VOID    *Context, >> +  IN  UINT32  Status >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +GetUsbEthMacAddress ( >> +  IN  EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  OUT EFI_MAC_ADDRESS              *MacAddress >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +UsbEthBulkSize ( >> +  IN  EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  OUT UINTN                        *BulkSize >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +RndisDummyReturn ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +RndisUndiStart ( >> +  IN PXE_CDB   *Cdb, >> +  IN NIC_DATA  *Nic >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +RndisUndiStop ( >> +  IN PXE_CDB   *Cdb, >> +  IN NIC_DATA  *Nic >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +RndisUndiGetInitInfo ( >> +  IN PXE_CDB   *Cdb, >> +  IN NIC_DATA  *Nic >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +RndisUndiGetConfigInfo ( >> +  IN PXE_CDB   *Cdb, >> +  IN NIC_DATA  *Nic >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +RndisUndiInitialize ( >> +  IN PXE_CDB   *Cdb, >> +  IN NIC_DATA  *Nic >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +RndisUndiTransmit ( >> +  IN      PXE_CDB                      *Cdb, >> +  IN      EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  IN      VOID                         *BulkOutData, >> +  IN OUT  UINTN                        *DataLength >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +RndisUndiReceive ( >> +  IN     PXE_CDB                      *Cdb, >> +  IN     EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  IN OUT VOID                         *BulkInData, >> +  IN OUT UINTN                        *DataLength >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +RndisUndiReset ( >> +  IN PXE_CDB   *Cdb, >> +  IN NIC_DATA  *Nic >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +RndisUndiShutdown ( >> +  IN PXE_CDB   *Cdb, >> +  IN NIC_DATA  *Nic >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +RndisUndiReceiveFilter ( >> +  IN PXE_CDB   *Cdb, >> +  IN NIC_DATA  *Nic >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +RndisUndiGetStatus ( >> +  IN PXE_CDB   *Cdb, >> +  IN NIC_DATA  *Nic >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +GetUsbHeaderFunDescriptor ( >> +  IN  EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  OUT USB_HEADER_FUN_DESCRIPTOR    *UsbHeaderFunDescriptor >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +GetUsbUnionFunDescriptor ( >> +  IN  EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  OUT USB_UNION_FUN_DESCRIPTOR     *UsbUnionFunDescriptor >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +GetUsbRndisFunDescriptor ( >> +  IN  EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  OUT USB_ETHERNET_FUN_DESCRIPTOR  *UsbEthFunDescriptor >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +SetUsbRndisMcastFilter ( >> +  IN EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  IN UINT16                       Value, >> +  IN VOID                         *McastAddr >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +SetUsbRndisPowerFilter ( >> +  IN EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  IN UINT16                       Value, >> +  IN UINT16                       Length, >> +  IN VOID                         *PatternFilter >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +GetUsbRndisPowerFilter ( >> +  IN EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  IN UINT16                       Value, >> +  IN BOOLEAN                      *PatternActive >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +SetUsbRndisPacketFilter ( >> +  IN EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  IN UINT16                       Value >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +GetRndisStatistic ( >> +  IN EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  IN UINT16                       Value, >> +  IN VOID                         *Statistic >> +  ); >> + >> +EFI_STATUS >> +RndisControlMsg ( >> +  IN  USB_RNDIS_DEVICE        *UsbRndisDevice, >> +  IN  REMOTE_NDIS_MSG_HEADER  *RndisMsg, >> +  OUT REMOTE_NDIS_MSG_HEADER  *RndisMsgResponse >> +  ); >> + >> +EFI_STATUS >> +RndisTransmitDataMsg ( >> +  IN  USB_RNDIS_DEVICE        *UsbRndisDevice, >> +  IN  REMOTE_NDIS_MSG_HEADER  *RndisMsg, >> +  UINTN                       *TransferLength >> +  ); >> + >> +EFI_STATUS >> +RndisReceiveDataMsg ( >> +  IN  USB_RNDIS_DEVICE        *UsbRndisDevice, >> +  IN  REMOTE_NDIS_MSG_HEADER  *RndisMsg, >> +  UINTN                       *TransferLength >> +  ); >> + >> +VOID >> +PrintRndisMsg ( >> +  IN  REMOTE_NDIS_MSG_HEADER  *RndisMsg >> +  ); >> + >> +#define RNDIS_MAJOR_VERSION      0x00000001 >> +#define RNDIS_MINOR_VERSION      0x00000000 >> +#define RNDIS_MAX_TRANSFER_SIZE  0x4000 >> + >> +#define RNDIS_PACKET_MSG           0x00000001 >> +#define RNDIS_INITIALIZE_MSG       0x00000002 >> +#define RNDIS_INITIALIZE_CMPLT     0x80000002 >> +#define RNDIS_HLT_MSG              0x00000003 >> +#define RNDIS_QUERY_MSG            0x00000004 >> +#define RNDIS_QUERY_CMPLT          0x80000004 >> +#define RNDIS_SET_MSG              0x00000005 >> +#define RNDIS_SET_CMPLT            0x80000005 >> +#define RNDIS_RESET_MSG            0x00000006 >> +#define RNDIS_RESET_CMPLT          0x80000006 >> +#define RNDIS_INDICATE_STATUS_MSG  0x00000007 >> +#define RNDIS_KEEPALIVE_MSG        0x00000008 >> +#define RNDIS_KEEPALIVE_CMPLT      0x80000008 >> + >> +#define RNDIS_STATUS_SUCCESS           0x00000000 >> +#define RNDIS_STATUS_FAILURE           0xC0000001 >> +#define RNDIS_STATUS_INVALID_DATA      0xC0010015 >> +#define RNDIS_STATUS_NOT_SUPPORTED     0xC00000BB >> +#define RNDIS_STATUS_MEDIA_CONNECT     0x4001000B >> +#define RNDIS_STATUS_MEDIA_DISCONNECT  0x4001000C >> + >> +#define RNDIS_CONTROL_TIMEOUT    10000            // 10sec >> +#define RNDIS_KEEPALIVE_TIMEOUT  5000             // 5sec >> + >> +#define SEND_ENCAPSULATED_COMMAND  0x00000000 >> +#define GET_ENCAPSULATED_RESPONSE  0x00000001 >> + >> +// >> +// General Objects >> +// >> +// Taken from NTDDNDIS.H >> +#define OID_GEN_SUPPORTED_LIST         0x00010101 >> +#define OID_GEN_HARDWARE_STATUS        0x00010102 >> +#define OID_GEN_MEDIA_SUPPORTED        0x00010103 >> +#define OID_GEN_MEDIA_IN_USE           0x00010104 >> +#define OID_GEN_MAXIMUM_LOOKAHEAD      0x00010105 >> +#define OID_GEN_MAXIMUM_FRAME_SIZE     0x00010106 >> +#define OID_GEN_LINK_SPEED             0x00010107 >> +#define OID_GEN_TRANSMIT_BUFFER_SPACE  0x00010108 >> +#define OID_GEN_RECEIVE_BUFFER_SPACE   0x00010109 >> +#define OID_GEN_TRANSMIT_BLOCK_SIZE    0x0001010A >> +#define OID_GEN_RECEIVE_BLOCK_SIZE     0x0001010B >> +#define OID_GEN_VENDOR_ID              0x0001010C >> +#define OID_GEN_VENDOR_DESCRIPTION     0x0001010D >> +#define OID_GEN_CURRENT_PACKET_FILTER  0x0001010E >> +#define OID_GEN_CURRENT_LOOKAHEAD      0x0001010F >> +#define OID_GEN_DRIVER_VERSION         0x00010110 >> +#define OID_GEN_MAXIMUM_TOTAL_SIZE     0x00010111 >> +#define OID_GEN_PROTOCOL_OPTIONS       0x00010112 >> +#define OID_GEN_MAC_OPTIONS            0x00010113 >> +#define OID_GEN_MEDIA_CONNECT_STATUS   0x00010114 >> +#define OID_GEN_MAXIMUM_SEND_PACKETS   0x00010115 >> +#define OID_GEN_VENDOR_DRIVER_VERSION  0x00010116 >> + >> +#define OID_GEN_XMIT_OK        0x00020101 >> +#define OID_GEN_RCV_OK         0x00020102 >> +#define OID_GEN_XMIT_ERROR     0x00020103 >> +#define OID_GEN_RCV_ERROR      0x00020104 >> +#define OID_GEN_RCV_NO_BUFFER  0x00020105 >> + >> +#define OID_GEN_DIRECTED_BYTES_XMIT    0x00020201 >> +#define OID_GEN_DIRECTED_FRAMES_XMIT   0x00020202 >> +#define OID_GEN_MULTICAST_BYTES_XMIT   0x00020203 >> +#define OID_GEN_MULTICAST_FRAMES_XMIT  0x00020204 >> +#define OID_GEN_BROADCAST_BYTES_XMIT   0x00020205 >> +#define OID_GEN_BROADCAST_FRAMES_XMIT  0x00020206 >> +#define OID_GEN_DIRECTED_BYTES_RCV     0x00020207 >> +#define OID_GEN_DIRECTED_FRAMES_RCV    0x00020208 >> +#define OID_GEN_MULTICAST_BYTES_RCV    0x00020209 >> +#define OID_GEN_MULTICAST_FRAMES_RCV   0x0002020A >> +#define OID_GEN_BROADCAST_BYTES_RCV    0x0002020B >> +#define OID_GEN_BROADCAST_FRAMES_RCV   0x0002020C >> +#define OID_GEN_RCV_CRC_ERROR          0x0002020D >> +#define OID_GEN_TRANSMIT_QUEUE_LENGTH  0x0002020E >> + >> +#define OID_802_3_CURRENT_ADDRESS  0x01010102 >> +// >> +// Ndis Packet Filter Bits (OID_GEN_CURRENT_PACKET_FILTER). >> +// >> +#define NDIS_PACKET_TYPE_DIRECTED        0x0001 >> +#define NDIS_PACKET_TYPE_MULTICAST       0x0002 >> +#define NDIS_PACKET_TYPE_ALL_MULTICAST   0x0004 >> +#define NDIS_PACKET_TYPE_BROADCAST       0x0008 >> +#define NDIS_PACKET_TYPE_SOURCE_ROUTING  0x0010 >> +#define NDIS_PACKET_TYPE_PROMISCUOUS     0x0020 >> +#define NDIS_PACKET_TYPE_SMT             0x0040 >> +#define NDIS_PACKET_TYPE_ALL_LOCAL       0x0080 >> +#define NDIS_PACKET_TYPE_MAC_FRAME       0x8000 >> +#define NDIS_PACKET_TYPE_FUNCTIONAL      0x4000 >> +#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL  0x2000 >> +#define NDIS_PACKET_TYPE_GROUP           0x1000 >> + >> +#pragma pack(1) >> + >> +typedef struct _REMOTE_NDIS_MSG_HEADER { >> +  UINT32    MessageType; >> +  UINT32    MessageLength; >> +} REMOTE_NDIS_MSG_HEADER; >> + >> +typedef struct { >> +  UINT32    MessageType; >> +  UINT32    MessageLength; >> +  UINT32    RequestID; >> +  UINT32    MajorVersion; >> +  UINT32    MinorVersion; >> +  UINT32    MaxTransferSize; >> +} REMOTE_NDIS_INITIALIZE_MSG; >> + >> +typedef struct { >> +  UINT32    MessageType; >> +  UINT32    MessageLength; >> +  UINT32    RequestID; >> +} REMOTE_NDIS_HALT_MSG; >> + >> +typedef struct { >> +  UINT32    MessageType; >> +  UINT32    MessageLength; >> +  UINT32    RequestID; >> +  UINT32    Oid; >> +  UINT32    InformationBufferLength; >> +  UINT32    InformationBufferOffset; >> +  UINT32    Reserved; >> +} REMOTE_NDIS_QUERY_MSG; >> + >> +typedef struct { >> +  REMOTE_NDIS_QUERY_MSG    QueryMsg; >> +  UINT8                    Addr[6]; >> +} REMOTE_NDIS_QUERY_MAC_MSG; >> + >> +typedef struct { >> +  REMOTE_NDIS_QUERY_MSG    QueryMsg; >> +  UINT32                   MaxTotalSize; >> +} REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_MSG; >> + >> +typedef struct { >> +  UINT32    MessageType; >> +  UINT32    MessageLength; >> +  UINT32    RequestID; >> +  UINT32    Oid; >> +  UINT32    InformationBufferLength; >> +  UINT32    InformationBufferOffset; >> +  UINT32    Reserved; >> +} REMOTE_NDIS_SET_MSG; >> + >> +typedef struct { >> +  UINT32    MessageType; >> +  UINT32    MessageLength; >> +  UINT32    Reserved; >> +} REMOTE_NDIS_RESET_MSG; >> + >> +typedef struct { >> +  UINT32    MessageType; >> +  UINT32    MessageLength; >> +  UINT32    Status; >> +  UINT32    StatusBufferLength; >> +  UINT32    StatusBufferOffset; >> +} REMOTE_NDIS_INDICATE_STATUS_MSG; >> + >> +typedef struct { >> +  UINT32    DiagStatus; >> +  UINT32    ErrorOffset; >> +} RNDIS_DIAGNOSTIC_INFO; >> + >> +typedef struct { >> +  UINT32    MessageType; >> +  UINT32    MessageLength; >> +  UINT32    RequestID; >> +} REMOTE_NDIS_KEEPALIVE_MSG; >> + >> +typedef struct { >> +  UINT32    MessageType; >> +  UINT32    MessageLength; >> +  UINT32    RequestID; >> +  UINT32    Status; >> +  UINT32    MajorVersion; >> +  UINT32    MinorVersion; >> +  UINT32    DeviceFlags; >> +  UINT32    Medium; >> +  UINT32    MaxPacketsPerTransfer; >> +  UINT32    MaxTransferSize; >> +  UINT32    PacketAlignmentFactor; >> +  UINT64    Reserved; >> +} REMOTE_NDIS_INITIALIZE_CMPLT; >> + >> +typedef struct { >> +  UINT32    MessageType; >> +  UINT32    MessageLength; >> +  UINT32    RequestID; >> +  UINT32    Status; >> +  UINT32    InformationBufferLength; >> +  UINT32    InformationBufferOffset; >> +} REMOTE_NDIS_QUERY_CMPLT; >> + >> +typedef struct { >> +  REMOTE_NDIS_QUERY_CMPLT    QueryCmplt; >> +  UINT8                      Addr[6]; >> +} REMOTE_NDIS_QUERY_MAC_CMPLT; >> + >> +typedef struct { >> +  REMOTE_NDIS_QUERY_CMPLT    QueryCmplt; >> +  UINT32                     MaxTotalSize; >> +} REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_CMPLT; >> + >> +typedef struct { >> +  UINT32    MessageType; >> +  UINT32    MessageLength; >> +  UINT32    RequestID; >> +  UINT32    Status; >> +} REMOTE_NDIS_SET_CMPLT; >> + >> +typedef struct { >> +  UINT32    MessageType; >> +  UINT32    MessageLength; >> +  UINT32    Status; >> +  UINT32    AddressingReset; >> +} REMOTE_NDIS_RESET_CMPLT; >> + >> +typedef struct { >> +  UINT32    MessageType; >> +  UINT32    MessageLength; >> +  UINT32    RequestID; >> +  UINT32    Status; >> +} REMOTE_NDIS_KEEPALIVE_CMPLT; >> + >> +typedef struct { >> +  UINT32    MessageType; >> +  UINT32    MessageLength; >> +  UINT32    DataOffset; >> +  UINT32    DataLength; >> +  UINT32    OutOfBandDataOffset; >> +  UINT32    OutOfBandDataLength; >> +  UINT32    NumOutOfBandDataElements; >> +  UINT32    PerPacketInfoOffset; >> +  UINT32    PerPacketInfoLength; >> +  UINT32    Reserved1; >> +  UINT32    Reserved2; >> +} REMOTE_NDIS_PACKET_MSG; >> + >> +typedef struct { >> +  UINT32    Size; >> +  UINT32    Type; >> +  UINT32    ClassInformationOffset; >> +} OUT_OF_BAND_DATA_RECORD; >> + >> +typedef struct { >> +  UINT32    Size; >> +  UINT32    Type; >> +  UINT32    ClassInformationOffset; >> +} PER_PACKET_INFO_DATA_RECORD; >> + >> +typedef struct { >> +  LIST_ENTRY    PacketList; >> +  UINT8         *OrgBuffer; >> +  UINTN         RemainingLength; >> +  UINT8         *PacketStartBuffer;    // Variable size data to follow >> +} PACKET_LIST; >> + >> +#pragma pack() >> + >> +#endif >> diff --git a/UsbNetworkPkg/NetworkCommon/ComponentName.c >> b/UsbNetworkPkg/NetworkCommon/ComponentName.c >> new file mode 100644 >> index 000000000000..e83469e13079 >> --- /dev/null >> +++ b/UsbNetworkPkg/NetworkCommon/ComponentName.c >> @@ -0,0 +1,263 @@ >> +/** @file >> +  This file contains code for USB network common driver >> +  component name definitions >> + >> +  Copyright (c) 2023, American Megatrends International LLC. All >> rights reserved.
>> +  SPDX-License-Identifier: BSD-2-Clause-Patent >> +**/ >> + >> +#include "DriverBinding.h" >> + >> +extern EFI_DRIVER_BINDING_PROTOCOL gNetworkCommonDriverBinding; >> + >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE >> gNetworkCommonDriverNameTable[] = { >> +  { >> +    "eng;en", >> +    L"Network Common Driver" >> +  }, >> +  { >> +    NULL, >> +    NULL >> +  } >> +}; >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE >> *gNetworkCommonControllerNameTable = NULL; >> + >> +EFI_STATUS >> +EFIAPI >> +NetworkCommonComponentNameGetDriverName ( >> +  IN  EFI_COMPONENT_NAME_PROTOCOL  *This, >> +  IN  CHAR8                        *Language, >> +  OUT CHAR16                       **DriverName >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +NetworkCommonComponentNameGetControllerName ( >> +  IN EFI_COMPONENT_NAME_PROTOCOL  *This, >> +  IN EFI_HANDLE                   Controller, >> +  IN EFI_HANDLE                   ChildHandle        OPTIONAL, >> +  IN CHAR8                        *Language, >> +  OUT CHAR16                      **ControllerName >> +  ); >> + >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL >> gNetworkCommonComponentName = { >> +  NetworkCommonComponentNameGetDriverName, >> +  NetworkCommonComponentNameGetControllerName, >> +  "eng" >> +}; >> + >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL >> gNetworkCommonComponentName2 = { >> + >> (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)NetworkCommonComponentNameGetDriverName, >> + >> (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)NetworkCommonComponentNameGetControllerName, >> +  "en" >> +}; >> + >> +/** >> +  Retrieves a Unicode string that is the user readable name of the >> driver. >> + >> +  This function retrieves the user readable name of a driver in the >> form of a >> +  Unicode string. If the driver specified by This has a user >> readable name in >> +  the language specified by Language, then a pointer to the driver >> name is >> +  returned in DriverName, and EFI_SUCCESS is returned. If the driver >> specified >> +  by This does not support the language specified by Language, >> +  then EFI_UNSUPPORTED is returned. >> + >> +  @param[in]  This              A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >> +                                EFI_COMPONENT_NAME_PROTOCOL instance. >> +  @param[in]  Language          A pointer to a Null-terminated ASCII >> string >> +                                array indicating the language. This >> is the >> +                                language of the driver name that the >> caller is >> +                                requesting, and it must match one of >> the >> +                                languages specified in >> SupportedLanguages. The >> +                                number of languages supported by a >> driver is up >> +                                to the driver writer. Language is >> specified >> +                                in RFC 4646 or ISO 639-2 language >> code format. >> +  @param[out] DriverName        A pointer to the Unicode string to >> return. >> +                                This Unicode string is the name of the >> +                                driver specified by This in the >> language >> +                                specified by Language. >> + >> +  @retval EFI_SUCCESS           The Unicode string for the Driver >> specified by >> +                                This and the language specified by >> Language was >> +                                returned in DriverName. >> +  @retval EFI_INVALID_PARAMETER Language is NULL. >> +  @retval EFI_INVALID_PARAMETER DriverName is NULL. >> +  @retval EFI_UNSUPPORTED       The driver specified by This does >> not support >> +                                the language specified by Language. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +NetworkCommonComponentNameGetDriverName ( >> +  IN  EFI_COMPONENT_NAME_PROTOCOL  *This, >> +  IN  CHAR8                        *Language, >> +  OUT CHAR16                       **DriverName >> +  ) >> +{ >> +  return LookupUnicodeString2 ( >> +           Language, >> +           This->SupportedLanguages, >> +           gNetworkCommonDriverNameTable, >> +           DriverName, >> +           (BOOLEAN)(This == &gNetworkCommonComponentName) >> +           ); >> +} >> + >> +/** >> +  Retrieves a Unicode string that is the user readable name of the >> controller >> +  that is being managed by a driver. >> + >> +  This function retrieves the user readable name of the controller >> specified by >> +  ControllerHandle and ChildHandle in the form of a Unicode string. >> If the >> +  driver specified by This has a user readable name in the language >> specified by >> +  Language, then a pointer to the controller name is returned in >> ControllerName, >> +  and EFI_SUCCESS is returned.  If the driver specified by This is >> not currently >> +  managing the controller specified by ControllerHandle and >> ChildHandle, >> +  then EFI_UNSUPPORTED is returned.  If the driver specified by This >> does not >> +  support the language specified by Language, then EFI_UNSUPPORTED >> is returned. >> + >> +  @param[in]  This              A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >> +                                EFI_COMPONENT_NAME_PROTOCOL instance. >> +  @param[in]  Controller        The handle of a controller that the >> driver >> +                                specified by This is managing. This >> handle >> +                                specifies the controller whose name >> is to be >> +                                returned. >> +  @param[in]  ChildHandle       The handle of the child controller >> to retrieve >> +                                the name of.  This is an optional >> parameter that >> +                                may be NULL.  It will be NULL for >> device >> +                                drivers.  It will also be NULL for a >> bus drivers >> +                                that wish to retrieve the name of >> the bus >> +                                controller.  It will not be NULL for >> a bus >> +                                driver that wishes to retrieve the >> name of a >> +                                child controller. >> +  @param[in]  Language          A pointer to a Null-terminated ASCII >> string >> +                                array indicating the language. This >> is the >> +                                language of the driver name that the >> caller is >> +                                requesting, and it must match one of >> the >> +                                languages specified in >> SupportedLanguages. The >> +                                number of languages supported by a >> driver is up >> +                                to the driver writer. Language is >> specified in >> +                                RFC 4646 or ISO 639-2 language code >> format. >> +  @param[out] ControllerName    A pointer to the Unicode string to >> return. >> +                                This Unicode string is the name of the >> +                                controller specified by >> ControllerHandle and >> +                                ChildHandle in the language >> specified by >> +                                Language from the point of view of >> the driver >> +                                specified by This. >> + >> +  @retval EFI_SUCCESS           The Unicode string for the user >> readable name in >> +                                the language specified by Language >> for the >> +                                driver specified by This was >> returned in >> +                                DriverName. >> +  @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid >> EFI_HANDLE. >> +  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is >> not a valid >> +                                EFI_HANDLE. >> +  @retval EFI_INVALID_PARAMETER Language is NULL. >> +  @retval EFI_INVALID_PARAMETER ControllerName is NULL. >> +  @retval EFI_UNSUPPORTED       The driver specified by This is not >> currently >> +                                managing the controller specified by >> +                                ControllerHandle and ChildHandle. >> +  @retval EFI_UNSUPPORTED       The driver specified by This does >> not support >> +                                the language specified by Language. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +NetworkCommonComponentNameGetControllerName ( >> +  IN  EFI_COMPONENT_NAME_PROTOCOL  *This, >> +  IN  EFI_HANDLE                   Controller, >> +  IN  EFI_HANDLE                   ChildHandle        OPTIONAL, >> +  IN  CHAR8                        *Language, >> +  OUT CHAR16                       **ControllerName >> +  ) >> +{ >> +  EFI_STATUS                 Status; >> +  CHAR16                     *HandleName; >> +  EFI_USB_IO_PROTOCOL        *UsbIo; >> +  EFI_USB_DEVICE_DESCRIPTOR  DevDesc; >> + >> +  if (!Language || !ControllerName) { >> +    return EFI_INVALID_PARAMETER; >> +  } >> + >> +  if (ChildHandle == NULL) { >> +    return EFI_UNSUPPORTED; >> +  } >> + >> +  // >> +  // Make sure this driver is currently managing ControllerHandle >> +  // >> +  Status = EfiTestManagedDevice ( >> +             Controller, >> +             gNetworkCommonDriverBinding.DriverBindingHandle, >> +             &gEdkIIUsbEthProtocolGuid >> +             ); >> +  if (EFI_ERROR (Status)) { >> +    return Status; >> +  } >> + >> +  // >> +  // Make sure this driver produced ChildHandle >> +  // >> +  Status = EfiTestChildHandle ( >> +             Controller, >> +             ChildHandle, >> +             &gEdkIIUsbEthProtocolGuid >> +             ); >> +  if (EFI_ERROR (Status)) { >> +    return Status; >> +  } >> + >> +  Status = gBS->HandleProtocol (Controller, &gEfiUsbIoProtocolGuid, >> (VOID **)&UsbIo); >> + >> +  if (!EFI_ERROR (Status)) { >> +    Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc); >> +    if (EFI_ERROR (Status)) { >> +      return Status; >> +    } >> + >> +    Status = UsbIo->UsbGetStringDescriptor (UsbIo, 0x409, >> DevDesc.StrManufacturer, &HandleName); >> +    if (EFI_ERROR (Status)) { >> +      return Status; >> +    } >> + >> +    *ControllerName = HandleName; >> + >> +    if (gNetworkCommonControllerNameTable != NULL) { >> +      FreeUnicodeStringTable (gNetworkCommonControllerNameTable); >> +      gNetworkCommonControllerNameTable = NULL; >> +    } >> + >> +    Status = AddUnicodeString2 ( >> +               "eng", >> +               gNetworkCommonComponentName.SupportedLanguages, >> +               &gNetworkCommonControllerNameTable, >> +               HandleName, >> +               TRUE >> +               ); >> +    if (EFI_ERROR (Status)) { >> +      return Status; >> +    } >> + >> +    Status = AddUnicodeString2 ( >> +               "en", >> +               gNetworkCommonComponentName2.SupportedLanguages, >> +               &gNetworkCommonControllerNameTable, >> +               HandleName, >> +               FALSE >> +               ); >> +    if (EFI_ERROR (Status)) { >> +      return Status; >> +    } >> + >> +    return LookupUnicodeString2 ( >> +             Language, >> +             This->SupportedLanguages, >> +             gNetworkCommonControllerNameTable, >> +             ControllerName, >> +             (BOOLEAN)(This == &gNetworkCommonComponentName) >> +             ); >> +  } >> + >> +  return EFI_UNSUPPORTED; >> +} >> diff --git a/UsbNetworkPkg/NetworkCommon/DriverBinding.c >> b/UsbNetworkPkg/NetworkCommon/DriverBinding.c >> new file mode 100644 >> index 000000000000..23b791362091 >> --- /dev/null >> +++ b/UsbNetworkPkg/NetworkCommon/DriverBinding.c >> @@ -0,0 +1,595 @@ >> +/** @file >> +  This file contains code for USB network binding driver >> + >> +  Copyright (c) 2023, American Megatrends International LLC. All >> rights reserved.
>> +  SPDX-License-Identifier: BSD-2-Clause-Patent >> +**/ >> + >> +#include "DriverBinding.h" >> + >> +PXE_SW_UNDI  *gPxe = NULL; >> +NIC_DEVICE   *gLanDeviceList[MAX_LAN_INTERFACE]; >> +UINT32       gRateLimitingCredit; >> +UINT32       gRateLimitingPollTimer; >> +BOOLEAN      gRateLimitingEnable; >> + >> +EFI_DRIVER_BINDING_PROTOCOL  gNetworkCommonDriverBinding = { >> +  NetworkCommonSupported, >> +  NetworkCommonDriverStart, >> +  NetworkCommonDriverStop, >> +  NETWORK_COMMON_DRIVER_VERSION, >> +  NULL, >> +  NULL >> +}; >> + >> +/** >> +  Create MAC Device Path >> + >> +  @param[in, out] Dev             A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> +  @param[in]      BaseDev         A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> +  @param[in]      Nic             A pointer to the Network interface >> controller data. >> + >> +  @retval EFI_OUT_OF_RESOURCES    The device path could not be >> created successfully due to a lack of resources. >> +  @retval EFI_SUCCESS             MAC device path created successfully. >> + >> +**/ >> +EFI_STATUS >> +CreateMacDevicePath ( >> +  IN OUT  EFI_DEVICE_PATH_PROTOCOL  **Dev, >> +  IN      EFI_DEVICE_PATH_PROTOCOL  *BaseDev, >> +  IN      NIC_DATA                  *Nic >> +  ) >> +{ >> +  EFI_STATUS                Status; >> +  MAC_ADDR_DEVICE_PATH      MacAddrNode; >> +  EFI_DEVICE_PATH_PROTOCOL  *EndNode; >> +  UINT8                     *DevicePath; >> +  UINT16                    TotalLength; >> +  UINT16                    BaseLength; >> + >> +  ZeroMem (&MacAddrNode, sizeof (MAC_ADDR_DEVICE_PATH)); >> +  CopyMem (&MacAddrNode.MacAddress, &Nic->MacAddr, sizeof >> (EFI_MAC_ADDRESS)); >> + >> +  MacAddrNode.Header.Type      = MESSAGING_DEVICE_PATH; >> +  MacAddrNode.Header.SubType   = MSG_MAC_ADDR_DP; >> +  MacAddrNode.Header.Length[0] = (UINT8)sizeof (MacAddrNode); >> +  MacAddrNode.Header.Length[1] = 0; >> + >> +  EndNode = BaseDev; >> + >> +  while (!IsDevicePathEnd (EndNode)) { >> +    EndNode = NextDevicePathNode (EndNode); >> +  } >> + >> +  BaseLength  = (UINT16)((UINTN)(EndNode) - (UINTN)(BaseDev)); >> +  TotalLength = (UINT16)(BaseLength + sizeof (MacAddrNode) + sizeof >> (EFI_DEVICE_PATH_PROTOCOL)); >> + >> +  Status = gBS->AllocatePool (EfiBootServicesData, TotalLength, >> (VOID **)&DevicePath); >> +  if (EFI_ERROR (Status)) { >> +    return Status; >> +  } >> + >> +  *Dev = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath; >> +  CopyMem (DevicePath, (CHAR8 *)BaseDev, BaseLength); >> +  DevicePath += BaseLength; >> +  CopyMem (DevicePath, (CHAR8 *)&MacAddrNode, sizeof (MacAddrNode)); >> +  DevicePath += sizeof (MacAddrNode); >> +  CopyMem (DevicePath, (CHAR8 *)EndNode, sizeof >> (EFI_DEVICE_PATH_PROTOCOL)); >> + >> +  return EFI_SUCCESS; >> +} >> + >> +/** >> +  Network Common Driver Binding Support. >> + >> +  @param[in]  This                    Protocol instance pointer. >> +  @param[in]  ControllerHandle        Handle of device to test. >> +  @param[in]  RemainingDevicePath     Optional parameter use to pick >> a specific child >> +                                      device to start. >> + >> +  @retval EFI_SUCCESS                 This driver supports this device. >> +  @retval EFI_ALREADY_STARTED         This driver is already running >> on this device. >> +  @retval other                       This driver does not support >> this device. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +NetworkCommonSupported ( >> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This, >> +  IN EFI_HANDLE                   ControllerHandle, >> +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath >> +  ) >> +{ >> +  EFI_STATUS                   Status; >> +  EDKII_USB_ETHERNET_PROTOCOL  *UsbEth; >> + >> +  Status = gBS->OpenProtocol ( >> +                  ControllerHandle, >> +                  &gEdkIIUsbEthProtocolGuid, >> +                  (VOID **)&UsbEth, >> +                  This->DriverBindingHandle, >> +                  ControllerHandle, >> +                  EFI_OPEN_PROTOCOL_BY_DRIVER >> +                  ); >> +  if (EFI_ERROR (Status)) { >> +    return Status; >> +  } >> + >> +  gBS->CloseProtocol ( >> +         ControllerHandle, >> +         &gEdkIIUsbEthProtocolGuid, >> +         This->DriverBindingHandle, >> +         ControllerHandle >> +         ); >> +  return Status; >> +} >> + >> +/** >> +  Network Common Driver Binding Start. >> + >> +  @param[in]  This                    Protocol instance pointer. >> +  @param[in]  ControllerHandle        Handle of device to bind >> driver to. >> +  @param[in]  RemainingDevicePath     Optional parameter use to pick >> a specific child >> +                                      device to start. >> + >> +  @retval EFI_SUCCESS                 This driver is added to >> ControllerHandle >> +  @retval EFI_DEVICE_ERROR            This driver could not be >> started due to a device error >> +  @retval EFI_OUT_OF_RESOURCES        The driver could not install >> successfully due to a lack of resources. >> +  @retval other                       This driver does not support >> this device >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +NetworkCommonDriverStart ( >> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This, >> +  IN EFI_HANDLE                   ControllerHandle, >> +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath >> +  ) >> +{ >> +  EFI_STATUS                   Status; >> +  EFI_DEVICE_PATH_PROTOCOL     *UsbEthPath; >> +  EDKII_USB_ETHERNET_PROTOCOL  *UsbEth; >> +  EFI_MAC_ADDRESS              MacAddress; >> +  UINTN                        BulkDataSize; >> +  NIC_DEVICE                   *NicDevice; >> +  UINT8                        *TmpPxePointer; >> + >> +  Status = gBS->OpenProtocol ( >> +                  ControllerHandle, >> +                  &gEdkIIUsbEthProtocolGuid, >> +                  (VOID **)&UsbEth, >> +                  This->DriverBindingHandle, >> +                  ControllerHandle, >> +                  EFI_OPEN_PROTOCOL_BY_DRIVER >> +                  ); >> +  if (EFI_ERROR (Status)) { >> +    return Status; >> +  } >> + >> +  Status = gBS->OpenProtocol ( >> +                  ControllerHandle, >> +                  &gEfiDevicePathProtocolGuid, >> +                  (VOID **)&UsbEthPath, >> +                  This->DriverBindingHandle, >> +                  ControllerHandle, >> +                  EFI_OPEN_PROTOCOL_BY_DRIVER >> +                  ); >> + >> +  if (EFI_ERROR (Status)) { >> +    gBS->CloseProtocol ( >> +           ControllerHandle, >> +           &gEdkIIUsbEthProtocolGuid, >> +           This->DriverBindingHandle, >> +           ControllerHandle >> +           ); >> +    return Status; >> +  } >> + >> +  ZeroMem (&MacAddress, sizeof (EFI_MAC_ADDRESS)); >> + >> +  Status = UsbEth->UsbEthMacAddress (UsbEth, &MacAddress); >> +  ASSERT_EFI_ERROR (Status); >> +  Status = UsbEth->UsbEthMaxBulkSize (UsbEth, &BulkDataSize); >> + >> +  if (EFI_ERROR (Status)) { >> +    gBS->CloseProtocol ( >> +           ControllerHandle, >> +           &gEfiDevicePathProtocolGuid, >> +           This->DriverBindingHandle, >> +           ControllerHandle >> +           ); >> +    gBS->CloseProtocol ( >> +           ControllerHandle, >> +           &gEdkIIUsbEthProtocolGuid, >> +           This->DriverBindingHandle, >> +           ControllerHandle >> +           ); >> +    return Status; >> +  } >> + >> +  NicDevice = AllocateZeroPool (sizeof (NIC_DEVICE) + BulkDataSize + >> 4096); >> +  if (!NicDevice) { >> +    gBS->CloseProtocol ( >> +           ControllerHandle, >> +           &gEfiDevicePathProtocolGuid, >> +           This->DriverBindingHandle, >> +           ControllerHandle >> +           ); >> +    gBS->CloseProtocol ( >> +           ControllerHandle, >> +           &gEdkIIUsbEthProtocolGuid, >> +           This->DriverBindingHandle, >> +           ControllerHandle >> +           ); >> +    return EFI_OUT_OF_RESOURCES; >> +  } >> + >> +  // for alignment adjustment >> +  if (gPxe == NULL) { >> +    TmpPxePointer = NULL; >> +    TmpPxePointer = AllocateZeroPool (sizeof (PXE_SW_UNDI) + 16); >> +    if (!TmpPxePointer) { >> +      if (NicDevice != NULL) { >> +        FreePool (NicDevice); >> +      } >> + >> +      gBS->CloseProtocol ( >> +             ControllerHandle, >> +             &gEfiDevicePathProtocolGuid, >> +             This->DriverBindingHandle, >> +             ControllerHandle >> +             ); >> +      gBS->CloseProtocol ( >> +             ControllerHandle, >> +             &gEdkIIUsbEthProtocolGuid, >> +             This->DriverBindingHandle, >> +             ControllerHandle >> +             ); >> + >> +      return EFI_OUT_OF_RESOURCES; >> +    } else { >> +      // check for paragraph alignment here >> +      if (((UINTN)TmpPxePointer & 0x0F) != 0) { >> +        gPxe = (PXE_SW_UNDI *)(TmpPxePointer + 8); >> +      } else { >> +        gPxe = (PXE_SW_UNDI *)TmpPxePointer; >> +      } >> + >> +      if (!gPxe) { >> +        if (NicDevice != NULL) { >> +          FreePool (NicDevice); >> +        } >> + >> +        gBS->CloseProtocol ( >> +               ControllerHandle, >> +               &gEfiDevicePathProtocolGuid, >> +               This->DriverBindingHandle, >> +               ControllerHandle >> +               ); >> +        gBS->CloseProtocol ( >> +               ControllerHandle, >> +               &gEdkIIUsbEthProtocolGuid, >> +               This->DriverBindingHandle, >> +               ControllerHandle >> +               ); >> +        return EFI_OUT_OF_RESOURCES; >> +      } >> + >> +      PxeStructInit (gPxe); >> +    } >> +  } >> + >> +  NicDevice->NiiProtocol.Id    = (UINT64)(UINTN)(gPxe); >> +  NicDevice->NiiProtocol.IfNum = gPxe->IFcnt | gPxe->IFcntExt << 8; >> + >> +  UpdateNicNum (&NicDevice->NicInfo, gPxe); >> + >> +  NicDevice->NicInfo.Signature = NIC_DATA_SIGNATURE; >> + >> +  NicDevice->NicInfo.UsbEth         = UsbEth; >> +  NicDevice->NicInfo.MaxSegmentSize = (UINT16)BulkDataSize; >> +  NicDevice->NicInfo.CableDetect    = 0; >> +  NicDevice->ReceiveBuffer          = ALIGN_POINTER ((VOID >> *)NicDevice, 4096); >> + >> +  CopyMem ((CHAR8 *)&(NicDevice->NicInfo.MacAddr), (CHAR8 >> *)&MacAddress, sizeof (MacAddress)); >> + >> +  NicDevice->NicInfo.TxBufferCount = 0; >> + >> +  if (NicDevice->NiiProtocol.IfNum < MAX_LAN_INTERFACE) { >> +    gLanDeviceList[NicDevice->NiiProtocol.IfNum] = NicDevice; >> +  } else { >> +    gBS->CloseProtocol ( >> +           ControllerHandle, >> +           &gEfiDevicePathProtocolGuid, >> +           This->DriverBindingHandle, >> +           ControllerHandle >> +           ); >> +    gBS->CloseProtocol ( >> +           ControllerHandle, >> +           &gEdkIIUsbEthProtocolGuid, >> +           This->DriverBindingHandle, >> +           ControllerHandle >> +           ); >> + >> +    if (TmpPxePointer != NULL) { >> +      FreePool (TmpPxePointer); >> +    } >> + >> +    if (NicDevice != NULL) { >> +      FreePool (NicDevice); >> +    } >> + >> +    return EFI_DEVICE_ERROR; >> +  } >> + >> +  Status = CreateMacDevicePath ( >> +             &NicDevice->DevPath, >> +             UsbEthPath, >> +             &NicDevice->NicInfo >> +             ); >> + >> +  if (EFI_ERROR (Status)) { >> +    UpdateNicNum (NULL, gPxe); >> +    if (TmpPxePointer != NULL) { >> +      FreePool (TmpPxePointer); >> +    } >> +  } >> + >> +  NicDevice->Signature                 = UNDI_DEV_SIGNATURE; >> +  NicDevice->NiiProtocol.Revision      = >> EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION; >> +  NicDevice->NiiProtocol.Type          = EfiNetworkInterfaceUndi; >> +  NicDevice->NiiProtocol.MajorVer      = PXE_ROMID_MAJORVER; >> +  NicDevice->NiiProtocol.MinorVer      = PXE_ROMID_MINORVER; >> +  NicDevice->NiiProtocol.ImageSize     = 0; >> +  NicDevice->NiiProtocol.ImageAddr     = 0; >> +  NicDevice->NiiProtocol.Ipv6Supported = TRUE; >> + >> +  NicDevice->NiiProtocol.StringId[0] = 'U'; >> +  NicDevice->NiiProtocol.StringId[1] = 'N'; >> +  NicDevice->NiiProtocol.StringId[2] = 'D'; >> +  NicDevice->NiiProtocol.StringId[3] = 'I'; >> +  NicDevice->DeviceHandle            = NULL; >> + >> +  NicDevice->NicInfo.RateLimitingEnable      = gRateLimitingEnable; >> +  NicDevice->NicInfo.RateLimitingCreditCount = 0; >> +  NicDevice->NicInfo.RateLimitingCredit      = gRateLimitingCredit; >> +  NicDevice->NicInfo.RateLimitingPollTimer   = gRateLimitingPollTimer; >> +  NicDevice->NicInfo.RateLimiter             = NULL; >> + >> +  ZeroMem (&NicDevice->NicInfo.Request, sizeof >> (EFI_USB_DEVICE_REQUEST)); >> + >> +  Status = UsbEth->UsbEthInterrupt (UsbEth, TRUE, >> NETWORK_COMMON_POLLING_INTERVAL, &NicDevice->NicInfo.Request); >> +  ASSERT_EFI_ERROR (Status); >> + >> +  Status = gBS->InstallMultipleProtocolInterfaces ( >> +                  &NicDevice->DeviceHandle, >> + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, >> +                  &NicDevice->NiiProtocol, >> +                  &gEfiDevicePathProtocolGuid, >> +                  NicDevice->DevPath, >> +                  NULL >> +                  ); >> + >> +  if (EFI_ERROR (Status)) { >> +    if (NicDevice->NiiProtocol.IfNum < MAX_LAN_INTERFACE) { >> +      gLanDeviceList[NicDevice->NiiProtocol.IfNum] = NULL; >> +    } >> + >> +    gBS->CloseProtocol ( >> +           ControllerHandle, >> +           &gEfiDevicePathProtocolGuid, >> +           This->DriverBindingHandle, >> +           ControllerHandle >> +           ); >> +    gBS->CloseProtocol ( >> +           ControllerHandle, >> +           &gEdkIIUsbEthProtocolGuid, >> +           This->DriverBindingHandle, >> +           ControllerHandle >> +           ); >> + >> +    if (TmpPxePointer != NULL) { >> +      FreePool (TmpPxePointer); >> +    } >> + >> +    if (NicDevice->DevPath != NULL) { >> +      FreePool (NicDevice->DevPath); >> +    } >> + >> +    if (NicDevice != NULL) { >> +      FreePool (NicDevice); >> +    } >> + >> +    return EFI_DEVICE_ERROR; >> +  } >> + >> +  Status = gBS->OpenProtocol ( >> +                  ControllerHandle, >> +                  &gEdkIIUsbEthProtocolGuid, >> +                  (VOID **)&UsbEth, >> +                  This->DriverBindingHandle, >> +                  NicDevice->DeviceHandle, >> +                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER >> +                  ); >> + >> +  return Status; >> +} >> + >> +/** >> +  Network Common Driver Binding Stop. >> + >> +  @param[in]  This                  Protocol instance pointer. >> +  @param[in]  ControllerHandle      Handle of device to stop driver on >> +  @param[in]  NumberOfChildren      Number of Handles in >> ChildHandleBuffer. If number of >> +                                    children is zero stop the entire >> bus driver. >> +  @param[in]  ChildHandleBuffer     List of Child Handles to Stop. >> + >> +  @retval EFI_SUCCESS               This driver is removed >> ControllerHandle >> +  @retval other                     This driver was not removed from >> this device >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +NetworkCommonDriverStop ( >> +  IN  EFI_DRIVER_BINDING_PROTOCOL  *This, >> +  IN  EFI_HANDLE                   ControllerHandle, >> +  IN  UINTN                        NumberOfChildren, >> +  IN  EFI_HANDLE                   *ChildHandleBuffer >> +  ) >> +{ >> +  EFI_STATUS                                 Status; >> +  BOOLEAN AllChildrenStopped; >> +  UINTN                                      Index; >> +  EDKII_USB_ETHERNET_PROTOCOL                *UsbEth; >> +  NIC_DEVICE                                 *NicDevice; >> +  EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL  *NiiProtocol; >> + >> +  if (NumberOfChildren == 0) { >> +    Status = gBS->OpenProtocol ( >> +                    ControllerHandle, >> + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, >> +                    (VOID **)&NiiProtocol, >> +                    This->DriverBindingHandle, >> +                    ControllerHandle, >> +                    EFI_OPEN_PROTOCOL_GET_PROTOCOL >> +                    ); >> + >> +    if (EFI_ERROR (Status)) { >> +      gBS->CloseProtocol ( >> +             ControllerHandle, >> +             &gEfiDevicePathProtocolGuid, >> +             This->DriverBindingHandle, >> +             ControllerHandle >> +             ); >> +      gBS->CloseProtocol ( >> +             ControllerHandle, >> +             &gEdkIIUsbEthProtocolGuid, >> +             This->DriverBindingHandle, >> +             ControllerHandle >> +             ); >> +      return EFI_SUCCESS; >> +    } >> + >> +    NicDevice = UNDI_DEV_FROM_THIS (NiiProtocol); >> +    Status    = gBS->UninstallMultipleProtocolInterfaces ( >> +                       ControllerHandle, >> + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, >> +                       &NicDevice->NiiProtocol, >> +                       &gEfiDevicePathProtocolGuid, >> +                       NicDevice->DevPath, >> +                       NULL >> +                       ); >> +    if (EFI_ERROR (Status)) { >> +      return Status; >> +    } >> + >> +    FreePool (NicDevice->DevPath); >> +    FreePool (NicDevice); >> + >> +    gBS->CloseProtocol ( >> +           ControllerHandle, >> +           &gEfiDevicePathProtocolGuid, >> +           This->DriverBindingHandle, >> +           ControllerHandle >> +           ); >> +    gBS->CloseProtocol ( >> +           ControllerHandle, >> +           &gEdkIIUsbEthProtocolGuid, >> +           This->DriverBindingHandle, >> +           ControllerHandle >> +           ); >> +    return EFI_SUCCESS; >> +  } >> + >> +  AllChildrenStopped = TRUE; >> + >> +  for (Index = 0; Index < NumberOfChildren; Index++) { >> +    Status = gBS->OpenProtocol ( >> +                    ChildHandleBuffer[Index], >> + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, >> +                    (VOID **)&NiiProtocol, >> +                    This->DriverBindingHandle, >> +                    ControllerHandle, >> +                    EFI_OPEN_PROTOCOL_GET_PROTOCOL >> +                    ); >> +    if (EFI_ERROR (Status)) { >> +      AllChildrenStopped = FALSE; >> +      continue; >> +    } >> + >> +    NicDevice = UNDI_DEV_FROM_THIS (NiiProtocol); >> + >> +    gBS->CloseProtocol ( >> +           ControllerHandle, >> +           &gEdkIIUsbEthProtocolGuid, >> +           This->DriverBindingHandle, >> +           ChildHandleBuffer[Index] >> +           ); >> + >> +    Status = gBS->UninstallMultipleProtocolInterfaces ( >> +                    ChildHandleBuffer[Index], >> + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, >> +                    &NicDevice->NiiProtocol, >> +                    &gEfiDevicePathProtocolGuid, >> +                    NicDevice->DevPath, >> +                    NULL >> +                    ); >> +    if (EFI_ERROR (Status)) { >> +      Status = gBS->OpenProtocol ( >> +                      ControllerHandle, >> +                      &gEdkIIUsbEthProtocolGuid, >> +                      (VOID **)&UsbEth, >> +                      This->DriverBindingHandle, >> +                      ChildHandleBuffer[Index], >> +                      EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER >> +                      ); >> +    } else { >> +      FreePool (NicDevice->DevPath); >> +      FreePool (NicDevice); >> +    } >> +  } >> + >> +  if (!AllChildrenStopped) { >> +    return EFI_DEVICE_ERROR; >> +  } >> + >> +  return Status; >> +} >> + >> +/** >> +  Entrypoint of Network Common Driver. >> + >> +  This function is the entrypoint of Network Common Driver. It >> installs Driver Binding >> +  Protocols together with Component Name Protocols. >> + >> +  @param[in]  ImageHandle       The firmware allocated handle for >> the EFI image. >> +  @param[in]  SystemTable       A pointer to the EFI System Table. >> + >> +  @retval EFI_SUCCESS           The entry point is executed >> successfully. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +NetworkCommonEntry ( >> +  IN EFI_HANDLE        ImageHandle, >> +  IN EFI_SYSTEM_TABLE  *SystemTable >> +  ) >> +{ >> +  EFI_STATUS  Status; >> + >> +  gNetworkCommonDriverBinding.DriverBindingHandle = ImageHandle; >> +  gNetworkCommonDriverBinding.ImageHandle         = ImageHandle; >> +  gRateLimitingEnable                             = PcdGetBool >> (EnableRateLimiting); >> +  gRateLimitingCredit                             = PcdGet32 >> (RateLimitingCredit); >> +  gRateLimitingPollTimer                          = PcdGet32 >> (RateLimitingFactor); >> + >> +  Status = gBS->InstallMultipleProtocolInterfaces ( >> + &gNetworkCommonDriverBinding.DriverBindingHandle, >> +                  &gEfiDriverBindingProtocolGuid, >> +                  &gNetworkCommonDriverBinding, >> +                  &gEfiComponentName2ProtocolGuid, >> +                  &gNetworkCommonComponentName2, >> +                  NULL >> +                  ); >> +  return Status; >> +} >> diff --git a/UsbNetworkPkg/NetworkCommon/PxeFunction.c >> b/UsbNetworkPkg/NetworkCommon/PxeFunction.c >> new file mode 100644 >> index 000000000000..687cabca4ce3 >> --- /dev/null >> +++ b/UsbNetworkPkg/NetworkCommon/PxeFunction.c >> @@ -0,0 +1,1803 @@ >> +/** @file >> +  This file contains code for UNDI command based on UEFI specification. >> + >> +  Copyright (c) 2023, American Megatrends International LLC. All >> rights reserved.
>> +  SPDX-License-Identifier: BSD-2-Clause-Patent >> +**/ >> + >> +#include "DriverBinding.h" >> + >> +// API table, defined in UEFI specification >> +API_FUNC  gUndiApiTable[] = { >> +  UndiGetState, >> +  UndiStart, >> +  UndiStop, >> +  UndiGetInitInfo, >> +  UndiGetConfigInfo, >> +  UndiInitialize, >> +  UndiReset, >> +  UndiShutdown, >> +  UndiInterruptEnable, >> +  UndiReceiveFilter, >> +  UndiStationAddress, >> +  UndiStatistics, >> +  UndiMcastIp2Mac, >> +  UndiNvData, >> +  UndiGetStatus, >> +  UndiFillHeader, >> +  UndiTransmit, >> +  UndiReceive >> +}; >> + >> +/** >> +   Callback function for enable Rate Limiter >> + >> +   @param[in] Event           Event whose notification function is >> being invoked >> +   @param[in] Context         Pointer to the notification function's >> context >> + >> +**/ >> +VOID >> +EFIAPI >> +UndiRateLimiterCallback ( >> +  IN  EFI_EVENT  Event, >> +  IN  VOID       *Context >> +  ) >> +{ >> +  NIC_DATA  *Nic = Context; >> + >> +  if (Nic->RateLimitingCreditCount < Nic->RateLimitingCredit) { >> +    Nic->RateLimitingCreditCount++; >> +  } >> +} >> + >> +/** >> +  This command is used to determine the operational state of the UNDI. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiGetState ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ) >> +{ >> +  EFI_STATUS  Status; >> + >> +  if ((Cdb->OpCode != PXE_OPCODE_GET_STATE) || >> +      (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> +      (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> +      (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> +      (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) || >> +      (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED) || >> +      (Cdb->DBsize != PXE_DBSIZE_NOT_USED) || >> +      (Cdb->DBaddr != PXE_DBADDR_NOT_USED) || >> +      (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED)) >> +  { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_INVALID_CDB; >> +    return; >> +  } else { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> +    Cdb->StatCode  = PXE_STATCODE_SUCCESS; >> +  } >> + >> +  Cdb->StatFlags = Cdb->StatFlags | Nic->State; >> + >> +  if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetState != NULL) { >> +    Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiGetState (Cdb, Nic); >> +    if (EFI_ERROR (Status)) { >> +      Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    } >> +  } >> +} >> + >> +/** >> +  This command is used to change the UNDI operational state from >> stopped to started. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiStart ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ) >> +{ >> +  PXE_CPB_START_31  *Cpb; >> +  EFI_STATUS        Status; >> +  BOOLEAN           EventError; >> + >> +  if ((Cdb->OpCode != PXE_OPCODE_START) || >> +      (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> +      (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> +      (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> +      (Cdb->CPBsize != sizeof (PXE_CPB_START_31)) || >> +      (Cdb->DBsize != PXE_DBSIZE_NOT_USED) || >> +      (Cdb->DBaddr != PXE_DBADDR_NOT_USED) || >> +      (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED)) >> +  { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_INVALID_CDB; >> +    return; >> +  } >> + >> +  if (Nic->State != PXE_STATFLAGS_GET_STATE_STOPPED) { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_ALREADY_STARTED; >> +    return; >> +  } >> + >> +  Cpb = (PXE_CPB_START_31 *)(UINTN)Cdb->CPBaddr; >> + >> +  Nic->PxeStart.Delay     = Cpb->Delay; >> +  Nic->PxeStart.Virt2Phys = Cpb->Virt2Phys; >> +  Nic->PxeStart.Block     = Cpb->Block; >> +  Nic->PxeStart.Map_Mem   = 0; >> +  Nic->PxeStart.UnMap_Mem = 0; >> +  Nic->PxeStart.Sync_Mem  = Cpb->Sync_Mem; >> +  Nic->PxeStart.Unique_ID = Cpb->Unique_ID; >> +  EventError              = FALSE; >> +  Status                  = EFI_SUCCESS; >> +  if (Nic->RateLimitingEnable == TRUE) { >> +    Status = gBS->CreateEvent ( >> +                    EVT_TIMER | EVT_NOTIFY_SIGNAL, >> +                    TPL_NOTIFY, >> +                    UndiRateLimiterCallback, >> +                    Nic, >> +                    &Nic->RateLimiter >> +                    ); >> +    if (!EFI_ERROR (Status)) { >> +      Status = gBS->SetTimer ( >> +                      Nic->RateLimiter, >> +                      TimerPeriodic, >> +                      Nic->RateLimitingPollTimer * 10000 >> +                      ); >> +      if (EFI_ERROR (Status)) { >> +        EventError = TRUE; >> +      } >> +    } >> +  } >> + >> +  if ((Nic->UsbEth->UsbEthUndi.UsbEthUndiStart != NULL) && >> (EventError == FALSE)) { >> +    Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiStart (Cdb, Nic); >> +  } >> + >> +  if (!EFI_ERROR (Status)) { >> +    // Initial the state for UNDI start. >> +    Nic->State     = PXE_STATFLAGS_GET_STATE_STARTED; >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> +    Cdb->StatCode  = PXE_STATCODE_SUCCESS; >> +  } else { >> +    if (Nic->RateLimitingEnable == TRUE) { >> +      if (!EventError) { >> +        gBS->SetTimer (&Nic->RateLimiter, TimerCancel, 0); >> +      } >> + >> +      if (Nic->RateLimiter) { >> +        gBS->CloseEvent (&Nic->RateLimiter); >> +        Nic->RateLimiter = 0; >> +      } >> +    } >> + >> +    // Initial the state when UNDI start is fail >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_DEVICE_FAILURE; >> +  } >> +} >> + >> +/** >> +  This command is used to change the UNDI operational state from >> started to stopped. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiStop ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ) >> +{ >> +  EFI_STATUS  Status; >> + >> +  if ((Cdb->OpCode != PXE_OPCODE_STOP) || >> +      (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> +      (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> +      (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> +      (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) || >> +      (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED) || >> +      (Cdb->DBsize != PXE_DBSIZE_NOT_USED) || >> +      (Cdb->DBaddr != PXE_DBADDR_NOT_USED) || >> +      (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED)) >> +  { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_INVALID_CDB; >> +    return; >> +  } else { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> +    Cdb->StatCode  = PXE_STATCODE_SUCCESS; >> +  } >> + >> +  if (Nic->State == PXE_STATFLAGS_GET_STATE_STOPPED) { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_NOT_STARTED; >> +    return; >> +  } >> + >> +  if (Nic->State == PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_NOT_SHUTDOWN; >> +    return; >> +  } >> + >> +  Nic->PxeStart.Delay     = 0; >> +  Nic->PxeStart.Virt2Phys = 0; >> +  Nic->PxeStart.Block     = 0; >> +  Nic->PxeStart.Map_Mem   = 0; >> +  Nic->PxeStart.UnMap_Mem = 0; >> +  Nic->PxeStart.Sync_Mem  = 0; >> +  Nic->State              = PXE_STATFLAGS_GET_STATE_STOPPED; >> + >> +  if (Nic->RateLimitingEnable == TRUE) { >> +    gBS->SetTimer (&Nic->RateLimiter, TimerCancel, 0); >> +    gBS->CloseEvent (&Nic->RateLimiter); >> +  } >> + >> +  if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStop != NULL) { >> +    Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiStop (Cdb, Nic); >> +    if (EFI_ERROR (Status)) { >> +      Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    } >> +  } >> +} >> + >> +/** >> +  This command is used to retrieve initialization information that is >> +  needed by drivers and applications to initialized UNDI. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiGetInitInfo ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ) >> +{ >> +  PXE_DB_GET_INIT_INFO  *Db; >> +  EFI_STATUS            Status; >> + >> +  if ((Cdb->OpCode != PXE_OPCODE_GET_INIT_INFO) || >> +      (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> +      (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> +      (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> +      (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) || >> +      (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED) || >> +      (Cdb->DBsize != sizeof (PXE_DB_GET_INIT_INFO)) || >> +      (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED)) >> +  { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_INVALID_CDB; >> +    return; >> +  } else { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> +    Cdb->StatCode  = PXE_STATCODE_SUCCESS; >> +  } >> + >> +  if (Nic->State == PXE_STATFLAGS_GET_STATE_STOPPED) { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_NOT_STARTED; >> +    return; >> +  } >> + >> +  Db = (PXE_DB_GET_INIT_INFO *)(UINTN)Cdb->DBaddr; >> + >> +  Db->MemoryRequired         = MEMORY_REQUIRE; >> +  Db->FrameDataLen           = PXE_MAX_TXRX_UNIT_ETHER; >> +  Db->LinkSpeeds[0]          = 10; >> +  Db->LinkSpeeds[1]          = 100; >> +  Db->LinkSpeeds[2]          = 1000; >> +  Db->LinkSpeeds[3]          = 0; >> +  Db->MediaHeaderLen         = PXE_MAC_HEADER_LEN_ETHER; >> +  Db->HWaddrLen              = PXE_HWADDR_LEN_ETHER; >> +  Db->MCastFilterCnt         = MAX_MCAST_ADDRESS_CNT; >> +  Db->TxBufCnt               = Nic->PxeInit.TxBufCnt; >> +  Db->TxBufSize              = Nic->PxeInit.TxBufSize; >> +  Db->RxBufCnt               = Nic->PxeInit.RxBufCnt; >> +  Db->RxBufSize              = Nic->PxeInit.RxBufSize; >> +  Db->IFtype                 = PXE_IFTYPE_ETHERNET; >> +  Db->SupportedDuplexModes   = PXE_DUPLEX_DEFAULT; >> +  Db->SupportedLoopBackModes = LOOPBACK_NORMAL; >> + >> +  Cdb->StatFlags |= (PXE_STATFLAGS_CABLE_DETECT_SUPPORTED | >> + PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED); >> + >> +  if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetInitInfo != NULL) { >> +    Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiGetInitInfo (Cdb, Nic); >> +    if (EFI_ERROR (Status)) { >> +      Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    } >> +  } >> +} >> + >> +/** >> +  This command is used to retrieve configuration information about >> +  the NIC being controlled by the UNDI. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiGetConfigInfo ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ) >> +{ >> +  PXE_DB_GET_CONFIG_INFO  *Db; >> +  EFI_STATUS              Status; >> + >> +  if ((Cdb->OpCode != PXE_OPCODE_GET_CONFIG_INFO) || >> +      (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> +      (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> +      (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> +      (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) || >> +      (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED) || >> +      (Cdb->DBsize != sizeof (PXE_DB_GET_CONFIG_INFO)) || >> +      (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED)) >> +  { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_INVALID_CDB; >> +    return; >> +  } else { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> +    Cdb->StatCode  = PXE_STATCODE_SUCCESS; >> +  } >> + >> +  if (Nic->State == PXE_STATFLAGS_GET_STATE_STOPPED) { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_NOT_STARTED; >> +    return; >> +  } >> + >> +  Db = (PXE_DB_GET_CONFIG_INFO *)(UINTN)Cdb->DBaddr; >> + >> +  Db->pci.BusType = PXE_BUSTYPE_USB; >> + >> +  if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetConfigInfo != NULL) { >> +    Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiGetConfigInfo (Cdb, >> Nic); >> +    if (EFI_ERROR (Status)) { >> +      Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    } >> +  } >> +} >> + >> +/** >> +  This command resets the network adapter and initializes UNDI using >> +  the parameters supplied in the CPB. >> + >> +  @param[in]      Cdb  A pointer to the command descriptor block. >> +  @param[in, out] Nic  A pointer to the Network interface controller >> data. >> + >> +**/ >> +VOID >> +UndiInitialize ( >> +  IN      PXE_CDB   *Cdb, >> +  IN OUT  NIC_DATA  *Nic >> +  ) >> +{ >> +  PXE_CPB_INITIALIZE  *Cpb; >> +  PXE_DB_INITIALIZE   *Db; >> +  EFI_STATUS          Status; >> + >> +  if ((Cdb->OpCode != PXE_OPCODE_INITIALIZE) || >> +      (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> +      (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> +      (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> +      (Cdb->CPBsize != sizeof (PXE_CPB_INITIALIZE))) >> +  { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_INVALID_CDB; >> +    return; >> +  } else { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> +  } >> + >> +  if (Nic->State == PXE_STATFLAGS_GET_STATE_STOPPED) { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_NOT_STARTED; >> +    return; >> +  } >> + >> +  if ((Cdb->OpFlags != PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) && >> +      (Cdb->OpFlags != PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE)) >> +  { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_INVALID_CDB; >> +    return; >> +  } >> + >> +  if (Nic->State == PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_ALREADY_INITIALIZED; >> +    return; >> +  } >> + >> +  Cpb = (PXE_CPB_INITIALIZE *)(UINTN)Cdb->CPBaddr; >> +  Db  = (PXE_DB_INITIALIZE *)(UINTN)Cdb->DBaddr; >> + >> +  Nic->PxeInit.LinkSpeed    = Cpb->LinkSpeed; >> +  Nic->PxeInit.DuplexMode   = Cpb->DuplexMode; >> +  Nic->PxeInit.LoopBackMode = Cpb->LoopBackMode; >> +  Nic->PxeInit.MemoryAddr   = Cpb->MemoryAddr; >> +  Nic->PxeInit.MemoryLength = Cpb->MemoryLength; >> +  Nic->PxeInit.TxBufCnt     = TX_BUFFER_COUNT; >> +  Nic->PxeInit.TxBufSize    = Nic->MaxSegmentSize; >> +  Nic->PxeInit.RxBufCnt     = RX_BUFFER_COUNT; >> +  Nic->PxeInit.RxBufSize    = Nic->MaxSegmentSize; >> + >> +  Cdb->StatCode = Initialize (Cdb, Nic); >> + >> +  Db->MemoryUsed = MEMORY_REQUIRE; >> +  Db->TxBufCnt   = Nic->PxeInit.TxBufCnt; >> +  Db->TxBufSize  = Nic->PxeInit.TxBufSize; >> +  Db->RxBufCnt   = Nic->PxeInit.RxBufCnt; >> +  Db->RxBufSize  = Nic->PxeInit.RxBufSize; >> + >> +  Nic->RxFilter    = PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST; >> +  Nic->CanTransmit = FALSE; >> + >> +  if (Cdb->OpFlags == PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) { >> +    if ((Nic->Request.Request == USB_CDC_NETWORK_CONNECTION) && >> (Nic->Request.Value == NETWORK_DISCONNECT)) { >> +      Nic->CableDetect = 0; >> +    } else if ((Nic->Request.Request == USB_CDC_NETWORK_CONNECTION) >> && (Nic->Request.Value == NETWORK_CONNECTED)) { >> +      Nic->CableDetect = 1; >> +    } >> + >> +    if (Nic->CableDetect == 0) { >> +      Cdb->StatFlags |= PXE_STATFLAGS_INITIALIZED_NO_MEDIA; >> +    } >> +  } >> + >> +  if (Cdb->StatCode != PXE_STATCODE_SUCCESS) { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +  } else { >> +    Nic->State = PXE_STATFLAGS_GET_STATE_INITIALIZED; >> +  } >> + >> +  if (Nic->UsbEth->UsbEthUndi.UsbEthUndiInitialize != NULL) { >> +    Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiInitialize (Cdb, Nic); >> +    if (EFI_ERROR (Status)) { >> +      Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    } >> +  } >> +} >> + >> +/** >> +  Initialize Network interface controller data. >> + >> +  @param[in]      Cdb     A pointer to the command descriptor block. >> +  @param[in, out] Nic     A pointer to the Network interface >> controller data. >> + >> +  @retval Status  A value of Pxe statcode. >> + >> +**/ >> +UINT16 >> +Initialize ( >> +  IN      PXE_CDB   *Cdb, >> +  IN OUT  NIC_DATA  *Nic >> +  ) >> +{ >> +  UINTN       Status; >> +  UINT32      Index; >> +  EFI_STATUS  EfiStatus; >> + >> +  Status = MapIt ( >> +             Nic, >> +             Nic->PxeInit.MemoryAddr, >> +             Nic->PxeInit.MemoryLength, >> +             TO_AND_FROM_DEVICE, >> +             (UINT64)(UINTN)&Nic->MappedAddr >> +             ); >> + >> +  if (Status != 0) { >> +    return (UINT16)Status; >> +  } >> + >> +  for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> +    Nic->PermNodeAddress[Index] = Nic->MacAddr.Addr[Index]; >> +  } >> + >> +  for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> +    Nic->CurrentNodeAddress[Index] = Nic->PermNodeAddress[Index]; >> +  } >> + >> +  for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> +    Nic->BroadcastNodeAddress[Index] = 0xFF; >> +  } >> + >> +  for (Index = PXE_HWADDR_LEN_ETHER; Index < PXE_MAC_LENGTH; Index++) { >> +    Nic->CurrentNodeAddress[Index]   = 0; >> +    Nic->PermNodeAddress[Index]      = 0; >> +    Nic->BroadcastNodeAddress[Index] = 0; >> +  } >> + >> +  if (Nic->UsbEth->UsbEthInitialize != NULL) { >> +    EfiStatus = Nic->UsbEth->UsbEthInitialize (Cdb, Nic); >> +    if (EFI_ERROR (EfiStatus)) { >> +      return PXE_STATFLAGS_COMMAND_FAILED; >> +    } >> +  } >> + >> +  return (UINT16)Status; >> +} >> + >> +/** >> +  This command resets the network adapter and reinitializes the UNDI >> +  with the same parameters provided in the Initialize command. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiReset ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ) >> +{ >> +  EFI_STATUS  Status; >> + >> +  if ((Cdb->OpCode != PXE_OPCODE_RESET) || >> +      (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> +      (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> +      (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> +      (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) || >> +      (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED) || >> +      (Cdb->DBsize != PXE_DBSIZE_NOT_USED) || >> +      (Cdb->DBaddr != PXE_DBADDR_NOT_USED)) >> +  { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_INVALID_CDB; >> +    return; >> +  } else { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> +    Cdb->StatCode  = PXE_STATCODE_SUCCESS; >> +  } >> + >> +  if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> +    Cdb->StatCode  = PXE_STATCODE_NOT_INITIALIZED; >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    return; >> +  } >> + >> +  if ((Cdb->OpFlags != PXE_OPFLAGS_NOT_USED) && >> +      (Cdb->OpFlags != PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS) && >> +      (Cdb->OpFlags != PXE_OPFLAGS_RESET_DISABLE_FILTERS)) >> +  { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_INVALID_CDB; >> +    return; >> +  } >> + >> +  if ((Cdb->OpFlags & PXE_OPFLAGS_RESET_DISABLE_FILTERS) == 0) { >> +    Nic->RxFilter = PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST; >> +  } >> + >> +  if ((Cdb->OpFlags & PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS) != 0) { >> +    Nic->InterrupOpFlag = 0; >> +  } >> + >> +  if (Nic->UsbEth->UsbEthUndi.UsbEthUndiReset != NULL) { >> +    Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiReset (Cdb, Nic); >> +    if (EFI_ERROR (Status)) { >> +      Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    } >> +  } >> +} >> + >> +/** >> +  The Shutdown command resets the network adapter and leaves it in a >> +  safe state for another driver to initialize. >> + >> +  @param[in]      Cdb  A pointer to the command descriptor block. >> +  @param[in, out] Nic  A pointer to the Network interface controller >> data. >> + >> +**/ >> +VOID >> +UndiShutdown ( >> +  IN      PXE_CDB   *Cdb, >> +  IN OUT  NIC_DATA  *Nic >> +  ) >> +{ >> +  EFI_STATUS  Status; >> + >> +  if ((Cdb->OpCode != PXE_OPCODE_SHUTDOWN) || >> +      (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> +      (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> +      (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> +      (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) || >> +      (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED) || >> +      (Cdb->DBsize != PXE_DBSIZE_NOT_USED) || >> +      (Cdb->DBaddr != PXE_DBADDR_NOT_USED) || >> +      (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED)) >> +  { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_INVALID_CDB; >> +    return; >> +  } else { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> +    Cdb->StatCode  = PXE_STATCODE_SUCCESS; >> +  } >> + >> +  if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> +    Cdb->StatCode  = PXE_STATCODE_NOT_INITIALIZED; >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    return; >> +  } >> + >> +  Nic->CanTransmit = FALSE; >> + >> +  Nic->State = PXE_STATFLAGS_GET_STATE_STARTED; >> + >> +  if (Nic->UsbEth->UsbEthUndi.UsbEthUndiShutdown != NULL) { >> +    Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiShutdown (Cdb, Nic); >> +    if (EFI_ERROR (Status)) { >> +      Cdb->StatCode  = PXE_STATCODE_NOT_INITIALIZED; >> +      Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    } >> +  } >> +} >> + >> +/** >> +  The Interrupt Enables command can be used to read and/or change >> +  the current external interrupt enable settings. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiInterruptEnable ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ) >> +{ >> +  EFI_STATUS  Status; >> + >> +  Cdb->StatCode = PXE_STATCODE_UNSUPPORTED; >> +  if (Nic->UsbEth->UsbEthUndi.UsbEthUndiInterruptEnable != NULL) { >> +    Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiInterruptEnable (Cdb, >> Nic); >> +    if (EFI_ERROR (Status)) { >> +      Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    } else { >> +      Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> +      Cdb->StatCode  = PXE_STATCODE_SUCCESS; >> +    } >> +  } >> +} >> + >> +/** >> +  This command is used to read and change receive filters and, >> +  if supported, read and change the multicast MAC address filter list. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiReceiveFilter ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ) >> +{ >> +  UINT16                  NewFilter; >> +  PXE_DB_RECEIVE_FILTERS  *Db; >> +  EFI_STATUS              Status; >> + >> +  if ((Cdb->OpCode != PXE_OPCODE_RECEIVE_FILTERS) || >> +      (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> +      (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> +      (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8))) >> +  { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_INVALID_CDB; >> +    return; >> +  } else { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> +    Cdb->StatCode  = PXE_STATCODE_SUCCESS; >> +  } >> + >> +  if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> +    Cdb->StatCode  = PXE_STATCODE_NOT_INITIALIZED; >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    return; >> +  } >> + >> +  NewFilter = (UINT16)(Cdb->OpFlags & 0x1F); >> + >> +  switch (Cdb->OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_OPMASK) { >> +    case PXE_OPFLAGS_RECEIVE_FILTER_READ: >> +      if (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) { >> +        Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +        Cdb->StatCode  = PXE_STATCODE_INVALID_CDB; >> +      } >> + >> +      if ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) >> == 0) { >> +        if ((Cdb->DBsize != 0)) { >> +          Db = (PXE_DB_RECEIVE_FILTERS *)(UINTN)Cdb->DBaddr; >> +          CopyMem (Db, &Nic->McastList, Nic->McastCount); >> +        } >> +      } >> + >> +      break; >> + >> +    case PXE_OPFLAGS_RECEIVE_FILTER_ENABLE: >> +      if (NewFilter == 0) { >> +        Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +      } >> + >> +      if (Cdb->CPBsize != 0) { >> +        if (((NewFilter & >> PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) == 0) || >> +            ((NewFilter & >> PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) != 0) || >> +            ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) >> != 0) || >> +            ((Cdb->CPBsize % sizeof (PXE_MAC_ADDR)) != 0)) >> +        { >> +          Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +        } >> +      } >> + >> +      if ((Cdb->OpFlags & >> PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) != 0) { >> +        if (((Cdb->OpFlags & >> PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) != 0) || >> +            ((Cdb->OpFlags & >> PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) != 0)) >> +        { >> +          Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +        } >> + >> +        if ((Cdb->CPBsize == 0)) { >> +          Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +        } >> +      } >> + >> +      Cdb->StatCode = SetFilter (Nic, NewFilter, Cdb->CPBaddr, >> Cdb->CPBsize); >> +      break; >> + >> +    case PXE_OPFLAGS_RECEIVE_FILTER_DISABLE: >> +      if (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) { >> +        Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +        Cdb->StatCode  = PXE_STATCODE_INVALID_CDB; >> +      } >> + >> +      break; >> + >> +    default: >> +      Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +      Cdb->StatCode  = PXE_STATCODE_INVALID_CDB; >> +  } >> + >> +  Cdb->StatFlags = (PXE_STATFLAGS)(Cdb->StatFlags | Nic->RxFilter); >> + >> +  if (Nic->UsbEth->UsbEthUndi.UsbEthUndiReceiveFilter != NULL) { >> +    Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiReceiveFilter (Cdb, >> Nic); >> +    if (EFI_ERROR (Status)) { >> +      Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    } >> +  } >> +} >> + >> +/** >> +  Set PXE receive filter. >> + >> +  @param[in]  Nic         A pointer to the Network interface >> controller data. >> +  @param[in]  SetFilter   PXE receive filter >> +  @param[in]  CpbAddr     Command Parameter Block Address >> +  @param[in]  CpbSize     Command Parameter Block Size >> + >> +**/ >> +UINT16 >> +SetFilter ( >> +  IN  NIC_DATA  *Nic, >> +  IN  UINT16    SetFilter, >> +  IN  UINT64    CpbAddr, >> +  IN  UINT32    CpbSize >> +  ) >> +{ >> +  EFI_STATUS                   Status; >> +  UINT8                        *McastList; >> +  UINT8                        Count; >> +  UINT8                        Index1; >> +  UINT8                        Index2; >> +  PXE_CPB_RECEIVE_FILTERS      *Cpb; >> +  USB_ETHERNET_FUN_DESCRIPTOR  UsbEthFunDescriptor; >> + >> +  Count = 0; >> +  Cpb   = (PXE_CPB_RECEIVE_FILTERS *)(UINTN)CpbAddr; >> + >> +  // The Cpb could be NULL.(ref:PXE_CPBADDR_NOT_USED) >> +  Nic->RxFilter = (UINT8)SetFilter; >> + >> +  if (((SetFilter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) >> != 0) || (Cpb != NULL)) { >> +    if (Cpb != NULL) { >> +      Nic->McastCount = (UINT8)(CpbSize / PXE_MAC_LENGTH); >> +      CopyMem (&Nic->McastList, Cpb, Nic->McastCount); >> +    } >> + >> +    Nic->UsbEth->UsbEthFunDescriptor (Nic->UsbEth, >> &UsbEthFunDescriptor); >> +    if ((UsbEthFunDescriptor.NumberMcFilters << 1) == 0) { >> +      Nic->RxFilter |= PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST; >> +      Nic->UsbEth->SetUsbEthPacketFilter (Nic->UsbEth, Nic->RxFilter); >> +    } else { >> +      Status = gBS->AllocatePool (EfiBootServicesData, >> Nic->McastCount * 6, (VOID **)&McastList); >> +      if (EFI_ERROR (Status)) { >> +        return PXE_STATCODE_INVALID_PARAMETER; >> +      } >> + >> +      if (Cpb != NULL) { >> +        for (Index1 = 0; Index1 < Nic->McastCount; Index1++) { >> +          for (Index2 = 0; Index2 < 6; Index2++) { >> +            McastList[Count++] = Cpb->MCastList[Index1][Index2]; >> +          } >> +        } >> +      } >> + >> +      Nic->RxFilter |= PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST; >> +      if (Cpb != NULL) { >> +        Nic->UsbEth->SetUsbEthMcastFilter (Nic->UsbEth, >> Nic->McastCount, McastList); >> +      } >> + >> +      Nic->UsbEth->SetUsbEthPacketFilter (Nic->UsbEth, Nic->RxFilter); >> +      FreePool (McastList); >> +    } >> +  } >> + >> +  return PXE_STATCODE_SUCCESS; >> +} >> + >> +/** >> +  This command is used to get current station and broadcast MAC >> addresses >> +  and, if supported, to change the current station MAC address. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiStationAddress ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ) >> +{ >> +  PXE_CPB_STATION_ADDRESS  *Cpb; >> +  PXE_DB_STATION_ADDRESS   *Db; >> +  UINT16                   Index; >> +  EFI_STATUS               Status; >> + >> +  if ((Cdb->OpCode != PXE_OPCODE_STATION_ADDRESS) || >> +      (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> +      (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> +      (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> +      (Cdb->DBsize != sizeof (PXE_DB_STATION_ADDRESS))) >> +  { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_INVALID_CDB; >> +    return; >> +  } else { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> +    Cdb->StatCode  = PXE_STATCODE_SUCCESS; >> +  } >> + >> +  if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> +    Cdb->StatCode  = PXE_STATCODE_NOT_INITIALIZED; >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    return; >> +  } >> + >> +  if (Cdb->OpFlags == PXE_OPFLAGS_STATION_ADDRESS_RESET) { >> +    if (CompareMem (&Nic->CurrentNodeAddress[0], >> &Nic->PermNodeAddress[0], PXE_MAC_LENGTH) != 0) { >> +      for (Index = 0; Index < PXE_MAC_LENGTH; Index++) { >> +        Nic->CurrentNodeAddress[Index] = Nic->PermNodeAddress[Index]; >> +      } >> +    } >> +  } >> + >> +  if (Cdb->CPBaddr != 0) { >> +    Cpb = (PXE_CPB_STATION_ADDRESS *)(UINTN)Cdb->CPBaddr; >> +    for (Index = 0; Index < PXE_MAC_LENGTH; Index++) { >> +      Nic->CurrentNodeAddress[Index] = Cpb->StationAddr[Index]; >> +    } >> +  } >> + >> +  if (Cdb->DBaddr != 0) { >> +    Db = (PXE_DB_STATION_ADDRESS *)(UINTN)Cdb->DBaddr; >> +    for (Index = 0; Index < PXE_MAC_LENGTH; Index++) { >> +      Db->StationAddr[Index]   = Nic->CurrentNodeAddress[Index]; >> +      Db->BroadcastAddr[Index] = Nic->BroadcastNodeAddress[Index]; >> +      Db->PermanentAddr[Index] = Nic->PermNodeAddress[Index]; >> +    } >> +  } >> + >> +  if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStationAddress != NULL) { >> +    Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiStationAddress (Cdb, >> Nic); >> +    if (EFI_ERROR (Status)) { >> +      Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    } >> +  } >> +} >> + >> +/** >> +  This command is used to read and clear the NIC traffic statistics. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiStatistics ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ) >> +{ >> +  EFI_STATUS  Status; >> + >> +  if ((Cdb->OpCode != PXE_OPCODE_STATISTICS) || >> +      (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> +      (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> +      (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> +      (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) || >> +      (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED)) >> +  { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_INVALID_CDB; >> +    return; >> +  } else { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> +  } >> + >> +  if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> +    Cdb->StatCode  = PXE_STATCODE_NOT_INITIALIZED; >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    return; >> +  } >> + >> +  if ((Cdb->OpFlags != PXE_OPFLAGS_STATISTICS_RESET) && >> +      (Cdb->OpFlags != PXE_OPFLAGS_STATISTICS_READ)) >> +  { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_INVALID_CDB; >> +    return; >> +  } >> + >> +  Cdb->StatCode = Statistics (Nic, Cdb->DBaddr, Cdb->DBsize); >> + >> +  if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStatistics != NULL) { >> +    Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiStatistics (Cdb, Nic); >> +    if (EFI_ERROR (Status)) { >> +      Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    } >> +  } >> +} >> + >> +/** >> +  Return data for DB data. >> + >> +  @param[in]  Nic      A pointer to the Network interface controller >> data. >> +  @param[in]  DbAddr   Data Block Address. >> +  @param[in]  DbSize   Data Block Size. >> + >> +**/ >> +UINT16 >> +Statistics ( >> +  IN NIC_DATA  *Nic, >> +  IN UINT64    DbAddr, >> +  IN UINT16    DbSize >> +  ) >> +{ >> +  PXE_DB_STATISTICS  *DbStatistic; >> +  EFI_STATUS         Status; >> + >> +  DbStatistic = (PXE_DB_STATISTICS *)(UINTN)DbAddr; >> + >> +  if (DbSize == 0) { >> +    return PXE_STATCODE_SUCCESS; >> +  } >> + >> +  DbStatistic->Supported  = 0x802; >> +  DbStatistic->Data[0x01] = Nic->RxFrame; >> +  DbStatistic->Data[0x0B] = Nic->TxFrame; >> + >> +  if (Nic->UsbEth->UsbEthStatistics != NULL) { >> +    Status = Nic->UsbEth->UsbEthStatistics (Nic, DbAddr, DbSize); >> +    if (EFI_ERROR (Status)) { >> +      return PXE_STATFLAGS_COMMAND_FAILED; >> +    } >> +  } >> + >> +  return PXE_STATCODE_SUCCESS; >> +} >> + >> +/** >> +  Translate a multicast IPv4 or IPv6 address to a multicast MAC >> address. >> + >> +  @param[in, out] Cdb  A pointer to the command descriptor block. >> +  @param[in]      Nic  A pointer to the Network interface controller >> data. >> + >> +**/ >> +VOID >> +UndiMcastIp2Mac ( >> +  IN OUT  PXE_CDB   *Cdb, >> +  IN      NIC_DATA  *Nic >> +  ) >> +{ >> +  PXE_CPB_MCAST_IP_TO_MAC  *Cpb; >> +  PXE_DB_MCAST_IP_TO_MAC   *Db; >> +  UINT8                    *Tmp; >> +  EFI_STATUS               Status; >> + >> +  if ((Cdb->OpCode != PXE_OPCODE_MCAST_IP_TO_MAC) || >> +      (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> +      (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> +      (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> +      (Cdb->CPBsize != sizeof (PXE_CPB_MCAST_IP_TO_MAC)) || >> +      (Cdb->DBsize != sizeof (PXE_DB_MCAST_IP_TO_MAC))) >> +  { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_INVALID_CDB; >> +    return; >> +  } else { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> +    Cdb->StatCode  = PXE_STATCODE_SUCCESS; >> +  } >> + >> +  if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> +    Cdb->StatCode  = PXE_STATCODE_NOT_INITIALIZED; >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    return; >> +  } >> + >> +  Cpb = (PXE_CPB_MCAST_IP_TO_MAC *)(UINTN)Cdb->CPBaddr; >> +  Db  = (PXE_DB_MCAST_IP_TO_MAC *)(UINTN)Cdb->DBaddr; >> + >> +  if ((Cdb->OpFlags & PXE_OPFLAGS_MCAST_IPV6_TO_MAC) != 0) { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_UNSUPPORTED; >> +    return; >> +  } >> + >> +  Tmp = (UINT8 *)(&Cpb->IP.IPv4); >> + >> +  if ((Tmp[0] & 0xF0) != 0xE0) { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_INVALID_CPB; >> +  } >> + >> +  Db->MAC[0] = 0x01; >> +  Db->MAC[1] = 0x00; >> +  Db->MAC[2] = 0x5E; >> +  Db->MAC[3] = Tmp[1] & 0x7F; >> +  Db->MAC[4] = Tmp[2]; >> +  Db->MAC[5] = Tmp[3]; >> + >> +  if (Nic->UsbEth->UsbEthUndi.UsbEthUndiMcastIp2Mac != NULL) { >> +    Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiMcastIp2Mac (Cdb, Nic); >> +    if (EFI_ERROR (Status)) { >> +      Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    } >> +  } >> +} >> + >> +/** >> +  This command is used to read and write (if supported by NIC H/W) >> +  nonvolatile storage on the NIC. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiNvData ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ) >> +{ >> +  EFI_STATUS  Status; >> + >> +  Cdb->StatCode = PXE_STATCODE_UNSUPPORTED; >> +  if (Nic->UsbEth->UsbEthUndi.UsbEthUndiNvData != NULL) { >> +    Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiNvData (Cdb, Nic); >> +    if (EFI_ERROR (Status)) { >> +      Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    } else { >> +      Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> +      Cdb->StatCode  = PXE_STATCODE_SUCCESS; >> +    } >> +  } >> +} >> + >> +/** >> +  This command returns the current interrupt status and/or the >> +  transmitted buffer addresses and the current media status. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiGetStatus ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ) >> +{ >> +  PXE_DB_GET_STATUS  *Db; >> +  PXE_DB_GET_STATUS  TmpGetStatus; >> +  UINT16             NumEntries; >> +  UINTN              Index; >> +  EFI_STATUS         Status; >> + >> +  if ((Cdb->OpCode != PXE_OPCODE_GET_STATUS) || >> +      (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> +      (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> +      (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> +      (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) || >> +      (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED)) >> +  { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_INVALID_CDB; >> +    return; >> +  } else { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> +    Cdb->StatCode  = PXE_STATCODE_SUCCESS; >> +  } >> + >> +  if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> +    Cdb->StatCode  = PXE_STATCODE_NOT_INITIALIZED; >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    return; >> +  } >> + >> +  TmpGetStatus.RxFrameLen = 0; >> +  TmpGetStatus.reserved   = 0; >> +  Db                      = (PXE_DB_GET_STATUS *)(UINTN)Cdb->DBaddr; >> + >> +  if ((Cdb->DBsize > 0) && (Cdb->DBsize < sizeof (UINT32) * 2)) { >> +    CopyMem (Db, &TmpGetStatus, Cdb->DBsize); >> +  } else { >> +    CopyMem (Db, &TmpGetStatus, sizeof (UINT32) * 2); >> +  } >> + >> +  if ((Cdb->OpFlags & PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS) != 0) { >> +    if (Cdb->DBsize == 0) { >> +      Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +      Cdb->StatCode  = PXE_STATCODE_INVALID_CDB; >> +      return; >> +    } >> + >> +    NumEntries  = Cdb->DBsize - sizeof (UINT64); >> +    Cdb->DBsize = sizeof (UINT32) * 2; >> + >> +    for (Index = 0; NumEntries >= sizeof (UINT64); Index++, >> NumEntries -= sizeof (UINT64)) { >> +      if (Nic->TxBufferCount > 0) { >> +        Nic->TxBufferCount--; >> +        Db->TxBuffer[Index] = Nic->MediaHeader[Nic->TxBufferCount]; >> +      } >> +    } >> +  } >> + >> +  if ((Cdb->OpFlags & PXE_OPFLAGS_GET_INTERRUPT_STATUS) != 0) { >> +    if (Nic->ReceiveStatus != 0) { >> +      Cdb->StatFlags |= PXE_STATFLAGS_GET_STATUS_RECEIVE; >> +    } >> +  } >> + >> +  if ((Nic->Request.Request == USB_CDC_NETWORK_CONNECTION) && >> (Nic->Request.Value == NETWORK_DISCONNECT)) { >> +    Nic->CableDetect = 0; >> +  } else if ((Nic->Request.Request == USB_CDC_NETWORK_CONNECTION) && >> (Nic->Request.Value == NETWORK_CONNECTED)) { >> +    Nic->CableDetect = 1; >> +  } >> + >> +  if ((Cdb->OpFlags & PXE_OPFLAGS_GET_MEDIA_STATUS) != 0) { >> +    if (Nic->CableDetect == 0) { >> +      Cdb->StatFlags |= PXE_STATFLAGS_GET_STATUS_NO_MEDIA; >> +    } >> +  } >> + >> +  if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetStatus != NULL) { >> +    Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiGetStatus (Cdb, Nic); >> +    if (EFI_ERROR (Status)) { >> +      Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    } >> +  } >> +} >> + >> +/** >> +  This command is used to fill the media header(s) in transmit >> packet(s). >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiFillHeader ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ) >> +{ >> +  PXE_CPB_FILL_HEADER             *CpbFillHeader; >> +  PXE_CPB_FILL_HEADER_FRAGMENTED  *CpbFill; >> +  EthernetHeader                  *MacHeader; >> +  UINTN                           Index; >> +  EFI_STATUS                      Status; >> + >> +  if ((Cdb->OpCode != PXE_OPCODE_FILL_HEADER) || >> +      (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> +      (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> +      (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> +      (Cdb->CPBsize != sizeof (PXE_CPB_FILL_HEADER_FRAGMENTED)) || >> +      (Cdb->DBsize != PXE_DBSIZE_NOT_USED) || >> +      (Cdb->DBaddr != PXE_DBADDR_NOT_USED)) >> +  { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_INVALID_CDB; >> +    return; >> +  } else { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> +    Cdb->StatCode  = PXE_STATCODE_SUCCESS; >> +  } >> + >> +  if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> +    Cdb->StatCode  = PXE_STATCODE_NOT_INITIALIZED; >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    return; >> +  } >> + >> +  if (Cdb->CPBsize == PXE_CPBSIZE_NOT_USED) { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_INVALID_CDB; >> +    return; >> +  } >> + >> +  if ((Cdb->OpFlags & PXE_OPFLAGS_FILL_HEADER_FRAGMENTED) != 0) { >> +    CpbFill = (PXE_CPB_FILL_HEADER_FRAGMENTED *)(UINTN)Cdb->CPBaddr; >> + >> +    if ((CpbFill->FragCnt == 0) || (CpbFill->FragDesc[0].FragLen < >> PXE_MAC_HEADER_LEN_ETHER)) { >> +      Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +      Cdb->StatCode  = PXE_STATCODE_INVALID_CDB; >> +      return; >> +    } >> + >> +    MacHeader           = (EthernetHeader >> *)(UINTN)CpbFill->FragDesc[0].FragAddr; >> +    MacHeader->Protocol = CpbFill->Protocol; >> + >> +    for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> +      MacHeader->DestAddr[Index] = CpbFill->DestAddr[Index]; >> +      MacHeader->SrcAddr[Index]  = CpbFill->SrcAddr[Index]; >> +    } >> +  } else { >> +    CpbFillHeader = (PXE_CPB_FILL_HEADER *)(UINTN)Cdb->CPBaddr; >> + >> +    MacHeader           = (EthernetHeader >> *)(UINTN)CpbFillHeader->MediaHeader; >> +    MacHeader->Protocol = CpbFillHeader->Protocol; >> + >> +    for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> +      MacHeader->DestAddr[Index] = CpbFillHeader->DestAddr[Index]; >> +      MacHeader->SrcAddr[Index]  = CpbFillHeader->SrcAddr[Index]; >> +    } >> +  } >> + >> +  if (Nic->UsbEth->UsbEthUndi.UsbEthUndiFillHeader != NULL) { >> +    Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiFillHeader (Cdb, Nic); >> +    if (EFI_ERROR (Status)) { >> +      Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    } >> +  } >> +} >> + >> +/** >> +  The Transmit command is used to place a packet into the transmit >> queue. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiTransmit ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ) >> +{ >> +  EFI_STATUS  Status; >> + >> +  if ((Cdb->OpCode != PXE_OPCODE_TRANSMIT) || >> +      (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> +      (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> +      (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> +      (Cdb->CPBsize != sizeof (PXE_CPB_TRANSMIT)) || >> +      (Cdb->DBsize != PXE_DBSIZE_NOT_USED) || >> +      (Cdb->DBaddr != PXE_DBADDR_NOT_USED)) >> +  { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_INVALID_CDB; >> +    return; >> +  } else { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> +    Cdb->StatCode  = PXE_STATCODE_SUCCESS; >> +  } >> + >> +  if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_NOT_INITIALIZED; >> +    return; >> +  } >> + >> +  if (Cdb->CPBsize == PXE_CPBSIZE_NOT_USED) { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_INVALID_CDB; >> +    return; >> +  } >> + >> +  if (Nic->UsbEth->UsbEthUndi.UsbEthUndiTransmit != NULL) { >> +    Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiTransmit (Cdb, Nic); >> +    if (EFI_ERROR (Status)) { >> +      Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    } >> + >> +    return; >> +  } >> + >> +  Cdb->StatCode = Transmit (Cdb, Nic, Cdb->CPBaddr, Cdb->OpFlags); >> + >> +  if (Cdb->StatCode != PXE_STATCODE_SUCCESS) { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +  } >> +} >> + >> +/** >> +  Use USB Ethernet Protocol Bulk out command to transmit data. >> + >> +  @param[in]      Cdb      A pointer to the command descriptor block. >> +  @param[in, out] Nic      A pointer to the Network interface >> controller data. >> +  @param[in]      CpbAddr  Command Parameter Block Address. >> +  @param[in]      OpFlags  Operation Flags. >> + >> +**/ >> +UINT16 >> +Transmit ( >> +  IN      PXE_CDB   *Cdb, >> +  IN OUT  NIC_DATA  *Nic, >> +  IN      UINT64    CpbAddr, >> +  IN      UINT16    OpFlags >> +  ) >> +{ >> +  EFI_STATUS        Status; >> +  PXE_CPB_TRANSMIT  *Cpb; >> +  UINT64            BulkOutData; >> +  UINTN             DataLength; >> +  UINTN             TransmitLength; >> +  UINTN             Map; >> +  UINT32            Counter; >> +  UINT16            StatCode; >> + >> +  BulkOutData = 0; >> +  Counter     = 0; >> +  Cpb         = (PXE_CPB_TRANSMIT *)(UINTN)CpbAddr; >> + >> +  if (Nic->CanTransmit) { >> +    return PXE_STATCODE_BUSY; >> +  } >> + >> +  Nic->CanTransmit = TRUE; >> + >> +  if ((OpFlags & PXE_OPFLAGS_TRANSMIT_FRAGMENTED) != 0) { >> +    return PXE_STATCODE_INVALID_PARAMETER; >> +  } >> + >> +  Map = MapIt ( >> +          Nic, >> +          Cpb->FrameAddr, >> +          Cpb->DataLen + (UINT32)Cpb->MediaheaderLen, >> +          TO_DEVICE, >> +          (UINT64)(UINTN)&BulkOutData >> +          ); >> + >> +  if (Map != 0) { >> +    Nic->CanTransmit = FALSE; >> +    return PXE_STATCODE_INVALID_PARAMETER; >> +  } >> + >> +  if (Nic->TxBufferCount < MAX_XMIT_BUFFERS) { >> +    Nic->MediaHeader[Nic->TxBufferCount] = Cpb->FrameAddr; >> +    Nic->TxBufferCount++; >> +  } >> + >> +  DataLength = (UINTN)(Cpb->DataLen + (UINT32)Cpb->MediaheaderLen); >> + >> +  while (1) { >> +    if (Counter >= 3) { >> +      StatCode = PXE_STATCODE_BUSY; >> +      break; >> +    } >> + >> +    TransmitLength = DataLength; >> + >> +    Status = Nic->UsbEth->UsbEthTransmit (Cdb, Nic->UsbEth, (VOID >> *)(UINTN)BulkOutData, &TransmitLength); >> +    if (EFI_ERROR (Status)) { >> +      StatCode =  PXE_STATFLAGS_COMMAND_FAILED; >> +    } >> + >> +    if (Status == EFI_INVALID_PARAMETER) { >> +      StatCode = PXE_STATCODE_INVALID_PARAMETER; >> +      break; >> +    } >> + >> +    if (Status == EFI_DEVICE_ERROR) { >> +      StatCode = PXE_STATCODE_DEVICE_FAILURE; >> +      break; >> +    } >> + >> +    if (!EFI_ERROR (Status)) { >> +      Nic->TxFrame++; >> +      StatCode = PXE_STATCODE_SUCCESS; >> +      break; >> +    } >> + >> +    Counter++; >> +  } >> + >> +  UnMapIt ( >> +    Nic, >> +    Cpb->FrameAddr, >> +    Cpb->DataLen + (UINT32)Cpb->MediaheaderLen, >> +    TO_DEVICE, >> +    BulkOutData >> +    ); >> + >> +  Nic->CanTransmit = FALSE; >> + >> +  return StatCode; >> +} >> + >> +/** >> +  When the network adapter has received a frame, this command is used >> +  to copy the frame into driver/application storage. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiReceive ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ) >> +{ >> +  EFI_STATUS  Status; >> + >> +  if ((Cdb->OpCode != PXE_OPCODE_RECEIVE) || >> +      (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> +      (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> +      (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> +      (Cdb->CPBsize != sizeof (PXE_CPB_RECEIVE)) || >> +      (Cdb->DBsize != sizeof (PXE_DB_RECEIVE)) || >> +      (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED)) >> +  { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_INVALID_CDB; >> +    return; >> +  } else { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> +    Cdb->StatCode  = PXE_STATCODE_SUCCESS; >> +  } >> + >> +  if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    Cdb->StatCode  = PXE_STATCODE_NOT_INITIALIZED; >> +    return; >> +  } >> + >> +  if (Nic->UsbEth->UsbEthUndi.UsbEthUndiReceive != NULL) { >> +    Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiReceive (Cdb, Nic); >> +    if (EFI_ERROR (Status)) { >> +      Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +    } >> + >> +    return; >> +  } >> + >> +  Cdb->StatCode = Receive (Cdb, Nic, Cdb->CPBaddr, Cdb->DBaddr); >> + >> +  if (Cdb->StatCode != PXE_STATCODE_SUCCESS) { >> +    Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> +  } >> +} >> + >> +/** >> +  Use USB Ethernet Protocol Bulk in command to receive data. >> + >> +  @param[in]      Cdb      A pointer to the command descriptor block. >> +  @param[in, out] Nic      A pointer to the Network interface >> controller data. >> +  @param[in]      CpbAddr  Command Parameter Block Address. >> +  @param[in, out] DbAddr   Data Block Address. >> + >> +**/ >> +UINT16 >> +Receive ( >> +  IN PXE_CDB       *Cdb, >> +  IN OUT NIC_DATA  *Nic, >> +  IN UINT64        CpbAddr, >> +  IN OUT UINT64    DbAddr >> +  ) >> +{ >> +  EFI_STATUS       Status; >> +  UINTN            Index; >> +  PXE_FRAME_TYPE   FrameType; >> +  PXE_CPB_RECEIVE  *Cpb; >> +  PXE_DB_RECEIVE   *Db; >> +  NIC_DEVICE       *NicDevice; >> +  UINT8            *BulkInData; >> +  UINTN            DataLength; >> +  EthernetHeader   *Header; >> +  EFI_TPL          OriginalTpl; >> + >> +  FrameType  = PXE_FRAME_TYPE_NONE; >> +  NicDevice  = UNDI_DEV_FROM_NIC (Nic); >> +  BulkInData = NicDevice->ReceiveBuffer; >> +  DataLength = (UINTN)Nic->MaxSegmentSize; >> +  Cpb        = (PXE_CPB_RECEIVE *)(UINTN)CpbAddr; >> +  Db         = (PXE_DB_RECEIVE *)(UINTN)DbAddr; >> + >> +  if (!BulkInData) { >> +    return PXE_STATCODE_INVALID_PARAMETER; >> +  } >> + >> +  if ((Nic->RateLimitingCreditCount == 0) && >> (Nic->RateLimitingEnable == TRUE)) { >> +    return PXE_STATCODE_NO_DATA; >> +  } >> + >> +  Status = Nic->UsbEth->UsbEthReceive (Cdb, Nic->UsbEth, (VOID >> *)BulkInData, &DataLength); >> +  if (EFI_ERROR (Status)) { >> +    Nic->ReceiveStatus = 0; >> +    if (Nic->RateLimitingEnable == TRUE) { >> +      OriginalTpl = gBS->RaiseTPL (TPL_NOTIFY); >> +      if (Nic->RateLimitingCreditCount != 0) { >> +        Nic->RateLimitingCreditCount--; >> +      } >> + >> +      gBS->RestoreTPL (OriginalTpl); >> +    } >> + >> +    return PXE_STATCODE_NO_DATA; >> +  } >> + >> +  Nic->RxFrame++; >> + >> +  if (DataLength != 0) { >> +    if (DataLength > Cpb->BufferLen) { >> +      DataLength = (UINTN)Cpb->BufferLen; >> +    } >> + >> +    CopyMem ((UINT8 *)(UINTN)Cpb->BufferAddr, (UINT8 *)BulkInData, >> DataLength); >> + >> +    Header = (EthernetHeader *)BulkInData; >> + >> +    Db->FrameLen       = (UINT32)DataLength; >> +    Db->MediaHeaderLen = PXE_MAC_HEADER_LEN_ETHER; >> + >> +    for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> +      if (Header->DestAddr[Index] != Nic->CurrentNodeAddress[Index]) { >> +        break; >> +      } >> +    } >> + >> +    if (Index >= PXE_HWADDR_LEN_ETHER) { >> +      FrameType = PXE_FRAME_TYPE_UNICAST; >> +    } else { >> +      for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> +        if (Header->DestAddr[Index] != >> Nic->BroadcastNodeAddress[Index]) { >> +          break; >> +        } >> +      } >> + >> +      if (Index >= PXE_HWADDR_LEN_ETHER) { >> +        FrameType = PXE_FRAME_TYPE_BROADCAST; >> +      } else { >> +        if ((Header->DestAddr[0] & 1) == 1) { >> +          FrameType = PXE_FRAME_TYPE_FILTERED_MULTICAST; >> +        } else { >> +          FrameType = PXE_FRAME_TYPE_PROMISCUOUS; >> +        } >> +      } >> +    } >> + >> +    Db->Type     = FrameType; >> +    Db->Protocol = Header->Protocol; >> + >> +    for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> +      Db->SrcAddr[Index]  = Header->SrcAddr[Index]; >> +      Db->DestAddr[Index] = Header->DestAddr[Index]; >> +    } >> +  } >> + >> +  if (FrameType == PXE_FRAME_TYPE_NONE) { >> +    Nic->ReceiveStatus = 0; >> +  } else { >> +    Nic->ReceiveStatus = 1; >> +  } >> + >> +  return PXE_STATCODE_SUCCESS; >> +} >> + >> +/** >> +  Fill out PXE SW UNDI structure. >> + >> +  @param[out]  PxeSw      A pointer to the PXE SW UNDI structure. >> + >> +**/ >> +VOID >> +PxeStructInit ( >> +  OUT PXE_SW_UNDI  *PxeSw >> +  ) >> +{ >> +  PxeSw->Signature = PXE_ROMID_SIGNATURE; >> +  PxeSw->Len       = (UINT8)sizeof (PXE_SW_UNDI); >> +  PxeSw->Fudge     = 0; >> +  PxeSw->IFcnt     = 0; >> +  PxeSw->IFcntExt  = 0; >> +  PxeSw->Rev       = PXE_ROMID_REV; >> +  PxeSw->MajorVer  = PXE_ROMID_MAJORVER; >> +  PxeSw->MinorVer  = PXE_ROMID_MINORVER; >> +  PxeSw->reserved1 = 0; >> + >> +  PxeSw->Implementation = PXE_ROMID_IMP_SW_VIRT_ADDR | >> +                          PXE_ROMID_IMP_FRAG_SUPPORTED | >> +                          PXE_ROMID_IMP_CMD_LINK_SUPPORTED | >> +                          PXE_ROMID_IMP_STATION_ADDR_SETTABLE | >> + PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED | >> + PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED | >> +                          PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED | >> + PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED; >> + >> +  PxeSw->EntryPoint   = (UINT64)(UINTN)UndiApiEntry; >> +  PxeSw->reserved2[0] = 0; >> +  PxeSw->reserved2[1] = 0; >> +  PxeSw->reserved2[2] = 0; >> +  PxeSw->BusCnt       = 1; >> +  PxeSw->BusType[0]   = PXE_BUSTYPE_USB; >> +  PxeSw->Fudge        = PxeSw->Fudge - CalculateSum8 ((VOID *)PxeSw, >> PxeSw->Len); >> +} >> + >> +/** >> +  Update NIC number. >> + >> +  @param[in]      Nic       A pointer to the Network interface >> controller data. >> +  @param[in, out] PxeSw     A pointer to the PXE SW UNDI structure. >> + >> +**/ >> +VOID >> +UpdateNicNum ( >> +  IN      NIC_DATA     *Nic, >> +  IN OUT  PXE_SW_UNDI  *PxeSw >> +  ) >> +{ >> +  UINT16  NicNum; >> + >> +  NicNum = (PxeSw->IFcnt | PxeSw->IFcntExt << 8); >> + >> +  if (Nic == NULL) { >> +    if (NicNum > 0) { >> +      NicNum--; >> +    } >> + >> +    PxeSw->IFcnt    = (UINT8)(NicNum & 0xFF); // Get lower byte >> +    PxeSw->IFcntExt = (UINT8)((NicNum & 0xFF00) >> 8); // Get upper >> byte >> +    PxeSw->Fudge    = (UINT8)(PxeSw->Fudge - CalculateSum8 ((VOID >> *)PxeSw, PxeSw->Len)); >> +    return; >> +  } >> + >> +  NicNum++; >> + >> +  PxeSw->IFcnt    = (UINT8)(NicNum & 0xFF);          // Get lower byte >> +  PxeSw->IFcntExt = (UINT8)((NicNum & 0xFF00) >> 8); // Get upper byte >> +  PxeSw->Fudge    = (UINT8)(PxeSw->Fudge - CalculateSum8 ((VOID >> *)PxeSw, PxeSw->Len)); >> +} >> + >> +/** >> +  UNDI API table entry. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +UndiApiEntry ( >> +  IN  UINT64  Cdb >> +  ) >> +{ >> +  PXE_CDB   *CdbPtr; >> +  NIC_DATA  *Nic; >> + >> +  if (Cdb == 0) { >> +    return EFI_INVALID_PARAMETER; >> +  } >> + >> +  CdbPtr = (PXE_CDB *)(UINTN)Cdb; >> +  Nic    = &(gLanDeviceList[CdbPtr->IFnum]->NicInfo); >> +  gUndiApiTable[CdbPtr->OpCode](CdbPtr, Nic); >> +  return EFI_SUCCESS; >> +} >> + >> +/** >> +  Map virtual memory address for DMA. This field can be set to >> +  zero if there is no mapping service. >> + >> +  @param[in]  Nic           A pointer to the Network interface >> controller data. >> +  @param[in]  MemAddr       Virtual address to be mapped. >> +  @param[in]  Size          Size of memory to be mapped. >> +  @param[in]  Direction     Direction of data flow for this memory's >> usage: >> +                            cpu->device, device->cpu or both ways. >> +  @param[out] MappedAddr    Pointer to return the mapped device >> address. >> + >> +**/ >> +UINTN >> +MapIt ( >> +  IN NIC_DATA  *Nic, >> +  IN UINT64    MemAddr, >> +  IN UINT32    Size, >> +  IN UINT32    Direction, >> +  OUT UINT64   MappedAddr >> +  ) >> +{ >> +  UINT64  *PhyAddr; >> + >> +  PhyAddr = (UINT64 *)(UINTN)MappedAddr; >> + >> +  if (Nic->PxeStart.Map_Mem == 0) { >> +    *PhyAddr = MemAddr; >> +  } else { >> +    ((void (*)(UINT64, UINT64, UINT32, UINT32, UINT64))(UINTN) >> Nic->PxeStart.Map_Mem)( >> +  Nic->PxeStart.Unique_ID, >> +  MemAddr, >> +  Size, >> +  Direction, >> +  MappedAddr >> +  ); >> +  } >> + >> +  return PXE_STATCODE_SUCCESS; >> +} >> + >> +/** >> +  Un-map previously mapped virtual memory address. This field can be >> set >> +  to zero only if the Map_Mem() service is also set to zero. >> + >> +  @param[in]  Nic           A pointer to the Network interface >> controller data. >> +  @param[in]  MemAddr       Virtual address to be mapped. >> +  @param[in]  Size          Size of memory to be mapped. >> +  @param[in]  Direction     Direction of data flow for this memory's >> usage: >> +                            cpu->device, device->cpu or both ways. >> +  @param[in]  MappedAddr    Pointer to return the mapped device >> address. >> + >> +**/ >> +VOID >> +UnMapIt ( >> +  IN NIC_DATA  *Nic, >> +  IN UINT64    MemAddr, >> +  IN UINT32    Size, >> +  IN UINT32    Direction, >> +  IN UINT64    MappedAddr >> +  ) >> +{ >> +  if (Nic->PxeStart.UnMap_Mem != 0) { >> +    ((void (*)(UINT64, UINT64, UINT32, UINT32, UINT64))(UINTN) >> Nic->PxeStart.UnMap_Mem)( >> +  Nic->PxeStart.Unique_ID, >> +  MemAddr, >> +  Size, >> +  Direction, >> +  MappedAddr >> +  ); >> +  } >> + >> +  return; >> +} >> diff --git a/UsbNetworkPkg/UsbRndis/ComponentName.c >> b/UsbNetworkPkg/UsbRndis/ComponentName.c >> new file mode 100644 >> index 000000000000..b9ba170c135b >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbRndis/ComponentName.c >> @@ -0,0 +1,172 @@ >> +/** @file >> +  This file contains code for USB RNDIS Driver Component >> +  Name definitions >> + >> +  Copyright (c) 2023, American Megatrends International LLC. All >> rights reserved.
>> +  SPDX-License-Identifier: BSD-2-Clause-Patent >> +**/ >> + >> +#include "UsbRndis.h" >> + >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE >> gUsbRndisDriverNameTable[] = { >> +  { >> +    "eng;en", >> +    L"USB RNDIS Driver" >> +  }, >> +  { >> +    NULL, >> +    NULL >> +  } >> +}; >> + >> +EFI_STATUS >> +EFIAPI >> +UsbRndisComponentNameGetDriverName ( >> +  IN  EFI_COMPONENT_NAME_PROTOCOL  *This, >> +  IN  CHAR8                        *Language, >> +  OUT CHAR16                       **DriverName >> +  ); >> + >> +EFI_STATUS >> +EFIAPI >> +UsbRndisComponentNameGetControllerName ( >> +  IN EFI_COMPONENT_NAME_PROTOCOL  *This, >> +  IN EFI_HANDLE                   Controller, >> +  IN EFI_HANDLE                   ChildHandle        OPTIONAL, >> +  IN CHAR8                        *Language, >> +  OUT CHAR16                      **ControllerName >> +  ); >> + >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL >> gUsbRndisComponentName = { >> +  UsbRndisComponentNameGetDriverName, >> +  UsbRndisComponentNameGetControllerName, >> +  "eng" >> +}; >> + >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL >> gUsbRndisComponentName2 = { >> + >> (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)UsbRndisComponentNameGetDriverName, >> + >> (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)UsbRndisComponentNameGetControllerName, >> +  "en" >> +}; >> + >> +/** >> +  Retrieves a Unicode string that is the user readable name of the >> driver. >> + >> +  This function retrieves the user readable name of a driver in the >> form of a >> +  Unicode string. If the driver specified by This has a user >> readable name in >> +  the language specified by Language, then a pointer to the driver >> name is >> +  returned in DriverName, and EFI_SUCCESS is returned. If the driver >> specified >> +  by This does not support the language specified by Language, >> +  then EFI_UNSUPPORTED is returned. >> + >> +  @param[in]  This              A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >> +                                EFI_COMPONENT_NAME_PROTOCOL instance. >> +  @param[in]  Language          A pointer to a Null-terminated ASCII >> string >> +                                array indicating the language. This >> is the >> +                                language of the driver name that the >> caller is >> +                                requesting, and it must match one of >> the >> +                                languages specified in >> SupportedLanguages. The >> +                                number of languages supported by a >> driver is up >> +                                to the driver writer. Language is >> specified >> +                                in RFC 4646 or ISO 639-2 language >> code format. >> +  @param[out] DriverName        A pointer to the Unicode string to >> return. >> +                                This Unicode string is the name of the >> +                                driver specified by This in the >> language >> +                                specified by Language. >> + >> +  @retval EFI_SUCCESS           The Unicode string for the Driver >> specified by >> +                                This and the language specified by >> Language was >> +                                returned in DriverName. >> +  @retval EFI_INVALID_PARAMETER Language is NULL. >> +  @retval EFI_INVALID_PARAMETER DriverName is NULL. >> +  @retval EFI_UNSUPPORTED       The driver specified by This does >> not support >> +                                the language specified by Language. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +UsbRndisComponentNameGetDriverName ( >> +  IN  EFI_COMPONENT_NAME_PROTOCOL  *This, >> +  IN  CHAR8                        *Language, >> +  OUT CHAR16                       **DriverName >> +  ) >> +{ >> +  return LookupUnicodeString2 ( >> +           Language, >> +           This->SupportedLanguages, >> +           gUsbRndisDriverNameTable, >> +           DriverName, >> +           (BOOLEAN)(This == &gUsbRndisComponentName) >> +           ); >> +} >> + >> +/** >> +  Retrieves a Unicode string that is the user readable name of the >> controller >> +  that is being managed by a driver. >> + >> +  This function retrieves the user readable name of the controller >> specified by >> +  ControllerHandle and ChildHandle in the form of a Unicode string. >> If the >> +  driver specified by This has a user readable name in the language >> specified by >> +  Language, then a pointer to the controller name is returned in >> ControllerName, >> +  and EFI_SUCCESS is returned.  If the driver specified by This is >> not currently >> +  managing the controller specified by ControllerHandle and >> ChildHandle, >> +  then EFI_UNSUPPORTED is returned.  If the driver specified by This >> does not >> +  support the language specified by Language, then EFI_UNSUPPORTED >> is returned. >> + >> +  @param[in]  This              A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >> +                                EFI_COMPONENT_NAME_PROTOCOL instance. >> +  @param[in]  Controller        The handle of a controller that the >> driver >> +                                specified by This is managing. This >> handle >> +                                specifies the controller whose name >> is to be >> +                                returned. >> +  @param[in]  ChildHandle       The handle of the child controller >> to retrieve >> +                                the name of.  This is an optional >> parameter that >> +                                may be NULL.  It will be NULL for >> device >> +                                drivers.  It will also be NULL for a >> bus drivers >> +                                that wish to retrieve the name of >> the bus >> +                                controller.  It will not be NULL for >> a bus >> +                                driver that wishes to retrieve the >> name of a >> +                                child controller. >> +  @param[in]  Language          A pointer to a Null-terminated ASCII >> string >> +                                array indicating the language. This >> is the >> +                                language of the driver name that the >> caller is >> +                                requesting, and it must match one of >> the >> +                                languages specified in >> SupportedLanguages. The >> +                                number of languages supported by a >> driver is up >> +                                to the driver writer. Language is >> specified in >> +                                RFC 4646 or ISO 639-2 language code >> format. >> +  @param[out] ControllerName    A pointer to the Unicode string to >> return. >> +                                This Unicode string is the name of the >> +                                controller specified by >> ControllerHandle and >> +                                ChildHandle in the language >> specified by >> +                                Language from the point of view of >> the driver >> +                                specified by This. >> + >> +  @retval EFI_SUCCESS           The Unicode string for the user >> readable name in >> +                                the language specified by Language >> for the >> +                                driver specified by This was >> returned in >> +                                DriverName. >> +  @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid >> EFI_HANDLE. >> +  @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is >> not a valid >> +                                EFI_HANDLE. >> +  @retval EFI_INVALID_PARAMETER Language is NULL. >> +  @retval EFI_INVALID_PARAMETER ControllerName is NULL. >> +  @retval EFI_UNSUPPORTED       The driver specified by This is not >> currently >> +                                managing the controller specified by >> +                                ControllerHandle and ChildHandle. >> +  @retval EFI_UNSUPPORTED       The driver specified by This does >> not support >> +                                the language specified by Language. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +UsbRndisComponentNameGetControllerName ( >> +  IN EFI_COMPONENT_NAME_PROTOCOL  *This, >> +  IN EFI_HANDLE                   Controller, >> +  IN EFI_HANDLE                   ChildHandle        OPTIONAL, >> +  IN CHAR8                        *Language, >> +  OUT CHAR16                      **ControllerName >> +  ) >> +{ >> +  return EFI_UNSUPPORTED; >> +} >> diff --git a/UsbNetworkPkg/UsbRndis/UsbRndis.c >> b/UsbNetworkPkg/UsbRndis/UsbRndis.c >> new file mode 100644 >> index 000000000000..92830771e408 >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbRndis/UsbRndis.c >> @@ -0,0 +1,886 @@ >> +/** @file >> +  This file contains code for USB Remote Network Driver >> +  Interface Spec. Driver Binding >> + >> +  Copyright (c) 2023, American Megatrends International LLC. All >> rights reserved.
>> +  SPDX-License-Identifier: BSD-2-Clause-Patent >> +**/ >> + >> +#include "UsbRndis.h" >> + >> +EFI_DRIVER_BINDING_PROTOCOL  gUsbRndisDriverBinding = { >> +  UsbRndisDriverSupported, >> +  UsbRndisDriverStart, >> +  UsbRndisDriverStop, >> +  USB_RNDIS_DRIVER_VERSION, >> +  NULL, >> +  NULL >> +}; >> + >> +/** >> +  Check if this interface is USB Rndis SubType >> + >> +  @param[in]  UsbIo  A pointer to the EFI_USB_IO_PROTOCOL instance. >> + >> +  @retval TRUE   USB Rndis SubType. >> +  @retval FALSE  Not USB Rndis SubType. >> + >> +**/ >> +BOOLEAN >> +IsSupportedDevice ( >> +  IN EFI_USB_IO_PROTOCOL  *UsbIo >> +  ) >> +{ >> +  EFI_STATUS                    Status; >> +  EFI_USB_INTERFACE_DESCRIPTOR  InterfaceDescriptor; >> + >> +  Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, >> &InterfaceDescriptor); >> +  if (EFI_ERROR (Status)) { >> +    return FALSE; >> +  } >> + >> +  // Check specific device/RNDIS and CDC-DATA >> +  if (((InterfaceDescriptor.InterfaceClass == 0x2) && >> +       (InterfaceDescriptor.InterfaceSubClass == 0x2) && >> +       (InterfaceDescriptor.InterfaceProtocol == 0xFF)) || \ >> +      ((InterfaceDescriptor.InterfaceClass == 0xEF) && >> +       (InterfaceDescriptor.InterfaceSubClass == 0x4) && >> +       (InterfaceDescriptor.InterfaceProtocol == 0x1)) || \ >> +      ((InterfaceDescriptor.InterfaceClass == 0xA) && >> +       (InterfaceDescriptor.InterfaceSubClass == 0x0) && >> +       (InterfaceDescriptor.InterfaceProtocol == 0x00)) >> +      ) >> +  { >> +    return TRUE; >> +  } >> + >> +  return FALSE; >> +} >> + >> +/** >> +  Check if this interface is USB Rndis SubType but not CDC Data >> interface >> + >> +  @param[in]  UsbIo  A pointer to the EFI_USB_IO_PROTOCOL instance. >> + >> +  @retval TRUE   USB Rndis SubType. >> +  @retval FALSE  Not USB Rndis SubType. >> +**/ >> +BOOLEAN >> +IsRndisInterface ( >> +  IN EFI_USB_IO_PROTOCOL  *UsbIo >> +  ) >> +{ >> +  EFI_STATUS                    Status; >> +  EFI_USB_INTERFACE_DESCRIPTOR  InterfaceDescriptor; >> + >> +  Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, >> &InterfaceDescriptor); >> +  if (EFI_ERROR (Status)) { >> +    return FALSE; >> +  } >> + >> +  // Check for specific device/RNDIS and CDC-DATA >> +  if (((InterfaceDescriptor.InterfaceClass == 0x2) && >> +       (InterfaceDescriptor.InterfaceSubClass == 0x2) && >> +       (InterfaceDescriptor.InterfaceProtocol == 0xFF)) || \ >> +      ((InterfaceDescriptor.InterfaceClass == 0xEF) && >> +       (InterfaceDescriptor.InterfaceSubClass == 0x4) && >> +       (InterfaceDescriptor.InterfaceProtocol == 0x1)) >> +      ) >> +  { >> +    return TRUE; >> +  } >> + >> +  return FALSE; >> +} >> + >> +/** >> +  Check if the USB RNDIS and USB CDC Data interfaces are from the >> same device. >> + >> +  @param[in]  UsbRndisDataPath  A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> +  @param[in]  UsbCdcDataPath    A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> + >> +  @retval EFI_SUCCESS           Is the same device. >> +  @retval EFI_UNSUPPORTED       Is not the same device. >> + >> +**/ >> +EFI_STATUS >> +IsSameDevice ( >> +  IN  EFI_DEVICE_PATH_PROTOCOL  *UsbRndisDataPath, >> +  IN  EFI_DEVICE_PATH_PROTOCOL  *UsbCdcDataPath >> +  ) >> +{ >> +  DEBUG ((DEBUG_VERBOSE, "IsSameDevice Entry \n")); >> +  while (1) { >> +    if (IsDevicePathEnd (NextDevicePathNode (UsbRndisDataPath))) { >> +      if (((USB_DEVICE_PATH *)UsbRndisDataPath)->ParentPortNumber == >> +          ((USB_DEVICE_PATH *)UsbCdcDataPath)->ParentPortNumber) >> +      { >> +        return EFI_SUCCESS; >> +      } else { >> +        return EFI_UNSUPPORTED; >> +      } >> +    } else { >> +      if (CompareMem (UsbCdcDataPath, UsbRndisDataPath, sizeof >> (EFI_DEVICE_PATH_PROTOCOL)) != 0) { >> +        return EFI_UNSUPPORTED; >> +      } >> + >> +      UsbRndisDataPath = NextDevicePathNode (UsbRndisDataPath); >> +      UsbCdcDataPath   = NextDevicePathNode (UsbCdcDataPath); >> +    } >> +  } >> + >> +  DEBUG ((DEBUG_VERBOSE, "IsSameDevice Exit \n")); >> +} >> + >> +/** >> +  Check if the USB CDC Data(UsbIo) installed and return USB CDC Data >> Handle. >> + >> +  @param[in]  UsbIo  A pointer to the EFI_USB_IO_PROTOCOL instance. >> + >> +  @retval TRUE              USB CDC Data(UsbIo) installed. >> +  @retval FALSE             USB CDC Data(UsbIo) did not installed. >> + >> +**/ >> +BOOLEAN >> +IsUsbCdcData ( >> +  IN EFI_USB_IO_PROTOCOL  *UsbIo >> +  ) >> +{ >> +  EFI_STATUS                    Status; >> +  EFI_USB_INTERFACE_DESCRIPTOR  InterfaceDescriptor; >> + >> +  Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, >> &InterfaceDescriptor); >> +  if (EFI_ERROR (Status)) { >> +    return FALSE; >> +  } >> + >> +  // Check for CDC-DATA >> +  if ((InterfaceDescriptor.InterfaceClass == 0xA) && >> +      (InterfaceDescriptor.InterfaceSubClass == 0x0) && >> +      (InterfaceDescriptor.InterfaceProtocol == 0x0)) >> +  { >> +    return TRUE; >> +  } >> + >> +  return FALSE; >> +} >> + >> +/** >> +  Check if the USB Rndis(UsbIo) installed >> + >> +  @param[in]  UsbIo        A pointer to the EFI_USB_IO_PROTOCOL >> instance. >> + >> +  @retval TRUE              USB Rndis(UsbIo) installed. >> +  @retval FALSE             USB Rndis(UsbIo) did not installed. >> + >> +**/ >> +BOOLEAN >> +IsUsbRndis ( >> +  IN EFI_USB_IO_PROTOCOL  *UsbIo >> +  ) >> +{ >> +  EFI_STATUS                    Status; >> +  EFI_USB_INTERFACE_DESCRIPTOR  InterfaceDescriptor; >> + >> +  Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, >> &InterfaceDescriptor); >> +  if (EFI_ERROR (Status)) { >> +    return FALSE; >> +  } >> + >> +  // Check for Rndis >> +  if ((InterfaceDescriptor.InterfaceClass == 0x2) && >> +      (InterfaceDescriptor.InterfaceSubClass == 0x2) && >> +      (InterfaceDescriptor.InterfaceProtocol == 0xFF)) >> +  { >> +    return TRUE; >> +  } >> + >> +  return FALSE; >> +} >> + >> +/** >> +  Control comes here when a CDC device is found.Check if a RNDIS >> interface is already found for this device or not. >> +  For one device two USBIO will be installed each for CDC and RNDIS >> interface. >> + >> +  @param[in]  UsbEthPath        A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> +  @param[out] UsbRndisDevice    A pointer to the USB_RNDIS_DEVICE Data. >> + >> +  @retval EFI_SUCCESS             The USB_RNDIS_DEVICE matching this >> CDC Data is found. >> +  @retval EFI_NOT_FOUND           The USB_RNDIS_DEVICE matching this >> CDC Data is not found. >> + >> +**/ >> +EFI_STATUS >> +UpdateRndisDevice ( >> +  IN  EFI_DEVICE_PATH_PROTOCOL  *UsbCdcDataPath, >> +  OUT USB_RNDIS_DEVICE          **UsbRndisDevice >> +  ) >> +{ >> +  EFI_STATUS                   Status; >> +  UINTN                        Index; >> +  UINTN                        HandleCount; >> +  EFI_HANDLE                   *HandleBuffer; >> +  EDKII_USB_ETHERNET_PROTOCOL  *UsbEthDevice; >> +  EFI_DEVICE_PATH_PROTOCOL     *UsbRndisDataPath; >> +  EFI_USB_IO_PROTOCOL          *UsbIo; >> +  BOOLEAN                      IsRndisInterfaceFlag; >> + >> +  IsRndisInterfaceFlag = FALSE; >> + >> +  Status = gBS->LocateHandleBuffer ( >> +                  ByProtocol, >> +                  &gEdkIIUsbEthProtocolGuid, >> +                  NULL, >> +                  &HandleCount, >> +                  &HandleBuffer >> +                  ); >> +  if (EFI_ERROR (Status)) { >> +    return Status; >> +  } >> + >> +  for (Index = 0; Index < HandleCount; Index++) { >> +    Status = gBS->HandleProtocol ( >> +                    HandleBuffer[Index], >> +                    &gEdkIIUsbEthProtocolGuid, >> +                    (VOID **)&UsbEthDevice >> +                    ); >> +    if (EFI_ERROR (Status)) { >> +      continue; >> +    } >> + >> +    Status = gBS->HandleProtocol ( >> +                    HandleBuffer[Index], >> +                    &gEfiUsbIoProtocolGuid, >> +                    (VOID **)&UsbIo >> +                    ); >> +    if (EFI_ERROR (Status)) { >> +      continue; >> +    } >> + >> +    IsRndisInterfaceFlag = IsRndisInterface (UsbIo); >> +    if (IsRndisInterfaceFlag == FALSE) { >> +      continue; >> +    } >> + >> +    Status = gBS->HandleProtocol ( >> +                    HandleBuffer[Index], >> +                    &gEfiDevicePathProtocolGuid, >> +                    (VOID **)&UsbRndisDataPath >> +                    ); >> +    if (EFI_ERROR (Status)) { >> +      continue; >> +    } >> + >> +    Status = IsSameDevice (UsbRndisDataPath, UsbCdcDataPath); >> + >> +    DEBUG ((DEBUG_VERBOSE, "Rndis IsSameDevice %r\n", Status)); >> + >> +    if (!EFI_ERROR (Status)) { >> +      *UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (UsbEthDevice); >> +      FreePool (HandleBuffer); >> +      return EFI_SUCCESS; >> +    } >> +  }   // End of For loop >> + >> +  FreePool (HandleBuffer); >> +  return EFI_NOT_FOUND; >> +} >> + >> +/** >> + >> +  For the given Rndis Device, find a matching CDC device already >> exists or not. If found update the handle >> +  and UsbIO protocol. >> + >> +  @param[in]  UsbRndisDevice        A pointer to the >> USB_RNDIS_DEVICE data. >> + >> +**/ >> +VOID >> +FindMatchingCdcData ( >> +  IN USB_RNDIS_DEVICE  *UsbRndisDevice >> +  ) >> +{ >> +  EFI_STATUS                Status; >> +  UINTN                     Index; >> +  UINTN                     HandleCount; >> +  EFI_HANDLE                *HandleBuffer; >> +  EFI_USB_IO_PROTOCOL       *UsbIo; >> +  EFI_DEVICE_PATH_PROTOCOL  *UsbRndisDataPath; >> +  EFI_DEVICE_PATH_PROTOCOL  *UsbCdcDataPath; >> + >> +  // Find the parent RNDIS and update the UsbIo for the CDC device >> +  Status = gBS->HandleProtocol ( >> +                  UsbRndisDevice->UsbRndisHandle, >> +                  &gEfiDevicePathProtocolGuid, >> +                  (VOID **)&UsbRndisDataPath >> +                  ); >> + >> +  if (EFI_ERROR (Status)) { >> +    return; >> +  } >> + >> +  Status = gBS->LocateHandleBuffer ( >> +                  ByProtocol, >> +                  &gEfiUsbIoProtocolGuid, >> +                  NULL, >> +                  &HandleCount, >> +                  &HandleBuffer >> +                  ); >> +  if (EFI_ERROR (Status)) { >> +    return; >> +  } >> + >> +  for (Index = 0; Index < HandleCount; Index++) { >> +    Status = gBS->HandleProtocol ( >> +                    HandleBuffer[Index], >> +                    &gEfiUsbIoProtocolGuid, >> +                    (VOID **)&UsbIo >> +                    ); >> +    ASSERT_EFI_ERROR (Status); >> + >> +    if (IsUsbCdcData (UsbIo)) { >> +      DEBUG ((DEBUG_VERBOSE, "Rndis FindMatchingCdcData CDCData >> interface found\n")); >> + >> +      Status = gBS->HandleProtocol ( >> +                      HandleBuffer[Index], >> +                      &gEfiDevicePathProtocolGuid, >> +                      (VOID **)&UsbCdcDataPath >> +                      ); >> +      if (EFI_ERROR (Status)) { >> +        DEBUG ((DEBUG_VERBOSE, "Rndis CDCData DevicePath not >> found\n")); >> +        FreePool (HandleBuffer); >> +        return; >> +      } >> + >> +      Status = IsSameDevice (UsbRndisDataPath, UsbCdcDataPath); >> +      DEBUG ((DEBUG_VERBOSE, "Rndis IsSameDevice %r\n", Status)); >> +      if (!EFI_ERROR (Status)) { >> +        UsbRndisDevice->UsbCdcDataHandle = HandleBuffer[Index]; >> +        UsbRndisDevice->UsbIoCdcData     = UsbIo; >> +        GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice); >> +        FreePool (HandleBuffer); >> +        return; >> +      } >> +    } >> +  }   // End of For loop >> + >> +  FreePool (HandleBuffer); >> +} >> + >> +/** >> + >> +  For the given UsbIo CdcData, find a matching RNDIS device already >> exists or not. >> + >> +  @param[in]  CdcHandle       A pointer to the EFI_HANDLE for USB >> CDC Data. >> +  @param[out] CdcUsbIo        A pointer for retrieve the >> EFI_USB_IO_PROTOCOL instance. >> +  @param[out] RndisHandle     A pointer for retrieve the handle of >> RNDIS device. >> + >> +  @retval EFI_SUCCESS             The USB_RNDIS_DEVICE matching this >> CDC Data is found. >> +  @retval EFI_NOT_FOUND           The USB_RNDIS_DEVICE matching this >> CDC Data is not found. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +FindMatchingRndisDev ( >> +  IN  EFI_HANDLE           CdcHandle, >> +  OUT EFI_USB_IO_PROTOCOL  **CdcUsbIo, >> +  OUT EFI_HANDLE           *RndisHandle >> +  ) >> +{ >> +  EFI_STATUS                Status; >> +  UINTN                     Index; >> +  UINTN                     HandleCount; >> +  EFI_HANDLE                *HandleBuffer; >> +  EFI_USB_IO_PROTOCOL       *UsbIo; >> +  EFI_DEVICE_PATH_PROTOCOL  *UsbRndisDataPath; >> +  EFI_DEVICE_PATH_PROTOCOL  *UsbCdcDataPath; >> + >> +  // Find the parent RNDIS and update the UsbIo for the CDC device >> +  Status = gBS->HandleProtocol ( >> +                  CdcHandle, >> +                  &gEfiDevicePathProtocolGuid, >> +                  (VOID **)&UsbCdcDataPath >> +                  ); >> + >> +  if (EFI_ERROR (Status)) { >> +    return Status; >> +  } >> + >> +  Status = gBS->LocateHandleBuffer ( >> +                  ByProtocol, >> +                  &gEfiUsbIoProtocolGuid, >> +                  NULL, >> +                  &HandleCount, >> +                  &HandleBuffer >> +                  ); >> +  if (EFI_ERROR (Status)) { >> +    return Status; >> +  } >> + >> +  for (Index = 0; Index < HandleCount; Index++) { >> +    Status = gBS->HandleProtocol ( >> +                    HandleBuffer[Index], >> +                    &gEfiUsbIoProtocolGuid, >> +                    (VOID **)&UsbIo >> +                    ); >> +    if (EFI_ERROR (Status)) { >> +      return Status; >> +    } >> + >> +    if (IsUsbRndis (UsbIo)) { >> +      Status = gBS->HandleProtocol ( >> +                      HandleBuffer[Index], >> +                      &gEfiDevicePathProtocolGuid, >> +                      (VOID **)&UsbRndisDataPath >> +                      ); >> +      if (EFI_ERROR (Status)) { >> +        DEBUG ((DEBUG_ERROR, "Usb Rndis DevicePath not found\n")); >> +        break; >> +      } >> + >> +      Status = IsSameDevice (UsbRndisDataPath, UsbCdcDataPath); >> + >> +      if (!EFI_ERROR (Status)) { >> +        *RndisHandle = HandleBuffer[Index]; >> +        *CdcUsbIo    = UsbIo; >> +        FreePool (HandleBuffer); >> +        return Status; >> +      } >> +    } >> +  }   // End of For loop >> + >> +  FreePool (HandleBuffer); >> + >> +  return EFI_NOT_FOUND; >> +} >> + >> +/** >> +  USB Rndis Driver Binding Support. >> + >> +  @param[in]  This                    Protocol instance pointer. >> +  @param[in]  ControllerHandle        Handle of device to test. >> +  @param[in]  RemainingDevicePath     Optional parameter use to pick >> a specific child >> +                                      device to start. >> + >> +  @retval EFI_SUCCESS                 This driver supports this device. >> +  @retval EFI_ALREADY_STARTED         This driver is already running >> on this device. >> +  @retval other                       This driver does not support >> this device. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +UsbRndisDriverSupported ( >> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This, >> +  IN EFI_HANDLE                   ControllerHandle, >> +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath >> +  ) >> +{ >> +  EFI_STATUS           Status; >> +  EFI_USB_IO_PROTOCOL  *UsbIo; >> + >> +  Status = gBS->OpenProtocol ( >> +                  ControllerHandle, >> +                  &gEfiUsbIoProtocolGuid, >> +                  (VOID **)&UsbIo, >> +                  This->DriverBindingHandle, >> +                  ControllerHandle, >> +                  EFI_OPEN_PROTOCOL_BY_DRIVER >> +                  ); >> +  if (EFI_ERROR (Status)) { >> +    return Status; >> +  } >> + >> +  Status = IsSupportedDevice (UsbIo) ? EFI_SUCCESS : EFI_UNSUPPORTED; >> + >> +  gBS->CloseProtocol ( >> +         ControllerHandle, >> +         &gEfiUsbIoProtocolGuid, >> +         This->DriverBindingHandle, >> +         ControllerHandle >> +         ); >> +  return Status; >> +} >> + >> +/** >> +  USB RNDIS Driver Binding Start. >> + >> +  @param[in]  This                    Protocol instance pointer. >> +  @param[in]  ControllerHandle        Handle of device to bind >> driver to. >> +  @param[in]  RemainingDevicePath     Optional parameter use to pick >> a specific child >> +                                      device to start. >> + >> +  @retval EFI_SUCCESS                 This driver is added to >> ControllerHandle >> +  @retval EFI_DEVICE_ERROR            This driver could not be >> started due to a device error >> +  @retval EFI_OUT_OF_RESOURCES        The driver could not install >> successfully due to a lack of resources. >> +  @retval other                       This driver does not support >> this device >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +UsbRndisDriverStart ( >> +  IN EFI_DRIVER_BINDING_PROTOCOL  *This, >> +  IN EFI_HANDLE                   ControllerHandle, >> +  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath >> +  ) >> +{ >> +  EFI_STATUS                    Status; >> +  USB_RNDIS_DEVICE              *UsbRndisDevice; >> +  EFI_DEVICE_PATH_PROTOCOL      *UsbEthPath; >> +  EFI_USB_IO_PROTOCOL           *UsbIo; >> +  EFI_USB_INTERFACE_DESCRIPTOR  Interface; >> +  EFI_HANDLE                    RndisHandle; >> + >> +  RndisHandle = ControllerHandle; >> + >> +  Status = gBS->OpenProtocol ( >> +                  ControllerHandle, >> +                  &gEfiUsbIoProtocolGuid, >> +                  (VOID **)&UsbIo, >> +                  This->DriverBindingHandle, >> +                  ControllerHandle, >> +                  EFI_OPEN_PROTOCOL_BY_DRIVER >> +                  ); >> +  if (EFI_ERROR (Status)) { >> +    return Status; >> +  } >> + >> +  Status = gBS->OpenProtocol ( >> +                  ControllerHandle, >> +                  &gEfiDevicePathProtocolGuid, >> +                  (VOID **)&UsbEthPath, >> +                  This->DriverBindingHandle, >> +                  ControllerHandle, >> +                  EFI_OPEN_PROTOCOL_BY_DRIVER >> +                  ); >> +  if (EFI_ERROR (Status)) { >> +    gBS->CloseProtocol ( >> +           ControllerHandle, >> +           &gEfiUsbIoProtocolGuid, >> +           This->DriverBindingHandle, >> +           ControllerHandle >> +           ); >> +    return Status; >> +  } >> + >> +  gBS->CloseProtocol ( >> +         ControllerHandle, >> +         &gEfiDevicePathProtocolGuid, >> +         This->DriverBindingHandle, >> +         ControllerHandle >> +         ); >> + >> +  // Controls come here for RNDIS and CDC. If it is CDC, check >> whether RNDIS is present on the same controller or not. >> +  if (IsUsbCdcData (UsbIo)) { >> +    DEBUG ((DEBUG_INFO, "Rndis CDCData interface found\n")); >> + >> +    // Find the parent RNDIS and update the UsbIo for the CDC device >> +    Status = UpdateRndisDevice ( >> +               UsbEthPath, >> +               &UsbRndisDevice >> +               ); >> + >> +    if (!EFI_ERROR (Status)) { >> +      DEBUG ((DEBUG_INFO, "Rndis Matching interface found\n")); >> +      UsbRndisDevice->UsbCdcDataHandle = ControllerHandle; >> +      UsbRndisDevice->UsbIoCdcData     = UsbIo; >> +      GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice); >> +      return Status; >> +    } else { >> +      // Check if RnDis exist >> +      Status = FindMatchingRndisDev ( >> +                 ControllerHandle, >> +                 &UsbIo, >> +                 &RndisHandle >> +                 ); >> + >> +      if (EFI_ERROR (Status)) { >> +        gBS->CloseProtocol ( >> +               ControllerHandle, >> +               &gEfiUsbIoProtocolGuid, >> +               This->DriverBindingHandle, >> +               ControllerHandle >> +               ); >> +        return Status; >> +      } >> +    } >> +  } >> + >> +  UsbRndisDevice = AllocateZeroPool (sizeof (USB_RNDIS_DEVICE)); >> + >> +  if (!UsbRndisDevice) { >> +    DEBUG ((DEBUG_ERROR, "AllocateZeroPool Fail\n")); >> + >> +    gBS->CloseProtocol ( >> +           ControllerHandle, >> +           &gEfiUsbIoProtocolGuid, >> +           This->DriverBindingHandle, >> +           ControllerHandle >> +           ); >> +    return EFI_OUT_OF_RESOURCES; >> +  } >> + >> +  Status = LoadAllDescriptor ( >> +             UsbIo, >> +             &UsbRndisDevice->Config >> +             ); >> +  if (EFI_ERROR (Status)) { >> +    DEBUG ((DEBUG_ERROR, "%a:LoadAllDescriptor status = %r\n", >> __FUNCTION__, Status)); >> +    gBS->CloseProtocol ( >> +           ControllerHandle, >> +           &gEfiUsbIoProtocolGuid, >> +           This->DriverBindingHandle, >> +           ControllerHandle >> +           ); >> +    FreePool (UsbRndisDevice); >> +    return Status; >> +  } >> + >> +  Status = UsbIo->UsbGetInterfaceDescriptor ( >> +                    UsbIo, >> +                    &Interface >> +                    ); >> +  if (EFI_ERROR (Status)) { >> +    DEBUG ((DEBUG_ERROR, "%a:UsbGetInterfaceDescriptor status = >> %r\n", __FUNCTION__, Status)); >> +    gBS->CloseProtocol ( >> +           ControllerHandle, >> +           &gEfiUsbIoProtocolGuid, >> +           This->DriverBindingHandle, >> +           ControllerHandle >> +           ); >> +    FreePool (UsbRndisDevice->Config); >> +    FreePool (UsbRndisDevice); >> +    return Status; >> +  } >> + >> +  UsbRndisDevice->Signature                          = >> USB_RNDIS_SIGNATURE; >> +  UsbRndisDevice->NumOfInterface                     = >> Interface.InterfaceNumber; >> +  UsbRndisDevice->UsbRndisHandle                     = RndisHandle; >> +  UsbRndisDevice->UsbCdcDataHandle                   = 0; >> +  UsbRndisDevice->UsbIo                              = UsbIo; >> +  UsbRndisDevice->UsbEth.UsbEthReceive               = >> RndisUndiReceive; >> +  UsbRndisDevice->UsbEth.UsbEthTransmit              = >> RndisUndiTransmit; >> +  UsbRndisDevice->UsbEth.UsbEthInterrupt             = >> UsbRndisInterrupt; >> +  UsbRndisDevice->UsbEth.UsbEthMacAddress            = >> GetUsbEthMacAddress; >> +  UsbRndisDevice->UsbEth.UsbEthMaxBulkSize           = UsbEthBulkSize; >> +  UsbRndisDevice->UsbEth.UsbHeaderFunDescriptor      = >> GetUsbHeaderFunDescriptor; >> +  UsbRndisDevice->UsbEth.UsbUnionFunDescriptor       = >> GetUsbUnionFunDescriptor; >> +  UsbRndisDevice->UsbEth.UsbEthFunDescriptor         = >> GetUsbRndisFunDescriptor; >> +  UsbRndisDevice->UsbEth.SetUsbEthMcastFilter        = >> SetUsbRndisMcastFilter; >> +  UsbRndisDevice->UsbEth.SetUsbEthPowerPatternFilter = >> SetUsbRndisPowerFilter; >> +  UsbRndisDevice->UsbEth.GetUsbEthPowerPatternFilter = >> GetUsbRndisPowerFilter; >> +  UsbRndisDevice->UsbEth.SetUsbEthPacketFilter       = >> SetUsbRndisPacketFilter; >> +  UsbRndisDevice->UsbEth.GetUsbEthStatistic          = >> GetRndisStatistic; >> + >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetState        = >> RndisDummyReturn; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStart           = >> RndisUndiStart; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStop            = >> RndisUndiStop; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetInitInfo     = >> RndisUndiGetInitInfo; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetConfigInfo   = >> RndisUndiGetConfigInfo; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiInitialize      = >> RndisUndiInitialize; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiReset           = >> RndisUndiReset; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiShutdown        = >> RndisUndiShutdown; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiInterruptEnable = >> RndisDummyReturn; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiReceiveFilter   = >> RndisUndiReceiveFilter; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStationAddress  = >> RndisDummyReturn; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStatistics      = NULL; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiMcastIp2Mac     = >> RndisDummyReturn; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiNvData          = >> RndisDummyReturn; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetStatus       = >> RndisUndiGetStatus; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiFillHeader      = >> RndisDummyReturn; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiTransmit        = NULL; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiReceive         = NULL; >> + >> +  UsbRndisDevice->MaxTransferSize       = RNDIS_MAX_TRANSFER_SIZE; >> +  UsbRndisDevice->MaxPacketsPerTransfer = 1; >> +  UsbRndisDevice->PacketAlignmentFactor = 0; >> + >> +  InitializeListHead (&UsbRndisDevice->ReceivePacketList); >> + >> +  // This is a RNDIS interface. See whether CDC-DATA interface has >> already been connected or not >> +  FindMatchingCdcData (UsbRndisDevice); >> + >> +  if (UsbRndisDevice->UsbIoCdcData) { >> +    Status = gBS->InstallProtocolInterface ( >> +                    &ControllerHandle, >> +                    &gEdkIIUsbEthProtocolGuid, >> +                    EFI_NATIVE_INTERFACE, >> +                    &(UsbRndisDevice->UsbEth) >> +                    ); >> +    if (EFI_ERROR (Status)) { >> +      gBS->CloseProtocol ( >> +             ControllerHandle, >> +             &gEfiUsbIoProtocolGuid, >> +             This->DriverBindingHandle, >> +             ControllerHandle >> +             ); >> + >> +      FreePool (UsbRndisDevice->Config); >> +      FreePool (UsbRndisDevice); >> +      return Status; >> +    } >> + >> +    GetEndpoint (UsbRndisDevice->UsbIo, UsbRndisDevice); >> + >> +    DEBUG ((DEBUG_INFO, "Rndis DeviceHandle %r\n", >> UsbRndisDevice->UsbRndisHandle)); >> +    DEBUG ((DEBUG_INFO, "CDC DeviceHandle %r\n", >> UsbRndisDevice->UsbCdcDataHandle)); >> +    return EFI_SUCCESS; >> +  } >> + >> +  FreePool (UsbRndisDevice->Config); >> +  FreePool (UsbRndisDevice); >> + >> +  return EFI_SUCCESS; >> +} >> + >> +/** >> +  CheckandStopRndisDevice >> + >> +  @param[in]  This                 Protocol instance pointer. >> +  @param[in]  ControllerHandle     Handle of device to bind driver to. >> + >> +  @retval EFI_SUCCESS          This driver is added to ControllerHandle >> +  @retval EFI_DEVICE_ERROR     This driver could not be started due >> to a device error >> +  @retval other                This driver does not support this device >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +CheckandStopRndisDevice ( >> +  IN  EFI_DRIVER_BINDING_PROTOCOL  *This, >> +  IN  EFI_HANDLE                   ControllerHandle >> +  ) >> +{ >> +  EFI_STATUS           Status; >> +  EFI_USB_IO_PROTOCOL  *UsbIo; >> + >> +  Status = gBS->OpenProtocol ( >> +                  ControllerHandle, >> +                  &gEfiUsbIoProtocolGuid, >> +                  (VOID **)&UsbIo, >> +                  This->DriverBindingHandle, >> +                  ControllerHandle, >> +                  EFI_OPEN_PROTOCOL_GET_PROTOCOL >> +                  ); >> +  if (EFI_ERROR (Status)) { >> +    return Status; >> +  } >> + >> +  if (IsUsbRndis (UsbIo)) { >> +    Status = gBS->CloseProtocol ( >> +                    ControllerHandle, >> +                    &gEfiUsbIoProtocolGuid, >> +                    This->DriverBindingHandle, >> +                    ControllerHandle >> +                    ); >> +    DEBUG ((DEBUG_ERROR, "Rndis ControllerHandle Stop %r\n", Status)); >> +    return Status; >> +  } >> + >> +  return EFI_UNSUPPORTED; >> +} >> + >> +/** >> +  USB Rndis Driver Binding Stop. >> + >> +  @param[in]  This                  Protocol instance pointer. >> +  @param[in]  ControllerHandle      Handle of device to stop driver on >> +  @param[in]  NumberOfChildren      Number of Handles in >> ChildHandleBuffer. If number of >> +                                    children is zero stop the entire >> bus driver. >> +  @param[in]  ChildHandleBuffer     List of Child Handles to Stop. >> + >> +  @retval EFI_SUCCESS               This driver is removed >> ControllerHandle >> +  @retval other                     This driver was not removed from >> this device >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +UsbRndisDriverStop ( >> +  IN  EFI_DRIVER_BINDING_PROTOCOL  *This, >> +  IN  EFI_HANDLE                   ControllerHandle, >> +  IN  UINTN                        NumberOfChildren, >> +  IN  EFI_HANDLE                   *ChildHandleBuffer >> +  ) >> +{ >> +  EFI_STATUS                   Status; >> +  EDKII_USB_ETHERNET_PROTOCOL  *UsbEthProtocol; >> +  USB_RNDIS_DEVICE             *UsbRndisDevice; >> + >> +  DEBUG ((DEBUG_INFO, "UsbRndisDriverStop ControllerHandle %lx\n", >> ControllerHandle)); >> + >> +  Status = gBS->OpenProtocol ( >> +                  ControllerHandle, >> +                  &gEdkIIUsbEthProtocolGuid, >> +                  (VOID **)&UsbEthProtocol, >> +                  This->DriverBindingHandle, >> +                  ControllerHandle, >> +                  EFI_OPEN_PROTOCOL_GET_PROTOCOL >> +                  ); >> +  if (EFI_ERROR (Status)) { >> +    Status = CheckandStopRndisDevice (This, ControllerHandle); >> +    return Status; >> +  } >> + >> +  UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (UsbEthProtocol); >> + >> +  Status = gBS->CloseProtocol ( >> +                  UsbRndisDevice->UsbCdcDataHandle, >> +                  &gEfiUsbIoProtocolGuid, >> +                  This->DriverBindingHandle, >> +                  UsbRndisDevice->UsbCdcDataHandle >> +                  ); >> +  if (EFI_ERROR (Status)) { >> +    DEBUG ((DEBUG_ERROR, "%a:CloseProtocol status = %r\n", >> __FUNCTION__, Status)); >> +  } >> + >> +  Status = gBS->UninstallProtocolInterface ( >> +                  ControllerHandle, >> +                  &gEdkIIUsbEthProtocolGuid, >> +                  UsbEthProtocol >> +                  ); >> +  if (EFI_ERROR (Status)) { >> +    return Status; >> +  } >> + >> +  Status = gBS->CloseProtocol ( >> +                  ControllerHandle, >> +                  &gEfiUsbIoProtocolGuid, >> +                  This->DriverBindingHandle, >> +                  ControllerHandle >> +                  ); >> + >> +  FreePool (UsbRndisDevice->Config); >> +  FreePool (UsbRndisDevice); >> + >> +  DEBUG ((DEBUG_INFO, "UsbRndisDriverStop %r\n", Status)); >> +  return Status; >> +} >> + >> +/** >> +  Entrypoint of RNDIS Driver. >> + >> +  This function is the entrypoint of RNDIS Driver. It installs >> Driver Binding >> +  Protocols together with Component Name Protocols. >> + >> +  @param[in]  ImageHandle       The firmware allocated handle for >> the EFI image. >> +  @param[in]  SystemTable       A pointer to the EFI System Table. >> + >> +  @retval EFI_SUCCESS           The entry point is executed >> successfully. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +UsbRndisEntry ( >> +  IN EFI_HANDLE        ImageHandle, >> +  IN EFI_SYSTEM_TABLE  *SystemTable >> +  ) >> +{ >> +  gUsbRndisDriverBinding.DriverBindingHandle = ImageHandle; >> +  gUsbRndisDriverBinding.ImageHandle         = ImageHandle; >> + >> +  return gBS->InstallMultipleProtocolInterfaces ( >> + &gUsbRndisDriverBinding.DriverBindingHandle, >> +                &gEfiDriverBindingProtocolGuid, >> +                &gUsbRndisDriverBinding, >> +                &gEfiComponentName2ProtocolGuid, >> +                &gUsbRndisComponentName2, >> +                NULL >> +                ); >> +} >> diff --git a/UsbNetworkPkg/UsbRndis/UsbRndisFunction.c >> b/UsbNetworkPkg/UsbRndis/UsbRndisFunction.c >> new file mode 100644 >> index 000000000000..e3fe737cdef1 >> --- /dev/null >> +++ b/UsbNetworkPkg/UsbRndis/UsbRndisFunction.c >> @@ -0,0 +1,1718 @@ >> +/** @file >> +  This file contains code for USB Ethernet descriptor >> +  and specific requests implement. >> + >> +  Copyright (c) 2023, American Megatrends International LLC. All >> rights reserved.
>> +  SPDX-License-Identifier: BSD-2-Clause-Patent >> +**/ >> + >> +#include "UsbRndis.h" >> + >> +UINT16  gStopBulkInCnt  = 0; >> +UINT16  gBlockBulkInCnt = 0; >> + >> +/** >> +  Load All of device descriptor. >> + >> +  @param[in]  UsbIo                 A pointer to the >> EFI_USB_IO_PROTOCOL instance. >> +  @param[out] ConfigDesc            A pointer to the configuration >> descriptor. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_OUT_OF_RESOURCES  The request could not be completed >> because the >> +                                buffer specified by DescriptorLength >> and Descriptor >> +                                is not large enough to hold the >> result of the request. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. The transfer >> +                                status is returned in Status. >> +**/ >> +EFI_STATUS >> +LoadAllDescriptor ( >> +  IN  EFI_USB_IO_PROTOCOL        *UsbIo, >> +  OUT EFI_USB_CONFIG_DESCRIPTOR  **ConfigDesc >> +  ) >> +{ >> +  EFI_STATUS                 Status; >> +  UINT32                     TransStatus; >> +  EFI_USB_CONFIG_DESCRIPTOR  Tmp; >> + >> +  Status = UsbIo->UsbGetConfigDescriptor (UsbIo, &Tmp); >> +  if (EFI_ERROR (Status)) { >> +    DEBUG ((DEBUG_ERROR, "%a:UsbGetConfigDescriptor status = %r\n", >> __FUNCTION__, Status)); >> +    return Status; >> +  } >> + >> +  Status = gBS->AllocatePool ( >> +                  EfiBootServicesData, >> +                  Tmp.TotalLength, >> +                  (VOID **)ConfigDesc >> +                  ); >> +  if (EFI_ERROR (Status)) { >> +    DEBUG ((DEBUG_ERROR, "%a: AllocatePool status = %r\n", >> __FUNCTION__, Status)); >> +    return Status; >> +  } >> + >> +  Status = UsbGetDescriptor ( >> +             UsbIo, >> +             USB_DESC_TYPE_CONFIG << 8 | (Tmp.ConfigurationValue - >> 1),                 // zero based >> +             0, >> +             Tmp.TotalLength, >> +             *ConfigDesc, >> +             &TransStatus >> +             ); >> +  return Status; >> +} >> + >> +/** >> +  Returns pointer to the next descriptor for the pack of USB >> descriptors >> +  located in continues memory segment >> + >> +  @param[in]      Desc   A pointer to the CONFIG_DESCRIPTOR instance. >> +  @param[in, out] Offset A pointer to the sum of descriptor length. >> + >> +  @retval TRUE   The request executed successfully. >> +  @retval FALSE  No next descriptor. >> + >> +**/ >> +BOOLEAN >> +NextDescriptor ( >> +  IN      EFI_USB_CONFIG_DESCRIPTOR  *Desc, >> +  IN OUT  UINTN                      *Offset >> +  ) >> +{ >> +  if ((Desc == NULL) || (*Offset >= Desc->TotalLength)) { >> +    return FALSE; >> +  } >> + >> +  if (((EFI_USB_CONFIG_DESCRIPTOR *)((char *)Desc+*Offset))->Length >> == 0) { >> +    return FALSE; >> +  } >> + >> +  *Offset += ((EFI_USB_CONFIG_DESCRIPTOR *)((char >> *)Desc+*Offset))->Length; >> +  if ( *Offset >= Desc->TotalLength ) { >> +    return FALSE; >> +  } >> + >> +  return TRUE; >> +} >> + >> +/** >> +  Read Function descriptor >> + >> +  @param[in]  Config             A pointer to all of configuration. >> +  @param[in]  FunDescriptorType  USB CDC class descriptor SubType. >> +  @param[out] DataBuffer         A pointer to the Data of >> corresponding to device capability. >> + >> +  @retval EFI_SUCCESS        The device capability descriptor was >> retrieved >> +                             successfully. >> +  @retval EFI_UNSUPPORTED    No supported. >> +  @retval EFI_NOT_FOUND      The device capability descriptor was >> not found. >> + >> +**/ >> +EFI_STATUS >> +GetFunctionalDescriptor ( >> +  IN  EFI_USB_CONFIG_DESCRIPTOR  *Config, >> +  IN  UINT8                      FunDescriptorType, >> +  OUT VOID                       *DataBuffer >> +  ) >> +{ >> +  EFI_STATUS                    Status; >> +  UINTN                         Offset; >> +  EFI_USB_INTERFACE_DESCRIPTOR  *Interface; >> + >> +  Status = EFI_NOT_FOUND; >> + >> +  for (Offset = 0; NextDescriptor (Config, &Offset);) { >> +    Interface = (EFI_USB_INTERFACE_DESCRIPTOR *)((UINT8 *)Config + >> Offset); >> +    if (Interface->DescriptorType == CS_INTERFACE) { >> +      if (((USB_HEADER_FUN_DESCRIPTOR >> *)Interface)->DescriptorSubtype == FunDescriptorType) { >> +        switch (FunDescriptorType) { >> +          case HEADER_FUN_DESCRIPTOR: >> +            CopyMem ( >> +              DataBuffer, >> +              (USB_HEADER_FUN_DESCRIPTOR *)Interface, >> +              sizeof (USB_HEADER_FUN_DESCRIPTOR) >> +              ); >> +            return EFI_SUCCESS; >> +          case UNION_FUN_DESCRIPTOR: >> +            CopyMem ( >> +              DataBuffer, >> +              (USB_UNION_FUN_DESCRIPTOR *)Interface, >> +              ((USB_UNION_FUN_DESCRIPTOR *)Interface)->FunctionLength >> +              ); >> +            return EFI_SUCCESS; >> +          case ETHERNET_FUN_DESCRIPTOR: >> +            CopyMem ( >> +              DataBuffer, >> +              (USB_ETHERNET_FUN_DESCRIPTOR *)Interface, >> +              sizeof (USB_ETHERNET_FUN_DESCRIPTOR) >> +              ); >> +            return EFI_SUCCESS; >> +          default: >> +            Status = EFI_UNSUPPORTED; >> +            break; >> +        } >> +      } >> +    } >> +  } >> + >> +  return Status; >> +} >> + >> +/** >> +  Get USB Ethernet IO endpoint and USB CDC data IO endpoint. >> + >> +  @param[in]      UsbIo           A pointer to the >> EFI_USB_IO_PROTOCOL instance. >> +  @param[in, out] UsbRndisDevice  A pointer to the USB_RNDIS_DEVICE >> instance. >> + >> +**/ >> +VOID >> +GetEndpoint ( >> +  IN      EFI_USB_IO_PROTOCOL  *UsbIo, >> +  IN OUT  USB_RNDIS_DEVICE     *UsbRndisDevice >> +  ) >> +{ >> +  EFI_STATUS                    Status; >> +  UINT8                         Index; >> +  UINT32                        Result; >> +  EFI_USB_INTERFACE_DESCRIPTOR  Interface; >> +  EFI_USB_ENDPOINT_DESCRIPTOR   Endpoint; >> + >> +  Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> +  if (EFI_ERROR (Status)) { >> +    DEBUG ((DEBUG_ERROR, "%a:UsbGetInterfaceDescriptor status = >> %r\n", __FUNCTION__, Status)); >> +    return; >> +  } >> + >> +  if (Interface.NumEndpoints == 0 ) { >> +    Status = UsbSetInterface (UsbIo, 1, 0, &Result); >> +    if (EFI_ERROR (Status)) { >> +      DEBUG ((DEBUG_ERROR, "%a:UsbSetInterface status = %r\n", >> __FUNCTION__, Status)); >> +      return; >> +    } >> + >> +    Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> +    if (EFI_ERROR (Status)) { >> +      DEBUG ((DEBUG_ERROR, "%a:UsbGetInterfaceDescriptor status = >> %r\n", __FUNCTION__, Status)); >> +      return; >> +    } >> +  } >> + >> +  for (Index = 0; Index < Interface.NumEndpoints; Index++) { >> +    Status = UsbIo->UsbGetEndpointDescriptor (UsbIo, Index, &Endpoint); >> +    if (EFI_ERROR (Status)) { >> +      DEBUG ((DEBUG_ERROR, "%a:UsbGetEndpointDescriptor status = >> %r\n", __FUNCTION__, Status)); >> +      return; >> +    } >> + >> +    switch ((Endpoint.Attributes & (BIT0 | BIT1))) { >> +      case USB_ENDPOINT_BULK: >> +        if (Endpoint.EndpointAddress & BIT7) { >> +          UsbRndisDevice->BulkInEndpoint = Endpoint.EndpointAddress; >> +        } else { >> +          UsbRndisDevice->BulkOutEndpoint = Endpoint.EndpointAddress; >> +        } >> + >> +        break; >> +      case USB_ENDPOINT_INTERRUPT: >> +        UsbRndisDevice->InterrupEndpoint = Endpoint.EndpointAddress; >> +        break; >> +    } >> +  } >> +} >> + >> +/** >> +  Async USB transfer callback routine. >> + >> +  @param[in]  Data            Data received or sent via the USB >> Asynchronous Transfer, if the >> +                              transfer completed successfully. >> +  @param[in]  DataLength      The length of Data received or sent >> via the Asynchronous >> +                              Transfer, if transfer successfully >> completes. >> +  @param[in]  Context         Data passed from >> UsbAsyncInterruptTransfer() request. >> +  @param[in]  Status          Indicates the result of the >> asynchronous transfer. >> + >> +  @retval EFI_SUCCESS           The asynchronous USB transfer >> request has been successfully executed. >> +  @retval EFI_DEVICE_ERROR      The asynchronous USB transfer >> request failed. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +InterruptCallback ( >> +  IN  VOID    *Data, >> +  IN  UINTN   DataLength, >> +  IN  VOID    *Context, >> +  IN  UINT32  Status >> +  ) >> +{ >> +  if ((Data == NULL) || (Context == NULL)) { >> +    return EFI_INVALID_PARAMETER; >> +  } >> + >> +  if (((EFI_USB_DEVICE_REQUEST *)Data)->Request == 0) { >> +    CopyMem ( >> +      (EFI_USB_DEVICE_REQUEST *)Context, >> +      (EFI_USB_DEVICE_REQUEST *)Data, >> +      sizeof (EFI_USB_DEVICE_REQUEST) >> +      ); >> +  } >> + >> +  return EFI_SUCCESS; >> +} >> + >> +/** >> +  This function is used to manage a USB device with an interrupt >> transfer pipe. >> + >> +  @param[in]  This              A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> +  @param[in]  IsNewTransfer     If TRUE, a new transfer will be >> submitted to USB controller. If >> +                                FALSE, the interrupt transfer is >> deleted from the device's interrupt >> +                                transfer queue. >> +  @param[in]  PollingInterval   Indicates the periodic rate, in >> milliseconds, that the transfer is to be >> +                                executed.This parameter is required >> when IsNewTransfer is TRUE. The >> +                                value must be between 1 to 255, >> otherwise EFI_INVALID_PARAMETER is returned. >> +                                The units are in milliseconds. >> +  @param[in]  Request           A pointer to the >> EFI_USB_DEVICE_REQUEST data. >> + >> +  @retval EFI_SUCCESS           The asynchronous USB transfer >> request transfer has been successfully executed. >> +  @retval EFI_DEVICE_ERROR      The asynchronous USB transfer >> request failed. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +UsbRndisInterrupt ( >> +  IN EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  IN BOOLEAN                      IsNewTransfer, >> +  IN UINTN                        PollingInterval, >> +  IN EFI_USB_DEVICE_REQUEST       *Requst >> +  ) >> +{ >> +  EFI_STATUS        Status; >> +  USB_RNDIS_DEVICE  *UsbRndisDevice; >> +  UINTN             DataLength; >> + >> +  UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> +  DataLength     = 0; >> + >> +  if (IsNewTransfer == TRUE) { >> +    DataLength = sizeof (EFI_USB_DEVICE_REQUEST) + sizeof >> (USB_CONNECT_SPEED_CHANGE); >> +    Status     = UsbRndisDevice->UsbIo->UsbAsyncInterruptTransfer ( >> + UsbRndisDevice->UsbIo, >> + UsbRndisDevice->InterrupEndpoint, >> +                                          IsNewTransfer, >> +                                          PollingInterval, >> +                                          DataLength, >> +                                          InterruptCallback, >> +                                          Requst >> +                                          ); >> + >> +    if (Status == EFI_INVALID_PARAMETER) { >> +      // Because of Stacked AsyncInterrupt request are not supported >> +      Status = UsbRndisDevice->UsbIo->UsbAsyncInterruptTransfer ( >> + UsbRndisDevice->UsbIo, >> + UsbRndisDevice->InterrupEndpoint, >> +                                        0, >> +                                        0, >> +                                        0, >> +                                        NULL, >> +                                        NULL >> +                                        ); >> +    } >> +  } else { >> +    Status = UsbRndisDevice->UsbIo->UsbAsyncInterruptTransfer ( >> +                                      UsbRndisDevice->UsbIo, >> + UsbRndisDevice->InterrupEndpoint, >> +                                      IsNewTransfer, >> +                                      0, >> +                                      0, >> +                                      NULL, >> +                                      NULL >> +                                      ); >> +  } >> + >> +  return Status; >> +} >> + >> +/** >> +  This function is used to read USB interrupt transfer before the >> response RNDIS message. >> + >> +  @param[in]  This              A pointer to the USB_RNDIS_DEVICE >> instance. >> + >> +  @retval EFI_SUCCESS           The USB interrupt transfer has been >> successfully executed. >> +  @retval EFI_DEVICE_ERROR      The USB interrupt transfer failed. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +ReadRndisResponseInterrupt ( >> +  IN USB_RNDIS_DEVICE  *UsbRndisDevice >> +  ) >> +{ >> +  EFI_STATUS  Status; >> +  UINT32      Data[2]; >> +  UINT32      UsbStatus; >> +  UINTN       DataLength; >> + >> +  DataLength = 8; >> + >> +  ZeroMem (Data, sizeof (Data)); >> + >> +  Status = UsbRndisDevice->UsbIo->UsbSyncInterruptTransfer ( >> +                                    UsbRndisDevice->UsbIo, >> + UsbRndisDevice->InterrupEndpoint, >> +                                    &Data, >> +                                    &DataLength, >> +                                    0x20, >> +                                    &UsbStatus >> +                                    ); >> + >> +  return Status; >> +} >> + >> +/** >> +  Retrieves the USB Ethernet Mac Address. >> + >> +  @param[in]  This          A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> +  @param[out] MacAddress    A pointer to the caller allocated USB >> Ethernet Mac Address. >> + >> +  @retval EFI_SUCCESS           The USB Header Functional descriptor >> was retrieved successfully. >> +  @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> +  @retval EFI_NOT_FOUND         The USB Header Functional descriptor >> was not found. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +GetUsbEthMacAddress ( >> +  IN  EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  OUT EFI_MAC_ADDRESS              *MacAddress >> +  ) >> +{ >> +  EFI_STATUS                   Status; >> +  USB_RNDIS_DEVICE             *UsbRndisDevice; >> +  USB_ETHERNET_FUN_DESCRIPTOR  UsbEthDescriptor; >> +  CHAR16                       *Data; >> +  CHAR16                       *DataPtr; >> +  CHAR16                       TmpStr[1]; >> +  UINT8                        Index; >> +  UINT8                        Hi; >> +  UINT8                        Low; >> + >> +  REMOTE_NDIS_QUERY_MAC_MSG    RndisQueryMsg; >> +  REMOTE_NDIS_QUERY_MAC_CMPLT  RndisQueryMsgCmplt; >> + >> +  UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> + >> +  ZeroMem (&RndisQueryMsg, sizeof (REMOTE_NDIS_QUERY_MAC_MSG)); >> +  ZeroMem (&RndisQueryMsgCmplt, sizeof (REMOTE_NDIS_QUERY_MAC_CMPLT)); >> + >> +  RndisQueryMsg.QueryMsg.MessageType   = RNDIS_QUERY_MSG; >> +  RndisQueryMsg.QueryMsg.MessageLength = sizeof >> (REMOTE_NDIS_QUERY_MAC_MSG); >> +  RndisQueryMsg.QueryMsg.RequestID     = UsbRndisDevice->RequestId; >> +  RndisQueryMsg.QueryMsg.Oid           = OID_802_3_CURRENT_ADDRESS; >> + >> +  RndisQueryMsgCmplt.QueryCmplt.MessageType   = RNDIS_QUERY_CMPLT; >> +  RndisQueryMsgCmplt.QueryCmplt.MessageLength = sizeof >> (REMOTE_NDIS_QUERY_MAC_CMPLT); >> + >> +  Status = RndisControlMsg ( >> +             UsbRndisDevice, >> +             (REMOTE_NDIS_MSG_HEADER *)&RndisQueryMsg, >> +             (REMOTE_NDIS_MSG_HEADER *)&RndisQueryMsgCmplt >> +             ); >> +  if (!EFI_ERROR (Status)) { >> +    DEBUG ((DEBUG_INFO, "Success to get Mac address from RNDIS >> message.\n")); >> +    for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> +      MacAddress->Addr[Index] = RndisQueryMsgCmplt.Addr[Index]; >> +    } >> + >> +    UsbRndisDevice->RequestId++; >> +    return Status; >> +  } >> + >> +  // If it is not support the OID_802_3_CURRENT_ADDRESS. >> +  // To check USB Ethernet functional Descriptor >> +  Status = This->UsbEthFunDescriptor (This, &UsbEthDescriptor); >> +  if (EFI_ERROR (Status)) { >> +    DEBUG ((DEBUG_ERROR, "%a:UsbEthFunDescriptor status = %r\n", >> __FUNCTION__, Status)); >> +    return Status; >> +  } >> + >> +  Status = UsbRndisDevice->UsbIo->UsbGetStringDescriptor ( >> +                                    UsbRndisDevice->UsbIo, >> + 0x409,                       // English-US Language ID >> + UsbEthDescriptor.MacAddress, >> +                                    &Data >> +                                    ); >> +  if (EFI_ERROR (Status)) { >> +    DEBUG ((DEBUG_ERROR, "%a:UsbGetStringDescriptor status = %r\n", >> __FUNCTION__, Status)); >> +    return Status; >> +  } >> + >> +  DataPtr = Data; >> +  for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> +    CopyMem (TmpStr, DataPtr, sizeof (CHAR16)); >> +    DataPtr++; >> +    Hi = (UINT8)StrHexToUintn (TmpStr); >> +    CopyMem (TmpStr, DataPtr, sizeof (CHAR16)); >> +    DataPtr++; >> +    Low                     = (UINT8)StrHexToUintn (TmpStr); >> +    MacAddress->Addr[Index] = (Hi << 4) | Low; >> +  } >> + >> +  return Status; >> +} >> + >> +/** >> +  Retrieves the USB Ethernet Bulk transfer data size. >> + >> +  @param[in]  This          A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> +  @param[out] BulkSize      A pointer to the Bulk transfer data size. >> + >> +  @retval EFI_SUCCESS       The bulk transfer data size was >> retrieved successfully. >> +  @retval other             Failed to retrieve the bulk transfer >> data size. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +UsbEthBulkSize ( >> +  IN  EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  OUT UINTN                        *BulkSize >> +  ) >> +{ >> +  EFI_STATUS                   Status; >> +  USB_ETHERNET_FUN_DESCRIPTOR  UsbEthFunDescriptor; >> +  USB_RNDIS_DEVICE             *UsbRndisDevice; >> + >> +  REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_MSG    RndisQueryMsg; >> +  REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_CMPLT  RndisQueryMsgCmplt; >> + >> +  UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> + >> +  ZeroMem (&RndisQueryMsg, sizeof >> (REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_MSG)); >> +  ZeroMem (&RndisQueryMsgCmplt, sizeof >> (REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_CMPLT)); >> + >> +  RndisQueryMsg.QueryMsg.MessageType   = RNDIS_QUERY_MSG; >> +  RndisQueryMsg.QueryMsg.MessageLength = sizeof >> (REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_MSG); >> +  RndisQueryMsg.QueryMsg.RequestID     = UsbRndisDevice->RequestId; >> +  RndisQueryMsg.QueryMsg.Oid           = OID_GEN_MAXIMUM_TOTAL_SIZE; >> + >> +  RndisQueryMsgCmplt.QueryCmplt.MessageType   = RNDIS_QUERY_CMPLT; >> +  RndisQueryMsgCmplt.QueryCmplt.MessageLength = sizeof >> (REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_CMPLT); >> + >> +  Status = RndisControlMsg ( >> +             UsbRndisDevice, >> +             (REMOTE_NDIS_MSG_HEADER *)&RndisQueryMsg, >> +             (REMOTE_NDIS_MSG_HEADER *)&RndisQueryMsgCmplt >> +             ); >> +  if (!EFI_ERROR (Status)) { >> +    DEBUG ((DEBUG_INFO, "Success to get Max Total size : %X \n", >> RndisQueryMsgCmplt.MaxTotalSize)); >> +    *BulkSize = RndisQueryMsgCmplt.MaxTotalSize; >> +    UsbRndisDevice->RequestId++; >> +    return Status; >> +  } >> + >> +  Status = This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor); >> +  if (EFI_ERROR (Status)) { >> +    return Status; >> +  } >> + >> +  *BulkSize = (UINTN)UsbEthFunDescriptor.MaxSegmentSize; >> +  return Status; >> +} >> + >> +/** >> +  Retrieves the USB Header functional Descriptor. >> + >> +  @param[in]  This                   A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> +  @param[out] UsbHeaderFunDescriptor A pointer to the caller >> allocated USB Header Functional Descriptor. >> + >> +  @retval EFI_SUCCESS           The USB Header Functional descriptor >> was retrieved successfully. >> +  @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> +  @retval EFI_NOT_FOUND         The USB Header Functional descriptor >> was not found. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +GetUsbHeaderFunDescriptor ( >> +  IN  EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  OUT USB_HEADER_FUN_DESCRIPTOR    *UsbHeaderFunDescriptor >> +  ) >> +{ >> +  EFI_STATUS        Status; >> +  USB_RNDIS_DEVICE  *UsbRndisDevice; >> + >> +  UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> + >> +  if (UsbHeaderFunDescriptor == NULL) { >> +    return EFI_INVALID_PARAMETER; >> +  } >> + >> +  Status = GetFunctionalDescriptor ( >> +             UsbRndisDevice->Config, >> +             HEADER_FUN_DESCRIPTOR, >> +             UsbHeaderFunDescriptor >> +             ); >> +  return Status; >> +} >> + >> +/** >> +  Retrieves the USB Union functional Descriptor. >> + >> +  @param[in]  This                   A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> +  @param[out] UsbUnionFunDescriptor  A pointer to the caller >> allocated USB Union Functional Descriptor. >> + >> +  @retval EFI_SUCCESS            The USB Union Functional descriptor >> was retrieved successfully. >> +  @retval EFI_INVALID_PARAMETER  UsbUnionFunDescriptor is NULL. >> +  @retval EFI_NOT_FOUND          The USB Union Functional descriptor >> was not found. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +GetUsbUnionFunDescriptor ( >> +  IN  EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  OUT USB_UNION_FUN_DESCRIPTOR     *UsbUnionFunDescriptor >> +  ) >> +{ >> +  EFI_STATUS        Status; >> +  USB_RNDIS_DEVICE  *UsbRndisDevice; >> + >> +  UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> + >> +  if (UsbUnionFunDescriptor == NULL) { >> +    return EFI_INVALID_PARAMETER; >> +  } >> + >> +  Status = GetFunctionalDescriptor ( >> +             UsbRndisDevice->Config, >> +             UNION_FUN_DESCRIPTOR, >> +             UsbUnionFunDescriptor >> +             ); >> +  return Status; >> +} >> + >> +/** >> +  Retrieves the USB Ethernet functional Descriptor. >> + >> +  This function get the Mac Address, Ethernet statistics, maximum >> segment size, >> +  number of multicast filters, and number of pattern filters from >> Ethernet >> +  functional Descriptor. >> + >> +  @param[in]  This                   A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> +  @param[out] UsbEthFunDescriptor    A pointer to the caller >> allocated USB Ethernet Functional Descriptor. >> + >> +  @retval EFI_SUCCESS            The USB Ethernet Functional >> descriptor was retrieved successfully. >> +  @retval EFI_INVALID_PARAMETER  UsbEthFunDescriptor is NULL. >> +  @retval EFI_NOT_FOUND          The USB Ethernet Functional >> descriptor was not found. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +GetUsbRndisFunDescriptor ( >> +  IN  EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  OUT USB_ETHERNET_FUN_DESCRIPTOR  *UsbEthFunDescriptor >> +  ) >> +{ >> +  EFI_STATUS        Status; >> +  USB_RNDIS_DEVICE  *UsbRndisDevice; >> + >> +  UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> + >> +  if (UsbEthFunDescriptor == NULL) { >> +    return EFI_INVALID_PARAMETER; >> +  } >> + >> +  Status = GetFunctionalDescriptor ( >> +             UsbRndisDevice->Config, >> +             ETHERNET_FUN_DESCRIPTOR, >> +             UsbEthFunDescriptor >> +             ); >> +  return Status; >> +} >> + >> +/** >> +  This request sets the Ethernet device multicast filters as >> specified in the >> +  sequential list of 48 bit Ethernet multicast addresses. >> + >> +  @param[in]  This                   A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> +  @param[in]  Value                  Number of filters. >> +  @param[in]  McastAddr              A pointer to the value of the >> multicast addresses. >> + >> +  @retval EFI_SUCCESS            The request executed successfully. >> +  @retval EFI_TIMEOUT            A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR       The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER  One of the parameters has an >> invalid value. >> +  @retval EFI_UNSUPPORTED        Not supported. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +SetUsbRndisMcastFilter ( >> +  IN EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  IN UINT16                       Value, >> +  IN VOID                         *McastAddr >> +  ) >> +{ >> +  EFI_STATUS                   Status; >> +  EFI_USB_DEVICE_REQUEST       Request; >> +  UINT32                       TransStatus; >> +  USB_ETHERNET_FUN_DESCRIPTOR  UsbEthFunDescriptor; >> +  USB_RNDIS_DEVICE             *UsbRndisDevice; >> + >> +  UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> + >> +  Status = This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor); >> +  if (EFI_ERROR (Status)) { >> +    return Status; >> +  } >> + >> +  if ((UsbEthFunDescriptor.NumberMcFilters << 1) == 0) { >> +    return EFI_UNSUPPORTED; >> +  } >> + >> +  Request.RequestType = USB_ETHERNET_SET_REQ_TYPE; >> +  Request.Request     = SET_ETH_MULTICAST_FILTERS_REQ; >> +  Request.Value       = Value; >> +  Request.Index       = UsbRndisDevice->NumOfInterface; >> +  Request.Length      = Value * 6; >> + >> +  return UsbRndisDevice->UsbIo->UsbControlTransfer ( >> +                                  UsbRndisDevice->UsbIo, >> +                                  &Request, >> +                                  EfiUsbDataOut, >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> +                                  McastAddr, >> +                                  Request.Length, >> +                                  &TransStatus >> +                                  ); >> +} >> + >> +/** >> +  This request sets up the specified Ethernet power management >> pattern filter as >> +  described in the data structure. >> + >> +  @param[in]  This                  A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> +  @param[in]  Value                 Number of filters. >> +  @param[in]  Length                Size of the power management >> pattern filter data. >> +  @param[in]  PatternFilter         A pointer to the power >> management pattern filter structure. >> + >> +  @retval EFI_SUCCESS            The request executed successfully. >> +  @retval EFI_TIMEOUT            A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR       The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER  One of the parameters has an >> invalid value. >> +  @retval EFI_UNSUPPORTED        Not supported. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +SetUsbRndisPowerFilter ( >> +  IN EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  IN UINT16                       Value, >> +  IN UINT16                       Length, >> +  IN VOID                         *PatternFilter >> +  ) >> +{ >> +  EFI_USB_DEVICE_REQUEST  Request; >> +  UINT32                  TransStatus; >> +  USB_RNDIS_DEVICE        *UsbRndisDevice; >> + >> +  UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> + >> +  Request.RequestType = USB_ETHERNET_SET_REQ_TYPE; >> +  Request.Request     = SET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ; >> +  Request.Value       = Value; >> +  Request.Index       = UsbRndisDevice->NumOfInterface; >> +  Request.Length      = Length; >> + >> +  return UsbRndisDevice->UsbIo->UsbControlTransfer ( >> +                                  UsbRndisDevice->UsbIo, >> +                                  &Request, >> +                                  EfiUsbDataOut, >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> +                                  PatternFilter, >> +                                  Length, >> +                                  &TransStatus >> +                                  ); >> +} >> + >> +/** >> +  This request retrieves the status of the specified Ethernet power >> management >> +  pattern filter from the device. >> + >> +  @param[in]  This                   A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> +  @param[in]  Value                  The filter number. >> +  @param[out] PatternActive          A pointer to the pattern active >> boolean. >> + >> +  @retval EFI_SUCCESS            The request executed successfully. >> +  @retval EFI_TIMEOUT            A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR       The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER  One of the parameters has an >> invalid value. >> +  @retval EFI_UNSUPPORTED        Not supported. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +GetUsbRndisPowerFilter ( >> +  IN  EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  IN  UINT16                       Value, >> +  OUT BOOLEAN                      *PatternActive >> +  ) >> +{ >> +  EFI_USB_DEVICE_REQUEST  Request; >> +  UINT32                  TransStatus; >> +  USB_RNDIS_DEVICE        *UsbRndisDevice; >> + >> +  UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> + >> +  Request.RequestType = USB_ETHERNET_GET_REQ_TYPE; >> +  Request.Request     = GET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ; >> +  Request.Value       = Value; >> +  Request.Index       = UsbRndisDevice->NumOfInterface; >> +  Request.Length      = USB_ETH_POWER_FILTER_LENGTH; >> + >> +  return UsbRndisDevice->UsbIo->UsbControlTransfer ( >> +                                  UsbRndisDevice->UsbIo, >> +                                  &Request, >> +                                  EfiUsbDataIn, >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> +                                  PatternActive, >> +                                  USB_ETH_POWER_FILTER_LENGTH, >> +                                  &TransStatus >> +                                  ); >> +} >> + >> +/** >> + >> +  Converts PXE filter settings to RNDIS values >> + >> +  @param[in]  Value      PXE filter data. >> +  @param[out] CdcFilter  A pointer to the Ethernet Packet Filter >> Bitmap value converted by PXE_OPFLAGS. >> + >> +**/ >> +VOID >> +ConvertFilter ( >> +  IN  UINT16  Value, >> +  OUT UINT16  *CdcFilter >> +  ) >> +{ >> +  UINT32                 Index; >> +  UINT32                 Count; >> +  static struct BIT_MAP  Table[] = { >> +    { PXE_OPFLAGS_RECEIVE_FILTER_UNICAST, >> NDIS_PACKET_TYPE_DIRECTED      }, >> +    { PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST, >> NDIS_PACKET_TYPE_BROADCAST     }, >> +    { PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST, >> NDIS_PACKET_TYPE_MULTICAST     }, >> +    { PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS, >> NDIS_PACKET_TYPE_PROMISCUOUS   }, >> +    { PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST, >> NDIS_PACKET_TYPE_ALL_MULTICAST }, >> +  }; >> + >> +  Count = sizeof (Table)/sizeof (Table[0]); >> + >> +  for (Index = 0; (Table[Index].Src != 0) && (Index < Count); >> Index++) { >> +    if (Table[Index].Src & Value) { >> +      *CdcFilter |= Table[Index].Dst; >> +    } >> +  } >> +} >> + >> +/** >> + >> +  Updates Filter settings on the device. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_STATUS >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +RndisUndiReceiveFilter ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ) >> +{ >> +  EFI_STATUS                   Status; >> +  UINT8                        *McastList; >> +  UINT8                        Count; >> +  UINT8                        Index1; >> +  UINT8                        Index2; >> +  UINT64                       CpbAddr; >> +  UINT32                       CpbSize; >> +  UINT16                       SetFilter; >> +  PXE_CPB_RECEIVE_FILTERS      *Cpb; >> +  USB_ETHERNET_FUN_DESCRIPTOR  UsbEthFunDescriptor; >> + >> +  Count     = 0; >> +  CpbAddr   = Cdb->CPBaddr; >> +  CpbSize   = Cdb->CPBsize; >> +  SetFilter = (UINT16)(Cdb->OpFlags & 0x1F); >> +  Cpb       = (PXE_CPB_RECEIVE_FILTERS *)(UINTN)CpbAddr; >> + >> +  // The Cpb could be NULL.(ref:PXE_CPBADDR_NOT_USED) >> +  Nic->RxFilter = (UINT8)SetFilter; >> + >> +  if (((SetFilter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) >> != 0) || (Cpb != NULL)) { >> +    if (Cpb != NULL) { >> +      Nic->McastCount = (UINT8)(CpbSize / PXE_MAC_LENGTH); >> +      CopyMem (&Nic->McastList, Cpb, Nic->McastCount); >> +    } else { >> +      Nic->McastCount = 0; >> +    } >> + >> +    Nic->UsbEth->UsbEthFunDescriptor (Nic->UsbEth, >> &UsbEthFunDescriptor); >> +    if ((UsbEthFunDescriptor.NumberMcFilters << 1) == 0) { >> +      Nic->RxFilter |= PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST; >> +      DEBUG ((DEBUG_INFO, "SetUsbEthPacketFilter Nic %lx Nic->UsbEth >> %lx ", Nic, Nic->UsbEth)); >> +      Nic->UsbEth->SetUsbEthPacketFilter (Nic->UsbEth, Nic->RxFilter); >> +    } else { >> +      Status = gBS->AllocatePool (EfiBootServicesData, >> Nic->McastCount * 6, (VOID **)&McastList); >> +      if (EFI_ERROR (Status)) { >> +        return PXE_STATCODE_INVALID_PARAMETER; >> +      } >> + >> +      if (Cpb != NULL) { >> +        for (Index1 = 0; Index1 < Nic->McastCount; Index1++) { >> +          for (Index2 = 0; Index2 < 6; Index2++) { >> +            McastList[Count++] = Cpb->MCastList[Index1][Index2]; >> +          } >> +        } >> +      } >> + >> +      Nic->RxFilter |= PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST; >> +      if (Cpb != NULL) { >> +        Nic->UsbEth->SetUsbEthMcastFilter (Nic->UsbEth, >> Nic->McastCount, McastList); >> +      } >> + >> +      Nic->UsbEth->SetUsbEthPacketFilter (Nic->UsbEth, Nic->RxFilter); >> +      FreePool (McastList); >> +    } >> +  } >> + >> +  return EFI_SUCCESS; >> +} >> + >> +/** >> +  This request is used to configure device Ethernet packet filter >> settings. >> + >> +  @param[in]  This              A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> +  @param[in]  Value             Packet Filter Bitmap. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +SetUsbRndisPacketFilter ( >> +  IN EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  IN UINT16                       Value >> +  ) >> +{ >> +  return EFI_SUCCESS; >> +} >> + >> +/** >> +  This request is used to retrieve a statistic based on the feature >> selector. >> + >> +  @param[in]  This                  A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> +  @param[in]  FeatureSelector       Value of the feature selector. >> +  @param[out] Statistic             A pointer to the 32 bit unsigned >> integer. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_TIMEOUT           A timeout occurred executing the >> request. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> +  @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> +  @retval EFI_UNSUPPORTED       Not supported. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +GetRndisStatistic ( >> +  IN  EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  IN  UINT16                       FeatureSelector, >> +  OUT VOID                         *Statistic >> +  ) >> +{ >> +  return EFI_SUCCESS; >> +} >> + >> +/** >> +  This function is called when UndiStart is invoked. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS     The request executed successfully. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +RndisUndiStart ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ) >> +{ >> +  EFI_STATUS  Status; >> + >> +  DEBUG ((DEBUG_INFO, "RndisUndiStart Nic %lx Cdb %lx Nic State >> %x\n", Nic, Cdb, Nic->State)); >> + >> +  // Issue Rndis Reset and bring the device to RNDIS_BUS_INITIALIZED >> state >> +  Status = RndisUndiReset (Cdb, Nic); >> +  if (EFI_ERROR (Status)) { >> +    RndisUndiReset (Cdb, Nic); >> +  } >> + >> +  Status = RndisUndiInitialize (Cdb, Nic); >> +  if (EFI_ERROR (Status)) { >> +    RndisUndiInitialize (Cdb, Nic); >> +  } >> + >> +  RndisUndiShutdown (Cdb, Nic); >> + >> +  return EFI_SUCCESS; >> +} >> + >> +/** >> +  This function is called when Undistop is invoked. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS     The request executed successfully. >> +**/ >> +EFI_STATUS >> +EFIAPI >> +RndisUndiStop ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ) >> +{ >> +  DEBUG ((DEBUG_INFO, "RndisUndiStop State %x\n", Nic->State)); >> +  return EFI_SUCCESS; >> +} >> + >> +/** >> +  This function is called when UndiGetInitInfo is invoked. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS     The request executed successfully. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +RndisUndiGetInitInfo ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ) >> +{ >> +  EDKII_USB_ETHERNET_PROTOCOL  *UsbEthDevice; >> +  USB_RNDIS_DEVICE             *UsbRndisDevice; >> +  PXE_DB_GET_INIT_INFO         *Db; >> + >> +  DEBUG ((DEBUG_INFO, "RndisUndiGetInitInfo\n")); >> + >> +  UsbEthDevice   = Nic->UsbEth; >> +  UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (UsbEthDevice); >> + >> +  Db = (PXE_DB_GET_INIT_INFO *)(UINTN)Cdb->DBaddr; >> + >> +  Db->FrameDataLen = UsbRndisDevice->MaxTransferSize - sizeof >> (REMOTE_NDIS_PACKET_MSG) - PXE_MAC_HEADER_LEN_ETHER; >> +  // Limit Max MTU size to 1500 bytes as RNDIS spec. >> +  if (Db->FrameDataLen > PXE_MAX_TXRX_UNIT_ETHER) { >> +    Db->FrameDataLen = PXE_MAX_TXRX_UNIT_ETHER; >> +  } >> + >> +  DEBUG ((DEBUG_INFO, "Db->FrameDataLen %x\n", Db->FrameDataLen)); >> + >> +  return EFI_SUCCESS; >> +} >> + >> +/** >> +  This function is called when RndisUndiGetConfigInfo is invoked. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS     The request executed successfully. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +RndisUndiGetConfigInfo ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ) >> +{ >> +  DEBUG ((DEBUG_INFO, "RndisUndiGetConfigInfo\n")); >> +  return EFI_SUCCESS; >> +} >> + >> +/** >> +  This function is called when UndiInitialize is invoked. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_UNSUPPORTED       Not supported. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +RndisUndiInitialize ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ) >> +{ >> +  EDKII_USB_ETHERNET_PROTOCOL   *UsbEthDriver; >> +  USB_RNDIS_DEVICE              *UsbRndisDevice; >> +  REMOTE_NDIS_INITIALIZE_MSG    RndisInitMsg; >> +  REMOTE_NDIS_INITIALIZE_CMPLT  RndisInitMsgCmplt; >> +  EFI_STATUS                    Status; >> + >> +  DEBUG ((DEBUG_INFO, "RndisUndiInitialize\n")); >> + >> +  UsbEthDriver   = Nic->UsbEth; >> +  UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (UsbEthDriver); >> + >> +  ZeroMem (&RndisInitMsg, sizeof (REMOTE_NDIS_INITIALIZE_MSG)); >> +  ZeroMem (&RndisInitMsgCmplt, sizeof (REMOTE_NDIS_INITIALIZE_CMPLT)); >> + >> +  RndisInitMsg.MessageType     = RNDIS_INITIALIZE_MSG; >> +  RndisInitMsg.MessageLength   = sizeof (REMOTE_NDIS_INITIALIZE_MSG); >> +  RndisInitMsg.RequestID       = UsbRndisDevice->RequestId; >> +  RndisInitMsg.MajorVersion    = RNDIS_MAJOR_VERSION; >> +  RndisInitMsg.MinorVersion    = RNDIS_MINOR_VERSION; >> +  RndisInitMsg.MaxTransferSize = RNDIS_MAX_TRANSFER_SIZE; >> + >> +  RndisInitMsgCmplt.MessageType   = RNDIS_INITIALIZE_CMPLT; >> +  RndisInitMsgCmplt.MessageLength = sizeof >> (REMOTE_NDIS_INITIALIZE_CMPLT); >> + >> +  Status = RndisControlMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_HEADER >> *)&RndisInitMsg, (REMOTE_NDIS_MSG_HEADER *)&RndisInitMsgCmplt); >> + >> +  UsbRndisDevice->RequestId++; >> + >> +  if (EFI_ERROR (Status) || (RndisInitMsgCmplt.Status & 0x80000000)) { >> +    return Status; >> +  } >> + >> +  // Only Wired Medium is supported >> +  if (RndisInitMsgCmplt.Medium) { >> +    return EFI_UNSUPPORTED; >> +  } >> + >> +  UsbRndisDevice->Medium                = RndisInitMsgCmplt.Medium; >> +  UsbRndisDevice->MaxPacketsPerTransfer = >> RndisInitMsgCmplt.MaxPacketsPerTransfer; >> +  UsbRndisDevice->MaxTransferSize       = >> RndisInitMsgCmplt.MaxTransferSize; >> +  UsbRndisDevice->PacketAlignmentFactor = >> RndisInitMsgCmplt.PacketAlignmentFactor; >> + >> +  DEBUG ((DEBUG_INFO, "Medium : %x \n", RndisInitMsgCmplt.Medium)); >> +  DEBUG ((DEBUG_INFO, "MaxPacketsPerTransfer : %x \n", >> RndisInitMsgCmplt.MaxPacketsPerTransfer)); >> +  DEBUG ((DEBUG_INFO, "MaxTransferSize : %x\n", >> RndisInitMsgCmplt.MaxTransferSize)); >> +  DEBUG ((DEBUG_INFO, "PacketAlignmentFactor : %x\n", >> RndisInitMsgCmplt.PacketAlignmentFactor)); >> + >> +  return Status; >> +} >> + >> +/** >> +  This function is called when UndiReset is invoked. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_DEVICE_ERROR      The request failed due to a device >> error. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +RndisUndiReset ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ) >> +{ >> +  EDKII_USB_ETHERNET_PROTOCOL  *UsbEthDriver; >> +  USB_RNDIS_DEVICE             *UsbRndisDevice; >> +  REMOTE_NDIS_RESET_MSG        RndisResetMsg; >> +  REMOTE_NDIS_RESET_CMPLT      RndisResetCmplt; >> +  EFI_STATUS                   Status; >> + >> +  DEBUG ((DEBUG_INFO, "RndisUndiReset\n")); >> + >> +  UsbEthDriver   = Nic->UsbEth; >> +  UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (UsbEthDriver); >> + >> +  ZeroMem (&RndisResetMsg, sizeof (REMOTE_NDIS_RESET_MSG)); >> +  ZeroMem (&RndisResetCmplt, sizeof (REMOTE_NDIS_RESET_CMPLT)); >> + >> +  RndisResetMsg.MessageType   = RNDIS_RESET_MSG; >> +  RndisResetMsg.MessageLength = sizeof (REMOTE_NDIS_RESET_MSG); >> + >> +  RndisResetCmplt.MessageType   = RNDIS_RESET_CMPLT; >> +  RndisResetCmplt.MessageLength = sizeof (REMOTE_NDIS_RESET_CMPLT); >> + >> +  Status = RndisControlMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_HEADER >> *)&RndisResetMsg, (REMOTE_NDIS_MSG_HEADER *)&RndisResetCmplt); >> + >> +  UsbRndisDevice->RequestId = 1;          // Let's start with 1 >> + >> +  if (EFI_ERROR (Status) || (RndisResetCmplt.Status & 0x80000000)) { >> +    return EFI_DEVICE_ERROR; >> +  } >> + >> +  return EFI_SUCCESS; >> +} >> + >> +/** >> +  This function is called when UndiShutdown is invoked. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS     The request executed successfully. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +RndisUndiShutdown ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ) >> +{ >> +  EDKII_USB_ETHERNET_PROTOCOL  *UsbEthDriver; >> +  USB_RNDIS_DEVICE             *UsbRndisDevice; >> +  REMOTE_NDIS_HALT_MSG         RndisHltMsg; >> +  EFI_STATUS                   Status; >> + >> +  DEBUG ((DEBUG_INFO, "RndisUndiShutdown\n")); >> + >> +  UsbEthDriver   = Nic->UsbEth; >> +  UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (UsbEthDriver); >> + >> +  ZeroMem (&RndisHltMsg, sizeof (REMOTE_NDIS_HALT_MSG)); >> + >> +  RndisHltMsg.MessageType   = RNDIS_HLT_MSG; >> +  RndisHltMsg.MessageLength = sizeof (REMOTE_NDIS_HALT_MSG); >> + >> +  Status = RndisControlMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_HEADER >> *)&RndisHltMsg, NULL); >> + >> +  if (Status == EFI_DEVICE_ERROR) { >> +    Status = EFI_SUCCESS; >> +  } >> + >> +  UsbRndisDevice->RequestId = 1; >> +  return Status; >> +} >> + >> +/** >> +  Update the Media connection. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS     The request executed successfully. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +RndisUndiGetStatus ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ) >> +{ >> +  Cdb->StatFlags &= ~(PXE_STATFLAGS_GET_STATUS_NO_MEDIA); >> +  return EFI_SUCCESS; >> +} >> + >> +/** >> +  Transmit the data after appending RNDIS header. >> + >> +  @param[in]      Cdb           A pointer to the command descriptor >> block. >> +  @param[in]      This          A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> +  @param[in]      BulkOutData   A pointer to the buffer of data that >> will be transmitted to USB >> +                                device or received from USB device. >> +  @param[in, out] DataLength    A pointer to the PacketLength. >> + >> +  @retval EFI_SUCCESS     The request executed successfully. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +RndisUndiTransmit ( >> +  IN      PXE_CDB                      *Cdb, >> +  IN      EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  IN      VOID                         *BulkOutData, >> +  IN OUT  UINTN                        *DataLength >> +  ) >> +{ >> +  EFI_STATUS              Status; >> +  USB_RNDIS_DEVICE        *UsbRndisDevice; >> +  REMOTE_NDIS_PACKET_MSG  *RndisPacketMsg; >> +  UINTN                   TransferLength; >> + >> +  DEBUG ((DEBUG_INFO, "RndisUndiTransmit DataLength : %x\n", >> *DataLength)); >> + >> +  UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> + >> +  RndisPacketMsg = AllocateZeroPool (sizeof (REMOTE_NDIS_PACKET_MSG) >> + *DataLength); >> +  if (RndisPacketMsg == NULL) { >> +    return EFI_OUT_OF_RESOURCES; >> +  } >> + >> +  RndisPacketMsg->MessageType   = RNDIS_PACKET_MSG; >> +  RndisPacketMsg->MessageLength = sizeof (REMOTE_NDIS_PACKET_MSG) + >> (UINT32)*DataLength; >> +  RndisPacketMsg->DataOffset    = sizeof (REMOTE_NDIS_PACKET_MSG) - 8; >> +  RndisPacketMsg->DataLength    = (UINT32)*DataLength; >> + >> +  CopyMem ( >> +    ((UINT8 *)RndisPacketMsg) + sizeof (REMOTE_NDIS_PACKET_MSG), >> +    BulkOutData, >> +    *DataLength >> +    ); >> + >> +  TransferLength = RndisPacketMsg->MessageLength; >> + >> +  Status = RndisTransmitDataMsg ( >> +             UsbRndisDevice, >> +             (REMOTE_NDIS_MSG_HEADER *)RndisPacketMsg, >> +             &TransferLength >> +             ); >> + >> +  DEBUG ((DEBUG_INFO, "\nRndisUndiTransmit TransferLength %lx\n", >> TransferLength)); >> + >> +  FreePool (RndisPacketMsg); >> + >> +  return Status; >> +} >> + >> +/** >> +  Receives and removes RNDIS header and returns the raw data. >> + >> +  @param[in]      Cdb           A pointer to the command descriptor >> block. >> +  @param[in]      This          A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> +  @param[in, out] BulkInData    A pointer to the buffer of data that >> will be transmitted to USB >> +                                device or received from USB device. >> +  @param[in, out] DataLength    A pointer to the PacketLength. >> + >> +  @retval EFI_SUCCESS           The request executed successfully. >> +  @retval EFI_BUFFER_TOO_SMALL  The user provided buffer is too small >> +  @retval EFI_NOT_FOUND         No buffer was found in the list. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +RndisUndiReceive ( >> +  IN     PXE_CDB                      *Cdb, >> +  IN     EDKII_USB_ETHERNET_PROTOCOL  *This, >> +  IN OUT VOID                         *BulkInData, >> +  IN OUT UINTN                        *DataLength >> +  ) >> +{ >> +  EFI_STATUS              Status; >> +  USB_RNDIS_DEVICE        *UsbRndisDevice; >> +  REMOTE_NDIS_PACKET_MSG  *RndisPacketMsg; >> +  UINTN                   TransferLength; >> +  VOID                    *Buffer; >> +  PACKET_LIST             *HeadPacket; >> +  PACKET_LIST             *PacketList; >> + >> +  // Check if there is any outstanding packet to receive >> +  // The buffer allocated has a linked List followed by the packet. >> + >> +  UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> +  Buffer         = NULL; >> +  HeadPacket     = NULL; >> + >> +  while (1) { >> +    Buffer = AllocateZeroPool (sizeof (PACKET_LIST) + sizeof >> (REMOTE_NDIS_PACKET_MSG) + UsbRndisDevice->MaxTransferSize); >> +    if (Buffer == NULL) { >> +      return EFI_OUT_OF_RESOURCES; >> +    } >> + >> +    RndisPacketMsg                = (REMOTE_NDIS_PACKET_MSG >> *)(sizeof (PACKET_LIST) + (UINT8 *)Buffer); >> +    PacketList                    = (PACKET_LIST *)Buffer; >> +    PacketList->PacketStartBuffer = (UINT8 *)Buffer + sizeof >> (PACKET_LIST); >> +    // Save the original address for freeing it up >> +    PacketList->OrgBuffer = (UINT8 *)Buffer; >> +    TransferLength        = UsbRndisDevice->MaxTransferSize; >> + >> +    Status = RndisReceiveDataMsg ( >> +               UsbRndisDevice, >> +               (REMOTE_NDIS_MSG_HEADER *)RndisPacketMsg, >> +               &TransferLength >> +               ); >> + >> +    if (EFI_ERROR (Status) || (TransferLength == 0)) { >> +      FreePool (Buffer); >> +      break; >> +    } >> + >> +    // Collect all the RNDIS packet in Linked list. >> +    if ((RndisPacketMsg->MessageType == RNDIS_PACKET_MSG) && >> +        (RndisPacketMsg->DataOffset == sizeof >> (REMOTE_NDIS_PACKET_MSG) - RNDIS_RESERVED_BYTE_LENGTH) && >> +        (TransferLength >= RndisPacketMsg->MessageLength)) >> +    { >> +      // Insert Packet >> +      PacketList->RemainingLength = TransferLength; >> +      InsertTailList (&UsbRndisDevice->ReceivePacketList, Buffer); >> +    } else { >> +      FreePool (Buffer); >> +    } >> +  } >> + >> +  while (!IsListEmpty (&UsbRndisDevice->ReceivePacketList)) { >> +    HeadPacket = (PACKET_LIST *)GetFirstNode >> (&UsbRndisDevice->ReceivePacketList); >> + >> +    RndisPacketMsg = (REMOTE_NDIS_PACKET_MSG *)(UINT8 >> *)HeadPacket->PacketStartBuffer; >> + >> +    PrintRndisMsg ((REMOTE_NDIS_MSG_HEADER *)RndisPacketMsg); >> + >> +    // Check whether the packet is valid RNDIS packet. >> +    if ((HeadPacket->RemainingLength > sizeof >> (REMOTE_NDIS_PACKET_MSG)) && (RndisPacketMsg->MessageType == >> RNDIS_PACKET_MSG) && >> +        (RndisPacketMsg->DataOffset == (sizeof >> (REMOTE_NDIS_PACKET_MSG) - RNDIS_RESERVED_BYTE_LENGTH)) && >> +        (HeadPacket->RemainingLength >= RndisPacketMsg->MessageLength)) >> +    { >> +      if (*DataLength >= RndisPacketMsg->DataLength) { >> +        CopyMem ( >> +          BulkInData, >> +          (UINT8 *)RndisPacketMsg + (RndisPacketMsg->DataOffset + >> RNDIS_RESERVED_BYTE_LENGTH), >> +          RndisPacketMsg->DataLength >> +          ); >> + >> +        *DataLength =  RndisPacketMsg->DataLength; >> + >> +        HeadPacket->RemainingLength   = HeadPacket->RemainingLength >> - RndisPacketMsg->MessageLength; >> +        HeadPacket->PacketStartBuffer = (UINT8 *)RndisPacketMsg + >> RndisPacketMsg->MessageLength; >> + >> +        return EFI_SUCCESS; >> +      } else { >> +        *DataLength = RndisPacketMsg->DataLength; >> +        return EFI_BUFFER_TOO_SMALL; >> +      } >> +    } >> + >> +    RemoveEntryList (&HeadPacket->PacketList); >> +    FreePool ((PACKET_LIST *)HeadPacket->OrgBuffer); >> +  } >> + >> +  return EFI_NOT_FOUND; >> +} >> + >> +/** >> +  This is a dummy function which just returns. Unimplemented >> EDKII_USB_ETHERNET_PROTOCOL functions >> +  point to this function. >> + >> +  @param[in]  Cdb  A pointer to the command descriptor block. >> +  @param[in]  Nic  A pointer to the Network interface controller data. >> + >> +  @retval EFI_SUCCESS     The request executed successfully. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +RndisDummyReturn ( >> +  IN  PXE_CDB   *Cdb, >> +  IN  NIC_DATA  *Nic >> +  ) >> +{ >> +  DEBUG ((DEBUG_INFO, "RndisDummyReturn called\n")); >> +  return EFI_SUCCESS; >> +} >> + >> +/** >> +  This function send the RNDIS command through the device's control >> endpoint >> + >> +  @param[in]  UsbRndisDevice    A pointer to the USB_RNDIS_DEVICE >> instance. >> +  @param[in]  RndisMsg          A pointer to the >> REMOTE_NDIS_MSG_HEADER data. >> +  @param[out] RndisMsgResponse  A pointer to the >> REMOTE_NDIS_MSG_HEADER data for getting responses. >> + >> +  @retval EFI_SUCCESS           The bulk transfer has been >> successfully executed. >> + >> +**/ >> +EFI_STATUS >> +RndisControlMsg ( >> +  IN  USB_RNDIS_DEVICE        *UsbRndisDevice, >> +  IN  REMOTE_NDIS_MSG_HEADER  *RndisMsg, >> +  OUT REMOTE_NDIS_MSG_HEADER  *RndisMsgResponse >> +  ) >> +{ >> +  EFI_USB_IO_PROTOCOL           *UsbIo = UsbRndisDevice->UsbIo; >> +  EFI_USB_DEVICE_REQUEST        DevReq; >> +  UINT32                        UsbStatus; >> +  EFI_STATUS                    Status; >> +  UINT32                        SaveResponseType; >> +  UINT32                        SaveResponseLength; >> +  UINT32                        Index; >> +  REMOTE_NDIS_INITIALIZE_CMPLT  *RndisInitCmplt; >> + >> +  SaveResponseType   = 0; >> +  SaveResponseLength = 0; >> +  RndisInitCmplt     = (REMOTE_NDIS_INITIALIZE_CMPLT >> *)RndisMsgResponse; >> + >> +  if (RndisMsgResponse) { >> +    SaveResponseType   = RndisMsgResponse->MessageType; >> +    SaveResponseLength = RndisMsgResponse->MessageLength; >> +  } >> + >> +  ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); >> + >> +  DevReq.RequestType = USB_REQ_TYPE_CLASS | USB_TARGET_INTERFACE; >> +  DevReq.Request     = SEND_ENCAPSULATED_COMMAND; >> +  DevReq.Value       = 0; >> +  DevReq.Index       = 0; >> +  DevReq.Length      = (UINT16)RndisMsg->MessageLength; >> + >> +  PrintRndisMsg (RndisMsg); >> + >> +  Status = UsbIo->UsbControlTransfer ( >> +                    UsbIo, >> +                    &DevReq, >> +                    EfiUsbDataOut, >> +                    USB_ETHERNET_TRANSFER_TIMEOUT, >> +                    RndisMsg, >> +                    RndisMsg->MessageLength, >> +                    &UsbStatus >> +                    ); >> + >> +  DEBUG ((DEBUG_INFO, "RndisControlMsg: UsbStatus : %x Status : %r >> RndisMsgResponse : %lx\n", UsbStatus, Status, RndisMsgResponse)); >> + >> +  // Error or no response expected >> +  if ((EFI_ERROR (Status)) || (RndisMsgResponse == NULL)) { >> +    DEBUG ((DEBUG_INFO, "RndisControlMsg: UsbStatus : %x Status : >> %r\n", UsbStatus, Status)); >> +    return Status; >> +  } >> + >> +  for (Index = 0; Index < (RNDIS_CONTROL_TIMEOUT/100); Index++) { >> +    ReadRndisResponseInterrupt (UsbRndisDevice); >> +    ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); >> + >> +    DevReq.RequestType = USB_ENDPOINT_DIR_IN | USB_REQ_TYPE_CLASS | >> USB_TARGET_INTERFACE; >> +    DevReq.Request     = GET_ENCAPSULATED_RESPONSE; >> +    DevReq.Value       = 0; >> +    DevReq.Index       = 0; >> +    DevReq.Length      = (UINT16)RndisMsgResponse->MessageLength; >> + >> +    Status = UsbIo->UsbControlTransfer ( >> +                      UsbIo, >> +                      &DevReq, >> +                      EfiUsbDataIn, >> +                      USB_ETHERNET_TRANSFER_TIMEOUT, >> +                      RndisMsgResponse, >> +                      RndisMsgResponse->MessageLength, >> +                      &UsbStatus >> +                      ); >> + >> +    DEBUG ((DEBUG_INFO, "RndisControlMsg Response: UsbStatus : %x >> Status : %r \n", UsbStatus, Status)); >> + >> +    PrintRndisMsg (RndisMsgResponse); >> + >> +    if (!EFI_ERROR (Status)) { >> +      if ((RndisInitCmplt->RequestID != >> ((REMOTE_NDIS_INITIALIZE_CMPLT *)RndisMsg)->RequestID) || >> (RndisInitCmplt->MessageType != SaveResponseType)) { >> +        DEBUG ((DEBUG_INFO, "Retry the response\n")); >> + >> +        RndisMsgResponse->MessageType   = SaveResponseType; >> +        RndisMsgResponse->MessageLength = SaveResponseLength; >> +        continue; >> +      } >> +    } >> + >> +    return Status; >> +  } >> + >> +  DEBUG ((DEBUG_INFO, "RndisControlMsg: TimeOut\n")); >> + >> +  return EFI_TIMEOUT; >> +} >> + >> +/** >> +  This function send the RNDIS command through the device's Data >> endpoint >> + >> +  @param[in]      UsbRndisDevice  A pointer to the USB_RNDIS_DEVICE >> instance. >> +  @param[in]      RndisMsg        A pointer to the >> REMOTE_NDIS_MSG_HEADER to send out. >> +  @param[in, out] TransferLength  The length of the RndisMsg data to >> transfer. >> + >> +  @retval EFI_SUCCESS     The request executed successfully. >> + >> +**/ >> +EFI_STATUS >> +RndisTransmitDataMsg ( >> +  IN      USB_RNDIS_DEVICE        *UsbRndisDevice, >> +  IN      REMOTE_NDIS_MSG_HEADER  *RndisMsg, >> +  IN OUT  UINTN                   *TransferLength >> +  ) >> +{ >> +  EFI_STATUS  Status; >> +  UINT32      UsbStatus; >> + >> +  if (UsbRndisDevice->BulkInEndpoint == 0) { >> +    GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice); >> +  } >> + >> +  PrintRndisMsg (RndisMsg); >> + >> +  Status = UsbRndisDevice->UsbIoCdcData->UsbBulkTransfer ( >> + UsbRndisDevice->UsbIoCdcData, >> + UsbRndisDevice->BulkOutEndpoint, >> +                                           RndisMsg, >> +                                           TransferLength, >> + USB_TX_ETHERNET_BULK_TIMEOUT, >> +                                           &UsbStatus >> +                                           ); >> + >> +  if (Status == EFI_SUCCESS) { >> +    gStopBulkInCnt = MAXIMUM_STOPBULKIN_CNT;     // After sending >> cmd ,we will polling receive package for MAXIMUM_STOPBULKIN_CNT times >> +  } >> + >> +  return Status; >> +} >> + >> +/** >> +  This function send the RNDIS command through the device's Data >> endpoint >> + >> +  @param[in]      UsbRndisDevice    A pointer to the >> USB_RNDIS_DEVICE instance. >> +  @param[in, out] RndisMsg          A pointer to the >> REMOTE_NDIS_MSG_HEADER to send out. >> +  @param[in, out] TransferLength    The length of the RndisMsg data >> to transfer. >> + >> +  @retval EFI_SUCCESS     The request executed successfully. >> + >> +**/ >> +EFI_STATUS >> +RndisReceiveDataMsg ( >> +  IN      USB_RNDIS_DEVICE        *UsbRndisDevice, >> +  IN OUT  REMOTE_NDIS_MSG_HEADER  *RndisMsg, >> +  IN OUT  UINTN                   *TransferLength >> +  ) >> +{ >> +  EFI_STATUS  Status; >> +  UINT32      UsbStatus; >> + >> +  UsbStatus = 0; >> + >> +  if (UsbRndisDevice->BulkInEndpoint == 0) { >> +    GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice); >> +  } >> + >> +  // Use gStopBulkInCnt to stop BulkIn command >> +  if (gStopBulkInCnt || LAN_BULKIN_CMD_CONTROL) { >> +    Status = UsbRndisDevice->UsbIoCdcData->UsbBulkTransfer ( >> + UsbRndisDevice->UsbIoCdcData, >> + UsbRndisDevice->BulkInEndpoint, >> +                                             RndisMsg, >> +                                             TransferLength, >> + USB_RX_ETHERNET_BULK_TIMEOUT, >> +                                             &UsbStatus >> +                                             ); >> + >> +    if (!EFI_ERROR (Status)) { >> +      gStopBulkInCnt = MINIMUM_STOPBULKIN_CNT; >> +    } else { >> +      gStopBulkInCnt--; >> +    } >> +  } else { >> +    Status          = EFI_TIMEOUT; >> +    *TransferLength = 0; >> +    gBlockBulkInCnt++; >> +  } >> + >> +  if (gBlockBulkInCnt > BULKIN_CMD_POLLING_CNT) { >> +    gStopBulkInCnt  = MINIMUM_STOPBULKIN_CNT; >> +    gBlockBulkInCnt = 0; >> +  } >> + >> +  PrintRndisMsg (RndisMsg); >> + >> +  return Status; >> +} >> + >> +/** >> +  Prints RNDIS Header and Data >> + >> +  @param[in] RndisMsg    A pointer to the REMOTE_NDIS_MSG_HEADER data. >> + >> +**/ >> +VOID >> +PrintRndisMsg ( >> +  IN  REMOTE_NDIS_MSG_HEADER  *RndisMsg >> +  ) >> +{ >> +  UINTN                    Length; >> +  REMOTE_NDIS_QUERY_CMPLT  *RndisQueryCmplt; >> + >> +  Length = 0; >> + >> +  switch (RndisMsg->MessageType) { >> +    case RNDIS_PACKET_MSG: >> +      DEBUG ((DEBUG_INFO, "RNDIS_PACKET_MSG:\n")); >> +      Length = sizeof (REMOTE_NDIS_PACKET_MSG) + 0x14; >> +      break; >> +    case RNDIS_INITIALIZE_MSG: >> +      DEBUG ((DEBUG_INFO, "RNDIS_INITIALIZE_MSG:\n")); >> +      Length = sizeof (REMOTE_NDIS_INITIALIZE_MSG); >> +      break; >> +    case RNDIS_INITIALIZE_CMPLT: >> +      DEBUG ((DEBUG_INFO, "RNDIS_INITIALIZE_CMPLT:\n")); >> +      Length = sizeof (REMOTE_NDIS_INITIALIZE_CMPLT); >> +      break; >> +    case RNDIS_HLT_MSG: >> +      DEBUG ((DEBUG_INFO, "RNDIS_HLT_MSG:\n")); >> +      Length = sizeof (REMOTE_NDIS_HALT_MSG); >> +      break; >> +    case RNDIS_QUERY_MSG: >> +      DEBUG ((DEBUG_INFO, "RNDIS_QUERY_MSG:\n")); >> +      Length = sizeof (REMOTE_NDIS_QUERY_MSG); >> +      break; >> +    case RNDIS_QUERY_CMPLT: >> +      DEBUG ((DEBUG_INFO, "RNDIS_QUERY_CMPLT:\n")); >> +      RndisQueryCmplt = (REMOTE_NDIS_QUERY_CMPLT *)RndisMsg; >> +      Length          = sizeof (REMOTE_NDIS_QUERY_CMPLT) + >> RndisQueryCmplt->InformationBufferLength; >> +      break; >> +    case RNDIS_SET_MSG: >> +      DEBUG ((DEBUG_INFO, "RNDIS_SET_MSG:\n")); >> +      Length = sizeof (REMOTE_NDIS_SET_MSG); >> +      break; >> +    case RNDIS_SET_CMPLT: >> +      DEBUG ((DEBUG_INFO, "RNDIS_SET_CMPLT:\n")); >> +      Length = sizeof (REMOTE_NDIS_SET_CMPLT); >> +      break; >> +    case RNDIS_RESET_MSG: >> +      DEBUG ((DEBUG_INFO, "RNDIS_RESET_MSG:\n")); >> +      Length = sizeof (REMOTE_NDIS_RESET_MSG); >> +      break; >> +    case RNDIS_RESET_CMPLT: >> +      DEBUG ((DEBUG_INFO, "RNDIS_RESET_CMPLT:\n")); >> +      Length = sizeof (REMOTE_NDIS_RESET_CMPLT); >> +      break; >> +    case RNDIS_INDICATE_STATUS_MSG: >> +      DEBUG ((DEBUG_INFO, "RNDIS_INDICATE_STATUS_MSG:\n")); >> +      Length = sizeof (REMOTE_NDIS_INDICATE_STATUS_MSG); >> +      break; >> +    case RNDIS_KEEPALIVE_MSG: >> +      DEBUG ((DEBUG_INFO, "RNDIS_KEEPALIVE_MSG:\n")); >> +      Length = sizeof (REMOTE_NDIS_KEEPALIVE_MSG); >> +      break; >> +    case RNDIS_KEEPALIVE_CMPLT: >> +      DEBUG ((DEBUG_INFO, "RNDIS_KEEPALIVE_CMPLT:\n")); >> +      Length = sizeof (REMOTE_NDIS_KEEPALIVE_CMPLT); >> +  } >> + >> +  if (Length) { >> +    UINTN  Index = 0; >> +    for ( ; Length; Length -= 4, Index++) { >> +      DEBUG ((DEBUG_INFO, "%8X\t", *((UINT32 *)RndisMsg + Index))); >> +      if (((Index % 4) == 3) && (Index != 0)) { >> +        DEBUG ((DEBUG_INFO, "\n")); >> +      } >> + >> +      if ((Length < 8) && (Length > 4)) { >> +        UINT32  Data32; >> +        Index++; >> +        Data32 = *((UINT32 *)RndisMsg + Index); >> +        DEBUG ((DEBUG_INFO, "%8X\t", Data32)); >> +        break; >> +      } >> +    } >> + >> +    if (Index % 4) { >> +      DEBUG ((DEBUG_INFO, "\n")); >> +    } >> +  } >> +} >> diff --git a/UsbNetworkPkg/ReadMe.md b/UsbNetworkPkg/ReadMe.md >> new file mode 100644 >> index 000000000000..cb70684f0bf1 >> --- /dev/null >> +++ b/UsbNetworkPkg/ReadMe.md >> @@ -0,0 +1,65 @@ >> +# UsbNetworkPkg >> + >> +This document is intend to provide package information, include the >> interface details. >> + >> +# INDEX >> +  * [Introduction](#introduction) >> +  * [Components](#components) >> +    * [[NetworkCommon]](#networkcommon) >> +    * [[UsbCdcEcm]](#usbcdcecm) >> +    * [[UsbCdcNcm]](#usbcdcncm) >> +    * [[UsbRndis]](#usbrndis) >> + >> +#  Introduction >> +UsbNetworkPkg provides network functions for USB LAN devices. >> + >> +# Components >> +Below module is included in this package:
>> +- NetworkCommon >> +- UsbCdcEcm >> +- UsbCdcNcm >> +- UsbRndis >> + >> +## [NetworkCommon] >> +Provides a LAN driver based on UEFI specification(UNDI). It supports >> USB communication class subclass devices and USB Rndis devices, >> depending on the UsbEthernetProtocol. >> + >> +## Required Components >> +- NetworkPkg >> + >> +## [UsbCdcEcm] >> +This driver provides a communication interface for USB Ethernet >> devices that follows the ECM protocol. The driver installs >> UsbEthernetProtocol with ECM functions which are consumed by the >> NetworkCommon driver. >> + >> +The driver is compatible with the following USB class codes: >> +|Class Code|SubClass Code|Protocol Code| >> +|:--------:|:-----------:|:-----------:| >> +|0x02|0x06|0x00| >> + >> +## Required Components >> +- NetworkCommon >> +- MdeModulePkg(USB bus driver) >> + >> +## [UsbCdcNcm] >> +This driver provides a communication interface for USB Ethernet >> devices that follows the NCM protocol. The driver installs >> UsbEthernetProtocol with NCM functions which are consumed by the >> NetworkCommon driver. >> + >> +The driver is compatible with the following USB class codes: >> +|Class Code|SubClass Code|Protocol Code| >> +|:--------:|:-----------:|:-----------:| >> +|0x02|0x0D|0x00| >> + >> +## Required Components >> +- NetworkCommon >> +- MdeModulePkg(USB bus driver) >> + >> +## [UsbRndis] >> +This driver provides a communication interface for USB Ethernet >> devices that follows the RNDIS protocol. The driver installs >> UsbEthernetProtocol with RNDIS functions which are consumed by the >> NetworkCommon driver. >> + >> +The driver is compatible with the following USB class codes: >> +|Class Code|SubClass Code|Protocol Code| >> +|:--------:|:-----------:|:-----------:| >> +|0x02|0x02|0xFF| >> +|0xEF|0x04|0x01| >> + >> +## Required Components >> +- NetworkCommon >> +- MdeModulePkg(USB bus driver) >> + >> diff --git a/UsbNetworkPkg/ReleaseNotes.md >> b/UsbNetworkPkg/ReleaseNotes.md >> new file mode 100644 >> index 000000000000..f8ccccdb0830 >> --- /dev/null >> +++ b/UsbNetworkPkg/ReleaseNotes.md >> @@ -0,0 +1,11 @@ >> +# UsbNetworkPkg Release Notes >> + >> +# Release History >> +- [1.00](#100) >> + >> +## 1.00 >> + >> +**Release Date:** Mar 10, 2022 >> + >> +**New Features** >> +- UsbNetworkPkg first release. >> -- >> 2.35.1.windows.2 >> -The information contained in this message may be confidential and >> proprietary to American Megatrends (AMI). This communication is >> intended to be read only by the individual or entity to whom it is >> addressed or by their designee. If the reader of this message is not >> the intended recipient, you are on notice that any distribution of >> this message, in any form, is strictly prohibited. Please promptly >> notify the sender by reply e-mail or by telephone at 770-246-8600, >> and then delete or destroy all copies of the transmission. > > > > >