1 /** @file 2 The driver binding for UEFI PXEBC protocol. 3 4 Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 16 #include "PxeBcImpl.h" 17 18 EFI_DRIVER_BINDING_PROTOCOL gPxeBcDriverBinding = { 19 PxeBcDriverBindingSupported, 20 PxeBcDriverBindingStart, 21 PxeBcDriverBindingStop, 22 0xa, 23 NULL, 24 NULL 25 }; 26 27 /** 28 This is the declaration of an EFI image entry point. This entry point is 29 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including 30 both device drivers and bus drivers. 31 32 @param ImageHandle The firmware allocated handle for the UEFI image. 33 @param SystemTable A pointer to the EFI System Table. 34 35 @retval EFI_SUCCESS The operation completed successfully. 36 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. 37 38 **/ 39 EFI_STATUS 40 EFIAPI 41 PxeBcDriverEntryPoint ( 42 IN EFI_HANDLE ImageHandle, 43 IN EFI_SYSTEM_TABLE *SystemTable 44 ) 45 { 46 return EfiLibInstallDriverBindingComponentName2 ( 47 ImageHandle, 48 SystemTable, 49 &gPxeBcDriverBinding, 50 ImageHandle, 51 &gPxeBcComponentName, 52 &gPxeBcComponentName2 53 ); 54 } 55 56 57 /** 58 Test to see if this driver supports ControllerHandle. This service 59 is called by the EFI boot service ConnectController(). In 60 order to make drivers as small as possible, there are a few calling 61 restrictions for this service. ConnectController() must 62 follow these calling restrictions. If any other agent wishes to call 63 Supported() it must also follow these calling restrictions. 64 PxeBc requires DHCP4 and MTFTP4 protocols. 65 66 @param This Protocol instance pointer. 67 @param ControllerHandle Handle of device to test 68 @param RemainingDevicePath Optional parameter use to pick a specific child 69 device to start. 70 71 @retval EFI_SUCCESS This driver supports this device 72 @retval EFI_ALREADY_STARTED This driver is already running on this device 73 @retval other This driver does not support this device 74 75 **/ 76 EFI_STATUS 77 EFIAPI 78 PxeBcDriverBindingSupported ( 79 IN EFI_DRIVER_BINDING_PROTOCOL * This, 80 IN EFI_HANDLE ControllerHandle, 81 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL 82 ) 83 { 84 EFI_PXE_BASE_CODE_PROTOCOL *PxeBc; 85 EFI_STATUS Status; 86 87 Status = gBS->OpenProtocol ( 88 ControllerHandle, 89 &gEfiPxeBaseCodeProtocolGuid, 90 (VOID **) &PxeBc, 91 This->DriverBindingHandle, 92 ControllerHandle, 93 EFI_OPEN_PROTOCOL_GET_PROTOCOL 94 ); 95 96 if (!EFI_ERROR (Status)) { 97 return EFI_ALREADY_STARTED; 98 } 99 100 Status = gBS->OpenProtocol ( 101 ControllerHandle, 102 &gEfiDhcp4ServiceBindingProtocolGuid, 103 NULL, 104 This->DriverBindingHandle, 105 ControllerHandle, 106 EFI_OPEN_PROTOCOL_TEST_PROTOCOL 107 ); 108 109 if (!EFI_ERROR (Status)) { 110 111 Status = gBS->OpenProtocol ( 112 ControllerHandle, 113 &gEfiMtftp4ServiceBindingProtocolGuid, 114 NULL, 115 This->DriverBindingHandle, 116 ControllerHandle, 117 EFI_OPEN_PROTOCOL_TEST_PROTOCOL 118 ); 119 120 } 121 122 return Status; 123 } 124 125 126 /** 127 Start this driver on ControllerHandle. This service is called by the 128 EFI boot service ConnectController(). In order to make 129 drivers as small as possible, there are a few calling restrictions for 130 this service. ConnectController() must follow these 131 calling restrictions. If any other agent wishes to call Start() it 132 must also follow these calling restrictions. 133 134 @param This Protocol instance pointer. 135 @param ControllerHandle Handle of device to bind driver to 136 @param RemainingDevicePath Optional parameter use to pick a specific child 137 device to start. 138 139 @retval EFI_SUCCESS This driver is added to ControllerHandle 140 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle 141 @retval other This driver does not support this device 142 143 **/ 144 EFI_STATUS 145 EFIAPI 146 PxeBcDriverBindingStart ( 147 IN EFI_DRIVER_BINDING_PROTOCOL * This, 148 IN EFI_HANDLE ControllerHandle, 149 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL 150 ) 151 { 152 PXEBC_PRIVATE_DATA *Private; 153 UINTN Index; 154 EFI_STATUS Status; 155 EFI_IP4_MODE_DATA Ip4ModeData; 156 157 Private = AllocateZeroPool (sizeof (PXEBC_PRIVATE_DATA)); 158 if (Private == NULL) { 159 return EFI_OUT_OF_RESOURCES; 160 } 161 162 Private->Signature = PXEBC_PRIVATE_DATA_SIGNATURE; 163 Private->Controller = ControllerHandle; 164 Private->Image = This->DriverBindingHandle; 165 CopyMem (&Private->PxeBc, &mPxeBcProtocolTemplate, sizeof (Private->PxeBc)); 166 Private->PxeBc.Mode = &Private->Mode; 167 CopyMem (&Private->LoadFile, &mLoadFileProtocolTemplate, sizeof (Private->LoadFile)); 168 169 Private->ProxyOffer.Packet.Offer.Size = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE; 170 Private->Dhcp4Ack.Packet.Ack.Size = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE; 171 Private->PxeReply.Packet.Ack.Size = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE; 172 173 for (Index = 0; Index < PXEBC_MAX_OFFER_NUM; Index++) { 174 Private->Dhcp4Offers[Index].Packet.Offer.Size = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE; 175 } 176 177 // 178 // Get the NII interface if it exists. 179 // 180 Status = gBS->OpenProtocol ( 181 ControllerHandle, 182 &gEfiNetworkInterfaceIdentifierProtocolGuid_31, 183 (VOID **) &Private->Nii, 184 This->DriverBindingHandle, 185 ControllerHandle, 186 EFI_OPEN_PROTOCOL_GET_PROTOCOL 187 ); 188 if (EFI_ERROR (Status)) { 189 Private->Nii = NULL; 190 } 191 192 Status = NetLibCreateServiceChild ( 193 ControllerHandle, 194 This->DriverBindingHandle, 195 &gEfiArpServiceBindingProtocolGuid, 196 &Private->ArpChild 197 ); 198 if (EFI_ERROR (Status)) { 199 goto ON_ERROR; 200 } 201 202 Status = gBS->OpenProtocol ( 203 Private->ArpChild, 204 &gEfiArpProtocolGuid, 205 (VOID **) &Private->Arp, 206 This->DriverBindingHandle, 207 ControllerHandle, 208 EFI_OPEN_PROTOCOL_BY_DRIVER 209 ); 210 if (EFI_ERROR (Status)) { 211 goto ON_ERROR; 212 } 213 214 Status = NetLibCreateServiceChild ( 215 ControllerHandle, 216 This->DriverBindingHandle, 217 &gEfiDhcp4ServiceBindingProtocolGuid, 218 &Private->Dhcp4Child 219 ); 220 if (EFI_ERROR (Status)) { 221 goto ON_ERROR; 222 } 223 224 Status = gBS->OpenProtocol ( 225 Private->Dhcp4Child, 226 &gEfiDhcp4ProtocolGuid, 227 (VOID **) &Private->Dhcp4, 228 This->DriverBindingHandle, 229 ControllerHandle, 230 EFI_OPEN_PROTOCOL_BY_DRIVER 231 ); 232 if (EFI_ERROR (Status)) { 233 goto ON_ERROR; 234 } 235 236 Status = NetLibCreateServiceChild ( 237 ControllerHandle, 238 This->DriverBindingHandle, 239 &gEfiIp4ServiceBindingProtocolGuid, 240 &Private->Ip4Child 241 ); 242 if (EFI_ERROR (Status)) { 243 goto ON_ERROR; 244 } 245 246 Status = gBS->OpenProtocol ( 247 Private->Ip4Child, 248 &gEfiIp4ProtocolGuid, 249 (VOID **) &Private->Ip4, 250 This->DriverBindingHandle, 251 ControllerHandle, 252 EFI_OPEN_PROTOCOL_BY_DRIVER 253 ); 254 if (EFI_ERROR (Status)) { 255 goto ON_ERROR; 256 } 257 258 // 259 // Get max packet size from Ip4 to calculate block size for Tftp later. 260 // 261 Status = Private->Ip4->GetModeData (Private->Ip4, &Ip4ModeData, NULL, NULL); 262 if (EFI_ERROR (Status)) { 263 goto ON_ERROR; 264 } 265 266 Private->Ip4MaxPacketSize = Ip4ModeData.MaxPacketSize; 267 268 Status = NetLibCreateServiceChild ( 269 ControllerHandle, 270 This->DriverBindingHandle, 271 &gEfiMtftp4ServiceBindingProtocolGuid, 272 &Private->Mtftp4Child 273 ); 274 275 if (EFI_ERROR (Status)) { 276 goto ON_ERROR; 277 } 278 279 Status = gBS->OpenProtocol ( 280 Private->Mtftp4Child, 281 &gEfiMtftp4ProtocolGuid, 282 (VOID **) &Private->Mtftp4, 283 This->DriverBindingHandle, 284 ControllerHandle, 285 EFI_OPEN_PROTOCOL_BY_DRIVER 286 ); 287 288 if (EFI_ERROR (Status)) { 289 goto ON_ERROR; 290 } 291 292 Status = NetLibCreateServiceChild ( 293 ControllerHandle, 294 This->DriverBindingHandle, 295 &gEfiUdp4ServiceBindingProtocolGuid, 296 &Private->Udp4ReadChild 297 ); 298 299 if (EFI_ERROR (Status)) { 300 goto ON_ERROR; 301 } 302 303 // 304 // The UDP instance for EfiPxeBcUdpRead 305 // 306 Status = gBS->OpenProtocol ( 307 Private->Udp4ReadChild, 308 &gEfiUdp4ProtocolGuid, 309 (VOID **) &Private->Udp4Read, 310 This->DriverBindingHandle, 311 ControllerHandle, 312 EFI_OPEN_PROTOCOL_BY_DRIVER 313 ); 314 315 if (EFI_ERROR (Status)) { 316 goto ON_ERROR; 317 } 318 319 // 320 // The UDP instance for EfiPxeBcUdpWrite 321 // 322 Status = NetLibCreateServiceChild ( 323 ControllerHandle, 324 This->DriverBindingHandle, 325 &gEfiUdp4ServiceBindingProtocolGuid, 326 &Private->Udp4WriteChild 327 ); 328 if (EFI_ERROR (Status)) { 329 goto ON_ERROR; 330 } 331 332 Status = gBS->OpenProtocol ( 333 Private->Udp4WriteChild, 334 &gEfiUdp4ProtocolGuid, 335 (VOID **) &Private->Udp4Write, 336 This->DriverBindingHandle, 337 ControllerHandle, 338 EFI_OPEN_PROTOCOL_BY_DRIVER 339 ); 340 if (EFI_ERROR (Status)) { 341 goto ON_ERROR; 342 } 343 ZeroMem (&Private->Udp4CfgData, sizeof (EFI_UDP4_CONFIG_DATA)); 344 Private->Udp4CfgData.AcceptBroadcast = FALSE; 345 Private->Udp4CfgData.AcceptPromiscuous = FALSE; 346 Private->Udp4CfgData.AcceptAnyPort = TRUE; 347 Private->Udp4CfgData.AllowDuplicatePort = TRUE; 348 Private->Udp4CfgData.TypeOfService = DEFAULT_ToS; 349 Private->Udp4CfgData.TimeToLive = DEFAULT_TTL; 350 Private->Udp4CfgData.DoNotFragment = FALSE; 351 Private->Udp4CfgData.ReceiveTimeout = PXEBC_DEFAULT_LIFETIME; 352 Private->Udp4CfgData.UseDefaultAddress = FALSE; 353 354 PxeBcInitSeedPacket (&Private->SeedPacket, Private->Udp4Read); 355 Private->MacLen = Private->SeedPacket.Dhcp4.Header.HwAddrLen; 356 CopyMem (&Private->Mac, &Private->SeedPacket.Dhcp4.Header.ClientHwAddr[0], Private->MacLen); 357 358 359 ZeroMem (&Private->Ip4ConfigData, sizeof (EFI_IP4_CONFIG_DATA)); 360 Private->Ip4ConfigData.DefaultProtocol = EFI_IP_PROTO_ICMP; 361 Private->Ip4ConfigData.AcceptIcmpErrors = TRUE; 362 Private->Ip4ConfigData.TypeOfService = DEFAULT_ToS; 363 Private->Ip4ConfigData.TimeToLive = DEFAULT_TTL; 364 Private->Ip4ConfigData.DoNotFragment = FALSE; 365 Private->Ip4ConfigData.RawData = FALSE; 366 367 Status = gBS->InstallMultipleProtocolInterfaces ( 368 &ControllerHandle, 369 &gEfiPxeBaseCodeProtocolGuid, 370 &Private->PxeBc, 371 &gEfiLoadFileProtocolGuid, 372 &Private->LoadFile, 373 NULL 374 ); 375 if (EFI_ERROR (Status)) { 376 goto ON_ERROR; 377 } 378 // 379 // Locate Ip4->Ip4Config2 and store it for set IPv4 Policy. 380 // 381 Status = gBS->HandleProtocol ( 382 ControllerHandle, 383 &gEfiIp4Config2ProtocolGuid, 384 (VOID **) &Private->Ip4Config2 385 ); 386 if (EFI_ERROR (Status)) { 387 goto ON_ERROR; 388 } 389 390 return EFI_SUCCESS; 391 392 ON_ERROR: 393 394 if (Private->Udp4WriteChild != NULL) { 395 gBS->CloseProtocol ( 396 Private->Udp4WriteChild, 397 &gEfiUdp4ProtocolGuid, 398 This->DriverBindingHandle, 399 ControllerHandle 400 ); 401 NetLibDestroyServiceChild ( 402 ControllerHandle, 403 This->DriverBindingHandle, 404 &gEfiUdp4ServiceBindingProtocolGuid, 405 Private->Udp4WriteChild 406 ); 407 } 408 409 if (Private->Udp4ReadChild != NULL) { 410 gBS->CloseProtocol ( 411 Private->Udp4ReadChild, 412 &gEfiUdp4ProtocolGuid, 413 This->DriverBindingHandle, 414 ControllerHandle 415 ); 416 NetLibDestroyServiceChild ( 417 ControllerHandle, 418 This->DriverBindingHandle, 419 &gEfiUdp4ServiceBindingProtocolGuid, 420 Private->Udp4ReadChild 421 ); 422 } 423 424 if (Private->Mtftp4Child != NULL) { 425 gBS->CloseProtocol ( 426 Private->Mtftp4Child, 427 &gEfiMtftp4ProtocolGuid, 428 This->DriverBindingHandle, 429 ControllerHandle 430 ); 431 432 NetLibDestroyServiceChild ( 433 ControllerHandle, 434 This->DriverBindingHandle, 435 &gEfiMtftp4ServiceBindingProtocolGuid, 436 Private->Mtftp4Child 437 ); 438 } 439 440 if (Private->Ip4Child != NULL) { 441 gBS->CloseProtocol ( 442 Private->Ip4Child, 443 &gEfiIp4ProtocolGuid, 444 This->DriverBindingHandle, 445 ControllerHandle 446 ); 447 448 NetLibDestroyServiceChild ( 449 ControllerHandle, 450 This->DriverBindingHandle, 451 &gEfiIp4ServiceBindingProtocolGuid, 452 Private->Ip4Child 453 ); 454 } 455 456 if (Private->Dhcp4Child != NULL) { 457 gBS->CloseProtocol ( 458 Private->Dhcp4Child, 459 &gEfiDhcp4ProtocolGuid, 460 This->DriverBindingHandle, 461 ControllerHandle 462 ); 463 464 NetLibDestroyServiceChild ( 465 ControllerHandle, 466 This->DriverBindingHandle, 467 &gEfiDhcp4ServiceBindingProtocolGuid, 468 Private->Dhcp4Child 469 ); 470 } 471 472 if (Private->ArpChild != NULL) { 473 gBS->CloseProtocol ( 474 Private->ArpChild, 475 &gEfiArpProtocolGuid, 476 This->DriverBindingHandle, 477 ControllerHandle 478 ); 479 480 NetLibDestroyServiceChild ( 481 ControllerHandle, 482 This->DriverBindingHandle, 483 &gEfiArpServiceBindingProtocolGuid, 484 Private->ArpChild 485 ); 486 } 487 488 FreePool (Private); 489 490 return Status; 491 } 492 493 494 /** 495 Stop this driver on ControllerHandle. This service is called by the 496 EFI boot service DisconnectController(). In order to 497 make drivers as small as possible, there are a few calling 498 restrictions for this service. DisconnectController() 499 must follow these calling restrictions. If any other agent wishes 500 to call Stop() it must also follow these calling restrictions. 501 502 @param This Protocol instance pointer. 503 @param ControllerHandle Handle of device to stop driver on 504 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of 505 children is zero stop the entire bus driver. 506 @param ChildHandleBuffer List of Child Handles to Stop. 507 508 @retval EFI_SUCCESS This driver is removed ControllerHandle 509 @retval other This driver was not removed from this device 510 511 **/ 512 EFI_STATUS 513 EFIAPI 514 PxeBcDriverBindingStop ( 515 IN EFI_DRIVER_BINDING_PROTOCOL *This, 516 IN EFI_HANDLE ControllerHandle, 517 IN UINTN NumberOfChildren, 518 IN EFI_HANDLE *ChildHandleBuffer 519 ) 520 { 521 PXEBC_PRIVATE_DATA *Private; 522 EFI_PXE_BASE_CODE_PROTOCOL *PxeBc; 523 EFI_HANDLE NicHandle; 524 EFI_STATUS Status; 525 526 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid); 527 if (NicHandle == NULL) { 528 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid); 529 530 if (NicHandle == NULL) { 531 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp4ProtocolGuid); 532 533 if (NicHandle == NULL) { 534 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp4ProtocolGuid); 535 536 if (NicHandle == NULL) { 537 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiMtftp4ProtocolGuid); 538 539 if (NicHandle == NULL) { 540 return EFI_SUCCESS; 541 } 542 } 543 } 544 } 545 } 546 547 Status = gBS->OpenProtocol ( 548 NicHandle, 549 &gEfiPxeBaseCodeProtocolGuid, 550 (VOID **) &PxeBc, 551 This->DriverBindingHandle, 552 ControllerHandle, 553 EFI_OPEN_PROTOCOL_GET_PROTOCOL 554 ); 555 556 if (EFI_ERROR (Status)) { 557 return Status; 558 } 559 560 // 561 // Stop functionality of PXE Base Code protocol 562 // 563 Status = PxeBc->Stop (PxeBc); 564 if (Status != EFI_SUCCESS && Status != EFI_NOT_STARTED) { 565 return Status; 566 } 567 568 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (PxeBc); 569 570 Status = gBS->UninstallMultipleProtocolInterfaces ( 571 NicHandle, 572 &gEfiPxeBaseCodeProtocolGuid, 573 &Private->PxeBc, 574 &gEfiLoadFileProtocolGuid, 575 &Private->LoadFile, 576 NULL 577 ); 578 579 if (!EFI_ERROR (Status)) { 580 581 gBS->CloseProtocol ( 582 Private->Udp4WriteChild, 583 &gEfiUdp4ProtocolGuid, 584 This->DriverBindingHandle, 585 NicHandle 586 ); 587 NetLibDestroyServiceChild ( 588 ControllerHandle, 589 This->DriverBindingHandle, 590 &gEfiUdp4ServiceBindingProtocolGuid, 591 Private->Udp4WriteChild 592 ); 593 594 gBS->CloseProtocol ( 595 Private->Udp4ReadChild, 596 &gEfiUdp4ProtocolGuid, 597 This->DriverBindingHandle, 598 NicHandle 599 ); 600 NetLibDestroyServiceChild ( 601 NicHandle, 602 This->DriverBindingHandle, 603 &gEfiUdp4ServiceBindingProtocolGuid, 604 Private->Udp4ReadChild 605 ); 606 607 gBS->CloseProtocol ( 608 Private->Dhcp4Child, 609 &gEfiDhcp4ProtocolGuid, 610 This->DriverBindingHandle, 611 NicHandle 612 ); 613 NetLibDestroyServiceChild ( 614 NicHandle, 615 This->DriverBindingHandle, 616 &gEfiDhcp4ServiceBindingProtocolGuid, 617 Private->Dhcp4Child 618 ); 619 620 gBS->CloseProtocol ( 621 Private->Mtftp4Child, 622 &gEfiMtftp4ProtocolGuid, 623 This->DriverBindingHandle, 624 NicHandle 625 ); 626 NetLibDestroyServiceChild ( 627 NicHandle, 628 This->DriverBindingHandle, 629 &gEfiMtftp4ServiceBindingProtocolGuid, 630 Private->Mtftp4Child 631 ); 632 633 gBS->CloseProtocol ( 634 Private->Ip4Child, 635 &gEfiIp4ProtocolGuid, 636 This->DriverBindingHandle, 637 NicHandle 638 ); 639 NetLibDestroyServiceChild ( 640 NicHandle, 641 This->DriverBindingHandle, 642 &gEfiIp4ServiceBindingProtocolGuid, 643 Private->Ip4Child 644 ); 645 646 gBS->CloseProtocol ( 647 Private->ArpChild, 648 &gEfiArpProtocolGuid, 649 This->DriverBindingHandle, 650 NicHandle 651 ); 652 NetLibDestroyServiceChild ( 653 NicHandle, 654 This->DriverBindingHandle, 655 &gEfiArpServiceBindingProtocolGuid, 656 Private->ArpChild 657 ); 658 659 FreePool (Private); 660 } 661 662 return Status; 663 } 664 665 666