ip4if.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 1,274 行 · 第 1/3 页

C
1,274
字号
/*++

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:

  Ip4If.c

Abstract:

  Implement IP4 pesudo interface.

--*/

#include "Ip4Impl.h"

//
// Mac address with all zero, used to determine whethter the ARP
// resolve succeeded. Failed ARP requests zero the MAC address buffer.
//
STATIC EFI_MAC_ADDRESS  mZeroMacAddress;

STATIC
VOID
EFIAPI
Ip4OnFrameSent (
  IN EFI_EVENT              Event,
  IN VOID                   *Context
  );

STATIC
VOID
EFIAPI
Ip4OnArpResolved (
  IN EFI_EVENT              Event,
  IN VOID                   *Context
  );

STATIC
VOID
EFIAPI
Ip4OnFrameReceived (
  IN EFI_EVENT              Event,
  IN VOID                   *Context
  );

STATIC
VOID
Ip4CancelFrameArp (
  IN IP4_ARP_QUE            *ArpQue,
  IN EFI_STATUS             IoStatus,
  IN IP4_FRAME_TO_CANCEL    FrameToCancel, OPTIONAL
  IN VOID                   *Context
  );

STATIC
IP4_LINK_TX_TOKEN *
Ip4WrapLinkTxToken (
  IN IP4_INTERFACE          *Interface,
  IN IP4_PROTOCOL           *IpInstance,    OPTIONAL
  IN NET_BUF                *Packet,
  IN IP4_FRAME_CALLBACK     CallBack,
  IN VOID                   *Context
  )
/*++

Routine Description:

  Wrap a transmit request into a newly allocated IP4_LINK_TX_TOKEN.

Arguments:

  Interface   - The interface to send out from
  IpInstance  - The IpInstance that transmit the packet. 
                NULL if the packet is sent by the IP4 driver itself.
  Packet      - The packet to transmit
  CallBack    - Call back function to execute if transmission finished.
  Context     - Opaque parameter to the call back.

Returns:

  The wrapped token if succeed or NULL

--*/
{
  EFI_MANAGED_NETWORK_COMPLETION_TOKEN  *MnpToken;
  EFI_MANAGED_NETWORK_TRANSMIT_DATA     *MnpTxData;
  IP4_LINK_TX_TOKEN                     *Token;
  EFI_STATUS                            Status;
  UINT32                                Count;

  Token = NetAllocatePool (sizeof (IP4_LINK_TX_TOKEN) + \
            (Packet->BlockOpNum - 1) * sizeof (EFI_MANAGED_NETWORK_FRAGMENT_DATA));

  if (Token == NULL) {
    return NULL;
  }

  Token->Signature = IP4_FRAME_TX_SIGNATURE;
  NetListInit (&Token->Link);

  Token->Interface  = Interface;
  Token->IpInstance = IpInstance;
  Token->CallBack   = CallBack;
  Token->Packet     = Packet;
  Token->Context    = Context;
  Token->DstMac     = mZeroMacAddress;
  Token->SrcMac     = Interface->Mac;

  MnpToken          = &(Token->MnpToken);
  MnpToken->Status  = EFI_NOT_READY;

  Status = gBS->CreateEvent (
                  EFI_EVENT_NOTIFY_SIGNAL,
                  EFI_TPL_CALLBACK,
                  Ip4OnFrameSent,
                  Token,
                  &MnpToken->Event
                  );

  if (EFI_ERROR (Status)) {
    NetFreePool (Token);
    return NULL;
  }

  MnpTxData                     = &Token->MnpTxData;
  MnpToken->Packet.TxData       = MnpTxData;

  MnpTxData->DestinationAddress = &Token->DstMac;
  MnpTxData->SourceAddress      = &Token->SrcMac;
  MnpTxData->ProtocolType       = IP4_ETHER_PROTO;
  MnpTxData->DataLength         = Packet->TotalSize;
  MnpTxData->HeaderLength       = 0;

  Count                         = Packet->BlockOpNum;
  
  NetbufBuildExt (Packet, (NET_FRAGMENT *) MnpTxData->FragmentTable, &Count);
  MnpTxData->FragmentCount      = (UINT16)Count;

  return Token;
}

STATIC
VOID
Ip4FreeLinkTxToken (
  IN IP4_LINK_TX_TOKEN      *Token
  )
/*++

Routine Description:

  Free the link layer transmit token. It will close the event
  then free the memory used.

Arguments:

  Token - Token to free

Returns:

  NONE

--*/
{
  NET_CHECK_SIGNATURE (Token, IP4_FRAME_TX_SIGNATURE);

  gBS->CloseEvent (Token->MnpToken.Event);
  NetFreePool (Token);
}

STATIC
IP4_ARP_QUE *
Ip4CreateArpQue (
  IN IP4_INTERFACE          *Interface,
  IN IP4_ADDR               DestIp
  )
/*++

Routine Description:

  Create an IP_ARP_QUE structure to request ARP service.

Arguments:

  Interface - The interface to send ARP from.
  DestIp    - The destination IP (host byte order) to request MAC for

Returns:

  Point to newly created IP4_ARP_QUE if succeed, otherwise NULL.

--*/
{
  IP4_ARP_QUE               *ArpQue;
  EFI_STATUS                Status;

  ArpQue = NetAllocatePool (sizeof (IP4_ARP_QUE));

  if (ArpQue == NULL) {
    return NULL;
  }

  ArpQue->Signature = IP4_FRAME_ARP_SIGNATURE;
  NetListInit (&ArpQue->Link);

  NetListInit (&ArpQue->Frames);
  ArpQue->Interface = Interface;

  Status = gBS->CreateEvent (
                  EFI_EVENT_NOTIFY_SIGNAL,
                  EFI_TPL_CALLBACK,
                  Ip4OnArpResolved,
                  ArpQue,
                  &ArpQue->OnResolved
                  );

  if (EFI_ERROR (Status)) {
    NetFreePool (ArpQue);
    return NULL;
  }

  ArpQue->Ip  = DestIp;
  ArpQue->Mac = mZeroMacAddress;

  return ArpQue;
}

