2 Driver Binding functions implementationfor for UefiPxeBc Driver.
4 Copyright (c) 2007 - 2012, 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
;
784 if (Private
->Ip6Nic
!= NULL
) {
786 // Already created before.
791 Private
->Ip6Nic
= AllocateZeroPool (sizeof (PXEBC_VIRTUAL_NIC
));
793 if (Private
->Ip6Nic
== NULL
) {
794 return EFI_OUT_OF_RESOURCES
;
797 Private
->Ip6Nic
->Private
= Private
;
798 Private
->Ip6Nic
->Signature
= PXEBC_VIRTUAL_NIC_SIGNATURE
;
801 // Create Dhcp6 child and open Dhcp6 protocol for PxeBc->Dhcp.
803 Status
= NetLibCreateServiceChild (
805 This
->DriverBindingHandle
,
806 &gEfiDhcp6ServiceBindingProtocolGuid
,
809 if (EFI_ERROR (Status
)) {
813 Status
= gBS
->OpenProtocol (
815 &gEfiDhcp6ProtocolGuid
,
816 (VOID
**) &Private
->Dhcp6
,
817 This
->DriverBindingHandle
,
819 EFI_OPEN_PROTOCOL_BY_DRIVER
821 if (EFI_ERROR (Status
)) {
826 // Generate a random IAID for the Dhcp6 assigned address.
828 Private
->IaId
= NET_RANDOM (NetRandomInitSeed ());
829 if (Private
->Snp
!= NULL
) {
830 for (Index
= 0; Index
< Private
->Snp
->Mode
->HwAddressSize
; Index
++) {
831 Private
->IaId
|= (Private
->Snp
->Mode
->CurrentAddress
.Addr
[Index
] << ((Index
<< 3) & 31));
836 // Create Mtftp6 child and open Mtftp6 protocol for PxeBc->Mtftp.
838 Status
= NetLibCreateServiceChild (
840 This
->DriverBindingHandle
,
841 &gEfiMtftp6ServiceBindingProtocolGuid
,
842 &Private
->Mtftp6Child
844 if (EFI_ERROR (Status
)) {
848 Status
= gBS
->OpenProtocol (
849 Private
->Mtftp6Child
,
850 &gEfiMtftp6ProtocolGuid
,
851 (VOID
**) &Private
->Mtftp6
,
852 This
->DriverBindingHandle
,
854 EFI_OPEN_PROTOCOL_BY_DRIVER
856 if (EFI_ERROR (Status
)) {
861 // Create Udp6 child and open Udp6 protocol for PxeBc->UdpRead.
863 Status
= NetLibCreateServiceChild (
865 This
->DriverBindingHandle
,
866 &gEfiUdp6ServiceBindingProtocolGuid
,
867 &Private
->Udp6ReadChild
869 if (EFI_ERROR (Status
)) {
873 Status
= gBS
->OpenProtocol (
874 Private
->Udp6ReadChild
,
875 &gEfiUdp6ProtocolGuid
,
876 (VOID
**) &Private
->Udp6Read
,
877 This
->DriverBindingHandle
,
879 EFI_OPEN_PROTOCOL_BY_DRIVER
881 if (EFI_ERROR (Status
)) {
886 // Create Udp6 child and open Udp6 protocol for PxeBc->UdpWrite.
888 Status
= NetLibCreateServiceChild (
890 This
->DriverBindingHandle
,
891 &gEfiUdp6ServiceBindingProtocolGuid
,
892 &Private
->Udp6WriteChild
894 if (EFI_ERROR (Status
)) {
898 Status
= gBS
->OpenProtocol (
899 Private
->Udp6WriteChild
,
900 &gEfiUdp6ProtocolGuid
,
901 (VOID
**) &Private
->Udp6Write
,
902 This
->DriverBindingHandle
,
904 EFI_OPEN_PROTOCOL_BY_DRIVER
906 if (EFI_ERROR (Status
)) {
911 // Create Ip6 child and open Ip6 protocol for background ICMP6 packets.
913 Status
= NetLibCreateServiceChild (
915 This
->DriverBindingHandle
,
916 &gEfiIp6ServiceBindingProtocolGuid
,
919 if (EFI_ERROR (Status
)) {
923 Status
= gBS
->OpenProtocol (
925 &gEfiIp6ProtocolGuid
,
926 (VOID
**) &Private
->Ip6
,
927 This
->DriverBindingHandle
,
929 EFI_OPEN_PROTOCOL_BY_DRIVER
931 if (EFI_ERROR (Status
)) {
936 // Get max packet size from Ip6 to calculate block size for Tftp later.
938 Status
= Private
->Ip6
->GetModeData (Private
->Ip6
, &Ip6ModeData
, NULL
, NULL
);
939 if (EFI_ERROR (Status
)) {
943 Private
->Ip6MaxPacketSize
= Ip6ModeData
.MaxPacketSize
;
946 // Locate Ip6->Ip6Config and store it for set IPv6 address.
948 Status
= gBS
->HandleProtocol (
950 &gEfiIp6ConfigProtocolGuid
,
951 (VOID
**) &Private
->Ip6Cfg
953 if (EFI_ERROR (Status
)) {
958 // Create a device path node for Ipv6 virtual nic, and append it.
960 ZeroMem (&Ip6Node
, sizeof (IPv6_DEVICE_PATH
));
961 Ip6Node
.Header
.Type
= MESSAGING_DEVICE_PATH
;
962 Ip6Node
.Header
.SubType
= MSG_IPv6_DP
;
963 Ip6Node
.PrefixLength
= IP6_PREFIX_LENGTH
;
965 SetDevicePathNodeLength (&Ip6Node
.Header
, sizeof (Ip6Node
));
967 Private
->Ip6Nic
->DevicePath
= AppendDevicePathNode (Private
->DevicePath
, &Ip6Node
.Header
);
969 if (Private
->Ip6Nic
->DevicePath
== NULL
) {
970 Status
= EFI_OUT_OF_RESOURCES
;
975 &Private
->Ip6Nic
->LoadFile
,
976 &gLoadFileProtocolTemplate
,
977 sizeof (EFI_LOAD_FILE_PROTOCOL
)
981 // Create a new handle for IPv6 virtual nic,
982 // and install PxeBaseCode, LoadFile and DevicePath protocols.
984 Status
= gBS
->InstallMultipleProtocolInterfaces (
985 &Private
->Ip6Nic
->Controller
,
986 &gEfiDevicePathProtocolGuid
,
987 Private
->Ip6Nic
->DevicePath
,
988 &gEfiLoadFileProtocolGuid
,
989 &Private
->Ip6Nic
->LoadFile
,
990 &gEfiPxeBaseCodeProtocolGuid
,
994 if (EFI_ERROR (Status
)) {
998 if (Private
->Snp
!= NULL
) {
1000 // Install SNP protocol on purpose is for some OS loader backward
1001 // compatibility consideration.
1003 Status
= gBS
->InstallProtocolInterface (
1004 &Private
->Ip6Nic
->Controller
,
1005 &gEfiSimpleNetworkProtocolGuid
,
1006 EFI_NATIVE_INTERFACE
,
1009 if (EFI_ERROR (Status
)) {
1014 // Open SNP on the child handle BY_DRIVER. It will prevent any additionally
1015 // layering to perform the experiment.
1017 Status
= gBS
->OpenProtocol (
1018 Private
->Ip6Nic
->Controller
,
1019 &gEfiSimpleNetworkProtocolGuid
,
1021 This
->DriverBindingHandle
,
1022 Private
->Ip6Nic
->Controller
,
1023 EFI_OPEN_PROTOCOL_BY_DRIVER
1025 if (EFI_ERROR (Status
)) {
1031 // Open PxeBaseCodePrivate protocol by child to setup a parent-child relationship between
1032 // real NIC handle and the virtual IPv6 NIC handle.
1034 Status
= gBS
->OpenProtocol (
1038 This
->DriverBindingHandle
,
1039 Private
->Ip6Nic
->Controller
,
1040 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1042 if (EFI_ERROR (Status
)) {
1047 // Set IPv6 avaiable flag and set default configure data for
1048 // Udp6Read and Ip6 instance.
1050 Private
->Mode
.Ipv6Available
= TRUE
;
1051 Udp6CfgData
= &Private
->Udp6CfgData
;
1052 Ip6CfgData
= &Private
->Ip6CfgData
;
1054 Udp6CfgData
->AcceptAnyPort
= TRUE
;
1055 Udp6CfgData
->AllowDuplicatePort
= TRUE
;
1056 Udp6CfgData
->HopLimit
= PXEBC_DEFAULT_HOPLIMIT
;
1057 Udp6CfgData
->ReceiveTimeout
= PXEBC_DEFAULT_LIFETIME
;
1058 Udp6CfgData
->TransmitTimeout
= PXEBC_DEFAULT_LIFETIME
;
1060 Ip6CfgData
->AcceptIcmpErrors
= TRUE
;
1061 Ip6CfgData
->DefaultProtocol
= IP6_ICMP
;
1062 Ip6CfgData
->HopLimit
= PXEBC_DEFAULT_HOPLIMIT
;
1063 Ip6CfgData
->ReceiveTimeout
= PXEBC_DEFAULT_LIFETIME
;
1064 Ip6CfgData
->TransmitTimeout
= PXEBC_DEFAULT_LIFETIME
;
1069 PxeBcDestroyIp6Children (This
, Private
);
1075 The entry point for UefiPxeBc driver that installs the driver
1076 binding and component name protocol on its image.
1078 @param[in] ImageHandle The Image handle of the driver.
1079 @param[in] SystemTable The system table.
1087 PxeBcDriverEntryPoint (
1088 IN EFI_HANDLE ImageHandle
,
1089 IN EFI_SYSTEM_TABLE
*SystemTable
1092 return EfiLibInstallDriverBindingComponentName2 (
1095 &gPxeBcDriverBinding
,
1097 &gPxeBcComponentName
,
1098 &gPxeBcComponentName2
1104 Test to see if this driver supports ControllerHandle. This service
1105 is called by the EFI boot service ConnectController(). In
1106 order to make drivers as small as possible, there are a few calling
1107 restrictions for this service. ConnectController() must
1108 follow these calling restrictions. If any other agent wishes to call
1109 Supported() it must also follow these calling restrictions.
1111 @param[in] This The pointer to the driver binding protocol.
1112 @param[in] ControllerHandle The handle of device to be tested.
1113 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
1114 device to be started.
1116 @retval EFI_SUCCESS This driver supports this device.
1117 @retval EFI_UNSUPPORTED This driver does not support this device.
1122 PxeBcDriverBindingSupported (
1123 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1124 IN EFI_HANDLE ControllerHandle
,
1125 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1128 EFI_STATUS Ip4Status
;
1129 EFI_STATUS Ip6Status
;
1132 // Try to open the Mtftp4 and Dhcp4 protocol to test whether IPv4 stack is ready.
1134 Ip4Status
= gBS
->OpenProtocol (
1136 &gEfiDhcp4ServiceBindingProtocolGuid
,
1138 This
->DriverBindingHandle
,
1140 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
1142 if (!EFI_ERROR (Ip4Status
)) {
1143 Ip4Status
= gBS
->OpenProtocol (
1145 &gEfiMtftp4ServiceBindingProtocolGuid
,
1147 This
->DriverBindingHandle
,
1149 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
1154 // Try to open the Mtftp6 and Dhcp6 protocol to test whether IPv4 stack is ready.
1156 Ip6Status
= gBS
->OpenProtocol (
1158 &gEfiDhcp6ServiceBindingProtocolGuid
,
1160 This
->DriverBindingHandle
,
1162 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
1164 if (!EFI_ERROR (Ip6Status
)) {
1165 Ip6Status
= gBS
->OpenProtocol (
1167 &gEfiMtftp6ServiceBindingProtocolGuid
,
1169 This
->DriverBindingHandle
,
1171 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
1176 // It's unsupported case if both stack are not ready.
1178 if (EFI_ERROR (Ip4Status
) && EFI_ERROR (Ip6Status
)) {
1179 return EFI_UNSUPPORTED
;
1187 Start this driver on ControllerHandle. This service is called by the
1188 EFI boot service ConnectController(). In order to make
1189 drivers as small as possible, there are a few calling restrictions for
1190 this service. ConnectController() must follow these
1191 calling restrictions. If any other agent wishes to call Start() it
1192 must also follow these calling restrictions.
1194 @param[in] This The pointer to the driver binding protocol.
1195 @param[in] ControllerHandle The handle of device to be started.
1196 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
1197 device to be started.
1199 @retval EFI_SUCCESS This driver is installed to ControllerHandle.
1200 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
1201 @retval other This driver does not support this device.
1206 PxeBcDriverBindingStart (
1207 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1208 IN EFI_HANDLE ControllerHandle
,
1209 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
1212 PXEBC_PRIVATE_DATA
*Private
;
1214 EFI_STATUS Ip4Status
;
1215 EFI_STATUS Ip6Status
;
1216 PXEBC_PRIVATE_PROTOCOL
*Id
;
1218 Status
= gBS
->OpenProtocol (
1222 This
->DriverBindingHandle
,
1224 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1226 if (!EFI_ERROR (Status
)) {
1228 // Skip the initialization if the driver has been started already.
1230 Private
= PXEBC_PRIVATE_DATA_FROM_ID (Id
);
1233 // If the driver has not been started yet, it should do initialization.
1235 Private
= AllocateZeroPool (sizeof (PXEBC_PRIVATE_DATA
));
1236 if (Private
== NULL
) {
1237 return EFI_OUT_OF_RESOURCES
;
1242 &gPxeBcProtocolTemplate
,
1243 sizeof (EFI_PXE_BASE_CODE_PROTOCOL
)
1246 Private
->Signature
= PXEBC_PRIVATE_DATA_SIGNATURE
;
1247 Private
->Controller
= ControllerHandle
;
1248 Private
->Image
= This
->ImageHandle
;
1249 Private
->PxeBc
.Mode
= &Private
->Mode
;
1250 Private
->Mode
.Ipv6Supported
= TRUE
;
1251 Private
->Mode
.AutoArp
= TRUE
;
1252 Private
->Mode
.TTL
= DEFAULT_TTL
;
1253 Private
->Mode
.ToS
= DEFAULT_ToS
;
1256 // Open device path to prepare for appending virtual NIC node.
1258 Status
= gBS
->OpenProtocol (
1260 &gEfiDevicePathProtocolGuid
,
1261 (VOID
**) &Private
->DevicePath
,
1262 This
->DriverBindingHandle
,
1264 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1267 if (EFI_ERROR (Status
)) {
1272 // Get the NII interface if it exists, it's not required.
1274 Status
= gBS
->OpenProtocol (
1276 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
1277 (VOID
**) &Private
->Nii
,
1278 This
->DriverBindingHandle
,
1280 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1282 if (EFI_ERROR (Status
)) {
1283 Private
->Nii
= NULL
;
1287 // Install PxeBaseCodePrivate protocol onto the real NIC handler.
1288 // PxeBaseCodePrivate protocol is only used to keep the relationship between
1289 // NIC handle and virtual child handles.
1290 // gEfiCallerIdGuid will be used as its protocol guid.
1292 Status
= gBS
->InstallProtocolInterface (
1295 EFI_NATIVE_INTERFACE
,
1298 if (EFI_ERROR (Status
)) {
1303 // Try to locate SNP protocol.
1305 NetLibGetSnpHandle(ControllerHandle
, &Private
->Snp
);
1309 // Try to create virtual NIC handle for IPv4.
1311 Ip4Status
= PxeBcCreateIp4Children (This
, ControllerHandle
, Private
);
1314 // Try to create virtual NIC handle for IPv6.
1316 Ip6Status
= PxeBcCreateIp6Children (This
, ControllerHandle
, Private
);
1318 if (EFI_ERROR (Ip4Status
) && EFI_ERROR (Ip6Status
)) {
1320 // Failed to start PXE driver if IPv4 and IPv6 stack are both not available.
1322 Status
= EFI_DEVICE_ERROR
;
1329 gBS
->UninstallProtocolInterface (
1334 PxeBcDestroyIp4Children (This
, Private
);
1335 PxeBcDestroyIp6Children (This
, Private
);
1343 Stop this driver on ControllerHandle. This service is called by the
1344 EFI boot service DisconnectController(). In order to
1345 make drivers as small as possible, there are a few calling
1346 restrictions for this service. DisconnectController()
1347 must follow these calling restrictions. If any other agent wishes
1348 to call Stop() it must also follow these calling restrictions.
1350 @param[in] This Protocol instance pointer.
1351 @param[in] ControllerHandle Handle of device to stop driver on.
1352 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
1353 children is zero stop the entire bus driver.
1354 @param[in] ChildHandleBuffer List of Child Handles to Stop.
1356 @retval EFI_SUCCESS This driver was removed ControllerHandle.
1357 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
1358 @retval Others This driver was not removed from this device
1363 PxeBcDriverBindingStop (
1364 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1365 IN EFI_HANDLE ControllerHandle
,
1366 IN UINTN NumberOfChildren
,
1367 IN EFI_HANDLE
*ChildHandleBuffer
1370 PXEBC_PRIVATE_DATA
*Private
;
1371 PXEBC_VIRTUAL_NIC
*VirtualNic
;
1372 EFI_LOAD_FILE_PROTOCOL
*LoadFile
;
1374 EFI_HANDLE NicHandle
;
1376 PXEBC_PRIVATE_PROTOCOL
*Id
;
1385 Status
= gBS
->OpenProtocol (
1387 &gEfiLoadFileProtocolGuid
,
1388 (VOID
**) &LoadFile
,
1389 This
->DriverBindingHandle
,
1391 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1393 if (EFI_ERROR (Status
)) {
1395 // Get the Nic handle by any pass-over service child handle.
1397 NicHandle
= PxeBcGetNicByIp4Children (ControllerHandle
);
1398 if (NicHandle
== NULL
) {
1399 NicHandle
= PxeBcGetNicByIp6Children (ControllerHandle
);
1400 if (NicHandle
== NULL
) {
1408 // Try to retrieve the private data by PxeBcPrivate protocol.
1410 Status
= gBS
->OpenProtocol (
1414 This
->DriverBindingHandle
,
1416 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1418 if (EFI_ERROR (Status
)) {
1421 Private
= PXEBC_PRIVATE_DATA_FROM_ID (Id
);
1425 // It's a virtual handle with LoadFileProtocol.
1427 Status
= gBS
->OpenProtocol (
1429 &gEfiLoadFileProtocolGuid
,
1430 (VOID
**) &LoadFile
,
1431 This
->DriverBindingHandle
,
1433 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1435 if (EFI_ERROR (Status
)) {
1439 VirtualNic
= PXEBC_VIRTUAL_NIC_FROM_LOADFILE (LoadFile
);
1440 Private
= VirtualNic
->Private
;
1441 NicHandle
= Private
->Controller
;
1443 if (Private
->Ip6Nic
== VirtualNic
) {
1449 // Stop functionality of PXE Base Code protocol
1451 Status
= Private
->PxeBc
.Stop (&Private
->PxeBc
);
1452 if (Status
!= EFI_SUCCESS
&& Status
!= EFI_NOT_STARTED
) {
1457 if (Private
->Ip4Nic
!= NULL
&& !IsIpv6
) {
1458 PxeBcDestroyIp4Children (This
, Private
);
1461 if (Private
->Ip6Nic
!= NULL
&& IsIpv6
) {
1462 PxeBcDestroyIp6Children (This
, Private
);
1465 if (Private
->Ip4Nic
== NULL
&& Private
->Ip6Nic
== NULL
) {
1466 gBS
->UninstallProtocolInterface (