MdeModulePkg/Bus/Usb/UsbNetwork/UsbCdcEcm: Add USB Cdc ECM devices support

This driver provides UEFI driver for USB CDC ECM 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:18:44 +08:00 committed by mergify[bot]
parent fc0d5922f1
commit 5e400d22a0
5 changed files with 1805 additions and 0 deletions

View File

@ -0,0 +1,170 @@
/** @file
This file contains code for USB Ecm Driver Component Name definitions
Copyright (c) 2023, American Megatrends International LLC. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "UsbCdcEcm.h"
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE gUsbEcmDriverNameTable[] = {
{
"eng;en",
L"USB ECM Driver"
},
{
NULL,
NULL
}
};
EFI_STATUS
EFIAPI
UsbEcmComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
);
EFI_STATUS
EFIAPI
UsbEcmComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
);
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gUsbEcmComponentName = {
UsbEcmComponentNameGetDriverName,
UsbEcmComponentNameGetControllerName,
"eng"
};
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gUsbEcmComponentName2 = {
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME)UsbEcmComponentNameGetDriverName,
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)UsbEcmComponentNameGetControllerName,
"en"
};
/**
Retrieves a Unicode string that is the user readable name of the driver.
This function retrieves the user readable name of a driver in the form of a
Unicode string. If the driver specified by This has a user readable name in
the language specified by Language, then a pointer to the driver name is
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
by This does not support the language specified by Language,
then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified
in RFC 4646 or ISO 639-2 language code format.
@param[out] DriverName A pointer to the Unicode string to return.
This Unicode string is the name of the
driver specified by This in the language
specified by Language.
@retval EFI_SUCCESS The Unicode string for the Driver specified by
This and the language specified by Language was
returned in DriverName.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER DriverName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
UsbEcmComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
{
return LookupUnicodeString2 (
Language,
This->SupportedLanguages,
gUsbEcmDriverNameTable,
DriverName,
(BOOLEAN)(This == &gUsbEcmComponentName)
);
}
/**
Retrieves a Unicode string that is the user readable name of the controller
that is being managed by a driver.
This function retrieves the user readable name of the controller specified by
ControllerHandle and ChildHandle in the form of a Unicode string. If the
driver specified by This has a user readable name in the language specified by
Language, then a pointer to the controller name is returned in ControllerName,
and EFI_SUCCESS is returned. If the driver specified by This is not currently
managing the controller specified by ControllerHandle and ChildHandle,
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
support the language specified by Language, then EFI_UNSUPPORTED is returned.
@param[in] This A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
EFI_COMPONENT_NAME_PROTOCOL instance.
@param[in] Controller The handle of a controller that the driver
specified by This is managing. This handle
specifies the controller whose name is to be
returned.
@param[in] ChildHandle The handle of the child controller to retrieve
the name of. This is an optional parameter that
may be NULL. It will be NULL for device
drivers. It will also be NULL for a bus drivers
that wish to retrieve the name of the bus
controller. It will not be NULL for a bus
driver that wishes to retrieve the name of a
child controller.
@param[in] Language A pointer to a Null-terminated ASCII string
array indicating the language. This is the
language of the driver name that the caller is
requesting, and it must match one of the
languages specified in SupportedLanguages. The
number of languages supported by a driver is up
to the driver writer. Language is specified in
RFC 4646 or ISO 639-2 language code format.
@param[out] ControllerName A pointer to the Unicode string to return.
This Unicode string is the name of the
controller specified by ControllerHandle and
ChildHandle in the language specified by
Language from the point of view of the driver
specified by This.
@retval EFI_SUCCESS The Unicode string for the user readable name in
the language specified by Language for the
driver specified by This was returned in
DriverName.
@retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE.
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
EFI_HANDLE.
@retval EFI_INVALID_PARAMETER Language is NULL.
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
@retval EFI_UNSUPPORTED The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
@retval EFI_UNSUPPORTED The driver specified by This does not support
the language specified by Language.
**/
EFI_STATUS
EFIAPI
UsbEcmComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE Controller,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
)
{
return EFI_UNSUPPORTED;
}

View File

