]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.c
Fix filer header
[mirror_edk2.git] / MdeModulePkg / Library / DxeUdpIoLib / DxeUdpIoLib.c
index d56456afb20e59aabde2f1643e6d7c7e729dd1af..39d3cc9a9507ad819c29680fcc758ffff4946492 100644 (file)
@@ -1,6 +1,7 @@
 /** @file\r
-\r
-Copyright (c) 2006 - 2007, Intel Corporation\r
+  Help functions to access UDP service, it is used by both the DHCP and MTFTP.\r
+  \r
+Copyright (c) 2005 - 2007, Intel Corporation.<BR>\r
 All rights reserved. This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -8,17 +9,6 @@ http://opensource.org/licenses/bsd-license.php
 \r
 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-\r
-Module Name:\r
-\r
-  Udp4Io.c\r
-\r
-Abstract:\r
-\r
-  Help functions to access UDP service, it is used by both the DHCP and MTFTP.\r
-\r
-\r
 **/\r
 \r
 #include <PiDxe.h>\r
@@ -30,139 +20,201 @@ Abstract:
 #include <Library/DebugLib.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
 #include <Library/MemoryAllocationLib.h>\r
-#include <library/BaseMemoryLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+\r
+\r
+/**\r
+  Free a UDP_TX_TOKEN. The event is closed and memory released.\r
 \r
-STATIC\r
+  @param  Token                 The UDP_TX_TOKEN to release.\r
+\r
+**/\r
 VOID\r
-EFIAPI\r
-UdpIoOnDgramSent (\r
-  IN EFI_EVENT              Event,\r
-  IN VOID                   *Context\r
-  );\r
+UdpIoFreeTxToken (\r
+  IN UDP_TX_TOKEN           *Token\r
+  )\r
+{\r
+  gBS->CloseEvent (Token->UdpToken.Event);\r
+  gBS->FreePool (Token);\r
+}\r
 \r
-STATIC\r
+/**\r
+  Free a receive request wrap.\r
+\r
+  @param  Token                 The receive request to release.\r
+\r
+**/\r
+VOID\r
+UdpIoFreeRxToken (\r
+  IN UDP_RX_TOKEN           *Token\r
+  )\r
+{\r
+  gBS->CloseEvent (Token->UdpToken.Event);\r
+  gBS->FreePool (Token);\r
+}\r
+\r
+/**\r
+  The callback function when the packet is sent by UDP.\r
+  It will remove the packet from the local list then call\r
+  the packet owner's callback function.\r
+\r
+  @param  Context               The UDP TX Token.\r
+\r
+**/\r
 VOID\r
 EFIAPI\r
