From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from out2-smtp.messagingengine.com (out2-smtp.messagingengine.com [66.111.4.26]) by mx.groups.io with SMTP id smtpd.web10.1591.1686197035816009293 for ; Wed, 07 Jun 2023 21:03:56 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="signature has expired" header.i=@bsdio.com header.s=fm2 header.b=xRiQi/WU; spf=pass (domain: bsdio.com, ip: 66.111.4.26, mailfrom: rebecca@bsdio.com) Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id CF2315C015E; Thu, 8 Jun 2023 00:03:54 -0400 (EDT) Received: from mailfrontend1 ([10.202.2.162]) by compute4.internal (MEProxy); Thu, 08 Jun 2023 00:03:54 -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=fm2; t= 1686197034; x=1686283434; bh=q2I2e8/Pw1xSqm4YGgBMQr/004+bN+1Wzar M+SUwNzY=; b=xRiQi/WU+giWmG6/0+2PIF3LWMCqHntUHVR9SVuvN+MY+ocTsYR ayZ03FI+UpiX391EQU92F0ToKMhRJV141oY0cOXwCJpdFA9g/Wq2Ay3nLm6n9zr+ HBUMc4ks7Ennf/potZI9kM00m28kj7uX0qW9yp8yDzCYtEtUOuH4q/RTFHyB2pPe ykxg37TQSefRbAm+0TfKllGcz9zqGK1/kYzQIfrbvWijQsFT335oc0+HlwRr5pP2 leu3S+vA8VzgVjGWlMMuUYtfFt9AWAhc9m10sod9lzn3nBlJZemGmGmaZM/h3XsV nJFQ6anwWmaj6ycQtkYAtjRP3F72SpgDYfg== 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=fm1; t= 1686197034; x=1686283434; bh=q2I2e8/Pw1xSqm4YGgBMQr/004+bN+1Wzar M+SUwNzY=; b=hwK+C8I30ZqtldKZ+h97sAXbrsIK6VvgpoqfhjNaCR50crpiMbT SriLDlgorZiTh8GVU6t5MEw8qZbF7FXsARL28zrkupG2QU//27Z+PCPbjnkUg5DT hyOp6qqpkpnPdYozny6Rdt+dT5t1ws4pflCSEjySovIFpLXbSAaxE6CpYCKdxZx0 zPZnytfE1Ab15TmujzcZnU4xw1oLXuoWB57mY5bbYqf3r6XzsIYa6fw0/qGEKabp fFtJRUCavHI+60OKVF25Mu9GRHLqUTXqaDz0MQ2swDyT4OnV19I7b3eVz99OK+GN Dn9z5JskMZgWMk8udrJy9cu8z1hQfQxH4/w== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgedvhedrgedthedgjeejucetufdoteggodetrfdotf fvucfrrhhofhhilhgvmecuhfgrshhtofgrihhlpdfqfgfvpdfurfetoffkrfgpnffqhgen uceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmne goufhushhpvggtthffohhmrghinhculdegledmnecujfgurhepkfffgggfuffvvehfhfgj tgfgsehtkeertddtfeejnecuhfhrohhmpeftvggsvggttggrucevrhgrnhcuoehrvggsvg gttggrsegsshguihhordgtohhmqeenucggtffrrghtthgvrhhnpedvieffveejteekhffg leeltdekjefgleetteegveduuddvjeeviefgheevvdehffenucffohhmrghinhepghhroh huphhsrdhiohdpthhirghnohgtohhrvgdrohhrghdpghhithhhuhgsrdgtohhmpdhgihht hhhusgdrihhonecuvehluhhsthgvrhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrh homheprhgvsggvtggtrgessghsughiohdrtghomh X-ME-Proxy: Feedback-ID: i5b994698:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Thu, 8 Jun 2023 00:03:52 -0400 (EDT) Message-ID: <424ef249-de46-ae74-2522-b3d1390118a9@bsdio.com> Date: Wed, 7 Jun 2023 22:03:51 -0600 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.11.0 Subject: Re: [edk2-devel] [PATCH v3 1/3] MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis: Add USB RNDIS devices support To: "Wu, Hao A" , =?UTF-8?B?UmljaGFyZCBIbyAo5L2V5piO5b+g?= =?UTF-8?Q?=29?= , "devel@edk2.groups.io" Cc: Andrew Fish , Leif Lindholm , "Kinney, Michael D" , Michael Kubacki , "Liu, Zhiguang" , "Gao, Liming" , "Ni, Ray" , Tinh Nguyen , =?UTF-8?B?VG9ueSBMbyAo576F6YeR5p2+KQ==?= References: <175D0EAC419FA602.2502@groups.io> From: "Rebecca Cran" In-Reply-To: Content-Language: en-US Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit I can create a branch and PR for the series. I'm not sure Richard has a GitHub account. -- Rebecca Cran On 6/7/23 20:05, Wu, Hao A wrote: > Not sure if previous reply was successfully delivered (seems sent to the mailing list). > Snippet of https://edk2.groups.io/g/devel/message/104100: > > ... > > Could you help to create a PR for this series (or share a personal branch > with the changes)? I am having issues when applying these patches after > extracting them from my mail client. Thanks. > > Also, is there a Bugzilla tracker for this? If not, my recommendation is > to file a feature request at: > https://bugzilla.tianocore.org/enter_bug.cgi?product=Tianocore%20Feature%20Requests > to track this and list such information in the commit log message. > > Best Regards, > Hao Wu > > >> -----Original Message----- >> From: Richard Ho (何明忠) >> Sent: Thursday, June 8, 2023 9:59 AM >> To: devel@edk2.groups.io; Richard Ho (何明忠) >> Cc: Andrew Fish ; Leif Lindholm >> ; Kinney, Michael D >> ; Michael Kubacki >> ; Liu, Zhiguang ; >> Gao, Liming ; Wu, Hao A >> ; Ni, Ray ; Tinh Nguyen >> ; Rebecca Cran >> ; Tony Lo (羅金松) >> Subject: RE: [EXTERNAL] [edk2-devel] [PATCH v3 1/3] >> MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis: Add USB RNDIS devices >> support >> >> Hi Hao Wu, >> >> Do you have any update on this patch? >> >> Thanks, >> Richard >> >> >> -----Original Message----- >> From: devel@edk2.groups.io On Behalf Of >> RichardHo [何明忠] via groups.io >> Sent: 2023年5月8日 11:53 AM >> To: devel@edk2.groups.io >> Cc: Andrew Fish ; Leif Lindholm >> ; Michael D Kinney >> ; Michael Kubacki >> ; Zhiguang Liu ; >> Liming Gao ; Hao A Wu >> ; Ray Ni ; Tinh Nguyen >> ; Rebecca Cran >> ; Tony Lo (羅金松) >> Subject: [EXTERNAL] [edk2-devel] [PATCH v3 1/3] >> MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis: Add USB RNDIS devices >> support >> >> >> **CAUTION: The e-mail below is from an external source. Please exercise >> caution before opening attachments, clicking links, or following guidance.** >> >> 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: Hao A Wu >> Cc: Ray Ni >> Tested-by: Tinh Nguyen >> Reviewed-by: Rebecca Cran >> Reviewed-by: Tony Lo >> --- >> Maintainers.txt | 6 + >> .../UsbNetwork/NetworkCommon/ComponentName.c | 263 +++ >> .../UsbNetwork/NetworkCommon/DriverBinding.c | 595 ++++++ >> .../UsbNetwork/NetworkCommon/DriverBinding.h | 266 +++ >> .../NetworkCommon/NetworkCommon.inf | 48 + >> .../UsbNetwork/NetworkCommon/PxeFunction.c | 1803 >> +++++++++++++++++ >> .../Usb/UsbNetwork/UsbRndis/ComponentName.c | 172 ++ >> .../Bus/Usb/UsbNetwork/UsbRndis/UsbRndis.c | 886 ++++++++ >> .../Bus/Usb/UsbNetwork/UsbRndis/UsbRndis.h | 586 ++++++ >> .../Bus/Usb/UsbNetwork/UsbRndis/UsbRndis.inf | 42 + >> .../UsbNetwork/UsbRndis/UsbRndisFunction.c | 1718 ++++++++++++++++ >> .../Include/Protocol/UsbEthernetProtocol.h | 878 ++++++++ >> MdeModulePkg/MdeModulePkg.dec | 18 + >> MdeModulePkg/MdeModulePkg.dsc | 4 + >> 14 files changed, 7285 insertions(+) >> create mode 100644 >> MdeModulePkg/Bus/Usb/UsbNetwork/NetworkCommon/ComponentName. >> c >> create mode 100644 >> MdeModulePkg/Bus/Usb/UsbNetwork/NetworkCommon/DriverBinding.c >> create mode 100644 >> MdeModulePkg/Bus/Usb/UsbNetwork/NetworkCommon/DriverBinding.h >> create mode 100644 >> MdeModulePkg/Bus/Usb/UsbNetwork/NetworkCommon/NetworkCommon. >> inf >> create mode 100644 >> MdeModulePkg/Bus/Usb/UsbNetwork/NetworkCommon/PxeFunction.c >> create mode 100644 >> MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis/ComponentName.c >> create mode 100644 >> MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis/UsbRndis.c >> create mode 100644 >> MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis/UsbRndis.h >> create mode 100644 >> MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis/UsbRndis.inf >> create mode 100644 >> MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis/UsbRndisFunction.c >> create mode 100644 >> MdeModulePkg/Include/Protocol/UsbEthernetProtocol.h >> >> diff --git a/Maintainers.txt b/Maintainers.txt >> index 09d04af27a..9a15cdb993 100644 >> --- a/Maintainers.txt >> +++ b/Maintainers.txt >> @@ -437,6 +437,12 @@ R: Zhiguang Liu >> [LiuZhiguang001] >> R: Ray Ni [niruiyu] >> R: Gua Guo [gguo11837463] >> >> +MdeModulePkg: USB Network modules >> +F: MdeModulePkg/Bus/Usb/UsbNetwork >> +F: MdeModulePkg/Include/Protocol/UsbEthernetProtocol.h >> +M: Richard Ho [richardho] >> +R: Rebecca Cran [bcran] >> + >> MdePkg >> F: MdePkg/ >> W: https://github.com/tianocore/tianocore.github.io/wiki/MdePkg >> diff --git >> a/MdeModulePkg/Bus/Usb/UsbNetwork/NetworkCommon/ComponentNa >> me.c >> b/MdeModulePkg/Bus/Usb/UsbNetwork/NetworkCommon/ComponentNa >> me.c >> new file mode 100644 >> index 0000000000..e83469e130 >> --- /dev/null >> +++ >> b/MdeModulePkg/Bus/Usb/UsbNetwork/NetworkCommon/ComponentNa >> me.c >> @@ -0,0 +1,263 @@ >> +/** @file >> + This file contains code for USB network common driver >> + component name definitions >> + >> + Copyright (c) 2023, American Megatrends International LLC. All rights >> reserved.
>> + SPDX-License-Identifier: BSD-2-Clause-Patent >> +**/ >> + >> +#include "DriverBinding.h" >> + >> +extern EFI_DRIVER_BINDING_PROTOCOL gNetworkCommonDriverBinding; >> + >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE >> gNetworkCommonDriverNameTable[] = { >> + { >> + "eng;en", >> + L"Network Common Driver" >> + }, >> + { >> + NULL, >> + NULL >> + } >> +}; >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE >> *gNetworkCommonControllerNameTable = NULL; >> + >> +EFI_STATUS >> +EFIAPI >> +NetworkCommonComponentNameGetDriverName ( >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> + IN CHAR8 *Language, >> + OUT CHAR16 **DriverName >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +NetworkCommonComponentNameGetControllerName ( >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> + IN EFI_HANDLE Controller, >> + IN EFI_HANDLE ChildHandle OPTIONAL, >> + IN CHAR8 *Language, >> + OUT CHAR16 **ControllerName >> + ); >> + >> +GLOBAL_REMOVE_IF_UNREFERENCED >> EFI_COMPONENT_NAME_PROTOCOL gNetworkCommonComponentName >> = { >> + NetworkCommonComponentNameGetDriverName, >> + NetworkCommonComponentNameGetControllerName, >> + "eng" >> +}; >> + >> +GLOBAL_REMOVE_IF_UNREFERENCED >> EFI_COMPONENT_NAME2_PROTOCOL >> gNetworkCommonComponentName2 = { >> + >> (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)NetworkCommonCompon >> entNameGetDriverName, >> + >> (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)NetworkCommonCo >> mponentNameGetControllerName, >> + "en" >> +}; >> + >> +/** >> + Retrieves a Unicode string that is the user readable name of the driver. >> + >> + This function retrieves the user readable name of a driver in the form of a >> + Unicode string. If the driver specified by This has a user readable name in >> + the language specified by Language, then a pointer to the driver name is >> + returned in DriverName, and EFI_SUCCESS is returned. If the driver >> specified >> + by This does not support the language specified by Language, >> + then EFI_UNSUPPORTED is returned. >> + >> + @param[in] This A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >> + EFI_COMPONENT_NAME_PROTOCOL instance. >> + @param[in] Language A pointer to a Null-terminated ASCII string >> + array indicating the language. This is the >> + language of the driver name that the caller is >> + requesting, and it must match one of the >> + languages specified in SupportedLanguages. The >> + number of languages supported by a driver is up >> + to the driver writer. Language is specified >> + in RFC 4646 or ISO 639-2 language code format. >> + @param[out] DriverName A pointer to the Unicode string to return. >> + This Unicode string is the name of the >> + driver specified by This in the language >> + specified by Language. >> + >> + @retval EFI_SUCCESS The Unicode string for the Driver specified by >> + This and the language specified by Language was >> + returned in DriverName. >> + @retval EFI_INVALID_PARAMETER Language is NULL. >> + @retval EFI_INVALID_PARAMETER DriverName is NULL. >> + @retval EFI_UNSUPPORTED The driver specified by This does not >> support >> + the language specified by Language. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +NetworkCommonComponentNameGetDriverName ( >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> + IN CHAR8 *Language, >> + OUT CHAR16 **DriverName >> + ) >> +{ >> + return LookupUnicodeString2 ( >> + Language, >> + This->SupportedLanguages, >> + gNetworkCommonDriverNameTable, >> + DriverName, >> + (BOOLEAN)(This == &gNetworkCommonComponentName) >> + ); >> +} >> + >> +/** >> + Retrieves a Unicode string that is the user readable name of the controller >> + that is being managed by a driver. >> + >> + This function retrieves the user readable name of the controller specified >> by >> + ControllerHandle and ChildHandle in the form of a Unicode string. If the >> + driver specified by This has a user readable name in the language specified >> by >> + Language, then a pointer to the controller name is returned in >> ControllerName, >> + and EFI_SUCCESS is returned. If the driver specified by This is not currently >> + managing the controller specified by ControllerHandle and ChildHandle, >> + then EFI_UNSUPPORTED is returned. If the driver specified by This does >> not >> + support the language specified by Language, then EFI_UNSUPPORTED is >> returned. >> + >> + @param[in] This A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >> + EFI_COMPONENT_NAME_PROTOCOL instance. >> + @param[in] Controller The handle of a controller that the driver >> + specified by This is managing. This handle >> + specifies the controller whose name is to be >> + returned. >> + @param[in] ChildHandle The handle of the child controller to retrieve >> + the name of. This is an optional parameter that >> + may be NULL. It will be NULL for device >> + drivers. It will also be NULL for a bus drivers >> + that wish to retrieve the name of the bus >> + controller. It will not be NULL for a bus >> + driver that wishes to retrieve the name of a >> + child controller. >> + @param[in] Language A pointer to a Null-terminated ASCII string >> + array indicating the language. This is the >> + language of the driver name that the caller is >> + requesting, and it must match one of the >> + languages specified in SupportedLanguages. The >> + number of languages supported by a driver is up >> + to the driver writer. Language is specified in >> + RFC 4646 or ISO 639-2 language code format. >> + @param[out] ControllerName A pointer to the Unicode string to return. >> + This Unicode string is the name of the >> + controller specified by ControllerHandle and >> + ChildHandle in the language specified by >> + Language from the point of view of the driver >> + specified by This. >> + >> + @retval EFI_SUCCESS The Unicode string for the user readable name >> in >> + the language specified by Language for the >> + driver specified by This was returned in >> + DriverName. >> + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid >> EFI_HANDLE. >> + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a >> valid >> + EFI_HANDLE. >> + @retval EFI_INVALID_PARAMETER Language is NULL. >> + @retval EFI_INVALID_PARAMETER ControllerName is NULL. >> + @retval EFI_UNSUPPORTED The driver specified by This is not currently >> + managing the controller specified by >> + ControllerHandle and ChildHandle. >> + @retval EFI_UNSUPPORTED The driver specified by This does not >> support >> + the language specified by Language. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +NetworkCommonComponentNameGetControllerName ( >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> + IN EFI_HANDLE Controller, >> + IN EFI_HANDLE ChildHandle OPTIONAL, >> + IN CHAR8 *Language, >> + OUT CHAR16 **ControllerName >> + ) >> +{ >> + EFI_STATUS Status; >> + CHAR16 *HandleName; >> + EFI_USB_IO_PROTOCOL *UsbIo; >> + EFI_USB_DEVICE_DESCRIPTOR DevDesc; >> + >> + if (!Language || !ControllerName) { >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + if (ChildHandle == NULL) { >> + return EFI_UNSUPPORTED; >> + } >> + >> + // >> + // Make sure this driver is currently managing ControllerHandle >> + // >> + Status = EfiTestManagedDevice ( >> + Controller, >> + gNetworkCommonDriverBinding.DriverBindingHandle, >> + &gEdkIIUsbEthProtocolGuid >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + // >> + // Make sure this driver produced ChildHandle >> + // >> + Status = EfiTestChildHandle ( >> + Controller, >> + ChildHandle, >> + &gEdkIIUsbEthProtocolGuid >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + Status = gBS->HandleProtocol (Controller, &gEfiUsbIoProtocolGuid, (VOID >> **)&UsbIo); >> + >> + if (!EFI_ERROR (Status)) { >> + Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + Status = UsbIo->UsbGetStringDescriptor (UsbIo, 0x409, >> DevDesc.StrManufacturer, &HandleName); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + *ControllerName = HandleName; >> + >> + if (gNetworkCommonControllerNameTable != NULL) { >> + FreeUnicodeStringTable (gNetworkCommonControllerNameTable); >> + gNetworkCommonControllerNameTable = NULL; >> + } >> + >> + Status = AddUnicodeString2 ( >> + "eng", >> + gNetworkCommonComponentName.SupportedLanguages, >> + &gNetworkCommonControllerNameTable, >> + HandleName, >> + TRUE >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + Status = AddUnicodeString2 ( >> + "en", >> + gNetworkCommonComponentName2.SupportedLanguages, >> + &gNetworkCommonControllerNameTable, >> + HandleName, >> + FALSE >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + return LookupUnicodeString2 ( >> + Language, >> + This->SupportedLanguages, >> + gNetworkCommonControllerNameTable, >> + ControllerName, >> + (BOOLEAN)(This == &gNetworkCommonComponentName) >> + ); >> + } >> + >> + return EFI_UNSUPPORTED; >> +} >> diff --git >> a/MdeModulePkg/Bus/Usb/UsbNetwork/NetworkCommon/DriverBinding.c >> b/MdeModulePkg/Bus/Usb/UsbNetwork/NetworkCommon/DriverBinding.c >> new file mode 100644 >> index 0000000000..8520cf886c >> --- /dev/null >> +++ >> b/MdeModulePkg/Bus/Usb/UsbNetwork/NetworkCommon/DriverBinding.c >> @@ -0,0 +1,595 @@ >> +/** @file >> + This file contains code for USB network binding driver >> + >> + Copyright (c) 2023, American Megatrends International LLC. All rights >> reserved.
>> + SPDX-License-Identifier: BSD-2-Clause-Patent >> +**/ >> + >> +#include "DriverBinding.h" >> + >> +PXE_SW_UNDI *gPxe = NULL; >> +NIC_DEVICE *gLanDeviceList[MAX_LAN_INTERFACE]; >> +UINT32 gRateLimitingCredit; >> +UINT32 gRateLimitingPollTimer; >> +BOOLEAN gRateLimitingEnable; >> + >> +EFI_DRIVER_BINDING_PROTOCOL gNetworkCommonDriverBinding = { >> + NetworkCommonSupported, >> + NetworkCommonDriverStart, >> + NetworkCommonDriverStop, >> + NETWORK_COMMON_DRIVER_VERSION, >> + NULL, >> + NULL >> +}; >> + >> +/** >> + Create MAC Device Path >> + >> + @param[in, out] Dev A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> + @param[in] BaseDev A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> + @param[in] Nic A pointer to the Network interface controller >> data. >> + >> + @retval EFI_OUT_OF_RESOURCES The device path could not be created >> successfully due to a lack of resources. >> + @retval EFI_SUCCESS MAC device path created successfully. >> + >> +**/ >> +EFI_STATUS >> +CreateMacDevicePath ( >> + IN OUT EFI_DEVICE_PATH_PROTOCOL **Dev, >> + IN EFI_DEVICE_PATH_PROTOCOL *BaseDev, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + EFI_STATUS Status; >> + MAC_ADDR_DEVICE_PATH MacAddrNode; >> + EFI_DEVICE_PATH_PROTOCOL *EndNode; >> + UINT8 *DevicePath; >> + UINT16 TotalLength; >> + UINT16 BaseLength; >> + >> + ZeroMem (&MacAddrNode, sizeof (MAC_ADDR_DEVICE_PATH)); >> + CopyMem (&MacAddrNode.MacAddress, &Nic->MacAddr, sizeof >> (EFI_MAC_ADDRESS)); >> + >> + MacAddrNode.Header.Type = MESSAGING_DEVICE_PATH; >> + MacAddrNode.Header.SubType = MSG_MAC_ADDR_DP; >> + MacAddrNode.Header.Length[0] = (UINT8)sizeof (MacAddrNode); >> + MacAddrNode.Header.Length[1] = 0; >> + >> + EndNode = BaseDev; >> + >> + while (!IsDevicePathEnd (EndNode)) { >> + EndNode = NextDevicePathNode (EndNode); >> + } >> + >> + BaseLength = (UINT16)((UINTN)(EndNode) - (UINTN)(BaseDev)); >> + TotalLength = (UINT16)(BaseLength + sizeof (MacAddrNode) + sizeof >> (EFI_DEVICE_PATH_PROTOCOL)); >> + >> + Status = gBS->AllocatePool (EfiBootServicesData, TotalLength, (VOID >> **)&DevicePath); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + *Dev = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath; >> + CopyMem (DevicePath, (CHAR8 *)BaseDev, BaseLength); >> + DevicePath += BaseLength; >> + CopyMem (DevicePath, (CHAR8 *)&MacAddrNode, sizeof (MacAddrNode)); >> + DevicePath += sizeof (MacAddrNode); >> + CopyMem (DevicePath, (CHAR8 *)EndNode, sizeof >> (EFI_DEVICE_PATH_PROTOCOL)); >> + >> + return EFI_SUCCESS; >> +} >> + >> +/** >> + Network Common Driver Binding Support. >> + >> + @param[in] This Protocol instance pointer. >> + @param[in] ControllerHandle Handle of device to test. >> + @param[in] RemainingDevicePath Optional parameter use to pick a >> specific child >> + device to start. >> + >> + @retval EFI_SUCCESS This driver supports this device. >> + @retval EFI_ALREADY_STARTED This driver is already running on this >> device. >> + @retval other This driver does not support this device. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +NetworkCommonSupported ( >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> + IN EFI_HANDLE ControllerHandle, >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> + ) >> +{ >> + EFI_STATUS Status; >> + EDKII_USB_ETHERNET_PROTOCOL *UsbEth; >> + >> + Status = gBS->OpenProtocol ( >> + ControllerHandle, >> + &gEdkIIUsbEthProtocolGuid, >> + (VOID **)&UsbEth, >> + This->DriverBindingHandle, >> + ControllerHandle, >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEdkIIUsbEthProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + return Status; >> +} >> + >> +/** >> + Network Common Driver Binding Start. >> + >> + @param[in] This Protocol instance pointer. >> + @param[in] ControllerHandle Handle of device to bind driver to. >> + @param[in] RemainingDevicePath Optional parameter use to pick a >> specific child >> + device to start. >> + >> + @retval EFI_SUCCESS This driver is added to ControllerHandle >> + @retval EFI_DEVICE_ERROR This driver could not be started due to a >> device error >> + @retval EFI_OUT_OF_RESOURCES The driver could not install >> successfully due to a lack of resources. >> + @retval other This driver does not support this device >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +NetworkCommonDriverStart ( >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> + IN EFI_HANDLE ControllerHandle, >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> + ) >> +{ >> + EFI_STATUS Status; >> + EFI_DEVICE_PATH_PROTOCOL *UsbEthPath; >> + EDKII_USB_ETHERNET_PROTOCOL *UsbEth; >> + EFI_MAC_ADDRESS MacAddress; >> + UINTN BulkDataSize; >> + NIC_DEVICE *NicDevice; >> + UINT8 *TmpPxePointer; >> + >> + Status = gBS->OpenProtocol ( >> + ControllerHandle, >> + &gEdkIIUsbEthProtocolGuid, >> + (VOID **)&UsbEth, >> + This->DriverBindingHandle, >> + ControllerHandle, >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + Status = gBS->OpenProtocol ( >> + ControllerHandle, >> + &gEfiDevicePathProtocolGuid, >> + (VOID **)&UsbEthPath, >> + This->DriverBindingHandle, >> + ControllerHandle, >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> + ); >> + >> + if (EFI_ERROR (Status)) { >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEdkIIUsbEthProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + return Status; >> + } >> + >> + ZeroMem (&MacAddress, sizeof (EFI_MAC_ADDRESS)); >> + >> + Status = UsbEth->UsbEthMacAddress (UsbEth, &MacAddress); >> + ASSERT_EFI_ERROR (Status); >> + Status = UsbEth->UsbEthMaxBulkSize (UsbEth, &BulkDataSize); >> + >> + if (EFI_ERROR (Status)) { >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEfiDevicePathProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEdkIIUsbEthProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + return Status; >> + } >> + >> + NicDevice = AllocateZeroPool (sizeof (NIC_DEVICE) + BulkDataSize + 4096); >> + if (!NicDevice) { >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEfiDevicePathProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEdkIIUsbEthProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + return EFI_OUT_OF_RESOURCES; >> + } >> + >> + // for alignment adjustment >> + if (gPxe == NULL) { >> + TmpPxePointer = NULL; >> + TmpPxePointer = AllocateZeroPool (sizeof (PXE_SW_UNDI) + 16); >> + if (!TmpPxePointer) { >> + if (NicDevice != NULL) { >> + FreePool (NicDevice); >> + } >> + >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEfiDevicePathProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEdkIIUsbEthProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + >> + return EFI_OUT_OF_RESOURCES; >> + } else { >> + // check for paragraph alignment here >> + if (((UINTN)TmpPxePointer & 0x0F) != 0) { >> + gPxe = (PXE_SW_UNDI *)(TmpPxePointer + 8); >> + } else { >> + gPxe = (PXE_SW_UNDI *)TmpPxePointer; >> + } >> + >> + if (!gPxe) { >> + if (NicDevice != NULL) { >> + FreePool (NicDevice); >> + } >> + >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEfiDevicePathProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEdkIIUsbEthProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + return EFI_OUT_OF_RESOURCES; >> + } >> + >> + PxeStructInit (gPxe); >> + } >> + } >> + >> + NicDevice->NiiProtocol.Id = (UINT64)(UINTN)(gPxe); >> + NicDevice->NiiProtocol.IfNum = gPxe->IFcnt | gPxe->IFcntExt << 8; >> + >> + UpdateNicNum (&NicDevice->NicInfo, gPxe); >> + >> + NicDevice->NicInfo.Signature = NIC_DATA_SIGNATURE; >> + >> + NicDevice->NicInfo.UsbEth = UsbEth; >> + NicDevice->NicInfo.MaxSegmentSize = (UINT16)BulkDataSize; >> + NicDevice->NicInfo.CableDetect = 0; >> + NicDevice->ReceiveBuffer = ALIGN_POINTER ((VOID *)NicDevice, >> 4096); >> + >> + CopyMem ((CHAR8 *)&(NicDevice->NicInfo.MacAddr), (CHAR8 >> *)&MacAddress, sizeof (MacAddress)); >> + >> + NicDevice->NicInfo.TxBufferCount = 0; >> + >> + if (NicDevice->NiiProtocol.IfNum < MAX_LAN_INTERFACE) { >> + gLanDeviceList[NicDevice->NiiProtocol.IfNum] = NicDevice; >> + } else { >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEfiDevicePathProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEdkIIUsbEthProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + >> + if (TmpPxePointer != NULL) { >> + FreePool (TmpPxePointer); >> + } >> + >> + if (NicDevice != NULL) { >> + FreePool (NicDevice); >> + } >> + >> + return EFI_DEVICE_ERROR; >> + } >> + >> + Status = CreateMacDevicePath ( >> + &NicDevice->DevPath, >> + UsbEthPath, >> + &NicDevice->NicInfo >> + ); >> + >> + if (EFI_ERROR (Status)) { >> + UpdateNicNum (NULL, gPxe); >> + if (TmpPxePointer != NULL) { >> + FreePool (TmpPxePointer); >> + } >> + } >> + >> + NicDevice->Signature = UNDI_DEV_SIGNATURE; >> + NicDevice->NiiProtocol.Revision = >> EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION; >> + NicDevice->NiiProtocol.Type = EfiNetworkInterfaceUndi; >> + NicDevice->NiiProtocol.MajorVer = PXE_ROMID_MAJORVER; >> + NicDevice->NiiProtocol.MinorVer = PXE_ROMID_MINORVER; >> + NicDevice->NiiProtocol.ImageSize = 0; >> + NicDevice->NiiProtocol.ImageAddr = 0; >> + NicDevice->NiiProtocol.Ipv6Supported = TRUE; >> + >> + NicDevice->NiiProtocol.StringId[0] = 'U'; >> + NicDevice->NiiProtocol.StringId[1] = 'N'; >> + NicDevice->NiiProtocol.StringId[2] = 'D'; >> + NicDevice->NiiProtocol.StringId[3] = 'I'; >> + NicDevice->DeviceHandle = NULL; >> + >> + NicDevice->NicInfo.RateLimitingEnable = gRateLimitingEnable; >> + NicDevice->NicInfo.RateLimitingCreditCount = 0; >> + NicDevice->NicInfo.RateLimitingCredit = gRateLimitingCredit; >> + NicDevice->NicInfo.RateLimitingPollTimer = gRateLimitingPollTimer; >> + NicDevice->NicInfo.RateLimiter = NULL; >> + >> + ZeroMem (&NicDevice->NicInfo.Request, sizeof >> (EFI_USB_DEVICE_REQUEST)); >> + >> + Status = UsbEth->UsbEthInterrupt (UsbEth, TRUE, >> NETWORK_COMMON_POLLING_INTERVAL, &NicDevice->NicInfo.Request); >> + ASSERT_EFI_ERROR (Status); >> + >> + Status = gBS->InstallMultipleProtocolInterfaces ( >> + &NicDevice->DeviceHandle, >> + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, >> + &NicDevice->NiiProtocol, >> + &gEfiDevicePathProtocolGuid, >> + NicDevice->DevPath, >> + NULL >> + ); >> + >> + if (EFI_ERROR (Status)) { >> + if (NicDevice->NiiProtocol.IfNum < MAX_LAN_INTERFACE) { >> + gLanDeviceList[NicDevice->NiiProtocol.IfNum] = NULL; >> + } >> + >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEfiDevicePathProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEdkIIUsbEthProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + >> + if (TmpPxePointer != NULL) { >> + FreePool (TmpPxePointer); >> + } >> + >> + if (NicDevice->DevPath != NULL) { >> + FreePool (NicDevice->DevPath); >> + } >> + >> + if (NicDevice != NULL) { >> + FreePool (NicDevice); >> + } >> + >> + return EFI_DEVICE_ERROR; >> + } >> + >> + Status = gBS->OpenProtocol ( >> + ControllerHandle, >> + &gEdkIIUsbEthProtocolGuid, >> + (VOID **)&UsbEth, >> + This->DriverBindingHandle, >> + NicDevice->DeviceHandle, >> + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER >> + ); >> + >> + return Status; >> +} >> + >> +/** >> + Network Common Driver Binding Stop. >> + >> + @param[in] This Protocol instance pointer. >> + @param[in] ControllerHandle Handle of device to stop driver on >> + @param[in] NumberOfChildren Number of Handles in >> ChildHandleBuffer. If number of >> + children is zero stop the entire bus driver. >> + @param[in] ChildHandleBuffer List of Child Handles to Stop. >> + >> + @retval EFI_SUCCESS This driver is removed ControllerHandle >> + @retval other This driver was not removed from this device >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +NetworkCommonDriverStop ( >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> + IN EFI_HANDLE ControllerHandle, >> + IN UINTN NumberOfChildren, >> + IN EFI_HANDLE *ChildHandleBuffer >> + ) >> +{ >> + EFI_STATUS Status; >> + BOOLEAN AllChildrenStopped; >> + UINTN Index; >> + EDKII_USB_ETHERNET_PROTOCOL *UsbEth; >> + NIC_DEVICE *NicDevice; >> + EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NiiProtocol; >> + >> + if (NumberOfChildren == 0) { >> + Status = gBS->OpenProtocol ( >> + ControllerHandle, >> + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, >> + (VOID **)&NiiProtocol, >> + This->DriverBindingHandle, >> + ControllerHandle, >> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >> + ); >> + >> + if (EFI_ERROR (Status)) { >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEfiDevicePathProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEdkIIUsbEthProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + return EFI_SUCCESS; >> + } >> + >> + NicDevice = UNDI_DEV_FROM_THIS (NiiProtocol); >> + Status = gBS->UninstallMultipleProtocolInterfaces ( >> + ControllerHandle, >> + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, >> + &NicDevice->NiiProtocol, >> + &gEfiDevicePathProtocolGuid, >> + NicDevice->DevPath, >> + NULL >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + FreePool (NicDevice->DevPath); >> + FreePool (NicDevice); >> + >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEfiDevicePathProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEdkIIUsbEthProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + return EFI_SUCCESS; >> + } >> + >> + AllChildrenStopped = TRUE; >> + >> + for (Index = 0; Index < NumberOfChildren; Index++) { >> + Status = gBS->OpenProtocol ( >> + ChildHandleBuffer[Index], >> + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, >> + (VOID **)&NiiProtocol, >> + This->DriverBindingHandle, >> + ControllerHandle, >> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >> + ); >> + if (EFI_ERROR (Status)) { >> + AllChildrenStopped = FALSE; >> + continue; >> + } >> + >> + NicDevice = UNDI_DEV_FROM_THIS (NiiProtocol); >> + >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEdkIIUsbEthProtocolGuid, >> + This->DriverBindingHandle, >> + ChildHandleBuffer[Index] >> + ); >> + >> + Status = gBS->UninstallMultipleProtocolInterfaces ( >> + ChildHandleBuffer[Index], >> + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, >> + &NicDevice->NiiProtocol, >> + &gEfiDevicePathProtocolGuid, >> + NicDevice->DevPath, >> + NULL >> + ); >> + if (EFI_ERROR (Status)) { >> + Status = gBS->OpenProtocol ( >> + ControllerHandle, >> + &gEdkIIUsbEthProtocolGuid, >> + (VOID **)&UsbEth, >> + This->DriverBindingHandle, >> + ChildHandleBuffer[Index], >> + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER >> + ); >> + } else { >> + FreePool (NicDevice->DevPath); >> + FreePool (NicDevice); >> + } >> + } >> + >> + if (!AllChildrenStopped) { >> + return EFI_DEVICE_ERROR; >> + } >> + >> + return Status; >> +} >> + >> +/** >> + Entrypoint of Network Common Driver. >> + >> + This function is the entrypoint of Network Common Driver. It installs Driver >> Binding >> + Protocols together with Component Name Protocols. >> + >> + @param[in] ImageHandle The firmware allocated handle for the EFI >> image. >> + @param[in] SystemTable A pointer to the EFI System Table. >> + >> + @retval EFI_SUCCESS The entry point is executed successfully. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +NetworkCommonEntry ( >> + IN EFI_HANDLE ImageHandle, >> + IN EFI_SYSTEM_TABLE *SystemTable >> + ) >> +{ >> + EFI_STATUS Status; >> + >> + gNetworkCommonDriverBinding.DriverBindingHandle = ImageHandle; >> + gNetworkCommonDriverBinding.ImageHandle = ImageHandle; >> + gRateLimitingEnable = PcdGetBool >> (PcdEnableUsbNetworkRateLimiting); >> + gRateLimitingCredit = PcdGet32 >> (PcdUsbNetworkRateLimitingCredit); >> + gRateLimitingPollTimer = PcdGet32 >> (PcdUsbNetworkRateLimitingFactor); >> + >> + Status = gBS->InstallMultipleProtocolInterfaces ( >> + &gNetworkCommonDriverBinding.DriverBindingHandle, >> + &gEfiDriverBindingProtocolGuid, >> + &gNetworkCommonDriverBinding, >> + &gEfiComponentName2ProtocolGuid, >> + &gNetworkCommonComponentName2, >> + NULL >> + ); >> + return Status; >> +} >> diff --git >> a/MdeModulePkg/Bus/Usb/UsbNetwork/NetworkCommon/DriverBinding.h >> b/MdeModulePkg/Bus/Usb/UsbNetwork/NetworkCommon/DriverBinding.h >> new file mode 100644 >> index 0000000000..a805834a78 >> --- /dev/null >> +++ >> b/MdeModulePkg/Bus/Usb/UsbNetwork/NetworkCommon/DriverBinding.h >> @@ -0,0 +1,266 @@ >> +/** @file >> + Header file for for USB network common driver >> + >> + Copyright (c) 2023, American Megatrends International LLC. All rights >> reserved.
>> + SPDX-License-Identifier: BSD-2-Clause-Patent >> +**/ >> + >> +#ifndef _DRIVER_BINDING_H_ >> +#define _DRIVER_BINDING_H_ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +#define NETWORK_COMMON_DRIVER_VERSION 1 >> +#define NETWORK_COMMON_POLLING_INTERVAL 0x10 >> +#define RX_BUFFER_COUNT 32 >> +#define TX_BUFFER_COUNT 32 >> +#define MEMORY_REQUIRE 0 >> + >> +#define UNDI_DEV_SIGNATURE SIGNATURE_32('u','n','d','i') >> +#define UNDI_DEV_FROM_THIS(a) CR(a, NIC_DEVICE, NiiProtocol, >> UNDI_DEV_SIGNATURE) >> +#define UNDI_DEV_FROM_NIC(a) CR(a, NIC_DEVICE, NicInfo, >> UNDI_DEV_SIGNATURE) >> + >> +#pragma pack(1) >> +typedef struct { >> + UINT8 DestAddr[PXE_HWADDR_LEN_ETHER]; >> + UINT8 SrcAddr[PXE_HWADDR_LEN_ETHER]; >> + UINT16 Protocol; >> +} EthernetHeader; >> +#pragma pack() >> + >> +typedef struct { >> + UINTN Signature; >> + EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL NiiProtocol; >> + EFI_HANDLE DeviceHandle; >> + EFI_DEVICE_PATH_PROTOCOL *BaseDevPath; >> + EFI_DEVICE_PATH_PROTOCOL *DevPath; >> + NIC_DATA NicInfo; >> + VOID *ReceiveBuffer; >> +} NIC_DEVICE; >> + >> +typedef VOID (*API_FUNC)( >> + PXE_CDB *, >> + NIC_DATA * >> + ); >> + >> +extern PXE_SW_UNDI *gPxe; >> +extern NIC_DEVICE *gLanDeviceList[MAX_LAN_INTERFACE]; >> +extern EFI_COMPONENT_NAME2_PROTOCOL >> gNetworkCommonComponentName2; >> + >> +EFI_STATUS >> +EFIAPI >> +NetworkCommonSupported ( >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> + IN EFI_HANDLE ControllerHandle, >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +NetworkCommonDriverStart ( >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> + IN EFI_HANDLE ControllerHandle, >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +NetworkCommonDriverStop ( >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> + IN EFI_HANDLE ControllerHandle, >> + IN UINTN NumberOfChildren, >> + IN EFI_HANDLE *ChildHandleBuffer >> + ); >> + >> +VOID >> +PxeStructInit ( >> + OUT PXE_SW_UNDI *PxeSw >> + ); >> + >> +VOID >> +UpdateNicNum ( >> + IN NIC_DATA *Nic, >> + IN OUT PXE_SW_UNDI *PxeSw >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +UndiApiEntry ( >> + IN UINT64 Cdb >> + ); >> + >> +UINTN >> +MapIt ( >> + IN NIC_DATA *Nic, >> + IN UINT64 MemAddr, >> + IN UINT32 Size, >> + IN UINT32 Direction, >> + OUT UINT64 MappedAddr >> + ); >> + >> +VOID >> +UnMapIt ( >> + IN NIC_DATA *Nic, >> + IN UINT64 MemAddr, >> + IN UINT32 Size, >> + IN UINT32 Direction, >> + IN UINT64 MappedAddr >> + ); >> + >> +VOID >> +UndiGetState ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +VOID >> +UndiStart ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +VOID >> +UndiStop ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +VOID >> +UndiGetInitInfo ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +VOID >> +UndiGetConfigInfo ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +VOID >> +UndiInitialize ( >> + IN PXE_CDB *Cdb, >> + IN OUT NIC_DATA *Nic >> + ); >> + >> +VOID >> +UndiReset ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +VOID >> +UndiShutdown ( >> + IN PXE_CDB *Cdb, >> + IN OUT NIC_DATA *Nic >> + ); >> + >> +VOID >> +UndiInterruptEnable ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +VOID >> +UndiReceiveFilter ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +VOID >> +UndiStationAddress ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +VOID >> +UndiStatistics ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +VOID >> +UndiMcastIp2Mac ( >> + IN OUT PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +VOID >> +UndiNvData ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +VOID >> +UndiGetStatus ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +VOID >> +UndiFillHeader ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +VOID >> +UndiTransmit ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +VOID >> +UndiReceive ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +UINT16 >> +Initialize ( >> + IN PXE_CDB *Cdb, >> + IN OUT NIC_DATA *Nic >> + ); >> + >> +UINT16 >> +Transmit ( >> + IN PXE_CDB *Cdb, >> + IN OUT NIC_DATA *Nic, >> + IN UINT64 CpbAddr, >> + IN UINT16 OpFlags >> + ); >> + >> +UINT16 >> +Receive ( >> + IN PXE_CDB *Cdb, >> + IN OUT NIC_DATA *Nic, >> + IN UINT64 CpbAddr, >> + IN OUT UINT64 DbAddr >> + ); >> + >> +UINT16 >> +SetFilter ( >> + IN NIC_DATA *Nic, >> + IN UINT16 SetFilter, >> + IN UINT64 CpbAddr, >> + IN UINT32 CpbSize >> + ); >> + >> +UINT16 >> +Statistics ( >> + IN NIC_DATA *Nic, >> + IN UINT64 DbAddr, >> + IN UINT16 DbSize >> + ); >> + >> +#endif >> diff --git >> a/MdeModulePkg/Bus/Usb/UsbNetwork/NetworkCommon/NetworkComm >> on.inf >> b/MdeModulePkg/Bus/Usb/UsbNetwork/NetworkCommon/NetworkComm >> on.inf >> new file mode 100644 >> index 0000000000..f9ca31fe80 >> --- /dev/null >> +++ >> b/MdeModulePkg/Bus/Usb/UsbNetwork/NetworkCommon/NetworkComm >> on.inf >> @@ -0,0 +1,48 @@ >> +## @file >> +# This is Usb Network Common driver for DXE phase. >> +# >> +# Copyright (c) 2023, American Megatrends International LLC. All rights >> reserved.
>> +# SPDX-License-Identifier: BSD-2-Clause-Patent >> +## >> + >> +[Defines] >> + INF_VERSION = 0x00010005 >> + BASE_NAME = NetworkCommon >> + FILE_GUID = ca6eb4f4-f1d6-4375-97d6-18856871e1bf >> + MODULE_TYPE = DXE_DRIVER >> + VERSION_STRING = 1.0 >> + ENTRY_POINT = NetworkCommonEntry >> + >> +[Sources] >> + DriverBinding.c >> + DriverBinding.h >> + ComponentName.c >> + PxeFunction.c >> + >> +[Packages] >> + MdePkg/MdePkg.dec >> + MdeModulePkg/MdeModulePkg.dec >> + >> +[LibraryClasses] >> + UefiDriverEntryPoint >> + UefiBootServicesTableLib >> + UefiLib >> + DebugLib >> + UefiUsbLib >> + MemoryAllocationLib >> + BaseMemoryLib >> + >> +[Protocols] >> + gEfiNetworkInterfaceIdentifierProtocolGuid_31 >> + gEfiUsbIoProtocolGuid >> + gEfiDevicePathProtocolGuid >> + gEfiDriverBindingProtocolGuid >> + gEdkIIUsbEthProtocolGuid >> + >> +[Pcd] >> + gEfiMdeModulePkgTokenSpaceGuid.PcdEnableUsbNetworkRateLimiting >> + gEfiMdeModulePkgTokenSpaceGuid.PcdUsbNetworkRateLimitingCredit >> + gEfiMdeModulePkgTokenSpaceGuid.PcdUsbNetworkRateLimitingFactor >> + >> +[Depex] >> + TRUE >> diff --git >> a/MdeModulePkg/Bus/Usb/UsbNetwork/NetworkCommon/PxeFunction.c >> b/MdeModulePkg/Bus/Usb/UsbNetwork/NetworkCommon/PxeFunction.c >> new file mode 100644 >> index 0000000000..687cabca4c >> --- /dev/null >> +++ >> b/MdeModulePkg/Bus/Usb/UsbNetwork/NetworkCommon/PxeFunction.c >> @@ -0,0 +1,1803 @@ >> +/** @file >> + This file contains code for UNDI command based on UEFI specification. >> + >> + Copyright (c) 2023, American Megatrends International LLC. All rights >> reserved.
>> + SPDX-License-Identifier: BSD-2-Clause-Patent >> +**/ >> + >> +#include "DriverBinding.h" >> + >> +// API table, defined in UEFI specification >> +API_FUNC gUndiApiTable[] = { >> + UndiGetState, >> + UndiStart, >> + UndiStop, >> + UndiGetInitInfo, >> + UndiGetConfigInfo, >> + UndiInitialize, >> + UndiReset, >> + UndiShutdown, >> + UndiInterruptEnable, >> + UndiReceiveFilter, >> + UndiStationAddress, >> + UndiStatistics, >> + UndiMcastIp2Mac, >> + UndiNvData, >> + UndiGetStatus, >> + UndiFillHeader, >> + UndiTransmit, >> + UndiReceive >> +}; >> + >> +/** >> + Callback function for enable Rate Limiter >> + >> + @param[in] Event Event whose notification function is being >> invoked >> + @param[in] Context Pointer to the notification function's context >> + >> +**/ >> +VOID >> +EFIAPI >> +UndiRateLimiterCallback ( >> + IN EFI_EVENT Event, >> + IN VOID *Context >> + ) >> +{ >> + NIC_DATA *Nic = Context; >> + >> + if (Nic->RateLimitingCreditCount < Nic->RateLimitingCredit) { >> + Nic->RateLimitingCreditCount++; >> + } >> +} >> + >> +/** >> + This command is used to determine the operational state of the UNDI. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiGetState ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + EFI_STATUS Status; >> + >> + if ((Cdb->OpCode != PXE_OPCODE_GET_STATE) || >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) || >> + (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED) || >> + (Cdb->DBsize != PXE_DBSIZE_NOT_USED) || >> + (Cdb->DBaddr != PXE_DBADDR_NOT_USED) || >> + (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED)) >> + { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> + } >> + >> + Cdb->StatFlags = Cdb->StatFlags | Nic->State; >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetState != NULL) { >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiGetState (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + } >> +} >> + >> +/** >> + This command is used to change the UNDI operational state from stopped >> to started. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiStart ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + PXE_CPB_START_31 *Cpb; >> + EFI_STATUS Status; >> + BOOLEAN EventError; >> + >> + if ((Cdb->OpCode != PXE_OPCODE_START) || >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize != sizeof (PXE_CPB_START_31)) || >> + (Cdb->DBsize != PXE_DBSIZE_NOT_USED) || >> + (Cdb->DBaddr != PXE_DBADDR_NOT_USED) || >> + (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED)) >> + { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> + return; >> + } >> + >> + if (Nic->State != PXE_STATFLAGS_GET_STATE_STOPPED) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_ALREADY_STARTED; >> + return; >> + } >> + >> + Cpb = (PXE_CPB_START_31 *)(UINTN)Cdb->CPBaddr; >> + >> + Nic->PxeStart.Delay = Cpb->Delay; >> + Nic->PxeStart.Virt2Phys = Cpb->Virt2Phys; >> + Nic->PxeStart.Block = Cpb->Block; >> + Nic->PxeStart.Map_Mem = 0; >> + Nic->PxeStart.UnMap_Mem = 0; >> + Nic->PxeStart.Sync_Mem = Cpb->Sync_Mem; >> + Nic->PxeStart.Unique_ID = Cpb->Unique_ID; >> + EventError = FALSE; >> + Status = EFI_SUCCESS; >> + if (Nic->RateLimitingEnable == TRUE) { >> + Status = gBS->CreateEvent ( >> + EVT_TIMER | EVT_NOTIFY_SIGNAL, >> + TPL_NOTIFY, >> + UndiRateLimiterCallback, >> + Nic, >> + &Nic->RateLimiter >> + ); >> + if (!EFI_ERROR (Status)) { >> + Status = gBS->SetTimer ( >> + Nic->RateLimiter, >> + TimerPeriodic, >> + Nic->RateLimitingPollTimer * 10000 >> + ); >> + if (EFI_ERROR (Status)) { >> + EventError = TRUE; >> + } >> + } >> + } >> + >> + if ((Nic->UsbEth->UsbEthUndi.UsbEthUndiStart != NULL) && (EventError >> == FALSE)) { >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiStart (Cdb, Nic); >> + } >> + >> + if (!EFI_ERROR (Status)) { >> + // Initial the state for UNDI start. >> + Nic->State = PXE_STATFLAGS_GET_STATE_STARTED; >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> + } else { >> + if (Nic->RateLimitingEnable == TRUE) { >> + if (!EventError) { >> + gBS->SetTimer (&Nic->RateLimiter, TimerCancel, 0); >> + } >> + >> + if (Nic->RateLimiter) { >> + gBS->CloseEvent (&Nic->RateLimiter); >> + Nic->RateLimiter = 0; >> + } >> + } >> + >> + // Initial the state when UNDI start is fail >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_DEVICE_FAILURE; >> + } >> +} >> + >> +/** >> + This command is used to change the UNDI operational state from started >> to stopped. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiStop ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + EFI_STATUS Status; >> + >> + if ((Cdb->OpCode != PXE_OPCODE_STOP) || >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) || >> + (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED) || >> + (Cdb->DBsize != PXE_DBSIZE_NOT_USED) || >> + (Cdb->DBaddr != PXE_DBADDR_NOT_USED) || >> + (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED)) >> + { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> + } >> + >> + if (Nic->State == PXE_STATFLAGS_GET_STATE_STOPPED) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_NOT_STARTED; >> + return; >> + } >> + >> + if (Nic->State == PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_NOT_SHUTDOWN; >> + return; >> + } >> + >> + Nic->PxeStart.Delay = 0; >> + Nic->PxeStart.Virt2Phys = 0; >> + Nic->PxeStart.Block = 0; >> + Nic->PxeStart.Map_Mem = 0; >> + Nic->PxeStart.UnMap_Mem = 0; >> + Nic->PxeStart.Sync_Mem = 0; >> + Nic->State = PXE_STATFLAGS_GET_STATE_STOPPED; >> + >> + if (Nic->RateLimitingEnable == TRUE) { >> + gBS->SetTimer (&Nic->RateLimiter, TimerCancel, 0); >> + gBS->CloseEvent (&Nic->RateLimiter); >> + } >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStop != NULL) { >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiStop (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + } >> +} >> + >> +/** >> + This command is used to retrieve initialization information that is >> + needed by drivers and applications to initialized UNDI. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiGetInitInfo ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + PXE_DB_GET_INIT_INFO *Db; >> + EFI_STATUS Status; >> + >> + if ((Cdb->OpCode != PXE_OPCODE_GET_INIT_INFO) || >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) || >> + (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED) || >> + (Cdb->DBsize != sizeof (PXE_DB_GET_INIT_INFO)) || >> + (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED)) >> + { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> + } >> + >> + if (Nic->State == PXE_STATFLAGS_GET_STATE_STOPPED) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_NOT_STARTED; >> + return; >> + } >> + >> + Db = (PXE_DB_GET_INIT_INFO *)(UINTN)Cdb->DBaddr; >> + >> + Db->MemoryRequired = MEMORY_REQUIRE; >> + Db->FrameDataLen = PXE_MAX_TXRX_UNIT_ETHER; >> + Db->LinkSpeeds[0] = 10; >> + Db->LinkSpeeds[1] = 100; >> + Db->LinkSpeeds[2] = 1000; >> + Db->LinkSpeeds[3] = 0; >> + Db->MediaHeaderLen = PXE_MAC_HEADER_LEN_ETHER; >> + Db->HWaddrLen = PXE_HWADDR_LEN_ETHER; >> + Db->MCastFilterCnt = MAX_MCAST_ADDRESS_CNT; >> + Db->TxBufCnt = Nic->PxeInit.TxBufCnt; >> + Db->TxBufSize = Nic->PxeInit.TxBufSize; >> + Db->RxBufCnt = Nic->PxeInit.RxBufCnt; >> + Db->RxBufSize = Nic->PxeInit.RxBufSize; >> + Db->IFtype = PXE_IFTYPE_ETHERNET; >> + Db->SupportedDuplexModes = PXE_DUPLEX_DEFAULT; >> + Db->SupportedLoopBackModes = LOOPBACK_NORMAL; >> + >> + Cdb->StatFlags |= (PXE_STATFLAGS_CABLE_DETECT_SUPPORTED | >> + PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED); >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetInitInfo != NULL) { >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiGetInitInfo (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + } >> +} >> + >> +/** >> + This command is used to retrieve configuration information about >> + the NIC being controlled by the UNDI. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiGetConfigInfo ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + PXE_DB_GET_CONFIG_INFO *Db; >> + EFI_STATUS Status; >> + >> + if ((Cdb->OpCode != PXE_OPCODE_GET_CONFIG_INFO) || >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) || >> + (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED) || >> + (Cdb->DBsize != sizeof (PXE_DB_GET_CONFIG_INFO)) || >> + (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED)) >> + { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> + } >> + >> + if (Nic->State == PXE_STATFLAGS_GET_STATE_STOPPED) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_NOT_STARTED; >> + return; >> + } >> + >> + Db = (PXE_DB_GET_CONFIG_INFO *)(UINTN)Cdb->DBaddr; >> + >> + Db->pci.BusType = PXE_BUSTYPE_USB; >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetConfigInfo != NULL) { >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiGetConfigInfo (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + } >> +} >> + >> +/** >> + This command resets the network adapter and initializes UNDI using >> + the parameters supplied in the CPB. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in, out] Nic A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiInitialize ( >> + IN PXE_CDB *Cdb, >> + IN OUT NIC_DATA *Nic >> + ) >> +{ >> + PXE_CPB_INITIALIZE *Cpb; >> + PXE_DB_INITIALIZE *Db; >> + EFI_STATUS Status; >> + >> + if ((Cdb->OpCode != PXE_OPCODE_INITIALIZE) || >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize != sizeof (PXE_CPB_INITIALIZE))) >> + { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> + } >> + >> + if (Nic->State == PXE_STATFLAGS_GET_STATE_STOPPED) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_NOT_STARTED; >> + return; >> + } >> + >> + if ((Cdb->OpFlags != PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) && >> + (Cdb->OpFlags != PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE)) >> + { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> + return; >> + } >> + >> + if (Nic->State == PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_ALREADY_INITIALIZED; >> + return; >> + } >> + >> + Cpb = (PXE_CPB_INITIALIZE *)(UINTN)Cdb->CPBaddr; >> + Db = (PXE_DB_INITIALIZE *)(UINTN)Cdb->DBaddr; >> + >> + Nic->PxeInit.LinkSpeed = Cpb->LinkSpeed; >> + Nic->PxeInit.DuplexMode = Cpb->DuplexMode; >> + Nic->PxeInit.LoopBackMode = Cpb->LoopBackMode; >> + Nic->PxeInit.MemoryAddr = Cpb->MemoryAddr; >> + Nic->PxeInit.MemoryLength = Cpb->MemoryLength; >> + Nic->PxeInit.TxBufCnt = TX_BUFFER_COUNT; >> + Nic->PxeInit.TxBufSize = Nic->MaxSegmentSize; >> + Nic->PxeInit.RxBufCnt = RX_BUFFER_COUNT; >> + Nic->PxeInit.RxBufSize = Nic->MaxSegmentSize; >> + >> + Cdb->StatCode = Initialize (Cdb, Nic); >> + >> + Db->MemoryUsed = MEMORY_REQUIRE; >> + Db->TxBufCnt = Nic->PxeInit.TxBufCnt; >> + Db->TxBufSize = Nic->PxeInit.TxBufSize; >> + Db->RxBufCnt = Nic->PxeInit.RxBufCnt; >> + Db->RxBufSize = Nic->PxeInit.RxBufSize; >> + >> + Nic->RxFilter = PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST; >> + Nic->CanTransmit = FALSE; >> + >> + if (Cdb->OpFlags == PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) { >> + if ((Nic->Request.Request == USB_CDC_NETWORK_CONNECTION) && >> (Nic->Request.Value == NETWORK_DISCONNECT)) { >> + Nic->CableDetect = 0; >> + } else if ((Nic->Request.Request == USB_CDC_NETWORK_CONNECTION) >> && (Nic->Request.Value == NETWORK_CONNECTED)) { >> + Nic->CableDetect = 1; >> + } >> + >> + if (Nic->CableDetect == 0) { >> + Cdb->StatFlags |= PXE_STATFLAGS_INITIALIZED_NO_MEDIA; >> + } >> + } >> + >> + if (Cdb->StatCode != PXE_STATCODE_SUCCESS) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + } else { >> + Nic->State = PXE_STATFLAGS_GET_STATE_INITIALIZED; >> + } >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiInitialize != NULL) { >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiInitialize (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + } >> +} >> + >> +/** >> + Initialize Network interface controller data. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in, out] Nic A pointer to the Network interface controller data. >> + >> + @retval Status A value of Pxe statcode. >> + >> +**/ >> +UINT16 >> +Initialize ( >> + IN PXE_CDB *Cdb, >> + IN OUT NIC_DATA *Nic >> + ) >> +{ >> + UINTN Status; >> + UINT32 Index; >> + EFI_STATUS EfiStatus; >> + >> + Status = MapIt ( >> + Nic, >> + Nic->PxeInit.MemoryAddr, >> + Nic->PxeInit.MemoryLength, >> + TO_AND_FROM_DEVICE, >> + (UINT64)(UINTN)&Nic->MappedAddr >> + ); >> + >> + if (Status != 0) { >> + return (UINT16)Status; >> + } >> + >> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> + Nic->PermNodeAddress[Index] = Nic->MacAddr.Addr[Index]; >> + } >> + >> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> + Nic->CurrentNodeAddress[Index] = Nic->PermNodeAddress[Index]; >> + } >> + >> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> + Nic->BroadcastNodeAddress[Index] = 0xFF; >> + } >> + >> + for (Index = PXE_HWADDR_LEN_ETHER; Index < PXE_MAC_LENGTH; >> Index++) { >> + Nic->CurrentNodeAddress[Index] = 0; >> + Nic->PermNodeAddress[Index] = 0; >> + Nic->BroadcastNodeAddress[Index] = 0; >> + } >> + >> + if (Nic->UsbEth->UsbEthInitialize != NULL) { >> + EfiStatus = Nic->UsbEth->UsbEthInitialize (Cdb, Nic); >> + if (EFI_ERROR (EfiStatus)) { >> + return PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + } >> + >> + return (UINT16)Status; >> +} >> + >> +/** >> + This command resets the network adapter and reinitializes the UNDI >> + with the same parameters provided in the Initialize command. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiReset ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + EFI_STATUS Status; >> + >> + if ((Cdb->OpCode != PXE_OPCODE_RESET) || >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) || >> + (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED) || >> + (Cdb->DBsize != PXE_DBSIZE_NOT_USED) || >> + (Cdb->DBaddr != PXE_DBADDR_NOT_USED)) >> + { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> + } >> + >> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED; >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + return; >> + } >> + >> + if ((Cdb->OpFlags != PXE_OPFLAGS_NOT_USED) && >> + (Cdb->OpFlags != PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS) && >> + (Cdb->OpFlags != PXE_OPFLAGS_RESET_DISABLE_FILTERS)) >> + { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> + return; >> + } >> + >> + if ((Cdb->OpFlags & PXE_OPFLAGS_RESET_DISABLE_FILTERS) == 0) { >> + Nic->RxFilter = PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST; >> + } >> + >> + if ((Cdb->OpFlags & PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS) != 0) { >> + Nic->InterrupOpFlag = 0; >> + } >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiReset != NULL) { >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiReset (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + } >> +} >> + >> +/** >> + The Shutdown command resets the network adapter and leaves it in a >> + safe state for another driver to initialize. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in, out] Nic A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiShutdown ( >> + IN PXE_CDB *Cdb, >> + IN OUT NIC_DATA *Nic >> + ) >> +{ >> + EFI_STATUS Status; >> + >> + if ((Cdb->OpCode != PXE_OPCODE_SHUTDOWN) || >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) || >> + (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED) || >> + (Cdb->DBsize != PXE_DBSIZE_NOT_USED) || >> + (Cdb->DBaddr != PXE_DBADDR_NOT_USED) || >> + (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED)) >> + { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> + } >> + >> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED; >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + return; >> + } >> + >> + Nic->CanTransmit = FALSE; >> + >> + Nic->State = PXE_STATFLAGS_GET_STATE_STARTED; >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiShutdown != NULL) { >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiShutdown (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED; >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + } >> +} >> + >> +/** >> + The Interrupt Enables command can be used to read and/or change >> + the current external interrupt enable settings. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiInterruptEnable ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + EFI_STATUS Status; >> + >> + Cdb->StatCode = PXE_STATCODE_UNSUPPORTED; >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiInterruptEnable != NULL) { >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiInterruptEnable (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + } else { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> + } >> + } >> +} >> + >> +/** >> + This command is used to read and change receive filters and, >> + if supported, read and change the multicast MAC address filter list. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiReceiveFilter ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + UINT16 NewFilter; >> + PXE_DB_RECEIVE_FILTERS *Db; >> + EFI_STATUS Status; >> + >> + if ((Cdb->OpCode != PXE_OPCODE_RECEIVE_FILTERS) || >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8))) >> + { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> + } >> + >> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED; >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + return; >> + } >> + >> + NewFilter = (UINT16)(Cdb->OpFlags & 0x1F); >> + >> + switch (Cdb->OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_OPMASK) { >> + case PXE_OPFLAGS_RECEIVE_FILTER_READ: >> + if (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> + } >> + >> + if ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) == >> 0) { >> + if ((Cdb->DBsize != 0)) { >> + Db = (PXE_DB_RECEIVE_FILTERS *)(UINTN)Cdb->DBaddr; >> + CopyMem (Db, &Nic->McastList, Nic->McastCount); >> + } >> + } >> + >> + break; >> + >> + case PXE_OPFLAGS_RECEIVE_FILTER_ENABLE: >> + if (NewFilter == 0) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + >> + if (Cdb->CPBsize != 0) { >> + if (((NewFilter & >> PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) == 0) || >> + ((NewFilter & >> PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) != 0) || >> + ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) != 0) >> || >> + ((Cdb->CPBsize % sizeof (PXE_MAC_ADDR)) != 0)) >> + { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + } >> + >> + if ((Cdb->OpFlags & >> PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) != 0) { >> + if (((Cdb->OpFlags & >> PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) != 0) || >> + ((Cdb->OpFlags & >> PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) != 0)) >> + { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + >> + if ((Cdb->CPBsize == 0)) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + } >> + >> + Cdb->StatCode = SetFilter (Nic, NewFilter, Cdb->CPBaddr, Cdb->CPBsize); >> + break; >> + >> + case PXE_OPFLAGS_RECEIVE_FILTER_DISABLE: >> + if (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> + } >> + >> + break; >> + >> + default: >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> + } >> + >> + Cdb->StatFlags = (PXE_STATFLAGS)(Cdb->StatFlags | Nic->RxFilter); >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiReceiveFilter != NULL) { >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiReceiveFilter (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + } >> +} >> + >> +/** >> + Set PXE receive filter. >> + >> + @param[in] Nic A pointer to the Network interface controller data. >> + @param[in] SetFilter PXE receive filter >> + @param[in] CpbAddr Command Parameter Block Address >> + @param[in] CpbSize Command Parameter Block Size >> + >> +**/ >> +UINT16 >> +SetFilter ( >> + IN NIC_DATA *Nic, >> + IN UINT16 SetFilter, >> + IN UINT64 CpbAddr, >> + IN UINT32 CpbSize >> + ) >> +{ >> + EFI_STATUS Status; >> + UINT8 *McastList; >> + UINT8 Count; >> + UINT8 Index1; >> + UINT8 Index2; >> + PXE_CPB_RECEIVE_FILTERS *Cpb; >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; >> + >> + Count = 0; >> + Cpb = (PXE_CPB_RECEIVE_FILTERS *)(UINTN)CpbAddr; >> + >> + // The Cpb could be NULL.(ref:PXE_CPBADDR_NOT_USED) >> + Nic->RxFilter = (UINT8)SetFilter; >> + >> + if (((SetFilter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) != >> 0) || (Cpb != NULL)) { >> + if (Cpb != NULL) { >> + Nic->McastCount = (UINT8)(CpbSize / PXE_MAC_LENGTH); >> + CopyMem (&Nic->McastList, Cpb, Nic->McastCount); >> + } >> + >> + Nic->UsbEth->UsbEthFunDescriptor (Nic->UsbEth, >> &UsbEthFunDescriptor); >> + if ((UsbEthFunDescriptor.NumberMcFilters << 1) == 0) { >> + Nic->RxFilter |= PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST; >> + Nic->UsbEth->SetUsbEthPacketFilter (Nic->UsbEth, Nic->RxFilter); >> + } else { >> + Status = gBS->AllocatePool (EfiBootServicesData, Nic->McastCount * 6, >> (VOID **)&McastList); >> + if (EFI_ERROR (Status)) { >> + return PXE_STATCODE_INVALID_PARAMETER; >> + } >> + >> + if (Cpb != NULL) { >> + for (Index1 = 0; Index1 < Nic->McastCount; Index1++) { >> + for (Index2 = 0; Index2 < 6; Index2++) { >> + McastList[Count++] = Cpb->MCastList[Index1][Index2]; >> + } >> + } >> + } >> + >> + Nic->RxFilter |= PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST; >> + if (Cpb != NULL) { >> + Nic->UsbEth->SetUsbEthMcastFilter (Nic->UsbEth, Nic->McastCount, >> McastList); >> + } >> + >> + Nic->UsbEth->SetUsbEthPacketFilter (Nic->UsbEth, Nic->RxFilter); >> + FreePool (McastList); >> + } >> + } >> + >> + return PXE_STATCODE_SUCCESS; >> +} >> + >> +/** >> + This command is used to get current station and broadcast MAC addresses >> + and, if supported, to change the current station MAC address. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiStationAddress ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + PXE_CPB_STATION_ADDRESS *Cpb; >> + PXE_DB_STATION_ADDRESS *Db; >> + UINT16 Index; >> + EFI_STATUS Status; >> + >> + if ((Cdb->OpCode != PXE_OPCODE_STATION_ADDRESS) || >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->DBsize != sizeof (PXE_DB_STATION_ADDRESS))) >> + { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> + } >> + >> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED; >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + return; >> + } >> + >> + if (Cdb->OpFlags == PXE_OPFLAGS_STATION_ADDRESS_RESET) { >> + if (CompareMem (&Nic->CurrentNodeAddress[0], &Nic- >>> PermNodeAddress[0], PXE_MAC_LENGTH) != 0) { >> + for (Index = 0; Index < PXE_MAC_LENGTH; Index++) { >> + Nic->CurrentNodeAddress[Index] = Nic->PermNodeAddress[Index]; >> + } >> + } >> + } >> + >> + if (Cdb->CPBaddr != 0) { >> + Cpb = (PXE_CPB_STATION_ADDRESS *)(UINTN)Cdb->CPBaddr; >> + for (Index = 0; Index < PXE_MAC_LENGTH; Index++) { >> + Nic->CurrentNodeAddress[Index] = Cpb->StationAddr[Index]; >> + } >> + } >> + >> + if (Cdb->DBaddr != 0) { >> + Db = (PXE_DB_STATION_ADDRESS *)(UINTN)Cdb->DBaddr; >> + for (Index = 0; Index < PXE_MAC_LENGTH; Index++) { >> + Db->StationAddr[Index] = Nic->CurrentNodeAddress[Index]; >> + Db->BroadcastAddr[Index] = Nic->BroadcastNodeAddress[Index]; >> + Db->PermanentAddr[Index] = Nic->PermNodeAddress[Index]; >> + } >> + } >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStationAddress != NULL) { >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiStationAddress (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + } >> +} >> + >> +/** >> + This command is used to read and clear the NIC traffic statistics. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiStatistics ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + EFI_STATUS Status; >> + >> + if ((Cdb->OpCode != PXE_OPCODE_STATISTICS) || >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) || >> + (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED)) >> + { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> + } >> + >> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED; >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + return; >> + } >> + >> + if ((Cdb->OpFlags != PXE_OPFLAGS_STATISTICS_RESET) && >> + (Cdb->OpFlags != PXE_OPFLAGS_STATISTICS_READ)) >> + { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> + return; >> + } >> + >> + Cdb->StatCode = Statistics (Nic, Cdb->DBaddr, Cdb->DBsize); >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiStatistics != NULL) { >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiStatistics (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + } >> +} >> + >> +/** >> + Return data for DB data. >> + >> + @param[in] Nic A pointer to the Network interface controller data. >> + @param[in] DbAddr Data Block Address. >> + @param[in] DbSize Data Block Size. >> + >> +**/ >> +UINT16 >> +Statistics ( >> + IN NIC_DATA *Nic, >> + IN UINT64 DbAddr, >> + IN UINT16 DbSize >> + ) >> +{ >> + PXE_DB_STATISTICS *DbStatistic; >> + EFI_STATUS Status; >> + >> + DbStatistic = (PXE_DB_STATISTICS *)(UINTN)DbAddr; >> + >> + if (DbSize == 0) { >> + return PXE_STATCODE_SUCCESS; >> + } >> + >> + DbStatistic->Supported = 0x802; >> + DbStatistic->Data[0x01] = Nic->RxFrame; >> + DbStatistic->Data[0x0B] = Nic->TxFrame; >> + >> + if (Nic->UsbEth->UsbEthStatistics != NULL) { >> + Status = Nic->UsbEth->UsbEthStatistics (Nic, DbAddr, DbSize); >> + if (EFI_ERROR (Status)) { >> + return PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + } >> + >> + return PXE_STATCODE_SUCCESS; >> +} >> + >> +/** >> + Translate a multicast IPv4 or IPv6 address to a multicast MAC address. >> + >> + @param[in, out] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiMcastIp2Mac ( >> + IN OUT PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + PXE_CPB_MCAST_IP_TO_MAC *Cpb; >> + PXE_DB_MCAST_IP_TO_MAC *Db; >> + UINT8 *Tmp; >> + EFI_STATUS Status; >> + >> + if ((Cdb->OpCode != PXE_OPCODE_MCAST_IP_TO_MAC) || >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize != sizeof (PXE_CPB_MCAST_IP_TO_MAC)) || >> + (Cdb->DBsize != sizeof (PXE_DB_MCAST_IP_TO_MAC))) >> + { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> + } >> + >> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED; >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + return; >> + } >> + >> + Cpb = (PXE_CPB_MCAST_IP_TO_MAC *)(UINTN)Cdb->CPBaddr; >> + Db = (PXE_DB_MCAST_IP_TO_MAC *)(UINTN)Cdb->DBaddr; >> + >> + if ((Cdb->OpFlags & PXE_OPFLAGS_MCAST_IPV6_TO_MAC) != 0) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_UNSUPPORTED; >> + return; >> + } >> + >> + Tmp = (UINT8 *)(&Cpb->IP.IPv4); >> + >> + if ((Tmp[0] & 0xF0) != 0xE0) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CPB; >> + } >> + >> + Db->MAC[0] = 0x01; >> + Db->MAC[1] = 0x00; >> + Db->MAC[2] = 0x5E; >> + Db->MAC[3] = Tmp[1] & 0x7F; >> + Db->MAC[4] = Tmp[2]; >> + Db->MAC[5] = Tmp[3]; >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiMcastIp2Mac != NULL) { >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiMcastIp2Mac (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + } >> +} >> + >> +/** >> + This command is used to read and write (if supported by NIC H/W) >> + nonvolatile storage on the NIC. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiNvData ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + EFI_STATUS Status; >> + >> + Cdb->StatCode = PXE_STATCODE_UNSUPPORTED; >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiNvData != NULL) { >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiNvData (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + } else { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> + } >> + } >> +} >> + >> +/** >> + This command returns the current interrupt status and/or the >> + transmitted buffer addresses and the current media status. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiGetStatus ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + PXE_DB_GET_STATUS *Db; >> + PXE_DB_GET_STATUS TmpGetStatus; >> + UINT16 NumEntries; >> + UINTN Index; >> + EFI_STATUS Status; >> + >> + if ((Cdb->OpCode != PXE_OPCODE_GET_STATUS) || >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize != PXE_CPBSIZE_NOT_USED) || >> + (Cdb->CPBaddr != PXE_CPBADDR_NOT_USED)) >> + { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> + } >> + >> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED; >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + return; >> + } >> + >> + TmpGetStatus.RxFrameLen = 0; >> + TmpGetStatus.reserved = 0; >> + Db = (PXE_DB_GET_STATUS *)(UINTN)Cdb->DBaddr; >> + >> + if ((Cdb->DBsize > 0) && (Cdb->DBsize < sizeof (UINT32) * 2)) { >> + CopyMem (Db, &TmpGetStatus, Cdb->DBsize); >> + } else { >> + CopyMem (Db, &TmpGetStatus, sizeof (UINT32) * 2); >> + } >> + >> + if ((Cdb->OpFlags & PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS) != 0) { >> + if (Cdb->DBsize == 0) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> + return; >> + } >> + >> + NumEntries = Cdb->DBsize - sizeof (UINT64); >> + Cdb->DBsize = sizeof (UINT32) * 2; >> + >> + for (Index = 0; NumEntries >= sizeof (UINT64); Index++, NumEntries -= >> sizeof (UINT64)) { >> + if (Nic->TxBufferCount > 0) { >> + Nic->TxBufferCount--; >> + Db->TxBuffer[Index] = Nic->MediaHeader[Nic->TxBufferCount]; >> + } >> + } >> + } >> + >> + if ((Cdb->OpFlags & PXE_OPFLAGS_GET_INTERRUPT_STATUS) != 0) { >> + if (Nic->ReceiveStatus != 0) { >> + Cdb->StatFlags |= PXE_STATFLAGS_GET_STATUS_RECEIVE; >> + } >> + } >> + >> + if ((Nic->Request.Request == USB_CDC_NETWORK_CONNECTION) && >> (Nic->Request.Value == NETWORK_DISCONNECT)) { >> + Nic->CableDetect = 0; >> + } else if ((Nic->Request.Request == USB_CDC_NETWORK_CONNECTION) >> && (Nic->Request.Value == NETWORK_CONNECTED)) { >> + Nic->CableDetect = 1; >> + } >> + >> + if ((Cdb->OpFlags & PXE_OPFLAGS_GET_MEDIA_STATUS) != 0) { >> + if (Nic->CableDetect == 0) { >> + Cdb->StatFlags |= PXE_STATFLAGS_GET_STATUS_NO_MEDIA; >> + } >> + } >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiGetStatus != NULL) { >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiGetStatus (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + } >> +} >> + >> +/** >> + This command is used to fill the media header(s) in transmit packet(s). >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiFillHeader ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + PXE_CPB_FILL_HEADER *CpbFillHeader; >> + PXE_CPB_FILL_HEADER_FRAGMENTED *CpbFill; >> + EthernetHeader *MacHeader; >> + UINTN Index; >> + EFI_STATUS Status; >> + >> + if ((Cdb->OpCode != PXE_OPCODE_FILL_HEADER) || >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize != sizeof (PXE_CPB_FILL_HEADER_FRAGMENTED)) || >> + (Cdb->DBsize != PXE_DBSIZE_NOT_USED) || >> + (Cdb->DBaddr != PXE_DBADDR_NOT_USED)) >> + { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> + } >> + >> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED; >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + return; >> + } >> + >> + if (Cdb->CPBsize == PXE_CPBSIZE_NOT_USED) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> + return; >> + } >> + >> + if ((Cdb->OpFlags & PXE_OPFLAGS_FILL_HEADER_FRAGMENTED) != 0) { >> + CpbFill = (PXE_CPB_FILL_HEADER_FRAGMENTED *)(UINTN)Cdb->CPBaddr; >> + >> + if ((CpbFill->FragCnt == 0) || (CpbFill->FragDesc[0].FragLen < >> PXE_MAC_HEADER_LEN_ETHER)) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> + return; >> + } >> + >> + MacHeader = (EthernetHeader *)(UINTN)CpbFill- >>> FragDesc[0].FragAddr; >> + MacHeader->Protocol = CpbFill->Protocol; >> + >> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> + MacHeader->DestAddr[Index] = CpbFill->DestAddr[Index]; >> + MacHeader->SrcAddr[Index] = CpbFill->SrcAddr[Index]; >> + } >> + } else { >> + CpbFillHeader = (PXE_CPB_FILL_HEADER *)(UINTN)Cdb->CPBaddr; >> + >> + MacHeader = (EthernetHeader *)(UINTN)CpbFillHeader- >>> MediaHeader; >> + MacHeader->Protocol = CpbFillHeader->Protocol; >> + >> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> + MacHeader->DestAddr[Index] = CpbFillHeader->DestAddr[Index]; >> + MacHeader->SrcAddr[Index] = CpbFillHeader->SrcAddr[Index]; >> + } >> + } >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiFillHeader != NULL) { >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiFillHeader (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + } >> +} >> + >> +/** >> + The Transmit command is used to place a packet into the transmit queue. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiTransmit ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + EFI_STATUS Status; >> + >> + if ((Cdb->OpCode != PXE_OPCODE_TRANSMIT) || >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize != sizeof (PXE_CPB_TRANSMIT)) || >> + (Cdb->DBsize != PXE_DBSIZE_NOT_USED) || >> + (Cdb->DBaddr != PXE_DBADDR_NOT_USED)) >> + { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> + } >> + >> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED; >> + return; >> + } >> + >> + if (Cdb->CPBsize == PXE_CPBSIZE_NOT_USED) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> + return; >> + } >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiTransmit != NULL) { >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiTransmit (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + >> + return; >> + } >> + >> + Cdb->StatCode = Transmit (Cdb, Nic, Cdb->CPBaddr, Cdb->OpFlags); >> + >> + if (Cdb->StatCode != PXE_STATCODE_SUCCESS) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + } >> +} >> + >> +/** >> + Use USB Ethernet Protocol Bulk out command to transmit data. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in, out] Nic A pointer to the Network interface controller data. >> + @param[in] CpbAddr Command Parameter Block Address. >> + @param[in] OpFlags Operation Flags. >> + >> +**/ >> +UINT16 >> +Transmit ( >> + IN PXE_CDB *Cdb, >> + IN OUT NIC_DATA *Nic, >> + IN UINT64 CpbAddr, >> + IN UINT16 OpFlags >> + ) >> +{ >> + EFI_STATUS Status; >> + PXE_CPB_TRANSMIT *Cpb; >> + UINT64 BulkOutData; >> + UINTN DataLength; >> + UINTN TransmitLength; >> + UINTN Map; >> + UINT32 Counter; >> + UINT16 StatCode; >> + >> + BulkOutData = 0; >> + Counter = 0; >> + Cpb = (PXE_CPB_TRANSMIT *)(UINTN)CpbAddr; >> + >> + if (Nic->CanTransmit) { >> + return PXE_STATCODE_BUSY; >> + } >> + >> + Nic->CanTransmit = TRUE; >> + >> + if ((OpFlags & PXE_OPFLAGS_TRANSMIT_FRAGMENTED) != 0) { >> + return PXE_STATCODE_INVALID_PARAMETER; >> + } >> + >> + Map = MapIt ( >> + Nic, >> + Cpb->FrameAddr, >> + Cpb->DataLen + (UINT32)Cpb->MediaheaderLen, >> + TO_DEVICE, >> + (UINT64)(UINTN)&BulkOutData >> + ); >> + >> + if (Map != 0) { >> + Nic->CanTransmit = FALSE; >> + return PXE_STATCODE_INVALID_PARAMETER; >> + } >> + >> + if (Nic->TxBufferCount < MAX_XMIT_BUFFERS) { >> + Nic->MediaHeader[Nic->TxBufferCount] = Cpb->FrameAddr; >> + Nic->TxBufferCount++; >> + } >> + >> + DataLength = (UINTN)(Cpb->DataLen + (UINT32)Cpb->MediaheaderLen); >> + >> + while (1) { >> + if (Counter >= 3) { >> + StatCode = PXE_STATCODE_BUSY; >> + break; >> + } >> + >> + TransmitLength = DataLength; >> + >> + Status = Nic->UsbEth->UsbEthTransmit (Cdb, Nic->UsbEth, (VOID >> *)(UINTN)BulkOutData, &TransmitLength); >> + if (EFI_ERROR (Status)) { >> + StatCode = PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + >> + if (Status == EFI_INVALID_PARAMETER) { >> + StatCode = PXE_STATCODE_INVALID_PARAMETER; >> + break; >> + } >> + >> + if (Status == EFI_DEVICE_ERROR) { >> + StatCode = PXE_STATCODE_DEVICE_FAILURE; >> + break; >> + } >> + >> + if (!EFI_ERROR (Status)) { >> + Nic->TxFrame++; >> + StatCode = PXE_STATCODE_SUCCESS; >> + break; >> + } >> + >> + Counter++; >> + } >> + >> + UnMapIt ( >> + Nic, >> + Cpb->FrameAddr, >> + Cpb->DataLen + (UINT32)Cpb->MediaheaderLen, >> + TO_DEVICE, >> + BulkOutData >> + ); >> + >> + Nic->CanTransmit = FALSE; >> + >> + return StatCode; >> +} >> + >> +/** >> + When the network adapter has received a frame, this command is used >> + to copy the frame into driver/application storage. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> +**/ >> +VOID >> +UndiReceive ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + EFI_STATUS Status; >> + >> + if ((Cdb->OpCode != PXE_OPCODE_RECEIVE) || >> + (Cdb->StatCode != PXE_STATCODE_INITIALIZE) || >> + (Cdb->StatFlags != PXE_STATFLAGS_INITIALIZE) || >> + (Cdb->IFnum >= (gPxe->IFcnt | gPxe->IFcntExt << 8)) || >> + (Cdb->CPBsize != sizeof (PXE_CPB_RECEIVE)) || >> + (Cdb->DBsize != sizeof (PXE_DB_RECEIVE)) || >> + (Cdb->OpFlags != PXE_OPFLAGS_NOT_USED)) >> + { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_INVALID_CDB; >> + return; >> + } else { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; >> + Cdb->StatCode = PXE_STATCODE_SUCCESS; >> + } >> + >> + if (Nic->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + Cdb->StatCode = PXE_STATCODE_NOT_INITIALIZED; >> + return; >> + } >> + >> + if (Nic->UsbEth->UsbEthUndi.UsbEthUndiReceive != NULL) { >> + Status = Nic->UsbEth->UsbEthUndi.UsbEthUndiReceive (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + } >> + >> + return; >> + } >> + >> + Cdb->StatCode = Receive (Cdb, Nic, Cdb->CPBaddr, Cdb->DBaddr); >> + >> + if (Cdb->StatCode != PXE_STATCODE_SUCCESS) { >> + Cdb->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; >> + } >> +} >> + >> +/** >> + Use USB Ethernet Protocol Bulk in command to receive data. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in, out] Nic A pointer to the Network interface controller data. >> + @param[in] CpbAddr Command Parameter Block Address. >> + @param[in, out] DbAddr Data Block Address. >> + >> +**/ >> +UINT16 >> +Receive ( >> + IN PXE_CDB *Cdb, >> + IN OUT NIC_DATA *Nic, >> + IN UINT64 CpbAddr, >> + IN OUT UINT64 DbAddr >> + ) >> +{ >> + EFI_STATUS Status; >> + UINTN Index; >> + PXE_FRAME_TYPE FrameType; >> + PXE_CPB_RECEIVE *Cpb; >> + PXE_DB_RECEIVE *Db; >> + NIC_DEVICE *NicDevice; >> + UINT8 *BulkInData; >> + UINTN DataLength; >> + EthernetHeader *Header; >> + EFI_TPL OriginalTpl; >> + >> + FrameType = PXE_FRAME_TYPE_NONE; >> + NicDevice = UNDI_DEV_FROM_NIC (Nic); >> + BulkInData = NicDevice->ReceiveBuffer; >> + DataLength = (UINTN)Nic->MaxSegmentSize; >> + Cpb = (PXE_CPB_RECEIVE *)(UINTN)CpbAddr; >> + Db = (PXE_DB_RECEIVE *)(UINTN)DbAddr; >> + >> + if (!BulkInData) { >> + return PXE_STATCODE_INVALID_PARAMETER; >> + } >> + >> + if ((Nic->RateLimitingCreditCount == 0) && (Nic->RateLimitingEnable == >> TRUE)) { >> + return PXE_STATCODE_NO_DATA; >> + } >> + >> + Status = Nic->UsbEth->UsbEthReceive (Cdb, Nic->UsbEth, (VOID >> *)BulkInData, &DataLength); >> + if (EFI_ERROR (Status)) { >> + Nic->ReceiveStatus = 0; >> + if (Nic->RateLimitingEnable == TRUE) { >> + OriginalTpl = gBS->RaiseTPL (TPL_NOTIFY); >> + if (Nic->RateLimitingCreditCount != 0) { >> + Nic->RateLimitingCreditCount--; >> + } >> + >> + gBS->RestoreTPL (OriginalTpl); >> + } >> + >> + return PXE_STATCODE_NO_DATA; >> + } >> + >> + Nic->RxFrame++; >> + >> + if (DataLength != 0) { >> + if (DataLength > Cpb->BufferLen) { >> + DataLength = (UINTN)Cpb->BufferLen; >> + } >> + >> + CopyMem ((UINT8 *)(UINTN)Cpb->BufferAddr, (UINT8 *)BulkInData, >> DataLength); >> + >> + Header = (EthernetHeader *)BulkInData; >> + >> + Db->FrameLen = (UINT32)DataLength; >> + Db->MediaHeaderLen = PXE_MAC_HEADER_LEN_ETHER; >> + >> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> + if (Header->DestAddr[Index] != Nic->CurrentNodeAddress[Index]) { >> + break; >> + } >> + } >> + >> + if (Index >= PXE_HWADDR_LEN_ETHER) { >> + FrameType = PXE_FRAME_TYPE_UNICAST; >> + } else { >> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> + if (Header->DestAddr[Index] != Nic->BroadcastNodeAddress[Index]) { >> + break; >> + } >> + } >> + >> + if (Index >= PXE_HWADDR_LEN_ETHER) { >> + FrameType = PXE_FRAME_TYPE_BROADCAST; >> + } else { >> + if ((Header->DestAddr[0] & 1) == 1) { >> + FrameType = PXE_FRAME_TYPE_FILTERED_MULTICAST; >> + } else { >> + FrameType = PXE_FRAME_TYPE_PROMISCUOUS; >> + } >> + } >> + } >> + >> + Db->Type = FrameType; >> + Db->Protocol = Header->Protocol; >> + >> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> + Db->SrcAddr[Index] = Header->SrcAddr[Index]; >> + Db->DestAddr[Index] = Header->DestAddr[Index]; >> + } >> + } >> + >> + if (FrameType == PXE_FRAME_TYPE_NONE) { >> + Nic->ReceiveStatus = 0; >> + } else { >> + Nic->ReceiveStatus = 1; >> + } >> + >> + return PXE_STATCODE_SUCCESS; >> +} >> + >> +/** >> + Fill out PXE SW UNDI structure. >> + >> + @param[out] PxeSw A pointer to the PXE SW UNDI structure. >> + >> +**/ >> +VOID >> +PxeStructInit ( >> + OUT PXE_SW_UNDI *PxeSw >> + ) >> +{ >> + PxeSw->Signature = PXE_ROMID_SIGNATURE; >> + PxeSw->Len = (UINT8)sizeof (PXE_SW_UNDI); >> + PxeSw->Fudge = 0; >> + PxeSw->IFcnt = 0; >> + PxeSw->IFcntExt = 0; >> + PxeSw->Rev = PXE_ROMID_REV; >> + PxeSw->MajorVer = PXE_ROMID_MAJORVER; >> + PxeSw->MinorVer = PXE_ROMID_MINORVER; >> + PxeSw->reserved1 = 0; >> + >> + PxeSw->Implementation = PXE_ROMID_IMP_SW_VIRT_ADDR | >> + PXE_ROMID_IMP_FRAG_SUPPORTED | >> + PXE_ROMID_IMP_CMD_LINK_SUPPORTED | >> + PXE_ROMID_IMP_STATION_ADDR_SETTABLE | >> + >> PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED | >> + PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED | >> + PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED | >> + PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED; >> + >> + PxeSw->EntryPoint = (UINT64)(UINTN)UndiApiEntry; >> + PxeSw->reserved2[0] = 0; >> + PxeSw->reserved2[1] = 0; >> + PxeSw->reserved2[2] = 0; >> + PxeSw->BusCnt = 1; >> + PxeSw->BusType[0] = PXE_BUSTYPE_USB; >> + PxeSw->Fudge = PxeSw->Fudge - CalculateSum8 ((VOID *)PxeSw, >> PxeSw->Len); >> +} >> + >> +/** >> + Update NIC number. >> + >> + @param[in] Nic A pointer to the Network interface controller data. >> + @param[in, out] PxeSw A pointer to the PXE SW UNDI structure. >> + >> +**/ >> +VOID >> +UpdateNicNum ( >> + IN NIC_DATA *Nic, >> + IN OUT PXE_SW_UNDI *PxeSw >> + ) >> +{ >> + UINT16 NicNum; >> + >> + NicNum = (PxeSw->IFcnt | PxeSw->IFcntExt << 8); >> + >> + if (Nic == NULL) { >> + if (NicNum > 0) { >> + NicNum--; >> + } >> + >> + PxeSw->IFcnt = (UINT8)(NicNum & 0xFF); // Get lower byte >> + PxeSw->IFcntExt = (UINT8)((NicNum & 0xFF00) >> 8); // Get upper byte >> + PxeSw->Fudge = (UINT8)(PxeSw->Fudge - CalculateSum8 ((VOID >> *)PxeSw, PxeSw->Len)); >> + return; >> + } >> + >> + NicNum++; >> + >> + PxeSw->IFcnt = (UINT8)(NicNum & 0xFF); // Get lower byte >> + PxeSw->IFcntExt = (UINT8)((NicNum & 0xFF00) >> 8); // Get upper byte >> + PxeSw->Fudge = (UINT8)(PxeSw->Fudge - CalculateSum8 ((VOID *)PxeSw, >> PxeSw->Len)); >> +} >> + >> +/** >> + UNDI API table entry. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +UndiApiEntry ( >> + IN UINT64 Cdb >> + ) >> +{ >> + PXE_CDB *CdbPtr; >> + NIC_DATA *Nic; >> + >> + if (Cdb == 0) { >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + CdbPtr = (PXE_CDB *)(UINTN)Cdb; >> + Nic = &(gLanDeviceList[CdbPtr->IFnum]->NicInfo); >> + gUndiApiTable[CdbPtr->OpCode](CdbPtr, Nic); >> + return EFI_SUCCESS; >> +} >> + >> +/** >> + Map virtual memory address for DMA. This field can be set to >> + zero if there is no mapping service. >> + >> + @param[in] Nic A pointer to the Network interface controller data. >> + @param[in] MemAddr Virtual address to be mapped. >> + @param[in] Size Size of memory to be mapped. >> + @param[in] Direction Direction of data flow for this memory's usage: >> + cpu->device, device->cpu or both ways. >> + @param[out] MappedAddr Pointer to return the mapped device address. >> + >> +**/ >> +UINTN >> +MapIt ( >> + IN NIC_DATA *Nic, >> + IN UINT64 MemAddr, >> + IN UINT32 Size, >> + IN UINT32 Direction, >> + OUT UINT64 MappedAddr >> + ) >> +{ >> + UINT64 *PhyAddr; >> + >> + PhyAddr = (UINT64 *)(UINTN)MappedAddr; >> + >> + if (Nic->PxeStart.Map_Mem == 0) { >> + *PhyAddr = MemAddr; >> + } else { >> + ((void (*)(UINT64, UINT64, UINT32, UINT32, UINT64))(UINTN) Nic- >>> PxeStart.Map_Mem)( >> + Nic->PxeStart.Unique_ID, >> + MemAddr, >> + Size, >> + Direction, >> + MappedAddr >> + ); >> + } >> + >> + return PXE_STATCODE_SUCCESS; >> +} >> + >> +/** >> + Un-map previously mapped virtual memory address. This field can be set >> + to zero only if the Map_Mem() service is also set to zero. >> + >> + @param[in] Nic A pointer to the Network interface controller data. >> + @param[in] MemAddr Virtual address to be mapped. >> + @param[in] Size Size of memory to be mapped. >> + @param[in] Direction Direction of data flow for this memory's usage: >> + cpu->device, device->cpu or both ways. >> + @param[in] MappedAddr Pointer to return the mapped device address. >> + >> +**/ >> +VOID >> +UnMapIt ( >> + IN NIC_DATA *Nic, >> + IN UINT64 MemAddr, >> + IN UINT32 Size, >> + IN UINT32 Direction, >> + IN UINT64 MappedAddr >> + ) >> +{ >> + if (Nic->PxeStart.UnMap_Mem != 0) { >> + ((void (*)(UINT64, UINT64, UINT32, UINT32, UINT64))(UINTN) Nic- >>> PxeStart.UnMap_Mem)( >> + Nic->PxeStart.Unique_ID, >> + MemAddr, >> + Size, >> + Direction, >> + MappedAddr >> + ); >> + } >> + >> + return; >> +} >> diff --git >> a/MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis/ComponentName.c >> b/MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis/ComponentName.c >> new file mode 100644 >> index 0000000000..b9ba170c13 >> --- /dev/null >> +++ b/MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis/ComponentName.c >> @@ -0,0 +1,172 @@ >> +/** @file >> + This file contains code for USB RNDIS Driver Component >> + Name definitions >> + >> + Copyright (c) 2023, American Megatrends International LLC. All rights >> reserved.
>> + SPDX-License-Identifier: BSD-2-Clause-Patent >> +**/ >> + >> +#include "UsbRndis.h" >> + >> +GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE >> gUsbRndisDriverNameTable[] = { >> + { >> + "eng;en", >> + L"USB RNDIS Driver" >> + }, >> + { >> + NULL, >> + NULL >> + } >> +}; >> + >> +EFI_STATUS >> +EFIAPI >> +UsbRndisComponentNameGetDriverName ( >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> + IN CHAR8 *Language, >> + OUT CHAR16 **DriverName >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +UsbRndisComponentNameGetControllerName ( >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> + IN EFI_HANDLE Controller, >> + IN EFI_HANDLE ChildHandle OPTIONAL, >> + IN CHAR8 *Language, >> + OUT CHAR16 **ControllerName >> + ); >> + >> +GLOBAL_REMOVE_IF_UNREFERENCED >> EFI_COMPONENT_NAME_PROTOCOL gUsbRndisComponentName = { >> + UsbRndisComponentNameGetDriverName, >> + UsbRndisComponentNameGetControllerName, >> + "eng" >> +}; >> + >> +GLOBAL_REMOVE_IF_UNREFERENCED >> EFI_COMPONENT_NAME2_PROTOCOL gUsbRndisComponentName2 = { >> + >> (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)UsbRndisComponentName >> GetDriverName, >> + >> (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)UsbRndisComponent >> NameGetControllerName, >> + "en" >> +}; >> + >> +/** >> + Retrieves a Unicode string that is the user readable name of the driver. >> + >> + This function retrieves the user readable name of a driver in the form of a >> + Unicode string. If the driver specified by This has a user readable name in >> + the language specified by Language, then a pointer to the driver name is >> + returned in DriverName, and EFI_SUCCESS is returned. If the driver >> specified >> + by This does not support the language specified by Language, >> + then EFI_UNSUPPORTED is returned. >> + >> + @param[in] This A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >> + EFI_COMPONENT_NAME_PROTOCOL instance. >> + @param[in] Language A pointer to a Null-terminated ASCII string >> + array indicating the language. This is the >> + language of the driver name that the caller is >> + requesting, and it must match one of the >> + languages specified in SupportedLanguages. The >> + number of languages supported by a driver is up >> + to the driver writer. Language is specified >> + in RFC 4646 or ISO 639-2 language code format. >> + @param[out] DriverName A pointer to the Unicode string to return. >> + This Unicode string is the name of the >> + driver specified by This in the language >> + specified by Language. >> + >> + @retval EFI_SUCCESS The Unicode string for the Driver specified by >> + This and the language specified by Language was >> + returned in DriverName. >> + @retval EFI_INVALID_PARAMETER Language is NULL. >> + @retval EFI_INVALID_PARAMETER DriverName is NULL. >> + @retval EFI_UNSUPPORTED The driver specified by This does not >> support >> + the language specified by Language. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +UsbRndisComponentNameGetDriverName ( >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> + IN CHAR8 *Language, >> + OUT CHAR16 **DriverName >> + ) >> +{ >> + return LookupUnicodeString2 ( >> + Language, >> + This->SupportedLanguages, >> + gUsbRndisDriverNameTable, >> + DriverName, >> + (BOOLEAN)(This == &gUsbRndisComponentName) >> + ); >> +} >> + >> +/** >> + Retrieves a Unicode string that is the user readable name of the controller >> + that is being managed by a driver. >> + >> + This function retrieves the user readable name of the controller specified >> by >> + ControllerHandle and ChildHandle in the form of a Unicode string. If the >> + driver specified by This has a user readable name in the language specified >> by >> + Language, then a pointer to the controller name is returned in >> ControllerName, >> + and EFI_SUCCESS is returned. If the driver specified by This is not currently >> + managing the controller specified by ControllerHandle and ChildHandle, >> + then EFI_UNSUPPORTED is returned. If the driver specified by This does >> not >> + support the language specified by Language, then EFI_UNSUPPORTED is >> returned. >> + >> + @param[in] This A pointer to the >> EFI_COMPONENT_NAME2_PROTOCOL or >> + EFI_COMPONENT_NAME_PROTOCOL instance. >> + @param[in] Controller The handle of a controller that the driver >> + specified by This is managing. This handle >> + specifies the controller whose name is to be >> + returned. >> + @param[in] ChildHandle The handle of the child controller to retrieve >> + the name of. This is an optional parameter that >> + may be NULL. It will be NULL for device >> + drivers. It will also be NULL for a bus drivers >> + that wish to retrieve the name of the bus >> + controller. It will not be NULL for a bus >> + driver that wishes to retrieve the name of a >> + child controller. >> + @param[in] Language A pointer to a Null-terminated ASCII string >> + array indicating the language. This is the >> + language of the driver name that the caller is >> + requesting, and it must match one of the >> + languages specified in SupportedLanguages. The >> + number of languages supported by a driver is up >> + to the driver writer. Language is specified in >> + RFC 4646 or ISO 639-2 language code format. >> + @param[out] ControllerName A pointer to the Unicode string to return. >> + This Unicode string is the name of the >> + controller specified by ControllerHandle and >> + ChildHandle in the language specified by >> + Language from the point of view of the driver >> + specified by This. >> + >> + @retval EFI_SUCCESS The Unicode string for the user readable name >> in >> + the language specified by Language for the >> + driver specified by This was returned in >> + DriverName. >> + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid >> EFI_HANDLE. >> + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a >> valid >> + EFI_HANDLE. >> + @retval EFI_INVALID_PARAMETER Language is NULL. >> + @retval EFI_INVALID_PARAMETER ControllerName is NULL. >> + @retval EFI_UNSUPPORTED The driver specified by This is not currently >> + managing the controller specified by >> + ControllerHandle and ChildHandle. >> + @retval EFI_UNSUPPORTED The driver specified by This does not >> support >> + the language specified by Language. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +UsbRndisComponentNameGetControllerName ( >> + IN EFI_COMPONENT_NAME_PROTOCOL *This, >> + IN EFI_HANDLE Controller, >> + IN EFI_HANDLE ChildHandle OPTIONAL, >> + IN CHAR8 *Language, >> + OUT CHAR16 **ControllerName >> + ) >> +{ >> + return EFI_UNSUPPORTED; >> +} >> diff --git a/MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis/UsbRndis.c >> b/MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis/UsbRndis.c >> new file mode 100644 >> index 0000000000..9c74d73f78 >> --- /dev/null >> +++ b/MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis/UsbRndis.c >> @@ -0,0 +1,886 @@ >> +/** @file >> + This file contains code for USB Remote Network Driver >> + Interface Spec. Driver Binding >> + >> + Copyright (c) 2023, American Megatrends International LLC. All rights >> reserved.
>> + SPDX-License-Identifier: BSD-2-Clause-Patent >> +**/ >> + >> +#include "UsbRndis.h" >> + >> +EFI_DRIVER_BINDING_PROTOCOL gUsbRndisDriverBinding = { >> + UsbRndisDriverSupported, >> + UsbRndisDriverStart, >> + UsbRndisDriverStop, >> + USB_RNDIS_DRIVER_VERSION, >> + NULL, >> + NULL >> +}; >> + >> +/** >> + Check if this interface is USB Rndis SubType >> + >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance. >> + >> + @retval TRUE USB Rndis SubType. >> + @retval FALSE Not USB Rndis SubType. >> + >> +**/ >> +BOOLEAN >> +IsSupportedDevice ( >> + IN EFI_USB_IO_PROTOCOL *UsbIo >> + ) >> +{ >> + EFI_STATUS Status; >> + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; >> + >> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &InterfaceDescriptor); >> + if (EFI_ERROR (Status)) { >> + return FALSE; >> + } >> + >> + // Check specific device/RNDIS and CDC-DATA >> + if (((InterfaceDescriptor.InterfaceClass == 0x2) && >> + (InterfaceDescriptor.InterfaceSubClass == 0x2) && >> + (InterfaceDescriptor.InterfaceProtocol == 0xFF)) || \ >> + ((InterfaceDescriptor.InterfaceClass == 0xEF) && >> + (InterfaceDescriptor.InterfaceSubClass == 0x4) && >> + (InterfaceDescriptor.InterfaceProtocol == 0x1)) || \ >> + ((InterfaceDescriptor.InterfaceClass == 0xA) && >> + (InterfaceDescriptor.InterfaceSubClass == 0x0) && >> + (InterfaceDescriptor.InterfaceProtocol == 0x00)) >> + ) >> + { >> + return TRUE; >> + } >> + >> + return FALSE; >> +} >> + >> +/** >> + Check if this interface is USB Rndis SubType but not CDC Data interface >> + >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance. >> + >> + @retval TRUE USB Rndis SubType. >> + @retval FALSE Not USB Rndis SubType. >> +**/ >> +BOOLEAN >> +IsRndisInterface ( >> + IN EFI_USB_IO_PROTOCOL *UsbIo >> + ) >> +{ >> + EFI_STATUS Status; >> + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; >> + >> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &InterfaceDescriptor); >> + if (EFI_ERROR (Status)) { >> + return FALSE; >> + } >> + >> + // Check for specific device/RNDIS and CDC-DATA >> + if (((InterfaceDescriptor.InterfaceClass == 0x2) && >> + (InterfaceDescriptor.InterfaceSubClass == 0x2) && >> + (InterfaceDescriptor.InterfaceProtocol == 0xFF)) || \ >> + ((InterfaceDescriptor.InterfaceClass == 0xEF) && >> + (InterfaceDescriptor.InterfaceSubClass == 0x4) && >> + (InterfaceDescriptor.InterfaceProtocol == 0x1)) >> + ) >> + { >> + return TRUE; >> + } >> + >> + return FALSE; >> +} >> + >> +/** >> + Check if the USB RNDIS and USB CDC Data interfaces are from the same >> device. >> + >> + @param[in] UsbRndisDataPath A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> + @param[in] UsbCdcDataPath A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> + >> + @retval EFI_SUCCESS Is the same device. >> + @retval EFI_UNSUPPORTED Is not the same device. >> + >> +**/ >> +EFI_STATUS >> +IsSameDevice ( >> + IN EFI_DEVICE_PATH_PROTOCOL *UsbRndisDataPath, >> + IN EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath >> + ) >> +{ >> + DEBUG ((DEBUG_VERBOSE, "IsSameDevice Entry \n")); >> + while (1) { >> + if (IsDevicePathEnd (NextDevicePathNode (UsbRndisDataPath))) { >> + if (((USB_DEVICE_PATH *)UsbRndisDataPath)->ParentPortNumber == >> + ((USB_DEVICE_PATH *)UsbCdcDataPath)->ParentPortNumber) >> + { >> + return EFI_SUCCESS; >> + } else { >> + return EFI_UNSUPPORTED; >> + } >> + } else { >> + if (CompareMem (UsbCdcDataPath, UsbRndisDataPath, sizeof >> (EFI_DEVICE_PATH_PROTOCOL)) != 0) { >> + return EFI_UNSUPPORTED; >> + } >> + >> + UsbRndisDataPath = NextDevicePathNode (UsbRndisDataPath); >> + UsbCdcDataPath = NextDevicePathNode (UsbCdcDataPath); >> + } >> + } >> + >> + DEBUG ((DEBUG_VERBOSE, "IsSameDevice Exit \n")); >> +} >> + >> +/** >> + Check if the USB CDC Data(UsbIo) installed and return USB CDC Data >> Handle. >> + >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance. >> + >> + @retval TRUE USB CDC Data(UsbIo) installed. >> + @retval FALSE USB CDC Data(UsbIo) did not installed. >> + >> +**/ >> +BOOLEAN >> +IsUsbCdcData ( >> + IN EFI_USB_IO_PROTOCOL *UsbIo >> + ) >> +{ >> + EFI_STATUS Status; >> + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; >> + >> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &InterfaceDescriptor); >> + if (EFI_ERROR (Status)) { >> + return FALSE; >> + } >> + >> + // Check for CDC-DATA >> + if ((InterfaceDescriptor.InterfaceClass == 0xA) && >> + (InterfaceDescriptor.InterfaceSubClass == 0x0) && >> + (InterfaceDescriptor.InterfaceProtocol == 0x0)) >> + { >> + return TRUE; >> + } >> + >> + return FALSE; >> +} >> + >> +/** >> + Check if the USB Rndis(UsbIo) installed >> + >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance. >> + >> + @retval TRUE USB Rndis(UsbIo) installed. >> + @retval FALSE USB Rndis(UsbIo) did not installed. >> + >> +**/ >> +BOOLEAN >> +IsUsbRndis ( >> + IN EFI_USB_IO_PROTOCOL *UsbIo >> + ) >> +{ >> + EFI_STATUS Status; >> + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; >> + >> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &InterfaceDescriptor); >> + if (EFI_ERROR (Status)) { >> + return FALSE; >> + } >> + >> + // Check for Rndis >> + if ((InterfaceDescriptor.InterfaceClass == 0x2) && >> + (InterfaceDescriptor.InterfaceSubClass == 0x2) && >> + (InterfaceDescriptor.InterfaceProtocol == 0xFF)) >> + { >> + return TRUE; >> + } >> + >> + return FALSE; >> +} >> + >> +/** >> + Control comes here when a CDC device is found.Check if a RNDIS interface >> is already found for this device or not. >> + For one device two USBIO will be installed each for CDC and RNDIS >> interface. >> + >> + @param[in] UsbEthPath A pointer to the >> EFI_DEVICE_PATH_PROTOCOL instance. >> + @param[out] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE Data. >> + >> + @retval EFI_SUCCESS The USB_RNDIS_DEVICE matching this CDC >> Data is found. >> + @retval EFI_NOT_FOUND The USB_RNDIS_DEVICE matching this >> CDC Data is not found. >> + >> +**/ >> +EFI_STATUS >> +UpdateRndisDevice ( >> + IN EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath, >> + OUT USB_RNDIS_DEVICE **UsbRndisDevice >> + ) >> +{ >> + EFI_STATUS Status; >> + UINTN Index; >> + UINTN HandleCount; >> + EFI_HANDLE *HandleBuffer; >> + EDKII_USB_ETHERNET_PROTOCOL *UsbEthDevice; >> + EFI_DEVICE_PATH_PROTOCOL *UsbRndisDataPath; >> + EFI_USB_IO_PROTOCOL *UsbIo; >> + BOOLEAN IsRndisInterfaceFlag; >> + >> + IsRndisInterfaceFlag = FALSE; >> + >> + Status = gBS->LocateHandleBuffer ( >> + ByProtocol, >> + &gEdkIIUsbEthProtocolGuid, >> + NULL, >> + &HandleCount, >> + &HandleBuffer >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + for (Index = 0; Index < HandleCount; Index++) { >> + Status = gBS->HandleProtocol ( >> + HandleBuffer[Index], >> + &gEdkIIUsbEthProtocolGuid, >> + (VOID **)&UsbEthDevice >> + ); >> + if (EFI_ERROR (Status)) { >> + continue; >> + } >> + >> + Status = gBS->HandleProtocol ( >> + HandleBuffer[Index], >> + &gEfiUsbIoProtocolGuid, >> + (VOID **)&UsbIo >> + ); >> + if (EFI_ERROR (Status)) { >> + continue; >> + } >> + >> + IsRndisInterfaceFlag = IsRndisInterface (UsbIo); >> + if (IsRndisInterfaceFlag == FALSE) { >> + continue; >> + } >> + >> + Status = gBS->HandleProtocol ( >> + HandleBuffer[Index], >> + &gEfiDevicePathProtocolGuid, >> + (VOID **)&UsbRndisDataPath >> + ); >> + if (EFI_ERROR (Status)) { >> + continue; >> + } >> + >> + Status = IsSameDevice (UsbRndisDataPath, UsbCdcDataPath); >> + >> + DEBUG ((DEBUG_VERBOSE, "Rndis IsSameDevice %r\n", Status)); >> + >> + if (!EFI_ERROR (Status)) { >> + *UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (UsbEthDevice); >> + FreePool (HandleBuffer); >> + return EFI_SUCCESS; >> + } >> + } // End of For loop >> + >> + FreePool (HandleBuffer); >> + return EFI_NOT_FOUND; >> +} >> + >> +/** >> + >> + For the given Rndis Device, find a matching CDC device already exists or >> not. If found update the handle >> + and UsbIO protocol. >> + >> + @param[in] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE >> data. >> + >> +**/ >> +VOID >> +FindMatchingCdcData ( >> + IN USB_RNDIS_DEVICE *UsbRndisDevice >> + ) >> +{ >> + EFI_STATUS Status; >> + UINTN Index; >> + UINTN HandleCount; >> + EFI_HANDLE *HandleBuffer; >> + EFI_USB_IO_PROTOCOL *UsbIo; >> + EFI_DEVICE_PATH_PROTOCOL *UsbRndisDataPath; >> + EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath; >> + >> + // Find the parent RNDIS and update the UsbIo for the CDC device >> + Status = gBS->HandleProtocol ( >> + UsbRndisDevice->UsbRndisHandle, >> + &gEfiDevicePathProtocolGuid, >> + (VOID **)&UsbRndisDataPath >> + ); >> + >> + if (EFI_ERROR (Status)) { >> + return; >> + } >> + >> + Status = gBS->LocateHandleBuffer ( >> + ByProtocol, >> + &gEfiUsbIoProtocolGuid, >> + NULL, >> + &HandleCount, >> + &HandleBuffer >> + ); >> + if (EFI_ERROR (Status)) { >> + return; >> + } >> + >> + for (Index = 0; Index < HandleCount; Index++) { >> + Status = gBS->HandleProtocol ( >> + HandleBuffer[Index], >> + &gEfiUsbIoProtocolGuid, >> + (VOID **)&UsbIo >> + ); >> + ASSERT_EFI_ERROR (Status); >> + >> + if (IsUsbCdcData (UsbIo)) { >> + DEBUG ((DEBUG_VERBOSE, "Rndis FindMatchingCdcData CDCData >> interface found\n")); >> + >> + Status = gBS->HandleProtocol ( >> + HandleBuffer[Index], >> + &gEfiDevicePathProtocolGuid, >> + (VOID **)&UsbCdcDataPath >> + ); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_VERBOSE, "Rndis CDCData DevicePath not found\n")); >> + FreePool (HandleBuffer); >> + return; >> + } >> + >> + Status = IsSameDevice (UsbRndisDataPath, UsbCdcDataPath); >> + DEBUG ((DEBUG_VERBOSE, "Rndis IsSameDevice %r\n", Status)); >> + if (!EFI_ERROR (Status)) { >> + UsbRndisDevice->UsbCdcDataHandle = HandleBuffer[Index]; >> + UsbRndisDevice->UsbIoCdcData = UsbIo; >> + GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice); >> + FreePool (HandleBuffer); >> + return; >> + } >> + } >> + } // End of For loop >> + >> + FreePool (HandleBuffer); >> +} >> + >> +/** >> + >> + For the given UsbIo CdcData, find a matching RNDIS device already exists >> or not. >> + >> + @param[in] CdcHandle A pointer to the EFI_HANDLE for USB CDC >> Data. >> + @param[out] CdcUsbIo A pointer for retrieve the >> EFI_USB_IO_PROTOCOL instance. >> + @param[out] RndisHandle A pointer for retrieve the handle of RNDIS >> device. >> + >> + @retval EFI_SUCCESS The USB_RNDIS_DEVICE matching this CDC >> Data is found. >> + @retval EFI_NOT_FOUND The USB_RNDIS_DEVICE matching this >> CDC Data is not found. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +FindMatchingRndisDev ( >> + IN EFI_HANDLE CdcHandle, >> + OUT EFI_USB_IO_PROTOCOL **CdcUsbIo, >> + OUT EFI_HANDLE *RndisHandle >> + ) >> +{ >> + EFI_STATUS Status; >> + UINTN Index; >> + UINTN HandleCount; >> + EFI_HANDLE *HandleBuffer; >> + EFI_USB_IO_PROTOCOL *UsbIo; >> + EFI_DEVICE_PATH_PROTOCOL *UsbRndisDataPath; >> + EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath; >> + >> + // Find the parent RNDIS and update the UsbIo for the CDC device >> + Status = gBS->HandleProtocol ( >> + CdcHandle, >> + &gEfiDevicePathProtocolGuid, >> + (VOID **)&UsbCdcDataPath >> + ); >> + >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + Status = gBS->LocateHandleBuffer ( >> + ByProtocol, >> + &gEfiUsbIoProtocolGuid, >> + NULL, >> + &HandleCount, >> + &HandleBuffer >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + for (Index = 0; Index < HandleCount; Index++) { >> + Status = gBS->HandleProtocol ( >> + HandleBuffer[Index], >> + &gEfiUsbIoProtocolGuid, >> + (VOID **)&UsbIo >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + if (IsUsbRndis (UsbIo)) { >> + Status = gBS->HandleProtocol ( >> + HandleBuffer[Index], >> + &gEfiDevicePathProtocolGuid, >> + (VOID **)&UsbRndisDataPath >> + ); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "Usb Rndis DevicePath not found\n")); >> + break; >> + } >> + >> + Status = IsSameDevice (UsbRndisDataPath, UsbCdcDataPath); >> + >> + if (!EFI_ERROR (Status)) { >> + *RndisHandle = HandleBuffer[Index]; >> + *CdcUsbIo = UsbIo; >> + FreePool (HandleBuffer); >> + return Status; >> + } >> + } >> + } // End of For loop >> + >> + FreePool (HandleBuffer); >> + >> + return EFI_NOT_FOUND; >> +} >> + >> +/** >> + USB Rndis Driver Binding Support. >> + >> + @param[in] This Protocol instance pointer. >> + @param[in] ControllerHandle Handle of device to test. >> + @param[in] RemainingDevicePath Optional parameter use to pick a >> specific child >> + device to start. >> + >> + @retval EFI_SUCCESS This driver supports this device. >> + @retval EFI_ALREADY_STARTED This driver is already running on this >> device. >> + @retval other This driver does not support this device. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +UsbRndisDriverSupported ( >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> + IN EFI_HANDLE ControllerHandle, >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> + ) >> +{ >> + EFI_STATUS Status; >> + EFI_USB_IO_PROTOCOL *UsbIo; >> + >> + Status = gBS->OpenProtocol ( >> + ControllerHandle, >> + &gEfiUsbIoProtocolGuid, >> + (VOID **)&UsbIo, >> + This->DriverBindingHandle, >> + ControllerHandle, >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + Status = IsSupportedDevice (UsbIo) ? EFI_SUCCESS : EFI_UNSUPPORTED; >> + >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEfiUsbIoProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + return Status; >> +} >> + >> +/** >> + USB RNDIS Driver Binding Start. >> + >> + @param[in] This Protocol instance pointer. >> + @param[in] ControllerHandle Handle of device to bind driver to. >> + @param[in] RemainingDevicePath Optional parameter use to pick a >> specific child >> + device to start. >> + >> + @retval EFI_SUCCESS This driver is added to ControllerHandle >> + @retval EFI_DEVICE_ERROR This driver could not be started due to a >> device error >> + @retval EFI_OUT_OF_RESOURCES The driver could not install >> successfully due to a lack of resources. >> + @retval other This driver does not support this device >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +UsbRndisDriverStart ( >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> + IN EFI_HANDLE ControllerHandle, >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> + ) >> +{ >> + EFI_STATUS Status; >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> + EFI_DEVICE_PATH_PROTOCOL *UsbEthPath; >> + EFI_USB_IO_PROTOCOL *UsbIo; >> + EFI_USB_INTERFACE_DESCRIPTOR Interface; >> + EFI_HANDLE RndisHandle; >> + >> + RndisHandle = ControllerHandle; >> + >> + Status = gBS->OpenProtocol ( >> + ControllerHandle, >> + &gEfiUsbIoProtocolGuid, >> + (VOID **)&UsbIo, >> + This->DriverBindingHandle, >> + ControllerHandle, >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + Status = gBS->OpenProtocol ( >> + ControllerHandle, >> + &gEfiDevicePathProtocolGuid, >> + (VOID **)&UsbEthPath, >> + This->DriverBindingHandle, >> + ControllerHandle, >> + EFI_OPEN_PROTOCOL_BY_DRIVER >> + ); >> + if (EFI_ERROR (Status)) { >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEfiUsbIoProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + return Status; >> + } >> + >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEfiDevicePathProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + >> + // Controls come here for RNDIS and CDC. If it is CDC, check whether >> RNDIS is present on the same controller or not. >> + if (IsUsbCdcData (UsbIo)) { >> + DEBUG ((DEBUG_INFO, "Rndis CDCData interface found\n")); >> + >> + // Find the parent RNDIS and update the UsbIo for the CDC device >> + Status = UpdateRndisDevice ( >> + UsbEthPath, >> + &UsbRndisDevice >> + ); >> + >> + if (!EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_INFO, "Rndis Matching interface found\n")); >> + UsbRndisDevice->UsbCdcDataHandle = ControllerHandle; >> + UsbRndisDevice->UsbIoCdcData = UsbIo; >> + GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice); >> + return Status; >> + } else { >> + // Check if RnDis exist >> + Status = FindMatchingRndisDev ( >> + ControllerHandle, >> + &UsbIo, >> + &RndisHandle >> + ); >> + >> + if (EFI_ERROR (Status)) { >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEfiUsbIoProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + return Status; >> + } >> + } >> + } >> + >> + UsbRndisDevice = AllocateZeroPool (sizeof (USB_RNDIS_DEVICE)); >> + >> + if (!UsbRndisDevice) { >> + DEBUG ((DEBUG_ERROR, "AllocateZeroPool Fail\n")); >> + >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEfiUsbIoProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + return EFI_OUT_OF_RESOURCES; >> + } >> + >> + Status = LoadAllDescriptor ( >> + UsbIo, >> + &UsbRndisDevice->Config >> + ); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "%a:LoadAllDescriptor status = %r\n", __func__, >> Status)); >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEfiUsbIoProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + FreePool (UsbRndisDevice); >> + return Status; >> + } >> + >> + Status = UsbIo->UsbGetInterfaceDescriptor ( >> + UsbIo, >> + &Interface >> + ); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "%a:UsbGetInterfaceDescriptor status = %r\n", >> __func__, Status)); >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEfiUsbIoProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + FreePool (UsbRndisDevice->Config); >> + FreePool (UsbRndisDevice); >> + return Status; >> + } >> + >> + UsbRndisDevice->Signature = USB_RNDIS_SIGNATURE; >> + UsbRndisDevice->NumOfInterface = Interface.InterfaceNumber; >> + UsbRndisDevice->UsbRndisHandle = RndisHandle; >> + UsbRndisDevice->UsbCdcDataHandle = 0; >> + UsbRndisDevice->UsbIo = UsbIo; >> + UsbRndisDevice->UsbEth.UsbEthReceive = RndisUndiReceive; >> + UsbRndisDevice->UsbEth.UsbEthTransmit = RndisUndiTransmit; >> + UsbRndisDevice->UsbEth.UsbEthInterrupt = UsbRndisInterrupt; >> + UsbRndisDevice->UsbEth.UsbEthMacAddress = >> GetUsbEthMacAddress; >> + UsbRndisDevice->UsbEth.UsbEthMaxBulkSize = UsbEthBulkSize; >> + UsbRndisDevice->UsbEth.UsbHeaderFunDescriptor = >> GetUsbHeaderFunDescriptor; >> + UsbRndisDevice->UsbEth.UsbUnionFunDescriptor = >> GetUsbUnionFunDescriptor; >> + UsbRndisDevice->UsbEth.UsbEthFunDescriptor = >> GetUsbRndisFunDescriptor; >> + UsbRndisDevice->UsbEth.SetUsbEthMcastFilter = >> SetUsbRndisMcastFilter; >> + UsbRndisDevice->UsbEth.SetUsbEthPowerPatternFilter = >> SetUsbRndisPowerFilter; >> + UsbRndisDevice->UsbEth.GetUsbEthPowerPatternFilter = >> GetUsbRndisPowerFilter; >> + UsbRndisDevice->UsbEth.SetUsbEthPacketFilter = >> SetUsbRndisPacketFilter; >> + UsbRndisDevice->UsbEth.GetUsbEthStatistic = GetRndisStatistic; >> + >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetState = >> RndisDummyReturn; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStart = >> RndisUndiStart; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStop = >> RndisUndiStop; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetInitInfo = >> RndisUndiGetInitInfo; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetConfigInfo = >> RndisUndiGetConfigInfo; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiInitialize = >> RndisUndiInitialize; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiReset = >> RndisUndiReset; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiShutdown = >> RndisUndiShutdown; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiInterruptEnable = >> RndisDummyReturn; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiReceiveFilter = >> RndisUndiReceiveFilter; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStationAddress = >> RndisDummyReturn; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiStatistics = NULL; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiMcastIp2Mac = >> RndisDummyReturn; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiNvData = >> RndisDummyReturn; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiGetStatus = >> RndisUndiGetStatus; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiFillHeader = >> RndisDummyReturn; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiTransmit = NULL; >> + UsbRndisDevice->UsbEth.UsbEthUndi.UsbEthUndiReceive = NULL; >> + >> + UsbRndisDevice->MaxTransferSize = RNDIS_MAX_TRANSFER_SIZE; >> + UsbRndisDevice->MaxPacketsPerTransfer = 1; >> + UsbRndisDevice->PacketAlignmentFactor = 0; >> + >> + InitializeListHead (&UsbRndisDevice->ReceivePacketList); >> + >> + // This is a RNDIS interface. See whether CDC-DATA interface has already >> been connected or not >> + FindMatchingCdcData (UsbRndisDevice); >> + >> + if (UsbRndisDevice->UsbIoCdcData) { >> + Status = gBS->InstallProtocolInterface ( >> + &ControllerHandle, >> + &gEdkIIUsbEthProtocolGuid, >> + EFI_NATIVE_INTERFACE, >> + &(UsbRndisDevice->UsbEth) >> + ); >> + if (EFI_ERROR (Status)) { >> + gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEfiUsbIoProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + >> + FreePool (UsbRndisDevice->Config); >> + FreePool (UsbRndisDevice); >> + return Status; >> + } >> + >> + GetEndpoint (UsbRndisDevice->UsbIo, UsbRndisDevice); >> + >> + DEBUG ((DEBUG_INFO, "Rndis DeviceHandle %r\n", UsbRndisDevice- >>> UsbRndisHandle)); >> + DEBUG ((DEBUG_INFO, "CDC DeviceHandle %r\n", UsbRndisDevice- >>> UsbCdcDataHandle)); >> + return EFI_SUCCESS; >> + } >> + >> + FreePool (UsbRndisDevice->Config); >> + FreePool (UsbRndisDevice); >> + >> + return EFI_SUCCESS; >> +} >> + >> +/** >> + CheckandStopRndisDevice >> + >> + @param[in] This Protocol instance pointer. >> + @param[in] ControllerHandle Handle of device to bind driver to. >> + >> + @retval EFI_SUCCESS This driver is added to ControllerHandle >> + @retval EFI_DEVICE_ERROR This driver could not be started due to a >> device error >> + @retval other This driver does not support this device >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +CheckandStopRndisDevice ( >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> + IN EFI_HANDLE ControllerHandle >> + ) >> +{ >> + EFI_STATUS Status; >> + EFI_USB_IO_PROTOCOL *UsbIo; >> + >> + Status = gBS->OpenProtocol ( >> + ControllerHandle, >> + &gEfiUsbIoProtocolGuid, >> + (VOID **)&UsbIo, >> + This->DriverBindingHandle, >> + ControllerHandle, >> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + if (IsUsbRndis (UsbIo)) { >> + Status = gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEfiUsbIoProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + DEBUG ((DEBUG_ERROR, "Rndis ControllerHandle Stop %r\n", Status)); >> + return Status; >> + } >> + >> + return EFI_UNSUPPORTED; >> +} >> + >> +/** >> + USB Rndis Driver Binding Stop. >> + >> + @param[in] This Protocol instance pointer. >> + @param[in] ControllerHandle Handle of device to stop driver on >> + @param[in] NumberOfChildren Number of Handles in >> ChildHandleBuffer. If number of >> + children is zero stop the entire bus driver. >> + @param[in] ChildHandleBuffer List of Child Handles to Stop. >> + >> + @retval EFI_SUCCESS This driver is removed ControllerHandle >> + @retval other This driver was not removed from this device >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +UsbRndisDriverStop ( >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> + IN EFI_HANDLE ControllerHandle, >> + IN UINTN NumberOfChildren, >> + IN EFI_HANDLE *ChildHandleBuffer >> + ) >> +{ >> + EFI_STATUS Status; >> + EDKII_USB_ETHERNET_PROTOCOL *UsbEthProtocol; >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> + >> + DEBUG ((DEBUG_INFO, "UsbRndisDriverStop ControllerHandle %lx\n", >> ControllerHandle)); >> + >> + Status = gBS->OpenProtocol ( >> + ControllerHandle, >> + &gEdkIIUsbEthProtocolGuid, >> + (VOID **)&UsbEthProtocol, >> + This->DriverBindingHandle, >> + ControllerHandle, >> + EFI_OPEN_PROTOCOL_GET_PROTOCOL >> + ); >> + if (EFI_ERROR (Status)) { >> + Status = CheckandStopRndisDevice (This, ControllerHandle); >> + return Status; >> + } >> + >> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (UsbEthProtocol); >> + >> + Status = gBS->CloseProtocol ( >> + UsbRndisDevice->UsbCdcDataHandle, >> + &gEfiUsbIoProtocolGuid, >> + This->DriverBindingHandle, >> + UsbRndisDevice->UsbCdcDataHandle >> + ); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "%a:CloseProtocol status = %r\n", __func__, >> Status)); >> + } >> + >> + Status = gBS->UninstallProtocolInterface ( >> + ControllerHandle, >> + &gEdkIIUsbEthProtocolGuid, >> + UsbEthProtocol >> + ); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + Status = gBS->CloseProtocol ( >> + ControllerHandle, >> + &gEfiUsbIoProtocolGuid, >> + This->DriverBindingHandle, >> + ControllerHandle >> + ); >> + >> + FreePool (UsbRndisDevice->Config); >> + FreePool (UsbRndisDevice); >> + >> + DEBUG ((DEBUG_INFO, "UsbRndisDriverStop %r\n", Status)); >> + return Status; >> +} >> + >> +/** >> + Entrypoint of RNDIS Driver. >> + >> + This function is the entrypoint of RNDIS Driver. It installs Driver Binding >> + Protocols together with Component Name Protocols. >> + >> + @param[in] ImageHandle The firmware allocated handle for the EFI >> image. >> + @param[in] SystemTable A pointer to the EFI System Table. >> + >> + @retval EFI_SUCCESS The entry point is executed successfully. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +UsbRndisEntry ( >> + IN EFI_HANDLE ImageHandle, >> + IN EFI_SYSTEM_TABLE *SystemTable >> + ) >> +{ >> + gUsbRndisDriverBinding.DriverBindingHandle = ImageHandle; >> + gUsbRndisDriverBinding.ImageHandle = ImageHandle; >> + >> + return gBS->InstallMultipleProtocolInterfaces ( >> + &gUsbRndisDriverBinding.DriverBindingHandle, >> + &gEfiDriverBindingProtocolGuid, >> + &gUsbRndisDriverBinding, >> + &gEfiComponentName2ProtocolGuid, >> + &gUsbRndisComponentName2, >> + NULL >> + ); >> +} >> diff --git a/MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis/UsbRndis.h >> b/MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis/UsbRndis.h >> new file mode 100644 >> index 0000000000..9c38642ffe >> --- /dev/null >> +++ b/MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis/UsbRndis.h >> @@ -0,0 +1,586 @@ >> +/** @file >> + Header file for for USB Rndis driver >> + >> + Copyright (c) 2023, American Megatrends International LLC. All rights >> reserved.
>> + SPDX-License-Identifier: BSD-2-Clause-Patent >> +**/ >> + >> +#ifndef _USB_RNDIS_H_ >> +#define _USB_RNDIS_H_ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +typedef struct _REMOTE_NDIS_MSG_HEADER >> REMOTE_NDIS_MSG_HEADER; >> + >> +typedef struct { >> + UINT32 Signature; >> + EDKII_USB_ETHERNET_PROTOCOL UsbEth; >> + EFI_HANDLE UsbCdcDataHandle; >> + EFI_HANDLE UsbRndisHandle; >> + EFI_USB_IO_PROTOCOL *UsbIo; >> + EFI_USB_IO_PROTOCOL *UsbIoCdcData; >> + EFI_USB_CONFIG_DESCRIPTOR *Config; >> + UINT8 NumOfInterface; >> + UINT8 BulkInEndpoint; >> + UINT8 BulkOutEndpoint; >> + UINT8 InterrupEndpoint; >> + EFI_MAC_ADDRESS MacAddress; >> + UINT32 RequestId; >> + UINT32 Medium; >> + UINT32 MaxPacketsPerTransfer; >> + UINT32 MaxTransferSize; >> + UINT32 PacketAlignmentFactor; >> + LIST_ENTRY ReceivePacketList; >> +} USB_RNDIS_DEVICE; >> + >> +#define USB_RNDIS_DRIVER_VERSION 1 >> +#define USB_TX_ETHERNET_BULK_TIMEOUT 3000 >> +#define USB_RX_ETHERNET_BULK_TIMEOUT 3 >> +#define USB_ETHERNET_TRANSFER_TIMEOUT 200 >> + >> +#define LAN_BULKIN_CMD_CONTROL 1 >> +#define MAXIMUM_STOPBULKIN_CNT 300 // Indicating maximum >> counts for waiting bulk in command >> +#define MINIMUM_STOPBULKIN_CNT 3 // Indicating minimum >> counts for waiting bulk in command >> +#define BULKIN_CMD_POLLING_CNT 300 // Indicating the waiting >> counts for send bulk in command when system pending >> +#define RNDIS_RESERVED_BYTE_LENGTH 8 >> + >> +#define USB_RNDIS_SIGNATURE SIGNATURE_32('r', 'n', 'd', 's') >> +#define USB_RNDIS_DEVICE_FROM_THIS(a) CR (a, USB_RNDIS_DEVICE, >> UsbEth, USB_RNDIS_SIGNATURE) >> + >> +extern EFI_COMPONENT_NAME2_PROTOCOL >> gUsbRndisComponentName2; >> + >> +struct BIT_MAP { >> + unsigned int Src; >> + unsigned int Dst; >> +}; >> + >> +EFI_STATUS >> +EFIAPI >> +UsbRndisDriverSupported ( >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> + IN EFI_HANDLE ControllerHandle, >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +UsbRndisDriverStart ( >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> + IN EFI_HANDLE ControllerHandle, >> + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +UsbRndisDriverStop ( >> + IN EFI_DRIVER_BINDING_PROTOCOL *This, >> + IN EFI_HANDLE ControllerHandle, >> + IN UINTN NumberOfChildren, >> + IN EFI_HANDLE *ChildHandleBuffer >> + ); >> + >> +EFI_STATUS >> +LoadAllDescriptor ( >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> + OUT EFI_USB_CONFIG_DESCRIPTOR **ConfigDesc >> + ); >> + >> +BOOLEAN >> +NextDescriptor ( >> + IN EFI_USB_CONFIG_DESCRIPTOR *Desc, >> + IN OUT UINTN *Offset >> + ); >> + >> +EFI_STATUS >> +GetFunctionalDescriptor ( >> + IN EFI_USB_CONFIG_DESCRIPTOR *Config, >> + IN UINT8 FunDescriptorType, >> + OUT VOID *DataBuffer >> + ); >> + >> +VOID >> +GetEndpoint ( >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> + IN OUT USB_RNDIS_DEVICE *UsbRndisDevice >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +UsbRndisInterrupt ( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + IN BOOLEAN IsNewTransfer, >> + IN UINTN PollingInterval, >> + IN EFI_USB_DEVICE_REQUEST *Requst >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +InterruptCallback ( >> + IN VOID *Data, >> + IN UINTN DataLength, >> + IN VOID *Context, >> + IN UINT32 Status >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +GetUsbEthMacAddress ( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + OUT EFI_MAC_ADDRESS *MacAddress >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +UsbEthBulkSize ( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + OUT UINTN *BulkSize >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +RndisDummyReturn ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +RndisUndiStart ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +RndisUndiStop ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +RndisUndiGetInitInfo ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +RndisUndiGetConfigInfo ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +RndisUndiInitialize ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +RndisUndiTransmit ( >> + IN PXE_CDB *Cdb, >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + IN VOID *BulkOutData, >> + IN OUT UINTN *DataLength >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +RndisUndiReceive ( >> + IN PXE_CDB *Cdb, >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + IN OUT VOID *BulkInData, >> + IN OUT UINTN *DataLength >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +RndisUndiReset ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +RndisUndiShutdown ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +RndisUndiReceiveFilter ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +RndisUndiGetStatus ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +GetUsbHeaderFunDescriptor ( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +GetUsbUnionFunDescriptor ( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +GetUsbRndisFunDescriptor ( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +SetUsbRndisMcastFilter ( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + IN UINT16 Value, >> + IN VOID *McastAddr >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +SetUsbRndisPowerFilter ( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + IN UINT16 Value, >> + IN UINT16 Length, >> + IN VOID *PatternFilter >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +GetUsbRndisPowerFilter ( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + IN UINT16 Value, >> + IN BOOLEAN *PatternActive >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +SetUsbRndisPacketFilter ( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + IN UINT16 Value >> + ); >> + >> +EFI_STATUS >> +EFIAPI >> +GetRndisStatistic ( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + IN UINT16 Value, >> + IN VOID *Statistic >> + ); >> + >> +EFI_STATUS >> +RndisControlMsg ( >> + IN USB_RNDIS_DEVICE *UsbRndisDevice, >> + IN REMOTE_NDIS_MSG_HEADER *RndisMsg, >> + OUT REMOTE_NDIS_MSG_HEADER *RndisMsgResponse >> + ); >> + >> +EFI_STATUS >> +RndisTransmitDataMsg ( >> + IN USB_RNDIS_DEVICE *UsbRndisDevice, >> + IN REMOTE_NDIS_MSG_HEADER *RndisMsg, >> + UINTN *TransferLength >> + ); >> + >> +EFI_STATUS >> +RndisReceiveDataMsg ( >> + IN USB_RNDIS_DEVICE *UsbRndisDevice, >> + IN REMOTE_NDIS_MSG_HEADER *RndisMsg, >> + UINTN *TransferLength >> + ); >> + >> +VOID >> +PrintRndisMsg ( >> + IN REMOTE_NDIS_MSG_HEADER *RndisMsg >> + ); >> + >> +#define RNDIS_MAJOR_VERSION 0x00000001 >> +#define RNDIS_MINOR_VERSION 0x00000000 >> +#define RNDIS_MAX_TRANSFER_SIZE 0x4000 >> + >> +#define RNDIS_PACKET_MSG 0x00000001 >> +#define RNDIS_INITIALIZE_MSG 0x00000002 >> +#define RNDIS_INITIALIZE_CMPLT 0x80000002 >> +#define RNDIS_HLT_MSG 0x00000003 >> +#define RNDIS_QUERY_MSG 0x00000004 >> +#define RNDIS_QUERY_CMPLT 0x80000004 >> +#define RNDIS_SET_MSG 0x00000005 >> +#define RNDIS_SET_CMPLT 0x80000005 >> +#define RNDIS_RESET_MSG 0x00000006 >> +#define RNDIS_RESET_CMPLT 0x80000006 >> +#define RNDIS_INDICATE_STATUS_MSG 0x00000007 >> +#define RNDIS_KEEPALIVE_MSG 0x00000008 >> +#define RNDIS_KEEPALIVE_CMPLT 0x80000008 >> + >> +#define RNDIS_STATUS_SUCCESS 0x00000000 >> +#define RNDIS_STATUS_FAILURE 0xC0000001 >> +#define RNDIS_STATUS_INVALID_DATA 0xC0010015 >> +#define RNDIS_STATUS_NOT_SUPPORTED 0xC00000BB >> +#define RNDIS_STATUS_MEDIA_CONNECT 0x4001000B >> +#define RNDIS_STATUS_MEDIA_DISCONNECT 0x4001000C >> + >> +#define RNDIS_CONTROL_TIMEOUT 10000 // 10sec >> +#define RNDIS_KEEPALIVE_TIMEOUT 5000 // 5sec >> + >> +#define SEND_ENCAPSULATED_COMMAND 0x00000000 >> +#define GET_ENCAPSULATED_RESPONSE 0x00000001 >> + >> +// >> +// General Objects >> +// >> +// Taken from NTDDNDIS.H >> +#define OID_GEN_SUPPORTED_LIST 0x00010101 >> +#define OID_GEN_HARDWARE_STATUS 0x00010102 >> +#define OID_GEN_MEDIA_SUPPORTED 0x00010103 >> +#define OID_GEN_MEDIA_IN_USE 0x00010104 >> +#define OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 >> +#define OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 >> +#define OID_GEN_LINK_SPEED 0x00010107 >> +#define OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 >> +#define OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 >> +#define OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A >> +#define OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B >> +#define OID_GEN_VENDOR_ID 0x0001010C >> +#define OID_GEN_VENDOR_DESCRIPTION 0x0001010D >> +#define OID_GEN_CURRENT_PACKET_FILTER 0x0001010E >> +#define OID_GEN_CURRENT_LOOKAHEAD 0x0001010F >> +#define OID_GEN_DRIVER_VERSION 0x00010110 >> +#define OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 >> +#define OID_GEN_PROTOCOL_OPTIONS 0x00010112 >> +#define OID_GEN_MAC_OPTIONS 0x00010113 >> +#define OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 >> +#define OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 >> +#define OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 >> + >> +#define OID_GEN_XMIT_OK 0x00020101 >> +#define OID_GEN_RCV_OK 0x00020102 >> +#define OID_GEN_XMIT_ERROR 0x00020103 >> +#define OID_GEN_RCV_ERROR 0x00020104 >> +#define OID_GEN_RCV_NO_BUFFER 0x00020105 >> + >> +#define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 >> +#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 >> +#define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 >> +#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 >> +#define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 >> +#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 >> +#define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 >> +#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 >> +#define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 >> +#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A >> +#define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B >> +#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C >> +#define OID_GEN_RCV_CRC_ERROR 0x0002020D >> +#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E >> + >> +#define OID_802_3_CURRENT_ADDRESS 0x01010102 >> +// >> +// Ndis Packet Filter Bits (OID_GEN_CURRENT_PACKET_FILTER). >> +// >> +#define NDIS_PACKET_TYPE_DIRECTED 0x0001 >> +#define NDIS_PACKET_TYPE_MULTICAST 0x0002 >> +#define NDIS_PACKET_TYPE_ALL_MULTICAST 0x0004 >> +#define NDIS_PACKET_TYPE_BROADCAST 0x0008 >> +#define NDIS_PACKET_TYPE_SOURCE_ROUTING 0x0010 >> +#define NDIS_PACKET_TYPE_PROMISCUOUS 0x0020 >> +#define NDIS_PACKET_TYPE_SMT 0x0040 >> +#define NDIS_PACKET_TYPE_ALL_LOCAL 0x0080 >> +#define NDIS_PACKET_TYPE_MAC_FRAME 0x8000 >> +#define NDIS_PACKET_TYPE_FUNCTIONAL 0x4000 >> +#define NDIS_PACKET_TYPE_ALL_FUNCTIONAL 0x2000 >> +#define NDIS_PACKET_TYPE_GROUP 0x1000 >> + >> +#pragma pack(1) >> + >> +typedef struct _REMOTE_NDIS_MSG_HEADER { >> + UINT32 MessageType; >> + UINT32 MessageLength; >> +} REMOTE_NDIS_MSG_HEADER; >> + >> +typedef struct { >> + UINT32 MessageType; >> + UINT32 MessageLength; >> + UINT32 RequestID; >> + UINT32 MajorVersion; >> + UINT32 MinorVersion; >> + UINT32 MaxTransferSize; >> +} REMOTE_NDIS_INITIALIZE_MSG; >> + >> +typedef struct { >> + UINT32 MessageType; >> + UINT32 MessageLength; >> + UINT32 RequestID; >> +} REMOTE_NDIS_HALT_MSG; >> + >> +typedef struct { >> + UINT32 MessageType; >> + UINT32 MessageLength; >> + UINT32 RequestID; >> + UINT32 Oid; >> + UINT32 InformationBufferLength; >> + UINT32 InformationBufferOffset; >> + UINT32 Reserved; >> +} REMOTE_NDIS_QUERY_MSG; >> + >> +typedef struct { >> + REMOTE_NDIS_QUERY_MSG QueryMsg; >> + UINT8 Addr[6]; >> +} REMOTE_NDIS_QUERY_MAC_MSG; >> + >> +typedef struct { >> + REMOTE_NDIS_QUERY_MSG QueryMsg; >> + UINT32 MaxTotalSize; >> +} REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_MSG; >> + >> +typedef struct { >> + UINT32 MessageType; >> + UINT32 MessageLength; >> + UINT32 RequestID; >> + UINT32 Oid; >> + UINT32 InformationBufferLength; >> + UINT32 InformationBufferOffset; >> + UINT32 Reserved; >> +} REMOTE_NDIS_SET_MSG; >> + >> +typedef struct { >> + UINT32 MessageType; >> + UINT32 MessageLength; >> + UINT32 Reserved; >> +} REMOTE_NDIS_RESET_MSG; >> + >> +typedef struct { >> + UINT32 MessageType; >> + UINT32 MessageLength; >> + UINT32 Status; >> + UINT32 StatusBufferLength; >> + UINT32 StatusBufferOffset; >> +} REMOTE_NDIS_INDICATE_STATUS_MSG; >> + >> +typedef struct { >> + UINT32 DiagStatus; >> + UINT32 ErrorOffset; >> +} RNDIS_DIAGNOSTIC_INFO; >> + >> +typedef struct { >> + UINT32 MessageType; >> + UINT32 MessageLength; >> + UINT32 RequestID; >> +} REMOTE_NDIS_KEEPALIVE_MSG; >> + >> +typedef struct { >> + UINT32 MessageType; >> + UINT32 MessageLength; >> + UINT32 RequestID; >> + UINT32 Status; >> + UINT32 MajorVersion; >> + UINT32 MinorVersion; >> + UINT32 DeviceFlags; >> + UINT32 Medium; >> + UINT32 MaxPacketsPerTransfer; >> + UINT32 MaxTransferSize; >> + UINT32 PacketAlignmentFactor; >> + UINT64 Reserved; >> +} REMOTE_NDIS_INITIALIZE_CMPLT; >> + >> +typedef struct { >> + UINT32 MessageType; >> + UINT32 MessageLength; >> + UINT32 RequestID; >> + UINT32 Status; >> + UINT32 InformationBufferLength; >> + UINT32 InformationBufferOffset; >> +} REMOTE_NDIS_QUERY_CMPLT; >> + >> +typedef struct { >> + REMOTE_NDIS_QUERY_CMPLT QueryCmplt; >> + UINT8 Addr[6]; >> +} REMOTE_NDIS_QUERY_MAC_CMPLT; >> + >> +typedef struct { >> + REMOTE_NDIS_QUERY_CMPLT QueryCmplt; >> + UINT32 MaxTotalSize; >> +} REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_CMPLT; >> + >> +typedef struct { >> + UINT32 MessageType; >> + UINT32 MessageLength; >> + UINT32 RequestID; >> + UINT32 Status; >> +} REMOTE_NDIS_SET_CMPLT; >> + >> +typedef struct { >> + UINT32 MessageType; >> + UINT32 MessageLength; >> + UINT32 Status; >> + UINT32 AddressingReset; >> +} REMOTE_NDIS_RESET_CMPLT; >> + >> +typedef struct { >> + UINT32 MessageType; >> + UINT32 MessageLength; >> + UINT32 RequestID; >> + UINT32 Status; >> +} REMOTE_NDIS_KEEPALIVE_CMPLT; >> + >> +typedef struct { >> + UINT32 MessageType; >> + UINT32 MessageLength; >> + UINT32 DataOffset; >> + UINT32 DataLength; >> + UINT32 OutOfBandDataOffset; >> + UINT32 OutOfBandDataLength; >> + UINT32 NumOutOfBandDataElements; >> + UINT32 PerPacketInfoOffset; >> + UINT32 PerPacketInfoLength; >> + UINT32 Reserved1; >> + UINT32 Reserved2; >> +} REMOTE_NDIS_PACKET_MSG; >> + >> +typedef struct { >> + UINT32 Size; >> + UINT32 Type; >> + UINT32 ClassInformationOffset; >> +} OUT_OF_BAND_DATA_RECORD; >> + >> +typedef struct { >> + UINT32 Size; >> + UINT32 Type; >> + UINT32 ClassInformationOffset; >> +} PER_PACKET_INFO_DATA_RECORD; >> + >> +typedef struct { >> + LIST_ENTRY PacketList; >> + UINT8 *OrgBuffer; >> + UINTN RemainingLength; >> + UINT8 *PacketStartBuffer; // Variable size data to follow >> +} PACKET_LIST; >> + >> +#pragma pack() >> + >> +#endif >> diff --git a/MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis/UsbRndis.inf >> b/MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis/UsbRndis.inf >> new file mode 100644 >> index 0000000000..1027828527 >> --- /dev/null >> +++ b/MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis/UsbRndis.inf >> @@ -0,0 +1,42 @@ >> +## @file >> +# This is Usb Rndis driver for DXE phase. >> +# >> +# Copyright (c) 2023, American Megatrends International LLC. All rights >> reserved.
>> +# SPDX-License-Identifier: BSD-2-Clause-Patent >> +## >> + >> +[Defines] >> + INF_VERSION = 0x00010005 >> + BASE_NAME = UsbRndis >> + FILE_GUID = 11E32C34-60B5-4991-8DEA-63D3E8C876DE >> + MODULE_TYPE = DXE_DRIVER >> + VERSION_STRING = 1.0 >> + ENTRY_POINT = UsbRndisEntry >> + >> +[Sources] >> + UsbRndis.c >> + UsbRndis.h >> + UsbRndisFunction.c >> + ComponentName.c >> + >> +[Packages] >> + MdePkg/MdePkg.dec >> + MdeModulePkg/MdeModulePkg.dec >> + >> +[LibraryClasses] >> + UefiDriverEntryPoint >> + UefiBootServicesTableLib >> + UefiLib >> + DebugLib >> + UefiUsbLib >> + MemoryAllocationLib >> + BaseMemoryLib >> + >> +[Protocols] >> + gEfiUsbIoProtocolGuid >> + gEfiDevicePathProtocolGuid >> + gEfiDriverBindingProtocolGuid >> + gEdkIIUsbEthProtocolGuid >> + >> +[Depex] >> + TRUE >> diff --git >> a/MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis/UsbRndisFunction.c >> b/MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis/UsbRndisFunction.c >> new file mode 100644 >> index 0000000000..9aba3f1129 >> --- /dev/null >> +++ b/MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis/UsbRndisFunction.c >> @@ -0,0 +1,1718 @@ >> +/** @file >> + This file contains code for USB Ethernet descriptor >> + and specific requests implement. >> + >> + Copyright (c) 2023, American Megatrends International LLC. All rights >> reserved.
>> + SPDX-License-Identifier: BSD-2-Clause-Patent >> +**/ >> + >> +#include "UsbRndis.h" >> + >> +UINT16 gStopBulkInCnt = 0; >> +UINT16 gBlockBulkInCnt = 0; >> + >> +/** >> + Load All of device descriptor. >> + >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL >> instance. >> + @param[out] ConfigDesc A pointer to the configuration descriptor. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_OUT_OF_RESOURCES The request could not be completed >> because the >> + buffer specified by DescriptorLength and Descriptor >> + is not large enough to hold the result of the request. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> The transfer >> + status is returned in Status. >> +**/ >> +EFI_STATUS >> +LoadAllDescriptor ( >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> + OUT EFI_USB_CONFIG_DESCRIPTOR **ConfigDesc >> + ) >> +{ >> + EFI_STATUS Status; >> + UINT32 TransStatus; >> + EFI_USB_CONFIG_DESCRIPTOR Tmp; >> + >> + Status = UsbIo->UsbGetConfigDescriptor (UsbIo, &Tmp); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "%a:UsbGetConfigDescriptor status = %r\n", >> __func__, Status)); >> + return Status; >> + } >> + >> + Status = gBS->AllocatePool ( >> + EfiBootServicesData, >> + Tmp.TotalLength, >> + (VOID **)ConfigDesc >> + ); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "%a: AllocatePool status = %r\n", __func__, >> Status)); >> + return Status; >> + } >> + >> + Status = UsbGetDescriptor ( >> + UsbIo, >> + USB_DESC_TYPE_CONFIG << 8 | (Tmp.ConfigurationValue - 1), >> // zero based >> + 0, >> + Tmp.TotalLength, >> + *ConfigDesc, >> + &TransStatus >> + ); >> + return Status; >> +} >> + >> +/** >> + Returns pointer to the next descriptor for the pack of USB descriptors >> + located in continues memory segment >> + >> + @param[in] Desc A pointer to the CONFIG_DESCRIPTOR instance. >> + @param[in, out] Offset A pointer to the sum of descriptor length. >> + >> + @retval TRUE The request executed successfully. >> + @retval FALSE No next descriptor. >> + >> +**/ >> +BOOLEAN >> +NextDescriptor ( >> + IN EFI_USB_CONFIG_DESCRIPTOR *Desc, >> + IN OUT UINTN *Offset >> + ) >> +{ >> + if ((Desc == NULL) || (*Offset >= Desc->TotalLength)) { >> + return FALSE; >> + } >> + >> + if (((EFI_USB_CONFIG_DESCRIPTOR *)((char *)Desc+*Offset))->Length == 0) >> { >> + return FALSE; >> + } >> + >> + *Offset += ((EFI_USB_CONFIG_DESCRIPTOR *)((char *)Desc+*Offset))- >>> Length; >> + if ( *Offset >= Desc->TotalLength ) { >> + return FALSE; >> + } >> + >> + return TRUE; >> +} >> + >> +/** >> + Read Function descriptor >> + >> + @param[in] Config A pointer to all of configuration. >> + @param[in] FunDescriptorType USB CDC class descriptor SubType. >> + @param[out] DataBuffer A pointer to the Data of corresponding to >> device capability. >> + >> + @retval EFI_SUCCESS The device capability descriptor was retrieved >> + successfully. >> + @retval EFI_UNSUPPORTED No supported. >> + @retval EFI_NOT_FOUND The device capability descriptor was not >> found. >> + >> +**/ >> +EFI_STATUS >> +GetFunctionalDescriptor ( >> + IN EFI_USB_CONFIG_DESCRIPTOR *Config, >> + IN UINT8 FunDescriptorType, >> + OUT VOID *DataBuffer >> + ) >> +{ >> + EFI_STATUS Status; >> + UINTN Offset; >> + EFI_USB_INTERFACE_DESCRIPTOR *Interface; >> + >> + Status = EFI_NOT_FOUND; >> + >> + for (Offset = 0; NextDescriptor (Config, &Offset);) { >> + Interface = (EFI_USB_INTERFACE_DESCRIPTOR *)((UINT8 *)Config + >> Offset); >> + if (Interface->DescriptorType == CS_INTERFACE) { >> + if (((USB_HEADER_FUN_DESCRIPTOR *)Interface)->DescriptorSubtype >> == FunDescriptorType) { >> + switch (FunDescriptorType) { >> + case HEADER_FUN_DESCRIPTOR: >> + CopyMem ( >> + DataBuffer, >> + (USB_HEADER_FUN_DESCRIPTOR *)Interface, >> + sizeof (USB_HEADER_FUN_DESCRIPTOR) >> + ); >> + return EFI_SUCCESS; >> + case UNION_FUN_DESCRIPTOR: >> + CopyMem ( >> + DataBuffer, >> + (USB_UNION_FUN_DESCRIPTOR *)Interface, >> + ((USB_UNION_FUN_DESCRIPTOR *)Interface)->FunctionLength >> + ); >> + return EFI_SUCCESS; >> + case ETHERNET_FUN_DESCRIPTOR: >> + CopyMem ( >> + DataBuffer, >> + (USB_ETHERNET_FUN_DESCRIPTOR *)Interface, >> + sizeof (USB_ETHERNET_FUN_DESCRIPTOR) >> + ); >> + return EFI_SUCCESS; >> + default: >> + Status = EFI_UNSUPPORTED; >> + break; >> + } >> + } >> + } >> + } >> + >> + return Status; >> +} >> + >> +/** >> + Get USB Ethernet IO endpoint and USB CDC data IO endpoint. >> + >> + @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL >> instance. >> + @param[in, out] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE >> instance. >> + >> +**/ >> +VOID >> +GetEndpoint ( >> + IN EFI_USB_IO_PROTOCOL *UsbIo, >> + IN OUT USB_RNDIS_DEVICE *UsbRndisDevice >> + ) >> +{ >> + EFI_STATUS Status; >> + UINT8 Index; >> + UINT32 Result; >> + EFI_USB_INTERFACE_DESCRIPTOR Interface; >> + EFI_USB_ENDPOINT_DESCRIPTOR Endpoint; >> + >> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "%a:UsbGetInterfaceDescriptor status = %r\n", >> __func__, Status)); >> + return; >> + } >> + >> + if (Interface.NumEndpoints == 0 ) { >> + Status = UsbSetInterface (UsbIo, 1, 0, &Result); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "%a:UsbSetInterface status = %r\n", __func__, >> Status)); >> + return; >> + } >> + >> + Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "%a:UsbGetInterfaceDescriptor status = %r\n", >> __func__, Status)); >> + return; >> + } >> + } >> + >> + for (Index = 0; Index < Interface.NumEndpoints; Index++) { >> + Status = UsbIo->UsbGetEndpointDescriptor (UsbIo, Index, &Endpoint); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "%a:UsbGetEndpointDescriptor status = %r\n", >> __func__, Status)); >> + return; >> + } >> + >> + switch ((Endpoint.Attributes & (BIT0 | BIT1))) { >> + case USB_ENDPOINT_BULK: >> + if (Endpoint.EndpointAddress & BIT7) { >> + UsbRndisDevice->BulkInEndpoint = Endpoint.EndpointAddress; >> + } else { >> + UsbRndisDevice->BulkOutEndpoint = Endpoint.EndpointAddress; >> + } >> + >> + break; >> + case USB_ENDPOINT_INTERRUPT: >> + UsbRndisDevice->InterrupEndpoint = Endpoint.EndpointAddress; >> + break; >> + } >> + } >> +} >> + >> +/** >> + Async USB transfer callback routine. >> + >> + @param[in] Data Data received or sent via the USB Asynchronous >> Transfer, if the >> + transfer completed successfully. >> + @param[in] DataLength The length of Data received or sent via the >> Asynchronous >> + Transfer, if transfer successfully completes. >> + @param[in] Context Data passed from UsbAsyncInterruptTransfer() >> request. >> + @param[in] Status Indicates the result of the asynchronous transfer. >> + >> + @retval EFI_SUCCESS The asynchronous USB transfer request has >> been successfully executed. >> + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request >> failed. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +InterruptCallback ( >> + IN VOID *Data, >> + IN UINTN DataLength, >> + IN VOID *Context, >> + IN UINT32 Status >> + ) >> +{ >> + if ((Data == NULL) || (Context == NULL)) { >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + if (((EFI_USB_DEVICE_REQUEST *)Data)->Request == 0) { >> + CopyMem ( >> + (EFI_USB_DEVICE_REQUEST *)Context, >> + (EFI_USB_DEVICE_REQUEST *)Data, >> + sizeof (EFI_USB_DEVICE_REQUEST) >> + ); >> + } >> + >> + return EFI_SUCCESS; >> +} >> + >> +/** >> + This function is used to manage a USB device with an interrupt transfer >> pipe. >> + >> + @param[in] This A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> + @param[in] IsNewTransfer If TRUE, a new transfer will be submitted to >> USB controller. If >> + FALSE, the interrupt transfer is deleted from the device's >> interrupt >> + transfer queue. >> + @param[in] PollingInterval Indicates the periodic rate, in milliseconds, >> that the transfer is to be >> + executed.This parameter is required when IsNewTransfer >> is TRUE. The >> + value must be between 1 to 255, otherwise >> EFI_INVALID_PARAMETER is returned. >> + The units are in milliseconds. >> + @param[in] Request A pointer to the EFI_USB_DEVICE_REQUEST >> data. >> + >> + @retval EFI_SUCCESS The asynchronous USB transfer request >> transfer has been successfully executed. >> + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request >> failed. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +UsbRndisInterrupt ( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + IN BOOLEAN IsNewTransfer, >> + IN UINTN PollingInterval, >> + IN EFI_USB_DEVICE_REQUEST *Requst >> + ) >> +{ >> + EFI_STATUS Status; >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> + UINTN DataLength; >> + >> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> + DataLength = 0; >> + >> + if (IsNewTransfer == TRUE) { >> + DataLength = sizeof (EFI_USB_DEVICE_REQUEST) + sizeof >> (USB_CONNECT_SPEED_CHANGE); >> + Status = UsbRndisDevice->UsbIo->UsbAsyncInterruptTransfer ( >> + UsbRndisDevice->UsbIo, >> + UsbRndisDevice->InterrupEndpoint, >> + IsNewTransfer, >> + PollingInterval, >> + DataLength, >> + InterruptCallback, >> + Requst >> + ); >> + >> + if (Status == EFI_INVALID_PARAMETER) { >> + // Because of Stacked AsyncInterrupt request are not supported >> + Status = UsbRndisDevice->UsbIo->UsbAsyncInterruptTransfer ( >> + UsbRndisDevice->UsbIo, >> + UsbRndisDevice->InterrupEndpoint, >> + 0, >> + 0, >> + 0, >> + NULL, >> + NULL >> + ); >> + } >> + } else { >> + Status = UsbRndisDevice->UsbIo->UsbAsyncInterruptTransfer ( >> + UsbRndisDevice->UsbIo, >> + UsbRndisDevice->InterrupEndpoint, >> + IsNewTransfer, >> + 0, >> + 0, >> + NULL, >> + NULL >> + ); >> + } >> + >> + return Status; >> +} >> + >> +/** >> + This function is used to read USB interrupt transfer before the response >> RNDIS message. >> + >> + @param[in] This A pointer to the USB_RNDIS_DEVICE instance. >> + >> + @retval EFI_SUCCESS The USB interrupt transfer has been >> successfully executed. >> + @retval EFI_DEVICE_ERROR The USB interrupt transfer failed. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +ReadRndisResponseInterrupt ( >> + IN USB_RNDIS_DEVICE *UsbRndisDevice >> + ) >> +{ >> + EFI_STATUS Status; >> + UINT32 Data[2]; >> + UINT32 UsbStatus; >> + UINTN DataLength; >> + >> + DataLength = 8; >> + >> + ZeroMem (Data, sizeof (Data)); >> + >> + Status = UsbRndisDevice->UsbIo->UsbSyncInterruptTransfer ( >> + UsbRndisDevice->UsbIo, >> + UsbRndisDevice->InterrupEndpoint, >> + &Data, >> + &DataLength, >> + 0x20, >> + &UsbStatus >> + ); >> + >> + return Status; >> +} >> + >> +/** >> + Retrieves the USB Ethernet Mac Address. >> + >> + @param[in] This A pointer to the EDKII_USB_ETHERNET_PROTOCOL >> instance. >> + @param[out] MacAddress A pointer to the caller allocated USB Ethernet >> Mac Address. >> + >> + @retval EFI_SUCCESS The USB Header Functional descriptor was >> retrieved successfully. >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor was >> not found. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +GetUsbEthMacAddress ( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + OUT EFI_MAC_ADDRESS *MacAddress >> + ) >> +{ >> + EFI_STATUS Status; >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthDescriptor; >> + CHAR16 *Data; >> + CHAR16 *DataPtr; >> + CHAR16 TmpStr[1]; >> + UINT8 Index; >> + UINT8 Hi; >> + UINT8 Low; >> + >> + REMOTE_NDIS_QUERY_MAC_MSG RndisQueryMsg; >> + REMOTE_NDIS_QUERY_MAC_CMPLT RndisQueryMsgCmplt; >> + >> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> + >> + ZeroMem (&RndisQueryMsg, sizeof (REMOTE_NDIS_QUERY_MAC_MSG)); >> + ZeroMem (&RndisQueryMsgCmplt, sizeof >> (REMOTE_NDIS_QUERY_MAC_CMPLT)); >> + >> + RndisQueryMsg.QueryMsg.MessageType = RNDIS_QUERY_MSG; >> + RndisQueryMsg.QueryMsg.MessageLength = sizeof >> (REMOTE_NDIS_QUERY_MAC_MSG); >> + RndisQueryMsg.QueryMsg.RequestID = UsbRndisDevice->RequestId; >> + RndisQueryMsg.QueryMsg.Oid = OID_802_3_CURRENT_ADDRESS; >> + >> + RndisQueryMsgCmplt.QueryCmplt.MessageType = RNDIS_QUERY_CMPLT; >> + RndisQueryMsgCmplt.QueryCmplt.MessageLength = sizeof >> (REMOTE_NDIS_QUERY_MAC_CMPLT); >> + >> + Status = RndisControlMsg ( >> + UsbRndisDevice, >> + (REMOTE_NDIS_MSG_HEADER *)&RndisQueryMsg, >> + (REMOTE_NDIS_MSG_HEADER *)&RndisQueryMsgCmplt >> + ); >> + if (!EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_INFO, "Success to get Mac address from RNDIS >> message.\n")); >> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> + MacAddress->Addr[Index] = RndisQueryMsgCmplt.Addr[Index]; >> + } >> + >> + UsbRndisDevice->RequestId++; >> + return Status; >> + } >> + >> + // If it is not support the OID_802_3_CURRENT_ADDRESS. >> + // To check USB Ethernet functional Descriptor >> + Status = This->UsbEthFunDescriptor (This, &UsbEthDescriptor); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "%a:UsbEthFunDescriptor status = %r\n", >> __func__, Status)); >> + return Status; >> + } >> + >> + Status = UsbRndisDevice->UsbIo->UsbGetStringDescriptor ( >> + UsbRndisDevice->UsbIo, >> + 0x409, // English-US Language ID >> + UsbEthDescriptor.MacAddress, >> + &Data >> + ); >> + if (EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_ERROR, "%a:UsbGetStringDescriptor status = %r\n", >> __func__, Status)); >> + return Status; >> + } >> + >> + DataPtr = Data; >> + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { >> + CopyMem (TmpStr, DataPtr, sizeof (CHAR16)); >> + DataPtr++; >> + Hi = (UINT8)StrHexToUintn (TmpStr); >> + CopyMem (TmpStr, DataPtr, sizeof (CHAR16)); >> + DataPtr++; >> + Low = (UINT8)StrHexToUintn (TmpStr); >> + MacAddress->Addr[Index] = (Hi << 4) | Low; >> + } >> + >> + return Status; >> +} >> + >> +/** >> + Retrieves the USB Ethernet Bulk transfer data size. >> + >> + @param[in] This A pointer to the EDKII_USB_ETHERNET_PROTOCOL >> instance. >> + @param[out] BulkSize A pointer to the Bulk transfer data size. >> + >> + @retval EFI_SUCCESS The bulk transfer data size was retrieved >> successfully. >> + @retval other Failed to retrieve the bulk transfer data size. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +UsbEthBulkSize ( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + OUT UINTN *BulkSize >> + ) >> +{ >> + EFI_STATUS Status; >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> + >> + REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_MSG RndisQueryMsg; >> + REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_CMPLT RndisQueryMsgCmplt; >> + >> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> + >> + ZeroMem (&RndisQueryMsg, sizeof >> (REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_MSG)); >> + ZeroMem (&RndisQueryMsgCmplt, sizeof >> (REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_CMPLT)); >> + >> + RndisQueryMsg.QueryMsg.MessageType = RNDIS_QUERY_MSG; >> + RndisQueryMsg.QueryMsg.MessageLength = sizeof >> (REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_MSG); >> + RndisQueryMsg.QueryMsg.RequestID = UsbRndisDevice->RequestId; >> + RndisQueryMsg.QueryMsg.Oid = OID_GEN_MAXIMUM_TOTAL_SIZE; >> + >> + RndisQueryMsgCmplt.QueryCmplt.MessageType = RNDIS_QUERY_CMPLT; >> + RndisQueryMsgCmplt.QueryCmplt.MessageLength = sizeof >> (REMOTE_NDIS_QUERY_MAX_TOTAL_SIZE_CMPLT); >> + >> + Status = RndisControlMsg ( >> + UsbRndisDevice, >> + (REMOTE_NDIS_MSG_HEADER *)&RndisQueryMsg, >> + (REMOTE_NDIS_MSG_HEADER *)&RndisQueryMsgCmplt >> + ); >> + if (!EFI_ERROR (Status)) { >> + DEBUG ((DEBUG_INFO, "Success to get Max Total size : %X \n", >> RndisQueryMsgCmplt.MaxTotalSize)); >> + *BulkSize = RndisQueryMsgCmplt.MaxTotalSize; >> + UsbRndisDevice->RequestId++; >> + return Status; >> + } >> + >> + Status = This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + *BulkSize = (UINTN)UsbEthFunDescriptor.MaxSegmentSize; >> + return Status; >> +} >> + >> +/** >> + Retrieves the USB Header functional Descriptor. >> + >> + @param[in] This A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> + @param[out] UsbHeaderFunDescriptor A pointer to the caller allocated >> USB Header Functional Descriptor. >> + >> + @retval EFI_SUCCESS The USB Header Functional descriptor was >> retrieved successfully. >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor was >> not found. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +GetUsbHeaderFunDescriptor ( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor >> + ) >> +{ >> + EFI_STATUS Status; >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> + >> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> + >> + if (UsbHeaderFunDescriptor == NULL) { >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + Status = GetFunctionalDescriptor ( >> + UsbRndisDevice->Config, >> + HEADER_FUN_DESCRIPTOR, >> + UsbHeaderFunDescriptor >> + ); >> + return Status; >> +} >> + >> +/** >> + Retrieves the USB Union functional Descriptor. >> + >> + @param[in] This A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> + @param[out] UsbUnionFunDescriptor A pointer to the caller allocated >> USB Union Functional Descriptor. >> + >> + @retval EFI_SUCCESS The USB Union Functional descriptor was >> retrieved successfully. >> + @retval EFI_INVALID_PARAMETER UsbUnionFunDescriptor is NULL. >> + @retval EFI_NOT_FOUND The USB Union Functional descriptor was >> not found. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +GetUsbUnionFunDescriptor ( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor >> + ) >> +{ >> + EFI_STATUS Status; >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> + >> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> + >> + if (UsbUnionFunDescriptor == NULL) { >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + Status = GetFunctionalDescriptor ( >> + UsbRndisDevice->Config, >> + UNION_FUN_DESCRIPTOR, >> + UsbUnionFunDescriptor >> + ); >> + return Status; >> +} >> + >> +/** >> + Retrieves the USB Ethernet functional Descriptor. >> + >> + This function get the Mac Address, Ethernet statistics, maximum segment >> size, >> + number of multicast filters, and number of pattern filters from Ethernet >> + functional Descriptor. >> + >> + @param[in] This A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> + @param[out] UsbEthFunDescriptor A pointer to the caller allocated USB >> Ethernet Functional Descriptor. >> + >> + @retval EFI_SUCCESS The USB Ethernet Functional descriptor was >> retrieved successfully. >> + @retval EFI_INVALID_PARAMETER UsbEthFunDescriptor is NULL. >> + @retval EFI_NOT_FOUND The USB Ethernet Functional descriptor >> was not found. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +GetUsbRndisFunDescriptor ( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor >> + ) >> +{ >> + EFI_STATUS Status; >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> + >> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> + >> + if (UsbEthFunDescriptor == NULL) { >> + return EFI_INVALID_PARAMETER; >> + } >> + >> + Status = GetFunctionalDescriptor ( >> + UsbRndisDevice->Config, >> + ETHERNET_FUN_DESCRIPTOR, >> + UsbEthFunDescriptor >> + ); >> + return Status; >> +} >> + >> +/** >> + This request sets the Ethernet device multicast filters as specified in the >> + sequential list of 48 bit Ethernet multicast addresses. >> + >> + @param[in] This A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> + @param[in] Value Number of filters. >> + @param[in] McastAddr A pointer to the value of the multicast >> addresses. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +SetUsbRndisMcastFilter ( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + IN UINT16 Value, >> + IN VOID *McastAddr >> + ) >> +{ >> + EFI_STATUS Status; >> + EFI_USB_DEVICE_REQUEST Request; >> + UINT32 TransStatus; >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> + >> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> + >> + Status = This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor); >> + if (EFI_ERROR (Status)) { >> + return Status; >> + } >> + >> + if ((UsbEthFunDescriptor.NumberMcFilters << 1) == 0) { >> + return EFI_UNSUPPORTED; >> + } >> + >> + Request.RequestType = USB_ETHERNET_SET_REQ_TYPE; >> + Request.Request = SET_ETH_MULTICAST_FILTERS_REQ; >> + Request.Value = Value; >> + Request.Index = UsbRndisDevice->NumOfInterface; >> + Request.Length = Value * 6; >> + >> + return UsbRndisDevice->UsbIo->UsbControlTransfer ( >> + UsbRndisDevice->UsbIo, >> + &Request, >> + EfiUsbDataOut, >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> + McastAddr, >> + Request.Length, >> + &TransStatus >> + ); >> +} >> + >> +/** >> + This request sets up the specified Ethernet power management pattern >> filter as >> + described in the data structure. >> + >> + @param[in] This A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> + @param[in] Value Number of filters. >> + @param[in] Length Size of the power management pattern filter >> data. >> + @param[in] PatternFilter A pointer to the power management >> pattern filter structure. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +SetUsbRndisPowerFilter ( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + IN UINT16 Value, >> + IN UINT16 Length, >> + IN VOID *PatternFilter >> + ) >> +{ >> + EFI_USB_DEVICE_REQUEST Request; >> + UINT32 TransStatus; >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> + >> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> + >> + Request.RequestType = USB_ETHERNET_SET_REQ_TYPE; >> + Request.Request = >> SET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ; >> + Request.Value = Value; >> + Request.Index = UsbRndisDevice->NumOfInterface; >> + Request.Length = Length; >> + >> + return UsbRndisDevice->UsbIo->UsbControlTransfer ( >> + UsbRndisDevice->UsbIo, >> + &Request, >> + EfiUsbDataOut, >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> + PatternFilter, >> + Length, >> + &TransStatus >> + ); >> +} >> + >> +/** >> + This request retrieves the status of the specified Ethernet power >> management >> + pattern filter from the device. >> + >> + @param[in] This A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> + @param[in] Value The filter number. >> + @param[out] PatternActive A pointer to the pattern active boolean. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +GetUsbRndisPowerFilter ( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + IN UINT16 Value, >> + OUT BOOLEAN *PatternActive >> + ) >> +{ >> + EFI_USB_DEVICE_REQUEST Request; >> + UINT32 TransStatus; >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> + >> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> + >> + Request.RequestType = USB_ETHERNET_GET_REQ_TYPE; >> + Request.Request = >> GET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ; >> + Request.Value = Value; >> + Request.Index = UsbRndisDevice->NumOfInterface; >> + Request.Length = USB_ETH_POWER_FILTER_LENGTH; >> + >> + return UsbRndisDevice->UsbIo->UsbControlTransfer ( >> + UsbRndisDevice->UsbIo, >> + &Request, >> + EfiUsbDataIn, >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> + PatternActive, >> + USB_ETH_POWER_FILTER_LENGTH, >> + &TransStatus >> + ); >> +} >> + >> +/** >> + >> + Converts PXE filter settings to RNDIS values >> + >> + @param[in] Value PXE filter data. >> + @param[out] CdcFilter A pointer to the Ethernet Packet Filter Bitmap >> value converted by PXE_OPFLAGS. >> + >> +**/ >> +VOID >> +ConvertFilter ( >> + IN UINT16 Value, >> + OUT UINT16 *CdcFilter >> + ) >> +{ >> + UINT32 Index; >> + UINT32 Count; >> + static struct BIT_MAP Table[] = { >> + { PXE_OPFLAGS_RECEIVE_FILTER_UNICAST, >> NDIS_PACKET_TYPE_DIRECTED }, >> + { PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST, >> NDIS_PACKET_TYPE_BROADCAST }, >> + { PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST, >> NDIS_PACKET_TYPE_MULTICAST }, >> + { PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS, >> NDIS_PACKET_TYPE_PROMISCUOUS }, >> + { PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST, >> NDIS_PACKET_TYPE_ALL_MULTICAST }, >> + }; >> + >> + Count = sizeof (Table)/sizeof (Table[0]); >> + >> + for (Index = 0; (Table[Index].Src != 0) && (Index < Count); Index++) { >> + if (Table[Index].Src & Value) { >> + *CdcFilter |= Table[Index].Dst; >> + } >> + } >> +} >> + >> +/** >> + >> + Updates Filter settings on the device. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_STATUS >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +RndisUndiReceiveFilter ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + EFI_STATUS Status; >> + UINT8 *McastList; >> + UINT8 Count; >> + UINT8 Index1; >> + UINT8 Index2; >> + UINT64 CpbAddr; >> + UINT32 CpbSize; >> + UINT16 SetFilter; >> + PXE_CPB_RECEIVE_FILTERS *Cpb; >> + USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor; >> + >> + Count = 0; >> + CpbAddr = Cdb->CPBaddr; >> + CpbSize = Cdb->CPBsize; >> + SetFilter = (UINT16)(Cdb->OpFlags & 0x1F); >> + Cpb = (PXE_CPB_RECEIVE_FILTERS *)(UINTN)CpbAddr; >> + >> + // The Cpb could be NULL.(ref:PXE_CPBADDR_NOT_USED) >> + Nic->RxFilter = (UINT8)SetFilter; >> + >> + if (((SetFilter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) != >> 0) || (Cpb != NULL)) { >> + if (Cpb != NULL) { >> + Nic->McastCount = (UINT8)(CpbSize / PXE_MAC_LENGTH); >> + CopyMem (&Nic->McastList, Cpb, Nic->McastCount); >> + } else { >> + Nic->McastCount = 0; >> + } >> + >> + Nic->UsbEth->UsbEthFunDescriptor (Nic->UsbEth, >> &UsbEthFunDescriptor); >> + if ((UsbEthFunDescriptor.NumberMcFilters << 1) == 0) { >> + Nic->RxFilter |= PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST; >> + DEBUG ((DEBUG_INFO, "SetUsbEthPacketFilter Nic %lx Nic->UsbEth %lx >> ", Nic, Nic->UsbEth)); >> + Nic->UsbEth->SetUsbEthPacketFilter (Nic->UsbEth, Nic->RxFilter); >> + } else { >> + Status = gBS->AllocatePool (EfiBootServicesData, Nic->McastCount * 6, >> (VOID **)&McastList); >> + if (EFI_ERROR (Status)) { >> + return PXE_STATCODE_INVALID_PARAMETER; >> + } >> + >> + if (Cpb != NULL) { >> + for (Index1 = 0; Index1 < Nic->McastCount; Index1++) { >> + for (Index2 = 0; Index2 < 6; Index2++) { >> + McastList[Count++] = Cpb->MCastList[Index1][Index2]; >> + } >> + } >> + } >> + >> + Nic->RxFilter |= PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST; >> + if (Cpb != NULL) { >> + Nic->UsbEth->SetUsbEthMcastFilter (Nic->UsbEth, Nic->McastCount, >> McastList); >> + } >> + >> + Nic->UsbEth->SetUsbEthPacketFilter (Nic->UsbEth, Nic->RxFilter); >> + FreePool (McastList); >> + } >> + } >> + >> + return EFI_SUCCESS; >> +} >> + >> +/** >> + This request is used to configure device Ethernet packet filter settings. >> + >> + @param[in] This A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> + @param[in] Value Packet Filter Bitmap. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +SetUsbRndisPacketFilter ( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + IN UINT16 Value >> + ) >> +{ >> + return EFI_SUCCESS; >> +} >> + >> +/** >> + This request is used to retrieve a statistic based on the feature selector. >> + >> + @param[in] This A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> + @param[in] FeatureSelector Value of the feature selector. >> + @param[out] Statistic A pointer to the 32 bit unsigned integer. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +GetRndisStatistic ( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + IN UINT16 FeatureSelector, >> + OUT VOID *Statistic >> + ) >> +{ >> + return EFI_SUCCESS; >> +} >> + >> +/** >> + This function is called when UndiStart is invoked. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +RndisUndiStart ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + EFI_STATUS Status; >> + >> + DEBUG ((DEBUG_INFO, "RndisUndiStart Nic %lx Cdb %lx Nic State %x\n", >> Nic, Cdb, Nic->State)); >> + >> + // Issue Rndis Reset and bring the device to RNDIS_BUS_INITIALIZED state >> + Status = RndisUndiReset (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + RndisUndiReset (Cdb, Nic); >> + } >> + >> + Status = RndisUndiInitialize (Cdb, Nic); >> + if (EFI_ERROR (Status)) { >> + RndisUndiInitialize (Cdb, Nic); >> + } >> + >> + RndisUndiShutdown (Cdb, Nic); >> + >> + return EFI_SUCCESS; >> +} >> + >> +/** >> + This function is called when Undistop is invoked. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> +**/ >> +EFI_STATUS >> +EFIAPI >> +RndisUndiStop ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + DEBUG ((DEBUG_INFO, "RndisUndiStop State %x\n", Nic->State)); >> + return EFI_SUCCESS; >> +} >> + >> +/** >> + This function is called when UndiGetInitInfo is invoked. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +RndisUndiGetInitInfo ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + EDKII_USB_ETHERNET_PROTOCOL *UsbEthDevice; >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> + PXE_DB_GET_INIT_INFO *Db; >> + >> + DEBUG ((DEBUG_INFO, "RndisUndiGetInitInfo\n")); >> + >> + UsbEthDevice = Nic->UsbEth; >> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (UsbEthDevice); >> + >> + Db = (PXE_DB_GET_INIT_INFO *)(UINTN)Cdb->DBaddr; >> + >> + Db->FrameDataLen = UsbRndisDevice->MaxTransferSize - sizeof >> (REMOTE_NDIS_PACKET_MSG) - PXE_MAC_HEADER_LEN_ETHER; >> + // Limit Max MTU size to 1500 bytes as RNDIS spec. >> + if (Db->FrameDataLen > PXE_MAX_TXRX_UNIT_ETHER) { >> + Db->FrameDataLen = PXE_MAX_TXRX_UNIT_ETHER; >> + } >> + >> + DEBUG ((DEBUG_INFO, "Db->FrameDataLen %x\n", Db->FrameDataLen)); >> + >> + return EFI_SUCCESS; >> +} >> + >> +/** >> + This function is called when RndisUndiGetConfigInfo is invoked. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +RndisUndiGetConfigInfo ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + DEBUG ((DEBUG_INFO, "RndisUndiGetConfigInfo\n")); >> + return EFI_SUCCESS; >> +} >> + >> +/** >> + This function is called when UndiInitialize is invoked. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_UNSUPPORTED Not supported. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +RndisUndiInitialize ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + EDKII_USB_ETHERNET_PROTOCOL *UsbEthDriver; >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> + REMOTE_NDIS_INITIALIZE_MSG RndisInitMsg; >> + REMOTE_NDIS_INITIALIZE_CMPLT RndisInitMsgCmplt; >> + EFI_STATUS Status; >> + >> + DEBUG ((DEBUG_INFO, "RndisUndiInitialize\n")); >> + >> + UsbEthDriver = Nic->UsbEth; >> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (UsbEthDriver); >> + >> + ZeroMem (&RndisInitMsg, sizeof (REMOTE_NDIS_INITIALIZE_MSG)); >> + ZeroMem (&RndisInitMsgCmplt, sizeof >> (REMOTE_NDIS_INITIALIZE_CMPLT)); >> + >> + RndisInitMsg.MessageType = RNDIS_INITIALIZE_MSG; >> + RndisInitMsg.MessageLength = sizeof (REMOTE_NDIS_INITIALIZE_MSG); >> + RndisInitMsg.RequestID = UsbRndisDevice->RequestId; >> + RndisInitMsg.MajorVersion = RNDIS_MAJOR_VERSION; >> + RndisInitMsg.MinorVersion = RNDIS_MINOR_VERSION; >> + RndisInitMsg.MaxTransferSize = RNDIS_MAX_TRANSFER_SIZE; >> + >> + RndisInitMsgCmplt.MessageType = RNDIS_INITIALIZE_CMPLT; >> + RndisInitMsgCmplt.MessageLength = sizeof >> (REMOTE_NDIS_INITIALIZE_CMPLT); >> + >> + Status = RndisControlMsg (UsbRndisDevice, >> (REMOTE_NDIS_MSG_HEADER *)&RndisInitMsg, >> (REMOTE_NDIS_MSG_HEADER *)&RndisInitMsgCmplt); >> + >> + UsbRndisDevice->RequestId++; >> + >> + if (EFI_ERROR (Status) || (RndisInitMsgCmplt.Status & 0x80000000)) { >> + return Status; >> + } >> + >> + // Only Wired Medium is supported >> + if (RndisInitMsgCmplt.Medium) { >> + return EFI_UNSUPPORTED; >> + } >> + >> + UsbRndisDevice->Medium = RndisInitMsgCmplt.Medium; >> + UsbRndisDevice->MaxPacketsPerTransfer = >> RndisInitMsgCmplt.MaxPacketsPerTransfer; >> + UsbRndisDevice->MaxTransferSize = >> RndisInitMsgCmplt.MaxTransferSize; >> + UsbRndisDevice->PacketAlignmentFactor = >> RndisInitMsgCmplt.PacketAlignmentFactor; >> + >> + DEBUG ((DEBUG_INFO, "Medium : %x \n", RndisInitMsgCmplt.Medium)); >> + DEBUG ((DEBUG_INFO, "MaxPacketsPerTransfer : %x \n", >> RndisInitMsgCmplt.MaxPacketsPerTransfer)); >> + DEBUG ((DEBUG_INFO, "MaxTransferSize : %x\n", >> RndisInitMsgCmplt.MaxTransferSize)); >> + DEBUG ((DEBUG_INFO, "PacketAlignmentFactor : %x\n", >> RndisInitMsgCmplt.PacketAlignmentFactor)); >> + >> + return Status; >> +} >> + >> +/** >> + This function is called when UndiReset is invoked. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +RndisUndiReset ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + EDKII_USB_ETHERNET_PROTOCOL *UsbEthDriver; >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> + REMOTE_NDIS_RESET_MSG RndisResetMsg; >> + REMOTE_NDIS_RESET_CMPLT RndisResetCmplt; >> + EFI_STATUS Status; >> + >> + DEBUG ((DEBUG_INFO, "RndisUndiReset\n")); >> + >> + UsbEthDriver = Nic->UsbEth; >> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (UsbEthDriver); >> + >> + ZeroMem (&RndisResetMsg, sizeof (REMOTE_NDIS_RESET_MSG)); >> + ZeroMem (&RndisResetCmplt, sizeof (REMOTE_NDIS_RESET_CMPLT)); >> + >> + RndisResetMsg.MessageType = RNDIS_RESET_MSG; >> + RndisResetMsg.MessageLength = sizeof (REMOTE_NDIS_RESET_MSG); >> + >> + RndisResetCmplt.MessageType = RNDIS_RESET_CMPLT; >> + RndisResetCmplt.MessageLength = sizeof (REMOTE_NDIS_RESET_CMPLT); >> + >> + Status = RndisControlMsg (UsbRndisDevice, >> (REMOTE_NDIS_MSG_HEADER *)&RndisResetMsg, >> (REMOTE_NDIS_MSG_HEADER *)&RndisResetCmplt); >> + >> + UsbRndisDevice->RequestId = 1; // Let's start with 1 >> + >> + if (EFI_ERROR (Status) || (RndisResetCmplt.Status & 0x80000000)) { >> + return EFI_DEVICE_ERROR; >> + } >> + >> + return EFI_SUCCESS; >> +} >> + >> +/** >> + This function is called when UndiShutdown is invoked. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +RndisUndiShutdown ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + EDKII_USB_ETHERNET_PROTOCOL *UsbEthDriver; >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> + REMOTE_NDIS_HALT_MSG RndisHltMsg; >> + EFI_STATUS Status; >> + >> + DEBUG ((DEBUG_INFO, "RndisUndiShutdown\n")); >> + >> + UsbEthDriver = Nic->UsbEth; >> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (UsbEthDriver); >> + >> + ZeroMem (&RndisHltMsg, sizeof (REMOTE_NDIS_HALT_MSG)); >> + >> + RndisHltMsg.MessageType = RNDIS_HLT_MSG; >> + RndisHltMsg.MessageLength = sizeof (REMOTE_NDIS_HALT_MSG); >> + >> + Status = RndisControlMsg (UsbRndisDevice, >> (REMOTE_NDIS_MSG_HEADER *)&RndisHltMsg, NULL); >> + >> + if (Status == EFI_DEVICE_ERROR) { >> + Status = EFI_SUCCESS; >> + } >> + >> + UsbRndisDevice->RequestId = 1; >> + return Status; >> +} >> + >> +/** >> + Update the Media connection. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +RndisUndiGetStatus ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + Cdb->StatFlags &= ~(PXE_STATFLAGS_GET_STATUS_NO_MEDIA); >> + return EFI_SUCCESS; >> +} >> + >> +/** >> + Transmit the data after appending RNDIS header. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] This A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> + @param[in] BulkOutData A pointer to the buffer of data that will be >> transmitted to USB >> + device or received from USB device. >> + @param[in, out] DataLength A pointer to the PacketLength. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +RndisUndiTransmit ( >> + IN PXE_CDB *Cdb, >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + IN VOID *BulkOutData, >> + IN OUT UINTN *DataLength >> + ) >> +{ >> + EFI_STATUS Status; >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> + REMOTE_NDIS_PACKET_MSG *RndisPacketMsg; >> + UINTN TransferLength; >> + >> + DEBUG ((DEBUG_INFO, "RndisUndiTransmit DataLength : %x\n", >> *DataLength)); >> + >> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> + >> + RndisPacketMsg = AllocateZeroPool (sizeof (REMOTE_NDIS_PACKET_MSG) >> + *DataLength); >> + if (RndisPacketMsg == NULL) { >> + return EFI_OUT_OF_RESOURCES; >> + } >> + >> + RndisPacketMsg->MessageType = RNDIS_PACKET_MSG; >> + RndisPacketMsg->MessageLength = sizeof (REMOTE_NDIS_PACKET_MSG) >> + (UINT32)*DataLength; >> + RndisPacketMsg->DataOffset = sizeof (REMOTE_NDIS_PACKET_MSG) - 8; >> + RndisPacketMsg->DataLength = (UINT32)*DataLength; >> + >> + CopyMem ( >> + ((UINT8 *)RndisPacketMsg) + sizeof (REMOTE_NDIS_PACKET_MSG), >> + BulkOutData, >> + *DataLength >> + ); >> + >> + TransferLength = RndisPacketMsg->MessageLength; >> + >> + Status = RndisTransmitDataMsg ( >> + UsbRndisDevice, >> + (REMOTE_NDIS_MSG_HEADER *)RndisPacketMsg, >> + &TransferLength >> + ); >> + >> + DEBUG ((DEBUG_INFO, "\nRndisUndiTransmit TransferLength %lx\n", >> TransferLength)); >> + >> + FreePool (RndisPacketMsg); >> + >> + return Status; >> +} >> + >> +/** >> + Receives and removes RNDIS header and returns the raw data. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] This A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> + @param[in, out] BulkInData A pointer to the buffer of data that will be >> transmitted to USB >> + device or received from USB device. >> + @param[in, out] DataLength A pointer to the PacketLength. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_BUFFER_TOO_SMALL The user provided buffer is too small >> + @retval EFI_NOT_FOUND No buffer was found in the list. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +RndisUndiReceive ( >> + IN PXE_CDB *Cdb, >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + IN OUT VOID *BulkInData, >> + IN OUT UINTN *DataLength >> + ) >> +{ >> + EFI_STATUS Status; >> + USB_RNDIS_DEVICE *UsbRndisDevice; >> + REMOTE_NDIS_PACKET_MSG *RndisPacketMsg; >> + UINTN TransferLength; >> + VOID *Buffer; >> + PACKET_LIST *HeadPacket; >> + PACKET_LIST *PacketList; >> + >> + // Check if there is any outstanding packet to receive >> + // The buffer allocated has a linked List followed by the packet. >> + >> + UsbRndisDevice = USB_RNDIS_DEVICE_FROM_THIS (This); >> + Buffer = NULL; >> + HeadPacket = NULL; >> + >> + while (1) { >> + Buffer = AllocateZeroPool (sizeof (PACKET_LIST) + sizeof >> (REMOTE_NDIS_PACKET_MSG) + UsbRndisDevice->MaxTransferSize); >> + if (Buffer == NULL) { >> + return EFI_OUT_OF_RESOURCES; >> + } >> + >> + RndisPacketMsg = (REMOTE_NDIS_PACKET_MSG *)(sizeof >> (PACKET_LIST) + (UINT8 *)Buffer); >> + PacketList = (PACKET_LIST *)Buffer; >> + PacketList->PacketStartBuffer = (UINT8 *)Buffer + sizeof (PACKET_LIST); >> + // Save the original address for freeing it up >> + PacketList->OrgBuffer = (UINT8 *)Buffer; >> + TransferLength = UsbRndisDevice->MaxTransferSize; >> + >> + Status = RndisReceiveDataMsg ( >> + UsbRndisDevice, >> + (REMOTE_NDIS_MSG_HEADER *)RndisPacketMsg, >> + &TransferLength >> + ); >> + >> + if (EFI_ERROR (Status) || (TransferLength == 0)) { >> + FreePool (Buffer); >> + break; >> + } >> + >> + // Collect all the RNDIS packet in Linked list. >> + if ((RndisPacketMsg->MessageType == RNDIS_PACKET_MSG) && >> + (RndisPacketMsg->DataOffset == sizeof (REMOTE_NDIS_PACKET_MSG) >> - RNDIS_RESERVED_BYTE_LENGTH) && >> + (TransferLength >= RndisPacketMsg->MessageLength)) >> + { >> + // Insert Packet >> + PacketList->RemainingLength = TransferLength; >> + InsertTailList (&UsbRndisDevice->ReceivePacketList, Buffer); >> + } else { >> + FreePool (Buffer); >> + } >> + } >> + >> + while (!IsListEmpty (&UsbRndisDevice->ReceivePacketList)) { >> + HeadPacket = (PACKET_LIST *)GetFirstNode (&UsbRndisDevice- >>> ReceivePacketList); >> + >> + RndisPacketMsg = (REMOTE_NDIS_PACKET_MSG *)(UINT8 >> *)HeadPacket->PacketStartBuffer; >> + >> + PrintRndisMsg ((REMOTE_NDIS_MSG_HEADER *)RndisPacketMsg); >> + >> + // Check whether the packet is valid RNDIS packet. >> + if ((HeadPacket->RemainingLength > sizeof >> (REMOTE_NDIS_PACKET_MSG)) && (RndisPacketMsg->MessageType == >> RNDIS_PACKET_MSG) && >> + (RndisPacketMsg->DataOffset == (sizeof (REMOTE_NDIS_PACKET_MSG) >> - RNDIS_RESERVED_BYTE_LENGTH)) && >> + (HeadPacket->RemainingLength >= RndisPacketMsg->MessageLength)) >> + { >> + if (*DataLength >= RndisPacketMsg->DataLength) { >> + CopyMem ( >> + BulkInData, >> + (UINT8 *)RndisPacketMsg + (RndisPacketMsg->DataOffset + >> RNDIS_RESERVED_BYTE_LENGTH), >> + RndisPacketMsg->DataLength >> + ); >> + >> + *DataLength = RndisPacketMsg->DataLength; >> + >> + HeadPacket->RemainingLength = HeadPacket->RemainingLength - >> RndisPacketMsg->MessageLength; >> + HeadPacket->PacketStartBuffer = (UINT8 *)RndisPacketMsg + >> RndisPacketMsg->MessageLength; >> + >> + return EFI_SUCCESS; >> + } else { >> + *DataLength = RndisPacketMsg->DataLength; >> + return EFI_BUFFER_TOO_SMALL; >> + } >> + } >> + >> + RemoveEntryList (&HeadPacket->PacketList); >> + FreePool ((PACKET_LIST *)HeadPacket->OrgBuffer); >> + } >> + >> + return EFI_NOT_FOUND; >> +} >> + >> +/** >> + This is a dummy function which just returns. Unimplemented >> EDKII_USB_ETHERNET_PROTOCOL functions >> + point to this function. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + >> +**/ >> +EFI_STATUS >> +EFIAPI >> +RndisDummyReturn ( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ) >> +{ >> + DEBUG ((DEBUG_INFO, "RndisDummyReturn called\n")); >> + return EFI_SUCCESS; >> +} >> + >> +/** >> + This function send the RNDIS command through the device's control >> endpoint >> + >> + @param[in] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE >> instance. >> + @param[in] RndisMsg A pointer to the REMOTE_NDIS_MSG_HEADER >> data. >> + @param[out] RndisMsgResponse A pointer to the >> REMOTE_NDIS_MSG_HEADER data for getting responses. >> + >> + @retval EFI_SUCCESS The bulk transfer has been successfully >> executed. >> + >> +**/ >> +EFI_STATUS >> +RndisControlMsg ( >> + IN USB_RNDIS_DEVICE *UsbRndisDevice, >> + IN REMOTE_NDIS_MSG_HEADER *RndisMsg, >> + OUT REMOTE_NDIS_MSG_HEADER *RndisMsgResponse >> + ) >> +{ >> + EFI_USB_IO_PROTOCOL *UsbIo = UsbRndisDevice->UsbIo; >> + EFI_USB_DEVICE_REQUEST DevReq; >> + UINT32 UsbStatus; >> + EFI_STATUS Status; >> + UINT32 SaveResponseType; >> + UINT32 SaveResponseLength; >> + UINT32 Index; >> + REMOTE_NDIS_INITIALIZE_CMPLT *RndisInitCmplt; >> + >> + SaveResponseType = 0; >> + SaveResponseLength = 0; >> + RndisInitCmplt = (REMOTE_NDIS_INITIALIZE_CMPLT >> *)RndisMsgResponse; >> + >> + if (RndisMsgResponse) { >> + SaveResponseType = RndisMsgResponse->MessageType; >> + SaveResponseLength = RndisMsgResponse->MessageLength; >> + } >> + >> + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); >> + >> + DevReq.RequestType = USB_REQ_TYPE_CLASS | USB_TARGET_INTERFACE; >> + DevReq.Request = SEND_ENCAPSULATED_COMMAND; >> + DevReq.Value = 0; >> + DevReq.Index = 0; >> + DevReq.Length = (UINT16)RndisMsg->MessageLength; >> + >> + PrintRndisMsg (RndisMsg); >> + >> + Status = UsbIo->UsbControlTransfer ( >> + UsbIo, >> + &DevReq, >> + EfiUsbDataOut, >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> + RndisMsg, >> + RndisMsg->MessageLength, >> + &UsbStatus >> + ); >> + >> + DEBUG ((DEBUG_INFO, "RndisControlMsg: UsbStatus : %x Status : %r >> RndisMsgResponse : %lx\n", UsbStatus, Status, RndisMsgResponse)); >> + >> + // Error or no response expected >> + if ((EFI_ERROR (Status)) || (RndisMsgResponse == NULL)) { >> + DEBUG ((DEBUG_INFO, "RndisControlMsg: UsbStatus : %x Status : %r\n", >> UsbStatus, Status)); >> + return Status; >> + } >> + >> + for (Index = 0; Index < (RNDIS_CONTROL_TIMEOUT/100); Index++) { >> + ReadRndisResponseInterrupt (UsbRndisDevice); >> + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); >> + >> + DevReq.RequestType = USB_ENDPOINT_DIR_IN | USB_REQ_TYPE_CLASS >> | USB_TARGET_INTERFACE; >> + DevReq.Request = GET_ENCAPSULATED_RESPONSE; >> + DevReq.Value = 0; >> + DevReq.Index = 0; >> + DevReq.Length = (UINT16)RndisMsgResponse->MessageLength; >> + >> + Status = UsbIo->UsbControlTransfer ( >> + UsbIo, >> + &DevReq, >> + EfiUsbDataIn, >> + USB_ETHERNET_TRANSFER_TIMEOUT, >> + RndisMsgResponse, >> + RndisMsgResponse->MessageLength, >> + &UsbStatus >> + ); >> + >> + DEBUG ((DEBUG_INFO, "RndisControlMsg Response: UsbStatus : %x >> Status : %r \n", UsbStatus, Status)); >> + >> + PrintRndisMsg (RndisMsgResponse); >> + >> + if (!EFI_ERROR (Status)) { >> + if ((RndisInitCmplt->RequestID != ((REMOTE_NDIS_INITIALIZE_CMPLT >> *)RndisMsg)->RequestID) || (RndisInitCmplt->MessageType != >> SaveResponseType)) { >> + DEBUG ((DEBUG_INFO, "Retry the response\n")); >> + >> + RndisMsgResponse->MessageType = SaveResponseType; >> + RndisMsgResponse->MessageLength = SaveResponseLength; >> + continue; >> + } >> + } >> + >> + return Status; >> + } >> + >> + DEBUG ((DEBUG_INFO, "RndisControlMsg: TimeOut\n")); >> + >> + return EFI_TIMEOUT; >> +} >> + >> +/** >> + This function send the RNDIS command through the device's Data >> endpoint >> + >> + @param[in] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE >> instance. >> + @param[in] RndisMsg A pointer to the >> REMOTE_NDIS_MSG_HEADER to send out. >> + @param[in, out] TransferLength The length of the RndisMsg data to >> transfer. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + >> +**/ >> +EFI_STATUS >> +RndisTransmitDataMsg ( >> + IN USB_RNDIS_DEVICE *UsbRndisDevice, >> + IN REMOTE_NDIS_MSG_HEADER *RndisMsg, >> + IN OUT UINTN *TransferLength >> + ) >> +{ >> + EFI_STATUS Status; >> + UINT32 UsbStatus; >> + >> + if (UsbRndisDevice->BulkInEndpoint == 0) { >> + GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice); >> + } >> + >> + PrintRndisMsg (RndisMsg); >> + >> + Status = UsbRndisDevice->UsbIoCdcData->UsbBulkTransfer ( >> + UsbRndisDevice->UsbIoCdcData, >> + UsbRndisDevice->BulkOutEndpoint, >> + RndisMsg, >> + TransferLength, >> + USB_TX_ETHERNET_BULK_TIMEOUT, >> + &UsbStatus >> + ); >> + >> + if (Status == EFI_SUCCESS) { >> + gStopBulkInCnt = MAXIMUM_STOPBULKIN_CNT; // After sending >> cmd ,we will polling receive package for MAXIMUM_STOPBULKIN_CNT >> times >> + } >> + >> + return Status; >> +} >> + >> +/** >> + This function send the RNDIS command through the device's Data >> endpoint >> + >> + @param[in] UsbRndisDevice A pointer to the USB_RNDIS_DEVICE >> instance. >> + @param[in, out] RndisMsg A pointer to the >> REMOTE_NDIS_MSG_HEADER to send out. >> + @param[in, out] TransferLength The length of the RndisMsg data to >> transfer. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + >> +**/ >> +EFI_STATUS >> +RndisReceiveDataMsg ( >> + IN USB_RNDIS_DEVICE *UsbRndisDevice, >> + IN OUT REMOTE_NDIS_MSG_HEADER *RndisMsg, >> + IN OUT UINTN *TransferLength >> + ) >> +{ >> + EFI_STATUS Status; >> + UINT32 UsbStatus; >> + >> + UsbStatus = 0; >> + >> + if (UsbRndisDevice->BulkInEndpoint == 0) { >> + GetEndpoint (UsbRndisDevice->UsbIoCdcData, UsbRndisDevice); >> + } >> + >> + // Use gStopBulkInCnt to stop BulkIn command >> + if (gStopBulkInCnt || LAN_BULKIN_CMD_CONTROL) { >> + Status = UsbRndisDevice->UsbIoCdcData->UsbBulkTransfer ( >> + UsbRndisDevice->UsbIoCdcData, >> + UsbRndisDevice->BulkInEndpoint, >> + RndisMsg, >> + TransferLength, >> + USB_RX_ETHERNET_BULK_TIMEOUT, >> + &UsbStatus >> + ); >> + >> + if (!EFI_ERROR (Status)) { >> + gStopBulkInCnt = MINIMUM_STOPBULKIN_CNT; >> + } else { >> + gStopBulkInCnt--; >> + } >> + } else { >> + Status = EFI_TIMEOUT; >> + *TransferLength = 0; >> + gBlockBulkInCnt++; >> + } >> + >> + if (gBlockBulkInCnt > BULKIN_CMD_POLLING_CNT) { >> + gStopBulkInCnt = MINIMUM_STOPBULKIN_CNT; >> + gBlockBulkInCnt = 0; >> + } >> + >> + PrintRndisMsg (RndisMsg); >> + >> + return Status; >> +} >> + >> +/** >> + Prints RNDIS Header and Data >> + >> + @param[in] RndisMsg A pointer to the REMOTE_NDIS_MSG_HEADER >> data. >> + >> +**/ >> +VOID >> +PrintRndisMsg ( >> + IN REMOTE_NDIS_MSG_HEADER *RndisMsg >> + ) >> +{ >> + UINTN Length; >> + REMOTE_NDIS_QUERY_CMPLT *RndisQueryCmplt; >> + >> + Length = 0; >> + >> + switch (RndisMsg->MessageType) { >> + case RNDIS_PACKET_MSG: >> + DEBUG ((DEBUG_INFO, "RNDIS_PACKET_MSG:\n")); >> + Length = sizeof (REMOTE_NDIS_PACKET_MSG) + 0x14; >> + break; >> + case RNDIS_INITIALIZE_MSG: >> + DEBUG ((DEBUG_INFO, "RNDIS_INITIALIZE_MSG:\n")); >> + Length = sizeof (REMOTE_NDIS_INITIALIZE_MSG); >> + break; >> + case RNDIS_INITIALIZE_CMPLT: >> + DEBUG ((DEBUG_INFO, "RNDIS_INITIALIZE_CMPLT:\n")); >> + Length = sizeof (REMOTE_NDIS_INITIALIZE_CMPLT); >> + break; >> + case RNDIS_HLT_MSG: >> + DEBUG ((DEBUG_INFO, "RNDIS_HLT_MSG:\n")); >> + Length = sizeof (REMOTE_NDIS_HALT_MSG); >> + break; >> + case RNDIS_QUERY_MSG: >> + DEBUG ((DEBUG_INFO, "RNDIS_QUERY_MSG:\n")); >> + Length = sizeof (REMOTE_NDIS_QUERY_MSG); >> + break; >> + case RNDIS_QUERY_CMPLT: >> + DEBUG ((DEBUG_INFO, "RNDIS_QUERY_CMPLT:\n")); >> + RndisQueryCmplt = (REMOTE_NDIS_QUERY_CMPLT *)RndisMsg; >> + Length = sizeof (REMOTE_NDIS_QUERY_CMPLT) + >> RndisQueryCmplt->InformationBufferLength; >> + break; >> + case RNDIS_SET_MSG: >> + DEBUG ((DEBUG_INFO, "RNDIS_SET_MSG:\n")); >> + Length = sizeof (REMOTE_NDIS_SET_MSG); >> + break; >> + case RNDIS_SET_CMPLT: >> + DEBUG ((DEBUG_INFO, "RNDIS_SET_CMPLT:\n")); >> + Length = sizeof (REMOTE_NDIS_SET_CMPLT); >> + break; >> + case RNDIS_RESET_MSG: >> + DEBUG ((DEBUG_INFO, "RNDIS_RESET_MSG:\n")); >> + Length = sizeof (REMOTE_NDIS_RESET_MSG); >> + break; >> + case RNDIS_RESET_CMPLT: >> + DEBUG ((DEBUG_INFO, "RNDIS_RESET_CMPLT:\n")); >> + Length = sizeof (REMOTE_NDIS_RESET_CMPLT); >> + break; >> + case RNDIS_INDICATE_STATUS_MSG: >> + DEBUG ((DEBUG_INFO, "RNDIS_INDICATE_STATUS_MSG:\n")); >> + Length = sizeof (REMOTE_NDIS_INDICATE_STATUS_MSG); >> + break; >> + case RNDIS_KEEPALIVE_MSG: >> + DEBUG ((DEBUG_INFO, "RNDIS_KEEPALIVE_MSG:\n")); >> + Length = sizeof (REMOTE_NDIS_KEEPALIVE_MSG); >> + break; >> + case RNDIS_KEEPALIVE_CMPLT: >> + DEBUG ((DEBUG_INFO, "RNDIS_KEEPALIVE_CMPLT:\n")); >> + Length = sizeof (REMOTE_NDIS_KEEPALIVE_CMPLT); >> + } >> + >> + if (Length) { >> + UINTN Index = 0; >> + for ( ; Length; Length -= 4, Index++) { >> + DEBUG ((DEBUG_INFO, "%8X\t", *((UINT32 *)RndisMsg + Index))); >> + if (((Index % 4) == 3) && (Index != 0)) { >> + DEBUG ((DEBUG_INFO, "\n")); >> + } >> + >> + if ((Length < 8) && (Length > 4)) { >> + UINT32 Data32; >> + Index++; >> + Data32 = *((UINT32 *)RndisMsg + Index); >> + DEBUG ((DEBUG_INFO, "%8X\t", Data32)); >> + break; >> + } >> + } >> + >> + if (Index % 4) { >> + DEBUG ((DEBUG_INFO, "\n")); >> + } >> + } >> +} >> diff --git a/MdeModulePkg/Include/Protocol/UsbEthernetProtocol.h >> b/MdeModulePkg/Include/Protocol/UsbEthernetProtocol.h >> new file mode 100644 >> index 0000000000..800945d4b3 >> --- /dev/null >> +++ b/MdeModulePkg/Include/Protocol/UsbEthernetProtocol.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 USB_ETHERNET_PROTOCOL_H_ >> +#define USB_ETHERNET_PROTOCOL_H_ >> + >> +#define EDKII_USB_ETHERNET_PROTOCOL_GUID \ >> + {0x8d8969cc, 0xfeb0, 0x4303, {0xb2, 0x1a, 0x1f, 0x11, 0x6f, 0x38, 0x56, >> 0x43}} >> + >> +typedef struct _EDKII_USB_ETHERNET_PROTOCOL >> EDKII_USB_ETHERNET_PROTOCOL; >> + >> +#define USB_CDC_CLASS 0x02 >> +#define USB_CDC_ACM_SUBCLASS 0x02 >> +#define USB_CDC_ECM_SUBCLASS 0x06 >> +#define USB_CDC_NCM_SUBCLASS 0x0D >> +#define USB_CDC_DATA_CLASS 0x0A >> +#define USB_CDC_DATA_SUBCLASS 0x00 >> +#define USB_NO_CLASS_PROTOCOL 0x00 >> +#define USB_NCM_NTB_PROTOCOL 0x01 >> +#define USB_VENDOR_PROTOCOL 0xFF >> + >> +// Type Values for the DescriptorType Field >> +#define CS_INTERFACE 0x24 >> +#define CS_ENDPOINT 0x25 >> + >> +// Descriptor SubType in Functional Descriptors >> +#define HEADER_FUN_DESCRIPTOR 0x00 >> +#define UNION_FUN_DESCRIPTOR 0x06 >> +#define ETHERNET_FUN_DESCRIPTOR 0x0F >> + >> +#define MAX_LAN_INTERFACE 0x10 >> + >> +// Table 20: Class-Specific Notification Codes >> +#define USB_CDC_NETWORK_CONNECTION 0x00 >> + >> +// 6.3.1 NetworkConnection >> +#define NETWORK_CONNECTED 0x01 >> +#define NETWORK_DISCONNECT 0x00 >> + >> +// USB Header functional Descriptor >> +typedef struct { >> + UINT8 FunctionLength; >> + UINT8 DescriptorType; >> + UINT8 DescriptorSubtype; >> + UINT16 BcdCdc; >> +} USB_HEADER_FUN_DESCRIPTOR; >> + >> +// USB Union Functional Descriptor >> +typedef struct { >> + UINT8 FunctionLength; >> + UINT8 DescriptorType; >> + UINT8 DescriptorSubtype; >> + UINT8 MasterInterface; >> + UINT8 SlaveInterface; >> +} USB_UNION_FUN_DESCRIPTOR; >> + >> +// USB Ethernet Functional Descriptor >> +typedef struct { >> + UINT8 FunctionLength; >> + UINT8 DescriptorType; >> + UINT8 DescriptorSubtype; >> + UINT8 MacAddress; >> + UINT32 EthernetStatistics; >> + UINT16 MaxSegmentSize; >> + UINT16 NumberMcFilters; >> + UINT8 NumberPowerFilters; >> +} USB_ETHERNET_FUN_DESCRIPTOR; >> + >> +typedef struct { >> + UINT32 UsBitRate; >> + UINT32 DsBitRate; >> +} USB_CONNECT_SPEED_CHANGE; >> + >> +// Request Type Codes for USB Ethernet >> +#define USB_ETHERNET_GET_REQ_TYPE 0xA1 >> +#define USB_ETHERNET_SET_REQ_TYPE 0x21 >> + >> +// Class-Specific Request Codes for Ethernet subclass >> +// USB ECM 1.2 specification, Section 6.2 >> +#define SET_ETH_MULTICAST_FILTERS_REQ 0x40 >> +#define SET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ 0x41 >> +#define GET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ 0x42 >> +#define SET_ETH_PACKET_FILTER_REQ 0x43 >> +#define GET_ETH_STATISTIC_REQ 0x44 >> + >> +// USB ECM command request length >> +#define USB_ETH_POWER_FILTER_LENGTH 2 // Section 6.2.3 >> +#define USB_ETH_PACKET_FILTER_LENGTH 0 // Section 6.2.4 >> +#define USB_ETH_STATISTIC 4 // Section 6.2.5 >> + >> +// USB Ethernet Packet Filter Bitmap >> +// USB ECM 1.2 specification, Section 6.2.4 >> +#define USB_ETH_PACKET_TYPE_PROMISCUOUS BIT0 >> +#define USB_ETH_PACKET_TYPE_ALL_MULTICAST BIT1 >> +#define USB_ETH_PACKET_TYPE_DIRECTED BIT2 >> +#define USB_ETH_PACKET_TYPE_BROADCAST BIT3 >> +#define USB_ETH_PACKET_TYPE_MULTICAST BIT4 >> + >> +// USB Ethernet Statistics Feature Selector Codes >> +// USB ECM 1.2 specification, Section 6.2.5 >> +#define USB_ETH_XMIT_OK 0x01 >> +#define USB_ETH_RCV_OK 0x02 >> +#define USB_ETH_XMIT_ERROR 0x03 >> +#define USB_ETH_RCV_ERROR 0x04 >> +#define USB_ETH_RCV_NO_BUFFER 0x05 >> +#define USB_ETH_DIRECTED_BYTES_XMIT 0x06 >> +#define USB_ETH_DIRECTED_FRAMES_XMIT 0x07 >> +#define USB_ETH_MULTICAST_BYTES_XMIT 0x08 >> +#define USB_ETH_MULTICAST_FRAMES_XMIT 0x09 >> +#define USB_ETH_BROADCAST_BYTES_XMIT 0x0A >> +#define USB_ETH_BROADCAST_FRAMES_XMIT 0x0B >> +#define USB_ETH_DIRECTED_BYTES_RCV 0x0C >> +#define USB_ETH_DIRECTED_FRAMES_RCV 0x0D >> +#define USB_ETH_MULTICAST_BYTES_RCV 0x0E >> +#define USB_ETH_MULTICAST_FRAMES_RCV 0x0F >> +#define USB_ETH_BROADCAST_BYTES_RCV 0x10 >> +#define USB_ETH_BROADCAST_FRAMES_RCV 0x11 >> +#define USB_ETH_RCV_CRC_ERROR 0x12 >> +#define USB_ETH_TRANSMIT_QUEUE_LENGTH 0x13 >> +#define USB_ETH_RCV_ERROR_ALIGNMENT 0x14 >> +#define USB_ETH_XMIT_ONE_COLLISION 0x15 >> +#define USB_ETH_XMIT_MORE_COLLISIONS 0x16 >> +#define USB_ETH_XMIT_DEFERRED 0x17 >> +#define USB_ETH_XMIT_MAX_COLLISIONS 0x18 >> +#define USB_ETH_RCV_OVERRUN 0x19 >> +#define USB_ETH_XMIT_UNDERRUN 0x1A >> +#define USB_ETH_XMIT_HEARTBEAT_FAILURE 0x1B >> +#define USB_ETH_XMIT_TIMES_CRS_LOST 0x1C >> +#define USB_ETH_XMIT_LATE_COLLISIONS 0x1D >> + >> +// NIC Information >> +typedef struct { >> + UINT32 Signature; >> + EDKII_USB_ETHERNET_PROTOCOL *UsbEth; >> + UINT16 InterrupOpFlag; >> + UINT64 MappedAddr; >> + PXE_MAC_ADDR McastList[MAX_MCAST_ADDRESS_CNT]; >> + UINT8 McastCount; >> + UINT64 MediaHeader[MAX_XMIT_BUFFERS]; >> + UINT8 TxBufferCount; >> + UINT16 State; >> + BOOLEAN CanTransmit; >> + UINT16 ReceiveStatus; >> + UINT8 RxFilter; >> + UINT32 RxFrame; >> + UINT32 TxFrame; >> + UINT16 NetworkConnect; >> + UINT8 CableDetect; >> + UINT16 MaxSegmentSize; >> + EFI_MAC_ADDRESS MacAddr; >> + PXE_CPB_START_31 PxeStart; >> + PXE_CPB_INITIALIZE PxeInit; >> + UINT8 PermNodeAddress[PXE_MAC_LENGTH]; >> + UINT8 CurrentNodeAddress[PXE_MAC_LENGTH]; >> + UINT8 BroadcastNodeAddress[PXE_MAC_LENGTH]; >> + EFI_USB_DEVICE_REQUEST Request; >> + EFI_EVENT RateLimiter; >> + UINT32 RateLimitingCredit; >> + UINT32 RateLimitingCreditCount; >> + UINT32 RateLimitingPollTimer; >> + BOOLEAN RateLimitingEnable; >> +} NIC_DATA; >> + >> +#define NIC_DATA_SIGNATURE SIGNATURE_32('n', 'i', 'c', 'd') >> +#define NIC_DATA_FROM_EDKII_USB_ETHERNET_PROTOCOL(a) CR (a, >> NIC_DATA, UsbEth, NIC_DATA_SIGNATURE) >> + >> +/** >> + This command is used to determine the operational state of the UNDI. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_GET_STATE)( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +/** >> + This command is used to change the UNDI operational state from stopped >> to started. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_START)( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +/** >> + This command is used to change the UNDI operational state from started >> to stopped. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_STOP)( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +/** >> + This command is used to retrieve initialization information that is >> + needed by drivers and applications to initialized UNDI. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_GET_INIT_INFO)( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +/** >> + This command is used to retrieve configuration information about >> + the NIC being controlled by the UNDI. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_GET_CONFIG_INFO)( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +/** >> + This command resets the network adapter and initializes UNDI using >> + the parameters supplied in the CPB. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_INITIALIZE)( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +/** >> + This command resets the network adapter and reinitializes the UNDI >> + with the same parameters provided in the Initialize command. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_RESET)( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +/** >> + The Shutdown command resets the network adapter and leaves it in a >> + safe state for another driver to initialize. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_SHUTDOWN)( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +/** >> + The Interrupt Enables command can be used to read and/or change >> + the current external interrupt enable settings. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_INTERRUPT_ENABLE)( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +/** >> + This command is used to read and change receive filters and, >> + if supported, read and change the multicast MAC address filter list. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_RECEIVE_FILTER)( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +/** >> + This command is used to get current station and broadcast MAC addresses >> + and, if supported, to change the current station MAC address. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_STATION_ADDRESS)( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +/** >> + This command is used to read and clear the NIC traffic statistics. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_STATISTICS)( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +/** >> + Translate a multicast IPv4 or IPv6 address to a multicast MAC address. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_MCAST_IPTOMAC)( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +/** >> + This command is used to read and write (if supported by NIC H/W) >> + nonvolatile storage on the NIC. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_NV_DATA)( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +/** >> + This command returns the current interrupt status and/or the >> + transmitted buffer addresses and the current media status. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_GET_STATUS)( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +/** >> + This command is used to fill the media header(s) in transmit packet(s). >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_FILL_HEADER)( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +/** >> + The Transmit command is used to place a packet into the transmit queue. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_TRANSMIT)( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +/** >> + When the network adapter has received a frame, this command is used >> + to copy the frame into driver/application storage. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_UNDI_RECEIVE)( >> + IN PXE_CDB *Cdb, >> + IN NIC_DATA *Nic >> + ); >> + >> +/** >> + This command resets the network adapter and initializes UNDI using >> + the parameters supplied in the CPB. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in, out] Nic A pointer to the Network interface controller data. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_INITIALIZE)( >> + IN PXE_CDB *Cdb, >> + IN OUT NIC_DATA *Nic >> + ); >> + >> +/** >> + This command is used to read and clear the NIC traffic statistics. >> + >> + @param[in] Nic A pointer to the Network interface controller data. >> + @param[in] DbAddr Data Block Address. >> + @param[in] DbSize Data Block Size. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_STATISTICS)( >> + IN NIC_DATA *Nic, >> + IN UINT64 DbAddr, >> + IN UINT16 DbSize >> + ); >> + >> +/** >> + This function is used to manage a USB device with the bulk transfer pipe. >> The endpoint is Bulk in. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] This A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> + @param[in, out] Packet A pointer to the buffer of data that will be >> transmitted to USB >> + device or received from USB device. >> + @param[in, out] PacketLength A pointer to the PacketLength. >> + >> + @retval EFI_SUCCESS The bulk transfer has been successfully >> executed. >> + @retval EFI_DEVICE_ERROR The transfer failed. The transfer status is >> returned in status. >> + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. >> + @retval EFI_OUT_OF_RESOURCES The request could not be submitted >> due to a lack of resources. >> + @retval EFI_TIMEOUT The control transfer fails due to timeout. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_RECEIVE)( >> + IN PXE_CDB *Cdb, >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + IN OUT VOID *Packet, >> + IN OUT UINTN *PacketLength >> + ); >> + >> +/** >> + This function is used to manage a USB device with the bulk transfer pipe. >> The endpoint is Bulk out. >> + >> + @param[in] Cdb A pointer to the command descriptor block. >> + @param[in] This A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> + @param[in, out] Packet A pointer to the buffer of data that will be >> transmitted to USB >> + device or received from USB device. >> + @param[in, out] PacketLength A pointer to the PacketLength. >> + >> + @retval EFI_SUCCESS The bulk transfer has been successfully >> executed. >> + @retval EFI_DEVICE_ERROR The transfer failed. The transfer status is >> returned in status. >> + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. >> + @retval EFI_OUT_OF_RESOURCES The request could not be submitted >> due to a lack of resources. >> + @retval EFI_TIMEOUT The control transfer fails due to timeout. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_TRANSMIT)( >> + IN PXE_CDB *Cdb, >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + IN OUT VOID *Packet, >> + IN OUT UINTN *PacketLength >> + ); >> + >> +/** >> + This function is used to manage a USB device with an interrupt transfer >> pipe. >> + >> + @param[in] This A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> + @param[in] IsNewTransfer If TRUE, a new transfer will be submitted to >> USB controller. If >> + FALSE, the interrupt transfer is deleted from the device's >> interrupt >> + transfer queue. >> + @param[in] PollingInterval Indicates the periodic rate, in milliseconds, >> that the transfer is to be >> + executed.This parameter is required when IsNewTransfer >> is TRUE. The >> + value must be between 1 to 255, otherwise >> EFI_INVALID_PARAMETER is returned. >> + The units are in milliseconds. >> + @param[in] Request A pointer to the EFI_USB_DEVICE_REQUEST >> data. >> + >> + @retval EFI_SUCCESS The asynchronous USB transfer request >> transfer has been successfully executed. >> + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request >> failed. >> + >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_INTERRUPT)( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + IN BOOLEAN IsNewTransfer, >> + IN UINTN PollingInterval, >> + IN EFI_USB_DEVICE_REQUEST *Request >> + ); >> + >> +/** >> + Retrieves the USB Ethernet Mac Address. >> + >> + @param[in] This A pointer to the EDKII_USB_ETHERNET_PROTOCOL >> instance. >> + @param[out] MacAddress A pointer to the caller allocated USB Ethernet >> Mac Address. >> + >> + @retval EFI_SUCCESS The USB Header Functional descriptor was >> retrieved successfully. >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor was >> not found. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_GET_ETH_MAC_ADDRESS)( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + OUT EFI_MAC_ADDRESS *MacAddress >> + ); >> + >> +/** >> + Retrieves the USB Ethernet Bulk transfer data size. >> + >> + @param[in] This A pointer to the EDKII_USB_ETHERNET_PROTOCOL >> instance. >> + @param[out] BulkSize A pointer to the Bulk transfer data size. >> + >> + @retval EFI_SUCCESS The USB Header Functional descriptor was >> retrieved successfully. >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor was >> not found. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETH_MAX_BULK_SIZE)( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + OUT UINTN *BulkSize >> + ); >> + >> +/** >> + Retrieves the USB Header functional Descriptor. >> + >> + @param[in] This A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> + @param[out] UsbHeaderFunDescriptor A pointer to the caller allocated >> USB Header Functional Descriptor. >> + >> + @retval EFI_SUCCESS The USB Header Functional descriptor was >> retrieved successfully. >> + @retval EFI_INVALID_PARAMETER UsbHeaderFunDescriptor is NULL. >> + @retval EFI_NOT_FOUND The USB Header Functional descriptor was >> not found. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_HEADER_FUNCTIONAL_DESCRIPTOR)( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + OUT USB_HEADER_FUN_DESCRIPTOR *UsbHeaderFunDescriptor >> + ); >> + >> +/** >> + Retrieves the USB Union functional Descriptor. >> + >> + @param[in] This A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> + @param[out] UsbUnionFunDescriptor A pointer to the caller allocated >> USB Union Functional Descriptor. >> + >> + @retval EFI_SUCCESS The USB Union Functional descriptor was >> retrieved successfully. >> + @retval EFI_INVALID_PARAMETER UsbUnionFunDescriptor is NULL. >> + @retval EFI_NOT_FOUND The USB Union Functional descriptor was >> not found. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_UNION_FUNCTIONAL_DESCRIPTOR)( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + OUT USB_UNION_FUN_DESCRIPTOR *UsbUnionFunDescriptor >> + ); >> + >> +/** >> + Retrieves the USB Ethernet functional Descriptor. >> + >> + @param[in] This A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> + @param[out] UsbEthFunDescriptor A pointer to the caller allocated USB >> Ethernet Functional Descriptor. >> + >> + @retval EFI_SUCCESS The USB Ethernet Functional descriptor was >> retrieved successfully. >> + @retval EFI_INVALID_PARAMETER UsbEthFunDescriptor is NULL. >> + @retval EFI_NOT_FOUND The USB Ethernet Functional descriptor was >> not found. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_FUNCTIONAL_DESCRIPTOR)( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor >> + ); >> + >> +/** >> + This request sets the Ethernet device multicast filters as specified in the >> + sequential list of 48 bit Ethernet multicast addresses. >> + >> + @param[in] This A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> + @param[in] Value Number of filters. >> + @param[in] McastAddr A pointer to the value of the multicast >> addresses. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_SET_ETH_MULTICAST_FILTERS)( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + IN UINT16 Value, >> + IN VOID *McastAddr >> + ); >> + >> +/** >> + This request sets up the specified Ethernet power management pattern >> filter as >> + described in the data structure. >> + >> + @param[in] This A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> + @param[in] Value Number of filters. >> + @param[in] Length Size of the power management pattern filter >> data. >> + @param[in] PatternFilter A pointer to the power management >> pattern filter structure. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI >> *EDKII_USB_ETHERNET_SET_ETH_POWER_MANAGE_PATTERN_FILTER)( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + IN UINT16 Value, >> + IN UINT16 Length, >> + IN VOID *PatternFilter >> + ); >> + >> +/** >> + This request retrieves the status of the specified Ethernet power >> management >> + pattern filter from the device. >> + >> + @param[in] This A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> + @param[in] Value The filter number. >> + @param[out] PatternActive A pointer to the pattern active boolean. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI >> *EDKII_USB_ETHERNET_GET_ETH_POWER_MANAGE_PATTERN_FILTER)( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + IN UINT16 Value, >> + OUT BOOLEAN *PatternActive >> + ); >> + >> +/** >> + This request is used to configure device Ethernet packet filter settings. >> + >> + @param[in] This A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> + @param[in] Value Packet Filter Bitmap. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_SET_ETH_PACKET_FILTER)( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + IN UINT16 Value >> + ); >> + >> +/** >> + This request is used to retrieve a statistic based on the feature selector. >> + >> + @param[in] This A pointer to the >> EDKII_USB_ETHERNET_PROTOCOL instance. >> + @param[in] FeatureSelector Value of the feature selector. >> + @param[out] Statistic A pointer to the 32 bit unsigned integer. >> + >> + @retval EFI_SUCCESS The request executed successfully. >> + @retval EFI_TIMEOUT A timeout occurred executing the request. >> + @retval EFI_DEVICE_ERROR The request failed due to a device error. >> + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid >> value. >> + @retval EFI_UNSUPPORTED Not supported. >> +**/ >> +typedef >> +EFI_STATUS >> +(EFIAPI *EDKII_USB_ETHERNET_GET_ETH_STATISTIC)( >> + IN EDKII_USB_ETHERNET_PROTOCOL *This, >> + IN UINT16 FeatureSelector, >> + OUT VOID *Statistic >> + ); >> + >> +typedef struct { >> + EDKII_USB_ETHERNET_UNDI_GET_STATE UsbEthUndiGetState; >> + EDKII_USB_ETHERNET_UNDI_START UsbEthUndiStart; >> + EDKII_USB_ETHERNET_UNDI_STOP UsbEthUndiStop; >> + EDKII_USB_ETHERNET_UNDI_GET_INIT_INFO UsbEthUndiGetInitInfo; >> + EDKII_USB_ETHERNET_UNDI_GET_CONFIG_INFO >> UsbEthUndiGetConfigInfo; >> + EDKII_USB_ETHERNET_UNDI_INITIALIZE UsbEthUndiInitialize; >> + EDKII_USB_ETHERNET_UNDI_RESET UsbEthUndiReset; >> + EDKII_USB_ETHERNET_UNDI_SHUTDOWN UsbEthUndiShutdown; >> + EDKII_USB_ETHERNET_UNDI_INTERRUPT_ENABLE >> UsbEthUndiInterruptEnable; >> + EDKII_USB_ETHERNET_UNDI_RECEIVE_FILTER >> UsbEthUndiReceiveFilter; >> + EDKII_USB_ETHERNET_UNDI_STATION_ADDRESS >> UsbEthUndiStationAddress; >> + EDKII_USB_ETHERNET_UNDI_STATISTICS UsbEthUndiStatistics; >> + EDKII_USB_ETHERNET_UNDI_MCAST_IPTOMAC >> UsbEthUndiMcastIp2Mac; >> + EDKII_USB_ETHERNET_UNDI_NV_DATA UsbEthUndiNvData; >> + EDKII_USB_ETHERNET_UNDI_GET_STATUS UsbEthUndiGetStatus; >> + EDKII_USB_ETHERNET_UNDI_FILL_HEADER UsbEthUndiFillHeader; >> + EDKII_USB_ETHERNET_UNDI_TRANSMIT UsbEthUndiTransmit; >> + EDKII_USB_ETHERNET_UNDI_RECEIVE UsbEthUndiReceive; >> +} EDKII_USB_ETHERNET_UNDI; >> + >> +// The EDKII_USB_ETHERNET_PROTOCOL provides some basic USB >> Ethernet device relevant >> +// descriptor and specific requests. >> +struct _EDKII_USB_ETHERNET_PROTOCOL { >> + EDKII_USB_ETHERNET_UNDI UsbEthUndi; >> + // for calling the UNDI child functions >> + EDKII_USB_ETHERNET_INITIALIZE UsbEthInitialize; >> + EDKII_USB_ETHERNET_STATISTICS UsbEthStatistics; >> + EDKII_USB_ETHERNET_RECEIVE UsbEthReceive; >> + EDKII_USB_ETHERNET_TRANSMIT UsbEthTransmit; >> + EDKII_USB_ETHERNET_INTERRUPT UsbEthInterrupt; >> + EDKII_USB_GET_ETH_MAC_ADDRESS UsbEthMacAddress; >> + EDKII_USB_ETH_MAX_BULK_SIZE UsbEthMaxBulkSize; >> + EDKII_USB_HEADER_FUNCTIONAL_DESCRIPTOR >> UsbHeaderFunDescriptor; >> + EDKII_USB_UNION_FUNCTIONAL_DESCRIPTOR >> UsbUnionFunDescriptor; >> + EDKII_USB_ETHERNET_FUNCTIONAL_DESCRIPTOR >> UsbEthFunDescriptor; >> + EDKII_USB_ETHERNET_SET_ETH_MULTICAST_FILTERS >> SetUsbEthMcastFilter; >> + EDKII_USB_ETHERNET_SET_ETH_POWER_MANAGE_PATTERN_FILTER >> SetUsbEthPowerPatternFilter; >> + EDKII_USB_ETHERNET_GET_ETH_POWER_MANAGE_PATTERN_FILTER >> GetUsbEthPowerPatternFilter; >> + EDKII_USB_ETHERNET_SET_ETH_PACKET_FILTER >> SetUsbEthPacketFilter; >> + EDKII_USB_ETHERNET_GET_ETH_STATISTIC >> GetUsbEthStatistic; >> +}; >> + >> +extern EFI_GUID gEdkIIUsbEthProtocolGuid; >> + >> +#endif >> diff --git a/MdeModulePkg/MdeModulePkg.dec >> b/MdeModulePkg/MdeModulePkg.dec >> index 3eb4a79bf7..860eec0f3c 100644 >> --- a/MdeModulePkg/MdeModulePkg.dec >> +++ b/MdeModulePkg/MdeModulePkg.dec >> @@ -685,6 +685,9 @@ >> ## Include/Protocol/VariablePolicy.h >> gEdkiiVariablePolicyProtocolGuid = { 0x81D1675C, 0x86F6, 0x48DF, { 0xBD, >> 0x95, 0x9A, 0x6E, 0x4F, 0x09, 0x25, 0xC3 } } >> >> + ## Include/Protocol/UsbEthernetProtocol.h >> + gEdkIIUsbEthProtocolGuid = { 0x8d8969cc, 0xfeb0, 0x4303, { 0xb2, 0x1a, >> 0x1f, 0x11, 0x6f, 0x38, 0x56, 0x43 } } >> + >> [PcdsFeatureFlag] >> ## Indicates if the platform can support update capsule across a system >> reset.

