2 Driver Binding functions implementationfor for UefiPxeBc Driver.
4 Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "PxeBcImpl.h"
19 EFI_DRIVER_BINDING_PROTOCOL gPxeBcDriverBinding
= {
20 PxeBcDriverBindingSupported
,
21 PxeBcDriverBindingStart
,
22 PxeBcDriverBindingStop
,
29 // PXE_PRIVATE_GUID is only used to keep the relationship between
30 // NIC handle and virtual child handles.
32 EFI_GUID mPxeBcPrivateGuid
= PXEBC_PRIVATE_GUID
;
37 Get the Nic handle using any child handle in the IPv4 stack.
39 @param[in] ControllerHandle Pointer to child handle over IPv4.
41 @return NicHandle The pointer to the Nic handle.
45 PxeBcGetNicByIp4Children (
46 IN EFI_HANDLE ControllerHandle
51 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiArpProtocolGuid
);
52 if (NicHandle
== NULL
) {
53 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiIp4ProtocolGuid
);
54 if (NicHandle
== NULL
) {
55 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiUdp4ProtocolGuid
);
56 if (NicHandle
== NULL
) {
57 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiDhcp4ProtocolGuid
);
58 if (NicHandle
== NULL
) {
59 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiMtftp4ProtocolGuid
);
60 if (NicHandle
== NULL
) {
73 Get the Nic handle using any child handle in the IPv6 stack.
75 @param[in] ControllerHandle Pointer to child handle over IPv6.
77 @return NicHandle The pointer to the Nic handle.
81 PxeBcGetNicByIp6Children (
82 IN EFI_HANDLE ControllerHandle
87 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiIp6ProtocolGuid
);
88 if (NicHandle
== NULL
) {
89 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiUdp6ProtocolGuid
);
90 if (NicHandle
== NULL
) {
91 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiDhcp6ProtocolGuid
);
92 if (NicHandle
== NULL
) {
93 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiMtftp6ProtocolGuid
);
94 if (NicHandle
== NULL
) {
106 Destroy the opened instances based on IPv4.
108 @param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
109 @param[in] Private Pointer to PXEBC_PRIVATE_DATA.
113 PxeBcDestroyIp4Children (
114 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
115 IN PXEBC_PRIVATE_DATA
*Private
118 ASSERT(Private
!= NULL
);
120 if (Private
->ArpChild
!= NULL
) {
122 // Close Arp for PxeBc->Arp and destroy the instance.
126 &gEfiArpProtocolGuid
,
127 This
->DriverBindingHandle
,
131 NetLibDestroyServiceChild (
133 This
->DriverBindingHandle
,
134 &gEfiArpServiceBindingProtocolGuid
,
139 if (Private
->Ip4Child
!= NULL
) {
141 // Close Ip4 for background ICMP error message and destroy the instance.
145 &gEfiIp4ProtocolGuid
,
146 This
->DriverBindingHandle
,
150 NetLibDestroyServiceChild (
152 This
->DriverBindingHandle
,
153 &gEfiIp4ServiceBindingProtocolGuid
,
158 if (Private
->Udp4WriteChild
!= NULL
) {
160 // Close Udp4 for PxeBc->UdpWrite and destroy the instance.
163 Private
->Udp4WriteChild
,
164 &gEfiUdp4ProtocolGuid
,
165 This
->DriverBindingHandle
,
169 NetLibDestroyServiceChild (
171 This
->DriverBindingHandle
,
172 &gEfiUdp4ServiceBindingProtocolGuid
,
173 Private
->Udp4WriteChild
177 if (Private
->Udp4ReadChild
!= NULL
) {
179 // Close Udp4 for PxeBc->UdpRead and destroy the instance.
182 Private
->Udp4ReadChild
,
183 &gEfiUdp4ProtocolGuid
,
184 This
->DriverBindingHandle
,
188 NetLibDestroyServiceChild (
190 This
->DriverBindingHandle
,
191 &gEfiUdp4ServiceBindingProtocolGuid
,
192 Private
->Udp4ReadChild
196 if (Private
->Mtftp4Child
!= NULL
) {
198 // Close Mtftp4 for PxeBc->Mtftp4 and destroy the instance.
201 Private
->Mtftp4Child
,
202 &gEfiMtftp4ProtocolGuid
,
203 This
->DriverBindingHandle
,
207 NetLibDestroyServiceChild (
209 This
->DriverBindingHandle
,
210 &gEfiMtftp4ServiceBindingProtocolGuid
,
215 if (Private
->Dhcp4Child
!= NULL
) {
217 // Close Dhcp4 for PxeBc->Dhcp4 and destroy the instance.
221 &gEfiDhcp4ProtocolGuid
,
222 This
->DriverBindingHandle
,
226 NetLibDestroyServiceChild (
228 This
->DriverBindingHandle
,
229 &gEfiDhcp4ServiceBindingProtocolGuid
,
234 if (Private
->Ip4Nic
!= NULL
) {
236 // Close PxeBcPrivate from the parent Nic handle and destroy the virtual handle.
241 This
->DriverBindingHandle
,
242 Private
->Ip4Nic
->Controller
245 gBS
->UninstallMultipleProtocolInterfaces (
246 Private
->Ip4Nic
->Controller
,
247 &gEfiDevicePathProtocolGuid
,
248 Private
->Ip4Nic
->DevicePath
,
249 &gEfiLoadFileProtocolGuid
,
250 &Private
->Ip4Nic
->LoadFile
,
251 &gEfiPxeBaseCodeProtocolGuid
,
256 if (Private
->Snp
!= NULL
) {
258 // Close SNP from the child virtual handle
261 Private
->Ip4Nic
->Controller
,
262 &gEfiSimpleNetworkProtocolGuid
,
263 This
->DriverBindingHandle
,
264 Private
->Ip4Nic
->Controller
267 gBS
->UninstallProtocolInterface (
268 Private
->Ip4Nic
->Controller
,
269 &gEfiSimpleNetworkProtocolGuid
,
273 FreePool (Private
->Ip4Nic
);
276 Private
->ArpChild
= NULL
;
277 Private
->Ip4Child
= NULL
;
278 Private
->Udp4WriteChild
= NULL
;
279 Private
->Udp4ReadChild
= NULL
;
280 Private
->Mtftp4Child
= NULL
;
281 Private
->Dhcp4Child
= NULL
;
282 Private
->Ip4Nic
= NULL
;
287 Destroy the opened instances based on IPv6.
289 @param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
290 @param[in] Private Pointer to PXEBC_PRIVATE_DATA.
294 PxeBcDestroyIp6Children (
295 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
296 IN PXEBC_PRIVATE_DATA
*Private
299 ASSERT(Private
!= NULL
);
301 if (Private
->Ip6Child
!= NULL
) {
303 // Close Ip6 for Ip6->Ip6Config and destroy the instance.
307 &gEfiIp6ProtocolGuid
,
308 This
->DriverBindingHandle
,
312 NetLibDestroyServiceChild (
314 This
->DriverBindingHandle
,
315 &gEfiIp6ServiceBindingProtocolGuid
,
320 if (Private
->Udp6WriteChild
!= NULL
) {
322 // Close Udp6 for PxeBc->UdpWrite and destroy the instance.
325 Private
->Udp6WriteChild
,
326 &gEfiUdp6ProtocolGuid
,
327 This
->DriverBindingHandle
,
330 NetLibDestroyServiceChild (
332 This
->DriverBindingHandle
,
333 &gEfiUdp6ServiceBindingProtocolGuid
,
334 Private
->Udp6WriteChild
338 if (Private
->Udp6ReadChild
!= NULL
) {
340 // Close Udp6 for PxeBc->UdpRead and destroy the instance.
343 Private
->Udp6ReadChild
,
344 &gEfiUdp6ProtocolGuid
,
345 This
->DriverBindingHandle
,
348 NetLibDestroyServiceChild (
350 This
->DriverBindingHandle
,
351 &gEfiUdp6ServiceBindingProtocolGuid
,
352 Private
->Udp6ReadChild
356 if (Private
->Mtftp6Child
!= NULL
) {
358 // Close Mtftp6 for PxeBc->Mtftp and destroy the instance.
361 Private
->Mtftp6Child
,
362 &gEfiMtftp6ProtocolGuid
,
363 This
->DriverBindingHandle
,
367 NetLibDestroyServiceChild (
369 This
->DriverBindingHandle
,
370 &gEfiMtftp6ServiceBindingProtocolGuid
,
375 if (Private
->Dhcp6Child
!= NULL
) {
377 // Close Dhcp6 for PxeBc->Dhcp and destroy the instance.
381 &gEfiDhcp6ProtocolGuid
,
382 This
->DriverBindingHandle
,
386 NetLibDestroyServiceChild (
388 This
->DriverBindingHandle
,
389 &gEfiDhcp6ServiceBindingProtocolGuid
,
394 if (Private
->Ip6Nic
!= NULL
) {
396 // Close PxeBcPrivate from the parent Nic handle and destroy the virtual handle.
401 This
->DriverBindingHandle
,
402 Private
->Ip6Nic
->Controller
405 gBS
->UninstallMultipleProtocolInterfaces (
406 Private
->Ip6Nic
->Controller
,
407 &gEfiDevicePathProtocolGuid
,
408 Private
->Ip6Nic
->DevicePath
,
409 &gEfiLoadFileProtocolGuid
,
410 &Private
->Ip6Nic
->LoadFile
,
411 &gEfiPxeBaseCodeProtocolGuid
,
415 if (Private
->Snp
!= NULL
) {
417 // Close SNP from the child virtual handle
420 Private
->Ip6Nic
->Controller
,
421 &gEfiSimpleNetworkProtocolGuid
,
422 This
->DriverBindingHandle
,
423 Private
->Ip6Nic
->Controller
425 gBS
->UninstallProtocolInterface (
426 Private
->Ip6Nic
->Controller
,
427 &gEfiSimpleNetworkProtocolGuid
,
431 FreePool (Private
->Ip6Nic
);
434 Private
->Ip6Child
= NULL
;
435 Private
->Udp6WriteChild
= NULL
;
436 Private
->Udp6ReadChild
= NULL
;
437 Private
->Mtftp6Child
= NULL
;
438 Private
->Dhcp6Child
= NULL
;
439 Private
->Ip6Nic
= NULL
;
440 Private
->Mode
.Ipv6Available
= FALSE
;
445 Create the opened instances based on IPv4.
447 @param[in] This Pointer to EFI_DRIVER_BINDING_PROTOCOL.
448 @param[in] ControllerHandle Handle of the child to destroy.
449 @param[in] Private Handle Pointer to PXEBC_PRIVATE_DATA.
451 @retval EFI_SUCCESS The instances based on IPv4 were all created successfully.
452 @retval Others An unexpected error occurred.
456 PxeBcCreateIp4Children (
457 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
458 IN EFI_HANDLE ControllerHandle
,
459 IN PXEBC_PRIVATE_DATA
*Private
463 IPv4_DEVICE_PATH Ip4Node
;
464 EFI_PXE_BASE_CODE_MODE
*Mode
;
465 EFI_UDP4_CONFIG_DATA
*Udp4CfgData
;
466 EFI_IP4_CONFIG_DATA
*Ip4CfgData
;
467 EFI_IP4_MODE_DATA Ip4ModeData
;
468 PXEBC_PRIVATE_PROTOCOL
*Id
;
469 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
471 if (Private
->Ip4Nic
!= NULL
) {
473 // Already created before.
479 // Create Dhcp4 child and open Dhcp4 protocol for PxeBc->Dhcp.
481 Status
= NetLibCreateServiceChild (
483 This
->DriverBindingHandle
,
484 &gEfiDhcp4ServiceBindingProtocolGuid
,
487 if (EFI_ERROR (Status
)) {
491 Status
= gBS
->OpenProtocol (
493 &gEfiDhcp4ProtocolGuid
,
494 (VOID
**) &Private
->Dhcp4
,
495 This
->DriverBindingHandle
,
497 EFI_OPEN_PROTOCOL_BY_DRIVER
499 if (EFI_ERROR (Status
)) {
504 // Create Mtftp4 child and open Mtftp4 protocol for PxeBc->Mtftp.
506 Status
= NetLibCreateServiceChild (
508 This
->DriverBindingHandle
,
509 &gEfiMtftp4ServiceBindingProtocolGuid
,
510 &Private
->Mtftp4Child
512 if (EFI_ERROR (Status
)) {
516 Status
= gBS
->OpenProtocol (
517 Private
->Mtftp4Child
,
518 &gEfiMtftp4ProtocolGuid
,
519 (VOID
**) &Private
->Mtftp4
,
520 This
->DriverBindingHandle
,
522 EFI_OPEN_PROTOCOL_BY_DRIVER
524 if (EFI_ERROR (Status
)) {
529 // Create Udp4 child and open Udp4 protocol for PxeBc->UdpRead.
531 Status
= NetLibCreateServiceChild (
533 This
->DriverBindingHandle
,
534 &gEfiUdp4ServiceBindingProtocolGuid
,
535 &Private
->Udp4ReadChild
537 if (EFI_ERROR (Status
)) {
541 Status
= gBS
->OpenProtocol (
542 Private
->Udp4ReadChild
,
543 &gEfiUdp4ProtocolGuid
,
544 (VOID
**) &Private
->Udp4Read
,
545 This
->DriverBindingHandle
,
547 EFI_OPEN_PROTOCOL_BY_DRIVER
549 if (EFI_ERROR (Status
)) {
554 // Create Udp4 child and open Udp4 protocol for PxeBc->UdpWrite.
556 Status
= NetLibCreateServiceChild (
558 This
->DriverBindingHandle
,
559 &gEfiUdp4ServiceBindingProtocolGuid
,
560 &Private
->Udp4WriteChild
562 if (EFI_ERROR (Status
)) {
566 Status
= gBS
->OpenProtocol (
567 Private
->Udp4WriteChild
,
568 &gEfiUdp4ProtocolGuid
,
569 (VOID
**) &Private
->Udp4Write
,
570 This
->DriverBindingHandle
,
572 EFI_OPEN_PROTOCOL_BY_DRIVER
574 if (EFI_ERROR (Status
)) {
579 // Create Arp child and open Arp protocol for PxeBc->Arp.
581 Status
= NetLibCreateServiceChild (
583 This
->DriverBindingHandle
,
584 &gEfiArpServiceBindingProtocolGuid
,
587 if (EFI_ERROR (Status
)) {
591 Status
= gBS
->OpenProtocol (
593 &gEfiArpProtocolGuid
,
594 (VOID
**) &Private
->Arp
,
595 This
->DriverBindingHandle
,
597 EFI_OPEN_PROTOCOL_BY_DRIVER
599 if (EFI_ERROR (Status
)) {
604 // Create Ip4 child and open Ip4 protocol for background ICMP packets.
606 Status
= NetLibCreateServiceChild (
608 This
->DriverBindingHandle
,
609 &gEfiIp4ServiceBindingProtocolGuid
,
612 if (EFI_ERROR (Status
)) {
616 Status
= gBS
->OpenProtocol (
618 &gEfiIp4ProtocolGuid
,
619 (VOID
**) &Private
->Ip4
,
620 This
->DriverBindingHandle
,
622 EFI_OPEN_PROTOCOL_BY_DRIVER
624 if (EFI_ERROR (Status
)) {
629 // Get max packet size from Ip4 to calculate block size for Tftp later.
631 Status
= Private
->Ip4
->GetModeData (Private
->Ip4
, &Ip4ModeData
, NULL
, NULL
);
632 if (EFI_ERROR (Status
)) {
636 Private
->Ip4MaxPacketSize
= Ip4ModeData
.MaxPacketSize
;
638 Private
->Ip4Nic
= AllocateZeroPool (sizeof (PXEBC_VIRTUAL_NIC
));
639 if (Private
->Ip4Nic
== NULL
) {
640 return EFI_OUT_OF_RESOURCES
;
643 Private
->Ip4Nic
->Private
= Private
;
644 Private
->Ip4Nic
->Signature
= PXEBC_VIRTUAL_NIC_SIGNATURE
;
647 // Create a device path node for Ipv4 virtual nic, and append it.
649 ZeroMem (&Ip4Node
, sizeof (IPv4_DEVICE_PATH
));
650 Ip4Node
.Header
.Type
= MESSAGING_DEVICE_PATH
;
651 Ip4Node
.Header
.SubType
= MSG_IPv4_DP
;
652 Ip4Node
.StaticIpAddress
= FALSE
;
654 SetDevicePathNodeLength (&Ip4Node
.Header
, sizeof (Ip4Node
));
656 Private
->Ip4Nic
->DevicePath
= AppendDevicePathNode (Private
->DevicePath
, &Ip4Node
.Header
);
658 if (Private
->Ip4Nic
->DevicePath
== NULL
) {
659 Status
= EFI_OUT_OF_RESOURCES
;
664 &Private
->Ip4Nic
->LoadFile
,
665 &gLoadFileProtocolTemplate
,
666 sizeof (EFI_LOAD_FILE_PROTOCOL
)
670 // Create a new handle for IPv4 virtual nic,
671 // and install PxeBaseCode, LoadFile and DevicePath protocols.
673 Status
= gBS
->InstallMultipleProtocolInterfaces (
674 &Private
->Ip4Nic
->Controller
,
675 &gEfiDevicePathProtocolGuid
,
676 Private
->Ip4Nic
->DevicePath
,
677 &gEfiLoadFileProtocolGuid
,
678 &Private
->Ip4Nic
->LoadFile
,
679 &gEfiPxeBaseCodeProtocolGuid
,
683 if (EFI_ERROR (Status
)) {
687 if (Private
->Snp
!= NULL
) {
689 // Install SNP protocol on purpose is for some OS loader backward
690 // compatibility consideration.
692 Status
= gBS
->InstallProtocolInterface (
693 &Private
->Ip4Nic
->Controller
,
694 &gEfiSimpleNetworkProtocolGuid
,
695 EFI_NATIVE_INTERFACE
,
698 if (EFI_ERROR (Status
)) {
703 // Open SNP on the child handle BY_DRIVER. It will prevent any additionally
704 // layering to perform the experiment.
706 Status
= gBS
->OpenProtocol (
707 Private
->Ip4Nic
->Controller
,
708 &gEfiSimpleNetworkProtocolGuid
,
710 This
->DriverBindingHandle
,
711 Private
->Ip4Nic
->Controller
,
712 EFI_OPEN_PROTOCOL_BY_DRIVER
714 if (EFI_ERROR (Status
)) {
720 // Open PxeBaseCodePrivate protocol by child to setup a parent-child relationship between
721 // real NIC handle and the virtual IPv4 NIC handle.
723 Status
= gBS
->OpenProtocol (
727 This
->DriverBindingHandle
,
728 Private
->Ip4Nic
->Controller
,
729 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
731 if (EFI_ERROR (Status
)) {
736 // Set default configure data for Udp4Read and Ip4 instance.
738 Mode
= Private
->PxeBc
.Mode
;
739 Udp4CfgData
= &Private
->Udp4CfgData
;
740 Ip4CfgData
= &Private
->Ip4CfgData
;
742 Udp4CfgData
->AcceptBroadcast
= TRUE
;
743 Udp4CfgData
->AcceptAnyPort
= TRUE
;
744 Udp4CfgData
->AllowDuplicatePort
= TRUE
;
745 Udp4CfgData
->TypeOfService
= Mode
->ToS
;
746 Udp4CfgData
->TimeToLive
= Mode
->TTL
;
747 Udp4CfgData
->ReceiveTimeout
= PXEBC_DEFAULT_LIFETIME
;
748 Udp4CfgData
->TransmitTimeout
= PXEBC_DEFAULT_LIFETIME
;
750 Ip4CfgData
->AcceptIcmpErrors
= TRUE
;
751 Ip4CfgData
->DefaultProtocol
= EFI_IP_PROTO_ICMP
;
752 Ip4CfgData
->TypeOfService
= Mode
->ToS
;
753 Ip4CfgData
->TimeToLive
= Mode
->TTL
;
754 Ip4CfgData
->ReceiveTimeout
= PXEBC_DEFAULT_LIFETIME
;
755 Ip4CfgData
->TransmitTimeout
= PXEBC_DEFAULT_LIFETIME
;
760 PxeBcDestroyIp4Children (This
, Private
);
766 Create the opened instances based on IPv6.
768 @param[in] This Pointer to EFI_DRIVER_BINDING_PROTOCOL.
769 @param[in] ControllerHandle Handle of the child to destroy.
770 @param[in] Private Handle Pointer to PXEBC_PRIVATE_DATA.
772 @retval EFI_SUCCESS The instances based on IPv6 were all created successfully.
773 @retval Others An unexpected error occurred.
777 PxeBcCreateIp6Children (
778 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
779 IN EFI_HANDLE ControllerHandle
,
780 IN PXEBC_PRIVATE_DATA
*Private
784 IPv6_DEVICE_PATH Ip6Node
;
785 EFI_UDP6_CONFIG_DATA
*Udp6CfgData
;
786 EFI_IP6_CONFIG_DATA
*Ip6CfgData
;
787 EFI_IP6_MODE_DATA Ip6ModeData
;
788 PXEBC_PRIVATE_PROTOCOL
*Id
;
789 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
791 if (Private
->Ip6Nic
!= NULL
) {
793 // Already created before.
798 Private
->Ip6Nic
= AllocateZeroPool (sizeof (PXEBC_VIRTUAL_NIC
));
800 if (Private
->Ip6Nic
== NULL
) {
801 return EFI_OUT_OF_RESOURCES
;
804 Private
->Ip6Nic
->Private
= Private
;
805 Private
->Ip6Nic
->Signature
= PXEBC_VIRTUAL_NIC_SIGNATURE
;
808 // Create Dhcp6 child and open Dhcp6 protocol for PxeBc->Dhcp.
810 Status
= NetLibCreateServiceChild (
812 This
->DriverBindingHandle
,
813 &gEfiDhcp6ServiceBindingProtocolGuid
,
816 if (EFI_ERROR (Status
)) {
820 Status
= gBS
->OpenProtocol (
822 &gEfiDhcp6ProtocolGuid
,
823 (VOID
**) &Private
->Dhcp6
,
824 This
->DriverBindingHandle
,
826 EFI_OPEN_PROTOCOL_BY_DRIVER
828 if (EFI_ERROR (Status
)) {
833 // Create Mtftp6 child and open Mtftp6 protocol for PxeBc->Mtftp.
835 Status
= NetLibCreateServiceChild (
837 This
->DriverBindingHandle
,
838 &gEfiMtftp6ServiceBindingProtocolGuid
,
839 &Private
->Mtftp6Child
841 if (EFI_ERROR (Status
)) {
845 Status
= gBS
->OpenProtocol (
846 Private
->Mtftp6Child
,
847 &gEfiMtftp6ProtocolGuid
,
848 (VOID
**) &Private
->Mtftp6
,
849 This
->DriverBindingHandle
,
851 EFI_OPEN_PROTOCOL_BY_DRIVER
853 if (EFI_ERROR (Status
)) {
858 // Create Udp6 child and open Udp6 protocol for PxeBc->UdpRead.
860 Status
= NetLibCreateServiceChild (
862 This
->DriverBindingHandle
,
863 &gEfiUdp6ServiceBindingProtocolGuid
,
864 &Private
->Udp6ReadChild
866 if (EFI_ERROR (Status
)) {
870 Status
= gBS
->OpenProtocol (
871 Private
->Udp6ReadChild
,
872 &gEfiUdp6ProtocolGuid
,
873 (VOID
**) &Private
->Udp6Read
,
874 This
->DriverBindingHandle
,
876 EFI_OPEN_PROTOCOL_BY_DRIVER
878 if (EFI_ERROR (Status
)) {
883 // Create Udp6 child and open Udp6 protocol for PxeBc->UdpWrite.
885 Status
= NetLibCreateServiceChild (
887 This
->DriverBindingHandle
,
888 &gEfiUdp6ServiceBindingProtocolGuid
,
889 &Private
->Udp6WriteChild
891 if (EFI_ERROR (Status
)) {
895 Status
= gBS
->OpenProtocol (
896 Private
->Udp6WriteChild
,
897 &gEfiUdp6ProtocolGuid
,
898 (VOID
**) &Private
->Udp6Write
,
899 This
->DriverBindingHandle
,
901 EFI_OPEN_PROTOCOL_BY_DRIVER
903 if (EFI_ERROR (Status
)) {
908 // Create Ip6 child and open Ip6 protocol for background ICMP6 packets.
910 Status
= NetLibCreateServiceChild (
912 This
->DriverBindingHandle
,
913 &gEfiIp6ServiceBindingProtocolGuid
,
916 if (EFI_ERROR (Status
)) {
920 Status
= gBS
->OpenProtocol (
922 &gEfiIp6ProtocolGuid
,
923 (VOID
**) &Private
->Ip6
,
924 This
->DriverBindingHandle
,
926 EFI_OPEN_PROTOCOL_BY_DRIVER
928 if (EFI_ERROR (Status
)) {
933 // Get max packet size from Ip6 to calculate block size for Tftp later.
935 Status
= Private
->Ip6
->GetModeData (Private
->Ip6
, &Ip6ModeData
, NULL
, NULL
);
936 if (EFI_ERROR (Status
)) {
940 Private
->Ip6MaxPacketSize
= Ip6ModeData
.MaxPacketSize
;
943 // Locate Ip6->Ip6Config and store it for set IPv6 address.
945 Status
= gBS
->HandleProtocol (
947 &gEfiIp6ConfigProtocolGuid
,
948 (VOID
**) &Private
->Ip6Cfg
950 if (EFI_ERROR (Status
)) {
955 // Create a device path node for Ipv6 virtual nic, and append it.
957 ZeroMem (&Ip6Node
, sizeof (IPv6_DEVICE_PATH
));
958 Ip6Node
.Header
.Type
= MESSAGING_DEVICE_PATH
;
959 Ip6Node
.Header
.SubType
= MSG_IPv6_DP
;
960 Ip6Node
.StaticIpAddress
= FALSE
;
962 SetDevicePathNodeLength (&Ip6Node
.Header
, sizeof (Ip6Node
));
964 Private
->Ip6Nic
->DevicePath
= AppendDevicePathNode (Private
->DevicePath
, &Ip6Node
.Header
);
966 if (Private
->Ip6Nic
->DevicePath
== NULL
) {
967 Status
= EFI_OUT_OF_RESOURCES
;
972 &Private
->Ip6Nic
->LoadFile
,
973 &gLoadFileProtocolTemplate
,
974 sizeof (EFI_LOAD_FILE_PROTOCOL
)
978 // Create a new handle for IPv6 virtual nic,
979 // and install PxeBaseCode, LoadFile and DevicePath protocols.
981 Status
= gBS
->InstallMultipleProtocolInterfaces (
982 &Private
->Ip6Nic
->Controller
,
983 &gEfiDevicePathProtocolGuid
,
984 Private
->Ip6Nic
->DevicePath
,
985 &gEfiLoadFileProtocolGuid
,
986 &Private
->Ip6Nic
->LoadFile
,
987 &gEfiPxeBaseCodeProtocolGuid
,
991 if (EFI_ERROR (Status
)) {
995 if (Private
->Snp
!= NULL
) {
997 // Install SNP protocol on purpose is for some OS loader backward
998 // compatibility consideration.
1000 Status
= gBS
->InstallProtocolInterface (
1001 &Private
->Ip6Nic
->Controller
,
1002 &gEfiSimpleNetworkProtocolGuid
,
1003 EFI_NATIVE_INTERFACE
,
1006 if (EFI_ERROR (Status
)) {
1011 // Open SNP on the child handle BY_DRIVER. It will prevent any additionally
1012 // layering to perform the experiment.
1014 Status
= gBS
->OpenProtocol (
1015 Private
->Ip6Nic
->Controller
,
1016 &gEfiSimpleNetworkProtocolGuid
,
1018 This
->DriverBindingHandle
,
1019 Private
->Ip6Nic
->Controller
,
1020 EFI_OPEN_PROTOCOL_BY_DRIVER
1022 if (EFI_ERROR (Status
)) {
1028 // Open PxeBaseCodePrivate protocol by child to setup a parent-child relationship between
1029 // real NIC handle and the virtual IPv6 NIC handle.
1031 Status
= gBS
->OpenProtocol (
1035 This
->DriverBindingHandle
,
1036 Private
->Ip6Nic
->Controller
,
1037 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1039 if (EFI_ERROR (Status
)) {
1044 // Set IPv6 avaiable flag and set default configure data for
1045 // Udp6Read and Ip6 instance.
1047 Private
->Mode
.Ipv6Available
= TRUE
;
1048 Udp6CfgData
= &Private
->Udp6CfgData
;
1049 Ip6CfgData
= &Private
->Ip6CfgData
;
1051 Udp6CfgData
->AcceptAnyPort
= TRUE
;
1052 Udp6CfgData
->AllowDuplicatePort
= TRUE
;
1053 Udp6CfgData
->HopLimit
= PXEBC_DEFAULT_HOPLIMIT
;
1054 Udp6CfgData
->ReceiveTimeout
= PXEBC_DEFAULT_LIFETIME
;
1055 Udp6CfgData
->TransmitTimeout
= PXEBC_DEFAULT_LIFETIME
;
1057 Ip6CfgData
->AcceptIcmpErrors
= TRUE
;
1058 Ip6CfgData
->DefaultProtocol
= IP6_ICMP
;
1059 Ip6CfgData
->HopLimit
= PXEBC_DEFAULT_HOPLIMIT
;
1060 Ip6CfgData
->ReceiveTimeout
= PXEBC_DEFAULT_LIFETIME
;
1061 Ip6CfgData
->TransmitTimeout
= PXEBC_DEFAULT_LIFETIME
;
1066 PxeBcDestroyIp6Children (This
, Private
);
1072 The entry point for UefiPxeBc driver that installs the driver
1073 binding and component name protocol on its image.
1075 @param[in] ImageHandle The Image handle of the driver.
1076 @param[in] SystemTable The system table.
1084 PxeBcDriverEntryPoint (
1085 IN EFI_HANDLE ImageHandle
,
1086 IN EFI_SYSTEM_TABLE
*SystemTable
1089 return EfiLibInstallDriverBindingComponentName2 (
1092 &gPxeBcDriverBinding
,
1094 &gPxeBcComponentName
,
1095 &gPxeBcComponentName2
1101 Test to see if this driver supports ControllerHandle. This service
1102 is called by the EFI boot service ConnectController(). In
1103 order to make drivers as small as possible, there are a few calling
1104 restrictions for this service. ConnectController() must
1105 follow these calling restrictions. If any other agent wishes to call
1106 Supported() it must also follow these calling restrictions.
1108 @param[in] This The pointer to the driver binding protocol.
1109 @param[in] ControllerHandle The handle of device to be tested.
1110 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
1111 device to be started.
1113 @retval EFI_SUCCESS This driver supports this device.
1114 @retval EFI_UNSUPPORTED This driver does not support this device.
1119 PxeBcDriverBindingSupported (
1120 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1121 IN EFI_HANDLE ControllerHandle
,
1122 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1125 EFI_STATUS Ip4Status
;
1126 EFI_STATUS Ip6Status
;
1129 // Try to open the Mtftp4 and Dhcp4 protocol to test whether IPv4 stack is ready.
1131 Ip4Status
= gBS
->OpenProtocol (
1133 &gEfiDhcp4ServiceBindingProtocolGuid
,
1135 This
->DriverBindingHandle
,
1137 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
1139 if (!EFI_ERROR (Ip4Status
)) {
1140 Ip4Status
= gBS
->OpenProtocol (
1142 &gEfiMtftp4ServiceBindingProtocolGuid
,
1144 This
->DriverBindingHandle
,
1146 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
1151 // Try to open the Mtftp6 and Dhcp6 protocol to test whether IPv4 stack is ready.
1153 Ip6Status
= gBS
->OpenProtocol (
1155 &gEfiDhcp6ServiceBindingProtocolGuid
,
1157 This
->DriverBindingHandle
,
1159 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
1161 if (!EFI_ERROR (Ip6Status
)) {
1162 Ip6Status
= gBS
->OpenProtocol (
1164 &gEfiMtftp6ServiceBindingProtocolGuid
,
1166 This
->DriverBindingHandle
,
1168 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
1173 // It's unsupported case if both stack are not ready.
1175 if (EFI_ERROR (Ip4Status
) && EFI_ERROR (Ip6Status
)) {
1176 return EFI_UNSUPPORTED
;
1184 Start this driver on ControllerHandle. This service is called by the
1185 EFI boot service ConnectController(). In order to make
1186 drivers as small as possible, there are a few calling restrictions for
1187 this service. ConnectController() must follow these
1188 calling restrictions. If any other agent wishes to call Start() it
1189 must also follow these calling restrictions.
1191 @param[in] This The pointer to the driver binding protocol.
1192 @param[in] ControllerHandle The handle of device to be started.
1193 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
1194 device to be started.
1196 @retval EFI_SUCCESS This driver is installed to ControllerHandle.
1197 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
1198 @retval other This driver does not support this device.
1203 PxeBcDriverBindingStart (
1204 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1205 IN EFI_HANDLE ControllerHandle
,
1206 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1209 PXEBC_PRIVATE_DATA
*Private
;
1211 EFI_STATUS Ip4Status
;
1212 EFI_STATUS Ip6Status
;
1213 PXEBC_PRIVATE_PROTOCOL
*Id
;
1215 Status
= gBS
->OpenProtocol (
1219 This
->DriverBindingHandle
,
1221 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1223 if (!EFI_ERROR (Status
)) {
1225 // Skip the initialization if the driver has been started already.
1227 Private
= PXEBC_PRIVATE_DATA_FROM_ID (Id
);
1230 // If the driver has not been started yet, it should do initialization.
1232 Private
= AllocateZeroPool (sizeof (PXEBC_PRIVATE_DATA
));
1233 if (Private
== NULL
) {
1234 return EFI_OUT_OF_RESOURCES
;
1239 &gPxeBcProtocolTemplate
,
1240 sizeof (EFI_PXE_BASE_CODE_PROTOCOL
)
1243 Private
->Signature
= PXEBC_PRIVATE_DATA_SIGNATURE
;
1244 Private
->Controller
= ControllerHandle
;
1245 Private
->Image
= This
->ImageHandle
;
1246 Private
->PxeBc
.Mode
= &Private
->Mode
;
1247 Private
->Mode
.Ipv6Supported
= TRUE
;
1248 Private
->Mode
.AutoArp
= TRUE
;
1249 Private
->Mode
.TTL
= DEFAULT_TTL
;
1250 Private
->Mode
.ToS
= DEFAULT_ToS
;
1253 // Open device path to prepare for appending virtual NIC node.
1255 Status
= gBS
->OpenProtocol (
1257 &gEfiDevicePathProtocolGuid
,
1258 (VOID
**) &Private
->DevicePath
,
1259 This
->DriverBindingHandle
,
1261 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1264 if (EFI_ERROR (Status
)) {
1269 // Get the NII interface if it exists, it's not required.
1271 Status
= gBS
->OpenProtocol (
1273 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
1274 (VOID
**) &Private
->Nii
,
1275 This
->DriverBindingHandle
,
1277 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1279 if (EFI_ERROR (Status
)) {
1280 Private
->Nii
= NULL
;
1284 // Install PxeBaseCodePrivate protocol onto the real NIC handler.
1286 Status
= gBS
->InstallProtocolInterface (
1289 EFI_NATIVE_INTERFACE
,
1292 if (EFI_ERROR (Status
)) {
1297 // Try to locate SNP protocol.
1299 NetLibGetSnpHandle(ControllerHandle
, &Private
->Snp
);
1303 // Try to create virtual NIC handle for IPv4.
1305 Ip4Status
= PxeBcCreateIp4Children (This
, ControllerHandle
, Private
);
1308 // Try to create virtual NIC handle for IPv6.
1310 Ip6Status
= PxeBcCreateIp6Children (This
, ControllerHandle
, Private
);
1312 if (EFI_ERROR (Ip4Status
) && EFI_ERROR (Ip6Status
)) {
1314 // Failed to start PXE driver if IPv4 and IPv6 stack are both not available.
1316 Status
= EFI_DEVICE_ERROR
;
1323 gBS
->UninstallProtocolInterface (
1328 PxeBcDestroyIp4Children (This
, Private
);
1329 PxeBcDestroyIp6Children (This
, Private
);
1337 Stop this driver on ControllerHandle. This service is called by the
1338 EFI boot service DisconnectController(). In order to
1339 make drivers as small as possible, there are a few calling
1340 restrictions for this service. DisconnectController()
1341 must follow these calling restrictions. If any other agent wishes
1342 to call Stop() it must also follow these calling restrictions.
1344 @param[in] This Protocol instance pointer.
1345 @param[in] ControllerHandle Handle of device to stop driver on.
1346 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
1347 children is zero stop the entire bus driver.
1348 @param[in] ChildHandleBuffer List of Child Handles to Stop.
1350 @retval EFI_SUCCESS This driver was removed ControllerHandle.
1351 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
1352 @retval Others This driver was not removed from this device
1357 PxeBcDriverBindingStop (
1358 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1359 IN EFI_HANDLE ControllerHandle
,
1360 IN UINTN NumberOfChildren
,
1361 IN EFI_HANDLE
*ChildHandleBuffer
1364 PXEBC_PRIVATE_DATA
*Private
;
1365 PXEBC_VIRTUAL_NIC
*VirtualNic
;
1366 EFI_LOAD_FILE_PROTOCOL
*LoadFile
;
1368 EFI_HANDLE NicHandle
;
1370 PXEBC_PRIVATE_PROTOCOL
*Id
;
1379 Status
= gBS
->OpenProtocol (
1381 &gEfiLoadFileProtocolGuid
,
1382 (VOID
**) &LoadFile
,
1383 This
->DriverBindingHandle
,
1385 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1387 if (EFI_ERROR (Status
)) {
1389 // Get the Nic handle by any pass-over service child handle.
1391 NicHandle
= PxeBcGetNicByIp4Children (ControllerHandle
);
1392 if (NicHandle
== NULL
) {
1393 NicHandle
= PxeBcGetNicByIp6Children (ControllerHandle
);
1394 if (NicHandle
== NULL
) {
1395 return EFI_DEVICE_ERROR
;
1402 // Try to retrieve the private data by PxeBcPrivate protocol.
1404 Status
= gBS
->OpenProtocol (
1408 This
->DriverBindingHandle
,
1410 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1412 if (EFI_ERROR (Status
)) {
1415 Private
= PXEBC_PRIVATE_DATA_FROM_ID (Id
);
1419 // It's a virtual handle with LoadFileProtocol.
1421 Status
= gBS
->OpenProtocol (
1423 &gEfiLoadFileProtocolGuid
,
1424 (VOID
**) &LoadFile
,
1425 This
->DriverBindingHandle
,
1427 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1429 if (EFI_ERROR (Status
)) {
1433 VirtualNic
= PXEBC_VIRTUAL_NIC_FROM_LOADFILE (LoadFile
);
1434 Private
= VirtualNic
->Private
;
1435 NicHandle
= Private
->Controller
;
1437 if (Private
->Ip6Nic
== VirtualNic
) {
1443 // Stop functionality of PXE Base Code protocol
1445 Status
= Private
->PxeBc
.Stop (&Private
->PxeBc
);
1446 if (Status
!= EFI_SUCCESS
&& Status
!= EFI_NOT_STARTED
) {
1451 if (Private
->Ip4Nic
!= NULL
&& !IsIpv6
) {
1452 PxeBcDestroyIp4Children (This
, Private
);
1455 if (Private
->Ip6Nic
!= NULL
&& IsIpv6
) {
1456 PxeBcDestroyIp6Children (This
, Private
);
1459 if (Private
->Ip4Nic
== NULL
&& Private
->Ip6Nic
== NULL
) {
1460 gBS
->UninstallProtocolInterface (