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 Get the Nic handle using any child handle in the IPv4 stack.
31 @param[in] ControllerHandle Pointer to child handle over IPv4.
33 @return NicHandle The pointer to the Nic handle.
37 PxeBcGetNicByIp4Children (
38 IN EFI_HANDLE ControllerHandle
43 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiArpProtocolGuid
);
44 if (NicHandle
== NULL
) {
45 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiIp4ProtocolGuid
);
46 if (NicHandle
== NULL
) {
47 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiUdp4ProtocolGuid
);
48 if (NicHandle
== NULL
) {
49 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiDhcp4ProtocolGuid
);
50 if (NicHandle
== NULL
) {
51 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiMtftp4ProtocolGuid
);
52 if (NicHandle
== NULL
) {
65 Get the Nic handle using any child handle in the IPv6 stack.
67 @param[in] ControllerHandle Pointer to child handle over IPv6.
69 @return NicHandle The pointer to the Nic handle.
73 PxeBcGetNicByIp6Children (
74 IN EFI_HANDLE ControllerHandle
79 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiIp6ProtocolGuid
);
80 if (NicHandle
== NULL
) {
81 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiUdp6ProtocolGuid
);
82 if (NicHandle
== NULL
) {
83 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiDhcp6ProtocolGuid
);
84 if (NicHandle
== NULL
) {
85 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiMtftp6ProtocolGuid
);
86 if (NicHandle
== NULL
) {
98 Destroy the opened instances based on IPv4.
100 @param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
101 @param[in] Private Pointer to PXEBC_PRIVATE_DATA.
105 PxeBcDestroyIp4Children (
106 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
107 IN PXEBC_PRIVATE_DATA
*Private
110 ASSERT(Private
!= NULL
);
112 if (Private
->ArpChild
!= NULL
) {
114 // Close Arp for PxeBc->Arp and destroy the instance.
118 &gEfiArpProtocolGuid
,
119 This
->DriverBindingHandle
,
123 NetLibDestroyServiceChild (
125 This
->DriverBindingHandle
,
126 &gEfiArpServiceBindingProtocolGuid
,
131 if (Private
->Ip4Child
!= NULL
) {
133 // Close Ip4 for background ICMP error message and destroy the instance.
137 &gEfiIp4ProtocolGuid
,
138 This
->DriverBindingHandle
,
142 NetLibDestroyServiceChild (
144 This
->DriverBindingHandle
,
145 &gEfiIp4ServiceBindingProtocolGuid
,
150 if (Private
->Udp4WriteChild
!= NULL
) {
152 // Close Udp4 for PxeBc->UdpWrite and destroy the instance.
155 Private
->Udp4WriteChild
,
156 &gEfiUdp4ProtocolGuid
,
157 This
->DriverBindingHandle
,
161 NetLibDestroyServiceChild (
163 This
->DriverBindingHandle
,
164 &gEfiUdp4ServiceBindingProtocolGuid
,
165 Private
->Udp4WriteChild
169 if (Private
->Udp4ReadChild
!= NULL
) {
171 // Close Udp4 for PxeBc->UdpRead and destroy the instance.
174 Private
->Udp4ReadChild
,
175 &gEfiUdp4ProtocolGuid
,
176 This
->DriverBindingHandle
,
180 NetLibDestroyServiceChild (
182 This
->DriverBindingHandle
,
183 &gEfiUdp4ServiceBindingProtocolGuid
,
184 Private
->Udp4ReadChild
188 if (Private
->Mtftp4Child
!= NULL
) {
190 // Close Mtftp4 for PxeBc->Mtftp4 and destroy the instance.
193 Private
->Mtftp4Child
,
194 &gEfiMtftp4ProtocolGuid
,
195 This
->DriverBindingHandle
,
199 NetLibDestroyServiceChild (
201 This
->DriverBindingHandle
,
202 &gEfiMtftp4ServiceBindingProtocolGuid
,
207 if (Private
->Dhcp4Child
!= NULL
) {
209 // Close Dhcp4 for PxeBc->Dhcp4 and destroy the instance.
213 &gEfiDhcp4ProtocolGuid
,
214 This
->DriverBindingHandle
,
218 NetLibDestroyServiceChild (
220 This
->DriverBindingHandle
,
221 &gEfiDhcp4ServiceBindingProtocolGuid
,
226 if (Private
->Ip4Nic
!= NULL
) {
228 // Close PxeBcPrivate from the parent Nic handle and destroy the virtual handle.
233 This
->DriverBindingHandle
,
234 Private
->Ip4Nic
->Controller
237 gBS
->UninstallMultipleProtocolInterfaces (
238 Private
->Ip4Nic
->Controller
,
239 &gEfiDevicePathProtocolGuid
,
240 Private
->Ip4Nic
->DevicePath
,
241 &gEfiLoadFileProtocolGuid
,
242 &Private
->Ip4Nic
->LoadFile
,
243 &gEfiPxeBaseCodeProtocolGuid
,
248 if (Private
->Snp
!= NULL
) {
250 // Close SNP from the child virtual handle
253 Private
->Ip4Nic
->Controller
,
254 &gEfiSimpleNetworkProtocolGuid
,
255 This
->DriverBindingHandle
,
256 Private
->Ip4Nic
->Controller
259 gBS
->UninstallProtocolInterface (
260 Private
->Ip4Nic
->Controller
,
261 &gEfiSimpleNetworkProtocolGuid
,
265 FreePool (Private
->Ip4Nic
);
268 Private
->ArpChild
= NULL
;
269 Private
->Ip4Child
= NULL
;
270 Private
->Udp4WriteChild
= NULL
;
271 Private
->Udp4ReadChild
= NULL
;
272 Private
->Mtftp4Child
= NULL
;
273 Private
->Dhcp4Child
= NULL
;
274 Private
->Ip4Nic
= NULL
;
279 Destroy the opened instances based on IPv6.
281 @param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
282 @param[in] Private Pointer to PXEBC_PRIVATE_DATA.
286 PxeBcDestroyIp6Children (
287 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
288 IN PXEBC_PRIVATE_DATA
*Private
291 ASSERT(Private
!= NULL
);
293 if (Private
->Ip6Child
!= NULL
) {
295 // Close Ip6 for Ip6->Ip6Config and destroy the instance.
299 &gEfiIp6ProtocolGuid
,
300 This
->DriverBindingHandle
,
304 NetLibDestroyServiceChild (
306 This
->DriverBindingHandle
,
307 &gEfiIp6ServiceBindingProtocolGuid
,
312 if (Private
->Udp6WriteChild
!= NULL
) {
314 // Close Udp6 for PxeBc->UdpWrite and destroy the instance.
317 Private
->Udp6WriteChild
,
318 &gEfiUdp6ProtocolGuid
,
319 This
->DriverBindingHandle
,
322 NetLibDestroyServiceChild (
324 This
->DriverBindingHandle
,
325 &gEfiUdp6ServiceBindingProtocolGuid
,
326 Private
->Udp6WriteChild
330 if (Private
->Udp6ReadChild
!= NULL
) {
332 // Close Udp6 for PxeBc->UdpRead and destroy the instance.
335 Private
->Udp6ReadChild
,
336 &gEfiUdp6ProtocolGuid
,
337 This
->DriverBindingHandle
,
340 NetLibDestroyServiceChild (
342 This
->DriverBindingHandle
,
343 &gEfiUdp6ServiceBindingProtocolGuid
,
344 Private
->Udp6ReadChild
348 if (Private
->Mtftp6Child
!= NULL
) {
350 // Close Mtftp6 for PxeBc->Mtftp and destroy the instance.
353 Private
->Mtftp6Child
,
354 &gEfiMtftp6ProtocolGuid
,
355 This
->DriverBindingHandle
,
359 NetLibDestroyServiceChild (
361 This
->DriverBindingHandle
,
362 &gEfiMtftp6ServiceBindingProtocolGuid
,
367 if (Private
->Dhcp6Child
!= NULL
) {
369 // Close Dhcp6 for PxeBc->Dhcp and destroy the instance.
373 &gEfiDhcp6ProtocolGuid
,
374 This
->DriverBindingHandle
,
378 NetLibDestroyServiceChild (
380 This
->DriverBindingHandle
,
381 &gEfiDhcp6ServiceBindingProtocolGuid
,
386 if (Private
->Ip6Nic
!= NULL
) {
388 // Close PxeBcPrivate from the parent Nic handle and destroy the virtual handle.
393 This
->DriverBindingHandle
,
394 Private
->Ip6Nic
->Controller
397 gBS
->UninstallMultipleProtocolInterfaces (
398 Private
->Ip6Nic
->Controller
,
399 &gEfiDevicePathProtocolGuid
,
400 Private
->Ip6Nic
->DevicePath
,
401 &gEfiLoadFileProtocolGuid
,
402 &Private
->Ip6Nic
->LoadFile
,
403 &gEfiPxeBaseCodeProtocolGuid
,
407 if (Private
->Snp
!= NULL
) {
409 // Close SNP from the child virtual handle
412 Private
->Ip6Nic
->Controller
,
413 &gEfiSimpleNetworkProtocolGuid
,
414 This
->DriverBindingHandle
,
415 Private
->Ip6Nic
->Controller
417 gBS
->UninstallProtocolInterface (
418 Private
->Ip6Nic
->Controller
,
419 &gEfiSimpleNetworkProtocolGuid
,
423 FreePool (Private
->Ip6Nic
);
426 Private
->Ip6Child
= NULL
;
427 Private
->Udp6WriteChild
= NULL
;
428 Private
->Udp6ReadChild
= NULL
;
429 Private
->Mtftp6Child
= NULL
;
430 Private
->Dhcp6Child
= NULL
;
431 Private
->Ip6Nic
= NULL
;
432 Private
->Mode
.Ipv6Available
= FALSE
;
437 Create the opened instances based on IPv4.
439 @param[in] This Pointer to EFI_DRIVER_BINDING_PROTOCOL.
440 @param[in] ControllerHandle Handle of the child to destroy.
441 @param[in] Private Handle Pointer to PXEBC_PRIVATE_DATA.
443 @retval EFI_SUCCESS The instances based on IPv4 were all created successfully.
444 @retval Others An unexpected error occurred.
448 PxeBcCreateIp4Children (
449 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
450 IN EFI_HANDLE ControllerHandle
,
451 IN PXEBC_PRIVATE_DATA
*Private
455 IPv4_DEVICE_PATH Ip4Node
;
456 EFI_PXE_BASE_CODE_MODE
*Mode
;
457 EFI_UDP4_CONFIG_DATA
*Udp4CfgData
;
458 EFI_IP4_CONFIG_DATA
*Ip4CfgData
;
459 EFI_IP4_MODE_DATA Ip4ModeData
;
460 PXEBC_PRIVATE_PROTOCOL
*Id
;
461 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
463 if (Private
->Ip4Nic
!= NULL
) {
465 // Already created before.
471 // Create Dhcp4 child and open Dhcp4 protocol for PxeBc->Dhcp.
473 Status
= NetLibCreateServiceChild (
475 This
->DriverBindingHandle
,
476 &gEfiDhcp4ServiceBindingProtocolGuid
,
479 if (EFI_ERROR (Status
)) {
483 Status
= gBS
->OpenProtocol (
485 &gEfiDhcp4ProtocolGuid
,
486 (VOID
**) &Private
->Dhcp4
,
487 This
->DriverBindingHandle
,
489 EFI_OPEN_PROTOCOL_BY_DRIVER
491 if (EFI_ERROR (Status
)) {
496 // Create Mtftp4 child and open Mtftp4 protocol for PxeBc->Mtftp.
498 Status
= NetLibCreateServiceChild (
500 This
->DriverBindingHandle
,
501 &gEfiMtftp4ServiceBindingProtocolGuid
,
502 &Private
->Mtftp4Child
504 if (EFI_ERROR (Status
)) {
508 Status
= gBS
->OpenProtocol (
509 Private
->Mtftp4Child
,
510 &gEfiMtftp4ProtocolGuid
,
511 (VOID
**) &Private
->Mtftp4
,
512 This
->DriverBindingHandle
,
514 EFI_OPEN_PROTOCOL_BY_DRIVER
516 if (EFI_ERROR (Status
)) {
521 // Create Udp4 child and open Udp4 protocol for PxeBc->UdpRead.
523 Status
= NetLibCreateServiceChild (
525 This
->DriverBindingHandle
,
526 &gEfiUdp4ServiceBindingProtocolGuid
,
527 &Private
->Udp4ReadChild
529 if (EFI_ERROR (Status
)) {
533 Status
= gBS
->OpenProtocol (
534 Private
->Udp4ReadChild
,
535 &gEfiUdp4ProtocolGuid
,
536 (VOID
**) &Private
->Udp4Read
,
537 This
->DriverBindingHandle
,
539 EFI_OPEN_PROTOCOL_BY_DRIVER
541 if (EFI_ERROR (Status
)) {
546 // Create Udp4 child and open Udp4 protocol for PxeBc->UdpWrite.
548 Status
= NetLibCreateServiceChild (
550 This
->DriverBindingHandle
,
551 &gEfiUdp4ServiceBindingProtocolGuid
,
552 &Private
->Udp4WriteChild
554 if (EFI_ERROR (Status
)) {
558 Status
= gBS
->OpenProtocol (
559 Private
->Udp4WriteChild
,
560 &gEfiUdp4ProtocolGuid
,
561 (VOID
**) &Private
->Udp4Write
,
562 This
->DriverBindingHandle
,
564 EFI_OPEN_PROTOCOL_BY_DRIVER
566 if (EFI_ERROR (Status
)) {
571 // Create Arp child and open Arp protocol for PxeBc->Arp.
573 Status
= NetLibCreateServiceChild (
575 This
->DriverBindingHandle
,
576 &gEfiArpServiceBindingProtocolGuid
,
579 if (EFI_ERROR (Status
)) {
583 Status
= gBS
->OpenProtocol (
585 &gEfiArpProtocolGuid
,
586 (VOID
**) &Private
->Arp
,
587 This
->DriverBindingHandle
,
589 EFI_OPEN_PROTOCOL_BY_DRIVER
591 if (EFI_ERROR (Status
)) {
596 // Create Ip4 child and open Ip4 protocol for background ICMP packets.
598 Status
= NetLibCreateServiceChild (
600 This
->DriverBindingHandle
,
601 &gEfiIp4ServiceBindingProtocolGuid
,
604 if (EFI_ERROR (Status
)) {
608 Status
= gBS
->OpenProtocol (
610 &gEfiIp4ProtocolGuid
,
611 (VOID
**) &Private
->Ip4
,
612 This
->DriverBindingHandle
,
614 EFI_OPEN_PROTOCOL_BY_DRIVER
616 if (EFI_ERROR (Status
)) {
621 // Get max packet size from Ip4 to calculate block size for Tftp later.
623 Status
= Private
->Ip4
->GetModeData (Private
->Ip4
, &Ip4ModeData
, NULL
, NULL
);
624 if (EFI_ERROR (Status
)) {
628 Private
->Ip4MaxPacketSize
= Ip4ModeData
.MaxPacketSize
;
630 Private
->Ip4Nic
= AllocateZeroPool (sizeof (PXEBC_VIRTUAL_NIC
));
631 if (Private
->Ip4Nic
== NULL
) {
632 return EFI_OUT_OF_RESOURCES
;
635 Private
->Ip4Nic
->Private
= Private
;
636 Private
->Ip4Nic
->Signature
= PXEBC_VIRTUAL_NIC_SIGNATURE
;
639 // Create a device path node for Ipv4 virtual nic, and append it.
641 ZeroMem (&Ip4Node
, sizeof (IPv4_DEVICE_PATH
));
642 Ip4Node
.Header
.Type
= MESSAGING_DEVICE_PATH
;
643 Ip4Node
.Header
.SubType
= MSG_IPv4_DP
;
644 Ip4Node
.StaticIpAddress
= FALSE
;
646 SetDevicePathNodeLength (&Ip4Node
.Header
, sizeof (Ip4Node
));
648 Private
->Ip4Nic
->DevicePath
= AppendDevicePathNode (Private
->DevicePath
, &Ip4Node
.Header
);
650 if (Private
->Ip4Nic
->DevicePath
== NULL
) {
651 Status
= EFI_OUT_OF_RESOURCES
;
656 &Private
->Ip4Nic
->LoadFile
,
657 &gLoadFileProtocolTemplate
,
658 sizeof (EFI_LOAD_FILE_PROTOCOL
)
662 // Create a new handle for IPv4 virtual nic,
663 // and install PxeBaseCode, LoadFile and DevicePath protocols.
665 Status
= gBS
->InstallMultipleProtocolInterfaces (
666 &Private
->Ip4Nic
->Controller
,
667 &gEfiDevicePathProtocolGuid
,
668 Private
->Ip4Nic
->DevicePath
,
669 &gEfiLoadFileProtocolGuid
,
670 &Private
->Ip4Nic
->LoadFile
,
671 &gEfiPxeBaseCodeProtocolGuid
,
675 if (EFI_ERROR (Status
)) {
679 if (Private
->Snp
!= NULL
) {
681 // Install SNP protocol on purpose is for some OS loader backward
682 // compatibility consideration.
684 Status
= gBS
->InstallProtocolInterface (
685 &Private
->Ip4Nic
->Controller
,
686 &gEfiSimpleNetworkProtocolGuid
,
687 EFI_NATIVE_INTERFACE
,
690 if (EFI_ERROR (Status
)) {
695 // Open SNP on the child handle BY_DRIVER. It will prevent any additionally
696 // layering to perform the experiment.
698 Status
= gBS
->OpenProtocol (
699 Private
->Ip4Nic
->Controller
,
700 &gEfiSimpleNetworkProtocolGuid
,
702 This
->DriverBindingHandle
,
703 Private
->Ip4Nic
->Controller
,
704 EFI_OPEN_PROTOCOL_BY_DRIVER
706 if (EFI_ERROR (Status
)) {
712 // Open PxeBaseCodePrivate protocol by child to setup a parent-child relationship between
713 // real NIC handle and the virtual IPv4 NIC handle.
715 Status
= gBS
->OpenProtocol (
719 This
->DriverBindingHandle
,
720 Private
->Ip4Nic
->Controller
,
721 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
723 if (EFI_ERROR (Status
)) {
728 // Set default configure data for Udp4Read and Ip4 instance.
730 Mode
= Private
->PxeBc
.Mode
;
731 Udp4CfgData
= &Private
->Udp4CfgData
;
732 Ip4CfgData
= &Private
->Ip4CfgData
;
734 Udp4CfgData
->AcceptBroadcast
= FALSE
;
735 Udp4CfgData
->AcceptAnyPort
= TRUE
;
736 Udp4CfgData
->AllowDuplicatePort
= TRUE
;
737 Udp4CfgData
->TypeOfService
= Mode
->ToS
;
738 Udp4CfgData
->TimeToLive
= Mode
->TTL
;
739 Udp4CfgData
->ReceiveTimeout
= PXEBC_DEFAULT_LIFETIME
;
740 Udp4CfgData
->TransmitTimeout
= PXEBC_DEFAULT_LIFETIME
;
742 Ip4CfgData
->AcceptIcmpErrors
= TRUE
;
743 Ip4CfgData
->DefaultProtocol
= EFI_IP_PROTO_ICMP
;
744 Ip4CfgData
->TypeOfService
= Mode
->ToS
;
745 Ip4CfgData
->TimeToLive
= Mode
->TTL
;
746 Ip4CfgData
->ReceiveTimeout
= PXEBC_DEFAULT_LIFETIME
;
747 Ip4CfgData
->TransmitTimeout
= PXEBC_DEFAULT_LIFETIME
;
752 PxeBcDestroyIp4Children (This
, Private
);
758 Create the opened instances based on IPv6.
760 @param[in] This Pointer to EFI_DRIVER_BINDING_PROTOCOL.
761 @param[in] ControllerHandle Handle of the child to destroy.
762 @param[in] Private Handle Pointer to PXEBC_PRIVATE_DATA.
764 @retval EFI_SUCCESS The instances based on IPv6 were all created successfully.
765 @retval Others An unexpected error occurred.
769 PxeBcCreateIp6Children (
770 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
771 IN EFI_HANDLE ControllerHandle
,
772 IN PXEBC_PRIVATE_DATA
*Private
776 IPv6_DEVICE_PATH Ip6Node
;
777 EFI_UDP6_CONFIG_DATA
*Udp6CfgData
;
778 EFI_IP6_CONFIG_DATA
*Ip6CfgData
;
779 EFI_IP6_MODE_DATA Ip6ModeData
;
780 PXEBC_PRIVATE_PROTOCOL
*Id
;
781 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
783 if (Private
->Ip6Nic
!= NULL
) {
785 // Already created before.
790 Private
->Ip6Nic
= AllocateZeroPool (sizeof (PXEBC_VIRTUAL_NIC
));
792 if (Private
->Ip6Nic
== NULL
) {
793 return EFI_OUT_OF_RESOURCES
;
796 Private
->Ip6Nic
->Private
= Private
;
797 Private
->Ip6Nic
->Signature
= PXEBC_VIRTUAL_NIC_SIGNATURE
;
800 // Create Dhcp6 child and open Dhcp6 protocol for PxeBc->Dhcp.
802 Status
= NetLibCreateServiceChild (
804 This
->DriverBindingHandle
,
805 &gEfiDhcp6ServiceBindingProtocolGuid
,
808 if (EFI_ERROR (Status
)) {
812 Status
= gBS
->OpenProtocol (
814 &gEfiDhcp6ProtocolGuid
,
815 (VOID
**) &Private
->Dhcp6
,
816 This
->DriverBindingHandle
,
818 EFI_OPEN_PROTOCOL_BY_DRIVER
820 if (EFI_ERROR (Status
)) {
825 // Create Mtftp6 child and open Mtftp6 protocol for PxeBc->Mtftp.
827 Status
= NetLibCreateServiceChild (
829 This
->DriverBindingHandle
,
830 &gEfiMtftp6ServiceBindingProtocolGuid
,
831 &Private
->Mtftp6Child
833 if (EFI_ERROR (Status
)) {
837 Status
= gBS
->OpenProtocol (
838 Private
->Mtftp6Child
,
839 &gEfiMtftp6ProtocolGuid
,
840 (VOID
**) &Private
->Mtftp6
,
841 This
->DriverBindingHandle
,
843 EFI_OPEN_PROTOCOL_BY_DRIVER
845 if (EFI_ERROR (Status
)) {
850 // Create Udp6 child and open Udp6 protocol for PxeBc->UdpRead.
852 Status
= NetLibCreateServiceChild (
854 This
->DriverBindingHandle
,
855 &gEfiUdp6ServiceBindingProtocolGuid
,
856 &Private
->Udp6ReadChild
858 if (EFI_ERROR (Status
)) {
862 Status
= gBS
->OpenProtocol (
863 Private
->Udp6ReadChild
,
864 &gEfiUdp6ProtocolGuid
,
865 (VOID
**) &Private
->Udp6Read
,
866 This
->DriverBindingHandle
,
868 EFI_OPEN_PROTOCOL_BY_DRIVER
870 if (EFI_ERROR (Status
)) {
875 // Create Udp6 child and open Udp6 protocol for PxeBc->UdpWrite.
877 Status
= NetLibCreateServiceChild (
879 This
->DriverBindingHandle
,
880 &gEfiUdp6ServiceBindingProtocolGuid
,
881 &Private
->Udp6WriteChild
883 if (EFI_ERROR (Status
)) {
887 Status
= gBS
->OpenProtocol (
888 Private
->Udp6WriteChild
,
889 &gEfiUdp6ProtocolGuid
,
890 (VOID
**) &Private
->Udp6Write
,
891 This
->DriverBindingHandle
,
893 EFI_OPEN_PROTOCOL_BY_DRIVER
895 if (EFI_ERROR (Status
)) {
900 // Create Ip6 child and open Ip6 protocol for background ICMP6 packets.
902 Status
= NetLibCreateServiceChild (
904 This
->DriverBindingHandle
,
905 &gEfiIp6ServiceBindingProtocolGuid
,
908 if (EFI_ERROR (Status
)) {
912 Status
= gBS
->OpenProtocol (
914 &gEfiIp6ProtocolGuid
,
915 (VOID
**) &Private
->Ip6
,
916 This
->DriverBindingHandle
,
918 EFI_OPEN_PROTOCOL_BY_DRIVER
920 if (EFI_ERROR (Status
)) {
925 // Get max packet size from Ip6 to calculate block size for Tftp later.
927 Status
= Private
->Ip6
->GetModeData (Private
->Ip6
, &Ip6ModeData
, NULL
, NULL
);
928 if (EFI_ERROR (Status
)) {
932 Private
->Ip6MaxPacketSize
= Ip6ModeData
.MaxPacketSize
;
935 // Locate Ip6->Ip6Config and store it for set IPv6 address.
937 Status
= gBS
->HandleProtocol (
939 &gEfiIp6ConfigProtocolGuid
,
940 (VOID
**) &Private
->Ip6Cfg
942 if (EFI_ERROR (Status
)) {
947 // Create a device path node for Ipv6 virtual nic, and append it.
949 ZeroMem (&Ip6Node
, sizeof (IPv6_DEVICE_PATH
));
950 Ip6Node
.Header
.Type
= MESSAGING_DEVICE_PATH
;
951 Ip6Node
.Header
.SubType
= MSG_IPv6_DP
;
952 Ip6Node
.PrefixLength
= IP6_PREFIX_LENGTH
;
954 SetDevicePathNodeLength (&Ip6Node
.Header
, sizeof (Ip6Node
));
956 Private
->Ip6Nic
->DevicePath
= AppendDevicePathNode (Private
->DevicePath
, &Ip6Node
.Header
);
958 if (Private
->Ip6Nic
->DevicePath
== NULL
) {
959 Status
= EFI_OUT_OF_RESOURCES
;
964 &Private
->Ip6Nic
->LoadFile
,
965 &gLoadFileProtocolTemplate
,
966 sizeof (EFI_LOAD_FILE_PROTOCOL
)
970 // Create a new handle for IPv6 virtual nic,
971 // and install PxeBaseCode, LoadFile and DevicePath protocols.
973 Status
= gBS
->InstallMultipleProtocolInterfaces (
974 &Private
->Ip6Nic
->Controller
,
975 &gEfiDevicePathProtocolGuid
,
976 Private
->Ip6Nic
->DevicePath
,
977 &gEfiLoadFileProtocolGuid
,
978 &Private
->Ip6Nic
->LoadFile
,
979 &gEfiPxeBaseCodeProtocolGuid
,
983 if (EFI_ERROR (Status
)) {
987 if (Private
->Snp
!= NULL
) {
989 // Install SNP protocol on purpose is for some OS loader backward
990 // compatibility consideration.
992 Status
= gBS
->InstallProtocolInterface (
993 &Private
->Ip6Nic
->Controller
,
994 &gEfiSimpleNetworkProtocolGuid
,
995 EFI_NATIVE_INTERFACE
,
998 if (EFI_ERROR (Status
)) {
1003 // Open SNP on the child handle BY_DRIVER. It will prevent any additionally
1004 // layering to perform the experiment.
1006 Status
= gBS
->OpenProtocol (
1007 Private
->Ip6Nic
->Controller
,
1008 &gEfiSimpleNetworkProtocolGuid
,
1010 This
->DriverBindingHandle
,
1011 Private
->Ip6Nic
->Controller
,
1012 EFI_OPEN_PROTOCOL_BY_DRIVER
1014 if (EFI_ERROR (Status
)) {
1020 // Open PxeBaseCodePrivate protocol by child to setup a parent-child relationship between
1021 // real NIC handle and the virtual IPv6 NIC handle.
1023 Status
= gBS
->OpenProtocol (
1027 This
->DriverBindingHandle
,
1028 Private
->Ip6Nic
->Controller
,
1029 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1031 if (EFI_ERROR (Status
)) {
1036 // Set IPv6 avaiable flag and set default configure data for
1037 // Udp6Read and Ip6 instance.
1039 Private
->Mode
.Ipv6Available
= TRUE
;
1040 Udp6CfgData
= &Private
->Udp6CfgData
;
1041 Ip6CfgData
= &Private
->Ip6CfgData
;
1043 Udp6CfgData
->AcceptAnyPort
= TRUE
;
1044 Udp6CfgData
->AllowDuplicatePort
= TRUE
;
1045 Udp6CfgData
->HopLimit
= PXEBC_DEFAULT_HOPLIMIT
;
1046 Udp6CfgData
->ReceiveTimeout
= PXEBC_DEFAULT_LIFETIME
;
1047 Udp6CfgData
->TransmitTimeout
= PXEBC_DEFAULT_LIFETIME
;
1049 Ip6CfgData
->AcceptIcmpErrors
= TRUE
;
1050 Ip6CfgData
->DefaultProtocol
= IP6_ICMP
;
1051 Ip6CfgData
->HopLimit
= PXEBC_DEFAULT_HOPLIMIT
;
1052 Ip6CfgData
->ReceiveTimeout
= PXEBC_DEFAULT_LIFETIME
;
1053 Ip6CfgData
->TransmitTimeout
= PXEBC_DEFAULT_LIFETIME
;
1058 PxeBcDestroyIp6Children (This
, Private
);
1064 The entry point for UefiPxeBc driver that installs the driver
1065 binding and component name protocol on its image.
1067 @param[in] ImageHandle The Image handle of the driver.
1068 @param[in] SystemTable The system table.
1076 PxeBcDriverEntryPoint (
1077 IN EFI_HANDLE ImageHandle
,
1078 IN EFI_SYSTEM_TABLE
*SystemTable
1081 return EfiLibInstallDriverBindingComponentName2 (
1084 &gPxeBcDriverBinding
,
1086 &gPxeBcComponentName
,
1087 &gPxeBcComponentName2
1093 Test to see if this driver supports ControllerHandle. This service
1094 is called by the EFI boot service ConnectController(). In
1095 order to make drivers as small as possible, there are a few calling
1096 restrictions for this service. ConnectController() must
1097 follow these calling restrictions. If any other agent wishes to call
1098 Supported() it must also follow these calling restrictions.
1100 @param[in] This The pointer to the driver binding protocol.
1101 @param[in] ControllerHandle The handle of device to be tested.
1102 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
1103 device to be started.
1105 @retval EFI_SUCCESS This driver supports this device.
1106 @retval EFI_UNSUPPORTED This driver does not support this device.
1111 PxeBcDriverBindingSupported (
1112 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1113 IN EFI_HANDLE ControllerHandle
,
1114 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1117 EFI_STATUS Ip4Status
;
1118 EFI_STATUS Ip6Status
;
1121 // Try to open the Mtftp4 and Dhcp4 protocol to test whether IPv4 stack is ready.
1123 Ip4Status
= gBS
->OpenProtocol (
1125 &gEfiDhcp4ServiceBindingProtocolGuid
,
1127 This
->DriverBindingHandle
,
1129 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
1131 if (!EFI_ERROR (Ip4Status
)) {
1132 Ip4Status
= gBS
->OpenProtocol (
1134 &gEfiMtftp4ServiceBindingProtocolGuid
,
1136 This
->DriverBindingHandle
,
1138 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
1143 // Try to open the Mtftp6 and Dhcp6 protocol to test whether IPv4 stack is ready.
1145 Ip6Status
= gBS
->OpenProtocol (
1147 &gEfiDhcp6ServiceBindingProtocolGuid
,
1149 This
->DriverBindingHandle
,
1151 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
1153 if (!EFI_ERROR (Ip6Status
)) {
1154 Ip6Status
= gBS
->OpenProtocol (
1156 &gEfiMtftp6ServiceBindingProtocolGuid
,
1158 This
->DriverBindingHandle
,
1160 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
1165 // It's unsupported case if both stack are not ready.
1167 if (EFI_ERROR (Ip4Status
) && EFI_ERROR (Ip6Status
)) {
1168 return EFI_UNSUPPORTED
;
1176 Start this driver on ControllerHandle. This service is called by the
1177 EFI boot service ConnectController(). In order to make
1178 drivers as small as possible, there are a few calling restrictions for
1179 this service. ConnectController() must follow these
1180 calling restrictions. If any other agent wishes to call Start() it
1181 must also follow these calling restrictions.
1183 @param[in] This The pointer to the driver binding protocol.
1184 @param[in] ControllerHandle The handle of device to be started.
1185 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
1186 device to be started.
1188 @retval EFI_SUCCESS This driver is installed to ControllerHandle.
1189 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
1190 @retval other This driver does not support this device.
1195 PxeBcDriverBindingStart (
1196 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1197 IN EFI_HANDLE ControllerHandle
,
1198 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1201 PXEBC_PRIVATE_DATA
*Private
;
1203 EFI_STATUS Ip4Status
;
1204 EFI_STATUS Ip6Status
;
1205 PXEBC_PRIVATE_PROTOCOL
*Id
;
1207 Status
= gBS
->OpenProtocol (
1211 This
->DriverBindingHandle
,
1213 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1215 if (!EFI_ERROR (Status
)) {
1217 // Skip the initialization if the driver has been started already.
1219 Private
= PXEBC_PRIVATE_DATA_FROM_ID (Id
);
1222 // If the driver has not been started yet, it should do initialization.
1224 Private
= AllocateZeroPool (sizeof (PXEBC_PRIVATE_DATA
));
1225 if (Private
== NULL
) {
1226 return EFI_OUT_OF_RESOURCES
;
1231 &gPxeBcProtocolTemplate
,
1232 sizeof (EFI_PXE_BASE_CODE_PROTOCOL
)
1235 Private
->Signature
= PXEBC_PRIVATE_DATA_SIGNATURE
;
1236 Private
->Controller
= ControllerHandle
;
1237 Private
->Image
= This
->ImageHandle
;
1238 Private
->PxeBc
.Mode
= &Private
->Mode
;
1239 Private
->Mode
.Ipv6Supported
= TRUE
;
1240 Private
->Mode
.AutoArp
= TRUE
;
1241 Private
->Mode
.TTL
= DEFAULT_TTL
;
1242 Private
->Mode
.ToS
= DEFAULT_ToS
;
1245 // Open device path to prepare for appending virtual NIC node.
1247 Status
= gBS
->OpenProtocol (
1249 &gEfiDevicePathProtocolGuid
,
1250 (VOID
**) &Private
->DevicePath
,
1251 This
->DriverBindingHandle
,
1253 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1256 if (EFI_ERROR (Status
)) {
1261 // Get the NII interface if it exists, it's not required.
1263 Status
= gBS
->OpenProtocol (
1265 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
1266 (VOID
**) &Private
->Nii
,
1267 This
->DriverBindingHandle
,
1269 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1271 if (EFI_ERROR (Status
)) {
1272 Private
->Nii
= NULL
;
1276 // Install PxeBaseCodePrivate protocol onto the real NIC handler.
1277 // PxeBaseCodePrivate protocol is only used to keep the relationship between
1278 // NIC handle and virtual child handles.
1279 // gEfiCallerIdGuid will be used as its protocol guid.
1281 Status
= gBS
->InstallProtocolInterface (
1284 EFI_NATIVE_INTERFACE
,
1287 if (EFI_ERROR (Status
)) {
1292 // Try to locate SNP protocol.
1294 NetLibGetSnpHandle(ControllerHandle
, &Private
->Snp
);
1298 // Try to create virtual NIC handle for IPv4.
1300 Ip4Status
= PxeBcCreateIp4Children (This
, ControllerHandle
, Private
);
1303 // Try to create virtual NIC handle for IPv6.
1305 Ip6Status
= PxeBcCreateIp6Children (This
, ControllerHandle
, Private
);
1307 if (EFI_ERROR (Ip4Status
) && EFI_ERROR (Ip6Status
)) {
1309 // Failed to start PXE driver if IPv4 and IPv6 stack are both not available.
1311 Status
= EFI_DEVICE_ERROR
;
1318 gBS
->UninstallProtocolInterface (
1323 PxeBcDestroyIp4Children (This
, Private
);
1324 PxeBcDestroyIp6Children (This
, Private
);
1332 Stop this driver on ControllerHandle. This service is called by the
1333 EFI boot service DisconnectController(). In order to
1334 make drivers as small as possible, there are a few calling
1335 restrictions for this service. DisconnectController()
1336 must follow these calling restrictions. If any other agent wishes
1337 to call Stop() it must also follow these calling restrictions.
1339 @param[in] This Protocol instance pointer.
1340 @param[in] ControllerHandle Handle of device to stop driver on.
1341 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
1342 children is zero stop the entire bus driver.
1343 @param[in] ChildHandleBuffer List of Child Handles to Stop.
1345 @retval EFI_SUCCESS This driver was removed ControllerHandle.
1346 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
1347 @retval Others This driver was not removed from this device
1352 PxeBcDriverBindingStop (
1353 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1354 IN EFI_HANDLE ControllerHandle
,
1355 IN UINTN NumberOfChildren
,
1356 IN EFI_HANDLE
*ChildHandleBuffer
1359 PXEBC_PRIVATE_DATA
*Private
;
1360 PXEBC_VIRTUAL_NIC
*VirtualNic
;
1361 EFI_LOAD_FILE_PROTOCOL
*LoadFile
;
1363 EFI_HANDLE NicHandle
;
1365 PXEBC_PRIVATE_PROTOCOL
*Id
;
1374 Status
= gBS
->OpenProtocol (
1376 &gEfiLoadFileProtocolGuid
,
1377 (VOID
**) &LoadFile
,
1378 This
->DriverBindingHandle
,
1380 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1382 if (EFI_ERROR (Status
)) {
1384 // Get the Nic handle by any pass-over service child handle.
1386 NicHandle
= PxeBcGetNicByIp4Children (ControllerHandle
);
1387 if (NicHandle
== NULL
) {
1388 NicHandle
= PxeBcGetNicByIp6Children (ControllerHandle
);
1389 if (NicHandle
== NULL
) {
1390 return EFI_DEVICE_ERROR
;
1397 // Try to retrieve the private data by PxeBcPrivate protocol.
1399 Status
= gBS
->OpenProtocol (
1403 This
->DriverBindingHandle
,
1405 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1407 if (EFI_ERROR (Status
)) {
1410 Private
= PXEBC_PRIVATE_DATA_FROM_ID (Id
);
1414 // It's a virtual handle with LoadFileProtocol.
1416 Status
= gBS
->OpenProtocol (
1418 &gEfiLoadFileProtocolGuid
,
1419 (VOID
**) &LoadFile
,
1420 This
->DriverBindingHandle
,
1422 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1424 if (EFI_ERROR (Status
)) {
1428 VirtualNic
= PXEBC_VIRTUAL_NIC_FROM_LOADFILE (LoadFile
);
1429 Private
= VirtualNic
->Private
;
1430 NicHandle
= Private
->Controller
;
1432 if (Private
->Ip6Nic
== VirtualNic
) {
1438 // Stop functionality of PXE Base Code protocol
1440 Status
= Private
->PxeBc
.Stop (&Private
->PxeBc
);
1441 if (Status
!= EFI_SUCCESS
&& Status
!= EFI_NOT_STARTED
) {
1446 if (Private
->Ip4Nic
!= NULL
&& !IsIpv6
) {
1447 PxeBcDestroyIp4Children (This
, Private
);
1450 if (Private
->Ip6Nic
!= NULL
&& IsIpv6
) {
1451 PxeBcDestroyIp6Children (This
, Private
);
1454 if (Private
->Ip4Nic
== NULL
&& Private
->Ip6Nic
== NULL
) {
1455 gBS
->UninstallProtocolInterface (