From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from wout1-smtp.messagingengine.com (wout1-smtp.messagingengine.com [64.147.123.24]) by mx.groups.io with SMTP id smtpd.web10.176322.1680835937897049061 for ; Thu, 06 Apr 2023 19:52:18 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="signature has expired" header.i=@bsdio.com header.s=fm3 header.b=F9arrZv0; spf=pass (domain: bsdio.com, ip: 64.147.123.24, mailfrom: rebecca@bsdio.com) Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailout.west.internal (Postfix) with ESMTP id 3E46B3200392; Thu, 6 Apr 2023 22:52:16 -0400 (EDT) Received: from imap43 ([10.202.2.93]) by compute5.internal (MEProxy); Thu, 06 Apr 2023 22:52:16 -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= 1680835935; x=1680922335; bh=9eXrtddiK5Mv5JpGkjv5V1cXAodEXd52pOu TDfPJrI0=; b=F9arrZv0yecygxFOTCSZ2eAzS0oUUrx+sPAVgWaWrqgIBBsrd1O VWJnHvn9tyhhlp5UWppiX98wh5qFGwME6VrKe9BKHHuX7Mx4wlOf1A5aJR0WuYf+ UoqoniY9a5o4RFqB79mZg5bn3txLMWYZMWSLN2WcmYnMJ9d6DoZl4yfQ5qd1ccKd j8V5X7Hy0N+hV/wFb0PK5xxcPagMfeo39PwWw8ZNYeY9jtp3SBxsb6qRei3QIA5K BTVpIm0oJVGHNyD3CXBg58PAB1eRA18BcnH+cNjZmRyyK4PKPfUXqu9DTRE10GuW bcA/HF72fL2VEUtmiHdeIb9TkotZen85+dA== 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= 1680835935; x=1680922335; bh=9eXrtddiK5Mv5JpGkjv5V1cXAodEXd52pOu TDfPJrI0=; b=WnnND7p9zpF0BLQg6ihoPnx09l78hNzJ651hMTo6TjqeCgJq99W /qd2hQoTXfm7GTVw9ltT5gBltgct7j1xixGl9VIsTmmx+4oK91qpI/DWW4cK3IsA cv3jJ4oBida45vi6FCTfhq72bdxeIEpkk0o6fIRQggx+urpwAYgHnKhGtwrhyyJx +XObRoyezEIEbAZ3nwWE/9cJj08x5FlIl2qdvUhaVF0nunzdGg1QR6uhK6sgQ0Q8 rkMDXjZY1dkwSMGeajIY/guqoi55xvVitSMM9YEdjFjRa36tB0JDxzSk4B4UXOf7 k7txbWceCse3dWhGMp+i5KDHgdQ4ibw4hrQ== X-ME-Sender: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvhedrvdejgedgieefucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne cujfgurhepofgfggfkjghffffhvfevufgtgfesthhqredtreerjeenucfhrhhomhepfdft vggsvggttggrucevrhgrnhdfuceorhgvsggvtggtrgessghsughiohdrtghomheqnecugg ftrfgrthhtvghrnhepvdeihfefudeugfdvieelffektedtjeegtdfhffeltefftefftedv vdegfeefgeeinecuffhomhgrihhnpehgihhthhhusgdrtghomhenucevlhhushhtvghruf hiiigvpedtnecurfgrrhgrmhepmhgrihhlfhhrohhmpehrvggsvggttggrsegsshguihho rdgtohhm X-ME-Proxy: Feedback-ID: i5b994698:Fastmail Received: by mailuser.nyi.internal (Postfix, from userid 501) id 3FB592D4008E; Thu, 6 Apr 2023 22:52:15 -0400 (EDT) X-Mailer: MessagingEngine.com Webmail Interface User-Agent: Cyrus-JMAP/3.9.0-alpha0-334-g8c072af647-fm-20230330.001-g8c072af6 Mime-Version: 1.0 Message-Id: In-Reply-To: References: <20230309075134.864-1-richardho@ami.com> Date: Thu, 06 Apr 2023 20:52:12 -0600 From: "Rebecca Cran" To: devel@edk2.groups.io, richardho@ami.com Cc: "Andrew Fish" , "Leif Lindholm" , "Kinney, Michael D" , "Michael Kubacki" , "'Zhiguang Liu'" , gaoliming , "Tinh Nguyen" , =?UTF-8?Q?Tony_Lo_=28=E7=BE=85=E9=87=91=E6=9D=BE=29?= Subject: Re: [edk2-devel] [PATCH v6 1/3] UsbNetworkPkg/UsbRndis: Add USB RNDIS devices support Content-Type: text/plain;charset=utf-8 Content-Transfer-Encoding: quoted-printable Thanks. I wonder if it=E2=80=99s an issue with Git on Windows: I=E2=80=99ll= do some testing tomorrow. =E2=80=94=20 Rebecca On Thu, Apr 6, 2023, at 8:49 PM, RichardHo [=E4=BD=95=E6=98=8E=E5=BF=A0] vi= a groups.io wrote: > Hi Rebecca, > > I have already run the SetupGit.py before send the mail. > (Use git send-email --transfer-encoding=3D8bit --annotate --suppress-from= =20 > --to devel@edk2.groups.io *.patch to send mail) > > Below is my .git/config > > [core] > repositoryformatversion =3D 0 > filemode =3D false > bare =3D false > logallrefupdates =3D true > symlinks =3D false > ignorecase =3D true > abbrev =3D 12 > attributesFile =3D D:/EDKII-Upstream/edk2/BaseTools/Conf/gitattri= butes > whitespace =3D cr-at-eol > [remote "origin"] > url =3D https://github.com/tianocore/edk2.git > fetch =3D +refs/heads/*:refs/remotes/origin/* > [branch "master"] > remote =3D origin > merge =3D refs/heads/master > [am] > keepcr =3D True > signoff =3D True > [cherry-pick] > signoff =3D True > [color] > diff =3D True > grep =3D auto > [commit] > signoff =3D True > [diff] > algorithm =3D patience > orderFile =3D D:/EDKII-Upstream/edk2/BaseTools/Conf/diff.order > renames =3D copies > statGraphWidth =3D 20 > [diff "ini"] > xfuncname =3D ^\\[[A-Za-z0-9_., ]+] > [format] > coverLetter =3D True > numbered =3D True > signoff =3D False > [log] > mailmap =3D True > [notes] > rewriteRef =3D refs/notes/commits > [sendemail] > chainreplyto =3D False > thread =3D True > transferEncoding =3D 8bit > to =3D devel@edk2.groups.io > > Thanks, > Richard > > -----Original Message----- > From: Rebecca Cran > Sent: 2023=E5=B9=B44=E6=9C=887=E6=97=A5 9:57 AM > To: Richard Ho (=E4=BD=95=E6=98=8E=E5=BF=A0) ; devel@e= dk2.groups.io > Cc: Andrew Fish ; Leif Lindholm=20 > ; Michael D Kinney=20 > ; Michael Kubacki=20 > ; Zhiguang Liu ;=20 > Liming Gao ; Tinh Nguyen=20 > ; Tony Lo (=E7=BE=85=E9=87=91=E6=9D=BE= ) > Subject: [EXTERNAL] Re: [PATCH v6 1/3] UsbNetworkPkg/UsbRndis: Add USB=20 > RNDIS devices support > > > **CAUTION: The e-mail below is from an external source. Please exercise= =20 > caution before opening attachments, clicking links, or following=20 > guidance.** > > Your patches are still coming through rather mangled, unfortunately. > > You should be sending them as 8bit, not quoted-printable - the > BaseTools/Scripts/SetupGit.py script will configure the settings for you. > > Also, there should be a cover letter with the patch series: that script > configures "git format-patch" to generate one. > > > If you've already run SetupGit.py, could you tell me what .git/config in > your edk2 clone contains, please? > > > -- > Rebecca Cran > > > On 3/9/23 12:51 AM, Richard Ho (=E4=BD=95=E6=98=8E=E5=BF=A0) 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/EdkIIUsbEthernetProt= ocol.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/UsbNetworkP= kg.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 cla= sses >> +# 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 =3D 0x00010005 >> + PACKAGE_NAME =3D UsbNetworkPkg >> + PACKAGE_GUID =3D abfab91e-37ea-4cb4-80a6-563dbb0bce= c6 >> + PACKAGE_VERSION =3D 0.1 >> + >> +[Includes] >> + Include >> + >> +[Protocols] >> + ## Include/Protocol/EdkIIUsbEthernet.h >> + gEdkIIUsbEthProtocolGuid =3D { 0x8d8969cc, 0xfeb0, 0x4303, { 0xb2, 0x= 1a, 0x1f, 0x11, 0x6f, 0x38, 0x56, 0x43 } } >> + >> +[Guids] >> + ## Usb Network package token space GUID >> + gUsbNetworkPkgTokenSpaceGuid =3D { 0xA1231E82, 0x21B8, 0x4204, { 0x9= 2, 0xBB, 0x37, 0x3A, 0xFB, 0x01, 0xC6, 0xA1 } } >> + >> +[PcdsFeatureFlag] >> + >> + ## Set the PCD 'UsbCdcEcmSupport' to 'TRUE' if 'Usb Cdc Ecm device' n= eed to be enabled. >> + gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport|FALSE|BOOLEAN|0x0000000= 1 >> + >> + ## Set the PCD 'UsbCdcNcmSupport' to 'TRUE' if 'Usb Cdc Ncm device' n= eed to be enabled. >> + gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport|FALSE|BOOLEAN|0x0000000= 2 >> + >> + ## 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|0x00010= 001 >> + >> + ## 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 i= s 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/U= sbNetworkPkg/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/UsbNetw= orkPkg/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=3DIA32 >> + DEFINE DXE=3DX64 >> +!else >> + DEFINE PEI=3DCOMMON >> + DEFINE DXE=3DCOMMON >> +!endif >> + >> +[Packages] >> + UsbNetworkPkg/UsbNetworkPkg.dec >> + >> +[PcdsFeatureFlag] >> + gUsbNetworkPkgTokenSpaceGuid.UsbCdcEcmSupport|FALSE >> + gUsbNetworkPkgTokenSpaceGuid.UsbCdcNcmSupport|FALSE >> + gUsbNetworkPkgTokenSpaceGuid.UsbRndisSupport|TRUE >> diff --git a/UsbNetworkPkg/Config/UsbNetworkPkgComponentsDxe.inc.fdf b/U= sbNetworkPkg/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/UsbNetworkP= kg/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 =3D 0x00010005 >> + BASE_NAME =3D NetworkCommon >> + FILE_GUID =3D ca6eb4f4-f1d6-4375-97d6-18856871e1= bf >> + MODULE_TYPE =3D DXE_DRIVER >> + VERSION_STRING =3D 1.0 >> + ENTRY_POINT =3D 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/UsbRndi= s/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 =3D 0x00010005 >> + BASE_NAME =3D UsbRndis >> + FILE_GUID =3D 11E32C34-60B5-4991-8DEA-63D3E8C876= DE >> + MODULE_TYPE =3D DXE_DRIVER >> + VERSION_STRING =3D 1.0 >> + ENTRY_POINT =3D 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, 0= x56, 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 reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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 stoppe= d 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 reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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 starte= d 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 reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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 reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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 reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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 reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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 reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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 reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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 reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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 reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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 address= es >> + 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 reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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 reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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 reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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 reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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 reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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 reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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 queu= e. >> + >> + @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 reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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 reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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 da= ta. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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 dat= a. >> + @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 reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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 p= ipe. The endpoint is Bulk in. >> + >> + @param[in] Cdb A pointer to the command descriptor blo= ck. >> + @param[in] This A pointer to the EDKII_USB_ETHERNET_PRO= TOCOL instance. >> + @param[in, out] Packet A pointer to the buffer of data that wi= ll 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 statu= s 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 timeo= ut. >> +**/ >> +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 p= ipe. The endpoint is Bulk out. >> + >> + @param[in] Cdb A pointer to the command descriptor blo= ck. >> + @param[in] This A pointer to the EDKII_USB_ETHERNET_PRO= TOCOL instance. >> + @param[in, out] Packet A pointer to the buffer of data that wi= ll 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 statu= s 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 timeo= ut. >> +**/ >> +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 transf= er pipe. >> + >> + @param[in] This A pointer to the EDKII_USB_ETHERNET_PRO= TOCOL instance. >> + @param[in] IsNewTransfer If TRUE, a new transfer will be submitt= ed to USB controller. If >> + FALSE, the interrupt transfer is delete= d from the device's interrupt >> + transfer queue. >> + @param[in] PollingInterval Indicates the periodic rate, in millise= conds, that the transfer is to be >> + executed.This parameter is required whe= n IsNewTransfer is TRUE. The >> + value must be between 1 to 255, otherwi= se 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 t= ransfer has been successfully executed. >> + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request f= ailed. >> + >> +**/ >> +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_PROTOCO= L instance. >> + @param[out] MacAddress A pointer to the caller allocated USB Ether= net Mac Address. >> + >> + @retval EFI_SUCCESS The USB Header Functional descriptor wa= s retrieved successfully. >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor wa= s 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_PROTOCO= L instance. >> + @param[out] BulkSize A pointer to the Bulk transfer data size. >> + >> + @retval EFI_SUCCESS The USB Header Functional descriptor wa= s retrieved successfully. >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor wa= s 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_ETHERNE= T_PROTOCOL instance. >> + @param[out] UsbHeaderFunDescriptor A pointer to the caller allocated = USB Header Functional Descriptor. >> + >> + @retval EFI_SUCCESS The USB Header Functional descriptor wa= s retrieved successfully. >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor wa= s 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_ETHERNE= T_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_ETHERNE= T_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_ETHERNE= T_PROTOCOL instance. >> + @param[in] Value Number of filters. >> + @param[in] McastAddr A pointer to the value of the mult= icast addresses. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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_ETHERNE= T_PROTOCOL instance. >> + @param[in] Value Number of filters. >> + @param[in] Length Size of the power management patte= rn 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 reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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 man= agement >> + pattern filter from the device. >> + >> + @param[in] This A pointer to the EDKII_USB_ETHERNE= T_PROTOCOL instance. >> + @param[in] Value The filter number. >> + @param[out] PatternActive A pointer to the pattern active bo= olean. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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 setti= ngs. >> + >> + @param[in] This A pointer to the EDKII_USB_ETHERNET_PRO= TOCOL instance. >> + @param[in] Value Packet Filter Bitmap. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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 sel= ector. >> + >> + @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 in= teger. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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 dev= ice 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 UsbEthIniti= alize; >> + EDKII_USB_ETHERNET_STATISTICS UsbEthStati= stics; >> + EDKII_USB_ETHERNET_RECEIVE UsbEthRecei= ve; >> + EDKII_USB_ETHERNET_TRANSMIT UsbEthTrans= mit; >> + EDKII_USB_ETHERNET_INTERRUPT UsbEthInter= rupt; >> + EDKII_USB_GET_ETH_MAC_ADDRESS UsbEthMacAd= dress; >> + EDKII_USB_ETH_MAX_BULK_SIZE UsbEthMaxBu= lkSize; >> + EDKII_USB_HEADER_FUNCTIONAL_DESCRIPTOR UsbHeaderFu= nDescriptor; >> + EDKII_USB_UNION_FUNCTIONAL_DESCRIPTOR UsbUnionFun= Descriptor; >> + EDKII_USB_ETHERNET_FUNCTIONAL_DESCRIPTOR UsbEthFunDe= scriptor; >> + EDKII_USB_ETHERNET_SET_ETH_MULTICAST_FILTERS SetUsbEthMc= astFilter; >> + EDKII_USB_ETHERNET_SET_ETH_POWER_MANAGE_PATTERN_FILTER SetUsbEthPo= werPatternFilter; >> + EDKII_USB_ETHERNET_GET_ETH_POWER_MANAGE_PATTERN_FILTER GetUsbEthPo= werPatternFilter; >> + EDKII_USB_ETHERNET_SET_ETH_PACKET_FILTER SetUsbEthPa= cketFilter; >> + EDKII_USB_ETHERNET_GET_ETH_STATISTIC GetUsbEthSt= atistic; >> +}; >> + >> +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_SIGN= ATURE) >> + >> +#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 co= unts for waiting bulk in command >> +#define MINIMUM_STOPBULKIN_CNT 3 // Indicating minimum co= unts for waiting bulk in command >> +#define BULKIN_CMD_POLLING_CNT 300 // Indicating the waitin= g 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 gNetworkCommonD= riverNameTable[] =3D { >> + { >> + "eng;en", >> + L"Network Common Driver" >> + }, >> + { >> + NULL, >> + NULL >> + } >> +}; >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE *gNetworkCommon= ControllerNameTable =3D 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 gNetworkComm= onComponentName =3D { >> + NetworkCommonComponentNameGetDriverName, >> + NetworkCommonComponentNameGetControllerName, >> + "eng" >> +}; >> + >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gNetworkCom= monComponentName2 =3D { >> + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)NetworkCommonComponentNameGetDri= verName, >> + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)NetworkCommonComponentNameGe= tControllerName, >> + "en" >> +}; >> + >> +/** >> + Retrieves a Unicode string that is the user readable name of the driv= er. >> + >> + This function retrieves the user readable name of a driver in the for= m of a >> + Unicode string. If the driver specified by This has a user readable n= ame 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 sp= ecified >> + 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_PR= OTOCOL or >> + EFI_COMPONENT_NAME_PROTOCOL instance. >> + @param[in] Language A pointer to a Null-terminated ASCII st= ring >> + array indicating the language. This is = the >> + language of the driver name that the ca= ller is >> + requesting, and it must match one of th= e >> + languages specified in SupportedLanguag= es. The >> + number of languages supported by a driv= er is up >> + to the driver writer. Language is speci= fied >> + in RFC 4646 or ISO 639-2 language code = format. >> + @param[out] DriverName A pointer to the Unicode string to retu= rn. >> + This Unicode string is the name of the >> + driver specified by This in the languag= e >> + specified by Language. >> + >> + @retval EFI_SUCCESS The Unicode string for the Driver speci= fied by >> + This and the language specified by Lang= uage 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 s= upport >> + 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 =3D=3D &gNetworkCommonComponentName) >> + ); >> +} >> + >> +/** >> + Retrieves a Unicode string that is the user readable name of the cont= roller >> + that is being managed by a driver. >> + >> + This function retrieves the user readable name of the controller spec= ified 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 spe= cified by >> + Language, then a pointer to the controller name is returned in Contro= llerName, >> + 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 do= es not >> + support the language specified by Language, then EFI_UNSUPPORTED is r= eturned. >> + >> + @param[in] This A pointer to the EFI_COMPONENT_NAME2_PR= OTOCOL or >> + EFI_COMPONENT_NAME_PROTOCOL instance. >> + @param[in] Controller The handle of a controller that the dri= ver >> + specified by This is managing. This ha= ndle >> + specifies the controller whose name is = to be >> + returned. >> + @param[in] ChildHandle The handle of the child controller to r= etrieve >> + the name of. This is an optional param= eter that >> + may be NULL. It will be NULL for devic= e >> + drivers. It will also be NULL for a bu= s drivers >> + that wish to retrieve the name of the b= us >> + 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 st= ring >> + array indicating the language. This is= the >> + language of the driver name that the ca= ller is >> + requesting, and it must match one of th= e >> + languages specified in SupportedLanguag= es. The >> + number of languages supported by a driv= er is up >> + to the driver writer. Language is speci= fied in >> + RFC 4646 or ISO 639-2 language code for= mat. >> + @param[out] ControllerName A pointer to the Unicode string to retu= rn. >> + This Unicode string is the name of the >> + controller specified by ControllerHandl= e and >> + ChildHandle in the language specified b= y >> + Language from the point of view of the = driver >> + specified by This. >> + >> + @retval EFI_SUCCESS The Unicode string for the user readabl= e name in >> + the language specified by Language for = the >> + driver specified by This was returned i= n >> + DriverName. >> + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HAN= DLE. >> + @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 cur= rently >> + managing the controller specified by >> + ControllerHandle and ChildHandle. >> + @retval EFI_UNSUPPORTED The driver specified by This does not s= upport >> + 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 =3D=3D NULL) { >> + return EFI_UNSUPPORTED; >> + } >> + >> + // >> + // Make sure this driver is currently managing ControllerHandle >> + // >> + Status =3D EfiTestManagedDevice ( >> + Controller, >> + gNetworkCommonDriverBinding.DriverBindingHandle, >> + &gEdkIIUsbEthProtocolGuid >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + // >> + // Make sure this driver produced ChildHandle >> + // >> + Status =3D EfiTestChildHandle ( >> + Controller, >> + ChildHandle, >> + &gEdkIIUsbEthProtocolGuid >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + Status =3D gBS->HandleProtocol (Controller, &gEfiUsbIoProtocolGuid, (= VOID **)&UsbIo); >> + >> + if (!EFI_ERROR (Status)) { >> + Status =3D UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + Status =3D UsbIo->UsbGetStringDescriptor (UsbIo, 0x409, DevDesc.Str= Manufacturer, &HandleName); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + *ControllerName =3D HandleName; >> + >> + if (gNetworkCommonControllerNameTable !=3D NULL) { >> + FreeUnicodeStringTable (gNetworkCommonControllerNameTable); >> + gNetworkCommonControllerNameTable =3D NULL; >> + } >> + >> + Status =3D AddUnicodeString2 ( >> + "eng", >> + gNetworkCommonComponentName.SupportedLanguages, >> + &gNetworkCommonControllerNameTable, >> + HandleName, >> + TRUE >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + Status =3D AddUnicodeString2 ( >> + "en", >> + gNetworkCommonComponentName2.SupportedLanguages, >> + &gNetworkCommonControllerNameTable, >> + HandleName, >> + FALSE >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + return LookupUnicodeString2 ( >> + Language, >> + This->SupportedLanguages, >> + gNetworkCommonControllerNameTable, >> + ControllerName, >> + (BOOLEAN)(This =3D=3D &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 =3D NULL; >> +NIC_DEVICE *gLanDeviceList[MAX_LAN_INTERFACE]; >> +UINT32 gRateLimitingCredit; >> +UINT32 gRateLimitingPollTimer; >> +BOOLEAN gRateLimitingEnable; >> + >> +EFI_DRIVER_BINDING_PROTOCOL gNetworkCommonDriverBinding =3D { >> + NetworkCommonSupported, >> + NetworkCommonDriverStart, >> + NetworkCommonDriverStop, >> + NETWORK_COMMON_DRIVER_VERSION, >> + NULL, >> + NULL >> +}; >> + >> +/** >> + Create MAC Device Path >> + >> + @param[in, out] Dev A pointer to the EFI_DEVICE_PATH_PROT= OCOL instance. >> + @param[in] BaseDev A pointer to the EFI_DEVICE_PATH_PROT= OCOL instance. >> + @param[in] Nic A pointer to the Network interface co= ntroller 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_ADDR= ESS)); >> + >> + MacAddrNode.Header.Type =3D MESSAGING_DEVICE_PATH; >> + MacAddrNode.Header.SubType =3D MSG_MAC_ADDR_DP; >> + MacAddrNode.Header.Length[0] =3D (UINT8)sizeof (MacAddrNode); >> + MacAddrNode.Header.Length[1] =3D 0; >> + >> + EndNode =3D BaseDev; >> + >> + while (!IsDevicePathEnd (EndNode)) { >> + EndNode =3D NextDevicePathNode (EndNode); >> + } >> + >> + BaseLength =3D (UINT16)((UINTN)(EndNode) - (UINTN)(BaseDev)); >> + TotalLength =3D (UINT16)(BaseLength + sizeof (MacAddrNode) + sizeof (= EFI_DEVICE_PATH_PROTOCOL)); >> + >> + Status =3D gBS->AllocatePool (EfiBootServicesData, TotalLength, (VOID= **)&DevicePath); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + *Dev =3D (EFI_DEVICE_PATH_PROTOCOL *)DevicePath; >> + CopyMem (DevicePath, (CHAR8 *)BaseDev, BaseLength); >> + DevicePath +=3D BaseLength; >> + CopyMem (DevicePath, (CHAR8 *)&MacAddrNode, sizeof (MacAddrNode)); >> + DevicePath +=3D sizeof (MacAddrNode); >> + CopyMem (DevicePath, (CHAR8 *)EndNode, sizeof (EFI_DEVICE_PATH_PROTOC= OL)); >> + >> + 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 =3D 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 t= o. >> + @param[in] RemainingDevicePath Optional parameter use to pick a = specific child >> + device to start. >> + >> + @retval EFI_SUCCESS This driver is added to Controlle= rHandle >> + @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 succ= essfully 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 =3D gBS->OpenProtocol ( >> + ControllerHandle, >> + &gEdkIIUsbEthProtocolGuid, >> + (VOID **)&UsbEth, >> + This->DriverBindingHandle, >> + ControllerHandle, >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + Status =3D 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 =3D UsbEth->UsbEthMacAddress (UsbEth, &MacAddress); >> + ASSERT_EFI_ERROR (Status); >> + Status =3D 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 =3D 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 =3D=3D NULL) { >> + TmpPxePointer =3D NULL; >> + TmpPxePointer =3D AllocateZeroPool (sizeof (PXE_SW_UNDI) + 16); >> + if (!TmpPxePointer) { >> + if (NicDevice !=3D 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) !=3D 0) { >> + gPxe =3D (PXE_SW_UNDI *)(TmpPxePointer + 8); >> + } else { >> + gPxe =3D (PXE_SW_UNDI *)TmpPxePointer; >> + } >> + >> + if (!gPxe) { >> + if (NicDevice !=3D 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 =3D (UINT64)(UINTN)(gPxe); >> + NicDevice->NiiProtocol.IfNum =3D gPxe->IFcnt | gPxe->IFcntExt << 8; >> + >> + UpdateNicNum (&NicDevice->NicInfo, gPxe); >> + >> + NicDevice->NicInfo.Signature =3D NIC_DATA_SIGNATURE; >> + >> + NicDevice->NicInfo.UsbEth =3D UsbEth; >> + NicDevice->NicInfo.MaxSegmentSize =3D (UINT16)BulkDataSize; >> + NicDevice->NicInfo.CableDetect =3D 0; >> + NicDevice->ReceiveBuffer =3D ALIGN_POINTER ((VOID *)NicDevic= e, 4096); >> + >> + CopyMem ((CHAR8 *)&(NicDevice->NicInfo.MacAddr), (CHAR8 *)&MacAddress= , sizeof (MacAddress)); >> + >> + NicDevice->NicInfo.TxBufferCount =3D 0; >> + >> + if (NicDevice->NiiProtocol.IfNum < MAX_LAN_INTERFACE) { >> + gLanDeviceList[NicDevice->NiiProtocol.IfNum] =3D NicDevice; >> + } else { >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEfiDevicePathProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEdkIIUsbEthProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + >> + if (TmpPxePointer !=3D NULL) { >> + FreePool (TmpPxePointer); >> + } >> + >> + if (NicDevice !=3D NULL) { >> + FreePool (NicDevice); >> + } >> + >> + return EFI_DEVICE_ERROR; >> + } >> + >> + Status =3D CreateMacDevicePath ( >> + &NicDevice->DevPath, >> + UsbEthPath, >> + &NicDevice->NicInfo >> + ); >> + >> + if (EFI_ERROR (Status)) { >> + UpdateNicNum (NULL, gPxe); >> + if (TmpPxePointer !=3D NULL) { >> + FreePool (TmpPxePointer); >> + } >> + } >> + >> + NicDevice->Signature =3D UNDI_DEV_SIGNATURE; >> + NicDevice->NiiProtocol.Revision =3D EFI_NETWORK_INTERFACE_IDENTI= FIER_PROTOCOL_REVISION; >> + NicDevice->NiiProtocol.Type =3D EfiNetworkInterfaceUndi; >> + NicDevice->NiiProtocol.MajorVer =3D PXE_ROMID_MAJORVER; >> + NicDevice->NiiProtocol.MinorVer =3D PXE_ROMID_MINORVER; >> + NicDevice->NiiProtocol.ImageSize =3D 0; >> + NicDevice->NiiProtocol.ImageAddr =3D 0; >> + NicDevice->NiiProtocol.Ipv6Supported =3D TRUE; >> + >> + NicDevice->NiiProtocol.StringId[0] =3D 'U'; >> + NicDevice->NiiProtocol.StringId[1] =3D 'N'; >> + NicDevice->NiiProtocol.StringId[2] =3D 'D'; >> + NicDevice->NiiProtocol.StringId[3] =3D 'I'; >> + NicDevice->DeviceHandle =3D NULL; >> + >> + NicDevice->NicInfo.RateLimitingEnable =3D gRateLimitingEnable; >> + NicDevice->NicInfo.RateLimitingCreditCount =3D 0; >> + NicDevice->NicInfo.RateLimitingCredit =3D gRateLimitingCredit; >> + NicDevice->NicInfo.RateLimitingPollTimer =3D gRateLimitingPollTimer= ; >> + NicDevice->NicInfo.RateLimiter =3D NULL; >> + >> + ZeroMem (&NicDevice->NicInfo.Request, sizeof (EFI_USB_DEVICE_REQUEST)= ); >> + >> + Status =3D UsbEth->UsbEthInterrupt (UsbEth, TRUE, NETWORK_COMMON_POLL= ING_INTERVAL, &NicDevice->NicInfo.Request); >> + ASSERT_EFI_ERROR (Status); >> + >> + Status =3D 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] =3D NULL; >> + } >> + >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEfiDevicePathProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEdkIIUsbEthProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + >> + if (TmpPxePointer !=3D NULL) { >> + FreePool (TmpPxePointer); >> + } >> + >> + if (NicDevice->DevPath !=3D NULL) { >> + FreePool (NicDevice->DevPath); >> + } >> + >> + if (NicDevice !=3D NULL) { >> + FreePool (NicDevice); >> + } >> + >> + return EFI_DEVICE_ERROR; >> + } >> + >> + Status =3D 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 ChildHandleBuf= fer. If number of >> + children is zero stop the entire bu= s driver. >> + @param[in] ChildHandleBuffer List of Child Handles to Stop. >> + >> + @retval EFI_SUCCESS This driver is removed ControllerHa= ndle >> + @retval other This driver was not removed from th= is 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 =3D=3D 0) { >> + Status =3D 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 =3D UNDI_DEV_FROM_THIS (NiiProtocol); >> + Status =3D 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 =3D TRUE; >> + >> + for (Index =3D 0; Index < NumberOfChildren; Index++) { >> + Status =3D gBS->OpenProtocol ( >> + ChildHandleBuffer[Index], >> + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, >> + (VOID **)&NiiProtocol, >> + This->DriverBindingHandle, >> + ControllerHandle, >> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >> + ); >> + if (EFI_ERROR (Status)) { >> + AllChildrenStopped =3D FALSE; >> + continue; >> + } >> + >> + NicDevice =3D UNDI_DEV_FROM_THIS (NiiProtocol); >> + >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEdkIIUsbEthProtocolGuid, >> + This->DriverBindingHandle, >> + ChildHandleBuffer[Index] >> + ); >> + >> + Status =3D gBS->UninstallMultipleProtocolInterfaces ( >> + ChildHandleBuffer[Index], >> + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, >> + &NicDevice->NiiProtocol, >> + &gEfiDevicePathProtocolGuid, >> + NicDevice->DevPath, >> + NULL >> + ); >> + if (EFI_ERROR (Status)) { >> + Status =3D 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 E= FI image. >> + @param[in] SystemTable A pointer to the EFI System Table. >> + >> + @retval EFI_SUCCESS The entry point is executed successfull= y. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +NetworkCommonEntry ( >> + IN EFI_HANDLE ImageHandle, >> + IN EFI_SYSTEM_TABLE *SystemTable >> + ) >> +{ >> + EFI_STATUS Status; >> + >> + gNetworkCommonDriverBinding.DriverBindingHandle =3D ImageHandle; >> + gNetworkCommonDriverBinding.ImageHandle =3D ImageHandle; >> + gRateLimitingEnable =3D PcdGetBool (Enabl= eRateLimiting); >> + gRateLimitingCredit =3D PcdGet32 (RateLim= itingCredit); >> + gRateLimitingPollTimer =3D PcdGet32 (RateLim= itingFactor); >> + >> + Status =3D gBS->InstallMultipleProtocolInterfaces ( >> + &gNetworkCommonDriverBinding.DriverBindingHandle, >> + &gEfiDriverBindingProtocolGuid, >> + &gNetworkCommonDriverBinding, >> + &gEfiComponentName2ProtocolGuid, >> + &gNetworkCommonComponentName2, >> + NULL >> + ); >> + return Status; >> +} >> diff --git a/UsbNetworkPkg/NetworkCommon/PxeFunction.c b/UsbNetworkPkg/N= etworkCommon/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[] =3D { >> + 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 bein= g invoked >> + @param[in] Context Pointer to the notification function's co= ntext >> + >> +**/ >> +VOID >> +EFIAPI >> +UndiRateLimiterCallback ( >> + IN EFI_EVENT Event, >> + IN VOID *Context >> + ) >> +{ >> + NIC_DATA *Nic =3D 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 !=3D PXE_OPCODE_GET_STATE) || >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) || >> + (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED) || >> + (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) || >> + (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED) || >> + (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED)) >> + { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> + } >> + >> + Cdb->StatFlags =3D Cdb->StatFlags | Nic->State; >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetState !=3D NULL) { >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiGetState (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + } >> +} >> + >> +/** >> + This command is used to change the UNDI operational state from stoppe= d 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 !=3D PXE_OPCODE_START) || >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize !=3D sizeof (PXE_CPB_START_31)) || >> + (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) || >> + (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED) || >> + (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED)) >> + { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> + return; >> + } >> + >> + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_STOPPED) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_ALREADY_STARTED; >> + return; >> + } >> + >> + Cpb =3D (PXE_CPB_START_31 *)(UINTN)Cdb->CPBaddr; >> + >> + Nic->PxeStart.Delay =3D Cpb->Delay; >> + Nic->PxeStart.Virt2Phys =3D Cpb->Virt2Phys; >> + Nic->PxeStart.Block =3D Cpb->Block; >> + Nic->PxeStart.Map_Mem =3D 0; >> + Nic->PxeStart.UnMap_Mem =3D 0; >> + Nic->PxeStart.Sync_Mem =3D Cpb->Sync_Mem; >> + Nic->PxeStart.Unique_ID =3D Cpb->Unique_ID; >> + EventError =3D FALSE; >> + Status =3D EFI_SUCCESS; >> + if (Nic->RateLimitingEnable =3D=3D TRUE) { >> + Status =3D gBS->CreateEvent ( >> + EVT_TIMER | EVT_NOTIFY_SIGNAL, >> + TPL_NOTIFY, >> + UndiRateLimiterCallback, >> + Nic, >> + &Nic->RateLimiter >> + ); >> + if (!EFI_ERROR (Status)) { >> + Status =3D gBS->SetTimer ( >> + Nic->RateLimiter, >> + TimerPeriodic, >> + Nic->RateLimitingPollTimer * 10000 >> + ); >> + if (EFI_ERROR (Status)) { >> + EventError =3D TRUE; >> + } >> + } >> + } >> + >> + if ((Nic->UsbEth->UsbEthUndi.UsbEthUndiStart !=3D NULL) && (EventErro= r =3D=3D FALSE)) { >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiStart (Cdb, Nic); >> + } >> + >> + if (!EFI_ERROR (Status)) { >> + // Initial the state for UNDI start. >> + Nic->State =3D PXE_STATFLAGS_GET_STATE_STARTED; >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> + } else { >> + if (Nic->RateLimitingEnable =3D=3D TRUE) { >> + if (!EventError) { >> + gBS->SetTimer (&Nic->RateLimiter, TimerCancel, 0); >> + } >> + >> + if (Nic->RateLimiter) { >> + gBS->CloseEvent (&Nic->RateLimiter); >> + Nic->RateLimiter =3D 0; >> + } >> + } >> + >> + // Initial the state when UNDI start is fail >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_DEVICE_FAILURE; >> + } >> +} >> + >> +/** >> + This command is used to change the UNDI operational state from starte= d 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 !=3D PXE_OPCODE_STOP) || >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) || >> + (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED) || >> + (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) || >> + (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED) || >> + (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED)) >> + { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> + } >> + >> + if (Nic->State =3D=3D PXE_STATFLAGS_GET_STATE_STOPPED) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_NOT_STARTED; >> + return; >> + } >> + >> + if (Nic->State =3D=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_NOT_SHUTDOWN; >> + return; >> + } >> + >> + Nic->PxeStart.Delay =3D 0; >> + Nic->PxeStart.Virt2Phys =3D 0; >> + Nic->PxeStart.Block =3D 0; >> + Nic->PxeStart.Map_Mem =3D 0; >> + Nic->PxeStart.UnMap_Mem =3D 0; >> + Nic->PxeStart.Sync_Mem =3D 0; >> + Nic->State =3D PXE_STATFLAGS_GET_STATE_STOPPED; >> + >> + if (Nic->RateLimitingEnable =3D=3D TRUE) { >> + gBS->SetTimer (&Nic->RateLimiter, TimerCancel, 0); >> + gBS->CloseEvent (&Nic->RateLimiter); >> + } >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStop !=3D NULL) { >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiStop (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags =3D 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 !=3D PXE_OPCODE_GET_INIT_INFO) || >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) || >> + (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED) || >> + (Cdb->DBsize !=3D sizeof (PXE_DB_GET_INIT_INFO)) || >> + (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED)) >> + { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> + } >> + >> + if (Nic->State =3D=3D PXE_STATFLAGS_GET_STATE_STOPPED) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_NOT_STARTED; >> + return; >> + } >> + >> + Db =3D (PXE_DB_GET_INIT_INFO *)(UINTN)Cdb->DBaddr; >> + >> + Db->MemoryRequired =3D MEMORY_REQUIRE; >> + Db->FrameDataLen =3D PXE_MAX_TXRX_UNIT_ETHER; >> + Db->LinkSpeeds[0] =3D 10; >> + Db->LinkSpeeds[1] =3D 100; >> + Db->LinkSpeeds[2] =3D 1000; >> + Db->LinkSpeeds[3] =3D 0; >> + Db->MediaHeaderLen =3D PXE_MAC_HEADER_LEN_ETHER; >> + Db->HWaddrLen =3D PXE_HWADDR_LEN_ETHER; >> + Db->MCastFilterCnt =3D MAX_MCAST_ADDRESS_CNT; >> + Db->TxBufCnt =3D Nic->PxeInit.TxBufCnt; >> + Db->TxBufSize =3D Nic->PxeInit.TxBufSize; >> + Db->RxBufCnt =3D Nic->PxeInit.RxBufCnt; >> + Db->RxBufSize =3D Nic->PxeInit.RxBufSize; >> + Db->IFtype =3D PXE_IFTYPE_ETHERNET; >> + Db->SupportedDuplexModes =3D PXE_DUPLEX_DEFAULT; >> + Db->SupportedLoopBackModes =3D LOOPBACK_NORMAL; >> + >> + Cdb->StatFlags |=3D (PXE_STATFLAGS_CABLE_DETECT_SUPPORTED | >> + PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED); >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetInitInfo !=3D NULL) { >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiGetInitInfo (Cdb, Nic)= ; >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags =3D 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 !=3D PXE_OPCODE_GET_CONFIG_INFO) || >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) || >> + (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED) || >> + (Cdb->DBsize !=3D sizeof (PXE_DB_GET_CONFIG_INFO)) || >> + (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED)) >> + { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> + } >> + >> + if (Nic->State =3D=3D PXE_STATFLAGS_GET_STATE_STOPPED) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_NOT_STARTED; >> + return; >> + } >> + >> + Db =3D (PXE_DB_GET_CONFIG_INFO *)(UINTN)Cdb->DBaddr; >> + >> + Db->pci.BusType =3D PXE_BUSTYPE_USB; >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetConfigInfo !=3D NULL) { >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiGetConfigInfo (Cdb, Ni= c); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags =3D 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 da= ta. >> + >> +**/ >> +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 !=3D PXE_OPCODE_INITIALIZE) || >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize !=3D sizeof (PXE_CPB_INITIALIZE))) >> + { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> + } >> + >> + if (Nic->State =3D=3D PXE_STATFLAGS_GET_STATE_STOPPED) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_NOT_STARTED; >> + return; >> + } >> + >> + if ((Cdb->OpFlags !=3D PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) && >> + (Cdb->OpFlags !=3D PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE)) >> + { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> + return; >> + } >> + >> + if (Nic->State =3D=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_ALREADY_INITIALIZED; >> + return; >> + } >> + >> + Cpb =3D (PXE_CPB_INITIALIZE *)(UINTN)Cdb->CPBaddr; >> + Db =3D (PXE_DB_INITIALIZE *)(UINTN)Cdb->DBaddr; >> + >> + Nic->PxeInit.LinkSpeed =3D Cpb->LinkSpeed; >> + Nic->PxeInit.DuplexMode =3D Cpb->DuplexMode; >> + Nic->PxeInit.LoopBackMode =3D Cpb->LoopBackMode; >> + Nic->PxeInit.MemoryAddr =3D Cpb->MemoryAddr; >> + Nic->PxeInit.MemoryLength =3D Cpb->MemoryLength; >> + Nic->PxeInit.TxBufCnt =3D TX_BUFFER_COUNT; >> + Nic->PxeInit.TxBufSize =3D Nic->MaxSegmentSize; >> + Nic->PxeInit.RxBufCnt =3D RX_BUFFER_COUNT; >> + Nic->PxeInit.RxBufSize =3D Nic->MaxSegmentSize; >> + >> + Cdb->StatCode =3D Initialize (Cdb, Nic); >> + >> + Db->MemoryUsed =3D MEMORY_REQUIRE; >> + Db->TxBufCnt =3D Nic->PxeInit.TxBufCnt; >> + Db->TxBufSize =3D Nic->PxeInit.TxBufSize; >> + Db->RxBufCnt =3D Nic->PxeInit.RxBufCnt; >> + Db->RxBufSize =3D Nic->PxeInit.RxBufSize; >> + >> + Nic->RxFilter =3D PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST; >> + Nic->CanTransmit =3D FALSE; >> + >> + if (Cdb->OpFlags =3D=3D PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) { >> + if ((Nic->Request.Request =3D=3D USB_CDC_NETWORK_CONNECTION) && (Ni= c->Request.Value =3D=3D NETWORK_DISCONNECT)) { >> + Nic->CableDetect =3D 0; >> + } else if ((Nic->Request.Request =3D=3D USB_CDC_NETWORK_CONNECTION)= && (Nic->Request.Value =3D=3D NETWORK_CONNECTED)) { >> + Nic->CableDetect =3D 1; >> + } >> + >> + if (Nic->CableDetect =3D=3D 0) { >> + Cdb->StatFlags |=3D PXE_STATFLAGS_INITIALIZED_NO_MEDIA; >> + } >> + } >> + >> + if (Cdb->StatCode !=3D PXE_STATCODE_SUCCESS) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + } else { >> + Nic->State =3D PXE_STATFLAGS_GET_STATE_INITIALIZED; >> + } >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiInitialize !=3D NULL) { >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiInitialize (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags =3D 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 =3D MapIt ( >> + Nic, >> + Nic->PxeInit.MemoryAddr, >> + Nic->PxeInit.MemoryLength, >> + TO_AND_FROM_DEVICE, >> + (UINT64)(UINTN)&Nic->MappedAddr >> + ); >> + >> + if (Status !=3D 0) { >> + return (UINT16)Status; >> + } >> + >> + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> + Nic->PermNodeAddress[Index] =3D Nic->MacAddr.Addr[Index]; >> + } >> + >> + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> + Nic->CurrentNodeAddress[Index] =3D Nic->PermNodeAddress[Index]; >> + } >> + >> + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> + Nic->BroadcastNodeAddress[Index] =3D 0xFF; >> + } >> + >> + for (Index =3D PXE_HWADDR_LEN_ETHER; Index < PXE_MAC_LENGTH; Index++)= { >> + Nic->CurrentNodeAddress[Index] =3D 0; >> + Nic->PermNodeAddress[Index] =3D 0; >> + Nic->BroadcastNodeAddress[Index] =3D 0; >> + } >> + >> + if (Nic->UsbEth->UsbEthInitialize !=3D NULL) { >> + EfiStatus =3D 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 !=3D PXE_OPCODE_RESET) || >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) || >> + (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED) || >> + (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) || >> + (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED)) >> + { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> + } >> + >> + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + return; >> + } >> + >> + if ((Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED) && >> + (Cdb->OpFlags !=3D PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS) && >> + (Cdb->OpFlags !=3D PXE_OPFLAGS_RESET_DISABLE_FILTERS)) >> + { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> + return; >> + } >> + >> + if ((Cdb->OpFlags & PXE_OPFLAGS_RESET_DISABLE_FILTERS) =3D=3D 0) { >> + Nic->RxFilter =3D PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST; >> + } >> + >> + if ((Cdb->OpFlags & PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS) !=3D 0) { >> + Nic->InterrupOpFlag =3D 0; >> + } >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiReset !=3D NULL) { >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiReset (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags =3D 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 da= ta. >> + >> +**/ >> +VOID >> +UndiShutdown ( >> + IN PXE_CDB *Cdb, >> + IN OUT NIC_DATA *Nic >> + ) >> +{ >> + EFI_STATUS Status; >> + >> + if ((Cdb->OpCode !=3D PXE_OPCODE_SHUTDOWN) || >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) || >> + (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED) || >> + (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) || >> + (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED) || >> + (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED)) >> + { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> + } >> + >> + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + return; >> + } >> + >> + Nic->CanTransmit =3D FALSE; >> + >> + Nic->State =3D PXE_STATFLAGS_GET_STATE_STARTED; >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiShutdown !=3D NULL) { >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiShutdown (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; >> + Cdb->StatFlags =3D 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 =3D PXE_STATCODE_UNSUPPORTED; >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiInterruptEnable !=3D NULL) { >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiInterruptEnable (Cdb, = Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + } else { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode =3D 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 !=3D PXE_OPCODE_RECEIVE_FILTERS) || >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8))) >> + { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> + } >> + >> + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + return; >> + } >> + >> + NewFilter =3D (UINT16)(Cdb->OpFlags & 0x1F); >> + >> + switch (Cdb->OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_OPMASK) { >> + case PXE_OPFLAGS_RECEIVE_FILTER_READ: >> + if (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> + } >> + >> + if ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) =3D= =3D 0) { >> + if ((Cdb->DBsize !=3D 0)) { >> + Db =3D (PXE_DB_RECEIVE_FILTERS *)(UINTN)Cdb->DBaddr; >> + CopyMem (Db, &Nic->McastList, Nic->McastCount); >> + } >> + } >> + >> + break; >> + >> + case PXE_OPFLAGS_RECEIVE_FILTER_ENABLE: >> + if (NewFilter =3D=3D 0) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + >> + if (Cdb->CPBsize !=3D 0) { >> + if (((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST= ) =3D=3D 0) || >> + ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) = !=3D 0) || >> + ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) != =3D 0) || >> + ((Cdb->CPBsize % sizeof (PXE_MAC_ADDR)) !=3D 0)) >> + { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + } >> + >> + if ((Cdb->OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST= ) !=3D 0) { >> + if (((Cdb->OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIS= T) !=3D 0) || >> + ((Cdb->OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) = !=3D 0)) >> + { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + >> + if ((Cdb->CPBsize =3D=3D 0)) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + } >> + >> + Cdb->StatCode =3D SetFilter (Nic, NewFilter, Cdb->CPBaddr, Cdb->C= PBsize); >> + break; >> + >> + case PXE_OPFLAGS_RECEIVE_FILTER_DISABLE: >> + if (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> + } >> + >> + break; >> + >> + default: >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> + } >> + >> + Cdb->StatFlags =3D (PXE_STATFLAGS)(Cdb->StatFlags | Nic->RxFilter); >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiReceiveFilter !=3D NULL) { >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiReceiveFilter (Cdb, Ni= c); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags =3D 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 =3D 0; >> + Cpb =3D (PXE_CPB_RECEIVE_FILTERS *)(UINTN)CpbAddr; >> + >> + // The Cpb could be NULL.(ref:PXE_CPBADDR_NOT_USED) >> + Nic->RxFilter =3D (UINT8)SetFilter; >> + >> + if (((SetFilter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) !=3D= 0) || (Cpb !=3D NULL)) { >> + if (Cpb !=3D NULL) { >> + Nic->McastCount =3D (UINT8)(CpbSize / PXE_MAC_LENGTH); >> + CopyMem (&Nic->McastList, Cpb, Nic->McastCount); >> + } >> + >> + Nic->UsbEth->UsbEthFunDescriptor (Nic->UsbEth, &UsbEthFunDescriptor= ); >> + if ((UsbEthFunDescriptor.NumberMcFilters << 1) =3D=3D 0) { >> + Nic->RxFilter |=3D PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST; >> + Nic->UsbEth->SetUsbEthPacketFilter (Nic->UsbEth, Nic->RxFilter); >> + } else { >> + Status =3D gBS->AllocatePool (EfiBootServicesData, Nic->McastCoun= t * 6, (VOID **)&McastList); >> + if (EFI_ERROR (Status)) { >> + return PXE_STATCODE_INVALID_PARAMETER; >> + } >> + >> + if (Cpb !=3D NULL) { >> + for (Index1 =3D 0; Index1 < Nic->McastCount; Index1++) { >> + for (Index2 =3D 0; Index2 < 6; Index2++) { >> + McastList[Count++] =3D Cpb->MCastList[Index1][Index2]; >> + } >> + } >> + } >> + >> + Nic->RxFilter |=3D PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST; >> + if (Cpb !=3D 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 address= es >> + 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 !=3D PXE_OPCODE_STATION_ADDRESS) || >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->DBsize !=3D sizeof (PXE_DB_STATION_ADDRESS))) >> + { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> + } >> + >> + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + return; >> + } >> + >> + if (Cdb->OpFlags =3D=3D PXE_OPFLAGS_STATION_ADDRESS_RESET) { >> + if (CompareMem (&Nic->CurrentNodeAddress[0], &Nic->PermNodeAddress[= 0], PXE_MAC_LENGTH) !=3D 0) { >> + for (Index =3D 0; Index < PXE_MAC_LENGTH; Index++) { >> + Nic->CurrentNodeAddress[Index] =3D Nic->PermNodeAddress[Index]; >> + } >> + } >> + } >> + >> + if (Cdb->CPBaddr !=3D 0) { >> + Cpb =3D (PXE_CPB_STATION_ADDRESS *)(UINTN)Cdb->CPBaddr; >> + for (Index =3D 0; Index < PXE_MAC_LENGTH; Index++) { >> + Nic->CurrentNodeAddress[Index] =3D Cpb->StationAddr[Index]; >> + } >> + } >> + >> + if (Cdb->DBaddr !=3D 0) { >> + Db =3D (PXE_DB_STATION_ADDRESS *)(UINTN)Cdb->DBaddr; >> + for (Index =3D 0; Index < PXE_MAC_LENGTH; Index++) { >> + Db->StationAddr[Index] =3D Nic->CurrentNodeAddress[Index]; >> + Db->BroadcastAddr[Index] =3D Nic->BroadcastNodeAddress[Index]; >> + Db->PermanentAddr[Index] =3D Nic->PermNodeAddress[Index]; >> + } >> + } >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStationAddress !=3D NULL) { >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiStationAddress (Cdb, N= ic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags =3D 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 !=3D PXE_OPCODE_STATISTICS) || >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) || >> + (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED)) >> + { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> + } >> + >> + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + return; >> + } >> + >> + if ((Cdb->OpFlags !=3D PXE_OPFLAGS_STATISTICS_RESET) && >> + (Cdb->OpFlags !=3D PXE_OPFLAGS_STATISTICS_READ)) >> + { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> + return; >> + } >> + >> + Cdb->StatCode =3D Statistics (Nic, Cdb->DBaddr, Cdb->DBsize); >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStatistics !=3D NULL) { >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiStatistics (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + } >> +} >> + >> +/** >> + Return data for DB data. >> + >> + @param[in] Nic A pointer to the Network interface controller da= ta. >> + @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 =3D (PXE_DB_STATISTICS *)(UINTN)DbAddr; >> + >> + if (DbSize =3D=3D 0) { >> + return PXE_STATCODE_SUCCESS; >> + } >> + >> + DbStatistic->Supported =3D 0x802; >> + DbStatistic->Data[0x01] =3D Nic->RxFrame; >> + DbStatistic->Data[0x0B] =3D Nic->TxFrame; >> + >> + if (Nic->UsbEth->UsbEthStatistics !=3D NULL) { >> + Status =3D 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 da= ta. >> + >> +**/ >> +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 !=3D PXE_OPCODE_MCAST_IP_TO_MAC) || >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize !=3D sizeof (PXE_CPB_MCAST_IP_TO_MAC)) || >> + (Cdb->DBsize !=3D sizeof (PXE_DB_MCAST_IP_TO_MAC))) >> + { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> + } >> + >> + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + return; >> + } >> + >> + Cpb =3D (PXE_CPB_MCAST_IP_TO_MAC *)(UINTN)Cdb->CPBaddr; >> + Db =3D (PXE_DB_MCAST_IP_TO_MAC *)(UINTN)Cdb->DBaddr; >> + >> + if ((Cdb->OpFlags & PXE_OPFLAGS_MCAST_IPV6_TO_MAC) !=3D 0) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_UNSUPPORTED; >> + return; >> + } >> + >> + Tmp =3D (UINT8 *)(&Cpb->IP.IPv4); >> + >> + if ((Tmp[0] & 0xF0) !=3D 0xE0) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CPB; >> + } >> + >> + Db->MAC[0] =3D 0x01; >> + Db->MAC[1] =3D 0x00; >> + Db->MAC[2] =3D 0x5E; >> + Db->MAC[3] =3D Tmp[1] & 0x7F; >> + Db->MAC[4] =3D Tmp[2]; >> + Db->MAC[5] =3D Tmp[3]; >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiMcastIp2Mac !=3D NULL) { >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiMcastIp2Mac (Cdb, Nic)= ; >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags =3D 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 =3D PXE_STATCODE_UNSUPPORTED; >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiNvData !=3D NULL) { >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiNvData (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + } else { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode =3D 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 !=3D PXE_OPCODE_GET_STATUS) || >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize !=3D PXE_CPBSIZE_NOT_USED) || >> + (Cdb->CPBaddr !=3D PXE_CPBADDR_NOT_USED)) >> + { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> + } >> + >> + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + return; >> + } >> + >> + TmpGetStatus.RxFrameLen =3D 0; >> + TmpGetStatus.reserved =3D 0; >> + Db =3D (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) !=3D 0) { >> + if (Cdb->DBsize =3D=3D 0) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> + return; >> + } >> + >> + NumEntries =3D Cdb->DBsize - sizeof (UINT64); >> + Cdb->DBsize =3D sizeof (UINT32) * 2; >> + >> + for (Index =3D 0; NumEntries >=3D sizeof (UINT64); Index++, NumEntr= ies -=3D sizeof (UINT64)) { >> + if (Nic->TxBufferCount > 0) { >> + Nic->TxBufferCount--; >> + Db->TxBuffer[Index] =3D Nic->MediaHeader[Nic->TxBufferCount]; >> + } >> + } >> + } >> + >> + if ((Cdb->OpFlags & PXE_OPFLAGS_GET_INTERRUPT_STATUS) !=3D 0) { >> + if (Nic->ReceiveStatus !=3D 0) { >> + Cdb->StatFlags |=3D PXE_STATFLAGS_GET_STATUS_RECEIVE; >> + } >> + } >> + >> + if ((Nic->Request.Request =3D=3D USB_CDC_NETWORK_CONNECTION) && (Nic-= >Request.Value =3D=3D NETWORK_DISCONNECT)) { >> + Nic->CableDetect =3D 0; >> + } else if ((Nic->Request.Request =3D=3D USB_CDC_NETWORK_CONNECTION) &= & (Nic->Request.Value =3D=3D NETWORK_CONNECTED)) { >> + Nic->CableDetect =3D 1; >> + } >> + >> + if ((Cdb->OpFlags & PXE_OPFLAGS_GET_MEDIA_STATUS) !=3D 0) { >> + if (Nic->CableDetect =3D=3D 0) { >> + Cdb->StatFlags |=3D PXE_STATFLAGS_GET_STATUS_NO_MEDIA; >> + } >> + } >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetStatus !=3D NULL) { >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiGetStatus (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags =3D 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 !=3D PXE_OPCODE_FILL_HEADER) || >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize !=3D sizeof (PXE_CPB_FILL_HEADER_FRAGMENTED)) || >> + (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) || >> + (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED)) >> + { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> + } >> + >> + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + return; >> + } >> + >> + if (Cdb->CPBsize =3D=3D PXE_CPBSIZE_NOT_USED) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> + return; >> + } >> + >> + if ((Cdb->OpFlags & PXE_OPFLAGS_FILL_HEADER_FRAGMENTED) !=3D 0) { >> + CpbFill =3D (PXE_CPB_FILL_HEADER_FRAGMENTED *)(UINTN)Cdb->CPBaddr; >> + >> + if ((CpbFill->FragCnt =3D=3D 0) || (CpbFill->FragDesc[0].FragLen < = PXE_MAC_HEADER_LEN_ETHER)) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> + return; >> + } >> + >> + MacHeader =3D (EthernetHeader *)(UINTN)CpbFill->FragDesc[= 0].FragAddr; >> + MacHeader->Protocol =3D CpbFill->Protocol; >> + >> + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> + MacHeader->DestAddr[Index] =3D CpbFill->DestAddr[Index]; >> + MacHeader->SrcAddr[Index] =3D CpbFill->SrcAddr[Index]; >> + } >> + } else { >> + CpbFillHeader =3D (PXE_CPB_FILL_HEADER *)(UINTN)Cdb->CPBaddr; >> + >> + MacHeader =3D (EthernetHeader *)(UINTN)CpbFillHeader->Med= iaHeader; >> + MacHeader->Protocol =3D CpbFillHeader->Protocol; >> + >> + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> + MacHeader->DestAddr[Index] =3D CpbFillHeader->DestAddr[Index]; >> + MacHeader->SrcAddr[Index] =3D CpbFillHeader->SrcAddr[Index]; >> + } >> + } >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiFillHeader !=3D NULL) { >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiFillHeader (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + } >> +} >> + >> +/** >> + The Transmit command is used to place a packet into the transmit queu= e. >> + >> + @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 !=3D PXE_OPCODE_TRANSMIT) || >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize !=3D sizeof (PXE_CPB_TRANSMIT)) || >> + (Cdb->DBsize !=3D PXE_DBSIZE_NOT_USED) || >> + (Cdb->DBaddr !=3D PXE_DBADDR_NOT_USED)) >> + { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> + } >> + >> + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; >> + return; >> + } >> + >> + if (Cdb->CPBsize =3D=3D PXE_CPBSIZE_NOT_USED) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> + return; >> + } >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiTransmit !=3D NULL) { >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiTransmit (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + >> + return; >> + } >> + >> + Cdb->StatCode =3D Transmit (Cdb, Nic, Cdb->CPBaddr, Cdb->OpFlags); >> + >> + if (Cdb->StatCode !=3D PXE_STATCODE_SUCCESS) { >> + Cdb->StatFlags =3D 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 controlle= r 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 =3D 0; >> + Counter =3D 0; >> + Cpb =3D (PXE_CPB_TRANSMIT *)(UINTN)CpbAddr; >> + >> + if (Nic->CanTransmit) { >> + return PXE_STATCODE_BUSY; >> + } >> + >> + Nic->CanTransmit =3D TRUE; >> + >> + if ((OpFlags & PXE_OPFLAGS_TRANSMIT_FRAGMENTED) !=3D 0) { >> + return PXE_STATCODE_INVALID_PARAMETER; >> + } >> + >> + Map =3D MapIt ( >> + Nic, >> + Cpb->FrameAddr, >> + Cpb->DataLen + (UINT32)Cpb->MediaheaderLen, >> + TO_DEVICE, >> + (UINT64)(UINTN)&BulkOutData >> + ); >> + >> + if (Map !=3D 0) { >> + Nic->CanTransmit =3D FALSE; >> + return PXE_STATCODE_INVALID_PARAMETER; >> + } >> + >> + if (Nic->TxBufferCount < MAX_XMIT_BUFFERS) { >> + Nic->MediaHeader[Nic->TxBufferCount] =3D Cpb->FrameAddr; >> + Nic->TxBufferCount++; >> + } >> + >> + DataLength =3D (UINTN)(Cpb->DataLen + (UINT32)Cpb->MediaheaderLen); >> + >> + while (1) { >> + if (Counter >=3D 3) { >> + StatCode =3D PXE_STATCODE_BUSY; >> + break; >> + } >> + >> + TransmitLength =3D DataLength; >> + >> + Status =3D Nic->UsbEth->UsbEthTransmit (Cdb, Nic->UsbEth, (VOID *)(= UINTN)BulkOutData, &TransmitLength); >> + if (EFI_ERROR (Status)) { >> + StatCode =3D PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + >> + if (Status =3D=3D EFI_INVALID_PARAMETER) { >> + StatCode =3D PXE_STATCODE_INVALID_PARAMETER; >> + break; >> + } >> + >> + if (Status =3D=3D EFI_DEVICE_ERROR) { >> + StatCode =3D PXE_STATCODE_DEVICE_FAILURE; >> + break; >> + } >> + >> + if (!EFI_ERROR (Status)) { >> + Nic->TxFrame++; >> + StatCode =3D PXE_STATCODE_SUCCESS; >> + break; >> + } >> + >> + Counter++; >> + } >> + >> + UnMapIt ( >> + Nic, >> + Cpb->FrameAddr, >> + Cpb->DataLen + (UINT32)Cpb->MediaheaderLen, >> + TO_DEVICE, >> + BulkOutData >> + ); >> + >> + Nic->CanTransmit =3D 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 !=3D PXE_OPCODE_RECEIVE) || >> + (Cdb->StatCode !=3D PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags !=3D PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >=3D (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize !=3D sizeof (PXE_CPB_RECEIVE)) || >> + (Cdb->DBsize !=3D sizeof (PXE_DB_RECEIVE)) || >> + (Cdb->OpFlags !=3D PXE_OPFLAGS_NOT_USED)) >> + { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode =3D PXE_STATCODE_SUCCESS; >> + } >> + >> + if (Nic->State !=3D PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode =3D PXE_STATCODE_NOT_INITIALIZED; >> + return; >> + } >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiReceive !=3D NULL) { >> + Status =3D Nic->UsbEth->UsbEthUndi.UsbEthUndiReceive (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags =3D PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + >> + return; >> + } >> + >> + Cdb->StatCode =3D Receive (Cdb, Nic, Cdb->CPBaddr, Cdb->DBaddr); >> + >> + if (Cdb->StatCode !=3D PXE_STATCODE_SUCCESS) { >> + Cdb->StatFlags =3D 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 controlle= r 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 =3D PXE_FRAME_TYPE_NONE; >> + NicDevice =3D UNDI_DEV_FROM_NIC (Nic); >> + BulkInData =3D NicDevice->ReceiveBuffer; >> + DataLength =3D (UINTN)Nic->MaxSegmentSize; >> + Cpb =3D (PXE_CPB_RECEIVE *)(UINTN)CpbAddr; >> + Db =3D (PXE_DB_RECEIVE *)(UINTN)DbAddr; >> + >> + if (!BulkInData) { >> + return PXE_STATCODE_INVALID_PARAMETER; >> + } >> + >> + if ((Nic->RateLimitingCreditCount =3D=3D 0) && (Nic->RateLimitingEnab= le =3D=3D TRUE)) { >> + return PXE_STATCODE_NO_DATA; >> + } >> + >> + Status =3D Nic->UsbEth->UsbEthReceive (Cdb, Nic->UsbEth, (VOID *)Bulk= InData, &DataLength); >> + if (EFI_ERROR (Status)) { >> + Nic->ReceiveStatus =3D 0; >> + if (Nic->RateLimitingEnable =3D=3D TRUE) { >> + OriginalTpl =3D gBS->RaiseTPL (TPL_NOTIFY); >> + if (Nic->RateLimitingCreditCount !=3D 0) { >> + Nic->RateLimitingCreditCount--; >> + } >> + >> + gBS->RestoreTPL (OriginalTpl); >> + } >> + >> + return PXE_STATCODE_NO_DATA; >> + } >> + >> + Nic->RxFrame++; >> + >> + if (DataLength !=3D 0) { >> + if (DataLength > Cpb->BufferLen) { >> + DataLength =3D (UINTN)Cpb->BufferLen; >> + } >> + >> + CopyMem ((UINT8 *)(UINTN)Cpb->BufferAddr, (UINT8 *)BulkInData, Data= Length); >> + >> + Header =3D (EthernetHeader *)BulkInData; >> + >> + Db->FrameLen =3D (UINT32)DataLength; >> + Db->MediaHeaderLen =3D PXE_MAC_HEADER_LEN_ETHER; >> + >> + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> + if (Header->DestAddr[Index] !=3D Nic->CurrentNodeAddress[Index]) = { >> + break; >> + } >> + } >> + >> + if (Index >=3D PXE_HWADDR_LEN_ETHER) { >> + FrameType =3D PXE_FRAME_TYPE_UNICAST; >> + } else { >> + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> + if (Header->DestAddr[Index] !=3D Nic->BroadcastNodeAddress[Inde= x]) { >> + break; >> + } >> + } >> + >> + if (Index >=3D PXE_HWADDR_LEN_ETHER) { >> + FrameType =3D PXE_FRAME_TYPE_BROADCAST; >> + } else { >> + if ((Header->DestAddr[0] & 1) =3D=3D 1) { >> + FrameType =3D PXE_FRAME_TYPE_FILTERED_MULTICAST; >> + } else { >> + FrameType =3D PXE_FRAME_TYPE_PROMISCUOUS; >> + } >> + } >> + } >> + >> + Db->Type =3D FrameType; >> + Db->Protocol =3D Header->Protocol; >> + >> + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> + Db->SrcAddr[Index] =3D Header->SrcAddr[Index]; >> + Db->DestAddr[Index] =3D Header->DestAddr[Index]; >> + } >> + } >> + >> + if (FrameType =3D=3D PXE_FRAME_TYPE_NONE) { >> + Nic->ReceiveStatus =3D 0; >> + } else { >> + Nic->ReceiveStatus =3D 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 =3D PXE_ROMID_SIGNATURE; >> + PxeSw->Len =3D (UINT8)sizeof (PXE_SW_UNDI); >> + PxeSw->Fudge =3D 0; >> + PxeSw->IFcnt =3D 0; >> + PxeSw->IFcntExt =3D 0; >> + PxeSw->Rev =3D PXE_ROMID_REV; >> + PxeSw->MajorVer =3D PXE_ROMID_MAJORVER; >> + PxeSw->MinorVer =3D PXE_ROMID_MINORVER; >> + PxeSw->reserved1 =3D 0; >> + >> + PxeSw->Implementation =3D 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_SUPPOR= TED | >> + PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED | >> + PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED | >> + PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED= ; >> + >> + PxeSw->EntryPoint =3D (UINT64)(UINTN)UndiApiEntry; >> + PxeSw->reserved2[0] =3D 0; >> + PxeSw->reserved2[1] =3D 0; >> + PxeSw->reserved2[2] =3D 0; >> + PxeSw->BusCnt =3D 1; >> + PxeSw->BusType[0] =3D PXE_BUSTYPE_USB; >> + PxeSw->Fudge =3D PxeSw->Fudge - CalculateSum8 ((VOID *)PxeSw, = PxeSw->Len); >> +} >> + >> +/** >> + Update NIC number. >> + >> + @param[in] Nic A pointer to the Network interface controll= er 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 =3D (PxeSw->IFcnt | PxeSw->IFcntExt << 8); >> + >> + if (Nic =3D=3D NULL) { >> + if (NicNum > 0) { >> + NicNum--; >> + } >> + >> + PxeSw->IFcnt =3D (UINT8)(NicNum & 0xFF); // Get lower b= yte >> + PxeSw->IFcntExt =3D (UINT8)((NicNum & 0xFF00) >> 8); // Get upper b= yte >> + PxeSw->Fudge =3D (UINT8)(PxeSw->Fudge - CalculateSum8 ((VOID *)P= xeSw, PxeSw->Len)); >> + return; >> + } >> + >> + NicNum++; >> + >> + PxeSw->IFcnt =3D (UINT8)(NicNum & 0xFF); // Get lower byt= e >> + PxeSw->IFcntExt =3D (UINT8)((NicNum & 0xFF00) >> 8); // Get upper byt= e >> + PxeSw->Fudge =3D (UINT8)(PxeSw->Fudge - CalculateSum8 ((VOID *)Pxe= Sw, 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 =3D=3D 0) { >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + CdbPtr =3D (PXE_CDB *)(UINTN)Cdb; >> + Nic =3D &(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 controll= er 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 us= age: >> + 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 =3D (UINT64 *)(UINTN)MappedAddr; >> + >> + if (Nic->PxeStart.Map_Mem =3D=3D 0) { >> + *PhyAddr =3D MemAddr; >> + } else { >> + ((void (*)(UINT64, UINT64, UINT32, UINT32, UINT64))(UINTN) Nic->Pxe= Start.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 se= t >> + to zero only if the Map_Mem() service is also set to zero. >> + >> + @param[in] Nic A pointer to the Network interface controll= er 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 us= age: >> + 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 !=3D 0) { >> + ((void (*)(UINT64, UINT64, UINT32, UINT32, UINT64))(UINTN) Nic->Pxe= Start.UnMap_Mem)( >> + Nic->PxeStart.Unique_ID, >> + MemAddr, >> + Size, >> + Direction, >> + MappedAddr >> + ); >> + } >> + >> + return; >> +} >> diff --git a/UsbNetworkPkg/UsbRndis/ComponentName.c b/UsbNetworkPkg/UsbR= ndis/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 gUsbRndisDriver= NameTable[] =3D { >> + { >> + "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 gUsbRndisCom= ponentName =3D { >> + UsbRndisComponentNameGetDriverName, >> + UsbRndisComponentNameGetControllerName, >> + "eng" >> +}; >> + >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gUsbRndisCo= mponentName2 =3D { >> + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)UsbRndisComponentNameGetDriverNa= me, >> + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)UsbRndisComponentNameGetCont= rollerName, >> + "en" >> +}; >> + >> +/** >> + Retrieves a Unicode string that is the user readable name of the driv= er. >> + >> + This function retrieves the user readable name of a driver in the for= m of a >> + Unicode string. If the driver specified by This has a user readable n= ame 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 sp= ecified >> + 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_PR= OTOCOL or >> + EFI_COMPONENT_NAME_PROTOCOL instance. >> + @param[in] Language A pointer to a Null-terminated ASCII st= ring >> + array indicating the language. This is = the >> + language of the driver name that the ca= ller is >> + requesting, and it must match one of th= e >> + languages specified in SupportedLanguag= es. The >> + number of languages supported by a driv= er is up >> + to the driver writer. Language is speci= fied >> + in RFC 4646 or ISO 639-2 language code = format. >> + @param[out] DriverName A pointer to the Unicode string to retu= rn. >> + This Unicode string is the name of the >> + driver specified by This in the languag= e >> + specified by Language. >> + >> + @retval EFI_SUCCESS The Unicode string for the Driver speci= fied by >> + This and the language specified by Lang= uage 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 s= upport >> + 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 =3D=3D &gUsbRndisComponentName) >> + ); >> +} >> + >> +/** >> + Retrieves a Unicode string that is the user readable name of the cont= roller >> + that is being managed by a driver. >> + >> + This function retrieves the user readable name of the controller spec= ified 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 spe= cified by >> + Language, then a pointer to the controller name is returned in Contro= llerName, >> + 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 do= es not >> + support the language specified by Language, then EFI_UNSUPPORTED is r= eturned. >> + >> + @param[in] This A pointer to the EFI_COMPONENT_NAME2_PR= OTOCOL or >> + EFI_COMPONENT_NAME_PROTOCOL instance. >> + @param[in] Controller The handle of a controller that the dri= ver >> + specified by This is managing. This ha= ndle >> + specifies the controller whose name is = to be >> + returned. >> + @param[in] ChildHandle The handle of the child controller to r= etrieve >> + the name of. This is an optional param= eter that >> + may be NULL. It will be NULL for devic= e >> + drivers. It will also be NULL for a bu= s drivers >> + that wish to retrieve the name of the b= us >> + 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 st= ring >> + array indicating the language. This is= the >> + language of the driver name that the ca= ller is >> + requesting, and it must match one of th= e >> + languages specified in SupportedLanguag= es. The >> + number of languages supported by a driv= er is up >> + to the driver writer. Language is speci= fied in >> + RFC 4646 or ISO 639-2 language code for= mat. >> + @param[out] ControllerName A pointer to the Unicode string to retu= rn. >> + This Unicode string is the name of the >> + controller specified by ControllerHandl= e and >> + ChildHandle in the language specified b= y >> + Language from the point of view of the = driver >> + specified by This. >> + >> + @retval EFI_SUCCESS The Unicode string for the user readabl= e name in >> + the language specified by Language for = the >> + driver specified by This was returned i= n >> + DriverName. >> + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HAN= DLE. >> + @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 cur= rently >> + managing the controller specified by >> + ControllerHandle and ChildHandle. >> + @retval EFI_UNSUPPORTED The driver specified by This does not s= upport >> + 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 =3D { >> + 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 =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &InterfaceDescrip= tor); >> + if (EFI_ERROR (Status)) { >> + return FALSE; >> + } >> + >> + // Check specific device/RNDIS and CDC-DATA >> + if (((InterfaceDescriptor.InterfaceClass =3D=3D 0x2) && >> + (InterfaceDescriptor.InterfaceSubClass =3D=3D 0x2) && >> + (InterfaceDescriptor.InterfaceProtocol =3D=3D 0xFF)) || \ >> + ((InterfaceDescriptor.InterfaceClass =3D=3D 0xEF) && >> + (InterfaceDescriptor.InterfaceSubClass =3D=3D 0x4) && >> + (InterfaceDescriptor.InterfaceProtocol =3D=3D 0x1)) || \ >> + ((InterfaceDescriptor.InterfaceClass =3D=3D 0xA) && >> + (InterfaceDescriptor.InterfaceSubClass =3D=3D 0x0) && >> + (InterfaceDescriptor.InterfaceProtocol =3D=3D 0x00)) >> + ) >> + { >> + return TRUE; >> + } >> + >> + return FALSE; >> +} >> + >> +/** >> + Check if this interface is USB Rndis SubType but not CDC Data interfa= ce >> + >> + @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 =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &InterfaceDescrip= tor); >> + if (EFI_ERROR (Status)) { >> + return FALSE; >> + } >> + >> + // Check for specific device/RNDIS and CDC-DATA >> + if (((InterfaceDescriptor.InterfaceClass =3D=3D 0x2) && >> + (InterfaceDescriptor.InterfaceSubClass =3D=3D 0x2) && >> + (InterfaceDescriptor.InterfaceProtocol =3D=3D 0xFF)) || \ >> + ((InterfaceDescriptor.InterfaceClass =3D=3D 0xEF) && >> + (InterfaceDescriptor.InterfaceSubClass =3D=3D 0x4) && >> + (InterfaceDescriptor.InterfaceProtocol =3D=3D 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_PROTOC= OL instance. >> + @param[in] UsbCdcDataPath A pointer to the EFI_DEVICE_PATH_PROTOC= OL 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 =3D= =3D >> + ((USB_DEVICE_PATH *)UsbCdcDataPath)->ParentPortNumber) >> + { >> + return EFI_SUCCESS; >> + } else { >> + return EFI_UNSUPPORTED; >> + } >> + } else { >> + if (CompareMem (UsbCdcDataPath, UsbRndisDataPath, sizeof (EFI_DEV= ICE_PATH_PROTOCOL)) !=3D 0) { >> + return EFI_UNSUPPORTED; >> + } >> + >> + UsbRndisDataPath =3D NextDevicePathNode (UsbRndisDataPath); >> + UsbCdcDataPath =3D NextDevicePathNode (UsbCdcDataPath); >> + } >> + } >> + >> + DEBUG ((DEBUG_VERBOSE, "IsSameDevice Exit \n")); >> +} >> + >> +/** >> + Check if the USB CDC Data(UsbIo) installed and return USB CDC Data Ha= ndle. >> + >> + @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 =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &InterfaceDescrip= tor); >> + if (EFI_ERROR (Status)) { >> + return FALSE; >> + } >> + >> + // Check for CDC-DATA >> + if ((InterfaceDescriptor.InterfaceClass =3D=3D 0xA) && >> + (InterfaceDescriptor.InterfaceSubClass =3D=3D 0x0) && >> + (InterfaceDescriptor.InterfaceProtocol =3D=3D 0x0)) >> + { >> + return TRUE; >> + } >> + >> + return FALSE; >> +} >> + >> +/** >> + Check if the USB Rndis(UsbIo) installed >> + >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instanc= e. >> + >> + @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 =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &InterfaceDescrip= tor); >> + if (EFI_ERROR (Status)) { >> + return FALSE; >> + } >> + >> + // Check for Rndis >> + if ((InterfaceDescriptor.InterfaceClass =3D=3D 0x2) && >> + (InterfaceDescriptor.InterfaceSubClass =3D=3D 0x2) && >> + (InterfaceDescriptor.InterfaceProtocol =3D=3D 0xFF)) >> + { >> + return TRUE; >> + } >> + >> + return FALSE; >> +} >> + >> +/** >> + Control comes here when a CDC device is found.Check if a RNDIS interf= ace is already found for this device or not. >> + For one device two USBIO will be installed each for CDC and RNDIS int= erface. >> + >> + @param[in] UsbEthPath A pointer to the EFI_DEVICE_PATH_PROTOC= OL instance. >> + @param[out] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE Data. >> + >> + @retval EFI_SUCCESS The USB_RNDIS_DEVICE matching this CD= C Data is found. >> + @retval EFI_NOT_FOUND The USB_RNDIS_DEVICE matching this CD= C 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 =3D FALSE; >> + >> + Status =3D gBS->LocateHandleBuffer ( >> + ByProtocol, >> + &gEdkIIUsbEthProtocolGuid, >> + NULL, >> + &HandleCount, >> + &HandleBuffer >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + for (Index =3D 0; Index < HandleCount; Index++) { >> + Status =3D gBS->HandleProtocol ( >> + HandleBuffer[Index], >> + &gEdkIIUsbEthProtocolGuid, >> + (VOID **)&UsbEthDevice >> + ); >> + if (EFI_ERROR (Status)) { >> + continue; >> + } >> + >> + Status =3D gBS->HandleProtocol ( >> + HandleBuffer[Index], >> + &gEfiUsbIoProtocolGuid, >> + (VOID **)&UsbIo >> + ); >> + if (EFI_ERROR (Status)) { >> + continue; >> + } >> + >> + IsRndisInterfaceFlag =3D IsRndisInterface (UsbIo); >> + if (IsRndisInterfaceFlag =3D=3D FALSE) { >> + continue; >> + } >> + >> + Status =3D gBS->HandleProtocol ( >> + HandleBuffer[Index], >> + &gEfiDevicePathProtocolGuid, >> + (VOID **)&UsbRndisDataPath >> + ); >> + if (EFI_ERROR (Status)) { >> + continue; >> + } >> + >> + Status =3D IsSameDevice (UsbRndisDataPath, UsbCdcDataPath); >> + >> + DEBUG ((DEBUG_VERBOSE, "Rndis IsSameDevice %r\n", Status)); >> + >> + if (!EFI_ERROR (Status)) { >> + *UsbRndisDevice =3D 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 d= ata. >> + >> +**/ >> +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 =3D gBS->HandleProtocol ( >> + UsbRndisDevice->UsbRndisHandle, >> + &gEfiDevicePathProtocolGuid, >> + (VOID **)&UsbRndisDataPath >> + ); >> + >> + if (EFI_ERROR (Status)) { >> + return; >> + } >> + >> + Status =3D gBS->LocateHandleBuffer ( >> + ByProtocol, >> + &gEfiUsbIoProtocolGuid, >> + NULL, >> + &HandleCount, >> + &HandleBuffer >> + ); >> + if (EFI_ERROR (Status)) { >> + return; >> + } >> + >> + for (Index =3D 0; Index < HandleCount; Index++) { >> + Status =3D gBS->HandleProtocol ( >> + HandleBuffer[Index], >> + &gEfiUsbIoProtocolGuid, >> + (VOID **)&UsbIo >> + ); >> + ASSERT_EFI_ERROR (Status); >> + >> + if (IsUsbCdcData (UsbIo)) { >> + DEBUG ((DEBUG_VERBOSE, "Rndis FindMatchingCdcData CDCData interfa= ce found\n")); >> + >> + Status =3D gBS->HandleProtocol ( >> + HandleBuffer[Index], >> + &gEfiDevicePathProtocolGuid, >> + (VOID **)&UsbCdcDataPath >> + ); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_VERBOSE, "Rndis CDCData DevicePath not found\n"))= ; >> + FreePool (HandleBuffer); >> + return; >> + } >> + >> + Status =3D IsSameDevice (UsbRndisDataPath, UsbCdcDataPath); >> + DEBUG ((DEBUG_VERBOSE, "Rndis IsSameDevice %r\n", Status)); >> + if (!EFI_ERROR (Status)) { >> + UsbRndisDevice->UsbCdcDataHandle =3D HandleBuffer[Index]; >> + UsbRndisDevice->UsbIoCdcData =3D 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 exi= sts or not. >> + >> + @param[in] CdcHandle A pointer to the EFI_HANDLE for USB CDC D= ata. >> + @param[out] CdcUsbIo A pointer for retrieve the EFI_USB_IO_PRO= TOCOL instance. >> + @param[out] RndisHandle A pointer for retrieve the handle of RNDI= S device. >> + >> + @retval EFI_SUCCESS The USB_RNDIS_DEVICE matching this CD= C Data is found. >> + @retval EFI_NOT_FOUND The USB_RNDIS_DEVICE matching this CD= C 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 =3D gBS->HandleProtocol ( >> + CdcHandle, >> + &gEfiDevicePathProtocolGuid, >> + (VOID **)&UsbCdcDataPath >> + ); >> + >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + Status =3D gBS->LocateHandleBuffer ( >> + ByProtocol, >> + &gEfiUsbIoProtocolGuid, >> + NULL, >> + &HandleCount, >> + &HandleBuffer >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + for (Index =3D 0; Index < HandleCount; Index++) { >> + Status =3D gBS->HandleProtocol ( >> + HandleBuffer[Index], >> + &gEfiUsbIoProtocolGuid, >> + (VOID **)&UsbIo >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + if (IsUsbRndis (UsbIo)) { >> + Status =3D gBS->HandleProtocol ( >> + HandleBuffer[Index], >> + &gEfiDevicePathProtocolGuid, >> + (VOID **)&UsbRndisDataPath >> + ); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "Usb Rndis DevicePath not found\n")); >> + break; >> + } >> + >> + Status =3D IsSameDevice (UsbRndisDataPath, UsbCdcDataPath); >> + >> + if (!EFI_ERROR (Status)) { >> + *RndisHandle =3D HandleBuffer[Index]; >> + *CdcUsbIo =3D 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 =3D gBS->OpenProtocol ( >> + ControllerHandle, >> + &gEfiUsbIoProtocolGuid, >> + (VOID **)&UsbIo, >> + This->DriverBindingHandle, >> + ControllerHandle, >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + Status =3D 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 t= o. >> + @param[in] RemainingDevicePath Optional parameter use to pick a = specific child >> + device to start. >> + >> + @retval EFI_SUCCESS This driver is added to Controlle= rHandle >> + @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 succ= essfully 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 =3D ControllerHandle; >> + >> + Status =3D gBS->OpenProtocol ( >> + ControllerHandle, >> + &gEfiUsbIoProtocolGuid, >> + (VOID **)&UsbIo, >> + This->DriverBindingHandle, >> + ControllerHandle, >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + Status =3D 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 =3D UpdateRndisDevice ( >> + UsbEthPath, >> + &UsbRndisDevice >> + ); >> + >> + if (!EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_INFO, "Rndis Matching interface found\n")); >> + UsbRndisDevice->UsbCdcDataHandle =3D ControllerHandle; >> + UsbRndisDevice->UsbIoCdcData =3D UsbIo; >> + GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice); >> + return Status; >> + } else { >> + // Check if RnDis exist >> + Status =3D FindMatchingRndisDev ( >> + ControllerHandle, >> + &UsbIo, >> + &RndisHandle >> + ); >> + >> + if (EFI_ERROR (Status)) { >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEfiUsbIoProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + return Status; >> + } >> + } >> + } >> + >> + UsbRndisDevice =3D 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 =3D LoadAllDescriptor ( >> + UsbIo, >> + &UsbRndisDevice->Config >> + ); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "%a:LoadAllDescriptor status =3D %r\n", __FUNC= TION__, Status)); >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEfiUsbIoProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + FreePool (UsbRndisDevice); >> + return Status; >> + } >> + >> + Status =3D UsbIo->UsbGetInterfaceDescriptor ( >> + UsbIo, >> + &Interface >> + ); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "%a:UsbGetInterfaceDescriptor status =3D %r\n"= , __FUNCTION__, Status)); >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEfiUsbIoProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + FreePool (UsbRndisDevice->Config); >> + FreePool (UsbRndisDevice); >> + return Status; >> + } >> + >> + UsbRndisDevice->Signature =3D USB_RNDIS_SIGN= ATURE; >> + UsbRndisDevice->NumOfInterface =3D Interface.Inte= rfaceNumber; >> + UsbRndisDevice->UsbRndisHandle =3D RndisHandle; >> + UsbRndisDevice->UsbCdcDataHandle =3D 0; >> + UsbRndisDevice->UsbIo =3D UsbIo; >> + UsbRndisDevice->UsbEth.UsbEthReceive =3D RndisUndiRecei= ve; >> + UsbRndisDevice->UsbEth.UsbEthTransmit =3D RndisUndiTrans= mit; >> + UsbRndisDevice->UsbEth.UsbEthInterrupt =3D UsbRndisInterr= upt; >> + UsbRndisDevice->UsbEth.UsbEthMacAddress =3D GetUsbEthMacAd= dress; >> + UsbRndisDevice->UsbEth.UsbEthMaxBulkSize =3D UsbEthBulkSize= ; >> + UsbRndisDevice->UsbEth.UsbHeaderFunDescriptor =3D GetUsbHeaderFu= nDescriptor; >> + UsbRndisDevice->UsbEth.UsbUnionFunDescriptor =3D GetUsbUnionFun= Descriptor; >> + UsbRndisDevice->UsbEth.UsbEthFunDescriptor =3D GetUsbRndisFun= Descriptor; >> + UsbRndisDevice->UsbEth.SetUsbEthMcastFilter =3D SetUsbRndisMca= stFilter; >> + UsbRndisDevice->UsbEth.SetUsbEthPowerPatternFilter =3D SetUsbRndisPow= erFilter; >> + UsbRndisDevice->UsbEth.GetUsbEthPowerPatternFilter =3D GetUsbRndisPow= erFilter; >> + UsbRndisDevice->UsbEth.SetUsbEthPacketFilter =3D SetUsbRndisPac= ketFilter; >> + UsbRndisDevice->UsbEth.GetUsbEthStatistic =3D GetRndisStatis= tic; >> + >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetState =3D Rndis= DummyReturn; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStart =3D Rndis= UndiStart; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStop =3D Rndis= UndiStop; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetInitInfo =3D Rndis= UndiGetInitInfo; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetConfigInfo =3D Rndis= UndiGetConfigInfo; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiInitialize =3D Rndis= UndiInitialize; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiReset =3D Rndis= UndiReset; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiShutdown =3D Rndis= UndiShutdown; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiInterruptEnable =3D Rndis= DummyReturn; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiReceiveFilter =3D Rndis= UndiReceiveFilter; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStationAddress =3D Rndis= DummyReturn; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStatistics =3D NULL; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiMcastIp2Mac =3D Rndis= DummyReturn; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiNvData =3D Rndis= DummyReturn; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetStatus =3D Rndis= UndiGetStatus; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiFillHeader =3D Rndis= DummyReturn; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiTransmit =3D NULL; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiReceive =3D NULL; >> + >> + UsbRndisDevice->MaxTransferSize =3D RNDIS_MAX_TRANSFER_SIZE; >> + UsbRndisDevice->MaxPacketsPerTransfer =3D 1; >> + UsbRndisDevice->PacketAlignmentFactor =3D 0; >> + >> + InitializeListHead (&UsbRndisDevice->ReceivePacketList); >> + >> + // This is a RNDIS interface. See whether CDC-DATA interface has alre= ady been connected or not >> + FindMatchingCdcData (UsbRndisDevice); >> + >> + if (UsbRndisDevice->UsbIoCdcData) { >> + Status =3D 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->UsbR= ndisHandle)); >> + DEBUG ((DEBUG_INFO, "CDC DeviceHandle %r\n", UsbRndisDevice->UsbCdc= DataHandle)); >> + 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 =3D gBS->OpenProtocol ( >> + ControllerHandle, >> + &gEfiUsbIoProtocolGuid, >> + (VOID **)&UsbIo, >> + This->DriverBindingHandle, >> + ControllerHandle, >> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + if (IsUsbRndis (UsbIo)) { >> + Status =3D 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 ChildHandleBuf= fer. If number of >> + children is zero stop the entire bu= s driver. >> + @param[in] ChildHandleBuffer List of Child Handles to Stop. >> + >> + @retval EFI_SUCCESS This driver is removed ControllerHa= ndle >> + @retval other This driver was not removed from th= is 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", Cont= rollerHandle)); >> + >> + Status =3D gBS->OpenProtocol ( >> + ControllerHandle, >> + &gEdkIIUsbEthProtocolGuid, >> + (VOID **)&UsbEthProtocol, >> + This->DriverBindingHandle, >> + ControllerHandle, >> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >> + ); >> + if (EFI_ERROR (Status)) { >> + Status =3D CheckandStopRndisDevice (This, ControllerHandle); >> + return Status; >> + } >> + >> + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (UsbEthProtocol); >> + >> + Status =3D gBS->CloseProtocol ( >> + UsbRndisDevice->UsbCdcDataHandle, >> + &gEfiUsbIoProtocolGuid, >> + This->DriverBindingHandle, >> + UsbRndisDevice->UsbCdcDataHandle >> + ); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "%a:CloseProtocol status =3D %r\n", __FUNCTION= __, Status)); >> + } >> + >> + Status =3D gBS->UninstallProtocolInterface ( >> + ControllerHandle, >> + &gEdkIIUsbEthProtocolGuid, >> + UsbEthProtocol >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + Status =3D 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 B= inding >> + Protocols together with Component Name Protocols. >> + >> + @param[in] ImageHandle The firmware allocated handle for the E= FI image. >> + @param[in] SystemTable A pointer to the EFI System Table. >> + >> + @retval EFI_SUCCESS The entry point is executed successfull= y. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +UsbRndisEntry ( >> + IN EFI_HANDLE ImageHandle, >> + IN EFI_SYSTEM_TABLE *SystemTable >> + ) >> +{ >> + gUsbRndisDriverBinding.DriverBindingHandle =3D ImageHandle; >> + gUsbRndisDriverBinding.ImageHandle =3D ImageHandle; >> + >> + return gBS->InstallMultipleProtocolInterfaces ( >> + &gUsbRndisDriverBinding.DriverBindingHandle, >> + &gEfiDriverBindingProtocolGuid, >> + &gUsbRndisDriverBinding, >> + &gEfiComponentName2ProtocolGuid, >> + &gUsbRndisComponentName2, >> + NULL >> + ); >> +} >> diff --git a/UsbNetworkPkg/UsbRndis/UsbRndisFunction.c b/UsbNetworkPkg/U= sbRndis/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 =3D 0; >> +UINT16 gBlockBulkInCnt =3D 0; >> + >> +/** >> + Load All of device descriptor. >> + >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCO= L instance. >> + @param[out] ConfigDesc A pointer to the configuration desc= riptor. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_OUT_OF_RESOURCES The request could not be completed beca= use the >> + buffer specified by DescriptorLength an= d Descriptor >> + is not large enough to hold the result = of the request. >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. 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 =3D UsbIo->UsbGetConfigDescriptor (UsbIo, &Tmp); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "%a:UsbGetConfigDescriptor status =3D %r\n", _= _FUNCTION__, Status)); >> + return Status; >> + } >> + >> + Status =3D gBS->AllocatePool ( >> + EfiBootServicesData, >> + Tmp.TotalLength, >> + (VOID **)ConfigDesc >> + ); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "%a: AllocatePool status =3D %r\n", __FUNCTION= __, Status)); >> + return Status; >> + } >> + >> + Status =3D 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 descriptor= s >> + 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 =3D=3D NULL) || (*Offset >=3D Desc->TotalLength)) { >> + return FALSE; >> + } >> + >> + if (((EFI_USB_CONFIG_DESCRIPTOR *)((char *)Desc+*Offset))->Length =3D= =3D 0) { >> + return FALSE; >> + } >> + >> + *Offset +=3D ((EFI_USB_CONFIG_DESCRIPTOR *)((char *)Desc+*Offset))->L= ength; >> + if ( *Offset >=3D 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 retri= eved >> + successfully. >> + @retval EFI_UNSUPPORTED No supported. >> + @retval EFI_NOT_FOUND The device capability descriptor was not f= ound. >> + >> +**/ >> +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 =3D EFI_NOT_FOUND; >> + >> + for (Offset =3D 0; NextDescriptor (Config, &Offset);) { >> + Interface =3D (EFI_USB_INTERFACE_DESCRIPTOR *)((UINT8 *)Config + Of= fset); >> + if (Interface->DescriptorType =3D=3D CS_INTERFACE) { >> + if (((USB_HEADER_FUN_DESCRIPTOR *)Interface)->DescriptorSubtype = =3D=3D 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 =3D 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 ins= tance. >> + >> +**/ >> +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 =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "%a:UsbGetInterfaceDescriptor status =3D %r\n"= , __FUNCTION__, Status)); >> + return; >> + } >> + >> + if (Interface.NumEndpoints =3D=3D 0 ) { >> + Status =3D UsbSetInterface (UsbIo, 1, 0, &Result); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "%a:UsbSetInterface status =3D %r\n", __FUNC= TION__, Status)); >> + return; >> + } >> + >> + Status =3D UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "%a:UsbGetInterfaceDescriptor status =3D %r\= n", __FUNCTION__, Status)); >> + return; >> + } >> + } >> + >> + for (Index =3D 0; Index < Interface.NumEndpoints; Index++) { >> + Status =3D UsbIo->UsbGetEndpointDescriptor (UsbIo, Index, &Endpoint= ); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "%a:UsbGetEndpointDescriptor status =3D %r\n= ", __FUNCTION__, Status)); >> + return; >> + } >> + >> + switch ((Endpoint.Attributes & (BIT0 | BIT1))) { >> + case USB_ENDPOINT_BULK: >> + if (Endpoint.EndpointAddress & BIT7) { >> + UsbRndisDevice->BulkInEndpoint =3D Endpoint.EndpointAddress; >> + } else { >> + UsbRndisDevice->BulkOutEndpoint =3D Endpoint.EndpointAddress; >> + } >> + >> + break; >> + case USB_ENDPOINT_INTERRUPT: >> + UsbRndisDevice->InterrupEndpoint =3D Endpoint.EndpointAddress; >> + break; >> + } >> + } >> +} >> + >> +/** >> + Async USB transfer callback routine. >> + >> + @param[in] Data Data received or sent via the USB Asynchr= onous Transfer, if the >> + transfer completed successfully. >> + @param[in] DataLength The length of Data received or sent via t= he Asynchronous >> + Transfer, if transfer successfully comple= tes. >> + @param[in] Context Data passed from UsbAsyncInterruptTransfe= r() request. >> + @param[in] Status Indicates the result of the asynchronous = transfer. >> + >> + @retval EFI_SUCCESS The asynchronous USB transfer request h= as been successfully executed. >> + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request f= ailed. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +InterruptCallback ( >> + IN VOID *Data, >> + IN UINTN DataLength, >> + IN VOID *Context, >> + IN UINT32 Status >> + ) >> +{ >> + if ((Data =3D=3D NULL) || (Context =3D=3D NULL)) { >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + if (((EFI_USB_DEVICE_REQUEST *)Data)->Request =3D=3D 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 transf= er pipe. >> + >> + @param[in] This A pointer to the EDKII_USB_ETHERNET_PRO= TOCOL instance. >> + @param[in] IsNewTransfer If TRUE, a new transfer will be submitt= ed to USB controller. If >> + FALSE, the interrupt transfer is delete= d from the device's interrupt >> + transfer queue. >> + @param[in] PollingInterval Indicates the periodic rate, in millise= conds, that the transfer is to be >> + executed.This parameter is required whe= n IsNewTransfer is TRUE. The >> + value must be between 1 to 255, otherwi= se 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 t= ransfer has been successfully executed. >> + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request f= ailed. >> + >> +**/ >> +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 =3D USB_RNDIS_DEVICE_FROM_THIS (This); >> + DataLength =3D 0; >> + >> + if (IsNewTransfer =3D=3D TRUE) { >> + DataLength =3D sizeof (EFI_USB_DEVICE_REQUEST) + sizeof (USB_CONNEC= T_SPEED_CHANGE); >> + Status =3D UsbRndisDevice->UsbIo->UsbAsyncInterruptTransfer ( >> + UsbRndisDevice->UsbIo, >> + UsbRndisDevice->InterrupEndpo= int, >> + IsNewTransfer, >> + PollingInterval, >> + DataLength, >> + InterruptCallback, >> + Requst >> + ); >> + >> + if (Status =3D=3D EFI_INVALID_PARAMETER) { >> + // Because of Stacked AsyncInterrupt request are not supported >> + Status =3D UsbRndisDevice->UsbIo->UsbAsyncInterruptTransfer ( >> + UsbRndisDevice->UsbIo, >> + UsbRndisDevice->InterrupEndpoin= t, >> + 0, >> + 0, >> + 0, >> + NULL, >> + NULL >> + ); >> + } >> + } else { >> + Status =3D 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 respo= nse RNDIS message. >> + >> + @param[in] This A pointer to the USB_RNDIS_DEVICE insta= nce. >> + >> + @retval EFI_SUCCESS The USB interrupt transfer has been suc= cessfully 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 =3D 8; >> + >> + ZeroMem (Data, sizeof (Data)); >> + >> + Status =3D 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_PROTOCO= L instance. >> + @param[out] MacAddress A pointer to the caller allocated USB Ether= net Mac Address. >> + >> + @retval EFI_SUCCESS The USB Header Functional descriptor wa= s retrieved successfully. >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor wa= s 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 =3D 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 =3D RNDIS_QUERY_MSG; >> + RndisQueryMsg.QueryMsg.MessageLength =3D sizeof (REMOTE_NDIS_QUERY_MA= C_MSG); >> + RndisQueryMsg.QueryMsg.RequestID =3D UsbRndisDevice->RequestId; >> + RndisQueryMsg.QueryMsg.Oid =3D OID_802_3_CURRENT_ADDRESS; >> + >> + RndisQueryMsgCmplt.QueryCmplt.MessageType =3D RNDIS_QUERY_CMPLT; >> + RndisQueryMsgCmplt.QueryCmplt.MessageLength =3D sizeof (REMOTE_NDIS_Q= UERY_MAC_CMPLT); >> + >> + Status =3D 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 =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> + MacAddress->Addr[Index] =3D 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 =3D This->UsbEthFunDescriptor (This, &UsbEthDescriptor); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "%a:UsbEthFunDescriptor status =3D %r\n", __FU= NCTION__, Status)); >> + return Status; >> + } >> + >> + Status =3D UsbRndisDevice->UsbIo->UsbGetStringDescriptor ( >> + UsbRndisDevice->UsbIo, >> + 0x409, // Eng= lish-US Language ID >> + UsbEthDescriptor.MacAddress, >> + &Data >> + ); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "%a:UsbGetStringDescriptor status =3D %r\n", _= _FUNCTION__, Status)); >> + return Status; >> + } >> + >> + DataPtr =3D Data; >> + for (Index =3D 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> + CopyMem (TmpStr, DataPtr, sizeof (CHAR16)); >> + DataPtr++; >> + Hi =3D (UINT8)StrHexToUintn (TmpStr); >> + CopyMem (TmpStr, DataPtr, sizeof (CHAR16)); >> + DataPtr++; >> + Low =3D (UINT8)StrHexToUintn (TmpStr); >> + MacAddress->Addr[Index] =3D (Hi << 4) | Low; >> + } >> + >> + return Status; >> +} >> + >> +/** >> + Retrieves the USB Ethernet Bulk transfer data size. >> + >> + @param[in] This A pointer to the EDKII_USB_ETHERNET_PROTOCO= L instance. >> + @param[out] BulkSize A pointer to the Bulk transfer data size. >> + >> + @retval EFI_SUCCESS The bulk transfer data size was retrieved s= uccessfully. >> + @retval other Failed to retrieve the bulk transfer data s= ize. >> + >> +**/ >> +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 =3D USB_RNDIS_DEVICE_FROM_THIS (This); >> + >> + ZeroMem (&RndisQueryMsg, sizeof (REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_MSG= )); >> + ZeroMem (&RndisQueryMsgCmplt, sizeof (REMOTE_NDIS_QUERY_MAX_TOTAL_SIZ= E_CMPLT)); >> + >> + RndisQueryMsg.QueryMsg.MessageType =3D RNDIS_QUERY_MSG; >> + RndisQueryMsg.QueryMsg.MessageLength =3D sizeof (REMOTE_NDIS_QUERY_MA= X_TOTAL_SIZE_MSG); >> + RndisQueryMsg.QueryMsg.RequestID =3D UsbRndisDevice->RequestId; >> + RndisQueryMsg.QueryMsg.Oid =3D OID_GEN_MAXIMUM_TOTAL_SIZE; >> + >> + RndisQueryMsgCmplt.QueryCmplt.MessageType =3D RNDIS_QUERY_CMPLT; >> + RndisQueryMsgCmplt.QueryCmplt.MessageLength =3D sizeof (REMOTE_NDIS_Q= UERY_MAX_TOTAL_SIZE_CMPLT); >> + >> + Status =3D 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", Rndis= QueryMsgCmplt.MaxTotalSize)); >> + *BulkSize =3D RndisQueryMsgCmplt.MaxTotalSize; >> + UsbRndisDevice->RequestId++; >> + return Status; >> + } >> + >> + Status =3D This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + *BulkSize =3D (UINTN)UsbEthFunDescriptor.MaxSegmentSize; >> + return Status; >> +} >> + >> +/** >> + Retrieves the USB Header functional Descriptor. >> + >> + @param[in] This A pointer to the EDKII_USB_ETHERNE= T_PROTOCOL instance. >> + @param[out] UsbHeaderFunDescriptor A pointer to the caller allocated = USB Header Functional Descriptor. >> + >> + @retval EFI_SUCCESS The USB Header Functional descriptor wa= s retrieved successfully. >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor wa= s 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 =3D USB_RNDIS_DEVICE_FROM_THIS (This); >> + >> + if (UsbHeaderFunDescriptor =3D=3D NULL) { >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + Status =3D GetFunctionalDescriptor ( >> + UsbRndisDevice->Config, >> + HEADER_FUN_DESCRIPTOR, >> + UsbHeaderFunDescriptor >> + ); >> + return Status; >> +} >> + >> +/** >> + Retrieves the USB Union functional Descriptor. >> + >> + @param[in] This A pointer to the EDKII_USB_ETHERNE= T_PROTOCOL instance. >> + @param[out] UsbUnionFunDescriptor A pointer to the caller allocated = USB Union Functional Descriptor. >> + >> + @retval EFI_SUCCESS The USB Union Functional descriptor wa= s retrieved successfully. >> + @retval EFI_INVALID_PARAMETER UsbUnionFunDescriptor is NULL. >> + @retval EFI_NOT_FOUND The USB Union Functional descriptor wa= s 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 =3D USB_RNDIS_DEVICE_FROM_THIS (This); >> + >> + if (UsbUnionFunDescriptor =3D=3D NULL) { >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + Status =3D GetFunctionalDescriptor ( >> + UsbRndisDevice->Config, >> + UNION_FUN_DESCRIPTOR, >> + UsbUnionFunDescriptor >> + ); >> + return Status; >> +} >> + >> +/** >> + Retrieves the USB Ethernet functional Descriptor. >> + >> + This function get the Mac Address, Ethernet statistics, maximum segme= nt size, >> + number of multicast filters, and number of pattern filters from Ether= net >> + functional Descriptor. >> + >> + @param[in] This A pointer to the EDKII_USB_ETHERNE= T_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 =3D USB_RNDIS_DEVICE_FROM_THIS (This); >> + >> + if (UsbEthFunDescriptor =3D=3D NULL) { >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + Status =3D 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_ETHERNE= T_PROTOCOL instance. >> + @param[in] Value Number of filters. >> + @param[in] McastAddr A pointer to the value of the mult= icast addresses. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the reque= st. >> + @retval EFI_DEVICE_ERROR The request failed due to a device err= or. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid v= alue. >> + @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 =3D USB_RNDIS_DEVICE_FROM_THIS (This); >> + >> + Status =3D This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + if ((UsbEthFunDescriptor.NumberMcFilters << 1) =3D=3D 0) { >> + return EFI_UNSUPPORTED; >> + } >> + >> + Request.RequestType =3D USB_ETHERNET_SET_REQ_TYPE; >> + Request.Request =3D SET_ETH_MULTICAST_FILTERS_REQ; >> + Request.Value =3D Value; >> + Request.Index =3D UsbRndisDevice->NumOfInterface; >> + Request.Length =3D 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 patter= n filter data. >> + @param[in] PatternFilter A pointer to the power management p= attern filter structure. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the reque= st. >> + @retval EFI_DEVICE_ERROR The request failed due to a device err= or. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid v= alue. >> + @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 =3D USB_RNDIS_DEVICE_FROM_THIS (This); >> + >> + Request.RequestType =3D USB_ETHERNET_SET_REQ_TYPE; >> + Request.Request =3D SET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ; >> + Request.Value =3D Value; >> + Request.Index =3D UsbRndisDevice->NumOfInterface; >> + Request.Length =3D 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 man= agement >> + pattern filter from the device. >> + >> + @param[in] This A pointer to the EDKII_USB_ETHERNE= T_PROTOCOL instance. >> + @param[in] Value The filter number. >> + @param[out] PatternActive A pointer to the pattern active bo= olean. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the reque= st. >> + @retval EFI_DEVICE_ERROR The request failed due to a device err= or. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid v= alue. >> + @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 =3D USB_RNDIS_DEVICE_FROM_THIS (This); >> + >> + Request.RequestType =3D USB_ETHERNET_GET_REQ_TYPE; >> + Request.Request =3D GET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ; >> + Request.Value =3D Value; >> + Request.Index =3D UsbRndisDevice->NumOfInterface; >> + Request.Length =3D 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[] =3D { >> + { PXE_OPFLAGS_RECEIVE_FILTER_UNICAST, NDIS_PACKET_TYPE_D= IRECTED }, >> + { PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST, NDIS_PACKET_TYPE_B= ROADCAST }, >> + { PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST, NDIS_PACKET_TYPE_M= ULTICAST }, >> + { PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS, NDIS_PACKET_TYPE_P= ROMISCUOUS }, >> + { PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST, NDIS_PACKET_TYPE_A= LL_MULTICAST }, >> + }; >> + >> + Count =3D sizeof (Table)/sizeof (Table[0]); >> + >> + for (Index =3D 0; (Table[Index].Src !=3D 0) && (Index < Count); Index= ++) { >> + if (Table[Index].Src & Value) { >> + *CdcFilter |=3D 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 =3D 0; >> + CpbAddr =3D Cdb->CPBaddr; >> + CpbSize =3D Cdb->CPBsize; >> + SetFilter =3D (UINT16)(Cdb->OpFlags & 0x1F); >> + Cpb =3D (PXE_CPB_RECEIVE_FILTERS *)(UINTN)CpbAddr; >> + >> + // The Cpb could be NULL.(ref:PXE_CPBADDR_NOT_USED) >> + Nic->RxFilter =3D (UINT8)SetFilter; >> + >> + if (((SetFilter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) !=3D= 0) || (Cpb !=3D NULL)) { >> + if (Cpb !=3D NULL) { >> + Nic->McastCount =3D (UINT8)(CpbSize / PXE_MAC_LENGTH); >> + CopyMem (&Nic->McastList, Cpb, Nic->McastCount); >> + } else { >> + Nic->McastCount =3D 0; >> + } >> + >> + Nic->UsbEth->UsbEthFunDescriptor (Nic->UsbEth, &UsbEthFunDescriptor= ); >> + if ((UsbEthFunDescriptor.NumberMcFilters << 1) =3D=3D 0) { >> + Nic->RxFilter |=3D PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST; >> + DEBUG ((DEBUG_INFO, "SetUsbEthPacketFilter Nic %lx Nic->UsbEth %l= x ", Nic, Nic->UsbEth)); >> + Nic->UsbEth->SetUsbEthPacketFilter (Nic->UsbEth, Nic->RxFilter); >> + } else { >> + Status =3D gBS->AllocatePool (EfiBootServicesData, Nic->McastCoun= t * 6, (VOID **)&McastList); >> + if (EFI_ERROR (Status)) { >> + return PXE_STATCODE_INVALID_PARAMETER; >> + } >> + >> + if (Cpb !=3D NULL) { >> + for (Index1 =3D 0; Index1 < Nic->McastCount; Index1++) { >> + for (Index2 =3D 0; Index2 < 6; Index2++) { >> + McastList[Count++] =3D Cpb->MCastList[Index1][Index2]; >> + } >> + } >> + } >> + >> + Nic->RxFilter |=3D PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST; >> + if (Cpb !=3D 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 setti= ngs. >> + >> + @param[in] This A pointer to the EDKII_USB_ETHERNET_PRO= TOCOL instance. >> + @param[in] Value Packet Filter Bitmap. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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 sel= ector. >> + >> + @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 in= teger. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the reques= t. >> + @retval EFI_DEVICE_ERROR The request failed due to a device erro= r. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid va= lue. >> + @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 st= ate >> + Status =3D RndisUndiReset (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + RndisUndiReset (Cdb, Nic); >> + } >> + >> + Status =3D 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 =3D Nic->UsbEth; >> + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (UsbEthDevice); >> + >> + Db =3D (PXE_DB_GET_INIT_INFO *)(UINTN)Cdb->DBaddr; >> + >> + Db->FrameDataLen =3D 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 =3D 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 =3D Nic->UsbEth; >> + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (UsbEthDriver); >> + >> + ZeroMem (&RndisInitMsg, sizeof (REMOTE_NDIS_INITIALIZE_MSG)); >> + ZeroMem (&RndisInitMsgCmplt, sizeof (REMOTE_NDIS_INITIALIZE_CMPLT)); >> + >> + RndisInitMsg.MessageType =3D RNDIS_INITIALIZE_MSG; >> + RndisInitMsg.MessageLength =3D sizeof (REMOTE_NDIS_INITIALIZE_MSG); >> + RndisInitMsg.RequestID =3D UsbRndisDevice->RequestId; >> + RndisInitMsg.MajorVersion =3D RNDIS_MAJOR_VERSION; >> + RndisInitMsg.MinorVersion =3D RNDIS_MINOR_VERSION; >> + RndisInitMsg.MaxTransferSize =3D RNDIS_MAX_TRANSFER_SIZE; >> + >> + RndisInitMsgCmplt.MessageType =3D RNDIS_INITIALIZE_CMPLT; >> + RndisInitMsgCmplt.MessageLength =3D sizeof (REMOTE_NDIS_INITIALIZE_CM= PLT); >> + >> + Status =3D 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 =3D RndisInitMsgCmplt.Medium; >> + UsbRndisDevice->MaxPacketsPerTransfer =3D RndisInitMsgCmplt.MaxPacket= sPerTransfer; >> + UsbRndisDevice->MaxTransferSize =3D RndisInitMsgCmplt.MaxTransf= erSize; >> + UsbRndisDevice->PacketAlignmentFactor =3D RndisInitMsgCmplt.PacketAli= gnmentFactor; >> + >> + DEBUG ((DEBUG_INFO, "Medium : %x \n", RndisInitMsgCmplt.Medium)); >> + DEBUG ((DEBUG_INFO, "MaxPacketsPerTransfer : %x \n", RndisInitMsgCmpl= t.MaxPacketsPerTransfer)); >> + DEBUG ((DEBUG_INFO, "MaxTransferSize : %x\n", RndisInitMsgCmplt.MaxTr= ansferSize)); >> + 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 erro= r. >> + >> +**/ >> +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 =3D Nic->UsbEth; >> + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (UsbEthDriver); >> + >> + ZeroMem (&RndisResetMsg, sizeof (REMOTE_NDIS_RESET_MSG)); >> + ZeroMem (&RndisResetCmplt, sizeof (REMOTE_NDIS_RESET_CMPLT)); >> + >> + RndisResetMsg.MessageType =3D RNDIS_RESET_MSG; >> + RndisResetMsg.MessageLength =3D sizeof (REMOTE_NDIS_RESET_MSG); >> + >> + RndisResetCmplt.MessageType =3D RNDIS_RESET_CMPLT; >> + RndisResetCmplt.MessageLength =3D sizeof (REMOTE_NDIS_RESET_CMPLT); >> + >> + Status =3D RndisControlMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_HEADER *= )&RndisResetMsg, (REMOTE_NDIS_MSG_HEADER *)&RndisResetCmplt); >> + >> + UsbRndisDevice->RequestId =3D 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 =3D Nic->UsbEth; >> + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (UsbEthDriver); >> + >> + ZeroMem (&RndisHltMsg, sizeof (REMOTE_NDIS_HALT_MSG)); >> + >> + RndisHltMsg.MessageType =3D RNDIS_HLT_MSG; >> + RndisHltMsg.MessageLength =3D sizeof (REMOTE_NDIS_HALT_MSG); >> + >> + Status =3D RndisControlMsg (UsbRndisDevice, (REMOTE_NDIS_MSG_HEADER *= )&RndisHltMsg, NULL); >> + >> + if (Status =3D=3D EFI_DEVICE_ERROR) { >> + Status =3D EFI_SUCCESS; >> + } >> + >> + UsbRndisDevice->RequestId =3D 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 &=3D ~(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 blo= ck. >> + @param[in] This A pointer to the EDKII_USB_ETHERNET_PRO= TOCOL instance. >> + @param[in] BulkOutData A pointer to the buffer of data that wi= ll 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", *DataLengt= h)); >> + >> + UsbRndisDevice =3D USB_RNDIS_DEVICE_FROM_THIS (This); >> + >> + RndisPacketMsg =3D AllocateZeroPool (sizeof (REMOTE_NDIS_PACKET_MSG) = + *DataLength); >> + if (RndisPacketMsg =3D=3D NULL) { >> + return EFI_OUT_OF_RESOURCES; >> + } >> + >> + RndisPacketMsg->MessageType =3D RNDIS_PACKET_MSG; >> + RndisPacketMsg->MessageLength =3D sizeof (REMOTE_NDIS_PACKET_MSG) + (= UINT32)*DataLength; >> + RndisPacketMsg->DataOffset =3D sizeof (REMOTE_NDIS_PACKET_MSG) - 8= ; >> + RndisPacketMsg->DataLength =3D (UINT32)*DataLength; >> + >> + CopyMem ( >> + ((UINT8 *)RndisPacketMsg) + sizeof (REMOTE_NDIS_PACKET_MSG), >> + BulkOutData, >> + *DataLength >> + ); >> + >> + TransferLength =3D RndisPacketMsg->MessageLength; >> + >> + Status =3D RndisTransmitDataMsg ( >> + UsbRndisDevice, >> + (REMOTE_NDIS_MSG_HEADER *)RndisPacketMsg, >> + &TransferLength >> + ); >> + >> + DEBUG ((DEBUG_INFO, "\nRndisUndiTransmit TransferLength %lx\n", Trans= ferLength)); >> + >> + FreePool (RndisPacketMsg); >> + >> + return Status; >> +} >> + >> +/** >> + Receives and removes RNDIS header and returns the raw data. >> + >> + @param[in] Cdb A pointer to the command descriptor blo= ck. >> + @param[in] This A pointer to the EDKII_USB_ETHERNET_PRO= TOCOL instance. >> + @param[in, out] BulkInData A pointer to the buffer of data that wi= ll 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 =3D USB_RNDIS_DEVICE_FROM_THIS (This); >> + Buffer =3D NULL; >> + HeadPacket =3D NULL; >> + >> + while (1) { >> + Buffer =3D AllocateZeroPool (sizeof (PACKET_LIST) + sizeof (REMOTE_= NDIS_PACKET_MSG) + UsbRndisDevice->MaxTransferSize); >> + if (Buffer =3D=3D NULL) { >> + return EFI_OUT_OF_RESOURCES; >> + } >> + >> + RndisPacketMsg =3D (REMOTE_NDIS_PACKET_MSG *)(sizeof= (PACKET_LIST) + (UINT8 *)Buffer); >> + PacketList =3D (PACKET_LIST *)Buffer; >> + PacketList->PacketStartBuffer =3D (UINT8 *)Buffer + sizeof (PACKET_= LIST); >> + // Save the original address for freeing it up >> + PacketList->OrgBuffer =3D (UINT8 *)Buffer; >> + TransferLength =3D UsbRndisDevice->MaxTransferSize; >> + >> + Status =3D RndisReceiveDataMsg ( >> + UsbRndisDevice, >> + (REMOTE_NDIS_MSG_HEADER *)RndisPacketMsg, >> + &TransferLength >> + ); >> + >> + if (EFI_ERROR (Status) || (TransferLength =3D=3D 0)) { >> + FreePool (Buffer); >> + break; >> + } >> + >> + // Collect all the RNDIS packet in Linked list. >> + if ((RndisPacketMsg->MessageType =3D=3D RNDIS_PACKET_MSG) && >> + (RndisPacketMsg->DataOffset =3D=3D sizeof (REMOTE_NDIS_PACKET_M= SG) - RNDIS_RESERVED_BYTE_LENGTH) && >> + (TransferLength >=3D RndisPacketMsg->MessageLength)) >> + { >> + // Insert Packet >> + PacketList->RemainingLength =3D TransferLength; >> + InsertTailList (&UsbRndisDevice->ReceivePacketList, Buffer); >> + } else { >> + FreePool (Buffer); >> + } >> + } >> + >> + while (!IsListEmpty (&UsbRndisDevice->ReceivePacketList)) { >> + HeadPacket =3D (PACKET_LIST *)GetFirstNode (&UsbRndisDevice->Receiv= ePacketList); >> + >> + RndisPacketMsg =3D (REMOTE_NDIS_PACKET_MSG *)(UINT8 *)HeadPacket->P= acketStartBuffer; >> + >> + PrintRndisMsg ((REMOTE_NDIS_MSG_HEADER *)RndisPacketMsg); >> + >> + // Check whether the packet is valid RNDIS packet. >> + if ((HeadPacket->RemainingLength > sizeof (REMOTE_NDIS_PACKET_MSG))= && (RndisPacketMsg->MessageType =3D=3D RNDIS_PACKET_MSG) && >> + (RndisPacketMsg->DataOffset =3D=3D (sizeof (REMOTE_NDIS_PACKET_= MSG) - RNDIS_RESERVED_BYTE_LENGTH)) && >> + (HeadPacket->RemainingLength >=3D RndisPacketMsg->MessageLength= )) >> + { >> + if (*DataLength >=3D RndisPacketMsg->DataLength) { >> + CopyMem ( >> + BulkInData, >> + (UINT8 *)RndisPacketMsg + (RndisPacketMsg->DataOffset + RNDIS= _RESERVED_BYTE_LENGTH), >> + RndisPacketMsg->DataLength >> + ); >> + >> + *DataLength =3D RndisPacketMsg->DataLength; >> + >> + HeadPacket->RemainingLength =3D HeadPacket->RemainingLength -= RndisPacketMsg->MessageLength; >> + HeadPacket->PacketStartBuffer =3D (UINT8 *)RndisPacketMsg + Rnd= isPacketMsg->MessageLength; >> + >> + return EFI_SUCCESS; >> + } else { >> + *DataLength =3D 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 end= point >> + >> + @param[in] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE insta= nce. >> + @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 =3D UsbRndisDevice->UsbIo; >> + EFI_USB_DEVICE_REQUEST DevReq; >> + UINT32 UsbStatus; >> + EFI_STATUS Status; >> + UINT32 SaveResponseType; >> + UINT32 SaveResponseLength; >> + UINT32 Index; >> + REMOTE_NDIS_INITIALIZE_CMPLT *RndisInitCmplt; >> + >> + SaveResponseType =3D 0; >> + SaveResponseLength =3D 0; >> + RndisInitCmplt =3D (REMOTE_NDIS_INITIALIZE_CMPLT *)RndisMsgRespon= se; >> + >> + if (RndisMsgResponse) { >> + SaveResponseType =3D RndisMsgResponse->MessageType; >> + SaveResponseLength =3D RndisMsgResponse->MessageLength; >> + } >> + >> + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); >> + >> + DevReq.RequestType =3D USB_REQ_TYPE_CLASS | USB_TARGET_INTERFACE; >> + DevReq.Request =3D SEND_ENCAPSULATED_COMMAND; >> + DevReq.Value =3D 0; >> + DevReq.Index =3D 0; >> + DevReq.Length =3D (UINT16)RndisMsg->MessageLength; >> + >> + PrintRndisMsg (RndisMsg); >> + >> + Status =3D UsbIo->UsbControlTransfer ( >> + UsbIo, >> + &DevReq, >> + EfiUsbDataOut, >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> + RndisMsg, >> + RndisMsg->MessageLength, >> + &UsbStatus >> + ); >> + >> + DEBUG ((DEBUG_INFO, "RndisControlMsg: UsbStatus : %x Status : %r Rndi= sMsgResponse : %lx\n", UsbStatus, Status, RndisMsgResponse)); >> + >> + // Error or no response expected >> + if ((EFI_ERROR (Status)) || (RndisMsgResponse =3D=3D NULL)) { >> + DEBUG ((DEBUG_INFO, "RndisControlMsg: UsbStatus : %x Status : %r\n"= , UsbStatus, Status)); >> + return Status; >> + } >> + >> + for (Index =3D 0; Index < (RNDIS_CONTROL_TIMEOUT/100); Index++) { >> + ReadRndisResponseInterrupt (UsbRndisDevice); >> + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); >> + >> + DevReq.RequestType =3D USB_ENDPOINT_DIR_IN | USB_REQ_TYPE_CLASS | U= SB_TARGET_INTERFACE; >> + DevReq.Request =3D GET_ENCAPSULATED_RESPONSE; >> + DevReq.Value =3D 0; >> + DevReq.Index =3D 0; >> + DevReq.Length =3D (UINT16)RndisMsgResponse->MessageLength; >> + >> + Status =3D UsbIo->UsbControlTransfer ( >> + UsbIo, >> + &DevReq, >> + EfiUsbDataIn, >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> + RndisMsgResponse, >> + RndisMsgResponse->MessageLength, >> + &UsbStatus >> + ); >> + >> + DEBUG ((DEBUG_INFO, "RndisControlMsg Response: UsbStatus : %x Statu= s : %r \n", UsbStatus, Status)); >> + >> + PrintRndisMsg (RndisMsgResponse); >> + >> + if (!EFI_ERROR (Status)) { >> + if ((RndisInitCmplt->RequestID !=3D ((REMOTE_NDIS_INITIALIZE_CMPL= T *)RndisMsg)->RequestID) || (RndisInitCmplt->MessageType !=3D SaveResponse= Type)) { >> + DEBUG ((DEBUG_INFO, "Retry the response\n")); >> + >> + RndisMsgResponse->MessageType =3D SaveResponseType; >> + RndisMsgResponse->MessageLength =3D SaveResponseLength; >> + continue; >> + } >> + } >> + >> + return Status; >> + } >> + >> + DEBUG ((DEBUG_INFO, "RndisControlMsg: TimeOut\n")); >> + >> + return EFI_TIMEOUT; >> +} >> + >> +/** >> + This function send the RNDIS command through the device's Data endpoi= nt >> + >> + @param[in] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE ins= tance. >> + @param[in] RndisMsg A pointer to the REMOTE_NDIS_MSG_HEAD= ER to send out. >> + @param[in, out] TransferLength The length of the RndisMsg data to tr= ansfer. >> + >> + @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 =3D=3D 0) { >> + GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice); >> + } >> + >> + PrintRndisMsg (RndisMsg); >> + >> + Status =3D UsbRndisDevice->UsbIoCdcData->UsbBulkTransfer ( >> + UsbRndisDevice->UsbIoCdcData= , >> + UsbRndisDevice->BulkOutEndpo= int, >> + RndisMsg, >> + TransferLength, >> + USB_TX_ETHERNET_BULK_TIMEOUT= , >> + &UsbStatus >> + ); >> + >> + if (Status =3D=3D EFI_SUCCESS) { >> + gStopBulkInCnt =3D 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 endpoi= nt >> + >> + @param[in] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE i= nstance. >> + @param[in, out] RndisMsg A pointer to the REMOTE_NDIS_MSG_HE= ADER 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 =3D 0; >> + >> + if (UsbRndisDevice->BulkInEndpoint =3D=3D 0) { >> + GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice); >> + } >> + >> + // Use gStopBulkInCnt to stop BulkIn command >> + if (gStopBulkInCnt || LAN_BULKIN_CMD_CONTROL) { >> + Status =3D UsbRndisDevice->UsbIoCdcData->UsbBulkTransfer ( >> + UsbRndisDevice->UsbIoCdcDa= ta, >> + UsbRndisDevice->BulkInEndp= oint, >> + RndisMsg, >> + TransferLength, >> + USB_RX_ETHERNET_BULK_TIMEO= UT, >> + &UsbStatus >> + ); >> + >> + if (!EFI_ERROR (Status)) { >> + gStopBulkInCnt =3D MINIMUM_STOPBULKIN_CNT; >> + } else { >> + gStopBulkInCnt--; >> + } >> + } else { >> + Status =3D EFI_TIMEOUT; >> + *TransferLength =3D 0; >> + gBlockBulkInCnt++; >> + } >> + >> + if (gBlockBulkInCnt > BULKIN_CMD_POLLING_CNT) { >> + gStopBulkInCnt =3D MINIMUM_STOPBULKIN_CNT; >> + gBlockBulkInCnt =3D 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 =3D 0; >> + >> + switch (RndisMsg->MessageType) { >> + case RNDIS_PACKET_MSG: >> + DEBUG ((DEBUG_INFO, "RNDIS_PACKET_MSG:\n")); >> + Length =3D sizeof (REMOTE_NDIS_PACKET_MSG) + 0x14; >> + break; >> + case RNDIS_INITIALIZE_MSG: >> + DEBUG ((DEBUG_INFO, "RNDIS_INITIALIZE_MSG:\n")); >> + Length =3D sizeof (REMOTE_NDIS_INITIALIZE_MSG); >> + break; >> + case RNDIS_INITIALIZE_CMPLT: >> + DEBUG ((DEBUG_INFO, "RNDIS_INITIALIZE_CMPLT:\n")); >> + Length =3D sizeof (REMOTE_NDIS_INITIALIZE_CMPLT); >> + break; >> + case RNDIS_HLT_MSG: >> + DEBUG ((DEBUG_INFO, "RNDIS_HLT_MSG:\n")); >> + Length =3D sizeof (REMOTE_NDIS_HALT_MSG); >> + break; >> + case RNDIS_QUERY_MSG: >> + DEBUG ((DEBUG_INFO, "RNDIS_QUERY_MSG:\n")); >> + Length =3D sizeof (REMOTE_NDIS_QUERY_MSG); >> + break; >> + case RNDIS_QUERY_CMPLT: >> + DEBUG ((DEBUG_INFO, "RNDIS_QUERY_CMPLT:\n")); >> + RndisQueryCmplt =3D (REMOTE_NDIS_QUERY_CMPLT *)RndisMsg; >> + Length =3D sizeof (REMOTE_NDIS_QUERY_CMPLT) + RndisQuery= Cmplt->InformationBufferLength; >> + break; >> + case RNDIS_SET_MSG: >> + DEBUG ((DEBUG_INFO, "RNDIS_SET_MSG:\n")); >> + Length =3D sizeof (REMOTE_NDIS_SET_MSG); >> + break; >> + case RNDIS_SET_CMPLT: >> + DEBUG ((DEBUG_INFO, "RNDIS_SET_CMPLT:\n")); >> + Length =3D sizeof (REMOTE_NDIS_SET_CMPLT); >> + break; >> + case RNDIS_RESET_MSG: >> + DEBUG ((DEBUG_INFO, "RNDIS_RESET_MSG:\n")); >> + Length =3D sizeof (REMOTE_NDIS_RESET_MSG); >> + break; >> + case RNDIS_RESET_CMPLT: >> + DEBUG ((DEBUG_INFO, "RNDIS_RESET_CMPLT:\n")); >> + Length =3D sizeof (REMOTE_NDIS_RESET_CMPLT); >> + break; >> + case RNDIS_INDICATE_STATUS_MSG: >> + DEBUG ((DEBUG_INFO, "RNDIS_INDICATE_STATUS_MSG:\n")); >> + Length =3D sizeof (REMOTE_NDIS_INDICATE_STATUS_MSG); >> + break; >> + case RNDIS_KEEPALIVE_MSG: >> + DEBUG ((DEBUG_INFO, "RNDIS_KEEPALIVE_MSG:\n")); >> + Length =3D sizeof (REMOTE_NDIS_KEEPALIVE_MSG); >> + break; >> + case RNDIS_KEEPALIVE_CMPLT: >> + DEBUG ((DEBUG_INFO, "RNDIS_KEEPALIVE_CMPLT:\n")); >> + Length =3D sizeof (REMOTE_NDIS_KEEPALIVE_CMPLT); >> + } >> + >> + if (Length) { >> + UINTN Index =3D 0; >> + for ( ; Length; Length -=3D 4, Index++) { >> + DEBUG ((DEBUG_INFO, "%8X\t", *((UINT32 *)RndisMsg + Index))); >> + if (((Index % 4) =3D=3D 3) && (Index !=3D 0)) { >> + DEBUG ((DEBUG_INFO, "\n")); >> + } >> + >> + if ((Length < 8) && (Length > 4)) { >> + UINT32 Data32; >> + Index++; >> + Data32 =3D *((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 int= erface 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 US= B 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 wit= h 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 wit= h 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 w= ith 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 propr= ietary to American Megatrends (AMI). This communication is intended to be r= ead only by the individual or entity to whom it is addressed or by their de= signee. If the reader of this message is not the intended recipient, you ar= e 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 teleph= one at 770-246-8600, and then delete or destroy all copies of the transmiss= ion. > -The information contained in this message may be confidential and=20 > proprietary to American Megatrends (AMI). This communication is=20 > intended to be read only by the individual or entity to whom it is=20 > addressed or by their designee. If the reader of this message is not=20 > the intended recipient, you are on notice that any distribution of this= =20 > message, in any form, is strictly prohibited. Please promptly notify=20 > the sender by reply e-mail or by telephone at 770-246-8600, and then=20 > delete or destroy all copies of the transmission. > > >=20