VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c

Last change on this file was 108794, checked in by vboxsync, 4 weeks ago

Devices/EFI/FirmwareNew: Merge edk2-stable202502 from the vendor branch and make it build for the important platforms, bugref:4643

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette