This patch fixes wrong condition because of UINT16 value to integer promotion. NumberMcFilters is UINT16 value, so when bitwise shift operator applied to small integer type, the operation is preceded by integral promotion. This is described in MISRA-C:2004 guideline as Rule 10.5: "If the bitwise operators ~ and << are applied to an operand of underlying type unsigned char or unsigned short, the result shall be immediately cast to the underlying type of the operand." A simple fix for this issue would be the following: if ((UINT16)(UsbEthFunDescriptor.NumberMcFilters << 1) == 0) But this patch proposes to use bitwise AND operation with a proper bit mask rather than shifting to prevent similar mistakes in future. Cc: Richard Ho <richardho@ami.com> Cc: Rebecca Cran <rebecca@bsdio.com> Signed-off-by: Mike Maslenkin <mike.maslenkin@gmail.com>
881 lines
30 KiB
C
881 lines
30 KiB
C
/** @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 & MAC_FILTERS_MASK) == 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
|
|
);
|
|
}
|