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
,
38 OUT BOOLEAN
*RequestBootType
42 BdsLoadOptionFileSystemUpdateDevicePath (
43 IN EFI_DEVICE_PATH
*OldDevicePath
,
45 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath
,
46 OUT BOOLEAN
*RequestBootType
50 BdsLoadOptionFileSystemIsSupported (
51 IN EFI_DEVICE_PATH
*DevicePath
55 BdsLoadOptionMemMapList (
56 IN OUT LIST_ENTRY
* BdsLoadOptionList
60 BdsLoadOptionMemMapCreateDevicePath (
62 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNodes
,
63 OUT BOOLEAN
*RequestBootType
67 BdsLoadOptionMemMapUpdateDevicePath (
68 IN EFI_DEVICE_PATH
*OldDevicePath
,
70 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath
,
71 OUT BOOLEAN
*RequestBootType
75 BdsLoadOptionMemMapIsSupported (
76 IN EFI_DEVICE_PATH
*DevicePath
80 BdsLoadOptionPxeList (
81 IN OUT LIST_ENTRY
* BdsLoadOptionList
85 BdsLoadOptionPxeCreateDevicePath (
87 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNodes
,
88 OUT BOOLEAN
*RequestBootType
92 BdsLoadOptionPxeUpdateDevicePath (
93 IN EFI_DEVICE_PATH
*OldDevicePath
,
95 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath
,
96 OUT BOOLEAN
*RequestBootType
100 BdsLoadOptionPxeIsSupported (
101 IN EFI_DEVICE_PATH
*DevicePath
105 BdsLoadOptionTftpList (
106 IN OUT LIST_ENTRY
* BdsLoadOptionList
110 BdsLoadOptionTftpCreateDevicePath (
112 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNodes
,
113 OUT BOOLEAN
*RequestBootType
117 BdsLoadOptionTftpUpdateDevicePath (
118 IN EFI_DEVICE_PATH
*OldDevicePath
,
120 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath
,
121 OUT BOOLEAN
*RequestBootType
125 BdsLoadOptionTftpIsSupported (
126 IN EFI_DEVICE_PATH
*DevicePath
129 BDS_LOAD_OPTION_SUPPORT BdsLoadOptionSupportList
[] = {
131 BDS_DEVICE_FILESYSTEM
,
132 BdsLoadOptionFileSystemList
,
133 BdsLoadOptionFileSystemIsSupported
,
134 BdsLoadOptionFileSystemCreateDevicePath
,
135 BdsLoadOptionFileSystemUpdateDevicePath
139 BdsLoadOptionMemMapList
,
140 BdsLoadOptionMemMapIsSupported
,
141 BdsLoadOptionMemMapCreateDevicePath
,
142 BdsLoadOptionMemMapUpdateDevicePath
146 BdsLoadOptionPxeList
,
147 BdsLoadOptionPxeIsSupported
,
148 BdsLoadOptionPxeCreateDevicePath
,
149 BdsLoadOptionPxeUpdateDevicePath
153 BdsLoadOptionTftpList
,
154 BdsLoadOptionTftpIsSupported
,
155 BdsLoadOptionTftpCreateDevicePath
,
156 BdsLoadOptionTftpUpdateDevicePath
161 BootDeviceListSupportedInit (
162 IN OUT LIST_ENTRY
*SupportedDeviceList
167 // Initialize list of supported devices
168 InitializeListHead (SupportedDeviceList
);
170 for (Index
= 0; Index
< BDS_DEVICE_MAX
; Index
++) {
171 BdsLoadOptionSupportList
[Index
].ListDevices (SupportedDeviceList
);
178 BootDeviceListSupportedFree (
179 IN LIST_ENTRY
*SupportedDeviceList
,
180 IN BDS_SUPPORTED_DEVICE
*Except
184 BDS_SUPPORTED_DEVICE
* SupportedDevice
;
186 Entry
= GetFirstNode (SupportedDeviceList
);
187 while (Entry
!= SupportedDeviceList
) {
188 SupportedDevice
= SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry
);
189 Entry
= RemoveEntryList (Entry
);
190 if (SupportedDevice
!= Except
) {
191 FreePool (SupportedDevice
);
199 BootDeviceGetDeviceSupport (
200 IN EFI_DEVICE_PATH
*DevicePath
,
201 OUT BDS_LOAD_OPTION_SUPPORT
**DeviceSupport
206 // Find which supported device is the most appropriate
207 for (Index
= 0; Index
< BDS_DEVICE_MAX
; Index
++) {
208 if (BdsLoadOptionSupportList
[Index
].IsSupported (DevicePath
)) {
209 *DeviceSupport
= &BdsLoadOptionSupportList
[Index
];
214 return EFI_UNSUPPORTED
;
219 IN EFI_DEVICE_PATH
* DevicePath
,
220 OUT ARM_BDS_LOADER_TYPE
*BootType
,
221 OUT UINT32
*Attributes
226 BOOLEAN IsBootLoader
;
227 BOOLEAN HasFDTSupport
;
229 EFI_DEVICE_PATH
* PrevDevicePathNode
;
230 EFI_DEVICE_PATH
* DevicePathNode
;
231 EFI_PHYSICAL_ADDRESS Image
;
233 EFI_IMAGE_DOS_HEADER
* DosHeader
;
234 UINTN PeCoffHeaderOffset
;
235 EFI_IMAGE_NT_HEADERS32
* NtHeader
;
238 // Check if the last node of the device path is a FilePath node
240 PrevDevicePathNode
= NULL
;
241 DevicePathNode
= DevicePath
;
242 while ((DevicePathNode
!= NULL
) && !IsDevicePathEnd (DevicePathNode
)) {
243 PrevDevicePathNode
= DevicePathNode
;
244 DevicePathNode
= NextDevicePathNode (DevicePathNode
);
247 if ((PrevDevicePathNode
!= NULL
) &&
248 (PrevDevicePathNode
->Type
== MEDIA_DEVICE_PATH
) &&
249 (PrevDevicePathNode
->SubType
== MEDIA_FILEPATH_DP
))
251 FileName
= ((FILEPATH_DEVICE_PATH
*)PrevDevicePathNode
)->PathName
;
256 if (FileName
== NULL
) {
257 Print(L
"Is an EFI Application? ");
258 Status
= GetHIInputBoolean (&IsEfiApp
);
259 if (EFI_ERROR(Status
)) {
262 } else if (HasFilePathEfiExtension(FileName
)) {
265 // Check if the file exist
266 Status
= BdsLoadImage (DevicePath
, AllocateAnyPages
, &Image
, &FileSize
);
267 if (!EFI_ERROR (Status
)) {
269 DosHeader
= (EFI_IMAGE_DOS_HEADER
*)(UINTN
) Image
;
270 if (DosHeader
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
272 // DOS image header is present,
273 // so read the PE header after the DOS image header.
275 PeCoffHeaderOffset
= DosHeader
->e_lfanew
;
277 PeCoffHeaderOffset
= 0;
281 // Check PE/COFF image.
283 NtHeader
= (EFI_IMAGE_NT_HEADERS32
*)(UINTN
) (Image
+ PeCoffHeaderOffset
);
284 if (NtHeader
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
291 gBS
->FreePages (Image
, EFI_SIZE_TO_PAGES(FileSize
));
293 // If we did not manage to open it then ask for the type
294 Print(L
"Is an EFI Application? ");
295 Status
= GetHIInputBoolean (&IsEfiApp
);
296 if (EFI_ERROR(Status
)) {
303 Print(L
"Is your application is an OS loader? ");
304 Status
= GetHIInputBoolean (&IsBootLoader
);
305 if (EFI_ERROR(Status
)) {
309 *Attributes
|= LOAD_OPTION_CATEGORY_APP
;
311 *BootType
= BDS_LOADER_EFI_APPLICATION
;
313 Print(L
"Has FDT support? ");
314 Status
= GetHIInputBoolean (&HasFDTSupport
);
315 if (EFI_ERROR(Status
)) {
319 *BootType
= BDS_LOADER_KERNEL_LINUX_FDT
;
321 *BootType
= BDS_LOADER_KERNEL_LINUX_ATAG
;
329 BdsLoadOptionFileSystemList (
330 IN OUT LIST_ENTRY
* BdsLoadOptionList
335 EFI_HANDLE
*HandleBuffer
;
337 BDS_SUPPORTED_DEVICE
*SupportedDevice
;
338 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
* FileProtocol
;
341 EFI_FILE_SYSTEM_INFO
* FsInfo
;
342 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
344 // List all the Simple File System Protocols
345 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiSimpleFileSystemProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
346 if (EFI_ERROR (Status
)) {
350 for (Index
= 0; Index
< HandleCount
; Index
++) {
351 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
352 if (!EFI_ERROR(Status
)) {
353 // Allocate BDS Supported Device structure
354 SupportedDevice
= (BDS_SUPPORTED_DEVICE
*)AllocatePool (sizeof(BDS_SUPPORTED_DEVICE
));
357 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiSimpleFileSystemProtocolGuid
, (VOID
**)&FileProtocol
);
358 ASSERT_EFI_ERROR(Status
);
360 FileProtocol
->OpenVolume (FileProtocol
, &Fs
);
362 // Generate a Description from the file system
365 Status
= Fs
->GetInfo (Fs
, &gEfiFileSystemInfoGuid
, &Size
, FsInfo
);
366 if (Status
== EFI_BUFFER_TOO_SMALL
) {
367 FsInfo
= AllocatePool (Size
);
368 Status
= Fs
->GetInfo (Fs
, &gEfiFileSystemInfoGuid
, &Size
, FsInfo
);
370 UnicodeSPrint (SupportedDevice
->Description
,BOOT_DEVICE_DESCRIPTION_MAX
,L
"%s (%d MB)",FsInfo
->VolumeLabel
,(UINT32
)(FsInfo
->VolumeSize
/ (1024 * 1024)));
374 SupportedDevice
->DevicePathProtocol
= DevicePathProtocol
;
375 SupportedDevice
->Support
= &BdsLoadOptionSupportList
[BDS_DEVICE_FILESYSTEM
];
377 InsertTailList (BdsLoadOptionList
,&SupportedDevice
->Link
);
385 BdsLoadOptionFileSystemCreateDevicePath (
387 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNodes
,
388 OUT BOOLEAN
*RequestBootType
392 FILEPATH_DEVICE_PATH
* FilePathDevicePath
;
393 CHAR16 BootFilePath
[BOOT_DEVICE_FILEPATH_MAX
];
394 UINTN BootFilePathSize
;
396 Print(L
"File path of the %s: ", FileName
);
397 Status
= GetHIInputStr (BootFilePath
, BOOT_DEVICE_FILEPATH_MAX
);
398 if (EFI_ERROR(Status
)) {
402 BootFilePathSize
= StrSize (BootFilePath
);
403 if (BootFilePathSize
== 2) {
404 *DevicePathNodes
= NULL
;
405 return EFI_NOT_FOUND
;
408 // Create the FilePath Device Path node
409 FilePathDevicePath
= (FILEPATH_DEVICE_PATH
*)AllocatePool(SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
+ END_DEVICE_PATH_LENGTH
);
410 FilePathDevicePath
->Header
.Type
= MEDIA_DEVICE_PATH
;
411 FilePathDevicePath
->Header
.SubType
= MEDIA_FILEPATH_DP
;
412 SetDevicePathNodeLength (FilePathDevicePath
, SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
413 CopyMem (FilePathDevicePath
->PathName
, BootFilePath
, BootFilePathSize
);
414 SetDevicePathEndNode ((VOID
*)((UINTN
)FilePathDevicePath
+ SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
));
415 *DevicePathNodes
= (EFI_DEVICE_PATH_PROTOCOL
*)FilePathDevicePath
;
421 BdsLoadOptionFileSystemUpdateDevicePath (
422 IN EFI_DEVICE_PATH
*OldDevicePath
,
424 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath
,
425 OUT BOOLEAN
*RequestBootType
429 CHAR16 BootFilePath
[BOOT_DEVICE_FILEPATH_MAX
];
430 UINTN BootFilePathSize
;
431 FILEPATH_DEVICE_PATH
* EndingDevicePath
;
432 FILEPATH_DEVICE_PATH
* FilePathDevicePath
;
433 EFI_DEVICE_PATH
* DevicePath
;
435 DevicePath
= DuplicateDevicePath (OldDevicePath
);
437 EndingDevicePath
= (FILEPATH_DEVICE_PATH
*)GetLastDevicePathNode (DevicePath
);
439 Print(L
"File path of the %s: ", FileName
);
440 StrnCpy (BootFilePath
, EndingDevicePath
->PathName
, BOOT_DEVICE_FILEPATH_MAX
);
441 Status
= EditHIInputStr (BootFilePath
, BOOT_DEVICE_FILEPATH_MAX
);
442 if (EFI_ERROR(Status
)) {
446 BootFilePathSize
= StrSize(BootFilePath
);
447 if (BootFilePathSize
== 2) {
448 *NewDevicePath
= NULL
;
449 return EFI_NOT_FOUND
;
452 // Create the FilePath Device Path node
453 FilePathDevicePath
= (FILEPATH_DEVICE_PATH
*)AllocatePool(SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
454 FilePathDevicePath
->Header
.Type
= MEDIA_DEVICE_PATH
;
455 FilePathDevicePath
->Header
.SubType
= MEDIA_FILEPATH_DP
;
456 SetDevicePathNodeLength (FilePathDevicePath
, SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
457 CopyMem (FilePathDevicePath
->PathName
, BootFilePath
, BootFilePathSize
);
459 // Generate the new Device Path by replacing the last node by the updated node
460 SetDevicePathEndNode (EndingDevicePath
);
461 *NewDevicePath
= AppendDevicePathNode (DevicePath
, (CONST EFI_DEVICE_PATH_PROTOCOL
*)FilePathDevicePath
);
462 FreePool(DevicePath
);
468 BdsLoadOptionFileSystemIsSupported (
469 IN EFI_DEVICE_PATH
*DevicePath
472 EFI_DEVICE_PATH
* DevicePathNode
;
474 DevicePathNode
= GetLastDevicePathNode (DevicePath
);
476 return IS_DEVICE_PATH_NODE(DevicePathNode
,MEDIA_DEVICE_PATH
,MEDIA_FILEPATH_DP
);
482 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
483 IN EFI_DEVICE_PATH_PROTOCOL
*ChildDevicePath
489 ParentSize
= GetDevicePathSize (ParentDevicePath
);
490 ChildSize
= GetDevicePathSize (ChildDevicePath
);
492 if (ParentSize
> ChildSize
) {
496 if (CompareMem (ParentDevicePath
, ChildDevicePath
, ParentSize
- END_DEVICE_PATH_LENGTH
) != 0) {
504 BdsLoadOptionMemMapList (
505 IN OUT LIST_ENTRY
* BdsLoadOptionList
510 EFI_HANDLE
*HandleBuffer
;
511 UINTN DevicePathHandleCount
;
512 EFI_HANDLE
*DevicePathHandleBuffer
;
516 BDS_SUPPORTED_DEVICE
*SupportedDevice
;
517 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
518 EFI_DEVICE_PATH
* DevicePath
;
520 // List all the BlockIo Protocols
521 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiBlockIoProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
522 if (EFI_ERROR (Status
)) {
526 for (Index
= 0; Index
< HandleCount
; Index
++) {
527 // We only select the handle WITH a Device Path AND not part of Media (to avoid duplication with HardDisk, CDROM, etc)
528 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
529 if (!EFI_ERROR(Status
)) {
530 // BlockIo is not part of Media Device Path
531 DevicePath
= DevicePathProtocol
;
532 while (!IsDevicePathEndType (DevicePath
) && (DevicePathType (DevicePath
) != MEDIA_DEVICE_PATH
)) {
533 DevicePath
= NextDevicePathNode (DevicePath
);
535 if (DevicePathType (DevicePath
) == MEDIA_DEVICE_PATH
) {
539 // Open all the handle supporting the DevicePath protocol and verify this handle has not got any child
540 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiDevicePathProtocolGuid
, NULL
, &DevicePathHandleCount
, &DevicePathHandleBuffer
);
541 ASSERT_EFI_ERROR (Status
);
543 for (Index2
= 0; (Index2
< DevicePathHandleCount
) && !IsParent
; Index2
++) {
544 if (HandleBuffer
[Index
] != DevicePathHandleBuffer
[Index2
]) {
545 gBS
->HandleProtocol (DevicePathHandleBuffer
[Index2
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePath
);
546 if (IsParentDevicePath (DevicePathProtocol
, DevicePath
)) {
555 // Allocate BDS Supported Device structure
556 SupportedDevice
= (BDS_SUPPORTED_DEVICE
*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE
));
558 Status
= GenerateDeviceDescriptionName (HandleBuffer
[Index
], SupportedDevice
->Description
);
559 ASSERT_EFI_ERROR (Status
);
561 SupportedDevice
->DevicePathProtocol
= DevicePathProtocol
;
562 SupportedDevice
->Support
= &BdsLoadOptionSupportList
[BDS_DEVICE_MEMMAP
];
564 InsertTailList (BdsLoadOptionList
,&SupportedDevice
->Link
);
572 BdsLoadOptionMemMapCreateDevicePath (
574 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNodes
,
575 OUT BOOLEAN
*RequestBootType
579 MEMMAP_DEVICE_PATH
*MemMapDevicePath
;
580 CHAR16 StrStartingAddress
[BOOT_DEVICE_ADDRESS_MAX
];
581 CHAR16 StrEndingAddress
[BOOT_DEVICE_ADDRESS_MAX
];
583 Print(L
"Starting Address of the %s: ", FileName
);
584 Status
= GetHIInputStr (StrStartingAddress
, BOOT_DEVICE_ADDRESS_MAX
);
585 if (EFI_ERROR(Status
)) {
589 Print(L
"Ending Address of the %s: ", FileName
);
590 Status
= GetHIInputStr (StrEndingAddress
, BOOT_DEVICE_ADDRESS_MAX
);
591 if (EFI_ERROR(Status
)) {
595 // Create the MemMap Device Path Node
596 MemMapDevicePath
= (MEMMAP_DEVICE_PATH
*)AllocatePool (sizeof(MEMMAP_DEVICE_PATH
) + END_DEVICE_PATH_LENGTH
);
597 MemMapDevicePath
->Header
.Type
= HARDWARE_DEVICE_PATH
;
598 MemMapDevicePath
->Header
.SubType
= HW_MEMMAP_DP
;
599 SetDevicePathNodeLength (MemMapDevicePath
, sizeof(MEMMAP_DEVICE_PATH
));
600 MemMapDevicePath
->MemoryType
= EfiBootServicesData
;
601 MemMapDevicePath
->StartingAddress
= StrHexToUint64 (StrStartingAddress
);
602 MemMapDevicePath
->EndingAddress
= StrHexToUint64 (StrEndingAddress
);
604 // Set a Device Path End Node after the Memory Map Device Path Node
605 SetDevicePathEndNode (MemMapDevicePath
+ 1);
606 *DevicePathNodes
= (EFI_DEVICE_PATH_PROTOCOL
*)MemMapDevicePath
;
612 BdsLoadOptionMemMapUpdateDevicePath (
613 IN EFI_DEVICE_PATH
*OldDevicePath
,
615 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath
,
616 OUT BOOLEAN
*RequestBootType
620 CHAR16 StrStartingAddress
[BOOT_DEVICE_ADDRESS_MAX
];
621 CHAR16 StrEndingAddress
[BOOT_DEVICE_ADDRESS_MAX
];
622 MEMMAP_DEVICE_PATH
* EndingDevicePath
;
623 EFI_DEVICE_PATH
* DevicePath
;
625 DevicePath
= DuplicateDevicePath (OldDevicePath
);
626 EndingDevicePath
= (MEMMAP_DEVICE_PATH
*)GetLastDevicePathNode (DevicePath
);
628 Print(L
"Starting Address of the %s: ", FileName
);
629 UnicodeSPrint (StrStartingAddress
, BOOT_DEVICE_ADDRESS_MAX
, L
"0x%X", (UINTN
)EndingDevicePath
->StartingAddress
);
630 Status
= EditHIInputStr (StrStartingAddress
, BOOT_DEVICE_ADDRESS_MAX
);
631 if (EFI_ERROR(Status
)) {
635 Print(L
"Ending Address of the %s: ", FileName
);
636 UnicodeSPrint (StrEndingAddress
, BOOT_DEVICE_ADDRESS_MAX
, L
"0x%X", (UINTN
)EndingDevicePath
->EndingAddress
);
637 Status
= EditHIInputStr (StrEndingAddress
, BOOT_DEVICE_ADDRESS_MAX
);
638 if (EFI_ERROR(Status
)) {
642 EndingDevicePath
->StartingAddress
= StrHexToUint64 (StrStartingAddress
);
643 EndingDevicePath
->EndingAddress
= StrHexToUint64 (StrEndingAddress
);
645 if (EFI_ERROR(Status
)) {
646 FreePool(DevicePath
);
648 *NewDevicePath
= DevicePath
;
655 BdsLoadOptionMemMapIsSupported (
656 IN EFI_DEVICE_PATH
*DevicePath
659 EFI_DEVICE_PATH
* DevicePathNode
;
661 DevicePathNode
= GetLastDevicePathNode (DevicePath
);
663 return IS_DEVICE_PATH_NODE(DevicePathNode
,HARDWARE_DEVICE_PATH
,HW_MEMMAP_DP
);
667 BdsLoadOptionPxeList (
668 IN OUT LIST_ENTRY
* BdsLoadOptionList
673 EFI_HANDLE
*HandleBuffer
;
675 BDS_SUPPORTED_DEVICE
*SupportedDevice
;
676 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
677 EFI_SIMPLE_NETWORK_PROTOCOL
* SimpleNet
;
678 CHAR16 DeviceDescription
[BOOT_DEVICE_DESCRIPTION_MAX
];
679 EFI_MAC_ADDRESS
*Mac
;
681 // List all the PXE Protocols
682 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiPxeBaseCodeProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
683 if (EFI_ERROR (Status
)) {
687 for (Index
= 0; Index
< HandleCount
; Index
++) {
688 // We only select the handle WITH a Device Path AND the PXE Protocol
689 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
690 if (!EFI_ERROR(Status
)) {
691 // Allocate BDS Supported Device structure
692 SupportedDevice
= (BDS_SUPPORTED_DEVICE
*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE
));
694 Status
= gBS
->LocateProtocol (&gEfiSimpleNetworkProtocolGuid
, NULL
, (VOID
**)&SimpleNet
);
695 if (!EFI_ERROR(Status
)) {
696 Mac
= &SimpleNet
->Mode
->CurrentAddress
;
697 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]);
699 Status
= GenerateDeviceDescriptionName (HandleBuffer
[Index
], DeviceDescription
);
700 ASSERT_EFI_ERROR (Status
);
702 UnicodeSPrint (SupportedDevice
->Description
,BOOT_DEVICE_DESCRIPTION_MAX
,L
"PXE on %s",DeviceDescription
);
704 SupportedDevice
->DevicePathProtocol
= DevicePathProtocol
;
705 SupportedDevice
->Support
= &BdsLoadOptionSupportList
[BDS_DEVICE_PXE
];
707 InsertTailList (BdsLoadOptionList
,&SupportedDevice
->Link
);
715 BdsLoadOptionPxeCreateDevicePath (
717 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNodes
,
718 OUT BOOLEAN
*RequestBootType
721 *DevicePathNodes
= (EFI_DEVICE_PATH_PROTOCOL
*) AllocatePool (END_DEVICE_PATH_LENGTH
);
722 SetDevicePathEndNode (*DevicePathNodes
);
724 if (RequestBootType
) {
725 *RequestBootType
= FALSE
;
731 Update the parameters of a Pxe boot option
733 @param[in] OldDevicePath Current complete device path of the Pxe boot option.
734 This has to be a valid complete Pxe boot option path.
735 @param[in] FileName Description of the file the path is asked for
736 @param[out] NewDevicePath Pointer to the new complete device path.
738 @retval EFI_SUCCESS Update completed
739 @retval EFI_OUT_OF_RESOURCES Fail to perform the update due to lack of resource
742 BdsLoadOptionPxeUpdateDevicePath (
743 IN EFI_DEVICE_PATH
*OldDevicePath
,
745 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath
,
746 OUT BOOLEAN
*RequestBootType
750 // Make a copy of the complete device path that is made of :
751 // the device path of the device supporting the Pxe base code protocol
752 // followed by an end node.
754 *NewDevicePath
= DuplicateDevicePath (OldDevicePath
);
755 if (*NewDevicePath
== NULL
) {
756 return EFI_OUT_OF_RESOURCES
;
763 BdsLoadOptionPxeIsSupported (
764 IN EFI_DEVICE_PATH
*DevicePath
769 EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
;
770 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBcProtocol
;
772 Status
= BdsConnectDevicePath (DevicePath
, &Handle
, &RemainingDevicePath
);
773 if (EFI_ERROR(Status
)) {
777 if (!IsDevicePathEnd(RemainingDevicePath
)) {
781 Status
= gBS
->HandleProtocol (Handle
, &gEfiPxeBaseCodeProtocolGuid
, (VOID
**)&PxeBcProtocol
);
782 if (EFI_ERROR (Status
)) {
790 BdsLoadOptionTftpList (
791 IN OUT LIST_ENTRY
* BdsLoadOptionList
796 EFI_HANDLE
*HandleBuffer
;
798 BDS_SUPPORTED_DEVICE
*SupportedDevice
;
799 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
800 EFI_SIMPLE_NETWORK_PROTOCOL
* SimpleNet
;
801 CHAR16 DeviceDescription
[BOOT_DEVICE_DESCRIPTION_MAX
];
802 EFI_MAC_ADDRESS
*Mac
;
804 // List all the PXE Protocols
805 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiPxeBaseCodeProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
806 if (EFI_ERROR (Status
)) {
810 for (Index
= 0; Index
< HandleCount
; Index
++) {
811 // 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)
812 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
813 if (!EFI_ERROR(Status
)) {
814 // Allocate BDS Supported Device structure
815 SupportedDevice
= (BDS_SUPPORTED_DEVICE
*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE
));
817 Status
= gBS
->LocateProtocol (&gEfiSimpleNetworkProtocolGuid
, NULL
, (VOID
**)&SimpleNet
);
818 if (!EFI_ERROR(Status
)) {
819 Mac
= &SimpleNet
->Mode
->CurrentAddress
;
820 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]);
822 Status
= GenerateDeviceDescriptionName (HandleBuffer
[Index
], DeviceDescription
);
823 ASSERT_EFI_ERROR (Status
);
825 UnicodeSPrint (SupportedDevice
->Description
,BOOT_DEVICE_DESCRIPTION_MAX
,L
"TFTP on %s",DeviceDescription
);
827 SupportedDevice
->DevicePathProtocol
= DevicePathProtocol
;
828 SupportedDevice
->Support
= &BdsLoadOptionSupportList
[BDS_DEVICE_TFTP
];
830 InsertTailList (BdsLoadOptionList
,&SupportedDevice
->Link
);
838 BdsLoadOptionTftpCreateDevicePath (
840 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNodes
,
841 OUT BOOLEAN
*RequestBootType
846 EFI_IP_ADDRESS LocalIp
;
847 EFI_IP_ADDRESS RemoteIp
;
848 IPv4_DEVICE_PATH
* IPv4DevicePathNode
;
849 FILEPATH_DEVICE_PATH
* FilePathDevicePath
;
850 CHAR16 BootFilePath
[BOOT_DEVICE_FILEPATH_MAX
];
851 UINTN BootFilePathSize
;
853 Print(L
"Get the IP address from DHCP: ");
854 Status
= GetHIInputBoolean (&IsDHCP
);
855 if (EFI_ERROR(Status
)) {
860 Print(L
"Get the static IP address: ");
861 Status
= GetHIInputIP (&LocalIp
);
862 if (EFI_ERROR(Status
)) {
867 Print(L
"Get the TFTP server IP address: ");
868 Status
= GetHIInputIP (&RemoteIp
);
869 if (EFI_ERROR(Status
)) {
873 Print(L
"File path of the %s : ", FileName
);
874 Status
= GetHIInputStr (BootFilePath
, BOOT_DEVICE_FILEPATH_MAX
);
875 if (EFI_ERROR(Status
)) {
879 BootFilePathSize
= StrSize(BootFilePath
);
880 if (BootFilePathSize
== 2) {
881 return EFI_NOT_FOUND
;
884 // Allocate the memory for the IPv4 + File Path Device Path Nodes
885 IPv4DevicePathNode
= (IPv4_DEVICE_PATH
*)AllocatePool(sizeof(IPv4_DEVICE_PATH
) + SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
+ END_DEVICE_PATH_LENGTH
);
887 // Create the IPv4 Device Path
888 IPv4DevicePathNode
->Header
.Type
= MESSAGING_DEVICE_PATH
;
889 IPv4DevicePathNode
->Header
.SubType
= MSG_IPv4_DP
;
890 SetDevicePathNodeLength (&IPv4DevicePathNode
->Header
, sizeof(IPv4_DEVICE_PATH
));
891 CopyMem (&IPv4DevicePathNode
->LocalIpAddress
, &LocalIp
.v4
, sizeof (EFI_IPv4_ADDRESS
));
892 CopyMem (&IPv4DevicePathNode
->RemoteIpAddress
, &RemoteIp
.v4
, sizeof (EFI_IPv4_ADDRESS
));
893 IPv4DevicePathNode
->LocalPort
= 0;
894 IPv4DevicePathNode
->RemotePort
= 0;
895 IPv4DevicePathNode
->Protocol
= EFI_IP_PROTO_TCP
;
896 IPv4DevicePathNode
->StaticIpAddress
= (IsDHCP
!= TRUE
);
898 // Create the FilePath Device Path node
899 FilePathDevicePath
= (FILEPATH_DEVICE_PATH
*)(IPv4DevicePathNode
+ 1);
900 FilePathDevicePath
->Header
.Type
= MEDIA_DEVICE_PATH
;
901 FilePathDevicePath
->Header
.SubType
= MEDIA_FILEPATH_DP
;
902 SetDevicePathNodeLength (FilePathDevicePath
, SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
903 CopyMem (FilePathDevicePath
->PathName
, BootFilePath
, BootFilePathSize
);
905 // Set the End Device Path Node
906 SetDevicePathEndNode ((VOID
*)((UINTN
)FilePathDevicePath
+ SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
));
907 *DevicePathNodes
= (EFI_DEVICE_PATH_PROTOCOL
*)IPv4DevicePathNode
;
913 BdsLoadOptionTftpUpdateDevicePath (
914 IN EFI_DEVICE_PATH
*OldDevicePath
,
916 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath
,
917 OUT BOOLEAN
*RequestBootType
921 return EFI_UNSUPPORTED
;
925 BdsLoadOptionTftpIsSupported (
926 IN EFI_DEVICE_PATH
*DevicePath
931 EFI_DEVICE_PATH
*RemainingDevicePath
;
932 EFI_DEVICE_PATH
*NextDevicePath
;
933 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBcProtocol
;
935 Status
= BdsConnectDevicePath (DevicePath
, &Handle
, &RemainingDevicePath
);
936 if (EFI_ERROR(Status
)) {
940 // Validate the Remaining Device Path
941 if (IsDevicePathEnd(RemainingDevicePath
)) {
944 if (!IS_DEVICE_PATH_NODE(RemainingDevicePath
,MESSAGING_DEVICE_PATH
,MSG_IPv4_DP
) &&
945 !IS_DEVICE_PATH_NODE(RemainingDevicePath
,MESSAGING_DEVICE_PATH
,MSG_IPv6_DP
)) {
948 NextDevicePath
= NextDevicePathNode (RemainingDevicePath
);
949 if (IsDevicePathEnd(NextDevicePath
)) {
952 if (!IS_DEVICE_PATH_NODE(NextDevicePath
,MEDIA_DEVICE_PATH
,MEDIA_FILEPATH_DP
)) {
956 Status
= gBS
->HandleProtocol (Handle
, &gEfiPxeBaseCodeProtocolGuid
, (VOID
**)&PxeBcProtocol
);
957 if (EFI_ERROR (Status
)) {