>> # TRUE - Supports update capsule across a system reset.
>> @@ -2108,6 +2111,21 @@ >> # @Prompt The shared bit mask when Intel Tdx is enabled. >> >> gEfiMdeModulePkgTokenSpaceGuid.PcdTdxSharedBitMask|0x0|UINT64|0x1 >> 0000025 >> >> + ## Indicates if the Usb Network rate limiting Supported.

>> + # TRUE - Usb Network rate limiting is supported.
>> + # FALSE - Usb Network rate limiting is not supported.
>> + # @Prompt Enable Usb Network rate limiting support. >> + >> gEfiMdeModulePkgTokenSpaceGuid.PcdEnableUsbNetworkRateLimiting|FAL >> SE|BOOLEAN|0x10000026 >> + >> + ## The rate limiting Credit value is check in rate limiter event. >> + # It is to control the RateLimitingCreditCount max value. >> + # @Prompt The value is use for Usb Network rate limiting supported. >> + >> gEfiMdeModulePkgTokenSpaceGuid.PcdUsbNetworkRateLimitingCredit|10| >> UINT32|0x10000027 >> + >> + ## The value of rate limiter event for timeout check. Default value is >> 100(unit 1ms). >> + # @Prompt The value is use for Usb Network rate limiting supported. >> + >> gEfiMdeModulePkgTokenSpaceGuid.PcdUsbNetworkRateLimitingFactor|100 >> |UINT32|0x10000028 >> + >> [PcdsPatchableInModule] >> ## Specify memory size with page number for PEI code when >> # Loading Module at Fixed Address feature is enabled. >> diff --git a/MdeModulePkg/MdeModulePkg.dsc >> b/MdeModulePkg/MdeModulePkg.dsc >> index 1014598f31..0aadd405f3 100644 >> --- a/MdeModulePkg/MdeModulePkg.dsc >> +++ b/MdeModulePkg/MdeModulePkg.dsc >> @@ -274,6 +274,10 @@ >> MdeModulePkg/Bus/Usb/UsbMassStorageDxe/UsbMassStorageDxe.inf >> >> MdeModulePkg/Bus/Usb/UsbMouseAbsolutePointerDxe/UsbMouseAbsolute >> PointerDxe.inf >> MdeModulePkg/Bus/Usb/UsbMouseDxe/UsbMouseDxe.inf >> + >> MdeModulePkg/Bus/Usb/UsbNetwork/NetworkCommon/NetworkCommon. >> inf >> + MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcEcm/UsbCdcEcm.inf >> + MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcNcm/UsbCdcNcm.inf >> + MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis/UsbRndis.inf >> MdeModulePkg/Bus/I2c/I2cDxe/I2cBusDxe.inf >> MdeModulePkg/Bus/I2c/I2cDxe/I2cHostDxe.inf >> MdeModulePkg/Bus/I2c/I2cDxe/I2cDxe.inf >> -- >> 2.35.1.windows.2 >> -The information contained in this message may be confidential and >> proprietary to American Megatrends (AMI). This communication is intended >> to be read only by the individual or entity to whom it is addressed or by their >> designee. If the reader of this message is not the intended recipient, you are >> on notice that any distribution of this message, in any form, is strictly >> prohibited. Please promptly notify the sender by reply e-mail or by telephone >> at 770-246-8600, and then delete or destroy all copies of the transmission. >> >> >> >> >> >> -The information contained in this message may be confidential and >> proprietary to American Megatrends (AMI). This communication is intended >> to be read only by the individual or entity to whom it is addressed or by their >> designee. If the reader of this message is not the intended recipient, you are >> on notice that any distribution of this message, in any form, is strictly >> prohibited. Please promptly notify the sender by reply e-mail or by telephone >> at 770-246-8600, and then delete or destroy all copies of the transmission.