NetworkPkg: Move Network library and drivers from MdeModulePkg to NetworkPkg
Signed-off-by: Liming Gao <liming.gao@intel.com> Cc: Siyuan Fu <siyuan.fu@intel.com> Cc: Jiaxin Wu <jiaxin.wu@intel.com> Reviewed-by: Jiaxin Wu <jiaxin.wu@intel.com> Reviewed-by: Siyuan Fu <siyuan.fu@intel.com>
This commit is contained in:
354
NetworkPkg/SnpDxe/Callback.c
Normal file
354
NetworkPkg/SnpDxe/Callback.c
Normal file
@@ -0,0 +1,354 @@
|
||||
/** @file
|
||||
This file contains the callback routines for undi3.1.
|
||||
the callback routines for Undi3.1 have an extra parameter UniqueId which
|
||||
stores the interface context for the NIC that snp is trying to talk.
|
||||
|
||||
Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "Snp.h"
|
||||
|
||||
/**
|
||||
Acquire or release a lock of the exclusive access to a critical section of the
|
||||
code/data.
|
||||
|
||||
This is a callback routine supplied to UNDI3.1 at undi_start time.
|
||||
New callbacks for 3.1: there won't be a virtual2physical callback for UNDI 3.1
|
||||
because undi3.1 uses the MemMap call to map the required address by itself!
|
||||
|
||||
@param UniqueId This was supplied to UNDI at Undi_Start, SNP uses this to
|
||||
store Undi interface context (Undi does not read or write
|
||||
this variable).
|
||||
@param Enable Non-zero indicates acquire; Zero indicates release.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SnpUndi32CallbackBlock (
|
||||
IN UINT64 UniqueId,
|
||||
IN UINT32 Enable
|
||||
)
|
||||
{
|
||||
SNP_DRIVER *Snp;
|
||||
|
||||
Snp = (SNP_DRIVER *) (UINTN) UniqueId;
|
||||
//
|
||||
// tcpip was calling snp at tpl_notify and when we acquire a lock that was
|
||||
// created at a lower level (TPL_CALLBACK) it gives an assert!
|
||||
//
|
||||
if (Enable != 0) {
|
||||
EfiAcquireLock (&Snp->Lock);
|
||||
} else {
|
||||
EfiReleaseLock (&Snp->Lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Delay MicroSeconds of micro seconds.
|
||||
|
||||
This is a callback routine supplied to UNDI at undi_start time.
|
||||
|
||||
@param UniqueId This was supplied to UNDI at Undi_Start, SNP uses this to
|
||||
store Undi interface context (Undi does not read or write
|
||||
this variable).
|
||||
@param MicroSeconds Number of micro seconds to pause, ususlly multiple of 10.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SnpUndi32CallbackDelay (
|
||||
IN UINT64 UniqueId,
|
||||
IN UINT64 MicroSeconds
|
||||
)
|
||||
{
|
||||
if (MicroSeconds != 0) {
|
||||
gBS->Stall ((UINTN) MicroSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
IO routine for UNDI3.1.
|
||||
|
||||
This is a callback routine supplied to UNDI at undi_start time.
|
||||
|
||||
@param UniqueId This was supplied to UNDI at Undi_Start, SNP uses this
|
||||
to store Undi interface context (Undi does not read or
|
||||
write this variable).
|
||||
@param ReadOrWrite Indicates read or write, IO or Memory.
|
||||
@param NumBytes Number of bytes to read or write.
|
||||
@param MemOrPortAddr IO or memory address to read from or write to.
|
||||
@param BufferPtr Memory location to read into or that contains the bytes
|
||||
to write.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SnpUndi32CallbackMemio (
|
||||
IN UINT64 UniqueId,
|
||||
IN UINT8 ReadOrWrite,
|
||||
IN UINT8 NumBytes,
|
||||
IN UINT64 MemOrPortAddr,
|
||||
IN OUT UINT64 BufferPtr
|
||||
)
|
||||
{
|
||||
SNP_DRIVER *Snp;
|
||||
EFI_PCI_IO_PROTOCOL_WIDTH Width;
|
||||
|
||||
Snp = (SNP_DRIVER *) (UINTN) UniqueId;
|
||||
|
||||
Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 0;
|
||||
switch (NumBytes) {
|
||||
case 2:
|
||||
Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 1;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 2;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 3;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (ReadOrWrite) {
|
||||
case PXE_IO_READ:
|
||||
Snp->PciIo->Io.Read (
|
||||
Snp->PciIo,
|
||||
Width,
|
||||
Snp->IoBarIndex, // BAR 1 (for 32bit regs), IO base address
|
||||
MemOrPortAddr,
|
||||
1, // count
|
||||
(VOID *) (UINTN) BufferPtr
|
||||
);
|
||||
break;
|
||||
|
||||
case PXE_IO_WRITE:
|
||||
Snp->PciIo->Io.Write (
|
||||
Snp->PciIo,
|
||||
Width,
|
||||
Snp->IoBarIndex, // BAR 1 (for 32bit regs), IO base address
|
||||
MemOrPortAddr,
|
||||
1, // count
|
||||
(VOID *) (UINTN) BufferPtr
|
||||
);
|
||||
break;
|
||||
|
||||
case PXE_MEM_READ:
|
||||
Snp->PciIo->Mem.Read (
|
||||
Snp->PciIo,
|
||||
Width,
|
||||
Snp->MemoryBarIndex, // BAR 0, Memory base address
|
||||
MemOrPortAddr,
|
||||
1, // count
|
||||
(VOID *) (UINTN) BufferPtr
|
||||
);
|
||||
break;
|
||||
|
||||
case PXE_MEM_WRITE:
|
||||
Snp->PciIo->Mem.Write (
|
||||
Snp->PciIo,
|
||||
Width,
|
||||
Snp->MemoryBarIndex, // BAR 0, Memory base address
|
||||
MemOrPortAddr,
|
||||
1, // count
|
||||
(VOID *) (UINTN) BufferPtr
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
/**
|
||||
Map a CPU address to a device address.
|
||||
|
||||
This is a callback routine supplied to UNDI at undi_start time.
|
||||
|
||||
@param UniqueId This was supplied to UNDI at Undi_Start, SNP uses this to
|
||||
store Undi interface context (Undi does not read or write
|
||||
this variable).
|
||||
@param CpuAddr Virtual address to be mapped.
|
||||
@param NumBytes Size of memory to be mapped.
|
||||
@param Direction Direction of data flow for this memory's usage:
|
||||
cpu->device, device->cpu or both ways.
|
||||
@param DeviceAddrPtr Pointer to return the mapped device address.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SnpUndi32CallbackMap (
|
||||
IN UINT64 UniqueId,
|
||||
IN UINT64 CpuAddr,
|
||||
IN UINT32 NumBytes,
|
||||
IN UINT32 Direction,
|
||||
IN OUT UINT64 DeviceAddrPtr
|
||||
)
|
||||
{
|
||||
EFI_PHYSICAL_ADDRESS *DevAddrPtr;
|
||||
EFI_PCI_IO_PROTOCOL_OPERATION DirectionFlag;
|
||||
UINTN BuffSize;
|
||||
SNP_DRIVER *Snp;
|
||||
UINTN Index;
|
||||
EFI_STATUS Status;
|
||||
|
||||
BuffSize = (UINTN) NumBytes;
|
||||
Snp = (SNP_DRIVER *) (UINTN) UniqueId;
|
||||
DevAddrPtr = (EFI_PHYSICAL_ADDRESS *) (UINTN) DeviceAddrPtr;
|
||||
|
||||
if (CpuAddr == 0) {
|
||||
*DevAddrPtr = 0;
|
||||
return ;
|
||||
}
|
||||
|
||||
switch (Direction) {
|
||||
case TO_AND_FROM_DEVICE:
|
||||
DirectionFlag = EfiPciIoOperationBusMasterCommonBuffer;
|
||||
break;
|
||||
|
||||
case FROM_DEVICE:
|
||||
DirectionFlag = EfiPciIoOperationBusMasterWrite;
|
||||
break;
|
||||
|
||||
case TO_DEVICE:
|
||||
DirectionFlag = EfiPciIoOperationBusMasterRead;
|
||||
break;
|
||||
|
||||
default:
|
||||
*DevAddrPtr = 0;
|
||||
//
|
||||
// any non zero indicates error!
|
||||
//
|
||||
return ;
|
||||
}
|
||||
//
|
||||
// find an unused map_list entry
|
||||
//
|
||||
for (Index = 0; Index < MAX_MAP_LENGTH; Index++) {
|
||||
if (Snp->MapList[Index].VirtualAddress == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Index >= MAX_MAP_LENGTH) {
|
||||
DEBUG ((EFI_D_INFO, "SNP maplist is FULL\n"));
|
||||
*DevAddrPtr = 0;
|
||||
return ;
|
||||
}
|
||||
|
||||
Snp->MapList[Index].VirtualAddress = (EFI_PHYSICAL_ADDRESS) CpuAddr;
|
||||
|
||||
Status = Snp->PciIo->Map (
|
||||
Snp->PciIo,
|
||||
DirectionFlag,
|
||||
(VOID *) (UINTN) CpuAddr,
|
||||
&BuffSize,
|
||||
DevAddrPtr,
|
||||
&(Snp->MapList[Index].MapCookie)
|
||||
);
|
||||
if (Status != EFI_SUCCESS) {
|
||||
*DevAddrPtr = 0;
|
||||
Snp->MapList[Index].VirtualAddress = 0;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
/**
|
||||
Unmap an address that was previously mapped using map callback.
|
||||
|
||||
This is a callback routine supplied to UNDI at undi_start time.
|
||||
|
||||
@param UniqueId This was supplied to UNDI at Undi_Start, SNP uses this to
|
||||
store. Undi interface context (Undi does not read or write
|
||||
this variable).
|
||||
@param CpuAddr Virtual address that was mapped.
|
||||
@param NumBytes Size of memory mapped.
|
||||
@param Direction Direction of data flow for this memory's usage:
|
||||
cpu->device, device->cpu or both ways.
|
||||
@param DeviceAddr The mapped device address.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SnpUndi32CallbackUnmap (
|
||||
IN UINT64 UniqueId,
|
||||
IN UINT64 CpuAddr,
|
||||
IN UINT32 NumBytes,
|
||||
IN UINT32 Direction,
|
||||
IN UINT64 DeviceAddr
|
||||
)
|
||||
{
|
||||
SNP_DRIVER *Snp;
|
||||
UINT16 Index;
|
||||
|
||||
Snp = (SNP_DRIVER *) (UINTN) UniqueId;
|
||||
|
||||
for (Index = 0; Index < MAX_MAP_LENGTH; Index++) {
|
||||
if (Snp->MapList[Index].VirtualAddress == CpuAddr) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Index >= MAX_MAP_LENGTH) {
|
||||
DEBUG ((EFI_D_ERROR, "SNP could not find a mapping, failed to unmap.\n"));
|
||||
return ;
|
||||
}
|
||||
|
||||
Snp->PciIo->Unmap (Snp->PciIo, Snp->MapList[Index].MapCookie);
|
||||
Snp->MapList[Index].VirtualAddress = 0;
|
||||
Snp->MapList[Index].MapCookie = NULL;
|
||||
return ;
|
||||
}
|
||||
|
||||
/**
|
||||
Synchronize the virtual buffer contents with the mapped buffer contents.
|
||||
|
||||
This is a callback routine supplied to UNDI at undi_start time. The virtual
|
||||
and mapped buffers need not correspond to the same physical memory (especially
|
||||
if the virtual address is > 4GB). Depending on the direction for which the
|
||||
buffer is mapped, undi will need to synchronize their contents whenever it
|
||||
writes to/reads from the buffer using either the cpu address or the device
|
||||
address.
|
||||
EFI does not provide a sync call since virt=physical, we should just do the
|
||||
synchronization ourselves here.
|
||||
|
||||
@param UniqueId This was supplied to UNDI at Undi_Start, SNP uses this to
|
||||
store Undi interface context (Undi does not read or write
|
||||
this variable).
|
||||
@param CpuAddr Virtual address that was mapped.
|
||||
@param NumBytes Size of memory mapped.
|
||||
@param Direction Direction of data flow for this memory's usage:
|
||||
cpu->device, device->cpu or both ways.
|
||||
@param DeviceAddr The mapped device address.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SnpUndi32CallbackSync (
|
||||
IN UINT64 UniqueId,
|
||||
IN UINT64 CpuAddr,
|
||||
IN UINT32 NumBytes,
|
||||
IN UINT32 Direction,
|
||||
IN UINT64 DeviceAddr
|
||||
)
|
||||
{
|
||||
if ((CpuAddr == 0) || (DeviceAddr == 0) || (NumBytes == 0)) {
|
||||
return ;
|
||||
|
||||
}
|
||||
|
||||
switch (Direction) {
|
||||
case FROM_DEVICE:
|
||||
CopyMem ((UINT8 *) (UINTN) CpuAddr, (UINT8 *) (UINTN) DeviceAddr, NumBytes);
|
||||
break;
|
||||
|
||||
case TO_DEVICE:
|
||||
CopyMem ((UINT8 *) (UINTN) DeviceAddr, (UINT8 *) (UINTN) CpuAddr, NumBytes);
|
||||
break;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
430
NetworkPkg/SnpDxe/ComponentName.c
Normal file
430
NetworkPkg/SnpDxe/ComponentName.c
Normal file
@@ -0,0 +1,430 @@
|
||||
/** @file
|
||||
UEFI Component Name(2) protocol implementation for SnpDxe driver.
|
||||
|
||||
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
|
||||
#include "Snp.h"
|
||||
|
||||
//
|
||||
// EFI Component Name Functions
|
||||
//
|
||||
/**
|
||||
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 This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
|
||||
@param Language[in] 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 DriverName[out] 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
|
||||
SimpleNetworkComponentNameGetDriverName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **DriverName
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
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 This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
|
||||
@param ControllerHandle[in] 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 ChildHandle[in] 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 Language[in] 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 ControllerName[out] 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 NULL.
|
||||
|
||||
@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
|
||||
SimpleNetworkComponentNameGetControllerName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_HANDLE ChildHandle OPTIONAL,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **ControllerName
|
||||
);
|
||||
|
||||
|
||||
//
|
||||
// EFI Component Name Protocol
|
||||
//
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gSimpleNetworkComponentName = {
|
||||
SimpleNetworkComponentNameGetDriverName,
|
||||
SimpleNetworkComponentNameGetControllerName,
|
||||
"eng"
|
||||
};
|
||||
|
||||
//
|
||||
// EFI Component Name 2 Protocol
|
||||
//
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gSimpleNetworkComponentName2 = {
|
||||
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) SimpleNetworkComponentNameGetDriverName,
|
||||
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) SimpleNetworkComponentNameGetControllerName,
|
||||
"en"
|
||||
};
|
||||
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSimpleNetworkDriverNameTable[] = {
|
||||
{
|
||||
"eng;en",
|
||||
L"Simple Network Protocol Driver"
|
||||
},
|
||||
{
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE *gSimpleNetworkControllerNameTable = NULL;
|
||||
|
||||
/**
|
||||
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 This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
|
||||
@param Language[in] 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 DriverName[out] 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
|
||||
SimpleNetworkComponentNameGetDriverName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **DriverName
|
||||
)
|
||||
{
|
||||
return LookupUnicodeString2 (
|
||||
Language,
|
||||
This->SupportedLanguages,
|
||||
mSimpleNetworkDriverNameTable,
|
||||
DriverName,
|
||||
(BOOLEAN)(This == &gSimpleNetworkComponentName)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Update the component name for the Snp child handle.
|
||||
|
||||
@param Snp[in] A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS Update the ControllerNameTable of this instance successfully.
|
||||
@retval EFI_INVALID_PARAMETER The input parameter is invalid.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UpdateName (
|
||||
IN EFI_SIMPLE_NETWORK_PROTOCOL *Snp
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
CHAR16 HandleName[80];
|
||||
UINTN OffSet;
|
||||
UINTN Index;
|
||||
|
||||
if (Snp == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
OffSet = 0;
|
||||
OffSet += UnicodeSPrint (
|
||||
HandleName,
|
||||
sizeof (HandleName),
|
||||
L"SNP (MAC="
|
||||
);
|
||||
for (Index = 0; Index < Snp->Mode->HwAddressSize; Index++) {
|
||||
OffSet += UnicodeSPrint (
|
||||
HandleName + OffSet,
|
||||
sizeof (HandleName) - OffSet * sizeof (CHAR16),
|
||||
L"%02X-",
|
||||
Snp->Mode->CurrentAddress.Addr[Index]
|
||||
);
|
||||
}
|
||||
ASSERT (OffSet > 0);
|
||||
//
|
||||
// Remove the last '-'
|
||||
//
|
||||
OffSet--;
|
||||
OffSet += UnicodeSPrint (
|
||||
HandleName + OffSet,
|
||||
sizeof (HandleName) - OffSet * sizeof (CHAR16),
|
||||
L")"
|
||||
);
|
||||
if (gSimpleNetworkControllerNameTable != NULL) {
|
||||
FreeUnicodeStringTable (gSimpleNetworkControllerNameTable);
|
||||
gSimpleNetworkControllerNameTable = NULL;
|
||||
}
|
||||
|
||||
Status = AddUnicodeString2 (
|
||||
"eng",
|
||||
gSimpleNetworkComponentName.SupportedLanguages,
|
||||
&gSimpleNetworkControllerNameTable,
|
||||
HandleName,
|
||||
TRUE
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
return AddUnicodeString2 (
|
||||
"en",
|
||||
gSimpleNetworkComponentName2.SupportedLanguages,
|
||||
&gSimpleNetworkControllerNameTable,
|
||||
HandleName,
|
||||
FALSE
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
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.
|
||||
Currently not implemented.
|
||||
|
||||
@param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
|
||||
@param ControllerHandle[in] 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 ChildHandle[in] 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 Language[in] 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 ControllerName[out] 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 NULL.
|
||||
|
||||
@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
|
||||
SimpleNetworkComponentNameGetControllerName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_HANDLE ChildHandle OPTIONAL,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **ControllerName
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
|
||||
|
||||
if (ChildHandle != NULL) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Make sure this driver is currently managing ControllHandle
|
||||
//
|
||||
Status = EfiTestManagedDevice (
|
||||
ControllerHandle,
|
||||
gSimpleNetworkDriverBinding.DriverBindingHandle,
|
||||
&gEfiSimpleNetworkProtocolGuid
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Retrieve an instance of a produced protocol from ControllerHandle
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ControllerHandle,
|
||||
&gEfiSimpleNetworkProtocolGuid,
|
||||
(VOID **)&Snp,
|
||||
NULL,
|
||||
NULL,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
//
|
||||
// Update the component name for this child handle.
|
||||
//
|
||||
Status = UpdateName (Snp);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
return LookupUnicodeString2 (
|
||||
Language,
|
||||
This->SupportedLanguages,
|
||||
gSimpleNetworkControllerNameTable,
|
||||
ControllerName,
|
||||
(BOOLEAN)(This == &gSimpleNetworkComponentName)
|
||||
);
|
||||
}
|
257
NetworkPkg/SnpDxe/Get_status.c
Normal file
257
NetworkPkg/SnpDxe/Get_status.c
Normal file
@@ -0,0 +1,257 @@
|
||||
/** @file
|
||||
Implementation of reading the current interrupt status and recycled transmit
|
||||
buffer status from a network interface.
|
||||
|
||||
Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "Snp.h"
|
||||
|
||||
/**
|
||||
Call undi to get the status of the interrupts, get the list of recycled transmit
|
||||
buffers that completed transmitting. The recycled transmit buffer address will
|
||||
be saved into Snp->RecycledTxBuf. This function will also update the MediaPresent
|
||||
field of EFI_SIMPLE_NETWORK_MODE if UNDI support it.
|
||||
|
||||
@param[in] Snp Pointer to snp driver structure.
|
||||
@param[out] InterruptStatusPtr A non null pointer to contain the interrupt
|
||||
status.
|
||||
@param[in] GetTransmittedBuf Set to TRUE to retrieve the recycled transmit
|
||||
buffer address.
|
||||
|
||||
@retval EFI_SUCCESS The status of the network interface was retrieved.
|
||||
@retval EFI_DEVICE_ERROR The command could not be sent to the network
|
||||
interface.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PxeGetStatus (
|
||||
IN SNP_DRIVER *Snp,
|
||||
OUT UINT32 *InterruptStatusPtr,
|
||||
IN BOOLEAN GetTransmittedBuf
|
||||
)
|
||||
{
|
||||
PXE_DB_GET_STATUS *Db;
|
||||
UINT16 InterruptFlags;
|
||||
UINT32 Index;
|
||||
UINT64 *Tmp;
|
||||
|
||||
Tmp = NULL;
|
||||
Db = Snp->Db;
|
||||
Snp->Cdb.OpCode = PXE_OPCODE_GET_STATUS;
|
||||
|
||||
Snp->Cdb.OpFlags = 0;
|
||||
|
||||
if (GetTransmittedBuf) {
|
||||
Snp->Cdb.OpFlags |= PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS;
|
||||
ZeroMem (Db->TxBuffer, sizeof (Db->TxBuffer));
|
||||
}
|
||||
|
||||
if (InterruptStatusPtr != NULL) {
|
||||
Snp->Cdb.OpFlags |= PXE_OPFLAGS_GET_INTERRUPT_STATUS;
|
||||
}
|
||||
|
||||
if (Snp->MediaStatusSupported) {
|
||||
Snp->Cdb.OpFlags |= PXE_OPFLAGS_GET_MEDIA_STATUS;
|
||||
}
|
||||
|
||||
Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
|
||||
Snp->Cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
|
||||
|
||||
Snp->Cdb.DBsize = (UINT16) sizeof (PXE_DB_GET_STATUS);
|
||||
Snp->Cdb.DBaddr = (UINT64)(UINTN) Db;
|
||||
|
||||
Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;
|
||||
Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
|
||||
Snp->Cdb.IFnum = Snp->IfNum;
|
||||
Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
|
||||
|
||||
//
|
||||
// Issue UNDI command and check result.
|
||||
//
|
||||
DEBUG ((EFI_D_NET, "\nSnp->undi.get_status() "));
|
||||
|
||||
(*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);
|
||||
|
||||
if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {
|
||||
DEBUG (
|
||||
(EFI_D_NET,
|
||||
"\nSnp->undi.get_status() %xh:%xh\n",
|
||||
Snp->Cdb.StatFlags,
|
||||
Snp->Cdb.StatCode)
|
||||
);
|
||||
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
//
|
||||
// report the values back..
|
||||
//
|
||||
if (InterruptStatusPtr != NULL) {
|
||||
InterruptFlags = (UINT16) (Snp->Cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_INTERRUPT_MASK);
|
||||
|
||||
*InterruptStatusPtr = 0;
|
||||
|
||||
if ((InterruptFlags & PXE_STATFLAGS_GET_STATUS_RECEIVE) == PXE_STATFLAGS_GET_STATUS_RECEIVE) {
|
||||
*InterruptStatusPtr |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
|
||||
}
|
||||
|
||||
if ((InterruptFlags & PXE_STATFLAGS_GET_STATUS_TRANSMIT) == PXE_STATFLAGS_GET_STATUS_TRANSMIT) {
|
||||
*InterruptStatusPtr |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
|
||||
}
|
||||
|
||||
if ((InterruptFlags & PXE_STATFLAGS_GET_STATUS_COMMAND) == PXE_STATFLAGS_GET_STATUS_COMMAND) {
|
||||
*InterruptStatusPtr |= EFI_SIMPLE_NETWORK_COMMAND_INTERRUPT;
|
||||
}
|
||||
|
||||
if ((InterruptFlags & PXE_STATFLAGS_GET_STATUS_SOFTWARE) == PXE_STATFLAGS_GET_STATUS_SOFTWARE) {
|
||||
*InterruptStatusPtr |= EFI_SIMPLE_NETWORK_COMMAND_INTERRUPT;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (GetTransmittedBuf) {
|
||||
if ((Snp->Cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN) == 0) {
|
||||
//
|
||||
// UNDI has written some transmitted buffer addresses into the DB. Store them into Snp->RecycledTxBuf.
|
||||
//
|
||||
for (Index = 0; Index < MAX_XMIT_BUFFERS; Index++) {
|
||||
if (Db->TxBuffer[Index] != 0) {
|
||||
if (Snp->RecycledTxBufCount == Snp->MaxRecycledTxBuf) {
|
||||
//
|
||||
// Snp->RecycledTxBuf is full, reallocate a new one.
|
||||
//
|
||||
if ((Snp->MaxRecycledTxBuf + SNP_TX_BUFFER_INCREASEMENT) >= SNP_MAX_TX_BUFFER_NUM) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
Tmp = AllocatePool (sizeof (UINT64) * (Snp->MaxRecycledTxBuf + SNP_TX_BUFFER_INCREASEMENT));
|
||||
if (Tmp == NULL) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
CopyMem (Tmp, Snp->RecycledTxBuf, sizeof (UINT64) * Snp->RecycledTxBufCount);
|
||||
FreePool (Snp->RecycledTxBuf);
|
||||
Snp->RecycledTxBuf = Tmp;
|
||||
Snp->MaxRecycledTxBuf += SNP_TX_BUFFER_INCREASEMENT;
|
||||
}
|
||||
Snp->RecycledTxBuf[Snp->RecycledTxBufCount] = Db->TxBuffer[Index];
|
||||
Snp->RecycledTxBufCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Update MediaPresent field of EFI_SIMPLE_NETWORK_MODE if the UNDI support
|
||||
// returning media status from GET_STATUS command
|
||||
//
|
||||
if (Snp->MediaStatusSupported) {
|
||||
Snp->Snp.Mode->MediaPresent =
|
||||
(BOOLEAN) (((Snp->Cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_NO_MEDIA) != 0) ? FALSE : TRUE);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Reads the current interrupt status and recycled transmit buffer status from a
|
||||
network interface.
|
||||
|
||||
This function gets the current interrupt and recycled transmit buffer status
|
||||
from the network interface. The interrupt status is returned as a bit mask in
|
||||
InterruptStatus. If InterruptStatus is NULL, the interrupt status will not be
|
||||
read. If TxBuf is not NULL, a recycled transmit buffer address will be retrieved.
|
||||
If a recycled transmit buffer address is returned in TxBuf, then the buffer has
|
||||
been successfully transmitted, and the status for that buffer is cleared. If
|
||||
the status of the network interface is successfully collected, EFI_SUCCESS
|
||||
will be returned. If the driver has not been initialized, EFI_DEVICE_ERROR will
|
||||
be returned.
|
||||
|
||||
@param This A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
|
||||
@param InterruptStatus A pointer to the bit mask of the currently active
|
||||
interrupts (see "Related Definitions"). If this is NULL,
|
||||
the interrupt status will not be read from the device.
|
||||
If this is not NULL, the interrupt status will be read
|
||||
from the device. When the interrupt status is read, it
|
||||
will also be cleared. Clearing the transmit interrupt does
|
||||
not empty the recycled transmit buffer array.
|
||||
@param TxBuf Recycled transmit buffer address. The network interface
|
||||
will not transmit if its internal recycled transmit
|
||||
buffer array is full. Reading the transmit buffer does
|
||||
not clear the transmit interrupt. If this is NULL, then
|
||||
the transmit buffer status will not be read. If there
|
||||
are no transmit buffers to recycle and TxBuf is not NULL,
|
||||
TxBuf will be set to NULL.
|
||||
|
||||
@retval EFI_SUCCESS The status of the network interface was retrieved.
|
||||
@retval EFI_NOT_STARTED The network interface has not been started.
|
||||
@retval EFI_INVALID_PARAMETER This parameter was NULL or did not point to a valid
|
||||
EFI_SIMPLE_NETWORK_PROTOCOL structure.
|
||||
@retval EFI_DEVICE_ERROR The command could not be sent to the network
|
||||
interface.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SnpUndi32GetStatus (
|
||||
IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
|
||||
OUT UINT32 *InterruptStatus, OPTIONAL
|
||||
OUT VOID **TxBuf OPTIONAL
|
||||
)
|
||||
{
|
||||
SNP_DRIVER *Snp;
|
||||
EFI_TPL OldTpl;
|
||||
EFI_STATUS Status;
|
||||
|
||||
if (This == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (InterruptStatus == NULL && TxBuf == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
|
||||
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
|
||||
if (Snp == NULL) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
switch (Snp->Mode.State) {
|
||||
case EfiSimpleNetworkInitialized:
|
||||
break;
|
||||
|
||||
case EfiSimpleNetworkStopped:
|
||||
Status = EFI_NOT_STARTED;
|
||||
goto ON_EXIT;
|
||||
|
||||
default:
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
if (Snp->RecycledTxBufCount == 0 && TxBuf != NULL) {
|
||||
Status = PxeGetStatus (Snp, InterruptStatus, TRUE);
|
||||
} else {
|
||||
Status = PxeGetStatus (Snp, InterruptStatus, FALSE);
|
||||
}
|
||||
|
||||
if (TxBuf != NULL) {
|
||||
//
|
||||
// Get a recycled buf from Snp->RecycledTxBuf
|
||||
//
|
||||
if (Snp->RecycledTxBufCount == 0) {
|
||||
*TxBuf = NULL;
|
||||
} else {
|
||||
Snp->RecycledTxBufCount--;
|
||||
*TxBuf = (VOID *) (UINTN) Snp->RecycledTxBuf[Snp->RecycledTxBufCount];
|
||||
}
|
||||
}
|
||||
|
||||
ON_EXIT:
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
return Status;
|
||||
}
|
277
NetworkPkg/SnpDxe/Initialize.c
Normal file
277
NetworkPkg/SnpDxe/Initialize.c
Normal file
@@ -0,0 +1,277 @@
|
||||
/** @file
|
||||
Implementation of initializing a network adapter.
|
||||
|
||||
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
|
||||
#include "Snp.h"
|
||||
|
||||
/**
|
||||
Call UNDI to initialize the interface.
|
||||
|
||||
@param Snp Pointer to snp driver structure.
|
||||
@param CableDetectFlag Do/don't detect the cable (depending on what
|
||||
undi supports).
|
||||
|
||||
@retval EFI_SUCCESS UNDI is initialized successfully.
|
||||
@retval EFI_DEVICE_ERROR UNDI could not be initialized.
|
||||
@retval Other Other errors as indicated.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PxeInit (
|
||||
SNP_DRIVER *Snp,
|
||||
UINT16 CableDetectFlag
|
||||
)
|
||||
{
|
||||
PXE_CPB_INITIALIZE *Cpb;
|
||||
VOID *Addr;
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
Cpb = Snp->Cpb;
|
||||
if (Snp->TxRxBufferSize != 0) {
|
||||
Status = Snp->PciIo->AllocateBuffer (
|
||||
Snp->PciIo,
|
||||
AllocateAnyPages,
|
||||
EfiBootServicesData,
|
||||
SNP_MEM_PAGES (Snp->TxRxBufferSize),
|
||||
&Addr,
|
||||
0
|
||||
);
|
||||
|
||||
if (Status != EFI_SUCCESS) {
|
||||
DEBUG (
|
||||
(EFI_D_ERROR,
|
||||
"\nSnp->PxeInit() AllocateBuffer %xh (%r)\n",
|
||||
Status,
|
||||
Status)
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
ASSERT (Addr);
|
||||
|
||||
Snp->TxRxBuffer = Addr;
|
||||
}
|
||||
|
||||
Cpb->MemoryAddr = (UINT64)(UINTN) Snp->TxRxBuffer;
|
||||
|
||||
Cpb->MemoryLength = Snp->TxRxBufferSize;
|
||||
|
||||
//
|
||||
// let UNDI decide/detect these values
|
||||
//
|
||||
Cpb->LinkSpeed = 0;
|
||||
Cpb->TxBufCnt = 0;
|
||||
Cpb->TxBufSize = 0;
|
||||
Cpb->RxBufCnt = 0;
|
||||
Cpb->RxBufSize = 0;
|
||||
|
||||
Cpb->DuplexMode = PXE_DUPLEX_DEFAULT;
|
||||
|
||||
Cpb->LoopBackMode = LOOPBACK_NORMAL;
|
||||
|
||||
Snp->Cdb.OpCode = PXE_OPCODE_INITIALIZE;
|
||||
Snp->Cdb.OpFlags = CableDetectFlag;
|
||||
|
||||
Snp->Cdb.CPBsize = (UINT16) sizeof (PXE_CPB_INITIALIZE);
|
||||
Snp->Cdb.DBsize = (UINT16) sizeof (PXE_DB_INITIALIZE);
|
||||
|
||||
Snp->Cdb.CPBaddr = (UINT64)(UINTN) Snp->Cpb;
|
||||
Snp->Cdb.DBaddr = (UINT64)(UINTN) Snp->Db;
|
||||
|
||||
Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;
|
||||
Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
|
||||
Snp->Cdb.IFnum = Snp->IfNum;
|
||||
Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
|
||||
|
||||
DEBUG ((EFI_D_NET, "\nSnp->undi.initialize() "));
|
||||
|
||||
(*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);
|
||||
|
||||
//
|
||||
// There are two fields need to be checked here:
|
||||
// First is the upper two bits (14 & 15) in the CDB.StatFlags field. Until these bits change to report
|
||||
// PXE_STATFLAGS_COMMAND_COMPLETE or PXE_STATFLAGS_COMMAND_FAILED, the command has not been executed by the UNDI.
|
||||
// Second is the CDB.StatCode field. After command execution completes, either successfully or not,
|
||||
// the CDB.StatCode field contains the result of the command execution.
|
||||
//
|
||||
if ((((Snp->Cdb.StatFlags) & PXE_STATFLAGS_STATUS_MASK) == PXE_STATFLAGS_COMMAND_COMPLETE) &&
|
||||
(Snp->Cdb.StatCode == PXE_STATCODE_SUCCESS)) {
|
||||
//
|
||||
// If cable detect feature is enabled in CDB.OpFlags, check the CDB.StatFlags to see if there is an
|
||||
// active connection to this network device. If the no media StatFlag is set, the UNDI and network
|
||||
// device are still initialized.
|
||||
//
|
||||
if (CableDetectFlag == PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) {
|
||||
if(((Snp->Cdb.StatFlags) & PXE_STATFLAGS_INITIALIZED_NO_MEDIA) != PXE_STATFLAGS_INITIALIZED_NO_MEDIA) {
|
||||
Snp->Mode.MediaPresent = TRUE;
|
||||
} else {
|
||||
Snp->Mode.MediaPresent = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
Snp->Mode.State = EfiSimpleNetworkInitialized;
|
||||
Status = EFI_SUCCESS;
|
||||
} else {
|
||||
DEBUG (
|
||||
(EFI_D_WARN,
|
||||
"\nSnp->undi.initialize() %xh:%xh\n",
|
||||
Snp->Cdb.StatFlags,
|
||||
Snp->Cdb.StatCode)
|
||||
);
|
||||
|
||||
if (Snp->TxRxBuffer != NULL) {
|
||||
Snp->PciIo->FreeBuffer (
|
||||
Snp->PciIo,
|
||||
SNP_MEM_PAGES (Snp->TxRxBufferSize),
|
||||
(VOID *) Snp->TxRxBuffer
|
||||
);
|
||||
}
|
||||
|
||||
Snp->TxRxBuffer = NULL;
|
||||
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Resets a network adapter and allocates the transmit and receive buffers
|
||||
required by the network interface; optionally, also requests allocation of
|
||||
additional transmit and receive buffers.
|
||||
|
||||
This function allocates the transmit and receive buffers required by the network
|
||||
interface. If this allocation fails, then EFI_OUT_OF_RESOURCES is returned.
|
||||
If the allocation succeeds and the network interface is successfully initialized,
|
||||
then EFI_SUCCESS will be returned.
|
||||
|
||||
@param This A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
|
||||
|
||||
@param ExtraRxBufferSize The size, in bytes, of the extra receive buffer space
|
||||
that the driver should allocate for the network interface.
|
||||
Some network interfaces will not be able to use the
|
||||
extra buffer, and the caller will not know if it is
|
||||
actually being used.
|
||||
@param ExtraTxBufferSize The size, in bytes, of the extra transmit buffer space
|
||||
that the driver should allocate for the network interface.
|
||||
Some network interfaces will not be able to use the
|
||||
extra buffer, and the caller will not know if it is
|
||||
actually being used.
|
||||
|
||||
@retval EFI_SUCCESS The network interface was initialized.
|
||||
@retval EFI_NOT_STARTED The network interface has not been started.
|
||||
@retval EFI_OUT_OF_RESOURCES There was not enough memory for the transmit and
|
||||
receive buffers.
|
||||
@retval EFI_INVALID_PARAMETER This parameter was NULL or did not point to a valid
|
||||
EFI_SIMPLE_NETWORK_PROTOCOL structure.
|
||||
@retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
|
||||
@retval EFI_UNSUPPORTED The increased buffer size feature is not supported.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SnpUndi32Initialize (
|
||||
IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
|
||||
IN UINTN ExtraRxBufferSize OPTIONAL,
|
||||
IN UINTN ExtraTxBufferSize OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS EfiStatus;
|
||||
SNP_DRIVER *Snp;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
if (This == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
|
||||
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
|
||||
if (Snp == NULL) {
|
||||
EfiStatus = EFI_INVALID_PARAMETER;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
switch (Snp->Mode.State) {
|
||||
case EfiSimpleNetworkStarted:
|
||||
break;
|
||||
|
||||
case EfiSimpleNetworkStopped:
|
||||
EfiStatus = EFI_NOT_STARTED;
|
||||
goto ON_EXIT;
|
||||
|
||||
default:
|
||||
EfiStatus = EFI_DEVICE_ERROR;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
EfiStatus = gBS->CreateEvent (
|
||||
EVT_NOTIFY_WAIT,
|
||||
TPL_NOTIFY,
|
||||
&SnpWaitForPacketNotify,
|
||||
Snp,
|
||||
&Snp->Snp.WaitForPacket
|
||||
);
|
||||
|
||||
if (EFI_ERROR (EfiStatus)) {
|
||||
Snp->Snp.WaitForPacket = NULL;
|
||||
EfiStatus = EFI_DEVICE_ERROR;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
//
|
||||
//
|
||||
//
|
||||
Snp->Mode.MCastFilterCount = 0;
|
||||
Snp->Mode.ReceiveFilterSetting = 0;
|
||||
ZeroMem (Snp->Mode.MCastFilter, sizeof Snp->Mode.MCastFilter);
|
||||
CopyMem (
|
||||
&Snp->Mode.CurrentAddress,
|
||||
&Snp->Mode.PermanentAddress,
|
||||
sizeof (EFI_MAC_ADDRESS)
|
||||
);
|
||||
|
||||
//
|
||||
// Compute tx/rx buffer sizes based on UNDI init info and parameters.
|
||||
//
|
||||
Snp->TxRxBufferSize = (UINT32) (Snp->InitInfo.MemoryRequired + ExtraRxBufferSize + ExtraTxBufferSize);
|
||||
|
||||
//
|
||||
// If UNDI support cable detect for INITIALIZE command, try it first.
|
||||
//
|
||||
if (Snp->CableDetectSupported) {
|
||||
if (PxeInit (Snp, PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) == EFI_SUCCESS) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
Snp->Mode.MediaPresent = FALSE;
|
||||
|
||||
EfiStatus = PxeInit (Snp, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE);
|
||||
|
||||
if (EFI_ERROR (EfiStatus)) {
|
||||
gBS->CloseEvent (Snp->Snp.WaitForPacket);
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// Try to update the MediaPresent field of EFI_SIMPLE_NETWORK_MODE if the UNDI support it.
|
||||
//
|
||||
if (Snp->MediaStatusSupported) {
|
||||
PxeGetStatus (Snp, NULL, FALSE);
|
||||
}
|
||||
|
||||
ON_EXIT:
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
return EfiStatus;
|
||||
}
|
173
NetworkPkg/SnpDxe/Mcast_ip_to_mac.c
Normal file
173
NetworkPkg/SnpDxe/Mcast_ip_to_mac.c
Normal file
@@ -0,0 +1,173 @@
|
||||
/** @file
|
||||
Implementation of converting an multicast IP address to multicast HW MAC
|
||||
address.
|
||||
|
||||
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "Snp.h"
|
||||
|
||||
/**
|
||||
Call undi to convert an multicast IP address to a MAC address.
|
||||
|
||||
@param Snp Pointer to snp driver structure.
|
||||
@param IPv6 Flag to indicate if this is an ipv6 address.
|
||||
@param IP Multicast IP address.
|
||||
@param MAC Pointer to hold the return MAC address.
|
||||
|
||||
@retval EFI_SUCCESS The multicast IP address was mapped to the
|
||||
multicast HW MAC address.
|
||||
@retval EFI_INVALID_PARAMETER Invalid UNDI command.
|
||||
@retval EFI_UNSUPPORTED Command is not supported by UNDI.
|
||||
@retval EFI_DEVICE_ERROR Fail to execute UNDI command.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PxeIp2Mac (
|
||||
IN SNP_DRIVER *Snp,
|
||||
IN BOOLEAN IPv6,
|
||||
IN EFI_IP_ADDRESS *IP,
|
||||
IN OUT EFI_MAC_ADDRESS *MAC
|
||||
)
|
||||
{
|
||||
PXE_CPB_MCAST_IP_TO_MAC *Cpb;
|
||||
PXE_DB_MCAST_IP_TO_MAC *Db;
|
||||
|
||||
Cpb = Snp->Cpb;
|
||||
Db = Snp->Db;
|
||||
Snp->Cdb.OpCode = PXE_OPCODE_MCAST_IP_TO_MAC;
|
||||
Snp->Cdb.OpFlags = (UINT16) (IPv6 ? PXE_OPFLAGS_MCAST_IPV6_TO_MAC : PXE_OPFLAGS_MCAST_IPV4_TO_MAC);
|
||||
Snp->Cdb.CPBsize = (UINT16) sizeof (PXE_CPB_MCAST_IP_TO_MAC);
|
||||
Snp->Cdb.DBsize = (UINT16) sizeof (PXE_DB_MCAST_IP_TO_MAC);
|
||||
|
||||
Snp->Cdb.CPBaddr = (UINT64)(UINTN) Cpb;
|
||||
Snp->Cdb.DBaddr = (UINT64)(UINTN) Db;
|
||||
|
||||
Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;
|
||||
Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
|
||||
Snp->Cdb.IFnum = Snp->IfNum;
|
||||
Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
|
||||
|
||||
CopyMem (&Cpb->IP, IP, sizeof (PXE_IP_ADDR));
|
||||
|
||||
//
|
||||
// Issue UNDI command and check result.
|
||||
//
|
||||
DEBUG ((EFI_D_NET, "\nSnp->undi.mcast_ip_to_mac() "));
|
||||
|
||||
(*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);
|
||||
|
||||
switch (Snp->Cdb.StatCode) {
|
||||
case PXE_STATCODE_SUCCESS:
|
||||
break;
|
||||
|
||||
case PXE_STATCODE_INVALID_CPB:
|
||||
return EFI_INVALID_PARAMETER;
|
||||
|
||||
case PXE_STATCODE_UNSUPPORTED:
|
||||
DEBUG (
|
||||
(EFI_D_NET,
|
||||
"\nSnp->undi.mcast_ip_to_mac() %xh:%xh\n",
|
||||
Snp->Cdb.StatFlags,
|
||||
Snp->Cdb.StatCode)
|
||||
);
|
||||
return EFI_UNSUPPORTED;
|
||||
|
||||
default:
|
||||
//
|
||||
// UNDI command failed. Return EFI_DEVICE_ERROR
|
||||
// to caller.
|
||||
//
|
||||
DEBUG (
|
||||
(EFI_D_NET,
|
||||
"\nSnp->undi.mcast_ip_to_mac() %xh:%xh\n",
|
||||
Snp->Cdb.StatFlags,
|
||||
Snp->Cdb.StatCode)
|
||||
);
|
||||
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
CopyMem (MAC, &Db->MAC, sizeof (PXE_MAC_ADDR));
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Converts a multicast IP address to a multicast HW MAC address.
|
||||
|
||||
This function converts a multicast IP address to a multicast HW MAC address
|
||||
for all packet transactions. If the mapping is accepted, then EFI_SUCCESS will
|
||||
be returned.
|
||||
|
||||
@param This A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
|
||||
@param IPv6 Set to TRUE if the multicast IP address is IPv6 [RFC 2460].
|
||||
Set to FALSE if the multicast IP address is IPv4 [RFC 791].
|
||||
@param IP The multicast IP address that is to be converted to a multicast
|
||||
HW MAC address.
|
||||
@param MAC The multicast HW MAC address that is to be generated from IP.
|
||||
|
||||
@retval EFI_SUCCESS The multicast IP address was mapped to the
|
||||
multicast HW MAC address.
|
||||
@retval EFI_NOT_STARTED The Simple Network Protocol interface has not
|
||||
been started by calling Start().
|
||||
@retval EFI_INVALID_PARAMETER IP is NULL.
|
||||
@retval EFI_INVALID_PARAMETER MAC is NULL.
|
||||
@retval EFI_INVALID_PARAMETER IP does not point to a valid IPv4 or IPv6
|
||||
multicast address.
|
||||
@retval EFI_DEVICE_ERROR The Simple Network Protocol interface has not
|
||||
been initialized by calling Initialize().
|
||||
@retval EFI_UNSUPPORTED IPv6 is TRUE and the implementation does not
|
||||
support IPv6 multicast to MAC address conversion.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SnpUndi32McastIpToMac (
|
||||
IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
|
||||
IN BOOLEAN IPv6,
|
||||
IN EFI_IP_ADDRESS *IP,
|
||||
OUT EFI_MAC_ADDRESS *MAC
|
||||
)
|
||||
{
|
||||
SNP_DRIVER *Snp;
|
||||
EFI_TPL OldTpl;
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Get pointer to SNP driver instance for *this.
|
||||
//
|
||||
if (This == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (IP == NULL || MAC == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
|
||||
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
|
||||
switch (Snp->Mode.State) {
|
||||
case EfiSimpleNetworkInitialized:
|
||||
break;
|
||||
|
||||
case EfiSimpleNetworkStopped:
|
||||
Status = EFI_NOT_STARTED;
|
||||
goto ON_EXIT;
|
||||
|
||||
default:
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
Status = PxeIp2Mac (Snp, IPv6, IP, MAC);
|
||||
|
||||
ON_EXIT:
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
return Status;
|
||||
}
|
217
NetworkPkg/SnpDxe/Nvdata.c
Normal file
217
NetworkPkg/SnpDxe/Nvdata.c
Normal file
@@ -0,0 +1,217 @@
|
||||
/** @file
|
||||
Implementation of reading and writing operations on the NVRAM device
|
||||
attached to a network interface.
|
||||
|
||||
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "Snp.h"
|
||||
|
||||
|
||||
/**
|
||||
This routine calls Undi to read the desired number of eeprom bytes.
|
||||
|
||||
@param Snp pointer to the snp driver structure
|
||||
@param Offset eeprom register value relative to the base address
|
||||
@param BufferSize number of bytes to read
|
||||
@param Buffer pointer where to read into
|
||||
|
||||
@retval EFI_SUCCESS The NVRAM access was performed.
|
||||
@retval EFI_INVALID_PARAMETER Invalid UNDI command.
|
||||
@retval EFI_UNSUPPORTED Command is not supported by UNDI.
|
||||
@retval EFI_DEVICE_ERROR Fail to execute UNDI command.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PxeNvDataRead (
|
||||
IN SNP_DRIVER *Snp,
|
||||
IN UINTN Offset,
|
||||
IN UINTN BufferSize,
|
||||
IN OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
PXE_DB_NVDATA *Db;
|
||||
|
||||
Db = Snp->Db;
|
||||
Snp->Cdb.OpCode = PXE_OPCODE_NVDATA;
|
||||
|
||||
Snp->Cdb.OpFlags = PXE_OPFLAGS_NVDATA_READ;
|
||||
|
||||
Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
|
||||
Snp->Cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
|
||||
|
||||
Snp->Cdb.DBsize = (UINT16) sizeof (PXE_DB_NVDATA);
|
||||
Snp->Cdb.DBaddr = (UINT64)(UINTN) Db;
|
||||
|
||||
Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;
|
||||
Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
|
||||
Snp->Cdb.IFnum = Snp->IfNum;
|
||||
Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
|
||||
|
||||
//
|
||||
// Issue UNDI command and check result.
|
||||
//
|
||||
DEBUG ((EFI_D_NET, "\nsnp->undi.nvdata () "));
|
||||
|
||||
(*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);
|
||||
|
||||
switch (Snp->Cdb.StatCode) {
|
||||
case PXE_STATCODE_SUCCESS:
|
||||
break;
|
||||
|
||||
case PXE_STATCODE_UNSUPPORTED:
|
||||
DEBUG (
|
||||
(EFI_D_NET,
|
||||
"\nsnp->undi.nvdata() %xh:%xh\n",
|
||||
Snp->Cdb.StatFlags,
|
||||
Snp->Cdb.StatCode)
|
||||
);
|
||||
|
||||
return EFI_UNSUPPORTED;
|
||||
|
||||
default:
|
||||
DEBUG (
|
||||
(EFI_D_NET,
|
||||
"\nsnp->undi.nvdata() %xh:%xh\n",
|
||||
Snp->Cdb.StatFlags,
|
||||
Snp->Cdb.StatCode)
|
||||
);
|
||||
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
ASSERT (Offset < sizeof (Db->Data));
|
||||
|
||||
CopyMem (Buffer, &Db->Data.Byte[Offset], BufferSize);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Performs read and write operations on the NVRAM device attached to a network
|
||||
interface.
|
||||
|
||||
This function performs read and write operations on the NVRAM device attached
|
||||
to a network interface. If ReadWrite is TRUE, a read operation is performed.
|
||||
If ReadWrite is FALSE, a write operation is performed. Offset specifies the
|
||||
byte offset at which to start either operation. Offset must be a multiple of
|
||||
NvRamAccessSize , and it must have a value between zero and NvRamSize.
|
||||
BufferSize specifies the length of the read or write operation. BufferSize must
|
||||
also be a multiple of NvRamAccessSize, and Offset + BufferSize must not exceed
|
||||
NvRamSize.
|
||||
If any of the above conditions is not met, then EFI_INVALID_PARAMETER will be
|
||||
returned.
|
||||
If all the conditions are met and the operation is "read," the NVRAM device
|
||||
attached to the network interface will be read into Buffer and EFI_SUCCESS
|
||||
will be returned. If this is a write operation, the contents of Buffer will be
|
||||
used to update the contents of the NVRAM device attached to the network
|
||||
interface and EFI_SUCCESS will be returned.
|
||||
|
||||
It does the basic checking on the input parameters and retrieves snp structure
|
||||
and then calls the read_nvdata() call which does the actual reading
|
||||
|
||||
@param This A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
|
||||
@param ReadWrite TRUE for read operations, FALSE for write operations.
|
||||
@param Offset Byte offset in the NVRAM device at which to start the read or
|
||||
write operation. This must be a multiple of NvRamAccessSize
|
||||
and less than NvRamSize. (See EFI_SIMPLE_NETWORK_MODE)
|
||||
@param BufferSize The number of bytes to read or write from the NVRAM device.
|
||||
This must also be a multiple of NvramAccessSize.
|
||||
@param Buffer A pointer to the data buffer.
|
||||
|
||||
@retval EFI_SUCCESS The NVRAM access was performed.
|
||||
@retval EFI_NOT_STARTED The network interface has not been started.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
|
||||
* The This parameter is NULL
|
||||
* The This parameter does not point to a valid
|
||||
EFI_SIMPLE_NETWORK_PROTOCOL structure
|
||||
* The Offset parameter is not a multiple of
|
||||
EFI_SIMPLE_NETWORK_MODE.NvRamAccessSize
|
||||
* The Offset parameter is not less than
|
||||
EFI_SIMPLE_NETWORK_MODE.NvRamSize
|
||||
* The BufferSize parameter is not a multiple of
|
||||
EFI_SIMPLE_NETWORK_MODE.NvRamAccessSize
|
||||
* The Buffer parameter is NULL
|
||||
@retval EFI_DEVICE_ERROR The command could not be sent to the network
|
||||
interface.
|
||||
@retval EFI_UNSUPPORTED This function is not supported by the network
|
||||
interface.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SnpUndi32NvData (
|
||||
IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
|
||||
IN BOOLEAN ReadWrite,
|
||||
IN UINTN Offset,
|
||||
IN UINTN BufferSize,
|
||||
IN OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
SNP_DRIVER *Snp;
|
||||
EFI_TPL OldTpl;
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Get pointer to SNP driver instance for *this.
|
||||
//
|
||||
if (This == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
|
||||
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
|
||||
//
|
||||
// Return error if the SNP is not initialized.
|
||||
//
|
||||
switch (Snp->Mode.State) {
|
||||
case EfiSimpleNetworkInitialized:
|
||||
break;
|
||||
|
||||
case EfiSimpleNetworkStopped:
|
||||
Status = EFI_NOT_STARTED;
|
||||
goto ON_EXIT;
|
||||
|
||||
default:
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
//
|
||||
// Return error if non-volatile memory variables are not valid.
|
||||
//
|
||||
if (Snp->Mode.NvRamSize == 0 || Snp->Mode.NvRamAccessSize == 0) {
|
||||
Status = EFI_UNSUPPORTED;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
//
|
||||
// Check for invalid parameter combinations.
|
||||
//
|
||||
if ((BufferSize == 0) ||
|
||||
(Buffer == NULL) ||
|
||||
(Offset >= Snp->Mode.NvRamSize) ||
|
||||
(Offset + BufferSize > Snp->Mode.NvRamSize) ||
|
||||
(BufferSize % Snp->Mode.NvRamAccessSize != 0) ||
|
||||
(Offset % Snp->Mode.NvRamAccessSize != 0)
|
||||
) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
//
|
||||
// check the implementation flags of undi if we can write the nvdata!
|
||||
//
|
||||
if (!ReadWrite) {
|
||||
Status = EFI_UNSUPPORTED;
|
||||
} else {
|
||||
Status = PxeNvDataRead (Snp, Offset, BufferSize, Buffer);
|
||||
}
|
||||
|
||||
ON_EXIT:
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
return Status;
|
||||
}
|
251
NetworkPkg/SnpDxe/Receive.c
Normal file
251
NetworkPkg/SnpDxe/Receive.c
Normal file
@@ -0,0 +1,251 @@
|
||||
/** @file
|
||||
Implementation of receiving a packet from a network interface.
|
||||
|
||||
Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
|
||||
#include "Snp.h"
|
||||
|
||||
/**
|
||||
Call UNDI to receive a packet and fills in the data in the input pointers.
|
||||
|
||||
@param Snp Pointer to snp driver structure
|
||||
@param Buffer Pointer to the memory for the received data
|
||||
@param BufferSize Pointer to the length of the buffer on entry and contains
|
||||
the length of the received data on return
|
||||
@param HeaderSize Pointer to the header portion of the data received.
|
||||
@param SrcAddr Pointer to contain the source ethernet address on return
|
||||
@param DestAddr Pointer to contain the destination ethernet address on
|
||||
return
|
||||
@param Protocol Pointer to contain the protocol type from the ethernet
|
||||
header on return
|
||||
|
||||
|
||||
@retval EFI_SUCCESS The received data was stored in Buffer, and
|
||||
BufferSize has been updated to the number of
|
||||
bytes received.
|
||||
@retval EFI_DEVICE_ERROR Fail to execute UNDI command.
|
||||
@retval EFI_NOT_READY No packets have been received on the network
|
||||
interface.
|
||||
@retval EFI_BUFFER_TOO_SMALL BufferSize is too small for the received
|
||||
packets. BufferSize has been updated to the
|
||||
required size.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PxeReceive (
|
||||
SNP_DRIVER *Snp,
|
||||
VOID *Buffer,
|
||||
UINTN *BufferSize,
|
||||
UINTN *HeaderSize,
|
||||
EFI_MAC_ADDRESS *SrcAddr,
|
||||
EFI_MAC_ADDRESS *DestAddr,
|
||||
UINT16 *Protocol
|
||||
)
|
||||
{
|
||||
PXE_CPB_RECEIVE *Cpb;
|
||||
PXE_DB_RECEIVE *Db;
|
||||
UINTN BuffSize;
|
||||
|
||||
Cpb = Snp->Cpb;
|
||||
Db = Snp->Db;
|
||||
BuffSize = *BufferSize;
|
||||
|
||||
Cpb->BufferAddr = (UINT64)(UINTN) Buffer;
|
||||
Cpb->BufferLen = (UINT32) *BufferSize;
|
||||
|
||||
Cpb->reserved = 0;
|
||||
|
||||
Snp->Cdb.OpCode = PXE_OPCODE_RECEIVE;
|
||||
Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
|
||||
|
||||
Snp->Cdb.CPBsize = (UINT16) sizeof (PXE_CPB_RECEIVE);
|
||||
Snp->Cdb.CPBaddr = (UINT64)(UINTN) Cpb;
|
||||
|
||||
Snp->Cdb.DBsize = (UINT16) sizeof (PXE_DB_RECEIVE);
|
||||
Snp->Cdb.DBaddr = (UINT64)(UINTN) Db;
|
||||
|
||||
Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;
|
||||
Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
|
||||
Snp->Cdb.IFnum = Snp->IfNum;
|
||||
Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
|
||||
|
||||
//
|
||||
// Issue UNDI command and check result.
|
||||
//
|
||||
DEBUG ((EFI_D_NET, "\nsnp->undi.receive () "));
|
||||
|
||||
(*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);
|
||||
|
||||
switch (Snp->Cdb.StatCode) {
|
||||
case PXE_STATCODE_SUCCESS:
|
||||
break;
|
||||
|
||||
case PXE_STATCODE_NO_DATA:
|
||||
DEBUG (
|
||||
(EFI_D_NET,
|
||||
"\nsnp->undi.receive () %xh:%xh\n",
|
||||
Snp->Cdb.StatFlags,
|
||||
Snp->Cdb.StatCode)
|
||||
);
|
||||
|
||||
return EFI_NOT_READY;
|
||||
|
||||
default:
|
||||
DEBUG (
|
||||
(EFI_D_ERROR,
|
||||
"\nsnp->undi.receive() %xh:%xh\n",
|
||||
Snp->Cdb.StatFlags,
|
||||
Snp->Cdb.StatCode)
|
||||
);
|
||||
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
*BufferSize = Db->FrameLen;
|
||||
|
||||
if (HeaderSize != NULL) {
|
||||
*HeaderSize = Db->MediaHeaderLen;
|
||||
}
|
||||
|
||||
if (SrcAddr != NULL) {
|
||||
CopyMem (SrcAddr, &Db->SrcAddr, Snp->Mode.HwAddressSize);
|
||||
}
|
||||
|
||||
if (DestAddr != NULL) {
|
||||
CopyMem (DestAddr, &Db->DestAddr, Snp->Mode.HwAddressSize);
|
||||
}
|
||||
|
||||
if (Protocol != NULL) {
|
||||
//
|
||||
// We need to do the byte swapping
|
||||
//
|
||||
*Protocol = (UINT16) PXE_SWAP_UINT16 (Db->Protocol);
|
||||
}
|
||||
|
||||
//
|
||||
// We have received a packet from network interface, which implies that the
|
||||
// network cable should be present. While, some UNDI driver may not report
|
||||
// correct media status during Snp->Initialize(). So, we need ensure
|
||||
// MediaPresent in SNP mode data is set to correct value.
|
||||
//
|
||||
if (Snp->Mode.MediaPresentSupported && !Snp->Mode.MediaPresent) {
|
||||
Snp->Mode.MediaPresent = TRUE;
|
||||
}
|
||||
|
||||
return (*BufferSize <= BuffSize) ? EFI_SUCCESS : EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
/**
|
||||
Receives a packet from a network interface.
|
||||
|
||||
This function retrieves one packet from the receive queue of a network interface.
|
||||
If there are no packets on the receive queue, then EFI_NOT_READY will be
|
||||
returned. If there is a packet on the receive queue, and the size of the packet
|
||||
is smaller than BufferSize, then the contents of the packet will be placed in
|
||||
Buffer, and BufferSize will be updated with the actual size of the packet.
|
||||
In addition, if SrcAddr, DestAddr, and Protocol are not NULL, then these values
|
||||
will be extracted from the media header and returned. EFI_SUCCESS will be
|
||||
returned if a packet was successfully received.
|
||||
If BufferSize is smaller than the received packet, then the size of the receive
|
||||
packet will be placed in BufferSize and EFI_BUFFER_TOO_SMALL will be returned.
|
||||
If the driver has not been initialized, EFI_DEVICE_ERROR will be returned.
|
||||
|
||||
@param This A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
|
||||
@param HeaderSize The size, in bytes, of the media header received on the network
|
||||
interface. If this parameter is NULL, then the media header size
|
||||
will not be returned.
|
||||
@param BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in
|
||||
bytes, of the packet that was received on the network interface.
|
||||
@param Buffer A pointer to the data buffer to receive both the media
|
||||
header and the data.
|
||||
@param SrcAddr The source HW MAC address. If this parameter is NULL, the HW
|
||||
MAC source address will not be extracted from the media header.
|
||||
@param DestAddr The destination HW MAC address. If this parameter is NULL,
|
||||
the HW MAC destination address will not be extracted from
|
||||
the media header.
|
||||
@param Protocol The media header type. If this parameter is NULL, then the
|
||||
protocol will not be extracted from the media header. See
|
||||
RFC 1700 section "Ether Types" for examples.
|
||||
|
||||
@retval EFI_SUCCESS The received data was stored in Buffer, and
|
||||
BufferSize has been updated to the number of
|
||||
bytes received.
|
||||
@retval EFI_NOT_STARTED The network interface has not been started.
|
||||
@retval EFI_NOT_READY No packets have been received on the network interface.
|
||||
@retval EFI_BUFFER_TOO_SMALL BufferSize is too small for the received packets.
|
||||
BufferSize has been updated to the required size.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
|
||||
* The This parameter is NULL
|
||||
* The This parameter does not point to a valid
|
||||
EFI_SIMPLE_NETWORK_PROTOCOL structure.
|
||||
* The BufferSize parameter is NULL
|
||||
* The Buffer parameter is NULL
|
||||
@retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SnpUndi32Receive (
|
||||
IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
|
||||
OUT UINTN *HeaderSize OPTIONAL,
|
||||
IN OUT UINTN *BufferSize,
|
||||
OUT VOID *Buffer,
|
||||
OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL,
|
||||
OUT EFI_MAC_ADDRESS *DestAddr OPTIONAL,
|
||||
OUT UINT16 *Protocol OPTIONAL
|
||||
)
|
||||
{
|
||||
SNP_DRIVER *Snp;
|
||||
EFI_TPL OldTpl;
|
||||
EFI_STATUS Status;
|
||||
|
||||
if (This == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
|
||||
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
|
||||
switch (Snp->Mode.State) {
|
||||
case EfiSimpleNetworkInitialized:
|
||||
break;
|
||||
|
||||
case EfiSimpleNetworkStopped:
|
||||
Status = EFI_NOT_STARTED;
|
||||
goto ON_EXIT;
|
||||
|
||||
default:
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
if ((BufferSize == NULL) || (Buffer == NULL)) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
if (Snp->Mode.ReceiveFilterSetting == 0) {
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
Status = PxeReceive (
|
||||
Snp,
|
||||
Buffer,
|
||||
BufferSize,
|
||||
HeaderSize,
|
||||
SrcAddr,
|
||||
DestAddr,
|
||||
Protocol
|
||||
);
|
||||
|
||||
ON_EXIT:
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
return Status;
|
||||
}
|
478
NetworkPkg/SnpDxe/Receive_filters.c
Normal file
478
NetworkPkg/SnpDxe/Receive_filters.c
Normal file
@@ -0,0 +1,478 @@
|
||||
/** @file
|
||||
Implementation of managing the multicast receive filters of a network
|
||||
interface.
|
||||
|
||||
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
|
||||
|
||||
#include "Snp.h"
|
||||
|
||||
/**
|
||||
Call undi to enable the receive filters.
|
||||
|
||||
@param Snp Pointer to snp driver structure.
|
||||
@param EnableFlags Bit mask for enabling the receive filters.
|
||||
@param MCastAddressCount Multicast address count for a new multicast address
|
||||
list.
|
||||
@param MCastAddressList List of new multicast addresses.
|
||||
|
||||
@retval EFI_SUCCESS The multicast receive filter list was updated.
|
||||
@retval EFI_INVALID_PARAMETER Invalid UNDI command.
|
||||
@retval EFI_UNSUPPORTED Command is not supported by UNDI.
|
||||
@retval EFI_DEVICE_ERROR Fail to execute UNDI command.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PxeRecvFilterEnable (
|
||||
SNP_DRIVER *Snp,
|
||||
UINT32 EnableFlags,
|
||||
UINTN MCastAddressCount,
|
||||
EFI_MAC_ADDRESS *MCastAddressList
|
||||
)
|
||||
{
|
||||
Snp->Cdb.OpCode = PXE_OPCODE_RECEIVE_FILTERS;
|
||||
Snp->Cdb.OpFlags = PXE_OPFLAGS_RECEIVE_FILTER_ENABLE;
|
||||
Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
|
||||
Snp->Cdb.DBsize = PXE_DBSIZE_NOT_USED;
|
||||
Snp->Cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
|
||||
Snp->Cdb.DBaddr = PXE_DBADDR_NOT_USED;
|
||||
Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;
|
||||
Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
|
||||
Snp->Cdb.IFnum = Snp->IfNum;
|
||||
Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
|
||||
|
||||
if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) != 0) {
|
||||
Snp->Cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_UNICAST;
|
||||
}
|
||||
|
||||
if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) != 0) {
|
||||
Snp->Cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST;
|
||||
}
|
||||
|
||||
if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) {
|
||||
Snp->Cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS;
|
||||
}
|
||||
|
||||
if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {
|
||||
Snp->Cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST;
|
||||
}
|
||||
|
||||
if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
|
||||
Snp->Cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST;
|
||||
}
|
||||
|
||||
if (MCastAddressCount != 0) {
|
||||
Snp->Cdb.CPBsize = (UINT16) (MCastAddressCount * sizeof (EFI_MAC_ADDRESS));
|
||||
Snp->Cdb.CPBaddr = (UINT64)(UINTN)Snp->Cpb;
|
||||
CopyMem (Snp->Cpb, MCastAddressList, Snp->Cdb.CPBsize);
|
||||
}
|
||||
//
|
||||
// Issue UNDI command and check result.
|
||||
//
|
||||
DEBUG ((EFI_D_NET, "\nsnp->undi.receive_filters() "));
|
||||
|
||||
(*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);
|
||||
|
||||
if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {
|
||||
//
|
||||
// UNDI command failed. Return UNDI status to caller.
|
||||
//
|
||||
DEBUG (
|
||||
(EFI_D_ERROR,
|
||||
"\nsnp->undi.receive_filters() %xh:%xh\n",
|
||||
Snp->Cdb.StatFlags,
|
||||
Snp->Cdb.StatCode)
|
||||
);
|
||||
|
||||
switch (Snp->Cdb.StatCode) {
|
||||
case PXE_STATCODE_INVALID_CDB:
|
||||
case PXE_STATCODE_INVALID_CPB:
|
||||
case PXE_STATCODE_INVALID_PARAMETER:
|
||||
return EFI_INVALID_PARAMETER;
|
||||
|
||||
case PXE_STATCODE_UNSUPPORTED:
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Call undi to disable the receive filters.
|
||||
|
||||
@param Snp Pointer to snp driver structure
|
||||
@param DisableFlags Bit mask for disabling the receive filters
|
||||
@param ResetMCastList Boolean flag to reset/delete the multicast filter
|
||||
list.
|
||||
|
||||
@retval EFI_SUCCESS The multicast receive filter list was updated.
|
||||
@retval EFI_DEVICE_ERROR Fail to execute UNDI command.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PxeRecvFilterDisable (
|
||||
SNP_DRIVER *Snp,
|
||||
UINT32 DisableFlags,
|
||||
BOOLEAN ResetMCastList
|
||||
)
|
||||
{
|
||||
Snp->Cdb.OpCode = PXE_OPCODE_RECEIVE_FILTERS;
|
||||
Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
|
||||
Snp->Cdb.DBsize = PXE_DBSIZE_NOT_USED;
|
||||
Snp->Cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
|
||||
Snp->Cdb.DBaddr = PXE_DBADDR_NOT_USED;
|
||||
Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;
|
||||
Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
|
||||
Snp->Cdb.IFnum = Snp->IfNum;
|
||||
Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
|
||||
|
||||
Snp->Cdb.OpFlags = (UINT16) ((DisableFlags != 0) ? PXE_OPFLAGS_RECEIVE_FILTER_DISABLE : PXE_OPFLAGS_NOT_USED);
|
||||
|
||||
if (ResetMCastList) {
|
||||
Snp->Cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST;
|
||||
}
|
||||
|
||||
if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) != 0) {
|
||||
Snp->Cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_UNICAST;
|
||||
}
|
||||
|
||||
if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) != 0) {
|
||||
Snp->Cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST;
|
||||
}
|
||||
|
||||
if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) {
|
||||
Snp->Cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS;
|
||||
}
|
||||
|
||||
if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) {
|
||||
Snp->Cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST;
|
||||
}
|
||||
|
||||
if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) {
|
||||
Snp->Cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST;
|
||||
}
|
||||
//
|
||||
// Issue UNDI command and check result.
|
||||
//
|
||||
DEBUG ((EFI_D_NET, "\nsnp->undi.receive_filters() "));
|
||||
|
||||
(*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);
|
||||
|
||||
if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {
|
||||
//
|
||||
// UNDI command failed. Return UNDI status to caller.
|
||||
//
|
||||
DEBUG (
|
||||
(EFI_D_ERROR,
|
||||
"\nsnp->undi.receive_filters() %xh:%xh\n",
|
||||
Snp->Cdb.StatFlags,
|
||||
Snp->Cdb.StatCode)
|
||||
);
|
||||
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Call undi to read the receive filters.
|
||||
|
||||
@param Snp Pointer to snp driver structure.
|
||||
|
||||
@retval EFI_SUCCESS The receive filter was read.
|
||||
@retval EFI_DEVICE_ERROR Fail to execute UNDI command.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PxeRecvFilterRead (
|
||||
SNP_DRIVER *Snp
|
||||
)
|
||||
{
|
||||
Snp->Cdb.OpCode = PXE_OPCODE_RECEIVE_FILTERS;
|
||||
Snp->Cdb.OpFlags = PXE_OPFLAGS_RECEIVE_FILTER_READ;
|
||||
Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
|
||||
Snp->Cdb.DBsize = (UINT16) (Snp->Mode.MaxMCastFilterCount * sizeof (EFI_MAC_ADDRESS));
|
||||
Snp->Cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
|
||||
if (Snp->Cdb.DBsize == 0) {
|
||||
Snp->Cdb.DBaddr = (UINT64)(UINTN) NULL;
|
||||
} else {
|
||||
Snp->Cdb.DBaddr = (UINT64)(UINTN) Snp->Db;
|
||||
ZeroMem (Snp->Db, Snp->Cdb.DBsize);
|
||||
}
|
||||
|
||||
Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;
|
||||
Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
|
||||
Snp->Cdb.IFnum = Snp->IfNum;
|
||||
Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
|
||||
|
||||
DEBUG ((EFI_D_NET, "\nsnp->undi.receive_filters() "));
|
||||
|
||||
(*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);
|
||||
|
||||
if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {
|
||||
//
|
||||
// UNDI command failed. Return UNDI status to caller.
|
||||
//
|
||||
DEBUG (
|
||||
(EFI_D_ERROR,
|
||||
"\nsnp->undi.receive_filters() %xh:%xh\n",
|
||||
Snp->Cdb.StatFlags,
|
||||
Snp->Cdb.StatCode)
|
||||
);
|
||||
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
//
|
||||
// Convert UNDI32 StatFlags to EFI SNP filter flags.
|
||||
//
|
||||
Snp->Mode.ReceiveFilterSetting = 0;
|
||||
|
||||
if ((Snp->Cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_UNICAST) != 0) {
|
||||
Snp->Mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
|
||||
}
|
||||
|
||||
if ((Snp->Cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_BROADCAST) != 0) {
|
||||
Snp->Mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
|
||||
}
|
||||
|
||||
if ((Snp->Cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_PROMISCUOUS) != 0) {
|
||||
Snp->Mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
|
||||
}
|
||||
|
||||
if ((Snp->Cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_ALL_MULTICAST) != 0) {
|
||||
Snp->Mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
|
||||
}
|
||||
|
||||
if ((Snp->Cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) != 0) {
|
||||
Snp->Mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;
|
||||
}
|
||||
|
||||
CopyMem (Snp->Mode.MCastFilter, Snp->Db, Snp->Cdb.DBsize);
|
||||
|
||||
//
|
||||
// Count number of active entries in multicast filter list.
|
||||
//
|
||||
{
|
||||
EFI_MAC_ADDRESS ZeroMacAddr;
|
||||
|
||||
SetMem (&ZeroMacAddr, sizeof ZeroMacAddr, 0);
|
||||
|
||||
for (Snp->Mode.MCastFilterCount = 0;
|
||||
Snp->Mode.MCastFilterCount < Snp->Mode.MaxMCastFilterCount;
|
||||
Snp->Mode.MCastFilterCount++
|
||||
) {
|
||||
if (CompareMem (
|
||||
&Snp->Mode.MCastFilter[Snp->Mode.MCastFilterCount],
|
||||
&ZeroMacAddr,
|
||||
sizeof ZeroMacAddr
|
||||
) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Manages the multicast receive filters of a network interface.
|
||||
|
||||
This function is used enable and disable the hardware and software receive
|
||||
filters for the underlying network device.
|
||||
The receive filter change is broken down into three steps:
|
||||
* The filter mask bits that are set (ON) in the Enable parameter are added to
|
||||
the current receive filter settings.
|
||||
* The filter mask bits that are set (ON) in the Disable parameter are subtracted
|
||||
from the updated receive filter settings.
|
||||
* If the resulting receive filter setting is not supported by the hardware a
|
||||
more liberal setting is selected.
|
||||
If the same bits are set in the Enable and Disable parameters, then the bits
|
||||
in the Disable parameter takes precedence.
|
||||
If the ResetMCastFilter parameter is TRUE, then the multicast address list
|
||||
filter is disabled (irregardless of what other multicast bits are set in the
|
||||
Enable and Disable parameters). The SNP->Mode->MCastFilterCount field is set
|
||||
to zero. The Snp->Mode->MCastFilter contents are undefined.
|
||||
After enabling or disabling receive filter settings, software should verify
|
||||
the new settings by checking the Snp->Mode->ReceiveFilterSettings,
|
||||
Snp->Mode->MCastFilterCount and Snp->Mode->MCastFilter fields.
|
||||
Note: Some network drivers and/or devices will automatically promote receive
|
||||
filter settings if the requested setting can not be honored. For example, if
|
||||
a request for four multicast addresses is made and the underlying hardware
|
||||
only supports two multicast addresses the driver might set the promiscuous
|
||||
or promiscuous multicast receive filters instead. The receiving software is
|
||||
responsible for discarding any extra packets that get through the hardware
|
||||
receive filters.
|
||||
Note: Note: To disable all receive filter hardware, the network driver must
|
||||
be Shutdown() and Stopped(). Calling ReceiveFilters() with Disable set to
|
||||
Snp->Mode->ReceiveFilterSettings will make it so no more packets are
|
||||
returned by the Receive() function, but the receive hardware may still be
|
||||
moving packets into system memory before inspecting and discarding them.
|
||||
Unexpected system errors, reboots and hangs can occur if an OS is loaded
|
||||
and the network devices are not Shutdown() and Stopped().
|
||||
If ResetMCastFilter is TRUE, then the multicast receive filter list on the
|
||||
network interface will be reset to the default multicast receive filter list.
|
||||
If ResetMCastFilter is FALSE, and this network interface allows the multicast
|
||||
receive filter list to be modified, then the MCastFilterCnt and MCastFilter
|
||||
are used to update the current multicast receive filter list. The modified
|
||||
receive filter list settings can be found in the MCastFilter field of
|
||||
EFI_SIMPLE_NETWORK_MODE. If the network interface does not allow the multicast
|
||||
receive filter list to be modified, then EFI_INVALID_PARAMETER will be returned.
|
||||
If the driver has not been initialized, EFI_DEVICE_ERROR will be returned.
|
||||
If the receive filter mask and multicast receive filter list have been
|
||||
successfully updated on the network interface, EFI_SUCCESS will be returned.
|
||||
|
||||
@param This A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
|
||||
@param Enable A bit mask of receive filters to enable on the network
|
||||
interface.
|
||||
@param Disable A bit mask of receive filters to disable on the network
|
||||
interface. For backward compatibility with EFI 1.1
|
||||
platforms, the EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit
|
||||
must be set when the ResetMCastFilter parameter is TRUE.
|
||||
@param ResetMCastFilter Set to TRUE to reset the contents of the multicast
|
||||
receive filters on the network interface to their
|
||||
default values.
|
||||
@param MCastFilterCnt Number of multicast HW MAC addresses in the new MCastFilter
|
||||
list. This value must be less than or equal to the
|
||||
MCastFilterCnt field of EFI_SIMPLE_NETWORK_MODE.
|
||||
This field is optional if ResetMCastFilter is TRUE.
|
||||
@param MCastFilter A pointer to a list of new multicast receive filter HW
|
||||
MAC addresses. This list will replace any existing
|
||||
multicast HW MAC address list. This field is optional
|
||||
if ResetMCastFilter is TRUE.
|
||||
|
||||
@retval EFI_SUCCESS The multicast receive filter list was updated.
|
||||
@retval EFI_NOT_STARTED The network interface has not been started.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
|
||||
* This is NULL
|
||||
* There are bits set in Enable that are not set
|
||||
in Snp->Mode->ReceiveFilterMask
|
||||
* There are bits set in Disable that are not set
|
||||
in Snp->Mode->ReceiveFilterMask
|
||||
* Multicast is being enabled (the
|
||||
EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST bit is
|
||||
set in Enable, it is not set in Disable, and
|
||||
ResetMCastFilter is FALSE) and MCastFilterCount
|
||||
is zero
|
||||
* Multicast is being enabled and MCastFilterCount
|
||||
is greater than Snp->Mode->MaxMCastFilterCount
|
||||
* Multicast is being enabled and MCastFilter is NULL
|
||||
* Multicast is being enabled and one or more of
|
||||
the addresses in the MCastFilter list are not
|
||||
valid multicast MAC addresses
|
||||
@retval EFI_DEVICE_ERROR One or more of the following conditions is TRUE:
|
||||
* The network interface has been started but has
|
||||
not been initialized
|
||||
* An unexpected error was returned by the
|
||||
underlying network driver or device
|
||||
@retval EFI_UNSUPPORTED This function is not supported by the network
|
||||
interface.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SnpUndi32ReceiveFilters (
|
||||
IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
|
||||
IN UINT32 Enable,
|
||||
IN UINT32 Disable,
|
||||
IN BOOLEAN ResetMCastFilter,
|
||||
IN UINTN MCastFilterCnt, OPTIONAL
|
||||
IN EFI_MAC_ADDRESS *MCastFilter OPTIONAL
|
||||
)
|
||||
{
|
||||
SNP_DRIVER *Snp;
|
||||
EFI_STATUS Status;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
if (This == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
|
||||
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
|
||||
switch (Snp->Mode.State) {
|
||||
case EfiSimpleNetworkInitialized:
|
||||
break;
|
||||
|
||||
case EfiSimpleNetworkStopped:
|
||||
Status = EFI_NOT_STARTED;
|
||||
goto ON_EXIT;
|
||||
|
||||
default:
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
//
|
||||
// check if we are asked to enable or disable something that the UNDI
|
||||
// does not even support!
|
||||
//
|
||||
if (((Enable &~Snp->Mode.ReceiveFilterMask) != 0) ||
|
||||
((Disable &~Snp->Mode.ReceiveFilterMask) != 0)) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
if (ResetMCastFilter) {
|
||||
|
||||
Disable |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST & Snp->Mode.ReceiveFilterMask;
|
||||
MCastFilterCnt = 0;
|
||||
MCastFilter = NULL;
|
||||
} else {
|
||||
if (MCastFilterCnt != 0) {
|
||||
if ((MCastFilterCnt > Snp->Mode.MaxMCastFilterCount) ||
|
||||
(MCastFilter == NULL)) {
|
||||
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Enable == 0 && Disable == 0 && !ResetMCastFilter && MCastFilterCnt == 0) {
|
||||
Status = EFI_SUCCESS;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
if ((Enable & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0 && MCastFilterCnt == 0) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
if ((Enable != 0) || (MCastFilterCnt != 0)) {
|
||||
Status = PxeRecvFilterEnable (
|
||||
Snp,
|
||||
Enable,
|
||||
MCastFilterCnt,
|
||||
MCastFilter
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
if ((Disable != 0) || ResetMCastFilter) {
|
||||
Status = PxeRecvFilterDisable (Snp, Disable, ResetMCastFilter);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
Status = PxeRecvFilterRead (Snp);
|
||||
|
||||
ON_EXIT:
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
return Status;
|
||||
}
|
130
NetworkPkg/SnpDxe/Reset.c
Normal file
130
NetworkPkg/SnpDxe/Reset.c
Normal file
@@ -0,0 +1,130 @@
|
||||
/** @file
|
||||
Implementation of resetting a network adapter.
|
||||
|
||||
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "Snp.h"
|
||||
|
||||
|
||||
/**
|
||||
Call UNDI to reset the NIC.
|
||||
|
||||
@param Snp Pointer to the snp driver structure.
|
||||
|
||||
@return EFI_SUCCESSFUL The NIC was reset.
|
||||
@retval EFI_DEVICE_ERROR The NIC cannot be reset.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PxeReset (
|
||||
SNP_DRIVER *Snp
|
||||
)
|
||||
{
|
||||
Snp->Cdb.OpCode = PXE_OPCODE_RESET;
|
||||
Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
|
||||
Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
|
||||
Snp->Cdb.DBsize = PXE_DBSIZE_NOT_USED;
|
||||
Snp->Cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
|
||||
Snp->Cdb.DBaddr = PXE_DBADDR_NOT_USED;
|
||||
Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;
|
||||
Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
|
||||
Snp->Cdb.IFnum = Snp->IfNum;
|
||||
Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
|
||||
|
||||
//
|
||||
// Issue UNDI command and check result.
|
||||
//
|
||||
DEBUG ((EFI_D_NET, "\nsnp->undi.reset() "));
|
||||
|
||||
(*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);
|
||||
|
||||
if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {
|
||||
DEBUG (
|
||||
(EFI_D_WARN,
|
||||
"\nsnp->undi32.reset() %xh:%xh\n",
|
||||
Snp->Cdb.StatFlags,
|
||||
Snp->Cdb.StatCode)
|
||||
);
|
||||
|
||||
//
|
||||
// UNDI could not be reset. Return UNDI error.
|
||||
//
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Resets a network adapter and reinitializes it with the parameters that were
|
||||
provided in the previous call to Initialize().
|
||||
|
||||
This function resets a network adapter and reinitializes it with the parameters
|
||||
that were provided in the previous call to Initialize(). The transmit and
|
||||
receive queues are emptied and all pending interrupts are cleared.
|
||||
Receive filters, the station address, the statistics, and the multicast-IP-to-HW
|
||||
MAC addresses are not reset by this call. If the network interface was
|
||||
successfully reset, then EFI_SUCCESS will be returned. If the driver has not
|
||||
been initialized, EFI_DEVICE_ERROR will be returned.
|
||||
|
||||
@param This A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
|
||||
@param ExtendedVerification Indicates that the driver may perform a more
|
||||
exhaustive verification operation of the device
|
||||
during reset.
|
||||
|
||||
@retval EFI_SUCCESS The network interface was reset.
|
||||
@retval EFI_NOT_STARTED The network interface has not been started.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value.
|
||||
@retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
|
||||
@retval EFI_UNSUPPORTED This function is not supported by the network interface.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SnpUndi32Reset (
|
||||
IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
|
||||
IN BOOLEAN ExtendedVerification
|
||||
)
|
||||
{
|
||||
SNP_DRIVER *Snp;
|
||||
EFI_TPL OldTpl;
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Resolve Warning 4 unreferenced parameter problem
|
||||
//
|
||||
ExtendedVerification = 0;
|
||||
DEBUG ((EFI_D_WARN, "ExtendedVerification = %d is not implemented!\n", ExtendedVerification));
|
||||
|
||||
if (This == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
|
||||
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
|
||||
switch (Snp->Mode.State) {
|
||||
case EfiSimpleNetworkInitialized:
|
||||
break;
|
||||
|
||||
case EfiSimpleNetworkStopped:
|
||||
Status = EFI_NOT_STARTED;
|
||||
goto ON_EXIT;
|
||||
|
||||
default:
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
Status = PxeReset (Snp);
|
||||
|
||||
ON_EXIT:
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
return Status;
|
||||
}
|
146
NetworkPkg/SnpDxe/Shutdown.c
Normal file
146
NetworkPkg/SnpDxe/Shutdown.c
Normal file
@@ -0,0 +1,146 @@
|
||||
/** @file
|
||||
Implementation of shuting down a network adapter.
|
||||
|
||||
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "Snp.h"
|
||||
|
||||
|
||||
/**
|
||||
Call UNDI to shut down the interface.
|
||||
|
||||
@param Snp Pointer to snp driver structure.
|
||||
|
||||
@retval EFI_SUCCESS UNDI is shut down successfully.
|
||||
@retval EFI_DEVICE_ERROR UNDI could not be shut down.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PxeShutdown (
|
||||
IN SNP_DRIVER *Snp
|
||||
)
|
||||
{
|
||||
Snp->Cdb.OpCode = PXE_OPCODE_SHUTDOWN;
|
||||
Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
|
||||
Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
|
||||
Snp->Cdb.DBsize = PXE_DBSIZE_NOT_USED;
|
||||
Snp->Cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
|
||||
Snp->Cdb.DBaddr = PXE_DBADDR_NOT_USED;
|
||||
Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;
|
||||
Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
|
||||
Snp->Cdb.IFnum = Snp->IfNum;
|
||||
Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
|
||||
|
||||
//
|
||||
// Issue UNDI command and check result.
|
||||
//
|
||||
DEBUG ((EFI_D_NET, "\nsnp->undi.shutdown() "));
|
||||
|
||||
(*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);
|
||||
|
||||
if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {
|
||||
//
|
||||
// UNDI could not be shutdown. Return UNDI error.
|
||||
//
|
||||
DEBUG ((EFI_D_WARN, "\nsnp->undi.shutdown() %xh:%xh\n", Snp->Cdb.StatFlags, Snp->Cdb.StatCode));
|
||||
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
//
|
||||
// Free allocated memory.
|
||||
//
|
||||
if (Snp->TxRxBuffer != NULL) {
|
||||
Snp->PciIo->FreeBuffer (
|
||||
Snp->PciIo,
|
||||
SNP_MEM_PAGES (Snp->TxRxBufferSize),
|
||||
(VOID *) Snp->TxRxBuffer
|
||||
);
|
||||
}
|
||||
|
||||
Snp->TxRxBuffer = NULL;
|
||||
Snp->TxRxBufferSize = 0;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Resets a network adapter and leaves it in a state that is safe for another
|
||||
driver to initialize.
|
||||
|
||||
This function releases the memory buffers assigned in the Initialize() call.
|
||||
Pending transmits and receives are lost, and interrupts are cleared and disabled.
|
||||
After this call, only the Initialize() and Stop() calls may be used. If the
|
||||
network interface was successfully shutdown, then EFI_SUCCESS will be returned.
|
||||
If the driver has not been initialized, EFI_DEVICE_ERROR will be returned.
|
||||
|
||||
@param This A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
|
||||
|
||||
@retval EFI_SUCCESS The network interface was shutdown.
|
||||
@retval EFI_NOT_STARTED The network interface has not been started.
|
||||
@retval EFI_INVALID_PARAMETER This parameter was NULL or did not point to a valid
|
||||
EFI_SIMPLE_NETWORK_PROTOCOL structure.
|
||||
@retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SnpUndi32Shutdown (
|
||||
IN EFI_SIMPLE_NETWORK_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
SNP_DRIVER *Snp;
|
||||
EFI_STATUS Status;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
//
|
||||
// Get pointer to SNP driver instance for *This.
|
||||
//
|
||||
if (This == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
|
||||
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
|
||||
//
|
||||
// Return error if the SNP is not initialized.
|
||||
//
|
||||
switch (Snp->Mode.State) {
|
||||
case EfiSimpleNetworkInitialized:
|
||||
break;
|
||||
|
||||
case EfiSimpleNetworkStopped:
|
||||
Status = EFI_NOT_STARTED;
|
||||
goto ON_EXIT;
|
||||
|
||||
default:
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
Status = PxeShutdown (Snp);
|
||||
|
||||
Snp->Mode.State = EfiSimpleNetworkStarted;
|
||||
Snp->Mode.ReceiveFilterSetting = 0;
|
||||
|
||||
Snp->Mode.MCastFilterCount = 0;
|
||||
Snp->Mode.ReceiveFilterSetting = 0;
|
||||
ZeroMem (Snp->Mode.MCastFilter, sizeof Snp->Mode.MCastFilter);
|
||||
CopyMem (
|
||||
&Snp->Mode.CurrentAddress,
|
||||
&Snp->Mode.PermanentAddress,
|
||||
sizeof (EFI_MAC_ADDRESS)
|
||||
);
|
||||
|
||||
gBS->CloseEvent (Snp->Snp.WaitForPacket);
|
||||
|
||||
ON_EXIT:
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
return Status;
|
||||
}
|
862
NetworkPkg/SnpDxe/Snp.c
Normal file
862
NetworkPkg/SnpDxe/Snp.c
Normal file
@@ -0,0 +1,862 @@
|
||||
/** @file
|
||||
Implementation of driver entry point and driver binding protocol.
|
||||
|
||||
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "Snp.h"
|
||||
|
||||
/**
|
||||
One notified function to stop UNDI device when gBS->ExitBootServices() called.
|
||||
|
||||
@param Event Pointer to this event
|
||||
@param Context Event handler private data
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SnpNotifyExitBootServices (
|
||||
EFI_EVENT Event,
|
||||
VOID *Context
|
||||
)
|
||||
{
|
||||
SNP_DRIVER *Snp;
|
||||
|
||||
Snp = (SNP_DRIVER *)Context;
|
||||
|
||||
//
|
||||
// Shutdown and stop UNDI driver
|
||||
//
|
||||
PxeShutdown (Snp);
|
||||
PxeStop (Snp);
|
||||
}
|
||||
|
||||
/**
|
||||
Send command to UNDI. It does nothing currently.
|
||||
|
||||
@param Cdb command to be sent to UNDI.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The command is 0.
|
||||
@retval EFI_UNSUPPORTED Default return status because it's not
|
||||
supported currently.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
IssueHwUndiCommand (
|
||||
UINT64 Cdb
|
||||
)
|
||||
{
|
||||
DEBUG ((EFI_D_ERROR, "\nIssueHwUndiCommand() - This should not be called!"));
|
||||
|
||||
if (Cdb == 0) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
|
||||
}
|
||||
//
|
||||
// %%TBD - For now, nothing is done.
|
||||
//
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Compute 8-bit checksum of a buffer.
|
||||
|
||||
@param Buffer Pointer to buffer.
|
||||
@param Length Length of buffer in bytes.
|
||||
|
||||
@return 8-bit checksum of all bytes in buffer, or zero if ptr is NULL or len
|
||||
is zero.
|
||||
|
||||
**/
|
||||
UINT8
|
||||
Calc8BitCksum (
|
||||
VOID *Buffer,
|
||||
UINTN Length
|
||||
)
|
||||
{
|
||||
UINT8 *Ptr;
|
||||
UINT8 Cksum;
|
||||
|
||||
Ptr = Buffer;
|
||||
Cksum = 0;
|
||||
|
||||
if (Ptr == NULL || Length == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (Length-- != 0) {
|
||||
Cksum = (UINT8) (Cksum + *Ptr++);
|
||||
}
|
||||
|
||||
return Cksum;
|
||||
}
|
||||
|
||||
/**
|
||||
Test to see if this driver supports ControllerHandle. This service
|
||||
is called by the EFI boot service ConnectController(). In
|
||||
order to make drivers as small as possible, there are a few calling
|
||||
restrictions for this service. ConnectController() must
|
||||
follow these calling restrictions. If any other agent wishes to call
|
||||
Supported() it must also follow these calling restrictions.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ControllerHandle Handle of device to test.
|
||||
@param 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
|
||||
SimpleNetworkDriverSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NiiProtocol;
|
||||
PXE_UNDI *Pxe;
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
Controller,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
NULL,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
Controller,
|
||||
&gEfiNetworkInterfaceIdentifierProtocolGuid_31,
|
||||
(VOID **) &NiiProtocol,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_BY_DRIVER
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
if (Status == EFI_ALREADY_STARTED) {
|
||||
DEBUG ((EFI_D_INFO, "Support(): Already Started. on handle %p\n", Controller));
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
DEBUG ((EFI_D_INFO, "Support(): UNDI3.1 found on handle %p\n", Controller));
|
||||
|
||||
//
|
||||
// check the version, we don't want to connect to the undi16
|
||||
//
|
||||
if (NiiProtocol->Type != EfiNetworkInterfaceUndi) {
|
||||
Status = EFI_UNSUPPORTED;
|
||||
goto Done;
|
||||
}
|
||||
//
|
||||
// Check to see if !PXE structure is valid. Paragraph alignment of !PXE structure is required.
|
||||
//
|
||||
if ((NiiProtocol->Id & 0x0F) != 0) {
|
||||
DEBUG ((EFI_D_NET, "\n!PXE structure is not paragraph aligned.\n"));
|
||||
Status = EFI_UNSUPPORTED;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
Pxe = (PXE_UNDI *) (UINTN) (NiiProtocol->Id);
|
||||
|
||||
//
|
||||
// Verify !PXE revisions.
|
||||
//
|
||||
if (Pxe->hw.Signature != PXE_ROMID_SIGNATURE) {
|
||||
DEBUG ((EFI_D_NET, "\n!PXE signature is not valid.\n"));
|
||||
Status = EFI_UNSUPPORTED;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
if (Pxe->hw.Rev < PXE_ROMID_REV) {
|
||||
DEBUG ((EFI_D_NET, "\n!PXE.Rev is not supported.\n"));
|
||||
Status = EFI_UNSUPPORTED;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
if (Pxe->hw.MajorVer < PXE_ROMID_MAJORVER) {
|
||||
|
||||
DEBUG ((EFI_D_NET, "\n!PXE.MajorVer is not supported.\n"));
|
||||
Status = EFI_UNSUPPORTED;
|
||||
goto Done;
|
||||
|
||||
} else if (Pxe->hw.MajorVer == PXE_ROMID_MAJORVER && Pxe->hw.MinorVer < PXE_ROMID_MINORVER) {
|
||||
DEBUG ((EFI_D_NET, "\n!PXE.MinorVer is not supported."));
|
||||
Status = EFI_UNSUPPORTED;
|
||||
goto Done;
|
||||
}
|
||||
//
|
||||
// Do S/W UNDI specific checks.
|
||||
//
|
||||
if ((Pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) == 0) {
|
||||
if (Pxe->sw.EntryPoint < Pxe->sw.Len) {
|
||||
DEBUG ((EFI_D_NET, "\n!PXE S/W entry point is not valid."));
|
||||
Status = EFI_UNSUPPORTED;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
if (Pxe->sw.BusCnt == 0) {
|
||||
DEBUG ((EFI_D_NET, "\n!PXE.BusCnt is zero."));
|
||||
Status = EFI_UNSUPPORTED;
|
||||
goto Done;
|
||||
}
|
||||
}
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
DEBUG ((EFI_D_INFO, "Support(): supported on %p\n", Controller));
|
||||
|
||||
Done:
|
||||
gBS->CloseProtocol (
|
||||
Controller,
|
||||
&gEfiNetworkInterfaceIdentifierProtocolGuid_31,
|
||||
This->DriverBindingHandle,
|
||||
Controller
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Start this driver on ControllerHandle. This service is called by the
|
||||
EFI boot service ConnectController(). In order to make
|
||||
drivers as small as possible, there are a few calling restrictions for
|
||||
this service. ConnectController() must follow these
|
||||
calling restrictions. If any other agent wishes to call Start() it
|
||||
must also follow these calling restrictions.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ControllerHandle Handle of device to bind driver to.
|
||||
@param 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 other This driver does not support this device
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SimpleNetworkDriverStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||
)
|
||||
{
|
||||
EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *Nii;
|
||||
EFI_DEVICE_PATH_PROTOCOL *NiiDevicePath;
|
||||
EFI_STATUS Status;
|
||||
PXE_UNDI *Pxe;
|
||||
SNP_DRIVER *Snp;
|
||||
VOID *Address;
|
||||
EFI_HANDLE Handle;
|
||||
UINT8 BarIndex;
|
||||
PXE_STATFLAGS InitStatFlags;
|
||||
EFI_PCI_IO_PROTOCOL *PciIo;
|
||||
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *BarDesc;
|
||||
BOOLEAN FoundIoBar;
|
||||
BOOLEAN FoundMemoryBar;
|
||||
|
||||
DEBUG ((EFI_D_NET, "\nSnpNotifyNetworkInterfaceIdentifier() "));
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
Controller,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
(VOID **) &NiiDevicePath,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_BY_DRIVER
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = gBS->LocateDevicePath (
|
||||
&gEfiPciIoProtocolGuid,
|
||||
&NiiDevicePath,
|
||||
&Handle
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
Handle,
|
||||
&gEfiPciIoProtocolGuid,
|
||||
(VOID **) &PciIo,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
//
|
||||
// Get the NII interface.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
Controller,
|
||||
&gEfiNetworkInterfaceIdentifierProtocolGuid_31,
|
||||
(VOID **) &Nii,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_BY_DRIVER
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
gBS->CloseProtocol (
|
||||
Controller,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
This->DriverBindingHandle,
|
||||
Controller
|
||||
);
|
||||
return Status;
|
||||
}
|
||||
|
||||
DEBUG ((EFI_D_INFO, "Start(): UNDI3.1 found\n"));
|
||||
|
||||
Pxe = (PXE_UNDI *) (UINTN) (Nii->Id);
|
||||
|
||||
if (Calc8BitCksum (Pxe, Pxe->hw.Len) != 0) {
|
||||
DEBUG ((EFI_D_NET, "\n!PXE checksum is not correct.\n"));
|
||||
goto NiiError;
|
||||
}
|
||||
|
||||
if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) {
|
||||
//
|
||||
// We can get any packets.
|
||||
//
|
||||
} else if ((Pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) {
|
||||
//
|
||||
// We need to be able to get broadcast packets for DHCP.
|
||||
// If we do not have promiscuous support, we must at least have
|
||||
// broadcast support or we cannot do DHCP!
|
||||
//
|
||||
} else {
|
||||
DEBUG ((EFI_D_NET, "\nUNDI does not have promiscuous or broadcast support."));
|
||||
goto NiiError;
|
||||
}
|
||||
//
|
||||
// OK, we like this UNDI, and we know snp is not already there on this handle
|
||||
// Allocate and initialize a new simple network protocol structure.
|
||||
//
|
||||
Status = PciIo->AllocateBuffer (
|
||||
PciIo,
|
||||
AllocateAnyPages,
|
||||
EfiBootServicesData,
|
||||
SNP_MEM_PAGES (sizeof (SNP_DRIVER)),
|
||||
&Address,
|
||||
0
|
||||
);
|
||||
|
||||
if (Status != EFI_SUCCESS) {
|
||||
DEBUG ((EFI_D_NET, "\nCould not allocate SNP_DRIVER structure.\n"));
|
||||
goto NiiError;
|
||||
}
|
||||
|
||||
Snp = (SNP_DRIVER *) (UINTN) Address;
|
||||
|
||||
ZeroMem (Snp, sizeof (SNP_DRIVER));
|
||||
|
||||
Snp->PciIo = PciIo;
|
||||
Snp->Signature = SNP_DRIVER_SIGNATURE;
|
||||
|
||||
EfiInitializeLock (&Snp->Lock, TPL_NOTIFY);
|
||||
|
||||
Snp->Snp.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
|
||||
Snp->Snp.Start = SnpUndi32Start;
|
||||
Snp->Snp.Stop = SnpUndi32Stop;
|
||||
Snp->Snp.Initialize = SnpUndi32Initialize;
|
||||
Snp->Snp.Reset = SnpUndi32Reset;
|
||||
Snp->Snp.Shutdown = SnpUndi32Shutdown;
|
||||
Snp->Snp.ReceiveFilters = SnpUndi32ReceiveFilters;
|
||||
Snp->Snp.StationAddress = SnpUndi32StationAddress;
|
||||
Snp->Snp.Statistics = SnpUndi32Statistics;
|
||||
Snp->Snp.MCastIpToMac = SnpUndi32McastIpToMac;
|
||||
Snp->Snp.NvData = SnpUndi32NvData;
|
||||
Snp->Snp.GetStatus = SnpUndi32GetStatus;
|
||||
Snp->Snp.Transmit = SnpUndi32Transmit;
|
||||
Snp->Snp.Receive = SnpUndi32Receive;
|
||||
Snp->Snp.WaitForPacket = NULL;
|
||||
|
||||
Snp->Snp.Mode = &Snp->Mode;
|
||||
|
||||
Snp->TxRxBufferSize = 0;
|
||||
Snp->TxRxBuffer = NULL;
|
||||
|
||||
Snp->RecycledTxBuf = AllocatePool (sizeof (UINT64) * SNP_TX_BUFFER_INCREASEMENT);
|
||||
if (Snp->RecycledTxBuf == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto Error_DeleteSNP;
|
||||
}
|
||||
Snp->MaxRecycledTxBuf = SNP_TX_BUFFER_INCREASEMENT;
|
||||
Snp->RecycledTxBufCount = 0;
|
||||
|
||||
if (Nii->Revision >= EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION) {
|
||||
Snp->IfNum = Nii->IfNum;
|
||||
|
||||
} else {
|
||||
Snp->IfNum = (UINT8) (Nii->IfNum & 0xFF);
|
||||
}
|
||||
|
||||
if ((Pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) != 0) {
|
||||
Snp->IsSwUndi = FALSE;
|
||||
Snp->IssueUndi32Command = &IssueHwUndiCommand;
|
||||
} else {
|
||||
Snp->IsSwUndi = TRUE;
|
||||
|
||||
if ((Pxe->sw.Implementation & PXE_ROMID_IMP_SW_VIRT_ADDR) != 0) {
|
||||
Snp->IssueUndi32Command = (ISSUE_UNDI32_COMMAND) (UINTN) Pxe->sw.EntryPoint;
|
||||
} else {
|
||||
Snp->IssueUndi32Command = (ISSUE_UNDI32_COMMAND) (UINTN) ((UINT8) (UINTN) Pxe + Pxe->sw.EntryPoint);
|
||||
}
|
||||
}
|
||||
//
|
||||
// Allocate a global CPB and DB buffer for this UNDI interface.
|
||||
// we do this because:
|
||||
//
|
||||
// -UNDI 3.0 wants all the addresses passed to it (even the cpb and db) to be
|
||||
// within 2GB limit, create them here and map them so that when undi calls
|
||||
// v2p callback to check if the physical address is < 2gb, we will pass.
|
||||
//
|
||||
// -This is not a requirement for 3.1 or later UNDIs but the code looks
|
||||
// simpler if we use the same cpb, db variables for both old and new undi
|
||||
// interfaces from all the SNP interface calls (we don't map the buffers
|
||||
// for the newer undi interfaces though)
|
||||
// .
|
||||
// -it is OK to allocate one global set of CPB, DB pair for each UNDI
|
||||
// interface as EFI does not multi-task and so SNP will not be re-entered!
|
||||
//
|
||||
Status = PciIo->AllocateBuffer (
|
||||
PciIo,
|
||||
AllocateAnyPages,
|
||||
EfiBootServicesData,
|
||||
SNP_MEM_PAGES (4096),
|
||||
&Address,
|
||||
0
|
||||
);
|
||||
|
||||
if (Status != EFI_SUCCESS) {
|
||||
DEBUG ((EFI_D_NET, "\nCould not allocate CPB and DB structures.\n"));
|
||||
goto Error_DeleteSNP;
|
||||
}
|
||||
|
||||
Snp->Cpb = (VOID *) (UINTN) Address;
|
||||
Snp->Db = (VOID *) ((UINTN) Address + 2048);
|
||||
|
||||
//
|
||||
// Find the correct BAR to do IO.
|
||||
//
|
||||
// Enumerate through the PCI BARs for the device to determine which one is
|
||||
// the IO BAR. Save the index of the BAR into the adapter info structure.
|
||||
// for regular 32bit BARs, 0 is memory mapped, 1 is io mapped
|
||||
//
|
||||
Snp->MemoryBarIndex = 0;
|
||||
Snp->IoBarIndex = 1;
|
||||
FoundMemoryBar = FALSE;
|
||||
FoundIoBar = FALSE;
|
||||
for (BarIndex = 0; BarIndex < PCI_MAX_BAR; BarIndex++) {
|
||||
Status = PciIo->GetBarAttributes (
|
||||
PciIo,
|
||||
BarIndex,
|
||||
NULL,
|
||||
(VOID**) &BarDesc
|
||||
);
|
||||
if (Status == EFI_UNSUPPORTED) {
|
||||
continue;
|
||||
} else if (EFI_ERROR (Status)) {
|
||||
goto Error_DeleteSNP;
|
||||
}
|
||||
|
||||
if ((!FoundMemoryBar) && (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM)) {
|
||||
Snp->MemoryBarIndex = BarIndex;
|
||||
FoundMemoryBar = TRUE;
|
||||
} else if ((!FoundIoBar) && (BarDesc->ResType == ACPI_ADDRESS_SPACE_TYPE_IO)) {
|
||||
Snp->IoBarIndex = BarIndex;
|
||||
FoundIoBar = TRUE;
|
||||
}
|
||||
|
||||
FreePool (BarDesc);
|
||||
|
||||
if (FoundMemoryBar && FoundIoBar) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Status = PxeStart (Snp);
|
||||
|
||||
if (Status != EFI_SUCCESS) {
|
||||
goto Error_DeleteSNP;
|
||||
}
|
||||
|
||||
Snp->Cdb.OpCode = PXE_OPCODE_GET_INIT_INFO;
|
||||
Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
|
||||
|
||||
Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
|
||||
Snp->Cdb.CPBaddr = PXE_DBADDR_NOT_USED;
|
||||
|
||||
Snp->Cdb.DBsize = (UINT16) sizeof (Snp->InitInfo);
|
||||
Snp->Cdb.DBaddr = (UINT64)(UINTN) (&Snp->InitInfo);
|
||||
|
||||
Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;
|
||||
Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
|
||||
|
||||
Snp->Cdb.IFnum = Snp->IfNum;
|
||||
Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
|
||||
|
||||
DEBUG ((EFI_D_NET, "\nSnp->undi.get_init_info() "));
|
||||
|
||||
(*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);
|
||||
|
||||
//
|
||||
// Save the INIT Stat Code...
|
||||
//
|
||||
InitStatFlags = Snp->Cdb.StatFlags;
|
||||
|
||||
if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {
|
||||
DEBUG ((EFI_D_NET, "\nSnp->undi.init_info() %xh:%xh\n", Snp->Cdb.StatFlags, Snp->Cdb.StatCode));
|
||||
PxeStop (Snp);
|
||||
goto Error_DeleteSNP;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize simple network protocol mode structure
|
||||
//
|
||||
Snp->Mode.State = EfiSimpleNetworkStopped;
|
||||
Snp->Mode.HwAddressSize = Snp->InitInfo.HWaddrLen;
|
||||
Snp->Mode.MediaHeaderSize = Snp->InitInfo.MediaHeaderLen;
|
||||
Snp->Mode.MaxPacketSize = Snp->InitInfo.FrameDataLen;
|
||||
Snp->Mode.NvRamAccessSize = Snp->InitInfo.NvWidth;
|
||||
Snp->Mode.NvRamSize = Snp->InitInfo.NvCount * Snp->Mode.NvRamAccessSize;
|
||||
Snp->Mode.IfType = Snp->InitInfo.IFtype;
|
||||
Snp->Mode.MaxMCastFilterCount = Snp->InitInfo.MCastFilterCnt;
|
||||
Snp->Mode.MCastFilterCount = 0;
|
||||
|
||||
switch (InitStatFlags & PXE_STATFLAGS_CABLE_DETECT_MASK) {
|
||||
case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED:
|
||||
Snp->CableDetectSupported = TRUE;
|
||||
break;
|
||||
|
||||
case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED:
|
||||
default:
|
||||
Snp->CableDetectSupported = FALSE;
|
||||
}
|
||||
|
||||
switch (InitStatFlags & PXE_STATFLAGS_GET_STATUS_NO_MEDIA_MASK) {
|
||||
case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED:
|
||||
Snp->MediaStatusSupported = TRUE;
|
||||
break;
|
||||
|
||||
case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_NOT_SUPPORTED:
|
||||
default:
|
||||
Snp->MediaStatusSupported = FALSE;
|
||||
}
|
||||
|
||||
if (Snp->CableDetectSupported || Snp->MediaStatusSupported) {
|
||||
Snp->Mode.MediaPresentSupported = TRUE;
|
||||
}
|
||||
|
||||
if ((Pxe->hw.Implementation & PXE_ROMID_IMP_STATION_ADDR_SETTABLE) != 0) {
|
||||
Snp->Mode.MacAddressChangeable = TRUE;
|
||||
} else {
|
||||
Snp->Mode.MacAddressChangeable = FALSE;
|
||||
}
|
||||
|
||||
if ((Pxe->hw.Implementation & PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED) != 0) {
|
||||
Snp->Mode.MultipleTxSupported = TRUE;
|
||||
} else {
|
||||
Snp->Mode.MultipleTxSupported = FALSE;
|
||||
}
|
||||
|
||||
Snp->Mode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
|
||||
|
||||
if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) {
|
||||
Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
|
||||
|
||||
}
|
||||
|
||||
if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) {
|
||||
Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
|
||||
|
||||
}
|
||||
|
||||
if ((Pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) {
|
||||
Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
|
||||
|
||||
}
|
||||
|
||||
if ((Pxe->hw.Implementation & PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED) != 0) {
|
||||
Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;
|
||||
|
||||
}
|
||||
|
||||
if ((Pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) {
|
||||
Snp->Mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
|
||||
|
||||
}
|
||||
|
||||
Snp->Mode.ReceiveFilterSetting = 0;
|
||||
|
||||
//
|
||||
// need to get the station address to save in the mode structure. we need to
|
||||
// initialize the UNDI first for this.
|
||||
//
|
||||
Snp->TxRxBufferSize = Snp->InitInfo.MemoryRequired;
|
||||
Status = PxeInit (Snp, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
PxeStop (Snp);
|
||||
goto Error_DeleteSNP;
|
||||
}
|
||||
|
||||
Status = PxeGetStnAddr (Snp);
|
||||
|
||||
if (Status != EFI_SUCCESS) {
|
||||
DEBUG ((EFI_D_ERROR, "\nSnp->undi.get_station_addr() failed.\n"));
|
||||
PxeShutdown (Snp);
|
||||
PxeStop (Snp);
|
||||
goto Error_DeleteSNP;
|
||||
}
|
||||
|
||||
Snp->Mode.MediaPresent = FALSE;
|
||||
|
||||
//
|
||||
// We should not leave UNDI started and initialized here. this DriverStart()
|
||||
// routine must only find and attach the SNP interface to UNDI layer that it
|
||||
// finds on the given handle!
|
||||
// The UNDI layer will be started when upper layers call Snp->start.
|
||||
// How ever, this DriverStart() must fill up the snp mode structure which
|
||||
// contains the MAC address of the NIC. For this reason we started and
|
||||
// initialized UNDI here, now we are done, do a shutdown and stop of the
|
||||
// UNDI interface!
|
||||
//
|
||||
PxeShutdown (Snp);
|
||||
PxeStop (Snp);
|
||||
|
||||
//
|
||||
// Create EXIT_BOOT_SERIVES Event
|
||||
//
|
||||
Status = gBS->CreateEventEx (
|
||||
EVT_NOTIFY_SIGNAL,
|
||||
TPL_NOTIFY,
|
||||
SnpNotifyExitBootServices,
|
||||
Snp,
|
||||
&gEfiEventExitBootServicesGuid,
|
||||
&Snp->ExitBootServicesEvent
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error_DeleteSNP;
|
||||
}
|
||||
|
||||
//
|
||||
// add SNP to the undi handle
|
||||
//
|
||||
Status = gBS->InstallProtocolInterface (
|
||||
&Controller,
|
||||
&gEfiSimpleNetworkProtocolGuid,
|
||||
EFI_NATIVE_INTERFACE,
|
||||
&(Snp->Snp)
|
||||
);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
PciIo->FreeBuffer (
|
||||
PciIo,
|
||||
SNP_MEM_PAGES (4096),
|
||||
Snp->Cpb
|
||||
);
|
||||
|
||||
Error_DeleteSNP:
|
||||
|
||||
if (Snp->RecycledTxBuf != NULL) {
|
||||
FreePool (Snp->RecycledTxBuf);
|
||||
}
|
||||
|
||||
PciIo->FreeBuffer (
|
||||
PciIo,
|
||||
SNP_MEM_PAGES (sizeof (SNP_DRIVER)),
|
||||
Snp
|
||||
);
|
||||
NiiError:
|
||||
gBS->CloseProtocol (
|
||||
Controller,
|
||||
&gEfiNetworkInterfaceIdentifierProtocolGuid_31,
|
||||
This->DriverBindingHandle,
|
||||
Controller
|
||||
);
|
||||
|
||||
gBS->CloseProtocol (
|
||||
Controller,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
This->DriverBindingHandle,
|
||||
Controller
|
||||
);
|
||||
|
||||
//
|
||||
// If we got here that means we are in error state.
|
||||
//
|
||||
if (!EFI_ERROR (Status)) {
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Stop this driver on ControllerHandle. This service is called by the
|
||||
EFI boot service DisconnectController(). In order to
|
||||
make drivers as small as possible, there are a few calling
|
||||
restrictions for this service. DisconnectController()
|
||||
must follow these calling restrictions. If any other agent wishes
|
||||
to call Stop() it must also follow these calling restrictions.
|
||||
|
||||
@param This Protocol instance pointer.
|
||||
@param ControllerHandle Handle of device to stop driver on
|
||||
@param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
|
||||
children is zero stop the entire bus driver.
|
||||
@param 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
|
||||
SimpleNetworkDriverStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_SIMPLE_NETWORK_PROTOCOL *SnpProtocol;
|
||||
SNP_DRIVER *Snp;
|
||||
EFI_PCI_IO_PROTOCOL *PciIo;
|
||||
|
||||
//
|
||||
// Get our context back.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
Controller,
|
||||
&gEfiSimpleNetworkProtocolGuid,
|
||||
(VOID **) &SnpProtocol,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SnpProtocol);
|
||||
|
||||
Status = gBS->UninstallProtocolInterface (
|
||||
Controller,
|
||||
&gEfiSimpleNetworkProtocolGuid,
|
||||
&Snp->Snp
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Close EXIT_BOOT_SERIVES Event
|
||||
//
|
||||
gBS->CloseEvent (Snp->ExitBootServicesEvent);
|
||||
|
||||
Status = gBS->CloseProtocol (
|
||||
Controller,
|
||||
&gEfiNetworkInterfaceIdentifierProtocolGuid_31,
|
||||
This->DriverBindingHandle,
|
||||
Controller
|
||||
);
|
||||
|
||||
Status = gBS->CloseProtocol (
|
||||
Controller,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
This->DriverBindingHandle,
|
||||
Controller
|
||||
);
|
||||
|
||||
PxeShutdown (Snp);
|
||||
PxeStop (Snp);
|
||||
|
||||
FreePool (Snp->RecycledTxBuf);
|
||||
|
||||
PciIo = Snp->PciIo;
|
||||
PciIo->FreeBuffer (
|
||||
PciIo,
|
||||
SNP_MEM_PAGES (4096),
|
||||
Snp->Cpb
|
||||
);
|
||||
|
||||
PciIo->FreeBuffer (
|
||||
PciIo,
|
||||
SNP_MEM_PAGES (sizeof (SNP_DRIVER)),
|
||||
Snp
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Simple Network Protocol Driver Global Variables
|
||||
//
|
||||
EFI_DRIVER_BINDING_PROTOCOL gSimpleNetworkDriverBinding = {
|
||||
SimpleNetworkDriverSupported,
|
||||
SimpleNetworkDriverStart,
|
||||
SimpleNetworkDriverStop,
|
||||
0xa,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
/**
|
||||
The SNP driver entry point.
|
||||
|
||||
@param ImageHandle The driver image handle.
|
||||
@param SystemTable The system table.
|
||||
|
||||
@retval EFI_SUCEESS Initialization routine has found UNDI hardware,
|
||||
loaded it's ROM, and installed a notify event for
|
||||
the Network Indentifier Interface Protocol
|
||||
successfully.
|
||||
@retval Other Return value from HandleProtocol for
|
||||
DeviceIoProtocol or LoadedImageProtocol
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
InitializeSnpNiiDriver (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
return EfiLibInstallDriverBindingComponentName2 (
|
||||
ImageHandle,
|
||||
SystemTable,
|
||||
&gSimpleNetworkDriverBinding,
|
||||
ImageHandle,
|
||||
&gSimpleNetworkComponentName,
|
||||
&gSimpleNetworkComponentName2
|
||||
);
|
||||
}
|
1033
NetworkPkg/SnpDxe/Snp.h
Normal file
1033
NetworkPkg/SnpDxe/Snp.h
Normal file
File diff suppressed because it is too large
Load Diff
77
NetworkPkg/SnpDxe/SnpDxe.inf
Normal file
77
NetworkPkg/SnpDxe/SnpDxe.inf
Normal file
@@ -0,0 +1,77 @@
|
||||
## @file
|
||||
# This module produces EFI SNP Protocol.
|
||||
#
|
||||
# This module produces Simple Network Protocol upon EFI Network Interface
|
||||
# Identifier Protocol, to provide a packet level interface to a network adapter.
|
||||
#
|
||||
# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = SnpDxe
|
||||
MODULE_UNI_FILE = SnpDxe.uni
|
||||
FILE_GUID = A2f436EA-A127-4EF8-957C-8048606FF670
|
||||
MODULE_TYPE = UEFI_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = InitializeSnpNiiDriver
|
||||
UNLOAD_IMAGE = NetLibDefaultUnload
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 EBC
|
||||
#
|
||||
# DRIVER_BINDING = mSimpleNetworkDriverBinding
|
||||
# COMPONENT_NAME = gSimpleNetworkComponentName
|
||||
# COMPONENT_NAME2 = gSimpleNetworkComponentName2
|
||||
#
|
||||
|
||||
[Sources]
|
||||
Receive.c
|
||||
Snp.h
|
||||
Nvdata.c
|
||||
Get_status.c
|
||||
Start.c
|
||||
Snp.c
|
||||
Stop.c
|
||||
Statistics.c
|
||||
Reset.c
|
||||
Shutdown.c
|
||||
Mcast_ip_to_mac.c
|
||||
Transmit.c
|
||||
WaitForPacket.c
|
||||
Receive_filters.c
|
||||
Initialize.c
|
||||
ComponentName.c
|
||||
Callback.c
|
||||
Station_address.c
|
||||
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
|
||||
[LibraryClasses]
|
||||
UefiLib
|
||||
BaseLib
|
||||
UefiBootServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
BaseMemoryLib
|
||||
DebugLib
|
||||
NetLib
|
||||
|
||||
[Guids]
|
||||
gEfiEventExitBootServicesGuid ## SOMETIMES_CONSUMES ## Event
|
||||
|
||||
[Protocols]
|
||||
gEfiSimpleNetworkProtocolGuid ## BY_START
|
||||
gEfiDevicePathProtocolGuid ## TO_START
|
||||
gEfiNetworkInterfaceIdentifierProtocolGuid_31 ## TO_START
|
||||
gEfiPciIoProtocolGuid ## TO_START
|
||||
|
||||
[UserExtensions.TianoCore."ExtraFiles"]
|
||||
SnpDxeExtra.uni
|
17
NetworkPkg/SnpDxe/SnpDxe.uni
Normal file
17
NetworkPkg/SnpDxe/SnpDxe.uni
Normal file
@@ -0,0 +1,17 @@
|
||||
// /** @file
|
||||
// This module produces EFI SNP Protocol.
|
||||
//
|
||||
// This module produces Simple Network Protocol upon EFI Network Interface
|
||||
// Identifier Protocol, to provide a packet level interface to a network adapter.
|
||||
//
|
||||
// Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
//
|
||||
// **/
|
||||
|
||||
|
||||
#string STR_MODULE_ABSTRACT #language en-US "Produces EFI SNP Protocol"
|
||||
|
||||
#string STR_MODULE_DESCRIPTION #language en-US "This module produces Simple Network Protocol upon EFI Network Interface Identifier Protocol to provide a packet level interface to a network adapter."
|
||||
|
14
NetworkPkg/SnpDxe/SnpDxeExtra.uni
Normal file
14
NetworkPkg/SnpDxe/SnpDxeExtra.uni
Normal file
@@ -0,0 +1,14 @@
|
||||
// /** @file
|
||||
// SnpDxe Localized Strings and Content
|
||||
//
|
||||
// Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
//
|
||||
// **/
|
||||
|
||||
#string STR_PROPERTIES_MODULE_NAME
|
||||
#language en-US
|
||||
"SNP DXE Driver"
|
||||
|
||||
|
162
NetworkPkg/SnpDxe/Start.c
Normal file
162
NetworkPkg/SnpDxe/Start.c
Normal file
@@ -0,0 +1,162 @@
|
||||
/** @file
|
||||
Implementation of starting a network adapter.
|
||||
|
||||
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "Snp.h"
|
||||
|
||||
|
||||
/**
|
||||
Call UNDI to start the interface and changes the snp state.
|
||||
|
||||
@param Snp pointer to snp driver structure.
|
||||
|
||||
@retval EFI_SUCCESS UNDI is started successfully.
|
||||
@retval EFI_DEVICE_ERROR UNDI could not be started.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PxeStart (
|
||||
IN SNP_DRIVER *Snp
|
||||
)
|
||||
{
|
||||
PXE_CPB_START_31 *Cpb31;
|
||||
|
||||
Cpb31 = Snp->Cpb;
|
||||
//
|
||||
// Initialize UNDI Start CDB for H/W UNDI
|
||||
//
|
||||
Snp->Cdb.OpCode = PXE_OPCODE_START;
|
||||
Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
|
||||
Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
|
||||
Snp->Cdb.DBsize = PXE_DBSIZE_NOT_USED;
|
||||
Snp->Cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
|
||||
Snp->Cdb.DBaddr = PXE_DBADDR_NOT_USED;
|
||||
Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;
|
||||
Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
|
||||
Snp->Cdb.IFnum = Snp->IfNum;
|
||||
Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
|
||||
|
||||
//
|
||||
// Make changes to H/W UNDI Start CDB if this is
|
||||
// a S/W UNDI.
|
||||
//
|
||||
if (Snp->IsSwUndi) {
|
||||
Snp->Cdb.CPBsize = (UINT16) sizeof (PXE_CPB_START_31);
|
||||
Snp->Cdb.CPBaddr = (UINT64)(UINTN) Cpb31;
|
||||
|
||||
Cpb31->Delay = (UINT64)(UINTN) &SnpUndi32CallbackDelay;
|
||||
Cpb31->Block = (UINT64)(UINTN) &SnpUndi32CallbackBlock;
|
||||
|
||||
//
|
||||
// Virtual == Physical. This can be set to zero.
|
||||
//
|
||||
Cpb31->Virt2Phys = (UINT64)(UINTN) 0;
|
||||
Cpb31->Mem_IO = (UINT64)(UINTN) &SnpUndi32CallbackMemio;
|
||||
|
||||
Cpb31->Map_Mem = (UINT64)(UINTN) &SnpUndi32CallbackMap;
|
||||
Cpb31->UnMap_Mem = (UINT64)(UINTN) &SnpUndi32CallbackUnmap;
|
||||
Cpb31->Sync_Mem = (UINT64)(UINTN) &SnpUndi32CallbackSync;
|
||||
|
||||
Cpb31->Unique_ID = (UINT64)(UINTN) Snp;
|
||||
}
|
||||
//
|
||||
// Issue UNDI command and check result.
|
||||
//
|
||||
DEBUG ((EFI_D_NET, "\nsnp->undi.start() "));
|
||||
|
||||
(*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);
|
||||
|
||||
if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {
|
||||
//
|
||||
// UNDI could not be started. Return UNDI error.
|
||||
//
|
||||
DEBUG (
|
||||
(EFI_D_ERROR,
|
||||
"\nsnp->undi.start() %xh:%xh\n",
|
||||
Snp->Cdb.StatCode,
|
||||
Snp->Cdb.StatFlags)
|
||||
);
|
||||
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
//
|
||||
// Set simple network state to Started and return success.
|
||||
//
|
||||
Snp->Mode.State = EfiSimpleNetworkStarted;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Change the state of a network interface from "stopped" to "started."
|
||||
|
||||
This function starts a network interface. If the network interface successfully
|
||||
starts, then EFI_SUCCESS will be returned.
|
||||
|
||||
@param This A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
|
||||
|
||||
@retval EFI_SUCCESS The network interface was started.
|
||||
@retval EFI_ALREADY_STARTED The network interface is already in the started state.
|
||||
@retval EFI_INVALID_PARAMETER This parameter was NULL or did not point to a valid
|
||||
EFI_SIMPLE_NETWORK_PROTOCOL structure.
|
||||
@retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
|
||||
@retval EFI_UNSUPPORTED This function is not supported by the network interface.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SnpUndi32Start (
|
||||
IN EFI_SIMPLE_NETWORK_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
SNP_DRIVER *Snp;
|
||||
EFI_STATUS Status;
|
||||
UINTN Index;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
if (This == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
|
||||
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
|
||||
switch (Snp->Mode.State) {
|
||||
case EfiSimpleNetworkStopped:
|
||||
break;
|
||||
|
||||
case EfiSimpleNetworkStarted:
|
||||
case EfiSimpleNetworkInitialized:
|
||||
Status = EFI_ALREADY_STARTED;
|
||||
goto ON_EXIT;
|
||||
|
||||
default:
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
Status = PxeStart (Snp);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
//
|
||||
// clear the map_list in SNP structure
|
||||
//
|
||||
for (Index = 0; Index < MAX_MAP_LENGTH; Index++) {
|
||||
Snp->MapList[Index].VirtualAddress = 0;
|
||||
Snp->MapList[Index].MapCookie = 0;
|
||||
}
|
||||
|
||||
Snp->Mode.MCastFilterCount = 0;
|
||||
|
||||
ON_EXIT:
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
return Status;
|
||||
}
|
243
NetworkPkg/SnpDxe/Station_address.c
Normal file
243
NetworkPkg/SnpDxe/Station_address.c
Normal file
@@ -0,0 +1,243 @@
|
||||
/** @file
|
||||
Implementation of reading the MAC address of a network adapter.
|
||||
|
||||
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "Snp.h"
|
||||
|
||||
|
||||
/**
|
||||
Call UNDI to read the MAC address of the NIC and update the mode structure
|
||||
with the address.
|
||||
|
||||
@param Snp Pointer to snp driver structure.
|
||||
|
||||
@retval EFI_SUCCESS The MAC address of the NIC is read successfully.
|
||||
@retval EFI_DEVICE_ERROR Failed to read the MAC address of the NIC.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PxeGetStnAddr (
|
||||
SNP_DRIVER *Snp
|
||||
)
|
||||
{
|
||||
PXE_DB_STATION_ADDRESS *Db;
|
||||
|
||||
Db = Snp->Db;
|
||||
Snp->Cdb.OpCode = PXE_OPCODE_STATION_ADDRESS;
|
||||
Snp->Cdb.OpFlags = PXE_OPFLAGS_STATION_ADDRESS_READ;
|
||||
|
||||
Snp->Cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
|
||||
Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
|
||||
|
||||
Snp->Cdb.DBsize = (UINT16) sizeof (PXE_DB_STATION_ADDRESS);
|
||||
Snp->Cdb.DBaddr = (UINT64)(UINTN) Db;
|
||||
|
||||
Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;
|
||||
Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
|
||||
Snp->Cdb.IFnum = Snp->IfNum;
|
||||
Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
|
||||
|
||||
//
|
||||
// Issue UNDI command and check result.
|
||||
//
|
||||
DEBUG ((EFI_D_NET, "\nsnp->undi.station_addr() "));
|
||||
|
||||
(*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);
|
||||
|
||||
if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {
|
||||
DEBUG (
|
||||
(EFI_D_ERROR,
|
||||
"\nsnp->undi.station_addr() %xh:%xh\n",
|
||||
Snp->Cdb.StatFlags,
|
||||
Snp->Cdb.StatCode)
|
||||
);
|
||||
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
//
|
||||
// Set new station address in SNP->Mode structure and return success.
|
||||
//
|
||||
CopyMem (
|
||||
&(Snp->Mode.CurrentAddress),
|
||||
&Db->StationAddr,
|
||||
Snp->Mode.HwAddressSize
|
||||
);
|
||||
|
||||
CopyMem (
|
||||
&Snp->Mode.BroadcastAddress,
|
||||
&Db->BroadcastAddr,
|
||||
Snp->Mode.HwAddressSize
|
||||
);
|
||||
|
||||
CopyMem (
|
||||
&Snp->Mode.PermanentAddress,
|
||||
&Db->PermanentAddr,
|
||||
Snp->Mode.HwAddressSize
|
||||
);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Call UNDI to set a new MAC address for the NIC.
|
||||
|
||||
@param Snp Pointer to Snp driver structure.
|
||||
@param NewMacAddr Pointer to a MAC address to be set for the NIC, if this is
|
||||
NULL then this routine resets the mac address to the NIC's
|
||||
original address.
|
||||
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PxeSetStnAddr (
|
||||
SNP_DRIVER *Snp,
|
||||
EFI_MAC_ADDRESS *NewMacAddr
|
||||
)
|
||||
{
|
||||
PXE_CPB_STATION_ADDRESS *Cpb;
|
||||
PXE_DB_STATION_ADDRESS *Db;
|
||||
|
||||
Cpb = Snp->Cpb;
|
||||
Db = Snp->Db;
|
||||
Snp->Cdb.OpCode = PXE_OPCODE_STATION_ADDRESS;
|
||||
|
||||
if (NewMacAddr == NULL) {
|
||||
Snp->Cdb.OpFlags = PXE_OPFLAGS_STATION_ADDRESS_RESET;
|
||||
Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
|
||||
Snp->Cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
|
||||
} else {
|
||||
Snp->Cdb.OpFlags = PXE_OPFLAGS_STATION_ADDRESS_WRITE;
|
||||
//
|
||||
// Supplying a new address in the CPB will make undi change the mac address to the new one.
|
||||
//
|
||||
CopyMem (&Cpb->StationAddr, NewMacAddr, Snp->Mode.HwAddressSize);
|
||||
|
||||
Snp->Cdb.CPBsize = (UINT16) sizeof (PXE_CPB_STATION_ADDRESS);
|
||||
Snp->Cdb.CPBaddr = (UINT64)(UINTN) Cpb;
|
||||
}
|
||||
|
||||
Snp->Cdb.DBsize = (UINT16) sizeof (PXE_DB_STATION_ADDRESS);
|
||||
Snp->Cdb.DBaddr = (UINT64)(UINTN) Db;
|
||||
|
||||
Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;
|
||||
Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
|
||||
Snp->Cdb.IFnum = Snp->IfNum;
|
||||
Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
|
||||
|
||||
//
|
||||
// Issue UNDI command and check result.
|
||||
//
|
||||
DEBUG ((EFI_D_NET, "\nsnp->undi.station_addr() "));
|
||||
|
||||
(*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);
|
||||
|
||||
if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {
|
||||
DEBUG (
|
||||
(EFI_D_ERROR,
|
||||
"\nsnp->undi.station_addr() %xh:%xh\n",
|
||||
Snp->Cdb.StatFlags,
|
||||
Snp->Cdb.StatCode)
|
||||
);
|
||||
|
||||
//
|
||||
// UNDI command failed. Return UNDI status to caller.
|
||||
//
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
//
|
||||
// read the changed address and save it in SNP->Mode structure
|
||||
//
|
||||
PxeGetStnAddr (Snp);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Modifies or resets the current station address, if supported.
|
||||
|
||||
This function modifies or resets the current station address of a network
|
||||
interface, if supported. If Reset is TRUE, then the current station address is
|
||||
set to the network interface's permanent address. If Reset is FALSE, and the
|
||||
network interface allows its station address to be modified, then the current
|
||||
station address is changed to the address specified by New. If the network
|
||||
interface does not allow its station address to be modified, then
|
||||
EFI_INVALID_PARAMETER will be returned. If the station address is successfully
|
||||
updated on the network interface, EFI_SUCCESS will be returned. If the driver
|
||||
has not been initialized, EFI_DEVICE_ERROR will be returned.
|
||||
|
||||
@param This A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
|
||||
@param Reset Flag used to reset the station address to the network interface's
|
||||
permanent address.
|
||||
@param New New station address to be used for the network interface.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS The network interface's station address was updated.
|
||||
@retval EFI_NOT_STARTED The Simple Network Protocol interface has not been
|
||||
started by calling Start().
|
||||
@retval EFI_INVALID_PARAMETER The New station address was not accepted by the NIC.
|
||||
@retval EFI_INVALID_PARAMETER Reset is FALSE and New is NULL.
|
||||
@retval EFI_DEVICE_ERROR The Simple Network Protocol interface has not
|
||||
been initialized by calling Initialize().
|
||||
@retval EFI_DEVICE_ERROR An error occurred attempting to set the new
|
||||
station address.
|
||||
@retval EFI_UNSUPPORTED The NIC does not support changing the network
|
||||
interface's station address.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SnpUndi32StationAddress (
|
||||
IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
|
||||
IN BOOLEAN Reset,
|
||||
IN EFI_MAC_ADDRESS *New OPTIONAL
|
||||
)
|
||||
{
|
||||
SNP_DRIVER *Snp;
|
||||
EFI_STATUS Status;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
//
|
||||
// Check for invalid parameter combinations.
|
||||
//
|
||||
if ((This == NULL) ||
|
||||
(!Reset && (New == NULL))) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
|
||||
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
|
||||
//
|
||||
// Return error if the SNP is not initialized.
|
||||
//
|
||||
switch (Snp->Mode.State) {
|
||||
case EfiSimpleNetworkInitialized:
|
||||
break;
|
||||
|
||||
case EfiSimpleNetworkStopped:
|
||||
Status = EFI_NOT_STARTED;
|
||||
goto ON_EXIT;
|
||||
|
||||
default:
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
if (Reset) {
|
||||
Status = PxeSetStnAddr (Snp, NULL);
|
||||
} else {
|
||||
Status = PxeSetStnAddr (Snp, New);
|
||||
}
|
||||
|
||||
ON_EXIT:
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
return Status;
|
||||
}
|
224
NetworkPkg/SnpDxe/Statistics.c
Normal file
224
NetworkPkg/SnpDxe/Statistics.c
Normal file
@@ -0,0 +1,224 @@
|
||||
/** @file
|
||||
Implementation of collecting the statistics on a network interface.
|
||||
|
||||
Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
|
||||
#include "Snp.h"
|
||||
|
||||
|
||||
/**
|
||||
Resets or collects the statistics on a network interface.
|
||||
|
||||
This function resets or collects the statistics on a network interface. If the
|
||||
size of the statistics table specified by StatisticsSize is not big enough for
|
||||
all the statistics that are collected by the network interface, then a partial
|
||||
buffer of statistics is returned in StatisticsTable, StatisticsSize is set to
|
||||
the size required to collect all the available statistics, and
|
||||
EFI_BUFFER_TOO_SMALL is returned.
|
||||
If StatisticsSize is big enough for all the statistics, then StatisticsTable
|
||||
will be filled, StatisticsSize will be set to the size of the returned
|
||||
StatisticsTable structure, and EFI_SUCCESS is returned.
|
||||
If the driver has not been initialized, EFI_DEVICE_ERROR will be returned.
|
||||
If Reset is FALSE, and both StatisticsSize and StatisticsTable are NULL, then
|
||||
no operations will be performed, and EFI_SUCCESS will be returned.
|
||||
If Reset is TRUE, then all of the supported statistics counters on this network
|
||||
interface will be reset to zero.
|
||||
|
||||
@param This A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
|
||||
@param Reset Set to TRUE to reset the statistics for the network interface.
|
||||
@param StatisticsSize On input the size, in bytes, of StatisticsTable. On output
|
||||
the size, in bytes, of the resulting table of statistics.
|
||||
@param StatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that
|
||||
contains the statistics. Type EFI_NETWORK_STATISTICS is
|
||||
defined in "Related Definitions" below.
|
||||
|
||||
@retval EFI_SUCCESS The requested operation succeeded.
|
||||
@retval EFI_NOT_STARTED The Simple Network Protocol interface has not been
|
||||
started by calling Start().
|
||||
@retval EFI_BUFFER_TOO_SMALL StatisticsSize is not NULL and StatisticsTable is
|
||||
NULL. The current buffer size that is needed to
|
||||
hold all the statistics is returned in StatisticsSize.
|
||||
@retval EFI_BUFFER_TOO_SMALL StatisticsSize is not NULL and StatisticsTable is
|
||||
not NULL. The current buffer size that is needed
|
||||
to hold all the statistics is returned in
|
||||
StatisticsSize. A partial set of statistics is
|
||||
returned in StatisticsTable.
|
||||
@retval EFI_INVALID_PARAMETER StatisticsSize is NULL and StatisticsTable is not
|
||||
NULL.
|
||||
@retval EFI_DEVICE_ERROR The Simple Network Protocol interface has not
|
||||
been initialized by calling Initialize().
|
||||
@retval EFI_DEVICE_ERROR An error was encountered collecting statistics
|
||||
from the NIC.
|
||||
@retval EFI_UNSUPPORTED The NIC does not support collecting statistics
|
||||
from the network interface.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SnpUndi32Statistics (
|
||||
IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
|
||||
IN BOOLEAN Reset,
|
||||
IN OUT UINTN *StatisticsSize, OPTIONAL
|
||||
IN OUT EFI_NETWORK_STATISTICS *StatisticsTable OPTIONAL
|
||||
)
|
||||
{
|
||||
SNP_DRIVER *Snp;
|
||||
PXE_DB_STATISTICS *Db;
|
||||
UINT64 *Stp;
|
||||
UINT64 Mask;
|
||||
UINTN Size;
|
||||
UINTN Index;
|
||||
EFI_TPL OldTpl;
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Get pointer to SNP driver instance for *This.
|
||||
//
|
||||
if (This == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
|
||||
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
|
||||
//
|
||||
// Return error if the SNP is not initialized.
|
||||
//
|
||||
switch (Snp->Mode.State) {
|
||||
case EfiSimpleNetworkInitialized:
|
||||
break;
|
||||
|
||||
case EfiSimpleNetworkStopped:
|
||||
Status = EFI_NOT_STARTED;
|
||||
goto ON_EXIT;
|
||||
|
||||
default:
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
//
|
||||
// if we are not resetting the counters, we have to have a valid stat table
|
||||
// with >0 size. if no reset, no table and no size, return success.
|
||||
//
|
||||
if (!Reset && StatisticsSize == NULL) {
|
||||
Status = (StatisticsTable != NULL) ? EFI_INVALID_PARAMETER : EFI_SUCCESS;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
//
|
||||
// Initialize UNDI Statistics CDB
|
||||
//
|
||||
Snp->Cdb.OpCode = PXE_OPCODE_STATISTICS;
|
||||
Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
|
||||
Snp->Cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
|
||||
Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;
|
||||
Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
|
||||
Snp->Cdb.IFnum = Snp->IfNum;
|
||||
Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
|
||||
|
||||
if (Reset) {
|
||||
Snp->Cdb.OpFlags = PXE_OPFLAGS_STATISTICS_RESET;
|
||||
Snp->Cdb.DBsize = PXE_DBSIZE_NOT_USED;
|
||||
Snp->Cdb.DBaddr = PXE_DBADDR_NOT_USED;
|
||||
Db = Snp->Db;
|
||||
} else {
|
||||
Snp->Cdb.OpFlags = PXE_OPFLAGS_STATISTICS_READ;
|
||||
Snp->Cdb.DBsize = (UINT16) sizeof (PXE_DB_STATISTICS);
|
||||
Snp->Cdb.DBaddr = (UINT64)(UINTN) (Db = Snp->Db);
|
||||
}
|
||||
//
|
||||
// Issue UNDI command and check result.
|
||||
//
|
||||
DEBUG ((EFI_D_NET, "\nsnp->undi.statistics() "));
|
||||
|
||||
(*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);
|
||||
|
||||
switch (Snp->Cdb.StatCode) {
|
||||
case PXE_STATCODE_SUCCESS:
|
||||
break;
|
||||
|
||||
case PXE_STATCODE_UNSUPPORTED:
|
||||
DEBUG (
|
||||
(EFI_D_ERROR,
|
||||
"\nsnp->undi.statistics() %xh:%xh\n",
|
||||
Snp->Cdb.StatFlags,
|
||||
Snp->Cdb.StatCode)
|
||||
);
|
||||
|
||||
Status = EFI_UNSUPPORTED;
|
||||
goto ON_EXIT;
|
||||
|
||||
default:
|
||||
DEBUG (
|
||||
(EFI_D_ERROR,
|
||||
"\nsnp->undi.statistics() %xh:%xh\n",
|
||||
Snp->Cdb.StatFlags,
|
||||
Snp->Cdb.StatCode)
|
||||
);
|
||||
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
if (Reset) {
|
||||
Status = EFI_SUCCESS;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
if (StatisticsTable == NULL) {
|
||||
*StatisticsSize = sizeof (EFI_NETWORK_STATISTICS);
|
||||
Status = EFI_BUFFER_TOO_SMALL;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
//
|
||||
// Convert the UNDI statistics information to SNP statistics
|
||||
// information.
|
||||
//
|
||||
ZeroMem (StatisticsTable, *StatisticsSize);
|
||||
Stp = (UINT64 *) StatisticsTable;
|
||||
Size = 0;
|
||||
|
||||
for (Index = 0, Mask = 1; Index < 64; Index++, Mask = LShiftU64 (Mask, 1), Stp++) {
|
||||
//
|
||||
// There must be room for a full UINT64. Partial
|
||||
// numbers will not be stored.
|
||||
//
|
||||
if ((Index + 1) * sizeof (UINT64) > *StatisticsSize) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ((Db->Supported & Mask) != 0) {
|
||||
*Stp = Db->Data[Index];
|
||||
Size = Index + 1;
|
||||
} else {
|
||||
SetMem (Stp, sizeof (UINT64), 0xFF);
|
||||
}
|
||||
}
|
||||
//
|
||||
// Compute size up to last supported statistic.
|
||||
//
|
||||
while (++Index < 64) {
|
||||
if ((Db->Supported & (Mask = LShiftU64 (Mask, 1))) != 0) {
|
||||
Size = Index;
|
||||
}
|
||||
}
|
||||
|
||||
Size *= sizeof (UINT64);
|
||||
|
||||
if (*StatisticsSize >= Size) {
|
||||
*StatisticsSize = Size;
|
||||
Status = EFI_SUCCESS;
|
||||
} else {
|
||||
*StatisticsSize = Size;
|
||||
Status = EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
ON_EXIT:
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
return Status;
|
||||
}
|
120
NetworkPkg/SnpDxe/Stop.c
Normal file
120
NetworkPkg/SnpDxe/Stop.c
Normal file
@@ -0,0 +1,120 @@
|
||||
/** @file
|
||||
Implementation of stopping a network interface.
|
||||
|
||||
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "Snp.h"
|
||||
|
||||
|
||||
/**
|
||||
Call UNDI to stop the interface and changes the snp state.
|
||||
|
||||
@param Snp Pointer to snp driver structure
|
||||
|
||||
@retval EFI_SUCCESS The network interface was stopped.
|
||||
@retval EFI_DEVICE_ERROR SNP is not initialized.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PxeStop (
|
||||
SNP_DRIVER *Snp
|
||||
)
|
||||
{
|
||||
Snp->Cdb.OpCode = PXE_OPCODE_STOP;
|
||||
Snp->Cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
|
||||
Snp->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
|
||||
Snp->Cdb.DBsize = PXE_DBSIZE_NOT_USED;
|
||||
Snp->Cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
|
||||
Snp->Cdb.DBaddr = PXE_DBADDR_NOT_USED;
|
||||
Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;
|
||||
Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
|
||||
Snp->Cdb.IFnum = Snp->IfNum;
|
||||
Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
|
||||
|
||||
//
|
||||
// Issue UNDI command
|
||||
//
|
||||
DEBUG ((EFI_D_NET, "\nsnp->undi.stop() "));
|
||||
|
||||
(*Snp->IssueUndi32Command) ((UINT64)(UINTN) &Snp->Cdb);
|
||||
|
||||
if (Snp->Cdb.StatCode != PXE_STATCODE_SUCCESS) {
|
||||
DEBUG (
|
||||
(EFI_D_WARN,
|
||||
"\nsnp->undi.stop() %xh:%xh\n",
|
||||
Snp->Cdb.StatFlags,
|
||||
Snp->Cdb.StatCode)
|
||||
);
|
||||
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
//
|
||||
// Set simple network state to Started and return success.
|
||||
//
|
||||
Snp->Mode.State = EfiSimpleNetworkStopped;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Changes the state of a network interface from "started" to "stopped."
|
||||
|
||||
This function stops a network interface. This call is only valid if the network
|
||||
interface is in the started state. If the network interface was successfully
|
||||
stopped, then EFI_SUCCESS will be returned.
|
||||
|
||||
@param This A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL
|
||||
instance.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS The network interface was stopped.
|
||||
@retval EFI_NOT_STARTED The network interface has not been started.
|
||||
@retval EFI_INVALID_PARAMETER This parameter was NULL or did not point to a
|
||||
valid EFI_SIMPLE_NETWORK_PROTOCOL structure.
|
||||
@retval EFI_DEVICE_ERROR The command could not be sent to the network
|
||||
interface.
|
||||
@retval EFI_UNSUPPORTED This function is not supported by the network
|
||||
interface.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SnpUndi32Stop (
|
||||
IN EFI_SIMPLE_NETWORK_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
SNP_DRIVER *Snp;
|
||||
EFI_TPL OldTpl;
|
||||
EFI_STATUS Status;
|
||||
|
||||
if (This == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
|
||||
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
|
||||
switch (Snp->Mode.State) {
|
||||
case EfiSimpleNetworkStarted:
|
||||
break;
|
||||
|
||||
case EfiSimpleNetworkStopped:
|
||||
Status = EFI_NOT_STARTED;
|
||||
goto ON_EXIT;
|
||||
|
||||
default:
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
Status = PxeStop (Snp);
|
||||
|
||||
ON_EXIT:
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
return Status;
|
||||
}
|
353
NetworkPkg/SnpDxe/Transmit.c
Normal file
353
NetworkPkg/SnpDxe/Transmit.c
Normal file
@@ -0,0 +1,353 @@
|
||||
/** @file
|
||||
Implementation of transmitting a packet.
|
||||
|
||||
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "Snp.h"
|
||||
|
||||
|
||||
/**
|
||||
Call UNDI to create the meadia header for the given data buffer.
|
||||
|
||||
@param Snp Pointer to SNP driver structure.
|
||||
@param MacHeaderPtr Address where the media header will be filled in.
|
||||
@param HeaderSize Size of the memory at MacHeaderPtr.
|
||||
@param Buffer Data buffer pointer.
|
||||
@param BufferSize Size of data in the Buffer
|
||||
@param DestAddr Address of the destination mac address buffer.
|
||||
@param SrcAddr Address of the source mac address buffer.
|
||||
@param ProtocolPtr Address of the protocol type.
|
||||
|
||||
@retval EFI_SUCCESS Successfully completed the undi call.
|
||||
@retval Other Error return from undi call.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PxeFillHeader (
|
||||
SNP_DRIVER *Snp,
|
||||
VOID *MacHeaderPtr,
|
||||
UINTN HeaderSize,
|
||||
VOID *Buffer,
|
||||
UINTN BufferSize,
|
||||
EFI_MAC_ADDRESS *DestAddr,
|
||||
EFI_MAC_ADDRESS *SrcAddr,
|
||||
UINT16 *ProtocolPtr
|
||||
)
|
||||
{
|
||||
PXE_CPB_FILL_HEADER_FRAGMENTED *Cpb;
|
||||
|
||||
Cpb = Snp->Cpb;
|
||||
if (SrcAddr != NULL) {
|
||||
CopyMem (
|
||||
(VOID *) Cpb->SrcAddr,
|
||||
(VOID *) SrcAddr,
|
||||
Snp->Mode.HwAddressSize
|
||||
);
|
||||
} else {
|
||||
CopyMem (
|
||||
(VOID *) Cpb->SrcAddr,
|
||||
(VOID *) &(Snp->Mode.CurrentAddress),
|
||||
Snp->Mode.HwAddressSize
|
||||
);
|
||||
}
|
||||
|
||||
CopyMem (
|
||||
(VOID *) Cpb->DestAddr,
|
||||
(VOID *) DestAddr,
|
||||
Snp->Mode.HwAddressSize
|
||||
);
|
||||
|
||||
//
|
||||
// we need to do the byte swapping
|
||||
//
|
||||
Cpb->Protocol = (UINT16) PXE_SWAP_UINT16 (*ProtocolPtr);
|
||||
|
||||
Cpb->PacketLen = (UINT32) (BufferSize);
|
||||
Cpb->MediaHeaderLen = (UINT16) HeaderSize;
|
||||
|
||||
Cpb->FragCnt = 2;
|
||||
Cpb->reserved = 0;
|
||||
|
||||
Cpb->FragDesc[0].FragAddr = (UINT64)(UINTN) MacHeaderPtr;
|
||||
Cpb->FragDesc[0].FragLen = (UINT32) HeaderSize;
|
||||
Cpb->FragDesc[1].FragAddr = (UINT64)(UINTN) Buffer;
|
||||
Cpb->FragDesc[1].FragLen = (UINT32) BufferSize;
|
||||
|
||||
Cpb->FragDesc[0].reserved = Cpb->FragDesc[1].reserved = 0;
|
||||
|
||||
Snp->Cdb.OpCode = PXE_OPCODE_FILL_HEADER;
|
||||
Snp->Cdb.OpFlags = PXE_OPFLAGS_FILL_HEADER_FRAGMENTED;
|
||||
|
||||
Snp->Cdb.DBsize = PXE_DBSIZE_NOT_USED;
|
||||
Snp->Cdb.DBaddr = PXE_DBADDR_NOT_USED;
|
||||
|
||||
Snp->Cdb.CPBsize = (UINT16) sizeof (PXE_CPB_FILL_HEADER_FRAGMENTED);
|
||||
Snp->Cdb.CPBaddr = (UINT64)(UINTN) Cpb;
|
||||
|
||||
Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;
|
||||
Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
|
||||
Snp->Cdb.IFnum = Snp->IfNum;
|
||||
Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
|
||||
|
||||
//
|
||||
// Issue UNDI command and check result.
|
||||
//
|
||||
DEBUG ((EFI_D_NET, "\nSnp->undi.fill_header() "));
|
||||
|
||||
(*Snp->IssueUndi32Command) ((UINT64) (UINTN) &Snp->Cdb);
|
||||
|
||||
switch (Snp->Cdb.StatCode) {
|
||||
case PXE_STATCODE_SUCCESS:
|
||||
return EFI_SUCCESS;
|
||||
|
||||
case PXE_STATCODE_INVALID_PARAMETER:
|
||||
DEBUG (
|
||||
(EFI_D_ERROR,
|
||||
"\nSnp->undi.fill_header() %xh:%xh\n",
|
||||
Snp->Cdb.StatFlags,
|
||||
Snp->Cdb.StatCode)
|
||||
);
|
||||
|
||||
return EFI_INVALID_PARAMETER;
|
||||
|
||||
default:
|
||||
DEBUG (
|
||||
(EFI_D_ERROR,
|
||||
"\nSnp->undi.fill_header() %xh:%xh\n",
|
||||
Snp->Cdb.StatFlags,
|
||||
Snp->Cdb.StatCode)
|
||||
);
|
||||
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
This routine calls undi to transmit the given data buffer
|
||||
|
||||
@param Snp pointer to SNP driver structure
|
||||
@param Buffer data buffer pointer
|
||||
@param BufferSize Size of data in the Buffer
|
||||
|
||||
@retval EFI_SUCCESS if successfully completed the undi call
|
||||
@retval Other error return from undi call.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PxeTransmit (
|
||||
SNP_DRIVER *Snp,
|
||||
VOID *Buffer,
|
||||
UINTN BufferSize
|
||||
)
|
||||
{
|
||||
PXE_CPB_TRANSMIT *Cpb;
|
||||
EFI_STATUS Status;
|
||||
|
||||
Cpb = Snp->Cpb;
|
||||
Cpb->FrameAddr = (UINT64) (UINTN) Buffer;
|
||||
Cpb->DataLen = (UINT32) BufferSize;
|
||||
|
||||
Cpb->MediaheaderLen = 0;
|
||||
Cpb->reserved = 0;
|
||||
|
||||
Snp->Cdb.OpFlags = PXE_OPFLAGS_TRANSMIT_WHOLE;
|
||||
|
||||
Snp->Cdb.CPBsize = (UINT16) sizeof (PXE_CPB_TRANSMIT);
|
||||
Snp->Cdb.CPBaddr = (UINT64)(UINTN) Cpb;
|
||||
|
||||
Snp->Cdb.OpCode = PXE_OPCODE_TRANSMIT;
|
||||
Snp->Cdb.DBsize = PXE_DBSIZE_NOT_USED;
|
||||
Snp->Cdb.DBaddr = PXE_DBADDR_NOT_USED;
|
||||
|
||||
Snp->Cdb.StatCode = PXE_STATCODE_INITIALIZE;
|
||||
Snp->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
|
||||
Snp->Cdb.IFnum = Snp->IfNum;
|
||||
Snp->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
|
||||
|
||||
//
|
||||
// Issue UNDI command and check result.
|
||||
//
|
||||
DEBUG ((EFI_D_NET, "\nSnp->undi.transmit() "));
|
||||
DEBUG ((EFI_D_NET, "\nSnp->Cdb.OpCode == %x", Snp->Cdb.OpCode));
|
||||
DEBUG ((EFI_D_NET, "\nSnp->Cdb.CPBaddr == %LX", Snp->Cdb.CPBaddr));
|
||||
DEBUG ((EFI_D_NET, "\nSnp->Cdb.DBaddr == %LX", Snp->Cdb.DBaddr));
|
||||
DEBUG ((EFI_D_NET, "\nCpb->FrameAddr == %LX\n", Cpb->FrameAddr));
|
||||
|
||||
(*Snp->IssueUndi32Command) ((UINT64) (UINTN) &Snp->Cdb);
|
||||
|
||||
DEBUG ((EFI_D_NET, "\nexit Snp->undi.transmit() "));
|
||||
|
||||
//
|
||||
// we will unmap the buffers in get_status call, not here
|
||||
//
|
||||
switch (Snp->Cdb.StatCode) {
|
||||
case PXE_STATCODE_SUCCESS:
|
||||
return EFI_SUCCESS;
|
||||
|
||||
case PXE_STATCODE_BUFFER_FULL:
|
||||
case PXE_STATCODE_QUEUE_FULL:
|
||||
case PXE_STATCODE_BUSY:
|
||||
Status = EFI_NOT_READY;
|
||||
DEBUG (
|
||||
(EFI_D_NET,
|
||||
"\nSnp->undi.transmit() %xh:%xh\n",
|
||||
Snp->Cdb.StatFlags,
|
||||
Snp->Cdb.StatCode)
|
||||
);
|
||||
break;
|
||||
|
||||
default:
|
||||
DEBUG (
|
||||
(EFI_D_ERROR,
|
||||
"\nSnp->undi.transmit() %xh:%xh\n",
|
||||
Snp->Cdb.StatFlags,
|
||||
Snp->Cdb.StatCode)
|
||||
);
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Places a packet in the transmit queue of a network interface.
|
||||
|
||||
This function places the packet specified by Header and Buffer on the transmit
|
||||
queue. If HeaderSize is nonzero and HeaderSize is not equal to
|
||||
This->Mode->MediaHeaderSize, then EFI_INVALID_PARAMETER will be returned. If
|
||||
BufferSize is less than This->Mode->MediaHeaderSize, then EFI_BUFFER_TOO_SMALL
|
||||
will be returned. If Buffer is NULL, then EFI_INVALID_PARAMETER will be
|
||||
returned. If HeaderSize is nonzero and DestAddr or Protocol is NULL, then
|
||||
EFI_INVALID_PARAMETER will be returned. If the transmit engine of the network
|
||||
interface is busy, then EFI_NOT_READY will be returned. If this packet can be
|
||||
accepted by the transmit engine of the network interface, the packet contents
|
||||
specified by Buffer will be placed on the transmit queue of the network
|
||||
interface, and EFI_SUCCESS will be returned. GetStatus() can be used to
|
||||
determine when the packet has actually been transmitted. The contents of the
|
||||
Buffer must not be modified until the packet has actually been transmitted.
|
||||
The Transmit() function performs nonblocking I/O. A caller who wants to perform
|
||||
blocking I/O, should call Transmit(), and then GetStatus() until the
|
||||
transmitted buffer shows up in the recycled transmit buffer.
|
||||
If the driver has not been initialized, EFI_DEVICE_ERROR will be returned.
|
||||
|
||||
@param This A pointer to the EFI_SIMPLE_NETWORK_PROTOCOL instance.
|
||||
@param HeaderSize The size, in bytes, of the media header to be filled in by the
|
||||
Transmit() function. If HeaderSize is nonzero, then it must
|
||||
be equal to This->Mode->MediaHeaderSize and the DestAddr and
|
||||
Protocol parameters must not be NULL.
|
||||
@param BufferSize The size, in bytes, of the entire packet (media header and
|
||||
data) to be transmitted through the network interface.
|
||||
@param Buffer A pointer to the packet (media header followed by data) to be
|
||||
transmitted. This parameter cannot be NULL. If HeaderSize is
|
||||
zero, then the media header in Buffer must already be filled
|
||||
in by the caller. If HeaderSize is nonzero, then the media
|
||||
header will be filled in by the Transmit() function.
|
||||
@param SrcAddr The source HW MAC address. If HeaderSize is zero, then this
|
||||
parameter is ignored. If HeaderSize is nonzero and SrcAddr
|
||||
is NULL, then This->Mode->CurrentAddress is used for the
|
||||
source HW MAC address.
|
||||
@param DestAddr The destination HW MAC address. If HeaderSize is zero, then
|
||||
this parameter is ignored.
|
||||
@param Protocol The type of header to build. If HeaderSize is zero, then this
|
||||
parameter is ignored. See RFC 1700, section "Ether Types,"
|
||||
for examples.
|
||||
|
||||
@retval EFI_SUCCESS The packet was placed on the transmit queue.
|
||||
@retval EFI_NOT_STARTED The network interface has not been started.
|
||||
@retval EFI_NOT_READY The network interface is too busy to accept this
|
||||
transmit request.
|
||||
@retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small.
|
||||
@retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported
|
||||
value.
|
||||
@retval EFI_DEVICE_ERROR The command could not be sent to the network interface.
|
||||
@retval EFI_UNSUPPORTED This function is not supported by the network interface.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SnpUndi32Transmit (
|
||||
IN EFI_SIMPLE_NETWORK_PROTOCOL *This,
|
||||
IN UINTN HeaderSize,
|
||||
IN UINTN BufferSize,
|
||||
IN VOID *Buffer,
|
||||
IN EFI_MAC_ADDRESS *SrcAddr, OPTIONAL
|
||||
IN EFI_MAC_ADDRESS *DestAddr, OPTIONAL
|
||||
IN UINT16 *Protocol OPTIONAL
|
||||
)
|
||||
{
|
||||
SNP_DRIVER *Snp;
|
||||
EFI_STATUS Status;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
if (This == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This);
|
||||
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
|
||||
if (Snp == NULL) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
switch (Snp->Mode.State) {
|
||||
case EfiSimpleNetworkInitialized:
|
||||
break;
|
||||
|
||||
case EfiSimpleNetworkStopped:
|
||||
Status = EFI_NOT_STARTED;
|
||||
goto ON_EXIT;
|
||||
|
||||
default:
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
if (Buffer == NULL) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
if (BufferSize < Snp->Mode.MediaHeaderSize) {
|
||||
Status = EFI_BUFFER_TOO_SMALL;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
//
|
||||
// if the HeaderSize is non-zero, we need to fill up the header and for that
|
||||
// we need the destination address and the protocol
|
||||
//
|
||||
if (HeaderSize != 0) {
|
||||
if (HeaderSize != Snp->Mode.MediaHeaderSize || DestAddr == 0 || Protocol == 0) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
goto ON_EXIT;
|
||||
}
|
||||
|
||||
Status = PxeFillHeader (
|
||||
Snp,
|
||||
Buffer,
|
||||
HeaderSize,
|
||||
(UINT8 *) Buffer + HeaderSize,
|
||||
BufferSize - HeaderSize,
|
||||
DestAddr,
|
||||
SrcAddr,
|
||||
Protocol
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ON_EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
Status = PxeTransmit (Snp, Buffer, BufferSize);
|
||||
|
||||
ON_EXIT:
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
return Status;
|
||||
}
|
86
NetworkPkg/SnpDxe/WaitForPacket.c
Normal file
86
NetworkPkg/SnpDxe/WaitForPacket.c
Normal file
@@ -0,0 +1,86 @@
|
||||
/** @file
|
||||
Event handler to check for available packet.
|
||||
|
||||
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "Snp.h"
|
||||
|
||||
|
||||
/**
|
||||
Nofication call back function for WaitForPacket event.
|
||||
|
||||
@param Event EFI Event.
|
||||
@param SnpPtr Pointer to SNP_DRIVER structure.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SnpWaitForPacketNotify (
|
||||
EFI_EVENT Event,
|
||||
VOID *SnpPtr
|
||||
)
|
||||
{
|
||||
PXE_DB_GET_STATUS PxeDbGetStatus;
|
||||
|
||||
//
|
||||
// Do nothing if either parameter is a NULL pointer.
|
||||
//
|
||||
if (Event == NULL || SnpPtr == NULL) {
|
||||
return ;
|
||||
}
|
||||
//
|
||||
// Do nothing if the SNP interface is not initialized.
|
||||
//
|
||||
switch (((SNP_DRIVER *) SnpPtr)->Mode.State) {
|
||||
case EfiSimpleNetworkInitialized:
|
||||
break;
|
||||
|
||||
case EfiSimpleNetworkStopped:
|
||||
case EfiSimpleNetworkStarted:
|
||||
default:
|
||||
return ;
|
||||
}
|
||||
//
|
||||
// Fill in CDB for UNDI GetStatus().
|
||||
//
|
||||
((SNP_DRIVER *) SnpPtr)->Cdb.OpCode = PXE_OPCODE_GET_STATUS;
|
||||
((SNP_DRIVER *) SnpPtr)->Cdb.OpFlags = 0;
|
||||
((SNP_DRIVER *) SnpPtr)->Cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
|
||||
((SNP_DRIVER *) SnpPtr)->Cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
|
||||
((SNP_DRIVER *) SnpPtr)->Cdb.DBsize = (UINT16) (sizeof (UINT32) * 2);
|
||||
((SNP_DRIVER *) SnpPtr)->Cdb.DBaddr = (UINT64)(UINTN) (((SNP_DRIVER *) SnpPtr)->Db);
|
||||
((SNP_DRIVER *) SnpPtr)->Cdb.StatCode = PXE_STATCODE_INITIALIZE;
|
||||
((SNP_DRIVER *) SnpPtr)->Cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
|
||||
((SNP_DRIVER *) SnpPtr)->Cdb.IFnum = ((SNP_DRIVER *) SnpPtr)->IfNum;
|
||||
((SNP_DRIVER *) SnpPtr)->Cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
|
||||
|
||||
//
|
||||
// Clear contents of DB buffer.
|
||||
//
|
||||
ZeroMem (((SNP_DRIVER *) SnpPtr)->Db, sizeof (UINT32) * 2);
|
||||
|
||||
//
|
||||
// Issue UNDI command and check result.
|
||||
//
|
||||
(*((SNP_DRIVER *) SnpPtr)->IssueUndi32Command) ((UINT64)(UINTN) &((SNP_DRIVER *) SnpPtr)->Cdb);
|
||||
|
||||
if (((SNP_DRIVER *) SnpPtr)->Cdb.StatCode != EFI_SUCCESS) {
|
||||
return ;
|
||||
}
|
||||
//
|
||||
// We might have a packet. Check the receive length and signal
|
||||
// the event if the length is not zero.
|
||||
//
|
||||
CopyMem (
|
||||
&PxeDbGetStatus,
|
||||
((SNP_DRIVER *) SnpPtr)->Db,
|
||||
sizeof (UINT32) * 2
|
||||
);
|
||||
|
||||
if (PxeDbGetStatus.RxFrameLen != 0) {
|
||||
gBS->SignalEvent (Event);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user