@ -0,0 +1,502 @@
/** @file
This file contains code for USB Ethernet Control Model
Driver
Copyright (c) 2023, American Megatrends International LLC. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "UsbCdcEcm.h"
EFI_DRIVER_BINDING_PROTOCOL gUsbEcmDriverBinding = {
UsbEcmDriverSupported,
UsbEcmDriverStart,
UsbEcmDriverStop,
USB_ECM_DRIVER_VERSION,
NULL,
NULL
};
/**
Check if this interface is USB ECM SubType
@param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance.
@retval TRUE USB ECM SubType.
@retval FALSE Not USB ECM SubType.
**/
BOOLEAN
IsSupportedDevice (
IN EFI_USB_IO_PROTOCOL *UsbIo
)
{
EFI_STATUS Status;
EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &InterfaceDescriptor);
if (EFI_ERROR (Status)) {
return FALSE;
}
if ((InterfaceDescriptor.InterfaceClass == USB_CDC_CLASS) &&
(InterfaceDescriptor.InterfaceSubClass == USB_CDC_ECM_SUBCLASS) &&
(InterfaceDescriptor.InterfaceProtocol == USB_NO_CLASS_PROTOCOL))
{
return TRUE;
}
return FALSE;
}
/**
USB ECM Driver Binding Support.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of device to test.
@param[in] RemainingDevicePath Optional parameter use to pick a specific child
device to start.
@retval EFI_SUCCESS This driver supports this device.
@retval EFI_ALREADY_STARTED This driver is already running on this device.
@retval other This driver does not support this device.
**/
EFI_STATUS
EFIAPI
UsbEcmDriverSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
{
EFI_STATUS Status;
EFI_USB_IO_PROTOCOL *UsbIo;
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiUsbIoProtocolGuid,
(VOID **)&UsbIo,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = IsSupportedDevice (UsbIo) ? EFI_SUCCESS : EFI_UNSUPPORTED;
gBS->CloseProtocol (
ControllerHandle,
&gEfiUsbIoProtocolGuid,
This->DriverBindingHandle,
ControllerHandle
);
return Status;
}
/**
Check if the USB ECM and USB CDC Data interfaces are from the same device.
@param[in] UsbEthPath A pointer to the EFI_DEVICE_PATH_PROTOCOL instance.
@param[in] UsbCdcDataPath A pointer to the EFI_DEVICE_PATH_PROTOCOL instance.
@retval EFI_SUCCESS Is the same device.
@retval EFI_NOT_FOUND Is not the same device.
**/
EFI_STATUS
IsSameDevice (
IN EFI_DEVICE_PATH_PROTOCOL *UsbEthPath,
IN EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath
)
{
while (1) {
if ((UsbEthPath->Type == ACPI_DEVICE_PATH) && (UsbEthPath->SubType == ACPI_DP)) {
if (CompareMem ((ACPI_HID_DEVICE_PATH *)UsbCdcDataPath, (ACPI_HID_DEVICE_PATH *)UsbEthPath, sizeof (ACPI_HID_DEVICE_PATH))) {
return EFI_NOT_FOUND;
}
}
if ((UsbEthPath->Type == HARDWARE_DEVICE_PATH) && (UsbEthPath->SubType == HW_PCI_DP)) {
if (CompareMem ((PCI_DEVICE_PATH *)UsbCdcDataPath, (PCI_DEVICE_PATH *)UsbEthPath, sizeof (PCI_DEVICE_PATH))) {
return EFI_NOT_FOUND;
}
}
if ((UsbEthPath->Type == MESSAGING_DEVICE_PATH) && (UsbEthPath->SubType == MSG_USB_DP)) {
if (IsDevicePathEnd (NextDevicePathNode (UsbEthPath))) {
if (((USB_DEVICE_PATH *)UsbEthPath)->ParentPortNumber ==
((USB_DEVICE_PATH *)UsbCdcDataPath)->ParentPortNumber)
{
return EFI_SUCCESS;
} else {
return EFI_NOT_FOUND;
}
} else {
if (CompareMem ((USB_DEVICE_PATH *)UsbCdcDataPath, (USB_DEVICE_PATH *)UsbEthPath, sizeof (USB_DEVICE_PATH))) {
return EFI_NOT_FOUND;
}
}
}
UsbEthPath = NextDevicePathNode (UsbEthPath);
UsbCdcDataPath = NextDevicePathNode (UsbCdcDataPath);
}
}
/**
Check if the USB CDC Data(UsbIo) installed and return USB CDC Data Handle.
@param[in] UsbEthPath A pointer to the EFI_DEVICE_PATH_PROTOCOL instance.
@param[in, out] UsbCdcDataHandle A pointer to the EFI_HANDLE for USB CDC Data.
@retval TRUE USB CDC Data(UsbIo) installed.
@retval FALSE USB CDC Data(UsbIo) did not installed.
**/
BOOLEAN
IsUsbCdcData (
IN EFI_DEVICE_PATH_PROTOCOL *UsbEthPath,
IN OUT EFI_HANDLE *UsbCdcDataHandle
)
{
EFI_STATUS Status;
UINTN Index;
UINTN HandleCount;
EFI_HANDLE *HandleBuffer;
EFI_USB_IO_PROTOCOL *UsbIo;
EFI_USB_INTERFACE_DESCRIPTOR Interface;
EFI_DEVICE_PATH_PROTOCOL *UsbCdcDataPath;
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiUsbIoProtocolGuid,
NULL,
&HandleCount,
&HandleBuffer
);
if (EFI_ERROR (Status)) {
return FALSE;
}
for (Index = 0; Index < HandleCount; Index++) {
Status = gBS->HandleProtocol (
HandleBuffer[Index],
&gEfiUsbIoProtocolGuid,
(VOID **)&UsbIo
);
ASSERT_EFI_ERROR (Status);
Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
ASSERT_EFI_ERROR (Status);
if ((Interface.InterfaceClass == USB_CDC_DATA_CLASS) &&
(Interface.InterfaceSubClass == USB_CDC_DATA_SUBCLASS) &&
(Interface.InterfaceProtocol == USB_NO_CLASS_PROTOCOL))
{
Status = gBS->HandleProtocol (
HandleBuffer[Index],
&gEfiDevicePathProtocolGuid,
(VOID **)&UsbCdcDataPath
);
if (EFI_ERROR (Status)) {
continue;
}
Status = IsSameDevice (UsbEthPath, UsbCdcDataPath);
if (!EFI_ERROR (Status)) {
CopyMem (UsbCdcDataHandle, &HandleBuffer[Index], sizeof (EFI_HANDLE));
FreePool (HandleBuffer);
return TRUE;
}
}
}
FreePool (HandleBuffer);
return FALSE;
}
/**
Call Back Function.
@param[in] Event Event whose notification function is being invoked.
@param[in] Context The pointer to the notification function's context,
which is implementation-dependent.
**/
VOID
EFIAPI
CallbackFunction (
IN EFI_EVENT Event,
IN VOID *Context
)
{
EFI_STATUS Status;
UINTN Index;
UINTN HandleCount;
EFI_HANDLE *HandleBuffer;
EFI_USB_IO_PROTOCOL *UsbIo;
EFI_USB_INTERFACE_DESCRIPTOR Interface;
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiUsbIoProtocolGuid,
NULL,
&HandleCount,
&HandleBuffer
);
if (EFI_ERROR (Status)) {
return;
}
for (Index = 0; Index < HandleCount; Index++) {
Status = gBS->HandleProtocol (
HandleBuffer[Index],
&gEfiUsbIoProtocolGuid,
(VOID **)&UsbIo
);
ASSERT_EFI_ERROR (Status);
Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
ASSERT_EFI_ERROR (Status);
if ((Interface.InterfaceClass == USB_CDC_CLASS) &&
(Interface.InterfaceSubClass == USB_CDC_ECM_SUBCLASS) &&
(Interface.InterfaceProtocol == USB_NO_CLASS_PROTOCOL))
{
gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
}
}
FreePool (HandleBuffer);
gBS->CloseEvent (Event);
}
/**
USB ECM Driver Binding Start.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of device to bind driver to.
@param[in] RemainingDevicePath Optional parameter use to pick a specific child
device to start.
@retval EFI_SUCCESS This driver is added to ControllerHandle
@retval EFI_DEVICE_ERROR This driver could not be started due to a device error
@retval EFI_OUT_OF_RESOURCES The driver could not install successfully due to a lack of resources.
@retval other This driver does not support this device
**/
EFI_STATUS
EFIAPI
UsbEcmDriverStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
)
{
EFI_STATUS Status;
VOID *Reg;
EFI_EVENT Event;
USB_ETHERNET_DRIVER *UsbEthDriver;
EFI_DEVICE_PATH_PROTOCOL *UsbEthPath;
EFI_HANDLE UsbCdcDataHandle;
EFI_USB_IO_PROTOCOL *UsbIo;
EFI_USB_INTERFACE_DESCRIPTOR Interface;
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiUsbIoProtocolGuid,
(VOID **)&UsbIo,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiDevicePathProtocolGuid,
(VOID **)&UsbEthPath,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
gBS->CloseProtocol (
ControllerHandle,
&gEfiUsbIoProtocolGuid,
This->DriverBindingHandle,
ControllerHandle
);
return Status;
}
Status = IsUsbCdcData (UsbEthPath, &UsbCdcDataHandle) ? EFI_SUCCESS : EFI_UNSUPPORTED;
if (EFI_ERROR (Status)) {
gBS->CloseProtocol (
ControllerHandle,
&gEfiUsbIoProtocolGuid,
This->DriverBindingHandle,
ControllerHandle
);
Status = gBS->CreateEvent (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, CallbackFunction, NULL, &Event);
if (EFI_ERROR (Status)) {
return Status;
}
Status = gBS->RegisterProtocolNotify (&gEfiUsbIoProtocolGuid, Event, &Reg);
return Status;
}
UsbEthDriver = AllocateZeroPool (sizeof (USB_ETHERNET_DRIVER));
if (!UsbEthDriver) {
gBS->CloseProtocol (
ControllerHandle,
&gEfiUsbIoProtocolGuid,
This->DriverBindingHandle,
ControllerHandle
);
return EFI_OUT_OF_RESOURCES;
}
Status = LoadAllDescriptor (UsbIo, &UsbEthDriver->Config);
ASSERT_EFI_ERROR (Status);
GetEndpoint (UsbIo, UsbEthDriver);
Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
ASSERT_EFI_ERROR (Status);
UsbEthDriver->Signature = USB_ETHERNET_SIGNATURE;
UsbEthDriver->NumOfInterface = Interface.InterfaceNumber;
UsbEthDriver->UsbCdcDataHandle = UsbCdcDataHandle;
UsbEthDriver->UsbIo = UsbIo;
UsbEthDriver->UsbEth.UsbEthReceive = UsbEthEcmReceive;
UsbEthDriver->UsbEth.UsbEthTransmit = UsbEthEcmTransmit;
UsbEthDriver->UsbEth.UsbEthInterrupt = UsbEthEcmInterrupt;
UsbEthDriver->UsbEth.UsbEthMacAddress = GetUsbEthMacAddress;
UsbEthDriver->UsbEth.UsbEthMaxBulkSize = UsbEthEcmBulkSize;
UsbEthDriver->UsbEth.UsbHeaderFunDescriptor = GetUsbHeaderFunDescriptor;
UsbEthDriver->UsbEth.UsbUnionFunDescriptor = GetUsbUnionFunDescriptor;
UsbEthDriver->UsbEth.UsbEthFunDescriptor = GetUsbEthFunDescriptor;
UsbEthDriver->UsbEth.SetUsbEthMcastFilter = SetUsbEthMcastFilter;
UsbEthDriver->UsbEth.SetUsbEthPowerPatternFilter = SetUsbEthPowerFilter;
UsbEthDriver->UsbEth.GetUsbEthPowerPatternFilter = GetUsbEthPowerFilter;
UsbEthDriver->UsbEth.SetUsbEthPacketFilter = SetUsbEthPacketFilter;
UsbEthDriver->UsbEth.GetUsbEthStatistic = GetUsbEthStatistic;
Status = gBS->InstallProtocolInterface (
&ControllerHandle,
&gEdkIIUsbEthProtocolGuid,
EFI_NATIVE_INTERFACE,
&(UsbEthDriver->UsbEth)
);
if (EFI_ERROR (Status)) {
gBS->CloseProtocol (
ControllerHandle,
&gEfiUsbIoProtocolGuid,
This->DriverBindingHandle,
ControllerHandle
);
FreePool (UsbEthDriver);
return Status;
}
return Status;
}
/**
USB ECM Driver Binding Stop.
@param[in] This Protocol instance pointer.
@param[in] ControllerHandle Handle of device to stop driver on
@param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
children is zero stop the entire bus driver.
@param[in] ChildHandleBuffer List of Child Handles to Stop.
@retval EFI_SUCCESS This driver is removed ControllerHandle
@retval other This driver was not removed from this device
**/
EFI_STATUS
EFIAPI
UsbEcmDriverStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
)
{
EFI_STATUS Status;
EDKII_USB_ETHERNET_PROTOCOL *UsbEthProtocol;
USB_ETHERNET_DRIVER *UsbEthDriver;
Status = gBS->OpenProtocol (
ControllerHandle,
&gEdkIIUsbEthProtocolGuid,
(VOID **)&UsbEthProtocol,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return Status;
}
UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (UsbEthProtocol);
Status = gBS->UninstallProtocolInterface (
ControllerHandle,
&gEdkIIUsbEthProtocolGuid,
UsbEthProtocol
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = gBS->CloseProtocol (
ControllerHandle,
&gEfiUsbIoProtocolGuid,
This->DriverBindingHandle,
ControllerHandle
);
FreePool (UsbEthDriver->Config);
FreePool (UsbEthDriver);
return Status;
}
/**
Entrypoint of ECM Driver.
This function is the entrypoint of ECM Driver. It installs Driver Binding
Protocols together with Component Name Protocols.
@param[in] ImageHandle The firmware allocated handle for the EFI image.
@param[in] SystemTable A pointer to the EFI System Table.
@retval EFI_SUCCESS The entry point is executed successfully.
**/
EFI_STATUS
EFIAPI
UsbEcmEntry (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
gUsbEcmDriverBinding.DriverBindingHandle = ImageHandle;
gUsbEcmDriverBinding.ImageHandle = ImageHandle;
return gBS->InstallMultipleProtocolInterfaces (
&gUsbEcmDriverBinding.DriverBindingHandle,
&gEfiDriverBindingProtocolGuid,
&gUsbEcmDriverBinding,
&gEfiComponentName2ProtocolGuid,
&gUsbEcmComponentName2,
NULL
);
}

View File

@ -0,0 +1,211 @@
/** @file
Header file contains code for USB Ethernet Control Model
driver definitions
Copyright (c) 2023, American Megatrends International LLC. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef USB_CDC_ECM_H_
#define USB_CDC_ECM_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 {
UINTN Signature;
EDKII_USB_ETHERNET_PROTOCOL UsbEth;
EFI_HANDLE UsbCdcDataHandle;
EFI_USB_IO_PROTOCOL *UsbIo;
EFI_USB_CONFIG_DESCRIPTOR *Config;
UINT8 NumOfInterface;
UINT8 BulkInEndpoint;
UINT8 BulkOutEndpoint;
UINT8 InterruptEndpoint;
EFI_MAC_ADDRESS MacAddress;
} USB_ETHERNET_DRIVER;
#define USB_ECM_DRIVER_VERSION 1
#define USB_ETHERNET_BULK_TIMEOUT 1
#define USB_ETHERNET_TRANSFER_TIMEOUT 200
#define USB_ETHERNET_SIGNATURE SIGNATURE_32('u', 'e', 't', 'h')
#define USB_ETHERNET_DEV_FROM_THIS(a) CR (a, USB_ETHERNET_DRIVER, UsbEth, USB_ETHERNET_SIGNATURE)
typedef struct {
UINT16 Src;
UINT16 Dst;
} BIT_MAP;
extern EFI_COMPONENT_NAME2_PROTOCOL gUsbEcmComponentName2;
EFI_STATUS
EFIAPI
UsbEcmDriverSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
);
EFI_STATUS
EFIAPI
UsbEcmDriverStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
);
EFI_STATUS
EFIAPI
UsbEcmDriverStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
);
EFI_STATUS
LoadAllDescriptor (
IN EFI_USB_IO_PROTOCOL *UsbIo,
OUT EFI_USB_CONFIG_DESCRIPTOR **ConfigDesc
);
BOOLEAN
NextDescriptor (
IN EFI_USB_CONFIG_DESCRIPTOR *Desc,
IN OUT UINTN *Offset
);
EFI_STATUS
GetFunctionalDescriptor (
IN EFI_USB_CONFIG_DESCRIPTOR *Config,
IN UINT8 FunDescriptorType,
OUT VOID *DataBuffer
);
VOID
GetEndpoint (
IN EFI_USB_IO_PROTOCOL *UsbIo,
IN OUT USB_ETHERNET_DRIVER *UsbEthDriver
);
EFI_STATUS
EFIAPI
UsbEthEcmReceive (
IN PXE_CDB *Cdb,
IN EDKII_USB_ETHERNET_PROTOCOL *This,
IN OUT VOID *Packet,
IN OUT UINTN *PacketLength
);
EFI_STATUS
EFIAPI
UsbEthEcmTransmit (
IN PXE_CDB *Cdb,
IN EDKII_USB_ETHERNET_PROTOCOL *This,
IN VOID *Packet,
IN OUT UINTN *PacketLength
);
EFI_STATUS
EFIAPI
UsbEthEcmInterrupt (
IN EDKII_USB_ETHERNET_PROTOCOL *This,
IN BOOLEAN IsNewTransfer,
IN UINTN PollingInterval,
IN EFI_USB_DEVICE_REQUEST *Request
);
EFI_STATUS
EFIAPI
InterruptCallback (
IN VOID *Data,
IN UINTN DataLength,
IN VOID *Context,
IN UINT32 Status
);
EFI_STATUS
EFIAPI
GetUsbEthMacAddress (
IN EDKII_USB_ETHERNET_PROTOCOL *This,
OUT EFI_MAC_ADDRESS *MacAddress
);
EFI_STATUS
EFIAPI
UsbEthEcmBulkSize (
IN EDKII_USB_ETHERNET_PROTOCOL *This,
OUT UINTN *BulkSize
);
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
GetUsbEthFunDescriptor (
IN EDKII_USB_ETHERNET_PROTOCOL *This,
OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor
);
EFI_STATUS
EFIAPI
SetUsbEthMcastFilter (
IN EDKII_USB_ETHERNET_PROTOCOL *This,
IN UINT16 Value,
IN VOID *McastAddr
);
EFI_STATUS
EFIAPI
SetUsbEthPowerFilter (
IN EDKII_USB_ETHERNET_PROTOCOL *This,
IN UINT16 Value,
IN UINT16 Length,
IN VOID *PatternFilter
);
EFI_STATUS
EFIAPI
GetUsbEthPowerFilter (
IN EDKII_USB_ETHERNET_PROTOCOL *This,
IN UINT16 Value,
OUT BOOLEAN *PatternActive
);
EFI_STATUS
EFIAPI
SetUsbEthPacketFilter (
IN EDKII_USB_ETHERNET_PROTOCOL *This,
IN UINT16 Value
);
EFI_STATUS
EFIAPI
GetUsbEthStatistic (
IN EDKII_USB_ETHERNET_PROTOCOL *This,
IN UINT16 FeatureSelector,
OUT VOID *Statistic
);
#endif

View File

@ -0,0 +1,42 @@
## @file
# This is Usb Cdc Ecm 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 = UsbCdcEcm
FILE_GUID = 07a84945-685d-48ec-a6a1-1b397579fa76
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = UsbEcmEntry
[Sources]
UsbCdcEcm.c
UsbCdcEcm.h
UsbEcmFunction.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

View File

@ -0,0 +1,880 @@
/** @file
This file contains code for USB Ethernet descriptor
and specific requests implement.
Copyright (c) 2023, American Megatrends International LLC. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "UsbCdcEcm.h"
/**
Load All of device descriptor.
@param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance.
@param[out] ConfigDesc A pointer to the configuration descriptor.
@retval EFI_SUCCESS The request executed successfully.
@retval EFI_OUT_OF_RESOURCES The request could not be completed because the
buffer specified by DescriptorLength and Descriptor
is not large enough to hold the result of the request.
@retval EFI_TIMEOUT A timeout occurred executing the request.
@retval EFI_DEVICE_ERROR The request failed due to a device error. The transfer
status is returned in Status.
**/
EFI_STATUS
LoadAllDescriptor (
IN EFI_USB_IO_PROTOCOL *UsbIo,
OUT EFI_USB_CONFIG_DESCRIPTOR **ConfigDesc
)
{
EFI_STATUS Status;
UINT32 TransStatus;
EFI_USB_CONFIG_DESCRIPTOR Tmp;
Status = UsbIo->UsbGetConfigDescriptor (UsbIo, &Tmp);
ASSERT_EFI_ERROR (Status);
Status = gBS->AllocatePool (EfiBootServicesData, Tmp.TotalLength, (VOID **)ConfigDesc);
ASSERT_EFI_ERROR (Status);
Status = UsbGetDescriptor (
UsbIo,
USB_DESC_TYPE_CONFIG << 8 | (Tmp.ConfigurationValue - 1), // zero based
0,
Tmp.TotalLength,
*ConfigDesc,
&TransStatus
);
return Status;
}
/**
Returns pointer to the next descriptor for the pack of USB descriptors
located in continues memory segment
@param[in] Desc A pointer to the CONFIG_DESCRIPTOR instance.
@param[in, out] Offset A pointer to the sum of descriptor length.
@retval TRUE The request executed successfully.
@retval FALSE No next descriptor.
**/
BOOLEAN
NextDescriptor (
IN EFI_USB_CONFIG_DESCRIPTOR *Desc,
IN OUT UINTN *Offset
)
{
if ((Desc == NULL) || (*Offset >= Desc->TotalLength)) {
return FALSE;
}
if (((EFI_USB_CONFIG_DESCRIPTOR *)((char *)Desc+*Offset))->Length == 0) {
return FALSE;
}
*Offset += ((EFI_USB_CONFIG_DESCRIPTOR *)((char *)Desc+*Offset))->Length;
if ( *Offset >= Desc->TotalLength ) {
return FALSE;
}
return TRUE;
}
/**
Read Function descriptor
@param[in] Config A pointer to all of configuration.
@param[in] FunDescriptorType USB CDC class descriptor SubType.
@param[out] DataBuffer A pointer to the Data of corresponding to device capability.
@retval EFI_SUCCESS The device capability descriptor was retrieved
successfully.
@retval EFI_UNSUPPORTED No supported.
@retval EFI_NOT_FOUND The device capability descriptor was not found.
**/
EFI_STATUS
GetFunctionalDescriptor (
IN EFI_USB_CONFIG_DESCRIPTOR *Config,
IN UINT8 FunDescriptorType,
OUT VOID *DataBuffer
)
{
EFI_STATUS Status;
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] UsbEthDriver A pointer to the USB_ETHERNET_DRIVER instance.
**/
VOID
GetEndpoint (
IN EFI_USB_IO_PROTOCOL *UsbIo,
IN OUT USB_ETHERNET_DRIVER *UsbEthDriver
)
{
EFI_STATUS Status;
UINT8 Index;
UINT32 Result;
EFI_USB_INTERFACE_DESCRIPTOR Interface;
EFI_USB_ENDPOINT_DESCRIPTOR Endpoint;
Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
ASSERT_EFI_ERROR (Status);
if (Interface.NumEndpoints == 0) {
Status = UsbSetInterface (UsbIo, Interface.InterfaceNumber, 1, &Result);
ASSERT_EFI_ERROR (Status);
Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &Interface);
ASSERT_EFI_ERROR (Status);
}
for (Index = 0; Index < Interface.NumEndpoints; Index++) {
Status = UsbIo->UsbGetEndpointDescriptor (UsbIo, Index, &Endpoint);
ASSERT_EFI_ERROR (Status);
switch ((Endpoint.Attributes & (BIT0 | BIT1))) {
case USB_ENDPOINT_BULK:
if (Endpoint.EndpointAddress & BIT7) {
UsbEthDriver->BulkInEndpoint = Endpoint.EndpointAddress;
} else {
UsbEthDriver->BulkOutEndpoint = Endpoint.EndpointAddress;
}
break;
case USB_ENDPOINT_INTERRUPT:
UsbEthDriver->InterruptEndpoint = Endpoint.EndpointAddress;
break;
}
}
}
/**
This function is used to manage a USB device with the bulk transfer pipe. The endpoint is Bulk in.
@param[in] Cdb A pointer to the command descriptor block.
@param[in] This A pointer to the 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.
**/
EFI_STATUS
EFIAPI
UsbEthEcmReceive (
IN PXE_CDB *Cdb,
IN EDKII_USB_ETHERNET_PROTOCOL *This,
IN OUT VOID *Packet,
IN OUT UINTN *PacketLength
)
{
EFI_STATUS Status;
USB_ETHERNET_DRIVER *UsbEthDriver;
EFI_USB_IO_PROTOCOL *UsbIo;
UINT32 TransStatus;
UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
Status = gBS->HandleProtocol (
UsbEthDriver->UsbCdcDataHandle,
&gEfiUsbIoProtocolGuid,
(VOID **)&UsbIo
);
if (EFI_ERROR (Status)) {
return Status;
}
if (UsbEthDriver->BulkInEndpoint == 0) {
GetEndpoint (UsbIo, UsbEthDriver);
}
Status = UsbIo->UsbBulkTransfer (
UsbIo,
UsbEthDriver->BulkInEndpoint,
Packet,
PacketLength,
USB_ETHERNET_BULK_TIMEOUT,
&TransStatus
);
return Status;
}
/**
This function is used to manage a USB device with the bulk transfer pipe. The endpoint is Bulk out.
@param[in] Cdb A pointer to the command descriptor block.
@param[in] This A pointer to the EDKII_USB_ETHERNET_PROTOCOL instance.
@param[in] Packet A pointer to the buffer of data that will be transmitted to USB
device or received from USB device.
@param[in, out] PacketLength A pointer to the PacketLength.
@retval EFI_SUCCESS The bulk transfer has been successfully executed.
@retval EFI_DEVICE_ERROR The transfer failed. The transfer status is returned in status.
@retval EFI_INVALID_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.
**/
EFI_STATUS
EFIAPI
UsbEthEcmTransmit (
IN PXE_CDB *Cdb,
IN EDKII_USB_ETHERNET_PROTOCOL *This,
IN VOID *Packet,
IN OUT UINTN *PacketLength
)
{
EFI_STATUS Status;
USB_ETHERNET_DRIVER *UsbEthDriver;
EFI_USB_IO_PROTOCOL *UsbIo;
UINT32 TransStatus;
UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
Status = gBS->HandleProtocol (
UsbEthDriver->UsbCdcDataHandle,
&gEfiUsbIoProtocolGuid,
(VOID **)&UsbIo
);
if (EFI_ERROR (Status)) {
return Status;
}
if (UsbEthDriver->BulkOutEndpoint == 0) {
GetEndpoint (UsbIo, UsbEthDriver);
}
Status = UsbIo->UsbBulkTransfer (
UsbIo,
UsbEthDriver->BulkOutEndpoint,
Packet,
PacketLength,
USB_ETHERNET_BULK_TIMEOUT,
&TransStatus
);
return Status;
}
/**
Async USB transfer callback routine.
@param[in] Data Data received or sent via the USB Asynchronous Transfer, if the
transfer completed successfully.
@param[in] DataLength The length of Data received or sent via the Asynchronous
Transfer, if transfer successfully completes.
@param[in] Context Data passed from UsbAsyncInterruptTransfer() request.
@param[in] Status Indicates the result of the asynchronous transfer.
@retval EFI_SUCCESS The asynchronous USB transfer request has been successfully executed.
@retval EFI_DEVICE_ERROR The asynchronous USB transfer request failed.
**/
EFI_STATUS
EFIAPI
InterruptCallback (
IN VOID *Data,
IN UINTN DataLength,
IN VOID *Context,
IN UINT32 Status
)
{
if ((Data == NULL) || (Context == NULL)) {
return EFI_INVALID_PARAMETER;
}
if (((EFI_USB_DEVICE_REQUEST *)Data)->Request == USB_CDC_NETWORK_CONNECTION) {
CopyMem (
(EFI_USB_DEVICE_REQUEST *)Context,
(EFI_USB_DEVICE_REQUEST *)Data,
sizeof (EFI_USB_DEVICE_REQUEST)
);
}
return EFI_SUCCESS;
}
/**
This function is used to manage a USB device with an interrupt transfer pipe.
@param[in] This A pointer to the 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
UsbEthEcmInterrupt (
IN EDKII_USB_ETHERNET_PROTOCOL *This,
IN BOOLEAN IsNewTransfer,
IN UINTN PollingInterval,
IN EFI_USB_DEVICE_REQUEST *Request
)
{
EFI_STATUS Status;
USB_ETHERNET_DRIVER *UsbEthDriver;
UINTN DataLength;
UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
DataLength = 0;
if (IsNewTransfer) {
DataLength = sizeof (EFI_USB_DEVICE_REQUEST) + sizeof (USB_CONNECT_SPEED_CHANGE);
Status = UsbEthDriver->UsbIo->UsbAsyncInterruptTransfer (
UsbEthDriver->UsbIo,
UsbEthDriver->InterruptEndpoint,
IsNewTransfer,
PollingInterval,
DataLength,
(EFI_ASYNC_USB_TRANSFER_CALLBACK)InterruptCallback,
Request
);
} else {
Status = UsbEthDriver->UsbIo->UsbAsyncInterruptTransfer (
UsbEthDriver->UsbIo,
UsbEthDriver->InterruptEndpoint,
IsNewTransfer,
0,
0,
NULL,
NULL
);
}
return Status;
}
/**
Retrieves the USB Ethernet Mac Address.
@param[in] This A pointer to the 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_ETHERNET_DRIVER *UsbEthDriver;
USB_ETHERNET_FUN_DESCRIPTOR UsbEthDescriptor;
CHAR16 *Data;
CHAR16 *DataPtr;
CHAR16 TmpStr[1];
UINT8 Index;
UINT8 Hi;
UINT8 Low;
UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
Status = This->UsbEthFunDescriptor (This, &UsbEthDescriptor);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "%a:UsbEthFunDescriptor status = %r\n", __func__, Status));
return Status;
}
Status = UsbEthDriver->UsbIo->UsbGetStringDescriptor (
UsbEthDriver->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
UsbEthEcmBulkSize (
IN EDKII_USB_ETHERNET_PROTOCOL *This,
OUT UINTN *BulkSize
)
{
EFI_STATUS Status;
USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor;
Status = This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor);
if (EFI_ERROR (Status)) {
return Status;
}
*BulkSize = (UINTN)UsbEthFunDescriptor.MaxSegmentSize;
return Status;
}
/**
Retrieves the USB Header functional Descriptor.
@param[in] This A pointer to the 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_ETHERNET_DRIVER *UsbEthDriver;
UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
if (UsbHeaderFunDescriptor == NULL) {
return EFI_INVALID_PARAMETER;
}
Status = GetFunctionalDescriptor (UsbEthDriver->Config, HEADER_FUN_DESCRIPTOR, UsbHeaderFunDescriptor);
return Status;
}
/**
Retrieves the USB Union functional Descriptor.
@param[in] This A pointer to the 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_ETHERNET_DRIVER *UsbEthDriver;
UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
if (UsbUnionFunDescriptor == NULL) {
return EFI_INVALID_PARAMETER;
}
Status = GetFunctionalDescriptor (UsbEthDriver->Config, UNION_FUN_DESCRIPTOR, UsbUnionFunDescriptor);
return Status;
}
/**
Retrieves the USB Ethernet functional Descriptor.
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
GetUsbEthFunDescriptor (
IN EDKII_USB_ETHERNET_PROTOCOL *This,
OUT USB_ETHERNET_FUN_DESCRIPTOR *UsbEthFunDescriptor
)
{
EFI_STATUS Status;
USB_ETHERNET_DRIVER *UsbEthDriver;
UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
if (UsbEthFunDescriptor == NULL) {
return EFI_INVALID_PARAMETER;
}
Status = GetFunctionalDescriptor (UsbEthDriver->Config, ETHERNET_FUN_DESCRIPTOR, UsbEthFunDescriptor);
return Status;
}
/**
This request sets the Ethernet device multicast filters as specified in the
sequential list of 48 bit Ethernet multicast addresses.
@param[in] This A pointer to the 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
SetUsbEthMcastFilter (
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_ETHERNET_DRIVER *UsbEthDriver;
UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
Status = This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor);
if (EFI_ERROR (Status)) {
return Status;
}
if ((UsbEthFunDescriptor.NumberMcFilters << 1) == 0) {
return EFI_UNSUPPORTED;
}
Request.RequestType = USB_ETHERNET_SET_REQ_TYPE;
Request.Request = SET_ETH_MULTICAST_FILTERS_REQ;
Request.Value = Value;
Request.Index = UsbEthDriver->NumOfInterface;
Request.Length = Value * 6;
return UsbEthDriver->UsbIo->UsbControlTransfer (
UsbEthDriver->UsbIo,
&Request,
EfiUsbDataOut,
USB_ETHERNET_TRANSFER_TIMEOUT,
McastAddr,
Request.Length,
&TransStatus
);
}
/**
This request sets up the specified Ethernet power management pattern filter as
described in the data structure.
@param[in] This A pointer to the 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
SetUsbEthPowerFilter (
IN EDKII_USB_ETHERNET_PROTOCOL *This,
IN UINT16 Value,
IN UINT16 Length,
IN VOID *PatternFilter
)
{
EFI_USB_DEVICE_REQUEST Request;
UINT32 TransStatus;
USB_ETHERNET_DRIVER *UsbEthDriver;
UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
Request.RequestType = USB_ETHERNET_SET_REQ_TYPE;
Request.Request = SET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ;
Request.Value = Value;
Request.Index = UsbEthDriver->NumOfInterface;
Request.Length = Length;
return UsbEthDriver->UsbIo->UsbControlTransfer (
UsbEthDriver->UsbIo,
&Request,
EfiUsbDataOut,
USB_ETHERNET_TRANSFER_TIMEOUT,
PatternFilter,
Length,
&TransStatus
);
}
/**
This request retrieves the status of the specified Ethernet power management
pattern filter from the device.
@param[in] This A pointer to the 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
GetUsbEthPowerFilter (
IN EDKII_USB_ETHERNET_PROTOCOL *This,
IN UINT16 Value,
OUT BOOLEAN *PatternActive
)
{
EFI_USB_DEVICE_REQUEST Request;
UINT32 TransStatus;
USB_ETHERNET_DRIVER *UsbEthDriver;
UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
Request.RequestType = USB_ETHERNET_GET_REQ_TYPE;
Request.Request = GET_ETH_POWER_MANAGEMENT_PATTERN_FILTER_REQ;
Request.Value = Value;
Request.Index = UsbEthDriver->NumOfInterface;
Request.Length = USB_ETH_POWER_FILTER_LENGTH;
return UsbEthDriver->UsbIo->UsbControlTransfer (
UsbEthDriver->UsbIo,
&Request,
EfiUsbDataIn,
USB_ETHERNET_TRANSFER_TIMEOUT,
PatternActive,
USB_ETH_POWER_FILTER_LENGTH,
&TransStatus
);
}
BIT_MAP gTable[] = {
{ PXE_OPFLAGS_RECEIVE_FILTER_UNICAST, USB_ETH_PACKET_TYPE_DIRECTED },
{ PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST, USB_ETH_PACKET_TYPE_BROADCAST },
{ PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST, USB_ETH_PACKET_TYPE_MULTICAST },
{ PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS, USB_ETH_PACKET_TYPE_PROMISCUOUS },
{ PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST, USB_ETH_PACKET_TYPE_ALL_MULTICAST },
};
/**
Convert value between PXE receive filter and USB ETH packet filter.
@param[in] Value PXE filter data.
@param[out] CdcFilter A pointer to the Ethernet Packet Filter Bitmap value converted by PXE_OPFLAGS.
**/
VOID
ConvertFilter (
IN UINT16 Value,
OUT UINT16 *CdcFilter
)
{
UINT32 Index;
UINT32 Count;
Count = sizeof (gTable)/sizeof (gTable[0]);
for (Index = 0; (gTable[Index].Src != 0) && (Index < Count); Index++) {
if (gTable[Index].Src & Value) {
*CdcFilter |= gTable[Index].Dst;
}
}
}
/**
This request is used to configure device Ethernet packet filter settings.
@param[in] This A pointer to the 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
SetUsbEthPacketFilter (
IN EDKII_USB_ETHERNET_PROTOCOL *This,
IN UINT16 Value
)
{
EFI_USB_DEVICE_REQUEST Request;
UINT32 TransStatus;
USB_ETHERNET_DRIVER *UsbEthDriver;
UINT16 CommandFilter;
UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
CommandFilter = 0;
ConvertFilter (Value, &CommandFilter);
Request.RequestType = USB_ETHERNET_SET_REQ_TYPE;
Request.Request = SET_ETH_PACKET_FILTER_REQ;
Request.Value = CommandFilter;
Request.Index = UsbEthDriver->NumOfInterface;
Request.Length = USB_ETH_PACKET_FILTER_LENGTH;
return UsbEthDriver->UsbIo->UsbControlTransfer (
UsbEthDriver->UsbIo,
&Request,
EfiUsbNoData,
USB_ETHERNET_TRANSFER_TIMEOUT,
NULL,
USB_ETH_PACKET_FILTER_LENGTH,
&TransStatus
);
}
/**
This request is used to retrieve a statistic based on the feature selector.
@param[in] This A pointer to the 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
GetUsbEthStatistic (
IN EDKII_USB_ETHERNET_PROTOCOL *This,
IN UINT16 FeatureSelector,
OUT VOID *Statistic
)
{
EFI_STATUS Status;
EFI_USB_DEVICE_REQUEST Request;
UINT32 TransStatus;
USB_ETHERNET_FUN_DESCRIPTOR UsbEthFunDescriptor;
USB_ETHERNET_DRIVER *UsbEthDriver;
UsbEthDriver = USB_ETHERNET_DEV_FROM_THIS (This);
Status = This->UsbEthFunDescriptor (This, &UsbEthFunDescriptor);
if (EFI_ERROR (Status)) {
return Status;
}
if (UsbEthFunDescriptor.EthernetStatistics == 0) {
return EFI_UNSUPPORTED;
}
Request.RequestType = USB_ETHERNET_GET_REQ_TYPE;
Request.Request = GET_ETH_STATISTIC_REQ;
Request.Value = FeatureSelector;
Request.Index = UsbEthDriver->NumOfInterface;
Request.Length = USB_ETH_STATISTIC;
return UsbEthDriver->UsbIo->UsbControlTransfer (
UsbEthDriver->UsbIo,
&Request,
EfiUsbDataIn,
USB_ETHERNET_TRANSFER_TIMEOUT,
Statistic,
USB_ETH_STATISTIC,
&TransStatus
);
}