Import ArpDxe, Dhcp4Dxe, Ip4Dxe, Mtftp4Dxe, PxeBcDxe and PxeDhcp4Dxe.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / ArpDxe / ArpDriver.c
1 /** @file\r
2 \r
3 Copyright (c) 2006, 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 lock.\r
182   //\r
183   NET_LOCK_INIT (&ArpService->Lock);\r
184 \r
185   //\r
186   // Init the lists.\r
187   //\r
188   NetListInit (&ArpService->ChildrenList);\r
189   NetListInit (&ArpService->PendingRequestTable);\r
190   NetListInit (&ArpService->DeniedCacheTable);\r
191   NetListInit (&ArpService->ResolvedCacheTable);\r
192 \r
193 ERROR_EXIT:\r
194 \r
195   return Status;\r
196 }\r
197 \r
198 \r
199 /**\r
200   Clean the arp service context data.\r
201 \r
202   @param  ArpService             Pointer to the buffer containing the arp service\r
203                                  context data.\r
204 \r
205   @return None.\r
206 \r
207 **/\r
208 STATIC\r
209 VOID\r
210 ArpCleanService (\r
211   IN ARP_SERVICE_DATA  *ArpService\r
212   )\r
213 {\r
214   NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);\r
215 \r
216   if (ArpService->PeriodicTimer != NULL) {\r
217     //\r
218     // Cancle and close the PeriodicTimer.\r
219     //\r
220     gBS->SetTimer (ArpService->PeriodicTimer, TimerCancel, 0);\r
221     gBS->CloseEvent (ArpService->PeriodicTimer);\r
222   }\r
223 \r
224   if (ArpService->RxToken.Event != NULL) {\r
225     //\r
226     // Cancle the RxToken and close the event in the RxToken.\r
227     //\r
228     ArpService->Mnp->Cancel (ArpService->Mnp, NULL);\r
229     gBS->CloseEvent (ArpService->RxToken.Event);\r
230   }\r
231 \r
232   if (ArpService->Mnp != NULL) {\r
233     //\r
234     // Reset the Mnp child and close the Mnp protocol.\r
235     //\r
236     ArpService->Mnp->Configure (ArpService->Mnp, NULL);\r
237     gBS->CloseProtocol (\r
238            ArpService->MnpChildHandle,\r
239            &gEfiManagedNetworkProtocolGuid,\r
240            ArpService->ImageHandle,\r
241            ArpService->ControllerHandle\r
242            );\r
243   }\r
244 \r
245   if (ArpService->MnpChildHandle != NULL) {\r
246     //\r
247     // Destroy the mnp child.\r
248     //\r
249     NetLibDestroyServiceChild(\r
250       ArpService->ControllerHandle,\r
251       ArpService->ImageHandle,\r
252       &gEfiManagedNetworkServiceBindingProtocolGuid,\r
253       ArpService->MnpChildHandle\r
254       );\r
255   }\r
256 }\r
257 \r
258 \r
259 /**\r
260   Test to see if this driver supports ControllerHandle.\r
261 \r
262   @param  This                   Protocol instance pointer.\r
263   @param  ControllerHandle       Handle of device to test.\r
264   @param  RemainingDevicePath    Optional parameter use to pick a specific child\r
265                                  device to start.\r
266 \r
267   @retval EFI_SUCCES             This driver supports this device\r
268   @retval EFI_ALREADY_STARTED    This driver is already running on this device.\r
269   @retval other                  This driver does not support this device.\r
270 \r
271 **/\r
272 EFI_STATUS\r
273 EFIAPI\r
274 ArpDriverBindingSupported (\r
275   IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
276   IN EFI_HANDLE                   ControllerHandle,\r
277   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL\r
278   )\r
279 {\r
280   EFI_STATUS  Status;\r
281 \r
282   //\r
283   // Test to see if Arp SB is already installed.\r
284   //\r
285   Status = gBS->OpenProtocol (\r
286                   ControllerHandle,\r
287                   &gEfiArpServiceBindingProtocolGuid,\r
288                   NULL,\r
289                   This->DriverBindingHandle,\r
290                   ControllerHandle,\r
291                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
292                   );\r
293   if (Status == EFI_SUCCESS) {\r
294     return EFI_ALREADY_STARTED;\r
295   }\r
296 \r
297   //\r
298   // Test to see if MNP SB is installed.\r
299   //\r
300   Status = gBS->OpenProtocol (\r
301                   ControllerHandle,\r
302                   &gEfiManagedNetworkServiceBindingProtocolGuid,\r
303                   NULL,\r
304                   This->DriverBindingHandle,\r
305                   ControllerHandle,\r
306                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
307                   );\r
308 \r
309   return Status;\r
310 }\r
311 \r
312 \r
313 /**\r
314   Start this driver on ControllerHandle.\r
315 \r
316   @param  This                   Protocol instance pointer.\r
317   @param  ControllerHandle       Handle of device to bind driver to\r
318   @param  RemainingDevicePath    Optional parameter use to pick a specific child\r
319                                  device to start.\r
320 \r
321   @retval EFI_SUCCES             This driver is added to ControllerHandle\r
322   @retval EFI_ALREADY_STARTED    This driver is already running on ControllerHandle\r
323   @retval other                  This driver does not support this device\r
324 \r
325 **/\r
326 EFI_STATUS\r
327 EFIAPI\r
328 ArpDriverBindingStart (\r
329   IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
330   IN EFI_HANDLE                   ControllerHandle,\r
331   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL\r
332   )\r
333 {\r
334   EFI_STATUS        Status;\r
335   ARP_SERVICE_DATA  *ArpService;\r
336 \r
337   //\r
338   // Allocate a zero pool for ArpService.\r
339   //\r
340   ArpService = NetAllocateZeroPool (sizeof(ARP_SERVICE_DATA));\r
341   if (ArpService == NULL) {\r
342     return EFI_OUT_OF_RESOURCES;\r
343   }\r
344 \r
345   //\r
346   // Initialize the arp service context data.\r
347   //\r
348   Status = ArpCreateService (This->DriverBindingHandle, ControllerHandle, ArpService);\r
349   if (EFI_ERROR (Status)) {\r
350     goto ERROR;\r
351   }\r
352 \r
353   //\r
354   // Install the ARP service binding protocol.\r
355   //\r
356   Status = gBS->InstallMultipleProtocolInterfaces (\r
357                   &ControllerHandle,\r
358                   &gEfiArpServiceBindingProtocolGuid,\r
359                   &ArpService->ServiceBinding,\r
360                   NULL\r
361                   );\r
362   if (EFI_ERROR (Status)) {\r
363     goto ERROR;\r
364   }\r
365 \r
366   //\r
367   // OK, start to receive arp packets from Mnp.\r
368   //\r
369   Status = ArpService->Mnp->Receive (ArpService->Mnp, &ArpService->RxToken);\r
370   if (EFI_ERROR (Status)) {\r
371     goto ERROR;\r
372   }\r
373 \r
374   return Status;\r
375 \r
376 ERROR:\r
377 \r
378   //\r
379   // On error, clean the arp service context data, and free the memory allocated.\r
380   //\r
381   ArpCleanService (ArpService);\r
382   NetFreePool (ArpService);\r
383 \r
384   return Status;\r
385 }\r
386 \r
387 \r
388 /**\r
389   Stop this driver on ControllerHandle.\r
390 \r
391   @param  This                   Protocol instance pointer.\r
392   @param  ControllerHandle       Handle of device to stop driver on\r
393   @param  NumberOfChildren       Number of Handles in ChildHandleBuffer. If number\r
394                                  of  children is zero stop the entire bus driver.\r
395   @param  ChildHandleBuffer      List of Child Handles to Stop.\r
396 \r
397   @retval EFI_SUCCES             This driver is removed ControllerHandle\r
398   @retval other                  This driver was not removed from this device\r
399 \r
400 **/\r
401 EFI_STATUS\r
402 EFIAPI\r
403 ArpDriverBindingStop (\r
404   IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
405   IN EFI_HANDLE                   ControllerHandle,\r
406   IN UINTN                        NumberOfChildren,\r
407   IN EFI_HANDLE                   *ChildHandleBuffer\r
408   )\r
409 {\r
410   EFI_STATUS                    Status;\r
411   EFI_HANDLE                    NicHandle;\r
412   EFI_SERVICE_BINDING_PROTOCOL  *ServiceBinding;\r
413   ARP_SERVICE_DATA              *ArpService;\r
414   ARP_INSTANCE_DATA             *Instance;\r
415 \r
416   //\r
417   // Get the NicHandle which the arp servicebinding is installed on.\r
418   //\r
419   NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);\r
420   if (NicHandle == NULL) {\r
421     return EFI_SUCCESS;\r
422   }\r
423 \r
424   //\r
425   // Try to get the arp servicebinding protocol on the NicHandle.\r
426   //\r
427   Status = gBS->OpenProtocol (\r
428                   NicHandle,\r
429                   &gEfiArpServiceBindingProtocolGuid,\r
430                   (VOID **)&ServiceBinding,\r
431                   This->DriverBindingHandle,\r
432                   ControllerHandle,\r
433                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
434                   );\r
435   if (EFI_ERROR (Status)) {\r
436     ARP_DEBUG_ERROR (("ArpDriverBindingStop: Open ArpSb failed, %r.\n", Status));\r
437     return Status;\r
438   }\r
439 \r
440   ArpService = ARP_SERVICE_DATA_FROM_THIS (ServiceBinding);\r
441 \r
442   while (!NetListIsEmpty (&ArpService->ChildrenList)) {\r
443     //\r
444     // Iterate all the instances.\r
445     //\r
446     Instance = NET_LIST_HEAD (&ArpService->ChildrenList, ARP_INSTANCE_DATA, List);\r
447 \r
448     //\r
449     // Destroy this arp child.\r
450     //\r
451     ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);\r
452   }\r
453 \r
454   ASSERT (NetListIsEmpty (&ArpService->PendingRequestTable));\r
455   ASSERT (NetListIsEmpty (&ArpService->DeniedCacheTable));\r
456   ASSERT (NetListIsEmpty (&ArpService->ResolvedCacheTable));\r
457 \r
458   //\r
459   // Uninstall the ARP ServiceBinding protocol.\r
460   //\r
461   Status = gBS->UninstallMultipleProtocolInterfaces (\r
462                   NicHandle,\r
463                   &gEfiArpServiceBindingProtocolGuid,\r
464                   &ArpService->ServiceBinding,\r
465                   NULL\r
466                   );\r
467   if (EFI_ERROR (Status)) {\r
468     ARP_DEBUG_ERROR (("ArpDriverBindingStop: Failed to uninstall ArpSb, %r.\n", Status));\r
469     return Status;\r
470   }\r
471 \r
472   //\r
473   // Clean the arp servicebinding context data and free the memory allocated.\r
474   //\r
475   ArpCleanService (ArpService);\r
476   NetFreePool (ArpService);\r
477 \r
478   return Status;\r
479 }\r
480 \r
481 \r
482 /**\r
483   Creates a child handle with a set of I/O services.\r
484 \r
485   @param  This                   Protocol instance pointer.\r
486   @param  ChildHandle            Pointer to the handle of the child to create. If\r
487                                  it is NULL, then a new handle is created. If it is\r
488                                  not NULL, then the I/O services are  added to the\r
489                                  existing child handle.\r
490 \r
491   @retval EFI_SUCCES             The child handle was created with the I/O\r
492                                  services.\r
493   @retval EFI_OUT_OF_RESOURCES   There are not enough resources availabe to create\r
494                                  the child.\r
495   @retval other                  The child handle was not created.\r
496 \r
497 **/\r
498 EFI_STATUS\r
499 EFIAPI\r
500 ArpServiceBindingCreateChild (\r
501   IN EFI_SERVICE_BINDING_PROTOCOL  *This,\r
502   IN EFI_HANDLE                    *ChildHandle\r
503   )\r
504 {\r
505   EFI_STATUS         Status;\r
506   ARP_SERVICE_DATA   *ArpService;\r
507   ARP_INSTANCE_DATA  *Instance;\r
508   VOID               *Mnp;\r
509 \r
510   if ((This == NULL) || (ChildHandle == NULL)) {\r
511     return EFI_INVALID_PARAMETER;\r
512   }\r
513 \r
514   ArpService = ARP_SERVICE_DATA_FROM_THIS (This);\r
515 \r
516   //\r
517   // Allocate memory for the instance context data.\r
518   //\r
519   Instance = NetAllocateZeroPool (sizeof(ARP_INSTANCE_DATA));\r
520   if (Instance == NULL) {\r
521     ARP_DEBUG_ERROR (("ArpSBCreateChild: Failed to allocate memory for Instance.\n"));\r
522 \r
523     return EFI_OUT_OF_RESOURCES;\r
524   }\r
525 \r
526   //\r
527   // Init the instance context data.\r
528   //\r
529   ArpInitInstance (ArpService, Instance);\r
530 \r
531   //\r
532   // Install the ARP protocol onto the ChildHandle.\r
533   //\r
534   Status = gBS->InstallMultipleProtocolInterfaces (\r
535                   ChildHandle,\r
536                   &gEfiArpProtocolGuid,\r
537                   (VOID *)&Instance->ArpProto,\r
538                   NULL\r
539                   );\r
540   if (EFI_ERROR (Status)) {\r
541     ARP_DEBUG_ERROR (("ArpSBCreateChild: faild to install ARP protocol, %r.\n", Status));\r
542 \r
543     NetFreePool (Instance);\r
544     return Status;\r
545   }\r
546 \r
547   //\r
548   // Save the ChildHandle.\r
549   //\r
550   Instance->Handle = *ChildHandle;\r
551 \r
552   //\r
553   // Open the Managed Network protocol BY_CHILD.\r
554   //\r
555   Status = gBS->OpenProtocol (\r
556                   ArpService->MnpChildHandle,\r
557                   &gEfiManagedNetworkProtocolGuid,\r
558                   (VOID **) &Mnp,\r
559                   gArpDriverBinding.DriverBindingHandle,\r
560                   Instance->Handle,\r
561                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
562                   );\r
563   if (EFI_ERROR (Status)) {\r
564     goto ERROR;\r
565   }\r
566 \r
567   if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {\r
568 \r
569     Status = EFI_ACCESS_DENIED;\r
570     goto ERROR;\r
571   }\r
572 \r
573   //\r
574   // Insert the instance into children list managed by the arp service context data.\r
575   //\r
576   NetListInsertTail (&ArpService->ChildrenList, &Instance->List);\r
577   ArpService->ChildrenNumber++;\r
578 \r
579   NET_UNLOCK (&ArpService->Lock);\r
580 \r
581 ERROR:\r
582 \r
583   if (EFI_ERROR (Status)) {\r
584 \r
585     gBS->CloseProtocol (\r
586            ArpService->MnpChildHandle,\r
587            &gEfiManagedNetworkProtocolGuid,\r
588            gArpDriverBinding.DriverBindingHandle,\r
589            Instance->Handle\r
590            );\r
591 \r
592     gBS->UninstallMultipleProtocolInterfaces (\r
593            Instance->Handle,\r
594            &gEfiArpProtocolGuid,\r
595            &Instance->ArpProto,\r
596            NULL\r
597            );\r
598 \r
599     //\r
600     // Free the allocated memory.\r
601     //\r
602     NetFreePool (Instance);\r
603   }\r
604 \r
605   return Status;\r
606 }\r
607 \r
608 \r
609 /**\r
610   Destroys a child handle with a set of I/O services.\r
611 \r
612   @param  This                   Protocol instance pointer.\r
613   @param  ChildHandle            Handle of the child to destroy.\r
614 \r
615   @retval EFI_SUCCES             The I/O services were removed from the child\r
616                                  handle.\r
617   @retval EFI_UNSUPPORTED        The child handle does not support the I/O services\r
618                                   that are being removed.\r
619   @retval EFI_INVALID_PARAMETER  Child handle is not a valid EFI Handle.\r
620   @retval EFI_ACCESS_DENIED      The child handle could not be destroyed because\r
621                                  its  I/O services are being used.\r
622   @retval other                  The child handle was not destroyed.\r
623 \r
624 **/\r
625 EFI_STATUS\r
626 EFIAPI\r
627 ArpServiceBindingDestroyChild (\r
628   IN EFI_SERVICE_BINDING_PROTOCOL  *This,\r
629   IN EFI_HANDLE                    ChildHandle\r
630   )\r
631 {\r
632   EFI_STATUS         Status;\r
633   ARP_SERVICE_DATA   *ArpService;\r
634   ARP_INSTANCE_DATA  *Instance;\r
635   EFI_ARP_PROTOCOL   *Arp;\r
636 \r
637   if ((This == NULL) || (ChildHandle == NULL)) {\r
638     return EFI_INVALID_PARAMETER;\r
639   }\r
640 \r
641   ArpService = ARP_SERVICE_DATA_FROM_THIS (This);\r
642 \r
643   //\r
644   // Get the arp protocol.\r
645   //\r
646   Status = gBS->OpenProtocol (\r
647                   ChildHandle,\r
648                   &gEfiArpProtocolGuid,\r
649                   (VOID **)&Arp,\r
650                   ArpService->ImageHandle,\r
651                   ChildHandle,\r
652                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
653                   );\r
654   if (EFI_ERROR (Status)) {\r
655     return EFI_UNSUPPORTED;\r
656   }\r
657 \r
658   Instance = ARP_INSTANCE_DATA_FROM_THIS (Arp);\r
659 \r
660   if (Instance->Destroyed) {\r
661     return EFI_SUCCESS;\r
662   }\r
663 \r
664   //\r
665   // Use the Destroyed as a flag to avoid re-entrance.\r
666   //\r
667   Instance->Destroyed = TRUE;\r
668 \r
669   //\r
670   // Close the Managed Network protocol.\r
671   //\r
672   gBS->CloseProtocol (\r
673          ArpService->MnpChildHandle,\r
674          &gEfiManagedNetworkProtocolGuid,\r
675          gArpDriverBinding.DriverBindingHandle,\r
676          ChildHandle\r
677          );\r
678 \r
679   //\r
680   // Uninstall the ARP protocol.\r
681   //\r
682   Status = gBS->UninstallMultipleProtocolInterfaces (\r
683                   ChildHandle,\r
684                   &gEfiArpProtocolGuid,\r
685                   &Instance->ArpProto,\r
686                   NULL\r
687                   );\r
688   if (EFI_ERROR (Status)) {\r
689     ARP_DEBUG_ERROR (("ArpSBDestroyChild: Failed to uninstall the arp protocol, %r.\n",\r
690       Status));\r
691 \r
692     Instance->Destroyed = FALSE;\r
693     return Status;\r
694   }\r
695 \r
696   if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {\r
697     Instance->Destroyed = FALSE;\r
698     return EFI_ACCESS_DENIED;\r
699   }\r
700 \r
701   if (Instance->Configured) {\r
702     //\r
703     // Delete the related cache entry.\r
704     //\r
705     ArpDeleteCacheEntry (Instance, FALSE, NULL, TRUE);\r
706 \r
707     //\r
708     // Reset the instance configuration.\r
709     //\r
710     ArpConfigureInstance (Instance, NULL);\r
711   }\r
712 \r
713   //\r
714   // Remove this instance from the ChildrenList.\r
715   //\r
716   NetListRemoveEntry (&Instance->List);\r
717   ArpService->ChildrenNumber--;\r
718 \r
719   NET_UNLOCK (&ArpService->Lock);\r
720 \r
721   NetFreePool (Instance);\r
722 \r
723   return Status;\r
724 }\r
725 \r
726 //@MT: EFI_DRIVER_ENTRY_POINT (ArpDriverEntryPoint)\r
727 \r
728 EFI_STATUS\r
729 EFIAPI\r
730 ArpDriverEntryPoint (\r
731   IN EFI_HANDLE        ImageHandle,\r
732   IN EFI_SYSTEM_TABLE  *SystemTable\r
733   )\r
734 /*++\r
735 \r
736 Routine Description:\r
737 \r
738   The entry point for Arp driver which installs the driver binding and component name\r
739   protocol on its ImageHandle.\r
740 \r
741 Arguments:\r
742 \r
743   ImageHandle - The image handle of the driver.\r
744   SystemTable - The system table.\r
745 \r
746 Returns:\r
747 \r
748   EFI_SUCCESS - if the driver binding and component name protocols are successfully\r
749                 installed, otherwise if failed.\r
750 \r
751 --*/\r
752 {\r
753   return NetLibInstallAllDriverProtocols (\r
754            ImageHandle,\r
755            SystemTable,\r
756            &gArpDriverBinding,\r
757            ImageHandle,\r
758            &gArpComponentName,\r
759            NULL,\r
760            NULL\r
761            );\r
762 }\r
763 \r