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