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