]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Network/ArpDxe/ArpDriver.c
Import ArpDxe, Dhcp4Dxe, Ip4Dxe, Mtftp4Dxe, PxeBcDxe and PxeDhcp4Dxe.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / ArpDxe / ArpDriver.c
diff --git a/MdeModulePkg/Universal/Network/ArpDxe/ArpDriver.c b/MdeModulePkg/Universal/Network/ArpDxe/ArpDriver.c
new file mode 100644 (file)
index 0000000..2c10857
--- /dev/null
@@ -0,0 +1,763 @@
+/** @file\r
+\r
+Copyright (c) 2006, Intel Corporation\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
+http://opensource.org/licenses/bsd-license.php\r
+\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
+Module Name:\r
+\r
+  ArpDriver.c\r
+\r
+Abstract:\r
+\r
+\r
+**/\r
+\r
+\r
+#include "ArpDriver.h"\r
+#include "ArpImpl.h"\r
+\r
+EFI_DRIVER_BINDING_PROTOCOL gArpDriverBinding = {\r
+  ArpDriverBindingSupported,\r
+  ArpDriverBindingStart,\r
+  ArpDriverBindingStop,\r
+  0xa,\r
+  NULL,\r
+  NULL\r
+};\r
+\r
+\r
+/**\r
+  Create and initialize the arp service context data.\r
+\r
+  @param  ImageHandle            The image handle representing the loaded driver\r
+                                 image.\r
+  @param  ControllerHandle       The controller handle the driver binds to.\r
+  @param  ArpService             Pointer to the buffer containing the arp service\r
+                                 context data.\r
+\r
+  @retval EFI_SUCCESS            The arp service context is initialized.\r
+  @retval other                  Failed to initialize the arp service context.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ArpCreateService (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_HANDLE        ControllerHandle,\r
+  IN ARP_SERVICE_DATA  *ArpService\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  ASSERT (ArpService != NULL);\r
+\r
+  ArpService->Signature = ARP_SERVICE_DATA_SIGNATURE;\r
+\r
+  //\r
+  // Init the servicebinding protocol members.\r
+  //\r
+  ArpService->ServiceBinding.CreateChild  = ArpServiceBindingCreateChild;\r
+  ArpService->ServiceBinding.DestroyChild = ArpServiceBindingDestroyChild;\r
+\r
+  //\r
+  // Save the handles.\r
+  //\r
+  ArpService->ImageHandle      = ImageHandle;\r
+  ArpService->ControllerHandle = ControllerHandle;\r
+\r
+  //\r
+  // Create a MNP child instance.\r
+  //\r
+  Status = NetLibCreateServiceChild (\r
+             ControllerHandle,\r
+             ImageHandle,\r
+             &gEfiManagedNetworkServiceBindingProtocolGuid,\r
+             &ArpService->MnpChildHandle\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Open the MNP protocol.\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  ArpService->MnpChildHandle,\r
+                  &gEfiManagedNetworkProtocolGuid,\r
+                  (VOID **)&ArpService->Mnp,\r
+                  ImageHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ERROR_EXIT;\r
+  }\r
+\r
+  //\r
+  // Get the underlayer Snp mode data.\r
+  //\r
+  Status = ArpService->Mnp->GetModeData (ArpService->Mnp, NULL, &ArpService->SnpMode);\r
+  if ((Status != EFI_NOT_STARTED) && EFI_ERROR (Status)) {\r
+    goto ERROR_EXIT;\r
+  }\r
+\r
+  if (ArpService->SnpMode.IfType != NET_IFTYPE_ETHERNET) {\r
+    //\r
+    // Only support the ethernet.\r
+    //\r
+    Status = EFI_UNSUPPORTED;\r
+    goto ERROR_EXIT;\r
+  }\r
+\r
+  //\r
+  // Set the Mnp config parameters.\r
+  //\r
+  ArpService->MnpConfigData.ReceivedQueueTimeoutValue = 0;\r
+  ArpService->MnpConfigData.TransmitQueueTimeoutValue = 0;\r
+  ArpService->MnpConfigData.ProtocolTypeFilter        = ARP_ETHER_PROTO_TYPE;\r
+  ArpService->MnpConfigData.EnableUnicastReceive      = TRUE;\r
+  ArpService->MnpConfigData.EnableMulticastReceive    = FALSE;\r
+  ArpService->MnpConfigData.EnableBroadcastReceive    = TRUE;\r
+  ArpService->MnpConfigData.EnablePromiscuousReceive  = FALSE;\r
+  ArpService->MnpConfigData.FlushQueuesOnReset        = TRUE;\r
+  ArpService->MnpConfigData.EnableReceiveTimestamps   = FALSE;\r
+  ArpService->MnpConfigData.DisableBackgroundPolling  = FALSE;\r
+\r
+  //\r
+  // Configure the Mnp child.\r
+  //\r
+  Status = ArpService->Mnp->Configure (ArpService->Mnp, &ArpService->MnpConfigData);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ERROR_EXIT;\r
+  }\r
+\r
+  //\r
+  // Create the event used in the RxToken.\r
+  //\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  NET_TPL_EVENT,\r
+                  ArpOnFrameRcvd,\r
+                  ArpService,\r
+                  &ArpService->RxToken.Event\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ERROR_EXIT;\r
+  }\r
+\r
+  //\r
+  // Create the Arp heartbeat timer.\r
+  //\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
+                  NET_TPL_TIMER,\r
+                  ArpTimerHandler,\r
+                  ArpService,\r
+                  &ArpService->PeriodicTimer\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ERROR_EXIT;\r
+  }\r
+\r
+  //\r
+  // Start the heartbeat timer.\r
+  //\r
+  Status = gBS->SetTimer (\r
+                  ArpService->PeriodicTimer,\r
+                  TimerPeriodic,\r
+                  ARP_PERIODIC_TIMER_INTERVAL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ERROR_EXIT;\r
+  }\r
+\r
+  //\r
+  // Init the lock.\r
+  //\r
+  NET_LOCK_INIT (&ArpService->Lock);\r
+\r
+  //\r
+  // Init the lists.\r
+  //\r
+  NetListInit (&ArpService->ChildrenList);\r
+  NetListInit (&ArpService->PendingRequestTable);\r
+  NetListInit (&ArpService->DeniedCacheTable);\r
+  NetListInit (&ArpService->ResolvedCacheTable);\r
+\r
+ERROR_EXIT:\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Clean the arp service context data.\r
+\r
+  @param  ArpService             Pointer to the buffer containing the arp service\r
+                                 context data.\r
+\r
+  @return None.\r
+\r
+**/\r
+STATIC\r
+VOID\r
+ArpCleanService (\r
+  IN ARP_SERVICE_DATA  *ArpService\r
+  )\r
+{\r
+  NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);\r
+\r
+  if (ArpService->PeriodicTimer != NULL) {\r
+    //\r
+    // Cancle and close the PeriodicTimer.\r
+    //\r
+    gBS->SetTimer (ArpService->PeriodicTimer, TimerCancel, 0);\r
+    gBS->CloseEvent (ArpService->PeriodicTimer);\r
+  }\r
+\r
+  if (ArpService->RxToken.Event != NULL) {\r
+    //\r
+    // Cancle the RxToken and close the event in the RxToken.\r
+    //\r
+    ArpService->Mnp->Cancel (ArpService->Mnp, NULL);\r
+    gBS->CloseEvent (ArpService->RxToken.Event);\r
+  }\r
+\r
+  if (ArpService->Mnp != NULL) {\r
+    //\r
+    // Reset the Mnp child and close the Mnp protocol.\r
+    //\r
+    ArpService->Mnp->Configure (ArpService->Mnp, NULL);\r
+    gBS->CloseProtocol (\r
+           ArpService->MnpChildHandle,\r
+           &gEfiManagedNetworkProtocolGuid,\r
+           ArpService->ImageHandle,\r
+           ArpService->ControllerHandle\r
+           );\r
+  }\r
+\r
+  if (ArpService->MnpChildHandle != NULL) {\r
+    //\r
+    // Destroy the mnp child.\r
+    //\r
+    NetLibDestroyServiceChild(\r
+      ArpService->ControllerHandle,\r
+      ArpService->ImageHandle,\r
+      &gEfiManagedNetworkServiceBindingProtocolGuid,\r
+      ArpService->MnpChildHandle\r
+      );\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Test to see if this driver supports ControllerHandle.\r
+\r
+  @param  This                   Protocol instance pointer.\r
+  @param  ControllerHandle       Handle of device to test.\r
+  @param  RemainingDevicePath    Optional parameter use to pick a specific child\r
+                                 device to start.\r
+\r
+  @retval EFI_SUCCES             This driver supports this device\r
+  @retval EFI_ALREADY_STARTED    This driver is already running on this device.\r
+  @retval other                  This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ArpDriverBindingSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   ControllerHandle,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Test to see if Arp SB is already installed.\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiArpServiceBindingProtocolGuid,\r
+                  NULL,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+                  );\r
+  if (Status == EFI_SUCCESS) {\r
+    return EFI_ALREADY_STARTED;\r
+  }\r
+\r
+  //\r
+  // Test to see if MNP SB is installed.\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiManagedNetworkServiceBindingProtocolGuid,\r
+                  NULL,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+                  );\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Start this driver on ControllerHandle.\r
+\r
+  @param  This                   Protocol instance pointer.\r
+  @param  ControllerHandle       Handle of device to bind driver to\r
+  @param  RemainingDevicePath    Optional parameter use to pick a specific child\r
+                                 device to start.\r
+\r
+  @retval EFI_SUCCES             This driver is added to ControllerHandle\r
+  @retval EFI_ALREADY_STARTED    This driver is already running on ControllerHandle\r
+  @retval other                  This driver does not support this device\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ArpDriverBindingStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   ControllerHandle,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS        Status;\r
+  ARP_SERVICE_DATA  *ArpService;\r
+\r
+  //\r
+  // Allocate a zero pool for ArpService.\r
+  //\r
+  ArpService = NetAllocateZeroPool (sizeof(ARP_SERVICE_DATA));\r
+  if (ArpService == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Initialize the arp service context data.\r
+  //\r
+  Status = ArpCreateService (This->DriverBindingHandle, ControllerHandle, ArpService);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ERROR;\r
+  }\r
+\r
+  //\r
+  // Install the ARP service binding protocol.\r
+  //\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  &ControllerHandle,\r
+                  &gEfiArpServiceBindingProtocolGuid,\r
+                  &ArpService->ServiceBinding,\r
+                  NULL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ERROR;\r
+  }\r
+\r
+  //\r
+  // OK, start to receive arp packets from Mnp.\r
+  //\r
+  Status = ArpService->Mnp->Receive (ArpService->Mnp, &ArpService->RxToken);\r
+  if (EFI_ERROR (Status)) {\r
+    goto ERROR;\r
+  }\r
+\r
+  return Status;\r
+\r
+ERROR:\r
+\r
+  //\r
+  // On error, clean the arp service context data, and free the memory allocated.\r
+  //\r
+  ArpCleanService (ArpService);\r
+  NetFreePool (ArpService);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Stop this driver on ControllerHandle.\r
+\r
+  @param  This                   Protocol instance pointer.\r
+  @param  ControllerHandle       Handle of device to stop driver on\r
+  @param  NumberOfChildren       Number of Handles in ChildHandleBuffer. If number\r
+                                 of  children is zero stop the entire bus driver.\r
+  @param  ChildHandleBuffer      List of Child Handles to Stop.\r
+\r
+  @retval EFI_SUCCES             This driver is removed ControllerHandle\r
+  @retval other                  This driver was not removed from this device\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ArpDriverBindingStop (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   ControllerHandle,\r
+  IN UINTN                        NumberOfChildren,\r
+  IN EFI_HANDLE                   *ChildHandleBuffer\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_HANDLE                    NicHandle;\r
+  EFI_SERVICE_BINDING_PROTOCOL  *ServiceBinding;\r
+  ARP_SERVICE_DATA              *ArpService;\r
+  ARP_INSTANCE_DATA             *Instance;\r
+\r
+  //\r
+  // Get the NicHandle which the arp servicebinding is installed on.\r
+  //\r
+  NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);\r
+  if (NicHandle == NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Try to get the arp servicebinding protocol on the NicHandle.\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  NicHandle,\r
+                  &gEfiArpServiceBindingProtocolGuid,\r
+                  (VOID **)&ServiceBinding,\r
+                  This->DriverBindingHandle,\r
+                  ControllerHandle,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    ARP_DEBUG_ERROR (("ArpDriverBindingStop: Open ArpSb failed, %r.\n", Status));\r
+    return Status;\r
+  }\r
+\r
+  ArpService = ARP_SERVICE_DATA_FROM_THIS (ServiceBinding);\r
+\r
+  while (!NetListIsEmpty (&ArpService->ChildrenList)) {\r
+    //\r
+    // Iterate all the instances.\r
+    //\r
+    Instance = NET_LIST_HEAD (&ArpService->ChildrenList, ARP_INSTANCE_DATA, List);\r
+\r
+    //\r
+    // Destroy this arp child.\r
+    //\r
+    ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);\r
+  }\r
+\r
+  ASSERT (NetListIsEmpty (&ArpService->PendingRequestTable));\r
+  ASSERT (NetListIsEmpty (&ArpService->DeniedCacheTable));\r
+  ASSERT (NetListIsEmpty (&ArpService->ResolvedCacheTable));\r
+\r
+  //\r
+  // Uninstall the ARP ServiceBinding protocol.\r
+  //\r
+  Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                  NicHandle,\r
+                  &gEfiArpServiceBindingProtocolGuid,\r
+                  &ArpService->ServiceBinding,\r
+                  NULL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    ARP_DEBUG_ERROR (("ArpDriverBindingStop: Failed to uninstall ArpSb, %r.\n", Status));\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Clean the arp servicebinding context data and free the memory allocated.\r
+  //\r
+  ArpCleanService (ArpService);\r
+  NetFreePool (ArpService);\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Creates a child handle with a set of I/O services.\r
+\r
+  @param  This                   Protocol instance pointer.\r
+  @param  ChildHandle            Pointer to the handle of the child to create. If\r
+                                 it is NULL, then a new handle is created. If it is\r
+                                 not NULL, then the I/O services are  added to the\r
+                                 existing child handle.\r
+\r
+  @retval EFI_SUCCES             The child handle was created with the I/O\r
+                                 services.\r
+  @retval EFI_OUT_OF_RESOURCES   There are not enough resources availabe to create\r
+                                 the child.\r
+  @retval other                  The child handle was not created.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ArpServiceBindingCreateChild (\r
+  IN EFI_SERVICE_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                    *ChildHandle\r
+  )\r
+{\r
+  EFI_STATUS         Status;\r
+  ARP_SERVICE_DATA   *ArpService;\r
+  ARP_INSTANCE_DATA  *Instance;\r
+  VOID               *Mnp;\r
+\r
+  if ((This == NULL) || (ChildHandle == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  ArpService = ARP_SERVICE_DATA_FROM_THIS (This);\r
+\r
+  //\r
+  // Allocate memory for the instance context data.\r
+  //\r
+  Instance = NetAllocateZeroPool (sizeof(ARP_INSTANCE_DATA));\r
+  if (Instance == NULL) {\r
+    ARP_DEBUG_ERROR (("ArpSBCreateChild: Failed to allocate memory for Instance.\n"));\r
+\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Init the instance context data.\r
+  //\r
+  ArpInitInstance (ArpService, Instance);\r
+\r
+  //\r
+  // Install the ARP protocol onto the ChildHandle.\r
+  //\r
+  Status = gBS->InstallMultipleProtocolInterfaces (\r
+                  ChildHandle,\r
+                  &gEfiArpProtocolGuid,\r
+                  (VOID *)&Instance->ArpProto,\r
+                  NULL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    ARP_DEBUG_ERROR (("ArpSBCreateChild: faild to install ARP protocol, %r.\n", Status));\r
+\r
+    NetFreePool (Instance);\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Save the ChildHandle.\r
+  //\r
+  Instance->Handle = *ChildHandle;\r
+\r
+  //\r
+  // Open the Managed Network protocol BY_CHILD.\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  ArpService->MnpChildHandle,\r
+                  &gEfiManagedNetworkProtocolGuid,\r
+                  (VOID **) &Mnp,\r
+                  gArpDriverBinding.DriverBindingHandle,\r
+                  Instance->Handle,\r
+                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ERROR;\r
+  }\r
+\r
+  if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {\r
+\r
+    Status = EFI_ACCESS_DENIED;\r
+    goto ERROR;\r
+  }\r
+\r
+  //\r
+  // Insert the instance into children list managed by the arp service context data.\r
+  //\r
+  NetListInsertTail (&ArpService->ChildrenList, &Instance->List);\r
+  ArpService->ChildrenNumber++;\r
+\r
+  NET_UNLOCK (&ArpService->Lock);\r
+\r
+ERROR:\r
+\r
+  if (EFI_ERROR (Status)) {\r
+\r
+    gBS->CloseProtocol (\r
+           ArpService->MnpChildHandle,\r
+           &gEfiManagedNetworkProtocolGuid,\r
+           gArpDriverBinding.DriverBindingHandle,\r
+           Instance->Handle\r
+           );\r
+\r
+    gBS->UninstallMultipleProtocolInterfaces (\r
+           Instance->Handle,\r
+           &gEfiArpProtocolGuid,\r
+           &Instance->ArpProto,\r
+           NULL\r
+           );\r
+\r
+    //\r
+    // Free the allocated memory.\r
+    //\r
+    NetFreePool (Instance);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Destroys a child handle with a set of I/O services.\r
+\r
+  @param  This                   Protocol instance pointer.\r
+  @param  ChildHandle            Handle of the child to destroy.\r
+\r
+  @retval EFI_SUCCES             The I/O services were removed from the child\r
+                                 handle.\r
+  @retval EFI_UNSUPPORTED        The child handle does not support the I/O services\r
+                                  that are being removed.\r
+  @retval EFI_INVALID_PARAMETER  Child handle is not a valid EFI Handle.\r
+  @retval EFI_ACCESS_DENIED      The child handle could not be destroyed because\r
+                                 its  I/O services are being used.\r
+  @retval other                  The child handle was not destroyed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ArpServiceBindingDestroyChild (\r
+  IN EFI_SERVICE_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                    ChildHandle\r
+  )\r
+{\r
+  EFI_STATUS         Status;\r
+  ARP_SERVICE_DATA   *ArpService;\r
+  ARP_INSTANCE_DATA  *Instance;\r
+  EFI_ARP_PROTOCOL   *Arp;\r
+\r
+  if ((This == NULL) || (ChildHandle == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  ArpService = ARP_SERVICE_DATA_FROM_THIS (This);\r
+\r
+  //\r
+  // Get the arp protocol.\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  ChildHandle,\r
+                  &gEfiArpProtocolGuid,\r
+                  (VOID **)&Arp,\r
+                  ArpService->ImageHandle,\r
+                  ChildHandle,\r
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Instance = ARP_INSTANCE_DATA_FROM_THIS (Arp);\r
+\r
+  if (Instance->Destroyed) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Use the Destroyed as a flag to avoid re-entrance.\r
+  //\r
+  Instance->Destroyed = TRUE;\r
+\r
+  //\r
+  // Close the Managed Network protocol.\r
+  //\r
+  gBS->CloseProtocol (\r
+         ArpService->MnpChildHandle,\r
+         &gEfiManagedNetworkProtocolGuid,\r
+         gArpDriverBinding.DriverBindingHandle,\r
+         ChildHandle\r
+         );\r
+\r
+  //\r
+  // Uninstall the ARP protocol.\r
+  //\r
+  Status = gBS->UninstallMultipleProtocolInterfaces (\r
+                  ChildHandle,\r
+                  &gEfiArpProtocolGuid,\r
+                  &Instance->ArpProto,\r
+                  NULL\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    ARP_DEBUG_ERROR (("ArpSBDestroyChild: Failed to uninstall the arp protocol, %r.\n",\r
+      Status));\r
+\r
+    Instance->Destroyed = FALSE;\r
+    return Status;\r
+  }\r
+\r
+  if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {\r
+    Instance->Destroyed = FALSE;\r
+    return EFI_ACCESS_DENIED;\r
+  }\r
+\r
+  if (Instance->Configured) {\r
+    //\r
+    // Delete the related cache entry.\r
+    //\r
+    ArpDeleteCacheEntry (Instance, FALSE, NULL, TRUE);\r
+\r
+    //\r
+    // Reset the instance configuration.\r
+    //\r
+    ArpConfigureInstance (Instance, NULL);\r
+  }\r
+\r
+  //\r
+  // Remove this instance from the ChildrenList.\r
+  //\r
+  NetListRemoveEntry (&Instance->List);\r
+  ArpService->ChildrenNumber--;\r
+\r
+  NET_UNLOCK (&ArpService->Lock);\r
+\r
+  NetFreePool (Instance);\r
+\r
+  return Status;\r
+}\r
+\r
+//@MT: EFI_DRIVER_ENTRY_POINT (ArpDriverEntryPoint)\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ArpDriverEntryPoint (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  The entry point for Arp driver which installs the driver binding and component name\r
+  protocol on its ImageHandle.\r
+\r
+Arguments:\r
+\r
+  ImageHandle - The image handle of the driver.\r
+  SystemTable - The system table.\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS - if the driver binding and component name protocols are successfully\r
+                installed, otherwise if failed.\r
+\r
+--*/\r
+{\r
+  return NetLibInstallAllDriverProtocols (\r
+           ImageHandle,\r
+           SystemTable,\r
+           &gArpDriverBinding,\r
+           ImageHandle,\r
+           &gArpComponentName,\r
+           NULL,\r
+           NULL\r
+           );\r
+}\r
+\r