udp4io.c

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

C
814
字号

  EFI_SUCCESS - The UDP IO port is freed.

--*/
{
  UDP_RX_TOKEN  *RxToken;

  //
  // Cancel all the sent datagram and receive requests. The
  // callbacks of transmit requests are executed to allow the 
  // caller to release the resource. The callback of receive
  // request are NOT executed. This is because it is most 
  // likely that the current user of the UDP IO port is closing
  // itself. 
  //
  UdpIoCancelDgrams (UdpIo, EFI_ABORTED, NULL, NULL);

  if ((RxToken = UdpIo->RecvRequest) != NULL) {
    UdpIo->RecvRequest = NULL;
    UdpIo->Udp->Cancel (UdpIo->Udp, &RxToken->UdpToken);
    UdpIoFreeRxToken (RxToken);
  }
  
  //
  // Close then destory the UDP child
  //
  gBS->CloseProtocol (
         UdpIo->UdpHandle,
         &gEfiUdp4ProtocolGuid,
         UdpIo->Image,
         UdpIo->Controller
         );

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

  NetListRemoveEntry (&UdpIo->Link);
  NetFreePool (UdpIo);
  return EFI_SUCCESS;
}

VOID
UdpIoCleanPort (
  IN  UDP_IO_PORT           *UdpIo
  )
/*++

Routine Description:

  Clean up the UDP IO port. It will release all the transmitted
  datagrams and receive request. It will also configure NULL the
  UDP child.

Arguments:

  UdpIo - UDP IO port to clean up.

Returns:

  None

--*/
{
  UDP_RX_TOKEN              *RxToken;

  //
  // Cancel all the sent datagram and receive requests.
  //
  UdpIoCancelDgrams (UdpIo, EFI_ABORTED, NULL, NULL);

  if ((RxToken = UdpIo->RecvRequest) != NULL) {
    UdpIo->RecvRequest = NULL;
    UdpIo->Udp->Cancel (UdpIo->Udp, &RxToken->UdpToken);
    UdpIoFreeRxToken (RxToken);
  }

  UdpIo->Udp->Configure (UdpIo->Udp, NULL);
}

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

Routine Description:

  The callback function when the packet is sent by UDP.
  It will remove the packet from the local list then call
  the packet owner's callback function.
  
Arguments:

  Event   - The event signalled.
  Context - The UDP TX Token.

Returns:

  None

--*/
{
  UDP_TX_TOKEN              *Token;
  EFI_TPL                   OldTpl;

  OldTpl  = NET_RAISE_TPL (NET_TPL_LOCK);

  Token   = (UDP_TX_TOKEN *) Context;
  ASSERT (Token->Signature == UDP_IO_TX_SIGNATURE);

  NetListRemoveEntry (&Token->Link);
  Token->CallBack (Token->Packet, NULL, Token->UdpToken.Status, Token->Context);

  UdpIoFreeTxToken (Token);

  NET_RESTORE_TPL (OldTpl);
}

EFI_STATUS
UdpIoSendDatagram (
  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:

  Send a packet through the UDP IO port.

Arguments:

  UdpIo     - The UDP IO Port to send the packet through
  Packet    - The packet to send
  EndPoint  - The local and remote access point
  Gateway   - The gateway to use
  CallBack  - The call back function to call when packet is 
              transmitted or failed.
  Context   - The opque parameter to the CallBack

Returns:

  EFI_OUT_OF_RESOURCES - Failed to allocate resource for the packet
  EFI_SUCCESS          - The packet is successfully delivered to UDP 
                         for transmission.

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

  Token = UdpIoWrapTx (UdpIo, Packet, EndPoint, Gateway, CallBack, Context);
  
  if (Token == NULL) {
    return EFI_OUT_OF_RESOURCES;
  }

  Status = UdpIo->Udp->Transmit (UdpIo->Udp, &Token->UdpToken);

  if (EFI_ERROR (Status)) {
    UdpIoFreeTxToken (Token);
    return Status;
  }

  NetListInsertHead (&UdpIo->SentDatagram, &Token->Link);
  return EFI_SUCCESS;
}

STATIC
BOOLEAN
UdpIoCancelSingleDgram (
  IN UDP_TX_TOKEN           *Token,
  IN VOID                   *Context
  )
/*++

Routine Description:

  The selection function to cancel a single sent datagram.

Arguments:

  Token   - The UDP TX token to test againist.
  Context - The context

Returns:

  TRUE if the packet is to be cancelled, otherwise FALSE.

--*/
{
  NET_BUF                   *Packet;

  Packet = (NET_BUF *) Context;

  if (Token->Packet == Packet) {
    return TRUE;
  }

  return FALSE;
}

VOID
UdpIoCancelSentDatagram (
  IN  UDP_IO_PORT           *UdpIo,
  IN  NET_BUF               *Packet
  )
