Import SnpDxe, Tcp4Dxe, Udp4Dxe and MnpDxe.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3416 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
vanjeff 2007-07-24 08:06:37 +00:00
parent f9bef4b3ac
commit 8a67d61da4
66 changed files with 25898 additions and 52 deletions

View File

@ -171,7 +171,7 @@ typedef struct _IP_IO_SEND_ENTRY {
EFI_IP4_COMPLETION_TOKEN *SndToken;
} IP_IO_SEND_ENTRY;
typedef struct _EFI_IP4_OVERRIDE_DATA IP_IO_OVERRIDE;
typedef EFI_IP4_OVERRIDE_DATA IP_IO_OVERRIDE;
typedef struct _IP_IO_IP_INFO {
IP4_ADDR Addr;

View File

@ -809,4 +809,79 @@ NetPseudoHeadChecksum (
IN UINT8 Proto,
IN UINT16 Len
);
//
// The debug level definition. This value is also used as the
// syslog's servity level. Don't change it.
//
enum {
NETDEBUG_LEVEL_TRACE = 5,
NETDEBUG_LEVEL_WARNING = 4,
NETDEBUG_LEVEL_ERROR = 3,
};
#ifdef EFI_NETWORK_STACK_DEBUG
//
// The debug output expects the ASCII format string, Use %a to print ASCII
// string, and %s to print UNICODE string. PrintArg must be enclosed in ().
// For example: NET_DEBUG_TRACE ("Tcp", ("State transit to %a\n", Name));
//
#define NET_DEBUG_TRACE(Module, PrintArg) \
NetDebugOutput ( \
NETDEBUG_LEVEL_TRACE, \
Module, \
__FILE__, \
__LINE__, \
NetDebugASPrint PrintArg \
)
#define NET_DEBUG_WARNING(Module, PrintArg) \
NetDebugOutput ( \
NETDEBUG_LEVEL_WARNING, \
Module, \
__FILE__, \
__LINE__, \
NetDebugASPrint PrintArg \
)
#define NET_DEBUG_ERROR(Module, PrintArg) \
NetDebugOutput ( \
NETDEBUG_LEVEL_ERROR, \
Module, \
__FILE__, \
__LINE__, \
NetDebugASPrint PrintArg \
)
#else
#define NET_DEBUG_TRACE(Module, PrintString)
#define NET_DEBUG_WARNING(Module, PrintString)
#define NET_DEBUG_ERROR(Module, PrintString)
#endif
UINT8 *
NetDebugASPrint (
UINT8 *Format,
...
);
EFI_STATUS
NetDebugOutput (
UINT32 Level,
UINT8 *Module,
UINT8 *File,
UINT32 Line,
UINT8 *Message
);
//
// Network debug message is sent out as syslog.
//
enum {
NET_SYSLOG_FACILITY = 16, // Syslog local facility local use
NET_SYSLOG_PACKET_LEN = 512,
NET_DEBUG_MSG_LEN = 470, // 512 - (ether+ip+udp head length)
NET_SYSLOG_TX_TIMEOUT = 500 *1000 *10, // 500ms
};
#endif

View File

@ -41,25 +41,12 @@
[LibraryClasses]
MemoryAllocationLib
UefiLib
IpIoLib
BaseLib
UefiBootServicesTableLib
UefiRuntimeServicesTableLib
BaseMemoryLib
DebugLib
PrintLib
UefiBootServicesTableLib
MemoryAllocationLib
[Protocols]
gEfiIp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiDriverDiagnosticsProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiUdp4ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiLoadedImageProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiIp4ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiDriverConfigurationProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiSimpleNetworkProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiDriverBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiUdp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiComponentNameProtocolGuid # PROTOCOL ALWAYS_CONSUMED

View File

@ -35,6 +35,7 @@
[Sources.common]
DxeNetLib.c
NetBuffer.c
NetDebug.c
[Packages]
MdePkg/MdePkg.dec
@ -42,25 +43,15 @@
[LibraryClasses]
MemoryAllocationLib
UefiLib
BaseLib
UefiBootServicesTableLib
UefiRuntimeServicesTableLib
BaseMemoryLib
DebugLib
PrintLib
NetLib
BaseLib
DebugLib
BaseMemoryLib
UefiBootServicesTableLib
UefiRuntimeServicesTableLib
UefiLib
MemoryAllocationLib
[Protocols]
gEfiIp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiDriverDiagnosticsProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiUdp4ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiLoadedImageProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiIp4ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiDriverConfigurationProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiSimpleNetworkProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiDriverBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiUdp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiComponentNameProtocolGuid # PROTOCOL ALWAYS_CONSUMED

View File

@ -0,0 +1,536 @@
/** @file
Copyright (c) 2005 - 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
NetDebug.c
Abstract:
Network debug facility. The debug information is wrapped in
SYSLOG packets, then sent over SNP. This debug facility can't
be used by SNP. Apply caution when used in MNP and non-network
module because SNP is most likely not "thread safe". We assume
that the SNP supports the EHTERNET.
**/
#include <PiDxe.h>
#include <Protocol/SimpleNetwork.h>
#include <Library/BaseLib.h>
#include <Library/NetLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/PrintLib.h>
//
// Any error level digitally larger than mNetDebugLevelMax
// will be silently discarded.
//
UINTN mNetDebugLevelMax = NETDEBUG_LEVEL_ERROR;
UINT32 mSyslogPacketSeq = 0xDEADBEEF;
//
// You can change mSyslogDstMac mSyslogDstIp and mSyslogSrcIp
// here to direct the syslog packets to the syslog deamon. The
// default is broadcast to both the ethernet and IP.
//
UINT8 mSyslogDstMac [NET_ETHER_ADDR_LEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
UINT32 mSyslogDstIp = 0xffffffff;
UINT32 mSyslogSrcIp = 0;
UINT8 *
MonthName[] = {
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
};
/**
Locate the handles that support SNP, then open one of them
to send the syslog packets. The caller isn't required to close
the SNP after use because the SNP is opened by HandleProtocol.
None
@return The point to SNP if one is properly openned. Otherwise NULL
**/
EFI_SIMPLE_NETWORK_PROTOCOL *
SyslogLocateSnp (
VOID
)
{
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
EFI_STATUS Status;
EFI_HANDLE *Handles;
UINTN HandleCount;
UINTN Index;
//
// Locate the handles which has SNP installed.
//
Handles = NULL;
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiSimpleNetworkProtocolGuid,
NULL,
&HandleCount,
&Handles
);
if (EFI_ERROR (Status) || (HandleCount == 0)) {
return NULL;
}
//
// Try to open one of the ethernet SNP protocol to send packet
//
Snp = NULL;
for (Index = 0; Index < HandleCount; Index++) {
Status = gBS->HandleProtocol (
Handles[Index],
&gEfiSimpleNetworkProtocolGuid,
(VOID **) &Snp
);
if ((Status == EFI_SUCCESS) && (Snp != NULL) &&
(Snp->Mode->IfType == NET_IFTYPE_ETHERNET) &&
(Snp->Mode->MaxPacketSize >= NET_SYSLOG_PACKET_LEN)) {
break;
}
Snp = NULL;
}
gBS->FreePool (Handles);
return Snp;
}
/**
Transmit a syslog packet synchronously through SNP. The Packet
already has the ethernet header prepended. This function should
fill in the source MAC because it will try to locate a SNP each
time it is called to avoid the problem if SNP is unloaded.
This code snip is copied from MNP.
@param Packet The Syslog packet
@param Length The length of the packet
@retval EFI_DEVICE_ERROR Failed to locate a usable SNP protocol
@retval EFI_TIMEOUT Timeout happened to send the packet.
@retval EFI_SUCCESS Packet is sent.
**/
EFI_STATUS
SyslogSendPacket (
IN UINT8 *Packet,
IN UINT32 Length
)
{
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
ETHER_HEAD *Ether;
EFI_STATUS Status;
EFI_EVENT TimeoutEvent;
UINT8 *TxBuf;
Snp = SyslogLocateSnp ();
if (Snp == NULL) {
return EFI_DEVICE_ERROR;
}
Ether = (ETHER_HEAD *) Packet;
CopyMem (Ether->SrcMac, Snp->Mode->CurrentAddress.Addr, NET_ETHER_ADDR_LEN);
//
// Start the timeout event.
//
Status = gBS->CreateEvent (
EVT_TIMER,
TPL_NOTIFY,
NULL,
NULL,
&TimeoutEvent
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = gBS->SetTimer (TimeoutEvent, TimerRelative, NET_SYSLOG_TX_TIMEOUT);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
for (;;) {
//
// Transmit the packet through SNP.
//
Status = Snp->Transmit (Snp, 0, Length, Packet, NULL, NULL, NULL);
if ((Status != EFI_SUCCESS) && (Status != EFI_NOT_READY)) {
Status = EFI_DEVICE_ERROR;
break;
}
//
// If Status is EFI_SUCCESS, the packet is put in the transmit queue.
// if Status is EFI_NOT_READY, the transmit engine of the network
// interface is busy. Both need to sync SNP.
//
TxBuf = NULL;
do {
//
// Get the recycled transmit buffer status.
//
Snp->GetStatus (Snp, NULL, &TxBuf);
if (!EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) {
Status = EFI_TIMEOUT;
break;
}
} while (TxBuf == NULL);
if ((Status == EFI_SUCCESS) || (Status == EFI_TIMEOUT)) {
break;
}
//
// Status is EFI_NOT_READY. Restart the timer event and
// call Snp->Transmit again.
//
gBS->SetTimer (TimeoutEvent, TimerRelative, NET_SYSLOG_TX_TIMEOUT);
}
gBS->SetTimer (TimeoutEvent, TimerCancel, 0);
ON_EXIT:
gBS->CloseEvent (TimeoutEvent);
return Status;
}
/**
Compute checksum for a bulk of data. This code is copied from the
Netbuffer library.
@param Bulk Pointer to the data.
@param Len Length of the data, in bytes.
@retval UINT16 The computed checksum.
**/
UINT16
SyslogChecksum (
IN UINT8 *Bulk,
IN UINT32 Len
)
{
register UINT32 Sum;
Sum = 0;
while (Len > 1) {
Sum += *(UINT16 *) Bulk;
Bulk += 2;
Len -= 2;
}
//
// Add left-over byte, if any
//
if (Len > 0) {
Sum += *(UINT8 *) Bulk;
}
//
// Fold 32-bit sum to 16 bits
//
while (Sum >> 16) {
Sum = (Sum & 0xffff) + (Sum >> 16);
}
return (UINT16) ~Sum;
}
/**
Build a syslog packet, including the Ethernet/Ip/Udp headers
and user's message.
@param Buf The buffer to put the packet data
@param BufLen The lenght of the Buf
@param Level Syslog servity level
@param Module The module that generates the log
@param File The file that contains the current log
@param Line The line of code in the File that contains the
current log
@param Message The log message
@return The length of the syslog packet built.
**/
UINT32
SyslogBuildPacket (
UINT8 *Buf,
UINT32 BufLen,
UINT32 Level,
UINT8 *Module,
UINT8 *File,
UINT32 Line,
UINT8 *Message
)
{
ETHER_HEAD *Ether;
IP4_HEAD *Ip4;
EFI_UDP4_HEADER *Udp4;
EFI_TIME Time;
UINT32 Pri;
UINT32 Len;
//
// Fill in the Ethernet header. Leave alone the source MAC.
// SyslogSendPacket will fill in the address for us.
//
Ether = (ETHER_HEAD *) Buf;
CopyMem (Ether->DstMac, mSyslogDstMac, NET_ETHER_ADDR_LEN);
ZeroMem (Ether->SrcMac, NET_ETHER_ADDR_LEN);
Ether->EtherType = HTONS (0x0800); // IP protocol
Buf += sizeof (ETHER_HEAD);
BufLen -= sizeof (ETHER_HEAD);
//
// Fill in the IP header
//
Ip4 = (IP4_HEAD *) Buf;
Ip4->HeadLen = 5;
Ip4->Ver = 4;
Ip4->Tos = 0;
Ip4->TotalLen = 0;
Ip4->Id = (UINT16) mSyslogPacketSeq;
Ip4->Fragment = 0;
Ip4->Ttl = 16;
Ip4->Protocol = 0x11;
Ip4->Checksum = 0;
Ip4->Src = mSyslogSrcIp;
Ip4->Dst = mSyslogDstIp;
Buf += sizeof (IP4_HEAD);
BufLen -= sizeof (IP4_HEAD);
//
// Fill in the UDP header, Udp checksum is optional. Leave it zero.
//
Udp4 = (EFI_UDP4_HEADER*) Buf;
Udp4->SrcPort = HTONS (514);
Udp4->DstPort = HTONS (514);
Udp4->Length = 0;
Udp4->Checksum = 0;
Buf += sizeof (EFI_UDP4_HEADER);
BufLen -= sizeof (EFI_UDP4_HEADER);
//
// Build the syslog message body with <PRI> Timestamp machine module Message
//
Pri = ((NET_SYSLOG_FACILITY & 31) << 3) | (Level & 7);
gRT->GetTime (&Time, NULL);
//
// Use %a to format the ASCII strings, %s to format UNICODE strings
//
Len = 0;
Len += (UINT32) AsciiSPrint (
Buf,
BufLen,
"<%d> %a %d %d:%d:%d ",
Pri,
MonthName [Time.Month-1],
Time.Day,
Time.Hour,
Time.Minute,
Time.Second
);
Len--;
Len += (UINT32) AsciiSPrint (
Buf + Len,
BufLen - Len,
"Tiano %a: %a (Line: %d File: %a)",
Module,
Message,
Line,
File
);
Len--;
//
// OK, patch the IP length/checksum and UDP length fields.
//
Len += sizeof (EFI_UDP4_HEADER);
Udp4->Length = HTONS ((UINT16) Len);
Len += sizeof (IP4_HEAD);
Ip4->TotalLen = HTONS ((UINT16) Len);
Ip4->Checksum = SyslogChecksum ((UINT8 *) Ip4, sizeof (IP4_HEAD));
return Len + sizeof (ETHER_HEAD);
}
/**
Allocate a buffer, then format the message to it. This is a
help function for the NET_DEBUG_XXX macros. The PrintArg of
these macros treats the variable length print parameters as a
single parameter, and pass it to the NetDebugASPrint. For
example, NET_DEBUG_TRACE ("Tcp", ("State transit to %a\n", Name))
if extracted to:
NetDebugOutput (
NETDEBUG_LEVEL_TRACE,
"Tcp",
__FILE__,
__LINE__,
NetDebugASPrint ("State transit to %a\n", Name)
)
This is exactly what we want.
@param Format The ASCII format string.
@param ... The variable length parameter whose format is
determined by the Format string.
@return The buffer containing the formatted message, or NULL if failed to
@return allocate memory.
**/
UINT8 *
NetDebugASPrint (
UINT8 *Format,
...
)
{
VA_LIST Marker;
UINT8 *Buf;
Buf = AllocatePool (NET_DEBUG_MSG_LEN);
if (Buf == NULL) {
return NULL;
}
VA_START (Marker, Format);
AsciiVSPrint (Buf, NET_DEBUG_MSG_LEN, Format, Marker);
VA_END (Marker);
return Buf;
}
/**
Output a debug message to syslog. This function will locate a
instance of SNP then send the message through it. Because it
isn't open the SNP BY_DRIVER, apply caution when using it.
@param Level The servity level of the message.
@param Module The Moudle that generates the log.
@param File The file that contains the log.
@param Line The exact line that contains the log.
@param Message The user message to log.
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the packet
@retval EFI_SUCCESS The log is discard because that it is more verbose
than the mNetDebugLevelMax. Or, it has been sent
out.
**/
EFI_STATUS
NetDebugOutput (
UINT32 Level,
UINT8 *Module,
UINT8 *File,
UINT32 Line,
UINT8 *Message
)
{
UINT8 *Packet;
UINT32 Len;
EFI_STATUS Status;
//
// Check whether the message should be sent out
//
if (Message == NULL) {
return EFI_OUT_OF_RESOURCES;
}
if (Level > mNetDebugLevelMax) {
Status = EFI_SUCCESS;
goto ON_EXIT;
}
//
// Allocate a maxium of 1024 bytes, the caller should ensure
// that the message plus the ethernet/ip/udp header is shorter
// than this
//
Packet = AllocatePool (NET_SYSLOG_PACKET_LEN);
if (Packet == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
//
// Build the message: Ethernet header + IP header + Udp Header + user data
//
Len = SyslogBuildPacket (
Packet,
NET_SYSLOG_PACKET_LEN,
Level,
Module,
File,
Line,
Message
);
mSyslogPacketSeq++;
Status = SyslogSendPacket (Packet, Len);
gBS->FreePool (Packet);
ON_EXIT:
gBS->FreePool (Message);
return Status;
}

View File

@ -41,25 +41,12 @@
[LibraryClasses]
MemoryAllocationLib
UefiLib
UdpIoLib
BaseLib
UefiBootServicesTableLib
UefiRuntimeServicesTableLib
BaseMemoryLib
DebugLib
PrintLib
UefiBootServicesTableLib
MemoryAllocationLib
[Protocols]
gEfiIp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiDriverDiagnosticsProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiUdp4ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiLoadedImageProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiIp4ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiDriverConfigurationProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiSimpleNetworkProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiDriverBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiUdp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiComponentNameProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiUdp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED

View File

@ -401,6 +401,10 @@
$(WORKSPACE)/MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf
$(WORKSPACE)/MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf
$(WORKSPACE)/MdeModulePkg/Universal/Network/MnpDxe/MnpDxe.inf
$(WORKSPACE)/MdeModulePkg/Universal/Network/SnpDxe/SnpDxe.inf
$(WORKSPACE)/MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dxe.inf
$(WORKSPACE)/MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Dxe.inf
$(WORKSPACE)/MdeModulePkg/Application/HelloWorld/HelloWorld.inf

View File

@ -0,0 +1,162 @@
/** @file
Copyright (c) 2005 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
ComponentName.c
Abstract:
**/
#include "MnpDriver.h"
//
// EFI Component Name Functions
//
EFI_STATUS
EFIAPI
MnpComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
);
EFI_STATUS
EFIAPI
MnpComponentNameGetControllerName (
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
//
EFI_COMPONENT_NAME_PROTOCOL gMnpComponentName = {
MnpComponentNameGetDriverName,
MnpComponentNameGetControllerName,
"eng"
};
STATIC EFI_UNICODE_STRING_TABLE mMnpDriverNameTable[] = {
{
"eng",
L"MNP Network Service Driver"
},
{
NULL,
NULL
}
};
EFI_STATUS
EFIAPI
MnpComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
/*++
Routine Description:
Retrieves a Unicode string that is the user readable name of the EFI Driver.
Arguments:
This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
Language - A pointer to a three character ISO 639-2 language identifier.
This is the language of the driver name that 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.
DriverName - A pointer to the Unicode string to return. This Unicode string
is the name of the driver specified by This in the language
specified by Language.
Returns:
EFI_SUCCES - The Unicode string for the Driver specified by This
and the language specified by Language was returned
in DriverName.
EFI_INVALID_PARAMETER - Language is NULL.
EFI_INVALID_PARAMETER - DriverName is NULL.
EFI_UNSUPPORTED - The driver specified by This does not support the
language specified by Language.
--*/
{
return LookupUnicodeString (
Language,
gMnpComponentName.SupportedLanguages,
mMnpDriverNameTable,
DriverName
);
}
EFI_STATUS
EFIAPI
MnpComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
)
/*++
Routine Description:
Retrieves a Unicode string that is the user readable name of the controller
that is being managed by an EFI Driver.
Arguments:
This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
ControllerHandle - The handle of a controller that the driver specified by
This is managing. This handle specifies the controller
whose name is to be returned.
ChildHandle - The handle of the child controller to retrieve the name
of. This is an optional parameter that may be NULL. It
will be NULL for device drivers. It will also be NULL
for a bus drivers that wish to retrieve the name of the
bus controller. It will not be NULL for a bus driver
that wishes to retrieve the name of a child controller.
Language - A pointer to a three character ISO 639-2 language
identifier. This is the language of the controller name
that 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.
ControllerName - A pointer to the Unicode string to return. This Unicode
string is the name of the controller specified by
ControllerHandle and ChildHandle in the language specified
by Language from the point of view of the driver specified
by This.
Returns:
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.
EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.
EFI_INVALID_PARAMETER - Language is NULL.
EFI_INVALID_PARAMETER - ControllerName is NULL.
EFI_UNSUPPORTED - The driver specified by This is not currently managing
the controller specified by ControllerHandle and
ChildHandle.
EFI_UNSUPPORTED - The driver specified by This does not support the
language specified by Language.
--*/
{
return EFI_UNSUPPORTED;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,28 @@
/** @file
Copyright (c) 2005 - 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
MnpDebug.h
Abstract:
**/
#ifndef _MNP_DEBUG_H_
#define _MNP_DEBUG_H_
#define MNP_DEBUG_TRACE(PrintArg) NET_DEBUG_TRACE ("Mnp", PrintArg)
#define MNP_DEBUG_WARN(PrintArg) NET_DEBUG_WARNING ("Mnp", PrintArg)
#define MNP_DEBUG_ERROR(PrintArg) NET_DEBUG_ERROR ("Mnp", PrintArg)
#endif

View File

@ -0,0 +1,560 @@
/** @file
Copyright (c) 2005 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
MnpDriver.c
Abstract:
**/
#include "MnpDriver.h"
#include "MnpDebug.h"
#include "MnpImpl.h"
EFI_DRIVER_BINDING_PROTOCOL gMnpDriverBinding = {
MnpDriverBindingSupported,
MnpDriverBindingStart,
MnpDriverBindingStop,
0xa,
NULL,
NULL
};
/**
Test to see if this driver supports ControllerHandle.
@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_SUCCES 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
MnpDriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
)
{
EFI_STATUS Status;
//
// Test to see if MNP is already installed.
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiManagedNetworkServiceBindingProtocolGuid,
NULL,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
if (!EFI_ERROR (Status)) {
return EFI_ALREADY_STARTED;
}
//
// Test to see if SNP is installed.
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiSimpleNetworkProtocolGuid,
NULL,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
return Status;
}
/**
Start this driver on ControllerHandle.
@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_SUCCES This driver is added to ControllerHandle.
@retval EFI_ALREADY_STARTED This driver is already running on
ControllerHandle.
@retval other This driver does not support this device.
**/
EFI_STATUS
EFIAPI
MnpDriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
)
{
EFI_STATUS Status;
MNP_SERVICE_DATA *MnpServiceData;
BOOLEAN MnpInitialized;
MnpInitialized = FALSE;
MnpServiceData = NetAllocateZeroPool (sizeof (MNP_SERVICE_DATA));
if (MnpServiceData == NULL) {
MNP_DEBUG_ERROR (("MnpDriverBindingStart(): Failed to allocate the "
L"Mnp Service Data.\n"));
return EFI_OUT_OF_RESOURCES;
}
//
// Initialize the Mnp Service Data.
//
Status = MnpInitializeServiceData (MnpServiceData, This->DriverBindingHandle, ControllerHandle);
if (EFI_ERROR (Status)) {
MNP_DEBUG_ERROR (("MnpDriverBindingStart: MnpInitializeServiceData "
L"failed, %r.\n",Status));
goto ErrorExit;
}
MnpInitialized = TRUE;
//
// Install the MNP Service Binding Protocol.
//
Status = gBS->InstallMultipleProtocolInterfaces (
&ControllerHandle,
&gEfiManagedNetworkServiceBindingProtocolGuid,
&MnpServiceData->ServiceBinding,
NULL
);
ErrorExit:
if (EFI_ERROR (Status)) {
if (MnpInitialized) {
//
// Flush the Mnp Service Data.
//
MnpFlushServiceData (MnpServiceData);
}
//
// Close the Simple Network Protocol.
//
gBS->CloseProtocol (
ControllerHandle,
&gEfiSimpleNetworkProtocolGuid,
This->DriverBindingHandle,
ControllerHandle
);
NetFreePool (MnpServiceData);
}
return Status;
}
/**
Stop this driver on ControllerHandle.
@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_SUCCES This driver is removed ControllerHandle.
@retval other This driver was not removed from this device.
**/
EFI_STATUS
EFIAPI
MnpDriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
)
{
EFI_STATUS Status;
EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
MNP_SERVICE_DATA *MnpServiceData;
MNP_INSTANCE_DATA *Instance;
//
// Retrieve the MNP service binding protocol from the ControllerHandle.
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiManagedNetworkServiceBindingProtocolGuid,
(VOID **) &ServiceBinding,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
MNP_DEBUG_ERROR (
("MnpDriverBindingStop: Locate MNP Service Binding Protocol failed, %r.\n",
Status)
);
goto EXIT;
}
MnpServiceData = MNP_SERVICE_DATA_FROM_THIS (ServiceBinding);
while (!NetListIsEmpty (&MnpServiceData->ChildrenList)) {
//
// Don't use NetListRemoveHead here, the remove opreration will be done
// in ServiceBindingDestroyChild.
//
Instance = NET_LIST_HEAD (
&MnpServiceData->ChildrenList,
MNP_INSTANCE_DATA,
InstEntry
);
ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);
}
//
// Uninstall the MNP Service Binding Protocol.
//
Status = gBS->UninstallMultipleProtocolInterfaces (
ControllerHandle,
&gEfiManagedNetworkServiceBindingProtocolGuid,
ServiceBinding,
NULL
);
if (EFI_ERROR (Status)) {
MNP_DEBUG_ERROR (("MnpDriverBindingStop: Uninstall MNP Service Binding Protocol failed, %r.\n"));
goto EXIT;
}
//
// Close the openned Snp protocol.
//
Status = gBS->CloseProtocol (
ControllerHandle,
&gEfiSimpleNetworkProtocolGuid,
This->DriverBindingHandle,
ControllerHandle
);
if (EFI_ERROR (Status)) {
MNP_DEBUG_ERROR (("MnpDriverBindingStop: Close SNP Protocol failed, %r.\n", Status));
goto EXIT;
}
//
// Flush the Mnp service data.
//
MnpFlushServiceData (MnpServiceData);
NetFreePool (MnpServiceData);
EXIT:
return Status;
}
/**
Creates a child handle with a set of I/O services.
@param This Protocol instance pointer.
@param ChildHandle Pointer to the handle of the child to create. If
it is NULL, then a new handle is created. If it is
not NULL, then the I/O services are added to the
existing child handle.
@retval EFI_SUCCES The child handle was created with the I/O
services.
@retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
the child.
@retval other The child handle was not created.
**/
EFI_STATUS
EFIAPI
MnpServiceBindingCreateChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN EFI_HANDLE *ChildHandle
)
{
EFI_STATUS Status;
MNP_SERVICE_DATA *MnpServiceData;
MNP_INSTANCE_DATA *Instance;
VOID *Snp;
EFI_TPL OldTpl;
if ((This == NULL) || (ChildHandle == NULL)) {
return EFI_INVALID_PARAMETER;
}
MnpServiceData = MNP_SERVICE_DATA_FROM_THIS (This);
//
// Allocate buffer for the new instance.
//
Instance = NetAllocateZeroPool (sizeof (MNP_INSTANCE_DATA));
if (Instance == NULL) {
MNP_DEBUG_ERROR (("MnpServiceBindingCreateChild: Faild to allocate memory for the new instance.\n"));
return EFI_OUT_OF_RESOURCES;
}
//
// Init the instance data.
//
MnpInitializeInstanceData (MnpServiceData, Instance);
Status = gBS->InstallMultipleProtocolInterfaces (
ChildHandle,
&gEfiManagedNetworkProtocolGuid,
&Instance->ManagedNetwork,
NULL
);
if (EFI_ERROR (Status)) {
MNP_DEBUG_ERROR (
("MnpServiceBindingCreateChild: Failed to install the MNP protocol, %r.\n",
Status)
);
goto ErrorExit;
}
//
// Save the instance's childhandle.
//
Instance->Handle = *ChildHandle;
Status = gBS->OpenProtocol (
MnpServiceData->ControllerHandle,
&gEfiSimpleNetworkProtocolGuid,
(VOID **) &Snp,
gMnpDriverBinding.DriverBindingHandle,
Instance->Handle,
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
);
if (EFI_ERROR (Status)) {
goto ErrorExit;
}
//
// Add the child instance into ChildrenList.
//
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
NetListInsertTail (&MnpServiceData->ChildrenList, &Instance->InstEntry);
MnpServiceData->ChildrenNumber++;
NET_RESTORE_TPL (OldTpl);
ErrorExit:
if (EFI_ERROR (Status)) {
if (Instance->Handle != NULL) {
gBS->UninstallMultipleProtocolInterfaces (
&gEfiManagedNetworkProtocolGuid,
&Instance->ManagedNetwork,
NULL
);
}
NetFreePool (Instance);
}
return Status;
}
/**
Destroys a child handle with a set of I/O services.
@param This Protocol instance pointer.
@param ChildHandle Handle of the child to destroy.
@retval EFI_SUCCES The I/O services were removed from the child
handle.
@retval EFI_UNSUPPORTED The child handle does not support the I/O services
that are being removed.
@retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.
@retval EFI_ACCESS_DENIED The child handle could not be destroyed because
its I/O services are being used.
@retval other The child handle was not destroyed.
**/
EFI_STATUS
EFIAPI
MnpServiceBindingDestroyChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN EFI_HANDLE ChildHandle
)
{
EFI_STATUS Status;
MNP_SERVICE_DATA *MnpServiceData;
EFI_MANAGED_NETWORK_PROTOCOL *ManagedNetwork;
MNP_INSTANCE_DATA *Instance;
EFI_TPL OldTpl;
if ((This == NULL) || (ChildHandle == NULL)) {
return EFI_INVALID_PARAMETER;
}
MnpServiceData = MNP_SERVICE_DATA_FROM_THIS (This);
//
// Try to retrieve ManagedNetwork Protocol from ChildHandle.
//
Status = gBS->OpenProtocol (
ChildHandle,
&gEfiManagedNetworkProtocolGuid,
(VOID **) &ManagedNetwork,
gMnpDriverBinding.DriverBindingHandle,
ChildHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return EFI_UNSUPPORTED;
}
Instance = MNP_INSTANCE_DATA_FROM_THIS (ManagedNetwork);
//
// MnpServiceBindingDestroyChild may be called twice: first called by
// MnpServiceBindingStop, second called by uninstalling the MNP protocol
// in this ChildHandle. Use destroyed to make sure the resource clean code
// will only excecute once.
//
if (Instance->Destroyed) {
return EFI_SUCCESS;
}
Instance->Destroyed = TRUE;
//
// Close the Simple Network protocol.
//
gBS->CloseProtocol (
MnpServiceData->ControllerHandle,
&gEfiSimpleNetworkProtocolGuid,
gMnpDriverBinding.DriverBindingHandle,
ChildHandle
);
//
// Uninstall the ManagedNetwork protocol.
//
Status = gBS->UninstallMultipleProtocolInterfaces (
ChildHandle,
&gEfiManagedNetworkProtocolGuid,
&Instance->ManagedNetwork,
NULL
);
if (EFI_ERROR (Status)) {
MNP_DEBUG_ERROR (
("MnpServiceBindingDestroyChild: Failed to uninstall the ManagedNetwork protocol, %r.\n",
Status)
);
Instance->Destroyed = FALSE;
return Status;
}
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
//
// Reset the configuration.
//
ManagedNetwork->Configure (ManagedNetwork, NULL);
//
// Try to flush the RcvdPacketQueue.
//
MnpFlushRcvdDataQueue (Instance);
//
// Clean the RxTokenMap.
//
NetMapClean (&Instance->RxTokenMap);
//
// Remove this instance from the ChildrenList.
//
NetListRemoveEntry (&Instance->InstEntry);
MnpServiceData->ChildrenNumber--;
NET_RESTORE_TPL (OldTpl);
NetFreePool (Instance);
return Status;
}
//@MT: EFI_DRIVER_ENTRY_POINT (MnpDriverEntryPoint)
EFI_STATUS
EFIAPI
MnpDriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
The entry point for Mnp driver which installs the driver binding and component name
protocol on its ImageHandle.
Arguments:
ImageHandle - The image handle of the driver.
SystemTable - The system table.
Returns:
EFI_SUCCESS - If the driver binding and component name protocols are successfully
installed, otherwise if failed.
--*/
{
return NetLibInstallAllDriverProtocols (
ImageHandle,
SystemTable,
&gMnpDriverBinding,
ImageHandle,
&gMnpComponentName,
NULL,
NULL
);
}

View File

@ -0,0 +1,136 @@
/** @file
Copyright (c) 2005 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
MnpDriver.h
Abstract:
**/
#ifndef _MNP_DRIVER_H_
#define _MNP_DRIVER_H_
#include <PiDxe.h>
#include <Protocol/ManagedNetwork.h>
#include <Protocol/SimpleNetwork.h>
#include <Protocol/ServiceBinding.h>
#include <Library/DebugLib.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
#include <Library/NetLib.h>
#include <Library/BaseLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/BaseMemoryLib.h>
#include "MnpDebug.h"
//
// Required Global Variables
//
extern EFI_DRIVER_BINDING_PROTOCOL gMnpDriverBinding;
extern EFI_COMPONENT_NAME_PROTOCOL gMnpComponentName;
#define MNP_SERVICE_DATA_SIGNATURE EFI_SIGNATURE_32 ('M', 'n', 'p', 'S')
typedef struct _MNP_SERVICE_DATA {
UINT32 Signature;
EFI_HANDLE ControllerHandle;
EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
UINT32 Mtu;
NET_LIST_ENTRY ChildrenList;
UINTN ChildrenNumber;
UINTN ConfiguredChildrenNumber;
NET_LIST_ENTRY GroupAddressList;
UINT32 GroupAddressCount;
EFI_EVENT TxTimeoutEvent;
NET_BUF_QUEUE FreeNbufQue;
INTN NbufCnt;
EFI_EVENT PollTimer;
BOOLEAN EnableSystemPoll;
EFI_EVENT TimeoutCheckTimer;
UINT32 UnicastCount;
UINT32 BroadcastCount;
UINT32 MulticastCount;
UINT32 PromiscuousCount;
//
// The size of the data buffer in the MNP_PACKET_BUFFER used to
// store a packet.
//
UINT32 BufferLength;
NET_BUF *RxNbufCache;
UINT8 *TxBuf;
} MNP_SERVICE_DATA;
#define MNP_SERVICE_DATA_FROM_THIS(a) \
CR ( \
(a), \
MNP_SERVICE_DATA, \
ServiceBinding, \
MNP_SERVICE_DATA_SIGNATURE \
)
EFI_STATUS
EFIAPI
MnpDriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL * This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
);
EFI_STATUS
EFIAPI
MnpDriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL * This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
);
EFI_STATUS
EFIAPI
MnpDriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
);
EFI_STATUS
EFIAPI
MnpServiceBindingCreateChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN EFI_HANDLE *ChildHandle
);
EFI_STATUS
EFIAPI
MnpServiceBindingDestroyChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN EFI_HANDLE ChildHandle
);
#endif

View File

@ -0,0 +1,63 @@
#/** @file
# Component name for module Mnp
#
# FIX ME!
# Copyright (c) 2006, Intel Corporation. All right reserved.
#
# All rights reserved. This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
#
#**/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = MnpDxe
FILE_GUID = 025BBFC7-E6A9-4b8b-82AD-6815A1AEAF4A
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
EDK_RELEASE_VERSION = 0x00020000
EFI_SPECIFICATION_VERSION = 0x00020000
ENTRY_POINT = MnpDriverEntryPoint
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources.common]
MnpDebug.h
MnpMain.c
MnpIo.c
MnpDriver.h
ComponentName.c
MnpDriver.c
MnpConfig.c
MnpImpl.h
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
UefiLib
UefiBootServicesTableLib
UefiDriverEntryPoint
DebugLib
NetLib
[Protocols]
gEfiManagedNetworkServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiSimpleNetworkProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiManagedNetworkProtocolGuid # PROTOCOL ALWAYS_CONSUMED

View File

@ -0,0 +1,70 @@
<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MsaHeader>
<ModuleName>MnpDxe</ModuleName>
<ModuleType>DXE_DRIVER</ModuleType>
<GuidValue>025BBFC7-E6A9-4b8b-82AD-6815A1AEAF4A</GuidValue>
<Version>1.0</Version>
<Abstract>Component name for module Mnp</Abstract>
<Description>FIX ME!</Description>
<Copyright>Copyright (c) 2006, Intel Corporation. All right reserved.</Copyright>
<License>All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>
<Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
</MsaHeader>
<ModuleDefinitions>
<SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
<BinaryModule>false</BinaryModule>
<OutputFileBasename>MnpDxe</OutputFileBasename>
</ModuleDefinitions>
<LibraryClassDefinitions>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>DebugLib</Keyword>
</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>UefiDriverEntryPoint</Keyword>
</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>UefiBootServicesTableLib</Keyword>
</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>UefiLib</Keyword>
</LibraryClass>
</LibraryClassDefinitions>
<SourceFiles>
<Filename>MnpImpl.h</Filename>
<Filename>MnpConfig.c</Filename>
<Filename>MnpDriver.c</Filename>
<Filename>ComponentName.c</Filename>
<Filename>MnpDriver.h</Filename>
<Filename>MnpIo.c</Filename>
<Filename>MnpMain.c</Filename>
<Filename>MnpDebug.h</Filename>
</SourceFiles>
<PackageDependencies>
<Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
<Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
</PackageDependencies>
<Protocols>
<Protocol Usage="ALWAYS_CONSUMED">
<ProtocolCName>gEfiManagedNetworkProtocolGuid</ProtocolCName>
</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">
<ProtocolCName>gEfiSimpleNetworkProtocolGuid</ProtocolCName>
</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">
<ProtocolCName>gEfiManagedNetworkServiceBindingProtocolGuid</ProtocolCName>
</Protocol>
</Protocols>
<Externs>
<Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
<Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
<Extern>
<ModuleEntryPoint>MnpDriverEntryPoint</ModuleEntryPoint>
</Extern>
</Externs>
</ModuleSurfaceArea>

View File

@ -0,0 +1,274 @@
/** @file
Copyright (c) 2005 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
MnpImpl.h
Abstract:
**/
#ifndef _MNP_IMPL_H_
#define _MNP_IMPL_H_
#include "MnpDriver.h"
#include "MnpDebug.h"
#define NET_ETHER_FCS_SIZE 4
#define MNP_SYS_POLL_INTERVAL (2 * TICKS_PER_MS) // 2 milliseconds
#define MNP_TIMEOUT_CHECK_INTERVAL (50 * TICKS_PER_MS) // 50 milliseconds
#define MNP_TX_TIMEOUT_TIME (500 * TICKS_PER_MS) // 500 milliseconds
#define MNP_INIT_NET_BUFFER_NUM 512
#define MNP_NET_BUFFER_INCREASEMENT 64
#define MNP_MAX_NET_BUFFER_NUM 65536
#define MNP_MAX_RCVD_PACKET_QUE_SIZE 256
#define MNP_RECEIVE_UNICAST 0x01
#define MNP_RECEIVE_BROADCAST 0x02
#define UNICAST_PACKET MNP_RECEIVE_UNICAST
#define BROADCAST_PACKET MNP_RECEIVE_BROADCAST
#define MNP_INSTANCE_DATA_SIGNATURE EFI_SIGNATURE_32 ('M', 'n', 'p', 'I')
#define MNP_INSTANCE_DATA_FROM_THIS(a) \
CR ( \
(a), \
MNP_INSTANCE_DATA, \
ManagedNetwork, \
MNP_INSTANCE_DATA_SIGNATURE \
)
typedef struct _MNP_INSTANCE_DATA {
UINT32 Signature;
MNP_SERVICE_DATA *MnpServiceData;
EFI_HANDLE Handle;
NET_LIST_ENTRY InstEntry;
EFI_MANAGED_NETWORK_PROTOCOL ManagedNetwork;
BOOLEAN Configured;
BOOLEAN Destroyed;
NET_LIST_ENTRY GroupCtrlBlkList;
NET_MAP RxTokenMap;
NET_LIST_ENTRY RxDeliveredPacketQueue;
NET_LIST_ENTRY RcvdPacketQueue;
UINTN RcvdPacketQueueSize;
EFI_MANAGED_NETWORK_CONFIG_DATA ConfigData;
UINT8 ReceiveFilter;
} MNP_INSTANCE_DATA;
typedef struct _MNP_GROUP_ADDRESS {
NET_LIST_ENTRY AddrEntry;
EFI_MAC_ADDRESS Address;
INTN RefCnt;
} MNP_GROUP_ADDRESS;
typedef struct _MNP_GROUP_CONTROL_BLOCK {
NET_LIST_ENTRY CtrlBlkEntry;
MNP_GROUP_ADDRESS *GroupAddress;
} MNP_GROUP_CONTROL_BLOCK;
typedef struct _MNP_RXDATA_WRAP {
NET_LIST_ENTRY WrapEntry;
MNP_INSTANCE_DATA *Instance;
EFI_MANAGED_NETWORK_RECEIVE_DATA RxData;
NET_BUF *Nbuf;
UINT64 TimeoutTick;
} MNP_RXDATA_WRAP;
EFI_STATUS
MnpInitializeServiceData (
IN MNP_SERVICE_DATA *MnpServiceData,
IN EFI_HANDLE ImageHandle,
IN EFI_HANDLE ControllerHandle
);
VOID
MnpFlushServiceData (
MNP_SERVICE_DATA *MnpServiceData
);
VOID
MnpInitializeInstanceData (
IN MNP_SERVICE_DATA *MnpServiceData,
IN MNP_INSTANCE_DATA *Instance
);
EFI_STATUS
MnpTokenExist (
IN NET_MAP *Map,
IN NET_MAP_ITEM *Item,
IN VOID *Arg
);
EFI_STATUS
MnpCancelTokens (
IN NET_MAP *Map,
IN NET_MAP_ITEM *Item,
IN VOID *Arg
);
VOID
MnpFlushRcvdDataQueue (
IN MNP_INSTANCE_DATA *Instance
);
EFI_STATUS
MnpConfigureInstance (
IN MNP_INSTANCE_DATA *Instance,
IN EFI_MANAGED_NETWORK_CONFIG_DATA *ConfigData OPTIONAL
);
EFI_STATUS
MnpGroupOp (
IN MNP_INSTANCE_DATA *Instance,
IN BOOLEAN JoinFlag,
IN EFI_MAC_ADDRESS *MacAddr OPTIONAL,
IN MNP_GROUP_CONTROL_BLOCK *CtrlBlk OPTIONAL
);
BOOLEAN
MnpIsValidTxToken (
IN MNP_INSTANCE_DATA *Instance,
IN EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token
);
VOID
MnpBuildTxPacket (
IN MNP_SERVICE_DATA *MnpServiceData,
IN EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData,
OUT UINT8 **PktBuf,
OUT UINT32 *PktLen
);
EFI_STATUS
MnpSyncSendPacket (
IN MNP_SERVICE_DATA *MnpServiceData,
IN UINT8 *Packet,
IN UINT32 Length,
IN EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token
);
EFI_STATUS
MnpInstanceDeliverPacket (
IN MNP_INSTANCE_DATA *Instance
);
VOID
EFIAPI
MnpRecycleRxData (
IN EFI_EVENT Event,
IN VOID *Context
);
EFI_STATUS
MnpReceivePacket (
IN MNP_SERVICE_DATA *MnpServiceData
);
NET_BUF *
MnpAllocNbuf (
IN MNP_SERVICE_DATA *MnpServiceData
);
VOID
MnpFreeNbuf (
IN MNP_SERVICE_DATA *MnpServiceData,
IN NET_BUF *Nbuf
);
VOID
EFIAPI
MnpCheckPacketTimeout (
IN EFI_EVENT Event,
IN VOID *Context
);
VOID
EFIAPI
MnpSystemPoll (
IN EFI_EVENT Event,
IN VOID *Context
);
EFI_STATUS
EFIAPI
MnpGetModeData (
IN EFI_MANAGED_NETWORK_PROTOCOL *This,
OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL,
OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL
);
EFI_STATUS
EFIAPI
MnpConfigure (
IN EFI_MANAGED_NETWORK_PROTOCOL *This,
IN EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL
);
EFI_STATUS
EFIAPI
MnpMcastIpToMac (
IN EFI_MANAGED_NETWORK_PROTOCOL *This,
IN BOOLEAN Ipv6Flag,
IN EFI_IP_ADDRESS *IpAddress,
OUT EFI_MAC_ADDRESS *MacAddress
);
EFI_STATUS
EFIAPI
MnpGroups (
IN EFI_MANAGED_NETWORK_PROTOCOL *This,
IN BOOLEAN JoinFlag,
IN EFI_MAC_ADDRESS *MacAddress OPTIONAL
);
EFI_STATUS
EFIAPI
MnpTransmit (
IN EFI_MANAGED_NETWORK_PROTOCOL *This,
IN EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token
);
EFI_STATUS
EFIAPI
MnpCancel (
IN EFI_MANAGED_NETWORK_PROTOCOL *This,
IN EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token OPTIONAL
);
EFI_STATUS
EFIAPI
MnpReceive (
IN EFI_MANAGED_NETWORK_PROTOCOL *This,
IN EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token
);
EFI_STATUS
EFIAPI
MnpPoll (
IN EFI_MANAGED_NETWORK_PROTOCOL *This
);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,655 @@
/** @file
Copyright (c) 2005 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
MnpMain.c
Abstract:
Implementation of Managed Network Protocol public services.
**/
#include <Library/BaseMemoryLib.h>
#include <Library/BaseLib.h>
#include "MnpImpl.h"
/**
Get configuration data of this instance.
@param This Pointer to the Managed Network Protocol.
@param MnpConfigData Pointer to strorage for MNP operational
parameters.
@param SnpModeData Pointer to strorage for SNP operational
parameters.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_INVALID_PARAMETER This is NULL.
@retval EFI_NOT_STARTED This MNP child driver instance has not been
configured The default values are returned in
MnpConfigData if it is not NULL.
**/
EFI_STATUS
EFIAPI
MnpGetModeData (
IN EFI_MANAGED_NETWORK_PROTOCOL *This,
OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL,
OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL
)
{
MNP_INSTANCE_DATA *Instance;
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
EFI_TPL OldTpl;
EFI_STATUS Status;
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
Instance = MNP_INSTANCE_DATA_FROM_THIS (This);
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
if (MnpConfigData != NULL) {
//
// Copy the instance configuration data.
//
*MnpConfigData = Instance->ConfigData;
}
if (SnpModeData != NULL) {
//
// Copy the underlayer Snp mode data.
//
Snp = Instance->MnpServiceData->Snp;
*SnpModeData = *(Snp->Mode);
}
if (!Instance->Configured) {
Status = EFI_NOT_STARTED;
} else {
Status = EFI_SUCCESS;
}
NET_RESTORE_TPL (OldTpl);
return Status;
}
/**
Set or clear the operational parameters for the MNP child driver.
@param This Pointer to the Managed Network Protocol.
@param MnpConfigData Pointer to the configuration data that will be
assigned to the MNP child driver instance. If
NULL, the MNP child driver instance is reset to
startup defaults and all pending transmit and
receive requests are flushed.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_INVALID_PARAMETER One or more parameter is invalid.
@retval EFI_OUT_OF_RESOURCES Required system resources (usually memory) could
not be allocated.
@retval EFI_UNSUPPORTED EnableReceiveTimestamps is TRUE, this
implementation doesn't support it.
@retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
@retval Other The MNP child driver instance has been reset to
startup defaults.
**/
EFI_STATUS
EFIAPI
MnpConfigure (
IN EFI_MANAGED_NETWORK_PROTOCOL *This,
IN EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL
)
{
MNP_INSTANCE_DATA *Instance;
EFI_TPL OldTpl;
EFI_STATUS Status;
if ((This == NULL) ||
((MnpConfigData != NULL) &&
(MnpConfigData->ProtocolTypeFilter > 0) &&
(MnpConfigData->ProtocolTypeFilter <= 1500))) {
return EFI_INVALID_PARAMETER;
}
Instance = MNP_INSTANCE_DATA_FROM_THIS (This);
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
if ((MnpConfigData == NULL) && (!Instance->Configured)) {
//
// If the instance is not configured and a reset is requested, just return.
//
Status = EFI_SUCCESS;
goto ON_EXIT;
}
//
// Configure the instance.
//
Status = MnpConfigureInstance (Instance, MnpConfigData);
ON_EXIT:
NET_RESTORE_TPL (OldTpl);
return Status;
}
/**
Translate a multicast IP address to a multicast hardware (MAC) address.
@param This Pointer to the Managed Network Protocol.
@param Ipv6Flag Set to TRUE if IpAddress is an IPv6 multicast
address. Set to FALSE if IpAddress is an IPv4
multicast address.
@param IpAddress Pointer to the multicast IP address to convert.
@param MacAddress Pointer to the resulting multicast MAC address.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_INVALID_PARAMETER One or more parameter is invalid.
@retval EFI_NOT_STARTED This MNP child driver instance has not been
configured.
@retval EFI_UNSUPPORTED Ipv6Flag is TRUE, this implementation doesn't
supported it.
@retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
@retval Other The address could not be converted.
**/
EFI_STATUS
EFIAPI
MnpMcastIpToMac (
IN EFI_MANAGED_NETWORK_PROTOCOL *This,
IN BOOLEAN Ipv6Flag,
IN EFI_IP_ADDRESS *IpAddress,
OUT EFI_MAC_ADDRESS *MacAddress
)
{
EFI_STATUS Status;
MNP_INSTANCE_DATA *Instance;
EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
EFI_TPL OldTpl;
if ((This == NULL) || (IpAddress == NULL) || (MacAddress == NULL)) {
return EFI_INVALID_PARAMETER;
}
if (Ipv6Flag) {
//
// Currently IPv6 isn't supported.
//
return EFI_UNSUPPORTED;
}
if (!IP4_IS_MULTICAST (EFI_NTOHL (*IpAddress))) {
//
// The IPv4 address passed in is not a multicast address.
//
return EFI_INVALID_PARAMETER;
}
Instance = MNP_INSTANCE_DATA_FROM_THIS (This);
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
if (!Instance->Configured) {
Status = EFI_NOT_STARTED;
goto ON_EXIT;
}
Snp = Instance->MnpServiceData->Snp;
ASSERT (Snp != NULL);
if (Snp->Mode->IfType == NET_IFTYPE_ETHERNET) {
//
// Translate the IPv4 address into a multicast MAC address if the NIC is an
// ethernet NIC.
//
MacAddress->Addr[0] = 0x01;
MacAddress->Addr[1] = 0x00;
MacAddress->Addr[2] = 0x5E;
MacAddress->Addr[3] = IpAddress->v4.Addr[1] & 0x7F;
MacAddress->Addr[4] = IpAddress->v4.Addr[2];
MacAddress->Addr[5] = IpAddress->v4.Addr[3];
Status = EFI_SUCCESS;
} else {
//
// Invoke Snp to translate the multicast IP address.
//
Status = Snp->MCastIpToMac (
Snp,
Ipv6Flag,
IpAddress,
MacAddress
);
}
ON_EXIT:
NET_RESTORE_TPL (OldTpl);
return Status;
}
/**
Enable or disable receie filters for multicast address.
@param This Pointer to the Managed Network Protocol.
@param JoinFlag Set to TRUE to join this multicast group. Set to
FALSE to leave this multicast group.
@param MacAddress Pointer to the multicast MAC group (address) to
join or leave.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_INVALID_PARAMETER One or more parameter is invalid
@retval EFI_NOT_STARTED This MNP child driver instance has not been
configured.
@retval EFI_ALREADY_STARTED The supplied multicast group is already joined.
@retval EFI_NOT_FOUND The supplied multicast group is not joined.
@retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
@retval Other The requested operation could not be completed.
The MNP multicast group settings are unchanged.
**/
EFI_STATUS
EFIAPI
MnpGroups (
IN EFI_MANAGED_NETWORK_PROTOCOL *This,
IN BOOLEAN JoinFlag,
IN EFI_MAC_ADDRESS *MacAddress OPTIONAL
)
{
MNP_INSTANCE_DATA *Instance;
EFI_SIMPLE_NETWORK_MODE *SnpMode;
MNP_GROUP_CONTROL_BLOCK *GroupCtrlBlk;
MNP_GROUP_ADDRESS *GroupAddress;
NET_LIST_ENTRY *ListEntry;
BOOLEAN AddressExist;
EFI_TPL OldTpl;
EFI_STATUS Status;
if (This == NULL || (JoinFlag && (MacAddress == NULL))) {
//
// This is NULL, or it's a join operation but MacAddress is NULL.
//
return EFI_INVALID_PARAMETER;
}
Instance = MNP_INSTANCE_DATA_FROM_THIS (This);
SnpMode = Instance->MnpServiceData->Snp->Mode;
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
if (!Instance->Configured) {
Status = EFI_NOT_STARTED;
goto ON_EXIT;
}
if ((!Instance->ConfigData.EnableMulticastReceive) ||
((MacAddress != NULL) && !NET_MAC_IS_MULTICAST (MacAddress, &SnpMode->BroadcastAddress, SnpMode->HwAddressSize))) {
//
// The instance isn't configured to do mulitcast receive. OR
// the passed in MacAddress is not a mutlticast mac address.
//
Status = EFI_INVALID_PARAMETER;
goto ON_EXIT;
}
Status = EFI_SUCCESS;
AddressExist = FALSE;
GroupCtrlBlk = NULL;
if (MacAddress != NULL) {
//
// Search the instance's GroupCtrlBlkList to find the specific address.
//
NET_LIST_FOR_EACH (ListEntry, &Instance->GroupCtrlBlkList) {
GroupCtrlBlk = NET_LIST_USER_STRUCT (
ListEntry,
MNP_GROUP_CONTROL_BLOCK,
CtrlBlkEntry
);
GroupAddress = GroupCtrlBlk->GroupAddress;
if (0 == NetCompareMem (
MacAddress,
&GroupAddress->Address,
SnpMode->HwAddressSize
)) {
//
// There is already the same multicast mac address configured.
//
AddressExist = TRUE;
break;
}
}
if (JoinFlag && AddressExist) {
//
// The multicast mac address to join already exists.
//
Status = EFI_ALREADY_STARTED;
}
if (!JoinFlag && !AddressExist) {
//
// The multicast mac address to leave doesn't exist in this instance.
//
Status = EFI_NOT_FOUND;
}
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
} else if (NetListIsEmpty (&Instance->GroupCtrlBlkList)) {
//
// The MacAddress is NULL and there is no configured multicast mac address,
// just return.
//
goto ON_EXIT;
}
//
// OK, it is time to take action.
//
Status = MnpGroupOp (Instance, JoinFlag, MacAddress, GroupCtrlBlk);
ON_EXIT:
NET_RESTORE_TPL (OldTpl);
return Status;
}
/**
Place an outgoing packet into the transmit queue.
@param This Pointer to the Managed Network Protocol.
@param Token Pointer to a token associated with the transmit
data descriptor.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_INVALID_PARAMETER One or more parameter is invalid
@retval EFI_NOT_STARTED This MNP child driver instance has not been
configured.
@retval EFI_ACCESS_DENIED The transmit completion token is already in the
transmit queue.
@retval EFI_OUT_OF_RESOURCES The transmit data could not be queued due to a
lack of system resources (usually memory).
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
The MNP child driver instance has been reset to
startup defaults.
@retval EFI_NOT_READY The transmit request could not be queued because
the transmit queue is full.
**/
EFI_STATUS
EFIAPI
MnpTransmit (
IN EFI_MANAGED_NETWORK_PROTOCOL *This,
IN EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token
)
{
EFI_STATUS Status;
MNP_INSTANCE_DATA *Instance;
MNP_SERVICE_DATA *MnpServiceData;
UINT8 *PktBuf;
UINT32 PktLen;
EFI_TPL OldTpl;
if ((This == NULL) || (Token == NULL)) {
return EFI_INVALID_PARAMETER;
}
Instance = MNP_INSTANCE_DATA_FROM_THIS (This);
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
if (!Instance->Configured) {
Status = EFI_NOT_STARTED;
goto ON_EXIT;
}
if (!MnpIsValidTxToken (Instance, Token)) {
//
// The Token is invalid.
//
Status = EFI_INVALID_PARAMETER;
goto ON_EXIT;
}
MnpServiceData = Instance->MnpServiceData;
NET_CHECK_SIGNATURE (MnpServiceData, MNP_SERVICE_DATA_SIGNATURE);
//
// Build the tx packet
//
MnpBuildTxPacket (MnpServiceData, Token->Packet.TxData, &PktBuf, &PktLen);
//
// OK, send the packet synchronously.
//
Status = MnpSyncSendPacket (MnpServiceData, PktBuf, PktLen, Token);
ON_EXIT:
NET_RESTORE_TPL (OldTpl);
return Status;
}
/**
Place an asynchronous receiving request into the receiving queue.
@param This Pointer to the EFI_MANAGED_NETWORK_PROTOCOL
instance.
@param Token Pointer to a token associated with the receive
data descriptor.
@retval EFI_SUCCESS The receive completion token was cached.
@retval EFI_NOT_STARTED This MNP child driver instance has not been
configured.
@retval EFI_INVALID_PARAMETER One or more parameter is invalid.
@retval EFI_OUT_OF_RESOURCES The transmit data could not be queued due to a
lack of system resources (usually memory).
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
The MNP child driver instance has been reset to
startup defaults.
@retval EFI_ACCESS_DENIED The receive completion token was already in the
receive queue.
@retval EFI_NOT_READY The receive request could not be queued because
the receive queue is full.
**/
EFI_STATUS
EFIAPI
MnpReceive (
IN EFI_MANAGED_NETWORK_PROTOCOL *This,
IN EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token
)
{
EFI_STATUS Status;
MNP_INSTANCE_DATA *Instance;
EFI_TPL OldTpl;
if ((This == NULL) || (Token == NULL) || (Token->Event == NULL)) {
return EFI_INVALID_PARAMETER;
}
Instance = MNP_INSTANCE_DATA_FROM_THIS (This);
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
if (!Instance->Configured) {
Status = EFI_NOT_STARTED;
goto ON_EXIT;
}
//
// Check whether this token(event) is already in the rx token queue.
//
Status = NetMapIterate (&Instance->RxTokenMap, MnpTokenExist, (VOID *) Token);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
//
// Insert the Token into the RxTokenMap.
//
Status = NetMapInsertTail (&Instance->RxTokenMap, (VOID *) Token, NULL);
if (!EFI_ERROR (Status)) {
//
// Try to deliver any buffered packets.
//
Status = MnpInstanceDeliverPacket (Instance);
}
ON_EXIT:
NET_RESTORE_TPL (OldTpl);
return Status;
}
/**
Abort a pending transmit or receive request.
@param This Pointer to the EFI_MANAGED_NETWORK_PROTOCOL
instance.
@param Token Pointer to a token that has been issued by
EFI_MANAGED_NETWORK_PROTOCOL.Transmit() or
EFI_MANAGED_NETWORK_PROTOCOL.Receive(). If NULL,
all pending tokens are aborted.
@retval EFI_SUCCESS The asynchronous I/O request was aborted and
Token->Event was signaled.
@retval EFI_NOT_STARTED This MNP child driver instance has not been
configured.
@retval EFI_INVALID_PARAMETER This is NULL.
@retval EFI_NOT_FOUND The asynchronous I/O request was not found in the
transmit or receive queue. It has either completed
or was not issued by Transmit() and Receive().
**/
EFI_STATUS
EFIAPI
MnpCancel (
IN EFI_MANAGED_NETWORK_PROTOCOL *This,
IN EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token OPTIONAL
)
{
EFI_STATUS Status;
MNP_INSTANCE_DATA *Instance;
EFI_TPL OldTpl;
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
Instance = MNP_INSTANCE_DATA_FROM_THIS (This);
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
if (!Instance->Configured) {
Status = EFI_NOT_STARTED;
goto ON_EXIT;
}
//
// Iterate the RxTokenMap to cancel the specified Token.
//
Status = NetMapIterate (&Instance->RxTokenMap, MnpCancelTokens, (VOID *) Token);
if (Token != NULL) {
Status = (Status == EFI_ABORTED) ? EFI_SUCCESS : EFI_NOT_FOUND;
}
ON_EXIT:
NET_RESTORE_TPL (OldTpl);
return Status;
}
/**
Poll the network interface to do transmit/receive work.
@param This Pointer to the EFI_MANAGED_NETWORK_PROTOCOL
instance.
@retval EFI_SUCCESS Incoming or outgoing data was processed.
@retval EFI_NOT_STARTED This MNP child driver instance has not been
configured.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
The MNP child driver instance has been reset to
startup defaults.
@retval EFI_NOT_READY No incoming or outgoing data was processed.
@retval EFI_TIMEOUT Data was dropped out of the transmit and/or
receive queue.
**/
EFI_STATUS
EFIAPI
MnpPoll (
IN EFI_MANAGED_NETWORK_PROTOCOL *This
)
{
EFI_STATUS Status;
MNP_INSTANCE_DATA *Instance;
EFI_TPL OldTpl;
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
Instance = MNP_INSTANCE_DATA_FROM_THIS (This);
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
if (!Instance->Configured) {
Status = EFI_NOT_STARTED;
goto ON_EXIT;
}
//
// Try to receive packets.
//
Status = MnpReceivePacket (Instance->MnpServiceData);
ON_EXIT:
NET_RESTORE_TPL (OldTpl);
return Status;
}

View File

@ -0,0 +1,163 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
ComponentName.c
Abstract:
**/
#include "Snp.h"
//
// EFI Component Name Functions
//
EFI_STATUS
EFIAPI
SimpleNetworkComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
);
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
//
EFI_COMPONENT_NAME_PROTOCOL gSimpleNetworkComponentName = {
SimpleNetworkComponentNameGetDriverName,
SimpleNetworkComponentNameGetControllerName,
"eng"
};
static EFI_UNICODE_STRING_TABLE mSimpleNetworkDriverNameTable[] = {
{
"eng",
L"Simple Network Protocol Driver"
},
{
NULL,
NULL
}
};
EFI_STATUS
EFIAPI
SimpleNetworkComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
/*++
Routine Description:
Retrieves a Unicode string that is the user readable name of the EFI Driver.
Arguments:
This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
Language - A pointer to a three character ISO 639-2 language identifier.
This is the language of the driver name that 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.
DriverName - A pointer to the Unicode string to return. This Unicode string
is the name of the driver specified by This in the language
specified by Language.
Returns:
EFI_SUCCESS - The Unicode string for the Driver specified by This
and the language specified by Language was returned
in DriverName.
EFI_INVALID_PARAMETER - Language is NULL.
EFI_INVALID_PARAMETER - DriverName is NULL.
EFI_UNSUPPORTED - The driver specified by This does not support the
language specified by Language.
--*/
{
return LookupUnicodeString (
Language,
gSimpleNetworkComponentName.SupportedLanguages,
mSimpleNetworkDriverNameTable,
DriverName
);
}
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
)
/*++
Routine Description:
Retrieves a Unicode string that is the user readable name of the controller
that is being managed by an EFI Driver.
Arguments:
This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
ControllerHandle - The handle of a controller that the driver specified by
This is managing. This handle specifies the controller
whose name is to be returned.
ChildHandle - The handle of the child controller to retrieve the name
of. This is an optional parameter that may be NULL. It
will be NULL for device drivers. It will also be NULL
for a bus drivers that wish to retrieve the name of the
bus controller. It will not be NULL for a bus driver
that wishes to retrieve the name of a child controller.
Language - A pointer to a three character ISO 639-2 language
identifier. This is the language of the controller name
that 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.
ControllerName - A pointer to the Unicode string to return. This Unicode
string is the name of the controller specified by
ControllerHandle and ChildHandle in the language specified
by Language from the point of view of the driver specified
by This.
Returns:
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.
EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.
EFI_INVALID_PARAMETER - Language is NULL.
EFI_INVALID_PARAMETER - ControllerName is NULL.
EFI_UNSUPPORTED - The driver specified by This is not currently managing
the controller specified by ControllerHandle and
ChildHandle.
EFI_UNSUPPORTED - The driver specified by This does not support the
language specified by Language.
--*/
{
return EFI_UNSUPPORTED;
}

View File

@ -0,0 +1,75 @@
#/** @file
# Component name for module SNP
#
# FIX ME!
# Copyright (c) 2006, Intel Corporation. All right reserved.
#
# All rights reserved. This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
#
#**/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = SnpDxe
FILE_GUID = A2f436EA-A127-4EF8-957C-8048606FF670
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
EDK_RELEASE_VERSION = 0x00020000
EFI_SPECIFICATION_VERSION = 0x00020000
ENTRY_POINT = InitializeSnpNiiDriver
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources.common]
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
[Protocols]
gEfiPciIoProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiSimpleNetworkProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiDevicePathProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiNetworkInterfaceIdentifierProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiNetworkInterfaceIdentifierProtocolGuid_31 # PROTOCOL ALWAYS_CONSUMED

View File

@ -0,0 +1,90 @@
<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MsaHeader>
<ModuleName>SnpDxe</ModuleName>
<ModuleType>DXE_DRIVER</ModuleType>
<GuidValue>A2f436EA-A127-4EF8-957C-8048606FF670</GuidValue>
<Version>1.0</Version>
<Abstract>Component name for module SNP</Abstract>
<Description>FIX ME!</Description>
<Copyright>Copyright (c) 2006, Intel Corporation. All right reserved.</Copyright>
<License>All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>
<Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
</MsaHeader>
<ModuleDefinitions>
<SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
<BinaryModule>false</BinaryModule>
<OutputFileBasename>SnpDxe</OutputFileBasename>
</ModuleDefinitions>
<LibraryClassDefinitions>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>DebugLib</Keyword>
</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>BaseMemoryLib</Keyword>
</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>UefiDriverEntryPoint</Keyword>
</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>UefiBootServicesTableLib</Keyword>
</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>BaseLib</Keyword>
</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>UefiLib</Keyword>
</LibraryClass>
</LibraryClassDefinitions>
<SourceFiles>
<Filename>station_address.c</Filename>
<Filename>SNPEntry.c</Filename>
<Filename>callback.c</Filename>
<Filename>ComponentName.c</Filename>
<Filename>initialize.c</Filename>
<Filename>receive_filters.c</Filename>
<Filename>WaitForPacket.c</Filename>
<Filename>transmit.c</Filename>
<Filename>mcast_ip_to_mac.c</Filename>
<Filename>shutdown.c</Filename>
<Filename>reset.c</Filename>
<Filename>statistics.c</Filename>
<Filename>stop.c</Filename>
<Filename>snp.c</Filename>
<Filename>start.c</Filename>
<Filename>get_status.c</Filename>
<Filename>nvdata.c</Filename>
<Filename>snp.h</Filename>
<Filename>receive.c</Filename>
</SourceFiles>
<PackageDependencies>
<Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
<Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
</PackageDependencies>
<Protocols>
<Protocol Usage="ALWAYS_CONSUMED">
<ProtocolCName>gEfiNetworkInterfaceIdentifierProtocolGuid</ProtocolCName>
</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">
<ProtocolCName>gEfiDevicePathProtocolGuid</ProtocolCName>
</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">
<ProtocolCName>gEfiSimpleNetworkProtocolGuid</ProtocolCName>
</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">
<ProtocolCName>gEfiPciIoProtocolGuid</ProtocolCName>
</Protocol>
</Protocols>
<Externs>
<Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
<Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
<Extern>
<ModuleEntryPoint>InitializeSnpNiiDriver</ModuleEntryPoint>
</Extern>
</Externs>
</ModuleSurfaceArea>

View File

@ -0,0 +1,97 @@
/** @file
Copyright (c) 2004, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
WaitForPacket.c
Abstract:
Event handler to check for available packet.
**/
#include "Snp.h"
/**
**/
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 = 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)->if_num;
((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)->issue_undi32_command) ((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);
}
}
/* eof - WaitForPacket.c */

View File

@ -0,0 +1,611 @@
/*++
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
callback.c
Abstract:
This file contains two sets of callback routines for undi3.0 and 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..
--*/
#include "Snp.h"
//
// Global variables
// these 2 global variables are used only for 3.0 undi. we could not place
// them in the snp structure because we will not know which snp structure
// in the callback context!
//
STATIC BOOLEAN mInitializeLock = TRUE;
STATIC EFI_LOCK mLock;
//
// End Global variables
//
extern EFI_PCI_IO_PROTOCOL *mPciIoFncs;
VOID
snp_undi32_callback_v2p_30 (
IN UINT64 CpuAddr,
IN OUT UINT64 DeviceAddrPtr
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
UNDI call this routine with a virtual or CPU address that SNP provided
to convert it to a physical or device address. Since EFI uses the identical
mapping, this routine returns the physical address same as the virtual address
for most of the addresses. an address above 4GB cannot generally be used as a
device address, it needs to be mapped to a lower physical address. This routine
does not call the map routine itself, but it assumes that the mapping was done
at the time of providing the address to UNDI. This routine just looks up the
address in a map table (which is the v2p structure chain)
Arguments:
CpuAddr - virtual address of a buffer
DeviceAddrPtr - pointer to the physical address
Returns:
void - The DeviceAddrPtr will contain 0 in case of any error
--*/
{
struct s_v2p *v2p;
//
// Do nothing if virtual address is zero or physical pointer is NULL.
// No need to map if the virtual address is within 4GB limit since
// EFI uses identical mapping
//
if ((CpuAddr == 0) || (DeviceAddrPtr == 0)) {
DEBUG ((EFI_D_ERROR, "\nv2p: Null virtual address or physical pointer.\n"));
return ;
}
if (CpuAddr < FOUR_GIGABYTES) {
*(UINT64 *) (UINTN) DeviceAddrPtr = CpuAddr;
return ;
}
//
// SNP creates a vaddr tp paddr mapping at the time of calling undi with any
// big address, this callback routine just looks up in the v2p list and
// returns the physical address for any given virtual address.
//
if (find_v2p (&v2p, (VOID *) (UINTN) CpuAddr) != EFI_SUCCESS) {
*(UINT64 *) (UINTN) DeviceAddrPtr = CpuAddr;
} else {
*(UINT64 *) (UINTN) DeviceAddrPtr = v2p->paddr;
}
}
VOID
snp_undi32_callback_block_30 (
IN UINT32 Enable
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
UNDI call this routine when it wants to have exclusive access to a critical
section of the code/data
Arguments:
Enable - non-zero indicates acquire
zero indicates release
Returns:
void
--*/
{
//
// tcpip was calling snp at tpl_notify and if we acquire a lock that was
// created at a lower level (TPL_CALLBACK) it gives an assert!
//
if (mInitializeLock) {
EfiInitializeLock (&mLock, TPL_NOTIFY);
mInitializeLock = FALSE;
}
if (Enable != 0) {
EfiAcquireLock (&mLock);
} else {
EfiReleaseLock (&mLock);
}
}
VOID
snp_undi32_callback_delay_30 (
IN UINT64 MicroSeconds
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
UNDI call this routine with the number of micro seconds when it wants to
pause.
Arguments:
MicroSeconds - number of micro seconds to pause, ususlly multiple of 10
Returns:
void
--*/
{
if (MicroSeconds != 0) {
gBS->Stall ((UINTN) MicroSeconds);
}
}
VOID
snp_undi32_callback_memio_30 (
IN UINT8 ReadOrWrite,
IN UINT8 NumBytes,
IN UINT64 Address,
IN OUT UINT64 BufferAddr
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
This is the IO routine for UNDI. This is not currently being used by UNDI3.0
because Undi3.0 uses io/mem offsets relative to the beginning of the device
io/mem address and so it needs to use the PCI_IO_FUNCTION that abstracts the
start of the device's io/mem addresses. Since SNP cannot retrive the context
of the undi3.0 interface it cannot use the PCI_IO_FUNCTION that specific for
that NIC and uses one global IO functions structure, this does not work.
This however works fine for EFI1.0 Undis because they use absolute addresses
for io/mem access.
Arguments:
ReadOrWrite - indicates read or write, IO or Memory
NumBytes - number of bytes to read or write
Address - IO or memory address to read from or write to
BufferAddr - memory location to read into or that contains the bytes
to write
Returns:
--*/
{
EFI_PCI_IO_PROTOCOL_WIDTH Width;
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;
default:
Width = (EFI_PCI_IO_PROTOCOL_WIDTH) 0;
}
switch (ReadOrWrite) {
case PXE_IO_READ:
mPciIoFncs->Io.Read (
mPciIoFncs,
Width,
1, // BAR 1, IO base address
Address,
1, // count
(VOID *) (UINTN) BufferAddr
);
break;
case PXE_IO_WRITE:
mPciIoFncs->Io.Write (
mPciIoFncs,
Width,
1, // BAR 1, IO base address
Address,
1, // count
(VOID *) (UINTN) BufferAddr
);
break;
case PXE_MEM_READ:
mPciIoFncs->Mem.Read (
mPciIoFncs,
Width,
0, // BAR 0, Memory base address
Address,
1, // count
(VOID *) (UINTN) BufferAddr
);
break;
case PXE_MEM_WRITE:
mPciIoFncs->Mem.Write (
mPciIoFncs,
Width,
0, // BAR 0, Memory base address
Address,
1, // count
(VOID *) (UINTN) BufferAddr
);
break;
}
return ;
}
//
// 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!
//
VOID
snp_undi32_callback_block (
IN UINT64 UniqueId,
IN UINT32 Enable
)
/*++
Routine Description:
This is a callback routine supplied to UNDI3.1 at undi_start time.
UNDI call this routine when it wants to have exclusive access to a critical
section of the code/data
Arguments:
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)
Enable - non-zero indicates acquire
zero indicates release
Returns:
void
--*/
{
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);
}
}
VOID
snp_undi32_callback_delay (
IN UINT64 UniqueId,
IN UINT64 MicroSeconds
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
UNDI call this routine with the number of micro seconds when it wants to
pause.
Arguments:
MicroSeconds - number of micro seconds to pause, ususlly multiple of 10
Returns:
void
--*/
{
if (MicroSeconds != 0) {
gBS->Stall ((UINTN) MicroSeconds);
}
}
/*
* IO routine for UNDI start CPB.
*/
VOID
snp_undi32_callback_memio (
UINT64 UniqueId,
UINT8 ReadOrWrite,
UINT8 NumBytes,
UINT64 Address,
UINT64 BufferAddr
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
This is the IO routine for UNDI3.1.
Arguments:
ReadOrWrite - indicates read or write, IO or Memory
NumBytes - number of bytes to read or write
Address - IO or memory address to read from or write to
BufferAddr - memory location to read into or that contains the bytes
to write
Returns:
--*/
{
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->IoFncs->Io.Read (
snp->IoFncs,
Width,
snp->IoBarIndex, // BAR 1 (for 32bit regs), IO base address
Address,
1, // count
(VOID *) (UINTN) BufferAddr
);
break;
case PXE_IO_WRITE:
snp->IoFncs->Io.Write (
snp->IoFncs,
Width,
snp->IoBarIndex, // BAR 1 (for 32bit regs), IO base address
Address,
1, // count
(VOID *) (UINTN) BufferAddr
);
break;
case PXE_MEM_READ:
snp->IoFncs->Mem.Read (
snp->IoFncs,
Width,
snp->MemoryBarIndex, // BAR 0, Memory base address
Address,
1, // count
(VOID *) (UINTN) BufferAddr
);
break;
case PXE_MEM_WRITE:
snp->IoFncs->Mem.Write (
snp->IoFncs,
Width,
snp->MemoryBarIndex, // BAR 0, Memory base address
Address,
1, // count
(VOID *) (UINTN) BufferAddr
);
break;
}
return ;
}
VOID
snp_undi32_callback_map (
IN UINT64 UniqueId,
IN UINT64 CpuAddr,
IN UINT32 NumBytes,
IN UINT32 Direction,
IN OUT UINT64 DeviceAddrPtr
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
UNDI call this routine when it has to map a CPU address to a device
address.
Arguments:
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)
CpuAddr - Virtual address to be mapped!
NumBytes - size of memory to be mapped
Direction - direction of data flow for this memory's usage:
cpu->device, device->cpu or both ways
DeviceAddrPtr - pointer to return the mapped device address
Returns:
None
--*/
{
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->map_list[Index].virt == 0) {
break;
}
}
if (Index >= MAX_MAP_LENGTH) {
DEBUG ((EFI_D_INFO, "SNP maplist is FULL\n"));
*DevAddrPtr = 0;
return ;
}
snp->map_list[Index].virt = (EFI_PHYSICAL_ADDRESS) CpuAddr;
Status = snp->IoFncs->Map (
snp->IoFncs,
DirectionFlag,
(VOID *) (UINTN) CpuAddr,
&BuffSize,
DevAddrPtr,
&(snp->map_list[Index].map_cookie)
);
if (Status != EFI_SUCCESS) {
*DevAddrPtr = 0;
snp->map_list[Index].virt = 0;
}
return ;
}
VOID
snp_undi32_callback_unmap (
IN UINT64 UniqueId,
IN UINT64 CpuAddr,
IN UINT32 NumBytes,
IN UINT32 Direction,
IN UINT64 DeviceAddr
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
UNDI call this routine when it wants to unmap an address that was previously
mapped using map callback
Arguments:
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)
CpuAddr - Virtual address that was mapped!
NumBytes - size of memory mapped
Direction- direction of data flow for this memory's usage:
cpu->device, device->cpu or both ways
DeviceAddr - the mapped device address
Returns:
--*/
{
SNP_DRIVER *snp;
UINT16 Index;
snp = (SNP_DRIVER *) (UINTN) UniqueId;
for (Index = 0; Index < MAX_MAP_LENGTH; Index++) {
if (snp->map_list[Index].virt == CpuAddr) {
break;
}
}
if (Index >= MAX_MAP_LENGTH)
{
DEBUG ((EFI_D_ERROR, "SNP could not find a mapping, failed to unmap.\n"));
return ;
}
snp->IoFncs->Unmap (snp->IoFncs, snp->map_list[Index].map_cookie);
snp->map_list[Index].virt = 0;
snp->map_list[Index].map_cookie = NULL;
return ;
}
VOID
snp_undi32_callback_sync (
UINT64 UniqueId,
UINT64 CpuAddr,
UINT32 NumBytes,
UINT32 Direction,
UINT64 DeviceAddr
)
/*++
Routine Description:
This is a callback routine supplied to UNDI at undi_start time.
UNDI call this routine when it wants synchronize the virtual buffer contents
with the mapped buffer contents. 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 sould just do
the synchronization ourself here!
Arguments:
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)
CpuAddr - Virtual address that was mapped!
NumBytes - size of memory mapped
Direction- direction of data flow for this memory's usage:
cpu->device, device->cpu or both ways
DeviceAddr - the mapped device address
Returns:
--*/
{
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 ;
}

View File

@ -0,0 +1,195 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
get_status.c
Abstract:
Revision history:
2000-Feb-03 M(f)J Genesis.
**/
#include "Snp.h"
STATIC
/**
this routine calls undi to get the status of the interrupts, get the list of
transmit buffers that completed transmitting!
@param snp pointer to snp driver structure
@param InterruptStatusPtr a non null pointer gets the interrupt status
@param TransmitBufferListPtrs a non null ointer gets the list of pointers of
previously transmitted buffers whose
transmission was completed asynchrnously.
**/
EFI_STATUS
pxe_getstatus (
SNP_DRIVER *snp,
UINT32 *InterruptStatusPtr,
VOID **TransmitBufferListPtr
)
{
PXE_DB_GET_STATUS *db;
UINT16 InterruptFlags;
UINT64 TempData;
db = snp->db;
snp->cdb.OpCode = PXE_OPCODE_GET_STATUS;
snp->cdb.OpFlags = 0;
if (TransmitBufferListPtr != NULL) {
snp->cdb.OpFlags |= PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS;
}
if (InterruptStatusPtr != NULL) {
snp->cdb.OpFlags |= PXE_OPFLAGS_GET_INTERRUPT_STATUS;
}
snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED;
//
// size DB for return of one buffer
//
snp->cdb.DBsize = (UINT16) (((UINT16) (sizeof (PXE_DB_GET_STATUS)) - (UINT16) (sizeof db->TxBuffer)) + (UINT16) (sizeof db->TxBuffer[0]));
snp->cdb.DBaddr = (UINT64)(UINTN) db;
snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
snp->cdb.IFnum = snp->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.get_status() "));
(*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
if (snp->cdb.StatCode != EFI_SUCCESS) {
DEBUG (
(EFI_D_NET,
"\nsnp->undi.get_status() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatFlags)
);
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) {
*InterruptStatusPtr |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT;
}
if (InterruptFlags & PXE_STATFLAGS_GET_STATUS_TRANSMIT) {
*InterruptStatusPtr |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT;
}
if (InterruptFlags & PXE_STATFLAGS_GET_STATUS_COMMAND) {
*InterruptStatusPtr |= EFI_SIMPLE_NETWORK_COMMAND_INTERRUPT;
}
if (InterruptFlags & PXE_STATFLAGS_GET_STATUS_SOFTWARE) {
*InterruptStatusPtr |= EFI_SIMPLE_NETWORK_COMMAND_INTERRUPT;
}
}
if (TransmitBufferListPtr != NULL) {
*TransmitBufferListPtr =
(
(snp->cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN) ||
(snp->cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_TXBUF_QUEUE_EMPTY)
) ? 0 : (VOID *) (UINTN) db->TxBuffer[0];
TempData = (UINT64) (UINTN) (*TransmitBufferListPtr);
if (snp->IsOldUndi && (TempData >= FOUR_GIGABYTES)) {
del_v2p ((VOID *) (UINTN) (db->TxBuffer[0]));
}
}
return EFI_SUCCESS;
}
/**
This is the SNP interface routine for getting the status
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_getstatus routine to actually get the undi status
@param this context pointer
@param InterruptStatusPtr a non null pointer gets the interrupt status
@param TransmitBufferListPtrs a non null ointer gets the list of pointers of
previously transmitted buffers whose
transmission was completed asynchrnously.
**/
EFI_STATUS
EFIAPI
snp_undi32_get_status (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
OUT UINT32 *InterruptStatusPtr OPTIONAL,
OUT VOID **TransmitBufferListPtr OPTIONAL
)
{
SNP_DRIVER *snp;
EFI_TPL OldTpl;
EFI_STATUS Status;
if (this == NULL) {
return EFI_INVALID_PARAMETER;
}
if (InterruptStatusPtr == NULL && TransmitBufferListPtr == 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;
}
Status = pxe_getstatus (snp, InterruptStatusPtr, TransmitBufferListPtr);
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return Status;
}

View File

@ -0,0 +1,245 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
initialize.c
Abstract:
Revision history:
2000-Feb-09 M(f)J Genesis.
**/
#include "Snp.h"
VOID
EFIAPI
SnpWaitForPacketNotify (
IN EFI_EVENT Event,
IN VOID *SnpPtr
);
/**
this routine calls 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)
**/
EFI_STATUS
pxe_init (
SNP_DRIVER *snp,
UINT16 CableDetectFlag
)
{
PXE_CPB_INITIALIZE *cpb;
VOID *addr;
EFI_STATUS Status;
cpb = snp->cpb;
if (snp->tx_rx_bufsize != 0) {
Status = snp->IoFncs->AllocateBuffer (
snp->IoFncs,
AllocateAnyPages,
EfiBootServicesData,
SNP_MEM_PAGES (snp->tx_rx_bufsize),
&addr,
0
);
if (Status != EFI_SUCCESS) {
DEBUG (
(EFI_D_ERROR,
"\nsnp->pxe_init() AllocateBuffer %xh (%r)\n",
Status,
Status)
);
return Status;
}
ASSERT (addr);
snp->tx_rx_buffer = addr;
}
cpb->MemoryAddr = (UINT64)(UINTN) snp->tx_rx_buffer;
cpb->MemoryLength = snp->tx_rx_bufsize;
//
// 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 = sizeof (PXE_CPB_INITIALIZE);
snp->cdb.DBsize = 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->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
DEBUG ((EFI_D_NET, "\nsnp->undi.initialize() "));
(*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
if (snp->cdb.StatCode == PXE_STATCODE_SUCCESS) {
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->tx_rx_buffer != NULL) {
snp->IoFncs->FreeBuffer (
snp->IoFncs,
SNP_MEM_PAGES (snp->tx_rx_bufsize),
(VOID *) snp->tx_rx_buffer
);
}
snp->tx_rx_buffer = NULL;
Status = EFI_DEVICE_ERROR;
}
return Status;
}
/**
This is the SNP interface routine for initializing the interface
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_initialize routine to actually do the undi initialization
@param this context pointer
@param extra_rx_buffer_size optional parameter, indicates extra space for
rx_buffers
@param extra_tx_buffer_size optional parameter, indicates extra space for
tx_buffers
**/
EFI_STATUS
EFIAPI
snp_undi32_initialize (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this,
IN UINTN extra_rx_buffer_size OPTIONAL,
IN UINTN extra_tx_buffer_size 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->tx_rx_bufsize = (UINT32) (snp->init_info.MemoryRequired + extra_rx_buffer_size + extra_tx_buffer_size);
if (snp->mode.MediaPresentSupported) {
if (pxe_init (snp, PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) == EFI_SUCCESS) {
snp->mode.MediaPresent = TRUE;
goto ON_EXIT;
}
}
snp->mode.MediaPresent = FALSE;
EfiStatus = pxe_init (snp, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE);
if (EFI_ERROR (EfiStatus)) {
gBS->CloseEvent (snp->snp.WaitForPacket);
}
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return EfiStatus;
}

View File

@ -0,0 +1,165 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
mcast_ip_to_mac.c
Abstract:
Revision history:
2000-Feb-17 M(f)J Genesis.
**/
#include "Snp.h"
/**
this routine calls 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
**/
STATIC
EFI_STATUS
pxe_ip2mac (
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 = sizeof (PXE_CPB_MCAST_IP_TO_MAC);
snp->cdb.DBsize = 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->if_num;
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->issue_undi32_command) ((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;
}
/**
This is the SNP interface routine for converting a multicast IP address to
a MAC address.
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_ip2mac routine to actually do the conversion
@param this context pointer
@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
**/
EFI_STATUS
EFIAPI
snp_undi32_mcast_ip_to_mac (
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 = pxe_ip2mac (snp, IPv6, IP, MAC);
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return Status;
}

View File

@ -0,0 +1,185 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
nvdata.c
Abstract:
Revision history:
2000-Feb-03 M(f)J Genesis.
**/
#include "snp.h"
/**
This routine calls Undi to read the desired number of eeprom bytes.
@param snp pointer to the snp driver structure
@param RegOffset eeprom register value relative to the base address
@param NumBytes number of bytes to read
@param BufferPtr pointer where to read into
**/
STATIC
EFI_STATUS
pxe_nvdata_read (
IN SNP_DRIVER *snp,
IN UINTN RegOffset,
IN UINTN NumBytes,
IN OUT VOID *BufferPtr
)
{
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 = 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->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.nvdata () "));
(*snp->issue_undi32_command) ((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;
}
CopyMem (BufferPtr, db->Data.Byte + RegOffset, NumBytes);
return EFI_SUCCESS;
}
/**
This is an interface call provided by SNP.
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 context pointer
@param ReadOrWrite true for reading and false for writing
@param RegOffset eeprom register relative to the base
@param NumBytes how many bytes to read
@param BufferPtr address of memory to read into
**/
EFI_STATUS
EFIAPI
snp_undi32_nvdata (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this,
IN BOOLEAN ReadOrWrite,
IN UINTN RegOffset,
IN UINTN NumBytes,
IN OUT VOID *BufferPtr
)
{
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 ((NumBytes == 0) ||
(BufferPtr == NULL) ||
(RegOffset >= snp->mode.NvRamSize) ||
(RegOffset + NumBytes > snp->mode.NvRamSize) ||
(NumBytes % snp->mode.NvRamAccessSize != 0) ||
(RegOffset % snp->mode.NvRamAccessSize != 0)
) {
Status = EFI_INVALID_PARAMETER;
goto ON_EXIT;
}
//
// check the implementation flags of undi if we can write the nvdata!
//
if (!ReadOrWrite) {
Status = EFI_UNSUPPORTED;
} else {
Status = pxe_nvdata_read (snp, RegOffset, NumBytes, BufferPtr);
}
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return Status;
}

View File

@ -0,0 +1,255 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
receive.c
Abstract:
Revision history:
2000-Feb-03 M(f)J Genesis.
**/
#include "Snp.h"
/**
this routine calls undi to receive a packet and fills in the data in the
input pointers!
@param snp pointer to snp driver structure
@param BufferPtr pointer to the memory for the received data
@param BuffSizePtr is a pointer to the length of the buffer on entry and
contains the length of the received data on return
@param HeaderSizePtr pointer to the header portion of the data received.
@param SourceAddrPtr optional parameter, is a pointer to contain the
source ethernet address on return
@param DestinationAddrPtr optional parameter, is a pointer to contain the
destination ethernet address on return
@param ProtocolPtr optional parameter, is a pointer to contain the
protocol type from the ethernet header on return
**/
STATIC
EFI_STATUS
pxe_receive (
SNP_DRIVER *snp,
VOID *BufferPtr,
UINTN *BuffSizePtr,
UINTN *HeaderSizePtr,
EFI_MAC_ADDRESS *SourceAddrPtr,
EFI_MAC_ADDRESS *DestinationAddrPtr,
UINT16 *ProtocolPtr
)
{
PXE_CPB_RECEIVE *cpb;
PXE_DB_RECEIVE *db;
UINTN buf_size;
UINT64 TempData;
cpb = snp->cpb;
db = snp->db;
buf_size = *BuffSizePtr;
//
// IMPORTANT NOTE:
// In case of the older 3.0 UNDI, if the input buffer address is beyond 4GB,
// DO NOT call the map function on the given buffer, instead use
// a global buffer. The reason is that UNDI3.0 has some unnecessary check of
// making sure that all the addresses (whether or not they will be given
// to the NIC ) supplied to it are below 4GB. It may or may not use
// the mapped address after all (like in case of CPB and DB)!
// Instead of using the global buffer whose address is allocated within the
// 2GB limit if I start mapping the given buffer we lose the data, here is
// why!!!
// if our address is > 4GB, the map call creates another buffer below 2GB and
// copies data to/from the original buffer to the mapped buffer either at
// map time or unmap time depending on the map direction.
// UNDI will not complain since we already mapped the buffer to be
// within the 2GB limit but will not use (I know undi) the mapped address
// since it does not give the user buffers to the NIC's receive unit,
// It just copies the received packet into the user buffer using the virtual
// (CPU) address rather than the mapped (device or physical) address.
// When the UNDI call returns, if we then unmap the buffer, we will lose
// the contents because unmap copies the contents of the mapped buffer into
// the original buffer (since the direction is FROM_DEVICE) !!!
//
// this is not a problem in Undi 3.1 because this undi uses it's map callback
// routine to map a cpu address to device address and it does it only if
// it is giving the address to the device and unmaps it before using the cpu
// address!
//
TempData = (UINT64) (UINTN) BufferPtr;
if (snp->IsOldUndi && (TempData >= FOUR_GIGABYTES)) {
cpb->BufferAddr = (UINT64)(UINTN) snp->receive_buf;
cpb->BufferLen = (UINT32) (snp->init_info.MediaHeaderLen + snp->init_info.FrameDataLen);
} else {
cpb->BufferAddr = (UINT64)(UINTN) BufferPtr;
cpb->BufferLen = (UINT32) *BuffSizePtr;
}
cpb->reserved = 0;
snp->cdb.OpCode = PXE_OPCODE_RECEIVE;
snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
snp->cdb.CPBsize = sizeof (PXE_CPB_RECEIVE);
snp->cdb.CPBaddr = (UINT64)(UINTN) cpb;
snp->cdb.DBsize = 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->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_INFO, "\nsnp->undi.receive () "));
(*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
switch (snp->cdb.StatCode) {
case PXE_STATCODE_SUCCESS:
break;
case PXE_STATCODE_NO_DATA:
DEBUG (
(EFI_D_INFO,
"\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;
}
*BuffSizePtr = db->FrameLen;
if (HeaderSizePtr != NULL) {
*HeaderSizePtr = db->MediaHeaderLen;
}
if (SourceAddrPtr != NULL) {
CopyMem (SourceAddrPtr, &db->SrcAddr, snp->mode.HwAddressSize);
}
if (DestinationAddrPtr != NULL) {
CopyMem (DestinationAddrPtr, &db->DestAddr, snp->mode.HwAddressSize);
}
if (ProtocolPtr != NULL) {
*ProtocolPtr = (UINT16) PXE_SWAP_UINT16 (db->Protocol); /* we need to do the byte swapping */
}
TempData = (UINT64) (UINTN) BufferPtr;
if (snp->IsOldUndi && (TempData >= FOUR_GIGABYTES)) {
CopyMem (BufferPtr, snp->receive_buf, snp->init_info.MediaHeaderLen + snp->init_info.FrameDataLen);
}
return (*BuffSizePtr <= buf_size) ? EFI_SUCCESS : EFI_BUFFER_TOO_SMALL;
}
/**
This is the SNP interface routine for receiving network data.
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_receive routine to actually do the receive!
@param this context pointer
@param HeaderSizePtr optional parameter and is a pointer to the header
portion of the data received.
@param BuffSizePtr is a pointer to the length of the buffer on entry and
contains the length of the received data on return
@param BufferPtr pointer to the memory for the received data
@param SourceAddrPtr optional parameter, is a pointer to contain the
source ethernet address on return
@param DestinationAddrPtr optional parameter, is a pointer to contain the
destination ethernet address on return
@param ProtocolPtr optional parameter, is a pointer to contain the
protocol type from the ethernet header on return
**/
EFI_STATUS
EFIAPI
snp_undi32_receive (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
OUT UINTN *HeaderSizePtr OPTIONAL,
IN OUT UINTN *BuffSizePtr,
OUT VOID *BufferPtr,
OUT EFI_MAC_ADDRESS * SourceAddrPtr OPTIONAL,
OUT EFI_MAC_ADDRESS * DestinationAddrPtr OPTIONAL,
OUT UINT16 *ProtocolPtr 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 ((BuffSizePtr == NULL) || (BufferPtr == NULL)) {
Status = EFI_INVALID_PARAMETER;
goto ON_EXIT;
}
if (!snp->mode.ReceiveFilterSetting) {
Status = EFI_DEVICE_ERROR;
goto ON_EXIT;
}
Status = pxe_receive (
snp,
BufferPtr,
BuffSizePtr,
HeaderSizePtr,
SourceAddrPtr,
DestinationAddrPtr,
ProtocolPtr
);
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return Status;
}

View File

@ -0,0 +1,406 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
receive_filters.c
Abstract:
Revision history:
2000-Feb-17 M(f)J Genesis.
**/
#include "Snp.h"
/**
this routine calls 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
**/
STATIC
EFI_STATUS
pxe_rcvfilter_enable (
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->if_num;
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->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
if (snp->cdb.StatCode != EFI_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;
}
/**
this routine calls 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
**/
STATIC
EFI_STATUS
pxe_rcvfilter_disable (
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->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
snp->cdb.OpFlags = (UINT16) (DisableFlags ? 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->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
if (snp->cdb.StatCode != EFI_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;
}
/**
this routine calls undi to read the receive filters.
@param snp pointer to snp driver structure
**/
STATIC
EFI_STATUS
pxe_rcvfilter_read (
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->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
DEBUG ((EFI_D_NET, "\nsnp->undi.receive_filters() "));
(*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
if (snp->cdb.StatCode != EFI_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;
}
/**
This is the SNP interface routine for reading/enabling/disabling the
receive filters.
This routine basically retrieves snp structure, checks the SNP state and
checks the parameter validity, calls one of the above routines to actually
do the work
@param this context pointer
@param EnableFlags bit mask for enabling the receive filters
@param DisableFlags bit mask for disabling the receive filters
@param ResetMCastList boolean flag to reset/delete the multicast filter list
@param MCastAddressCount multicast address count for a new multicast address
list
@param MCastAddressList list of new multicast addresses
**/
EFI_STATUS
EFIAPI
snp_undi32_receive_filters (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
IN UINT32 EnableFlags,
IN UINT32 DisableFlags,
IN BOOLEAN ResetMCastList,
IN UINTN MCastAddressCount OPTIONAL,
IN EFI_MAC_ADDRESS * MCastAddressList 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 (((EnableFlags &~snp->mode.ReceiveFilterMask) != 0) ||
((DisableFlags &~snp->mode.ReceiveFilterMask) != 0)) {
Status = EFI_INVALID_PARAMETER;
goto ON_EXIT;
}
if (ResetMCastList) {
DisableFlags |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST & snp->mode.ReceiveFilterMask;
MCastAddressCount = 0;
MCastAddressList = NULL;
} else {
if (MCastAddressCount != 0) {
if ((MCastAddressCount > snp->mode.MaxMCastFilterCount) ||
(MCastAddressList == NULL)) {
Status = EFI_INVALID_PARAMETER;
goto ON_EXIT;
}
}
}
if (EnableFlags == 0 && DisableFlags == 0 && !ResetMCastList && MCastAddressCount == 0) {
Status = EFI_SUCCESS;
goto ON_EXIT;
}
if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0 && MCastAddressCount == 0) {
Status = EFI_INVALID_PARAMETER;
goto ON_EXIT;
}
if ((EnableFlags != 0) || (MCastAddressCount != 0)) {
Status = pxe_rcvfilter_enable (
snp,
EnableFlags,
MCastAddressCount,
MCastAddressList
);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
}
if ((DisableFlags != 0) || ResetMCastList) {
Status = pxe_rcvfilter_disable (snp, DisableFlags, ResetMCastList);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
}
Status = pxe_rcvfilter_read (snp);
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return Status;
}

View File

@ -0,0 +1,128 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
reset.c
Abstract:
Revision history:
2000-Feb-09 M(f)J Genesis.
**/
#include "Snp.h"
/**
This routine calls undi to reset the nic.
@param snp pointer to the snp driver structure
@return EFI_SUCCESSFUL for a successful completion
@return other for failed calls
**/
STATIC
EFI_STATUS
pxe_reset (
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->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.reset() "));
(*snp->issue_undi32_command) ((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;
}
/**
This is the SNP interface routine for resetting the NIC
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_reset routine to actually do the reset!
@param this context pointer
@param ExtendedVerification not implemented
**/
EFI_STATUS
EFIAPI
snp_undi32_reset (
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;
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 = pxe_reset (snp);
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return Status;
}

View File

@ -0,0 +1,148 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
shutdown.c
Abstract:
Revision history:
2000-Feb-14 M(f)J Genesis.
**/
#include "Snp.h"
/**
this routine calls undi to shut down the interface.
@param snp pointer to snp driver structure
**/
EFI_STATUS
pxe_shutdown (
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->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.shutdown() "));
(*snp->issue_undi32_command) ((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->tx_rx_buffer != NULL) {
snp->IoFncs->FreeBuffer (
snp->IoFncs,
SNP_MEM_PAGES (snp->tx_rx_bufsize),
(VOID *) snp->tx_rx_buffer
);
}
snp->tx_rx_buffer = NULL;
snp->tx_rx_bufsize = 0;
return EFI_SUCCESS;
}
/**
This is the SNP interface routine for shutting down the interface
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_shutdown routine to actually do the undi shutdown
@param this context pointer
**/
EFI_STATUS
EFIAPI
snp_undi32_shutdown (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this
)
{
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;
}
//
//
//
Status = pxe_shutdown (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;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,454 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
snp.h
Abstract:
Revision history:
**/
#ifndef _SNP_H
#define _SNP_H
#include <PiDxe.h>
#include <Protocol/SimpleNetwork.h>
#include <Protocol/PciIo.h>
#include <Protocol/NetworkInterfaceIdentifier.h>
#include <Protocol/DevicePath.h>
#include <Library/DebugLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/BaseLib.h>
#include <Library/UefiLib.h>
#include <Library/MemoryAllocationLib.h>
#include <IndustryStandard/Pci22.h>
#define FOUR_GIGABYTES (UINT64) 0x100000000ULL
//
// Driver Consumed Protocol Prototypes
//
//@MT:#include EFI_PROTOCOL_DEFINITION (DevicePath)
//@MT:#include EFI_PROTOCOL_DEFINITION (PciIo)
//@MT:#include EFI_PROTOCOL_DEFINITION (EfiNetworkInterfaceIdentifier)
//
// Driver Produced Protocol Prototypes
//
//@MT:#include EFI_PROTOCOL_DEFINITION (DriverBinding)
//@MT:#include EFI_PROTOCOL_DEFINITION (ComponentName)
//@MT:#include EFI_PROTOCOL_DEFINITION (ComponentName2)
//@MT:#include EFI_PROTOCOL_DEFINITION (SimpleNetwork)
#define SNP_DRIVER_SIGNATURE EFI_SIGNATURE_32 ('s', 'n', 'd', 's')
#define MAX_MAP_LENGTH 100
#define PCI_BAR_IO_MASK 0x00000003
#define PCI_BAR_IO_MODE 0x00000001
#define PCI_BAR_MEM_MASK 0x0000000F
#define PCI_BAR_MEM_MODE 0x00000000
#define PCI_BAR_MEM_64BIT 0x00000004
typedef struct {
UINT32 Signature;
EFI_LOCK lock;
EFI_SIMPLE_NETWORK_PROTOCOL snp;
EFI_SIMPLE_NETWORK_MODE mode;
EFI_HANDLE device_handle;
EFI_DEVICE_PATH_PROTOCOL *device_path;
//
// Local instance data needed by SNP driver
//
// Pointer to S/W UNDI API entry point
// This will be NULL for H/W UNDI
//
EFI_STATUS (*issue_undi32_command) (UINT64 cdb);
BOOLEAN is_swundi;
//
// undi interface number, if one undi manages more nics
//
PXE_IFNUM if_num;
//
// Allocated tx/rx buffer that was passed to UNDI Initialize.
//
UINT32 tx_rx_bufsize;
VOID *tx_rx_buffer;
//
// mappable buffers for receive and fill header for undi3.0
// these will be used if the user buffers are above 4GB limit (instead of
// mapping the user buffers)
//
UINT8 *receive_buf;
VOID *ReceiveBufUnmap;
UINT8 *fill_hdr_buf;
VOID *FillHdrBufUnmap;
EFI_PCI_IO_PROTOCOL *IoFncs;
UINT8 IoBarIndex;
UINT8 MemoryBarIndex;
BOOLEAN IsOldUndi; // true for EFI1.0 UNDI (3.0) drivers
//
// Buffers for command descriptor block, command parameter block
// and data block.
//
PXE_CDB cdb;
VOID *cpb;
VOID *CpbUnmap;
VOID *db;
//
// UNDI structure, we need to remember the init info for a long time!
//
PXE_DB_GET_INIT_INFO init_info;
VOID *SnpDriverUnmap;
//
// when ever we map an address, we must remember it's address and the un-map
// cookie so that we can unmap later
//
struct s_map_list {
EFI_PHYSICAL_ADDRESS virt;
VOID *map_cookie;
} map_list[MAX_MAP_LENGTH];
}
SNP_DRIVER;
#define EFI_SIMPLE_NETWORK_DEV_FROM_THIS(a) CR (a, SNP_DRIVER, snp, SNP_DRIVER_SIGNATURE)
//
// Global Variables
//
extern EFI_COMPONENT_NAME_PROTOCOL gSimpleNetworkComponentName;
//
// Virtual to physical mapping for all UNDI 3.0s.
//
extern struct s_v2p {
struct s_v2p *next;
VOID *vaddr;
UINTN bsize;
EFI_PHYSICAL_ADDRESS paddr;
VOID *unmap;
}
*_v2p;
EFI_STATUS
add_v2p (
struct s_v2p **v2p,
EFI_PCI_IO_PROTOCOL_OPERATION type,
VOID *vaddr,
UINTN bsize
)
;
EFI_STATUS
find_v2p (
struct s_v2p **v2p,
VOID *vaddr
)
;
EFI_STATUS
del_v2p (
VOID *vaddr
)
;
extern
VOID
snp_undi32_callback_block_30 (
IN UINT32 Enable
)
;
extern
VOID
snp_undi32_callback_delay_30 (
IN UINT64 MicroSeconds
)
;
extern
VOID
snp_undi32_callback_memio_30 (
IN UINT8 ReadOrWrite,
IN UINT8 NumBytes,
IN UINT64 MemOrPortAddress,
IN OUT UINT64 BufferPtr
)
;
extern
VOID
snp_undi32_callback_v2p_30 (
IN UINT64 CpuAddr,
IN OUT UINT64 DeviceAddrPtr
)
;
extern
VOID
snp_undi32_callback_block (
IN UINT64 UniqueId,
IN UINT32 Enable
)
;
extern
VOID
snp_undi32_callback_delay (
IN UINT64 UniqueId,
IN UINT64 MicroSeconds
)
;
extern
VOID
snp_undi32_callback_memio (
IN UINT64 UniqueId,
IN UINT8 ReadOrWrite,
IN UINT8 NumBytes,
IN UINT64 MemOrPortAddr,
IN OUT UINT64 BufferPtr
)
;
extern
VOID
snp_undi32_callback_map (
IN UINT64 UniqueId,
IN UINT64 CpuAddr,
IN UINT32 NumBytes,
IN UINT32 Direction,
IN OUT UINT64 DeviceAddrPtr
)
;
extern
VOID
snp_undi32_callback_unmap (
IN UINT64 UniqueId,
IN UINT64 CpuAddr,
IN UINT32 NumBytes,
IN UINT32 Direction,
IN UINT64 DeviceAddr // not a pointer to device address
)
;
extern
VOID
snp_undi32_callback_sync (
IN UINT64 UniqueId,
IN UINT64 CpuAddr,
IN UINT32 NumBytes,
IN UINT32 Direction,
IN UINT64 DeviceAddr // not a pointer to device address
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_start (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_stop (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_initialize (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this,
IN UINTN extra_rx_buffer_size OPTIONAL,
IN UINTN extra_tx_buffer_size OPTIONAL
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_reset (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this,
IN BOOLEAN ExtendedVerification
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_shutdown (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_receive_filters (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
IN UINT32 enable,
IN UINT32 disable,
IN BOOLEAN reset_mcast_filter,
IN UINTN mcast_filter_count OPTIONAL,
IN EFI_MAC_ADDRESS * mcast_filter OPTIONAL
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_station_address (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
IN BOOLEAN reset,
IN EFI_MAC_ADDRESS *new OPTIONAL
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_statistics (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
IN BOOLEAN reset,
IN OUT UINTN *statistics_size OPTIONAL,
IN OUT EFI_NETWORK_STATISTICS * statistics_table OPTIONAL
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_mcast_ip_to_mac (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this,
IN BOOLEAN IPv6,
IN EFI_IP_ADDRESS *IP,
OUT EFI_MAC_ADDRESS *MAC
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_nvdata (
IN EFI_SIMPLE_NETWORK_PROTOCOL *this,
IN BOOLEAN read_write,
IN UINTN offset,
IN UINTN buffer_size,
IN OUT VOID *buffer
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_get_status (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
OUT UINT32 *interrupt_status OPTIONAL,
OUT VOID **tx_buffer OPTIONAL
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_transmit (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
IN UINTN header_size,
IN UINTN buffer_size,
IN VOID *buffer,
IN EFI_MAC_ADDRESS * src_addr OPTIONAL,
IN EFI_MAC_ADDRESS * dest_addr OPTIONAL,
IN UINT16 *protocol OPTIONAL
)
;
extern
EFI_STATUS
EFIAPI
snp_undi32_receive (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
OUT UINTN *header_size OPTIONAL,
IN OUT UINTN *buffer_size,
OUT VOID *buffer,
OUT EFI_MAC_ADDRESS * src_addr OPTIONAL,
OUT EFI_MAC_ADDRESS * dest_addr OPTIONAL,
OUT UINT16 *protocol OPTIONAL
)
;
typedef
EFI_STATUS
(*issue_undi32_command) (
UINT64 cdb
);
typedef
VOID
(*ptr) (
VOID
);
/**
Install all the driver protocol
@param ImageHandle Driver image handle
@param SystemTable System services 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
)
;
#ifdef EFI_SIZE_REDUCTION_APPLIED
#define COMPONENT_NAME_CODE(code)
#define COMPONENT_NAME NULL
#else
#define COMPONENT_NAME_CODE(code) code
#define COMPONENT_NAME &gSimpleNetworkComponentName
#endif
#define SNP_MEM_PAGES(x) (((x) - 1) / 4096 + 1)
#endif /* _SNP_H */

View File

@ -0,0 +1,191 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
start.c
Abstract:
Revision history:
2000-Feb-07 M(f)J Genesis.
**/
#include "Snp.h"
/**
this routine calls undi to start the interface and changes the snp state!
@param snp pointer to snp driver structure
**/
EFI_STATUS
pxe_start (
SNP_DRIVER *snp
)
{
PXE_CPB_START_30 *cpb;
PXE_CPB_START_31 *cpb_31;
cpb = snp->cpb;
cpb_31 = 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->if_num;
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->is_swundi) {
if (snp->IsOldUndi) {
snp->cdb.CPBsize = sizeof (PXE_CPB_START_30);
snp->cdb.CPBaddr = (UINT64)(UINTN) cpb;
cpb->Delay = (UINT64)(UINTN) &snp_undi32_callback_delay_30;
cpb->Block = (UINT64)(UINTN) &snp_undi32_callback_block_30;
//
// Virtual == Physical. This can be set to zero.
//
cpb->Virt2Phys = (UINT64)(UINTN) &snp_undi32_callback_v2p_30;
cpb->Mem_IO = (UINT64)(UINTN) &snp_undi32_callback_memio_30;
} else {
snp->cdb.CPBsize = sizeof (PXE_CPB_START_31);
snp->cdb.CPBaddr = (UINT64)(UINTN) cpb_31;
cpb_31->Delay = (UINT64)(UINTN) &snp_undi32_callback_delay;
cpb_31->Block = (UINT64)(UINTN) &snp_undi32_callback_block;
//
// Virtual == Physical. This can be set to zero.
//
cpb_31->Virt2Phys = (UINT64)(UINTN) 0;
cpb_31->Mem_IO = (UINT64)(UINTN) &snp_undi32_callback_memio;
cpb_31->Map_Mem = (UINT64)(UINTN) &snp_undi32_callback_map;
cpb_31->UnMap_Mem = (UINT64)(UINTN) &snp_undi32_callback_unmap;
cpb_31->Sync_Mem = (UINT64)(UINTN) &snp_undi32_callback_sync;
cpb_31->Unique_ID = (UINT64)(UINTN) snp;
}
}
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.start() "));
(*snp->issue_undi32_command) ((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;
}
/**
This is the SNP interface routine for starting the interface
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_start routine to actually do start undi interface
@param This context pointer
@retval EFI_INVALID_PARAMETER "This" is Null
@retval No SNP driver can be extracted from "This"
@retval EFI_ALREADY_STARTED The state of SNP is EfiSimpleNetworkStarted or
EfiSimpleNetworkInitialized
@retval EFI_DEVICE_ERROR The state of SNP is other than
EfiSimpleNetworkStarted,
EfiSimpleNetworkInitialized, and
EfiSimpleNetworkStopped
@retval EFI_SUCCESS UNDI interface is succesfully started
@retval Other Error occurs while calling pxe_start function.
**/
EFI_STATUS
EFIAPI
snp_undi32_start (
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 = pxe_start (Snp);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
//
// clear the map_list in SNP structure
//
for (Index = 0; Index < MAX_MAP_LENGTH; Index++) {
Snp->map_list[Index].virt = 0;
Snp->map_list[Index].map_cookie = 0;
}
Snp->mode.MCastFilterCount = 0;
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return Status;
}

View File

@ -0,0 +1,237 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
station_address.c
Abstract:
Revision history:
2000-Feb-17 M(f)J Genesis.
**/
#include "Snp.h"
/**
this routine calls undi to read the MAC address of the NIC and updates the
mode structure with the address.
@param snp pointer to snp driver structure
**/
EFI_STATUS
pxe_get_stn_addr (
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 = 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->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.station_addr() "));
(*snp->issue_undi32_command) ((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;
}
/**
this routine calls 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.
**/
STATIC
EFI_STATUS
pxe_set_stn_addr (
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_READ;
//
// even though the OPFLAGS are set to READ, 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 = sizeof (PXE_CPB_STATION_ADDRESS);
snp->cdb.CPBaddr = (UINT64)(UINTN) cpb;
}
snp->cdb.DBsize = 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->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.station_addr() "));
(*snp->issue_undi32_command) ((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
//
pxe_get_stn_addr (snp);
return EFI_SUCCESS;
}
/**
This is the SNP interface routine for changing the NIC's mac address.
This routine basically retrieves snp structure, checks the SNP state and
calls the above routines to actually do the work
@param this context pointer
@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.
@param ResetFlag If true, the mac address will change to NIC's original
address
**/
EFI_STATUS
EFIAPI
snp_undi32_station_address (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
IN BOOLEAN ResetFlag,
IN EFI_MAC_ADDRESS * NewMacAddr OPTIONAL
)
{
SNP_DRIVER *snp;
EFI_STATUS Status;
EFI_TPL OldTpl;
//
// Check for invalid parameter combinations.
//
if ((this == NULL) ||
(!ResetFlag && (NewMacAddr == 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 (ResetFlag) {
Status = pxe_set_stn_addr (snp, NULL);
} else {
Status = pxe_set_stn_addr (snp, NewMacAddr);
}
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return Status;
}

View File

@ -0,0 +1,201 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
statistics.c
Abstract:
Revision history:
2000-Feb-17 M(f)J Genesis.
**/
#include "Snp.h"
/**
This is the SNP interface routine for getting the NIC's statistics.
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_ routine to actually do the
@param this context pointer
@param ResetFlag true to reset the NIC's statistics counters to zero.
@param StatTableSizePtr pointer to the statistics table size
@param StatTablePtr pointer to the statistics table
**/
EFI_STATUS
EFIAPI
snp_undi32_statistics (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
IN BOOLEAN ResetFlag,
IN OUT UINTN *StatTableSizePtr OPTIONAL,
IN OUT EFI_NETWORK_STATISTICS * StatTablePtr OPTIONAL
)
{
SNP_DRIVER *snp;
PXE_DB_STATISTICS *db;
UINT64 *stp;
UINT64 mask;
UINTN size;
UINTN n;
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 (!ResetFlag && StatTableSizePtr == NULL) {
Status = StatTablePtr ? 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->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
if (ResetFlag) {
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 = 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->issue_undi32_command) ((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 (ResetFlag) {
Status = EFI_SUCCESS;
goto ON_EXIT;
}
if (StatTablePtr == NULL) {
*StatTableSizePtr = sizeof (EFI_NETWORK_STATISTICS);
Status = EFI_BUFFER_TOO_SMALL;
goto ON_EXIT;
}
//
// Convert the UNDI statistics information to SNP statistics
// information.
//
ZeroMem (StatTablePtr, *StatTableSizePtr);
stp = (UINT64 *) StatTablePtr;
size = 0;
for (n = 0, mask = 1; n < 64; n++, mask = LShiftU64 (mask, 1), stp++) {
//
// There must be room for a full UINT64. Partial
// numbers will not be stored.
//
if ((n + 1) * sizeof (UINT64) > *StatTableSizePtr) {
break;
}
if (db->Supported & mask) {
*stp = db->Data[n];
size = n + 1;
} else {
SetMem (stp, sizeof (UINT64), 0xFF);
}
}
//
// Compute size up to last supported statistic.
//
while (++n < 64) {
if (db->Supported & (mask = LShiftU64 (mask, 1))) {
size = n;
}
}
size *= sizeof (UINT64);
if (*StatTableSizePtr >= size) {
*StatTableSizePtr = size;
Status = EFI_SUCCESS;
} else {
*StatTableSizePtr = size;
Status = EFI_BUFFER_TOO_SMALL;
}
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return Status;
}

View File

@ -0,0 +1,118 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
stop.c
Abstract:
Revision history:
2000-Feb-09 M(f)J Genesis.
**/
#include "Snp.h"
/**
this routine calls undi to stop the interface and changes the snp state
@param snp pointer to snp driver structure
**/
EFI_STATUS
pxe_stop (
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->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command
//
DEBUG ((EFI_D_NET, "\nsnp->undi.stop() "));
(*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);
if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) {
DEBUG (
(EFI_D_WARN,
"\nsnp->undi.stop() %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 = EfiSimpleNetworkStopped;
return EFI_SUCCESS;
}
/**
This is the SNP interface routine for stopping the interface.
This routine basically retrieves snp structure, checks the SNP state and
calls the pxe_stop routine to actually stop the undi interface
@param this context pointer
**/
EFI_STATUS
EFIAPI
snp_undi32_stop (
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 = pxe_stop (snp);
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return Status;
}

View File

@ -0,0 +1,399 @@
/** @file
Copyright (c) 2004 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module name:
transmit.c
Abstract:
Revision history:
2000-Feb-03 M(f)J Genesis.
**/
#include "Snp.h"
/**
This routine calls 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 MacHeaderSize size of the memory at MacHeaderPtr
@param BufferPtr data buffer pointer
@param BufferLength Size of data in the BufferPtr
@param DestinationAddrPtr address of the destination mac address buffer
@param SourceAddrPtr address of the source mac address buffer
@param ProtocolPtr address of the protocol type
@retval EFI_SUCCESS if successfully completed the undi call
@retval Other error return from undi call.
**/
STATIC
EFI_STATUS
pxe_fillheader (
SNP_DRIVER *snp,
VOID *MacHeaderPtr,
UINTN MacHeaderSize,
VOID *BufferPtr,
UINTN BufferLength,
EFI_MAC_ADDRESS *DestinationAddrPtr,
EFI_MAC_ADDRESS *SourceAddrPtr,
UINT16 *ProtocolPtr
)
{
PXE_CPB_FILL_HEADER_FRAGMENTED *cpb;
EFI_STATUS Status;
struct s_v2p *pkt_v2p;
UINT64 TempData;
cpb = snp->cpb;
if (SourceAddrPtr) {
CopyMem (
(VOID *) cpb->SrcAddr,
(VOID *) SourceAddrPtr,
snp->mode.HwAddressSize
);
} else {
CopyMem (
(VOID *) cpb->SrcAddr,
(VOID *) &(snp->mode.CurrentAddress),
snp->mode.HwAddressSize
);
}
CopyMem (
(VOID *) cpb->DestAddr,
(VOID *) DestinationAddrPtr,
snp->mode.HwAddressSize
);
//
// we need to do the byte swapping
//
cpb->Protocol = (UINT16) PXE_SWAP_UINT16 (*ProtocolPtr);
cpb->PacketLen = (UINT32) (BufferLength);
cpb->MediaHeaderLen = (UINT16) MacHeaderSize;
cpb->FragCnt = 2;
cpb->reserved = 0;
cpb->FragDesc[0].FragAddr = (UINT64)(UINTN) MacHeaderPtr;
cpb->FragDesc[0].FragLen = (UINT32) MacHeaderSize;
cpb->FragDesc[1].FragAddr = (UINT64)(UINTN) BufferPtr;
cpb->FragDesc[1].FragLen = (UINT32) BufferLength;
cpb->FragDesc[0].reserved = cpb->FragDesc[1].reserved = 0;
if (snp->IsOldUndi) {
TempData = (UINT64) (UINTN) MacHeaderPtr;
if (TempData >= FOUR_GIGABYTES) {
cpb->FragDesc[0].FragAddr = (UINT64) (UINTN) snp->fill_hdr_buf;
cpb->FragDesc[0].FragLen = (UINT32) snp->init_info.MediaHeaderLen;
}
TempData = (UINT64) (UINTN) (BufferPtr);
if (TempData >= FOUR_GIGABYTES) {
//
// Let the device just read this buffer
//
Status = add_v2p (
&pkt_v2p,
EfiPciIoOperationBusMasterRead,
BufferPtr,
BufferLength
);
if (Status != EFI_SUCCESS) {
return Status;
}
//
// give the virtual address to UNDI and it will call back on Virt2Phys
// to get the mapped address, if it needs it
//
cpb->FragDesc[1].FragLen = (UINT32) pkt_v2p->bsize;
}
}
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 = 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->if_num;
snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
//
// Issue UNDI command and check result.
//
DEBUG ((EFI_D_NET, "\nsnp->undi.fill_header() "));
(*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);
if (snp->IsOldUndi) {
TempData = (UINT64) (UINTN) (BufferPtr);
if (TempData >= FOUR_GIGABYTES) {
del_v2p (BufferPtr);
}
//
// if we used the global buffer for header, copy the contents
//
TempData = (UINT64) (UINTN) MacHeaderPtr;
if (TempData >= FOUR_GIGABYTES) {
CopyMem (
MacHeaderPtr,
snp->fill_hdr_buf,
snp->init_info.MediaHeaderLen
);
}
}
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 BufferPtr data buffer pointer
@param BufferLength Size of data in the BufferPtr
@retval EFI_SUCCESS if successfully completed the undi call
@retval Other error return from undi call.
**/
STATIC
EFI_STATUS
pxe_transmit (
SNP_DRIVER *snp,
VOID *BufferPtr,
UINTN BufferLength
)
{
PXE_CPB_TRANSMIT *cpb;
EFI_STATUS Status;
struct s_v2p *v2p;
UINT64 TempData;
cpb = snp->cpb;
cpb->FrameAddr = (UINT64) (UINTN) BufferPtr;
cpb->DataLen = (UINT32) BufferLength;
TempData = (UINT64) (UINTN) BufferPtr;
if (snp->IsOldUndi && (TempData >= FOUR_GIGABYTES)) {
//
// we need to create a mapping now and give it to the undi when it calls
// the Virt2Phys on this address.
// this is a transmit, just map it for the device to READ
//
Status = add_v2p (
&v2p,
EfiPciIoOperationBusMasterRead,
BufferPtr,
BufferLength
);
if (Status != EFI_SUCCESS) {
return Status;
}
cpb->DataLen = (UINT32) v2p->bsize;
}
cpb->MediaheaderLen = 0;
cpb->reserved = 0;
snp->cdb.OpFlags = PXE_OPFLAGS_TRANSMIT_WHOLE;
snp->cdb.CPBsize = 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->if_num;
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 == %X", snp->cdb.CPBaddr));
DEBUG ((EFI_D_NET, "\nsnp->cdb.DBaddr == %X", snp->cdb.DBaddr));
DEBUG ((EFI_D_NET, "\ncpb->FrameAddr == %X\n", cpb->FrameAddr));
(*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);
DEBUG ((EFI_D_NET, "\nexit snp->undi.transmit() "));
DEBUG ((EFI_D_NET, "\nsnp->cdb.StatCode == %r", snp->cdb.StatCode));
//
// 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_QUEUE_FULL:
case PXE_STATCODE_BUSY:
Status = EFI_NOT_READY;
break;
default:
Status = EFI_DEVICE_ERROR;
}
DEBUG (
(EFI_D_ERROR,
"\nsnp->undi.transmit() %xh:%xh\n",
snp->cdb.StatFlags,
snp->cdb.StatCode)
);
return Status;
}
/**
This is the snp interface routine for transmitting a packet. this routine
basically retrieves the snp structure, checks the snp state and calls
pxe_fill_header and pxe_transmit calls to complete the transmission.
@param this pointer to SNP driver context
@param MacHeaderSize size of the memory at MacHeaderPtr
@param BufferLength Size of data in the BufferPtr
@param BufferPtr data buffer pointer
@param SourceAddrPtr address of the source mac address buffer
@param DestinationAddrPtr address of the destination mac address buffer
@param ProtocolPtr address of the protocol type
@retval EFI_SUCCESS if successfully completed the undi call
@retval Other error return from undi call.
**/
EFI_STATUS
EFIAPI
snp_undi32_transmit (
IN EFI_SIMPLE_NETWORK_PROTOCOL * this,
IN UINTN MacHeaderSize,
IN UINTN BufferLength,
IN VOID *BufferPtr,
IN EFI_MAC_ADDRESS * SourceAddrPtr OPTIONAL,
IN EFI_MAC_ADDRESS * DestinationAddrPtr OPTIONAL,
IN UINT16 *ProtocolPtr 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 (BufferPtr == NULL) {
Status = EFI_INVALID_PARAMETER;
goto ON_EXIT;
}
if (BufferLength < snp->mode.MediaHeaderSize) {
Status = EFI_BUFFER_TOO_SMALL;
goto ON_EXIT;
}
//
// if the MacHeaderSize is non-zero, we need to fill up the header and for that
// we need the destination address and the protocol
//
if (MacHeaderSize != 0) {
if (MacHeaderSize != snp->mode.MediaHeaderSize || DestinationAddrPtr == 0 || ProtocolPtr == 0) {
Status = EFI_INVALID_PARAMETER;
goto ON_EXIT;
}
Status = pxe_fillheader (
snp,
BufferPtr,
MacHeaderSize,
(UINT8 *) BufferPtr + MacHeaderSize,
BufferLength - MacHeaderSize,
DestinationAddrPtr,
SourceAddrPtr,
ProtocolPtr
);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
}
Status = pxe_transmit (snp, BufferPtr, BufferLength);
ON_EXIT:
gBS->RestoreTPL (OldTpl);
return Status;
}

View File

@ -0,0 +1,169 @@
/** @file
Copyright (c) 2005 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
ComponentName.c
Abstract:
**/
#include "Tcp4Main.h"
//
// EFI Component Name Functions
//
EFI_STATUS
EFIAPI
TcpComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
);
EFI_STATUS
EFIAPI
TcpComponentNameGetControllerName (
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
//
EFI_COMPONENT_NAME_PROTOCOL gTcp4ComponentName = {
TcpComponentNameGetDriverName,
TcpComponentNameGetControllerName,
"eng"
};
static EFI_UNICODE_STRING_TABLE mTcpDriverNameTable[] = {
{
"eng",
L"Tcp Network Service Driver"
},
{
NULL,
NULL
}
};
EFI_STATUS
EFIAPI
TcpComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
/*++
Routine Description:
Retrieves a Unicode string that is the user readable name of the EFI Driver.
Arguments:
This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
Language - A pointer to a three character ISO 639-2 language identifier.
This is the language of the driver name that 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.
DriverName - A pointer to the Unicode string to return. This Unicode
string is the name of the driver specified by This in the
language specified by Language.
Returns:
EFI_SUCCES - The Unicode string for the Driver specified by
This and the language specified by Language was
returned in DriverName.
EFI_INVALID_PARAMETER - Language is NULL.
EFI_INVALID_PARAMETER - DriverName is NULL.
EFI_UNSUPPORTED - The driver specified by This does not support the
language specified by Language.
--*/
{
return LookupUnicodeString (
Language,
gTcp4ComponentName.SupportedLanguages,
mTcpDriverNameTable,
DriverName
);
}
EFI_STATUS
EFIAPI
TcpComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
)
/*++
Routine Description:
Retrieves a Unicode string that is the user readable name of the controller
that is being managed by an EFI Driver.
Arguments:
This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
ControllerHandle - The handle of a controller that the driver specified by
This is managing. This handle specifies the controller
whose name is to be returned.
ChildHandle - The handle of the child controller to retrieve the name
of. This is an optional parameter that may be NULL.
It will be NULL for device drivers. It will also be
NULL for a bus drivers that wish to retrieve the name of
the bus controller. It will not be NULL for a bus
driver that wishes to retrieve the name of a child
controller.
Language - A pointer to a three character ISO 639-2 language
identifier. This is the language of the controller
name that that the caller is requesting, and it must
match one of the languages specified in supported
languages. The number of languages supported by a driver
is up to the driver writer.
ControllerName - A pointer to the Unicode string to return. This Unicode
string is the name of the controller specified by
ControllerHandle and ChildHandle in the language
specified by Language from the point of view of the
driver specified by This.
Returns:
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.
EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid
EFI_HANDLE.
EFI_INVALID_PARAMETER - Language is NULL.
EFI_INVALID_PARAMETER - ControllerName is NULL.
EFI_UNSUPPORTED - The driver specified by This is not currently
managing the controller specified by
ControllerHandle and ChildHandle.
EFI_UNSUPPORTED - The driver specified by This does not support the
language specified by Language.
--*/
{
return EFI_UNSUPPORTED;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,84 @@
/** @file
Copyright (c) 2005 - 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
SockImpl.h
Abstract:
**/
#ifndef _SOCK_IMPL_H_
#define _SOCK_IMPL_H_
#include "Socket.h"
#define SOCK_DEBUG_ERROR(PrintArg) NET_DEBUG_ERROR("Sock", PrintArg)
#define SOCK_DEBUG_WARN(PrintArg) NET_DEBUG_WARNING("Sock", PrintArg)
#define SOCK_DEBUG_TRACE(PrintArg) NET_DEBUG_TRACE("Sock", PrintArg)
#define SOCK_TRIM_RCV_BUFF(Sock, Len) \
(NetbufQueTrim ((Sock)->RcvBuffer.DataQueue, (Len)))
#define SIGNAL_TOKEN(Token, TokenStatus) \
do { \
(Token)->Status = (TokenStatus); \
gBS->SignalEvent ((Token)->Event); \
} while (0)
#define SOCK_HEADER_SPACE (60 + 60 + 72)
//
// Supporting function for both SockImpl and SockInterface
//
VOID
SockFreeFoo (
IN EFI_EVENT Event
);
EFI_STATUS
SockProcessTcpSndData (
IN SOCKET *Sock,
IN VOID *TcpTxData
);
VOID
SockSetTcpRxData (
IN SOCKET *Sock,
IN VOID *TcpRxData,
IN UINT32 RcvdBytes,
IN BOOLEAN IsOOB
);
UINT32
SockProcessRcvToken (
IN SOCKET *Sock,
IN SOCK_IO_TOKEN *RcvToken
);
VOID
SockConnFlush (
IN SOCKET *Sock
);
SOCKET *
SockCreate (
IN SOCK_INIT_DATA *SockInitData
);
VOID
SockDestroy (
IN SOCKET *Sock
);
#endif

View File

@ -0,0 +1,980 @@
/** @file
Copyright (c) 2005 - 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
SockInterface.c
Abstract:
**/
#include "SockImpl.h"
/**
Check whether the Event is in the List.
@param List Pointer to the token list to be searched.
@param Event The event to be checked.
@retval BOOLEAN If TRUE, the specific Event exists in the List. If
FALSE, the specific Event is not in the List.
**/
STATIC
BOOLEAN
SockTokenExistedInList (
IN NET_LIST_ENTRY *List,
IN EFI_EVENT Event
)
{
NET_LIST_ENTRY *ListEntry;
SOCK_TOKEN *SockToken;
NET_LIST_FOR_EACH (ListEntry, List) {
SockToken = NET_LIST_USER_STRUCT (
ListEntry,
SOCK_TOKEN,
TokenList
);
if (Event == SockToken->Token->Event) {
return TRUE;
}
}
return FALSE;
}
/**
Call SockTokenExistedInList() to check whether the Event is
in the related socket's lists.
@param Sock Pointer to the instance's socket.
@param Event The event to be checked.
@return The specific Event exists in one of socket's lists or not.
**/
BOOLEAN
SockTokenExisted (
IN SOCKET *Sock,
IN EFI_EVENT Event
)
{
if (SockTokenExistedInList (&Sock->SndTokenList, Event) ||
SockTokenExistedInList (&Sock->ProcessingSndTokenList, Event) ||
SockTokenExistedInList (&Sock->RcvTokenList, Event) ||
SockTokenExistedInList (&Sock->ListenTokenList, Event)
) {
return TRUE;
}
if ((Sock->ConnectionToken != NULL) &&
(Sock->ConnectionToken->Event == Event)) {
return TRUE;
}
if ((Sock->CloseToken != NULL) && (Sock->CloseToken->Event == Event)) {
return TRUE;
}
return FALSE;
}
/**
Buffer a token into the specific list of socket Sock.
@param Sock Pointer to the instance's socket.
@param List Pointer to the list to store the token.
@param Token Pointer to the token to be buffered.
@param DataLen The data length of the buffer contained in Token.
@return Pointer to the token that wraps Token. If NULL, error condition occurred.
**/
SOCK_TOKEN *
SockBufferToken (
IN SOCKET *Sock,
IN NET_LIST_ENTRY *List,
IN VOID *Token,
IN UINT32 DataLen
)
{
SOCK_TOKEN *SockToken;
SockToken = NetAllocatePool (sizeof (SOCK_TOKEN));
if (NULL == SockToken) {
SOCK_DEBUG_ERROR (("SockBufferIOToken: No Memory "
"to allocate SockToken\n"));
return NULL;
}
SockToken->Sock = Sock;
SockToken->Token = (SOCK_COMPLETION_TOKEN *) Token;
SockToken->RemainDataLen = DataLen;
NetListInsertTail (List, &SockToken->TokenList);
return SockToken;
}
/**
Destory the socket Sock and its associated protocol control block.
@param Sock The socket to be destroyed.
@retval EFI_SUCCESS The socket Sock is destroyed successfully.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
**/
EFI_STATUS
SockDestroyChild (
IN SOCKET *Sock
)
{
EFI_STATUS Status;
ASSERT (Sock && Sock->ProtoHandler);
if (Sock->IsDestroyed) {
return EFI_SUCCESS;
}
Sock->IsDestroyed = TRUE;
Status = NET_TRYLOCK (&(Sock->Lock));
if (EFI_ERROR (Status)) {
SOCK_DEBUG_ERROR (("SockDestroyChild: Get the lock to "
"access socket failed with %r\n", Status));
return EFI_ACCESS_DENIED;
}
//
// force protocol layer to detach the PCB
//
Status = Sock->ProtoHandler (Sock, SOCK_DETACH, NULL);
if (EFI_ERROR (Status)) {
SOCK_DEBUG_ERROR (("SockDestroyChild: Protocol detach socket"
" failed with %r\n", Status));
Sock->IsDestroyed = FALSE;
} else if (SOCK_IS_CONFIGURED (Sock)) {
SockConnFlush (Sock);
SockSetState (Sock, SO_CLOSED);
Sock->ConfigureState = SO_UNCONFIGURED;
}
NET_UNLOCK (&(Sock->Lock));
if (EFI_ERROR (Status)) {
return Status;
}
SockDestroy (Sock);
return EFI_SUCCESS;
}
/**
Create a socket and its associated protocol control block
with the intial data SockInitData and protocol specific
data ProtoData.
@param SockInitData Inital data to setting the socket.
@param ProtoData Pointer to the protocol specific data.
@param Len Length of the protocol specific data.
@return Pointer to the newly created socket. If NULL, error condition occured.
**/
SOCKET *
SockCreateChild (
IN SOCK_INIT_DATA *SockInitData,
IN VOID *ProtoData,
IN UINT32 Len
)
{
SOCKET *Sock;
EFI_STATUS Status;
ASSERT (ProtoData && (Len <= PROTO_RESERVED_LEN));
//
// create a new socket
//
Sock = SockCreate (SockInitData);
if (NULL == Sock) {
SOCK_DEBUG_ERROR (("SockCreateChild: No resource to "
"create a new socket\n"));
return NULL;
}
//
// Open the
//
//
// copy the protodata into socket
//
NetCopyMem (Sock->ProtoReserved, ProtoData, Len);
Status = NET_TRYLOCK (&(Sock->Lock));
if (EFI_ERROR (Status)) {
SOCK_DEBUG_ERROR (("SockCreateChild: Get the lock to "
"access socket failed with %r\n", Status));
SockDestroy (Sock);
return NULL;
}
//
// inform the protocol layer to attach the socket
// with a new protocol control block
//
Status = Sock->ProtoHandler (Sock, SOCK_ATTACH, NULL);
if (EFI_ERROR (Status)) {
SOCK_DEBUG_ERROR (("SockCreateChild: Protocol failed to"
" attach a socket with %r\n", Status));
SockDestroy (Sock);
Sock = NULL;
}
NET_UNLOCK (&(Sock->Lock));
return Sock;
}
/**
Configure the specific socket Sock using configuration data
ConfigData.
@param Sock Pointer to the socket to be configured.
@param ConfigData Pointer to the configuration data.
@retval EFI_SUCCESS The socket is configured successfully.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket or the
socket is already configured.
**/
EFI_STATUS
SockConfigure (
IN SOCKET *Sock,
IN VOID *ConfigData
)
{
EFI_STATUS Status;
Status = NET_TRYLOCK (&(Sock->Lock));
if (EFI_ERROR (Status)) {
SOCK_DEBUG_ERROR (("SockConfigure: Get the access for "
"socket failed with %r", Status));
return EFI_ACCESS_DENIED;
}
if (SOCK_IS_CONFIGURED (Sock)) {
Status = EFI_ACCESS_DENIED;
goto OnExit;
}
ASSERT (Sock->State == SO_CLOSED);
Status = Sock->ProtoHandler (Sock, SOCK_CONFIGURE, ConfigData);
OnExit:
NET_UNLOCK (&(Sock->Lock));
return Status;
}
/**
Initiate a connection establishment process.
@param Sock Pointer to the socket to initiate the initate the
connection.
@param Token Pointer to the token used for the connection
operation.
@retval EFI_SUCCESS The connection is initialized successfully.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
socket is closed, or the socket is not configured to
be an active one, or the token is already in one of
this socket's lists.
@retval EFI_NO_MAPPING The IP address configuration operation is not
finished.
@retval EFI_NOT_STARTED The socket is not configured.
**/
EFI_STATUS
SockConnect (
IN SOCKET *Sock,
IN VOID *Token
)
{
EFI_STATUS Status;
EFI_EVENT Event;
Status = NET_TRYLOCK (&(Sock->Lock));
if (EFI_ERROR (Status)) {
SOCK_DEBUG_ERROR (("SockConnect: Get the access for "
"socket failed with %r", Status));
return EFI_ACCESS_DENIED;
}
if (SOCK_IS_NO_MAPPING (Sock)) {
Status = EFI_NO_MAPPING;
goto OnExit;
}
if (SOCK_IS_UNCONFIGURED (Sock)) {
Status = EFI_NOT_STARTED;
goto OnExit;
}
if (!SOCK_IS_CLOSED (Sock) || !SOCK_IS_CONFIGURED_ACTIVE (Sock)) {
Status = EFI_ACCESS_DENIED;
goto OnExit;
}
Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;
if (SockTokenExisted (Sock, Event)) {
Status = EFI_ACCESS_DENIED;
goto OnExit;
}
Sock->ConnectionToken = (SOCK_COMPLETION_TOKEN *) Token;
SockSetState (Sock, SO_CONNECTING);
Status = Sock->ProtoHandler (Sock, SOCK_CONNECT, NULL);
OnExit:
NET_UNLOCK (&(Sock->Lock));
return Status;
}
/**
Issue a listen token to get an existed connected network instance
or wait for a connection if there is none.
@param Sock Pointer to the socket to accept connections.
@param Token The token to accept a connection.
@retval EFI_SUCCESS Either a connection is accpeted or the Token is
buffered for further acception.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
socket is closed, or the socket is not configured to
be a passive one, or the token is already in one of
this socket's lists.
@retval EFI_NO_MAPPING The IP address configuration operation is not
finished.
@retval EFI_NOT_STARTED The socket is not configured.
@retval EFI_OUT_OF_RESOURCE Failed to buffer the Token due to memory limit.
**/
EFI_STATUS
SockAccept (
IN SOCKET *Sock,
IN VOID *Token
)
{
EFI_TCP4_LISTEN_TOKEN *ListenToken;
NET_LIST_ENTRY *ListEntry;
EFI_STATUS Status;
SOCKET *Socket;
EFI_EVENT Event;
ASSERT (SOCK_STREAM == Sock->Type);
Status = NET_TRYLOCK (&(Sock->Lock));
if (EFI_ERROR (Status)) {
SOCK_DEBUG_ERROR (("SockAccept: Get the access for socket"
" failed with %r", Status));
return EFI_ACCESS_DENIED;
}
if (SOCK_IS_NO_MAPPING (Sock)) {
Status = EFI_NO_MAPPING;
goto Exit;
}
if (SOCK_IS_UNCONFIGURED (Sock)) {
Status = EFI_NOT_STARTED;
goto Exit;
}
if (!SOCK_IS_LISTENING (Sock)) {
Status = EFI_ACCESS_DENIED;
goto Exit;
}
Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;
if (SockTokenExisted (Sock, Event)) {
Status = EFI_ACCESS_DENIED;
goto Exit;
}
ListenToken = (EFI_TCP4_LISTEN_TOKEN *) Token;
//
// Check if a connection has already in this Sock->ConnectionList
//
NET_LIST_FOR_EACH (ListEntry, &Sock->ConnectionList) {
Socket = NET_LIST_USER_STRUCT (ListEntry, SOCKET, ConnectionList);
if (SOCK_IS_CONNECTED (Socket)) {
ListenToken->NewChildHandle = Socket->SockHandle;
SIGNAL_TOKEN (&(ListenToken->CompletionToken), EFI_SUCCESS);
NetListRemoveEntry (ListEntry);
ASSERT (Socket->Parent);
Socket->Parent->ConnCnt--;
SOCK_DEBUG_WARN (("SockAccept: Accept a socket,"
"now conncount is %d", Socket->Parent->ConnCnt)
);
Socket->Parent = NULL;
goto Exit;
}
}
//
// Buffer this token for latter incoming connection request
//
if (NULL == SockBufferToken (Sock, &(Sock->ListenTokenList), Token, 0)) {
Status = EFI_OUT_OF_RESOURCES;
}
Exit:
NET_UNLOCK (&(Sock->Lock));
return Status;
}
/**
Issue a token with data to the socket to send out.
@param Sock Pointer to the socket to process the token with
data.
@param Token The token with data that needs to send out.
@retval EFI_SUCCESS The token is processed successfully.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
socket is closed, or the socket is not in a
synchronized state , or the token is already in one
of this socket's lists.
@retval EFI_NO_MAPPING The IP address configuration operation is not
finished.
@retval EFI_NOT_STARTED The socket is not configured.
@retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
**/
EFI_STATUS
SockSend (
IN SOCKET *Sock,
IN VOID *Token
)
{
SOCK_IO_TOKEN *SndToken;
EFI_EVENT Event;
UINT32 FreeSpace;
EFI_TCP4_TRANSMIT_DATA *TxData;
EFI_STATUS Status;
SOCK_TOKEN *SockToken;
UINT32 DataLen;
ASSERT (SOCK_STREAM == Sock->Type);
Status = NET_TRYLOCK (&(Sock->Lock));
if (EFI_ERROR (Status)) {
SOCK_DEBUG_ERROR (("SockSend: Get the access for socket"
" failed with %r", Status));
return EFI_ACCESS_DENIED;
}
if (SOCK_IS_NO_MAPPING (Sock)) {
Status = EFI_NO_MAPPING;
goto Exit;
}
SndToken = (SOCK_IO_TOKEN *) Token;
TxData = (EFI_TCP4_TRANSMIT_DATA *) SndToken->Packet.TxData;
if (SOCK_IS_UNCONFIGURED (Sock)) {
Status = EFI_NOT_STARTED;
goto Exit;
}
if (!(SOCK_IS_CONNECTING (Sock) || SOCK_IS_CONNECTED (Sock))) {
Status = EFI_ACCESS_DENIED;
goto Exit;
}
//
// check if a token is already in the token buffer
//
Event = SndToken->Token.Event;
if (SockTokenExisted (Sock, Event)) {
Status = EFI_ACCESS_DENIED;
goto Exit;
}
DataLen = TxData->DataLength;
//
// process this sending token now or buffer it only?
//
FreeSpace = SockGetFreeSpace (Sock, SOCK_SND_BUF);
if ((FreeSpace < Sock->SndBuffer.LowWater) || !SOCK_IS_CONNECTED (Sock)) {
SockToken = SockBufferToken (
Sock,
&Sock->SndTokenList,
SndToken,
DataLen
);
if (NULL == SockToken) {
Status = EFI_OUT_OF_RESOURCES;
}
} else {
SockToken = SockBufferToken (
Sock,
&Sock->ProcessingSndTokenList,
SndToken,
DataLen
);
if (NULL == SockToken) {
SOCK_DEBUG_ERROR (("SockSend: Failed to buffer IO token into"
" socket processing SndToken List\n", Status));
Status = EFI_OUT_OF_RESOURCES;
goto Exit;
}
Status = SockProcessTcpSndData (Sock, TxData);
if (EFI_ERROR (Status)) {
SOCK_DEBUG_ERROR (("SockSend: Failed to process "
"Snd Data\n", Status));
NetListRemoveEntry (&(SockToken->TokenList));
NetFreePool (SockToken);
}
}
Exit:
NET_UNLOCK (&(Sock->Lock));
return Status;
}
/**
Issue a token to get data from the socket.
@param Sock Pointer to the socket to get data from.
@param Token The token to store the received data from the
socket.
@retval EFI_SUCCESS The token is processed successfully.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
socket is closed, or the socket is not in a
synchronized state , or the token is already in one
of this socket's lists.
@retval EFI_NO_MAPPING The IP address configuration operation is not
finished.
@retval EFI_NOT_STARTED The socket is not configured.
@retval EFI_CONNECTION_FIN The connection is closed and there is no more data.
@retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.
**/
EFI_STATUS
SockRcv (
IN SOCKET *Sock,
IN VOID *Token
)
{
SOCK_IO_TOKEN *RcvToken;
UINT32 RcvdBytes;
EFI_STATUS Status;
EFI_EVENT Event;
ASSERT (SOCK_STREAM == Sock->Type);
Status = NET_TRYLOCK (&(Sock->Lock));
if (EFI_ERROR (Status)) {
SOCK_DEBUG_ERROR (("SockRcv: Get the access for socket"
" failed with %r", Status));
return EFI_ACCESS_DENIED;
}
if (SOCK_IS_NO_MAPPING (Sock)) {
Status = EFI_NO_MAPPING;
goto Exit;
}
if (SOCK_IS_UNCONFIGURED (Sock)) {
Status = EFI_NOT_STARTED;
goto Exit;
}
if (!(SOCK_IS_CONNECTED (Sock) || SOCK_IS_CONNECTING (Sock))) {
Status = EFI_ACCESS_DENIED;
goto Exit;
}
RcvToken = (SOCK_IO_TOKEN *) Token;
//
// check if a token is already in the token buffer of this socket
//
Event = RcvToken->Token.Event;
if (SockTokenExisted (Sock, Event)) {
Status = EFI_ACCESS_DENIED;
goto Exit;
}
RcvToken = (SOCK_IO_TOKEN *) Token;
RcvdBytes = GET_RCV_DATASIZE (Sock);
//
// check whether an error has happened before
//
if (EFI_ABORTED != Sock->SockError) {
SIGNAL_TOKEN (&(RcvToken->Token), Sock->SockError);
Sock->SockError = EFI_ABORTED;
goto Exit;
}
//
// check whether can not receive and there is no any
// data buffered in Sock->RcvBuffer
//
if (SOCK_IS_NO_MORE_DATA (Sock) && (0 == RcvdBytes)) {
Status = EFI_CONNECTION_FIN;
goto Exit;
}
if (RcvdBytes != 0) {
Status = SockProcessRcvToken (Sock, RcvToken);
if (EFI_ERROR (Status)) {
goto Exit;
}
Status = Sock->ProtoHandler (Sock, SOCK_CONSUMED, NULL);
} else {
if (NULL == SockBufferToken (Sock, &Sock->RcvTokenList, RcvToken, 0)) {
Status = EFI_OUT_OF_RESOURCES;
}
}
Exit:
NET_UNLOCK (&(Sock->Lock));
return Status;
}
/**
Reset the socket and its associated protocol control block.
@param Sock Pointer to the socket to be flushed.
@retval EFI_SUCCESS The socket is flushed successfully.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
**/
EFI_STATUS
SockFlush (
IN SOCKET *Sock
)
{
EFI_STATUS Status;
ASSERT (SOCK_STREAM == Sock->Type);
Status = NET_TRYLOCK (&(Sock->Lock));
if (EFI_ERROR (Status)) {
SOCK_DEBUG_ERROR (("SockFlush: Get the access for socket"
" failed with %r", Status));
return EFI_ACCESS_DENIED;
}
if (!SOCK_IS_CONFIGURED (Sock)) {
goto Exit;
}
Status = Sock->ProtoHandler (Sock, SOCK_FLUSH, NULL);
if (EFI_ERROR (Status)) {
SOCK_DEBUG_ERROR (("SockFlush: Protocol failed handling"
" SOCK_FLUSH with %r", Status));
goto Exit;
}
SOCK_ERROR (Sock, EFI_ABORTED);
SockConnFlush (Sock);
SockSetState (Sock, SO_CLOSED);
Sock->ConfigureState = SO_UNCONFIGURED;
Exit:
NET_UNLOCK (&(Sock->Lock));
return Status;
}
/**
Close or abort the socket associated connection.
@param Sock Pointer to the socket of the connection to close or
abort.
@param Token The token for close operation.
@param OnAbort TRUE for aborting the connection, FALSE to close it.
@retval EFI_SUCCESS The close or abort operation is initialized
successfully.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the
socket is closed, or the socket is not in a
synchronized state , or the token is already in one
of this socket's lists.
@retval EFI_NO_MAPPING The IP address configuration operation is not
finished.
@retval EFI_NOT_STARTED The socket is not configured.
**/
EFI_STATUS
SockClose (
IN SOCKET *Sock,
IN VOID *Token,
IN BOOLEAN OnAbort
)
{
EFI_STATUS Status;
EFI_EVENT Event;
ASSERT (SOCK_STREAM == Sock->Type);
Status = NET_TRYLOCK (&(Sock->Lock));
if (EFI_ERROR (Status)) {
SOCK_DEBUG_ERROR (("SockClose: Get the access for socket"
" failed with %r", Status));
return EFI_ACCESS_DENIED;
}
if (SOCK_IS_NO_MAPPING (Sock)) {
Status = EFI_NO_MAPPING;
goto Exit;
}
if (SOCK_IS_UNCONFIGURED (Sock)) {
Status = EFI_NOT_STARTED;
goto Exit;
}
if (SOCK_IS_DISCONNECTING (Sock)) {
Status = EFI_ACCESS_DENIED;
goto Exit;
}
Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;
if (SockTokenExisted (Sock, Event)) {
Status = EFI_ACCESS_DENIED;
goto Exit;
}
Sock->CloseToken = Token;
SockSetState (Sock, SO_DISCONNECTING);
if (OnAbort) {
Status = Sock->ProtoHandler (Sock, SOCK_ABORT, NULL);
} else {
Status = Sock->ProtoHandler (Sock, SOCK_CLOSE, NULL);
}
Exit:
NET_UNLOCK (&(Sock->Lock));
return Status;
}
/**
Get the mode data of the low layer protocol.
@param Sock Pointer to the socket to get mode data from.
@param Mode Pointer to the data to store the low layer mode
information.
@retval EFI_SUCCESS The mode data is got successfully.
@retval EFI_NOT_STARTED The socket is not configured.
**/
EFI_STATUS
SockGetMode (
IN SOCKET *Sock,
IN VOID *Mode
)
{
return Sock->ProtoHandler (Sock, SOCK_MODE, Mode);
}
/**
Configure the low level protocol to join a multicast group for
this socket's connection.
@param Sock Pointer to the socket of the connection to join the
specific multicast group.
@param GroupInfo Pointer to the multicast group info.
@retval EFI_SUCCESS The configuration is done successfully.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
@retval EFI_NOT_STARTED The socket is not configured.
**/
EFI_STATUS
SockGroup (
IN SOCKET *Sock,
IN VOID *GroupInfo
)
{
EFI_STATUS Status;
Status = NET_TRYLOCK (&(Sock->Lock));
if (EFI_ERROR (Status)) {
SOCK_DEBUG_ERROR (("SockGroup: Get the access for socket"
" failed with %r", Status));
return EFI_ACCESS_DENIED;
}
if (SOCK_IS_UNCONFIGURED (Sock)) {
Status = EFI_NOT_STARTED;
goto Exit;
}
Status = Sock->ProtoHandler (Sock, SOCK_GROUP, GroupInfo);
Exit:
NET_UNLOCK (&(Sock->Lock));
return Status;
}
/**
Add or remove route information in IP route table associated
with this socket.
@param Sock Pointer to the socket associated with the IP route
table to operate on.
@param RouteInfo Pointer to the route information to be processed.
@retval EFI_SUCCESS The route table is updated successfully.
@retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.
@retval EFI_NO_MAPPING The IP address configuration operation is not
finished.
@retval EFI_NOT_STARTED The socket is not configured.
**/
EFI_STATUS
SockRoute (
IN SOCKET *Sock,
IN VOID *RouteInfo
)
{
EFI_STATUS Status;
Status = NET_TRYLOCK (&(Sock->Lock));
if (EFI_ERROR (Status)) {
SOCK_DEBUG_ERROR (("SockRoute: Get the access for socket"
" failed with %r", Status));
return EFI_ACCESS_DENIED;
}
if (SOCK_IS_NO_MAPPING (Sock)) {
Status = EFI_NO_MAPPING;
goto Exit;
}
if (SOCK_IS_UNCONFIGURED (Sock)) {
Status = EFI_NOT_STARTED;
goto Exit;
}
Status = Sock->ProtoHandler (Sock, SOCK_ROUTE, RouteInfo);
Exit:
NET_UNLOCK (&(Sock->Lock));
return Status;
}

View File

@ -0,0 +1,518 @@
/** @file
Copyright (c) 2005 - 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Socket.h
Abstract:
**/
#ifndef _SOCKET_H_
#define _SOCKET_H_
#include <PiDxe.h>
#include <Protocol/IP4.h>
#include <Protocol/Tcp4.h>
#include <Protocol/Udp4.h>
#include <Library/NetLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/BaseLib.h>
#include <Library/UefiLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/BaseMemoryLib.h>
#define SOCK_SND_BUF 0
#define SOCK_RCV_BUF 1
#define SOCK_BUFF_LOW_WATER 2 * 1024
#define SOCK_RCV_BUFF_SIZE 8 * 1024
#define SOCK_SND_BUFF_SIZE 8 * 1024
#define SOCK_BACKLOG 5
#define PROTO_RESERVED_LEN 20
#define SO_NO_MORE_DATA 0x0001
//
//
//
// When a socket is created it enters into SO_UNCONFIGURED,
// no actions can be taken on this socket, only after calling
// SockConfigure. The state transition diagram of socket is
// as following:
//
// SO_UNCONFIGURED --- SO_CONFIGURED --- SO_CONNECTING
// ^ | |
// | ---> SO_LISTENING |
// | |
// |------------------SO_DISCONNECTING<-- SO_CONNECTED
//
// A passive socket can only go into SO_LISTENING and
// SO_UNCONFIGURED state. SO_XXXING state is a middle state
// when a socket is undergoing a protocol procedure such
// as requesting a TCP connection.
//
//
//
typedef enum {
SO_CLOSED = 0,
SO_LISTENING,
SO_CONNECTING,
SO_CONNECTED,
SO_DISCONNECTING
} SOCK_STATE;
typedef enum {
SO_UNCONFIGURED = 0,
SO_CONFIGURED_ACTIVE,
SO_CONFIGURED_PASSIVE,
SO_NO_MAPPING
} SOCK_CONFIGURE_STATE;
#define SOCK_NO_MORE_DATA(Sock) ((Sock)->Flag |= SO_NO_MORE_DATA)
#define SOCK_IS_UNCONFIGURED(Sock) ((Sock)->ConfigureState == SO_UNCONFIGURED)
#define SOCK_IS_CONFIGURED(Sock) \
(((Sock)->ConfigureState == SO_CONFIGURED_ACTIVE) || \
((Sock)->ConfigureState == SO_CONFIGURED_PASSIVE))
#define SOCK_IS_CONFIGURED_ACTIVE(Sock) \
((Sock)->ConfigureState == SO_CONFIGURED_ACTIVE)
#define SOCK_IS_CONNECTED_PASSIVE(Sock) \
((Sock)->ConfigureState == SO_CONFIGURED_PASSIVE)
#define SOCK_IS_NO_MAPPING(Sock) \
((Sock)->ConfigureState == SO_NO_MAPPING)
#define SOCK_IS_CLOSED(Sock) ((Sock)->State == SO_CLOSED)
#define SOCK_IS_LISTENING(Sock) ((Sock)->State == SO_LISTENING)
#define SOCK_IS_CONNECTING(Sock) ((Sock)->State == SO_CONNECTING)
#define SOCK_IS_CONNECTED(Sock) ((Sock)->State == SO_CONNECTED)
#define SOCK_IS_DISCONNECTING(Sock) ((Sock)->State == SO_DISCONNECTING)
#define SOCK_IS_NO_MORE_DATA(Sock) (0 != ((Sock)->Flag & SO_NO_MORE_DATA))
#define SOCK_SIGNATURE EFI_SIGNATURE_32 ('S', 'O', 'C', 'K')
#define SOCK_FROM_THIS(a) CR ((a), SOCKET, NetProtocol, SOCK_SIGNATURE)
#define SET_RCV_BUFFSIZE(Sock, Size) ((Sock)->RcvBuffer.HighWater = (Size))
#define GET_RCV_BUFFSIZE(Sock) ((Sock)->RcvBuffer.HighWater)
#define GET_RCV_DATASIZE(Sock) (((Sock)->RcvBuffer.DataQueue)->BufSize)
#define SET_SND_BUFFSIZE(Sock, Size) ((Sock)->SndBuffer.HighWater = (Size))
#define GET_SND_BUFFSIZE(Sock) ((Sock)->SndBuffer.HighWater)
#define GET_SND_DATASIZE(Sock) (((Sock)->SndBuffer.DataQueue)->BufSize)
#define SET_BACKLOG(Sock, Value) ((Sock)->BackLog = (Value))
#define GET_BACKLOG(Sock) ((Sock)->BackLog)
#define SOCK_ERROR(Sock, Error) ((Sock)->SockError = (Error))
#define SND_BUF_HDR_LEN(Sock) \
((SockBufFirst (&((Sock)->SndBuffer)))->TotalSize)
#define RCV_BUF_HDR_LEN(Sock) \
((SockBufFirst (&((Sock)->RcvBuffer)))->TotalSize)
#define SOCK_FROM_TOKEN(Token) (((SOCK_TOKEN *) (Token))->Sock)
#define PROTO_TOKEN_FORM_SOCK(SockToken, Type) \
((Type *) (((SOCK_TOKEN *) (SockToken))->Token))
typedef struct _SOCKET SOCKET;
typedef struct _SOCK_COMPLETION_TOKEN {
EFI_EVENT Event;
EFI_STATUS Status;
} SOCK_COMPLETION_TOKEN;
typedef struct _SOCK_IO_TOKEN {
SOCK_COMPLETION_TOKEN Token;
union {
VOID *RxData;
VOID *TxData;
} Packet;
} SOCK_IO_TOKEN;
//
// the request issued from socket layer to protocol layer
//
typedef enum {
SOCK_ATTACH, // attach current socket to a new PCB
SOCK_DETACH, // detach current socket from the PCB
SOCK_CONFIGURE, // configure attached PCB
SOCK_FLUSH, // flush attached PCB
SOCK_SND, // need protocol to send something
SOCK_SNDPUSH, // need protocol to send pushed data
SOCK_SNDURG, // need protocol to send urgent data
SOCK_CONSUMED, // application has retrieved data from socket
SOCK_CONNECT, // need to connect to a peer
SOCK_CLOSE, // need to close the protocol process
SOCK_ABORT, // need to reset the protocol process
SOCK_POLL, // need to poll to the protocol layer
SOCK_ROUTE, // need to add a route information
SOCK_MODE, // need to get the mode data of the protocol
SOCK_GROUP // need to join a mcast group
} SOCK_REQUEST;
//
// the socket type
//
typedef enum {
SOCK_DGRAM, // this socket providing datagram service
SOCK_STREAM // this socket providing stream service
} SOCK_TYPE;
//
// the handler of protocol for request from socket
//
typedef
EFI_STATUS
(*SOCK_PROTO_HANDLER) (
IN SOCKET * Socket, // the socket issuing the request to protocol
IN SOCK_REQUEST Request, // the request issued by socket
IN VOID *RequestData // the request related data
);
//
// the buffer structure of rcvd data and send data used by socket
//
typedef struct _SOCK_BUFFER {
UINT32 HighWater; // the buffersize upper limit of sock_buffer
UINT32 LowWater; // the low warter mark of sock_buffer
NET_BUF_QUEUE *DataQueue; // the queue to buffer data
} SOCK_BUFFER;
//
// the initialize data for create a new socket
//
typedef struct _SOCK_INIT_DATA {
SOCK_TYPE Type;
SOCK_STATE State;
SOCKET *Parent; // the parent of this socket
UINT32 BackLog; // the connection limit for listening socket
UINT32 SndBufferSize; // the high warter mark of send buffer
UINT32 RcvBufferSize; // the high warter mark of receive buffer
VOID *Protocol; // the pointer to protocol function template
// wanted to install on socket
SOCK_PROTO_HANDLER ProtoHandler;
EFI_HANDLE DriverBinding; // the driver binding handle
} SOCK_INIT_DATA;
//
// socket provided oprerations for low layer protocol
//
//
// socket provided operations for user interface
//
VOID
SockSetState (
IN SOCKET *Sock,
IN SOCK_STATE State
);
//
// when the connection establishment process for a Sock
// is finished low layer protocol calling this function
// to notify socket layer
//
VOID
SockConnEstablished (
IN SOCKET *Sock
);
VOID
SockConnClosed (
IN SOCKET *Sock
);
//
// called by low layer protocol to trim send buffer of
// Sock, when Count data is sent out completely
//
VOID
SockDataSent (
IN SOCKET *Sock,
IN UINT32 Count
);
//
// called by low layer protocol to get Len of data from
// socket to send and copy it in Dest
//
UINT32
SockGetDataToSend (
IN SOCKET *Sock,
IN UINT32 Offset,
IN UINT32 Len,
IN UINT8 *Dest
);
//
// called by low layer protocol to notify socket no more data can be
// received
//
VOID
SockNoMoreData (
IN SOCKET *Sock
);
//
// called by low layer protocol to append a NetBuffer
// to rcv buffer of sock
//
VOID
SockDataRcvd (
IN SOCKET *Sock,
IN NET_BUF *NetBuffer,
IN UINT32 UrgLen
);
UINT32
SockGetFreeSpace (
IN SOCKET *Sock,
IN UINT32 Which
);
SOCKET *
SockClone (
IN SOCKET *Sock
);
VOID
SockRcvdErr (
IN SOCKET *Sock,
IN EFI_STATUS Error
);
//
// the socket structure representing a network service access point
//
typedef struct _SOCKET {
//
// socket description information
//
UINT32 Signature;
EFI_HANDLE SockHandle; // the virtual handle of the socket
EFI_HANDLE DriverBinding; // socket't driver binding protocol
SOCK_CONFIGURE_STATE ConfigureState;
SOCK_TYPE Type;
SOCK_STATE State;
UINT16 Flag;
NET_LOCK Lock; // the lock of socket
SOCK_BUFFER SndBuffer; // send buffer of application's data
SOCK_BUFFER RcvBuffer; // receive buffer of received data
EFI_STATUS SockError; // the error returned by low layer protocol
BOOLEAN IsDestroyed;
//
// fields used to manage the connection request
//
UINT32 BackLog; // the limit of connection to this socket
UINT32 ConnCnt; // the current count of connections to it
SOCKET *Parent; // listening parent that accept the connection
NET_LIST_ENTRY ConnectionList; // the connections maintained by this socket
//
// the queue to buffer application's asynchronous token
//
NET_LIST_ENTRY ListenTokenList;
NET_LIST_ENTRY RcvTokenList;
NET_LIST_ENTRY SndTokenList;
NET_LIST_ENTRY ProcessingSndTokenList;
SOCK_COMPLETION_TOKEN *ConnectionToken; // app's token to signal if connected
SOCK_COMPLETION_TOKEN *CloseToken; // app's token to signal if closed
//
// interface for low level protocol
//
SOCK_PROTO_HANDLER ProtoHandler; // the request handler of protocol
UINT8 ProtoReserved[PROTO_RESERVED_LEN]; // Data fields reserved for protocol
union {
EFI_TCP4_PROTOCOL TcpProtocol;
EFI_UDP4_PROTOCOL UdpProtocol;
} NetProtocol;
} SOCKET;
//
// the token structure buffered in socket layer
//
typedef struct _SOCK_TOKEN {
NET_LIST_ENTRY TokenList; // the entry to add in the token list
SOCK_COMPLETION_TOKEN *Token; // The application's token
UINT32 RemainDataLen; // unprocessed data length
SOCKET *Sock; // the poninter to the socket this token
// belongs to
} SOCK_TOKEN;
//
// reserved data to access the NET_BUF delivered by UDP driver
//
typedef struct _UDP_RSV_DATA {
EFI_TIME TimeStamp;
EFI_UDP4_SESSION_DATA Session;
} UDP_RSV_DATA;
//
// reserved data to access the NET_BUF delivered by TCP driver
//
typedef struct _TCP_RSV_DATA {
UINT32 UrgLen;
} TCP_RSV_DATA;
//
// call it to creat a socket and attach it to a PCB
//
SOCKET *
SockCreateChild (
IN SOCK_INIT_DATA *SockInitData,
IN VOID *ProtoData,
IN UINT32 Len
);
//
// call it to destroy a socket and its related PCB
//
EFI_STATUS
SockDestroyChild (
IN SOCKET *Sock
);
//
// call it to configure a socket and its related PCB
//
EFI_STATUS
SockConfigure (
IN SOCKET *Sock,
IN VOID *ConfigData
);
//
// call it to connect a socket to the peer
//
EFI_STATUS
SockConnect (
IN SOCKET *Sock,
IN VOID *Token
);
//
// call it to issue an asynchronous listen token to the socket
//
EFI_STATUS
SockAccept (
IN SOCKET *Sock,
IN VOID *Token
);
//
// Call it to send data using this socket
//
EFI_STATUS
SockSend (
IN SOCKET *Sock,
IN VOID *Token
);
//
// Call it to receive data from this socket
//
EFI_STATUS
SockRcv (
IN SOCKET *Sock,
IN VOID *Token
);
//
// Call it to flush a socket
//
EFI_STATUS
SockFlush (
IN SOCKET *Sock
);
//
// Call it to close a socket in the light of policy in Token
//
EFI_STATUS
SockClose (
IN SOCKET *Sock,
IN VOID *Token,
IN BOOLEAN OnAbort
);
//
// Call it to get the mode data of low layer protocol
//
EFI_STATUS
SockGetMode (
IN SOCKET *Sock,
IN VOID *Mode
);
//
// call it to add this socket instance into a group
//
EFI_STATUS
SockGroup (
IN SOCKET *Sock,
IN VOID *GroupInfo
);
//
// call it to add a route entry for this socket instance
//
EFI_STATUS
SockRoute (
IN SOCKET *Sock,
IN VOID *RouteInfo
);
//
// Supporting function to operate on socket buffer
//
NET_BUF *
SockBufFirst (
IN SOCK_BUFFER *Sockbuf
);
NET_BUF *
SockBufNext (
IN SOCK_BUFFER *Sockbuf,
IN NET_BUF *SockEntry
);
#endif

View File

@ -0,0 +1,680 @@
/** @file
Copyright (c) 2005 - 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Tcp4Dispatcher.c
Abstract:
**/
#include "Tcp4Main.h"
#define TCP_COMP_VAL(Min, Max, Default, Val) \
((((Val) <= (Max)) && ((Val) >= (Min))) ? (Val) : (Default))
STATIC
EFI_STATUS
Tcp4Route (
IN TCP_CB *Tcb,
IN TCP4_ROUTE_INFO *RouteInfo
)
/*++
Routine Description:
Add or remove a route entry in the IP route table associated
with this TCP instance.
Arguments:
Tcb - Pointer to the TCP_CB of this TCP instance.
RouteInfo - Pointer to the route info to be processed.
Returns:
EFI_SUCCESS - The operation completed successfully.
EFI_NOT_STARTED - The driver instance has not been started.
EFI_NO_MAPPING - When using the default address, configuration(DHCP,
BOOTP, RARP, etc.) is not finished yet.
EFI_OUT_OF_RESOURCES - Could not add the entry to the routing table.
EFI_NOT_FOUND - This route is not in the routing table
(when RouteInfo->DeleteRoute is TRUE).
EFI_ACCESS_DENIED - The route is already defined in the routing table
(when RouteInfo->DeleteRoute is FALSE).
--*/
{
EFI_IP4_PROTOCOL *Ip;
Ip = Tcb->IpInfo->Ip;
ASSERT (Ip);
return Ip->Routes (
Ip,
RouteInfo->DeleteRoute,
RouteInfo->SubnetAddress,
RouteInfo->SubnetMask,
RouteInfo->GatewayAddress
);
}
/**
Get the operational settings of this TCP instance.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Mode Pointer to the buffer to store the operational
settings.
@retval EFI_SUCCESS The mode data is read.
@retval EFI_NOT_STARTED No configuration data is available because this
instance hasn't been started.
**/
STATIC
EFI_STATUS
Tcp4GetMode (
IN TCP_CB *Tcb,
IN TCP4_MODE_DATA *Mode
)
{
SOCKET *Sock;
EFI_TCP4_CONFIG_DATA *ConfigData;
EFI_TCP4_ACCESS_POINT *AccessPoint;
EFI_TCP4_OPTION *Option;
EFI_IP4_PROTOCOL *Ip;
Sock = Tcb->Sk;
if (!SOCK_IS_CONFIGURED (Sock) && (Mode->Tcp4ConfigData != NULL)) {
return EFI_NOT_STARTED;
}
if (Mode->Tcp4State) {
*(Mode->Tcp4State) = Tcb->State;
}
if (Mode->Tcp4ConfigData) {
ConfigData = Mode->Tcp4ConfigData;
AccessPoint = &(ConfigData->AccessPoint);
Option = ConfigData->ControlOption;
ConfigData->TypeOfService = Tcb->TOS;
ConfigData->TimeToLive = Tcb->TTL;
AccessPoint->UseDefaultAddress = Tcb->UseDefaultAddr;
EFI_IP4 (AccessPoint->StationAddress) = Tcb->LocalEnd.Ip;
AccessPoint->SubnetMask = Tcb->SubnetMask;
AccessPoint->StationPort = NTOHS (Tcb->LocalEnd.Port);
EFI_IP4 (AccessPoint->RemoteAddress) = Tcb->RemoteEnd.Ip;
AccessPoint->RemotePort = NTOHS (Tcb->RemoteEnd.Port);
AccessPoint->ActiveFlag = (BOOLEAN) (Tcb->State != TCP_LISTEN);
if (Option != NULL) {
Option->ReceiveBufferSize = GET_RCV_BUFFSIZE (Tcb->Sk);
Option->SendBufferSize = GET_SND_BUFFSIZE (Tcb->Sk);
Option->MaxSynBackLog = GET_BACKLOG (Tcb->Sk);
Option->ConnectionTimeout = Tcb->ConnectTimeout / TCP_TICK_HZ;
Option->DataRetries = Tcb->MaxRexmit;
Option->FinTimeout = Tcb->FinWait2Timeout / TCP_TICK_HZ;
Option->TimeWaitTimeout = Tcb->TimeWaitTimeout / TCP_TICK_HZ;
Option->KeepAliveProbes = Tcb->MaxKeepAlive;
Option->KeepAliveTime = Tcb->KeepAliveIdle / TCP_TICK_HZ;
Option->KeepAliveInterval = Tcb->KeepAlivePeriod / TCP_TICK_HZ;
Option->EnableNagle = !TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE);
Option->EnableTimeStamp = !TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS);
Option->EnableWindowScaling = !TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS);
Option->EnableSelectiveAck = FALSE;
Option->EnablePathMtuDiscovery = FALSE;
}
}
Ip = Tcb->IpInfo->Ip;
ASSERT (Ip);
return Ip->GetModeData (Ip, Mode->Ip4ModeData, Mode->MnpConfigData, Mode->SnpModeData);
}
/**
If AP->StationPort isn't zero, check whether the access point
is registered, else generate a random station port for this
access point.
@param AP Pointer to the access point.
@retval EFI_SUCCESS The check is passed or the port is assigned.
@retval EFI_INVALID_PARAMETER The non-zero station port is already used.
@retval EFI_OUT_OF_RESOURCES No port can be allocated.
**/
STATIC
EFI_STATUS
Tcp4Bind (
IN EFI_TCP4_ACCESS_POINT *AP
)
{
BOOLEAN Cycle;
if (0 != AP->StationPort) {
//
// check if a same endpoint is bound
//
if (TcpFindTcbByPeer (&AP->StationAddress, AP->StationPort)) {
return EFI_INVALID_PARAMETER;
}
} else {
//
// generate a random port
//
Cycle = FALSE;
if (TCP4_PORT_USER_RESERVED == mTcp4RandomPort) {
mTcp4RandomPort = TCP4_PORT_KNOWN;
}
mTcp4RandomPort++;
while (TcpFindTcbByPeer (&AP->StationAddress, mTcp4RandomPort)) {
mTcp4RandomPort++;
if (mTcp4RandomPort <= TCP4_PORT_KNOWN) {
if (Cycle) {
TCP4_DEBUG_ERROR (("Tcp4Bind: no port can be allocated "
"for this pcb\n"));
return EFI_OUT_OF_RESOURCES;
}
mTcp4RandomPort = TCP4_PORT_KNOWN + 1;
Cycle = TRUE;
}
}
AP->StationPort = mTcp4RandomPort;
}
return EFI_SUCCESS;
}
/**
Flush the Tcb add its associated protocols..
@param Tcb Pointer to the TCP_CB to be flushed.
@retval EFI_SUCCESS The operation is completed successfully.
**/
STATIC
VOID
Tcp4FlushPcb (
IN TCP_CB *Tcb
)
{
SOCKET *Sock;
TCP4_PROTO_DATA *TcpProto;
IpIoConfigIp (Tcb->IpInfo, NULL);
Sock = Tcb->Sk;
TcpProto = (TCP4_PROTO_DATA *) Sock->ProtoReserved;
if (SOCK_IS_CONFIGURED (Sock)) {
NetListRemoveEntry (&Tcb->List);
TcpSetVariableData (TcpProto->TcpService);
}
NetbufFreeList (&Tcb->SndQue);
NetbufFreeList (&Tcb->RcvQue);
}
STATIC
EFI_STATUS
Tcp4AttachPcb (
IN SOCKET *Sk
)
{
TCP_CB *Tcb;
TCP4_PROTO_DATA *ProtoData;
IP_IO *IpIo;
Tcb = NetAllocateZeroPool (sizeof (TCP_CB));
if (Tcb == NULL) {
TCP4_DEBUG_ERROR (("Tcp4ConfigurePcb: failed to allocate a TCB\n"));
return EFI_OUT_OF_RESOURCES;
}
ProtoData = (TCP4_PROTO_DATA *) Sk->ProtoReserved;
IpIo = ProtoData->TcpService->IpIo;
//
// Create an IpInfo for this Tcb.
//
Tcb->IpInfo = IpIoAddIp (IpIo);
if (Tcb->IpInfo == NULL) {
NetFreePool (Tcb);
return EFI_OUT_OF_RESOURCES;
}
NetListInit (&Tcb->List);
NetListInit (&Tcb->SndQue);
NetListInit (&Tcb->RcvQue);
Tcb->State = TCP_CLOSED;
Tcb->Sk = Sk;
ProtoData->TcpPcb = Tcb;
return EFI_SUCCESS;
}
STATIC
VOID
Tcp4DetachPcb (
IN SOCKET *Sk
)
{
TCP4_PROTO_DATA *ProtoData;
TCP_CB *Tcb;
ProtoData = (TCP4_PROTO_DATA *) Sk->ProtoReserved;
Tcb = ProtoData->TcpPcb;
ASSERT (Tcb != NULL);
Tcp4FlushPcb (Tcb);
IpIoRemoveIp (ProtoData->TcpService->IpIo, Tcb->IpInfo);
NetFreePool (Tcb);
ProtoData->TcpPcb = NULL;
}
/**
Configure the Tcb using CfgData.
@param Sk Pointer to the socket of this TCP instance.
@param SkTcb Pointer to the TCP_CB of this TCP instance.
@param CfgData Pointer to the TCP configuration data.
@retval EFI_SUCCESS The operation is completed successfully.
@retval EFI_INVALID_PARAMETER A same access point has been configured in
another TCP instance.
@retval EFI_OUT_OF_RESOURCES Failed due to resource limit.
**/
STATIC
EFI_STATUS
Tcp4ConfigurePcb (
IN SOCKET *Sk,
IN EFI_TCP4_CONFIG_DATA *CfgData
)
{
IP_IO *IpIo;
EFI_IP4_CONFIG_DATA IpCfgData;
EFI_STATUS Status;
EFI_TCP4_OPTION *Option;
TCP4_PROTO_DATA *TcpProto;
TCP_CB *Tcb;
ASSERT (CfgData && Sk && Sk->SockHandle);
TcpProto = (TCP4_PROTO_DATA *) Sk->ProtoReserved;
Tcb = TcpProto->TcpPcb;
IpIo = TcpProto->TcpService->IpIo;
ASSERT (Tcb != NULL);
//
// Add Ip for send pkt to the peer
//
IpCfgData = mIpIoDefaultIpConfigData;
IpCfgData.DefaultProtocol = EFI_IP_PROTO_TCP;
IpCfgData.UseDefaultAddress = CfgData->AccessPoint.UseDefaultAddress;
IpCfgData.StationAddress = CfgData->AccessPoint.StationAddress;
IpCfgData.SubnetMask = CfgData->AccessPoint.SubnetMask;
IpCfgData.ReceiveTimeout = (UINT32) (-1);
//
// Configure the IP instance this Tcb consumes.
//
Status = IpIoConfigIp (Tcb->IpInfo, &IpCfgData);
if (EFI_ERROR (Status)) {
goto OnExit;
}
//
// Get the default address info if the instance is configured to use default address.
//
if (CfgData->AccessPoint.UseDefaultAddress) {
CfgData->AccessPoint.StationAddress = IpCfgData.StationAddress;
CfgData->AccessPoint.SubnetMask = IpCfgData.SubnetMask;
}
//
// check if we can bind this endpoint in CfgData
//
Status = Tcp4Bind (&(CfgData->AccessPoint));
if (EFI_ERROR (Status)) {
TCP4_DEBUG_ERROR (("Tcp4ConfigurePcb: Bind endpoint failed "
"with %r\n", Status));
goto OnExit;
}
//
// Initalize the operating information in this Tcb
//
ASSERT (Tcb->State == TCP_CLOSED &&
NetListIsEmpty (&Tcb->SndQue) &&
NetListIsEmpty (&Tcb->RcvQue));
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE);
Tcb->State = TCP_CLOSED;
Tcb->SndMss = 536;
Tcb->RcvMss = TcpGetRcvMss (Sk);
Tcb->SRtt = 0;
Tcb->Rto = 3 * TCP_TICK_HZ;
Tcb->CWnd = Tcb->SndMss;
Tcb->Ssthresh = 0xffffffff;
Tcb->CongestState = TCP_CONGEST_OPEN;
Tcb->KeepAliveIdle = TCP_KEEPALIVE_IDLE_MIN;
Tcb->KeepAlivePeriod = TCP_KEEPALIVE_PERIOD;
Tcb->MaxKeepAlive = TCP_MAX_KEEPALIVE;
Tcb->MaxRexmit = TCP_MAX_LOSS;
Tcb->FinWait2Timeout = TCP_FIN_WAIT2_TIME;
Tcb->TimeWaitTimeout = TCP_TIME_WAIT_TIME;
Tcb->ConnectTimeout = TCP_CONNECT_TIME;
//
// initialize Tcb in the light of CfgData
//
Tcb->TTL = CfgData->TimeToLive;
Tcb->TOS = CfgData->TypeOfService;
Tcb->LocalEnd.Ip = EFI_IP4 (CfgData->AccessPoint.StationAddress);
Tcb->LocalEnd.Port = HTONS (CfgData->AccessPoint.StationPort);
Tcb->SubnetMask = CfgData->AccessPoint.SubnetMask;
Tcb->RemoteEnd.Ip = EFI_IP4 (CfgData->AccessPoint.RemoteAddress);
Tcb->RemoteEnd.Port = HTONS (CfgData->AccessPoint.RemotePort);
Option = CfgData->ControlOption;
if (Option != NULL) {
SET_RCV_BUFFSIZE (
Sk,
TCP_COMP_VAL (TCP_RCV_BUF_SIZE_MIN,
TCP_RCV_BUF_SIZE,
TCP_RCV_BUF_SIZE,
Option->ReceiveBufferSize)
);
SET_SND_BUFFSIZE (
Sk,
TCP_COMP_VAL (TCP_SND_BUF_SIZE_MIN,
TCP_SND_BUF_SIZE,
TCP_SND_BUF_SIZE,
Option->SendBufferSize)
);
SET_BACKLOG (
Sk,
TCP_COMP_VAL (TCP_BACKLOG_MIN,
TCP_BACKLOG,
TCP_BACKLOG,
Option->MaxSynBackLog)
);
Tcb->MaxRexmit = (UINT16) TCP_COMP_VAL (
TCP_MAX_LOSS_MIN,
TCP_MAX_LOSS,
TCP_MAX_LOSS,
Option->DataRetries
);
Tcb->FinWait2Timeout = TCP_COMP_VAL (
TCP_FIN_WAIT2_TIME,
TCP_FIN_WAIT2_TIME_MAX,
TCP_FIN_WAIT2_TIME,
Option->FinTimeout * TCP_TICK_HZ
);
if (Option->TimeWaitTimeout != 0) {
Tcb->TimeWaitTimeout = TCP_COMP_VAL (
TCP_TIME_WAIT_TIME,
TCP_TIME_WAIT_TIME_MAX,
TCP_TIME_WAIT_TIME,
Option->TimeWaitTimeout * TCP_TICK_HZ
);
} else {
Tcb->TimeWaitTimeout = 0;
}
if (Option->KeepAliveProbes != 0) {
TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE);
Tcb->MaxKeepAlive = (UINT8) TCP_COMP_VAL (
TCP_MAX_KEEPALIVE_MIN,
TCP_MAX_KEEPALIVE,
TCP_MAX_KEEPALIVE,
Option->KeepAliveProbes
);
Tcb->KeepAliveIdle = TCP_COMP_VAL (
TCP_KEEPALIVE_IDLE_MIN,
TCP_KEEPALIVE_IDLE_MAX,
TCP_KEEPALIVE_IDLE_MIN,
Option->KeepAliveTime * TCP_TICK_HZ
);
Tcb->KeepAlivePeriod = TCP_COMP_VAL (
TCP_KEEPALIVE_PERIOD_MIN,
TCP_KEEPALIVE_PERIOD,
TCP_KEEPALIVE_PERIOD,
Option->KeepAliveInterval * TCP_TICK_HZ
);
}
Tcb->ConnectTimeout = TCP_COMP_VAL (
TCP_CONNECT_TIME_MIN,
TCP_CONNECT_TIME,
TCP_CONNECT_TIME,
Option->ConnectionTimeout * TCP_TICK_HZ
);
if (Option->EnableNagle == FALSE) {
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_NAGLE);
}
if (Option->EnableTimeStamp == FALSE) {
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_TS);
}
if (Option->EnableWindowScaling == FALSE) {
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_NO_WS);
}
}
//
// update state of Tcb and socket
//
if (CfgData->AccessPoint.ActiveFlag == FALSE) {
TcpSetState (Tcb, TCP_LISTEN);
SockSetState (Sk, SO_LISTENING);
Sk->ConfigureState = SO_CONFIGURED_PASSIVE;
} else {
Sk->ConfigureState = SO_CONFIGURED_ACTIVE;
}
TcpInsertTcb (Tcb);
OnExit:
return Status;
}
/**
The procotol handler provided to the socket layer, used to
dispatch the socket level requests by calling the corresponding
TCP layer functions.
@param Sock Pointer to the socket of this TCP instance.
@param Request The code of this operation request.
@param Data Pointer to the operation specific data passed in
together with the operation request.
@retval EFI_SUCCESS The socket request is completed successfully.
@retval other The error status returned by the corresponding TCP
layer function.
**/
EFI_STATUS
Tcp4Dispatcher (
IN SOCKET *Sock,
IN SOCK_REQUEST Request,
IN VOID *Data OPTIONAL
)
{
TCP_CB *Tcb;
TCP4_PROTO_DATA *ProtoData;
EFI_IP4_PROTOCOL *Ip;
ProtoData = (TCP4_PROTO_DATA *) Sock->ProtoReserved;
Tcb = ProtoData->TcpPcb;
switch (Request) {
case SOCK_POLL:
Ip = ProtoData->TcpService->IpIo->Ip;
Ip->Poll (Ip);
break;
case SOCK_CONSUMED:
//
// After user received data from socket buffer, socket will
// notify TCP using this message to give it a chance to send out
// window update information
//
ASSERT (Tcb);
TcpOnAppConsume (Tcb);
break;
case SOCK_SND:
ASSERT (Tcb);
TcpOnAppSend (Tcb);
break;
case SOCK_CLOSE:
TcpOnAppClose (Tcb);
break;
case SOCK_ABORT:
TcpOnAppAbort (Tcb);
break;
case SOCK_SNDPUSH:
Tcb->SndPsh = TcpGetMaxSndNxt (Tcb) + GET_SND_DATASIZE (Tcb->Sk);
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_PSH);
break;
case SOCK_SNDURG:
Tcb->SndUp = TcpGetMaxSndNxt (Tcb) + GET_SND_DATASIZE (Tcb->Sk) - 1;
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_SND_URG);
break;
case SOCK_CONNECT:
TcpOnAppConnect (Tcb);
break;
case SOCK_ATTACH:
return Tcp4AttachPcb (Sock);
break;
case SOCK_FLUSH:
Tcp4FlushPcb (Tcb);
break;
case SOCK_DETACH:
Tcp4DetachPcb (Sock);
break;
case SOCK_CONFIGURE:
return Tcp4ConfigurePcb (
Sock,
(EFI_TCP4_CONFIG_DATA *) Data
);
break;
case SOCK_MODE:
ASSERT (Data && Tcb);
return Tcp4GetMode (Tcb, (TCP4_MODE_DATA *) Data);
break;
case SOCK_ROUTE:
ASSERT (Data && Tcb);
return Tcp4Route (Tcb, (TCP4_ROUTE_INFO *) Data);
}
return EFI_SUCCESS;
}

View File

@ -0,0 +1,669 @@
/** @file
Copyright (c) 2005 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Tcp4Driver.c
Abstract:
**/
#include "Tcp4Main.h"
UINT16 mTcp4RandomPort;
extern EFI_COMPONENT_NAME_PROTOCOL gTcp4ComponentName;
TCP4_HEARTBEAT_TIMER mTcp4Timer = {
NULL,
0
};
EFI_TCP4_PROTOCOL mTcp4ProtocolTemplate = {
Tcp4GetModeData,
Tcp4Configure,
Tcp4Routes,
Tcp4Connect,
Tcp4Accept,
Tcp4Transmit,
Tcp4Receive,
Tcp4Close,
Tcp4Cancel,
Tcp4Poll
};
SOCK_INIT_DATA mTcp4DefaultSockData = {
SOCK_STREAM,
0,
NULL,
TCP_BACKLOG,
TCP_SND_BUF_SIZE,
TCP_RCV_BUF_SIZE,
&mTcp4ProtocolTemplate,
Tcp4Dispatcher,
NULL,
};
EFI_DRIVER_BINDING_PROTOCOL mTcp4DriverBinding = {
Tcp4DriverBindingSupported,
Tcp4DriverBindingStart,
Tcp4DriverBindingStop,
0xa,
NULL,
NULL
};
EFI_SERVICE_BINDING_PROTOCOL mTcp4ServiceBinding = {
Tcp4ServiceBindingCreateChild,
Tcp4ServiceBindingDestroyChild
};
/**
Create and start the heartbeat timer for TCP driver.
None.
@retval EFI_SUCCESS The timer is successfully created and started.
@retval other The timer is not created.
**/
STATIC
EFI_STATUS
Tcp4CreateTimer (
VOID
)
{
EFI_STATUS Status;
Status = EFI_SUCCESS;
if (mTcp4Timer.RefCnt == 0) {
Status = gBS->CreateEvent (
EVT_TIMER | EVT_NOTIFY_SIGNAL,
NET_TPL_TIMER,
TcpTicking,
NULL,
&mTcp4Timer.TimerEvent
);
if (!EFI_ERROR (Status)) {
Status = gBS->SetTimer (
mTcp4Timer.TimerEvent,
TimerPeriodic,
(UINT64) (TICKS_PER_SECOND / TCP_TICK_HZ)
);
}
}
if (!EFI_ERROR (Status)) {
mTcp4Timer.RefCnt++;
}
return Status;
}
/**
Stop and destroy the heartbeat timer for TCP driver.
None.
@return None.
**/
STATIC
VOID
Tcp4DestroyTimer (
VOID
)
{
ASSERT (mTcp4Timer.RefCnt > 0);
mTcp4Timer.RefCnt--;
if (mTcp4Timer.RefCnt > 0) {
return;
}
gBS->SetTimer (mTcp4Timer.TimerEvent, TimerCancel, 0);
gBS->CloseEvent (mTcp4Timer.TimerEvent);
mTcp4Timer.TimerEvent = NULL;
}
//@MT: EFI_DRIVER_ENTRY_POINT (Tcp4DriverEntryPoint)
EFI_STATUS
EFIAPI
Tcp4DriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
The entry point for Tcp4 driver. used to install
Tcp4 driver on the ImageHandle.
Arguments:
ImageHandle - The firmware allocated handle for this
driver image.
SystemTable - Pointer to the EFI system table.
Returns:
EFI_SUCCESS - Driver loaded.
other - Driver not loaded.
--*/
{
EFI_STATUS Status;
UINT32 Seed;
//
// Install the TCP4 Driver Binding Protocol
//
Status = NetLibInstallAllDriverProtocols (
ImageHandle,
SystemTable,
&mTcp4DriverBinding,
ImageHandle,
&gTcp4ComponentName,
NULL,
NULL
);
//
// Initialize ISS and random port.
//
Seed = NetRandomInitSeed ();
mTcpGlobalIss = NET_RANDOM (Seed) % mTcpGlobalIss;
mTcp4RandomPort = TCP4_PORT_KNOWN +
(UINT16) (NET_RANDOM(Seed) % TCP4_PORT_KNOWN);
return Status;
}
/**
Test to see if this driver supports ControllerHandle.
@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
Tcp4DriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL * This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
)
{
EFI_STATUS Status;
//
// Test for the Tcp4ServiceBinding Protocol
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiTcp4ServiceBindingProtocolGuid,
NULL,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
if (!EFI_ERROR (Status)) {
return EFI_ALREADY_STARTED;
}
//
// Test for the Ip4 Protocol
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiIp4ServiceBindingProtocolGuid,
NULL,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
return Status;
}
/**
Start this driver on ControllerHandle.
@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 The driver is added to ControllerHandle.
@retval EFI_OUT_OF_RESOURCES There are not enough resources to start the
driver.
@retval other The driver cannot be added to ControllerHandle.
**/
EFI_STATUS
EFIAPI
Tcp4DriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL * This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
)
{
EFI_STATUS Status;
TCP4_SERVICE_DATA *TcpServiceData;
IP_IO_OPEN_DATA OpenData;
TcpServiceData = NetAllocateZeroPool (sizeof (TCP4_SERVICE_DATA));
if (NULL == TcpServiceData) {
TCP4_DEBUG_ERROR (("Tcp4DriverBindingStart: Have no enough"
" resource to create a Tcp Servcie Data!\n"));
return EFI_OUT_OF_RESOURCES;
}
//
// Create a new IP IO to Consume it
//
TcpServiceData->IpIo = IpIoCreate (This->DriverBindingHandle, ControllerHandle);
if (NULL == TcpServiceData->IpIo) {
TCP4_DEBUG_ERROR (("Tcp4DriverBindingStart: Have no enough"
" resource to create an Ip Io!\n"));
Status = EFI_OUT_OF_RESOURCES;
goto ReleaseServiceData;
}
//
// Configure and start IpIo.
//
NetZeroMem (&OpenData, sizeof (IP_IO_OPEN_DATA));
OpenData.IpConfigData = mIpIoDefaultIpConfigData;
OpenData.IpConfigData.DefaultProtocol = EFI_IP_PROTO_TCP;
OpenData.PktRcvdNotify = Tcp4RxCallback;
Status = IpIoOpen (TcpServiceData->IpIo, &OpenData);
if (EFI_ERROR (Status)) {
goto ReleaseServiceData;
}
//
// Create the timer event used by TCP driver
//
Status = Tcp4CreateTimer ();
if (EFI_ERROR (Status)) {
TCP4_DEBUG_ERROR (("Tcp4DriverBindingStart: Create TcpTimer"
" Event failed with %r\n", Status));
goto ReleaseIpIo;
}
//
// Install the Tcp4ServiceBinding Protocol on the
// controller handle
//
TcpServiceData->Tcp4ServiceBinding = mTcp4ServiceBinding;
Status = gBS->InstallMultipleProtocolInterfaces (
&ControllerHandle,
&gEfiTcp4ServiceBindingProtocolGuid,
&TcpServiceData->Tcp4ServiceBinding,
NULL
);
if (EFI_ERROR (Status)) {
TCP4_DEBUG_ERROR (("Tcp4DriverBindingStart: Install Tcp4 Service Binding"
" Protocol failed for %r\n", Status));
goto ReleaseTimer;
}
//
// Initialize member in TcpServiceData
//
TcpServiceData->ControllerHandle = ControllerHandle;
TcpServiceData->Signature = TCP4_DRIVER_SIGNATURE;
TcpServiceData->DriverBindingHandle = This->DriverBindingHandle;
TcpSetVariableData (TcpServiceData);
return EFI_SUCCESS;
ReleaseTimer:
Tcp4DestroyTimer ();
ReleaseIpIo:
IpIoDestroy (TcpServiceData->IpIo);
ReleaseServiceData:
NetFreePool (TcpServiceData);
return Status;
}
/**
Stop this driver on ControllerHandle.
@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 from ControllerHandle.
@retval other This driver is not removed from ControllerHandle.
**/
EFI_STATUS
EFIAPI
Tcp4DriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
)
{
EFI_STATUS Status;
EFI_HANDLE NicHandle;
EFI_SERVICE_BINDING_PROTOCOL *Tcp4ServiceBinding;
TCP4_SERVICE_DATA *TcpServiceData;
TCP_CB *TcpPcb;
SOCKET *Sock;
TCP4_PROTO_DATA *TcpProto;
NET_LIST_ENTRY *Entry;
NET_LIST_ENTRY *NextEntry;
// Find the NicHandle where Tcp4 ServiceBinding Protocol is installed.
//
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp4ProtocolGuid);
if (NicHandle == NULL) {
return EFI_SUCCESS;
}
//
// Retrieve the TCP driver Data Structure
//
Status = gBS->OpenProtocol (
NicHandle,
&gEfiTcp4ServiceBindingProtocolGuid,
(VOID **) &Tcp4ServiceBinding,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
TCP4_DEBUG_ERROR (("Tcp4DriverBindingStop: Locate Tcp4 Service "
" Binding Protocol failed with %r\n", Status));
return Status;
}
TcpServiceData = TCP4_FROM_THIS (Tcp4ServiceBinding);
//
// Kill TCP driver
//
NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mTcpRunQue) {
TcpPcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
//
// Try to destroy this child
//
Sock = TcpPcb->Sk;
TcpProto = (TCP4_PROTO_DATA *) Sock->ProtoReserved;
if (TcpProto->TcpService == TcpServiceData) {
Status = SockDestroyChild (Sock);
if (EFI_ERROR (Status)) {
TCP4_DEBUG_ERROR (("Tcp4DriverBindingStop: Destroy Tcp "
"instance failed with %r\n", Status));
return Status;
}
}
}
NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &mTcpListenQue) {
TcpPcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
//
// Try to destroy this child
//
Sock = TcpPcb->Sk;
TcpProto = (TCP4_PROTO_DATA *) Sock->ProtoReserved;
if (TcpProto->TcpService == TcpServiceData) {
Status = SockDestroyChild (TcpPcb->Sk);
if (EFI_ERROR (Status)) {
TCP4_DEBUG_ERROR (("Tcp4DriverBindingStop: Destroy Tcp "
"instance failed with %r\n", Status));
return Status;
}
}
}
//
// Uninstall TCP servicebinding protocol
//
Status = gBS->UninstallMultipleProtocolInterfaces (
NicHandle,
&gEfiTcp4ServiceBindingProtocolGuid,
Tcp4ServiceBinding,
NULL
);
if (EFI_ERROR (Status)) {
TCP4_DEBUG_ERROR (("Tcp4DriverBindingStop: Uninstall TCP service "
"binding protocol failed with %r\n", Status));
return Status;
}
//
// Destroy the IpIO consumed by TCP driver
//
Status = IpIoDestroy (TcpServiceData->IpIo);
//
// Destroy the heartbeat timer.
//
Tcp4DestroyTimer ();
//
// Clear the variable.
//
TcpClearVariableData (TcpServiceData);
//
// Release the TCP service data
//
NetFreePool (TcpServiceData);
return Status;
}
/**
Creates a child handle with a set of TCP4 services.
@param This Protocol instance pointer.
@param ChildHandle Pointer to the handle of the child to create. If
it is NULL, then a new handle is created. If it is
not NULL, then the I/O services are added to the
existing child handle.
@retval EFI_SUCCESS The child handle is created.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_OUT_OF_RESOURCES There are not enough resources to create the
child.
**/
EFI_STATUS
EFIAPI
Tcp4ServiceBindingCreateChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN EFI_HANDLE *ChildHandle
)
{
SOCKET *Sock;
TCP4_SERVICE_DATA *TcpServiceData;
TCP4_PROTO_DATA TcpProto;
EFI_STATUS Status;
VOID *Ip4;
EFI_TPL OldTpl;
if (NULL == This || NULL == ChildHandle) {
return EFI_INVALID_PARAMETER;
}
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
TcpServiceData = TCP4_FROM_THIS (This);
TcpProto.TcpService = TcpServiceData;
TcpProto.TcpPcb = NULL;
//
// Create a tcp instance with defualt Tcp default
// sock init data and TcpProto
//
mTcp4DefaultSockData.DriverBinding = TcpServiceData->DriverBindingHandle;
Sock = SockCreateChild (&mTcp4DefaultSockData, &TcpProto, sizeof (TCP4_PROTO_DATA));
if (NULL == Sock) {
TCP4_DEBUG_ERROR (("Tcp4DriverBindingCreateChild: "
"No resource to create a Tcp Child\n"));
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
*ChildHandle = Sock->SockHandle;
//
// Open the default Ip4 protocol of IP_IO BY_DRIVER.
//
Status = gBS->OpenProtocol (
TcpServiceData->IpIo->ChildHandle,
&gEfiIp4ProtocolGuid,
(VOID **) &Ip4,
TcpServiceData->DriverBindingHandle,
Sock->SockHandle,
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
);
if (EFI_ERROR (Status)) {
SockDestroyChild (Sock);
}
ON_EXIT:
NET_RESTORE_TPL (OldTpl);
return Status;
}
/**
Destroys a child handle with a set of UDP4 services.
@param This Protocol instance pointer.
@param ChildHandle Handle of the child to be destroyed.
@retval EFI_SUCCESS The TCP4 services are removed from the child
handle.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval other The child handle is not destroyed.
**/
EFI_STATUS
EFIAPI
Tcp4ServiceBindingDestroyChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN EFI_HANDLE ChildHandle
)
{
EFI_STATUS Status;
EFI_TCP4_PROTOCOL *Tcp4;
SOCKET *Sock;
TCP4_PROTO_DATA *TcpProtoData;
TCP4_SERVICE_DATA *TcpServiceData;
EFI_TPL OldTpl;
if (NULL == This || NULL == ChildHandle) {
return EFI_INVALID_PARAMETER;
}
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
//
// retrieve the Tcp4 protocol from ChildHandle
//
Status = gBS->OpenProtocol (
ChildHandle,
&gEfiTcp4ProtocolGuid,
(VOID **) &Tcp4,
mTcp4DriverBinding.DriverBindingHandle,
ChildHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
Status = EFI_UNSUPPORTED;
goto ON_EXIT;
}
//
// destroy this sock and related Tcp protocol control
// block
//
Sock = SOCK_FROM_THIS (Tcp4);
TcpProtoData = (TCP4_PROTO_DATA *) Sock->ProtoReserved;
TcpServiceData = TcpProtoData->TcpService;
Status = SockDestroyChild (Sock);
//
// Close the Ip4 protocol.
//
gBS->CloseProtocol (
TcpServiceData->IpIo->ChildHandle,
&gEfiIp4ProtocolGuid,
TcpServiceData->DriverBindingHandle,
ChildHandle
);
ON_EXIT:
NET_RESTORE_TPL (OldTpl);
return Status;
}

View File

@ -0,0 +1,141 @@
/** @file
Copyright (c) 2005 - 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Tcp4Driver.h
Abstract:
**/
#ifndef _TCP4_DRIVER_H_
#define _TCP4_DRIVER_H_
#include <Protocol/ServiceBinding.h>
#include <Library/IpIoLib.h>
#define TCP4_DRIVER_SIGNATURE EFI_SIGNATURE_32 ('T', 'C', 'P', '4')
#define TCP4_PORT_KNOWN 1024
#define TCP4_PORT_USER_RESERVED 65535
typedef struct _TCP4_HEARTBEAT_TIMER {
EFI_EVENT TimerEvent;
INTN RefCnt;
} TCP4_HEARTBEAT_TIMER;
typedef struct _TCP4_SERVICE_DATA {
UINT32 Signature;
EFI_HANDLE ControllerHandle;
IP_IO *IpIo; // IP Io consumed by TCP4
EFI_SERVICE_BINDING_PROTOCOL Tcp4ServiceBinding;
EFI_HANDLE DriverBindingHandle;
CHAR16 *MacString;
} TCP4_SERVICE_DATA;
//
// Prototype for TCP4 driver Rcv callback function registered to IP_IO
//
VOID
Tcp4RxCallback (
IN EFI_STATUS Status,
IN ICMP_ERROR IcmpErr,
IN EFI_NET_SESSION_DATA *NetSession,
IN NET_BUF *Pkt,
IN VOID *Context OPTIONAL
);
INTN
TcpSendIpPacket (
IN TCP_CB *Tcb,
IN NET_BUF *Nbuf,
IN UINT32 Src,
IN UINT32 Dest
);
EFI_STATUS
Tcp4Dispatcher (
IN SOCKET *Sock,
IN SOCK_REQUEST Request,
IN VOID *Data OPTIONAL
);
typedef struct _TCP4_PROTO_DATA {
TCP4_SERVICE_DATA *TcpService;
TCP_CB *TcpPcb;
} TCP4_PROTO_DATA;
#define TCP4_FROM_THIS(a) \
CR ( \
(a), \
TCP4_SERVICE_DATA, \
Tcp4ServiceBinding, \
TCP4_DRIVER_SIGNATURE \
)
//
// Function prototype for the driver's entry point
//
EFI_STATUS
EFIAPI
Tcp4DriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
);
//
// Function prototypes for the Drivr Binding Protocol
//
EFI_STATUS
EFIAPI
Tcp4DriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL * This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
);
EFI_STATUS
EFIAPI
Tcp4DriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL * This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
);
EFI_STATUS
EFIAPI
Tcp4DriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
);
//
// Function ptototypes for the ServiceBinding Prococol
//
EFI_STATUS
EFIAPI
Tcp4ServiceBindingCreateChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN EFI_HANDLE *ChildHandle
);
EFI_STATUS
EFIAPI
Tcp4ServiceBindingDestroyChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN EFI_HANDLE ChildHandle
);
#endif

View File

@ -0,0 +1,77 @@
#/** @file
# Component name for module Tcp4
#
# FIX ME!
# Copyright (c) 2006, Intel Corporation. All right reserved.
#
# All rights reserved. This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
#
#**/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = Tcp4Dxe
FILE_GUID = 6d6963ab-906d-4a65-a7ca-bd40e5d6af4d
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
EDK_RELEASE_VERSION = 0x00020000
EFI_SPECIFICATION_VERSION = 0x00020000
ENTRY_POINT = Tcp4DriverEntryPoint
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources.common]
SockImpl.c
SockInterface.c
Tcp4Proto.h
Tcp4Main.h
SockImpl.h
Tcp4Output.c
Tcp4Timer.c
Tcp4Option.h
Tcp4Dispatcher.c
Tcp4Input.c
Tcp4Misc.c
Tcp4Main.c
Socket.h
ComponentName.c
Tcp4Driver.h
Tcp4Io.c
Tcp4Driver.c
Tcp4Func.h
Tcp4Option.c
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
UefiLib
BaseLib
UefiBootServicesTableLib
UefiDriverEntryPoint
UefiRuntimeServicesTableLib
DebugLib
NetLib
IpIoLib
[Protocols]
gEfiIp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiTcp4ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiIp4ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiTcp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED

View File

@ -0,0 +1,90 @@
<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MsaHeader>
<ModuleName>Tcp4Dxe</ModuleName>
<ModuleType>DXE_DRIVER</ModuleType>
<GuidValue>6d6963ab-906d-4a65-a7ca-bd40e5d6af4d</GuidValue>
<Version>1.0</Version>
<Abstract>Component name for module Tcp4</Abstract>
<Description>FIX ME!</Description>
<Copyright>Copyright (c) 2006, Intel Corporation. All right reserved.</Copyright>
<License>All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>
<Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
</MsaHeader>
<ModuleDefinitions>
<SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
<BinaryModule>false</BinaryModule>
<OutputFileBasename>Tcp4Dxe</OutputFileBasename>
</ModuleDefinitions>
<LibraryClassDefinitions>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>DebugLib</Keyword>
</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>UefiRuntimeServicesTableLib</Keyword>
</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>UefiDriverEntryPoint</Keyword>
</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>UefiBootServicesTableLib</Keyword>
</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>BaseLib</Keyword>
</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>UefiLib</Keyword>
</LibraryClass>
</LibraryClassDefinitions>
<SourceFiles>
<Filename>Tcp4Option.c</Filename>
<Filename>Tcp4Func.h</Filename>
<Filename>Tcp4Driver.c</Filename>
<Filename>Tcp4Io.c</Filename>
<Filename>Tcp4Driver.h</Filename>
<Filename>ComponentName.c</Filename>
<Filename>Socket.h</Filename>
<Filename>Tcp4Main.c</Filename>
<Filename>Tcp4Misc.c</Filename>
<Filename>Tcp4Input.c</Filename>
<Filename>Tcp4Dispatcher.c</Filename>
<Filename>Tcp4Option.h</Filename>
<Filename>Tcp4Timer.c</Filename>
<Filename>Tcp4Output.c</Filename>
<Filename>SockImpl.h</Filename>
<Filename>Tcp4Main.h</Filename>
<Filename>Tcp4Proto.h</Filename>
<Filename>SockInterface.c</Filename>
<Filename>SockImpl.c</Filename>
</SourceFiles>
<PackageDependencies>
<Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
<Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
</PackageDependencies>
<Protocols>
<Protocol Usage="ALWAYS_CONSUMED">
<ProtocolCName>gEfiTcp4ProtocolGuid</ProtocolCName>
</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">
<ProtocolCName>gEfiIp4ServiceBindingProtocolGuid</ProtocolCName>
</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">
<ProtocolCName>gEfiTcp4ServiceBindingProtocolGuid</ProtocolCName>
</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">
<ProtocolCName>gEfiIp4ProtocolGuid</ProtocolCName>
</Protocol>
</Protocols>
<Externs>
<Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
<Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
<Extern>
<ModuleEntryPoint>Tcp4DriverEntryPoint</ModuleEntryPoint>
</Extern>
</Externs>
</ModuleSurfaceArea>

View File

@ -0,0 +1,353 @@
/** @file
Copyright (c) 2005 - 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Tcp4Func.h
Abstract:
**/
#ifndef _TCP4_FUNC_H_
#define _TCP4_FUNC_H_
//
// Declaration of all the functions in TCP
// protocol. It is intended to keep tcp.h
// clear.
//
//
// Functions in tcp.c
//
BOOLEAN
TcpFindTcbByPeer (
IN EFI_IPv4_ADDRESS *Addr,
IN TCP_PORTNO Port
);
TCP_CB *
TcpLocateTcb (
IN TCP_PORTNO LocalPort,
IN UINT32 LocalIp,
IN TCP_PORTNO RemotePort,
IN UINT32 RemoteIp,
IN BOOLEAN Syn
);
INTN
TcpInsertTcb (
IN TCP_CB *Tcb
);
TCP_CB *
TcpCloneTcb (
IN TCP_CB *Tcb
);
TCP_SEQNO
TcpGetIss (
VOID
);
VOID
TcpInitTcbLocal (
IN TCP_CB *Tcb
);
VOID
TcpInitTcbPeer (
IN TCP_CB *Tcb,
IN TCP_SEG *Seg,
IN TCP_OPTION *Opt
);
UINT16
TcpGetRcvMss (
IN SOCKET *Sock
);
VOID
TcpSetState (
IN TCP_CB *Tcb,
IN UINT8 State
);
//
// Functions in Tcp4Output.c
//
INTN
TcpSendIpPacket (
IN TCP_CB *Tcb,
IN NET_BUF *Nbuf,
IN UINT32 Src,
IN UINT32 Dst
);
INTN
TcpToSendData (
IN TCP_CB *Tcb,
IN INTN Force
);
VOID
TcpToSendAck (
IN TCP_CB *Tcb
);
VOID
TcpSendAck (
IN TCP_CB *Tcb
);
INTN
TcpSendZeroProbe (
IN TCP_CB *Tcb
);
INTN
TcpDeliverData (
IN TCP_CB *Tcb
);
INTN
TcpSendReset (
IN TCP_CB *Tcb,
IN TCP_HEAD *Head,
IN INT32 Len,
IN UINT32 Local,
IN UINT32 Remote
);
UINT32
TcpRcvWinOld (
IN TCP_CB *Tcb
);
UINT32
TcpRcvWinNow (
IN TCP_CB *Tcb
);
INTN
TcpRetransmit (
IN TCP_CB *Tcb,
IN TCP_SEQNO Seq
);
UINT32
TcpDataToSend (
IN TCP_CB *Tcb,
IN INTN Force
);
INTN
TcpVerifySegment (
IN NET_BUF *Nbuf
);
INTN
TcpCheckSndQue (
IN NET_LIST_ENTRY *Head
);
NET_BUF *
TcpGetSegmentSndQue (
IN TCP_CB *Tcb,
IN TCP_SEQNO Seq,
IN UINT32 Len
);
NET_BUF *
TcpGetSegmentSock (
IN TCP_CB *Tcb,
IN TCP_SEQNO Seq,
IN UINT32 Len
);
NET_BUF *
TcpGetSegment (
IN TCP_CB *Tcb,
IN TCP_SEQNO Seq,
IN UINT32 Len
);
TCP_SEQNO
TcpGetMaxSndNxt (
IN TCP_CB *Tcb
);
//
// Functions from Tcp4Input.c
//
VOID
TcpIcmpInput (
IN NET_BUF *Nbuf,
IN ICMP_ERROR IcmpErr,
IN UINT32 Src,
IN UINT32 Dst
);
INTN
TcpInput (
IN NET_BUF *Nbuf,
IN UINT32 Src,
IN UINT32 Dst
);
INTN
TcpSeqAcceptable (
IN TCP_CB *Tcb,
IN TCP_SEG *Seg
);
VOID
TcpFastRecover (
IN TCP_CB *Tcb,
IN TCP_SEG *Seg
);
VOID
TcpFastLossRecover (
IN TCP_CB *Tcb,
IN TCP_SEG *Seg
);
VOID
TcpComputeRtt (
IN TCP_CB *Tcb,
IN UINT32 Measure
);
INTN
TcpTrimInWnd (
IN TCP_CB *Tcb,
IN NET_BUF *Buf
);
VOID
TcpQueueData (
IN TCP_CB *Tcb,
IN NET_BUF *Nbuf
);
VOID
TcpAdjustSndQue (
IN TCP_CB *Tcb,
IN TCP_SEQNO Ack
);
//
// Functions from Tcp4Misc.c
//
UINT16
TcpChecksum (
IN NET_BUF *Buf,
IN UINT16 HeadChecksum
);
TCP_SEG *
TcpFormatNetbuf (
IN TCP_CB *Tcb,
IN NET_BUF *Nbuf
);
VOID
TcpOnAppConnect (
IN TCP_CB *Tcb
);
INTN
TcpOnAppConsume (
IN TCP_CB *Tcb
);
VOID
TcpOnAppClose (
IN TCP_CB *Tcb
);
INTN
TcpOnAppSend (
IN TCP_CB *Tcb
);
VOID
TcpOnAppAbort (
IN TCP_CB *Tcb
);
VOID
TcpResetConnection (
IN TCP_CB *Tcb
);
//
// Functions in Tcp4Timer.c
//
VOID
TcpClose (
IN TCP_CB *Tcb
);
VOID
EFIAPI
TcpTicking (
IN EFI_EVENT Event,
IN VOID *Context
);
VOID
TcpSetTimer (
IN TCP_CB *Tcb,
IN UINT16 Timer,
IN UINT32 TimeOut
);
VOID
TcpClearTimer (
IN TCP_CB *Tcb,
IN UINT16 Timer
);
VOID
TcpClearAllTimer (
IN TCP_CB *Tcb
);
VOID
TcpSetProbeTimer (
IN TCP_CB *Tcb
);
VOID
TcpSetKeepaliveTimer (
IN TCP_CB *Tcb
);
VOID
TcpBackoffRto (
IN TCP_CB *Tcb
);
EFI_STATUS
TcpSetVariableData (
IN TCP4_SERVICE_DATA *Tcp4Service
);
VOID
TcpClearVariableData (
IN TCP4_SERVICE_DATA *Tcp4Service
);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,117 @@
/** @file
Copyright (c) 2005 - 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Tcp4Io.c
Abstract:
I/O interfaces between TCP and IpIo.
**/
#include "Tcp4Main.h"
/**
Packet receive callback function provided to IP_IO, used to call
the proper function to handle the packet received by IP.
@param Status Status of the received packet.
@param IcmpErr ICMP error number.
@param NetSession Pointer to the net session of this packet.
@param Pkt Pointer to the recieved packet.
@param Context Pointer to the context configured in IpIoOpen(), not used
now.
@return None
**/
VOID
Tcp4RxCallback (
IN EFI_STATUS Status,
IN ICMP_ERROR IcmpErr,
IN EFI_NET_SESSION_DATA *NetSession,
IN NET_BUF *Pkt,
IN VOID *Context OPTIONAL
)
{
if (EFI_SUCCESS == Status) {
TcpInput (Pkt, NetSession->Source, NetSession->Dest);
} else {
TcpIcmpInput (Pkt, IcmpErr, NetSession->Source, NetSession->Dest);
}
}
/**
Send the segment to IP via IpIo function.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Nbuf Pointer to the TCP segment to be sent.
@param Src Source address of the TCP segment.
@param Dest Destination address of the TCP segment.
@retval 0 The segment was sent out successfully.
@retval -1 The segment was failed to send.
**/
INTN
TcpSendIpPacket (
IN TCP_CB *Tcb,
IN NET_BUF *Nbuf,
IN UINT32 Src,
IN UINT32 Dest
)
{
EFI_STATUS Status;
IP_IO *IpIo;
IP_IO_OVERRIDE Override;
SOCKET *Sock;
VOID *IpSender;
TCP4_PROTO_DATA *TcpProto;
if (NULL == Tcb) {
IpIo = NULL;
IpSender = IpIoFindSender (&IpIo, Src);
if (IpSender == NULL) {
TCP4_DEBUG_WARN (("TcpSendIpPacket: No appropriate IpSender.\n"));
return -1;
}
} else {
Sock = Tcb->Sk;
TcpProto = (TCP4_PROTO_DATA *) Sock->ProtoReserved;
IpIo = TcpProto->TcpService->IpIo;
IpSender = Tcb->IpInfo;
}
Override.TypeOfService = 0;
Override.TimeToLive = 255;
Override.DoNotFragment = FALSE;
Override.Protocol = EFI_IP_PROTO_TCP;
EFI_IP4 (Override.GatewayAddress) = 0;
EFI_IP4 (Override.SourceAddress) = Src;
Status = IpIoSend (IpIo, Nbuf, IpSender, NULL, NULL, Dest, &Override);
if (EFI_ERROR (Status)) {
TCP4_DEBUG_ERROR (("TcpSendIpPacket: return %r error\n", Status));
return -1;
}
return 0;
}

View File

@ -0,0 +1,564 @@
/** @file
Copyright (c) 2005 - 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Tcp4Main.c
Abstract:
Implementation of TCP4 protocol services.
**/
#include "Tcp4Main.h"
/**
Check the integrity of the data buffer.
@param DataLen The total length of the data buffer.
@param FragmentCount The fragment count of the fragment table.
@param FragmentTable Pointer to the fragment table of the data
buffer.
@retval EFI_SUCCESS The integrity check is passed.
@retval EFI_INVALID_PARAMETER The integrity check is failed.
**/
STATIC
EFI_STATUS
Tcp4ChkDataBuf (
IN UINT32 DataLen,
IN UINT32 FragmentCount,
IN EFI_TCP4_FRAGMENT_DATA *FragmentTable
)
{
UINT32 Index;
UINT32 Len;
for (Index = 0, Len = 0; Index < FragmentCount; Index++) {
Len = Len + FragmentTable[Index].FragmentLength;
}
if (DataLen != Len) {
return EFI_INVALID_PARAMETER;
}
return EFI_SUCCESS;
}
/**
Get the current operational status.
@param This Pointer to the EFI_TCP4_PROTOCOL instance.
@param Tcp4State Pointer to the buffer to receive the current TCP
state.
@param Tcp4ConfigData Pointer to the buffer to receive the current TCP
configuration.
@param Ip4ModeData Pointer to the buffer to receive the current
IPv4 configuration.
@param MnpConfigData Pointer to the buffer to receive the current MNP
configuration data indirectly used by the TCPv4
Instance.
@param SnpModeData Pointer to the buffer to receive the current SNP
configuration data indirectly used by the TCPv4
Instance.
@retval EFI_SUCCESS The mode data was read.
@retval EFI_NOT_STARTED No configuration data is available because this
instance hasn't been started.
@retval EFI_INVALID_PARAMETER This is NULL.
**/
EFI_STATUS
EFIAPI
Tcp4GetModeData (
IN CONST EFI_TCP4_PROTOCOL * This,
OUT EFI_TCP4_CONNECTION_STATE * Tcp4State OPTIONAL,
OUT EFI_TCP4_CONFIG_DATA * Tcp4ConfigData OPTIONAL,
OUT EFI_IP4_MODE_DATA * Ip4ModeData OPTIONAL,
OUT EFI_MANAGED_NETWORK_CONFIG_DATA * MnpConfigData OPTIONAL,
OUT EFI_SIMPLE_NETWORK_MODE * SnpModeData OPTIONAL
)
{
TCP4_MODE_DATA TcpMode;
SOCKET *Sock;
if (NULL == This) {
return EFI_INVALID_PARAMETER;
}
Sock = SOCK_FROM_THIS (This);
TcpMode.Tcp4State = Tcp4State;
TcpMode.Tcp4ConfigData = Tcp4ConfigData;
TcpMode.Ip4ModeData = Ip4ModeData;
TcpMode.MnpConfigData = MnpConfigData;
TcpMode.SnpModeData = SnpModeData;
return SockGetMode (Sock, &TcpMode);
}
/**
Initialize or brutally reset the operational parameters for
this EFI TCPv4 instance.
@param This Pointer to the EFI_TCP4_PROTOCOL instance.
@param TcpConfigData Pointer to the configure data to configure the
instance.
@retval EFI_SUCCESS The operational settings are set, changed, or
reset successfully.
@retval EFI_NO_MAPPING When using a default address, configuration
(through DHCP, BOOTP, RARP, etc.) is not
finished.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_ACCESS_DENIED Configuring TCP instance when it is already
configured.
@retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
@retval EFI_UNSUPPORTED One or more of the control options are not
supported in the implementation.
@retval EFI_OUT_OF_RESOURCES Could not allocate enough system resources.
**/
EFI_STATUS
EFIAPI
Tcp4Configure (
IN EFI_TCP4_PROTOCOL * This,
IN EFI_TCP4_CONFIG_DATA * TcpConfigData OPTIONAL
)
{
EFI_TCP4_OPTION *Option;
SOCKET *Sock;
EFI_STATUS Status;
if (NULL == This) {
return EFI_INVALID_PARAMETER;
}
//
// Tcp protocol related parameter check will be conducted here
//
if (NULL != TcpConfigData) {
if ((EFI_IP4 (TcpConfigData->AccessPoint.RemoteAddress) != 0) &&
!Ip4IsUnicast (EFI_NTOHL (TcpConfigData->AccessPoint.RemoteAddress), 0)) {
return EFI_INVALID_PARAMETER;
}
if (!TcpConfigData->AccessPoint.UseDefaultAddress) {
if (!Ip4IsUnicast (EFI_NTOHL (TcpConfigData->AccessPoint.StationAddress), 0) ||
!IP4_IS_VALID_NETMASK (EFI_NTOHL (TcpConfigData->AccessPoint.SubnetMask))
) {
return EFI_INVALID_PARAMETER;
}
}
if (TcpConfigData->AccessPoint.ActiveFlag &&
(0 == TcpConfigData->AccessPoint.RemotePort ||
(EFI_IP4 (TcpConfigData->AccessPoint.RemoteAddress) == 0))
) {
return EFI_INVALID_PARAMETER;
}
Option = TcpConfigData->ControlOption;
if ((NULL != Option) &&
(Option->EnableSelectiveAck || Option->EnablePathMtuDiscovery)) {
return EFI_UNSUPPORTED;
}
}
Sock = SOCK_FROM_THIS (This);
if (NULL == TcpConfigData) {
return SockFlush (Sock);
}
Status = SockConfigure (Sock, TcpConfigData);
if (EFI_NO_MAPPING == Status) {
Sock->ConfigureState = SO_NO_MAPPING;
}
return Status;
}
/**
Add or delete routing entries.
@param This Pointer to the EFI_TCP4_PROTOCOL instance.
@param DeleteRoute If TRUE, delete the specified route from routing
table; if FALSE, add the specified route to
routing table.
@param SubnetAddress The destination network.
@param SubnetMask The subnet mask for the destination network.
@param GatewayAddress The gateway address for this route.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance has not been
configured.
@retval EFI_NO_MAPPING When using a default address, configuration
(through DHCP, BOOTP, RARP, etc.) is not
finished.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_OUT_OF_RESOURCES Could not allocate enough resources to add the
entry to the routing table.
@retval EFI_NOT_FOUND This route is not in the routing table.
@retval EFI_ACCESS_DENIED This route is already in the routing table.
@retval EFI_UNSUPPORTED The TCP driver does not support this operation.
**/
EFI_STATUS
EFIAPI
Tcp4Routes (
IN EFI_TCP4_PROTOCOL *This,
IN BOOLEAN DeleteRoute,
IN EFI_IPv4_ADDRESS *SubnetAddress,
IN EFI_IPv4_ADDRESS *SubnetMask,
IN EFI_IPv4_ADDRESS *GatewayAddress
)
{
SOCKET *Sock;
TCP4_ROUTE_INFO RouteInfo;
if (NULL == This) {
return EFI_INVALID_PARAMETER;
}
Sock = SOCK_FROM_THIS (This);
RouteInfo.DeleteRoute = DeleteRoute;
RouteInfo.SubnetAddress = SubnetAddress;
RouteInfo.SubnetMask = SubnetMask;
RouteInfo.GatewayAddress = GatewayAddress;
return SockRoute (Sock, &RouteInfo);
}
/**
Initiate a nonblocking TCP connection request for an active TCP instance.
@param This Pointer to the EFI_TCP4_PROTOCOL instance
@param ConnectionToken Pointer to the connection token to return when
the TCP three way handshake finishes.
@retval EFI_SUCCESS The connection request is successfully
initiated.
@retval EFI_NOT_STARTED This EFI_TCP4_PROTOCOL instance hasn't been
configured.
@retval EFI_ACCESS_DENIED The instance is not configured as an active one
or it is not in Tcp4StateClosed state.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_OUT_OF_RESOURCES The driver can't allocate enough resource to
initiate the active open.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
**/
EFI_STATUS
EFIAPI
Tcp4Connect (
IN EFI_TCP4_PROTOCOL *This,
IN EFI_TCP4_CONNECTION_TOKEN *ConnectionToken
)
{
SOCKET *Sock;
if (NULL == This ||
NULL == ConnectionToken ||
NULL == ConnectionToken->CompletionToken.Event) {
return EFI_INVALID_PARAMETER;
}
Sock = SOCK_FROM_THIS (This);
return SockConnect (Sock, ConnectionToken);
}
/**
Listen on the passive instance to accept an incoming connection request.
@param This Pointer to the EFI_TCP4_PROTOCOL instance
@param ListenToken Pointer to the listen token to return when
operation finishes.
@retval EFI_SUCCESS The listen token has been queued successfully.
@retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been
configured.
@retval EFI_ACCESS_DENIED The instatnce is not a passive one or it is not
in Tcp4StateListen state or a same listen token
has already existed in the listen token queue of
this TCP instance.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_OUT_OF_RESOURCES Could not allocate enough resources to finish
the operation.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
**/
EFI_STATUS
EFIAPI
Tcp4Accept (
IN EFI_TCP4_PROTOCOL *This,
IN EFI_TCP4_LISTEN_TOKEN *ListenToken
)
{
SOCKET *Sock;
if (NULL == This ||
NULL == ListenToken ||
NULL == ListenToken->CompletionToken.Event) {
return EFI_INVALID_PARAMETER;
}
Sock = SOCK_FROM_THIS (This);
return SockAccept (Sock, ListenToken);
}
/**
Queues outgoing data into the transmit queue
@param This Pointer to the EFI_TCP4_PROTOCOL instance
@param Token Pointer to the completion token to queue to the
transmit queue
@retval EFI_SUCCESS The data has been queued for transmission
@retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been
configured.
@retval EFI_NO_MAPPING When using a default address, configuration
(DHCP, BOOTP, RARP, etc.) is not finished yet.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid
@retval EFI_ACCESS_DENIED One or more of the following conditions is TRUE:
* A transmit completion token with the same
Token-> CompletionToken.Event was already in the
transmission queue. * The current instance is in
Tcp4StateClosed state * The current instance is
a passive one and it is in Tcp4StateListen
state. * User has called Close() to disconnect
this connection.
@retval EFI_NOT_READY The completion token could not be queued because
the transmit queue is full.
@retval EFI_OUT_OF_RESOURCES Could not queue the transmit data because of
resource shortage.
@retval EFI_NETWORK_UNREACHABLE There is no route to the destination network or
address.
**/
EFI_STATUS
EFIAPI
Tcp4Transmit (
IN EFI_TCP4_PROTOCOL *This,
IN EFI_TCP4_IO_TOKEN *Token
)
{
SOCKET *Sock;
EFI_STATUS Status;
if (NULL == This ||
NULL == Token ||
NULL == Token->CompletionToken.Event ||
NULL == Token->Packet.TxData ||
0 == Token->Packet.TxData->FragmentCount ||
0 == Token->Packet.TxData->DataLength
) {
return EFI_INVALID_PARAMETER;
}
Status = Tcp4ChkDataBuf (
Token->Packet.TxData->DataLength,
Token->Packet.TxData->FragmentCount,
Token->Packet.TxData->FragmentTable
);
if (EFI_ERROR (Status)) {
return Status;
}
Sock = SOCK_FROM_THIS (This);
return SockSend (Sock, Token);
}
/**
Place an asynchronous receive request into the receiving queue.
@param This Pointer to the EFI_TCP4_PROTOCOL instance.
@param Token Pointer to a token that is associated with the
receive data descriptor.
@retval EFI_SUCCESS The receive completion token was cached
@retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been
configured.
@retval EFI_NO_MAPPING When using a default address, configuration
(DHCP, BOOTP, RARP, etc.) is not finished yet.
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
@retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued
due to a lack of system resources.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
@retval EFI_ACCESS_DENIED One or more of the following conditions is TRUE:
* A receive completion token with the same
Token->CompletionToken.Event was already in the
receive queue. * The current instance is in
Tcp4StateClosed state. * The current instance is
a passive one and it is in Tcp4StateListen
state. * User has called Close() to disconnect
this connection.
@retval EFI_CONNECTION_FIN The communication peer has closed the connection
and there is no any buffered data in the receive
buffer of this instance.
@retval EFI_NOT_READY The receive request could not be queued because
the receive queue is full.
**/
EFI_STATUS
EFIAPI
Tcp4Receive (
IN EFI_TCP4_PROTOCOL *This,
IN EFI_TCP4_IO_TOKEN *Token
)
{
SOCKET *Sock;
EFI_STATUS Status;
if (NULL == This ||
NULL == Token ||
NULL == Token->CompletionToken.Event ||
NULL == Token->Packet.RxData ||
0 == Token->Packet.RxData->FragmentCount ||
0 == Token->Packet.RxData->DataLength
) {
return EFI_INVALID_PARAMETER;
}
Status = Tcp4ChkDataBuf (
Token->Packet.RxData->DataLength,
Token->Packet.RxData->FragmentCount,
Token->Packet.RxData->FragmentTable
);
if (EFI_ERROR (Status)) {
return Status;
}
Sock = SOCK_FROM_THIS (This);
return SockRcv (Sock, Token);
}
/**
Disconnecting a TCP connection gracefully or reset a TCP connection.
@param This Pointer to the EFI_TCP4_PROTOCOL instance
@param CloseToken Pointer to the close token to return when
operation finishes.
@retval EFI_SUCCESS The operation completed successfully
@retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been
configured.
@retval EFI_ACCESS_DENIED One or more of the following are TRUE: *
Configure() has been called with TcpConfigData
set to NULL and this function has not returned.
* Previous Close() call on this instance has not
finished.
@retval EFI_INVALID_PARAMETER One ore more parameters are invalid
@retval EFI_OUT_OF_RESOURCES Could not allocate enough resource to finish the
operation
@retval EFI_DEVICE_ERROR Any unexpected and not belonged to above
category error.
**/
EFI_STATUS
EFIAPI
Tcp4Close (
IN EFI_TCP4_PROTOCOL *This,
IN EFI_TCP4_CLOSE_TOKEN *CloseToken
)
{
SOCKET *Sock;
if (NULL == This ||
NULL == CloseToken ||
NULL == CloseToken->CompletionToken.Event) {
return EFI_INVALID_PARAMETER;
}
Sock = SOCK_FROM_THIS (This);
return SockClose (Sock, CloseToken, CloseToken->AbortOnClose);
}
/**
Abort an asynchronous connection, listen, transmission or receive request.
@param This Pointer to the EFI_TCP4_PROTOCOL instance.
@param Token Pointer to a token that has been issued by
Connect(), Accept(), Transmit() or Receive(). If
NULL, all pending tokens issued by above four
functions will be aborted.
@retval EFI_UNSUPPORTED The operation is not supported in current
implementation.
**/
EFI_STATUS
EFIAPI
Tcp4Cancel (
IN EFI_TCP4_PROTOCOL * This,
IN EFI_TCP4_COMPLETION_TOKEN * Token OPTIONAL
)
{
return EFI_UNSUPPORTED;
}
/**
Poll to receive incoming data and transmit outgoing segments.
@param This Pointer to the EFI_TCP4_PROTOCOL instance.
@retval EFI_SUCCESS Incoming or outgoing data was processed.
@retval EFI_INVALID_PARAMETER This is NULL.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
@retval EFI_NOT_READY No incoming or outgoing data was processed.
@retval EFI_TIMEOUT Data was dropped out of the transmission or
receive queue. Consider increasing the polling
rate.
**/
EFI_STATUS
EFIAPI
Tcp4Poll (
IN EFI_TCP4_PROTOCOL *This
)
{
SOCKET *Sock;
EFI_STATUS Status;
if (NULL == This) {
return EFI_INVALID_PARAMETER;
}
Sock = SOCK_FROM_THIS (This);
Status = Sock->ProtoHandler (Sock, SOCK_POLL, NULL);
return Status;
}

View File

@ -0,0 +1,176 @@
/** @file
Copyright (c) 2005 - 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Tcp4Main.h
Abstract:
**/
#ifndef _TCP4_MAIN_H_
#define _TCP4_MAIN_H_
#include "Socket.h"
#include "Tcp4Proto.h"
#include "Tcp4Driver.h"
extern UINT16 mTcp4RandomPort;
//
// Driver Produced Protocol Prototypes
//
//@MT:#include EFI_PROTOCOL_PRODUCER (Tcp4)
#define TCP4_DEBUG_ERROR(PrintArg) NET_DEBUG_ERROR ("Tcp", PrintArg)
#define TCP4_DEBUG_WARN(PrintArg) NET_DEBUG_WARNING ("Tcp", PrintArg)
#define TCP4_DEBUG_TRACE(PrintArg) NET_DEBUG_TRACE ("Tcp", PrintArg)
//
// Function prototype for the Tcp4 socket request handler
//
EFI_STATUS
Tcp4Dispatcher (
IN SOCKET *Sock,
IN SOCK_REQUEST Request,
IN VOID *Data OPTIONAL
);
typedef struct _TCP4_MODE_DATA {
EFI_TCP4_CONNECTION_STATE *Tcp4State;
EFI_TCP4_CONFIG_DATA *Tcp4ConfigData;
EFI_IP4_MODE_DATA *Ip4ModeData;
EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData;
EFI_SIMPLE_NETWORK_MODE *SnpModeData;
} TCP4_MODE_DATA;
typedef struct _TCP4_ROUTE_INFO {
BOOLEAN DeleteRoute;
EFI_IPv4_ADDRESS *SubnetAddress;
EFI_IPv4_ADDRESS *SubnetMask;
EFI_IPv4_ADDRESS *GatewayAddress;
} TCP4_ROUTE_INFO;
//
// Get the mode data of a TCP instance
//
EFI_STATUS
EFIAPI
Tcp4GetModeData (
IN CONST EFI_TCP4_PROTOCOL * This,
OUT EFI_TCP4_CONNECTION_STATE * Tcp4State OPTIONAL,
OUT EFI_TCP4_CONFIG_DATA * Tcp4ConfigData OPTIONAL,
OUT EFI_IP4_MODE_DATA * Ip4ModeData OPTIONAL,
OUT EFI_MANAGED_NETWORK_CONFIG_DATA * MnpConfigData OPTIONAL,
OUT EFI_SIMPLE_NETWORK_MODE * SnpModeData OPTIONAL
);
//
// Initialize or reset a TCP instance
//
EFI_STATUS
EFIAPI
Tcp4Configure (
IN EFI_TCP4_PROTOCOL * This,
IN EFI_TCP4_CONFIG_DATA * TcpConfigData OPTIONAL
);
//
// Add a route entry to the route table
//
EFI_STATUS
EFIAPI
Tcp4Routes (
IN EFI_TCP4_PROTOCOL *This,
IN BOOLEAN DeleteRoute,
IN EFI_IPv4_ADDRESS *SubnetAddress,
IN EFI_IPv4_ADDRESS *SubnetMask,
IN EFI_IPv4_ADDRESS *GatewayAddress
);
//
// Issue an asynchronous connection establishment
// request to the peer
//
EFI_STATUS
EFIAPI
Tcp4Connect (
IN EFI_TCP4_PROTOCOL *This,
IN EFI_TCP4_CONNECTION_TOKEN *ConnectionToken
);
//
// Issue an asynchronous listent token to accept an
// incoming connection reques
//
EFI_STATUS
EFIAPI
Tcp4Accept (
IN EFI_TCP4_PROTOCOL *This,
IN EFI_TCP4_LISTEN_TOKEN *ListenToken
);
//
// Issue an asynchronous IO token to transmit some data
// through this TCP instance
//
EFI_STATUS
EFIAPI
Tcp4Transmit (
IN EFI_TCP4_PROTOCOL *This,
IN EFI_TCP4_IO_TOKEN *Token
);
//
// Issue an asynchronous IO token to receive some data
// through this TCP instance
//
EFI_STATUS
Tcp4Receive (
IN EFI_TCP4_PROTOCOL *This,
IN EFI_TCP4_IO_TOKEN *Token
);
//
// Issue an asynchronous CloseToken to close a TCP
// connection represented by instance
//
EFI_STATUS
EFIAPI
Tcp4Close (
IN EFI_TCP4_PROTOCOL *This,
IN EFI_TCP4_CLOSE_TOKEN *CloseToken
);
//
// cancle an connect, listent or IO token
//
EFI_STATUS
EFIAPI
Tcp4Cancel (
IN EFI_TCP4_PROTOCOL * This,
IN EFI_TCP4_COMPLETION_TOKEN * Token OPTIONAL
);
//
// poll data from NIC for receive
//
EFI_STATUS
EFIAPI
Tcp4Poll (
IN EFI_TCP4_PROTOCOL *This
);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,380 @@
/** @file
Copyright (c) 2005 - 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Tcp4Option.c
Abstract:
Routines to process TCP option.
**/
#include "Tcp4Main.h"
STATIC
UINT16
TcpGetUint16 (
IN UINT8 *Buf
)
{
UINT16 Value;
NetCopyMem (&Value, Buf, sizeof (UINT16));
return NTOHS (Value);
}
STATIC
VOID
TcpPutUint16 (
IN UINT8 *Buf,
IN UINT16 Data
)
{
Data = HTONS (Data);
NetCopyMem (Buf, &Data, sizeof (UINT16));
}
STATIC
UINT32
TcpGetUint32 (
IN UINT8 *Buf
)
{
UINT32 Value;
NetCopyMem (&Value, Buf, sizeof (UINT32));
return NTOHL (Value);
}
STATIC
VOID
TcpPutUint32 (
IN UINT8 *Buf,
IN UINT32 Data
)
{
Data = HTONL (Data);
NetCopyMem (Buf, &Data, sizeof (UINT32));
}
/**
Compute the window scale value according to the given
buffer size.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@retval UINT8 The scale value.
**/
UINT8
TcpComputeScale (
IN TCP_CB *Tcb
)
{
UINT8 Scale;
UINT32 BufSize;
ASSERT (Tcb && Tcb->Sk);
BufSize = GET_RCV_BUFFSIZE (Tcb->Sk);
Scale = 0;
while ((Scale < TCP_OPTION_MAX_WS) &&
((UINT32) (TCP_OPTION_MAX_WIN << Scale) < BufSize)) {
Scale++;
}
return Scale;
}
/**
Build the TCP option in three-way handshake.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Nbuf Pointer to the buffer to store the options.
@return The total length of the TCP option field.
**/
UINT16
TcpSynBuildOption (
IN TCP_CB *Tcb,
IN NET_BUF *Nbuf
)
{
char *Data;
UINT16 Len;
ASSERT (Tcb && Nbuf && !Nbuf->Tcp);
Len = 0;
//
// Add timestamp option if not disabled by application
// and it is the first SYN segment or the peer has sent
// us its timestamp.
//
if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_TS) &&
(!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_ACK) ||
TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_TS))) {
Data = NetbufAllocSpace (
Nbuf,
TCP_OPTION_TS_ALIGNED_LEN,
NET_BUF_HEAD
);
ASSERT (Data);
Len += TCP_OPTION_TS_ALIGNED_LEN;
TcpPutUint32 (Data, TCP_OPTION_TS_FAST);
TcpPutUint32 (Data + 4, mTcpTick);
TcpPutUint32 (Data + 8, 0);
}
//
// Build window scale option, only when are configured
// to send WS option, and either we are doing active
// open or we have received WS option from peer.
//
if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_WS) &&
(!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_ACK) ||
TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RCVD_WS))) {
Data = NetbufAllocSpace (
Nbuf,
TCP_OPTION_WS_ALIGNED_LEN,
NET_BUF_HEAD
);
ASSERT (Data);
Len += TCP_OPTION_WS_ALIGNED_LEN;
TcpPutUint32 (Data, TCP_OPTION_WS_FAST | TcpComputeScale (Tcb));
}
//
// Build MSS option
//
Data = NetbufAllocSpace (Nbuf, TCP_OPTION_MSS_LEN, 1);
ASSERT (Data);
Len += TCP_OPTION_MSS_LEN;
TcpPutUint32 (Data, TCP_OPTION_MSS_FAST | Tcb->RcvMss);
return Len;
}
/**
Build the TCP option in synchronized states.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Nbuf Pointer to the buffer to store the options.
@return The total length of the TCP option field.
**/
UINT16
TcpBuildOption (
IN TCP_CB *Tcb,
IN NET_BUF *Nbuf
)
{
char *Data;
UINT16 Len;
ASSERT (Tcb && Nbuf && !Nbuf->Tcp);
Len = 0;
//
// Build Timestamp option
//
if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_SND_TS) &&
!TCP_FLG_ON (TCPSEG_NETBUF (Nbuf)->Flag, TCP_FLG_RST)) {
Data = NetbufAllocSpace (
Nbuf,
TCP_OPTION_TS_ALIGNED_LEN,
NET_BUF_HEAD
);
ASSERT (Data);
Len += TCP_OPTION_TS_ALIGNED_LEN;
TcpPutUint32 (Data, TCP_OPTION_TS_FAST);
TcpPutUint32 (Data + 4, mTcpTick);
TcpPutUint32 (Data + 8, Tcb->TsRecent);
}
return Len;
}
/**
Parse the supported options.
@param Tcp Pointer to the TCP_CB of this TCP instance.
@param Option Pointer to the TCP_OPTION used to store the successfully pasrsed
options.
@retval 0 The options are successfully pasrsed.
@retval -1 Ilegal option was found.
**/
INTN
TcpParseOption (
IN TCP_HEAD *Tcp,
IN TCP_OPTION *Option
)
{
UINT8 *Head;
UINT8 TotalLen;
UINT8 Cur;
UINT8 Type;
UINT8 Len;
ASSERT (Tcp && Option);
Option->Flag = 0;
TotalLen = (Tcp->HeadLen << 2) - sizeof (TCP_HEAD);
if (TotalLen <= 0) {
return 0;
}
Head = (UINT8 *) (Tcp + 1);
//
// Fast process of timestamp option
//
if ((TotalLen == TCP_OPTION_TS_ALIGNED_LEN) &&
(TcpGetUint32 (Head) == TCP_OPTION_TS_FAST)) {
Option->TSVal = TcpGetUint32 (Head + 4);
Option->TSEcr = TcpGetUint32 (Head + 8);
Option->Flag = TCP_OPTION_RCVD_TS;
return 0;
}
//
// Slow path to process the options.
//
Cur = 0;
while (Cur < TotalLen) {
Type = Head[Cur];
switch (Type) {
case TCP_OPTION_MSS:
Len = Head[Cur + 1];
if ((Len != TCP_OPTION_MSS_LEN) ||
(TotalLen - Cur < TCP_OPTION_MSS_LEN)) {
return -1;
}
Option->Mss = TcpGetUint16 (&Head[Cur + 2]);
TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_MSS);
Cur += TCP_OPTION_MSS_LEN;
break;
case TCP_OPTION_WS:
Len = Head[Cur + 1];
if ((Len != TCP_OPTION_WS_LEN) ||
(TotalLen - Cur < TCP_OPTION_WS_LEN)) {
return -1;
}
Option->WndScale = NET_MIN (14, Head[Cur + 2]);
TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_WS);
Cur += TCP_OPTION_WS_LEN;
break;
case TCP_OPTION_TS:
Len = Head[Cur + 1];
if ((Len != TCP_OPTION_TS_LEN) ||
(TotalLen - Cur < TCP_OPTION_TS_LEN)) {
return -1;
}
Option->TSVal = TcpGetUint32 (&Head[Cur + 2]);
Option->TSEcr = TcpGetUint32 (&Head[Cur + 6]);
TCP_SET_FLG (Option->Flag, TCP_OPTION_RCVD_TS);
Cur += TCP_OPTION_TS_LEN;
break;
case TCP_OPTION_NOP:
Cur++;
break;
case TCP_OPTION_EOP:
Cur = TotalLen;
break;
default:
Len = Head[Cur + 1];
if (TotalLen - Cur < Len || Len < 2) {
return -1;
}
Cur = Cur + Len;
break;
}
}
return 0;
}
/**
Check the segment against PAWS.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param TSVal The timestamp value.
@retval 1 The segment passed the PAWS check.
@retval 0 The segment failed to pass the PAWS check.
**/
UINT32
TcpPawsOK (
IN TCP_CB *Tcb,
IN UINT32 TSVal
)
{
//
// PAWS as defined in RFC1323, buggy...
//
if (TCP_TIME_LT (TSVal, Tcb->TsRecent) &&
TCP_TIME_LT (Tcb->TsRecentAge + TCP_PAWS_24DAY, mTcpTick)) {
return 0;
}
return 1;
}

View File

@ -0,0 +1,107 @@
/** @file
Copyright (c) 2005 - 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Tcp4Option.h
Abstract:
**/
#ifndef _TCP4_OPTION_H_
#define _TCP4_OPTION_H_
//
// The structure to store the parse option value.
// ParseOption only parse the options, don't process them.
//
typedef struct s_TCP_OPTION {
UINT8 Flag; // flag such as TCP_OPTION_RCVD_MSS
UINT8 WndScale; // the WndScale received
UINT16 Mss; // the Mss received
UINT32 TSVal; // the TSVal field in a timestamp option
UINT32 TSEcr; // the TSEcr field in a timestamp option
} TCP_OPTION;
enum {
//
// supported TCP option type and their length
//
TCP_OPTION_EOP = 0, // End Of oPtion
TCP_OPTION_NOP = 1, // No-Option.
TCP_OPTION_MSS = 2, // Maximum Segment Size
TCP_OPTION_WS = 3, // Window scale
TCP_OPTION_TS = 8, // Timestamp
TCP_OPTION_MSS_LEN = 4, // length of MSS option
TCP_OPTION_WS_LEN = 3, // length of window scale option
TCP_OPTION_TS_LEN = 10, // length of timestamp option
TCP_OPTION_WS_ALIGNED_LEN = 4, // length of window scale option, aligned
TCP_OPTION_TS_ALIGNED_LEN = 12, // length of timestamp option, aligned
//
// recommend format of timestamp window scale
// option for fast process.
//
TCP_OPTION_TS_FAST = ((TCP_OPTION_NOP << 24) |
(TCP_OPTION_NOP << 16) |
(TCP_OPTION_TS << 8) |
TCP_OPTION_TS_LEN),
TCP_OPTION_WS_FAST = ((TCP_OPTION_NOP << 24) |
(TCP_OPTION_WS << 16) |
(TCP_OPTION_WS_LEN << 8)),
TCP_OPTION_MSS_FAST = ((TCP_OPTION_MSS << 24) |
(TCP_OPTION_MSS_LEN << 16)),
//
// Other misc definations
//
TCP_OPTION_MAX_WS = 14, // Maxium window scale value
TCP_OPTION_MAX_WIN = 0xffff, // max window size in TCP header
TCP_OPTION_RCVD_MSS = 0x01,
TCP_OPTION_RCVD_WS = 0x02,
TCP_OPTION_RCVD_TS = 0x04,
};
UINT8
TcpComputeScale (
IN TCP_CB *Tcb
);
UINT16
TcpSynBuildOption (
IN TCP_CB *Tcb,
IN NET_BUF *Buf
);
UINT16
TcpBuildOption (
IN TCP_CB *Tcb,
IN NET_BUF *Buf
);
INTN
TcpParseOption (
IN TCP_HEAD *Tcp,
IN TCP_OPTION *Option
);
UINT32
TcpPawsOK (
IN TCP_CB *Tcb,
IN UINT32 TSVal
);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,355 @@
/** @file
Copyright (c) 2005 - 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Tcp4Proto.h
Abstract:
**/
#ifndef _TCP4_PROTO_H_
#define _TCP4_PROTO_H_
typedef struct _TCP_CB TCP_CB;
#include "Tcp4Driver.h"
#include "Socket.h"
#include "Tcp4Option.h"
//
// tcp states, Don't change their order, it is used as
// index to mTcpOutFlag and other macros
//
enum {
TCP_CLOSED = 0,
TCP_LISTEN,
TCP_SYN_SENT,
TCP_SYN_RCVD,
TCP_ESTABLISHED,
TCP_FIN_WAIT_1,
TCP_FIN_WAIT_2,
TCP_CLOSING,
TCP_TIME_WAIT,
TCP_CLOSE_WAIT,
TCP_LAST_ACK,
};
//
// flags in the TCP header
//
enum {
TCP_FLG_FIN = 0x01,
TCP_FLG_SYN = 0x02,
TCP_FLG_RST = 0x04,
TCP_FLG_PSH = 0x08,
TCP_FLG_ACK = 0x10,
TCP_FLG_URG = 0x20,
TCP_FLG_FLAG = 0x3F, // mask for all the flags
};
enum {
//
// TCP error status
//
TCP_CONNECT_REFUSED = -1,
TCP_CONNECT_RESET = -2,
TCP_CONNECT_CLOSED = -3,
//
// Current congestion status as suggested by RFC3782.
//
TCP_CONGEST_RECOVER = 1, // during the NewReno fast recovery
TCP_CONGEST_LOSS = 2, // retxmit because of retxmit time out
TCP_CONGEST_OPEN = 3, // TCP is opening its congestion window
//
// TCP control flags
//
TCP_CTRL_NO_NAGLE = 0x0001, // disable Nagle algorithm
TCP_CTRL_NO_KEEPALIVE = 0x0002, // disable keepalive timer
TCP_CTRL_NO_WS = 0x0004, // disable window scale option
TCP_CTRL_RCVD_WS = 0x0008, // rcvd a wnd scale option in syn
TCP_CTRL_NO_TS = 0x0010, // disable Timestamp option
TCP_CTRL_RCVD_TS = 0x0020, // rcvd a Timestamp option in syn
TCP_CTRL_SND_TS = 0x0040, // Send Timestamp option to remote
TCP_CTRL_SND_URG = 0x0080, // in urgent send mode
TCP_CTRL_RCVD_URG = 0x0100, // in urgent receive mode
TCP_CTRL_SND_PSH = 0x0200, // in PUSH send mode
TCP_CTRL_FIN_SENT = 0x0400, // FIN is sent
TCP_CTRL_FIN_ACKED = 0x0800, // FIN is ACKed.
TCP_CTRL_TIMER_ON = 0x1000, // At least one of the timer is on
TCP_CTRL_RTT_ON = 0x2000, // The RTT measurement is on
TCP_CTRL_ACK_NOW = 0x4000, // Send the ACK now, don't delay
//
// Timer related values
//
TCP_TIMER_CONNECT = 0, // Connection establishment timer
TCP_TIMER_REXMIT = 1, // retransmit timer
TCP_TIMER_PROBE = 2, // Window probe timer
TCP_TIMER_KEEPALIVE = 3, // Keepalive timer
TCP_TIMER_FINWAIT2 = 4, // FIN_WAIT_2 timer
TCP_TIMER_2MSL = 5, // TIME_WAIT tiemr
TCP_TIMER_NUMBER = 6, // the total number of TCP timer.
TCP_TICK = 200, // every TCP tick is 200ms
TCP_TICK_HZ = 5, // the frequence of TCP tick
TCP_RTT_SHIFT = 3, // SRTT & RTTVAR scaled by 8
TCP_RTO_MIN = TCP_TICK_HZ, // the minium value of RTO
TCP_RTO_MAX = TCP_TICK_HZ *60, // the maxium value of RTO
TCP_FOLD_RTT = 4, // timeout threshod to fold RTT
//
// default values for some timers
//
TCP_MAX_LOSS = 12, // default max times to retxmit
TCP_KEEPALIVE_IDLE_MIN = TCP_TICK_HZ *60 *60 *2, // First keep alive
TCP_KEEPALIVE_PERIOD = TCP_TICK_HZ *60,
TCP_MAX_KEEPALIVE = 8,
TCP_FIN_WAIT2_TIME = 2 *TCP_TICK_HZ, // * 60,
TCP_TIME_WAIT_TIME = 2 *TCP_TICK_HZ,
TCP_PAWS_24DAY = 24 *24 *60 *60 *TCP_TICK_HZ,
TCP_CONNECT_TIME = 75 *TCP_TICK_HZ,
//
// The header space to be reserved before TCP data to accomodate :
// 60byte IP head + 60byte TCP head + link layer head
//
TCP_MAX_HEAD = 192,
//
// value ranges for some control option
//
TCP_RCV_BUF_SIZE = 2 *1024 *1024,
TCP_RCV_BUF_SIZE_MIN = 8 *1024,
TCP_SND_BUF_SIZE = 2 *1024 *1024,
TCP_SND_BUF_SIZE_MIN = 8 *1024,
TCP_BACKLOG = 10,
TCP_BACKLOG_MIN = 5,
TCP_MAX_LOSS_MIN = 6,
TCP_CONNECT_TIME_MIN = 60 *TCP_TICK_HZ,
TCP_MAX_KEEPALIVE_MIN = 4,
TCP_KEEPALIVE_IDLE_MAX = TCP_TICK_HZ *60 *60 *4,
TCP_KEEPALIVE_PERIOD_MIN= TCP_TICK_HZ *30,
TCP_FIN_WAIT2_TIME_MAX = 4 *TCP_TICK_HZ,
TCP_TIME_WAIT_TIME_MAX = 60 *TCP_TICK_HZ,
};
typedef struct _TCP_SEG {
TCP_SEQNO Seq; // Starting sequence number
TCP_SEQNO End; // The sequence of the last byte + 1,
// include SYN/FIN. End-Seq = SEG.LEN
TCP_SEQNO Ack; // ACK fild in the segment
UINT8 Flag; // TCP header flags
UINT16 Urg; // Valid if URG flag is set.
UINT32 Wnd; // TCP window size field
} TCP_SEG;
typedef struct _TCP_PEER {
UINT32 Ip; // Network byte order
TCP_PORTNO Port; // Network byte order
} TCP_PEER;
//
// tcp control block, it includes various states
//
typedef struct _TCP_CB {
NET_LIST_ENTRY List;
TCP_CB *Parent;
SOCKET *Sk;
TCP_PEER LocalEnd;
TCP_PEER RemoteEnd;
NET_LIST_ENTRY SndQue; // retxmission queue
NET_LIST_ENTRY RcvQue; // reassemble queue
UINT32 CtrlFlag; // control flags, such as NO_NAGLE
INT32 Error; // soft error status,TCP_CONNECT_RESET...
//
// RFC793 and RFC1122 defined variables
//
UINT8 State; // TCP state, such as SYN_SENT, LISTEN
UINT8 DelayedAck; // number of delayed ACKs
UINT16 HeadSum; // checksum of the fixed parts of pesudo
// header: Src IP, Dst IP, 0, Protocol,
// not include the TCP length.
TCP_SEQNO Iss; // Initial Sending Sequence
TCP_SEQNO SndUna; // first unacknowledged data
TCP_SEQNO SndNxt; // next data sequence to send.
TCP_SEQNO SndPsh; // Send PUSH point
TCP_SEQNO SndUp; // Send urgent point
UINT32 SndWnd; // Window advertised by the remote peer
UINT32 SndWndMax; // max send window advertised by the peer
TCP_SEQNO SndWl1; // Seq number used for last window update
TCP_SEQNO SndWl2; // ack no of last window update
UINT16 SndMss; // Max send segment size
TCP_SEQNO RcvNxt; // Next sequence no to receive
UINT32 RcvWnd; // Window advertised by the local peer
TCP_SEQNO RcvWl2; // The RcvNxt (or ACK) of last window update.
// It is necessary because of delayed ACK
TCP_SEQNO RcvUp; // urgent point;
TCP_SEQNO Irs; // Initial Receiving Sequence
UINT16 RcvMss; // Max receive segment size
UINT16 EnabledTimer; // which timer is currently enabled
UINT32 Timer[TCP_TIMER_NUMBER]; // when the timer will expire
INT32 NextExpire; // count down offset for the nearest timer
UINT32 Idle; // How long the connection is in idle
UINT32 ProbeTime; // the time out value for current window prober
//
// RFC1323 defined variables, about window scale,
// timestamp and PAWS
//
UINT8 SndWndScale; // Wndscale received from the peer
UINT8 RcvWndScale; // Wndscale used to scale local buffer
UINT32 TsRecent; // TsRecent to echo to the remote peer
UINT32 TsRecentAge; // When this TsRecent is updated
// TCP_SEQNO LastAckSent;
// It isn't necessary to add LastAckSent here,
// since it is the same as RcvWl2
//
// RFC2988 defined variables. about RTT measurement
//
TCP_SEQNO RttSeq; // the seq of measured segment now
UINT32 RttMeasure; // currently measured RTT in heart beats
UINT32 SRtt; // Smoothed RTT, scaled by 8
UINT32 RttVar; // RTT variance, scaled by 8
UINT32 Rto; // Current RTO, not scaled
//
// RFC2581, and 3782 variables.
// Congestion control + NewReno fast recovery.
//
UINT32 CWnd; // Sender's congestion window
UINT32 Ssthresh; // Slow start threshold.
TCP_SEQNO Recover; // recover point for NewReno
UINT16 DupAck; // number of duplicate ACKs
UINT8 CongestState; // the current congestion state(RFC3782)
UINT8 LossTimes; // number of retxmit timeouts in a row
TCP_SEQNO LossRecover; // recover point for retxmit
//
// configuration parameters, for EFI_TCP4_PROTOCOL specification
//
UINT32 KeepAliveIdle; // idle time before sending first probe
UINT32 KeepAlivePeriod; // interval for subsequent keep alive probe
UINT8 MaxKeepAlive; // Maxium keep alive probe times.
UINT8 KeepAliveProbes; // the number of keep alive probe.
UINT16 MaxRexmit; // The maxium number of retxmit before abort
UINT32 FinWait2Timeout; // The FIN_WAIT_2 time out
UINT32 TimeWaitTimeout; // The TIME_WAIT time out
UINT32 ConnectTimeout;
//
// configuration for tcp provided by user
//
BOOLEAN UseDefaultAddr;
UINT8 TOS;
UINT8 TTL;
EFI_IPv4_ADDRESS SubnetMask;
//
// pointer reference to Ip used to send pkt
//
IP_IO_IP_INFO *IpInfo;
} TCP_CB;
extern NET_LIST_ENTRY mTcpRunQue;
extern NET_LIST_ENTRY mTcpListenQue;
extern TCP_SEQNO mTcpGlobalIss;
extern UINT32 mTcpTick;
//
// TCP_CONNECTED: both ends have synchronized their ISN.
//
#define TCP_CONNECTED(state) ((state) > TCP_SYN_RCVD)
#define TCP_FIN_RCVD(State) \
(((State) == TCP_CLOSE_WAIT) || \
((State) == TCP_LAST_ACK) || \
((State) == TCP_CLOSING) || \
((State) == TCP_TIME_WAIT))
#define TCP_LOCAL_CLOSED(State) \
(((State) == TCP_FIN_WAIT_1) || \
((State) == TCP_FIN_WAIT_2) || \
((State) == TCP_CLOSING) || \
((State) == TCP_TIME_WAIT) || \
((State) == TCP_LAST_ACK))
//
// Get the TCP_SEG point from a net buffer's ProtoData
//
#define TCPSEG_NETBUF(NBuf) ((TCP_SEG *) ((NBuf)->ProtoData))
//
// macros to compare sequence no
//
#define TCP_SEQ_LT(SeqA, SeqB) ((INT32) ((SeqA) - (SeqB)) < 0)
#define TCP_SEQ_LEQ(SeqA, SeqB) ((INT32) ((SeqA) - (SeqB)) <= 0)
#define TCP_SEQ_GT(SeqA, SeqB) ((INT32) ((SeqB) - (SeqA)) < 0)
#define TCP_SEQ_GEQ(SeqA, SeqB) ((INT32) ((SeqB) - (SeqA)) <= 0)
//
// TCP_SEQ_BETWEEN return whether b <= m <= e
//
#define TCP_SEQ_BETWEEN(b, m, e) ((e) - (b) >= (m) - (b))
//
// TCP_SUB_SEQ returns Seq1 - Seq2. Make sure Seq1 >= Seq2
//
#define TCP_SUB_SEQ(Seq1, Seq2) ((UINT32) ((Seq1) - (Seq2)))
#define TCP_FLG_ON(Value, Flag) ((BOOLEAN) (((Value) & (Flag)) != 0))
#define TCP_SET_FLG(Value, Flag) ((Value) |= (Flag))
#define TCP_CLEAR_FLG(Value, Flag) ((Value) &= ~(Flag))
//
// test whether two peers are equal
//
#define TCP_PEER_EQUAL(Pa, Pb) \
(((Pa)->Ip == (Pb)->Ip) && ((Pa)->Port == (Pb)->Port))
//
// test whether Pa matches Pb, or Pa is more specific
// than pb. Zero means wildcard.
//
#define TCP_PEER_MATCH(Pa, Pb) \
((((Pb)->Ip == 0) || ((Pb)->Ip == (Pa)->Ip)) && \
(((Pb)->Port == 0) || ((Pb)->Port == (Pa)->Port)))
#define TCP_TIMER_ON(Flag, Timer) ((Flag) & (1 << (Timer)))
#define TCP_SET_TIMER(Flag, Timer) ((Flag) |= (1 << (Timer)))
#define TCP_CLEAR_TIMER(Flag, Timer) ((Flag) &= ~(1 << (Timer)))
#define TCP_TIME_LT(Ta, Tb) ((INT32) ((Ta) - (Tb)) < 0)
#define TCP_TIME_LEQ(Ta, Tb) ((INT32) ((Ta) - (Tb)) <= 0)
#define TCP_SUB_TIME(Ta, Tb) ((UINT32) ((Ta) - (Tb)))
#define TCP_MAX_WIN 0xFFFFU
typedef
VOID
(*TCP_TIMER_HANDLER) (
IN TCP_CB * Tcb
);
#include "Tcp4Func.h"
#endif

View File

@ -0,0 +1,582 @@
/** @file
Copyright (c) 2005 - 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Tcp4Timer.c
Abstract:
TCP timer related functions.
**/
#include "Tcp4Main.h"
UINT32 mTcpTick = 1000;
STATIC
VOID
TcpConnectTimeout (
IN TCP_CB *Tcb
);
STATIC
VOID
TcpRexmitTimeout (
IN TCP_CB *Tcb
);
STATIC
VOID
TcpProbeTimeout (
IN TCP_CB *Tcb
);
STATIC
VOID
TcpKeepaliveTimeout (
IN TCP_CB *Tcb
);
STATIC
VOID
TcpFinwait2Timeout (
IN TCP_CB *Tcb
);
STATIC
VOID
Tcp2MSLTimeout (
IN TCP_CB *Tcb
);
TCP_TIMER_HANDLER mTcpTimerHandler[TCP_TIMER_NUMBER] = {
TcpConnectTimeout,
TcpRexmitTimeout,
TcpProbeTimeout,
TcpKeepaliveTimeout,
TcpFinwait2Timeout,
Tcp2MSLTimeout,
};
/**
Close the TCP connection.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@return None.
**/
VOID
TcpClose (
IN TCP_CB *Tcb
)
{
NetbufFreeList (&Tcb->SndQue);
NetbufFreeList (&Tcb->RcvQue);
TcpSetState (Tcb, TCP_CLOSED);
}
/**
Connect timeout handler.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@return None.
**/
STATIC
VOID
TcpConnectTimeout (
IN TCP_CB *Tcb
)
{
if (!TCP_CONNECTED (Tcb->State)) {
TCP4_DEBUG_ERROR (("TcpConnectTimeout: connection closed "
"because conenction timer timeout for TCB %x\n", Tcb));
if (EFI_ABORTED == Tcb->Sk->SockError) {
SOCK_ERROR (Tcb->Sk, EFI_TIMEOUT);
}
if (TCP_SYN_RCVD == Tcb->State) {
TCP4_DEBUG_WARN (("TcpConnectTimeout: send reset because "
"connection timer timeout for TCB %x\n", Tcb));
TcpResetConnection (Tcb);
}
TcpClose (Tcb);
}
}
/**
Timeout handler for TCP retransmission timer.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@return None.
**/
STATIC
VOID
TcpRexmitTimeout (
IN TCP_CB *Tcb
)
{
UINT32 FlightSize;
TCP4_DEBUG_WARN (("TcpRexmitTimeout: transmission "
"timeout for TCB %x\n", Tcb));
//
// Set the congestion window. FlightSize is the
// amount of data that has been sent but not
// yet ACKed.
//
FlightSize = TCP_SUB_SEQ (Tcb->SndNxt, Tcb->SndUna);
Tcb->Ssthresh = NET_MAX ((UINT32) (2 * Tcb->SndMss), FlightSize / 2);
Tcb->CWnd = Tcb->SndMss;
Tcb->LossRecover = Tcb->SndNxt;
Tcb->LossTimes++;
if (Tcb->LossTimes > Tcb->MaxRexmit &&
!TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_CONNECT)) {
TCP4_DEBUG_ERROR (("TcpRexmitTimeout: connection closed "
"because too many timeouts for TCB %x\n", Tcb));
if (EFI_ABORTED == Tcb->Sk->SockError) {
SOCK_ERROR (Tcb->Sk, EFI_TIMEOUT);
}
TcpClose (Tcb);
return ;
}
TcpBackoffRto (Tcb);
TcpRetransmit (Tcb, Tcb->SndUna);
TcpSetTimer (Tcb, TCP_TIMER_REXMIT, Tcb->Rto);
Tcb->CongestState = TCP_CONGEST_LOSS;
TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_RTT_ON);
}
/**
Timeout handler for window probe timer.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@return None.
**/
STATIC
VOID
TcpProbeTimeout (
IN TCP_CB *Tcb
)
{
//
// This is the timer for sender's SWSA. RFC1122 requires
// a timer set for sender's SWSA, and suggest combine it
// with window probe timer. If data is sent, don't set
// the probe timer, since retransmit timer is on.
//
if ((TcpDataToSend (Tcb, 1) != 0) && (TcpToSendData (Tcb, 1) > 0)) {
ASSERT (TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_REXMIT));
return ;
}
TcpSendZeroProbe (Tcb);
TcpSetProbeTimer (Tcb);
}
/**
Timeout handler for keepalive timer.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@return None.
**/
STATIC
VOID
TcpKeepaliveTimeout (
IN TCP_CB *Tcb
)
{
Tcb->KeepAliveProbes++;
//
// Too many Keep-alive probes, drop the connection
//
if (Tcb->KeepAliveProbes > Tcb->MaxKeepAlive) {
if (EFI_ABORTED == Tcb->Sk->SockError) {
SOCK_ERROR (Tcb->Sk, EFI_TIMEOUT);
}
TcpClose (Tcb);
return ;
}
TcpSendZeroProbe (Tcb);
TcpSetKeepaliveTimer (Tcb);
}
/**
Timeout handler for FIN_WAIT_2 timer.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@return None.
**/
STATIC
VOID
TcpFinwait2Timeout (
IN TCP_CB *Tcb
)
{
TCP4_DEBUG_WARN (("TcpFinwait2Timeout: connection closed "
"because FIN_WAIT2 timer timeouts for TCB %x\n", Tcb));
TcpClose (Tcb);
}
/**
Timeout handler for 2MSL timer.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@return None.
**/
STATIC
VOID
Tcp2MSLTimeout (
IN TCP_CB *Tcb
)
{
TCP4_DEBUG_WARN (("Tcp2MSLTimeout: connection closed "
"because TIME_WAIT timer timeouts for TCB %x\n", Tcb));
TcpClose (Tcb);
}
/**
Update the timer status and the next expire time
according to the timers to expire in a specific
future time slot.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@return None.
**/
STATIC
VOID
TcpUpdateTimer (
IN TCP_CB *Tcb
)
{
UINT16 Index;
//
// Don't use a too large value to init NextExpire
// since mTcpTick wraps around as sequence no does.
//
Tcb->NextExpire = 65535;
TCP_CLEAR_FLG (Tcb->CtrlFlag, TCP_CTRL_TIMER_ON);
for (Index = 0; Index < TCP_TIMER_NUMBER; Index++) {
if (TCP_TIMER_ON (Tcb->EnabledTimer, Index) &&
TCP_TIME_LT (Tcb->Timer[Index], mTcpTick + Tcb->NextExpire)) {
Tcb->NextExpire = TCP_SUB_TIME (Tcb->Timer[Index], mTcpTick);
TCP_SET_FLG (Tcb->CtrlFlag, TCP_CTRL_TIMER_ON);
}
}
}
/**
Enable a TCP timer.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Timer The index of the timer to be enabled.
@param TimeOut The timeout value of this timer.
@return None.
**/
VOID
TcpSetTimer (
IN TCP_CB *Tcb,
IN UINT16 Timer,
IN UINT32 TimeOut
)
{
TCP_SET_TIMER (Tcb->EnabledTimer, Timer);
Tcb->Timer[Timer] = mTcpTick + TimeOut;
TcpUpdateTimer (Tcb);
}
/**
Clear one TCP timer.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@param Timer The index of the timer to be cleared.
@return None.
**/
VOID
TcpClearTimer (
IN TCP_CB *Tcb,
IN UINT16 Timer
)
{
TCP_CLEAR_TIMER (Tcb->EnabledTimer, Timer);
TcpUpdateTimer (Tcb);
}
/**
Clear all TCP timers.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@return None.
**/
VOID
TcpClearAllTimer (
IN TCP_CB *Tcb
)
{
Tcb->EnabledTimer = 0;
TcpUpdateTimer (Tcb);
}
/**
Enable the window prober timer and set the timeout value.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@return None.
**/
VOID
TcpSetProbeTimer (
IN TCP_CB *Tcb
)
{
if (!TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_PROBE)) {
Tcb->ProbeTime = Tcb->Rto;
} else {
Tcb->ProbeTime <<= 1;
}
if (Tcb->ProbeTime < TCP_RTO_MIN) {
Tcb->ProbeTime = TCP_RTO_MIN;
} else if (Tcb->ProbeTime > TCP_RTO_MAX) {
Tcb->ProbeTime = TCP_RTO_MAX;
}
TcpSetTimer (Tcb, TCP_TIMER_PROBE, Tcb->ProbeTime);
}
/**
Enable the keepalive timer and set the timeout value.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@return None.
**/
VOID
TcpSetKeepaliveTimer (
IN TCP_CB *Tcb
)
{
if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_NO_KEEPALIVE)) {
return ;
}
//
// Set the timer to KeepAliveIdle if either
// 1. the keepalive timer is off
// 2. The keepalive timer is on, but the idle
// is less than KeepAliveIdle, that means the
// connection is alive since our last probe.
//
if (!TCP_TIMER_ON (Tcb->EnabledTimer, TCP_TIMER_KEEPALIVE) ||
(Tcb->Idle < Tcb->KeepAliveIdle)) {
TcpSetTimer (Tcb, TCP_TIMER_KEEPALIVE, Tcb->KeepAliveIdle);
Tcb->KeepAliveProbes = 0;
} else {
TcpSetTimer (Tcb, TCP_TIMER_KEEPALIVE, Tcb->KeepAlivePeriod);
}
}
/**
Backoff the RTO.
@param Tcb Pointer to the TCP_CB of this TCP instance.
@return None.
**/
VOID
TcpBackoffRto (
IN TCP_CB *Tcb
)
{
//
// Fold the RTT estimate if too many times, the estimate
// may be wrong, fold it. So the next time a valid
// measurement is sampled, we can start fresh.
//
if ((Tcb->LossTimes >= TCP_FOLD_RTT) && Tcb->SRtt) {
Tcb->RttVar += Tcb->SRtt >> 2;
Tcb->SRtt = 0;
}
Tcb->Rto <<= 1;
if (Tcb->Rto < TCP_RTO_MIN) {
Tcb->Rto = TCP_RTO_MIN;
} else if (Tcb->Rto > TCP_RTO_MAX) {
Tcb->Rto = TCP_RTO_MAX;
}
}
/**
Heart beat timer handler.
@param Event Timer event signaled, ignored.
@param Context Context of the timer event, ignored.
@return None.
**/
VOID
EFIAPI
TcpTicking (
IN EFI_EVENT Event,
IN VOID *Context
)
{
NET_LIST_ENTRY *Entry;
NET_LIST_ENTRY *Next;
TCP_CB *Tcb;
INT16 Index;
mTcpTick++;
mTcpGlobalIss += 100;
//
// Don't use LIST_FOR_EACH, which isn't delete safe.
//
for (Entry = mTcpRunQue.ForwardLink; Entry != &mTcpRunQue; Entry = Next) {
Next = Entry->ForwardLink;
Tcb = NET_LIST_USER_STRUCT (Entry, TCP_CB, List);
if (Tcb->State == TCP_CLOSED) {
continue;
}
//
// The connection is doing RTT measurement.
//
if (TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_RTT_ON)) {
Tcb->RttMeasure++;
}
Tcb->Idle++;
if (Tcb->DelayedAck) {
TcpSendAck (Tcb);
}
//
// No timer is active or no timer expired
//
if (!TCP_FLG_ON (Tcb->CtrlFlag, TCP_CTRL_TIMER_ON) ||
((--Tcb->NextExpire) > 0)) {
continue;
}
//
// Call the timeout handler for each expired timer.
//
for (Index = 0; Index < TCP_TIMER_NUMBER; Index++) {
if (TCP_TIMER_ON (Tcb->EnabledTimer, Index) &&
TCP_TIME_LEQ (Tcb->Timer[Index], mTcpTick)) {
//
// disable the timer before calling the handler
// in case the handler enables it again.
//
TCP_CLEAR_TIMER (Tcb->EnabledTimer, Index);
mTcpTimerHandler[Index](Tcb);
//
// The Tcb may have been deleted by the timer, or
// no other timer is set.
//
if ((Next->BackLink != Entry) ||
(Tcb->EnabledTimer == 0)) {
goto NextConnection;
}
}
}
TcpUpdateTimer (Tcb);
NextConnection:
;
}
}

View File

@ -0,0 +1,169 @@
/** @file
Copyright (c) 2006 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
ComponentName.c
Abstract:
**/
#include "Udp4Impl.h"
//
// EFI Component Name Functions
//
EFI_STATUS
EFIAPI
UdpComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
);
EFI_STATUS
EFIAPI
UdpComponentNameGetControllerName (
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
//
EFI_COMPONENT_NAME_PROTOCOL gUdp4ComponentName = {
UdpComponentNameGetDriverName,
UdpComponentNameGetControllerName,
"eng"
};
static EFI_UNICODE_STRING_TABLE mUdpDriverNameTable[] = {
{
"eng",
L"UDP Network Service Driver"
},
{
NULL,
NULL
}
};
EFI_STATUS
EFIAPI
UdpComponentNameGetDriverName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN CHAR8 *Language,
OUT CHAR16 **DriverName
)
/*++
Routine Description:
Retrieves a Unicode string that is the user readable name of the EFI Driver.
Arguments:
This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
Language - A pointer to a three character ISO 639-2 language identifier.
This is the language of the driver name that 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.
DriverName - A pointer to the Unicode string to return. This Unicode string
is the name of the driver specified by This in the language
specified by Language.
Returns:
EFI_SUCCES - The Unicode string for the Driver specified by This
and the language specified by Language was returned
in DriverName.
EFI_INVALID_PARAMETER - Language is NULL.
EFI_INVALID_PARAMETER - DriverName is NULL.
EFI_UNSUPPORTED - The driver specified by This does not support the
language specified by Language.
--*/
{
return LookupUnicodeString (
Language,
gUdp4ComponentName.SupportedLanguages,
mUdpDriverNameTable,
DriverName
);
}
EFI_STATUS
EFIAPI
UdpComponentNameGetControllerName (
IN EFI_COMPONENT_NAME_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_HANDLE ChildHandle OPTIONAL,
IN CHAR8 *Language,
OUT CHAR16 **ControllerName
)
/*++
Routine Description:
Retrieves a Unicode string that is the user readable name of the controller
that is being managed by an EFI Driver.
Arguments:
This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
ControllerHandle - The handle of a controller that the driver specified by
This is managing. This handle specifies the controller
whose name is to be returned.
ChildHandle - The handle of the child controller to retrieve the name
of. This is an optional parameter that may be NULL. It
will be NULL for device drivers. It will also be NULL
for a bus drivers that wish to retrieve the name of the
bus controller. It will not be NULL for a bus driver
that wishes to retrieve the name of a child controller.
Language - A pointer to a three character ISO 639-2 language
identifier. This is the language of the controller name
that 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.
ControllerName - A pointer to the Unicode string to return. This Unicode
string is the name of the controller specified by
ControllerHandle and ChildHandle in the language specified
by Language from the point of view of the driver specified
by This.
Returns:
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.
EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.
EFI_INVALID_PARAMETER - Language is NULL.
EFI_INVALID_PARAMETER - ControllerName is NULL.
EFI_UNSUPPORTED - The driver specified by This is not currently managing
the controller specified by ControllerHandle and
ChildHandle.
EFI_UNSUPPORTED - The driver specified by This does not support the
language specified by Language.
--*/
{
return EFI_UNSUPPORTED;
}

View File

@ -0,0 +1,526 @@
/** @file
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Udp4Driver.c
Abstract:
**/
#include "Udp4Impl.h"
EFI_DRIVER_BINDING_PROTOCOL gUdp4DriverBinding = {
Udp4DriverBindingSupported,
Udp4DriverBindingStart,
Udp4DriverBindingStop,
0xa,
NULL,
NULL
};
EFI_SERVICE_BINDING_PROTOCOL mUdp4ServiceBinding = {
Udp4ServiceBindingCreateChild,
Udp4ServiceBindingDestroyChild
};
/**
Test to see if this driver supports ControllerHandle.
@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_SUCCES This driver supports this device.
@retval EFI_ALREADY_STARTED This driver is already running on this device.
**/
EFI_STATUS
EFIAPI
Udp4DriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
)
{
EFI_STATUS Status;
//
// Test for the Udp4ServiceBinding Protocol
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiUdp4ServiceBindingProtocolGuid,
NULL,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
if (!EFI_ERROR (Status)) {
return EFI_ALREADY_STARTED;
}
//
// Test for the Ip4 Protocol
//
Status = gBS->OpenProtocol (
ControllerHandle,
&gEfiIp4ServiceBindingProtocolGuid,
NULL,
This->DriverBindingHandle,
ControllerHandle,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
return Status;
}
/**
Start this driver on ControllerHandle.
@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_SUCCES This driver is added to ControllerHandle
@retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
@retval other This driver does not support this device
**/
EFI_STATUS
EFIAPI
Udp4DriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
)
{
EFI_STATUS Status;
UDP4_SERVICE_DATA *Udp4Service;
//
// Allocate Private Context Data Structure.
//
Udp4Service = NetAllocatePool (sizeof (UDP4_SERVICE_DATA));
if (Udp4Service == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = Udp4CreateService (Udp4Service, This->DriverBindingHandle, ControllerHandle);
if (EFI_ERROR (Status)) {
goto FREE_SERVICE;
}
//
// Install the Udp4ServiceBindingProtocol on the ControllerHandle.
//
Status = gBS->InstallMultipleProtocolInterfaces (
&ControllerHandle,
&gEfiUdp4ServiceBindingProtocolGuid,
&Udp4Service->ServiceBinding,
NULL
);
if (EFI_ERROR (Status)) {
goto CLEAN_SERVICE;
}
Udp4SetVariableData (Udp4Service);
return Status;
CLEAN_SERVICE:
Udp4CleanService (Udp4Service);
FREE_SERVICE:
NetFreePool (Udp4Service);
return Status;
}
/**
Stop this driver on ControllerHandle.
@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_SUCCES This driver is removed ControllerHandle.
@retval other This driver was not removed from this device.
**/
EFI_STATUS
EFIAPI
Udp4DriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
)
{
EFI_STATUS Status;
EFI_HANDLE NicHandle;
EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
UDP4_SERVICE_DATA *Udp4Service;
UDP4_INSTANCE_DATA *Instance;
//
// Find the NicHandle where UDP4 ServiceBinding Protocol is installed.
//
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp4ProtocolGuid);
if (NicHandle == NULL) {
return EFI_SUCCESS;
}
//
// Retrieve the UDP4 ServiceBinding Protocol.
//
Status = gBS->OpenProtocol (
NicHandle,
&gEfiUdp4ServiceBindingProtocolGuid,
(VOID **) &ServiceBinding,
This->DriverBindingHandle,
NicHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
Udp4Service = UDP4_SERVICE_DATA_FROM_THIS (ServiceBinding);
//
// Uninstall the UDP4 ServiceBinding Protocol.
//
Status = gBS->UninstallMultipleProtocolInterfaces (
NicHandle,
&gEfiUdp4ServiceBindingProtocolGuid,
&Udp4Service->ServiceBinding,
NULL
);
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
while (!NetListIsEmpty (&Udp4Service->ChildrenList)) {
//
// Destroy all instances.
//
Instance = NET_LIST_HEAD (&Udp4Service->ChildrenList, UDP4_INSTANCE_DATA, Link);
ServiceBinding->DestroyChild (ServiceBinding, Instance->ChildHandle);
}
Udp4ClearVariableData (Udp4Service);
Udp4CleanService (Udp4Service);
NetFreePool (Udp4Service);
return EFI_SUCCESS;
}
/**
Creates a child handle with a set of I/O services.
@param This Protocol instance pointer.
@param ChildHandle Pointer to the handle of the child to create. If
it is NULL, then a new handle is created. If it
is not NULL, then the I/O services are added to
the existing child handle.
@retval EFI_SUCCES The child handle was created with the I/O services
@retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
the child
@retval other The child handle was not created
**/
EFI_STATUS
EFIAPI
Udp4ServiceBindingCreateChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN EFI_HANDLE *ChildHandle
)
{
EFI_STATUS Status;
UDP4_SERVICE_DATA *Udp4Service;
UDP4_INSTANCE_DATA *Instance;
EFI_TPL OldTpl;
VOID *Ip4;
if ((This == NULL) || (ChildHandle == NULL)) {
return EFI_INVALID_PARAMETER;
}
Udp4Service = UDP4_SERVICE_DATA_FROM_THIS (This);
//
// Allocate the instance private data structure.
//
Instance = NetAllocatePool (sizeof (UDP4_INSTANCE_DATA));
if (Instance == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Udp4InitInstance (Udp4Service, Instance);
//
// Add an IpInfo for this instance.
//
Instance->IpInfo = IpIoAddIp (Udp4Service->IpIo);
if (Instance->IpInfo == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto FREE_INSTANCE;
}
//
// Install the Udp4Protocol for this instance.
//
Status = gBS->InstallMultipleProtocolInterfaces (
ChildHandle,
&gEfiUdp4ProtocolGuid,
&Instance->Udp4Proto,
NULL
);
if (EFI_ERROR (Status)) {
goto REMOVE_IPINFO;
}
Instance->ChildHandle = *ChildHandle;
//
// Open the default Ip4 protocol in the IP_IO BY_CHILD.
//
Status = gBS->OpenProtocol (
Udp4Service->IpIo->ChildHandle,
&gEfiIp4ProtocolGuid,
(VOID **) &Ip4,
gUdp4DriverBinding.DriverBindingHandle,
Instance->ChildHandle,
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
);
if (EFI_ERROR (Status)) {
goto UNINSTALL_PROTOCOL;
}
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
//
// Link this instance into the service context data and increase the ChildrenNumber.
//
NetListInsertTail (&Udp4Service->ChildrenList, &Instance->Link);
Udp4Service->ChildrenNumber++;
NET_RESTORE_TPL (OldTpl);
return Status;
UNINSTALL_PROTOCOL:
gBS->UninstallMultipleProtocolInterfaces (
Instance->ChildHandle,
&gEfiUdp4ProtocolGuid,
&Instance->Udp4Proto,
NULL
);
REMOVE_IPINFO:
IpIoRemoveIp (Udp4Service->IpIo, Instance->IpInfo);
FREE_INSTANCE:
Udp4CleanInstance (Instance);
NetFreePool (Instance);
return Status;
}
/**
Destroys a child handle with a set of I/O services.
@param This Protocol instance pointer.
@param ChildHandle Handle of the child to destroy
@retval EFI_SUCCES The I/O services were removed from the child
handle
@retval EFI_UNSUPPORTED The child handle does not support the I/O services
that are being removed
@retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.
@retval EFI_ACCESS_DENIED The child handle could not be destroyed because
its I/O services are being used.
@retval other The child handle was not destroyed
**/
EFI_STATUS
EFIAPI
Udp4ServiceBindingDestroyChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN EFI_HANDLE ChildHandle
)
{
EFI_STATUS Status;
UDP4_SERVICE_DATA *Udp4Service;
EFI_UDP4_PROTOCOL *Udp4Proto;
UDP4_INSTANCE_DATA *Instance;
EFI_TPL OldTpl;
if ((This == NULL) || (ChildHandle == NULL)) {
return EFI_INVALID_PARAMETER;
}
Udp4Service = UDP4_SERVICE_DATA_FROM_THIS (This);
//
// Try to get the Udp4 protocol from the ChildHandle.
//
Status = gBS->OpenProtocol (
ChildHandle,
&gEfiUdp4ProtocolGuid,
(VOID **) &Udp4Proto,
gUdp4DriverBinding.DriverBindingHandle,
ChildHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
if (EFI_ERROR (Status)) {
return EFI_UNSUPPORTED;
}
Instance = UDP4_INSTANCE_DATA_FROM_THIS (Udp4Proto);
if (Instance->Destroyed) {
return EFI_SUCCESS;
}
//
// Use the Destroyed flag to avoid the re-entering of the following code.
//
Instance->Destroyed = TRUE;
//
// Close the Ip4 protocol.
//
gBS->CloseProtocol (
Udp4Service->IpIo->ChildHandle,
&gEfiIp4ProtocolGuid,
gUdp4DriverBinding.DriverBindingHandle,
Instance->ChildHandle
);
//
// Uninstall the Udp4Protocol previously installed on the ChildHandle.
//
Status = gBS->UninstallMultipleProtocolInterfaces (
ChildHandle,
&gEfiUdp4ProtocolGuid,
(VOID *) &Instance->Udp4Proto,
NULL
);
if (EFI_ERROR (Status)) {
Instance->Destroyed = FALSE;
return Status;
}
//
// Reset the configuration in case the instance's consumer forgets to do this.
//
Udp4Proto->Configure (Udp4Proto, NULL);
//
// Remove the IpInfo this instance consumes.
//
IpIoRemoveIp (Udp4Service->IpIo, Instance->IpInfo);
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
//
// Remove this instance from the service context data's ChildrenList.
//
NetListRemoveEntry (&Instance->Link);
Udp4Service->ChildrenNumber--;
//
// Clean the instance.
//
Udp4CleanInstance (Instance);
NET_RESTORE_TPL (OldTpl);
NetFreePool (Instance);
return EFI_SUCCESS;
}
//@MT: EFI_DRIVER_ENTRY_POINT (Udp4DriverEntryPoint)
EFI_STATUS
EFIAPI
Udp4DriverEntryPoint (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
/*++
Routine Description:
The entry point for Udp4 driver which installs the driver binding
and component name protocol on its ImageHandle.
Arguments:
ImageHandle - The image handle of the driver.
SystemTable - The system table.
Returns:
EFI_SUCCESS - if the driver binding and component name protocols are
successfully installed, otherwise if failed.
--*/
{
EFI_STATUS Status;
//
// Install the Udp4DriverBinding and Udp4ComponentName protocols.
//
Status = NetLibInstallAllDriverProtocols (
ImageHandle,
SystemTable,
&gUdp4DriverBinding,
ImageHandle,
&gUdp4ComponentName,
NULL,
NULL
);
if (!EFI_ERROR (Status)) {
//
// Initialize the UDP random port.
//
mUdp4RandomPort = ((UINT16) NetRandomInitSeed ()) % UDP4_PORT_KNOWN + UDP4_PORT_KNOWN;
}
return Status;
}

View File

@ -0,0 +1,70 @@
/** @file
Copyright (c) 2006, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Udp4Driver.h
Abstract:
**/
#ifndef _UDP4_DRIVER_H_
#define _UDP4_DRIVER_H_
#include <PiDxe.h>
#include <Library/BaseLib.h>
#include <Library/NetLib.h>
#include <Protocol/DriverBinding.h>
#include <Protocol/ServiceBinding.h>
EFI_STATUS
EFIAPI
Udp4DriverBindingSupported (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
);
EFI_STATUS
EFIAPI
Udp4DriverBindingStart (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
);
EFI_STATUS
EFIAPI
Udp4DriverBindingStop (
IN EFI_DRIVER_BINDING_PROTOCOL *This,
IN EFI_HANDLE ControllerHandle,
IN UINTN NumberOfChildren,
IN EFI_HANDLE *ChildHandleBuffer
);
EFI_STATUS
EFIAPI
Udp4ServiceBindingCreateChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN EFI_HANDLE *ChildHandle
);
EFI_STATUS
EFIAPI
Udp4ServiceBindingDestroyChild (
IN EFI_SERVICE_BINDING_PROTOCOL *This,
IN EFI_HANDLE ChildHandle
);
#endif

View File

@ -0,0 +1,66 @@
#/** @file
# Component name for module Udp4
#
# FIX ME!
# Copyright (c) 2006, Intel Corporation. All right reserved.
#
# All rights reserved. This program and the accompanying materials
# are licensed and made available under the terms and conditions of the BSD License
# which accompanies this distribution. The full text of the license may be found at
# http://opensource.org/licenses/bsd-license.php
#
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#
#
#**/
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = Udp4
FILE_GUID = 6d6963ab-906d-4a65-a7ca-bd40e5d6af2b
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
EDK_RELEASE_VERSION = 0x00020000
EFI_SPECIFICATION_VERSION = 0x00020000
ENTRY_POINT = Udp4DriverEntryPoint
#
# The following information is for reference only and not required by the build tools.
#
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
#
[Sources.common]
Udp4Impl.h
Udp4Main.c
ComponentName.c
Udp4Impl.c
Udp4Driver.h
Udp4Driver.c
CommonHeader.h
[Packages]
MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
[LibraryClasses]
UefiLib
BaseLib
UefiBootServicesTableLib
UefiDriverEntryPoint
UefiRuntimeServicesTableLib
DebugLib
IpIoLib
NetLib
[Protocols]
gEfiIp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiUdp4ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiIp4ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
gEfiUdp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED

View File

@ -0,0 +1,77 @@
<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<MsaHeader>
<ModuleName>Udp4</ModuleName>
<ModuleType>DXE_DRIVER</ModuleType>
<GuidValue>6d6963ab-906d-4a65-a7ca-bd40e5d6af2b</GuidValue>
<Version>1.0</Version>
<Abstract>Component name for module Udp4</Abstract>
<Description>FIX ME!</Description>
<Copyright>Copyright (c) 2006, Intel Corporation. All right reserved.</Copyright>
<License>All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>
<Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
</MsaHeader>
<ModuleDefinitions>
<SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
<BinaryModule>false</BinaryModule>
<OutputFileBasename>Udp4</OutputFileBasename>
</ModuleDefinitions>
<LibraryClassDefinitions>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>DebugLib</Keyword>
</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>UefiRuntimeServicesTableLib</Keyword>
</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>UefiDriverEntryPoint</Keyword>
</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>UefiBootServicesTableLib</Keyword>
</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>BaseLib</Keyword>
</LibraryClass>
<LibraryClass Usage="ALWAYS_CONSUMED">
<Keyword>UefiLib</Keyword>
</LibraryClass>
</LibraryClassDefinitions>
<SourceFiles>
<Filename>Udp4Driver.c</Filename>
<Filename>Udp4Driver.h</Filename>
<Filename>Udp4Impl.c</Filename>
<Filename>ComponentName.c</Filename>
<Filename>Udp4Main.c</Filename>
<Filename>Udp4Impl.h</Filename>
</SourceFiles>
<PackageDependencies>
<Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
<Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
</PackageDependencies>
<Protocols>
<Protocol Usage="ALWAYS_CONSUMED">
<ProtocolCName>gEfiUdp4ProtocolGuid</ProtocolCName>
</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">
<ProtocolCName>gEfiIp4ServiceBindingProtocolGuid</ProtocolCName>
</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">
<ProtocolCName>gEfiUdp4ServiceBindingProtocolGuid</ProtocolCName>
</Protocol>
<Protocol Usage="ALWAYS_CONSUMED">
<ProtocolCName>gEfiIp4ProtocolGuid</ProtocolCName>
</Protocol>
</Protocols>
<Externs>
<Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
<Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
<Extern>
<ModuleEntryPoint>Udp4DriverEntryPoint</ModuleEntryPoint>
</Extern>
</Externs>
</ModuleSurfaceArea>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,299 @@
/** @file
Copyright (c) 2006 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Udp4Impl.h
Abstract:
EFI UDPv4 protocol implementation
**/
#ifndef _UDP4_IMPL_H_
#define _UDP4_IMPL_H_
#include <PiDxe.h>
#include <Protocol/IP4.h>
#include <Protocol/Udp4.h>
#include <Library/IpIoLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/UefiDriverEntryPoint.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/BaseLib.h>
#include <Library/UefiLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include "Udp4Driver.h"
extern EFI_COMPONENT_NAME_PROTOCOL gUdp4ComponentName;
extern EFI_SERVICE_BINDING_PROTOCOL mUdp4ServiceBinding;
extern EFI_UDP4_PROTOCOL mUdp4Protocol;
extern UINT16 mUdp4RandomPort;
#define ICMP_ERROR_PACKET_LENGTH 8
#define UDP4_TIMEOUT_INTERVAL (50 * TICKS_PER_MS) // 50 milliseconds
#define UDP4_HEADER_SIZE sizeof (EFI_UDP4_HEADER)
#define UDP4_MAX_DATA_SIZE 65507
#define UDP4_PORT_KNOWN 1024
#define UDP4_SERVICE_DATA_SIGNATURE EFI_SIGNATURE_32('U', 'd', 'p', '4')
#define UDP4_SERVICE_DATA_FROM_THIS(a) \
CR ( \
(a), \
UDP4_SERVICE_DATA, \
ServiceBinding, \
UDP4_SERVICE_DATA_SIGNATURE \
)
typedef struct _UDP4_SERVICE_DATA_ {
UINT32 Signature;
EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;
EFI_HANDLE ImageHandle;
EFI_HANDLE ControllerHandle;
NET_LIST_ENTRY ChildrenList;
UINTN ChildrenNumber;
IP_IO *IpIo;
EFI_EVENT TimeoutEvent;
CHAR16 *MacString;
} UDP4_SERVICE_DATA;
#define UDP4_INSTANCE_DATA_SIGNATURE EFI_SIGNATURE_32('U', 'd', 'p', 'I')
#define UDP4_INSTANCE_DATA_FROM_THIS(a) \
CR ( \
(a), \
UDP4_INSTANCE_DATA, \
Udp4Proto, \
UDP4_INSTANCE_DATA_SIGNATURE \
)
typedef struct _UDP4_INSTANCE_DATA_ {
UINT32 Signature;
NET_LIST_ENTRY Link;
UDP4_SERVICE_DATA *Udp4Service;
EFI_UDP4_PROTOCOL Udp4Proto;
EFI_UDP4_CONFIG_DATA ConfigData;
EFI_HANDLE ChildHandle;
BOOLEAN Configured;
BOOLEAN IsNoMapping;
NET_MAP TxTokens;
NET_MAP RxTokens;
NET_MAP McastIps;
NET_LIST_ENTRY RcvdDgramQue;
NET_LIST_ENTRY DeliveredDgramQue;
UINT16 HeadSum;
EFI_STATUS IcmpError;
IP_IO_IP_INFO *IpInfo;
BOOLEAN Destroyed;
} UDP4_INSTANCE_DATA;
typedef struct _UDP4_RXDATA_WRAP_ {
NET_LIST_ENTRY Link;
NET_BUF *Packet;
UINT32 TimeoutTick;
EFI_UDP4_RECEIVE_DATA RxData;
} UDP4_RXDATA_WRAP;
EFI_STATUS
EFIAPI
Udp4GetModeData (
IN EFI_UDP4_PROTOCOL *This,
OUT EFI_UDP4_CONFIG_DATA *Udp4ConfigData OPTIONAL,
OUT EFI_IP4_MODE_DATA *Ip4ModeData OPTIONAL,
OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL,
OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL
);
EFI_STATUS
EFIAPI
Udp4Configure (
IN EFI_UDP4_PROTOCOL *This,
IN EFI_UDP4_CONFIG_DATA *UdpConfigData OPTIONAL
);
EFI_STATUS
EFIAPI
Udp4Groups (
IN EFI_UDP4_PROTOCOL *This,
IN BOOLEAN JoinFlag,
IN EFI_IPv4_ADDRESS *MulticastAddress OPTIONAL
);
EFI_STATUS
EFIAPI
Udp4Routes (
IN EFI_UDP4_PROTOCOL *This,
IN BOOLEAN DeleteRoute,
IN EFI_IPv4_ADDRESS *SubnetAddress,
IN EFI_IPv4_ADDRESS *SubnetMask,
IN EFI_IPv4_ADDRESS *GatewayAddress
);
EFI_STATUS
EFIAPI
Udp4Transmit (
IN EFI_UDP4_PROTOCOL *This,
IN EFI_UDP4_COMPLETION_TOKEN *Token
);
EFI_STATUS
EFIAPI
Udp4Receive (
IN EFI_UDP4_PROTOCOL *This,
IN EFI_UDP4_COMPLETION_TOKEN *Token
);
EFI_STATUS
EFIAPI
Udp4Cancel (
IN EFI_UDP4_PROTOCOL *This,
IN EFI_UDP4_COMPLETION_TOKEN *Token OPTIONAL
);
EFI_STATUS
EFIAPI
Udp4Poll (
IN EFI_UDP4_PROTOCOL *This
);
EFI_STATUS
Udp4CreateService (
IN UDP4_SERVICE_DATA *Udp4Service,
IN EFI_HANDLE ImageHandle,
IN EFI_HANDLE ControllerHandle
);
VOID
Udp4CleanService (
IN UDP4_SERVICE_DATA *Udp4Service
);
VOID
Udp4InitInstance (
IN UDP4_SERVICE_DATA *Udp4Service,
IN UDP4_INSTANCE_DATA *Instance
);
VOID
Udp4CleanInstance (
IN UDP4_INSTANCE_DATA *Instance
);
EFI_STATUS
Udp4Bind (
IN NET_LIST_ENTRY *InstanceList,
IN EFI_UDP4_CONFIG_DATA *ConfigData
);
BOOLEAN
Udp4IsReconfigurable (
IN EFI_UDP4_CONFIG_DATA *OldConfigData,
IN EFI_UDP4_CONFIG_DATA *NewConfigData
);
VOID
Udp4BuildIp4ConfigData (
IN EFI_UDP4_CONFIG_DATA *Udp4ConfigData,
IN EFI_IP4_CONFIG_DATA *Ip4ConfigData
);
EFI_STATUS
Udp4ValidateTxToken (
IN UDP4_INSTANCE_DATA *Instance,
IN EFI_UDP4_COMPLETION_TOKEN *TxToken
);
EFI_STATUS
Udp4TokenExist (
IN NET_MAP *Map,
IN NET_MAP_ITEM *Item,
IN VOID *Context
);
UINT16
Udp4Checksum (
IN NET_BUF *Packet,
IN UINT16 HeadSum
);
EFI_STATUS
Udp4RemoveToken (
IN NET_MAP *TokenMap,
IN EFI_UDP4_COMPLETION_TOKEN *Token
);
EFI_STATUS
Udp4LeaveGroup (
IN NET_MAP *Map,
IN NET_MAP_ITEM *Item,
IN VOID *Arg OPTIONAL
);
VOID
Udp4FlushRxData (
IN NET_LIST_ENTRY *RcvdDgramQue
);
EFI_STATUS
Udp4InstanceCancelToken (
IN UDP4_INSTANCE_DATA *Instance,
IN EFI_UDP4_COMPLETION_TOKEN *Token OPTIONAL
);
VOID
Udp4InstanceDeliverDgram (
IN UDP4_INSTANCE_DATA *Instance
);
VOID
Udp4ReportIcmpError (
IN UDP4_INSTANCE_DATA *Instance
);
VOID
Udp4NetVectorExtFree (
VOID *Context
);
EFI_STATUS
Udp4SetVariableData (
IN UDP4_SERVICE_DATA *Udp4Service
);
VOID
Udp4ClearVariableData (
IN UDP4_SERVICE_DATA *Udp4Service
);
#endif

View File

@ -0,0 +1,869 @@
/** @file
Copyright (c) 2006 - 2007, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
Module Name:
Udp4Main.c
Abstract:
**/
#include "Udp4Impl.h"
#include <Protocol/Ip4.h>
EFI_UDP4_PROTOCOL mUdp4Protocol = {
Udp4GetModeData,
Udp4Configure,
Udp4Groups,
Udp4Routes,
Udp4Transmit,
Udp4Receive,
Udp4Cancel,
Udp4Poll
};
/**
This function copies the current operational settings of this EFI UDPv4 Protocol
instance into user-supplied buffers. This function is used optionally to retrieve
the operational mode data of underlying networks or drivers.
@param This Pointer to the EFI_UDP4_PROTOCOL instance.
@param Udp4ConfigData Pointer to the buffer to receive the current
configuration data.
@param Ip4ModeData Pointer to the EFI IPv4 Protocol mode data
structure.
@param MnpConfigData Pointer to the managed network configuration data
structure.
@param SnpModeData Pointer to the simple network mode data structure.
@retval EFI_SUCCESS The mode data was read.
@retval EFI_NOT_STARTED When Udp4ConfigData is queried, no configuration
data is available because this instance has not
been started.
@retval EFI_INVALID_PARAMETER This is NULL.
**/
EFI_STATUS
EFIAPI
Udp4GetModeData (
IN EFI_UDP4_PROTOCOL *This,
OUT EFI_UDP4_CONFIG_DATA *Udp4ConfigData OPTIONAL,
OUT EFI_IP4_MODE_DATA *Ip4ModeData OPTIONAL,
OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL,
OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL
)
{
UDP4_INSTANCE_DATA *Instance;
EFI_IP4_PROTOCOL *Ip;
EFI_TPL OldTpl;
EFI_STATUS Status;
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
Instance = UDP4_INSTANCE_DATA_FROM_THIS (This);
if (!Instance->Configured && (Udp4ConfigData != NULL)) {
return EFI_NOT_STARTED;
}
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
if (Udp4ConfigData != NULL) {
//
// Set the Udp4ConfigData.
//
*Udp4ConfigData = Instance->ConfigData;
}
Ip = Instance->IpInfo->Ip;
//
// Get the underlying Ip4ModeData, MnpConfigData and SnpModeData.
//
Status = Ip->GetModeData (Ip, Ip4ModeData, MnpConfigData, SnpModeData);
NET_RESTORE_TPL (OldTpl);
return Status;
}
/**
This function is used to do the following:
Initialize and start this instance of the EFI UDPv4 Protocol.
Change the filtering rules and operational parameters.
Reset this instance of the EFI UDPv4 Protocol.
@param This Pointer to the EFI_UDP4_PROTOCOL instance.
@param UdpConfigData Pointer to the buffer to receive the current mode
data.
@retval EFI_SUCCESS The configuration settings were set, changed, or
reset successfully.
@retval EFI_NO_MAPPING When using a default address, configuration (DHCP,
BOOTP, RARP, etc.) is not finished yet.
@retval EFI_INVALID_PARAMETER One or more following conditions are TRUE: This is
NULL. UdpConfigData.StationAddress is not a valid
unicast IPv4 address. UdpConfigData.SubnetMask is
not a valid IPv4 address mask.
UdpConfigData.RemoteAddress is not a valid unicast
IPv4 address if it is not zero.
@retval EFI_ALREADY_STARTED The EFI UDPv4 Protocol instance is already
started/configured and must be stopped/reset
before it can be reconfigured. Only TypeOfService,
TimeToLive, DoNotFragment, ReceiveTimeout, and
TransmitTimeout can be reconfigured without
stopping the current instance of the EFI UDPv4
Protocol.
@retval EFI_ACCESS_DENIED UdpConfigData.AllowDuplicatePort is FALSE and
UdpConfigData.StationPort is already used by other
instance.
@retval EFI_OUT_OF_RESOURCES The EFI UDPv4 Protocol driver cannot allocate
memory for this EFI UDPv4 Protocol instance.
@retval EFI_DEVICE_ERROR An unexpected network or system error occurred and
this instance was not opened.
**/
EFI_STATUS
EFIAPI
Udp4Configure (
IN EFI_UDP4_PROTOCOL *This,
IN EFI_UDP4_CONFIG_DATA *UdpConfigData OPTIONAL
)
{
EFI_STATUS Status;
UDP4_INSTANCE_DATA *Instance;
UDP4_SERVICE_DATA *Udp4Service;
EFI_TPL OldTpl;
IP4_ADDR StationAddress;
IP4_ADDR SubnetMask;
IP4_ADDR RemoteAddress;
EFI_IP4_CONFIG_DATA Ip4ConfigData;
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
Instance = UDP4_INSTANCE_DATA_FROM_THIS (This);
if (!Instance->Configured && (UdpConfigData == NULL)) {
return EFI_SUCCESS;
}
Udp4Service = Instance->Udp4Service;
Status = EFI_SUCCESS;
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
if (UdpConfigData != NULL) {
StationAddress = EFI_NTOHL (UdpConfigData->StationAddress);
SubnetMask = EFI_NTOHL (UdpConfigData->SubnetMask);
RemoteAddress = EFI_NTOHL (UdpConfigData->RemoteAddress);
if (!UdpConfigData->UseDefaultAddress &&
(!IP4_IS_VALID_NETMASK (SubnetMask) ||
!((StationAddress == 0) || Ip4IsUnicast (StationAddress, SubnetMask)) ||
!((RemoteAddress == 0) || Ip4IsUnicast (RemoteAddress, 0)))) {
//
// Don't use default address, and subnet mask is invalid or StationAddress is not
// a valid unicast IPv4 address or RemoteAddress is not a valid unicast IPv4 address
// if it is not 0.
//
Status = EFI_INVALID_PARAMETER;
goto ON_EXIT;
}
if (Instance->Configured) {
//
// The instance is already configured, try to do the re-configuration.
//
if (!Udp4IsReconfigurable (&Instance->ConfigData, UdpConfigData)) {
//
// If the new configuration data wants to change some unreconfigurable
// settings, return EFI_ALREADY_STARTED.
//
Status = EFI_ALREADY_STARTED;
goto ON_EXIT;
}
//
// Save the reconfigurable parameters.
//
Instance->ConfigData.TypeOfService = UdpConfigData->TypeOfService;
Instance->ConfigData.TimeToLive = UdpConfigData->TimeToLive;
Instance->ConfigData.DoNotFragment = UdpConfigData->DoNotFragment;
Instance->ConfigData.ReceiveTimeout = UdpConfigData->ReceiveTimeout;
Instance->ConfigData.TransmitTimeout = UdpConfigData->TransmitTimeout;
} else {
//
// Construct the Ip configuration data from the UdpConfigData.
//
Udp4BuildIp4ConfigData (UdpConfigData, &Ip4ConfigData);
//
// Configure the Ip instance wrapped in the IpInfo.
//
Status = IpIoConfigIp (Instance->IpInfo, &Ip4ConfigData);
if (EFI_ERROR (Status)) {
if (Status == EFI_NO_MAPPING) {
Instance->IsNoMapping = TRUE;
}
goto ON_EXIT;
}
Instance->IsNoMapping = FALSE;
//
// Save the configuration data.
//
Instance->ConfigData = *UdpConfigData;
Instance->ConfigData.StationAddress = Ip4ConfigData.StationAddress;
Instance->ConfigData.SubnetMask = Ip4ConfigData.SubnetMask;
//
// Try to allocate the required port resource.
//
Status = Udp4Bind (&Udp4Service->ChildrenList, &Instance->ConfigData);
if (EFI_ERROR (Status)) {
//
// Reset the ip instance if bind fails.
//
IpIoConfigIp (Instance->IpInfo, NULL);
goto ON_EXIT;
}
//
// Pre calculate the checksum for the pseudo head, ignore the UDP length first.
//
Instance->HeadSum = NetPseudoHeadChecksum (
EFI_IP4 (Instance->ConfigData.StationAddress),
EFI_IP4 (Instance->ConfigData.RemoteAddress),
EFI_IP_PROTO_UDP,
0
);
Instance->Configured = TRUE;
}
} else {
//
// UdpConfigData is NULL, reset the instance.
//
Instance->Configured = FALSE;
Instance->IsNoMapping = FALSE;
//
// Reset the Ip instance wrapped in the IpInfo.
//
IpIoConfigIp (Instance->IpInfo, NULL);
//
// Cancel all the user tokens.
//
Udp4InstanceCancelToken (Instance, NULL);
//
// Remove the buffered RxData for this instance.
//
Udp4FlushRxData (&Instance->RcvdDgramQue);
}
Udp4SetVariableData (Instance->Udp4Service);
ON_EXIT:
NET_RESTORE_TPL (OldTpl);
return Status;
}
/**
This function is used to enable and disable the multicast group filtering.
@param This Pointer to the EFI_UDP4_PROTOCOL instance.
@param JoinFlag Set to TRUE to join a multicast group. Set to
FALSE to leave one or all multicast groups.
@param MulticastAddress Pointer to multicast group address to join or
leave.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_NOT_STARTED The EFI UDPv4 Protocol instance has not been
started.
@retval EFI_NO_MAPPING When using a default address, configuration (DHCP,
BOOTP, RARP, etc.) is not finished yet.
@retval EFI_OUT_OF_RESOURCES Could not allocate resources to join the group.
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
This is NULL. JoinFlag is TRUE and
MulticastAddress is NULL. JoinFlag is TRUE and
*MulticastAddress is not a valid multicast
address.
@retval EFI_ALREADY_STARTED The group address is already in the group table
(when JoinFlag is TRUE).
@retval EFI_NOT_FOUND The group address is not in the group table (when
JoinFlag is FALSE).
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
**/
EFI_STATUS
EFIAPI
Udp4Groups (
IN EFI_UDP4_PROTOCOL *This,
IN BOOLEAN JoinFlag,
IN EFI_IPv4_ADDRESS *MulticastAddress OPTIONAL
)
{
EFI_STATUS Status;
UDP4_INSTANCE_DATA *Instance;
EFI_IP4_PROTOCOL *Ip;
EFI_TPL OldTpl;
if ((This == NULL) ||
(JoinFlag && (MulticastAddress == NULL)) ||
(JoinFlag && !IP4_IS_MULTICAST (EFI_NTOHL (*MulticastAddress)))) {
return EFI_INVALID_PARAMETER;
}
Instance = UDP4_INSTANCE_DATA_FROM_THIS (This);
if (Instance->IsNoMapping) {
return EFI_NO_MAPPING;
}
if (!Instance->Configured) {
return EFI_NOT_STARTED;
}
Ip = Instance->IpInfo->Ip;
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
//
// Invoke the Ip instance the Udp4 instance consumes to do the group operation.
//
Status = Ip->Groups (Ip, JoinFlag, MulticastAddress);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
//
// Keep a local copy of the configured multicast IPs because IpIo receives
// datagrams from the 0 station address IP instance and then UDP delivers to
// the matched instance. This copy of multicast IPs is used to avoid receive
// the mutlicast datagrams destinated to multicast IPs the other instances configured.
//
if (JoinFlag) {
NetMapInsertTail (
&Instance->McastIps,
(VOID *) (UINTN) EFI_IP4 (*MulticastAddress),
NULL
);
} else {
NetMapIterate (&Instance->McastIps, Udp4LeaveGroup, MulticastAddress);
}
ON_EXIT:
NET_RESTORE_TPL (OldTpl);
return Status;
}
/**
This function adds a route to or deletes a route from the routing table.
@param This Pointer to the EFI_UDP4_PROTOCOL instance.
@param DeleteRoute Set to TRUE to delete this route from the routing
table. Set to FALSE to add this route to the
routing table.
@param SubnetAddress The destination network address that needs to be
routed.
@param SubnetMask The subnet mask of SubnetAddress.
@param GatewayAddress The gateway IP address for this route.
@retval EFI_SUCCESS The operation completed successfully.
@retval EFI_NOT_STARTED The EFI UDPv4 Protocol instance has not been
started.
@retval EFI_NO_MAPPING When using a default address, configuration (DHCP,
BOOTP, RARP, etc.) is not finished yet.
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
This is NULL. SubnetAddress is NULL. SubnetMask is
NULL. GatewayAddress is NULL. SubnetAddress is not
a valid subnet address. SubnetMask is not a valid
subnet mask. GatewayAddress is not a valid unicast
IP address.
@retval EFI_OUT_OF_RESOURCES Could not add the entry to the routing table.
@retval EFI_NOT_FOUND This route is not in the routing table.
@retval EFI_ACCESS_DENIED The route is already defined in the routing table.
**/
EFI_STATUS
EFIAPI
Udp4Routes (
IN EFI_UDP4_PROTOCOL *This,
IN BOOLEAN DeleteRoute,
IN EFI_IPv4_ADDRESS *SubnetAddress,
IN EFI_IPv4_ADDRESS *SubnetMask,
IN EFI_IPv4_ADDRESS *GatewayAddress
)
{
UDP4_INSTANCE_DATA *Instance;
EFI_IP4_PROTOCOL *Ip;
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
Instance = UDP4_INSTANCE_DATA_FROM_THIS (This);
if (Instance->IsNoMapping) {
return EFI_NO_MAPPING;
}
if (!Instance->Configured) {
return EFI_NOT_STARTED;
}
Ip = Instance->IpInfo->Ip;
//
// Invoke the Ip instance the Udp4 instance consumes to do the actual operation.
//
return Ip->Routes (Ip, DeleteRoute, SubnetAddress, SubnetMask, GatewayAddress);
}
/**
This function places a sending request to this instance of the EFI UDPv4 Protocol,
alongside the transmit data that was filled by the user.
@param This Pointer to the EFI_UDP4_PROTOCOL instance.
@param Token Pointer to the completion token that will be
placed into the transmit queue.
@retval EFI_SUCCESS The data has been queued for transmission.
@retval EFI_NOT_STARTED This EFI UDPv4 Protocol instance has not been
started.
@retval EFI_NO_MAPPING When using a default address, configuration (DHCP,
BOOTP, RARP, etc.) is not finished yet.
@retval EFI_INVALID_PARAMETER One or more of the following are TRUE: This is
NULL. Token is NULL. Token.Event is NULL.
Token.Packet.TxData is NULL.
Token.Packet.TxData.FragmentCount is zero.
Token.Packet.TxData.DataLength is not equal to the
sum of fragment lengths. One or more of the
Token.Packet.TxData.FragmentTable[].
FragmentLength fields is zero. One or more of the
Token.Packet.TxData.FragmentTable[].
FragmentBuffer fields is NULL.
Token.Packet.TxData. GatewayAddress is not a
unicast IPv4 address if it is not NULL. One or
more IPv4 addresses in Token.Packet.TxData.
UdpSessionData are not valid unicast IPv4
addresses if the UdpSessionData is not NULL.
@retval EFI_ACCESS_DENIED The transmit completion token with the same
Token.Event is already in the transmit queue.
@retval EFI_NOT_READY The completion token could not be queued because
the transmit queue is full.
@retval EFI_OUT_OF_RESOURCES Could not queue the transmit data.
@retval EFI_NOT_FOUND There is no route to the destination network or
address.
@retval EFI_BAD_BUFFER_SIZE The data length is greater than the maximum UDP
packet size. Or the length of the IP header + UDP
header + data length is greater than MTU if
DoNotFragment is TRUE.
**/
EFI_STATUS
EFIAPI
Udp4Transmit (
IN EFI_UDP4_PROTOCOL *This,
IN EFI_UDP4_COMPLETION_TOKEN *Token
)
{
EFI_STATUS Status;
UDP4_INSTANCE_DATA *Instance;
EFI_TPL OldTpl;
NET_BUF *Packet;
EFI_UDP4_HEADER *Udp4Header;
EFI_UDP4_CONFIG_DATA *ConfigData;
IP4_ADDR Destination;
EFI_UDP4_TRANSMIT_DATA *TxData;
EFI_UDP4_SESSION_DATA *UdpSessionData;
UDP4_SERVICE_DATA *Udp4Service;
IP_IO_OVERRIDE Override;
UINT16 HeadSum;
if ((This == NULL) || (Token == NULL)) {
return EFI_INVALID_PARAMETER;
}
Instance = UDP4_INSTANCE_DATA_FROM_THIS (This);
if (Instance->IsNoMapping) {
return EFI_NO_MAPPING;
}
if (!Instance->Configured) {
return EFI_NOT_STARTED;
}
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
//
// Validate the Token, if the token is invalid return the error code.
//
Status = Udp4ValidateTxToken (Instance, Token);
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
if (EFI_ERROR (NetMapIterate (&Instance->TxTokens, Udp4TokenExist, Token)) ||
EFI_ERROR (NetMapIterate (&Instance->RxTokens, Udp4TokenExist, Token))) {
//
// Try to find a duplicate token in the two token maps, if found, return
// EFI_ACCESS_DENIED.
//
Status = EFI_ACCESS_DENIED;
goto ON_EXIT;
}
TxData = Token->Packet.TxData;
//
// Create a net buffer to hold the user buffer and the udp header.
//
Packet = NetbufFromExt (
(NET_FRAGMENT *)TxData->FragmentTable,
TxData->FragmentCount,
UDP4_HEADER_SIZE,
0,
Udp4NetVectorExtFree,
NULL
);
if (Packet == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto ON_EXIT;
}
//
// Store the IpIo in ProtoData.
//
Udp4Service = Instance->Udp4Service;
*((UINTN *) &Packet->ProtoData[0]) = (UINTN) (Udp4Service->IpIo);
Udp4Header = (EFI_UDP4_HEADER *) NetbufAllocSpace (Packet, UDP4_HEADER_SIZE, TRUE);
ConfigData = &Instance->ConfigData;
//
// Fill the udp header.
//
Udp4Header->SrcPort = HTONS (ConfigData->StationPort);
Udp4Header->DstPort = HTONS (ConfigData->RemotePort);
Udp4Header->Length = HTONS (Packet->TotalSize);
Udp4Header->Checksum = 0;
UdpSessionData = TxData->UdpSessionData;
Override.SourceAddress = ConfigData->StationAddress;
if (UdpSessionData != NULL) {
//
// Set the SourceAddress, SrcPort and Destination according to the specified
// UdpSessionData.
//
if (EFI_IP4 (UdpSessionData->SourceAddress) != 0) {
Override.SourceAddress = UdpSessionData->SourceAddress;
}
if (UdpSessionData->SourcePort != 0) {
Udp4Header->SrcPort = HTONS (UdpSessionData->SourcePort);
}
Destination = EFI_IP4 (UdpSessionData->DestinationAddress);
if (UdpSessionData->DestinationPort != 0) {
Udp4Header->DstPort = HTONS (UdpSessionData->DestinationPort);
}
//
// calculate the pseudo head checksum using the overridden parameters.
//
HeadSum = NetPseudoHeadChecksum (
EFI_IP4 (Override.SourceAddress),
Destination,
EFI_IP_PROTO_UDP,
0
);
} else {
//
// UdpSessionData is NULL, use the address and port information previously configured.
//
Destination = EFI_IP4 (ConfigData->RemoteAddress);
HeadSum = Instance->HeadSum;
}
//
// calculate the checksum.
//
Udp4Header->Checksum = Udp4Checksum (Packet, HeadSum);
if (Udp4Header->Checksum == 0) {
//
// If the calculated checksum is 0, fill the Checksum field with all ones.
//
Udp4Header->Checksum = 0xffff;
}
//
// Fill the IpIo Override data.
//
EFI_IP4 (Override.GatewayAddress) = (TxData->GatewayAddress != NULL) ?
EFI_IP4 (*(TxData->GatewayAddress)) : 0;
Override.Protocol = EFI_IP_PROTO_UDP;
Override.TypeOfService = ConfigData->TypeOfService;
Override.TimeToLive = ConfigData->TimeToLive;
Override.DoNotFragment = ConfigData->DoNotFragment;
//
// Save the token into the TxToken map.
//
Status = NetMapInsertTail (&Instance->TxTokens, Token, Packet);
if (EFI_ERROR (Status)) {
goto FREE_PACKET;
}
//
// Send out this datagram through IpIo.
//
Status = IpIoSend (
Udp4Service->IpIo,
Packet,
Instance->IpInfo,
Instance,
Token,
Destination,
&Override
);
if (EFI_ERROR (Status)) {
//
// Remove this token from the TxTokens.
//
Udp4RemoveToken (&Instance->TxTokens, Token);
}
FREE_PACKET:
NetbufFree (Packet);
ON_EXIT:
NET_RESTORE_TPL (OldTpl);
return Status;
}
/**
This function places a completion token into the receive packet queue. This function
is always asynchronous.
@param This Pointer to the EFI_UDP4_PROTOCOL instance.
@param Token Pointer to a token that is associated with the
receive data descriptor.
@retval EFI_SUCCESS The receive completion token is cached.
@retval EFI_NOT_STARTED This EFI UDPv4 Protocol instance has not been
started.
@retval EFI_NO_MAPPING When using a default address, configuration (DHCP,
BOOTP, RARP, etc.) is not finished yet.
@retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
This is NULL. Token is NULL. Token.Event is NULL.
@retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued
due to a lack of system resources (usually
memory).
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
The EFI UDPv4 Protocol instance has been reset to
startup defaults.
@retval EFI_ACCESS_DENIED A receive completion token with the same
Token.Event is already in the receive queue.
@retval EFI_NOT_READY The receive request could not be queued because
the receive queue is full.
**/
EFI_STATUS
EFIAPI
Udp4Receive (
IN EFI_UDP4_PROTOCOL *This,
IN EFI_UDP4_COMPLETION_TOKEN *Token
)
{
EFI_STATUS Status;
UDP4_INSTANCE_DATA *Instance;
EFI_TPL OldTpl;
if ((This == NULL) || (Token == NULL) || (Token->Event == NULL)) {
return EFI_INVALID_PARAMETER;
}
Instance = UDP4_INSTANCE_DATA_FROM_THIS (This);
if (Instance->IsNoMapping) {
return EFI_NO_MAPPING;
}
if (!Instance->Configured) {
return EFI_NOT_STARTED;
}
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
if (EFI_ERROR (NetMapIterate (&Instance->RxTokens, Udp4TokenExist, Token))||
EFI_ERROR (NetMapIterate (&Instance->TxTokens, Udp4TokenExist, Token))) {
//
// Return EFI_ACCESS_DENIED if the specified token is already in the TxTokens or
// RxTokens map.
//
Status = EFI_ACCESS_DENIED;
goto ON_EXIT;
}
Token->Packet.RxData = NULL;
//
// Save the token into the RxTokens map.
//
Status = NetMapInsertTail (&Instance->RxTokens, Token, NULL);
if (EFI_ERROR (Status)) {
return EFI_NOT_READY;
}
//
// If there is an icmp error, report it.
//
Udp4ReportIcmpError (Instance);
//
// Try to delivered the received datagrams.
//
Udp4InstanceDeliverDgram (Instance);
ON_EXIT:
NET_RESTORE_TPL (OldTpl);
return Status;
}
/**
This function is used to abort a pending transmit or receive request.
@param This Pointer to the EFI_UDP4_PROTOCOL instance.
@param Token Pointer to a token that has been issued by
EFI_UDP4_PROTOCOL.Transmit() or
EFI_UDP4_PROTOCOL.Receive().
@retval EFI_SUCCESS The asynchronous I/O request is aborted and
Token.Event is signaled. When Token is NULL, all
pending requests are aborted and their events are
signaled.
@retval EFI_INVALID_PARAMETER This is NULL.
@retval EFI_NOT_STARTED This instance has not been started.
@retval EFI_NO_MAPPING When using the default address, configuration
(DHCP, BOOTP, RARP, etc.) is not finished yet.
@retval EFI_NOT_FOUND When Token is not NULL, the asynchronous I/O
request is not found in the transmit or receive
queue. It is either completed or not issued by
Transmit() or Receive().
**/
EFI_STATUS
EFIAPI
Udp4Cancel (
IN EFI_UDP4_PROTOCOL *This,
IN EFI_UDP4_COMPLETION_TOKEN *Token OPTIONAL
)
{
EFI_STATUS Status;
UDP4_INSTANCE_DATA *Instance;
EFI_TPL OldTpl;
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
Instance = UDP4_INSTANCE_DATA_FROM_THIS (This);
if (Instance->IsNoMapping) {
return EFI_NO_MAPPING;
}
if (!Instance->Configured) {
return EFI_NOT_STARTED;
}
OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
//
// Cancle the tokens specified by Token for this instance.
//
Status = Udp4InstanceCancelToken (Instance, Token);
NET_RESTORE_TPL (OldTpl);
return Status;
}
/**
This function can be used by network drivers and applications to increase the rate that
data packets are moved between the communications device and the transmit/receive queues.
Argumens:
This - Pointer to the EFI_UDP4_PROTOCOL instance.
@retval EFI_SUCCESS Incoming or outgoing data was processed.
@retval EFI_INVALID_PARAMETER This is NULL.
@retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
@retval EFI_TIMEOUT Data was dropped out of the transmit and/or
receive queue.
**/
EFI_STATUS
EFIAPI
Udp4Poll (
IN EFI_UDP4_PROTOCOL *This
)
{
UDP4_INSTANCE_DATA *Instance;
EFI_IP4_PROTOCOL *Ip;
if (This == NULL) {
return EFI_INVALID_PARAMETER;
}
Instance = UDP4_INSTANCE_DATA_FROM_THIS (This);
Ip = Instance->IpInfo->Ip;
//
// Invode the Ip instance consumed by the udp instance to do the poll operation.
//
return Ip->Poll (Ip);
}