Use Mde library and definition instead of some native definitions in NetLib, to simpl...
[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                   TPL_NOTIFY,\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                   TPL_CALLBACK,\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   InitializeListHead (&ArpService->ChildrenList);\r
184   InitializeListHead (&ArpService->PendingRequestTable);\r
185   InitializeListHead (&ArpService->DeniedCacheTable);\r
186   InitializeListHead (&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 = AllocateZeroPool (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   gBS->FreePool (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_DEVICE_ERROR;\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     DEBUG ((EFI_D_ERROR, "ArpDriverBindingStop: Open ArpSb failed, %r.\n", Status));\r
432     return EFI_DEVICE_ERROR;\r
433   }\r
434 \r
435   ArpService = ARP_SERVICE_DATA_FROM_THIS (ServiceBinding);\r
436 \r
437   if (NumberOfChildren == 0) {\r
438     //\r
439     // Uninstall the ARP ServiceBinding protocol.\r
440     //\r
441     gBS->UninstallMultipleProtocolInterfaces (\r
442            NicHandle,\r
443            &gEfiArpServiceBindingProtocolGuid,\r
444            &ArpService->ServiceBinding,\r
445            NULL\r
446            );\r
447 \r
448     //\r
449     // Clean the arp servicebinding context data and free the memory allocated.\r
450     //\r
451     ArpCleanService (ArpService);\r
452 \r
453     gBS->FreePool (ArpService);\r
454   } else {\r
455 \r
456     while (!IsListEmpty (&ArpService->ChildrenList)) {\r
457       Instance = NET_LIST_HEAD (&ArpService->ChildrenList, ARP_INSTANCE_DATA, List);\r
458 \r
459       ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);\r
460     }\r
461 \r
462     ASSERT (IsListEmpty (&ArpService->PendingRequestTable));\r
463     ASSERT (IsListEmpty (&ArpService->DeniedCacheTable));\r
464     ASSERT (IsListEmpty (&ArpService->ResolvedCacheTable));\r
465   }\r
466 \r
467   return EFI_SUCCESS;\r
468 }\r
469 \r
470 /**\r
471   Creates a child handle with a set of I/O services.\r
472 \r
473   @param  This                   Protocol instance pointer.\r
474   @param  ChildHandle            Pointer to the handle of the child to create. If\r
475                                  it is NULL, then a new handle is created. If it is\r
476                                  not NULL, then the I/O services are  added to the\r
477                                  existing child handle.\r
478 \r
479   @retval EFI_SUCCES             The child handle was created with the I/O\r
480                                  services.\r
481   @retval EFI_OUT_OF_RESOURCES   There are not enough resources availabe to create\r
482                                  the child.\r
483   @retval other                  The child handle was not created.\r
484 \r
485 **/\r
486 EFI_STATUS\r
487 EFIAPI\r
488 ArpServiceBindingCreateChild (\r
489   IN EFI_SERVICE_BINDING_PROTOCOL  *This,\r
490   IN EFI_HANDLE                    *ChildHandle\r
491   )\r
492 {\r
493   EFI_STATUS         Status;\r
494   ARP_SERVICE_DATA   *ArpService;\r
495   ARP_INSTANCE_DATA  *Instance;\r
496   VOID               *Mnp;\r
497   EFI_TPL            OldTpl;\r
498 \r
499   if ((This == NULL) || (ChildHandle == NULL)) {\r
500     return EFI_INVALID_PARAMETER;\r
501   }\r
502 \r
503   ArpService = ARP_SERVICE_DATA_FROM_THIS (This);\r
504 \r
505   //\r
506   // Allocate memory for the instance context data.\r
507   //\r
508   Instance = AllocateZeroPool (sizeof(ARP_INSTANCE_DATA));\r
509   if (Instance == NULL) {\r
510     DEBUG ((EFI_D_ERROR, "ArpSBCreateChild: Failed to allocate memory for Instance.\n"));\r
511 \r
512     return EFI_OUT_OF_RESOURCES;\r
513   }\r
514 \r
515   //\r
516   // Init the instance context data.\r
517   //\r
518   ArpInitInstance (ArpService, Instance);\r
519 \r
520   //\r
521   // Install the ARP protocol onto the ChildHandle.\r
522   //\r
523   Status = gBS->InstallMultipleProtocolInterfaces (\r
524                   ChildHandle,\r
525                   &gEfiArpProtocolGuid,\r
526                   (VOID *)&Instance->ArpProto,\r
527                   NULL\r
528                   );\r
529   if (EFI_ERROR (Status)) {\r
530     DEBUG ((EFI_D_ERROR, "ArpSBCreateChild: faild to install ARP protocol, %r.\n", Status));\r
531 \r
532     gBS->FreePool (Instance);\r
533     return Status;\r
534   }\r
535 \r
536   //\r
537   // Save the ChildHandle.\r
538   //\r
539   Instance->Handle = *ChildHandle;\r
540 \r
541   //\r
542   // Open the Managed Network protocol BY_CHILD.\r
543   //\r
544   Status = gBS->OpenProtocol (\r
545                   ArpService->MnpChildHandle,\r
546                   &gEfiManagedNetworkProtocolGuid,\r
547                   (VOID **) &Mnp,\r
548                   gArpDriverBinding.DriverBindingHandle,\r
549                   Instance->Handle,\r
550                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
551                   );\r
552   if (EFI_ERROR (Status)) {\r
553     goto ERROR;\r
554   }\r
555 \r
556   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
557 \r
558   //\r
559   // Insert the instance into children list managed by the arp service context data.\r
560   //\r
561   InsertTailList (&ArpService->ChildrenList, &Instance->List);\r
562   ArpService->ChildrenNumber++;\r
563 \r
564   gBS->RestoreTPL (OldTpl);\r
565 \r
566 ERROR:\r
567 \r
568   if (EFI_ERROR (Status)) {\r
569 \r
570     gBS->CloseProtocol (\r
571            ArpService->MnpChildHandle,\r
572            &gEfiManagedNetworkProtocolGuid,\r
573            gArpDriverBinding.DriverBindingHandle,\r
574            Instance->Handle\r
575            );\r
576 \r
577     gBS->UninstallMultipleProtocolInterfaces (\r
578            Instance->Handle,\r
579            &gEfiArpProtocolGuid,\r
580            &Instance->ArpProto,\r
581            NULL\r
582            );\r
583 \r
584     //\r
585     // Free the allocated memory.\r
586     //\r
587     gBS->FreePool (Instance);\r
588   }\r
589 \r
590   return Status;\r
591 }\r
592 \r
593 \r
594 /**\r
595   Destroys a child handle with a set of I/O services.\r
596 \r
597   @param  This                   Protocol instance pointer.\r
598   @param  ChildHandle            Handle of the child to destroy.\r
599 \r
600   @retval EFI_SUCCES             The I/O services were removed from the child\r
601                                  handle.\r
602   @retval EFI_UNSUPPORTED        The child handle does not support the I/O services\r
603                                   that are being removed.\r
604   @retval EFI_INVALID_PARAMETER  Child handle is not a valid EFI Handle.\r
605   @retval EFI_ACCESS_DENIED      The child handle could not be destroyed because\r
606                                  its  I/O services are being used.\r
607   @retval other                  The child handle was not destroyed.\r
608 \r
609 **/\r
610 EFI_STATUS\r
611 EFIAPI\r
612 ArpServiceBindingDestroyChild (\r
613   IN EFI_SERVICE_BINDING_PROTOCOL  *This,\r
614   IN EFI_HANDLE                    ChildHandle\r
615   )\r
616 {\r
617   EFI_STATUS         Status;\r
618   ARP_SERVICE_DATA   *ArpService;\r
619   ARP_INSTANCE_DATA  *Instance;\r
620   EFI_ARP_PROTOCOL   *Arp;\r
621   EFI_TPL            OldTpl;\r
622 \r
623   if ((This == NULL) || (ChildHandle == NULL)) {\r
624     return EFI_INVALID_PARAMETER;\r
625   }\r
626 \r
627   ArpService = ARP_SERVICE_DATA_FROM_THIS (This);\r
628 \r
629   //\r
630   // Get the arp protocol.\r
631   //\r
632   Status = gBS->OpenProtocol (\r
633                   ChildHandle,\r
634                   &gEfiArpProtocolGuid,\r
635                   (VOID **)&Arp,\r
636                   ArpService->ImageHandle,\r
637                   ChildHandle,\r
638                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
639                   );\r
640   if (EFI_ERROR (Status)) {\r
641     return EFI_UNSUPPORTED;\r
642   }\r
643 \r
644   Instance = ARP_INSTANCE_DATA_FROM_THIS (Arp);\r
645 \r
646   if (Instance->Destroyed) {\r
647     return EFI_SUCCESS;\r
648   }\r
649 \r
650   //\r
651   // Use the Destroyed as a flag to avoid re-entrance.\r
652   //\r
653   Instance->Destroyed = TRUE;\r
654 \r
655   //\r
656   // Close the Managed Network protocol.\r
657   //\r
658   gBS->CloseProtocol (\r
659          ArpService->MnpChildHandle,\r
660          &gEfiManagedNetworkProtocolGuid,\r
661          gArpDriverBinding.DriverBindingHandle,\r
662          ChildHandle\r
663          );\r
664 \r
665   //\r
666   // Uninstall the ARP protocol.\r
667   //\r
668   Status = gBS->UninstallMultipleProtocolInterfaces (\r
669                   ChildHandle,\r
670                   &gEfiArpProtocolGuid,\r
671                   &Instance->ArpProto,\r
672                   NULL\r
673                   );\r
674   if (EFI_ERROR (Status)) {\r
675     DEBUG ((EFI_D_ERROR, "ArpSBDestroyChild: Failed to uninstall the arp protocol, %r.\n",\r
676       Status));\r
677 \r
678     Instance->Destroyed = FALSE;\r
679     return Status;\r
680   }\r
681 \r
682   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
683 \r
684   if (Instance->Configured) {\r
685     //\r
686     // Delete the related cache entry.\r
687     //\r
688     ArpDeleteCacheEntry (Instance, FALSE, NULL, TRUE);\r
689 \r
690     //\r
691     // Reset the instance configuration.\r
692     //\r
693     ArpConfigureInstance (Instance, NULL);\r
694   }\r
695 \r
696   //\r
697   // Remove this instance from the ChildrenList.\r
698   //\r
699   RemoveEntryList (&Instance->List);\r
700   ArpService->ChildrenNumber--;\r
701 \r
702   gBS->RestoreTPL (OldTpl);\r
703 \r
704   gBS->FreePool (Instance);\r
705 \r
706   return Status;\r
707 }\r
708 \r
709 \r
710 EFI_STATUS\r
711 EFIAPI\r
712 ArpDriverEntryPoint (\r
713   IN EFI_HANDLE        ImageHandle,\r
714   IN EFI_SYSTEM_TABLE  *SystemTable\r
715   )\r
716 /*++\r
717 \r
718 Routine Description:\r
719 \r
720   The entry point for Arp driver which installs the driver binding and component name\r
721   protocol on its ImageHandle.\r
722 \r
723 Arguments:\r
724 \r
725   ImageHandle - The image handle of the driver.\r
726   SystemTable - The system table.\r
727 \r
728 Returns:\r
729 \r
730   EFI_SUCCESS - if the driver binding and component name protocols are successfully\r
731                 installed, otherwise if failed.\r
732 \r
733 --*/\r
734 {\r
735   return EfiLibInstallDriverBindingComponentName2 (\r
736            ImageHandle,\r
737            SystemTable,\r
738            &gArpDriverBinding,\r
739            ImageHandle,\r
740            &gArpComponentName,\r
741            &gArpComponentName2\r
742            );\r
743 }\r
744 \r