Home | History | Annotate | Download | only in ArpDxe
      1 /** @file
      2   ARP driver functions.
      3 
      4 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at<BR>
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "ArpDriver.h"
     16 #include "ArpImpl.h"
     17 
     18 EFI_DRIVER_BINDING_PROTOCOL gArpDriverBinding = {
     19   ArpDriverBindingSupported,
     20   ArpDriverBindingStart,
     21   ArpDriverBindingStop,
     22   0xa,
     23   NULL,
     24   NULL
     25 };
     26 
     27 
     28 /**
     29   Create and initialize the arp service context data.
     30 
     31   @param[in]       ImageHandle       The image handle representing the loaded driver
     32                                      image.
     33   @param[in]       ControllerHandle  The controller handle the driver binds to.
     34   @param[in, out]  ArpService        Pointer to the buffer containing the arp service
     35                                      context data.
     36 
     37   @retval EFI_SUCCESS                The arp service context is initialized.
     38 
     39   @retval EFI_UNSUPPORTED            The underlayer Snp mode type is not ethernet.
     40                                      Failed to initialize the service context.
     41   @retval other                      Failed to initialize the arp service context.
     42 
     43 **/
     44 EFI_STATUS
     45 ArpCreateService (
     46   IN EFI_HANDLE        ImageHandle,
     47   IN EFI_HANDLE        ControllerHandle,
     48   IN OUT ARP_SERVICE_DATA  *ArpService
     49   )
     50 {
     51   EFI_STATUS  Status;
     52 
     53   ASSERT (ArpService != NULL);
     54 
     55   ArpService->Signature = ARP_SERVICE_DATA_SIGNATURE;
     56 
     57   //
     58   // Init the lists.
     59   //
     60   InitializeListHead (&ArpService->ChildrenList);
     61   InitializeListHead (&ArpService->PendingRequestTable);
     62   InitializeListHead (&ArpService->DeniedCacheTable);
     63   InitializeListHead (&ArpService->ResolvedCacheTable);
     64 
     65   //
     66   // Init the servicebinding protocol members.
     67   //
     68   ArpService->ServiceBinding.CreateChild  = ArpServiceBindingCreateChild;
     69   ArpService->ServiceBinding.DestroyChild = ArpServiceBindingDestroyChild;
     70 
     71   //
     72   // Save the handles.
     73   //
     74   ArpService->ImageHandle      = ImageHandle;
     75   ArpService->ControllerHandle = ControllerHandle;
     76 
     77   //
     78   // Create a MNP child instance.
     79   //
     80   Status = NetLibCreateServiceChild (
     81              ControllerHandle,
     82              ImageHandle,
     83              &gEfiManagedNetworkServiceBindingProtocolGuid,
     84              &ArpService->MnpChildHandle
     85              );
     86   if (EFI_ERROR (Status)) {
     87     return Status;
     88   }
     89 
     90   //
     91   // Open the MNP protocol.
     92   //
     93   Status = gBS->OpenProtocol (
     94                   ArpService->MnpChildHandle,
     95                   &gEfiManagedNetworkProtocolGuid,
     96                   (VOID **)&ArpService->Mnp,
     97                   ImageHandle,
     98                   ControllerHandle,
     99                   EFI_OPEN_PROTOCOL_BY_DRIVER
    100                   );
    101   if (EFI_ERROR (Status)) {
    102     goto ERROR_EXIT;
    103   }
    104 
    105   //
    106   // Get the underlayer Snp mode data.
    107   //
    108   Status = ArpService->Mnp->GetModeData (ArpService->Mnp, NULL, &ArpService->SnpMode);
    109   if ((Status != EFI_NOT_STARTED) && EFI_ERROR (Status)) {
    110     goto ERROR_EXIT;
    111   }
    112 
    113   if (ArpService->SnpMode.IfType != NET_IFTYPE_ETHERNET) {
    114     //
    115     // Only support the ethernet.
    116     //
    117     Status = EFI_UNSUPPORTED;
    118     goto ERROR_EXIT;
    119   }
    120 
    121   //
    122   // Set the Mnp config parameters.
    123   //
    124   ArpService->MnpConfigData.ReceivedQueueTimeoutValue = 0;
    125   ArpService->MnpConfigData.TransmitQueueTimeoutValue = 0;
    126   ArpService->MnpConfigData.ProtocolTypeFilter        = ARP_ETHER_PROTO_TYPE;
    127   ArpService->MnpConfigData.EnableUnicastReceive      = TRUE;
    128   ArpService->MnpConfigData.EnableMulticastReceive    = FALSE;
    129   ArpService->MnpConfigData.EnableBroadcastReceive    = TRUE;
    130   ArpService->MnpConfigData.EnablePromiscuousReceive  = FALSE;
    131   ArpService->MnpConfigData.FlushQueuesOnReset        = TRUE;
    132   ArpService->MnpConfigData.EnableReceiveTimestamps   = FALSE;
    133   ArpService->MnpConfigData.DisableBackgroundPolling  = FALSE;
    134 
    135   //
    136   // Configure the Mnp child.
    137   //
    138   Status = ArpService->Mnp->Configure (ArpService->Mnp, &ArpService->MnpConfigData);
    139   if (EFI_ERROR (Status)) {
    140     goto ERROR_EXIT;
    141   }
    142 
    143   //
    144   // Create the event used in the RxToken.
    145   //
    146   Status = gBS->CreateEvent (
    147                   EVT_NOTIFY_SIGNAL,
    148                   TPL_NOTIFY,
    149                   ArpOnFrameRcvd,
    150                   ArpService,
    151                   &ArpService->RxToken.Event
    152                   );
    153   if (EFI_ERROR (Status)) {
    154     goto ERROR_EXIT;
    155   }
    156 
    157   //
    158   // Create the Arp heartbeat timer.
    159   //
    160   Status = gBS->CreateEvent (
    161                   EVT_NOTIFY_SIGNAL | EVT_TIMER,
    162                   TPL_CALLBACK,
    163                   ArpTimerHandler,
    164                   ArpService,
    165                   &ArpService->PeriodicTimer
    166                   );
    167   if (EFI_ERROR (Status)) {
    168     goto ERROR_EXIT;
    169   }
    170 
    171   //
    172   // Start the heartbeat timer.
    173   //
    174   Status = gBS->SetTimer (
    175                   ArpService->PeriodicTimer,
    176                   TimerPeriodic,
    177                   ARP_PERIODIC_TIMER_INTERVAL
    178                   );
    179 
    180 ERROR_EXIT:
    181 
    182   return Status;
    183 }
    184 
    185 
    186 /**
    187   Clean the arp service context data.
    188 
    189   @param[in, out]  ArpService        Pointer to the buffer containing the arp service
    190                                      context data.
    191 
    192   @return None.
    193 
    194 **/
    195 VOID
    196 ArpCleanService (
    197   IN OUT ARP_SERVICE_DATA  *ArpService
    198   )
    199 {
    200   NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);
    201 
    202   if (ArpService->PeriodicTimer != NULL) {
    203     //
    204     // Cancle and close the PeriodicTimer.
    205     //
    206     gBS->SetTimer (ArpService->PeriodicTimer, TimerCancel, 0);
    207     gBS->CloseEvent (ArpService->PeriodicTimer);
    208   }
    209 
    210   if (ArpService->RxToken.Event != NULL) {
    211     //
    212     // Cancle the RxToken and close the event in the RxToken.
    213     //
    214     ArpService->Mnp->Cancel (ArpService->Mnp, NULL);
    215     gBS->CloseEvent (ArpService->RxToken.Event);
    216   }
    217 
    218   if (ArpService->Mnp != NULL) {
    219     //
    220     // Reset the Mnp child and close the Mnp protocol.
    221     //
    222     ArpService->Mnp->Configure (ArpService->Mnp, NULL);
    223     gBS->CloseProtocol (
    224            ArpService->MnpChildHandle,
    225            &gEfiManagedNetworkProtocolGuid,
    226            ArpService->ImageHandle,
    227            ArpService->ControllerHandle
    228            );
    229   }
    230 
    231   if (ArpService->MnpChildHandle != NULL) {
    232     //
    233     // Destroy the mnp child.
    234     //
    235     NetLibDestroyServiceChild(
    236       ArpService->ControllerHandle,
    237       ArpService->ImageHandle,
    238       &gEfiManagedNetworkServiceBindingProtocolGuid,
    239       ArpService->MnpChildHandle
    240       );
    241   }
    242 }
    243 
    244 /**
    245   Callback function which provided by user to remove one node in NetDestroyLinkList process.
    246 
    247   @param[in]    Entry           The entry to be removed.
    248   @param[in]    Context         Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
    249 
    250   @retval EFI_SUCCESS           The entry has been removed successfully.
    251   @retval Others                Fail to remove the entry.
    252 
    253 **/
    254 EFI_STATUS
    255 EFIAPI
    256 ArpDestroyChildEntryInHandleBuffer (
    257   IN LIST_ENTRY         *Entry,
    258   IN VOID               *Context
    259   )
    260 {
    261   ARP_INSTANCE_DATA             *Instance;
    262   EFI_SERVICE_BINDING_PROTOCOL  *ServiceBinding;
    263 
    264   if (Entry == NULL || Context == NULL) {
    265     return EFI_INVALID_PARAMETER;
    266   }
    267 
    268   Instance = NET_LIST_USER_STRUCT_S (Entry, ARP_INSTANCE_DATA, List, ARP_INSTANCE_DATA_SIGNATURE);
    269   ServiceBinding    = (EFI_SERVICE_BINDING_PROTOCOL *) Context;
    270 
    271   return ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);
    272 }
    273 
    274 /**
    275   Tests to see if this driver supports a given controller.
    276 
    277   If a child device is provided, it further tests to see if this driver supports
    278   creating a handle for the specified child device.
    279 
    280   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    281   @param[in]  ControllerHandle     The handle of the controller to test. This handle
    282                                    must support a protocol interface that supplies
    283                                    an I/O abstraction to the driver.
    284   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.
    285                                    This parameter is ignored by device drivers,
    286                                    and is optional for bus drivers.
    287 
    288   @retval EFI_SUCCESS              The device specified by ControllerHandle and
    289                                    RemainingDevicePath is supported by the driver
    290                                    specified by This.
    291   @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
    292                                    RemainingDevicePath is already being managed
    293                                    by the driver specified by This.
    294   @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
    295                                    RemainingDevicePath is already being managed by
    296                                    a different driver or an application that
    297                                    requires exclusive acces. Currently not implemented.
    298   @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
    299                                    RemainingDevicePath is not supported by the
    300                                    driver specified by This.
    301 
    302 **/
    303 EFI_STATUS
    304 EFIAPI
    305 ArpDriverBindingSupported (
    306   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    307   IN EFI_HANDLE                   ControllerHandle,
    308   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
    309   )
    310 {
    311   EFI_STATUS  Status;
    312 
    313   //
    314   // Test to see if Arp SB is already installed.
    315   //
    316   Status = gBS->OpenProtocol (
    317                   ControllerHandle,
    318                   &gEfiArpServiceBindingProtocolGuid,
    319                   NULL,
    320                   This->DriverBindingHandle,
    321                   ControllerHandle,
    322                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
    323                   );
    324   if (Status == EFI_SUCCESS) {
    325     return EFI_ALREADY_STARTED;
    326   }
    327 
    328   //
    329   // Test to see if MNP SB is installed.
    330   //
    331   Status = gBS->OpenProtocol (
    332                   ControllerHandle,
    333                   &gEfiManagedNetworkServiceBindingProtocolGuid,
    334                   NULL,
    335                   This->DriverBindingHandle,
    336                   ControllerHandle,
    337                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
    338                   );
    339 
    340   return Status;
    341 }
    342 
    343 
    344 /**
    345   Start this driver on ControllerHandle.
    346 
    347   The Start() function is designed to be invoked from the EFI boot service ConnectController().
    348   As a result, much of the error checking on the parameters to Start() has been
    349   moved into this common boot service. It is legal to call Start() from other locations,
    350   but the following calling restrictions must be followed or the system behavior
    351   will not be deterministic.
    352   1. ControllerHandle must be a valid EFI_HANDLE.
    353   2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally
    354      aligned EFI_DEVICE_PATH_PROTOCOL.
    355   3. Prior to calling Start(), the Supported() function for the driver specified
    356      by This must have been called with the same calling parameters, and Supported()
    357      must have returned EFI_SUCCESS.
    358 
    359   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    360   @param[in]  ControllerHandle     The handle of the controller to start. This handle
    361                                    must support a protocol interface that supplies
    362                                    an I/O abstraction to the driver.
    363   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.
    364                                    This parameter is ignored by device drivers,
    365                                    and is optional for bus drivers.
    366 
    367   @retval EFI_SUCCESS              The device was started.
    368   @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.
    369                                    Currently not implemented.
    370   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of
    371                                    resources.
    372   @retval Others                   The driver failded to start the device.
    373 
    374 **/
    375 EFI_STATUS
    376 EFIAPI
    377 ArpDriverBindingStart (
    378   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    379   IN EFI_HANDLE                   ControllerHandle,
    380   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
    381   )
    382 {
    383   EFI_STATUS        Status;
    384   ARP_SERVICE_DATA  *ArpService;
    385 
    386   //
    387   // Allocate a zero pool for ArpService.
    388   //
    389   ArpService = AllocateZeroPool (sizeof(ARP_SERVICE_DATA));
    390   if (ArpService == NULL) {
    391     return EFI_OUT_OF_RESOURCES;
    392   }
    393 
    394   //
    395   // Initialize the arp service context data.
    396   //
    397   Status = ArpCreateService (This->DriverBindingHandle, ControllerHandle, ArpService);
    398   if (EFI_ERROR (Status)) {
    399     goto ERROR;
    400   }
    401 
    402   //
    403   // Install the ARP service binding protocol.
    404   //
    405   Status = gBS->InstallMultipleProtocolInterfaces (
    406                   &ControllerHandle,
    407                   &gEfiArpServiceBindingProtocolGuid,
    408                   &ArpService->ServiceBinding,
    409                   NULL
    410                   );
    411   if (EFI_ERROR (Status)) {
    412     goto ERROR;
    413   }
    414 
    415   //
    416   // OK, start to receive arp packets from Mnp.
    417   //
    418   Status = ArpService->Mnp->Receive (ArpService->Mnp, &ArpService->RxToken);
    419   if (EFI_ERROR (Status)) {
    420     goto ERROR;
    421   }
    422 
    423   return Status;
    424 
    425 ERROR:
    426 
    427   //
    428   // On error, clean the arp service context data, and free the memory allocated.
    429   //
    430   ArpCleanService (ArpService);
    431   FreePool (ArpService);
    432 
    433   return Status;
    434 }
    435 
    436 
    437 /**
    438   Stop this driver on ControllerHandle.
    439 
    440   Release the control of this controller and remove the IScsi functions. The Stop()
    441   function is designed to be invoked from the EFI boot service DisconnectController().
    442   As a result, much of the error checking on the parameters to Stop() has been moved
    443   into this common boot service. It is legal to call Stop() from other locations,
    444   but the following calling restrictions must be followed or the system behavior
    445   will not be deterministic.
    446   1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
    447      same driver's Start() function.
    448   2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
    449      EFI_HANDLE. In addition, all of these handles must have been created in this driver's
    450      Start() function, and the Start() function must have called OpenProtocol() on
    451      ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
    452 
    453   @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    454   @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
    455                                 support a bus specific I/O protocol for the driver
    456                                 to use to stop the device.
    457   @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
    458                                 Not used.
    459   @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
    460                                 if NumberOfChildren is 0.Not used.
    461 
    462   @retval EFI_SUCCESS           The device was stopped.
    463   @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
    464 
    465 **/
    466 EFI_STATUS
    467 EFIAPI
    468 ArpDriverBindingStop (
    469   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    470   IN EFI_HANDLE                   ControllerHandle,
    471   IN UINTN                        NumberOfChildren,
    472   IN EFI_HANDLE                   *ChildHandleBuffer
    473   )
    474 {
    475   EFI_STATUS                    Status;
    476   EFI_HANDLE                    NicHandle;
    477   EFI_SERVICE_BINDING_PROTOCOL  *ServiceBinding;
    478   ARP_SERVICE_DATA              *ArpService;
    479   LIST_ENTRY                    *List;
    480 
    481   //
    482   // Get the NicHandle which the arp servicebinding is installed on.
    483   //
    484   NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);
    485   if (NicHandle == NULL) {
    486     return EFI_SUCCESS;
    487   }
    488 
    489   //
    490   // Try to get the arp servicebinding protocol on the NicHandle.
    491   //
    492   Status = gBS->OpenProtocol (
    493                   NicHandle,
    494                   &gEfiArpServiceBindingProtocolGuid,
    495                   (VOID **)&ServiceBinding,
    496                   This->DriverBindingHandle,
    497                   ControllerHandle,
    498                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    499                   );
    500   if (EFI_ERROR (Status)) {
    501     DEBUG ((EFI_D_ERROR, "ArpDriverBindingStop: Open ArpSb failed, %r.\n", Status));
    502     return EFI_DEVICE_ERROR;
    503   }
    504 
    505   ArpService = ARP_SERVICE_DATA_FROM_THIS (ServiceBinding);
    506 
    507   if (NumberOfChildren != 0) {
    508     //
    509     // NumberOfChildren is not zero, destroy all the ARP children instances.
    510     //
    511     List = &ArpService->ChildrenList;
    512     Status = NetDestroyLinkList (
    513                List,
    514                ArpDestroyChildEntryInHandleBuffer,
    515                ServiceBinding,
    516                NULL
    517                );
    518     ASSERT (IsListEmpty (&ArpService->PendingRequestTable));
    519     ASSERT (IsListEmpty (&ArpService->DeniedCacheTable));
    520     ASSERT (IsListEmpty (&ArpService->ResolvedCacheTable));
    521   } else if (IsListEmpty (&ArpService->ChildrenList)) {
    522     //
    523     // Uninstall the ARP ServiceBinding protocol.
    524     //
    525     gBS->UninstallMultipleProtocolInterfaces (
    526            NicHandle,
    527            &gEfiArpServiceBindingProtocolGuid,
    528            &ArpService->ServiceBinding,
    529            NULL
    530            );
    531 
    532     //
    533     // Clean the arp servicebinding context data and free the memory allocated.
    534     //
    535     ArpCleanService (ArpService);
    536 
    537     FreePool (ArpService);
    538   }
    539 
    540   return EFI_SUCCESS;
    541 }
    542 
    543 /**
    544   Creates a child handle and installs a protocol.
    545 
    546   The CreateChild() function installs a protocol on ChildHandle.
    547   If ChildHandle is a pointer to NULL, then a new handle is created and returned
    548   in ChildHandle. If ChildHandle is not a pointer to NULL, then the protocol
    549   installs on the existing ChildHandle.
    550 
    551   @param  This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
    552   @param  ChildHandle Pointer to the handle of the child to create. If it is NULL,
    553                       then a new handle is created. If it is a pointer to an existing
    554                       UEFI handle, then the protocol is added to the existing UEFI handle.
    555 
    556   @retval EFI_SUCCES            The protocol was added to ChildHandle.
    557   @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
    558   @retval EFI_OUT_OF_RESOURCES  There are not enough resources availabe to create
    559                                 the child
    560   @retval other                 The child handle was not created
    561 
    562 **/
    563 EFI_STATUS
    564 EFIAPI
    565 ArpServiceBindingCreateChild (
    566   IN EFI_SERVICE_BINDING_PROTOCOL  *This,
    567   IN EFI_HANDLE                    *ChildHandle
    568   )
    569 {
    570   EFI_STATUS         Status;
    571   ARP_SERVICE_DATA   *ArpService;
    572   ARP_INSTANCE_DATA  *Instance;
    573   VOID               *Mnp;
    574   EFI_TPL            OldTpl;
    575 
    576   if ((This == NULL) || (ChildHandle == NULL)) {
    577     return EFI_INVALID_PARAMETER;
    578   }
    579 
    580   ArpService = ARP_SERVICE_DATA_FROM_THIS (This);
    581 
    582   //
    583   // Allocate memory for the instance context data.
    584   //
    585   Instance = AllocateZeroPool (sizeof(ARP_INSTANCE_DATA));
    586   if (Instance == NULL) {
    587     DEBUG ((EFI_D_ERROR, "ArpSBCreateChild: Failed to allocate memory for Instance.\n"));
    588 
    589     return EFI_OUT_OF_RESOURCES;
    590   }
    591 
    592   //
    593   // Init the instance context data.
    594   //
    595   ArpInitInstance (ArpService, Instance);
    596 
    597   //
    598   // Install the ARP protocol onto the ChildHandle.
    599   //
    600   Status = gBS->InstallMultipleProtocolInterfaces (
    601                   ChildHandle,
    602                   &gEfiArpProtocolGuid,
    603                   (VOID *)&Instance->ArpProto,
    604                   NULL
    605                   );
    606   if (EFI_ERROR (Status)) {
    607     DEBUG ((EFI_D_ERROR, "ArpSBCreateChild: faild to install ARP protocol, %r.\n", Status));
    608 
    609     FreePool (Instance);
    610     return Status;
    611   }
    612 
    613   //
    614   // Save the ChildHandle.
    615   //
    616   Instance->Handle = *ChildHandle;
    617 
    618   //
    619   // Open the Managed Network protocol BY_CHILD.
    620   //
    621   Status = gBS->OpenProtocol (
    622                   ArpService->MnpChildHandle,
    623                   &gEfiManagedNetworkProtocolGuid,
    624                   (VOID **) &Mnp,
    625                   gArpDriverBinding.DriverBindingHandle,
    626                   Instance->Handle,
    627                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
    628                   );
    629   if (EFI_ERROR (Status)) {
    630     goto ERROR;
    631   }
    632 
    633   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
    634 
    635   //
    636   // Insert the instance into children list managed by the arp service context data.
    637   //
    638   InsertTailList (&ArpService->ChildrenList, &Instance->List);
    639   ArpService->ChildrenNumber++;
    640 
    641   gBS->RestoreTPL (OldTpl);
    642 
    643 ERROR:
    644 
    645   if (EFI_ERROR (Status)) {
    646 
    647     gBS->CloseProtocol (
    648            ArpService->MnpChildHandle,
    649            &gEfiManagedNetworkProtocolGuid,
    650            gArpDriverBinding.DriverBindingHandle,
    651            Instance->Handle
    652            );
    653 
    654     gBS->UninstallMultipleProtocolInterfaces (
    655            Instance->Handle,
    656            &gEfiArpProtocolGuid,
    657            &Instance->ArpProto,
    658            NULL
    659            );
    660 
    661     //
    662     // Free the allocated memory.
    663     //
    664     FreePool (Instance);
    665   }
    666 
    667   return Status;
    668 }
    669 
    670 
    671 /**
    672   Destroys a child handle with a protocol installed on it.
    673 
    674   The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
    675   that was installed by CreateChild() from ChildHandle. If the removed protocol is the
    676   last protocol on ChildHandle, then ChildHandle is destroyed.
    677 
    678   @param  This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
    679   @param  ChildHandle Handle of the child to destroy
    680 
    681   @retval EFI_SUCCES            The protocol was removed from ChildHandle.
    682   @retval EFI_UNSUPPORTED       ChildHandle does not support the protocol that is
    683                                 being removed.
    684   @retval EFI_INVALID_PARAMETER Child handle is NULL.
    685   @retval EFI_ACCESS_DENIED     The protocol could not be removed from the ChildHandle
    686                                 because its services are being used.
    687   @retval other                 The child handle was not destroyed
    688 
    689 **/
    690 EFI_STATUS
    691 EFIAPI
    692 ArpServiceBindingDestroyChild (
    693   IN EFI_SERVICE_BINDING_PROTOCOL  *This,
    694   IN EFI_HANDLE                    ChildHandle
    695   )
    696 {
    697   EFI_STATUS         Status;
    698   ARP_SERVICE_DATA   *ArpService;
    699   ARP_INSTANCE_DATA  *Instance;
    700   EFI_ARP_PROTOCOL   *Arp;
    701   EFI_TPL            OldTpl;
    702 
    703   if ((This == NULL) || (ChildHandle == NULL)) {
    704     return EFI_INVALID_PARAMETER;
    705   }
    706 
    707   ArpService = ARP_SERVICE_DATA_FROM_THIS (This);
    708 
    709   //
    710   // Get the arp protocol.
    711   //
    712   Status = gBS->OpenProtocol (
    713                   ChildHandle,
    714                   &gEfiArpProtocolGuid,
    715                   (VOID **)&Arp,
    716                   ArpService->ImageHandle,
    717                   ChildHandle,
    718                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    719                   );
    720   if (EFI_ERROR (Status)) {
    721     return EFI_UNSUPPORTED;
    722   }
    723 
    724   Instance = ARP_INSTANCE_DATA_FROM_THIS (Arp);
    725 
    726   if (Instance->InDestroy) {
    727     return EFI_SUCCESS;
    728   }
    729 
    730   //
    731   // Use the InDestroy as a flag to avoid re-entrance.
    732   //
    733   Instance->InDestroy = TRUE;
    734 
    735   //
    736   // Close the Managed Network protocol.
    737   //
    738   gBS->CloseProtocol (
    739          ArpService->MnpChildHandle,
    740          &gEfiManagedNetworkProtocolGuid,
    741          gArpDriverBinding.DriverBindingHandle,
    742          ChildHandle
    743          );
    744 
    745   //
    746   // Uninstall the ARP protocol.
    747   //
    748   Status = gBS->UninstallMultipleProtocolInterfaces (
    749                   ChildHandle,
    750                   &gEfiArpProtocolGuid,
    751                   &Instance->ArpProto,
    752                   NULL
    753                   );
    754   if (EFI_ERROR (Status)) {
    755     DEBUG ((EFI_D_ERROR, "ArpSBDestroyChild: Failed to uninstall the arp protocol, %r.\n",
    756       Status));
    757 
    758     Instance->InDestroy = FALSE;
    759     return Status;
    760   }
    761 
    762   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
    763 
    764   if (Instance->Configured) {
    765     //
    766     // Delete the related cache entry.
    767     //
    768     ArpDeleteCacheEntry (Instance, FALSE, NULL, TRUE);
    769 
    770     //
    771     // Reset the instance configuration.
    772     //
    773     ArpConfigureInstance (Instance, NULL);
    774   }
    775 
    776   //
    777   // Remove this instance from the ChildrenList.
    778   //
    779   RemoveEntryList (&Instance->List);
    780   ArpService->ChildrenNumber--;
    781 
    782   gBS->RestoreTPL (OldTpl);
    783 
    784   FreePool (Instance);
    785 
    786   return Status;
    787 }
    788 
    789 /**
    790   The entry point for Arp driver which installs the driver binding and component name
    791   protocol on its ImageHandle.
    792 
    793   @param[in]  ImageHandle        The image handle of the driver.
    794   @param[in]  SystemTable        The system table.
    795 
    796   @retval EFI_SUCCESS            if the driver binding and component name protocols
    797                                  are successfully
    798   @retval Others                 Failed to install the protocols.
    799 
    800 **/
    801 EFI_STATUS
    802 EFIAPI
    803 ArpDriverEntryPoint (
    804   IN EFI_HANDLE        ImageHandle,
    805   IN EFI_SYSTEM_TABLE  *SystemTable
    806   )
    807 {
    808   return EfiLibInstallDriverBindingComponentName2 (
    809            ImageHandle,
    810            SystemTable,
    811            &gArpDriverBinding,
    812            ImageHandle,
    813            &gArpComponentName,
    814            &gArpComponentName2
    815            );
    816 }
    817 
    818