/*++

Routine Description:

  Cancel a single sent datagram.

Arguments:

  UdpIo   - The UDP IO port to cancel the packet from
  Packet  - The packet to cancel

Returns:

  None

--*/
{
  UdpIoCancelDgrams (UdpIo, EFI_ABORTED, UdpIoCancelSingleDgram, Packet);
}

STATIC
VOID
UdpIoRecycleDgram (
  IN VOID                   *Context
  )
/*++

Routine Description:

  Recycle the received UDP data. 

Arguments:

  Context - The UDP_RX_TOKEN

Returns:

  None

--*/
{
  UDP_RX_TOKEN              *Token;

  Token = (UDP_RX_TOKEN *) Context;
  gBS->SignalEvent (Token->UdpToken.Packet.RxData->RecycleSignal);
  UdpIoFreeRxToken (Token);
}

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

Routine Description:

  The event handle for UDP receive request. It will build
  a NET_BUF from the recieved UDP data, then deliver it 
  to the receiver. 

Arguments:

  Event   - The UDP receive request event
  Context - The UDP RX token.

Returns:

  None

--*/
{
  EFI_UDP4_COMPLETION_TOKEN *UdpToken;
  EFI_UDP4_RECEIVE_DATA     *UdpRxData;
  EFI_UDP4_SESSION_DATA     *UdpSession;
  UDP_RX_TOKEN              *Token;
  UDP_POINTS                Points;
  EFI_TPL                   OldTpl;
  NET_BUF                   *Netbuf;

  OldTpl  = NET_RAISE_TPL (NET_TPL_LOCK);
  Token   = (UDP_RX_TOKEN *) Context;

  ASSERT ((Token->Signature == UDP_IO_RX_SIGNATURE) && 
          (Token == Token->UdpIo->RecvRequest));

  //
  // Clear the receive request first in case that the caller 
  // wants to restart the receive in the callback.
  //
  Token->UdpIo->RecvRequest = NULL;
  
  UdpToken  = &Token->UdpToken;
  UdpRxData = UdpToken->Packet.RxData;

  if (EFI_ERROR (UdpToken->Status) || (UdpRxData == NULL)) {
    Token->CallBack (NULL, NULL, UdpToken->Status, Token->Context);
    UdpIoFreeRxToken (Token);

    goto ON_EXIT;
  }

  //
  // Build a NET_BUF from the UDP receive data, then deliver it up.
  //
  Netbuf = NetbufFromExt (
             (NET_FRAGMENT *) UdpRxData->FragmentTable,
             UdpRxData->FragmentCount,
             0,
             (UINT32) Token->HeadLen,
             UdpIoRecycleDgram,
             Token
             );

  if (Netbuf == NULL) {
    gBS->SignalEvent (UdpRxData->RecycleSignal);
    Token->CallBack (NULL, NULL, EFI_OUT_OF_RESOURCES, Token->Context);

    UdpIoFreeRxToken (Token);
    goto ON_EXIT;
  }

  UdpSession        = &UdpRxData->UdpSession;
  Points.LocalAddr  = EFI_NTOHL (UdpSession->DestinationAddress);
  Points.LocalPort  = UdpSession->DestinationPort;
  Points.RemoteAddr = EFI_NTOHL (UdpSession->SourceAddress);
  Points.RemotePort = UdpSession->SourcePort;

  Token->CallBack (Netbuf, &Points, EFI_SUCCESS, Token->Context);

ON_EXIT:
  NET_RESTORE_TPL (OldTpl);
  return;
}

EFI_STATUS
UdpIoRecvDatagram (
  IN  UDP_IO_PORT           *UdpIo,
  IN  UDP_IO_CALLBACK       CallBack,
  IN  VOID                  *Context,
  IN  UINT32                HeadLen
  )
/*++

Routine Description:

  Issue a receive request to the UDP IO port.

Arguments:

  UdpIo     - The UDP IO port to recieve the packet from.
  CallBack  - The call back function to execute when receive finished.
  Context   - The opque context to the call back
  HeadLen   - The lenght of the application's header

Returns:

  EFI_ALREADY_STARTED  - There is already a pending receive request. Only
                         one receive request is supported.
  EFI_OUT_OF_RESOURCES - Failed to allocate some resource.
  EFI_SUCCESS          - The receive request is issued successfully.

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

  if (UdpIo->RecvRequest != NULL) {
    return EFI_ALREADY_STARTED;
  }

  Token = UdpIoCreateRxToken (UdpIo, CallBack, Context, HeadLen);

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

  Status = UdpIo->Udp->Receive (UdpIo->Udp, &Token->UdpToken);

  if (EFI_ERROR (Status)) {
    UdpIoFreeRxToken (Token);
    return Status;
  }

  UdpIo->RecvRequest = Token;
  return EFI_SUCCESS;
}

⌨️ 快捷键说明

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