udp4io.c

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

C
814
字号
/*++

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:

  Udp4Io.c

Abstract:

  Help functions to access UDP service, it is used by both the DHCP and MTFTP.
  
--*/

#include "Udp4Io.h"

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

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

STATIC
UDP_TX_TOKEN *
UdpIoWrapTx (
  IN UDP_IO_PORT            *UdpIo,
  IN NET_BUF                *Packet,
  IN UDP_POINTS             *EndPoint, OPTIONAL
  IN IP4_ADDR               Gateway,
  IN UDP_IO_CALLBACK        CallBack,
  IN VOID                   *Context
  )
/*++

Routine Description:

  Wrap a transmit request into a UDP_TX_TOKEN.

Arguments:

  UdpIo     - The UdpIo port to send packet to
  Packet    - The user's packet
  EndPoint  - The local and remote access point
  Gateway   - The overrided next hop
  CallBack  - The function to call when transmission completed.
  Context   - The opaque parameter to the call back

Returns:

  The wrapped transmission request or NULL if failed to allocate resources.

--*/
{
  UDP_TX_TOKEN              *Token;
  EFI_UDP4_COMPLETION_TOKEN *UdpToken;
  EFI_UDP4_TRANSMIT_DATA    *UdpTxData;
  EFI_STATUS                Status;
  UINT32                    Count;

  Token = NetAllocatePool (sizeof (UDP_TX_TOKEN) + 
                           sizeof (EFI_UDP4_FRAGMENT_DATA) * (Packet->BlockOpNum - 1));

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

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

  Token->UdpIo      = UdpIo;
  Token->CallBack   = CallBack;
  Token->Packet     = Packet;
  Token->Context    = Context;

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

  Status = gBS->CreateEvent (
                  EFI_EVENT_NOTIFY_SIGNAL,
                  EFI_TPL_CALLBACK,
                  UdpIoOnDgramSent,
                  Token,
                  &UdpToken->Event
                  );

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

  UdpTxData                 = &Token->UdpTxData;
  UdpToken->Packet.TxData   = UdpTxData;

  UdpTxData->UdpSessionData = NULL;
  UdpTxData->GatewayAddress = NULL;

  if (EndPoint != NULL) {
    EFI_IP4 (Token->UdpSession.SourceAddress)      = HTONL (EndPoint->LocalAddr);
    EFI_IP4 (Token->UdpSession.DestinationAddress) = HTONL (EndPoint->RemoteAddr);
    Token->UdpSession.SourcePort                   = EndPoint->LocalPort;
    Token->UdpSession.DestinationPort              = EndPoint->RemotePort;
    UdpTxData->UdpSessionData                      = &Token->UdpSession;
  }

  if (Gateway != 0) {
    EFI_IP4 (Token->Gateway)  = HTONL (Gateway);
    UdpTxData->GatewayAddress = &Token->Gateway;
  }

  UdpTxData->DataLength = Packet->TotalSize;
  Count                 = Packet->BlockOpNum;
  NetbufBuildExt (Packet, (NET_FRAGMENT *) UdpTxData->FragmentTable, &Count);
  UdpTxData->FragmentCount = Count;

  return Token;
}

VOID
UdpIoFreeTxToken (
  IN UDP_TX_TOKEN           *Token
  )
/*++

Routine Description:

  Free a UDP_TX_TOKEN. The event is closed and memory released.

Arguments:

  Token - The UDP_TX_TOKEN to release.

Returns:

  None

--*/
{
  gBS->CloseEvent (Token->UdpToken.Event);
  NetFreePool (Token);
}

UDP_RX_TOKEN *
UdpIoCreateRxToken (
  IN UDP_IO_PORT            *UdpIo,
  IN UDP_IO_CALLBACK        CallBack,
  IN VOID                   *Context,
  IN UINT32                 HeadLen
  )
/*++

Routine Description:

  Create a UDP_RX_TOKEN to wrap the request.

Arguments:

  UdpIo     - The UdpIo to receive packets from
  CallBack  - The function to call when receive finished.
  Context   - The opaque parameter to the CallBack
  HeadLen   - The head length to reserver for the packet.

Returns:

  The Wrapped request or NULL if failed to allocate resources.

--*/
{
  UDP_RX_TOKEN              *Token;
  EFI_STATUS                Status;

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

  Token->Signature              = UDP_IO_RX_SIGNATURE;
  Token->UdpIo                  = UdpIo;
  Token->CallBack               = CallBack;
  Token->Context                = Context;
  Token->HeadLen                = HeadLen;

  Token->UdpToken.Status        = EFI_NOT_READY;
  Token->UdpToken.Packet.RxData = NULL;

  Status = gBS->CreateEvent (
                  EFI_EVENT_NOTIFY_SIGNAL,
                  EFI_TPL_CALLBACK,
                  UdpIoOnDgramRcvd,
                  Token,
                  &Token->UdpToken.Event
                  );

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

  return Token;
}

