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