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