1 /** @file 2 * 3 * Copyright (c) 2011-2014, ARM Limited. All rights reserved. 4 * 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 #include "BdsInternal.h" 16 17 #include <Library/NetLib.h> 18 19 #include <Protocol/BlockIo.h> 20 #include <Protocol/DevicePathToText.h> 21 #include <Protocol/FirmwareVolumeBlock.h> 22 #include <Protocol/PxeBaseCode.h> 23 #include <Protocol/SimpleFileSystem.h> 24 #include <Protocol/SimpleNetwork.h> 25 #include <Protocol/Dhcp4.h> 26 #include <Protocol/Mtftp4.h> 27 28 #include <Guid/FileSystemInfo.h> 29 30 #define IS_DEVICE_PATH_NODE(node,type,subtype) (((node)->Type == (type)) && ((node)->SubType == (subtype))) 31 32 EFI_STATUS 33 BdsLoadOptionFileSystemList ( 34 IN OUT LIST_ENTRY* BdsLoadOptionList 35 ); 36 37 EFI_STATUS 38 BdsLoadOptionFileSystemCreateDevicePath ( 39 IN CHAR16* FileName, 40 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes 41 ); 42 43 EFI_STATUS 44 BdsLoadOptionFileSystemUpdateDevicePath ( 45 IN EFI_DEVICE_PATH *OldDevicePath, 46 IN CHAR16* FileName, 47 OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath 48 ); 49 50 BOOLEAN 51 BdsLoadOptionFileSystemIsSupported ( 52 IN EFI_DEVICE_PATH *DevicePath 53 ); 54 55 EFI_STATUS 56 BdsLoadOptionMemMapList ( 57 IN OUT LIST_ENTRY* BdsLoadOptionList 58 ); 59 60 EFI_STATUS 61 BdsLoadOptionMemMapCreateDevicePath ( 62 IN CHAR16* FileName, 63 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes 64 ); 65 66 EFI_STATUS 67 BdsLoadOptionMemMapUpdateDevicePath ( 68 IN EFI_DEVICE_PATH *OldDevicePath, 69 IN CHAR16* FileName, 70 OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath 71 ); 72 73 BOOLEAN 74 BdsLoadOptionMemMapIsSupported ( 75 IN EFI_DEVICE_PATH *DevicePath 76 ); 77 78 EFI_STATUS 79 BdsLoadOptionPxeList ( 80 IN OUT LIST_ENTRY* BdsLoadOptionList 81 ); 82 83 EFI_STATUS 84 BdsLoadOptionPxeCreateDevicePath ( 85 IN CHAR16* FileName, 86 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes 87 ); 88 89 EFI_STATUS 90 BdsLoadOptionPxeUpdateDevicePath ( 91 IN EFI_DEVICE_PATH *OldDevicePath, 92 IN CHAR16* FileName, 93 OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath 94 ); 95 96 BOOLEAN 97 BdsLoadOptionPxeIsSupported ( 98 IN EFI_DEVICE_PATH *DevicePath 99 ); 100 101 EFI_STATUS 102 BdsLoadOptionTftpList ( 103 IN OUT LIST_ENTRY* BdsLoadOptionList 104 ); 105 106 EFI_STATUS 107 BdsLoadOptionTftpCreateDevicePath ( 108 IN CHAR16* FileName, 109 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes 110 ); 111 112 EFI_STATUS 113 BdsLoadOptionTftpUpdateDevicePath ( 114 IN EFI_DEVICE_PATH *OldDevicePath, 115 IN CHAR16* FileName, 116 OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath 117 ); 118 119 BOOLEAN 120 BdsLoadOptionTftpIsSupported ( 121 IN EFI_DEVICE_PATH *DevicePath 122 ); 123 124 BDS_LOAD_OPTION_SUPPORT BdsLoadOptionSupportList[] = { 125 { 126 BDS_DEVICE_FILESYSTEM, 127 BdsLoadOptionFileSystemList, 128 BdsLoadOptionFileSystemIsSupported, 129 BdsLoadOptionFileSystemCreateDevicePath, 130 BdsLoadOptionFileSystemUpdateDevicePath, 131 TRUE 132 }, 133 { 134 BDS_DEVICE_MEMMAP, 135 BdsLoadOptionMemMapList, 136 BdsLoadOptionMemMapIsSupported, 137 BdsLoadOptionMemMapCreateDevicePath, 138 BdsLoadOptionMemMapUpdateDevicePath, 139 TRUE 140 }, 141 { 142 BDS_DEVICE_PXE, 143 BdsLoadOptionPxeList, 144 BdsLoadOptionPxeIsSupported, 145 BdsLoadOptionPxeCreateDevicePath, 146 BdsLoadOptionPxeUpdateDevicePath, 147 FALSE 148 }, 149 { 150 BDS_DEVICE_TFTP, 151 BdsLoadOptionTftpList, 152 BdsLoadOptionTftpIsSupported, 153 BdsLoadOptionTftpCreateDevicePath, 154 BdsLoadOptionTftpUpdateDevicePath, 155 TRUE 156 } 157 }; 158 159 EFI_STATUS 160 BootDeviceListSupportedInit ( 161 IN OUT LIST_ENTRY *SupportedDeviceList 162 ) 163 { 164 UINTN Index; 165 166 // Initialize list of supported devices 167 InitializeListHead (SupportedDeviceList); 168 169 for (Index = 0; Index < BDS_DEVICE_MAX; Index++) { 170 BdsLoadOptionSupportList[Index].ListDevices (SupportedDeviceList); 171 } 172 173 return EFI_SUCCESS; 174 } 175 176 EFI_STATUS 177 BootDeviceListSupportedFree ( 178 IN LIST_ENTRY *SupportedDeviceList, 179 IN BDS_SUPPORTED_DEVICE *Except 180 ) 181 { 182 LIST_ENTRY *Entry; 183 BDS_SUPPORTED_DEVICE* SupportedDevice; 184 185 Entry = GetFirstNode (SupportedDeviceList); 186 while (Entry != SupportedDeviceList) { 187 SupportedDevice = SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry); 188 Entry = RemoveEntryList (Entry); 189 if (SupportedDevice != Except) { 190 FreePool (SupportedDevice); 191 } 192 } 193 194 return EFI_SUCCESS; 195 } 196 197 EFI_STATUS 198 BootDeviceGetDeviceSupport ( 199 IN EFI_DEVICE_PATH *DevicePath, 200 OUT BDS_LOAD_OPTION_SUPPORT **DeviceSupport 201 ) 202 { 203 UINTN Index; 204 205 // Find which supported device is the most appropriate 206 for (Index = 0; Index < BDS_DEVICE_MAX; Index++) { 207 if (BdsLoadOptionSupportList[Index].IsSupported (DevicePath)) { 208 *DeviceSupport = &BdsLoadOptionSupportList[Index]; 209 return EFI_SUCCESS; 210 } 211 } 212 213 return EFI_UNSUPPORTED; 214 } 215 216 EFI_STATUS 217 BdsLoadOptionFileSystemList ( 218 IN OUT LIST_ENTRY* BdsLoadOptionList 219 ) 220 { 221 EFI_STATUS Status; 222 UINTN HandleCount; 223 EFI_HANDLE *HandleBuffer; 224 UINTN Index; 225 BDS_SUPPORTED_DEVICE *SupportedDevice; 226 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* FileProtocol; 227 EFI_FILE_HANDLE Fs; 228 UINTN Size; 229 EFI_FILE_SYSTEM_INFO* FsInfo; 230 EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol; 231 232 // List all the Simple File System Protocols 233 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSimpleFileSystemProtocolGuid, NULL, &HandleCount, &HandleBuffer); 234 if (EFI_ERROR (Status)) { 235 return Status; 236 } 237 238 for (Index = 0; Index < HandleCount; Index++) { 239 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol); 240 if (!EFI_ERROR(Status)) { 241 // Allocate BDS Supported Device structure 242 SupportedDevice = (BDS_SUPPORTED_DEVICE*)AllocatePool (sizeof(BDS_SUPPORTED_DEVICE)); 243 244 FileProtocol = NULL; 245 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSimpleFileSystemProtocolGuid, (VOID **)&FileProtocol); 246 ASSERT_EFI_ERROR(Status); 247 248 FileProtocol->OpenVolume (FileProtocol, &Fs); 249 250 // Generate a Description from the file system 251 Size = 0; 252 FsInfo = NULL; 253 Status = Fs->GetInfo (Fs, &gEfiFileSystemInfoGuid, &Size, FsInfo); 254 if (Status == EFI_BUFFER_TOO_SMALL) { 255 FsInfo = AllocatePool (Size); 256 Status = Fs->GetInfo (Fs, &gEfiFileSystemInfoGuid, &Size, FsInfo); 257 } 258 UnicodeSPrint (SupportedDevice->Description,BOOT_DEVICE_DESCRIPTION_MAX,L"%s (%d MB)",FsInfo->VolumeLabel,(UINT32)(FsInfo->VolumeSize / (1024 * 1024))); 259 FreePool(FsInfo); 260 Fs->Close (Fs); 261 262 SupportedDevice->DevicePathProtocol = DevicePathProtocol; 263 SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_FILESYSTEM]; 264 265 InsertTailList (BdsLoadOptionList,&SupportedDevice->Link); 266 } 267 } 268 269 return EFI_SUCCESS; 270 } 271 272 EFI_STATUS 273 BdsLoadOptionFileSystemCreateDevicePath ( 274 IN CHAR16* FileName, 275 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes 276 ) 277 { 278 EFI_STATUS Status; 279 FILEPATH_DEVICE_PATH* FilePathDevicePath; 280 CHAR16 BootFilePath[BOOT_DEVICE_FILEPATH_MAX]; 281 UINTN BootFilePathSize; 282 283 Print(L"File path of the %s: ", FileName); 284 Status = GetHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX); 285 if (EFI_ERROR(Status)) { 286 return EFI_ABORTED; 287 } 288 289 BootFilePathSize = StrSize (BootFilePath); 290 if (BootFilePathSize == 2) { 291 *DevicePathNodes = NULL; 292 return EFI_NOT_FOUND; 293 } 294 295 // Create the FilePath Device Path node 296 FilePathDevicePath = (FILEPATH_DEVICE_PATH*)AllocatePool(SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize + END_DEVICE_PATH_LENGTH); 297 FilePathDevicePath->Header.Type = MEDIA_DEVICE_PATH; 298 FilePathDevicePath->Header.SubType = MEDIA_FILEPATH_DP; 299 SetDevicePathNodeLength (FilePathDevicePath, SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize); 300 CopyMem (FilePathDevicePath->PathName, BootFilePath, BootFilePathSize); 301 SetDevicePathEndNode ((VOID*)((UINTN)FilePathDevicePath + SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize)); 302 *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL*)FilePathDevicePath; 303 304 return Status; 305 } 306 307 EFI_STATUS 308 BdsLoadOptionFileSystemUpdateDevicePath ( 309 IN EFI_DEVICE_PATH *OldDevicePath, 310 IN CHAR16* FileName, 311 OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath 312 ) 313 { 314 EFI_STATUS Status; 315 CHAR16 BootFilePath[BOOT_DEVICE_FILEPATH_MAX]; 316 UINTN BootFilePathSize; 317 FILEPATH_DEVICE_PATH* EndingDevicePath; 318 FILEPATH_DEVICE_PATH* FilePathDevicePath; 319 EFI_DEVICE_PATH* DevicePath; 320 321 DevicePath = DuplicateDevicePath (OldDevicePath); 322 323 EndingDevicePath = (FILEPATH_DEVICE_PATH*)GetLastDevicePathNode (DevicePath); 324 325 Print(L"File path of the %s: ", FileName); 326 StrnCpy (BootFilePath, EndingDevicePath->PathName, BOOT_DEVICE_FILEPATH_MAX); 327 Status = EditHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX); 328 if (EFI_ERROR(Status)) { 329 return Status; 330 } 331 332 BootFilePathSize = StrSize(BootFilePath); 333 if (BootFilePathSize == 2) { 334 *NewDevicePath = NULL; 335 return EFI_NOT_FOUND; 336 } 337 338 // Create the FilePath Device Path node 339 FilePathDevicePath = (FILEPATH_DEVICE_PATH*)AllocatePool(SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize); 340 FilePathDevicePath->Header.Type = MEDIA_DEVICE_PATH; 341 FilePathDevicePath->Header.SubType = MEDIA_FILEPATH_DP; 342 SetDevicePathNodeLength (FilePathDevicePath, SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize); 343 CopyMem (FilePathDevicePath->PathName, BootFilePath, BootFilePathSize); 344 345 // Generate the new Device Path by replacing the last node by the updated node 346 SetDevicePathEndNode (EndingDevicePath); 347 *NewDevicePath = AppendDevicePathNode (DevicePath, (CONST EFI_DEVICE_PATH_PROTOCOL *)FilePathDevicePath); 348 FreePool(DevicePath); 349 350 return EFI_SUCCESS; 351 } 352 353 /** 354 Check if a boot option path is a file system boot option path or not. 355 356 The device specified by the beginning of the path has to support the Simple File 357 System protocol. Furthermore, the remaining part of the path has to be composed of 358 a single node of type MEDIA_DEVICE_PATH and sub-type MEDIA_FILEPATH_DP. 359 360 @param[in] DevicePath Complete device path of a boot option. 361 362 @retval FALSE The boot option path has not been identified as that of a 363 file system boot option. 364 @retval TRUE The boot option path is a file system boot option. 365 **/ 366 BOOLEAN 367 BdsLoadOptionFileSystemIsSupported ( 368 IN EFI_DEVICE_PATH *DevicePath 369 ) 370 { 371 EFI_STATUS Status; 372 EFI_HANDLE Handle; 373 EFI_DEVICE_PATH *RemainingDevicePath; 374 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileProtocol; 375 376 Status = BdsConnectDevicePath (DevicePath, &Handle, &RemainingDevicePath); 377 if (EFI_ERROR (Status)) { 378 return FALSE; 379 } 380 381 Status = gBS->HandleProtocol ( 382 Handle, 383 &gEfiSimpleFileSystemProtocolGuid, 384 (VOID **)(&FileProtocol) 385 ); 386 if (EFI_ERROR (Status)) { 387 return FALSE; 388 } 389 390 if (!IS_DEVICE_PATH_NODE (RemainingDevicePath, MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP)) 391 return FALSE; 392 393 return TRUE; 394 } 395 396 STATIC 397 BOOLEAN 398 IsParentDevicePath ( 399 IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, 400 IN EFI_DEVICE_PATH_PROTOCOL *ChildDevicePath 401 ) 402 { 403 UINTN ParentSize; 404 UINTN ChildSize; 405 406 ParentSize = GetDevicePathSize (ParentDevicePath); 407 ChildSize = GetDevicePathSize (ChildDevicePath); 408 409 if (ParentSize > ChildSize) { 410 return FALSE; 411 } 412 413 if (CompareMem (ParentDevicePath, ChildDevicePath, ParentSize - END_DEVICE_PATH_LENGTH) != 0) { 414 return FALSE; 415 } 416 417 return TRUE; 418 } 419 420 EFI_STATUS 421 BdsLoadOptionMemMapList ( 422 IN OUT LIST_ENTRY* BdsLoadOptionList 423 ) 424 { 425 EFI_STATUS Status; 426 UINTN HandleCount; 427 EFI_HANDLE *HandleBuffer; 428 UINTN DevicePathHandleCount; 429 EFI_HANDLE *DevicePathHandleBuffer; 430 BOOLEAN IsParent; 431 UINTN Index; 432 UINTN Index2; 433 BDS_SUPPORTED_DEVICE *SupportedDevice; 434 EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol; 435 EFI_DEVICE_PATH* DevicePath; 436 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *FileProtocol; 437 EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvbProtocol; 438 439 // List all the BlockIo Protocols 440 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &HandleCount, &HandleBuffer); 441 if (EFI_ERROR (Status)) { 442 return Status; 443 } 444 445 for (Index = 0; Index < HandleCount; Index++) { 446 // We only select handles WITH a Device Path AND not part of Media (to 447 // avoid duplication with HardDisk, CDROM, etc). Skip handles used by 448 // Simple Filesystem or used for Variable Storage. 449 450 451 Status = gBS->HandleProtocol (HandleBuffer[Index], 452 &gEfiSimpleFileSystemProtocolGuid, 453 (VOID *)&FileProtocol); 454 if (!EFI_ERROR(Status)) { 455 // SimpleFilesystem supported on this handle, skip 456 continue; 457 } 458 459 Status = gBS->HandleProtocol (HandleBuffer[Index], 460 &gEfiFirmwareVolumeBlockProtocolGuid, 461 (VOID *)&FvbProtocol); 462 if (!EFI_ERROR(Status)) { 463 // Firmware Volme Block / Variable storage supported on this handle, skip 464 continue; 465 } 466 467 Status = gBS->HandleProtocol (HandleBuffer[Index], 468 &gEfiFirmwareVolumeBlock2ProtocolGuid, 469 (VOID *)&FvbProtocol); 470 if (!EFI_ERROR(Status)) { 471 // Firmware Volme Block / Variable storage supported on this handle, skip 472 continue; 473 } 474 475 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol); 476 if (!EFI_ERROR(Status)) { 477 // BlockIo is not part of Media Device Path 478 DevicePath = DevicePathProtocol; 479 while (!IsDevicePathEndType (DevicePath) && (DevicePathType (DevicePath) != MEDIA_DEVICE_PATH)) { 480 DevicePath = NextDevicePathNode (DevicePath); 481 } 482 if (DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) { 483 continue; 484 } 485 486 // Open all the handle supporting the DevicePath protocol and verify this handle has not got any child 487 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiDevicePathProtocolGuid, NULL, &DevicePathHandleCount, &DevicePathHandleBuffer); 488 ASSERT_EFI_ERROR (Status); 489 IsParent = FALSE; 490 for (Index2 = 0; (Index2 < DevicePathHandleCount) && !IsParent; Index2++) { 491 if (HandleBuffer[Index] != DevicePathHandleBuffer[Index2]) { 492 gBS->HandleProtocol (DevicePathHandleBuffer[Index2], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePath); 493 if (IsParentDevicePath (DevicePathProtocol, DevicePath)) { 494 IsParent = TRUE; 495 } 496 } 497 } 498 if (IsParent) { 499 continue; 500 } 501 502 // Allocate BDS Supported Device structure 503 SupportedDevice = (BDS_SUPPORTED_DEVICE*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE)); 504 505 Status = GenerateDeviceDescriptionName (HandleBuffer[Index], SupportedDevice->Description); 506 ASSERT_EFI_ERROR (Status); 507 508 SupportedDevice->DevicePathProtocol = DevicePathProtocol; 509 SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_MEMMAP]; 510 511 InsertTailList (BdsLoadOptionList,&SupportedDevice->Link); 512 } 513 } 514 515 return EFI_SUCCESS; 516 } 517 518 EFI_STATUS 519 BdsLoadOptionMemMapCreateDevicePath ( 520 IN CHAR16* FileName, 521 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes 522 ) 523 { 524 EFI_STATUS Status; 525 MEMMAP_DEVICE_PATH *MemMapDevicePath; 526 CHAR16 StrStartingAddress[BOOT_DEVICE_ADDRESS_MAX]; 527 CHAR16 StrEndingAddress[BOOT_DEVICE_ADDRESS_MAX]; 528 529 Print(L"Starting Address of the %s: ", FileName); 530 Status = GetHIInputStr (StrStartingAddress, BOOT_DEVICE_ADDRESS_MAX); 531 if (EFI_ERROR(Status)) { 532 return EFI_ABORTED; 533 } 534 535 Print(L"Ending Address of the %s: ", FileName); 536 Status = GetHIInputStr (StrEndingAddress, BOOT_DEVICE_ADDRESS_MAX); 537 if (EFI_ERROR(Status)) { 538 return EFI_ABORTED; 539 } 540 541 // Create the MemMap Device Path Node 542 MemMapDevicePath = (MEMMAP_DEVICE_PATH*)AllocatePool (sizeof(MEMMAP_DEVICE_PATH) + END_DEVICE_PATH_LENGTH); 543 MemMapDevicePath->Header.Type = HARDWARE_DEVICE_PATH; 544 MemMapDevicePath->Header.SubType = HW_MEMMAP_DP; 545 SetDevicePathNodeLength (MemMapDevicePath, sizeof(MEMMAP_DEVICE_PATH)); 546 MemMapDevicePath->MemoryType = EfiBootServicesData; 547 MemMapDevicePath->StartingAddress = StrHexToUint64 (StrStartingAddress); 548 MemMapDevicePath->EndingAddress = StrHexToUint64 (StrEndingAddress); 549 550 // Set a Device Path End Node after the Memory Map Device Path Node 551 SetDevicePathEndNode (MemMapDevicePath + 1); 552 *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL*)MemMapDevicePath; 553 554 return Status; 555 } 556 557 EFI_STATUS 558 BdsLoadOptionMemMapUpdateDevicePath ( 559 IN EFI_DEVICE_PATH *OldDevicePath, 560 IN CHAR16* FileName, 561 OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath 562 ) 563 { 564 EFI_STATUS Status; 565 CHAR16 StrStartingAddress[BOOT_DEVICE_ADDRESS_MAX]; 566 CHAR16 StrEndingAddress[BOOT_DEVICE_ADDRESS_MAX]; 567 MEMMAP_DEVICE_PATH* EndingDevicePath; 568 EFI_DEVICE_PATH* DevicePath; 569 570 DevicePath = DuplicateDevicePath (OldDevicePath); 571 EndingDevicePath = (MEMMAP_DEVICE_PATH*)GetLastDevicePathNode (DevicePath); 572 573 Print(L"Starting Address of the %s: ", FileName); 574 UnicodeSPrint (StrStartingAddress, BOOT_DEVICE_ADDRESS_MAX, L"0x%X", (UINTN)EndingDevicePath->StartingAddress); 575 Status = EditHIInputStr (StrStartingAddress, BOOT_DEVICE_ADDRESS_MAX); 576 if (EFI_ERROR(Status)) { 577 return EFI_ABORTED; 578 } 579 580 Print(L"Ending Address of the %s: ", FileName); 581 UnicodeSPrint (StrEndingAddress, BOOT_DEVICE_ADDRESS_MAX, L"0x%X", (UINTN)EndingDevicePath->EndingAddress); 582 Status = EditHIInputStr (StrEndingAddress, BOOT_DEVICE_ADDRESS_MAX); 583 if (EFI_ERROR(Status)) { 584 return EFI_ABORTED; 585 } 586 587 EndingDevicePath->StartingAddress = StrHexToUint64 (StrStartingAddress); 588 EndingDevicePath->EndingAddress = StrHexToUint64 (StrEndingAddress); 589 590 if (EFI_ERROR(Status)) { 591 FreePool(DevicePath); 592 } else { 593 *NewDevicePath = DevicePath; 594 } 595 596 return Status; 597 } 598 599 /** 600 Check if a boot option path is a memory map boot option path or not. 601 602 The device specified by the beginning of the path has to support the BlockIo 603 protocol. Furthermore, the remaining part of the path has to be composed of 604 a single node of type HARDWARE_DEVICE_PATH and sub-type HW_MEMMAP_DP. 605 606 @param[in] DevicePath Complete device path of a boot option. 607 608 @retval FALSE The boot option path has not been identified as that of a 609 memory map boot option. 610 @retval TRUE The boot option path is a a memory map boot option. 611 **/ 612 BOOLEAN 613 BdsLoadOptionMemMapIsSupported ( 614 IN EFI_DEVICE_PATH *DevicePath 615 ) 616 { 617 EFI_STATUS Status; 618 EFI_HANDLE Handle; 619 EFI_DEVICE_PATH *RemainingDevicePath; 620 EFI_BLOCK_IO_PROTOCOL *BlockIoProtocol; 621 622 Status = BdsConnectDevicePath (DevicePath, &Handle, &RemainingDevicePath); 623 if (EFI_ERROR (Status)) { 624 return FALSE; 625 } 626 627 Status = gBS->HandleProtocol ( 628 Handle, 629 &gEfiBlockIoProtocolGuid, 630 (VOID **)(&BlockIoProtocol) 631 ); 632 if (EFI_ERROR (Status)) { 633 return FALSE; 634 } 635 636 if (!IS_DEVICE_PATH_NODE (RemainingDevicePath, HARDWARE_DEVICE_PATH, HW_MEMMAP_DP)) 637 return FALSE; 638 639 return TRUE; 640 } 641 642 EFI_STATUS 643 BdsLoadOptionPxeList ( 644 IN OUT LIST_ENTRY* BdsLoadOptionList 645 ) 646 { 647 EFI_STATUS Status; 648 UINTN HandleCount; 649 EFI_HANDLE *HandleBuffer; 650 UINTN Index; 651 BDS_SUPPORTED_DEVICE *SupportedDevice; 652 EFI_DEVICE_PATH_PROTOCOL* DevicePathProtocol; 653 EFI_SIMPLE_NETWORK_PROTOCOL* SimpleNet; 654 CHAR16 DeviceDescription[BOOT_DEVICE_DESCRIPTION_MAX]; 655 EFI_MAC_ADDRESS *Mac; 656 657 // List all the PXE Protocols 658 Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiPxeBaseCodeProtocolGuid, NULL, &HandleCount, &HandleBuffer); 659 if (EFI_ERROR (Status)) { 660 return Status; 661 } 662 663 for (Index = 0; Index < HandleCount; Index++) { 664 // We only select the handle WITH a Device Path AND the PXE Protocol 665 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID **)&DevicePathProtocol); 666 if (!EFI_ERROR(Status)) { 667 // Allocate BDS Supported Device structure 668 SupportedDevice = (BDS_SUPPORTED_DEVICE*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE)); 669 670 Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiSimpleNetworkProtocolGuid, (VOID **)&SimpleNet); 671 if (!EFI_ERROR(Status)) { 672 Mac = &SimpleNet->Mode->CurrentAddress; 673 UnicodeSPrint (DeviceDescription,BOOT_DEVICE_DESCRIPTION_MAX,L"MAC Address: %02x:%02x:%02x:%02x:%02x:%02x", Mac->Addr[0], Mac->Addr[1], Mac->Addr[2], Mac->Addr[3], Mac->Addr[4], Mac->Addr[5]); 674 } else { 675 Status = GenerateDeviceDescriptionName (HandleBuffer[Index], DeviceDescription); 676 ASSERT_EFI_ERROR (Status); 677 } 678 UnicodeSPrint (SupportedDevice->Description,BOOT_DEVICE_DESCRIPTION_MAX,L"PXE on %s",DeviceDescription); 679 680 SupportedDevice->DevicePathProtocol = DevicePathProtocol; 681 SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_PXE]; 682 683 InsertTailList (BdsLoadOptionList,&SupportedDevice->Link); 684 } 685 } 686 687 return EFI_SUCCESS; 688 } 689 690 EFI_STATUS 691 BdsLoadOptionPxeCreateDevicePath ( 692 IN CHAR16* FileName, 693 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes 694 ) 695 { 696 *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH); 697 SetDevicePathEndNode (*DevicePathNodes); 698 699 return EFI_SUCCESS; 700 } 701 702 /** 703 Update the parameters of a Pxe boot option 704 705 @param[in] OldDevicePath Current complete device path of the Pxe boot option. 706 This has to be a valid complete Pxe boot option path. 707 @param[in] FileName Description of the file the path is asked for 708 @param[out] NewDevicePath Pointer to the new complete device path. 709 710 @retval EFI_SUCCESS Update completed 711 @retval EFI_OUT_OF_RESOURCES Fail to perform the update due to lack of resource 712 **/ 713 EFI_STATUS 714 BdsLoadOptionPxeUpdateDevicePath ( 715 IN EFI_DEVICE_PATH *OldDevicePath, 716 IN CHAR16* FileName, 717 OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath 718 ) 719 { 720 // 721 // Make a copy of the complete device path that is made of : 722 // the device path of the device supporting the Pxe base code protocol 723 // followed by an end node. 724 // 725 *NewDevicePath = DuplicateDevicePath (OldDevicePath); 726 if (*NewDevicePath == NULL) { 727 return EFI_OUT_OF_RESOURCES; 728 } else { 729 return EFI_SUCCESS; 730 } 731 } 732 733 BOOLEAN 734 BdsLoadOptionPxeIsSupported ( 735 IN EFI_DEVICE_PATH *DevicePath 736 ) 737 { 738 EFI_STATUS Status; 739 EFI_HANDLE Handle; 740 EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath; 741 EFI_PXE_BASE_CODE_PROTOCOL *PxeBcProtocol; 742 743 Status = BdsConnectDevicePath (DevicePath, &Handle, &RemainingDevicePath); 744 if (EFI_ERROR(Status)) { 745 return FALSE; 746 } 747 748 if (!IsDevicePathEnd(RemainingDevicePath)) { 749 return FALSE; 750 } 751 752 Status = gBS->HandleProtocol (Handle, &gEfiPxeBaseCodeProtocolGuid, (VOID **)&PxeBcProtocol); 753 if (EFI_ERROR (Status)) { 754 return FALSE; 755 } else { 756 return TRUE; 757 } 758 } 759 760 /** 761 Add to the list of boot devices the devices allowing a TFTP boot 762 763 @param[in] BdsLoadOptionList List of devices to boot from 764 765 @retval EFI_SUCCESS Update completed 766 @retval EFI_OUT_OF_RESOURCES Fail to perform the update due to lack of resource 767 **/ 768 EFI_STATUS 769 BdsLoadOptionTftpList ( 770 IN OUT LIST_ENTRY* BdsLoadOptionList 771 ) 772 { 773 EFI_STATUS Status; 774 UINTN HandleCount; 775 EFI_HANDLE *HandleBuffer; 776 EFI_HANDLE Handle; 777 UINTN Index; 778 EFI_DEVICE_PATH_PROTOCOL *DevicePathProtocol; 779 VOID *Interface; 780 EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetworkProtocol; 781 BDS_SUPPORTED_DEVICE *SupportedDevice; 782 EFI_MAC_ADDRESS *Mac; 783 784 // 785 // List all the handles on which the Simple Network Protocol is installed. 786 // 787 Status = gBS->LocateHandleBuffer ( 788 ByProtocol, 789 &gEfiSimpleNetworkProtocolGuid, 790 NULL, 791 &HandleCount, 792 &HandleBuffer 793 ); 794 if (EFI_ERROR (Status)) { 795 return Status; 796 } 797 798 for (Index = 0; Index < HandleCount; Index++) { 799 Handle = HandleBuffer[Index]; 800 // 801 // We select the handles that support : 802 // . the Device Path Protocol 803 // . the MTFTP4 Protocol 804 // 805 Status = gBS->HandleProtocol ( 806 Handle, 807 &gEfiDevicePathProtocolGuid, 808 (VOID **)&DevicePathProtocol 809 ); 810 if (EFI_ERROR (Status)) { 811 continue; 812 } 813 814 Status = gBS->HandleProtocol ( 815 Handle, 816 &gEfiMtftp4ServiceBindingProtocolGuid, 817 &Interface 818 ); 819 if (EFI_ERROR (Status)) { 820 continue; 821 } 822 823 Status = gBS->HandleProtocol ( 824 Handle, 825 &gEfiSimpleNetworkProtocolGuid, 826 (VOID **)&SimpleNetworkProtocol 827 ); 828 if (EFI_ERROR (Status)) { 829 continue; 830 } 831 832 // Allocate BDS Supported Device structure 833 SupportedDevice = (BDS_SUPPORTED_DEVICE*)AllocatePool (sizeof (BDS_SUPPORTED_DEVICE)); 834 if (SupportedDevice == NULL) { 835 continue; 836 } 837 838 Mac = &SimpleNetworkProtocol->Mode->CurrentAddress; 839 UnicodeSPrint ( 840 SupportedDevice->Description, 841 BOOT_DEVICE_DESCRIPTION_MAX, 842 L"TFTP on MAC Address: %02x:%02x:%02x:%02x:%02x:%02x", 843 Mac->Addr[0], Mac->Addr[1], Mac->Addr[2], Mac->Addr[3], Mac->Addr[4], Mac->Addr[5] 844 ); 845 846 SupportedDevice->DevicePathProtocol = DevicePathProtocol; 847 SupportedDevice->Support = &BdsLoadOptionSupportList[BDS_DEVICE_TFTP]; 848 849 InsertTailList (BdsLoadOptionList, &SupportedDevice->Link); 850 } 851 852 return EFI_SUCCESS; 853 } 854 855 EFI_STATUS 856 BdsLoadOptionTftpCreateDevicePath ( 857 IN CHAR16* FileName, 858 OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathNodes 859 ) 860 { 861 EFI_STATUS Status; 862 BOOLEAN IsDHCP; 863 EFI_IP_ADDRESS LocalIp; 864 EFI_IP_ADDRESS SubnetMask; 865 EFI_IP_ADDRESS GatewayIp; 866 EFI_IP_ADDRESS RemoteIp; 867 IPv4_DEVICE_PATH *IPv4DevicePathNode; 868 FILEPATH_DEVICE_PATH *FilePathDevicePath; 869 CHAR16 BootFilePath[BOOT_DEVICE_FILEPATH_MAX]; 870 UINTN BootFilePathSize; 871 872 Print (L"Get the IP address from DHCP: "); 873 Status = GetHIInputBoolean (&IsDHCP); 874 if (EFI_ERROR (Status)) { 875 return EFI_ABORTED; 876 } 877 878 if (!IsDHCP) { 879 Print (L"Local static IP address: "); 880 Status = GetHIInputIP (&LocalIp); 881 if (EFI_ERROR (Status)) { 882 return EFI_ABORTED; 883 } 884 Print (L"Get the network mask: "); 885 Status = GetHIInputIP (&SubnetMask); 886 if (EFI_ERROR (Status)) { 887 return EFI_ABORTED; 888 } 889 Print (L"Get the gateway IP address: "); 890 Status = GetHIInputIP (&GatewayIp); 891 if (EFI_ERROR (Status)) { 892 return EFI_ABORTED; 893 } 894 } 895 896 Print (L"Get the TFTP server IP address: "); 897 Status = GetHIInputIP (&RemoteIp); 898 if (EFI_ERROR (Status)) { 899 return EFI_ABORTED; 900 } 901 902 Print (L"File path of the %s : ", FileName); 903 Status = GetHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX); 904 if (EFI_ERROR (Status)) { 905 return EFI_ABORTED; 906 } 907 908 BootFilePathSize = StrSize(BootFilePath); 909 if (BootFilePathSize == 2) { 910 return EFI_NOT_FOUND; 911 } 912 913 // Allocate the memory for the IPv4 + File Path Device Path Nodes 914 IPv4DevicePathNode = (IPv4_DEVICE_PATH*)AllocatePool(sizeof(IPv4_DEVICE_PATH) + SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize + END_DEVICE_PATH_LENGTH); 915 916 // Create the IPv4 Device Path 917 IPv4DevicePathNode->Header.Type = MESSAGING_DEVICE_PATH; 918 IPv4DevicePathNode->Header.SubType = MSG_IPv4_DP; 919 SetDevicePathNodeLength (&IPv4DevicePathNode->Header, sizeof(IPv4_DEVICE_PATH)); 920 921 if (!IsDHCP) { 922 CopyMem (&IPv4DevicePathNode->LocalIpAddress, &LocalIp.v4, sizeof (EFI_IPv4_ADDRESS)); 923 CopyMem (&IPv4DevicePathNode->SubnetMask, &SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS)); 924 CopyMem (&IPv4DevicePathNode->GatewayIpAddress, &GatewayIp.v4, sizeof (EFI_IPv4_ADDRESS)); 925 } 926 927 CopyMem (&IPv4DevicePathNode->RemoteIpAddress, &RemoteIp.v4, sizeof (EFI_IPv4_ADDRESS)); 928 IPv4DevicePathNode->LocalPort = 0; 929 IPv4DevicePathNode->RemotePort = 0; 930 IPv4DevicePathNode->Protocol = EFI_IP_PROTO_TCP; 931 IPv4DevicePathNode->StaticIpAddress = (IsDHCP != TRUE); 932 933 // Create the FilePath Device Path node 934 FilePathDevicePath = (FILEPATH_DEVICE_PATH*)(IPv4DevicePathNode + 1); 935 FilePathDevicePath->Header.Type = MEDIA_DEVICE_PATH; 936 FilePathDevicePath->Header.SubType = MEDIA_FILEPATH_DP; 937 SetDevicePathNodeLength (FilePathDevicePath, SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize); 938 CopyMem (FilePathDevicePath->PathName, BootFilePath, BootFilePathSize); 939 940 // Set the End Device Path Node 941 SetDevicePathEndNode ((VOID*)((UINTN)FilePathDevicePath + SIZE_OF_FILEPATH_DEVICE_PATH + BootFilePathSize)); 942 *DevicePathNodes = (EFI_DEVICE_PATH_PROTOCOL*)IPv4DevicePathNode; 943 944 return Status; 945 } 946 947 /** 948 Update the parameters of a TFTP boot option 949 950 The function asks sequentially to update the IPv4 parameters as well as the boot file path, 951 providing the previously set value if any. 952 953 @param[in] OldDevicePath Current complete device path of the Tftp boot option. 954 This has to be a valid complete Tftp boot option path. 955 By complete, we mean that it is not only the Tftp 956 specific end part built by the 957 "BdsLoadOptionTftpCreateDevicePath()" function. 958 This path is handled as read only. 959 @param[in] FileName Description of the file the path is asked for 960 @param[out] NewDevicePath Pointer to the new complete device path. 961 962 @retval EFI_SUCCESS Update completed 963 @retval EFI_ABORTED Update aborted by the user 964 @retval EFI_OUT_OF_RESOURCES Fail to perform the update due to lack of resource 965 **/ 966 EFI_STATUS 967 BdsLoadOptionTftpUpdateDevicePath ( 968 IN EFI_DEVICE_PATH *OldDevicePath, 969 IN CHAR16 *FileName, 970 OUT EFI_DEVICE_PATH_PROTOCOL **NewDevicePath 971 ) 972 { 973 EFI_STATUS Status; 974 EFI_DEVICE_PATH *DevicePath; 975 EFI_DEVICE_PATH *DevicePathNode; 976 UINT8 *Ipv4NodePtr; 977 IPv4_DEVICE_PATH Ipv4Node; 978 BOOLEAN IsDHCP; 979 EFI_IP_ADDRESS OldIp; 980 EFI_IP_ADDRESS OldSubnetMask; 981 EFI_IP_ADDRESS OldGatewayIp; 982 EFI_IP_ADDRESS LocalIp; 983 EFI_IP_ADDRESS SubnetMask; 984 EFI_IP_ADDRESS GatewayIp; 985 EFI_IP_ADDRESS RemoteIp; 986 UINT8 *FileNodePtr; 987 CHAR16 BootFilePath[BOOT_DEVICE_FILEPATH_MAX]; 988 UINTN PathSize; 989 UINTN BootFilePathSize; 990 FILEPATH_DEVICE_PATH *NewFilePathNode; 991 992 Ipv4NodePtr = NULL; 993 994 // 995 // Make a copy of the complete device path that is made of : 996 // the device path of the device that support the Simple Network protocol 997 // followed by an IPv4 node (type IPv4_DEVICE_PATH), 998 // followed by a file path node (type FILEPATH_DEVICE_PATH) and ended up 999 // by an end node. The IPv6 case is not handled yet. 1000 // 1001 1002 DevicePath = DuplicateDevicePath (OldDevicePath); 1003 if (DevicePath == NULL) { 1004 Status = EFI_OUT_OF_RESOURCES; 1005 goto ErrorExit; 1006 } 1007 1008 // 1009 // Because of the check done by "BdsLoadOptionTftpIsSupported()" prior to the 1010 // call to this function, we know that the device path ends with an IPv4 node 1011 // followed by a file path node and finally an end node. To get the address of 1012 // the last IPv4 node, we loop over the whole device path, noting down the 1013 // address of each encountered IPv4 node. 1014 // 1015 1016 for (DevicePathNode = DevicePath; 1017 !IsDevicePathEnd (DevicePathNode); 1018 DevicePathNode = NextDevicePathNode (DevicePathNode)) 1019 { 1020 if (IS_DEVICE_PATH_NODE (DevicePathNode, MESSAGING_DEVICE_PATH, MSG_IPv4_DP)) { 1021 Ipv4NodePtr = (UINT8*)DevicePathNode; 1022 } 1023 } 1024 1025 // Copy for alignment of the IPv4 node data 1026 CopyMem (&Ipv4Node, Ipv4NodePtr, sizeof (IPv4_DEVICE_PATH)); 1027 1028 Print (L"Get the IP address from DHCP: "); 1029 Status = GetHIInputBoolean (&IsDHCP); 1030 if (EFI_ERROR (Status)) { 1031 goto ErrorExit; 1032 } 1033 1034 if (!IsDHCP) { 1035 Print (L"Local static IP address: "); 1036 if (Ipv4Node.StaticIpAddress) { 1037 CopyMem (&OldIp.v4, &Ipv4Node.LocalIpAddress, sizeof (EFI_IPv4_ADDRESS)); 1038 Status = EditHIInputIP (&OldIp, &LocalIp); 1039 } else { 1040 Status = GetHIInputIP (&LocalIp); 1041 } 1042 if (EFI_ERROR (Status)) { 1043 goto ErrorExit; 1044 } 1045 1046 Print (L"Get the network mask: "); 1047 if (Ipv4Node.StaticIpAddress) { 1048 CopyMem (&OldSubnetMask.v4, &Ipv4Node.SubnetMask, sizeof (EFI_IPv4_ADDRESS)); 1049 Status = EditHIInputIP (&OldSubnetMask, &SubnetMask); 1050 } else { 1051 Status = GetHIInputIP (&SubnetMask); 1052 } 1053 if (EFI_ERROR (Status)) { 1054 goto ErrorExit; 1055 } 1056 1057 Print (L"Get the gateway IP address: "); 1058 if (Ipv4Node.StaticIpAddress) { 1059 CopyMem (&OldGatewayIp.v4, &Ipv4Node.GatewayIpAddress, sizeof (EFI_IPv4_ADDRESS)); 1060 Status = EditHIInputIP (&OldGatewayIp, &GatewayIp); 1061 } else { 1062 Status = GetHIInputIP (&GatewayIp); 1063 } 1064 if (EFI_ERROR (Status)) { 1065 goto ErrorExit; 1066 } 1067 } 1068 1069 Print (L"TFTP server IP address: "); 1070 // Copy remote IPv4 address into IPv4 or IPv6 union 1071 CopyMem (&OldIp.v4, &Ipv4Node.RemoteIpAddress, sizeof (EFI_IPv4_ADDRESS)); 1072 1073 Status = EditHIInputIP (&OldIp, &RemoteIp); 1074 if (EFI_ERROR (Status)) { 1075 goto ErrorExit; 1076 } 1077 1078 // Get the path of the boot file and its size in number of bytes 1079 FileNodePtr = Ipv4NodePtr + sizeof (IPv4_DEVICE_PATH); 1080 BootFilePathSize = DevicePathNodeLength (FileNodePtr) - SIZE_OF_FILEPATH_DEVICE_PATH; 1081 1082 // 1083 // Ask for update of the boot file path 1084 // 1085 do { 1086 // Copy for 2-byte alignment of the Unicode string 1087 CopyMem ( 1088 BootFilePath, FileNodePtr + SIZE_OF_FILEPATH_DEVICE_PATH, 1089 MIN (BootFilePathSize, BOOT_DEVICE_FILEPATH_MAX) 1090 ); 1091 BootFilePath[BOOT_DEVICE_FILEPATH_MAX - 1] = L'\0'; 1092 1093 Print (L"File path of the %s: ", FileName); 1094 Status = EditHIInputStr (BootFilePath, BOOT_DEVICE_FILEPATH_MAX); 1095 if (EFI_ERROR (Status)) { 1096 goto ErrorExit; 1097 } 1098 PathSize = StrSize (BootFilePath); 1099 if (PathSize > 2) { 1100 break; 1101 } 1102 // Empty string, give the user another try 1103 Print (L"Empty string - Invalid path\n"); 1104 } while (PathSize <= 2) ; 1105 1106 // 1107 // Update the IPv4 node. IPv6 case not handled yet. 1108 // 1109 if (IsDHCP) { 1110 Ipv4Node.StaticIpAddress = FALSE; 1111 ZeroMem (&Ipv4Node.LocalIpAddress, sizeof (EFI_IPv4_ADDRESS)); 1112 ZeroMem (&Ipv4Node.SubnetMask, sizeof (EFI_IPv4_ADDRESS)); 1113 ZeroMem (&Ipv4Node.GatewayIpAddress, sizeof (EFI_IPv4_ADDRESS)); 1114 } else { 1115 Ipv4Node.StaticIpAddress = TRUE; 1116 CopyMem (&Ipv4Node.LocalIpAddress, &LocalIp.v4, sizeof (EFI_IPv4_ADDRESS)); 1117 CopyMem (&Ipv4Node.SubnetMask, &SubnetMask.v4, sizeof (EFI_IPv4_ADDRESS)); 1118 CopyMem (&Ipv4Node.GatewayIpAddress, &GatewayIp.v4, sizeof (EFI_IPv4_ADDRESS)); 1119 } 1120 1121 CopyMem (&Ipv4Node.RemoteIpAddress, &RemoteIp.v4, sizeof (EFI_IPv4_ADDRESS)); 1122 CopyMem (Ipv4NodePtr, &Ipv4Node, sizeof (IPv4_DEVICE_PATH)); 1123 1124 // 1125 // Create the new file path node 1126 // 1127 NewFilePathNode = (FILEPATH_DEVICE_PATH*)AllocatePool ( 1128 SIZE_OF_FILEPATH_DEVICE_PATH + 1129 PathSize 1130 ); 1131 NewFilePathNode->Header.Type = MEDIA_DEVICE_PATH; 1132 NewFilePathNode->Header.SubType = MEDIA_FILEPATH_DP; 1133 SetDevicePathNodeLength ( 1134 NewFilePathNode, 1135 SIZE_OF_FILEPATH_DEVICE_PATH + PathSize 1136 ); 1137 CopyMem (NewFilePathNode->PathName, BootFilePath, PathSize); 1138 1139 // 1140 // Generate the new Device Path by replacing the file path node at address 1141 // "FileNodePtr" by the new one "NewFilePathNode" and return its address. 1142 // 1143 SetDevicePathEndNode (FileNodePtr); 1144 *NewDevicePath = AppendDevicePathNode ( 1145 DevicePath, 1146 (CONST EFI_DEVICE_PATH_PROTOCOL*)NewFilePathNode 1147 ); 1148 1149 ErrorExit: 1150 if (DevicePath != NULL) { 1151 FreePool (DevicePath) ; 1152 } 1153 1154 return Status; 1155 } 1156 1157 BOOLEAN 1158 BdsLoadOptionTftpIsSupported ( 1159 IN EFI_DEVICE_PATH *DevicePath 1160 ) 1161 { 1162 EFI_STATUS Status; 1163 EFI_HANDLE Handle; 1164 EFI_DEVICE_PATH *RemainingDevicePath; 1165 EFI_DEVICE_PATH *NextDevicePath; 1166 EFI_PXE_BASE_CODE_PROTOCOL *PxeBcProtocol; 1167 1168 Status = BdsConnectDevicePath (DevicePath, &Handle, &RemainingDevicePath); 1169 if (EFI_ERROR(Status)) { 1170 return FALSE; 1171 } 1172 1173 // Validate the Remaining Device Path 1174 if (IsDevicePathEnd(RemainingDevicePath)) { 1175 return FALSE; 1176 } 1177 if (!IS_DEVICE_PATH_NODE(RemainingDevicePath,MESSAGING_DEVICE_PATH,MSG_IPv4_DP) && 1178 !IS_DEVICE_PATH_NODE(RemainingDevicePath,MESSAGING_DEVICE_PATH,MSG_IPv6_DP)) { 1179 return FALSE; 1180 } 1181 NextDevicePath = NextDevicePathNode (RemainingDevicePath); 1182 if (IsDevicePathEnd(NextDevicePath)) { 1183 return FALSE; 1184 } 1185 if (!IS_DEVICE_PATH_NODE(NextDevicePath,MEDIA_DEVICE_PATH,MEDIA_FILEPATH_DP)) { 1186 return FALSE; 1187 } 1188 1189 Status = gBS->HandleProtocol (Handle, &gEfiPxeBaseCodeProtocolGuid, (VOID **)&PxeBcProtocol); 1190 if (EFI_ERROR (Status)) { 1191 return FALSE; 1192 } else { 1193 return TRUE; 1194 } 1195 } 1196