3 * Copyright (c) 2011, 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 (
36 IN BDS_SUPPORTED_DEVICE
* BdsLoadOption
,
37 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNode
,
38 OUT BDS_LOADER_TYPE
*BootType
,
39 OUT UINT32
*Attributes
43 BdsLoadOptionFileSystemUpdateDevicePath (
44 IN EFI_DEVICE_PATH
*OldDevicePath
,
45 OUT EFI_DEVICE_PATH_PROTOCOL
** NewDevicePath
,
46 OUT BDS_LOADER_TYPE
*BootType
,
47 OUT UINT32
*Attributes
51 BdsLoadOptionFileSystemIsSupported (
52 IN BDS_LOAD_OPTION
* BdsLoadOption
56 BdsLoadOptionMemMapList (
57 IN OUT LIST_ENTRY
* BdsLoadOptionList
61 BdsLoadOptionMemMapCreateDevicePath (
62 IN BDS_SUPPORTED_DEVICE
* BdsLoadOption
,
63 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNode
,
64 OUT BDS_LOADER_TYPE
*BootType
,
65 OUT UINT32
*Attributes
69 BdsLoadOptionMemMapUpdateDevicePath (
70 IN EFI_DEVICE_PATH
*OldDevicePath
,
71 OUT EFI_DEVICE_PATH_PROTOCOL
** NewDevicePath
,
72 OUT BDS_LOADER_TYPE
*BootType
,
73 OUT UINT32
*Attributes
77 BdsLoadOptionMemMapIsSupported (
78 IN BDS_LOAD_OPTION
* BdsLoadOption
82 BdsLoadOptionPxeList (
83 IN OUT LIST_ENTRY
* BdsLoadOptionList
87 BdsLoadOptionPxeCreateDevicePath (
88 IN BDS_SUPPORTED_DEVICE
* BdsLoadOption
,
89 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNode
,
90 OUT BDS_LOADER_TYPE
*BootType
,
91 OUT UINT32
*Attributes
95 BdsLoadOptionPxeUpdateDevicePath (
96 IN EFI_DEVICE_PATH
*OldDevicePath
,
97 OUT EFI_DEVICE_PATH_PROTOCOL
** NewDevicePath
,
98 OUT BDS_LOADER_TYPE
*BootType
,
99 OUT UINT32
*Attributes
103 BdsLoadOptionPxeIsSupported (
104 IN BDS_LOAD_OPTION
* BdsLoadOption
108 BdsLoadOptionTftpList (
109 IN OUT LIST_ENTRY
* BdsLoadOptionList
113 BdsLoadOptionTftpCreateDevicePath (
114 IN BDS_SUPPORTED_DEVICE
* BdsLoadOption
,
115 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNode
,
116 OUT BDS_LOADER_TYPE
*BootType
,
117 OUT UINT32
*Attributes
121 BdsLoadOptionTftpUpdateDevicePath (
122 IN EFI_DEVICE_PATH
*OldDevicePath
,
123 OUT EFI_DEVICE_PATH_PROTOCOL
** NewDevicePath
,
124 OUT BDS_LOADER_TYPE
*BootType
,
125 OUT UINT32
*Attributes
129 BdsLoadOptionTftpIsSupported (
130 IN BDS_LOAD_OPTION
* BdsLoadOption
133 BDS_LOAD_OPTION_SUPPORT BdsLoadOptionSupportList
[] = {
135 BDS_DEVICE_FILESYSTEM
,
136 BdsLoadOptionFileSystemList
,
137 BdsLoadOptionFileSystemIsSupported
,
138 BdsLoadOptionFileSystemCreateDevicePath
,
139 BdsLoadOptionFileSystemUpdateDevicePath
143 BdsLoadOptionMemMapList
,
144 BdsLoadOptionMemMapIsSupported
,
145 BdsLoadOptionMemMapCreateDevicePath
,
146 BdsLoadOptionMemMapUpdateDevicePath
150 BdsLoadOptionPxeList
,
151 BdsLoadOptionPxeIsSupported
,
152 BdsLoadOptionPxeCreateDevicePath
,
153 BdsLoadOptionPxeUpdateDevicePath
157 BdsLoadOptionTftpList
,
158 BdsLoadOptionTftpIsSupported
,
159 BdsLoadOptionTftpCreateDevicePath
,
160 BdsLoadOptionTftpUpdateDevicePath
165 BootDeviceListSupportedInit (
166 IN OUT LIST_ENTRY
*SupportedDeviceList
171 // Initialize list of supported devices
172 InitializeListHead (SupportedDeviceList
);
174 for (Index
= 0; Index
< BDS_DEVICE_MAX
; Index
++) {
175 BdsLoadOptionSupportList
[Index
].ListDevices(SupportedDeviceList
);
182 BootDeviceListSupportedFree (
183 IN LIST_ENTRY
*SupportedDeviceList
,
184 IN BDS_SUPPORTED_DEVICE
*Except
188 BDS_SUPPORTED_DEVICE
* SupportedDevice
;
190 Entry
= GetFirstNode (SupportedDeviceList
);
191 while (Entry
!= SupportedDeviceList
) {
192 SupportedDevice
= SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry
);
193 Entry
= RemoveEntryList (Entry
);
194 if (SupportedDevice
!= Except
) {
195 FreePool(SupportedDevice
);
203 BootDeviceGetDeviceSupport (
204 IN BDS_LOAD_OPTION
*BootOption
,
205 OUT BDS_LOAD_OPTION_SUPPORT
** DeviceSupport
210 // Find which supported device is the most appropriate
211 for (Index
= 0; Index
< BDS_DEVICE_MAX
; Index
++) {
212 if (BdsLoadOptionSupportList
[Index
].IsSupported(BootOption
)) {
213 *DeviceSupport
= &BdsLoadOptionSupportList
[Index
];
218 return EFI_UNSUPPORTED
;
225 OUT BDS_LOADER_TYPE
*BootType
,
226 OUT UINT32
*Attributes
231 BOOLEAN IsBootLoader
;
232 BOOLEAN HasFDTSupport
;
234 if (FileName
== NULL
) {
235 Print(L
"Is an EFI Application? ");
236 Status
= GetHIInputBoolean (&IsEfiApp
);
237 if (EFI_ERROR(Status
)) {
240 } else if (HasFilePathEfiExtension(FileName
)) {
247 Print(L
"Is your application is an OS loader? ");
248 Status
= GetHIInputBoolean (&IsBootLoader
);
249 if (EFI_ERROR(Status
)) {
253 *Attributes
|= LOAD_OPTION_CATEGORY_APP
;
255 *BootType
= BDS_LOADER_EFI_APPLICATION
;
257 Print(L
"Has FDT support? ");
258 Status
= GetHIInputBoolean (&HasFDTSupport
);
259 if (EFI_ERROR(Status
)) {
263 *BootType
= BDS_LOADER_KERNEL_LINUX_FDT
;
265 *BootType
= BDS_LOADER_KERNEL_LINUX_ATAG
;
273 BdsLoadOptionFileSystemList (
274 IN OUT LIST_ENTRY
* BdsLoadOptionList
279 EFI_HANDLE
*HandleBuffer
;
281 BDS_SUPPORTED_DEVICE
*SupportedDevice
;
282 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
* FileProtocol
;
285 EFI_FILE_SYSTEM_INFO
* FsInfo
;
286 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
288 // List all the Simple File System Protocols
289 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiSimpleFileSystemProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
290 if (EFI_ERROR (Status
)) {
294 for (Index
= 0; Index
< HandleCount
; Index
++) {
295 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
296 if (!EFI_ERROR(Status
)) {
297 // Allocate BDS Supported Device structure
298 SupportedDevice
= (BDS_SUPPORTED_DEVICE
*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE
));
301 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiSimpleFileSystemProtocolGuid
, (VOID
**)&FileProtocol
);
302 ASSERT_EFI_ERROR(Status
);
304 FileProtocol
->OpenVolume (FileProtocol
, &Fs
);
306 // Generate a Description from the file system
309 Status
= Fs
->GetInfo (Fs
, &gEfiFileSystemInfoGuid
, &Size
, FsInfo
);
310 if (Status
== EFI_BUFFER_TOO_SMALL
) {
311 FsInfo
= AllocatePool (Size
);
312 Status
= Fs
->GetInfo (Fs
, &gEfiFileSystemInfoGuid
, &Size
, FsInfo
);
314 UnicodeSPrint (SupportedDevice
->Description
,BOOT_DEVICE_DESCRIPTION_MAX
,L
"%s (%d MB)",FsInfo
->VolumeLabel
,(UINT32
)(FsInfo
->VolumeSize
/ (1024 * 1024)));
318 SupportedDevice
->DevicePathProtocol
= DevicePathProtocol
;
319 SupportedDevice
->Support
= &BdsLoadOptionSupportList
[BDS_DEVICE_FILESYSTEM
];
321 InsertTailList (BdsLoadOptionList
,&SupportedDevice
->Link
);
329 BdsLoadOptionFileSystemCreateDevicePath (
330 IN BDS_SUPPORTED_DEVICE
* BdsLoadOption
,
331 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNode
,
332 OUT BDS_LOADER_TYPE
*BootType
,
333 OUT UINT32
*Attributes
337 FILEPATH_DEVICE_PATH
* FilePathDevicePath
;
338 CHAR8 AsciiBootFilePath
[BOOT_DEVICE_FILEPATH_MAX
];
339 CHAR16
*BootFilePath
;
340 UINTN BootFilePathSize
;
342 Status
= GetHIInputAscii (AsciiBootFilePath
,BOOT_DEVICE_FILEPATH_MAX
);
343 if (EFI_ERROR(Status
)) {
347 if (AsciiStrSize(AsciiBootFilePath
) == 1) {
348 *DevicePathNode
= NULL
;
349 return EFI_NOT_FOUND
;
352 // Convert Ascii into Unicode
353 BootFilePath
= (CHAR16
*)AllocatePool(AsciiStrSize(AsciiBootFilePath
) * sizeof(CHAR16
));
354 AsciiStrToUnicodeStr (AsciiBootFilePath
, BootFilePath
);
355 BootFilePathSize
= StrSize(BootFilePath
);
357 // Create the FilePath Device Path node
358 FilePathDevicePath
= (FILEPATH_DEVICE_PATH
*)AllocatePool(SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
359 FilePathDevicePath
->Header
.Type
= MEDIA_DEVICE_PATH
;
360 FilePathDevicePath
->Header
.SubType
= MEDIA_FILEPATH_DP
;
361 SetDevicePathNodeLength (FilePathDevicePath
, SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
362 CopyMem (FilePathDevicePath
->PathName
, BootFilePath
, BootFilePathSize
);
363 FreePool (BootFilePath
);
365 if (BootType
!= NULL
|| Attributes
!= NULL
) {
366 Status
= BootDeviceGetType (FilePathDevicePath
->PathName
, BootType
, Attributes
);
369 if (EFI_ERROR(Status
)) {
370 FreePool (FilePathDevicePath
);
372 *DevicePathNode
= (EFI_DEVICE_PATH_PROTOCOL
*)FilePathDevicePath
;
379 BdsLoadOptionFileSystemUpdateDevicePath (
380 IN EFI_DEVICE_PATH
*OldDevicePath
,
381 OUT EFI_DEVICE_PATH_PROTOCOL
** NewDevicePath
,
382 OUT BDS_LOADER_TYPE
*BootType
,
383 OUT UINT32
*Attributes
387 CHAR8 AsciiBootFilePath
[BOOT_DEVICE_FILEPATH_MAX
];
388 CHAR16
*BootFilePath
;
389 UINTN BootFilePathSize
;
390 FILEPATH_DEVICE_PATH
* EndingDevicePath
;
391 FILEPATH_DEVICE_PATH
* FilePathDevicePath
;
392 EFI_DEVICE_PATH
* DevicePath
;
394 DevicePath
= DuplicateDevicePath(OldDevicePath
);
396 EndingDevicePath
= (FILEPATH_DEVICE_PATH
*)GetLastDevicePathNode (DevicePath
);
398 UnicodeStrToAsciiStr (EndingDevicePath
->PathName
,AsciiBootFilePath
);
399 Status
= EditHIInputAscii (AsciiBootFilePath
,BOOT_DEVICE_FILEPATH_MAX
);
400 if (EFI_ERROR(Status
)) {
404 if (AsciiStrSize(AsciiBootFilePath
) == 1) {
405 *NewDevicePath
= NULL
;
406 return EFI_NOT_FOUND
;
409 // Convert Ascii into Unicode
410 BootFilePath
= (CHAR16
*)AllocatePool(AsciiStrSize(AsciiBootFilePath
) * sizeof(CHAR16
));
411 AsciiStrToUnicodeStr (AsciiBootFilePath
, BootFilePath
);
412 BootFilePathSize
= StrSize(BootFilePath
);
414 // Create the FilePath Device Path node
415 FilePathDevicePath
= (FILEPATH_DEVICE_PATH
*)AllocatePool(SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
416 FilePathDevicePath
->Header
.Type
= MEDIA_DEVICE_PATH
;
417 FilePathDevicePath
->Header
.SubType
= MEDIA_FILEPATH_DP
;
418 SetDevicePathNodeLength (FilePathDevicePath
, SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
419 CopyMem (FilePathDevicePath
->PathName
, BootFilePath
, BootFilePathSize
);
420 FreePool (BootFilePath
);
422 // Generate the new Device Path by replacing the last node by the updated node
423 SetDevicePathEndNode (EndingDevicePath
);
424 *NewDevicePath
= AppendDevicePathNode (DevicePath
, (CONST EFI_DEVICE_PATH_PROTOCOL
*)FilePathDevicePath
);
425 FreePool(DevicePath
);
427 if (BootType
!= NULL
|| Attributes
!= NULL
) {
428 return BootDeviceGetType (FilePathDevicePath
->PathName
, BootType
, Attributes
);
435 BdsLoadOptionFileSystemIsSupported (
436 IN BDS_LOAD_OPTION
* BdsLoadOption
439 EFI_DEVICE_PATH
* DevicePathNode
;
441 DevicePathNode
= GetLastDevicePathNode (BdsLoadOption
->FilePathList
);
443 return IS_DEVICE_PATH_NODE(DevicePathNode
,MEDIA_DEVICE_PATH
,MEDIA_FILEPATH_DP
);
449 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
450 IN EFI_DEVICE_PATH_PROTOCOL
*ChildDevicePath
456 ParentSize
= GetDevicePathSize (ParentDevicePath
);
457 ChildSize
= GetDevicePathSize (ChildDevicePath
);
459 if (ParentSize
> ChildSize
) {
463 if (CompareMem (ParentDevicePath
, ChildDevicePath
, ParentSize
- END_DEVICE_PATH_LENGTH
) != 0) {
471 BdsLoadOptionMemMapList (
472 IN OUT LIST_ENTRY
* BdsLoadOptionList
477 EFI_HANDLE
*HandleBuffer
;
478 UINTN DevicePathHandleCount
;
479 EFI_HANDLE
*DevicePathHandleBuffer
;
483 BDS_SUPPORTED_DEVICE
*SupportedDevice
;
484 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
485 EFI_DEVICE_PATH
* DevicePath
;
487 // List all the BlockIo Protocols
488 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiBlockIoProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
489 if (EFI_ERROR (Status
)) {
493 for (Index
= 0; Index
< HandleCount
; Index
++) {
494 // We only select the handle WITH a Device Path AND not part of Media (to avoid duplication with HardDisk, CDROM, etc)
495 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
496 if (!EFI_ERROR(Status
)) {
497 // BlockIo is not part of Media Device Path
498 DevicePath
= DevicePathProtocol
;
499 while (!IsDevicePathEndType (DevicePath
) && (DevicePathType (DevicePath
) != MEDIA_DEVICE_PATH
)) {
500 DevicePath
= NextDevicePathNode (DevicePath
);
502 if (DevicePathType (DevicePath
) == MEDIA_DEVICE_PATH
) {
506 // Open all the handle supporting the DevicePath protocol and verify this handle has not got any child
507 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiDevicePathProtocolGuid
, NULL
, &DevicePathHandleCount
, &DevicePathHandleBuffer
);
508 ASSERT_EFI_ERROR (Status
);
510 for (Index2
= 0; (Index2
< DevicePathHandleCount
) && !IsParent
; Index2
++) {
511 if (HandleBuffer
[Index
] != DevicePathHandleBuffer
[Index2
]) {
512 gBS
->HandleProtocol (DevicePathHandleBuffer
[Index2
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePath
);
513 if (IsParentDevicePath (DevicePathProtocol
, DevicePath
)) {
522 // Allocate BDS Supported Device structure
523 SupportedDevice
= (BDS_SUPPORTED_DEVICE
*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE
));
525 Status
= GenerateDeviceDescriptionName (HandleBuffer
[Index
], SupportedDevice
->Description
);
526 ASSERT_EFI_ERROR (Status
);
528 SupportedDevice
->DevicePathProtocol
= DevicePathProtocol
;
529 SupportedDevice
->Support
= &BdsLoadOptionSupportList
[BDS_DEVICE_MEMMAP
];
531 InsertTailList (BdsLoadOptionList
,&SupportedDevice
->Link
);
539 BdsLoadOptionMemMapCreateDevicePath (
540 IN BDS_SUPPORTED_DEVICE
* BdsLoadOption
,
541 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNode
,
542 OUT BDS_LOADER_TYPE
*BootType
,
543 OUT UINT32
*Attributes
547 MEMMAP_DEVICE_PATH
* MemMapDevicePath
;
548 CHAR8 AsciiStartingAddress
[BOOT_DEVICE_ADDRESS_MAX
];
549 CHAR8 AsciiEndingAddress
[BOOT_DEVICE_ADDRESS_MAX
];
551 Print(L
"Starting Address of the binary: ");
552 Status
= GetHIInputAscii (AsciiStartingAddress
,BOOT_DEVICE_ADDRESS_MAX
);
553 if (EFI_ERROR(Status
)) {
557 Print(L
"Ending Address of the binary: ");
558 Status
= GetHIInputAscii (AsciiEndingAddress
,BOOT_DEVICE_ADDRESS_MAX
);
559 if (EFI_ERROR(Status
)) {
563 // Create the MemMap Device Path Node
564 MemMapDevicePath
= (MEMMAP_DEVICE_PATH
*)AllocatePool(sizeof(MEMMAP_DEVICE_PATH
));
565 MemMapDevicePath
->Header
.Type
= HARDWARE_DEVICE_PATH
;
566 MemMapDevicePath
->Header
.SubType
= HW_MEMMAP_DP
;
567 MemMapDevicePath
->MemoryType
= EfiBootServicesData
;
568 MemMapDevicePath
->StartingAddress
= AsciiStrHexToUint64 (AsciiStartingAddress
);
569 MemMapDevicePath
->EndingAddress
= AsciiStrHexToUint64 (AsciiEndingAddress
);
571 Status
= BootDeviceGetType (NULL
, BootType
, Attributes
);
572 if (EFI_ERROR(Status
)) {
573 FreePool (MemMapDevicePath
);
575 *DevicePathNode
= (EFI_DEVICE_PATH_PROTOCOL
*)MemMapDevicePath
;
582 BdsLoadOptionMemMapUpdateDevicePath (
583 IN EFI_DEVICE_PATH
*OldDevicePath
,
584 OUT EFI_DEVICE_PATH_PROTOCOL
** NewDevicePath
,
585 OUT BDS_LOADER_TYPE
*BootType
,
586 OUT UINT32
*Attributes
590 CHAR8 AsciiStartingAddress
[BOOT_DEVICE_ADDRESS_MAX
];
591 CHAR8 AsciiEndingAddress
[BOOT_DEVICE_ADDRESS_MAX
];
592 MEMMAP_DEVICE_PATH
* EndingDevicePath
;
593 EFI_DEVICE_PATH
* DevicePath
;
595 DevicePath
= DuplicateDevicePath (OldDevicePath
);
596 EndingDevicePath
= (MEMMAP_DEVICE_PATH
*)GetLastDevicePathNode (DevicePath
);
598 Print(L
"Starting Address of the binary: ");
599 AsciiSPrint (AsciiStartingAddress
,BOOT_DEVICE_ADDRESS_MAX
,"0x%X",(UINTN
)EndingDevicePath
->StartingAddress
);
600 Status
= EditHIInputAscii (AsciiStartingAddress
,BOOT_DEVICE_ADDRESS_MAX
);
601 if (EFI_ERROR(Status
)) {
605 Print(L
"Ending Address of the binary: ");
606 AsciiSPrint (AsciiEndingAddress
,BOOT_DEVICE_ADDRESS_MAX
,"0x%X",(UINTN
)EndingDevicePath
->EndingAddress
);
607 Status
= EditHIInputAscii (AsciiEndingAddress
,BOOT_DEVICE_ADDRESS_MAX
);
608 if (EFI_ERROR(Status
)) {
612 EndingDevicePath
->StartingAddress
= AsciiStrHexToUint64 (AsciiStartingAddress
);
613 EndingDevicePath
->EndingAddress
= AsciiStrHexToUint64 (AsciiEndingAddress
);
615 Status
= BootDeviceGetType (NULL
, BootType
, Attributes
);
616 if (EFI_ERROR(Status
)) {
617 FreePool(DevicePath
);
619 *NewDevicePath
= DevicePath
;
626 BdsLoadOptionMemMapIsSupported (
627 IN BDS_LOAD_OPTION
* BdsLoadOption
630 EFI_DEVICE_PATH
* DevicePathNode
;
632 DevicePathNode
= GetLastDevicePathNode (BdsLoadOption
->FilePathList
);
634 return IS_DEVICE_PATH_NODE(DevicePathNode
,HARDWARE_DEVICE_PATH
,HW_MEMMAP_DP
);
638 BdsLoadOptionPxeList (
639 IN OUT LIST_ENTRY
* BdsLoadOptionList
644 EFI_HANDLE
*HandleBuffer
;
646 BDS_SUPPORTED_DEVICE
*SupportedDevice
;
647 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
648 EFI_SIMPLE_NETWORK_PROTOCOL
* SimpleNet
;
649 CHAR16 DeviceDescription
[BOOT_DEVICE_DESCRIPTION_MAX
];
650 EFI_MAC_ADDRESS
*Mac
;
652 // List all the PXE Protocols
653 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiPxeBaseCodeProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
654 if (EFI_ERROR (Status
)) {
658 for (Index
= 0; Index
< HandleCount
; Index
++) {
659 // We only select the handle WITH a Device Path AND the PXE Protocol
660 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
661 if (!EFI_ERROR(Status
)) {
662 // Allocate BDS Supported Device structure
663 SupportedDevice
= (BDS_SUPPORTED_DEVICE
*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE
));
665 Status
= gBS
->LocateProtocol (&gEfiSimpleNetworkProtocolGuid
, NULL
, (VOID
**)&SimpleNet
);
666 if (!EFI_ERROR(Status
)) {
667 Mac
= &SimpleNet
->Mode
->CurrentAddress
;
668 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]);
670 Status
= GenerateDeviceDescriptionName (HandleBuffer
[Index
], DeviceDescription
);
671 ASSERT_EFI_ERROR (Status
);
673 UnicodeSPrint (SupportedDevice
->Description
,BOOT_DEVICE_DESCRIPTION_MAX
,L
"PXE on %s",DeviceDescription
);
675 SupportedDevice
->DevicePathProtocol
= DevicePathProtocol
;
676 SupportedDevice
->Support
= &BdsLoadOptionSupportList
[BDS_DEVICE_PXE
];
678 InsertTailList (BdsLoadOptionList
,&SupportedDevice
->Link
);
686 BdsLoadOptionPxeCreateDevicePath (
687 IN BDS_SUPPORTED_DEVICE
* BdsLoadOption
,
688 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNode
,
689 OUT BDS_LOADER_TYPE
*BootType
,
690 OUT UINT32
*Attributes
693 *DevicePathNode
= (EFI_DEVICE_PATH_PROTOCOL
*) AllocatePool (END_DEVICE_PATH_LENGTH
);
694 SetDevicePathEndNode (*DevicePathNode
);
695 *BootType
= BDS_LOADER_EFI_APPLICATION
;
700 BdsLoadOptionPxeUpdateDevicePath (
701 IN EFI_DEVICE_PATH
*OldDevicePath
,
702 OUT EFI_DEVICE_PATH_PROTOCOL
** NewDevicePath
,
703 OUT BDS_LOADER_TYPE
*BootType
,
704 OUT UINT32
*Attributes
712 BdsLoadOptionPxeIsSupported (
713 IN BDS_LOAD_OPTION
* BdsLoadOption
718 EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
;
719 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBcProtocol
;
721 Status
= BdsConnectDevicePath (BdsLoadOption
->FilePathList
, &Handle
, &RemainingDevicePath
);
722 if (EFI_ERROR(Status
)) {
726 if (!IsDevicePathEnd(RemainingDevicePath
)) {
730 Status
= gBS
->HandleProtocol (Handle
, &gEfiPxeBaseCodeProtocolGuid
, (VOID
**)&PxeBcProtocol
);
731 if (EFI_ERROR (Status
)) {
739 BdsLoadOptionTftpList (
740 IN OUT LIST_ENTRY
* BdsLoadOptionList
745 EFI_HANDLE
*HandleBuffer
;
747 BDS_SUPPORTED_DEVICE
*SupportedDevice
;
748 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
749 EFI_SIMPLE_NETWORK_PROTOCOL
* SimpleNet
;
750 CHAR16 DeviceDescription
[BOOT_DEVICE_DESCRIPTION_MAX
];
751 EFI_MAC_ADDRESS
*Mac
;
753 // List all the PXE Protocols
754 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiPxeBaseCodeProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
755 if (EFI_ERROR (Status
)) {
759 for (Index
= 0; Index
< HandleCount
; Index
++) {
760 // 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)
761 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
762 if (!EFI_ERROR(Status
)) {
763 // Allocate BDS Supported Device structure
764 SupportedDevice
= (BDS_SUPPORTED_DEVICE
*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE
));
766 Status
= gBS
->LocateProtocol (&gEfiSimpleNetworkProtocolGuid
, NULL
, (VOID
**)&SimpleNet
);
767 if (!EFI_ERROR(Status
)) {
768 Mac
= &SimpleNet
->Mode
->CurrentAddress
;
769 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]);
771 Status
= GenerateDeviceDescriptionName (HandleBuffer
[Index
], DeviceDescription
);
772 ASSERT_EFI_ERROR (Status
);
774 UnicodeSPrint (SupportedDevice
->Description
,BOOT_DEVICE_DESCRIPTION_MAX
,L
"TFP on %s",DeviceDescription
);
776 SupportedDevice
->DevicePathProtocol
= DevicePathProtocol
;
777 SupportedDevice
->Support
= &BdsLoadOptionSupportList
[BDS_DEVICE_TFTP
];
779 InsertTailList (BdsLoadOptionList
,&SupportedDevice
->Link
);
787 BdsLoadOptionTftpCreateDevicePath (
788 IN BDS_SUPPORTED_DEVICE
* BdsLoadOption
,
789 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNode
,
790 OUT BDS_LOADER_TYPE
*BootType
,
791 OUT UINT32
*Attributes
796 EFI_IP_ADDRESS LocalIp
;
797 EFI_IP_ADDRESS RemoteIp
;
798 IPv4_DEVICE_PATH
* IPv4DevicePathNode
;
799 FILEPATH_DEVICE_PATH
* FilePathDevicePath
;
800 CHAR8 AsciiBootFilePath
[BOOT_DEVICE_FILEPATH_MAX
];
801 CHAR16
* BootFilePath
;
802 UINTN BootFilePathSize
;
804 Print(L
"Get the IP address from DHCP: ");
805 Status
= GetHIInputBoolean (&IsDHCP
);
806 if (EFI_ERROR(Status
)) {
811 Print(L
"Get the static IP address: ");
812 Status
= GetHIInputIP (&LocalIp
);
813 if (EFI_ERROR(Status
)) {
818 Print(L
"Get the TFTP server IP address: ");
819 Status
= GetHIInputIP (&RemoteIp
);
820 if (EFI_ERROR(Status
)) {
824 Print(L
"File path of the EFI Application or the kernel: ");
825 Status
= GetHIInputAscii (AsciiBootFilePath
,BOOT_DEVICE_FILEPATH_MAX
);
826 if (EFI_ERROR(Status
)) {
830 // Convert Ascii into Unicode
831 BootFilePath
= (CHAR16
*)AllocatePool(AsciiStrSize(AsciiBootFilePath
) * sizeof(CHAR16
));
832 AsciiStrToUnicodeStr (AsciiBootFilePath
, BootFilePath
);
833 BootFilePathSize
= StrSize(BootFilePath
);
835 // Allocate the memory for the IPv4 + File Path Device Path Nodes
836 IPv4DevicePathNode
= (IPv4_DEVICE_PATH
*)AllocatePool(sizeof(IPv4_DEVICE_PATH
) + SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
838 // Create the IPv4 Device Path
839 IPv4DevicePathNode
->Header
.Type
= MESSAGING_DEVICE_PATH
;
840 IPv4DevicePathNode
->Header
.SubType
= MSG_IPv4_DP
;
841 SetDevicePathNodeLength (&IPv4DevicePathNode
->Header
, sizeof(IPv4_DEVICE_PATH
));
842 CopyMem (&IPv4DevicePathNode
->LocalIpAddress
, &LocalIp
.v4
, sizeof (EFI_IPv4_ADDRESS
));
843 CopyMem (&IPv4DevicePathNode
->RemoteIpAddress
, &RemoteIp
.v4
, sizeof (EFI_IPv4_ADDRESS
));
844 IPv4DevicePathNode
->LocalPort
= 0;
845 IPv4DevicePathNode
->RemotePort
= 0;
846 IPv4DevicePathNode
->Protocol
= EFI_IP_PROTO_TCP
;
847 IPv4DevicePathNode
->StaticIpAddress
= (IsDHCP
!= TRUE
);
849 // Create the FilePath Device Path node
850 FilePathDevicePath
= (FILEPATH_DEVICE_PATH
*)(IPv4DevicePathNode
+ 1);
851 FilePathDevicePath
->Header
.Type
= MEDIA_DEVICE_PATH
;
852 FilePathDevicePath
->Header
.SubType
= MEDIA_FILEPATH_DP
;
853 SetDevicePathNodeLength (FilePathDevicePath
, SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
854 CopyMem (FilePathDevicePath
->PathName
, BootFilePath
, BootFilePathSize
);
855 FreePool (BootFilePath
);
857 Status
= BootDeviceGetType (NULL
, BootType
, Attributes
);
858 if (EFI_ERROR(Status
)) {
859 FreePool (IPv4DevicePathNode
);
861 *DevicePathNode
= (EFI_DEVICE_PATH_PROTOCOL
*)IPv4DevicePathNode
;
868 BdsLoadOptionTftpUpdateDevicePath (
869 IN EFI_DEVICE_PATH
*OldDevicePath
,
870 OUT EFI_DEVICE_PATH_PROTOCOL
** NewDevicePath
,
871 OUT BDS_LOADER_TYPE
*BootType
,
872 OUT UINT32
*Attributes
880 BdsLoadOptionTftpIsSupported (
881 IN BDS_LOAD_OPTION
* BdsLoadOption
886 EFI_DEVICE_PATH
*RemainingDevicePath
;
887 EFI_DEVICE_PATH
*NextDevicePath
;
888 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBcProtocol
;
890 Status
= BdsConnectDevicePath (BdsLoadOption
->FilePathList
, &Handle
, &RemainingDevicePath
);
891 if (EFI_ERROR(Status
)) {
895 // Validate the Remaining Device Path
896 if (IsDevicePathEnd(RemainingDevicePath
)) {
899 if (!IS_DEVICE_PATH_NODE(RemainingDevicePath
,MESSAGING_DEVICE_PATH
,MSG_IPv4_DP
) &&
900 !IS_DEVICE_PATH_NODE(RemainingDevicePath
,MESSAGING_DEVICE_PATH
,MSG_IPv6_DP
)) {
903 NextDevicePath
= NextDevicePathNode (RemainingDevicePath
);
904 if (IsDevicePathEnd(NextDevicePath
)) {
907 if (!IS_DEVICE_PATH_NODE(NextDevicePath
,MEDIA_DEVICE_PATH
,MEDIA_FILEPATH_DP
)) {
911 Status
= gBS
->HandleProtocol (Handle
, &gEfiPxeBaseCodeProtocolGuid
, (VOID
**)&PxeBcProtocol
);
912 if (EFI_ERROR (Status
)) {