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