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
ArpCreateService(IN EFI_HANDLE ImageHandle,IN EFI_HANDLE ControllerHandle,IN OUT ARP_SERVICE_DATA * ArpService)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
ArpCleanService(IN OUT ARP_SERVICE_DATA * ArpService)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
ArpDestroyChildEntryInHandleBuffer(IN LIST_ENTRY * Entry,IN VOID * Context)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
ArpDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)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
ArpDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)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
ArpDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)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
ArpServiceBindingCreateChild(IN EFI_SERVICE_BINDING_PROTOCOL * This,IN EFI_HANDLE * ChildHandle)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
ArpServiceBindingDestroyChild(IN EFI_SERVICE_BINDING_PROTOCOL * This,IN EFI_HANDLE ChildHandle)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
ArpDriverEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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