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