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