STATIC
VOID
Ip4FreeArpQue (
  IN IP4_ARP_QUE            *ArpQue,
  IN EFI_STATUS             IoStatus
  )
/*++

Routine Description:

  Remove all the transmit requests queued on the ARP queue, then free it.

Arguments:

  ArpQue    - Arp queue to free
  IoStatus  - The transmit status returned to transmit requests' callback.

Returns:

  NONE

--*/
{
  NET_CHECK_SIGNATURE (ArpQue, IP4_FRAME_ARP_SIGNATURE);

  //
  // Remove all the frame waiting the ARP response
  //
  Ip4CancelFrameArp (ArpQue, IoStatus, NULL, NULL);

  gBS->CloseEvent (ArpQue->OnResolved);
  NetFreePool (ArpQue);
}

STATIC
IP4_LINK_RX_TOKEN *
Ip4CreateLinkRxToken (
  IN IP4_INTERFACE          *Interface,
  IN IP4_PROTOCOL           *IpInstance,
  IN IP4_FRAME_CALLBACK     CallBack,
  IN VOID                   *Context
  )
/*++

Routine Description:

  Create a link layer receive token to wrap the receive request

Arguments:

  Interface   - The interface to receive from
  IpInstance  - The instance that request the receive (NULL for IP4 driver itself)
  CallBack    - Call back function to execute when finished.
  Context     - Opaque parameters to the callback

Returns:

  Point to created IP4_LINK_RX_TOKEN if succeed, otherwise NULL.

--*/
{
  EFI_MANAGED_NETWORK_COMPLETION_TOKEN  *MnpToken;
  IP4_LINK_RX_TOKEN                     *Token;
  EFI_STATUS                            Status;

  Token = NetAllocatePool (sizeof (IP4_LINK_RX_TOKEN));
  if (Token == NULL) {
    return NULL;
  }

  Token->Signature  = IP4_FRAME_RX_SIGNATURE;
  Token->Interface  = Interface;
  Token->IpInstance = IpInstance;
  Token->CallBack   = CallBack;
  Token->Context    = Context;

  MnpToken          = &Token->MnpToken;
  MnpToken->Status  = EFI_NOT_READY;

  Status = gBS->CreateEvent (
                  EFI_EVENT_NOTIFY_SIGNAL,
                  EFI_TPL_CALLBACK,
                  Ip4OnFrameReceived,
                  Token,
                  &MnpToken->Event
                  );

  if (EFI_ERROR (Status)) {
    NetFreePool (Token);
    return NULL;
  }

  MnpToken->Packet.RxData = NULL;
  return Token;
}

STATIC
VOID
Ip4FreeFrameRxToken (
  IN IP4_LINK_RX_TOKEN      *Token
  )
/*++

Routine Description:

  Free the link layer request token. It will close the event
  then free the memory used.

Arguments:

  Token - Request token to free

Returns:

  NONE

--*/
{

  NET_CHECK_SIGNATURE (Token, IP4_FRAME_RX_SIGNATURE);

  gBS->CloseEvent (Token->MnpToken.Event);
  NetFreePool (Token);
}

STATIC
VOID
Ip4CancelFrameArp (
  IN IP4_ARP_QUE            *ArpQue,
  IN EFI_STATUS             IoStatus,
  IN IP4_FRAME_TO_CANCEL    FrameToCancel, OPTIONAL
  IN VOID                   *Context
  )
/*++

Routine Description:

  Remove all the frames on the ARP queue that pass the FrameToCancel, 
  that is, either FrameToCancel is NULL or it returns true for the frame.

Arguments:

  ArpQue        - ARP frame to remove the frames from.
  IoStatus      - The status returned to the cancelled frames' callback function.
  FrameToCancel - Function to select which frame to cancel.
  Context       - Opaque parameter to the FrameToCancel.

Returns:

  NONE

--*/
{
  NET_LIST_ENTRY            *Entry;
  NET_LIST_ENTRY            *Next;
  IP4_LINK_TX_TOKEN         *Token;

  NET_LIST_FOR_EACH_SAFE (Entry, Next, &ArpQue->Frames) {
    Token = NET_LIST_USER_STRUCT (Entry, IP4_LINK_TX_TOKEN, Link);

    if ((FrameToCancel == NULL) || FrameToCancel (Token, Context)) {
      NetListRemoveEntry (Entry);

      Token->CallBack (Token->IpInstance, Token->Packet, IoStatus, 0, Token->Context);
      Ip4FreeLinkTxToken (Token);
    }
  }
}

VOID
Ip4CancelFrames (
  IN IP4_INTERFACE          *Interface,
  IN EFI_STATUS             IoStatus,
  IN IP4_FRAME_TO_CANCEL    FrameToCancel,   OPTIONAL
  IN VOID                   *Context
  )
/*++

Routine Description:

  Remove all the frames on the interface that pass the FrameToCancel, 
  either queued on ARP queues or that have already been delivered to 
  MNP and not yet recycled.

Arguments:

  Interface     - Interface to remove the frames from
  IoStatus      - The transmit status returned to the frames' callback
  FrameToCancel - Function to select the frame to cancel, NULL to select all
  Context       - Opaque parameters passed to FrameToCancel

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?