• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   The driver binding for UEFI PXEBC protocol.
3 
4 Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution.  The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9 
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 
16 #include "PxeBcImpl.h"
17 
18 EFI_DRIVER_BINDING_PROTOCOL gPxeBcDriverBinding = {
19   PxeBcDriverBindingSupported,
20   PxeBcDriverBindingStart,
21   PxeBcDriverBindingStop,
22   0xa,
23   NULL,
24   NULL
25 };
26 
27 /**
28   This is the declaration of an EFI image entry point. This entry point is
29   the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
30   both device drivers and bus drivers.
31 
32   @param  ImageHandle           The firmware allocated handle for the UEFI image.
33   @param  SystemTable           A pointer to the EFI System Table.
34 
35   @retval EFI_SUCCESS           The operation completed successfully.
36   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
37 
38 **/
39 EFI_STATUS
40 EFIAPI
PxeBcDriverEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)41 PxeBcDriverEntryPoint (
42   IN EFI_HANDLE             ImageHandle,
43   IN EFI_SYSTEM_TABLE       *SystemTable
44   )
45 {
46   return EfiLibInstallDriverBindingComponentName2 (
47           ImageHandle,
48           SystemTable,
49           &gPxeBcDriverBinding,
50           ImageHandle,
51           &gPxeBcComponentName,
52           &gPxeBcComponentName2
53           );
54 }
55 
56 
57 /**
58   Test to see if this driver supports ControllerHandle. This service
59   is called by the EFI boot service ConnectController(). In
60   order to make drivers as small as possible, there are a few calling
61   restrictions for this service. ConnectController() must
62   follow these calling restrictions. If any other agent wishes to call
63   Supported() it must also follow these calling restrictions.
64   PxeBc requires DHCP4 and MTFTP4 protocols.
65 
66   @param  This                Protocol instance pointer.
67   @param  ControllerHandle    Handle of device to test
68   @param  RemainingDevicePath Optional parameter use to pick a specific child
69                               device to start.
70 
71   @retval EFI_SUCCESS         This driver supports this device
72   @retval EFI_ALREADY_STARTED This driver is already running on this device
73   @retval other               This driver does not support this device
74 
75 **/
76 EFI_STATUS
77 EFIAPI
PxeBcDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)78 PxeBcDriverBindingSupported (
79   IN EFI_DRIVER_BINDING_PROTOCOL  * This,
80   IN EFI_HANDLE                   ControllerHandle,
81   IN EFI_DEVICE_PATH_PROTOCOL     * RemainingDevicePath OPTIONAL
82   )
83 {
84   EFI_PXE_BASE_CODE_PROTOCOL  *PxeBc;
85   EFI_STATUS                  Status;
86 
87   Status = gBS->OpenProtocol (
88                   ControllerHandle,
89                   &gEfiPxeBaseCodeProtocolGuid,
90                   (VOID **) &PxeBc,
91                   This->DriverBindingHandle,
92                   ControllerHandle,
93                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
94                   );
95 
96   if (!EFI_ERROR (Status)) {
97     return EFI_ALREADY_STARTED;
98   }
99 
100   Status = gBS->OpenProtocol (
101                   ControllerHandle,
102                   &gEfiDhcp4ServiceBindingProtocolGuid,
103                   NULL,
104                   This->DriverBindingHandle,
105                   ControllerHandle,
106                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
107                   );
108 
109   if (!EFI_ERROR (Status)) {
110 
111     Status = gBS->OpenProtocol (
112                     ControllerHandle,
113                     &gEfiMtftp4ServiceBindingProtocolGuid,
114                     NULL,
115                     This->DriverBindingHandle,
116                     ControllerHandle,
117                     EFI_OPEN_PROTOCOL_TEST_PROTOCOL
118                     );
119 
120   }
121 
122   return Status;
123 }
124 
125 
126 /**
127   Start this driver on ControllerHandle. This service is called by the
128   EFI boot service ConnectController(). In order to make
129   drivers as small as possible, there are a few calling restrictions for
130   this service. ConnectController() must follow these
131   calling restrictions. If any other agent wishes to call Start() it
132   must also follow these calling restrictions.
133 
134   @param  This                 Protocol instance pointer.
135   @param  ControllerHandle     Handle of device to bind driver to
136   @param  RemainingDevicePath  Optional parameter use to pick a specific child
137                                device to start.
138 
139   @retval EFI_SUCCESS          This driver is added to ControllerHandle
140   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle
141   @retval other                This driver does not support this device
142 
143 **/
144 EFI_STATUS
145 EFIAPI
PxeBcDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)146 PxeBcDriverBindingStart (
147   IN EFI_DRIVER_BINDING_PROTOCOL  * This,
148   IN EFI_HANDLE                   ControllerHandle,
149   IN EFI_DEVICE_PATH_PROTOCOL     * RemainingDevicePath OPTIONAL
150   )
151 {
152   PXEBC_PRIVATE_DATA  *Private;
153   UINTN               Index;
154   EFI_STATUS          Status;
155   EFI_IP4_MODE_DATA   Ip4ModeData;
156 
157   Private = AllocateZeroPool (sizeof (PXEBC_PRIVATE_DATA));
158   if (Private == NULL) {
159     return EFI_OUT_OF_RESOURCES;
160   }
161 
162   Private->Signature                    = PXEBC_PRIVATE_DATA_SIGNATURE;
163   Private->Controller                   = ControllerHandle;
164   Private->Image                        = This->DriverBindingHandle;
165   CopyMem (&Private->PxeBc, &mPxeBcProtocolTemplate, sizeof (Private->PxeBc));
166   Private->PxeBc.Mode                   = &Private->Mode;
167   CopyMem (&Private->LoadFile, &mLoadFileProtocolTemplate, sizeof (Private->LoadFile));
168 
169   Private->ProxyOffer.Packet.Offer.Size = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;
170   Private->Dhcp4Ack.Packet.Ack.Size     = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;
171   Private->PxeReply.Packet.Ack.Size     = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;
172 
173   for (Index = 0; Index < PXEBC_MAX_OFFER_NUM; Index++) {
174     Private->Dhcp4Offers[Index].Packet.Offer.Size = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;
175   }
176 
177   //
178   // Get the NII interface if it exists.
179   //
180   Status = gBS->OpenProtocol (
181                   ControllerHandle,
182                   &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
183                   (VOID **) &Private->Nii,
184                   This->DriverBindingHandle,
185                   ControllerHandle,
186                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
187                   );
188   if (EFI_ERROR (Status)) {
189     Private->Nii = NULL;
190   }
191 
192   Status = NetLibCreateServiceChild (
193             ControllerHandle,
194             This->DriverBindingHandle,
195             &gEfiArpServiceBindingProtocolGuid,
196             &Private->ArpChild
197             );
198   if (EFI_ERROR (Status)) {
199     goto ON_ERROR;
200   }
201 
202   Status = gBS->OpenProtocol (
203                   Private->ArpChild,
204                   &gEfiArpProtocolGuid,
205                   (VOID **) &Private->Arp,
206                   This->DriverBindingHandle,
207                   ControllerHandle,
208                   EFI_OPEN_PROTOCOL_BY_DRIVER
209                   );
210   if (EFI_ERROR (Status)) {
211     goto ON_ERROR;
212   }
213 
214   Status = NetLibCreateServiceChild (
215             ControllerHandle,
216             This->DriverBindingHandle,
217             &gEfiDhcp4ServiceBindingProtocolGuid,
218             &Private->Dhcp4Child
219             );
220   if (EFI_ERROR (Status)) {
221     goto ON_ERROR;
222   }
223 
224   Status = gBS->OpenProtocol (
225                   Private->Dhcp4Child,
226                   &gEfiDhcp4ProtocolGuid,
227                   (VOID **) &Private->Dhcp4,
228                   This->DriverBindingHandle,
229                   ControllerHandle,
230                   EFI_OPEN_PROTOCOL_BY_DRIVER
231                   );
232   if (EFI_ERROR (Status)) {
233     goto ON_ERROR;
234   }
235 
236   Status = NetLibCreateServiceChild (
237              ControllerHandle,
238              This->DriverBindingHandle,
239              &gEfiIp4ServiceBindingProtocolGuid,
240              &Private->Ip4Child
241              );
242   if (EFI_ERROR (Status)) {
243     goto ON_ERROR;
244   }
245 
246   Status = gBS->OpenProtocol (
247                   Private->Ip4Child,
248                   &gEfiIp4ProtocolGuid,
249                   (VOID **) &Private->Ip4,
250                   This->DriverBindingHandle,
251                   ControllerHandle,
252                   EFI_OPEN_PROTOCOL_BY_DRIVER
253                   );
254   if (EFI_ERROR (Status)) {
255     goto ON_ERROR;
256   }
257 
258   //
259   // Get max packet size from Ip4 to calculate block size for Tftp later.
260   //
261   Status = Private->Ip4->GetModeData (Private->Ip4, &Ip4ModeData, NULL, NULL);
262   if (EFI_ERROR (Status)) {
263     goto ON_ERROR;
264   }
265 
266   Private->Ip4MaxPacketSize = Ip4ModeData.MaxPacketSize;
267 
268   Status = NetLibCreateServiceChild (
269              ControllerHandle,
270              This->DriverBindingHandle,
271              &gEfiMtftp4ServiceBindingProtocolGuid,
272              &Private->Mtftp4Child
273              );
274 
275   if (EFI_ERROR (Status)) {
276     goto ON_ERROR;
277   }
278 
279   Status = gBS->OpenProtocol (
280                   Private->Mtftp4Child,
281                   &gEfiMtftp4ProtocolGuid,
282                   (VOID **) &Private->Mtftp4,
283                   This->DriverBindingHandle,
284                   ControllerHandle,
285                   EFI_OPEN_PROTOCOL_BY_DRIVER
286                   );
287 
288   if (EFI_ERROR (Status)) {
289     goto ON_ERROR;
290   }
291 
292   Status = NetLibCreateServiceChild (
293              ControllerHandle,
294              This->DriverBindingHandle,
295              &gEfiUdp4ServiceBindingProtocolGuid,
296              &Private->Udp4ReadChild
297              );
298 
299   if (EFI_ERROR (Status)) {
300     goto ON_ERROR;
301   }
302 
303   //
304   // The UDP instance for EfiPxeBcUdpRead
305   //
306   Status = gBS->OpenProtocol (
307                   Private->Udp4ReadChild,
308                   &gEfiUdp4ProtocolGuid,
309                   (VOID **) &Private->Udp4Read,
310                   This->DriverBindingHandle,
311                   ControllerHandle,
312                   EFI_OPEN_PROTOCOL_BY_DRIVER
313                   );
314 
315   if (EFI_ERROR (Status)) {
316     goto ON_ERROR;
317   }
318 
319   //
320   // The UDP instance for EfiPxeBcUdpWrite
321   //
322   Status = NetLibCreateServiceChild (
323              ControllerHandle,
324              This->DriverBindingHandle,
325              &gEfiUdp4ServiceBindingProtocolGuid,
326              &Private->Udp4WriteChild
327              );
328   if (EFI_ERROR (Status)) {
329     goto ON_ERROR;
330   }
331 
332   Status = gBS->OpenProtocol (
333                   Private->Udp4WriteChild,
334                   &gEfiUdp4ProtocolGuid,
335                   (VOID **) &Private->Udp4Write,
336                   This->DriverBindingHandle,
337                   ControllerHandle,
338                   EFI_OPEN_PROTOCOL_BY_DRIVER
339                   );
340   if (EFI_ERROR (Status)) {
341     goto ON_ERROR;
342   }
343   ZeroMem (&Private->Udp4CfgData, sizeof (EFI_UDP4_CONFIG_DATA));
344   Private->Udp4CfgData.AcceptBroadcast    = FALSE;
345   Private->Udp4CfgData.AcceptPromiscuous  = FALSE;
346   Private->Udp4CfgData.AcceptAnyPort      = TRUE;
347   Private->Udp4CfgData.AllowDuplicatePort = TRUE;
348   Private->Udp4CfgData.TypeOfService      = DEFAULT_ToS;
349   Private->Udp4CfgData.TimeToLive         = DEFAULT_TTL;
350   Private->Udp4CfgData.DoNotFragment      = FALSE;
351   Private->Udp4CfgData.ReceiveTimeout     = PXEBC_DEFAULT_LIFETIME;
352   Private->Udp4CfgData.UseDefaultAddress  = FALSE;
353 
354   PxeBcInitSeedPacket (&Private->SeedPacket, Private->Udp4Read);
355   Private->MacLen = Private->SeedPacket.Dhcp4.Header.HwAddrLen;
356   CopyMem (&Private->Mac, &Private->SeedPacket.Dhcp4.Header.ClientHwAddr[0], Private->MacLen);
357 
358 
359   ZeroMem (&Private->Ip4ConfigData, sizeof (EFI_IP4_CONFIG_DATA));
360   Private->Ip4ConfigData.DefaultProtocol   = EFI_IP_PROTO_ICMP;
361   Private->Ip4ConfigData.AcceptIcmpErrors  = TRUE;
362   Private->Ip4ConfigData.TypeOfService     = DEFAULT_ToS;
363   Private->Ip4ConfigData.TimeToLive        = DEFAULT_TTL;
364   Private->Ip4ConfigData.DoNotFragment     = FALSE;
365   Private->Ip4ConfigData.RawData           = FALSE;
366 
367   Status = gBS->InstallMultipleProtocolInterfaces (
368                   &ControllerHandle,
369                   &gEfiPxeBaseCodeProtocolGuid,
370                   &Private->PxeBc,
371                   &gEfiLoadFileProtocolGuid,
372                   &Private->LoadFile,
373                   NULL
374                   );
375   if (EFI_ERROR (Status)) {
376     goto ON_ERROR;
377   }
378   //
379   // Locate Ip4->Ip4Config2 and store it for set IPv4 Policy.
380   //
381   Status = gBS->HandleProtocol (
382                   ControllerHandle,
383                   &gEfiIp4Config2ProtocolGuid,
384                   (VOID **) &Private->Ip4Config2
385                   );
386   if (EFI_ERROR (Status)) {
387     goto ON_ERROR;
388   }
389 
390   return EFI_SUCCESS;
391 
392 ON_ERROR:
393 
394   if (Private->Udp4WriteChild != NULL) {
395     gBS->CloseProtocol (
396            Private->Udp4WriteChild,
397            &gEfiUdp4ProtocolGuid,
398            This->DriverBindingHandle,
399            ControllerHandle
400            );
401     NetLibDestroyServiceChild (
402       ControllerHandle,
403       This->DriverBindingHandle,
404       &gEfiUdp4ServiceBindingProtocolGuid,
405       Private->Udp4WriteChild
406       );
407   }
408 
409   if (Private->Udp4ReadChild != NULL) {
410     gBS->CloseProtocol (
411           Private->Udp4ReadChild,
412           &gEfiUdp4ProtocolGuid,
413           This->DriverBindingHandle,
414           ControllerHandle
415           );
416     NetLibDestroyServiceChild (
417       ControllerHandle,
418       This->DriverBindingHandle,
419       &gEfiUdp4ServiceBindingProtocolGuid,
420       Private->Udp4ReadChild
421       );
422   }
423 
424   if (Private->Mtftp4Child != NULL) {
425     gBS->CloseProtocol (
426           Private->Mtftp4Child,
427           &gEfiMtftp4ProtocolGuid,
428           This->DriverBindingHandle,
429           ControllerHandle
430           );
431 
432     NetLibDestroyServiceChild (
433       ControllerHandle,
434       This->DriverBindingHandle,
435       &gEfiMtftp4ServiceBindingProtocolGuid,
436       Private->Mtftp4Child
437       );
438   }
439 
440   if (Private->Ip4Child != NULL) {
441     gBS->CloseProtocol (
442           Private->Ip4Child,
443           &gEfiIp4ProtocolGuid,
444           This->DriverBindingHandle,
445           ControllerHandle
446           );
447 
448     NetLibDestroyServiceChild (
449       ControllerHandle,
450       This->DriverBindingHandle,
451       &gEfiIp4ServiceBindingProtocolGuid,
452       Private->Ip4Child
453       );
454   }
455 
456   if (Private->Dhcp4Child != NULL) {
457     gBS->CloseProtocol (
458           Private->Dhcp4Child,
459           &gEfiDhcp4ProtocolGuid,
460           This->DriverBindingHandle,
461           ControllerHandle
462           );
463 
464     NetLibDestroyServiceChild (
465       ControllerHandle,
466       This->DriverBindingHandle,
467       &gEfiDhcp4ServiceBindingProtocolGuid,
468       Private->Dhcp4Child
469       );
470   }
471 
472   if (Private->ArpChild != NULL) {
473     gBS->CloseProtocol (
474           Private->ArpChild,
475           &gEfiArpProtocolGuid,
476           This->DriverBindingHandle,
477           ControllerHandle
478           );
479 
480     NetLibDestroyServiceChild (
481       ControllerHandle,
482       This->DriverBindingHandle,
483       &gEfiArpServiceBindingProtocolGuid,
484       Private->ArpChild
485       );
486   }
487 
488   FreePool (Private);
489 
490   return Status;
491 }
492 
493 
494 /**
495   Stop this driver on ControllerHandle. This service is called by the
496   EFI boot service DisconnectController(). In order to
497   make drivers as small as possible, there are a few calling
498   restrictions for this service. DisconnectController()
499   must follow these calling restrictions. If any other agent wishes
500   to call Stop() it must also follow these calling restrictions.
501 
502   @param  This              Protocol instance pointer.
503   @param  ControllerHandle  Handle of device to stop driver on
504   @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
505                             children is zero stop the entire bus driver.
506   @param  ChildHandleBuffer List of Child Handles to Stop.
507 
508   @retval EFI_SUCCESS       This driver is removed ControllerHandle
509   @retval other             This driver was not removed from this device
510 
511 **/
512 EFI_STATUS
513 EFIAPI
PxeBcDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)514 PxeBcDriverBindingStop (
515   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
516   IN EFI_HANDLE                   ControllerHandle,
517   IN UINTN                        NumberOfChildren,
518   IN EFI_HANDLE                   *ChildHandleBuffer
519   )
520 {
521   PXEBC_PRIVATE_DATA          *Private;
522   EFI_PXE_BASE_CODE_PROTOCOL  *PxeBc;
523   EFI_HANDLE                  NicHandle;
524   EFI_STATUS                  Status;
525 
526   NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid);
527   if (NicHandle == NULL) {
528     NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);
529 
530     if (NicHandle == NULL) {
531       NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp4ProtocolGuid);
532 
533       if (NicHandle == NULL) {
534         NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp4ProtocolGuid);
535 
536         if (NicHandle == NULL) {
537           NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiMtftp4ProtocolGuid);
538 
539           if (NicHandle == NULL) {
540             return EFI_SUCCESS;
541           }
542         }
543       }
544     }
545   }
546 
547   Status = gBS->OpenProtocol (
548                   NicHandle,
549                   &gEfiPxeBaseCodeProtocolGuid,
550                   (VOID **) &PxeBc,
551                   This->DriverBindingHandle,
552                   ControllerHandle,
553                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
554                   );
555 
556   if (EFI_ERROR (Status)) {
557     return Status;
558   }
559 
560   //
561   // Stop functionality of PXE Base Code protocol
562   //
563   Status = PxeBc->Stop (PxeBc);
564   if (Status != EFI_SUCCESS && Status != EFI_NOT_STARTED) {
565     return Status;
566   }
567 
568   Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (PxeBc);
569 
570   Status = gBS->UninstallMultipleProtocolInterfaces (
571                   NicHandle,
572                   &gEfiPxeBaseCodeProtocolGuid,
573                   &Private->PxeBc,
574                   &gEfiLoadFileProtocolGuid,
575                   &Private->LoadFile,
576                   NULL
577                   );
578 
579   if (!EFI_ERROR (Status)) {
580 
581     gBS->CloseProtocol (
582            Private->Udp4WriteChild,
583            &gEfiUdp4ProtocolGuid,
584            This->DriverBindingHandle,
585            NicHandle
586            );
587     NetLibDestroyServiceChild (
588       ControllerHandle,
589       This->DriverBindingHandle,
590       &gEfiUdp4ServiceBindingProtocolGuid,
591       Private->Udp4WriteChild
592       );
593 
594     gBS->CloseProtocol (
595           Private->Udp4ReadChild,
596           &gEfiUdp4ProtocolGuid,
597           This->DriverBindingHandle,
598           NicHandle
599           );
600     NetLibDestroyServiceChild (
601       NicHandle,
602       This->DriverBindingHandle,
603       &gEfiUdp4ServiceBindingProtocolGuid,
604       Private->Udp4ReadChild
605       );
606 
607     gBS->CloseProtocol (
608           Private->Dhcp4Child,
609           &gEfiDhcp4ProtocolGuid,
610           This->DriverBindingHandle,
611           NicHandle
612           );
613     NetLibDestroyServiceChild (
614       NicHandle,
615       This->DriverBindingHandle,
616       &gEfiDhcp4ServiceBindingProtocolGuid,
617       Private->Dhcp4Child
618       );
619 
620     gBS->CloseProtocol (
621           Private->Mtftp4Child,
622           &gEfiMtftp4ProtocolGuid,
623           This->DriverBindingHandle,
624           NicHandle
625           );
626     NetLibDestroyServiceChild (
627       NicHandle,
628       This->DriverBindingHandle,
629       &gEfiMtftp4ServiceBindingProtocolGuid,
630       Private->Mtftp4Child
631       );
632 
633     gBS->CloseProtocol (
634           Private->Ip4Child,
635           &gEfiIp4ProtocolGuid,
636           This->DriverBindingHandle,
637           NicHandle
638           );
639     NetLibDestroyServiceChild (
640       NicHandle,
641       This->DriverBindingHandle,
642       &gEfiIp4ServiceBindingProtocolGuid,
643       Private->Ip4Child
644       );
645 
646     gBS->CloseProtocol (
647           Private->ArpChild,
648           &gEfiArpProtocolGuid,
649           This->DriverBindingHandle,
650           NicHandle
651           );
652     NetLibDestroyServiceChild (
653       NicHandle,
654       This->DriverBindingHandle,
655       &gEfiArpServiceBindingProtocolGuid,
656       Private->ArpChild
657       );
658 
659     FreePool (Private);
660   }
661 
662   return Status;
663 }
664 
665 
666