MdeModulePkg/Bus/Usb/UsbNetwork/UsbRndis: Add USB RNDIS devices support

This driver provides UEFI driver for USB RNDIS device

Signed-off-by: Richard Ho <richardho@ami.com>
Cc: Andrew Fish <afish@apple.com>
Cc: Leif Lindholm <quic_llindhol@quicinc.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Michael Kubacki <mikuback@linux.microsoft.com>
Cc: Zhiguang Liu <zhiguang.liu@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Tested-by: Tinh Nguyen <tinhnguyen@os.amperecomputing.com>
Acked-by: Hao A Wu <hao.a.wu@intel.com>
Reviewed-by: Rebecca Cran <rebecca@bsdio.com>
Reviewed-by: Tony Lo <tonylo@ami.com>
This commit is contained in:
Richard Ho
2023-07-13 14:15:32 +08:00
committed by mergify[bot]
parent 8dab4eebe4
commit fc0d5922f1
13 changed files with 7286 additions and 0 deletions

View File

@@ -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.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "DriverBinding.h"
extern EFI_DRIVER_BINDING_PROTOCOL gNetworkCommonDriverBinding;
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE gNetworkCommonDriverNameTable[] = {
{
"eng;en",
L"Network Common Driver"
},
{
NULL,
NULL
}
};
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE *gNetworkCommonControllerNameTable = NULL;
EFI_STATUS
EFIAPI
NetworkCommonComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
);
EFI_STATUS
EFIAPI
NetworkCommonComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
);
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gNetworkCommonComponentName = {
NetworkCommonComponentNameGetDriverName,
NetworkCommonComponentNameGetControllerName,
"eng"
};
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gNetworkCommonComponentName2 = {
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME)NetworkCommonComponentNameGetDriverName,
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)NetworkCommonComponentNameGetControllerName,
"en"
};
/**
Retrieves a Unicode string that is the user readable name of the driver.
This function retrieves the user readable name of a driver in the form of a
Unicode string. If the driver specified by This has a user readable name in
the language specified by Language, then a pointer to the driver name is
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
by This does not support the language specified by Language,
then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified
in RFC 4646 or ISO 639-2 language code format.
@param[out] DriverName A pointer to the Unicode string to return.
This Unicode string is the name of the
driver specified by This in the language
specified by Language.
@retval EFI_SUCCESS The Unicode string for the Driver specified by
This and the language specified by Language was
returned in DriverName.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER DriverName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
NetworkCommonComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
{
return LookupUnicodeString2 (
Language,
This->SupportedLanguages,
gNetworkCommonDriverNameTable,
DriverName,
(BOOLEAN)(This == &gNetworkCommonComponentName)
);
}
/**
Retrieves a Unicode string that is the user readable name of the controller
that is being managed by a driver.
This function retrieves the user readable name of the controller specified by
ControllerHandle and ChildHandle in the form of a Unicode string. If the
driver specified by This has a user readable name in the language specified by
Language, then a pointer to the controller name is returned in ControllerName,
and EFI_SUCCESS is returned. If the driver specified by This is not currently
managing the controller specified by ControllerHandle and ChildHandle,
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
support the language specified by Language, then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] Controller The handle of a controller that the driver
specified by This is managing. This handle
specifies the controller whose name is to be
returned.
@param[in] ChildHandle The handle of the child controller to retrieve
the name of. This is an optional parameter that
may be NULL. It will be NULL for device
drivers. It will also be NULL for a bus drivers
that wish to retrieve the name of the bus
controller. It will not be NULL for a bus
driver that wishes to retrieve the name of a
child controller.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified in
RFC 4646 or ISO 639-2 language code format.
@param[out] ControllerName A pointer to the Unicode string to return.
This Unicode string is the name of the
controller specified by ControllerHandle and
ChildHandle in the language specified by
Language from the point of view of the driver
specified by This.
@retval EFI_SUCCESS The Unicode string for the user readable name in
the language specified by Language for the
driver specified by This was returned in
DriverName.
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
EFI_HANDLE.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
NetworkCommonComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
)
{
EFI_STATUS Status;
CHAR16 *HandleName;
EFI_USB_IO_PROTOCOL *UsbIo;
EFI_USB_DEVICE_DESCRIPTOR DevDesc;
if ((Language == NULL) || (ControllerName == NULL)) {
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;
}

View File

@@ -0,0 +1,595 @@
/** @file
This file contains code for USB network binding driver
Copyright (c) 2023, American Megatrends International LLC. All rights reserved.<BR>
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 == NULL) {
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;
}

View File

@@ -0,0 +1,266 @@
/** @file
Header file for for USB network common driver
Copyright (c) 2023, American Megatrends International LLC. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef DRIVER_BINDING_H_
#define DRIVER_BINDING_H_
#include <Library/UefiDriverEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/DevicePathLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PcdLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiUsbLib.h>
#include <Protocol/UsbIo.h>
#include <Protocol/NetworkInterfaceIdentifier.h>
#include <Protocol/UsbEthernetProtocol.h>
#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;
} ETHERNET_HEADER;
#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

View File

@@ -0,0 +1,48 @@
## @file
# This is Usb Network Common driver for DXE phase.
#
# Copyright (c) 2023, American Megatrends International LLC. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = NetworkCommon
FILE_GUID = ca6eb4f4-f1d6-4375-97d6-18856871e1bf
MODULE_TYPE = UEFI_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

File diff suppressed because it is too large Load Diff

View File

@@ -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.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "UsbRndis.h"
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE gUsbRndisDriverNameTable[] = {
{
"eng;en",
L"USB RNDIS Driver"
},
{
NULL,
NULL
}
};
EFI_STATUS
EFIAPI
UsbRndisComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
);
EFI_STATUS
EFIAPI
UsbRndisComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
);
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gUsbRndisComponentName = {
UsbRndisComponentNameGetDriverName,
UsbRndisComponentNameGetControllerName,
"eng"
};
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gUsbRndisComponentName2 = {
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME)UsbRndisComponentNameGetDriverName,
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)UsbRndisComponentNameGetControllerName,
"en"
};
/**
Retrieves a Unicode string that is the user readable name of the driver.
This function retrieves the user readable name of a driver in the form of a
Unicode string. If the driver specified by This has a user readable name in
the language specified by Language, then a pointer to the driver name is
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
by This does not support the language specified by Language,
then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified
in RFC 4646 or ISO 639-2 language code format.
@param[out] DriverName A pointer to the Unicode string to return.
This Unicode string is the name of the
driver specified by This in the language
specified by Language.
@retval EFI_SUCCESS The Unicode string for the Driver specified by
This and the language specified by Language was
returned in DriverName.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER DriverName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
UsbRndisComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
{
return LookupUnicodeString2 (
Language,
This->SupportedLanguages,
gUsbRndisDriverNameTable,
DriverName,
(BOOLEAN)(This == &gUsbRndisComponentName)
);
}
/**
Retrieves a Unicode string that is the user readable name of the controller
that is being managed by a driver.
This function retrieves the user readable name of the controller specified by
ControllerHandle and ChildHandle in the form of a Unicode string. If the
driver specified by This has a user readable name in the language specified by
Language, then a pointer to the controller name is returned in ControllerName,
and EFI_SUCCESS is returned. If the driver specified by This is not currently
managing the controller specified by ControllerHandle and ChildHandle,
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
support the language specified by Language, then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] Controller The handle of a controller that the driver
specified by This is managing. This handle
specifies the controller whose name is to be
returned.
@param[in] ChildHandle The handle of the child controller to retrieve
the name of. This is an optional parameter that
may be NULL. It will be NULL for device
drivers. It will also be NULL for a bus drivers
that wish to retrieve the name of the bus
controller. It will not be NULL for a bus
driver that wishes to retrieve the name of a
child controller.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified in
RFC 4646 or ISO 639-2 language code format.
@param[out] ControllerName A pointer to the Unicode string to return.
This Unicode string is the name of the
controller specified by ControllerHandle and
ChildHandle in the language specified by
Language from the point of view of the driver
specified by This.
@retval EFI_SUCCESS The Unicode string for the user readable name in
the language specified by Language for the
driver specified by This was returned in
DriverName.
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
EFI_HANDLE.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
UsbRndisComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
)
{
return EFI_UNSUPPORTED;
}

View File

@@ -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.<BR>
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] UsbCdcDataPath 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
);
}

View File

@@ -0,0 +1,586 @@
/** @file
Header file for for USB Rndis driver
Copyright (c) 2023, American Megatrends International LLC. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef USB_RNDIS_H_
#define USB_RNDIS_H_
#include <Library/UefiDriverEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/DevicePathLib.h>
#include <Library/DebugLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiUsbLib.h>
#include <Protocol/UsbIo.h>
#include <Protocol/UsbEthernetProtocol.h>
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;
typedef struct {
UINT16 Src;
UINT16 Dst;
} BIT_MAP;
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

View File

@@ -0,0 +1,42 @@
## @file
# This is Usb Rndis driver for DXE phase.
#
# Copyright (c) 2023, American Megatrends International LLC. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = UsbRndis
FILE_GUID = 11E32C34-60B5-4991-8DEA-63D3E8C876DE
MODULE_TYPE = UEFI_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

File diff suppressed because it is too large Load Diff