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