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