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