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