1. Add EFI_COMPONENT_NAME2_PROTOCOL.GetControllerName() support.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / ArpDxe / ArpDriver.c
1 /** @file\r
2   ARP driver functions.\r
3   \r
4 Copyright (c) 2006 - 2012, 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   Callback function which provided by user to remove one node in NetDestroyLinkList process.\r
246   \r
247   @param[in]    Entry           The entry to be removed.\r
248   @param[in]    Context         Pointer to the callback context corresponds to the Context in NetDestroyLinkList.\r
249 \r
250   @retval EFI_SUCCESS           The entry has been removed successfully.\r
251   @retval Others                Fail to remove the entry.\r
252 \r
253 **/\r
254 EFI_STATUS\r
255 ArpDestroyChildEntryInHandleBuffer (\r
256   IN LIST_ENTRY         *Entry,\r
257   IN VOID               *Context\r
258 )\r
259 {\r
260   ARP_INSTANCE_DATA             *Instance;\r
261   EFI_SERVICE_BINDING_PROTOCOL  *ServiceBinding;\r
262   \r
263   if (Entry == NULL || Context == NULL) {\r
264     return EFI_INVALID_PARAMETER;\r
265   }\r
266 \r
267   Instance = NET_LIST_USER_STRUCT_S (Entry, ARP_INSTANCE_DATA, List, ARP_INSTANCE_DATA_SIGNATURE);\r
268   ServiceBinding    = (EFI_SERVICE_BINDING_PROTOCOL *) Context;\r
269 \r
270   return ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);\r
271 }\r
272 \r
273 /**\r
274   Tests to see if this driver supports a given controller. \r
275   \r
276   If a child device is provided, it further tests to see if this driver supports \r
277   creating a handle for the specified child device.\r
278 \r
279   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
280   @param[in]  ControllerHandle     The handle of the controller to test. This handle \r
281                                    must support a protocol interface that supplies \r
282                                    an I/O abstraction to the driver.\r
283   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path. \r
284                                    This parameter is ignored by device drivers, \r
285                                    and is optional for bus drivers.\r
286 \r
287   @retval EFI_SUCCESS              The device specified by ControllerHandle and\r
288                                    RemainingDevicePath is supported by the driver \r
289                                    specified by This.\r
290   @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and\r
291                                    RemainingDevicePath is already being managed \r
292                                    by the driver specified by This.\r
293   @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and\r
294                                    RemainingDevicePath is already being managed by \r
295                                    a different driver or an application that \r
296                                    requires exclusive acces. Currently not implemented.\r
297   @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and\r
298                                    RemainingDevicePath is not supported by the \r
299                                    driver specified by This.\r
300 \r
301 **/\r
302 EFI_STATUS\r
303 EFIAPI\r
304 ArpDriverBindingSupported (\r
305   IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
306   IN EFI_HANDLE                   ControllerHandle,\r
307   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL\r
308   )\r
309 {\r
310   EFI_STATUS  Status;\r
311 \r
312   //\r
313   // Test to see if Arp SB is already installed.\r
314   //\r
315   Status = gBS->OpenProtocol (\r
316                   ControllerHandle,\r
317                   &gEfiArpServiceBindingProtocolGuid,\r
318                   NULL,\r
319                   This->DriverBindingHandle,\r
320                   ControllerHandle,\r
321                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
322                   );\r
323   if (Status == EFI_SUCCESS) {\r
324     return EFI_ALREADY_STARTED;\r
325   }\r
326 \r
327   //\r
328   // Test to see if MNP SB is installed.\r
329   //\r
330   Status = gBS->OpenProtocol (\r
331                   ControllerHandle,\r
332                   &gEfiManagedNetworkServiceBindingProtocolGuid,\r
333                   NULL,\r
334                   This->DriverBindingHandle,\r
335                   ControllerHandle,\r
336                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
337                   );\r
338 \r
339   return Status;\r
340 }\r
341 \r
342 \r
343 /**\r
344   Start this driver on ControllerHandle. \r
345   \r
346   The Start() function is designed to be invoked from the EFI boot service ConnectController(). \r
347   As a result, much of the error checking on the parameters to Start() has been \r
348   moved into this common boot service. It is legal to call Start() from other locations, \r
349   but the following calling restrictions must be followed or the system behavior \r
350   will not be deterministic.\r
351   1. ControllerHandle must be a valid EFI_HANDLE.\r
352   2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally \r
353      aligned EFI_DEVICE_PATH_PROTOCOL.\r
354   3. Prior to calling Start(), the Supported() function for the driver specified \r
355      by This must have been called with the same calling parameters, and Supported() \r
356      must have returned EFI_SUCCESS.  \r
357 \r
358   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
359   @param[in]  ControllerHandle     The handle of the controller to start. This handle \r
360                                    must support a protocol interface that supplies \r
361                                    an I/O abstraction to the driver.\r
362   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path. \r
363                                    This parameter is ignored by device drivers, \r
364                                    and is optional for bus drivers.\r
365 \r
366   @retval EFI_SUCCESS              The device was started.\r
367   @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.\r
368                                    Currently not implemented.\r
369   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of \r
370                                    resources.\r
371   @retval Others                   The driver failded to start the device.\r
372 \r
373 **/\r
374 EFI_STATUS\r
375 EFIAPI\r
376 ArpDriverBindingStart (\r
377   IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
378   IN EFI_HANDLE                   ControllerHandle,\r
379   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL\r
380   )\r
381 {\r
382   EFI_STATUS        Status;\r
383   ARP_SERVICE_DATA  *ArpService;\r
384 \r
385   //\r
386   // Allocate a zero pool for ArpService.\r
387   //\r
388   ArpService = AllocateZeroPool (sizeof(ARP_SERVICE_DATA));\r
389   if (ArpService == NULL) {\r
390     return EFI_OUT_OF_RESOURCES;\r
391   }\r
392 \r
393   //\r
394   // Initialize the arp service context data.\r
395   //\r
396   Status = ArpCreateService (This->DriverBindingHandle, ControllerHandle, ArpService);\r
397   if (EFI_ERROR (Status)) {\r
398     goto ERROR;\r
399   }\r
400 \r
401   //\r
402   // Install the ARP service binding protocol.\r
403   //\r
404   Status = gBS->InstallMultipleProtocolInterfaces (\r
405                   &ControllerHandle,\r
406                   &gEfiArpServiceBindingProtocolGuid,\r
407                   &ArpService->ServiceBinding,\r
408                   NULL\r
409                   );\r
410   if (EFI_ERROR (Status)) {\r
411     goto ERROR;\r
412   }\r
413 \r
414   //\r
415   // OK, start to receive arp packets from Mnp.\r
416   //\r
417   Status = ArpService->Mnp->Receive (ArpService->Mnp, &ArpService->RxToken);\r
418   if (EFI_ERROR (Status)) {\r
419     goto ERROR;\r
420   }\r
421 \r
422   return Status;\r
423 \r
424 ERROR:\r
425 \r
426   //\r
427   // On error, clean the arp service context data, and free the memory allocated.\r
428   //\r
429   ArpCleanService (ArpService);\r
430   FreePool (ArpService);\r
431 \r
432   return Status;\r
433 }\r
434 \r
435 \r
436 /**\r
437   Stop this driver on ControllerHandle. \r
438   \r
439   Release the control of this controller and remove the IScsi functions. The Stop()\r
440   function is designed to be invoked from the EFI boot service DisconnectController(). \r
441   As a result, much of the error checking on the parameters to Stop() has been moved \r
442   into this common boot service. It is legal to call Stop() from other locations, \r
443   but the following calling restrictions must be followed or the system behavior \r
444   will not be deterministic.\r
445   1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
446      same driver's Start() function.\r
447   2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
448      EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
449      Start() function, and the Start() function must have called OpenProtocol() on\r
450      ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
451   \r
452   @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
453   @param[in]  ControllerHandle  A handle to the device being stopped. The handle must \r
454                                 support a bus specific I/O protocol for the driver \r
455                                 to use to stop the device.\r
456   @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.\r
457                                 Not used.\r
458   @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL \r
459                                 if NumberOfChildren is 0.Not used.\r
460 \r
461   @retval EFI_SUCCESS           The device was stopped.\r
462   @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.\r
463 \r
464 **/\r
465 EFI_STATUS\r
466 EFIAPI\r
467 ArpDriverBindingStop (\r
468   IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
469   IN EFI_HANDLE                   ControllerHandle,\r
470   IN UINTN                        NumberOfChildren,\r
471   IN EFI_HANDLE                   *ChildHandleBuffer\r
472   )\r
473 {\r
474   EFI_STATUS                    Status;\r
475   EFI_HANDLE                    NicHandle;\r
476   EFI_SERVICE_BINDING_PROTOCOL  *ServiceBinding;\r
477   ARP_SERVICE_DATA              *ArpService;\r
478   LIST_ENTRY                    *List;\r
479 \r
480   //\r
481   // Get the NicHandle which the arp servicebinding is installed on.\r
482   //\r
483   NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);\r
484   if (NicHandle == NULL) {\r
485     return EFI_SUCCESS;\r
486   }\r
487 \r
488   //\r
489   // Try to get the arp servicebinding protocol on the NicHandle.\r
490   //\r
491   Status = gBS->OpenProtocol (\r
492                   NicHandle,\r
493                   &gEfiArpServiceBindingProtocolGuid,\r
494                   (VOID **)&ServiceBinding,\r
495                   This->DriverBindingHandle,\r
496                   ControllerHandle,\r
497                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
498                   );\r
499   if (EFI_ERROR (Status)) {\r
500     DEBUG ((EFI_D_ERROR, "ArpDriverBindingStop: Open ArpSb failed, %r.\n", Status));\r
501     return EFI_DEVICE_ERROR;\r
502   }\r
503 \r
504   ArpService = ARP_SERVICE_DATA_FROM_THIS (ServiceBinding);\r
505 \r
506   if (NumberOfChildren != 0) {\r
507     //\r
508     // NumberOfChildren is not zero, destroy all the ARP children instances.\r
509     //\r
510     List = &ArpService->ChildrenList;\r
511     Status = NetDestroyLinkList (\r
512                List,\r
513                ArpDestroyChildEntryInHandleBuffer,\r
514                ServiceBinding,\r
515                NULL\r
516                );\r
517     ASSERT (IsListEmpty (&ArpService->PendingRequestTable));\r
518     ASSERT (IsListEmpty (&ArpService->DeniedCacheTable));\r
519     ASSERT (IsListEmpty (&ArpService->ResolvedCacheTable));\r
520   } else if (IsListEmpty (&ArpService->ChildrenList)) {\r
521     //\r
522     // Uninstall the ARP ServiceBinding protocol.\r
523     //\r
524     gBS->UninstallMultipleProtocolInterfaces (\r
525            NicHandle,\r
526            &gEfiArpServiceBindingProtocolGuid,\r
527            &ArpService->ServiceBinding,\r
528            NULL\r
529            );\r
530 \r
531     //\r
532     // Clean the arp servicebinding context data and free the memory allocated.\r
533     //\r
534     ArpCleanService (ArpService);\r
535 \r
536     FreePool (ArpService);\r
537   }\r
538 \r
539   return EFI_SUCCESS;\r
540 }\r
541 \r
542 /**\r
543   Creates a child handle and installs a protocol.\r
544   \r
545   The CreateChild() function installs a protocol on ChildHandle. \r
546   If ChildHandle is a pointer to NULL, then a new handle is created and returned \r
547   in ChildHandle. If ChildHandle is not a pointer to NULL, then the protocol \r
548   installs on the existing ChildHandle.\r
549 \r
550   @param  This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
551   @param  ChildHandle Pointer to the handle of the child to create. If it is NULL,\r
552                       then a new handle is created. If it is a pointer to an existing \r
553                       UEFI handle, then the protocol is added to the existing UEFI handle.\r
554 \r
555   @retval EFI_SUCCES            The protocol was added to ChildHandle.\r
556   @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r
557   @retval EFI_OUT_OF_RESOURCES  There are not enough resources availabe to create\r
558                                 the child\r
559   @retval other                 The child handle was not created\r
560 \r
561 **/\r
562 EFI_STATUS\r
563 EFIAPI\r
564 ArpServiceBindingCreateChild (\r
565   IN EFI_SERVICE_BINDING_PROTOCOL  *This,\r
566   IN EFI_HANDLE                    *ChildHandle\r
567   )\r
568 {\r
569   EFI_STATUS         Status;\r
570   ARP_SERVICE_DATA   *ArpService;\r
571   ARP_INSTANCE_DATA  *Instance;\r
572   VOID               *Mnp;\r
573   EFI_TPL            OldTpl;\r
574 \r
575   if ((This == NULL) || (ChildHandle == NULL)) {\r
576     return EFI_INVALID_PARAMETER;\r
577   }\r
578 \r
579   ArpService = ARP_SERVICE_DATA_FROM_THIS (This);\r
580 \r
581   //\r
582   // Allocate memory for the instance context data.\r
583   //\r
584   Instance = AllocateZeroPool (sizeof(ARP_INSTANCE_DATA));\r
585   if (Instance == NULL) {\r
586     DEBUG ((EFI_D_ERROR, "ArpSBCreateChild: Failed to allocate memory for Instance.\n"));\r
587 \r
588     return EFI_OUT_OF_RESOURCES;\r
589   }\r
590 \r
591   //\r
592   // Init the instance context data.\r
593   //\r
594   ArpInitInstance (ArpService, Instance);\r
595 \r
596   //\r
597   // Install the ARP protocol onto the ChildHandle.\r
598   //\r
599   Status = gBS->InstallMultipleProtocolInterfaces (\r
600                   ChildHandle,\r
601                   &gEfiArpProtocolGuid,\r
602                   (VOID *)&Instance->ArpProto,\r
603                   NULL\r
604                   );\r
605   if (EFI_ERROR (Status)) {\r
606     DEBUG ((EFI_D_ERROR, "ArpSBCreateChild: faild to install ARP protocol, %r.\n", Status));\r
607 \r
608     FreePool (Instance);\r
609     return Status;\r
610   }\r
611 \r
612   //\r
613   // Save the ChildHandle.\r
614   //\r
615   Instance->Handle = *ChildHandle;\r
616 \r
617   //\r
618   // Open the Managed Network protocol BY_CHILD.\r
619   //\r
620   Status = gBS->OpenProtocol (\r
621                   ArpService->MnpChildHandle,\r
622                   &gEfiManagedNetworkProtocolGuid,\r
623                   (VOID **) &Mnp,\r
624                   gArpDriverBinding.DriverBindingHandle,\r
625                   Instance->Handle,\r
626                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
627                   );\r
628   if (EFI_ERROR (Status)) {\r
629     goto ERROR;\r
630   }\r
631 \r
632   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
633 \r
634   //\r
635   // Insert the instance into children list managed by the arp service context data.\r
636   //\r
637   InsertTailList (&ArpService->ChildrenList, &Instance->List);\r
638   ArpService->ChildrenNumber++;\r
639 \r
640   gBS->RestoreTPL (OldTpl);\r
641 \r
642 ERROR:\r
643 \r
644   if (EFI_ERROR (Status)) {\r
645 \r
646     gBS->CloseProtocol (\r
647            ArpService->MnpChildHandle,\r
648            &gEfiManagedNetworkProtocolGuid,\r
649            gArpDriverBinding.DriverBindingHandle,\r
650            Instance->Handle\r
651            );\r
652 \r
653     gBS->UninstallMultipleProtocolInterfaces (\r
654            Instance->Handle,\r
655            &gEfiArpProtocolGuid,\r
656            &Instance->ArpProto,\r
657            NULL\r
658            );\r
659 \r
660     //\r
661     // Free the allocated memory.\r
662     //\r
663     FreePool (Instance);\r
664   }\r
665 \r
666   return Status;\r
667 }\r
668 \r
669 \r
670 /**\r
671   Destroys a child handle with a protocol installed on it.\r
672   \r
673   The DestroyChild() function does the opposite of CreateChild(). It removes a protocol \r
674   that was installed by CreateChild() from ChildHandle. If the removed protocol is the \r
675   last protocol on ChildHandle, then ChildHandle is destroyed.\r
676 \r
677   @param  This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
678   @param  ChildHandle Handle of the child to destroy\r
679 \r
680   @retval EFI_SUCCES            The protocol was removed from ChildHandle.\r
681   @retval EFI_UNSUPPORTED       ChildHandle does not support the protocol that is \r
682                                 being removed.\r
683   @retval EFI_INVALID_PARAMETER Child handle is NULL.\r
684   @retval EFI_ACCESS_DENIED     The protocol could not be removed from the ChildHandle\r
685                                 because its services are being used.\r
686   @retval other                 The child handle was not destroyed\r
687 \r
688 **/\r
689 EFI_STATUS\r
690 EFIAPI\r
691 ArpServiceBindingDestroyChild (\r
692   IN EFI_SERVICE_BINDING_PROTOCOL  *This,\r
693   IN EFI_HANDLE                    ChildHandle\r
694   )\r
695 {\r
696   EFI_STATUS         Status;\r
697   ARP_SERVICE_DATA   *ArpService;\r
698   ARP_INSTANCE_DATA  *Instance;\r
699   EFI_ARP_PROTOCOL   *Arp;\r
700   EFI_TPL            OldTpl;\r
701 \r
702   if ((This == NULL) || (ChildHandle == NULL)) {\r
703     return EFI_INVALID_PARAMETER;\r
704   }\r
705 \r
706   ArpService = ARP_SERVICE_DATA_FROM_THIS (This);\r
707 \r
708   //\r
709   // Get the arp protocol.\r
710   //\r
711   Status = gBS->OpenProtocol (\r
712                   ChildHandle,\r
713                   &gEfiArpProtocolGuid,\r
714                   (VOID **)&Arp,\r
715                   ArpService->ImageHandle,\r
716                   ChildHandle,\r
717                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
718                   );\r
719   if (EFI_ERROR (Status)) {\r
720     return EFI_UNSUPPORTED;\r
721   }\r
722 \r
723   Instance = ARP_INSTANCE_DATA_FROM_THIS (Arp);\r
724 \r
725   if (Instance->InDestroy) {\r
726     return EFI_SUCCESS;\r
727   }\r
728 \r
729   //\r
730   // Use the InDestroy as a flag to avoid re-entrance.\r
731   //\r
732   Instance->InDestroy = TRUE;\r
733 \r
734   //\r
735   // Close the Managed Network protocol.\r
736   //\r
737   gBS->CloseProtocol (\r
738          ArpService->MnpChildHandle,\r
739          &gEfiManagedNetworkProtocolGuid,\r
740          gArpDriverBinding.DriverBindingHandle,\r
741          ChildHandle\r
742          );\r
743 \r
744   //\r
745   // Uninstall the ARP protocol.\r
746   //\r
747   Status = gBS->UninstallMultipleProtocolInterfaces (\r
748                   ChildHandle,\r
749                   &gEfiArpProtocolGuid,\r
750                   &Instance->ArpProto,\r
751                   NULL\r
752                   );\r
753   if (EFI_ERROR (Status)) {\r
754     DEBUG ((EFI_D_ERROR, "ArpSBDestroyChild: Failed to uninstall the arp protocol, %r.\n",\r
755       Status));\r
756 \r
757     Instance->InDestroy = FALSE;\r
758     return Status;\r
759   }\r
760 \r
761   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
762 \r
763   if (Instance->Configured) {\r
764     //\r
765     // Delete the related cache entry.\r
766     //\r
767     ArpDeleteCacheEntry (Instance, FALSE, NULL, TRUE);\r
768 \r
769     //\r
770     // Reset the instance configuration.\r
771     //\r
772     ArpConfigureInstance (Instance, NULL);\r
773   }\r
774 \r
775   //\r
776   // Remove this instance from the ChildrenList.\r
777   //\r
778   RemoveEntryList (&Instance->List);\r
779   ArpService->ChildrenNumber--;\r
780 \r
781   gBS->RestoreTPL (OldTpl);\r
782 \r
783   FreePool (Instance);\r
784 \r
785   return Status;\r
786 }\r
787 \r
788 /**\r
789   The entry point for Arp driver which installs the driver binding and component name\r
790   protocol on its ImageHandle.\r
791 \r
792   @param[in]  ImageHandle        The image handle of the driver.\r
793   @param[in]  SystemTable        The system table.\r
794 \r
795   @retval EFI_SUCCESS            if the driver binding and component name protocols \r
796                                  are successfully\r
797   @retval Others                 Failed to install the protocols.\r
798 \r
799 **/\r
800 EFI_STATUS\r
801 EFIAPI\r
802 ArpDriverEntryPoint (\r
803   IN EFI_HANDLE        ImageHandle,\r
804   IN EFI_SYSTEM_TABLE  *SystemTable\r
805   )\r
806 {\r
807   return EfiLibInstallDriverBindingComponentName2 (\r
808            ImageHandle,\r
809            SystemTable,\r
810            &gArpDriverBinding,\r
811            ImageHandle,\r
812            &gArpComponentName,\r
813            &gArpComponentName2\r
814            );\r
815 }\r
816 \r