-UdpIoOnDgramRcvd (\r
-  IN EFI_EVENT              Event,\r
+UdpIoOnDgramSentDpc (\r
   IN VOID                   *Context\r
-  );\r
+  )\r
+{\r
+  UDP_TX_TOKEN              *Token;\r
 \r
+  Token   = (UDP_TX_TOKEN *) Context;\r
+  ASSERT (Token->Signature == UDP_IO_TX_SIGNATURE);\r
 \r
-/**\r
-  Wrap a transmit request into a UDP_TX_TOKEN.\r
+  RemoveEntryList (&Token->Link);\r
+  Token->CallBack (Token->Packet, NULL, Token->UdpToken.Status, Token->Context);\r
 \r
-  @param  UdpIo                 The UdpIo port to send packet to\r
-  @param  Packet                The user's packet\r
-  @param  EndPoint              The local and remote access point\r
-  @param  Gateway               The overrided next hop\r
-  @param  CallBack              The function to call when transmission completed.\r
-  @param  Context               The opaque parameter to the call back\r
+  UdpIoFreeTxToken (Token);\r
+}\r
 \r
-  @return The wrapped transmission request or NULL if failed to allocate resources.\r
+/**\r
+  Request UdpIoOnDgramSentDpc as a DPC at TPL_CALLBACK.\r
+  \r
+  @param  Event                 The event signaled.\r
+  @param  Context               The UDP TX Token.\r
 \r
 **/\r
-STATIC\r
-UDP_TX_TOKEN *\r
-UdpIoWrapTx (\r
-  IN UDP_IO_PORT            *UdpIo,\r
-  IN NET_BUF                *Packet,\r
-  IN UDP_POINTS             *EndPoint, OPTIONAL\r
-  IN IP4_ADDR               Gateway,\r
-  IN UDP_IO_CALLBACK        CallBack,\r
+VOID\r
+EFIAPI\r
+UdpIoOnDgramSent (\r
+  IN EFI_EVENT              Event,\r
   IN VOID                   *Context\r
   )\r
 {\r
-  UDP_TX_TOKEN              *Token;\r
-  EFI_UDP4_COMPLETION_TOKEN *UdpToken;\r
-  EFI_UDP4_TRANSMIT_DATA    *UdpTxData;\r
-  EFI_STATUS                Status;\r
-  UINT32                    Count;\r
-  IP4_ADDR                  Ip;\r
+  //\r
+  // Request UdpIoOnDgramSentDpc as a DPC at TPL_CALLBACK\r
+  //\r
+  NetLibQueueDpc (TPL_CALLBACK, UdpIoOnDgramSentDpc, Context);\r
+}\r
 \r
-  Token = NetAllocatePool (sizeof (UDP_TX_TOKEN) +\r
-                           sizeof (EFI_UDP4_FRAGMENT_DATA) * (Packet->BlockOpNum - 1));\r
+/**\r
+  Recycle the received UDP data.\r
 \r
-  if (Token == NULL) {\r
-    return NULL;\r
-  }\r
+  @param  Context               The UDP_RX_TOKEN\r
 \r
-  Token->Signature  = UDP_IO_TX_SIGNATURE;\r
-  NetListInit (&Token->Link);\r
+**/\r
+VOID\r
+UdpIoRecycleDgram (\r
+  IN VOID                   *Context\r
+  )\r
+{\r
+  UDP_RX_TOKEN              *Token;\r
 \r
-  Token->UdpIo      = UdpIo;\r
-  Token->CallBack   = CallBack;\r
-  Token->Packet     = Packet;\r
-  Token->Context    = Context;\r
+  Token = (UDP_RX_TOKEN *) Context;\r
+  gBS->SignalEvent (Token->UdpToken.Packet.RxData->RecycleSignal);\r
+  UdpIoFreeRxToken (Token);\r
+}\r
 \r
-  UdpToken          = &(Token->UdpToken);\r
-  UdpToken->Status  = EFI_NOT_READY;\r
+/**\r
+  The event handle for UDP receive request. It will build\r
+  a NET_BUF from the recieved UDP data, then deliver it\r
+  to the receiver.\r
 \r
-  Status = gBS->CreateEvent (\r
-                  EVT_NOTIFY_SIGNAL,\r
-                  TPL_CALLBACK,\r
-                  UdpIoOnDgramSent,\r
-                  Token,\r
-                  &UdpToken->Event\r
-                  );\r
+  @param  Context               The UDP RX token.\r
 \r
-  if (EFI_ERROR (Status)) {\r
-    NetFreePool (Token);\r
-    return NULL;\r
-  }\r
+**/\r
+VOID\r
+EFIAPI\r
+UdpIoOnDgramRcvdDpc (\r
+  IN VOID                   *Context\r
+  )\r
+{\r
+  EFI_UDP4_COMPLETION_TOKEN *UdpToken;\r
+  EFI_UDP4_RECEIVE_DATA     *UdpRxData;\r
+  EFI_UDP4_SESSION_DATA     *UdpSession;\r
+  UDP_RX_TOKEN              *Token;\r
+  UDP_POINTS                Points;\r
+  NET_BUF                   *Netbuf;\r
 \r
-  UdpTxData                 = &Token->UdpTxData;\r
-  UdpToken->Packet.TxData   = UdpTxData;\r
+  Token   = (UDP_RX_TOKEN *) Context;\r
 \r
-  UdpTxData->UdpSessionData = NULL;\r
-  UdpTxData->GatewayAddress = NULL;\r
+  ASSERT ((Token->Signature == UDP_IO_RX_SIGNATURE) &&\r
+          (Token == Token->UdpIo->RecvRequest));\r
 \r
-  if (EndPoint != NULL) {\r
-    Ip = HTONL (EndPoint->LocalAddr);\r
-    NetCopyMem (&Token->UdpSession.SourceAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
+  //\r
+  // Clear the receive request first in case that the caller\r
+  // wants to restart the receive in the callback.\r
+  //\r
+  Token->UdpIo->RecvRequest = NULL;\r
 \r
-    Ip = HTONL (EndPoint->RemoteAddr);\r
-    NetCopyMem (&Token->UdpSession.DestinationAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
+  UdpToken  = &Token->UdpToken;\r
+  UdpRxData = UdpToken->Packet.RxData;\r
 \r
-    Token->UdpSession.SourcePort      = EndPoint->LocalPort;\r
-    Token->UdpSession.DestinationPort = EndPoint->RemotePort;\r
-    UdpTxData->UdpSessionData         = &Token->UdpSession;\r
+  if (EFI_ERROR (UdpToken->Status) || (UdpRxData == NULL)) {\r
+    if (UdpToken->Status != EFI_ABORTED) {\r
+      //\r
+      // Invoke the CallBack only if the reception is not actively aborted.\r
+      //\r
+      Token->CallBack (NULL, NULL, UdpToken->Status, Token->Context);\r
+    }\r
+\r
+    UdpIoFreeRxToken (Token);\r
+    return;\r
   }\r
 \r
-  if (Gateway != 0) {\r
-    Ip = HTONL (Gateway);\r
-    NetCopyMem (&Token->Gateway, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
+  //\r
+  // Build a NET_BUF from the UDP receive data, then deliver it up.\r
+  //\r
+  Netbuf = NetbufFromExt (\r
+             (NET_FRAGMENT *) UdpRxData->FragmentTable,\r
+             UdpRxData->FragmentCount,\r
+             0,\r
+             (UINT32) Token->HeadLen,\r
+             UdpIoRecycleDgram,\r
+             Token\r
+             );\r
 \r
-    UdpTxData->GatewayAddress = &Token->Gateway;\r
+  if (Netbuf == NULL) {\r
+    gBS->SignalEvent (UdpRxData->RecycleSignal);\r
+    Token->CallBack (NULL, NULL, EFI_OUT_OF_RESOURCES, Token->Context);\r
+\r
+    UdpIoFreeRxToken (Token);\r
+    return;\r
   }\r
 \r
-  UdpTxData->DataLength = Packet->TotalSize;\r
-  Count                 = Packet->BlockOpNum;\r
-  NetbufBuildExt (Packet, (NET_FRAGMENT *) UdpTxData->FragmentTable, &Count);\r
-  UdpTxData->FragmentCount = Count;\r
+  UdpSession        = &UdpRxData->UdpSession;\r
+  Points.LocalPort  = UdpSession->DestinationPort;\r
+  Points.RemotePort = UdpSession->SourcePort;\r
 \r
-  return Token;\r
-}\r
+  CopyMem (&Points.LocalAddr, &UdpSession->DestinationAddress, sizeof (IP4_ADDR));\r
+  CopyMem (&Points.RemoteAddr, &UdpSession->SourceAddress, sizeof (IP4_ADDR));\r
+  Points.LocalAddr  = NTOHL (Points.LocalAddr);\r
+  Points.RemoteAddr = NTOHL (Points.RemoteAddr);\r
 \r
+  Token->CallBack (Netbuf, &Points, EFI_SUCCESS, Token->Context);\r
+}\r
 \r
 /**\r
-  Free a UDP_TX_TOKEN. The event is closed and memory released.\r
-\r
-  @param  Token                 The UDP_TX_TOKEN to release.\r
+  Request UdpIoOnDgramRcvdDpc as a DPC at TPL_CALLBACK.\r
 \r
-  @return None\r
+  @param  Event                 The UDP receive request event.\r
+  @param  Context               The UDP RX token.\r
 \r
 **/\r
 VOID\r
-UdpIoFreeTxToken (\r
-  IN UDP_TX_TOKEN           *Token\r
+EFIAPI\r
+UdpIoOnDgramRcvd (\r
+  IN EFI_EVENT              Event,\r
+  IN VOID                   *Context\r
   )\r
 {\r
-  gBS->CloseEvent (Token->UdpToken.Event);\r
-  NetFreePool (Token);\r
+  //\r
+  // Request UdpIoOnDgramRcvdDpc as a DPC at TPL_CALLBACK\r
+  //\r
+  NetLibQueueDpc (TPL_CALLBACK, UdpIoOnDgramRcvdDpc, Context);\r
 }\r
 \r
-\r
 /**\r
   Create a UDP_RX_TOKEN to wrap the request.\r
 \r
@@ -171,7 +223,7 @@ UdpIoFreeTxToken (
   @param  Context               The opaque parameter to the CallBack\r
   @param  HeadLen               The head length to reserver for the packet.\r
 \r
-  @return The Wrapped request or NULL if failed to allocate resources.\r
+  @return The Wrapped request or NULL if failed to allocate resources or some errors happened.\r
 \r
 **/\r
 UDP_RX_TOKEN *\r
@@ -185,7 +237,7 @@ UdpIoCreateRxToken (
   UDP_RX_TOKEN              *Token;\r
   EFI_STATUS                Status;\r
 \r
-  Token = NetAllocatePool (sizeof (UDP_RX_TOKEN));\r
+  Token = AllocatePool (sizeof (UDP_RX_TOKEN));\r
 \r
   if (Token == NULL) {\r
     return NULL;\r
@@ -202,39 +254,118 @@ UdpIoCreateRxToken (
 \r
   Status = gBS->CreateEvent (\r
                   EVT_NOTIFY_SIGNAL,\r
-                  TPL_CALLBACK,\r
+                  TPL_NOTIFY,\r
                   UdpIoOnDgramRcvd,\r
                   Token,\r
                   &Token->UdpToken.Event\r
                   );\r
 \r
   if (EFI_ERROR (Status)) {\r
-    NetFreePool (Token);\r
+    gBS->FreePool (Token);\r
     return NULL;\r
   }\r
 \r
   return Token;\r
 }\r
 \r
-\r
 /**\r
-  Free a receive request wrap.\r
+  Wrap a transmit request into a UDP_TX_TOKEN.\r
 \r
-  @param  Token                 The receive request to release.\r
+  @param  UdpIo                 The UdpIo port to send packet to\r
+  @param  Packet                The user's packet\r
+  @param  EndPoint              The local and remote access point\r
+  @param  Gateway               The overrided next hop\r
+  @param  CallBack              The function to call when transmission completed.\r
+  @param  Context               The opaque parameter to the call back\r
 \r
-  @return None\r
+  @return The wrapped transmission request or NULL if failed to allocate resources \r
+          or for some errors.\r
 \r
 **/\r
-VOID\r
-UdpIoFreeRxToken (\r
-  IN UDP_RX_TOKEN           *Token\r
+UDP_TX_TOKEN *\r
+UdpIoWrapTx (\r
+  IN UDP_IO_PORT            *UdpIo,\r
+  IN NET_BUF                *Packet,\r
+  IN UDP_POINTS             *EndPoint, OPTIONAL\r
+  IN IP4_ADDR               Gateway,\r
+  IN UDP_IO_CALLBACK        CallBack,\r
+  IN VOID                   *Context\r
   )\r
 {\r
-  gBS->CloseEvent (Token->UdpToken.Event);\r
-  NetFreePool (Token);\r
+  UDP_TX_TOKEN              *Token;\r
+  EFI_UDP4_COMPLETION_TOKEN *UdpToken;\r
+  EFI_UDP4_TRANSMIT_DATA    *UdpTxData;\r
+  EFI_STATUS                Status;\r
+  UINT32                    Count;\r
+  IP4_ADDR                  Ip;\r
+\r
+  Token = AllocatePool (sizeof (UDP_TX_TOKEN) +\r
+                           sizeof (EFI_UDP4_FRAGMENT_DATA) * (Packet->BlockOpNum - 1));\r
+\r
+  if (Token == NULL) {\r
+    return NULL;\r
+  }\r
+\r
+  Token->Signature  = UDP_IO_TX_SIGNATURE;\r
+  InitializeListHead (&Token->Link);\r
+\r
+  Token->UdpIo      = UdpIo;\r
+  Token->CallBack   = CallBack;\r
+  Token->Packet     = Packet;\r
+  Token->Context    = Context;\r
+\r
+  UdpToken          = &(Token->UdpToken);\r
+  UdpToken->Status  = EFI_NOT_READY;\r
+\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_NOTIFY,\r
+                  UdpIoOnDgramSent,\r
+                  Token,\r
+                  &UdpToken->Event\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    gBS->FreePool (Token);\r
+    return NULL;\r
+  }\r
+\r
+  UdpTxData                 = &Token->UdpTxData;\r
+  UdpToken->Packet.TxData   = UdpTxData;\r
+\r
+  UdpTxData->UdpSessionData = NULL;\r
+  UdpTxData->GatewayAddress = NULL;\r
+\r
+  if (EndPoint != NULL) {\r
+    Ip = HTONL (EndPoint->LocalAddr);\r
+    CopyMem (&Token->UdpSession.SourceAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
+\r
+    Ip = HTONL (EndPoint->RemoteAddr);\r
+    CopyMem (&Token->UdpSession.DestinationAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
+\r
+    Token->UdpSession.SourcePort      = EndPoint->LocalPort;\r
+    Token->UdpSession.DestinationPort = EndPoint->RemotePort;\r
+    UdpTxData->UdpSessionData         = &Token->UdpSession;\r
+  }\r
+\r
+  if (Gateway != 0) {\r
+    Ip = HTONL (Gateway);\r
+    CopyMem (&Token->Gateway, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
+\r
+    UdpTxData->GatewayAddress = &Token->Gateway;\r
+  }\r
+\r
+  UdpTxData->DataLength = Packet->TotalSize;\r
+  Count                 = Packet->BlockOpNum;\r
+  NetbufBuildExt (Packet, (NET_FRAGMENT *) UdpTxData->FragmentTable, &Count);\r
+  UdpTxData->FragmentCount = Count;\r
+\r
+  return Token;\r
 }\r
 \r
 \r
+\r
+\r
 /**\r
   Create a UDP IO port to access the UDP service. It will\r
   create and configure a UDP child.\r
@@ -245,10 +376,11 @@ UdpIoFreeRxToken (
   @param  Configure             The function to configure the created UDP child\r
   @param  Context               The opaque parameter for the Configure funtion.\r
 \r
-  @return A point to just created UDP IO port or NULL if failed.\r
+  @return A point to just created UDP IO port or NULL if some error happened.\r
 \r
 **/\r
 UDP_IO_PORT *\r
+EFIAPI\r
 UdpIoCreatePort (\r
   IN  EFI_HANDLE            Controller,\r
   IN  EFI_HANDLE            Image,\r
@@ -261,20 +393,20 @@ UdpIoCreatePort (
 \r
   ASSERT (Configure != NULL);\r
 \r
-  UdpIo = NetAllocatePool (sizeof (UDP_IO_PORT));\r
+  UdpIo = AllocatePool (sizeof (UDP_IO_PORT));\r
 \r
   if (UdpIo == NULL) {\r
     return NULL;\r
   }\r
 \r
   UdpIo->Signature    = UDP_IO_SIGNATURE;\r
-  NetListInit (&UdpIo->Link);\r
+  InitializeListHead (&UdpIo->Link);\r
   UdpIo->RefCnt       = 1;\r
 \r
   UdpIo->Controller   = Controller;\r
   UdpIo->Image        = Image;\r
 \r
-  NetListInit (&UdpIo->SentDatagram);\r
+  InitializeListHead (&UdpIo->SentDatagram);\r
   UdpIo->RecvRequest  = NULL;\r
   UdpIo->UdpHandle    = NULL;\r
 \r
@@ -329,7 +461,7 @@ FREE_CHILD:
     );\r
 \r
 FREE_MEM:\r
-  NetFreePool (UdpIo);\r
+  gBS->FreePool (UdpIo);\r
   return NULL;\r
 }\r
 \r
@@ -344,10 +476,7 @@ FREE_MEM:
                                 packet or not.\r
   @param  Context               The opaque parameter to the ToCancel.\r
 \r
-  @return None\r
-\r
 **/\r
-STATIC\r
 VOID\r
 UdpIoCancelDgrams (\r
   IN UDP_IO_PORT            *UdpIo,\r
@@ -356,18 +485,15 @@ UdpIoCancelDgrams (
   IN VOID                   *Context\r
   )\r
 {\r
-  NET_LIST_ENTRY            *Entry;\r
-  NET_LIST_ENTRY            *Next;\r
+  LIST_ENTRY                *Entry;\r
+  LIST_ENTRY                *Next;\r
   UDP_TX_TOKEN              *Token;\r
 \r
   NET_LIST_FOR_EACH_SAFE (Entry, Next, &UdpIo->SentDatagram) {\r
     Token = NET_LIST_USER_STRUCT (Entry, UDP_TX_TOKEN, Link);\r
 \r
     if ((ToCancel == NULL) || (ToCancel (Token, Context))) {\r
-      NetListRemoveEntry (Entry);\r
       UdpIo->Udp->Cancel (UdpIo->Udp, &Token->UdpToken);\r
-      Token->CallBack (Token->Packet, NULL, IoStatus, Token->Context);\r
-      UdpIoFreeTxToken (Token);\r
     }\r
   }\r
 }\r
@@ -383,6 +509,7 @@ UdpIoCancelDgrams (
 \r
 **/\r
 EFI_STATUS\r
+EFIAPI\r
 UdpIoFreePort (\r
   IN  UDP_IO_PORT           *UdpIo\r
   )\r
@@ -400,9 +527,7 @@ UdpIoFreePort (
   UdpIoCancelDgrams (UdpIo, EFI_ABORTED, NULL, NULL);\r
 \r
   if ((RxToken = UdpIo->RecvRequest) != NULL) {\r
-    UdpIo->RecvRequest = NULL;\r
     UdpIo->Udp->Cancel (UdpIo->Udp, &RxToken->UdpToken);\r
-    UdpIoFreeRxToken (RxToken);\r
   }\r
 \r
   //\r
@@ -423,10 +548,10 @@ UdpIoFreePort (
     );\r
 \r
   if (!IsListEmpty(&UdpIo->Link)) {\r
-    NetListRemoveEntry (&UdpIo->Link);\r
+    RemoveEntryList (&UdpIo->Link);\r
   }\r
 \r
-  NetFreePool (UdpIo);\r
+  gBS->FreePool (UdpIo);\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -438,10 +563,9 @@ UdpIoFreePort (
 \r
   @param  UdpIo                 UDP IO port to clean up.\r
 \r
-  @return None\r
-\r
 **/\r
 VOID\r
+EFIAPI\r
 UdpIoCleanPort (\r
   IN  UDP_IO_PORT           *UdpIo\r
   )\r
@@ -454,46 +578,12 @@ UdpIoCleanPort (
   UdpIoCancelDgrams (UdpIo, EFI_ABORTED, NULL, NULL);\r
 \r
   if ((RxToken = UdpIo->RecvRequest) != NULL) {\r
-    UdpIo->RecvRequest = NULL;\r
     UdpIo->Udp->Cancel (UdpIo->Udp, &RxToken->UdpToken);\r
-    UdpIoFreeRxToken (RxToken);\r
   }\r
 \r
   UdpIo->Udp->Configure (UdpIo->Udp, NULL);\r
 }\r
 \r
-\r
-/**\r
-  The callback function when the packet is sent by UDP.\r
-  It will remove the packet from the local list then call\r
-  the packet owner's callback function.\r
-\r
-  @param  Event                 The event signalled.\r
-  @param  Context               The UDP TX Token.\r
-\r
-  @return None\r
-\r
-**/\r
-STATIC\r
-VOID\r
-EFIAPI\r
-UdpIoOnDgramSent (\r
-  IN EFI_EVENT              Event,\r
-  IN VOID                   *Context\r
-  )\r
-{\r
-  UDP_TX_TOKEN              *Token;\r
-\r
-  Token   = (UDP_TX_TOKEN *) Context;\r
-  ASSERT (Token->Signature == UDP_IO_TX_SIGNATURE);\r
-\r
-  NetListRemoveEntry (&Token->Link);\r
-  Token->CallBack (Token->Packet, NULL, Token->UdpToken.Status, Token->Context);\r
-\r
-  UdpIoFreeTxToken (Token);\r
-}\r
-\r
-\r
 /**\r
   Send a packet through the UDP IO port.\r
 \r
@@ -511,6 +601,7 @@ UdpIoOnDgramSent (
 \r
 **/\r
 EFI_STATUS\r
+EFIAPI\r
 UdpIoSendDatagram (\r
   IN  UDP_IO_PORT           *UdpIo,\r
   IN  NET_BUF               *Packet,\r
@@ -529,14 +620,18 @@ UdpIoSendDatagram (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
+  //\r
+  // Insert the tx token into SendDatagram list before transmitting it. Remove\r
+  // it from the list if the returned status is not EFI_SUCCESS.\r
+  //\r
+  InsertHeadList (&UdpIo->SentDatagram, &Token->Link);\r
   Status = UdpIo->Udp->Transmit (UdpIo->Udp, &Token->UdpToken);\r
-\r
   if (EFI_ERROR (Status)) {\r
+    RemoveEntryList (&Token->Link);\r
     UdpIoFreeTxToken (Token);\r
     return Status;\r
   }\r
 \r
-  NetListInsertHead (&UdpIo->SentDatagram, &Token->Link);\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -547,10 +642,9 @@ UdpIoSendDatagram (
   @param  Token                 The UDP TX token to test againist.\r
   @param  Context               The context\r
 \r
-  @return TRUE if the packet is to be cancelled, otherwise FALSE.\r
-\r
+  @retval TRUE              The packet is to be cancelled.\r
+  @retval FALSE             The packet is not to be cancelled.\r
 **/\r
-STATIC\r
 BOOLEAN\r
 UdpIoCancelSingleDgram (\r
   IN UDP_TX_TOKEN           *Token,\r
@@ -575,10 +669,9 @@ UdpIoCancelSingleDgram (
   @param  UdpIo                 The UDP IO port to cancel the packet from\r
   @param  Packet                The packet to cancel\r
 \r
-  @return None\r
-\r
 **/\r
 VOID\r
+EFIAPI\r
 UdpIoCancelSentDatagram (\r
   IN  UDP_IO_PORT           *UdpIo,\r
   IN  NET_BUF               *Packet\r
@@ -587,112 +680,6 @@ UdpIoCancelSentDatagram (
   UdpIoCancelDgrams (UdpIo, EFI_ABORTED, UdpIoCancelSingleDgram, Packet);\r
 }\r
 \r
-\r
-/**\r
-  Recycle the received UDP data.\r
-\r
-  @param  Context               The UDP_RX_TOKEN\r
-\r
-  @return None\r
-\r
-**/\r
-STATIC\r
-VOID\r
-UdpIoRecycleDgram (\r
-  IN VOID                   *Context\r
-  )\r
-{\r
-  UDP_RX_TOKEN              *Token;\r
-\r
-  Token = (UDP_RX_TOKEN *) Context;\r
-  gBS->SignalEvent (Token->UdpToken.Packet.RxData->RecycleSignal);\r
-  UdpIoFreeRxToken (Token);\r
-}\r
-\r
-\r
-/**\r
-  The event handle for UDP receive request. It will build\r
-  a NET_BUF from the recieved UDP data, then deliver it\r
-  to the receiver.\r
-\r
-  @param  Event                 The UDP receive request event\r
-  @param  Context               The UDP RX token.\r
-\r
-  @return None\r
-\r
-**/\r
-STATIC\r
-VOID\r
-EFIAPI\r
-UdpIoOnDgramRcvd (\r
-  IN EFI_EVENT              Event,\r
-  IN VOID                   *Context\r
-  )\r
-{\r
-  EFI_UDP4_COMPLETION_TOKEN *UdpToken;\r
-  EFI_UDP4_RECEIVE_DATA     *UdpRxData;\r
-  EFI_UDP4_SESSION_DATA     *UdpSession;\r
-  UDP_RX_TOKEN              *Token;\r
-  UDP_POINTS                Points;\r
-  NET_BUF                   *Netbuf;\r
-\r
-  Token   = (UDP_RX_TOKEN *) Context;\r
-\r
-  ASSERT ((Token->Signature == UDP_IO_RX_SIGNATURE) &&\r
-          (Token == Token->UdpIo->RecvRequest));\r
-\r
-  //\r
-  // Clear the receive request first in case that the caller\r
-  // wants to restart the receive in the callback.\r
-  //\r
-  Token->UdpIo->RecvRequest = NULL;\r
-\r
-  UdpToken  = &Token->UdpToken;\r
-  UdpRxData = UdpToken->Packet.RxData;\r
-\r
-  if (EFI_ERROR (UdpToken->Status) || (UdpRxData == NULL)) {\r
-    Token->CallBack (NULL, NULL, UdpToken->Status, Token->Context);\r
-    UdpIoFreeRxToken (Token);\r
-\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  //\r
-  // Build a NET_BUF from the UDP receive data, then deliver it up.\r
-  //\r
-  Netbuf = NetbufFromExt (\r
-             (NET_FRAGMENT *) UdpRxData->FragmentTable,\r
-             UdpRxData->FragmentCount,\r
-             0,\r
-             (UINT32) Token->HeadLen,\r
-             UdpIoRecycleDgram,\r
-             Token\r
-             );\r
-\r
-  if (Netbuf == NULL) {\r
-    gBS->SignalEvent (UdpRxData->RecycleSignal);\r
-    Token->CallBack (NULL, NULL, EFI_OUT_OF_RESOURCES, Token->Context);\r
-\r
-    UdpIoFreeRxToken (Token);\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  UdpSession        = &UdpRxData->UdpSession;\r
-  Points.LocalPort  = UdpSession->DestinationPort;\r
-  Points.RemotePort = UdpSession->SourcePort;\r
-\r
-  NetCopyMem (&Points.LocalAddr, &UdpSession->DestinationAddress, sizeof (IP4_ADDR));\r
-  NetCopyMem (&Points.RemoteAddr, &UdpSession->SourceAddress, sizeof (IP4_ADDR));\r
-  Points.LocalAddr  = NTOHL (Points.LocalAddr);\r
-  Points.RemoteAddr = NTOHL (Points.RemoteAddr);\r
-\r
-  Token->CallBack (Netbuf, &Points, EFI_SUCCESS, Token->Context);\r
-\r
-ON_EXIT:\r
-  return;\r
-}\r
-\r
-\r
 /**\r
   Issue a receive request to the UDP IO port.\r
 \r
@@ -709,6 +696,7 @@ ON_EXIT:
 \r
 **/\r
 EFI_STATUS\r
+EFIAPI\r
 UdpIoRecvDatagram (\r
   IN  UDP_IO_PORT           *UdpIo,\r
   IN  UDP_IO_CALLBACK       CallBack,\r
@@ -729,13 +717,13 @@ UdpIoRecvDatagram (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
+  UdpIo->RecvRequest = Token;\r
   Status = UdpIo->Udp->Receive (UdpIo->Udp, &Token->UdpToken);\r
 \r
   if (EFI_ERROR (Status)) {\r
+    UdpIo->RecvRequest = NULL;\r
     UdpIoFreeRxToken (Token);\r
-    return Status;\r
   }\r
 \r
-  UdpIo->RecvRequest = Token;\r
-  return EFI_SUCCESS;\r
+  return Status;\r
 }\r