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