ip4if.c
来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,274 行 · 第 1/3 页
C
1,274 行
Returns:
NONE
--*/
{
NET_LIST_ENTRY *Entry;
NET_LIST_ENTRY *Next;
IP4_ARP_QUE *ArpQue;
IP4_LINK_TX_TOKEN *Token;
EFI_TPL OldTpl;
//
// Raise the TPL to cancel the ARP and MNP asynchronous requests
// to prevent the callback of the signal being called to close it.
//
OldTpl = gBS->RaiseTPL (NET_TPL_LOCK);
//
// Cancel all the pending frames on ARP requests
//
NET_LIST_FOR_EACH_SAFE (Entry, Next, &Interface->ArpQues) {
ArpQue = NET_LIST_USER_STRUCT (Entry, IP4_ARP_QUE, Link);
Ip4CancelFrameArp (ArpQue, IoStatus, FrameToCancel, Context);
if (NetListIsEmpty (&ArpQue->Frames)) {
NetListRemoveEntry (Entry);
Interface->Arp->Cancel (Interface->Arp, &ArpQue->Ip, ArpQue->OnResolved);
Ip4FreeArpQue (ArpQue, EFI_ABORTED);
}
}
//
// Cancel all the frames that have been delivered to MNP
// but not yet recycled.
//
NET_LIST_FOR_EACH_SAFE (Entry, Next, &Interface->SentFrames) {
Token = NET_LIST_USER_STRUCT (Entry, IP4_LINK_TX_TOKEN, Link);
if ((FrameToCancel == NULL) || FrameToCancel (Token, Context)) {
NetListRemoveEntry (Entry);
Interface->Mnp->Cancel (Interface->Mnp, &Token->MnpToken);
Token->CallBack (Token->IpInstance, Token->Packet, IoStatus, 0, Token->Context);
Ip4FreeLinkTxToken (Token);
}
}
gBS->RestoreTPL (OldTpl);
}
IP4_INTERFACE *
Ip4CreateInterface (
IN EFI_MANAGED_NETWORK_PROTOCOL *Mnp,
IN EFI_HANDLE Controller,
IN EFI_HANDLE ImageHandle
)
/*++
Routine Description:
Create an IP4_INTERFACE. Delay the creation of ARP instance until
the interface is configured.
Arguments:
Mnp - The shared MNP child of this IP4 service binding instance
Controller - The controller this IP4 service binding instance
is installed. Most like the UNDI handle.
ImageHandle - This driver's image handle
Returns:
Point to the created IP4_INTERFACE, otherwise NULL.
--*/
{
IP4_INTERFACE *Interface;
EFI_SIMPLE_NETWORK_MODE SnpMode;
Interface = NetAllocatePool (sizeof (IP4_INTERFACE));
if ((Interface == NULL) || (Mnp == NULL)) {
return NULL;
}
Interface->Signature = IP4_INTERFACE_SIGNATURE;
NetListInit (&Interface->Link);
Interface->RefCnt = 1;
Interface->Ip = IP4_ALLZERO_ADDRESS;
Interface->SubnetMask = IP4_ALLZERO_ADDRESS;
Interface->Configured = FALSE;
Interface->Controller = Controller;
Interface->Image = ImageHandle;
Interface->Mnp = Mnp;
Interface->Arp = NULL;
Interface->ArpHandle = NULL;
NetListInit (&Interface->ArpQues);
NetListInit (&Interface->SentFrames);
Interface->RecvRequest = NULL;
//
// Get the interface's Mac address and broadcast mac address from SNP
//
if (EFI_ERROR (Mnp->GetModeData (Mnp, NULL, &SnpMode))) {
NetFreePool (Interface);
return NULL;
}
Interface->Mac = SnpMode.CurrentAddress;
Interface->BroadcastMac = SnpMode.BroadcastAddress;
Interface->HwaddrLen = SnpMode.HwAddressSize;
NetListInit (&Interface->IpInstances);
Interface->PromiscRecv = FALSE;
return Interface;
}
EFI_STATUS
Ip4SetAddress (
IN IP4_INTERFACE *Interface,
IN IP4_ADDR IpAddr,
IN IP4_ADDR SubnetMask
)
/*++
Routine Description:
Set the interface's address, create and configure
the ARP child if necessary.
Arguments:
Interface - The interface to set the address
IpAddr - The interface's IP address
SubnetMask - The interface's netmask
Returns:
EFI_SUCCESS - The interface is configured with Ip/netmask pair,
and a ARP is created for it.
Others - Failed to set the interface's address.
--*/
{
EFI_ARP_CONFIG_DATA ArpConfig;
EFI_STATUS Status;
INTN Type;
INTN Len;
IP4_ADDR Netmask;
NET_CHECK_SIGNATURE (Interface, IP4_INTERFACE_SIGNATURE);
ASSERT (!Interface->Configured);
//
// Set the ip/netmask, then compute the subnet broadcast
// and network broadcast for easy access. When computing
// nework broadcast, the subnet mask is most like longer
// than the default netmask (not subneted) as defined in
// RFC793. If that isn't the case, we are aggregating the
// networks, use the subnet's mask instead.
//
Interface->Ip = IpAddr;
Interface->SubnetMask = SubnetMask;
Interface->SubnetBrdcast = (IpAddr | ~SubnetMask);
Type = NetGetIpClass (IpAddr);
Len = NetGetMaskLength (SubnetMask);
Netmask = mIp4AllMasks[NET_MIN (Len, Type << 3)];
Interface->NetBrdcast = (IpAddr | ~Netmask);
//
// If the address is NOT all zero, create then configure an ARP child.
// Pay attention: DHCP configures its station address as 0.0.0.0/0
//
Interface->Arp = NULL;
Interface->ArpHandle = NULL;
if (IpAddr != IP4_ALLZERO_ADDRESS) {
Status = NetLibCreateServiceChild (
Interface->Controller,
Interface->Image,
&gEfiArpServiceBindingProtocolGuid,
&Interface->ArpHandle
);
if (EFI_ERROR (Status)) {
return Status;;
}
Status = gBS->OpenProtocol (
Interface->ArpHandle,
&gEfiArpProtocolGuid,
&Interface->Arp,
Interface->Image,
Interface->Controller,
EFI_OPEN_PROTOCOL_BY_DRIVER
);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}
IpAddr = HTONL (IpAddr);
ArpConfig.SwAddressType = IP4_ETHER_PROTO;
ArpConfig.SwAddressLength = 4;
ArpConfig.StationAddress = &IpAddr;
ArpConfig.EntryTimeOut = 0;
ArpConfig.RetryCount = 0;
ArpConfig.RetryTimeOut = 0;
Status = Interface->Arp->Configure (Interface->Arp, &ArpConfig);
if (EFI_ERROR (Status)) {
gBS->CloseProtocol (
Interface->ArpHandle,
&gEfiArpProtocolGuid,
Interface->Image,
Interface->Controller
);
goto ON_ERROR;
}
}
Interface->Configured = TRUE;
return EFI_SUCCESS;
ON_ERROR:
NetLibDestroyServiceChild (
Interface->Controller,
Interface->Image,
&gEfiArpServiceBindingProtocolGuid,
&Interface->ArpHandle
);
return Status;
}
STATIC
BOOLEAN
Ip4CancelInstanceFrame (
IN IP4_LINK_TX_TOKEN *Frame,
IN VOID *Context
)
/*++
Routine Description:
Fileter function to cancel all the frame related to an IP instance.
Arguments:
Frame - The transmit request to test whether to cancel
Context - The context which is the Ip instance that issued the transmit.
Returns:
TRUE - The frame belongs to this instance and is to be removed
FALSE - The frame doesn't belong to this instance.
--*/
{
if (Frame->IpInstance == (IP4_PROTOCOL *) Context) {
return TRUE;
}
return FALSE;
}
VOID
Ip4CancelReceive (
IN IP4_INTERFACE *Interface
)
/*++
Routine Description:
If there is a pending receive request, cancel it. Don't call
the receive request's callback because this function can be only
called if the instance or driver is tearing itself down. It
doesn't make sense to call it back. But it is necessary to call
the transmit token's callback to give it a chance to free the
packet and update the upper layer's transmit request status, say
that from the UDP.
Arguments:
Interface - The interface used by the IpInstance
Returns:
None
--*/
{
EFI_TPL OldTpl;
IP4_LINK_RX_TOKEN *Token;
if ((Token = Interface->RecvRequest) != NULL) {
OldTpl = gBS->RaiseTPL (NET_TPL_LOCK);
Interface->RecvRequest = NULL;
Interface->Mnp->Cancel (Interface->Mnp, &Token->MnpToken);
Ip4FreeFrameRxToken (Token);
gBS->RestoreTPL (OldTpl);
}
}
EFI_STATUS
Ip4FreeInterface (
IN IP4_INTERFACE *Interface,
IN IP4_PROTOCOL *IpInstance OPTIONAL
)
/*++
Routine Description:
Free the interface used by IpInstance. All the IP instance with
the same Ip/Netmask pair share the same interface. It is reference
counted. All the frames haven't been sent will be cancelled.
Because the IpInstance is optional, the caller must remove
IpInstance from the interface's instance list itself.
Arguments:
Interface - The interface used by the IpInstance
IpInstance - The Ip instance that free the interface. NULL if the
Ip driver is releasing the default interface.
Returns:
EFI_SUCCESS - The interface use IpInstance is freed.
--*/
{
NET_CHECK_SIGNATURE (Interface, IP4_INTERFACE_SIGNATURE);
ASSERT (Interface->RefCnt > 0);
//
// Remove all the pending transmit token related to this IP instance.
//
Ip4CancelFrames (Interface, EFI_ABORTED, Ip4CancelInstanceFrame, IpInstance);
if (--Interface->RefCnt > 0) {
return EFI_SUCCESS;
}
//
// Destory the interface if this is the last IP instance that
// has the address. Remove all the system transmitted packets
// from this interface, cancel the receive request if there is
// one, and destory the ARP requests.
//
Ip4CancelFrames (Interface, EFI_ABORTED, Ip4CancelInstanceFrame, NULL);
Ip4CancelReceive (Interface);
ASSERT (NetListIsEmpty (&Interface->IpInstances));
ASSERT (NetListIsEmpty (&Interface->ArpQues));
ASSERT (NetListIsEmpty (&Interface->SentFrames));
if (Interface->Arp != NULL) {
gBS->CloseProtocol (
Interface->ArpHandle,
&gEfiArpProtocolGuid,
Interface->Image,
Interface->Controller
);
NetLibDestroyServiceChild (
Interface->Controller,
Interface->Image,
&gEfiArpServiceBindingProtocolGuid,
Interface->ArpHandle
);
}
NetListRemoveEntry (&Interface->Link);
NetFreePool (Interface);
return EFI_SUCCESS;
}
STATIC
VOID
EFIAPI
Ip4OnArpResolved (
IN EFI_EVENT Event,
IN VOID *Context
)
/*++
Routine Description:
Callback function when ARP request are finished. It will cancelled
all the queued frame if the ARP requests failed. Or transmit them
if the request succeed.
Arguments:
Event - The Arp request event
Context - The context of the callback, a point to the ARP queue
Returns:
None
--*/
{
NET_LIST_ENTRY *Entry;
NET_LIST_ENTRY *Next;
IP4_ARP_QUE *ArpQue;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?