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 BdsLoadOptionPxeUpdateDevicePath (
732 IN EFI_DEVICE_PATH
*OldDevicePath
,
734 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath
,
735 OUT BOOLEAN
*RequestBootType
739 return EFI_UNSUPPORTED
;
743 BdsLoadOptionPxeIsSupported (
744 IN EFI_DEVICE_PATH
*DevicePath
749 EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
;
750 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBcProtocol
;
752 Status
= BdsConnectDevicePath (DevicePath
, &Handle
, &RemainingDevicePath
);
753 if (EFI_ERROR(Status
)) {
757 if (!IsDevicePathEnd(RemainingDevicePath
)) {
761 Status
= gBS
->HandleProtocol (Handle
, &gEfiPxeBaseCodeProtocolGuid
, (VOID
**)&PxeBcProtocol
);
762 if (EFI_ERROR (Status
)) {
770 BdsLoadOptionTftpList (
771 IN OUT LIST_ENTRY
* BdsLoadOptionList
776 EFI_HANDLE
*HandleBuffer
;
778 BDS_SUPPORTED_DEVICE
*SupportedDevice
;
779 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
780 EFI_SIMPLE_NETWORK_PROTOCOL
* SimpleNet
;
781 CHAR16 DeviceDescription
[BOOT_DEVICE_DESCRIPTION_MAX
];
782 EFI_MAC_ADDRESS
*Mac
;
784 // List all the PXE Protocols
785 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiPxeBaseCodeProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
786 if (EFI_ERROR (Status
)) {
790 for (Index
= 0; Index
< HandleCount
; Index
++) {
791 // 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)
792 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
793 if (!EFI_ERROR(Status
)) {
794 // Allocate BDS Supported Device structure
795 SupportedDevice
= (BDS_SUPPORTED_DEVICE
*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE
));
797 Status
= gBS
->LocateProtocol (&gEfiSimpleNetworkProtocolGuid
, NULL
, (VOID
**)&SimpleNet
);
798 if (!EFI_ERROR(Status
)) {
799 Mac
= &SimpleNet
->Mode
->CurrentAddress
;
800 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]);
802 Status
= GenerateDeviceDescriptionName (HandleBuffer
[Index
], DeviceDescription
);
803 ASSERT_EFI_ERROR (Status
);
805 UnicodeSPrint (SupportedDevice
->Description
,BOOT_DEVICE_DESCRIPTION_MAX
,L
"TFTP on %s",DeviceDescription
);
807 SupportedDevice
->DevicePathProtocol
= DevicePathProtocol
;
808 SupportedDevice
->Support
= &BdsLoadOptionSupportList
[BDS_DEVICE_TFTP
];
810 InsertTailList (BdsLoadOptionList
,&SupportedDevice
->Link
);
818 BdsLoadOptionTftpCreateDevicePath (
820 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNodes
,
821 OUT BOOLEAN
*RequestBootType
826 EFI_IP_ADDRESS LocalIp
;
827 EFI_IP_ADDRESS RemoteIp
;
828 IPv4_DEVICE_PATH
* IPv4DevicePathNode
;
829 FILEPATH_DEVICE_PATH
* FilePathDevicePath
;
830 CHAR16 BootFilePath
[BOOT_DEVICE_FILEPATH_MAX
];
831 UINTN BootFilePathSize
;
833 Print(L
"Get the IP address from DHCP: ");
834 Status
= GetHIInputBoolean (&IsDHCP
);
835 if (EFI_ERROR(Status
)) {
840 Print(L
"Get the static IP address: ");
841 Status
= GetHIInputIP (&LocalIp
);
842 if (EFI_ERROR(Status
)) {
847 Print(L
"Get the TFTP server IP address: ");
848 Status
= GetHIInputIP (&RemoteIp
);
849 if (EFI_ERROR(Status
)) {
853 Print(L
"File path of the %s : ", FileName
);
854 Status
= GetHIInputStr (BootFilePath
, BOOT_DEVICE_FILEPATH_MAX
);
855 if (EFI_ERROR(Status
)) {
859 BootFilePathSize
= StrSize(BootFilePath
);
860 if (BootFilePathSize
== 2) {
861 return EFI_NOT_FOUND
;
864 // Allocate the memory for the IPv4 + File Path Device Path Nodes
865 IPv4DevicePathNode
= (IPv4_DEVICE_PATH
*)AllocatePool(sizeof(IPv4_DEVICE_PATH
) + SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
+ END_DEVICE_PATH_LENGTH
);
867 // Create the IPv4 Device Path
868 IPv4DevicePathNode
->Header
.Type
= MESSAGING_DEVICE_PATH
;
869 IPv4DevicePathNode
->Header
.SubType
= MSG_IPv4_DP
;
870 SetDevicePathNodeLength (&IPv4DevicePathNode
->Header
, sizeof(IPv4_DEVICE_PATH
));
871 CopyMem (&IPv4DevicePathNode
->LocalIpAddress
, &LocalIp
.v4
, sizeof (EFI_IPv4_ADDRESS
));
872 CopyMem (&IPv4DevicePathNode
->RemoteIpAddress
, &RemoteIp
.v4
, sizeof (EFI_IPv4_ADDRESS
));
873 IPv4DevicePathNode
->LocalPort
= 0;
874 IPv4DevicePathNode
->RemotePort
= 0;
875 IPv4DevicePathNode
->Protocol
= EFI_IP_PROTO_TCP
;
876 IPv4DevicePathNode
->StaticIpAddress
= (IsDHCP
!= TRUE
);
878 // Create the FilePath Device Path node
879 FilePathDevicePath
= (FILEPATH_DEVICE_PATH
*)(IPv4DevicePathNode
+ 1);
880 FilePathDevicePath
->Header
.Type
= MEDIA_DEVICE_PATH
;
881 FilePathDevicePath
->Header
.SubType
= MEDIA_FILEPATH_DP
;
882 SetDevicePathNodeLength (FilePathDevicePath
, SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
883 CopyMem (FilePathDevicePath
->PathName
, BootFilePath
, BootFilePathSize
);
885 // Set the End Device Path Node
886 SetDevicePathEndNode ((VOID
*)((UINTN
)FilePathDevicePath
+ SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
));
887 *DevicePathNodes
= (EFI_DEVICE_PATH_PROTOCOL
*)IPv4DevicePathNode
;
893 BdsLoadOptionTftpUpdateDevicePath (
894 IN EFI_DEVICE_PATH
*OldDevicePath
,
896 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath
,
897 OUT BOOLEAN
*RequestBootType
901 return EFI_UNSUPPORTED
;
905 BdsLoadOptionTftpIsSupported (
906 IN EFI_DEVICE_PATH
*DevicePath
911 EFI_DEVICE_PATH
*RemainingDevicePath
;
912 EFI_DEVICE_PATH
*NextDevicePath
;
913 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBcProtocol
;
915 Status
= BdsConnectDevicePath (DevicePath
, &Handle
, &RemainingDevicePath
);
916 if (EFI_ERROR(Status
)) {
920 // Validate the Remaining Device Path
921 if (IsDevicePathEnd(RemainingDevicePath
)) {
924 if (!IS_DEVICE_PATH_NODE(RemainingDevicePath
,MESSAGING_DEVICE_PATH
,MSG_IPv4_DP
) &&
925 !IS_DEVICE_PATH_NODE(RemainingDevicePath
,MESSAGING_DEVICE_PATH
,MSG_IPv6_DP
)) {
928 NextDevicePath
= NextDevicePathNode (RemainingDevicePath
);
929 if (IsDevicePathEnd(NextDevicePath
)) {
932 if (!IS_DEVICE_PATH_NODE(NextDevicePath
,MEDIA_DEVICE_PATH
,MEDIA_FILEPATH_DP
)) {
936 Status
= gBS
->HandleProtocol (Handle
, &gEfiPxeBaseCodeProtocolGuid
, (VOID
**)&PxeBcProtocol
);
937 if (EFI_ERROR (Status
)) {