3 * Copyright (c) 2011-2014, ARM Limited. All rights reserved.
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
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.
15 #include "BdsInternal.h"
17 #include <Library/NetLib.h>
19 #include <Protocol/BlockIo.h>
20 #include <Protocol/DevicePathToText.h>
21 #include <Protocol/PxeBaseCode.h>
22 #include <Protocol/SimpleFileSystem.h>
23 #include <Protocol/SimpleNetwork.h>
25 #include <Guid/FileSystemInfo.h>
27 #define IS_DEVICE_PATH_NODE(node,type,subtype) (((node)->Type == (type)) && ((node)->SubType == (subtype)))
30 BdsLoadOptionFileSystemList (
31 IN OUT LIST_ENTRY
* BdsLoadOptionList
35 BdsLoadOptionFileSystemCreateDevicePath (
37 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNodes
41 BdsLoadOptionFileSystemUpdateDevicePath (
42 IN EFI_DEVICE_PATH
*OldDevicePath
,
44 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath
48 BdsLoadOptionFileSystemIsSupported (
49 IN EFI_DEVICE_PATH
*DevicePath
53 BdsLoadOptionMemMapList (
54 IN OUT LIST_ENTRY
* BdsLoadOptionList
58 BdsLoadOptionMemMapCreateDevicePath (
60 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNodes
64 BdsLoadOptionMemMapUpdateDevicePath (
65 IN EFI_DEVICE_PATH
*OldDevicePath
,
67 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath
71 BdsLoadOptionMemMapIsSupported (
72 IN EFI_DEVICE_PATH
*DevicePath
76 BdsLoadOptionPxeList (
77 IN OUT LIST_ENTRY
* BdsLoadOptionList
81 BdsLoadOptionPxeCreateDevicePath (
83 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNodes
87 BdsLoadOptionPxeUpdateDevicePath (
88 IN EFI_DEVICE_PATH
*OldDevicePath
,
90 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath
94 BdsLoadOptionPxeIsSupported (
95 IN EFI_DEVICE_PATH
*DevicePath
99 BdsLoadOptionTftpList (
100 IN OUT LIST_ENTRY
* BdsLoadOptionList
104 BdsLoadOptionTftpCreateDevicePath (
106 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNodes
110 BdsLoadOptionTftpUpdateDevicePath (
111 IN EFI_DEVICE_PATH
*OldDevicePath
,
113 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath
117 BdsLoadOptionTftpIsSupported (
118 IN EFI_DEVICE_PATH
*DevicePath
121 BDS_LOAD_OPTION_SUPPORT BdsLoadOptionSupportList
[] = {
123 BDS_DEVICE_FILESYSTEM
,
124 BdsLoadOptionFileSystemList
,
125 BdsLoadOptionFileSystemIsSupported
,
126 BdsLoadOptionFileSystemCreateDevicePath
,
127 BdsLoadOptionFileSystemUpdateDevicePath
,
132 BdsLoadOptionMemMapList
,
133 BdsLoadOptionMemMapIsSupported
,
134 BdsLoadOptionMemMapCreateDevicePath
,
135 BdsLoadOptionMemMapUpdateDevicePath
,
140 BdsLoadOptionPxeList
,
141 BdsLoadOptionPxeIsSupported
,
142 BdsLoadOptionPxeCreateDevicePath
,
143 BdsLoadOptionPxeUpdateDevicePath
,
148 BdsLoadOptionTftpList
,
149 BdsLoadOptionTftpIsSupported
,
150 BdsLoadOptionTftpCreateDevicePath
,
151 BdsLoadOptionTftpUpdateDevicePath
,
157 BootDeviceListSupportedInit (
158 IN OUT LIST_ENTRY
*SupportedDeviceList
163 // Initialize list of supported devices
164 InitializeListHead (SupportedDeviceList
);
166 for (Index
= 0; Index
< BDS_DEVICE_MAX
; Index
++) {
167 BdsLoadOptionSupportList
[Index
].ListDevices (SupportedDeviceList
);
174 BootDeviceListSupportedFree (
175 IN LIST_ENTRY
*SupportedDeviceList
,
176 IN BDS_SUPPORTED_DEVICE
*Except
180 BDS_SUPPORTED_DEVICE
* SupportedDevice
;
182 Entry
= GetFirstNode (SupportedDeviceList
);
183 while (Entry
!= SupportedDeviceList
) {
184 SupportedDevice
= SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry
);
185 Entry
= RemoveEntryList (Entry
);
186 if (SupportedDevice
!= Except
) {
187 FreePool (SupportedDevice
);
195 BootDeviceGetDeviceSupport (
196 IN EFI_DEVICE_PATH
*DevicePath
,
197 OUT BDS_LOAD_OPTION_SUPPORT
**DeviceSupport
202 // Find which supported device is the most appropriate
203 for (Index
= 0; Index
< BDS_DEVICE_MAX
; Index
++) {
204 if (BdsLoadOptionSupportList
[Index
].IsSupported (DevicePath
)) {
205 *DeviceSupport
= &BdsLoadOptionSupportList
[Index
];
210 return EFI_UNSUPPORTED
;
215 IN EFI_DEVICE_PATH
* DevicePath
,
216 OUT ARM_BDS_LOADER_TYPE
*BootType
,
217 OUT UINT32
*Attributes
222 BOOLEAN IsBootLoader
;
223 BOOLEAN HasFDTSupport
;
225 EFI_DEVICE_PATH
* PrevDevicePathNode
;
226 EFI_DEVICE_PATH
* DevicePathNode
;
227 EFI_PHYSICAL_ADDRESS Image
;
229 EFI_IMAGE_DOS_HEADER
* DosHeader
;
230 UINTN PeCoffHeaderOffset
;
231 EFI_IMAGE_NT_HEADERS32
* NtHeader
;
234 // Check if the last node of the device path is a FilePath node
236 PrevDevicePathNode
= NULL
;
237 DevicePathNode
= DevicePath
;
238 while ((DevicePathNode
!= NULL
) && !IsDevicePathEnd (DevicePathNode
)) {
239 PrevDevicePathNode
= DevicePathNode
;
240 DevicePathNode
= NextDevicePathNode (DevicePathNode
);
243 if ((PrevDevicePathNode
!= NULL
) &&
244 (PrevDevicePathNode
->Type
== MEDIA_DEVICE_PATH
) &&
245 (PrevDevicePathNode
->SubType
== MEDIA_FILEPATH_DP
))
247 FileName
= ((FILEPATH_DEVICE_PATH
*)PrevDevicePathNode
)->PathName
;
252 if (FileName
== NULL
) {
253 Print(L
"Is an EFI Application? ");
254 Status
= GetHIInputBoolean (&IsEfiApp
);
255 if (EFI_ERROR(Status
)) {
258 } else if (HasFilePathEfiExtension(FileName
)) {
261 // Check if the file exist
262 Status
= BdsLoadImage (DevicePath
, AllocateAnyPages
, &Image
, &FileSize
);
263 if (!EFI_ERROR (Status
)) {
265 DosHeader
= (EFI_IMAGE_DOS_HEADER
*)(UINTN
) Image
;
266 if (DosHeader
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
268 // DOS image header is present,
269 // so read the PE header after the DOS image header.
271 PeCoffHeaderOffset
= DosHeader
->e_lfanew
;
273 PeCoffHeaderOffset
= 0;
277 // Check PE/COFF image.
279 NtHeader
= (EFI_IMAGE_NT_HEADERS32
*)(UINTN
) (Image
+ PeCoffHeaderOffset
);
280 if (NtHeader
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
287 gBS
->FreePages (Image
, EFI_SIZE_TO_PAGES(FileSize
));
289 // If we did not manage to open it then ask for the type
290 Print(L
"Is an EFI Application? ");
291 Status
= GetHIInputBoolean (&IsEfiApp
);
292 if (EFI_ERROR(Status
)) {
299 Print(L
"Is your application is an OS loader? ");
300 Status
= GetHIInputBoolean (&IsBootLoader
);
301 if (EFI_ERROR(Status
)) {
305 *Attributes
|= LOAD_OPTION_CATEGORY_APP
;
307 *BootType
= BDS_LOADER_EFI_APPLICATION
;
309 Print(L
"Has FDT support? ");
310 Status
= GetHIInputBoolean (&HasFDTSupport
);
311 if (EFI_ERROR(Status
)) {
315 *BootType
= BDS_LOADER_KERNEL_LINUX_FDT
;
317 *BootType
= BDS_LOADER_KERNEL_LINUX_ATAG
;
325 BdsLoadOptionFileSystemList (
326 IN OUT LIST_ENTRY
* BdsLoadOptionList
331 EFI_HANDLE
*HandleBuffer
;
333 BDS_SUPPORTED_DEVICE
*SupportedDevice
;
334 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
* FileProtocol
;
337 EFI_FILE_SYSTEM_INFO
* FsInfo
;
338 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
340 // List all the Simple File System Protocols
341 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiSimpleFileSystemProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
342 if (EFI_ERROR (Status
)) {
346 for (Index
= 0; Index
< HandleCount
; Index
++) {
347 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
348 if (!EFI_ERROR(Status
)) {
349 // Allocate BDS Supported Device structure
350 SupportedDevice
= (BDS_SUPPORTED_DEVICE
*)AllocatePool (sizeof(BDS_SUPPORTED_DEVICE
));
353 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiSimpleFileSystemProtocolGuid
, (VOID
**)&FileProtocol
);
354 ASSERT_EFI_ERROR(Status
);
356 FileProtocol
->OpenVolume (FileProtocol
, &Fs
);
358 // Generate a Description from the file system
361 Status
= Fs
->GetInfo (Fs
, &gEfiFileSystemInfoGuid
, &Size
, FsInfo
);
362 if (Status
== EFI_BUFFER_TOO_SMALL
) {
363 FsInfo
= AllocatePool (Size
);
364 Status
= Fs
->GetInfo (Fs
, &gEfiFileSystemInfoGuid
, &Size
, FsInfo
);
366 UnicodeSPrint (SupportedDevice
->Description
,BOOT_DEVICE_DESCRIPTION_MAX
,L
"%s (%d MB)",FsInfo
->VolumeLabel
,(UINT32
)(FsInfo
->VolumeSize
/ (1024 * 1024)));
370 SupportedDevice
->DevicePathProtocol
= DevicePathProtocol
;
371 SupportedDevice
->Support
= &BdsLoadOptionSupportList
[BDS_DEVICE_FILESYSTEM
];
373 InsertTailList (BdsLoadOptionList
,&SupportedDevice
->Link
);
381 BdsLoadOptionFileSystemCreateDevicePath (
383 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNodes
387 FILEPATH_DEVICE_PATH
* FilePathDevicePath
;
388 CHAR16 BootFilePath
[BOOT_DEVICE_FILEPATH_MAX
];
389 UINTN BootFilePathSize
;
391 Print(L
"File path of the %s: ", FileName
);
392 Status
= GetHIInputStr (BootFilePath
, BOOT_DEVICE_FILEPATH_MAX
);
393 if (EFI_ERROR(Status
)) {
397 BootFilePathSize
= StrSize (BootFilePath
);
398 if (BootFilePathSize
== 2) {
399 *DevicePathNodes
= NULL
;
400 return EFI_NOT_FOUND
;
403 // Create the FilePath Device Path node
404 FilePathDevicePath
= (FILEPATH_DEVICE_PATH
*)AllocatePool(SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
+ END_DEVICE_PATH_LENGTH
);
405 FilePathDevicePath
->Header
.Type
= MEDIA_DEVICE_PATH
;
406 FilePathDevicePath
->Header
.SubType
= MEDIA_FILEPATH_DP
;
407 SetDevicePathNodeLength (FilePathDevicePath
, SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
408 CopyMem (FilePathDevicePath
->PathName
, BootFilePath
, BootFilePathSize
);
409 SetDevicePathEndNode ((VOID
*)((UINTN
)FilePathDevicePath
+ SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
));
410 *DevicePathNodes
= (EFI_DEVICE_PATH_PROTOCOL
*)FilePathDevicePath
;
416 BdsLoadOptionFileSystemUpdateDevicePath (
417 IN EFI_DEVICE_PATH
*OldDevicePath
,
419 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath
423 CHAR16 BootFilePath
[BOOT_DEVICE_FILEPATH_MAX
];
424 UINTN BootFilePathSize
;
425 FILEPATH_DEVICE_PATH
* EndingDevicePath
;
426 FILEPATH_DEVICE_PATH
* FilePathDevicePath
;
427 EFI_DEVICE_PATH
* DevicePath
;
429 DevicePath
= DuplicateDevicePath (OldDevicePath
);
431 EndingDevicePath
= (FILEPATH_DEVICE_PATH
*)GetLastDevicePathNode (DevicePath
);
433 Print(L
"File path of the %s: ", FileName
);
434 StrnCpy (BootFilePath
, EndingDevicePath
->PathName
, BOOT_DEVICE_FILEPATH_MAX
);
435 Status
= EditHIInputStr (BootFilePath
, BOOT_DEVICE_FILEPATH_MAX
);
436 if (EFI_ERROR(Status
)) {
440 BootFilePathSize
= StrSize(BootFilePath
);
441 if (BootFilePathSize
== 2) {
442 *NewDevicePath
= NULL
;
443 return EFI_NOT_FOUND
;
446 // Create the FilePath Device Path node
447 FilePathDevicePath
= (FILEPATH_DEVICE_PATH
*)AllocatePool(SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
448 FilePathDevicePath
->Header
.Type
= MEDIA_DEVICE_PATH
;
449 FilePathDevicePath
->Header
.SubType
= MEDIA_FILEPATH_DP
;
450 SetDevicePathNodeLength (FilePathDevicePath
, SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
451 CopyMem (FilePathDevicePath
->PathName
, BootFilePath
, BootFilePathSize
);
453 // Generate the new Device Path by replacing the last node by the updated node
454 SetDevicePathEndNode (EndingDevicePath
);
455 *NewDevicePath
= AppendDevicePathNode (DevicePath
, (CONST EFI_DEVICE_PATH_PROTOCOL
*)FilePathDevicePath
);
456 FreePool(DevicePath
);
462 BdsLoadOptionFileSystemIsSupported (
463 IN EFI_DEVICE_PATH
*DevicePath
466 EFI_DEVICE_PATH
* DevicePathNode
;
468 DevicePathNode
= GetLastDevicePathNode (DevicePath
);
470 return IS_DEVICE_PATH_NODE(DevicePathNode
,MEDIA_DEVICE_PATH
,MEDIA_FILEPATH_DP
);
476 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
477 IN EFI_DEVICE_PATH_PROTOCOL
*ChildDevicePath
483 ParentSize
= GetDevicePathSize (ParentDevicePath
);
484 ChildSize
= GetDevicePathSize (ChildDevicePath
);
486 if (ParentSize
> ChildSize
) {
490 if (CompareMem (ParentDevicePath
, ChildDevicePath
, ParentSize
- END_DEVICE_PATH_LENGTH
) != 0) {
498 BdsLoadOptionMemMapList (
499 IN OUT LIST_ENTRY
* BdsLoadOptionList
504 EFI_HANDLE
*HandleBuffer
;
505 UINTN DevicePathHandleCount
;
506 EFI_HANDLE
*DevicePathHandleBuffer
;
510 BDS_SUPPORTED_DEVICE
*SupportedDevice
;
511 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
512 EFI_DEVICE_PATH
* DevicePath
;
514 // List all the BlockIo Protocols
515 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiBlockIoProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
516 if (EFI_ERROR (Status
)) {
520 for (Index
= 0; Index
< HandleCount
; Index
++) {
521 // We only select the handle WITH a Device Path AND not part of Media (to avoid duplication with HardDisk, CDROM, etc)
522 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
523 if (!EFI_ERROR(Status
)) {
524 // BlockIo is not part of Media Device Path
525 DevicePath
= DevicePathProtocol
;
526 while (!IsDevicePathEndType (DevicePath
) && (DevicePathType (DevicePath
) != MEDIA_DEVICE_PATH
)) {
527 DevicePath
= NextDevicePathNode (DevicePath
);
529 if (DevicePathType (DevicePath
) == MEDIA_DEVICE_PATH
) {
533 // Open all the handle supporting the DevicePath protocol and verify this handle has not got any child
534 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiDevicePathProtocolGuid
, NULL
, &DevicePathHandleCount
, &DevicePathHandleBuffer
);
535 ASSERT_EFI_ERROR (Status
);
537 for (Index2
= 0; (Index2
< DevicePathHandleCount
) && !IsParent
; Index2
++) {
538 if (HandleBuffer
[Index
] != DevicePathHandleBuffer
[Index2
]) {
539 gBS
->HandleProtocol (DevicePathHandleBuffer
[Index2
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePath
);
540 if (IsParentDevicePath (DevicePathProtocol
, DevicePath
)) {
549 // Allocate BDS Supported Device structure
550 SupportedDevice
= (BDS_SUPPORTED_DEVICE
*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE
));
552 Status
= GenerateDeviceDescriptionName (HandleBuffer
[Index
], SupportedDevice
->Description
);
553 ASSERT_EFI_ERROR (Status
);
555 SupportedDevice
->DevicePathProtocol
= DevicePathProtocol
;
556 SupportedDevice
->Support
= &BdsLoadOptionSupportList
[BDS_DEVICE_MEMMAP
];
558 InsertTailList (BdsLoadOptionList
,&SupportedDevice
->Link
);
566 BdsLoadOptionMemMapCreateDevicePath (
568 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNodes
572 MEMMAP_DEVICE_PATH
*MemMapDevicePath
;
573 CHAR16 StrStartingAddress
[BOOT_DEVICE_ADDRESS_MAX
];
574 CHAR16 StrEndingAddress
[BOOT_DEVICE_ADDRESS_MAX
];
576 Print(L
"Starting Address of the %s: ", FileName
);
577 Status
= GetHIInputStr (StrStartingAddress
, BOOT_DEVICE_ADDRESS_MAX
);
578 if (EFI_ERROR(Status
)) {
582 Print(L
"Ending Address of the %s: ", FileName
);
583 Status
= GetHIInputStr (StrEndingAddress
, BOOT_DEVICE_ADDRESS_MAX
);
584 if (EFI_ERROR(Status
)) {
588 // Create the MemMap Device Path Node
589 MemMapDevicePath
= (MEMMAP_DEVICE_PATH
*)AllocatePool (sizeof(MEMMAP_DEVICE_PATH
) + END_DEVICE_PATH_LENGTH
);
590 MemMapDevicePath
->Header
.Type
= HARDWARE_DEVICE_PATH
;
591 MemMapDevicePath
->Header
.SubType
= HW_MEMMAP_DP
;
592 SetDevicePathNodeLength (MemMapDevicePath
, sizeof(MEMMAP_DEVICE_PATH
));
593 MemMapDevicePath
->MemoryType
= EfiBootServicesData
;
594 MemMapDevicePath
->StartingAddress
= StrHexToUint64 (StrStartingAddress
);
595 MemMapDevicePath
->EndingAddress
= StrHexToUint64 (StrEndingAddress
);
597 // Set a Device Path End Node after the Memory Map Device Path Node
598 SetDevicePathEndNode (MemMapDevicePath
+ 1);
599 *DevicePathNodes
= (EFI_DEVICE_PATH_PROTOCOL
*)MemMapDevicePath
;
605 BdsLoadOptionMemMapUpdateDevicePath (
606 IN EFI_DEVICE_PATH
*OldDevicePath
,
608 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath
612 CHAR16 StrStartingAddress
[BOOT_DEVICE_ADDRESS_MAX
];
613 CHAR16 StrEndingAddress
[BOOT_DEVICE_ADDRESS_MAX
];
614 MEMMAP_DEVICE_PATH
* EndingDevicePath
;
615 EFI_DEVICE_PATH
* DevicePath
;
617 DevicePath
= DuplicateDevicePath (OldDevicePath
);
618 EndingDevicePath
= (MEMMAP_DEVICE_PATH
*)GetLastDevicePathNode (DevicePath
);
620 Print(L
"Starting Address of the %s: ", FileName
);
621 UnicodeSPrint (StrStartingAddress
, BOOT_DEVICE_ADDRESS_MAX
, L
"0x%X", (UINTN
)EndingDevicePath
->StartingAddress
);
622 Status
= EditHIInputStr (StrStartingAddress
, BOOT_DEVICE_ADDRESS_MAX
);
623 if (EFI_ERROR(Status
)) {
627 Print(L
"Ending Address of the %s: ", FileName
);
628 UnicodeSPrint (StrEndingAddress
, BOOT_DEVICE_ADDRESS_MAX
, L
"0x%X", (UINTN
)EndingDevicePath
->EndingAddress
);
629 Status
= EditHIInputStr (StrEndingAddress
, BOOT_DEVICE_ADDRESS_MAX
);
630 if (EFI_ERROR(Status
)) {
634 EndingDevicePath
->StartingAddress
= StrHexToUint64 (StrStartingAddress
);
635 EndingDevicePath
->EndingAddress
= StrHexToUint64 (StrEndingAddress
);
637 if (EFI_ERROR(Status
)) {
638 FreePool(DevicePath
);
640 *NewDevicePath
= DevicePath
;
647 BdsLoadOptionMemMapIsSupported (
648 IN EFI_DEVICE_PATH
*DevicePath
651 EFI_DEVICE_PATH
* DevicePathNode
;
653 DevicePathNode
= GetLastDevicePathNode (DevicePath
);
655 return IS_DEVICE_PATH_NODE(DevicePathNode
,HARDWARE_DEVICE_PATH
,HW_MEMMAP_DP
);
659 BdsLoadOptionPxeList (
660 IN OUT LIST_ENTRY
* BdsLoadOptionList
665 EFI_HANDLE
*HandleBuffer
;
667 BDS_SUPPORTED_DEVICE
*SupportedDevice
;
668 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
669 EFI_SIMPLE_NETWORK_PROTOCOL
* SimpleNet
;
670 CHAR16 DeviceDescription
[BOOT_DEVICE_DESCRIPTION_MAX
];
671 EFI_MAC_ADDRESS
*Mac
;
673 // List all the PXE Protocols
674 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiPxeBaseCodeProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
675 if (EFI_ERROR (Status
)) {
679 for (Index
= 0; Index
< HandleCount
; Index
++) {
680 // We only select the handle WITH a Device Path AND the PXE Protocol
681 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
682 if (!EFI_ERROR(Status
)) {
683 // Allocate BDS Supported Device structure
684 SupportedDevice
= (BDS_SUPPORTED_DEVICE
*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE
));
686 Status
= gBS
->LocateProtocol (&gEfiSimpleNetworkProtocolGuid
, NULL
, (VOID
**)&SimpleNet
);
687 if (!EFI_ERROR(Status
)) {
688 Mac
= &SimpleNet
->Mode
->CurrentAddress
;
689 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]);
691 Status
= GenerateDeviceDescriptionName (HandleBuffer
[Index
], DeviceDescription
);
692 ASSERT_EFI_ERROR (Status
);
694 UnicodeSPrint (SupportedDevice
->Description
,BOOT_DEVICE_DESCRIPTION_MAX
,L
"PXE on %s",DeviceDescription
);
696 SupportedDevice
->DevicePathProtocol
= DevicePathProtocol
;
697 SupportedDevice
->Support
= &BdsLoadOptionSupportList
[BDS_DEVICE_PXE
];
699 InsertTailList (BdsLoadOptionList
,&SupportedDevice
->Link
);
707 BdsLoadOptionPxeCreateDevicePath (
709 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNodes
712 *DevicePathNodes
= (EFI_DEVICE_PATH_PROTOCOL
*) AllocatePool (END_DEVICE_PATH_LENGTH
);
713 SetDevicePathEndNode (*DevicePathNodes
);
719 Update the parameters of a Pxe boot option
721 @param[in] OldDevicePath Current complete device path of the Pxe boot option.
722 This has to be a valid complete Pxe boot option path.
723 @param[in] FileName Description of the file the path is asked for
724 @param[out] NewDevicePath Pointer to the new complete device path.
726 @retval EFI_SUCCESS Update completed
727 @retval EFI_OUT_OF_RESOURCES Fail to perform the update due to lack of resource
730 BdsLoadOptionPxeUpdateDevicePath (
731 IN EFI_DEVICE_PATH
*OldDevicePath
,
733 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath
737 // Make a copy of the complete device path that is made of :
738 // the device path of the device supporting the Pxe base code protocol
739 // followed by an end node.
741 *NewDevicePath
= DuplicateDevicePath (OldDevicePath
);
742 if (*NewDevicePath
== NULL
) {
743 return EFI_OUT_OF_RESOURCES
;
750 BdsLoadOptionPxeIsSupported (
751 IN EFI_DEVICE_PATH
*DevicePath
756 EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
;
757 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBcProtocol
;
759 Status
= BdsConnectDevicePath (DevicePath
, &Handle
, &RemainingDevicePath
);
760 if (EFI_ERROR(Status
)) {
764 if (!IsDevicePathEnd(RemainingDevicePath
)) {
768 Status
= gBS
->HandleProtocol (Handle
, &gEfiPxeBaseCodeProtocolGuid
, (VOID
**)&PxeBcProtocol
);
769 if (EFI_ERROR (Status
)) {
777 BdsLoadOptionTftpList (
778 IN OUT LIST_ENTRY
* BdsLoadOptionList
783 EFI_HANDLE
*HandleBuffer
;
785 BDS_SUPPORTED_DEVICE
*SupportedDevice
;
786 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
787 EFI_SIMPLE_NETWORK_PROTOCOL
* SimpleNet
;
788 CHAR16 DeviceDescription
[BOOT_DEVICE_DESCRIPTION_MAX
];
789 EFI_MAC_ADDRESS
*Mac
;
791 // List all the PXE Protocols
792 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiPxeBaseCodeProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
793 if (EFI_ERROR (Status
)) {
797 for (Index
= 0; Index
< HandleCount
; Index
++) {
798 // We only select the handle WITH a Device Path AND the PXE Protocol AND the TFTP Protocol (the TFTP protocol is required to start PXE)
799 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
800 if (!EFI_ERROR(Status
)) {
801 // Allocate BDS Supported Device structure
802 SupportedDevice
= (BDS_SUPPORTED_DEVICE
*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE
));
804 Status
= gBS
->LocateProtocol (&gEfiSimpleNetworkProtocolGuid
, NULL
, (VOID
**)&SimpleNet
);
805 if (!EFI_ERROR(Status
)) {
806 Mac
= &SimpleNet
->Mode
->CurrentAddress
;
807 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]);
809 Status
= GenerateDeviceDescriptionName (HandleBuffer
[Index
], DeviceDescription
);
810 ASSERT_EFI_ERROR (Status
);
812 UnicodeSPrint (SupportedDevice
->Description
,BOOT_DEVICE_DESCRIPTION_MAX
,L
"TFTP on %s",DeviceDescription
);
814 SupportedDevice
->DevicePathProtocol
= DevicePathProtocol
;
815 SupportedDevice
->Support
= &BdsLoadOptionSupportList
[BDS_DEVICE_TFTP
];
817 InsertTailList (BdsLoadOptionList
,&SupportedDevice
->Link
);
825 BdsLoadOptionTftpCreateDevicePath (
827 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNodes
832 EFI_IP_ADDRESS LocalIp
;
833 EFI_IP_ADDRESS RemoteIp
;
834 IPv4_DEVICE_PATH
* IPv4DevicePathNode
;
835 FILEPATH_DEVICE_PATH
* FilePathDevicePath
;
836 CHAR16 BootFilePath
[BOOT_DEVICE_FILEPATH_MAX
];
837 UINTN BootFilePathSize
;
839 Print(L
"Get the IP address from DHCP: ");
840 Status
= GetHIInputBoolean (&IsDHCP
);
841 if (EFI_ERROR(Status
)) {
846 Print(L
"Get the static IP address: ");
847 Status
= GetHIInputIP (&LocalIp
);
848 if (EFI_ERROR(Status
)) {
853 Print(L
"Get the TFTP server IP address: ");
854 Status
= GetHIInputIP (&RemoteIp
);
855 if (EFI_ERROR(Status
)) {
859 Print(L
"File path of the %s : ", FileName
);
860 Status
= GetHIInputStr (BootFilePath
, BOOT_DEVICE_FILEPATH_MAX
);
861 if (EFI_ERROR(Status
)) {
865 BootFilePathSize
= StrSize(BootFilePath
);
866 if (BootFilePathSize
== 2) {
867 return EFI_NOT_FOUND
;
870 // Allocate the memory for the IPv4 + File Path Device Path Nodes
871 IPv4DevicePathNode
= (IPv4_DEVICE_PATH
*)AllocatePool(sizeof(IPv4_DEVICE_PATH
) + SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
+ END_DEVICE_PATH_LENGTH
);
873 // Create the IPv4 Device Path
874 IPv4DevicePathNode
->Header
.Type
= MESSAGING_DEVICE_PATH
;
875 IPv4DevicePathNode
->Header
.SubType
= MSG_IPv4_DP
;
876 SetDevicePathNodeLength (&IPv4DevicePathNode
->Header
, sizeof(IPv4_DEVICE_PATH
));
877 CopyMem (&IPv4DevicePathNode
->LocalIpAddress
, &LocalIp
.v4
, sizeof (EFI_IPv4_ADDRESS
));
878 CopyMem (&IPv4DevicePathNode
->RemoteIpAddress
, &RemoteIp
.v4
, sizeof (EFI_IPv4_ADDRESS
));
879 IPv4DevicePathNode
->LocalPort
= 0;
880 IPv4DevicePathNode
->RemotePort
= 0;
881 IPv4DevicePathNode
->Protocol
= EFI_IP_PROTO_TCP
;
882 IPv4DevicePathNode
->StaticIpAddress
= (IsDHCP
!= TRUE
);
884 // Create the FilePath Device Path node
885 FilePathDevicePath
= (FILEPATH_DEVICE_PATH
*)(IPv4DevicePathNode
+ 1);
886 FilePathDevicePath
->Header
.Type
= MEDIA_DEVICE_PATH
;
887 FilePathDevicePath
->Header
.SubType
= MEDIA_FILEPATH_DP
;
888 SetDevicePathNodeLength (FilePathDevicePath
, SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
889 CopyMem (FilePathDevicePath
->PathName
, BootFilePath
, BootFilePathSize
);
891 // Set the End Device Path Node
892 SetDevicePathEndNode ((VOID
*)((UINTN
)FilePathDevicePath
+ SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
));
893 *DevicePathNodes
= (EFI_DEVICE_PATH_PROTOCOL
*)IPv4DevicePathNode
;
899 BdsLoadOptionTftpUpdateDevicePath (
900 IN EFI_DEVICE_PATH
*OldDevicePath
,
902 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath
906 return EFI_UNSUPPORTED
;
910 BdsLoadOptionTftpIsSupported (
911 IN EFI_DEVICE_PATH
*DevicePath
916 EFI_DEVICE_PATH
*RemainingDevicePath
;
917 EFI_DEVICE_PATH
*NextDevicePath
;
918 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBcProtocol
;
920 Status
= BdsConnectDevicePath (DevicePath
, &Handle
, &RemainingDevicePath
);
921 if (EFI_ERROR(Status
)) {
925 // Validate the Remaining Device Path
926 if (IsDevicePathEnd(RemainingDevicePath
)) {
929 if (!IS_DEVICE_PATH_NODE(RemainingDevicePath
,MESSAGING_DEVICE_PATH
,MSG_IPv4_DP
) &&
930 !IS_DEVICE_PATH_NODE(RemainingDevicePath
,MESSAGING_DEVICE_PATH
,MSG_IPv6_DP
)) {
933 NextDevicePath
= NextDevicePathNode (RemainingDevicePath
);
934 if (IsDevicePathEnd(NextDevicePath
)) {
937 if (!IS_DEVICE_PATH_NODE(NextDevicePath
,MEDIA_DEVICE_PATH
,MEDIA_FILEPATH_DP
)) {
941 Status
= gBS
->HandleProtocol (Handle
, &gEfiPxeBaseCodeProtocolGuid
, (VOID
**)&PxeBcProtocol
);
942 if (EFI_ERROR (Status
)) {