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 - 2015, 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 Check whether UNDI protocol supports IPv6. 447 448 @param[in] ControllerHandle Controller handle. 449 @param[in] Private Pointer to PXEBC_PRIVATE_DATA. 450 @param[out] Ipv6Support TRUE if UNDI supports IPv6. 451 452 @retval EFI_SUCCESS Get the result whether UNDI supports IPv6 by NII or AIP protocol successfully. 453 @retval EFI_NOT_FOUND Don't know whether UNDI supports IPv6 since NII or AIP is not available. 454 455 **/ 456 EFI_STATUS 457 PxeBcCheckIpv6Support ( 458 IN EFI_HANDLE ControllerHandle, 459 IN PXEBC_PRIVATE_DATA *Private, 460 OUT BOOLEAN *Ipv6Support 461 ) 462 { 463 EFI_HANDLE Handle; 464 EFI_ADAPTER_INFORMATION_PROTOCOL *Aip; 465 EFI_STATUS Status; 466 EFI_GUID *InfoTypesBuffer; 467 UINTN InfoTypeBufferCount; 468 UINTN TypeIndex; 469 BOOLEAN Supported; 470 VOID *InfoBlock; 471 UINTN InfoBlockSize; 472 473 ASSERT (Private != NULL && Ipv6Support != NULL); 474 475 // 476 // Check whether the UNDI supports IPv6 by NII protocol. 477 // 478 if (Private->Nii != NULL) { 479 *Ipv6Support = Private->Nii->Ipv6Supported; 480 return EFI_SUCCESS; 481 } 482 483 // 484 // Check whether the UNDI supports IPv6 by AIP protocol. 485 // 486 487 // 488 // Get the NIC handle by SNP protocol. 489 // 490 Handle = NetLibGetSnpHandle (ControllerHandle, NULL); 491 if (Handle == NULL) { 492 return EFI_NOT_FOUND; 493 } 494 495 Aip = NULL; 496 Status = gBS->HandleProtocol ( 497 Handle, 498 &gEfiAdapterInformationProtocolGuid, 499 (VOID *) &Aip 500 ); 501 if (EFI_ERROR (Status) || Aip == NULL) { 502 return EFI_NOT_FOUND; 503 } 504 505 InfoTypesBuffer = NULL; 506 InfoTypeBufferCount = 0; 507 Status = Aip->GetSupportedTypes (Aip, &InfoTypesBuffer, &InfoTypeBufferCount); 508 if (EFI_ERROR (Status) || InfoTypesBuffer == NULL) { 509 FreePool (InfoTypesBuffer); 510 return EFI_NOT_FOUND; 511 } 512 513 Supported = FALSE; 514 for (TypeIndex = 0; TypeIndex < InfoTypeBufferCount; TypeIndex++) { 515 if (CompareGuid (&InfoTypesBuffer[TypeIndex], &gEfiAdapterInfoUndiIpv6SupportGuid)) { 516 Supported = TRUE; 517 break; 518 } 519 } 520 521 FreePool (InfoTypesBuffer); 522 if (!Supported) { 523 return EFI_NOT_FOUND; 524 } 525 526 // 527 // We now have adapter information block. 528 // 529 InfoBlock = NULL; 530 InfoBlockSize = 0; 531 Status = Aip->GetInformation (Aip, &gEfiAdapterInfoUndiIpv6SupportGuid, &InfoBlock, &InfoBlockSize); 532 if (EFI_ERROR (Status) || InfoBlock == NULL) { 533 FreePool (InfoBlock); 534 return EFI_NOT_FOUND; 535 } 536 537 *Ipv6Support = ((EFI_ADAPTER_INFO_UNDI_IPV6_SUPPORT *) InfoBlock)->Ipv6Support; 538 FreePool (InfoBlock); 539 return EFI_SUCCESS; 540 541 } 542 543 /** 544 Create the opened instances based on IPv4. 545 546 @param[in] This Pointer to EFI_DRIVER_BINDING_PROTOCOL. 547 @param[in] ControllerHandle Handle of the child to destroy. 548 @param[in] Private Handle Pointer to PXEBC_PRIVATE_DATA. 549 550 @retval EFI_SUCCESS The instances based on IPv4 were all created successfully. 551 @retval Others An unexpected error occurred. 552 553 **/ 554 EFI_STATUS 555 PxeBcCreateIp4Children ( 556 IN EFI_DRIVER_BINDING_PROTOCOL *This, 557 IN EFI_HANDLE ControllerHandle, 558 IN PXEBC_PRIVATE_DATA *Private 559 ) 560 { 561 EFI_STATUS Status; 562 IPv4_DEVICE_PATH Ip4Node; 563 EFI_PXE_BASE_CODE_MODE *Mode; 564 EFI_UDP4_CONFIG_DATA *Udp4CfgData; 565 EFI_IP4_CONFIG_DATA *Ip4CfgData; 566 EFI_IP4_MODE_DATA Ip4ModeData; 567 PXEBC_PRIVATE_PROTOCOL *Id; 568 EFI_SIMPLE_NETWORK_PROTOCOL *Snp; 569 570 if (Private->Ip4Nic != NULL) { 571 // 572 // Already created before. 573 // 574 return EFI_SUCCESS; 575 } 576 577 // 578 // Create Dhcp4 child and open Dhcp4 protocol for PxeBc->Dhcp. 579 // 580 Status = NetLibCreateServiceChild ( 581 ControllerHandle, 582 This->DriverBindingHandle, 583 &gEfiDhcp4ServiceBindingProtocolGuid, 584 &Private->Dhcp4Child 585 ); 586 if (EFI_ERROR (Status)) { 587 goto ON_ERROR; 588 } 589 590 Status = gBS->OpenProtocol ( 591 Private->Dhcp4Child, 592 &gEfiDhcp4ProtocolGuid, 593 (VOID **) &Private->Dhcp4, 594 This->DriverBindingHandle, 595 ControllerHandle, 596 EFI_OPEN_PROTOCOL_BY_DRIVER 597 ); 598 if (EFI_ERROR (Status)) { 599 goto ON_ERROR; 600 } 601 602 // 603 // Create Mtftp4 child and open Mtftp4 protocol for PxeBc->Mtftp. 604 // 605 Status = NetLibCreateServiceChild ( 606 ControllerHandle, 607 This->DriverBindingHandle, 608 &gEfiMtftp4ServiceBindingProtocolGuid, 609 &Private->Mtftp4Child 610 ); 611 if (EFI_ERROR (Status)) { 612 goto ON_ERROR; 613 } 614 615 Status = gBS->OpenProtocol ( 616 Private->Mtftp4Child, 617 &gEfiMtftp4ProtocolGuid, 618 (VOID **) &Private->Mtftp4, 619 This->DriverBindingHandle, 620 ControllerHandle, 621 EFI_OPEN_PROTOCOL_BY_DRIVER 622 ); 623 if (EFI_ERROR (Status)) { 624 goto ON_ERROR; 625 } 626 627 // 628 // Create Udp4 child and open Udp4 protocol for PxeBc->UdpRead. 629 // 630 Status = NetLibCreateServiceChild ( 631 ControllerHandle, 632 This->DriverBindingHandle, 633 &gEfiUdp4ServiceBindingProtocolGuid, 634 &Private->Udp4ReadChild 635 ); 636 if (EFI_ERROR (Status)) { 637 goto ON_ERROR; 638 } 639 640 Status = gBS->OpenProtocol ( 641 Private->Udp4ReadChild, 642 &gEfiUdp4ProtocolGuid, 643 (VOID **) &Private->Udp4Read, 644 This->DriverBindingHandle, 645 ControllerHandle, 646 EFI_OPEN_PROTOCOL_BY_DRIVER 647 ); 648 if (EFI_ERROR (Status)) { 649 goto ON_ERROR; 650 } 651 652 // 653 // Create Udp4 child and open Udp4 protocol for PxeBc->UdpWrite. 654 // 655 Status = NetLibCreateServiceChild ( 656 ControllerHandle, 657 This->DriverBindingHandle, 658 &gEfiUdp4ServiceBindingProtocolGuid, 659 &Private->Udp4WriteChild 660 ); 661 if (EFI_ERROR (Status)) { 662 goto ON_ERROR; 663 } 664 665 Status = gBS->OpenProtocol ( 666 Private->Udp4WriteChild, 667 &gEfiUdp4ProtocolGuid, 668 (VOID **) &Private->Udp4Write, 669 This->DriverBindingHandle, 670 ControllerHandle, 671 EFI_OPEN_PROTOCOL_BY_DRIVER 672 ); 673 if (EFI_ERROR (Status)) { 674 goto ON_ERROR; 675 } 676 677 // 678 // Create Arp child and open Arp protocol for PxeBc->Arp. 679 // 680 Status = NetLibCreateServiceChild ( 681 ControllerHandle, 682 This->DriverBindingHandle, 683 &gEfiArpServiceBindingProtocolGuid, 684 &Private->ArpChild 685 ); 686 if (EFI_ERROR (Status)) { 687 goto ON_ERROR; 688 } 689 690 Status = gBS->OpenProtocol ( 691 Private->ArpChild, 692 &gEfiArpProtocolGuid, 693 (VOID **) &Private->Arp, 694 This->DriverBindingHandle, 695 ControllerHandle, 696 EFI_OPEN_PROTOCOL_BY_DRIVER 697 ); 698 if (EFI_ERROR (Status)) { 699 goto ON_ERROR; 700 } 701 702 // 703 // Create Ip4 child and open Ip4 protocol for background ICMP packets. 704 // 705 Status = NetLibCreateServiceChild ( 706 ControllerHandle, 707 This->DriverBindingHandle, 708 &gEfiIp4ServiceBindingProtocolGuid, 709 &Private->Ip4Child 710 ); 711 if (EFI_ERROR (Status)) { 712 goto ON_ERROR; 713 } 714 715 Status = gBS->OpenProtocol ( 716 Private->Ip4Child, 717 &gEfiIp4ProtocolGuid, 718 (VOID **) &Private->Ip4, 719 This->DriverBindingHandle, 720 ControllerHandle, 721 EFI_OPEN_PROTOCOL_BY_DRIVER 722 ); 723 if (EFI_ERROR (Status)) { 724 goto ON_ERROR; 725 } 726 727 // 728 // Get max packet size from Ip4 to calculate block size for Tftp later. 729 // 730 Status = Private->Ip4->GetModeData (Private->Ip4, &Ip4ModeData, NULL, NULL); 731 if (EFI_ERROR (Status)) { 732 goto ON_ERROR; 733 } 734 735 Private->Ip4MaxPacketSize = Ip4ModeData.MaxPacketSize; 736 737 Private->Ip4Nic = AllocateZeroPool (sizeof (PXEBC_VIRTUAL_NIC)); 738 if (Private->Ip4Nic == NULL) { 739 return EFI_OUT_OF_RESOURCES; 740 } 741 742 Private->Ip4Nic->Private = Private; 743 Private->Ip4Nic->Signature = PXEBC_VIRTUAL_NIC_SIGNATURE; 744 745 // 746 // Locate Ip4->Ip4Config2 and store it for set IPv4 Policy. 747 // 748 Status = gBS->HandleProtocol ( 749 ControllerHandle, 750 &gEfiIp4Config2ProtocolGuid, 751 (VOID **) &Private->Ip4Config2 752 ); 753 if (EFI_ERROR (Status)) { 754 goto ON_ERROR; 755 } 756 757 // 758 // Create a device path node for Ipv4 virtual nic, and append it. 759 // 760 ZeroMem (&Ip4Node, sizeof (IPv4_DEVICE_PATH)); 761 Ip4Node.Header.Type = MESSAGING_DEVICE_PATH; 762 Ip4Node.Header.SubType = MSG_IPv4_DP; 763 Ip4Node.StaticIpAddress = FALSE; 764 765 SetDevicePathNodeLength (&Ip4Node.Header, sizeof (Ip4Node)); 766 767 Private->Ip4Nic->DevicePath = AppendDevicePathNode (Private->DevicePath, &Ip4Node.Header); 768 769 if (Private->Ip4Nic->DevicePath == NULL) { 770 Status = EFI_OUT_OF_RESOURCES; 771 goto ON_ERROR; 772 } 773 774 CopyMem ( 775 &Private->Ip4Nic->LoadFile, 776 &gLoadFileProtocolTemplate, 777 sizeof (EFI_LOAD_FILE_PROTOCOL) 778 ); 779 780 // 781 // Create a new handle for IPv4 virtual nic, 782 // and install PxeBaseCode, LoadFile and DevicePath protocols. 783 // 784 Status = gBS->InstallMultipleProtocolInterfaces ( 785 &Private->Ip4Nic->Controller, 786 &gEfiDevicePathProtocolGuid, 787 Private->Ip4Nic->DevicePath, 788 &gEfiLoadFileProtocolGuid, 789 &Private->Ip4Nic->LoadFile, 790 &gEfiPxeBaseCodeProtocolGuid, 791 &Private->PxeBc, 792 NULL 793 ); 794 if (EFI_ERROR (Status)) { 795 goto ON_ERROR; 796 } 797 798 if (Private->Snp != NULL) { 799 // 800 // Install SNP protocol on purpose is for some OS loader backward 801 // compatibility consideration. 802 // 803 Status = gBS->InstallProtocolInterface ( 804 &Private->Ip4Nic->Controller, 805 &gEfiSimpleNetworkProtocolGuid, 806 EFI_NATIVE_INTERFACE, 807 Private->Snp 808 ); 809 if (EFI_ERROR (Status)) { 810 goto ON_ERROR; 811 } 812 813 // 814 // Open SNP on the child handle BY_DRIVER. It will prevent any additionally 815 // layering to perform the experiment. 816 // 817 Status = gBS->OpenProtocol ( 818 Private->Ip4Nic->Controller, 819 &gEfiSimpleNetworkProtocolGuid, 820 (VOID **) &Snp, 821 This->DriverBindingHandle, 822 Private->Ip4Nic->Controller, 823 EFI_OPEN_PROTOCOL_BY_DRIVER 824 ); 825 if (EFI_ERROR (Status)) { 826 goto ON_ERROR; 827 } 828 } 829 830 // 831 // Open PxeBaseCodePrivate protocol by child to setup a parent-child relationship between 832 // real NIC handle and the virtual IPv4 NIC handle. 833 // 834 Status = gBS->OpenProtocol ( 835 ControllerHandle, 836 &gEfiCallerIdGuid, 837 (VOID **) &Id, 838 This->DriverBindingHandle, 839 Private->Ip4Nic->Controller, 840 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 841 ); 842 if (EFI_ERROR (Status)) { 843 goto ON_ERROR; 844 } 845 846 // 847 // Set default configure data for Udp4Read and Ip4 instance. 848 // 849 Mode = Private->PxeBc.Mode; 850 Udp4CfgData = &Private->Udp4CfgData; 851 Ip4CfgData = &Private->Ip4CfgData; 852 853 Udp4CfgData->AcceptBroadcast = FALSE; 854 Udp4CfgData->AcceptAnyPort = TRUE; 855 Udp4CfgData->AllowDuplicatePort = TRUE; 856 Udp4CfgData->TypeOfService = Mode->ToS; 857 Udp4CfgData->TimeToLive = Mode->TTL; 858 Udp4CfgData->ReceiveTimeout = PXEBC_DEFAULT_LIFETIME; 859 Udp4CfgData->TransmitTimeout = PXEBC_DEFAULT_LIFETIME; 860 861 Ip4CfgData->AcceptIcmpErrors = TRUE; 862 Ip4CfgData->DefaultProtocol = EFI_IP_PROTO_ICMP; 863 Ip4CfgData->TypeOfService = Mode->ToS; 864 Ip4CfgData->TimeToLive = Mode->TTL; 865 Ip4CfgData->ReceiveTimeout = PXEBC_DEFAULT_LIFETIME; 866 Ip4CfgData->TransmitTimeout = PXEBC_DEFAULT_LIFETIME; 867 868 return EFI_SUCCESS; 869 870 ON_ERROR: 871 PxeBcDestroyIp4Children (This, Private); 872 return Status; 873 } 874 875 876 /** 877 Create the opened instances based on IPv6. 878 879 @param[in] This Pointer to EFI_DRIVER_BINDING_PROTOCOL. 880 @param[in] ControllerHandle Handle of the child to destroy. 881 @param[in] Private Handle Pointer to PXEBC_PRIVATE_DATA. 882 883 @retval EFI_SUCCESS The instances based on IPv6 were all created successfully. 884 @retval Others An unexpected error occurred. 885 886 **/ 887 EFI_STATUS 888 PxeBcCreateIp6Children ( 889 IN EFI_DRIVER_BINDING_PROTOCOL *This, 890 IN EFI_HANDLE ControllerHandle, 891 IN PXEBC_PRIVATE_DATA *Private 892 ) 893 { 894 EFI_STATUS Status; 895 IPv6_DEVICE_PATH Ip6Node; 896 EFI_UDP6_CONFIG_DATA *Udp6CfgData; 897 EFI_IP6_CONFIG_DATA *Ip6CfgData; 898 EFI_IP6_MODE_DATA Ip6ModeData; 899 PXEBC_PRIVATE_PROTOCOL *Id; 900 EFI_SIMPLE_NETWORK_PROTOCOL *Snp; 901 UINTN Index; 902 903 if (Private->Ip6Nic != NULL) { 904 // 905 // Already created before. 906 // 907 return EFI_SUCCESS; 908 } 909 910 Private->Ip6Nic = AllocateZeroPool (sizeof (PXEBC_VIRTUAL_NIC)); 911 912 if (Private->Ip6Nic == NULL) { 913 return EFI_OUT_OF_RESOURCES; 914 } 915 916 Private->Ip6Nic->Private = Private; 917 Private->Ip6Nic->Signature = PXEBC_VIRTUAL_NIC_SIGNATURE; 918 919 // 920 // Create Dhcp6 child and open Dhcp6 protocol for PxeBc->Dhcp. 921 // 922 Status = NetLibCreateServiceChild ( 923 ControllerHandle, 924 This->DriverBindingHandle, 925 &gEfiDhcp6ServiceBindingProtocolGuid, 926 &Private->Dhcp6Child 927 ); 928 if (EFI_ERROR (Status)) { 929 goto ON_ERROR; 930 } 931 932 Status = gBS->OpenProtocol ( 933 Private->Dhcp6Child, 934 &gEfiDhcp6ProtocolGuid, 935 (VOID **) &Private->Dhcp6, 936 This->DriverBindingHandle, 937 ControllerHandle, 938 EFI_OPEN_PROTOCOL_BY_DRIVER 939 ); 940 if (EFI_ERROR (Status)) { 941 goto ON_ERROR; 942 } 943 944 // 945 // Generate a random IAID for the Dhcp6 assigned address. 946 // 947 Private->IaId = NET_RANDOM (NetRandomInitSeed ()); 948 if (Private->Snp != NULL) { 949 for (Index = 0; Index < Private->Snp->Mode->HwAddressSize; Index++) { 950 Private->IaId |= (Private->Snp->Mode->CurrentAddress.Addr[Index] << ((Index << 3) & 31)); 951 } 952 } 953 954 // 955 // Create Mtftp6 child and open Mtftp6 protocol for PxeBc->Mtftp. 956 // 957 Status = NetLibCreateServiceChild ( 958 ControllerHandle, 959 This->DriverBindingHandle, 960 &gEfiMtftp6ServiceBindingProtocolGuid, 961 &Private->Mtftp6Child 962 ); 963 if (EFI_ERROR (Status)) { 964 goto ON_ERROR; 965 } 966 967 Status = gBS->OpenProtocol ( 968 Private->Mtftp6Child, 969 &gEfiMtftp6ProtocolGuid, 970 (VOID **) &Private->Mtftp6, 971 This->DriverBindingHandle, 972 ControllerHandle, 973 EFI_OPEN_PROTOCOL_BY_DRIVER 974 ); 975 if (EFI_ERROR (Status)) { 976 goto ON_ERROR; 977 } 978 979 // 980 // Create Udp6 child and open Udp6 protocol for PxeBc->UdpRead. 981 // 982 Status = NetLibCreateServiceChild ( 983 ControllerHandle, 984 This->DriverBindingHandle, 985 &gEfiUdp6ServiceBindingProtocolGuid, 986 &Private->Udp6ReadChild 987 ); 988 if (EFI_ERROR (Status)) { 989 goto ON_ERROR; 990 } 991 992 Status = gBS->OpenProtocol ( 993 Private->Udp6ReadChild, 994 &gEfiUdp6ProtocolGuid, 995 (VOID **) &Private->Udp6Read, 996 This->DriverBindingHandle, 997 ControllerHandle, 998 EFI_OPEN_PROTOCOL_BY_DRIVER 999 ); 1000 if (EFI_ERROR (Status)) { 1001 goto ON_ERROR; 1002 } 1003 1004 // 1005 // Create Udp6 child and open Udp6 protocol for PxeBc->UdpWrite. 1006 // 1007 Status = NetLibCreateServiceChild ( 1008 ControllerHandle, 1009 This->DriverBindingHandle, 1010 &gEfiUdp6ServiceBindingProtocolGuid, 1011 &Private->Udp6WriteChild 1012 ); 1013 if (EFI_ERROR (Status)) { 1014 goto ON_ERROR; 1015 } 1016 1017 Status = gBS->OpenProtocol ( 1018 Private->Udp6WriteChild, 1019 &gEfiUdp6ProtocolGuid, 1020 (VOID **) &Private->Udp6Write, 1021 This->DriverBindingHandle, 1022 ControllerHandle, 1023 EFI_OPEN_PROTOCOL_BY_DRIVER 1024 ); 1025 if (EFI_ERROR (Status)) { 1026 goto ON_ERROR; 1027 } 1028 1029 // 1030 // Create Ip6 child and open Ip6 protocol for background ICMP6 packets. 1031 // 1032 Status = NetLibCreateServiceChild ( 1033 ControllerHandle, 1034 This->DriverBindingHandle, 1035 &gEfiIp6ServiceBindingProtocolGuid, 1036 &Private->Ip6Child 1037 ); 1038 if (EFI_ERROR (Status)) { 1039 goto ON_ERROR; 1040 } 1041 1042 Status = gBS->OpenProtocol ( 1043 Private->Ip6Child, 1044 &gEfiIp6ProtocolGuid, 1045 (VOID **) &Private->Ip6, 1046 This->DriverBindingHandle, 1047 ControllerHandle, 1048 EFI_OPEN_PROTOCOL_BY_DRIVER 1049 ); 1050 if (EFI_ERROR (Status)) { 1051 goto ON_ERROR; 1052 } 1053 1054 // 1055 // Get max packet size from Ip6 to calculate block size for Tftp later. 1056 // 1057 Status = Private->Ip6->GetModeData (Private->Ip6, &Ip6ModeData, NULL, NULL); 1058 if (EFI_ERROR (Status)) { 1059 goto ON_ERROR; 1060 } 1061 1062 Private->Ip6MaxPacketSize = Ip6ModeData.MaxPacketSize; 1063 1064 // 1065 // Locate Ip6->Ip6Config and store it for set IPv6 address. 1066 // 1067 Status = gBS->HandleProtocol ( 1068 ControllerHandle, 1069 &gEfiIp6ConfigProtocolGuid, 1070 (VOID **) &Private->Ip6Cfg 1071 ); 1072 if (EFI_ERROR (Status)) { 1073 goto ON_ERROR; 1074 } 1075 1076 // 1077 // Create a device path node for Ipv6 virtual nic, and append it. 1078 // 1079 ZeroMem (&Ip6Node, sizeof (IPv6_DEVICE_PATH)); 1080 Ip6Node.Header.Type = MESSAGING_DEVICE_PATH; 1081 Ip6Node.Header.SubType = MSG_IPv6_DP; 1082 Ip6Node.PrefixLength = IP6_PREFIX_LENGTH; 1083 1084 SetDevicePathNodeLength (&Ip6Node.Header, sizeof (Ip6Node)); 1085 1086 Private->Ip6Nic->DevicePath = AppendDevicePathNode (Private->DevicePath, &Ip6Node.Header); 1087 1088 if (Private->Ip6Nic->DevicePath == NULL) { 1089 Status = EFI_OUT_OF_RESOURCES; 1090 goto ON_ERROR; 1091 } 1092 1093 CopyMem ( 1094 &Private->Ip6Nic->LoadFile, 1095 &gLoadFileProtocolTemplate, 1096 sizeof (EFI_LOAD_FILE_PROTOCOL) 1097 ); 1098 1099 // 1100 // Create a new handle for IPv6 virtual nic, 1101 // and install PxeBaseCode, LoadFile and DevicePath protocols. 1102 // 1103 Status = gBS->InstallMultipleProtocolInterfaces ( 1104 &Private->Ip6Nic->Controller, 1105 &gEfiDevicePathProtocolGuid, 1106 Private->Ip6Nic->DevicePath, 1107 &gEfiLoadFileProtocolGuid, 1108 &Private->Ip6Nic->LoadFile, 1109 &gEfiPxeBaseCodeProtocolGuid, 1110 &Private->PxeBc, 1111 NULL 1112 ); 1113 if (EFI_ERROR (Status)) { 1114 goto ON_ERROR; 1115 } 1116 1117 if (Private->Snp != NULL) { 1118 // 1119 // Install SNP protocol on purpose is for some OS loader backward 1120 // compatibility consideration. 1121 // 1122 Status = gBS->InstallProtocolInterface ( 1123 &Private->Ip6Nic->Controller, 1124 &gEfiSimpleNetworkProtocolGuid, 1125 EFI_NATIVE_INTERFACE, 1126 Private->Snp 1127 ); 1128 if (EFI_ERROR (Status)) { 1129 goto ON_ERROR; 1130 } 1131 1132 // 1133 // Open SNP on the child handle BY_DRIVER. It will prevent any additionally 1134 // layering to perform the experiment. 1135 // 1136 Status = gBS->OpenProtocol ( 1137 Private->Ip6Nic->Controller, 1138 &gEfiSimpleNetworkProtocolGuid, 1139 (VOID **) &Snp, 1140 This->DriverBindingHandle, 1141 Private->Ip6Nic->Controller, 1142 EFI_OPEN_PROTOCOL_BY_DRIVER 1143 ); 1144 if (EFI_ERROR (Status)) { 1145 goto ON_ERROR; 1146 } 1147 } 1148 1149 // 1150 // Open PxeBaseCodePrivate protocol by child to setup a parent-child relationship between 1151 // real NIC handle and the virtual IPv6 NIC handle. 1152 // 1153 Status = gBS->OpenProtocol ( 1154 ControllerHandle, 1155 &gEfiCallerIdGuid, 1156 (VOID **) &Id, 1157 This->DriverBindingHandle, 1158 Private->Ip6Nic->Controller, 1159 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 1160 ); 1161 if (EFI_ERROR (Status)) { 1162 goto ON_ERROR; 1163 } 1164 1165 // 1166 // Set IPv6 avaiable flag and set default configure data for 1167 // Udp6Read and Ip6 instance. 1168 // 1169 Status = PxeBcCheckIpv6Support (ControllerHandle, Private, &Private->Mode.Ipv6Available); 1170 if (EFI_ERROR (Status)) { 1171 // 1172 // Fail to get the data whether UNDI supports IPv6. Set default value. 1173 // 1174 Private->Mode.Ipv6Available = TRUE; 1175 } 1176 1177 if (!Private->Mode.Ipv6Available) { 1178 goto ON_ERROR; 1179 } 1180 1181 Udp6CfgData = &Private->Udp6CfgData; 1182 Ip6CfgData = &Private->Ip6CfgData; 1183 1184 Udp6CfgData->AcceptAnyPort = TRUE; 1185 Udp6CfgData->AllowDuplicatePort = TRUE; 1186 Udp6CfgData->HopLimit = PXEBC_DEFAULT_HOPLIMIT; 1187 Udp6CfgData->ReceiveTimeout = PXEBC_DEFAULT_LIFETIME; 1188 Udp6CfgData->TransmitTimeout = PXEBC_DEFAULT_LIFETIME; 1189 1190 Ip6CfgData->AcceptIcmpErrors = TRUE; 1191 Ip6CfgData->DefaultProtocol = IP6_ICMP; 1192 Ip6CfgData->HopLimit = PXEBC_DEFAULT_HOPLIMIT; 1193 Ip6CfgData->ReceiveTimeout = PXEBC_DEFAULT_LIFETIME; 1194 Ip6CfgData->TransmitTimeout = PXEBC_DEFAULT_LIFETIME; 1195 1196 return EFI_SUCCESS; 1197 1198 ON_ERROR: 1199 PxeBcDestroyIp6Children (This, Private); 1200 return Status; 1201 } 1202 1203 1204 /** 1205 The entry point for UefiPxeBc driver that installs the driver 1206 binding and component name protocol on its image. 1207 1208 @param[in] ImageHandle The Image handle of the driver. 1209 @param[in] SystemTable The system table. 1210 1211 @return EFI_SUCCESS 1212 @return Others 1213 1214 **/ 1215 EFI_STATUS 1216 EFIAPI 1217 PxeBcDriverEntryPoint ( 1218 IN EFI_HANDLE ImageHandle, 1219 IN EFI_SYSTEM_TABLE *SystemTable 1220 ) 1221 { 1222 EFI_STATUS Status; 1223 1224 Status = EfiLibInstallDriverBindingComponentName2 ( 1225 ImageHandle, 1226 SystemTable, 1227 &gPxeBcIp4DriverBinding, 1228 ImageHandle, 1229 &gPxeBcComponentName, 1230 &gPxeBcComponentName2 1231 ); 1232 if (EFI_ERROR (Status)) { 1233 return Status; 1234 } 1235 1236 Status = EfiLibInstallDriverBindingComponentName2 ( 1237 ImageHandle, 1238 SystemTable, 1239 &gPxeBcIp6DriverBinding, 1240 NULL, 1241 &gPxeBcComponentName, 1242 &gPxeBcComponentName2 1243 ); 1244 if (EFI_ERROR (Status)) { 1245 gBS->UninstallMultipleProtocolInterfaces ( 1246 ImageHandle, 1247 &gEfiDriverBindingProtocolGuid, 1248 &gPxeBcIp4DriverBinding, 1249 &gEfiComponentName2ProtocolGuid, 1250 &gPxeBcComponentName2, 1251 &gEfiComponentNameProtocolGuid, 1252 &gPxeBcComponentName, 1253 NULL 1254 ); 1255 } 1256 1257 return Status; 1258 } 1259 1260 /** 1261 Test to see if this driver supports ControllerHandle. This is the worker function for 1262 PxeBcIp4(6)DriverBindingSupported. 1263 1264 @param[in] This The pointer to the driver binding protocol. 1265 @param[in] ControllerHandle The handle of device to be tested. 1266 @param[in] RemainingDevicePath Optional parameter used to pick a specific child 1267 device to be started. 1268 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6. 1269 1270 @retval EFI_SUCCESS This driver supports this device. 1271 @retval EFI_UNSUPPORTED This driver does not support this device. 1272 1273 **/ 1274 EFI_STATUS 1275 EFIAPI 1276 PxeBcSupported ( 1277 IN EFI_DRIVER_BINDING_PROTOCOL *This, 1278 IN EFI_HANDLE ControllerHandle, 1279 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL, 1280 IN UINT8 IpVersion 1281 ) 1282 { 1283 EFI_STATUS Status; 1284 EFI_GUID *DhcpServiceBindingGuid; 1285 EFI_GUID *MtftpServiceBindingGuid; 1286 1287 if (IpVersion == IP_VERSION_4) { 1288 DhcpServiceBindingGuid = &gEfiDhcp4ServiceBindingProtocolGuid; 1289 MtftpServiceBindingGuid = &gEfiMtftp4ServiceBindingProtocolGuid; 1290 } else { 1291 DhcpServiceBindingGuid = &gEfiDhcp6ServiceBindingProtocolGuid; 1292 MtftpServiceBindingGuid = &gEfiMtftp6ServiceBindingProtocolGuid; 1293 } 1294 1295 // 1296 // Try to open the Mtftp and Dhcp protocol to test whether IP stack is ready. 1297 // 1298 Status = gBS->OpenProtocol ( 1299 ControllerHandle, 1300 DhcpServiceBindingGuid, 1301 NULL, 1302 This->DriverBindingHandle, 1303 ControllerHandle, 1304 EFI_OPEN_PROTOCOL_TEST_PROTOCOL 1305 ); 1306 if (!EFI_ERROR (Status)) { 1307 Status = gBS->OpenProtocol ( 1308 ControllerHandle, 1309 MtftpServiceBindingGuid, 1310 NULL, 1311 This->DriverBindingHandle, 1312 ControllerHandle, 1313 EFI_OPEN_PROTOCOL_TEST_PROTOCOL 1314 ); 1315 } 1316 1317 // 1318 // It's unsupported case if IP stack are not ready. 1319 // 1320 if (EFI_ERROR (Status)) { 1321 return EFI_UNSUPPORTED; 1322 } 1323 1324 return EFI_SUCCESS; 1325 } 1326 1327 /** 1328 Start this driver on ControllerHandle. This is the worker function for 1329 PxeBcIp4(6)DriverBindingStart. 1330 1331 @param[in] This The pointer to the driver binding protocol. 1332 @param[in] ControllerHandle The handle of device to be started. 1333 @param[in] RemainingDevicePath Optional parameter used to pick a specific child 1334 device to be started. 1335 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6. 1336 1337 1338 @retval EFI_SUCCESS This driver is installed to ControllerHandle. 1339 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle. 1340 @retval other This driver does not support this device. 1341 1342 **/ 1343 EFI_STATUS 1344 EFIAPI 1345 PxeBcStart ( 1346 IN EFI_DRIVER_BINDING_PROTOCOL *This, 1347 IN EFI_HANDLE ControllerHandle, 1348 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL, 1349 IN UINT8 IpVersion 1350 ) 1351 { 1352 PXEBC_PRIVATE_DATA *Private; 1353 EFI_STATUS Status; 1354 PXEBC_PRIVATE_PROTOCOL *Id; 1355 BOOLEAN FirstStart; 1356 1357 FirstStart = FALSE; 1358 Status = gBS->OpenProtocol ( 1359 ControllerHandle, 1360 &gEfiCallerIdGuid, 1361 (VOID **) &Id, 1362 This->DriverBindingHandle, 1363 ControllerHandle, 1364 EFI_OPEN_PROTOCOL_GET_PROTOCOL 1365 ); 1366 if (!EFI_ERROR (Status)) { 1367 // 1368 // Skip the initialization if the driver has been started already. 1369 // 1370 Private = PXEBC_PRIVATE_DATA_FROM_ID (Id); 1371 } else { 1372 FirstStart = TRUE; 1373 // 1374 // If the driver has not been started yet, it should do initialization. 1375 // 1376 Private = AllocateZeroPool (sizeof (PXEBC_PRIVATE_DATA)); 1377 if (Private == NULL) { 1378 return EFI_OUT_OF_RESOURCES; 1379 } 1380 1381 CopyMem ( 1382 &Private->PxeBc, 1383 &gPxeBcProtocolTemplate, 1384 sizeof (EFI_PXE_BASE_CODE_PROTOCOL) 1385 ); 1386 1387 Private->Signature = PXEBC_PRIVATE_DATA_SIGNATURE; 1388 Private->Controller = ControllerHandle; 1389 Private->Image = This->ImageHandle; 1390 Private->PxeBc.Mode = &Private->Mode; 1391 Private->Mode.Ipv6Supported = TRUE; 1392 Private->Mode.AutoArp = TRUE; 1393 Private->Mode.TTL = DEFAULT_TTL; 1394 Private->Mode.ToS = DEFAULT_ToS; 1395 1396 // 1397 // Open device path to prepare for appending virtual NIC node. 1398 // 1399 Status = gBS->OpenProtocol ( 1400 ControllerHandle, 1401 &gEfiDevicePathProtocolGuid, 1402 (VOID **) &Private->DevicePath, 1403 This->DriverBindingHandle, 1404 ControllerHandle, 1405 EFI_OPEN_PROTOCOL_GET_PROTOCOL 1406 ); 1407 1408 if (EFI_ERROR (Status)) { 1409 goto ON_ERROR; 1410 } 1411 1412 // 1413 // Get the NII interface if it exists, it's not required. 1414 // 1415 Status = gBS->OpenProtocol ( 1416 ControllerHandle, 1417 &gEfiNetworkInterfaceIdentifierProtocolGuid_31, 1418 (VOID **) &Private->Nii, 1419 This->DriverBindingHandle, 1420 ControllerHandle, 1421 EFI_OPEN_PROTOCOL_GET_PROTOCOL 1422 ); 1423 if (EFI_ERROR (Status)) { 1424 Private->Nii = NULL; 1425 } 1426 1427 // 1428 // Install PxeBaseCodePrivate protocol onto the real NIC handler. 1429 // PxeBaseCodePrivate protocol is only used to keep the relationship between 1430 // NIC handle and virtual child handles. 1431 // gEfiCallerIdGuid will be used as its protocol guid. 1432 // 1433 Status = gBS->InstallProtocolInterface ( 1434 &ControllerHandle, 1435 &gEfiCallerIdGuid, 1436 EFI_NATIVE_INTERFACE, 1437 &Private->Id 1438 ); 1439 if (EFI_ERROR (Status)) { 1440 goto ON_ERROR; 1441 } 1442 1443 // 1444 // Try to locate SNP protocol. 1445 // 1446 NetLibGetSnpHandle(ControllerHandle, &Private->Snp); 1447 } 1448 1449 if (IpVersion == IP_VERSION_4) { 1450 // 1451 // Try to create virtual NIC handle for IPv4. 1452 // 1453 Status = PxeBcCreateIp4Children (This, ControllerHandle, Private); 1454 } else { 1455 // 1456 // Try to create virtual NIC handle for IPv6. 1457 // 1458 Status = PxeBcCreateIp6Children (This, ControllerHandle, Private); 1459 } 1460 if (EFI_ERROR (Status)) { 1461 // 1462 // Failed to start PXE driver if IPv4 and IPv6 stack are both not available. 1463 // 1464 Status = EFI_DEVICE_ERROR; 1465 goto ON_ERROR; 1466 } 1467 1468 return EFI_SUCCESS; 1469 1470 ON_ERROR: 1471 if (FirstStart) { 1472 gBS->UninstallProtocolInterface ( 1473 ControllerHandle, 1474 &gEfiCallerIdGuid, 1475 &Private->Id 1476 ); 1477 } 1478 1479 if (IpVersion == IP_VERSION_4) { 1480 PxeBcDestroyIp4Children (This, Private); 1481 } else { 1482 PxeBcDestroyIp6Children (This, Private); 1483 } 1484 1485 if (FirstStart && Private != NULL) { 1486 FreePool (Private); 1487 } 1488 1489 return Status; 1490 } 1491 1492 1493 /** 1494 Stop this driver on ControllerHandle. This is the worker function for 1495 PxeBcIp4(6)DriverBindingStop. 1496 1497 @param[in] This Protocol instance pointer. 1498 @param[in] ControllerHandle Handle of device to stop driver on. 1499 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of 1500 children is zero stop the entire bus driver. 1501 @param[in] ChildHandleBuffer List of Child Handles to Stop. 1502 @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6. 1503 1504 @retval EFI_SUCCESS This driver was removed ControllerHandle. 1505 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. 1506 @retval Others This driver was not removed from this device 1507 1508 **/ 1509 EFI_STATUS 1510 EFIAPI 1511 PxeBcStop ( 1512 IN EFI_DRIVER_BINDING_PROTOCOL *This, 1513 IN EFI_HANDLE ControllerHandle, 1514 IN UINTN NumberOfChildren, 1515 IN EFI_HANDLE *ChildHandleBuffer, 1516 IN UINT8 IpVersion 1517 ) 1518 { 1519 PXEBC_PRIVATE_DATA *Private; 1520 PXEBC_VIRTUAL_NIC *VirtualNic; 1521 EFI_LOAD_FILE_PROTOCOL *LoadFile; 1522 EFI_STATUS Status; 1523 EFI_HANDLE NicHandle; 1524 PXEBC_PRIVATE_PROTOCOL *Id; 1525 1526 Private = NULL; 1527 NicHandle = NULL; 1528 VirtualNic = NULL; 1529 LoadFile = NULL; 1530 Id = NULL; 1531 1532 Status = gBS->OpenProtocol ( 1533 ControllerHandle, 1534 &gEfiLoadFileProtocolGuid, 1535 (VOID **) &LoadFile, 1536 This->DriverBindingHandle, 1537 ControllerHandle, 1538 EFI_OPEN_PROTOCOL_GET_PROTOCOL 1539 ); 1540 if (EFI_ERROR (Status)) { 1541 // 1542 // Get the Nic handle by any pass-over service child handle. 1543 // 1544 if (IpVersion == IP_VERSION_4) { 1545 NicHandle = PxeBcGetNicByIp4Children (ControllerHandle); 1546 } else { 1547 NicHandle = PxeBcGetNicByIp6Children (ControllerHandle); 1548 } 1549 if (NicHandle == NULL) { 1550 return EFI_SUCCESS; 1551 } 1552 1553 // 1554 // Try to retrieve the private data by PxeBcPrivate protocol. 1555 // 1556 Status = gBS->OpenProtocol ( 1557 NicHandle, 1558 &gEfiCallerIdGuid, 1559 (VOID **) &Id, 1560 This->DriverBindingHandle, 1561 ControllerHandle, 1562 EFI_OPEN_PROTOCOL_GET_PROTOCOL 1563 ); 1564 if (EFI_ERROR (Status)) { 1565 return Status; 1566 } 1567 Private = PXEBC_PRIVATE_DATA_FROM_ID (Id); 1568 1569 } else { 1570 // 1571 // It's a virtual handle with LoadFileProtocol. 1572 // 1573 Status = gBS->OpenProtocol ( 1574 ControllerHandle, 1575 &gEfiLoadFileProtocolGuid, 1576 (VOID **) &LoadFile, 1577 This->DriverBindingHandle, 1578 ControllerHandle, 1579 EFI_OPEN_PROTOCOL_GET_PROTOCOL 1580 ); 1581 if (EFI_ERROR (Status)) { 1582 return Status; 1583 } 1584 1585 VirtualNic = PXEBC_VIRTUAL_NIC_FROM_LOADFILE (LoadFile); 1586 Private = VirtualNic->Private; 1587 NicHandle = Private->Controller; 1588 } 1589 1590 // 1591 // Stop functionality of PXE Base Code protocol 1592 // 1593 Status = Private->PxeBc.Stop (&Private->PxeBc); 1594 if (Status != EFI_SUCCESS && Status != EFI_NOT_STARTED) { 1595 return Status; 1596 } 1597 1598 1599 if (Private->Ip4Nic != NULL && IpVersion == IP_VERSION_4) { 1600 PxeBcDestroyIp4Children (This, Private); 1601 } 1602 1603 if (Private->Ip6Nic != NULL && IpVersion == IP_VERSION_6) { 1604 PxeBcDestroyIp6Children (This, Private); 1605 } 1606 1607 if (Private->Ip4Nic == NULL && Private->Ip6Nic == NULL) { 1608 gBS->UninstallProtocolInterface ( 1609 NicHandle, 1610 &gEfiCallerIdGuid, 1611 &Private->Id 1612 ); 1613 FreePool (Private); 1614 } 1615 1616 return EFI_SUCCESS; 1617 } 1618 1619 /** 1620 Test to see if this driver supports ControllerHandle. This service 1621 is called by the EFI boot service ConnectController(). In 1622 order to make drivers as small as possible, there are a few calling 1623 restrictions for this service. ConnectController() must 1624 follow these calling restrictions. If any other agent wishes to call 1625 Supported() it must also follow these calling restrictions. 1626 1627 @param[in] This The pointer to the driver binding protocol. 1628 @param[in] ControllerHandle The handle of device to be tested. 1629 @param[in] RemainingDevicePath Optional parameter used to pick a specific child 1630 device to be started. 1631 1632 @retval EFI_SUCCESS This driver supports this device. 1633 @retval EFI_UNSUPPORTED This driver does not support this device. 1634 1635 **/ 1636 EFI_STATUS 1637 EFIAPI 1638 PxeBcIp4DriverBindingSupported ( 1639 IN EFI_DRIVER_BINDING_PROTOCOL *This, 1640 IN EFI_HANDLE ControllerHandle, 1641 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL 1642 ) 1643 { 1644 return PxeBcSupported ( 1645 This, 1646 ControllerHandle, 1647 RemainingDevicePath, 1648 IP_VERSION_4 1649 ); 1650 } 1651 1652 /** 1653 Start this driver on ControllerHandle. This service is called by the 1654 EFI boot service ConnectController(). In order to make 1655 drivers as small as possible, there are a few calling restrictions for 1656 this service. ConnectController() must follow these 1657 calling restrictions. If any other agent wishes to call Start() it 1658 must also follow these calling restrictions. 1659 1660 @param[in] This The pointer to the driver binding protocol. 1661 @param[in] ControllerHandle The handle of device to be started. 1662 @param[in] RemainingDevicePath Optional parameter used to pick a specific child 1663 device to be started. 1664 1665 @retval EFI_SUCCESS This driver is installed to ControllerHandle. 1666 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle. 1667 @retval other This driver does not support this device. 1668 1669 **/ 1670 EFI_STATUS 1671 EFIAPI 1672 PxeBcIp4DriverBindingStart ( 1673 IN EFI_DRIVER_BINDING_PROTOCOL *This, 1674 IN EFI_HANDLE ControllerHandle, 1675 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL 1676 ) 1677 { 1678 return PxeBcStart ( 1679 This, 1680 ControllerHandle, 1681 RemainingDevicePath, 1682 IP_VERSION_4 1683 ); 1684 } 1685 1686 /** 1687 Stop this driver on ControllerHandle. This service is called by the 1688 EFI boot service DisconnectController(). In order to 1689 make drivers as small as possible, there are a few calling 1690 restrictions for this service. DisconnectController() 1691 must follow these calling restrictions. If any other agent wishes 1692 to call Stop() it must also follow these calling restrictions. 1693 1694 @param[in] This Protocol instance pointer. 1695 @param[in] ControllerHandle Handle of device to stop driver on 1696 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of 1697 children is zero stop the entire bus driver. 1698 @param[in] ChildHandleBuffer List of Child Handles to Stop. 1699 1700 @retval EFI_SUCCESS This driver is removed ControllerHandle 1701 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. 1702 @retval Others This driver was not removed from this device. 1703 1704 **/ 1705 EFI_STATUS 1706 EFIAPI 1707 PxeBcIp4DriverBindingStop ( 1708 IN EFI_DRIVER_BINDING_PROTOCOL *This, 1709 IN EFI_HANDLE ControllerHandle, 1710 IN UINTN NumberOfChildren, 1711 IN EFI_HANDLE *ChildHandleBuffer 1712 ) 1713 { 1714 return PxeBcStop ( 1715 This, 1716 ControllerHandle, 1717 NumberOfChildren, 1718 ChildHandleBuffer, 1719 IP_VERSION_4 1720 ); 1721 } 1722 1723 /** 1724 Test to see if this driver supports ControllerHandle. This service 1725 is called by the EFI boot service ConnectController(). In 1726 order to make drivers as small as possible, there are a few calling 1727 restrictions for this service. ConnectController() must 1728 follow these calling restrictions. If any other agent wishes to call 1729 Supported() it must also follow these calling restrictions. 1730 1731 @param[in] This The pointer to the driver binding protocol. 1732 @param[in] ControllerHandle The handle of device to be tested. 1733 @param[in] RemainingDevicePath Optional parameter use to pick a specific child 1734 device to be started. 1735 1736 @retval EFI_SUCCESS This driver supports this device. 1737 @retval EFI_UNSUPPORTED This driver does not support this device. 1738 1739 **/ 1740 EFI_STATUS 1741 EFIAPI 1742 PxeBcIp6DriverBindingSupported ( 1743 IN EFI_DRIVER_BINDING_PROTOCOL *This, 1744 IN EFI_HANDLE ControllerHandle, 1745 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL 1746 ) 1747 { 1748 return PxeBcSupported ( 1749 This, 1750 ControllerHandle, 1751 RemainingDevicePath, 1752 IP_VERSION_6 1753 ); 1754 } 1755 1756 /** 1757 Start this driver on ControllerHandle. This service is called by the 1758 EFI boot service ConnectController(). In order to make 1759 drivers as small as possible, there are a few calling restrictions for 1760 this service. ConnectController() must follow these 1761 calling restrictions. If any other agent wishes to call Start() it 1762 must also follow these calling restrictions. 1763 1764 @param[in] This The pointer to the driver binding protocol. 1765 @param[in] ControllerHandle The handle of device to be started. 1766 @param[in] RemainingDevicePath Optional parameter used to pick a specific child 1767 device to be started. 1768 1769 @retval EFI_SUCCESS This driver is installed to ControllerHandle. 1770 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle. 1771 @retval other This driver does not support this device. 1772 1773 **/ 1774 EFI_STATUS 1775 EFIAPI 1776 PxeBcIp6DriverBindingStart ( 1777 IN EFI_DRIVER_BINDING_PROTOCOL *This, 1778 IN EFI_HANDLE ControllerHandle, 1779 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL 1780 ) 1781 { 1782 return PxeBcStart ( 1783 This, 1784 ControllerHandle, 1785 RemainingDevicePath, 1786 IP_VERSION_6 1787 ); 1788 } 1789 1790 /** 1791 Stop this driver on ControllerHandle. This service is called by the 1792 EFI boot service DisconnectController(). In order to 1793 make drivers as small as possible, there are a few calling 1794 restrictions for this service. DisconnectController() 1795 must follow these calling restrictions. If any other agent wishes 1796 to call Stop() it must also follow these calling restrictions. 1797 1798 @param[in] This Protocol instance pointer. 1799 @param[in] ControllerHandle Handle of device to stop driver on 1800 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of 1801 children is zero stop the entire bus driver. 1802 @param[in] ChildHandleBuffer List of Child Handles to Stop. 1803 1804 @retval EFI_SUCCESS This driver is removed ControllerHandle 1805 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. 1806 @retval Others This driver was not removed from this device. 1807 1808 **/ 1809 EFI_STATUS 1810 EFIAPI 1811 PxeBcIp6DriverBindingStop ( 1812 IN EFI_DRIVER_BINDING_PROTOCOL *This, 1813 IN EFI_HANDLE ControllerHandle, 1814 IN UINTN NumberOfChildren, 1815 IN EFI_HANDLE *ChildHandleBuffer 1816 ) 1817 { 1818 return PxeBcStop ( 1819 This, 1820 ControllerHandle, 1821 NumberOfChildren, 1822 ChildHandleBuffer, 1823 IP_VERSION_6 1824 ); 1825 } 1826