1 /** @file
2   Driver Binding functions implementationfor for UefiPxeBc Driver.
3 
4   (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
5   Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
6 
7   SPDX-License-Identifier: BSD-2-Clause-Patent
8 
9 **/
10 
11 #include "PxeBcImpl.h"
12 
13 
14 EFI_DRIVER_BINDING_PROTOCOL gPxeBcIp4DriverBinding = {
15   PxeBcIp4DriverBindingSupported,
16   PxeBcIp4DriverBindingStart,
17   PxeBcIp4DriverBindingStop,
18   0xa,
19   NULL,
20   NULL
21 };
22 
23 EFI_DRIVER_BINDING_PROTOCOL gPxeBcIp6DriverBinding = {
24   PxeBcIp6DriverBindingSupported,
25   PxeBcIp6DriverBindingStart,
26   PxeBcIp6DriverBindingStop,
27   0xa,
28   NULL,
29   NULL
30 };
31 
32 /**
33   Get the Nic handle using any child handle in the IPv4 stack.
34 
35   @param[in]  ControllerHandle    Pointer to child handle over IPv4.
36 
37   @return NicHandle               The pointer to the Nic handle.
38 
39 **/
40 EFI_HANDLE
PxeBcGetNicByIp4Children(IN EFI_HANDLE ControllerHandle)41 PxeBcGetNicByIp4Children (
42   IN EFI_HANDLE                 ControllerHandle
43   )
44 {
45   EFI_HANDLE                    NicHandle;
46 
47   NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid);
48   if (NicHandle == NULL) {
49     NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp4ProtocolGuid);
50     if (NicHandle == NULL) {
51       NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp4ProtocolGuid);
52       if (NicHandle == NULL) {
53         NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);
54         if (NicHandle == NULL) {
55           NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiMtftp4ProtocolGuid);
56           if (NicHandle == NULL) {
57             return NULL;
58           }
59         }
60       }
61     }
62   }
63 
64   return NicHandle;
65 }
66 
67 
68 /**
69   Get the Nic handle using any child handle in the IPv6 stack.
70 
71   @param[in]  ControllerHandle    Pointer to child handle over IPv6.
72 
73   @return NicHandle               The pointer to the Nic handle.
74 
75 **/
76 EFI_HANDLE
PxeBcGetNicByIp6Children(IN EFI_HANDLE ControllerHandle)77 PxeBcGetNicByIp6Children (
78   IN EFI_HANDLE                  ControllerHandle
79   )
80 {
81   EFI_HANDLE                     NicHandle;
82 
83   NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp6ProtocolGuid);
84   if (NicHandle == NULL) {
85     NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp6ProtocolGuid);
86     if (NicHandle == NULL) {
87       NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp6ProtocolGuid);
88       if (NicHandle == NULL) {
89         NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiMtftp6ProtocolGuid);
90         if (NicHandle == NULL) {
91           return NULL;
92         }
93       }
94     }
95   }
96 
97   return NicHandle;
98 }
99 
100 
101 /**
102   Destroy the opened instances based on IPv4.
103 
104   @param[in]  This              Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
105   @param[in]  Private           Pointer to PXEBC_PRIVATE_DATA.
106 
107 **/
108 VOID
PxeBcDestroyIp4Children(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN PXEBC_PRIVATE_DATA * Private)109 PxeBcDestroyIp4Children (
110   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
111   IN PXEBC_PRIVATE_DATA           *Private
112   )
113 {
114   ASSERT(Private != NULL);
115 
116   if (Private->ArpChild != NULL) {
117     //
118     // Close Arp for PxeBc->Arp and destroy the instance.
119     //
120     gBS->CloseProtocol (
121            Private->ArpChild,
122            &gEfiArpProtocolGuid,
123            This->DriverBindingHandle,
124            Private->Controller
125            );
126 
127     NetLibDestroyServiceChild (
128       Private->Controller,
129       This->DriverBindingHandle,
130       &gEfiArpServiceBindingProtocolGuid,
131       Private->ArpChild
132       );
133   }
134 
135   if (Private->Ip4Child != NULL) {
136     //
137     // Close Ip4 for background ICMP error message and destroy the instance.
138     //
139     gBS->CloseProtocol (
140            Private->Ip4Child,
141            &gEfiIp4ProtocolGuid,
142            This->DriverBindingHandle,
143            Private->Controller
144            );
145 
146     NetLibDestroyServiceChild (
147       Private->Controller,
148       This->DriverBindingHandle,
149       &gEfiIp4ServiceBindingProtocolGuid,
150       Private->Ip4Child
151       );
152   }
153 
154   if (Private->Udp4WriteChild != NULL) {
155     //
156     // Close Udp4 for PxeBc->UdpWrite and destroy the instance.
157     //
158     gBS->CloseProtocol (
159            Private->Udp4WriteChild,
160            &gEfiUdp4ProtocolGuid,
161            This->DriverBindingHandle,
162            Private->Controller
163            );
164 
165     NetLibDestroyServiceChild (
166       Private->Controller,
167       This->DriverBindingHandle,
168       &gEfiUdp4ServiceBindingProtocolGuid,
169       Private->Udp4WriteChild
170       );
171   }
172 
173   if (Private->Udp4ReadChild != NULL) {
174     //
175     // Close Udp4 for PxeBc->UdpRead and destroy the instance.
176     //
177     gBS->CloseProtocol (
178           Private->Udp4ReadChild,
179           &gEfiUdp4ProtocolGuid,
180           This->DriverBindingHandle,
181           Private->Controller
182           );
183 
184     NetLibDestroyServiceChild (
185       Private->Controller,
186       This->DriverBindingHandle,
187       &gEfiUdp4ServiceBindingProtocolGuid,
188       Private->Udp4ReadChild
189       );
190   }
191 
192   if (Private->Mtftp4Child != NULL) {
193     //
194     // Close Mtftp4 for PxeBc->Mtftp4 and destroy the instance.
195     //
196     gBS->CloseProtocol (
197           Private->Mtftp4Child,
198           &gEfiMtftp4ProtocolGuid,
199           This->DriverBindingHandle,
200           Private->Controller
201           );
202 
203     NetLibDestroyServiceChild (
204       Private->Controller,
205       This->DriverBindingHandle,
206       &gEfiMtftp4ServiceBindingProtocolGuid,
207       Private->Mtftp4Child
208       );
209   }
210 
211   if (Private->Dhcp4Child != NULL) {
212     //
213     // Close Dhcp4 for PxeBc->Dhcp4 and destroy the instance.
214     //
215     gBS->CloseProtocol (
216           Private->Dhcp4Child,
217           &gEfiDhcp4ProtocolGuid,
218           This->DriverBindingHandle,
219           Private->Controller
220           );
221 
222     NetLibDestroyServiceChild (
223       Private->Controller,
224       This->DriverBindingHandle,
225       &gEfiDhcp4ServiceBindingProtocolGuid,
226       Private->Dhcp4Child
227       );
228   }
229 
230   if (Private->Ip4Nic != NULL) {
231     //
232     // Close PxeBcPrivate from the parent Nic handle and destroy the virtual handle.
233     //
234     gBS->CloseProtocol (
235            Private->Controller,
236            &gEfiCallerIdGuid,
237            This->DriverBindingHandle,
238            Private->Ip4Nic->Controller
239            );
240 
241     gBS->UninstallMultipleProtocolInterfaces (
242            Private->Ip4Nic->Controller,
243            &gEfiDevicePathProtocolGuid,
244            Private->Ip4Nic->DevicePath,
245            &gEfiLoadFileProtocolGuid,
246            &Private->Ip4Nic->LoadFile,
247            &gEfiPxeBaseCodeProtocolGuid,
248            &Private->PxeBc,
249            NULL
250            );
251     FreePool (Private->Ip4Nic->DevicePath);
252 
253     if (Private->Snp != NULL) {
254       //
255       // Close SNP from the child virtual handle
256       //
257       gBS->CloseProtocol (
258              Private->Ip4Nic->Controller,
259              &gEfiSimpleNetworkProtocolGuid,
260              This->DriverBindingHandle,
261              Private->Ip4Nic->Controller
262              );
263 
264       gBS->UninstallProtocolInterface (
265              Private->Ip4Nic->Controller,
266              &gEfiSimpleNetworkProtocolGuid,
267              Private->Snp
268              );
269     }
270     FreePool (Private->Ip4Nic);
271   }
272 
273   Private->ArpChild         = NULL;
274   Private->Ip4Child         = NULL;
275   Private->Udp4WriteChild   = NULL;
276   Private->Udp4ReadChild    = NULL;
277   Private->Mtftp4Child      = NULL;
278   Private->Dhcp4Child       = NULL;
279   Private->Ip4Nic           = NULL;
280 }
281 
282 
283 /**
284   Destroy the opened instances based on IPv6.
285 
286   @param[in]  This              Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
287   @param[in]  Private           Pointer to PXEBC_PRIVATE_DATA.
288 
289 **/
290 VOID
PxeBcDestroyIp6Children(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN PXEBC_PRIVATE_DATA * Private)291 PxeBcDestroyIp6Children (
292   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
293   IN PXEBC_PRIVATE_DATA           *Private
294   )
295 {
296   ASSERT(Private != NULL);
297 
298   if (Private->Ip6Child != NULL) {
299     //
300     // Close Ip6 for Ip6->Ip6Config and destroy the instance.
301     //
302     gBS->CloseProtocol (
303           Private->Ip6Child,
304           &gEfiIp6ProtocolGuid,
305           This->DriverBindingHandle,
306           Private->Controller
307           );
308 
309     NetLibDestroyServiceChild (
310       Private->Controller,
311       This->DriverBindingHandle,
312       &gEfiIp6ServiceBindingProtocolGuid,
313       Private->Ip6Child
314       );
315   }
316 
317   if (Private->Udp6WriteChild != NULL) {
318     //
319     // Close Udp6 for PxeBc->UdpWrite and destroy the instance.
320     //
321     gBS->CloseProtocol (
322            Private->Udp6WriteChild,
323            &gEfiUdp6ProtocolGuid,
324            This->DriverBindingHandle,
325            Private->Controller
326            );
327     NetLibDestroyServiceChild (
328       Private->Controller,
329       This->DriverBindingHandle,
330       &gEfiUdp6ServiceBindingProtocolGuid,
331       Private->Udp6WriteChild
332       );
333   }
334 
335   if (Private->Udp6ReadChild != NULL) {
336     //
337     // Close Udp6 for PxeBc->UdpRead and destroy the instance.
338     //
339     gBS->CloseProtocol (
340           Private->Udp6ReadChild,
341           &gEfiUdp6ProtocolGuid,
342           This->DriverBindingHandle,
343           Private->Controller
344           );
345     NetLibDestroyServiceChild (
346       Private->Controller,
347       This->DriverBindingHandle,
348       &gEfiUdp6ServiceBindingProtocolGuid,
349       Private->Udp6ReadChild
350       );
351   }
352 
353   if (Private->Mtftp6Child != NULL) {
354     //
355     // Close Mtftp6 for PxeBc->Mtftp and destroy the instance.
356     //
357     gBS->CloseProtocol (
358           Private->Mtftp6Child,
359           &gEfiMtftp6ProtocolGuid,
360           This->DriverBindingHandle,
361           Private->Controller
362           );
363 
364     NetLibDestroyServiceChild (
365       Private->Controller,
366       This->DriverBindingHandle,
367       &gEfiMtftp6ServiceBindingProtocolGuid,
368       Private->Mtftp6Child
369       );
370   }
371 
372   if (Private->Dhcp6Child != NULL) {
373     //
374     // Close Dhcp6 for PxeBc->Dhcp and destroy the instance.
375     //
376     gBS->CloseProtocol (
377           Private->Dhcp6Child,
378           &gEfiDhcp6ProtocolGuid,
379           This->DriverBindingHandle,
380           Private->Controller
381           );
382 
383     NetLibDestroyServiceChild (
384       Private->Controller,
385       This->DriverBindingHandle,
386       &gEfiDhcp6ServiceBindingProtocolGuid,
387       Private->Dhcp6Child
388       );
389   }
390 
391   if (Private->Ip6Nic != NULL) {
392     //
393     // Close PxeBcPrivate from the parent Nic handle and destroy the virtual handle.
394     //
395     gBS->CloseProtocol (
396            Private->Controller,
397            &gEfiCallerIdGuid,
398            This->DriverBindingHandle,
399            Private->Ip6Nic->Controller
400            );
401 
402     gBS->UninstallMultipleProtocolInterfaces (
403            Private->Ip6Nic->Controller,
404            &gEfiDevicePathProtocolGuid,
405            Private->Ip6Nic->DevicePath,
406            &gEfiLoadFileProtocolGuid,
407            &Private->Ip6Nic->LoadFile,
408            &gEfiPxeBaseCodeProtocolGuid,
409            &Private->PxeBc,
410            NULL
411            );
412     FreePool (Private->Ip6Nic->DevicePath);
413 
414     if (Private->Snp != NULL) {
415       //
416       // Close SNP from the child virtual handle
417       //
418       gBS->CloseProtocol (
419              Private->Ip6Nic->Controller,
420              &gEfiSimpleNetworkProtocolGuid,
421              This->DriverBindingHandle,
422              Private->Ip6Nic->Controller
423              );
424       gBS->UninstallProtocolInterface (
425              Private->Ip6Nic->Controller,
426              &gEfiSimpleNetworkProtocolGuid,
427              Private->Snp
428              );
429     }
430     FreePool (Private->Ip6Nic);
431   }
432 
433   Private->Ip6Child           = NULL;
434   Private->Udp6WriteChild     = NULL;
435   Private->Udp6ReadChild      = NULL;
436   Private->Mtftp6Child        = NULL;
437   Private->Dhcp6Child         = NULL;
438   Private->Ip6Nic             = NULL;
439   Private->Mode.Ipv6Available = FALSE;
440 }
441 
442 /**
443   Check whether UNDI protocol supports IPv6.
444 
445   @param[in]   ControllerHandle  Controller handle.
446   @param[in]   Private           Pointer to PXEBC_PRIVATE_DATA.
447   @param[out]  Ipv6Support       TRUE if UNDI supports IPv6.
448 
449   @retval EFI_SUCCESS            Get the result whether UNDI supports IPv6 by NII or AIP protocol successfully.
450   @retval EFI_NOT_FOUND          Don't know whether UNDI supports IPv6 since NII or AIP is not available.
451 
452 **/
453 EFI_STATUS
PxeBcCheckIpv6Support(IN EFI_HANDLE ControllerHandle,IN PXEBC_PRIVATE_DATA * Private,OUT BOOLEAN * Ipv6Support)454 PxeBcCheckIpv6Support (
455   IN  EFI_HANDLE                   ControllerHandle,
456   IN  PXEBC_PRIVATE_DATA           *Private,
457   OUT BOOLEAN                      *Ipv6Support
458   )
459 {
460   EFI_HANDLE                       Handle;
461   EFI_ADAPTER_INFORMATION_PROTOCOL *Aip;
462   EFI_STATUS                       Status;
463   EFI_GUID                         *InfoTypesBuffer;
464   UINTN                            InfoTypeBufferCount;
465   UINTN                            TypeIndex;
466   BOOLEAN                          Supported;
467   VOID                             *InfoBlock;
468   UINTN                            InfoBlockSize;
469 
470   ASSERT (Private != NULL && Ipv6Support != NULL);
471 
472   //
473   // Check whether the UNDI supports IPv6 by NII protocol.
474   //
475   if (Private->Nii != NULL) {
476     *Ipv6Support = Private->Nii->Ipv6Supported;
477     return EFI_SUCCESS;
478   }
479 
480   //
481   // Check whether the UNDI supports IPv6 by AIP protocol.
482   //
483 
484   //
485   // Get the NIC handle by SNP protocol.
486   //
487   Handle = NetLibGetSnpHandle (ControllerHandle, NULL);
488   if (Handle == NULL) {
489     return EFI_NOT_FOUND;
490   }
491 
492   Aip    = NULL;
493   Status = gBS->HandleProtocol (
494                   Handle,
495                   &gEfiAdapterInformationProtocolGuid,
496                   (VOID *) &Aip
497                   );
498   if (EFI_ERROR (Status) || Aip == NULL) {
499     return EFI_NOT_FOUND;
500   }
501 
502   InfoTypesBuffer     = NULL;
503   InfoTypeBufferCount = 0;
504   Status = Aip->GetSupportedTypes (Aip, &InfoTypesBuffer, &InfoTypeBufferCount);
505   if (EFI_ERROR (Status) || InfoTypesBuffer == NULL) {
506     FreePool (InfoTypesBuffer);
507     return EFI_NOT_FOUND;
508   }
509 
510   Supported = FALSE;
511   for (TypeIndex = 0; TypeIndex < InfoTypeBufferCount; TypeIndex++) {
512     if (CompareGuid (&InfoTypesBuffer[TypeIndex], &gEfiAdapterInfoUndiIpv6SupportGuid)) {
513       Supported = TRUE;
514       break;
515     }
516   }
517 
518   FreePool (InfoTypesBuffer);
519   if (!Supported) {
520     return EFI_NOT_FOUND;
521   }
522 
523   //
524   // We now have adapter information block.
525   //
526   InfoBlock     = NULL;
527   InfoBlockSize = 0;
528   Status = Aip->GetInformation (Aip, &gEfiAdapterInfoUndiIpv6SupportGuid, &InfoBlock, &InfoBlockSize);
529   if (EFI_ERROR (Status) || InfoBlock == NULL) {
530     FreePool (InfoBlock);
531     return EFI_NOT_FOUND;
532   }
533 
534   *Ipv6Support = ((EFI_ADAPTER_INFO_UNDI_IPV6_SUPPORT *) InfoBlock)->Ipv6Support;
535   FreePool (InfoBlock);
536   return EFI_SUCCESS;
537 
538 }
539 
540 /**
541   Create the opened instances based on IPv4.
542 
543   @param[in]  This              Pointer to EFI_DRIVER_BINDING_PROTOCOL.
544   @param[in]  ControllerHandle  Handle of the child to destroy.
545   @param[in]  Private Handle    Pointer to PXEBC_PRIVATE_DATA.
546 
547   @retval EFI_SUCCESS           The instances based on IPv4 were all created successfully.
548   @retval Others                An unexpected error occurred.
549 
550 **/
551 EFI_STATUS
PxeBcCreateIp4Children(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN PXEBC_PRIVATE_DATA * Private)552 PxeBcCreateIp4Children (
553   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
554   IN EFI_HANDLE                   ControllerHandle,
555   IN PXEBC_PRIVATE_DATA           *Private
556   )
557 {
558   EFI_STATUS                      Status;
559   IPv4_DEVICE_PATH                Ip4Node;
560   EFI_PXE_BASE_CODE_MODE          *Mode;
561   EFI_UDP4_CONFIG_DATA            *Udp4CfgData;
562   EFI_IP4_CONFIG_DATA             *Ip4CfgData;
563   EFI_IP4_MODE_DATA               Ip4ModeData;
564   PXEBC_PRIVATE_PROTOCOL          *Id;
565   EFI_SIMPLE_NETWORK_PROTOCOL     *Snp;
566 
567   if (Private->Ip4Nic != NULL) {
568     //
569     // Already created before.
570     //
571     return EFI_SUCCESS;
572   }
573 
574   //
575   // Create Dhcp4 child and open Dhcp4 protocol for PxeBc->Dhcp.
576   //
577   Status = NetLibCreateServiceChild (
578              ControllerHandle,
579              This->DriverBindingHandle,
580              &gEfiDhcp4ServiceBindingProtocolGuid,
581              &Private->Dhcp4Child
582              );
583   if (EFI_ERROR (Status)) {
584     goto ON_ERROR;
585   }
586 
587   Status = gBS->OpenProtocol (
588                   Private->Dhcp4Child,
589                   &gEfiDhcp4ProtocolGuid,
590                   (VOID **) &Private->Dhcp4,
591                   This->DriverBindingHandle,
592                   ControllerHandle,
593                   EFI_OPEN_PROTOCOL_BY_DRIVER
594                   );
595   if (EFI_ERROR (Status)) {
596     goto ON_ERROR;
597   }
598 
599   //
600   // Create Mtftp4 child and open Mtftp4 protocol for PxeBc->Mtftp.
601   //
602   Status = NetLibCreateServiceChild (
603              ControllerHandle,
604              This->DriverBindingHandle,
605              &gEfiMtftp4ServiceBindingProtocolGuid,
606              &Private->Mtftp4Child
607              );
608   if (EFI_ERROR (Status)) {
609     goto ON_ERROR;
610   }
611 
612   Status = gBS->OpenProtocol (
613                   Private->Mtftp4Child,
614                   &gEfiMtftp4ProtocolGuid,
615                   (VOID **) &Private->Mtftp4,
616                   This->DriverBindingHandle,
617                   ControllerHandle,
618                   EFI_OPEN_PROTOCOL_BY_DRIVER
619                   );
620   if (EFI_ERROR (Status)) {
621     goto ON_ERROR;
622   }
623 
624   //
625   // Create Udp4 child and open Udp4 protocol for PxeBc->UdpRead.
626   //
627   Status = NetLibCreateServiceChild (
628              ControllerHandle,
629              This->DriverBindingHandle,
630              &gEfiUdp4ServiceBindingProtocolGuid,
631              &Private->Udp4ReadChild
632              );
633   if (EFI_ERROR (Status)) {
634     goto ON_ERROR;
635   }
636 
637   Status = gBS->OpenProtocol (
638                   Private->Udp4ReadChild,
639                   &gEfiUdp4ProtocolGuid,
640                   (VOID **) &Private->Udp4Read,
641                   This->DriverBindingHandle,
642                   ControllerHandle,
643                   EFI_OPEN_PROTOCOL_BY_DRIVER
644                   );
645   if (EFI_ERROR (Status)) {
646     goto ON_ERROR;
647   }
648 
649   //
650   // Create Udp4 child and open Udp4 protocol for PxeBc->UdpWrite.
651   //
652   Status = NetLibCreateServiceChild (
653              ControllerHandle,
654              This->DriverBindingHandle,
655              &gEfiUdp4ServiceBindingProtocolGuid,
656              &Private->Udp4WriteChild
657              );
658   if (EFI_ERROR (Status)) {
659     goto ON_ERROR;
660   }
661 
662   Status = gBS->OpenProtocol (
663                   Private->Udp4WriteChild,
664                   &gEfiUdp4ProtocolGuid,
665                   (VOID **) &Private->Udp4Write,
666                   This->DriverBindingHandle,
667                   ControllerHandle,
668                   EFI_OPEN_PROTOCOL_BY_DRIVER
669                   );
670   if (EFI_ERROR (Status)) {
671     goto ON_ERROR;
672   }
673 
674   //
675   // Create Arp child and open Arp protocol for PxeBc->Arp.
676   //
677   Status = NetLibCreateServiceChild (
678              ControllerHandle,
679              This->DriverBindingHandle,
680              &gEfiArpServiceBindingProtocolGuid,
681              &Private->ArpChild
682              );
683   if (EFI_ERROR (Status)) {
684     goto ON_ERROR;
685   }
686 
687   Status = gBS->OpenProtocol (
688                   Private->ArpChild,
689                   &gEfiArpProtocolGuid,
690                   (VOID **) &Private->Arp,
691                   This->DriverBindingHandle,
692                   ControllerHandle,
693                   EFI_OPEN_PROTOCOL_BY_DRIVER
694                   );
695   if (EFI_ERROR (Status)) {
696     goto ON_ERROR;
697   }
698 
699   //
700   // Create Ip4 child and open Ip4 protocol for background ICMP packets.
701   //
702   Status = NetLibCreateServiceChild (
703              ControllerHandle,
704              This->DriverBindingHandle,
705              &gEfiIp4ServiceBindingProtocolGuid,
706              &Private->Ip4Child
707              );
708   if (EFI_ERROR (Status)) {
709     goto ON_ERROR;
710   }
711 
712   Status = gBS->OpenProtocol (
713                   Private->Ip4Child,
714                   &gEfiIp4ProtocolGuid,
715                   (VOID **) &Private->Ip4,
716                   This->DriverBindingHandle,
717                   ControllerHandle,
718                   EFI_OPEN_PROTOCOL_BY_DRIVER
719                   );
720   if (EFI_ERROR (Status)) {
721     goto ON_ERROR;
722   }
723 
724   //
725   // Get max packet size from Ip4 to calculate block size for Tftp later.
726   //
727   Status = Private->Ip4->GetModeData (Private->Ip4, &Ip4ModeData, NULL, NULL);
728   if (EFI_ERROR (Status)) {
729     goto ON_ERROR;
730   }
731 
732   Private->Ip4MaxPacketSize = Ip4ModeData.MaxPacketSize;
733 
734   Private->Ip4Nic = AllocateZeroPool (sizeof (PXEBC_VIRTUAL_NIC));
735   if (Private->Ip4Nic == NULL) {
736     return EFI_OUT_OF_RESOURCES;
737   }
738 
739   Private->Ip4Nic->Private   = Private;
740   Private->Ip4Nic->Signature = PXEBC_VIRTUAL_NIC_SIGNATURE;
741 
742    //
743   // Locate Ip4->Ip4Config2 and store it for set IPv4 Policy.
744   //
745   Status = gBS->HandleProtocol (
746                   ControllerHandle,
747                   &gEfiIp4Config2ProtocolGuid,
748                   (VOID **) &Private->Ip4Config2
749                   );
750   if (EFI_ERROR (Status)) {
751     goto ON_ERROR;
752   }
753 
754   //
755   // Create a device path node for Ipv4 virtual nic, and append it.
756   //
757   ZeroMem (&Ip4Node, sizeof (IPv4_DEVICE_PATH));
758   Ip4Node.Header.Type     = MESSAGING_DEVICE_PATH;
759   Ip4Node.Header.SubType  = MSG_IPv4_DP;
760   Ip4Node.StaticIpAddress = FALSE;
761 
762   SetDevicePathNodeLength (&Ip4Node.Header, sizeof (Ip4Node));
763 
764   Private->Ip4Nic->DevicePath = AppendDevicePathNode (Private->DevicePath, &Ip4Node.Header);
765 
766   if (Private->Ip4Nic->DevicePath == NULL) {
767     Status = EFI_OUT_OF_RESOURCES;
768     goto ON_ERROR;
769   }
770 
771   CopyMem (
772     &Private->Ip4Nic->LoadFile,
773     &gLoadFileProtocolTemplate,
774     sizeof (EFI_LOAD_FILE_PROTOCOL)
775     );
776 
777   //
778   // Create a new handle for IPv4 virtual nic,
779   // and install PxeBaseCode, LoadFile and DevicePath protocols.
780   //
781   Status = gBS->InstallMultipleProtocolInterfaces (
782                   &Private->Ip4Nic->Controller,
783                   &gEfiDevicePathProtocolGuid,
784                   Private->Ip4Nic->DevicePath,
785                   &gEfiLoadFileProtocolGuid,
786                   &Private->Ip4Nic->LoadFile,
787                   &gEfiPxeBaseCodeProtocolGuid,
788                   &Private->PxeBc,
789                   NULL
790                   );
791   if (EFI_ERROR (Status)) {
792     goto ON_ERROR;
793   }
794 
795   if (Private->Snp != NULL) {
796     //
797     // Install SNP protocol on purpose is for some OS loader backward
798     // compatibility consideration.
799     //
800     Status = gBS->InstallProtocolInterface (
801                     &Private->Ip4Nic->Controller,
802                     &gEfiSimpleNetworkProtocolGuid,
803                     EFI_NATIVE_INTERFACE,
804                     Private->Snp
805                     );
806     if (EFI_ERROR (Status)) {
807       goto ON_ERROR;
808     }
809 
810     //
811     // Open SNP on the child handle BY_DRIVER|EXCLUSIVE. It will prevent any additionally
812     // layering to perform the experiment.
813     //
814     Status = gBS->OpenProtocol (
815                     Private->Ip4Nic->Controller,
816                     &gEfiSimpleNetworkProtocolGuid,
817                     (VOID **) &Snp,
818                     This->DriverBindingHandle,
819                     Private->Ip4Nic->Controller,
820                     EFI_OPEN_PROTOCOL_BY_DRIVER|EFI_OPEN_PROTOCOL_EXCLUSIVE
821                     );
822     if (EFI_ERROR (Status)) {
823       goto ON_ERROR;
824     }
825   }
826 
827   //
828   // Open PxeBaseCodePrivate protocol by child to setup a parent-child relationship between
829   // real NIC handle and the virtual IPv4 NIC handle.
830   //
831   Status = gBS->OpenProtocol (
832                   ControllerHandle,
833                   &gEfiCallerIdGuid,
834                   (VOID **) &Id,
835                   This->DriverBindingHandle,
836                   Private->Ip4Nic->Controller,
837                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
838                   );
839   if (EFI_ERROR (Status)) {
840     goto ON_ERROR;
841   }
842 
843   //
844   // Set default configure data for Udp4Read and Ip4 instance.
845   //
846   Mode                            = Private->PxeBc.Mode;
847   Udp4CfgData                     = &Private->Udp4CfgData;
848   Ip4CfgData                      = &Private->Ip4CfgData;
849 
850   Udp4CfgData->AcceptBroadcast    = FALSE;
851   Udp4CfgData->AcceptAnyPort      = TRUE;
852   Udp4CfgData->AllowDuplicatePort = TRUE;
853   Udp4CfgData->TypeOfService      = Mode->ToS;
854   Udp4CfgData->TimeToLive         = Mode->TTL;
855   Udp4CfgData->ReceiveTimeout     = PXEBC_DEFAULT_LIFETIME;
856   Udp4CfgData->TransmitTimeout    = PXEBC_DEFAULT_LIFETIME;
857 
858   Ip4CfgData->AcceptIcmpErrors    = TRUE;
859   Ip4CfgData->DefaultProtocol     = EFI_IP_PROTO_ICMP;
860   Ip4CfgData->TypeOfService       = Mode->ToS;
861   Ip4CfgData->TimeToLive          = Mode->TTL;
862   Ip4CfgData->ReceiveTimeout      = PXEBC_DEFAULT_LIFETIME;
863   Ip4CfgData->TransmitTimeout     = PXEBC_DEFAULT_LIFETIME;
864 
865   return EFI_SUCCESS;
866 
867 ON_ERROR:
868   PxeBcDestroyIp4Children (This, Private);
869   return Status;
870 }
871 
872 
873 /**
874   Create the opened instances based on IPv6.
875 
876   @param[in]  This              Pointer to EFI_DRIVER_BINDING_PROTOCOL.
877   @param[in]  ControllerHandle  Handle of the child to destroy.
878   @param[in]  Private Handle    Pointer to PXEBC_PRIVATE_DATA.
879 
880   @retval EFI_SUCCESS           The instances based on IPv6 were all created successfully.
881   @retval Others                An unexpected error occurred.
882 
883 **/
884 EFI_STATUS
PxeBcCreateIp6Children(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN PXEBC_PRIVATE_DATA * Private)885 PxeBcCreateIp6Children (
886   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
887   IN EFI_HANDLE                   ControllerHandle,
888   IN PXEBC_PRIVATE_DATA           *Private
889   )
890 {
891   EFI_STATUS                      Status;
892   IPv6_DEVICE_PATH                Ip6Node;
893   EFI_UDP6_CONFIG_DATA            *Udp6CfgData;
894   EFI_IP6_CONFIG_DATA             *Ip6CfgData;
895   EFI_IP6_MODE_DATA               Ip6ModeData;
896   PXEBC_PRIVATE_PROTOCOL          *Id;
897   EFI_SIMPLE_NETWORK_PROTOCOL     *Snp;
898   UINTN                           Index;
899 
900   if (Private->Ip6Nic != NULL) {
901     //
902     // Already created before.
903     //
904     return EFI_SUCCESS;
905   }
906 
907   Private->Ip6Nic = AllocateZeroPool (sizeof (PXEBC_VIRTUAL_NIC));
908 
909   if (Private->Ip6Nic == NULL) {
910     return EFI_OUT_OF_RESOURCES;
911   }
912 
913   Private->Ip6Nic->Private   = Private;
914   Private->Ip6Nic->Signature = PXEBC_VIRTUAL_NIC_SIGNATURE;
915 
916   //
917   // Create Dhcp6 child and open Dhcp6 protocol for PxeBc->Dhcp.
918   //
919   Status = NetLibCreateServiceChild (
920              ControllerHandle,
921              This->DriverBindingHandle,
922              &gEfiDhcp6ServiceBindingProtocolGuid,
923              &Private->Dhcp6Child
924              );
925   if (EFI_ERROR (Status)) {
926     goto ON_ERROR;
927   }
928 
929   Status = gBS->OpenProtocol (
930                   Private->Dhcp6Child,
931                   &gEfiDhcp6ProtocolGuid,
932                   (VOID **) &Private->Dhcp6,
933                   This->DriverBindingHandle,
934                   ControllerHandle,
935                   EFI_OPEN_PROTOCOL_BY_DRIVER
936                   );
937   if (EFI_ERROR (Status)) {
938     goto ON_ERROR;
939   }
940 
941   //
942   // Generate a random IAID for the Dhcp6 assigned address.
943   //
944   Private->IaId = NET_RANDOM (NetRandomInitSeed ());
945   if (Private->Snp != NULL) {
946     for (Index = 0; Index < Private->Snp->Mode->HwAddressSize; Index++) {
947       Private->IaId |= (Private->Snp->Mode->CurrentAddress.Addr[Index] << ((Index << 3) & 31));
948     }
949   }
950 
951   //
952   // Create Mtftp6 child and open Mtftp6 protocol for PxeBc->Mtftp.
953   //
954   Status = NetLibCreateServiceChild (
955              ControllerHandle,
956              This->DriverBindingHandle,
957              &gEfiMtftp6ServiceBindingProtocolGuid,
958              &Private->Mtftp6Child
959              );
960   if (EFI_ERROR (Status)) {
961     goto ON_ERROR;
962   }
963 
964   Status = gBS->OpenProtocol (
965                   Private->Mtftp6Child,
966                   &gEfiMtftp6ProtocolGuid,
967                   (VOID **) &Private->Mtftp6,
968                   This->DriverBindingHandle,
969                   ControllerHandle,
970                   EFI_OPEN_PROTOCOL_BY_DRIVER
971                   );
972   if (EFI_ERROR (Status)) {
973     goto ON_ERROR;
974   }
975 
976   //
977   // Create Udp6 child and open Udp6 protocol for PxeBc->UdpRead.
978   //
979   Status = NetLibCreateServiceChild (
980              ControllerHandle,
981              This->DriverBindingHandle,
982              &gEfiUdp6ServiceBindingProtocolGuid,
983              &Private->Udp6ReadChild
984              );
985   if (EFI_ERROR (Status)) {
986     goto ON_ERROR;
987   }
988 
989   Status = gBS->OpenProtocol (
990                   Private->Udp6ReadChild,
991                   &gEfiUdp6ProtocolGuid,
992                   (VOID **) &Private->Udp6Read,
993                   This->DriverBindingHandle,
994                   ControllerHandle,
995                   EFI_OPEN_PROTOCOL_BY_DRIVER
996                   );
997   if (EFI_ERROR (Status)) {
998     goto ON_ERROR;
999   }
1000 
1001   //
1002   // Create Udp6 child and open Udp6 protocol for PxeBc->UdpWrite.
1003   //
1004   Status = NetLibCreateServiceChild (
1005              ControllerHandle,
1006              This->DriverBindingHandle,
1007              &gEfiUdp6ServiceBindingProtocolGuid,
1008              &Private->Udp6WriteChild
1009              );
1010   if (EFI_ERROR (Status)) {
1011     goto ON_ERROR;
1012   }
1013 
1014   Status = gBS->OpenProtocol (
1015                   Private->Udp6WriteChild,
1016                   &gEfiUdp6ProtocolGuid,
1017                   (VOID **) &Private->Udp6Write,
1018                   This->DriverBindingHandle,
1019                   ControllerHandle,
1020                   EFI_OPEN_PROTOCOL_BY_DRIVER
1021                   );
1022   if (EFI_ERROR (Status)) {
1023     goto ON_ERROR;
1024   }
1025 
1026   //
1027   // Create Ip6 child and open Ip6 protocol for background ICMP6 packets.
1028   //
1029   Status = NetLibCreateServiceChild (
1030              ControllerHandle,
1031              This->DriverBindingHandle,
1032              &gEfiIp6ServiceBindingProtocolGuid,
1033              &Private->Ip6Child
1034              );
1035   if (EFI_ERROR (Status)) {
1036     goto ON_ERROR;
1037   }
1038 
1039   Status = gBS->OpenProtocol (
1040                   Private->Ip6Child,
1041                   &gEfiIp6ProtocolGuid,
1042                   (VOID **) &Private->Ip6,
1043                   This->DriverBindingHandle,
1044                   ControllerHandle,
1045                   EFI_OPEN_PROTOCOL_BY_DRIVER
1046                   );
1047   if (EFI_ERROR (Status)) {
1048     goto ON_ERROR;
1049   }
1050 
1051   //
1052   // Get max packet size from Ip6 to calculate block size for Tftp later.
1053   //
1054   Status = Private->Ip6->GetModeData (Private->Ip6, &Ip6ModeData, NULL, NULL);
1055   if (EFI_ERROR (Status)) {
1056     goto ON_ERROR;
1057   }
1058 
1059   Private->Ip6MaxPacketSize = Ip6ModeData.MaxPacketSize;
1060 
1061   if (Ip6ModeData.AddressList != NULL) {
1062     FreePool (Ip6ModeData.AddressList);
1063   }
1064 
1065   if (Ip6ModeData.GroupTable != NULL) {
1066     FreePool (Ip6ModeData.GroupTable);
1067   }
1068 
1069   if (Ip6ModeData.RouteTable != NULL) {
1070     FreePool (Ip6ModeData.RouteTable);
1071   }
1072 
1073   if (Ip6ModeData.NeighborCache != NULL) {
1074     FreePool (Ip6ModeData.NeighborCache);
1075   }
1076 
1077   if (Ip6ModeData.PrefixTable != NULL) {
1078     FreePool (Ip6ModeData.PrefixTable);
1079   }
1080 
1081   if (Ip6ModeData.IcmpTypeList != NULL) {
1082     FreePool (Ip6ModeData.IcmpTypeList);
1083   }
1084 
1085   //
1086   // Locate Ip6->Ip6Config and store it for set IPv6 address.
1087   //
1088   Status = gBS->HandleProtocol (
1089                   ControllerHandle,
1090                   &gEfiIp6ConfigProtocolGuid,
1091                   (VOID **) &Private->Ip6Cfg
1092                   );
1093   if (EFI_ERROR (Status)) {
1094     goto ON_ERROR;
1095   }
1096 
1097   //
1098   // Create a device path node for Ipv6 virtual nic, and append it.
1099   //
1100   ZeroMem (&Ip6Node, sizeof (IPv6_DEVICE_PATH));
1101   Ip6Node.Header.Type     = MESSAGING_DEVICE_PATH;
1102   Ip6Node.Header.SubType  = MSG_IPv6_DP;
1103   Ip6Node.PrefixLength    = IP6_PREFIX_LENGTH;
1104 
1105   SetDevicePathNodeLength (&Ip6Node.Header, sizeof (Ip6Node));
1106 
1107   Private->Ip6Nic->DevicePath = AppendDevicePathNode (Private->DevicePath, &Ip6Node.Header);
1108 
1109   if (Private->Ip6Nic->DevicePath == NULL) {
1110     Status = EFI_OUT_OF_RESOURCES;
1111     goto ON_ERROR;
1112   }
1113 
1114   CopyMem (
1115     &Private->Ip6Nic->LoadFile,
1116     &gLoadFileProtocolTemplate,
1117     sizeof (EFI_LOAD_FILE_PROTOCOL)
1118     );
1119 
1120   //
1121   // Create a new handle for IPv6 virtual nic,
1122   // and install PxeBaseCode, LoadFile and DevicePath protocols.
1123   //
1124   Status = gBS->InstallMultipleProtocolInterfaces (
1125                   &Private->Ip6Nic->Controller,
1126                   &gEfiDevicePathProtocolGuid,
1127                   Private->Ip6Nic->DevicePath,
1128                   &gEfiLoadFileProtocolGuid,
1129                   &Private->Ip6Nic->LoadFile,
1130                   &gEfiPxeBaseCodeProtocolGuid,
1131                   &Private->PxeBc,
1132                   NULL
1133                   );
1134   if (EFI_ERROR (Status)) {
1135     goto ON_ERROR;
1136   }
1137 
1138   if (Private->Snp != NULL) {
1139     //
1140     // Install SNP protocol on purpose is for some OS loader backward
1141     // compatibility consideration.
1142     //
1143     Status = gBS->InstallProtocolInterface (
1144                     &Private->Ip6Nic->Controller,
1145                     &gEfiSimpleNetworkProtocolGuid,
1146                     EFI_NATIVE_INTERFACE,
1147                     Private->Snp
1148                     );
1149     if (EFI_ERROR (Status)) {
1150       goto ON_ERROR;
1151     }
1152 
1153     //
1154     // Open SNP on the child handle BY_DRIVER|EXCLUSIVE. It will prevent any additionally
1155     // layering to perform the experiment.
1156     //
1157     Status = gBS->OpenProtocol (
1158                     Private->Ip6Nic->Controller,
1159                     &gEfiSimpleNetworkProtocolGuid,
1160                     (VOID **) &Snp,
1161                     This->DriverBindingHandle,
1162                     Private->Ip6Nic->Controller,
1163                     EFI_OPEN_PROTOCOL_BY_DRIVER|EFI_OPEN_PROTOCOL_EXCLUSIVE
1164                     );
1165     if (EFI_ERROR (Status)) {
1166       goto ON_ERROR;
1167     }
1168   }
1169 
1170   //
1171   // Open PxeBaseCodePrivate protocol by child to setup a parent-child relationship between
1172   // real NIC handle and the virtual IPv6 NIC handle.
1173   //
1174   Status = gBS->OpenProtocol (
1175                   ControllerHandle,
1176                   &gEfiCallerIdGuid,
1177                   (VOID **) &Id,
1178                   This->DriverBindingHandle,
1179                   Private->Ip6Nic->Controller,
1180                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1181                   );
1182   if (EFI_ERROR (Status)) {
1183     goto ON_ERROR;
1184   }
1185 
1186   //
1187   // Set IPv6 avaiable flag and set default configure data for
1188   // Udp6Read and Ip6 instance.
1189   //
1190   Status = PxeBcCheckIpv6Support (ControllerHandle, Private, &Private->Mode.Ipv6Available);
1191   if (EFI_ERROR (Status)) {
1192     //
1193     // Fail to get the data whether UNDI supports IPv6. Set default value.
1194     //
1195     Private->Mode.Ipv6Available   = TRUE;
1196   }
1197 
1198   if (!Private->Mode.Ipv6Available) {
1199     goto ON_ERROR;
1200   }
1201 
1202   Udp6CfgData                     = &Private->Udp6CfgData;
1203   Ip6CfgData                      = &Private->Ip6CfgData;
1204 
1205   Udp6CfgData->AcceptAnyPort      = TRUE;
1206   Udp6CfgData->AllowDuplicatePort = TRUE;
1207   Udp6CfgData->HopLimit           = PXEBC_DEFAULT_HOPLIMIT;
1208   Udp6CfgData->ReceiveTimeout     = PXEBC_DEFAULT_LIFETIME;
1209   Udp6CfgData->TransmitTimeout    = PXEBC_DEFAULT_LIFETIME;
1210 
1211   Ip6CfgData->AcceptIcmpErrors    = TRUE;
1212   Ip6CfgData->DefaultProtocol     = IP6_ICMP;
1213   Ip6CfgData->HopLimit            = PXEBC_DEFAULT_HOPLIMIT;
1214   Ip6CfgData->ReceiveTimeout      = PXEBC_DEFAULT_LIFETIME;
1215   Ip6CfgData->TransmitTimeout     = PXEBC_DEFAULT_LIFETIME;
1216 
1217   return EFI_SUCCESS;
1218 
1219 ON_ERROR:
1220   PxeBcDestroyIp6Children (This, Private);
1221   return Status;
1222 }
1223 
1224 
1225 /**
1226   The entry point for UefiPxeBc driver that installs the driver
1227   binding and component name protocol on its image.
1228 
1229   @param[in]  ImageHandle          The Image handle of the driver.
1230   @param[in]  SystemTable          The system table.
1231 
1232   @return EFI_SUCCESS
1233   @return Others
1234 
1235 **/
1236 EFI_STATUS
1237 EFIAPI
PxeBcDriverEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)1238 PxeBcDriverEntryPoint (
1239   IN EFI_HANDLE             ImageHandle,
1240   IN EFI_SYSTEM_TABLE       *SystemTable
1241   )
1242 {
1243   EFI_STATUS  Status;
1244 
1245   if ((PcdGet8(PcdIPv4PXESupport) == PXE_DISABLED) && (PcdGet8(PcdIPv6PXESupport) == PXE_DISABLED)) {
1246     return EFI_UNSUPPORTED;
1247   }
1248 
1249   Status = EfiLibInstallDriverBindingComponentName2 (
1250              ImageHandle,
1251              SystemTable,
1252              &gPxeBcIp4DriverBinding,
1253              ImageHandle,
1254              &gPxeBcComponentName,
1255              &gPxeBcComponentName2
1256              );
1257   if (EFI_ERROR (Status)) {
1258     return Status;
1259   }
1260 
1261   Status = EfiLibInstallDriverBindingComponentName2 (
1262              ImageHandle,
1263              SystemTable,
1264              &gPxeBcIp6DriverBinding,
1265              NULL,
1266              &gPxeBcComponentName,
1267              &gPxeBcComponentName2
1268              );
1269   if (EFI_ERROR (Status)) {
1270     EfiLibUninstallDriverBindingComponentName2 (
1271       &gPxeBcIp4DriverBinding,
1272       &gPxeBcComponentName,
1273       &gPxeBcComponentName2
1274       );
1275   }
1276 
1277   return Status;
1278 }
1279 
1280 /**
1281   Test to see if this driver supports ControllerHandle. This is the worker function for
1282   PxeBcIp4(6)DriverBindingSupported.
1283 
1284   @param[in]  This                The pointer to the driver binding protocol.
1285   @param[in]  ControllerHandle    The handle of device to be tested.
1286   @param[in]  RemainingDevicePath Optional parameter used to pick a specific child
1287                                   device to be started.
1288   @param[in]  IpVersion           IP_VERSION_4 or IP_VERSION_6.
1289 
1290   @retval EFI_SUCCESS         This driver supports this device.
1291   @retval EFI_UNSUPPORTED     This driver does not support this device.
1292 
1293 **/
1294 EFI_STATUS
1295 EFIAPI
PxeBcSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL,IN UINT8 IpVersion)1296 PxeBcSupported (
1297   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
1298   IN EFI_HANDLE                   ControllerHandle,
1299   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL,
1300   IN UINT8                        IpVersion
1301   )
1302 {
1303   EFI_STATUS                      Status;
1304   EFI_GUID                        *DhcpServiceBindingGuid;
1305   EFI_GUID                        *MtftpServiceBindingGuid;
1306 
1307   if (IpVersion == IP_VERSION_4) {
1308     if (PcdGet8(PcdIPv4PXESupport) == PXE_DISABLED) {
1309       return EFI_UNSUPPORTED;
1310     }
1311     DhcpServiceBindingGuid  = &gEfiDhcp4ServiceBindingProtocolGuid;
1312     MtftpServiceBindingGuid = &gEfiMtftp4ServiceBindingProtocolGuid;
1313   } else {
1314     if (PcdGet8(PcdIPv6PXESupport) == PXE_DISABLED) {
1315       return EFI_UNSUPPORTED;
1316     }
1317     DhcpServiceBindingGuid  = &gEfiDhcp6ServiceBindingProtocolGuid;
1318     MtftpServiceBindingGuid = &gEfiMtftp6ServiceBindingProtocolGuid;
1319   }
1320 
1321   //
1322   // Try to open the Mtftp and Dhcp protocol to test whether IP stack is ready.
1323   //
1324   Status = gBS->OpenProtocol (
1325                      ControllerHandle,
1326                      DhcpServiceBindingGuid,
1327                      NULL,
1328                      This->DriverBindingHandle,
1329                      ControllerHandle,
1330                      EFI_OPEN_PROTOCOL_TEST_PROTOCOL
1331                      );
1332   if (!EFI_ERROR (Status)) {
1333     Status = gBS->OpenProtocol (
1334                        ControllerHandle,
1335                        MtftpServiceBindingGuid,
1336                        NULL,
1337                        This->DriverBindingHandle,
1338                        ControllerHandle,
1339                        EFI_OPEN_PROTOCOL_TEST_PROTOCOL
1340                        );
1341   }
1342 
1343   //
1344   // It's unsupported case if IP stack are not ready.
1345   //
1346   if (EFI_ERROR (Status)) {
1347     return EFI_UNSUPPORTED;
1348   }
1349 
1350   return EFI_SUCCESS;
1351 }
1352 
1353 /**
1354   Start this driver on ControllerHandle. This is the worker function for
1355   PxeBcIp4(6)DriverBindingStart.
1356 
1357   @param[in]  This                 The pointer to the driver binding protocol.
1358   @param[in]  ControllerHandle     The handle of device to be started.
1359   @param[in]  RemainingDevicePath  Optional parameter used to pick a specific child
1360                                    device to be started.
1361   @param[in]  IpVersion            IP_VERSION_4 or IP_VERSION_6.
1362 
1363 
1364   @retval EFI_SUCCESS          This driver is installed to ControllerHandle.
1365   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle.
1366   @retval other                This driver does not support this device.
1367 
1368 **/
1369 EFI_STATUS
1370 EFIAPI
PxeBcStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL,IN UINT8 IpVersion)1371 PxeBcStart (
1372   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
1373   IN EFI_HANDLE                   ControllerHandle,
1374   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL,
1375   IN UINT8                        IpVersion
1376   )
1377 {
1378   PXEBC_PRIVATE_DATA              *Private;
1379   EFI_STATUS                      Status;
1380   PXEBC_PRIVATE_PROTOCOL          *Id;
1381   BOOLEAN                         FirstStart;
1382 
1383   FirstStart = FALSE;
1384   Status = gBS->OpenProtocol (
1385                   ControllerHandle,
1386                   &gEfiCallerIdGuid,
1387                   (VOID **) &Id,
1388                   This->DriverBindingHandle,
1389                   ControllerHandle,
1390                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
1391                   );
1392   if (!EFI_ERROR (Status)) {
1393     //
1394     // Skip the initialization if the driver has been started already.
1395     //
1396     Private = PXEBC_PRIVATE_DATA_FROM_ID (Id);
1397   } else {
1398     FirstStart = TRUE;
1399     //
1400     // If the driver has not been started yet, it should do initialization.
1401     //
1402     Private = AllocateZeroPool (sizeof (PXEBC_PRIVATE_DATA));
1403     if (Private == NULL) {
1404       return EFI_OUT_OF_RESOURCES;
1405     }
1406 
1407     CopyMem (
1408       &Private->PxeBc,
1409       &gPxeBcProtocolTemplate,
1410       sizeof (EFI_PXE_BASE_CODE_PROTOCOL)
1411       );
1412 
1413     Private->Signature          = PXEBC_PRIVATE_DATA_SIGNATURE;
1414     Private->Controller         = ControllerHandle;
1415     Private->Image              = This->ImageHandle;
1416     Private->PxeBc.Mode         = &Private->Mode;
1417     Private->Mode.Ipv6Supported = TRUE;
1418     Private->Mode.AutoArp       = TRUE;
1419     Private->Mode.TTL           = DEFAULT_TTL;
1420     Private->Mode.ToS           = DEFAULT_ToS;
1421 
1422     //
1423     // Open device path to prepare for appending virtual NIC node.
1424     //
1425     Status = gBS->OpenProtocol (
1426                     ControllerHandle,
1427                     &gEfiDevicePathProtocolGuid,
1428                     (VOID **) &Private->DevicePath,
1429                     This->DriverBindingHandle,
1430                     ControllerHandle,
1431                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
1432                     );
1433 
1434     if (EFI_ERROR (Status)) {
1435       goto ON_ERROR;
1436     }
1437 
1438     //
1439     // Get the NII interface if it exists, it's not required.
1440     //
1441     Status = gBS->OpenProtocol (
1442                     ControllerHandle,
1443                     &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
1444                     (VOID **) &Private->Nii,
1445                     This->DriverBindingHandle,
1446                     ControllerHandle,
1447                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
1448                     );
1449     if (EFI_ERROR (Status)) {
1450       Private->Nii = NULL;
1451     }
1452 
1453     //
1454     // Install PxeBaseCodePrivate protocol onto the real NIC handler.
1455     // PxeBaseCodePrivate protocol is only used to keep the relationship between
1456     // NIC handle and virtual child handles.
1457     // gEfiCallerIdGuid will be used as its protocol guid.
1458     //
1459     Status = gBS->InstallProtocolInterface (
1460                     &ControllerHandle,
1461                     &gEfiCallerIdGuid,
1462                     EFI_NATIVE_INTERFACE,
1463                     &Private->Id
1464                     );
1465     if (EFI_ERROR (Status)) {
1466       goto ON_ERROR;
1467     }
1468 
1469     //
1470     // Try to locate SNP protocol.
1471     //
1472     NetLibGetSnpHandle(ControllerHandle, &Private->Snp);
1473   }
1474 
1475   if (IpVersion == IP_VERSION_4) {
1476     //
1477     // Try to create virtual NIC handle for IPv4.
1478     //
1479     Status = PxeBcCreateIp4Children (This, ControllerHandle, Private);
1480   } else {
1481     //
1482     // Try to create virtual NIC handle for IPv6.
1483     //
1484     Status = PxeBcCreateIp6Children (This, ControllerHandle, Private);
1485   }
1486   if (EFI_ERROR (Status)) {
1487     //
1488     // Failed to start PXE driver if IPv4 and IPv6 stack are both not available.
1489     //
1490     Status = EFI_DEVICE_ERROR;
1491     goto ON_ERROR;
1492   }
1493 
1494   return EFI_SUCCESS;
1495 
1496 ON_ERROR:
1497   if (FirstStart) {
1498     gBS->UninstallProtocolInterface (
1499            ControllerHandle,
1500            &gEfiCallerIdGuid,
1501            &Private->Id
1502            );
1503   }
1504 
1505   if (IpVersion == IP_VERSION_4) {
1506     PxeBcDestroyIp4Children (This, Private);
1507   } else {
1508     PxeBcDestroyIp6Children (This, Private);
1509   }
1510 
1511   if (FirstStart && Private != NULL) {
1512     FreePool (Private);
1513   }
1514 
1515   return Status;
1516 }
1517 
1518 
1519 /**
1520   Stop this driver on ControllerHandle. This is the worker function for
1521   PxeBcIp4(6)DriverBindingStop.
1522 
1523   @param[in]  This              Protocol instance pointer.
1524   @param[in]  ControllerHandle  Handle of device to stop driver on.
1525   @param[in]  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
1526                                 children is zero stop the entire bus driver.
1527   @param[in]  ChildHandleBuffer List of Child Handles to Stop.
1528   @param[in]  IpVersion         IP_VERSION_4 or IP_VERSION_6.
1529 
1530   @retval EFI_SUCCESS           This driver was removed ControllerHandle.
1531   @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.
1532   @retval Others                This driver was not removed from this device
1533 
1534 **/
1535 EFI_STATUS
1536 EFIAPI
PxeBcStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer,IN UINT8 IpVersion)1537 PxeBcStop (
1538   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
1539   IN EFI_HANDLE                   ControllerHandle,
1540   IN UINTN                        NumberOfChildren,
1541   IN EFI_HANDLE                   *ChildHandleBuffer,
1542   IN UINT8                        IpVersion
1543   )
1544 {
1545   PXEBC_PRIVATE_DATA              *Private;
1546   PXEBC_VIRTUAL_NIC               *VirtualNic;
1547   EFI_LOAD_FILE_PROTOCOL          *LoadFile;
1548   EFI_STATUS                      Status;
1549   EFI_HANDLE                      NicHandle;
1550   PXEBC_PRIVATE_PROTOCOL          *Id;
1551 
1552   Private    = NULL;
1553   NicHandle  = NULL;
1554   VirtualNic = NULL;
1555   LoadFile   = NULL;
1556   Id         = NULL;
1557 
1558   Status = gBS->OpenProtocol (
1559                   ControllerHandle,
1560                   &gEfiLoadFileProtocolGuid,
1561                   (VOID **) &LoadFile,
1562                   This->DriverBindingHandle,
1563                   ControllerHandle,
1564                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
1565                   );
1566   if (EFI_ERROR (Status)) {
1567     //
1568     // Get the Nic handle by any pass-over service child handle.
1569     //
1570     if (IpVersion == IP_VERSION_4) {
1571       NicHandle = PxeBcGetNicByIp4Children (ControllerHandle);
1572     } else {
1573       NicHandle = PxeBcGetNicByIp6Children (ControllerHandle);
1574     }
1575     if (NicHandle == NULL) {
1576       return EFI_SUCCESS;
1577     }
1578 
1579     //
1580     // Try to retrieve the private data by PxeBcPrivate protocol.
1581     //
1582     Status = gBS->OpenProtocol (
1583                     NicHandle,
1584                     &gEfiCallerIdGuid,
1585                     (VOID **) &Id,
1586                     This->DriverBindingHandle,
1587                     ControllerHandle,
1588                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
1589                     );
1590     if (EFI_ERROR (Status)) {
1591       return Status;
1592     }
1593     Private = PXEBC_PRIVATE_DATA_FROM_ID (Id);
1594 
1595   } else {
1596     //
1597     // It's a virtual handle with LoadFileProtocol.
1598     //
1599     Status = gBS->OpenProtocol (
1600                     ControllerHandle,
1601                     &gEfiLoadFileProtocolGuid,
1602                     (VOID **) &LoadFile,
1603                     This->DriverBindingHandle,
1604                     ControllerHandle,
1605                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
1606                     );
1607     if (EFI_ERROR (Status)) {
1608       return Status;
1609     }
1610 
1611     VirtualNic = PXEBC_VIRTUAL_NIC_FROM_LOADFILE (LoadFile);
1612     Private    = VirtualNic->Private;
1613     NicHandle  = Private->Controller;
1614   }
1615 
1616   //
1617   // Stop functionality of PXE Base Code protocol
1618   //
1619   Status = Private->PxeBc.Stop (&Private->PxeBc);
1620   if (Status != EFI_SUCCESS && Status != EFI_NOT_STARTED) {
1621     return Status;
1622   }
1623 
1624 
1625   if (Private->Ip4Nic != NULL && IpVersion == IP_VERSION_4) {
1626     PxeBcDestroyIp4Children (This, Private);
1627   }
1628 
1629   if (Private->Ip6Nic != NULL && IpVersion == IP_VERSION_6) {
1630     PxeBcDestroyIp6Children (This, Private);
1631   }
1632 
1633   if (Private->Ip4Nic == NULL && Private->Ip6Nic == NULL) {
1634     gBS->UninstallProtocolInterface (
1635            NicHandle,
1636            &gEfiCallerIdGuid,
1637            &Private->Id
1638            );
1639     FreePool (Private);
1640   }
1641 
1642   return EFI_SUCCESS;
1643 }
1644 
1645 /**
1646   Test to see if this driver supports ControllerHandle. This service
1647   is called by the EFI boot service ConnectController(). In
1648   order to make drivers as small as possible, there are a few calling
1649   restrictions for this service. ConnectController() must
1650   follow these calling restrictions. If any other agent wishes to call
1651   Supported() it must also follow these calling restrictions.
1652 
1653   @param[in]  This                The pointer to the driver binding protocol.
1654   @param[in]  ControllerHandle    The handle of device to be tested.
1655   @param[in]  RemainingDevicePath Optional parameter used to pick a specific child
1656                                   device to be started.
1657 
1658   @retval EFI_SUCCESS         This driver supports this device.
1659   @retval EFI_UNSUPPORTED     This driver does not support this device.
1660 
1661 **/
1662 EFI_STATUS
1663 EFIAPI
PxeBcIp4DriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)1664 PxeBcIp4DriverBindingSupported (
1665   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
1666   IN EFI_HANDLE                   ControllerHandle,
1667   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
1668   )
1669 {
1670   return PxeBcSupported (
1671            This,
1672            ControllerHandle,
1673            RemainingDevicePath,
1674            IP_VERSION_4
1675            );
1676 }
1677 
1678 /**
1679   Start this driver on ControllerHandle. This service is called by the
1680   EFI boot service ConnectController(). In order to make
1681   drivers as small as possible, there are a few calling restrictions for
1682   this service. ConnectController() must follow these
1683   calling restrictions. If any other agent wishes to call Start() it
1684   must also follow these calling restrictions.
1685 
1686   @param[in]  This                 The pointer to the driver binding protocol.
1687   @param[in]  ControllerHandle     The handle of device to be started.
1688   @param[in]  RemainingDevicePath  Optional parameter used to pick a specific child
1689                                    device to be started.
1690 
1691   @retval EFI_SUCCESS          This driver is installed to ControllerHandle.
1692   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle.
1693   @retval other                This driver does not support this device.
1694 
1695 **/
1696 EFI_STATUS
1697 EFIAPI
PxeBcIp4DriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)1698 PxeBcIp4DriverBindingStart (
1699   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
1700   IN EFI_HANDLE                   ControllerHandle,
1701   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
1702   )
1703 {
1704   return PxeBcStart (
1705            This,
1706            ControllerHandle,
1707            RemainingDevicePath,
1708            IP_VERSION_4
1709            );
1710 }
1711 
1712 /**
1713   Stop this driver on ControllerHandle. This service is called by the
1714   EFI boot service DisconnectController(). In order to
1715   make drivers as small as possible, there are a few calling
1716   restrictions for this service. DisconnectController()
1717   must follow these calling restrictions. If any other agent wishes
1718   to call Stop() it must also follow these calling restrictions.
1719 
1720   @param[in]  This              Protocol instance pointer.
1721   @param[in]  ControllerHandle  Handle of device to stop driver on
1722   @param[in]  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
1723                                 children is zero stop the entire bus driver.
1724   @param[in]  ChildHandleBuffer List of Child Handles to Stop.
1725 
1726   @retval EFI_SUCCESS           This driver is removed ControllerHandle
1727   @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.
1728   @retval Others                This driver was not removed from this device.
1729 
1730 **/
1731 EFI_STATUS
1732 EFIAPI
PxeBcIp4DriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)1733 PxeBcIp4DriverBindingStop (
1734   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
1735   IN EFI_HANDLE                   ControllerHandle,
1736   IN UINTN                        NumberOfChildren,
1737   IN EFI_HANDLE                   *ChildHandleBuffer
1738   )
1739 {
1740   return PxeBcStop (
1741            This,
1742            ControllerHandle,
1743            NumberOfChildren,
1744            ChildHandleBuffer,
1745            IP_VERSION_4
1746            );
1747 }
1748 
1749 /**
1750   Test to see if this driver supports ControllerHandle. This service
1751   is called by the EFI boot service ConnectController(). In
1752   order to make drivers as small as possible, there are a few calling
1753   restrictions for this service. ConnectController() must
1754   follow these calling restrictions. If any other agent wishes to call
1755   Supported() it must also follow these calling restrictions.
1756 
1757   @param[in]  This                The pointer to the driver binding protocol.
1758   @param[in]  ControllerHandle    The handle of device to be tested.
1759   @param[in]  RemainingDevicePath Optional parameter use to pick a specific child
1760                                   device to be started.
1761 
1762   @retval EFI_SUCCESS         This driver supports this device.
1763   @retval EFI_UNSUPPORTED     This driver does not support this device.
1764 
1765 **/
1766 EFI_STATUS
1767 EFIAPI
PxeBcIp6DriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)1768 PxeBcIp6DriverBindingSupported (
1769   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
1770   IN EFI_HANDLE                   ControllerHandle,
1771   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
1772   )
1773 {
1774   return PxeBcSupported (
1775            This,
1776            ControllerHandle,
1777            RemainingDevicePath,
1778            IP_VERSION_6
1779            );
1780 }
1781 
1782 /**
1783   Start this driver on ControllerHandle. This service is called by the
1784   EFI boot service ConnectController(). In order to make
1785   drivers as small as possible, there are a few calling restrictions for
1786   this service. ConnectController() must follow these
1787   calling restrictions. If any other agent wishes to call Start() it
1788   must also follow these calling restrictions.
1789 
1790   @param[in]  This                 The pointer to the driver binding protocol.
1791   @param[in]  ControllerHandle     The handle of device to be started.
1792   @param[in]  RemainingDevicePath  Optional parameter used to pick a specific child
1793                                    device to be started.
1794 
1795   @retval EFI_SUCCESS          This driver is installed to ControllerHandle.
1796   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle.
1797   @retval other                This driver does not support this device.
1798 
1799 **/
1800 EFI_STATUS
1801 EFIAPI
PxeBcIp6DriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)1802 PxeBcIp6DriverBindingStart (
1803   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
1804   IN EFI_HANDLE                   ControllerHandle,
1805   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
1806   )
1807 {
1808   return PxeBcStart (
1809            This,
1810            ControllerHandle,
1811            RemainingDevicePath,
1812            IP_VERSION_6
1813            );
1814 }
1815 
1816 /**
1817   Stop this driver on ControllerHandle. This service is called by the
1818   EFI boot service DisconnectController(). In order to
1819   make drivers as small as possible, there are a few calling
1820   restrictions for this service. DisconnectController()
1821   must follow these calling restrictions. If any other agent wishes
1822   to call Stop() it must also follow these calling restrictions.
1823 
1824   @param[in]  This              Protocol instance pointer.
1825   @param[in]  ControllerHandle  Handle of device to stop driver on
1826   @param[in]  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
1827                                 children is zero stop the entire bus driver.
1828   @param[in]  ChildHandleBuffer List of Child Handles to Stop.
1829 
1830   @retval EFI_SUCCESS           This driver is removed ControllerHandle
1831   @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.
1832   @retval Others                This driver was not removed from this device.
1833 
1834 **/
1835 EFI_STATUS
1836 EFIAPI
PxeBcIp6DriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)1837 PxeBcIp6DriverBindingStop (
1838   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
1839   IN EFI_HANDLE                   ControllerHandle,
1840   IN UINTN                        NumberOfChildren,
1841   IN EFI_HANDLE                   *ChildHandleBuffer
1842   )
1843 {
1844   return PxeBcStop (
1845            This,
1846            ControllerHandle,
1847            NumberOfChildren,
1848            ChildHandleBuffer,
1849            IP_VERSION_6
1850            );
1851 }
1852