]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Network/ArpDxe/ArpImpl.c
NetworkPkg: Move Network library and drivers from MdeModulePkg to NetworkPkg
[mirror_edk2.git] / MdeModulePkg / Universal / Network / ArpDxe / ArpImpl.c
diff --git a/MdeModulePkg/Universal/Network/ArpDxe/ArpImpl.c b/MdeModulePkg/Universal/Network/ArpDxe/ArpImpl.c
deleted file mode 100644 (file)
index 0e9ef10..0000000
+++ /dev/null
@@ -1,1667 +0,0 @@
-/** @file\r
-  The implementation of the ARP protocol.\r
-\r
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
-SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include "ArpImpl.h"\r
-\r
-//\r
-// Global variable of EFI ARP Protocol Interface.\r
-//\r
-EFI_ARP_PROTOCOL  mEfiArpProtocolTemplate = {\r
-  ArpConfigure,\r
-  ArpAdd,\r
-  ArpFind,\r
-  ArpDelete,\r
-  ArpFlush,\r
-  ArpRequest,\r
-  ArpCancel\r
-};\r
-\r
-\r
-/**\r
-  Initialize the instance context data.\r
-\r
-  @param[in]   ArpService        Pointer to the arp service context data this\r
-                                 instance belongs to.\r
-  @param[out]  Instance          Pointer to the instance context data.\r
-\r
-  @return None.\r
-\r
-**/\r
-VOID\r
-ArpInitInstance (\r
-  IN  ARP_SERVICE_DATA   *ArpService,\r
-  OUT ARP_INSTANCE_DATA  *Instance\r
-  )\r
-{\r
-  NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);\r
-\r
-  Instance->Signature  = ARP_INSTANCE_DATA_SIGNATURE;\r
-  Instance->ArpService = ArpService;\r
-\r
-  CopyMem (&Instance->ArpProto, &mEfiArpProtocolTemplate, sizeof (Instance->ArpProto));\r
-\r
-  Instance->Configured = FALSE;\r
-  Instance->InDestroy  = FALSE;\r
-\r
-  InitializeListHead (&Instance->List);\r
-}\r
-\r
-\r
-/**\r
-  Process the Arp packets received from Mnp, the procedure conforms to RFC826.\r
-\r
-  @param[in]  Context            Pointer to the context data registerd to the\r
-                                 Event.\r
-\r
-  @return None.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-ArpOnFrameRcvdDpc (\r
-  IN VOID       *Context\r
-  )\r
-{\r
-  EFI_STATUS                            Status;\r
-  ARP_SERVICE_DATA                      *ArpService;\r
-  EFI_MANAGED_NETWORK_COMPLETION_TOKEN  *RxToken;\r
-  EFI_MANAGED_NETWORK_RECEIVE_DATA      *RxData;\r
-  ARP_HEAD                              *Head;\r
-  ARP_ADDRESS                           ArpAddress;\r
-  ARP_CACHE_ENTRY                       *CacheEntry;\r
-  LIST_ENTRY                            *Entry;\r
-  ARP_INSTANCE_DATA                     *Instance;\r
-  EFI_ARP_CONFIG_DATA                   *ConfigData;\r
-  NET_ARP_ADDRESS                       SenderAddress[2];\r
-  BOOLEAN                               ProtoMatched;\r
-  BOOLEAN                               IsTarget;\r
-  BOOLEAN                               MergeFlag;\r
-\r
-  ArpService = (ARP_SERVICE_DATA *)Context;\r
-  NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);\r
-\r
-  RxToken = &ArpService->RxToken;\r
-\r
-  if (RxToken->Status == EFI_ABORTED) {\r
-    //\r
-    // The Token is aborted, possibly by arp itself, just return and the receiving\r
-    // process is stopped.\r
-    //\r
-    return;\r
-  }\r
-\r
-  if (EFI_ERROR (RxToken->Status)) {\r
-    //\r
-    // Restart the receiving if any other error Status occurs.\r
-    //\r
-    goto RESTART_RECEIVE;\r
-  }\r
-\r
-  //\r
-  // Status is EFI_SUCCESS, process the received frame.\r
-  //\r
-  RxData = RxToken->Packet.RxData;\r
-  //\r
-  // Sanity check.\r
-  //\r
-  if (RxData->DataLength < sizeof (ARP_HEAD)) {\r
-    //\r
-    // Restart the receiving if packet size is not correct.\r
-    //\r
-    goto RESTART_RECEIVE;\r
-  }\r
-\r
-  //\r
-  // Convert the byte order of the multi-byte fields.\r
-  //\r
-  Head   = (ARP_HEAD *) RxData->PacketData;\r
-  Head->HwType    = NTOHS (Head->HwType);\r
-  Head->ProtoType = NTOHS (Head->ProtoType);\r
-  Head->OpCode    = NTOHS (Head->OpCode);\r
-\r
-  if (RxData->DataLength < (sizeof (ARP_HEAD) + 2 * Head->HwAddrLen + 2 * Head->ProtoAddrLen)) {\r
-    goto RESTART_RECEIVE;\r
-  }\r
-\r
-  if ((Head->HwType != ArpService->SnpMode.IfType) ||\r
-    (Head->HwAddrLen != ArpService->SnpMode.HwAddressSize) ||\r
-    (RxData->ProtocolType != ARP_ETHER_PROTO_TYPE)) {\r
-    //\r
-    // The hardware type or the hardware address length doesn't match.\r
-    // There is a sanity check for the protocol type too.\r
-    //\r
-    goto RECYCLE_RXDATA;\r
-  }\r
-\r
-  //\r
-  // Set the pointers to the addresses contained in the arp packet.\r
-  //\r
-  ArpAddress.SenderHwAddr    = (UINT8 *)(Head + 1);\r
-  ArpAddress.SenderProtoAddr = ArpAddress.SenderHwAddr + Head->HwAddrLen;\r
-  ArpAddress.TargetHwAddr    = ArpAddress.SenderProtoAddr + Head->ProtoAddrLen;\r
-  ArpAddress.TargetProtoAddr = ArpAddress.TargetHwAddr + Head->HwAddrLen;\r
-\r
-  SenderAddress[Hardware].Type       = Head->HwType;\r
-  SenderAddress[Hardware].Length     = Head->HwAddrLen;\r
-  SenderAddress[Hardware].AddressPtr = ArpAddress.SenderHwAddr;\r
-\r
-  SenderAddress[Protocol].Type       = Head->ProtoType;\r
-  SenderAddress[Protocol].Length     = Head->ProtoAddrLen;\r
-  SenderAddress[Protocol].AddressPtr = ArpAddress.SenderProtoAddr;\r
-\r
-  //\r
-  // First, check the denied cache table.\r
-  //\r
-  CacheEntry = ArpFindDeniedCacheEntry (\r
-                 ArpService,\r
-                 &SenderAddress[Protocol],\r
-                 &SenderAddress[Hardware]\r
-                 );\r
-  if (CacheEntry != NULL) {\r
-    //\r
-    // This address (either hardware or protocol address, or both) is configured to\r
-    // be a deny entry, silently skip the normal process.\r
-    //\r
-    goto RECYCLE_RXDATA;\r
-  }\r
-\r
-  ProtoMatched = FALSE;\r
-  IsTarget     = FALSE;\r
-  Instance     = NULL;\r
-  NET_LIST_FOR_EACH (Entry, &ArpService->ChildrenList) {\r
-    //\r
-    // Iterate all the children.\r
-    //\r
-    Instance = NET_LIST_USER_STRUCT (Entry, ARP_INSTANCE_DATA, List);\r
-    NET_CHECK_SIGNATURE (Instance, ARP_INSTANCE_DATA_SIGNATURE);\r
-    ConfigData = &Instance->ConfigData;\r
-\r
-    if ((Instance->Configured) &&\r
-      (Head->ProtoType == ConfigData->SwAddressType) &&\r
-      (Head->ProtoAddrLen == ConfigData->SwAddressLength)) {\r
-      //\r
-      // The protocol type is matched for the received arp packet.\r
-      //\r
-      ProtoMatched = TRUE;\r
-      if (0 == CompareMem (\r
-                 (VOID *)ArpAddress.TargetProtoAddr,\r
-                 ConfigData->StationAddress,\r
-                 ConfigData->SwAddressLength\r
-                 )) {\r
-        //\r
-        // The arp driver has the target address required by the received arp packet.\r
-        //\r
-        IsTarget = TRUE;\r
-        break;\r
-      }\r
-    }\r
-  }\r
-\r
-  if (!ProtoMatched) {\r
-    //\r
-    // Protocol type unmatchable, skip.\r
-    //\r
-    goto RECYCLE_RXDATA;\r
-  }\r
-\r
-  //\r
-  // Check whether the sender's address information is already in the cache.\r
-  //\r
-  MergeFlag  = FALSE;\r
-  CacheEntry = ArpFindNextCacheEntryInTable (\r
-                 &ArpService->ResolvedCacheTable,\r
-                 NULL,\r
-                 ByProtoAddress,\r
-                 &SenderAddress[Protocol],\r
-                 NULL\r
-                 );\r
-  if (CacheEntry != NULL) {\r
-    //\r
-    // Update the entry with the new information.\r
-    //\r
-    ArpFillAddressInCacheEntry (CacheEntry, &SenderAddress[Hardware], NULL);\r
-    CacheEntry->DecayTime = CacheEntry->DefaultDecayTime;\r
-    MergeFlag = TRUE;\r
-  }\r
-\r
-  if (!IsTarget) {\r
-    //\r
-    // This arp packet isn't targeted to us, skip now.\r
-    //\r
-    goto RECYCLE_RXDATA;\r
-  }\r
-\r
-  if (!MergeFlag) {\r
-    //\r
-    // Add the triplet <protocol type, sender protocol address, sender hardware address>\r
-    // to the translation table.\r
-    //\r
-    CacheEntry = ArpFindNextCacheEntryInTable (\r
-                   &ArpService->PendingRequestTable,\r
-                   NULL,\r
-                   ByProtoAddress,\r
-                   &SenderAddress[Protocol],\r
-                   NULL\r
-                   );\r
-    if (CacheEntry == NULL) {\r
-      //\r
-      // Allocate a new CacheEntry.\r
-      //\r
-      CacheEntry = ArpAllocCacheEntry (NULL);\r
-      if (CacheEntry == NULL) {\r
-        goto RECYCLE_RXDATA;\r
-      }\r
-    }\r
-\r
-    if (!IsListEmpty (&CacheEntry->List)) {\r
-      RemoveEntryList (&CacheEntry->List);\r
-    }\r
-\r
-    //\r
-    // Fill the addresses into the CacheEntry.\r
-    //\r
-    ArpFillAddressInCacheEntry (\r
-      CacheEntry,\r
-      &SenderAddress[Hardware],\r
-      &SenderAddress[Protocol]\r
-      );\r
-\r
-    //\r
-    // Inform the user.\r
-    //\r
-    ArpAddressResolved (CacheEntry, NULL, NULL);\r
-\r
-    //\r
-    // Add this entry into the ResolvedCacheTable\r
-    //\r
-    InsertHeadList (&ArpService->ResolvedCacheTable, &CacheEntry->List);\r
-  }\r
-\r
-  if (Head->OpCode == ARP_OPCODE_REQUEST) {\r
-    //\r
-    // Send back the ARP Reply. If we reach here, Instance is not NULL and CacheEntry\r
-    // is not NULL.\r
-    //\r
-    ArpSendFrame (Instance, CacheEntry, ARP_OPCODE_REPLY);\r
-  }\r
-\r
-RECYCLE_RXDATA:\r
-\r
-  //\r
-  // Signal Mnp to recycle the RxData.\r
-  //\r
-  gBS->SignalEvent (RxData->RecycleEvent);\r
-\r
-RESTART_RECEIVE:\r
-\r
-  //\r
-  // Continue to receive packets from Mnp.\r
-  //\r
-  Status = ArpService->Mnp->Receive (ArpService->Mnp, RxToken);\r
-\r
-  DEBUG_CODE (\r
-    if (EFI_ERROR (Status)) {\r
-      DEBUG ((EFI_D_ERROR, "ArpOnFrameRcvd: ArpService->Mnp->Receive "\r
-        "failed, %r\n.", Status));\r
-    }\r
-  );\r
-}\r
-\r
-/**\r
-  Queue ArpOnFrameRcvdDpc as a DPC at TPL_CALLBACK.\r
-\r
-  @param[in]  Event                  The Event this notify function registered to.\r
-  @param[in]  Context                Pointer to the context data registerd to the\r
-                                     Event.\r
-\r
-  @return None.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-ArpOnFrameRcvd (\r
-  IN EFI_EVENT  Event,\r
-  IN VOID       *Context\r
-  )\r
-{\r
-  //\r
-  // Request ArpOnFrameRcvdDpc as a DPC at TPL_CALLBACK\r
-  //\r
-  QueueDpc (TPL_CALLBACK, ArpOnFrameRcvdDpc, Context);\r
-}\r
-\r
-/**\r
-  Process the already sent arp packets.\r
-\r
-  @param[in]  Context                Pointer to the context data registerd to the\r
-                                     Event.\r
-\r
-  @return None.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-ArpOnFrameSentDpc (\r
-  IN VOID       *Context\r
-  )\r
-{\r
-  EFI_MANAGED_NETWORK_COMPLETION_TOKEN  *TxToken;\r
-  EFI_MANAGED_NETWORK_TRANSMIT_DATA     *TxData;\r
-\r
-  ASSERT (Context != NULL);\r
-\r
-  TxToken = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *)Context;\r
-  TxData  = TxToken->Packet.TxData;\r
-\r
-  DEBUG_CODE (\r
-    if (EFI_ERROR (TxToken->Status)) {\r
-      DEBUG ((EFI_D_ERROR, "ArpOnFrameSent: TxToken->Status, %r.\n", TxToken->Status));\r
-    }\r
-  );\r
-\r
-  //\r
-  // Free the allocated memory and close the event.\r
-  //\r
-  FreePool (TxData->FragmentTable[0].FragmentBuffer);\r
-  FreePool (TxData);\r
-  gBS->CloseEvent (TxToken->Event);\r
-  FreePool (TxToken);\r
-}\r
-\r
-/**\r
-  Request ArpOnFrameSentDpc as a DPC at TPL_CALLBACK.\r
-\r
-  @param[in]  Event                  The Event this notify function registered to.\r
-  @param[in]  Context                Pointer to the context data registerd to the\r
-                                     Event.\r
-\r
-  @return None.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-ArpOnFrameSent (\r
-  IN EFI_EVENT  Event,\r
-  IN VOID       *Context\r
-  )\r
-{\r
-  //\r
-  // Request ArpOnFrameSentDpc as a DPC at TPL_CALLBACK\r
-  //\r
-  QueueDpc (TPL_CALLBACK, ArpOnFrameSentDpc, Context);\r
-}\r
-\r
-\r
-/**\r
-  Process the arp cache olding and drive the retrying arp requests.\r
-\r
-  @param[in]  Event                  The Event this notify function registered to.\r
-  @param[in]  Context                Pointer to the context data registerd to the\r
-                                     Event.\r
-\r
-  @return None.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-ArpTimerHandler (\r
-  IN EFI_EVENT  Event,\r
-  IN VOID       *Context\r
-  )\r
-{\r
-  ARP_SERVICE_DATA      *ArpService;\r
-  LIST_ENTRY            *Entry;\r
-  LIST_ENTRY            *NextEntry;\r
-  LIST_ENTRY            *ContextEntry;\r
-  ARP_CACHE_ENTRY       *CacheEntry;\r
-  USER_REQUEST_CONTEXT  *RequestContext;\r
-\r
-  ASSERT (Context != NULL);\r
-  ArpService = (ARP_SERVICE_DATA *)Context;\r
-\r
-  //\r
-  // Iterate all the pending requests to see whether a retry is needed to send out\r
-  // or the request finally fails because the retry time reaches the limitation.\r
-  //\r
-  NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &ArpService->PendingRequestTable) {\r
-    CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);\r
-\r
-    if (CacheEntry->NextRetryTime <= ARP_PERIODIC_TIMER_INTERVAL) {\r
-      //\r
-      // Timeout, if we can retry more, send out the request again, otherwise abort\r
-      // this request.\r
-      //\r
-      if (CacheEntry->RetryCount == 0) {\r
-        //\r
-        // Abort this request.\r
-        //\r
-        ArpAddressResolved (CacheEntry, NULL, NULL);\r
-        ASSERT (IsListEmpty (&CacheEntry->UserRequestList));\r
-\r
-        RemoveEntryList (&CacheEntry->List);\r
-        FreePool (CacheEntry);\r
-      } else {\r
-        //\r
-        // resend the ARP request.\r
-        //\r
-        ASSERT (!IsListEmpty(&CacheEntry->UserRequestList));\r
-\r
-        ContextEntry   = CacheEntry->UserRequestList.ForwardLink;\r
-        RequestContext = NET_LIST_USER_STRUCT (ContextEntry, USER_REQUEST_CONTEXT, List);\r
-\r
-        ArpSendFrame (RequestContext->Instance, CacheEntry, ARP_OPCODE_REQUEST);\r
-\r
-        CacheEntry->RetryCount--;\r
-        CacheEntry->NextRetryTime = RequestContext->Instance->ConfigData.RetryTimeOut;\r
-      }\r
-    } else {\r
-      //\r
-      // Update the NextRetryTime.\r
-      //\r
-      CacheEntry->NextRetryTime -= ARP_PERIODIC_TIMER_INTERVAL;\r
-    }\r
-  }\r
-\r
-  //\r
-  // Check the timeouts for the DeniedCacheTable.\r
-  //\r
-  NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &ArpService->DeniedCacheTable) {\r
-    CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);\r
-    ASSERT (IsListEmpty (&CacheEntry->UserRequestList));\r
-\r
-    if (CacheEntry->DefaultDecayTime == 0) {\r
-      //\r
-      // It's a static entry, skip it.\r
-      //\r
-      continue;\r
-    }\r
-\r
-    if (CacheEntry->DecayTime <= ARP_PERIODIC_TIMER_INTERVAL) {\r
-      //\r
-      // Time out, remove it.\r
-      //\r
-      RemoveEntryList (&CacheEntry->List);\r
-      FreePool (CacheEntry);\r
-    } else {\r
-      //\r
-      // Update the DecayTime.\r
-      //\r
-      CacheEntry->DecayTime -= ARP_PERIODIC_TIMER_INTERVAL;\r
-    }\r
-  }\r
-\r
-  //\r
-  // Check the timeouts for the ResolvedCacheTable.\r
-  //\r
-  NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &ArpService->ResolvedCacheTable) {\r
-    CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);\r
-    ASSERT (IsListEmpty (&CacheEntry->UserRequestList));\r
-\r
-    if (CacheEntry->DefaultDecayTime == 0) {\r
-      //\r
-      // It's a static entry, skip it.\r
-      //\r
-      continue;\r
-    }\r
-\r
-    if (CacheEntry->DecayTime <= ARP_PERIODIC_TIMER_INTERVAL) {\r
-      //\r
-      // Time out, remove it.\r
-      //\r
-      RemoveEntryList (&CacheEntry->List);\r
-      FreePool (CacheEntry);\r
-    } else {\r
-      //\r
-      // Update the DecayTime.\r
-      //\r
-      CacheEntry->DecayTime -= ARP_PERIODIC_TIMER_INTERVAL;\r
-    }\r
-  }\r
-}\r
-\r
-\r
-/**\r
-  Match the two NET_ARP_ADDRESSes.\r
-\r
-  @param[in]  AddressOne             Pointer to the first address to match.\r
-  @param[in]  AddressTwo             Pointer to the second address to match.\r
-\r
-  @return The two addresses match or not.\r
-\r
-**/\r
-BOOLEAN\r
-ArpMatchAddress (\r
-  IN NET_ARP_ADDRESS  *AddressOne,\r
-  IN NET_ARP_ADDRESS  *AddressTwo\r
-  )\r
-{\r
-  ASSERT (AddressOne != NULL && AddressTwo != NULL);\r
-\r
-  if ((AddressOne->Type != AddressTwo->Type) ||\r
-    (AddressOne->Length != AddressTwo->Length)) {\r
-    //\r
-    // Either Type or Length doesn't match.\r
-    //\r
-    return FALSE;\r
-  }\r
-\r
-  if ((AddressOne->AddressPtr != NULL) &&\r
-    (CompareMem (\r
-      AddressOne->AddressPtr,\r
-      AddressTwo->AddressPtr,\r
-      AddressOne->Length\r
-      ) != 0)) {\r
-    //\r
-    // The address is not the same.\r
-    //\r
-    return FALSE;\r
-  }\r
-\r
-  return TRUE;\r
-}\r
-\r
-\r
-/**\r
-  Find the CacheEntry which matches the requirements in the specified CacheTable.\r
-\r
-  @param[in]  CacheTable             Pointer to the arp cache table.\r
-  @param[in]  StartEntry             Pointer to the start entry this search begins with\r
-                                     in the cache table.\r
-  @param[in]  FindOpType             The search type.\r
-  @param[in]  ProtocolAddress        Pointer to the protocol address to match.\r
-  @param[in]  HardwareAddress        Pointer to the hardware address to match.\r
-\r
-  @return Pointer to the matched arp cache entry, if NULL, no match is found.\r
-\r
-**/\r
-ARP_CACHE_ENTRY *\r
-ArpFindNextCacheEntryInTable (\r
-  IN LIST_ENTRY        *CacheTable,\r
-  IN LIST_ENTRY        *StartEntry,\r
-  IN FIND_OPTYPE       FindOpType,\r
-  IN NET_ARP_ADDRESS   *ProtocolAddress OPTIONAL,\r
-  IN NET_ARP_ADDRESS   *HardwareAddress OPTIONAL\r
-  )\r
-{\r
-  LIST_ENTRY       *Entry;\r
-  ARP_CACHE_ENTRY  *CacheEntry;\r
-\r
-  if (StartEntry == NULL) {\r
-    //\r
-    // Start from the beginning of the table if no StartEntry is specified.\r
-    //\r
-    StartEntry = CacheTable;\r
-  }\r
-\r
-  for (Entry = StartEntry->ForwardLink; Entry != CacheTable; Entry = Entry->ForwardLink) {\r
-    CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);\r
-\r
-    if ((FindOpType & MATCH_SW_ADDRESS) != 0) {\r
-      //\r
-      // Find by the software address.\r
-      //\r
-      if (!ArpMatchAddress (ProtocolAddress, &CacheEntry->Addresses[Protocol])) {\r
-        //\r
-        // The ProtocolAddress doesn't match, continue to the next cache entry.\r
-        //\r
-        continue;\r
-      }\r
-    }\r
-\r
-    if ((FindOpType & MATCH_HW_ADDRESS) != 0) {\r
-      //\r
-      // Find by the hardware address.\r
-      //\r
-      if (!ArpMatchAddress (HardwareAddress, &CacheEntry->Addresses[Hardware])) {\r
-        //\r
-        // The HardwareAddress doesn't match, continue to the next cache entry.\r
-        //\r
-        continue;\r
-      }\r
-    }\r
-\r
-    //\r
-    // The CacheEntry meets the requirements now, return this entry.\r
-    //\r
-    return CacheEntry;\r
-  }\r
-\r
-  //\r
-  // No matching.\r
-  //\r
-  return NULL;\r
-}\r
-\r
-\r
-/**\r
-  Find the CacheEntry, using ProtocolAddress or HardwareAddress or both, as the keyword,\r
-  in the DeniedCacheTable.\r
-\r
-  @param[in]  ArpService             Pointer to the arp service context data.\r
-  @param[in]  ProtocolAddress        Pointer to the protocol address.\r
-  @param[in]  HardwareAddress        Pointer to the hardware address.\r
-\r
-  @return Pointer to the matched cache entry, if NULL no match is found.\r
-\r
-**/\r
-ARP_CACHE_ENTRY *\r
-ArpFindDeniedCacheEntry (\r
-  IN ARP_SERVICE_DATA  *ArpService,\r
-  IN NET_ARP_ADDRESS   *ProtocolAddress OPTIONAL,\r
-  IN NET_ARP_ADDRESS   *HardwareAddress OPTIONAL\r
-  )\r
-{\r
-  ARP_CACHE_ENTRY  *CacheEntry;\r
-\r
-  ASSERT ((ProtocolAddress != NULL) || (HardwareAddress != NULL));\r
-  NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);\r
-\r
-  CacheEntry = NULL;\r
-\r
-  if ((ProtocolAddress != NULL) && (ProtocolAddress->AddressPtr != NULL)) {\r
-    //\r
-    // Find the cache entry in the DeniedCacheTable by the protocol address.\r
-    //\r
-    CacheEntry = ArpFindNextCacheEntryInTable (\r
-                   &ArpService->DeniedCacheTable,\r
-                   NULL,\r
-                   ByProtoAddress,\r
-                   ProtocolAddress,\r
-                   NULL\r
-                   );\r
-    if (CacheEntry != NULL) {\r
-      //\r
-      // There is a match.\r
-      //\r
-      return CacheEntry;\r
-    }\r
-  }\r
-\r
-  if ((HardwareAddress != NULL) && (HardwareAddress->AddressPtr != NULL)) {\r
-    //\r
-    // Find the cache entry in the DeniedCacheTable by the hardware address.\r
-    //\r
-    CacheEntry = ArpFindNextCacheEntryInTable (\r
-                   &ArpService->DeniedCacheTable,\r
-                   NULL,\r
-                   ByHwAddress,\r
-                   NULL,\r
-                   HardwareAddress\r
-                   );\r
-  }\r
-\r
-  return CacheEntry;\r
-}\r
-\r
-\r
-/**\r
-  Allocate a cache entry and initialize it.\r
-\r
-  @param[in]  Instance               Pointer to the instance context data.\r
-\r
-  @return Pointer to the new created cache entry.\r
-\r
-**/\r
-ARP_CACHE_ENTRY *\r
-ArpAllocCacheEntry (\r
-  IN ARP_INSTANCE_DATA  *Instance\r
-  )\r
-{\r
-  ARP_CACHE_ENTRY  *CacheEntry;\r
-  NET_ARP_ADDRESS  *Address;\r
-  UINT16           Index;\r
-\r
-  //\r
-  // Allocate memory for the cache entry.\r
-  //\r
-  CacheEntry = AllocatePool (sizeof (ARP_CACHE_ENTRY));\r
-  if (CacheEntry == NULL) {\r
-    return NULL;\r
-  }\r
-\r
-  //\r
-  // Init the lists.\r
-  //\r
-  InitializeListHead (&CacheEntry->List);\r
-  InitializeListHead (&CacheEntry->UserRequestList);\r
-\r
-  for (Index = 0; Index < 2; Index++) {\r
-    //\r
-    // Init the address pointers to point to the concrete buffer.\r
-    //\r
-    Address = &CacheEntry->Addresses[Index];\r
-    Address->AddressPtr = Address->Buffer.ProtoAddress;\r
-  }\r
-\r
-  //\r
-  // Zero the hardware address first.\r
-  //\r
-  ZeroMem (CacheEntry->Addresses[Hardware].AddressPtr, ARP_MAX_HARDWARE_ADDRESS_LEN);\r
-\r
-  if (Instance != NULL) {\r
-    //\r
-    // Inherit the parameters from the instance configuration.\r
-    //\r
-    CacheEntry->RetryCount       = Instance->ConfigData.RetryCount;\r
-    CacheEntry->NextRetryTime    = Instance->ConfigData.RetryTimeOut;\r
-    CacheEntry->DefaultDecayTime = Instance->ConfigData.EntryTimeOut;\r
-    CacheEntry->DecayTime        = Instance->ConfigData.EntryTimeOut;\r
-  } else {\r
-    //\r
-    // Use the default parameters if this cache entry isn't allocate in a\r
-    // instance's  scope.\r
-    //\r
-    CacheEntry->RetryCount       = ARP_DEFAULT_RETRY_COUNT;\r
-    CacheEntry->NextRetryTime    = ARP_DEFAULT_RETRY_INTERVAL;\r
-    CacheEntry->DefaultDecayTime = ARP_DEFAULT_TIMEOUT_VALUE;\r
-    CacheEntry->DecayTime        = ARP_DEFAULT_TIMEOUT_VALUE;\r
-  }\r
-\r
-  return CacheEntry;\r
-}\r
-\r
-\r
-/**\r
-  Turn the CacheEntry into the resolved status.\r
-\r
-  @param[in]  CacheEntry             Pointer to the resolved cache entry.\r
-  @param[in]  Instance               Pointer to the instance context data.\r
-  @param[in]  UserEvent              Pointer to the UserEvent to notify.\r
-\r
-  @return The count of notifications sent to the instance.\r
-\r
-**/\r
-UINTN\r
-ArpAddressResolved (\r
-  IN ARP_CACHE_ENTRY    *CacheEntry,\r
-  IN ARP_INSTANCE_DATA  *Instance OPTIONAL,\r
-  IN EFI_EVENT          UserEvent OPTIONAL\r
-  )\r
-{\r
-  LIST_ENTRY            *Entry;\r
-  LIST_ENTRY            *NextEntry;\r
-  USER_REQUEST_CONTEXT  *Context;\r
-  UINTN                 Count;\r
-\r
-  Count = 0;\r
-\r
-  //\r
-  // Iterate all the linked user requests to notify them.\r
-  //\r
-  NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &CacheEntry->UserRequestList) {\r
-    Context = NET_LIST_USER_STRUCT (Entry, USER_REQUEST_CONTEXT, List);\r
-\r
-    if (((Instance == NULL) || (Context->Instance == Instance)) &&\r
-      ((UserEvent == NULL) || (Context->UserRequestEvent == UserEvent))) {\r
-      //\r
-      // Copy the address to the user-provided buffer and notify the user.\r
-      //\r
-      CopyMem (\r
-        Context->UserHwAddrBuffer,\r
-        CacheEntry->Addresses[Hardware].AddressPtr,\r
-        CacheEntry->Addresses[Hardware].Length\r
-        );\r
-      gBS->SignalEvent (Context->UserRequestEvent);\r
-\r
-      //\r
-      // Remove this user request and free the context data.\r
-      //\r
-      RemoveEntryList (&Context->List);\r
-      FreePool (Context);\r
-\r
-      Count++;\r
-    }\r
-  }\r
-\r
-  //\r
-  // Dispatch the DPCs queued by the NotifyFunction of the Context->UserRequestEvent.\r
-  //\r
-  DispatchDpc ();\r
-\r
-  return Count;\r
-}\r
-\r
-\r
-/**\r
-  Fill the addresses in the CacheEntry using the information passed in by\r
-  HwAddr and SwAddr.\r
-\r
-  @param[in]  CacheEntry             Pointer to the cache entry.\r
-  @param[in]  HwAddr                 Pointer to the software address.\r
-  @param[in]  SwAddr                 Pointer to the hardware address.\r
-\r
-  @return None.\r
-\r
-**/\r
-VOID\r
-ArpFillAddressInCacheEntry (\r
-  IN ARP_CACHE_ENTRY  *CacheEntry,\r
-  IN NET_ARP_ADDRESS  *HwAddr OPTIONAL,\r
-  IN NET_ARP_ADDRESS  *SwAddr OPTIONAL\r
-  )\r
-{\r
-  NET_ARP_ADDRESS  *Address[2];\r
-  NET_ARP_ADDRESS  *CacheAddress;\r
-  UINT32           Index;\r
-\r
-  Address[Hardware] = HwAddr;\r
-  Address[Protocol] = SwAddr;\r
-\r
-  for (Index = 0; Index < 2; Index++) {\r
-    if (Address[Index] != NULL) {\r
-      //\r
-      // Fill the address if the passed in pointer is not NULL.\r
-      //\r
-      CacheAddress = &CacheEntry->Addresses[Index];\r
-\r
-      CacheAddress->Type   = Address[Index]->Type;\r
-      CacheAddress->Length = Address[Index]->Length;\r
-\r
-      if (Address[Index]->AddressPtr != NULL) {\r
-        //\r
-        // Copy it if the AddressPtr points to some buffer.\r
-        //\r
-        CopyMem (\r
-          CacheAddress->AddressPtr,\r
-          Address[Index]->AddressPtr,\r
-          CacheAddress->Length\r
-          );\r
-      } else {\r
-        //\r
-        // Zero the corresponding address buffer in the CacheEntry.\r
-        //\r
-        ZeroMem (CacheAddress->AddressPtr, CacheAddress->Length);\r
-      }\r
-    }\r
-  }\r
-}\r
-\r
-\r
-/**\r
-  Configure the instance using the ConfigData. ConfigData is already validated.\r
-\r
-  @param[in]  Instance           Pointer to the instance context data to be\r
-                                 configured.\r
-  @param[in]  ConfigData         Pointer to the configuration data used to\r
-                                 configure the instance.\r
-\r
-  @retval EFI_SUCCESS            The instance is configured with the ConfigData.\r
-  @retval EFI_ACCESS_DENIED      The instance is already configured and the\r
-                                 ConfigData tries to reset some unchangeable\r
-                                 fields.\r
-  @retval EFI_INVALID_PARAMETER  The ConfigData provides a non-unicast IPv4 address\r
-                                 when the SwAddressType is IPv4.\r
-  @retval EFI_OUT_OF_RESOURCES   The instance fails to configure due to memory\r
-                                 limitation.\r
-\r
-**/\r
-EFI_STATUS\r
-ArpConfigureInstance (\r
-  IN ARP_INSTANCE_DATA    *Instance,\r
-  IN EFI_ARP_CONFIG_DATA  *ConfigData OPTIONAL\r
-  )\r
-{\r
-  EFI_ARP_CONFIG_DATA  *OldConfigData;\r
-  IP4_ADDR             Ip;\r
-\r
-  OldConfigData = &Instance->ConfigData;\r
-\r
-  if (ConfigData != NULL) {\r
-\r
-    if (Instance->Configured) {\r
-      //\r
-      // The instance is configured, check the unchangeable fields.\r
-      //\r
-      if ((OldConfigData->SwAddressType != ConfigData->SwAddressType) ||\r
-        (OldConfigData->SwAddressLength != ConfigData->SwAddressLength) ||\r
-        (CompareMem (\r
-           OldConfigData->StationAddress,\r
-           ConfigData->StationAddress,\r
-           OldConfigData->SwAddressLength\r
-           ) != 0)) {\r
-        //\r
-        // Deny the unallowed changes.\r
-        //\r
-        return EFI_ACCESS_DENIED;\r
-      }\r
-    } else {\r
-      //\r
-      // The instance is not configured.\r
-      //\r
-\r
-      if (ConfigData->SwAddressType == IPV4_ETHER_PROTO_TYPE) {\r
-        CopyMem (&Ip, ConfigData->StationAddress, sizeof (IP4_ADDR));\r
-\r
-        if (IP4_IS_UNSPECIFIED (Ip) || IP4_IS_LOCAL_BROADCAST (Ip)) {\r
-          //\r
-          // The station address should not be zero or broadcast address.\r
-          //\r
-          return EFI_INVALID_PARAMETER;\r
-        }\r
-      }\r
-\r
-      //\r
-      // Save the configuration.\r
-      //\r
-      CopyMem (OldConfigData, ConfigData, sizeof (*OldConfigData));\r
-\r
-      OldConfigData->StationAddress = AllocatePool (OldConfigData->SwAddressLength);\r
-      if (OldConfigData->StationAddress == NULL) {\r
-        DEBUG ((EFI_D_ERROR, "ArpConfigInstance: AllocatePool for the StationAddress "\r
-          "failed.\n"));\r
-        return EFI_OUT_OF_RESOURCES;\r
-      }\r
-\r
-      //\r
-      // Save the StationAddress.\r
-      //\r
-      CopyMem (\r
-        OldConfigData->StationAddress,\r
-        ConfigData->StationAddress,\r
-        OldConfigData->SwAddressLength\r
-        );\r
-\r
-      //\r
-      // Set the state to configured.\r
-      //\r
-      Instance->Configured = TRUE;\r
-    }\r
-\r
-    //\r
-    // Use the implementation specific values if the following field is zero.\r
-    //\r
-    OldConfigData->EntryTimeOut = (ConfigData->EntryTimeOut == 0) ?\r
-      ARP_DEFAULT_TIMEOUT_VALUE : ConfigData->EntryTimeOut;\r
-\r
-    OldConfigData->RetryCount   = (ConfigData->RetryCount == 0) ?\r
-      ARP_DEFAULT_RETRY_COUNT : ConfigData->RetryCount;\r
-\r
-    OldConfigData->RetryTimeOut = (ConfigData->RetryTimeOut == 0) ?\r
-      ARP_DEFAULT_RETRY_INTERVAL : ConfigData->RetryTimeOut;\r
-  } else {\r
-    //\r
-    // Reset the configuration.\r
-    //\r
-\r
-    if (Instance->Configured) {\r
-      //\r
-      // Cancel the arp requests issued by this instance.\r
-      //\r
-      Instance->ArpProto.Cancel (&Instance->ArpProto, NULL, NULL);\r
-\r
-      //\r
-      // Free the buffer previously allocated to hold the station address.\r
-      //\r
-      FreePool (OldConfigData->StationAddress);\r
-    }\r
-\r
-    Instance->Configured = FALSE;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
-  Send out an arp frame using the CachEntry and the ArpOpCode.\r
-\r
-  @param[in]  Instance               Pointer to the instance context data.\r
-  @param[in]  CacheEntry             Pointer to the configuration data used to\r
-                                     configure the instance.\r
-  @param[in]  ArpOpCode              The opcode used to send out this Arp frame, either\r
-                                     request or reply.\r
-\r
-  @return None.\r
-\r
-**/\r
-VOID\r
-ArpSendFrame (\r
-  IN ARP_INSTANCE_DATA  *Instance,\r
-  IN ARP_CACHE_ENTRY    *CacheEntry,\r
-  IN UINT16             ArpOpCode\r
-  )\r
-{\r
-  EFI_STATUS                            Status;\r
-  EFI_MANAGED_NETWORK_COMPLETION_TOKEN  *TxToken;\r
-  EFI_MANAGED_NETWORK_TRANSMIT_DATA     *TxData;\r
-  UINT32                                TotalLength;\r
-  UINT8                                 *Packet;\r
-  ARP_SERVICE_DATA                      *ArpService;\r
-  EFI_SIMPLE_NETWORK_MODE               *SnpMode;\r
-  EFI_ARP_CONFIG_DATA                   *ConfigData;\r
-  UINT8                                 *TmpPtr;\r
-  ARP_HEAD                              *ArpHead;\r
-\r
-  ASSERT ((Instance != NULL) && (CacheEntry != NULL));\r
-\r
-  //\r
-  // Allocate memory for the TxToken.\r
-  //\r
-  TxToken = AllocatePool (sizeof(EFI_MANAGED_NETWORK_COMPLETION_TOKEN));\r
-  if (TxToken == NULL) {\r
-    DEBUG ((EFI_D_ERROR, "ArpSendFrame: Allocate memory for TxToken failed.\n"));\r
-    return;\r
-  }\r
-\r
-  TxToken->Event = NULL;\r
-  TxData         = NULL;\r
-  Packet         = NULL;\r
-\r
-  //\r
-  // Create the event for this TxToken.\r
-  //\r
-  Status = gBS->CreateEvent (\r
-                  EVT_NOTIFY_SIGNAL,\r
-                  TPL_NOTIFY,\r
-                  ArpOnFrameSent,\r
-                  (VOID *)TxToken,\r
-                  &TxToken->Event\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "ArpSendFrame: CreateEvent failed for TxToken->Event.\n"));\r
-    goto CLEAN_EXIT;\r
-  }\r
-\r
-  //\r
-  // Allocate memory for the TxData used in the TxToken.\r
-  //\r
-  TxData = AllocatePool (sizeof(EFI_MANAGED_NETWORK_TRANSMIT_DATA));\r
-  if (TxData == NULL) {\r
-    DEBUG ((EFI_D_ERROR, "ArpSendFrame: Allocate memory for TxData failed.\n"));\r
-    goto CLEAN_EXIT;\r
-  }\r
-\r
-  ArpService = Instance->ArpService;\r
-  SnpMode    = &ArpService->SnpMode;\r
-  ConfigData = &Instance->ConfigData;\r
-\r
-  //\r
-  // Calculate the buffer length for this arp frame.\r
-  //\r
-  TotalLength = SnpMode->MediaHeaderSize + sizeof (ARP_HEAD) +\r
-                2 * (ConfigData->SwAddressLength + SnpMode->HwAddressSize);\r
-\r
-  //\r
-  // Allocate buffer for the arp frame.\r
-  //\r
-  Packet = AllocatePool (TotalLength);\r
-  if (Packet == NULL) {\r
-    DEBUG ((EFI_D_ERROR, "ArpSendFrame: Allocate memory for Packet failed.\n"));\r
-    ASSERT (Packet != NULL);\r
-  }\r
-\r
-  TmpPtr = Packet;\r
-\r
-  //\r
-  // The destination MAC address.\r
-  //\r
-  if (ArpOpCode == ARP_OPCODE_REQUEST) {\r
-    CopyMem (TmpPtr, &SnpMode->BroadcastAddress, SnpMode->HwAddressSize);\r
-  } else {\r
-    CopyMem (\r
-      TmpPtr,\r
-      CacheEntry->Addresses[Hardware].AddressPtr,\r
-      SnpMode->HwAddressSize\r
-      );\r
-  }\r
-  TmpPtr += SnpMode->HwAddressSize;\r
-\r
-  //\r
-  // The source MAC address.\r
-  //\r
-  CopyMem (TmpPtr, &SnpMode->CurrentAddress, SnpMode->HwAddressSize);\r
-  TmpPtr += SnpMode->HwAddressSize;\r
-\r
-  //\r
-  // The ethernet protocol type.\r
-  //\r
-  *(UINT16 *)TmpPtr = HTONS (ARP_ETHER_PROTO_TYPE);\r
-  TmpPtr            += 2;\r
-\r
-  //\r
-  // The ARP Head.\r
-  //\r
-  ArpHead               = (ARP_HEAD *) TmpPtr;\r
-  ArpHead->HwType       = HTONS ((UINT16)SnpMode->IfType);\r
-  ArpHead->ProtoType    = HTONS (ConfigData->SwAddressType);\r
-  ArpHead->HwAddrLen    = (UINT8)SnpMode->HwAddressSize;\r
-  ArpHead->ProtoAddrLen = ConfigData->SwAddressLength;\r
-  ArpHead->OpCode       = HTONS (ArpOpCode);\r
-  TmpPtr                += sizeof (ARP_HEAD);\r
-\r
-  //\r
-  // The sender hardware address.\r
-  //\r
-  CopyMem (TmpPtr, &SnpMode->CurrentAddress, SnpMode->HwAddressSize);\r
-  TmpPtr += SnpMode->HwAddressSize;\r
-\r
-  //\r
-  // The sender protocol address.\r
-  //\r
-  CopyMem (TmpPtr, ConfigData->StationAddress, ConfigData->SwAddressLength);\r
-  TmpPtr += ConfigData->SwAddressLength;\r
-\r
-  //\r
-  // The target hardware address.\r
-  //\r
-  CopyMem (\r
-    TmpPtr,\r
-    CacheEntry->Addresses[Hardware].AddressPtr,\r
-    SnpMode->HwAddressSize\r
-    );\r
-  TmpPtr += SnpMode->HwAddressSize;\r
-\r
-  //\r
-  // The target protocol address.\r
-  //\r
-  CopyMem (\r
-    TmpPtr,\r
-    CacheEntry->Addresses[Protocol].AddressPtr,\r
-    ConfigData->SwAddressLength\r
-    );\r
-\r
-  //\r
-  // Set all the fields of the TxData.\r
-  //\r
-  TxData->DestinationAddress = NULL;\r
-  TxData->SourceAddress      = NULL;\r
-  TxData->ProtocolType       = 0;\r
-  TxData->DataLength         = TotalLength - SnpMode->MediaHeaderSize;\r
-  TxData->HeaderLength       = (UINT16) SnpMode->MediaHeaderSize;\r
-  TxData->FragmentCount      = 1;\r
-\r
-  TxData->FragmentTable[0].FragmentBuffer = Packet;\r
-  TxData->FragmentTable[0].FragmentLength = TotalLength;\r
-\r
-  //\r
-  // Associate the TxData with the TxToken.\r
-  //\r
-  TxToken->Packet.TxData = TxData;\r
-  TxToken->Status        = EFI_NOT_READY;\r
-\r
-  //\r
-  // Send out this arp packet by Mnp.\r
-  //\r
-  Status = ArpService->Mnp->Transmit (ArpService->Mnp, TxToken);\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "Mnp->Transmit failed, %r.\n", Status));\r
-    goto CLEAN_EXIT;\r
-  }\r
-\r
-  return;\r
-\r
-CLEAN_EXIT:\r
-\r
-  if (Packet != NULL) {\r
-    FreePool (Packet);\r
-  }\r
-\r
-  if (TxData != NULL) {\r
-    FreePool (TxData);\r
-  }\r
-\r
-  if (TxToken->Event != NULL) {\r
-    gBS->CloseEvent (TxToken->Event);\r
-  }\r
-\r
-  FreePool (TxToken);\r
-}\r
-\r
-\r
-/**\r
-  Delete the cache entries in the specified CacheTable, using the BySwAddress,\r
-  SwAddressType, AddressBuffer combination as the matching key, if Force is TRUE,\r
-  the cache is deleted event it's a static entry.\r
-\r
-  @param[in]  CacheTable             Pointer to the cache table to do the deletion.\r
-  @param[in]  BySwAddress            Delete the cache entry by software address or by\r
-                                     hardware address.\r
-  @param[in]  SwAddressType          The software address used to do the deletion.\r
-  @param[in]  AddressBuffer          Pointer to the buffer containing the address to\r
-                                     match for the deletion.\r
-  @param[in]  Force                  This deletion is forced or not.\r
-\r
-  @return The count of the deleted cache entries.\r
-\r
-**/\r
-UINTN\r
-ArpDeleteCacheEntryInTable (\r
-  IN LIST_ENTRY      *CacheTable,\r
-  IN BOOLEAN         BySwAddress,\r
-  IN UINT16          SwAddressType,\r
-  IN UINT8           *AddressBuffer OPTIONAL,\r
-  IN BOOLEAN         Force\r
-  )\r
-{\r
-  LIST_ENTRY       *Entry;\r
-  LIST_ENTRY       *NextEntry;\r
-  ARP_CACHE_ENTRY  *CacheEntry;\r
-  UINTN            Count;\r
-\r
-  Count = 0;\r
-\r
-  NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, CacheTable) {\r
-    CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);\r
-\r
-    if ((CacheEntry->DefaultDecayTime == 0) && !Force) {\r
-      //\r
-      // It's a static entry and we are not forced to delete it, skip.\r
-      //\r
-      continue;\r
-    }\r
-\r
-    if (BySwAddress) {\r
-      if (SwAddressType == CacheEntry->Addresses[Protocol].Type) {\r
-        //\r
-        // Protocol address type matched. Check the address.\r
-        //\r
-        if ((AddressBuffer == NULL) ||\r
-          (CompareMem (\r
-             AddressBuffer,\r
-             CacheEntry->Addresses[Protocol].AddressPtr,\r
-             CacheEntry->Addresses[Protocol].Length\r
-             ) == 0)) {\r
-          //\r
-          // Address matched.\r
-          //\r
-          goto MATCHED;\r
-        }\r
-      }\r
-    } else {\r
-      if ((AddressBuffer == NULL) ||\r
-        (CompareMem (\r
-           AddressBuffer,\r
-           CacheEntry->Addresses[Hardware].AddressPtr,\r
-           CacheEntry->Addresses[Hardware].Length\r
-           ) == 0)) {\r
-        //\r
-        // Address matched.\r
-        //\r
-        goto MATCHED;\r
-      }\r
-    }\r
-\r
-    continue;\r
-\r
-MATCHED:\r
-\r
-    //\r
-    // Delete this entry.\r
-    //\r
-    RemoveEntryList (&CacheEntry->List);\r
-    ASSERT (IsListEmpty (&CacheEntry->UserRequestList));\r
-    FreePool (CacheEntry);\r
-\r
-    Count++;\r
-  }\r
-\r
-  return Count;\r
-}\r
-\r
-\r
-/**\r
-  Delete cache entries in all the cache tables.\r
-\r
-  @param[in]  Instance               Pointer to the instance context data.\r
-  @param[in]  BySwAddress            Delete the cache entry by software address or by\r
-                                     hardware address.\r
-  @param[in]  AddressBuffer          Pointer to the buffer containing the address to\r
-                                     match for the deletion.\r
-  @param[in]  Force                  This deletion is forced or not.\r
-\r
-  @return The count of the deleted cache entries.\r
-\r
-**/\r
-UINTN\r
-ArpDeleteCacheEntry (\r
-  IN ARP_INSTANCE_DATA  *Instance,\r
-  IN BOOLEAN            BySwAddress,\r
-  IN UINT8              *AddressBuffer OPTIONAL,\r
-  IN BOOLEAN            Force\r
-  )\r
-{\r
-  ARP_SERVICE_DATA  *ArpService;\r
-  UINTN             Count;\r
-\r
-  NET_CHECK_SIGNATURE (Instance, ARP_INSTANCE_DATA_SIGNATURE);\r
-\r
-  ArpService = Instance->ArpService;\r
-\r
-  //\r
-  // Delete the cache entries in the DeniedCacheTable.\r
-  //\r
-  Count = ArpDeleteCacheEntryInTable (\r
-            &ArpService->DeniedCacheTable,\r
-            BySwAddress,\r
-            Instance->ConfigData.SwAddressType,\r
-            AddressBuffer,\r
-            Force\r
-            );\r
-\r
-  //\r
-  // Delete the cache entries inthe ResolvedCacheTable.\r
-  //\r
-  Count += ArpDeleteCacheEntryInTable (\r
-             &ArpService->ResolvedCacheTable,\r
-             BySwAddress,\r
-             Instance->ConfigData.SwAddressType,\r
-             AddressBuffer,\r
-             Force\r
-             );\r
-\r
-  return Count;\r
-}\r
-\r
-\r
-/**\r
-  Cancel the arp request.\r
-\r
-  @param[in]  Instance               Pointer to the instance context data.\r
-  @param[in]  TargetSwAddress        Pointer to the buffer containing the target\r
-                                     software address to match the arp request.\r
-  @param[in]  UserEvent              The user event used to notify this request\r
-                                     cancellation.\r
-\r
-  @return The count of the cancelled requests.\r
-\r
-**/\r
-UINTN\r
-ArpCancelRequest (\r
-  IN ARP_INSTANCE_DATA  *Instance,\r
-  IN VOID               *TargetSwAddress OPTIONAL,\r
-  IN EFI_EVENT          UserEvent        OPTIONAL\r
-  )\r
-{\r
-  ARP_SERVICE_DATA  *ArpService;\r
-  LIST_ENTRY        *Entry;\r
-  LIST_ENTRY        *NextEntry;\r
-  ARP_CACHE_ENTRY   *CacheEntry;\r
-  UINTN             Count;\r
-\r
-  NET_CHECK_SIGNATURE (Instance, ARP_INSTANCE_DATA_SIGNATURE);\r
-\r
-  ArpService = Instance->ArpService;\r
-\r
-  Count = 0;\r
-  NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &ArpService->PendingRequestTable) {\r
-    CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);\r
-\r
-    if ((TargetSwAddress == NULL) ||\r
-      (CompareMem (\r
-         TargetSwAddress,\r
-         CacheEntry->Addresses[Protocol].AddressPtr,\r
-         CacheEntry->Addresses[Protocol].Length\r
-         ) == 0)) {\r
-      //\r
-      // This request entry matches the TargetSwAddress or all requests are to be\r
-      // cancelled as TargetSwAddress is NULL.\r
-      //\r
-      Count += ArpAddressResolved (CacheEntry, Instance, UserEvent);\r
-\r
-      if (IsListEmpty (&CacheEntry->UserRequestList)) {\r
-        //\r
-        // No user requests any more, remove this request cache entry.\r
-        //\r
-        RemoveEntryList (&CacheEntry->List);\r
-        FreePool (CacheEntry);\r
-      }\r
-    }\r
-  }\r
-\r
-  return Count;\r
-}\r
-\r
-\r
-/**\r
-  Find the cache entry in the cache table.\r
-\r
-  @param[in]  Instance           Pointer to the instance context data.\r
-  @param[in]  BySwAddress        Set to TRUE to look for matching software protocol\r
-                                 addresses. Set to FALSE to look for matching\r
-                                 hardware protocol addresses.\r
-  @param[in]  AddressBuffer      Pointer to address buffer. Set to NULL to match\r
-                                 all addresses.\r
-  @param[out] EntryLength        The size of an entry in the entries buffer.\r
-  @param[out] EntryCount         The number of ARP cache entries that are found by\r
-                                 the specified criteria.\r
-  @param[out] Entries            Pointer to the buffer that will receive the ARP\r
-                                 cache entries.\r
-  @param[in]  Refresh            Set to TRUE to refresh the timeout value of the\r
-                                 matching ARP cache entry.\r
-\r
-  @retval EFI_SUCCESS            The requested ARP cache entries are copied into\r
-                                 the buffer.\r
-  @retval EFI_NOT_FOUND          No matching entries found.\r
-  @retval EFI_OUT_OF_RESOURCE    There is a memory allocation failure.\r
-\r
-**/\r
-EFI_STATUS\r
-ArpFindCacheEntry (\r
-  IN ARP_INSTANCE_DATA   *Instance,\r
-  IN BOOLEAN             BySwAddress,\r
-  IN VOID                *AddressBuffer OPTIONAL,\r
-  OUT UINT32             *EntryLength   OPTIONAL,\r
-  OUT UINT32             *EntryCount    OPTIONAL,\r
-  OUT EFI_ARP_FIND_DATA  **Entries      OPTIONAL,\r
-  IN BOOLEAN             Refresh\r
-  )\r
-{\r
-  EFI_STATUS         Status;\r
-  ARP_SERVICE_DATA   *ArpService;\r
-  NET_ARP_ADDRESS    MatchAddress;\r
-  FIND_OPTYPE        FindOpType;\r
-  LIST_ENTRY         *StartEntry;\r
-  ARP_CACHE_ENTRY    *CacheEntry;\r
-  NET_MAP            FoundEntries;\r
-  UINT32             FoundCount;\r
-  EFI_ARP_FIND_DATA  *FindData;\r
-  LIST_ENTRY         *CacheTable;\r
-  UINT32             FoundEntryLength;\r
-\r
-  ArpService = Instance->ArpService;\r
-\r
-  //\r
-  // Init the FounEntries used to hold the found cache entries.\r
-  //\r
-  NetMapInit (&FoundEntries);\r
-\r
-  //\r
-  // Set the MatchAddress.\r
-  //\r
-  if (BySwAddress) {\r
-    MatchAddress.Type   = Instance->ConfigData.SwAddressType;\r
-    MatchAddress.Length = Instance->ConfigData.SwAddressLength;\r
-    FindOpType          = ByProtoAddress;\r
-  } else {\r
-    MatchAddress.Type   = ArpService->SnpMode.IfType;\r
-    MatchAddress.Length = (UINT8)ArpService->SnpMode.HwAddressSize;\r
-    FindOpType          = ByHwAddress;\r
-  }\r
-\r
-  MatchAddress.AddressPtr = AddressBuffer;\r
-\r
-  //\r
-  // Search the DeniedCacheTable\r
-  //\r
-  StartEntry = NULL;\r
-  while (TRUE) {\r
-    //\r
-    // Try to find the matched entries in the DeniedCacheTable.\r
-    //\r
-    CacheEntry = ArpFindNextCacheEntryInTable (\r
-                   &ArpService->DeniedCacheTable,\r
-                   StartEntry,\r
-                   FindOpType,\r
-                   &MatchAddress,\r
-                   &MatchAddress\r
-                   );\r
-    if (CacheEntry == NULL) {\r
-      //\r
-      // Once the CacheEntry is NULL, there are no more matches.\r
-      //\r
-      break;\r
-    }\r
-\r
-    //\r
-    // Insert the found entry into the map.\r
-    //\r
-    NetMapInsertTail (\r
-      &FoundEntries,\r
-      (VOID *)CacheEntry,\r
-      (VOID *)&ArpService->DeniedCacheTable\r
-      );\r
-\r
-    //\r
-    // Let the next search start from this cache entry.\r
-    //\r
-    StartEntry = &CacheEntry->List;\r
-\r
-    if (Refresh) {\r
-      //\r
-      // Refresh the DecayTime if needed.\r
-      //\r
-      CacheEntry->DecayTime = CacheEntry->DefaultDecayTime;\r
-    }\r
-  }\r
-\r
-  //\r
-  // Search the ResolvedCacheTable\r
-  //\r
-  StartEntry = NULL;\r
-  while (TRUE) {\r
-    CacheEntry = ArpFindNextCacheEntryInTable (\r
-                   &ArpService->ResolvedCacheTable,\r
-                   StartEntry,\r
-                   FindOpType,\r
-                   &MatchAddress,\r
-                   &MatchAddress\r
-                   );\r
-    if (CacheEntry == NULL) {\r
-      //\r
-      // Once the CacheEntry is NULL, there are no more matches.\r
-      //\r
-      break;\r
-    }\r
-\r
-    //\r
-    // Insert the found entry into the map.\r
-    //\r
-    NetMapInsertTail (\r
-      &FoundEntries,\r
-      (VOID *)CacheEntry,\r
-      (VOID *)&ArpService->ResolvedCacheTable\r
-      );\r
-\r
-    //\r
-    // Let the next search start from this cache entry.\r
-    //\r
-    StartEntry = &CacheEntry->List;\r
-\r
-    if (Refresh) {\r
-      //\r
-      // Refresh the DecayTime if needed.\r
-      //\r
-      CacheEntry->DecayTime = CacheEntry->DefaultDecayTime;\r
-    }\r
-  }\r
-\r
-  Status = EFI_SUCCESS;\r
-\r
-  FoundCount = (UINT32) NetMapGetCount (&FoundEntries);\r
-  if (FoundCount == 0) {\r
-    Status = EFI_NOT_FOUND;\r
-    goto CLEAN_EXIT;\r
-  }\r
-\r
-  //\r
-  // Found the entry length, make sure its 8 bytes alignment.\r
-  //\r
-  FoundEntryLength = (((sizeof (EFI_ARP_FIND_DATA) + Instance->ConfigData.SwAddressLength +\r
-                       ArpService->SnpMode.HwAddressSize) + 3) & ~(0x3));\r
-\r
-  if (EntryLength != NULL) {\r
-    *EntryLength = FoundEntryLength;\r
-  }\r
-\r
-  if (EntryCount != NULL) {\r
-    //\r
-    // Return the found entry count.\r
-    //\r
-    *EntryCount = FoundCount;\r
-  }\r
-\r
-  if (Entries == NULL) {\r
-    goto CLEAN_EXIT;\r
-  }\r
-\r
-  //\r
-  // Allocate buffer to copy the found entries.\r
-  //\r
-  FindData = AllocatePool (FoundCount * FoundEntryLength);\r
-  if (FindData == NULL) {\r
-    DEBUG ((EFI_D_ERROR, "ArpFindCacheEntry: Failed to allocate memory.\n"));\r
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto CLEAN_EXIT;\r
-  }\r
-\r
-  //\r
-  // Return the address to the user.\r
-  //\r
-  *Entries = FindData;\r
-\r
-  //\r
-  // Dump the entries.\r
-  //\r
-  while (!NetMapIsEmpty (&FoundEntries)) {\r
-    //\r
-    // Get a cache entry from the map.\r
-    //\r
-    CacheEntry = NetMapRemoveHead (&FoundEntries, (VOID **)&CacheTable);\r
-\r
-    //\r
-    // Set the fields in FindData.\r
-    //\r
-    FindData->Size            = FoundEntryLength;\r
-    FindData->DenyFlag        = (BOOLEAN)(CacheTable == &ArpService->DeniedCacheTable);\r
-    FindData->StaticFlag      = (BOOLEAN)(CacheEntry->DefaultDecayTime == 0);\r
-    FindData->HwAddressType   = ArpService->SnpMode.IfType;\r
-    FindData->SwAddressType   = Instance->ConfigData.SwAddressType;\r
-    FindData->HwAddressLength = (UINT8)ArpService->SnpMode.HwAddressSize;\r
-    FindData->SwAddressLength = Instance->ConfigData.SwAddressLength;\r
-\r
-    //\r
-    // Copy the software address.\r
-    //\r
-    CopyMem (\r
-      FindData + 1,\r
-      CacheEntry->Addresses[Protocol].AddressPtr,\r
-      FindData->SwAddressLength\r
-      );\r
-\r
-    //\r
-    // Copy the hardware address.\r
-    //\r
-    CopyMem (\r
-      (UINT8 *)(FindData + 1) + FindData->SwAddressLength,\r
-      CacheEntry->Addresses[Hardware].AddressPtr,\r
-      FindData->HwAddressLength\r
-      );\r
-\r
-    //\r
-    // Slip to the next FindData.\r
-    //\r
-    FindData = (EFI_ARP_FIND_DATA *)((UINT8 *)FindData + FoundEntryLength);\r
-  }\r
-\r
-CLEAN_EXIT:\r
-\r
-  NetMapClean (&FoundEntries);\r
-\r
-  return Status;\r
-}\r
-\r