]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c
Update dual network stack drivers to produce multiple Driver Binding Protocol.
[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 if (Private != NULL) {
1357 FreePool (Private);
1358 }
1359 }
1360
1361 if (IpVersion == IP_VERSION_4) {
1362 PxeBcDestroyIp4Children (This, Private);
1363 } else {
1364 PxeBcDestroyIp6Children (This, Private);
1365 }
1366
1367 return Status;
1368 }
1369
1370
1371 /**
1372 Stop this driver on ControllerHandle. This is the worker function for
1373 PxeBcIp4(6)DriverBindingStop.
1374
1375 @param[in] This Protocol instance pointer.
1376 @param[in] ControllerHandle Handle of device to stop driver on.
1377 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
1378 children is zero stop the entire bus driver.
1379 @param[in] ChildHandleBuffer List of Child Handles to Stop.
1380 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.
1381
1382 @retval EFI_SUCCESS This driver was removed ControllerHandle.
1383 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
1384 @retval Others This driver was not removed from this device
1385
1386 **/
1387 EFI_STATUS
1388 EFIAPI
1389 PxeBcStop (
1390 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1391 IN EFI_HANDLE ControllerHandle,
1392 IN UINTN NumberOfChildren,
1393 IN EFI_HANDLE *ChildHandleBuffer,
1394 IN UINT8 IpVersion
1395 )
1396 {
1397 PXEBC_PRIVATE_DATA *Private;
1398 PXEBC_VIRTUAL_NIC *VirtualNic;
1399 EFI_LOAD_FILE_PROTOCOL *LoadFile;
1400 EFI_STATUS Status;
1401 EFI_HANDLE NicHandle;
1402 BOOLEAN IsIpv6;
1403 PXEBC_PRIVATE_PROTOCOL *Id;
1404
1405 Private = NULL;
1406 NicHandle = NULL;
1407 VirtualNic = NULL;
1408 LoadFile = NULL;
1409 Id = NULL;
1410 IsIpv6 = FALSE;
1411
1412 Status = gBS->OpenProtocol (
1413 ControllerHandle,
1414 &gEfiLoadFileProtocolGuid,
1415 (VOID **) &LoadFile,
1416 This->DriverBindingHandle,
1417 ControllerHandle,
1418 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1419 );
1420 if (EFI_ERROR (Status)) {
1421 //
1422 // Get the Nic handle by any pass-over service child handle.
1423 //
1424 if (IpVersion == IP_VERSION_4) {
1425 NicHandle = PxeBcGetNicByIp4Children (ControllerHandle);
1426 } else {
1427 NicHandle = PxeBcGetNicByIp6Children (ControllerHandle);
1428 }
1429 if (NicHandle == NULL) {
1430 return EFI_SUCCESS;
1431 }
1432
1433 //
1434 // Try to retrieve the private data by PxeBcPrivate protocol.
1435 //
1436 Status = gBS->OpenProtocol (
1437 NicHandle,
1438 &gEfiCallerIdGuid,
1439 (VOID **) &Id,
1440 This->DriverBindingHandle,
1441 ControllerHandle,
1442 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1443 );
1444 if (EFI_ERROR (Status)) {
1445 return Status;
1446 }
1447 Private = PXEBC_PRIVATE_DATA_FROM_ID (Id);
1448
1449 } else {
1450 //
1451 // It's a virtual handle with LoadFileProtocol.
1452 //
1453 Status = gBS->OpenProtocol (
1454 ControllerHandle,
1455 &gEfiLoadFileProtocolGuid,
1456 (VOID **) &LoadFile,
1457 This->DriverBindingHandle,
1458 ControllerHandle,
1459 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1460 );
1461 if (EFI_ERROR (Status)) {
1462 return Status;
1463 }
1464
1465 VirtualNic = PXEBC_VIRTUAL_NIC_FROM_LOADFILE (LoadFile);
1466 Private = VirtualNic->Private;
1467 NicHandle = Private->Controller;
1468 }
1469
1470 //
1471 // Stop functionality of PXE Base Code protocol
1472 //
1473 Status = Private->PxeBc.Stop (&Private->PxeBc);
1474 if (Status != EFI_SUCCESS && Status != EFI_NOT_STARTED) {
1475 return Status;
1476 }
1477
1478
1479 if (Private->Ip4Nic != NULL && IpVersion == IP_VERSION_4) {
1480 PxeBcDestroyIp4Children (This, Private);
1481 }
1482
1483 if (Private->Ip6Nic != NULL && IpVersion == IP_VERSION_6) {
1484 PxeBcDestroyIp6Children (This, Private);
1485 }
1486
1487 if (Private->Ip4Nic == NULL && Private->Ip6Nic == NULL) {
1488 gBS->UninstallProtocolInterface (
1489 NicHandle,
1490 &gEfiCallerIdGuid,
1491 &Private->Id
1492 );
1493 FreePool (Private);
1494 }
1495
1496 return EFI_SUCCESS;
1497 }
1498
1499 /**
1500 Test to see if this driver supports ControllerHandle. This service
1501 is called by the EFI boot service ConnectController(). In
1502 order to make drivers as small as possible, there are a few calling
1503 restrictions for this service. ConnectController() must
1504 follow these calling restrictions. If any other agent wishes to call
1505 Supported() it must also follow these calling restrictions.
1506
1507 @param[in] This The pointer to the driver binding protocol.
1508 @param[in] ControllerHandle The handle of device to be tested.
1509 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
1510 device to be started.
1511
1512 @retval EFI_SUCCESS This driver supports this device.
1513 @retval EFI_UNSUPPORTED This driver does not support this device.
1514
1515 **/
1516 EFI_STATUS
1517 EFIAPI
1518 PxeBcIp4DriverBindingSupported (
1519 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1520 IN EFI_HANDLE ControllerHandle,
1521 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
1522 )
1523 {
1524 return PxeBcSupported (
1525 This,
1526 ControllerHandle,
1527 RemainingDevicePath,
1528 IP_VERSION_4
1529 );
1530 }
1531
1532 /**
1533 Start this driver on ControllerHandle. This service is called by the
1534 EFI boot service ConnectController(). In order to make
1535 drivers as small as possible, there are a few calling restrictions for
1536 this service. ConnectController() must follow these
1537 calling restrictions. If any other agent wishes to call Start() it
1538 must also follow these calling restrictions.
1539
1540 @param[in] This The pointer to the driver binding protocol.
1541 @param[in] ControllerHandle The handle of device to be started.
1542 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
1543 device to be started.
1544
1545 @retval EFI_SUCCESS This driver is installed to ControllerHandle.
1546 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
1547 @retval other This driver does not support this device.
1548
1549 **/
1550 EFI_STATUS
1551 EFIAPI
1552 PxeBcIp4DriverBindingStart (
1553 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1554 IN EFI_HANDLE ControllerHandle,
1555 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
1556 )
1557 {
1558 return PxeBcStart (
1559 This,
1560 ControllerHandle,
1561 RemainingDevicePath,
1562 IP_VERSION_4
1563 );
1564 }
1565
1566 /**
1567 Stop this driver on ControllerHandle. This service is called by the
1568 EFI boot service DisconnectController(). In order to
1569 make drivers as small as possible, there are a few calling
1570 restrictions for this service. DisconnectController()
1571 must follow these calling restrictions. If any other agent wishes
1572 to call Stop() it must also follow these calling restrictions.
1573
1574 @param[in] This Protocol instance pointer.
1575 @param[in] ControllerHandle Handle of device to stop driver on
1576 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
1577 children is zero stop the entire bus driver.
1578 @param[in] ChildHandleBuffer List of Child Handles to Stop.
1579
1580 @retval EFI_SUCCESS This driver is removed ControllerHandle
1581 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
1582 @retval Others This driver was not removed from this device.
1583
1584 **/
1585 EFI_STATUS
1586 EFIAPI
1587 PxeBcIp4DriverBindingStop (
1588 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1589 IN EFI_HANDLE ControllerHandle,
1590 IN UINTN NumberOfChildren,
1591 IN EFI_HANDLE *ChildHandleBuffer
1592 )
1593 {
1594 return PxeBcStop (
1595 This,
1596 ControllerHandle,
1597 NumberOfChildren,
1598 ChildHandleBuffer,
1599 IP_VERSION_4
1600 );
1601 }
1602
1603 /**
1604 Test to see if this driver supports ControllerHandle. This service
1605 is called by the EFI boot service ConnectController(). In
1606 order to make drivers as small as possible, there are a few calling
1607 restrictions for this service. ConnectController() must
1608 follow these calling restrictions. If any other agent wishes to call
1609 Supported() it must also follow these calling restrictions.
1610
1611 @param[in] This The pointer to the driver binding protocol.
1612 @param[in] ControllerHandle The handle of device to be tested.
1613 @param[in] RemainingDevicePath Optional parameter use to pick a specific child
1614 device to be started.
1615
1616 @retval EFI_SUCCESS This driver supports this device.
1617 @retval EFI_UNSUPPORTED This driver does not support this device.
1618
1619 **/
1620 EFI_STATUS
1621 EFIAPI
1622 PxeBcIp6DriverBindingSupported (
1623 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1624 IN EFI_HANDLE ControllerHandle,
1625 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
1626 )
1627 {
1628 return PxeBcSupported (
1629 This,
1630 ControllerHandle,
1631 RemainingDevicePath,
1632 IP_VERSION_6
1633 );
1634 }
1635
1636 /**
1637 Start this driver on ControllerHandle. This service is called by the
1638 EFI boot service ConnectController(). In order to make
1639 drivers as small as possible, there are a few calling restrictions for
1640 this service. ConnectController() must follow these
1641 calling restrictions. If any other agent wishes to call Start() it
1642 must also follow these calling restrictions.
1643
1644 @param[in] This The pointer to the driver binding protocol.
1645 @param[in] ControllerHandle The handle of device to be started.
1646 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
1647 device to be started.
1648
1649 @retval EFI_SUCCESS This driver is installed to ControllerHandle.
1650 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
1651 @retval other This driver does not support this device.
1652
1653 **/
1654 EFI_STATUS
1655 EFIAPI
1656 PxeBcIp6DriverBindingStart (
1657 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1658 IN EFI_HANDLE ControllerHandle,
1659 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
1660 )
1661 {
1662 return PxeBcStart (
1663 This,
1664 ControllerHandle,
1665 RemainingDevicePath,
1666 IP_VERSION_6
1667 );
1668 }
1669
1670 /**
1671 Stop this driver on ControllerHandle. This service is called by the
1672 EFI boot service DisconnectController(). In order to
1673 make drivers as small as possible, there are a few calling
1674 restrictions for this service. DisconnectController()
1675 must follow these calling restrictions. If any other agent wishes
1676 to call Stop() it must also follow these calling restrictions.
1677
1678 @param[in] This Protocol instance pointer.
1679 @param[in] ControllerHandle Handle of device to stop driver on
1680 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
1681 children is zero stop the entire bus driver.
1682 @param[in] ChildHandleBuffer List of Child Handles to Stop.
1683
1684 @retval EFI_SUCCESS This driver is removed ControllerHandle
1685 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
1686 @retval Others This driver was not removed from this device.
1687
1688 **/
1689 EFI_STATUS
1690 EFIAPI
1691 PxeBcIp6DriverBindingStop (
1692 IN EFI_DRIVER_BINDING_PROTOCOL *This,
1693 IN EFI_HANDLE ControllerHandle,
1694 IN UINTN NumberOfChildren,
1695 IN EFI_HANDLE *ChildHandleBuffer
1696 )
1697 {
1698 return PxeBcStop (
1699 This,
1700 ControllerHandle,
1701 NumberOfChildren,
1702 ChildHandleBuffer,
1703 IP_VERSION_6
1704 );
1705 }