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