VOID
UdpIoFreeRxToken (
  IN UDP_RX_TOKEN           *Token
  )
/*++

Routine Description:

  Free a receive request wrap.

Arguments:

  Token - The receive request to release.

Returns:

  None

--*/
{
  gBS->CloseEvent (Token->UdpToken.Event);
  NetFreePool (Token);
}

UDP_IO_PORT *
UdpIoCreatePort (
  IN  EFI_HANDLE            Controller,
  IN  EFI_HANDLE            Image,
  IN  UDP_IO_CONFIG         Configure,
  IN  VOID                  *Context
  )
/*++

Routine Description:

  Create a UDP IO port to access the UDP service. It will 
  create and configure a UDP child.

Arguments:

  Controller  - The controller that has the UDP service binding protocol installed.
  Image       - The image handle for the driver.
  Configure   - The function to configure the created UDP child
  Context     - The opaque parameter for the Configure funtion.

Returns:

  A point to just created UDP IO port or NULL if failed.

--*/
{
  UDP_IO_PORT               *UdpIo;
  EFI_STATUS                Status;

  ASSERT (Configure != NULL);

  UdpIo = NetAllocatePool (sizeof (UDP_IO_PORT));
  
  if (UdpIo == NULL) {
    return NULL;
  }

  UdpIo->Signature    = UDP_IO_SIGNATURE;
  NetListInit (&UdpIo->Link);
  UdpIo->RefCnt       = 1;

  UdpIo->Controller   = Controller;
  UdpIo->Image        = Image;

  NetListInit (&UdpIo->SentDatagram);
  UdpIo->RecvRequest  = NULL;
  UdpIo->UdpHandle    = NULL;

  //
  // Create a UDP child then open and configure it
  //
  Status = NetLibCreateServiceChild (
             Controller,
             Image,
             &gEfiUdp4ServiceBindingProtocolGuid,
             &UdpIo->UdpHandle
             );

  if (EFI_ERROR (Status)) {
    goto FREE_MEM;
  }

  Status = gBS->OpenProtocol (
                  UdpIo->UdpHandle,
                  &gEfiUdp4ProtocolGuid,
                  &UdpIo->Udp,
                  Image,
                  Controller,
                  EFI_OPEN_PROTOCOL_BY_DRIVER
                  );

  if (EFI_ERROR (Status)) {
    goto FREE_CHILD;
  }

  if (EFI_ERROR (Configure (UdpIo, Context))) {
    goto CLOSE_PROTOCOL;
  }

  Status = UdpIo->Udp->GetModeData (UdpIo->Udp, NULL, NULL, NULL, &UdpIo->SnpMode);

  if (EFI_ERROR (Status)) {
    goto CLOSE_PROTOCOL;
  }

  return UdpIo;

CLOSE_PROTOCOL:
  gBS->CloseProtocol (UdpIo->UdpHandle, &gEfiUdp4ProtocolGuid, Image, Controller);

FREE_CHILD:
  NetLibDestroyServiceChild (
    Controller,
    Image,
    &gEfiUdp4ServiceBindingProtocolGuid,
    UdpIo->UdpHandle
    );

FREE_MEM:
  NetFreePool (UdpIo);
  return NULL;
}

STATIC
VOID
UdpIoCancelDgrams (
  IN UDP_IO_PORT            *UdpIo,
  IN EFI_STATUS             IoStatus,
  IN UDP_IO_TO_CANCEL       ToCancel,        OPTIONAL
  IN VOID                   *Context
  )
/*++

Routine Description:

  Cancel all the sent datagram that pass the selection of ToCancel. 
  If ToCancel is NULL, all the datagrams are cancelled.

Arguments:

  UdpIo     - The UDP IO port to cancel packet
  IoStatus  - The IoStatus to return to the packet owners.
  ToCancel  - The select funtion to test whether to cancel this packet or not.
  Context   - The opaque parameter to the ToCancel.

Returns:

  None

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

  NET_LIST_FOR_EACH_SAFE (Entry, Next, &UdpIo->SentDatagram) {
    Token = NET_LIST_USER_STRUCT (Entry, UDP_TX_TOKEN, Link);

    if ((ToCancel == NULL) || (ToCancel (Token, Context))) {
      NetListRemoveEntry (Entry);
      UdpIo->Udp->Cancel (UdpIo->Udp, &Token->UdpToken);
      Token->CallBack (Token->Packet, NULL, IoStatus, Token->Context);
      UdpIoFreeTxToken (Token);
    }
  }
}

EFI_STATUS
UdpIoFreePort (
  IN  UDP_IO_PORT           *UdpIo
  )
/*++

Routine Description:

  Free the UDP IO port and all its related resources including 
  all the transmitted packet.

Arguments:

  UdpIo - The UDP IO port to free.

Returns:

⌨️ 快捷键说明

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