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 BDS_LOAD_OPTION
*BootOption
,
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 BDS_LOAD_OPTION
*BootOption
,
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 BDS_LOAD_OPTION
*BootOption
,
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 BDS_LOAD_OPTION
*BootOption
,
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
187 BDS_SUPPORTED_DEVICE
* SupportedDevice
;
189 Entry
= GetFirstNode (SupportedDeviceList
);
190 while (Entry
!= SupportedDeviceList
) {
191 SupportedDevice
= SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry
);
192 Entry
= RemoveEntryList (Entry
);
193 FreePool(SupportedDevice
);
200 BootDeviceGetDeviceSupport (
201 IN BDS_LOAD_OPTION
*BootOption
,
202 OUT BDS_LOAD_OPTION_SUPPORT
** DeviceSupport
207 // Find which supported device is the most appropriate
208 for (Index
= 0; Index
< BDS_DEVICE_MAX
; Index
++) {
209 if (BdsLoadOptionSupportList
[Index
].IsSupported(BootOption
)) {
210 *DeviceSupport
= &BdsLoadOptionSupportList
[Index
];
215 return EFI_UNSUPPORTED
;
222 OUT BDS_LOADER_TYPE
*BootType
,
223 OUT UINT32
*Attributes
228 BOOLEAN IsBootLoader
;
229 BOOLEAN HasFDTSupport
;
231 if (FileName
== NULL
) {
232 Print(L
"Is an EFI Application? ");
233 Status
= GetHIInputBoolean (&IsEfiApp
);
234 if (EFI_ERROR(Status
)) {
237 } else if (HasFilePathEfiExtension(FileName
)) {
244 Print(L
"Is your application is an OS loader? ");
245 Status
= GetHIInputBoolean (&IsBootLoader
);
246 if (EFI_ERROR(Status
)) {
250 *Attributes
|= LOAD_OPTION_CATEGORY_APP
;
252 *BootType
= BDS_LOADER_EFI_APPLICATION
;
254 Print(L
"Has FDT support? ");
255 Status
= GetHIInputBoolean (&HasFDTSupport
);
256 if (EFI_ERROR(Status
)) {
260 *BootType
= BDS_LOADER_KERNEL_LINUX_FDT
;
262 *BootType
= BDS_LOADER_KERNEL_LINUX_ATAG
;
270 BdsLoadOptionFileSystemList (
271 IN OUT LIST_ENTRY
* BdsLoadOptionList
276 EFI_HANDLE
*HandleBuffer
;
278 BDS_SUPPORTED_DEVICE
*SupportedDevice
;
279 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
* FileProtocol
;
282 EFI_FILE_SYSTEM_INFO
* FsInfo
;
283 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
285 // List all the Simple File System Protocols
286 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiSimpleFileSystemProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
287 if (EFI_ERROR (Status
)) {
291 for (Index
= 0; Index
< HandleCount
; Index
++) {
292 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
293 if (!EFI_ERROR(Status
)) {
294 // Allocate BDS Supported Device structure
295 SupportedDevice
= (BDS_SUPPORTED_DEVICE
*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE
));
298 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiSimpleFileSystemProtocolGuid
, (VOID
**)&FileProtocol
);
299 ASSERT_EFI_ERROR(Status
);
301 FileProtocol
->OpenVolume (FileProtocol
, &Fs
);
303 // Generate a Description from the file system
306 Status
= Fs
->GetInfo (Fs
, &gEfiFileSystemInfoGuid
, &Size
, FsInfo
);
307 if (Status
== EFI_BUFFER_TOO_SMALL
) {
308 FsInfo
= AllocatePool (Size
);
309 Status
= Fs
->GetInfo (Fs
, &gEfiFileSystemInfoGuid
, &Size
, FsInfo
);
311 UnicodeSPrint (SupportedDevice
->Description
,BOOT_DEVICE_DESCRIPTION_MAX
,L
"%s (%d MB)",FsInfo
->VolumeLabel
,(UINT32
)(FsInfo
->VolumeSize
/ (1024 * 1024)));
315 SupportedDevice
->DevicePathProtocol
= DevicePathProtocol
;
316 SupportedDevice
->Support
= &BdsLoadOptionSupportList
[BDS_DEVICE_FILESYSTEM
];
318 InsertTailList (BdsLoadOptionList
,&SupportedDevice
->Link
);
326 BdsLoadOptionFileSystemCreateDevicePath (
327 IN BDS_SUPPORTED_DEVICE
* BdsLoadOption
,
328 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNode
,
329 OUT BDS_LOADER_TYPE
*BootType
,
330 OUT UINT32
*Attributes
334 FILEPATH_DEVICE_PATH
* FilePathDevicePath
;
335 CHAR8 AsciiBootFilePath
[BOOT_DEVICE_FILEPATH_MAX
];
336 CHAR16
*BootFilePath
;
337 UINTN BootFilePathSize
;
339 Print(L
"File path of the EFI Application or the kernel: ");
340 Status
= GetHIInputAscii (AsciiBootFilePath
,BOOT_DEVICE_FILEPATH_MAX
);
341 if (EFI_ERROR(Status
)) {
345 // Convert Ascii into Unicode
346 BootFilePath
= (CHAR16
*)AllocatePool(AsciiStrSize(AsciiBootFilePath
) * sizeof(CHAR16
));
347 AsciiStrToUnicodeStr (AsciiBootFilePath
, BootFilePath
);
348 BootFilePathSize
= StrSize(BootFilePath
);
350 // Create the FilePath Device Path node
351 FilePathDevicePath
= (FILEPATH_DEVICE_PATH
*)AllocatePool(SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
352 FilePathDevicePath
->Header
.Type
= MEDIA_DEVICE_PATH
;
353 FilePathDevicePath
->Header
.SubType
= MEDIA_FILEPATH_DP
;
354 SetDevicePathNodeLength (FilePathDevicePath
, SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
355 CopyMem (FilePathDevicePath
->PathName
, BootFilePath
, BootFilePathSize
);
356 FreePool (BootFilePath
);
358 Status
= BootDeviceGetType (FilePathDevicePath
->PathName
, BootType
, Attributes
);
359 if (EFI_ERROR(Status
)) {
360 FreePool (FilePathDevicePath
);
362 *DevicePathNode
= (EFI_DEVICE_PATH_PROTOCOL
*)FilePathDevicePath
;
369 BdsLoadOptionFileSystemUpdateDevicePath (
370 IN BDS_LOAD_OPTION
*BootOption
,
371 OUT EFI_DEVICE_PATH_PROTOCOL
** NewDevicePath
,
372 OUT BDS_LOADER_TYPE
*BootType
,
373 OUT UINT32
*Attributes
377 CHAR8 AsciiBootFilePath
[BOOT_DEVICE_FILEPATH_MAX
];
378 CHAR16
*BootFilePath
;
379 UINTN BootFilePathSize
;
380 FILEPATH_DEVICE_PATH
* EndingDevicePath
;
381 FILEPATH_DEVICE_PATH
* FilePathDevicePath
;
382 EFI_DEVICE_PATH
* DevicePath
;
384 DevicePath
= DuplicateDevicePath (BootOption
->FilePathList
);
385 EndingDevicePath
= (FILEPATH_DEVICE_PATH
*)GetLastDevicePathNode (DevicePath
);
387 Print(L
"File path of the EFI Application or the kernel: ");
388 UnicodeStrToAsciiStr (EndingDevicePath
->PathName
,AsciiBootFilePath
);
389 Status
= EditHIInputAscii(AsciiBootFilePath
,BOOT_DEVICE_FILEPATH_MAX
);
390 if (EFI_ERROR(Status
)) {
394 // Convert Ascii into Unicode
395 BootFilePath
= (CHAR16
*)AllocatePool(AsciiStrSize(AsciiBootFilePath
) * sizeof(CHAR16
));
396 AsciiStrToUnicodeStr (AsciiBootFilePath
, BootFilePath
);
397 BootFilePathSize
= StrSize(BootFilePath
);
399 // Create the FilePath Device Path node
400 FilePathDevicePath
= (FILEPATH_DEVICE_PATH
*)AllocatePool(SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
401 FilePathDevicePath
->Header
.Type
= MEDIA_DEVICE_PATH
;
402 FilePathDevicePath
->Header
.SubType
= MEDIA_FILEPATH_DP
;
403 SetDevicePathNodeLength (FilePathDevicePath
, SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
404 CopyMem (FilePathDevicePath
->PathName
, BootFilePath
, BootFilePathSize
);
405 FreePool (BootFilePath
);
407 // Generate the new Device Path by replacing the last node by the updated node
408 SetDevicePathEndNode (EndingDevicePath
);
409 *NewDevicePath
= AppendDevicePathNode (DevicePath
, (CONST EFI_DEVICE_PATH_PROTOCOL
*)FilePathDevicePath
);
410 FreePool(DevicePath
);
412 return BootDeviceGetType (FilePathDevicePath
->PathName
, BootType
, Attributes
);
416 BdsLoadOptionFileSystemIsSupported (
417 IN BDS_LOAD_OPTION
* BdsLoadOption
420 EFI_DEVICE_PATH
* DevicePathNode
;
422 DevicePathNode
= GetLastDevicePathNode (BdsLoadOption
->FilePathList
);
424 return IS_DEVICE_PATH_NODE(DevicePathNode
,MEDIA_DEVICE_PATH
,MEDIA_FILEPATH_DP
);
430 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
431 IN EFI_DEVICE_PATH_PROTOCOL
*ChildDevicePath
437 ParentSize
= GetDevicePathSize (ParentDevicePath
);
438 ChildSize
= GetDevicePathSize (ChildDevicePath
);
440 if (ParentSize
> ChildSize
) {
444 if (CompareMem (ParentDevicePath
, ChildDevicePath
, ParentSize
- END_DEVICE_PATH_LENGTH
) != 0) {
452 BdsLoadOptionMemMapList (
453 IN OUT LIST_ENTRY
* BdsLoadOptionList
458 EFI_HANDLE
*HandleBuffer
;
459 UINTN DevicePathHandleCount
;
460 EFI_HANDLE
*DevicePathHandleBuffer
;
464 BDS_SUPPORTED_DEVICE
*SupportedDevice
;
465 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
466 EFI_DEVICE_PATH
* DevicePath
;
468 // List all the BlockIo Protocols
469 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiBlockIoProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
470 if (EFI_ERROR (Status
)) {
474 for (Index
= 0; Index
< HandleCount
; Index
++) {
475 // We only select the handle WITH a Device Path AND not part of Media (to avoid duplication with HardDisk, CDROM, etc)
476 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
477 if (!EFI_ERROR(Status
)) {
478 // BlockIo is not part of Media Device Path
479 DevicePath
= DevicePathProtocol
;
480 while (!IsDevicePathEndType (DevicePath
) && (DevicePathType (DevicePath
) != MEDIA_DEVICE_PATH
)) {
481 DevicePath
= NextDevicePathNode (DevicePath
);
483 if (DevicePathType (DevicePath
) == MEDIA_DEVICE_PATH
) {
487 // Open all the handle supporting the DevicePath protocol and verify this handle has not got any child
488 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiDevicePathProtocolGuid
, NULL
, &DevicePathHandleCount
, &DevicePathHandleBuffer
);
489 ASSERT_EFI_ERROR (Status
);
491 for (Index2
= 0; (Index2
< DevicePathHandleCount
) && !IsParent
; Index2
++) {
492 if (HandleBuffer
[Index
] != DevicePathHandleBuffer
[Index2
]) {
493 gBS
->HandleProtocol (DevicePathHandleBuffer
[Index2
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePath
);
494 if (IsParentDevicePath (DevicePathProtocol
, DevicePath
)) {
503 // Allocate BDS Supported Device structure
504 SupportedDevice
= (BDS_SUPPORTED_DEVICE
*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE
));
506 Status
= GenerateDeviceDescriptionName (HandleBuffer
[Index
], SupportedDevice
->Description
);
507 ASSERT_EFI_ERROR (Status
);
509 SupportedDevice
->DevicePathProtocol
= DevicePathProtocol
;
510 SupportedDevice
->Support
= &BdsLoadOptionSupportList
[BDS_DEVICE_MEMMAP
];
512 InsertTailList (BdsLoadOptionList
,&SupportedDevice
->Link
);
520 BdsLoadOptionMemMapCreateDevicePath (
521 IN BDS_SUPPORTED_DEVICE
* BdsLoadOption
,
522 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNode
,
523 OUT BDS_LOADER_TYPE
*BootType
,
524 OUT UINT32
*Attributes
528 MEMMAP_DEVICE_PATH
* MemMapDevicePath
;
529 CHAR8 AsciiStartingAddress
[BOOT_DEVICE_ADDRESS_MAX
];
530 CHAR8 AsciiEndingAddress
[BOOT_DEVICE_ADDRESS_MAX
];
532 Print(L
"Starting Address of the binary: ");
533 Status
= GetHIInputAscii (AsciiStartingAddress
,BOOT_DEVICE_ADDRESS_MAX
);
534 if (EFI_ERROR(Status
)) {
538 Print(L
"Ending Address of the binary: ");
539 Status
= GetHIInputAscii (AsciiEndingAddress
,BOOT_DEVICE_ADDRESS_MAX
);
540 if (EFI_ERROR(Status
)) {
544 // Create the MemMap Device Path Node
545 MemMapDevicePath
= (MEMMAP_DEVICE_PATH
*)AllocatePool(sizeof(MEMMAP_DEVICE_PATH
));
546 MemMapDevicePath
->Header
.Type
= HARDWARE_DEVICE_PATH
;
547 MemMapDevicePath
->Header
.SubType
= HW_MEMMAP_DP
;
548 MemMapDevicePath
->MemoryType
= EfiBootServicesData
;
549 MemMapDevicePath
->StartingAddress
= AsciiStrHexToUint64 (AsciiStartingAddress
);
550 MemMapDevicePath
->EndingAddress
= AsciiStrHexToUint64 (AsciiEndingAddress
);
552 Status
= BootDeviceGetType (NULL
, BootType
, Attributes
);
553 if (EFI_ERROR(Status
)) {
554 FreePool (MemMapDevicePath
);
556 *DevicePathNode
= (EFI_DEVICE_PATH_PROTOCOL
*)MemMapDevicePath
;
563 BdsLoadOptionMemMapUpdateDevicePath (
564 IN BDS_LOAD_OPTION
*BootOption
,
565 OUT EFI_DEVICE_PATH_PROTOCOL
** NewDevicePath
,
566 OUT BDS_LOADER_TYPE
*BootType
,
567 OUT UINT32
*Attributes
576 BdsLoadOptionMemMapIsSupported (
577 IN BDS_LOAD_OPTION
* BdsLoadOption
580 EFI_DEVICE_PATH
* DevicePathNode
;
582 DevicePathNode
= GetLastDevicePathNode (BdsLoadOption
->FilePathList
);
584 return IS_DEVICE_PATH_NODE(DevicePathNode
,HARDWARE_DEVICE_PATH
,HW_MEMMAP_DP
);
588 BdsLoadOptionPxeList (
589 IN OUT LIST_ENTRY
* BdsLoadOptionList
594 EFI_HANDLE
*HandleBuffer
;
596 BDS_SUPPORTED_DEVICE
*SupportedDevice
;
597 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
598 EFI_SIMPLE_NETWORK_PROTOCOL
* SimpleNet
;
599 CHAR16 DeviceDescription
[BOOT_DEVICE_DESCRIPTION_MAX
];
600 EFI_MAC_ADDRESS
*Mac
;
602 // List all the PXE Protocols
603 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiPxeBaseCodeProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
604 if (EFI_ERROR (Status
)) {
608 for (Index
= 0; Index
< HandleCount
; Index
++) {
609 // We only select the handle WITH a Device Path AND the PXE Protocol
610 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
611 if (!EFI_ERROR(Status
)) {
612 // Allocate BDS Supported Device structure
613 SupportedDevice
= (BDS_SUPPORTED_DEVICE
*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE
));
615 Status
= gBS
->LocateProtocol (&gEfiSimpleNetworkProtocolGuid
, NULL
, (VOID
**)&SimpleNet
);
616 if (!EFI_ERROR(Status
)) {
617 Mac
= &SimpleNet
->Mode
->CurrentAddress
;
618 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]);
620 Status
= GenerateDeviceDescriptionName (HandleBuffer
[Index
], DeviceDescription
);
621 ASSERT_EFI_ERROR (Status
);
623 UnicodeSPrint (SupportedDevice
->Description
,BOOT_DEVICE_DESCRIPTION_MAX
,L
"PXE on %s",DeviceDescription
);
625 SupportedDevice
->DevicePathProtocol
= DevicePathProtocol
;
626 SupportedDevice
->Support
= &BdsLoadOptionSupportList
[BDS_DEVICE_PXE
];
628 InsertTailList (BdsLoadOptionList
,&SupportedDevice
->Link
);
636 BdsLoadOptionPxeCreateDevicePath (
637 IN BDS_SUPPORTED_DEVICE
* BdsLoadOption
,
638 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNode
,
639 OUT BDS_LOADER_TYPE
*BootType
,
640 OUT UINT32
*Attributes
643 *DevicePathNode
= (EFI_DEVICE_PATH_PROTOCOL
*) AllocatePool (END_DEVICE_PATH_LENGTH
);
644 SetDevicePathEndNode (*DevicePathNode
);
645 *BootType
= BDS_LOADER_EFI_APPLICATION
;
650 BdsLoadOptionPxeUpdateDevicePath (
651 IN BDS_LOAD_OPTION
*BootOption
,
652 OUT EFI_DEVICE_PATH_PROTOCOL
** NewDevicePath
,
653 OUT BDS_LOADER_TYPE
*BootType
,
654 OUT UINT32
*Attributes
662 BdsLoadOptionPxeIsSupported (
663 IN BDS_LOAD_OPTION
* BdsLoadOption
668 EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
;
669 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBcProtocol
;
671 Status
= BdsConnectDevicePath (BdsLoadOption
->FilePathList
, &Handle
, &RemainingDevicePath
);
672 if (EFI_ERROR(Status
)) {
676 if (!IsDevicePathEnd(RemainingDevicePath
)) {
680 Status
= gBS
->HandleProtocol (Handle
, &gEfiPxeBaseCodeProtocolGuid
, (VOID
**)&PxeBcProtocol
);
681 if (EFI_ERROR (Status
)) {
689 BdsLoadOptionTftpList (
690 IN OUT LIST_ENTRY
* BdsLoadOptionList
695 EFI_HANDLE
*HandleBuffer
;
697 BDS_SUPPORTED_DEVICE
*SupportedDevice
;
698 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
699 EFI_SIMPLE_NETWORK_PROTOCOL
* SimpleNet
;
700 CHAR16 DeviceDescription
[BOOT_DEVICE_DESCRIPTION_MAX
];
701 EFI_MAC_ADDRESS
*Mac
;
703 // List all the PXE Protocols
704 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiPxeBaseCodeProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
705 if (EFI_ERROR (Status
)) {
709 for (Index
= 0; Index
< HandleCount
; Index
++) {
710 // 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)
711 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
712 if (!EFI_ERROR(Status
)) {
713 // Allocate BDS Supported Device structure
714 SupportedDevice
= (BDS_SUPPORTED_DEVICE
*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE
));
716 Status
= gBS
->LocateProtocol (&gEfiSimpleNetworkProtocolGuid
, NULL
, (VOID
**)&SimpleNet
);
717 if (!EFI_ERROR(Status
)) {
718 Mac
= &SimpleNet
->Mode
->CurrentAddress
;
719 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]);
721 Status
= GenerateDeviceDescriptionName (HandleBuffer
[Index
], DeviceDescription
);
722 ASSERT_EFI_ERROR (Status
);
724 UnicodeSPrint (SupportedDevice
->Description
,BOOT_DEVICE_DESCRIPTION_MAX
,L
"TFP on %s",DeviceDescription
);
726 SupportedDevice
->DevicePathProtocol
= DevicePathProtocol
;
727 SupportedDevice
->Support
= &BdsLoadOptionSupportList
[BDS_DEVICE_TFTP
];
729 InsertTailList (BdsLoadOptionList
,&SupportedDevice
->Link
);
737 BdsLoadOptionTftpCreateDevicePath (
738 IN BDS_SUPPORTED_DEVICE
* BdsLoadOption
,
739 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNode
,
740 OUT BDS_LOADER_TYPE
*BootType
,
741 OUT UINT32
*Attributes
746 EFI_IP_ADDRESS LocalIp
;
747 EFI_IP_ADDRESS RemoteIp
;
748 IPv4_DEVICE_PATH
* IPv4DevicePathNode
;
749 FILEPATH_DEVICE_PATH
* FilePathDevicePath
;
750 CHAR8 AsciiBootFilePath
[BOOT_DEVICE_FILEPATH_MAX
];
751 CHAR16
* BootFilePath
;
752 UINTN BootFilePathSize
;
754 Print(L
"Get the IP address from DHCP: ");
755 Status
= GetHIInputBoolean (&IsDHCP
);
756 if (EFI_ERROR(Status
)) {
761 Print(L
"Get the static IP address: ");
762 Status
= GetHIInputIP (&LocalIp
);
763 if (EFI_ERROR(Status
)) {
768 Print(L
"Get the TFTP server IP address: ");
769 Status
= GetHIInputIP (&RemoteIp
);
770 if (EFI_ERROR(Status
)) {
774 Print(L
"File path of the EFI Application or the kernel: ");
775 Status
= GetHIInputAscii (AsciiBootFilePath
,BOOT_DEVICE_FILEPATH_MAX
);
776 if (EFI_ERROR(Status
)) {
780 // Convert Ascii into Unicode
781 BootFilePath
= (CHAR16
*)AllocatePool(AsciiStrSize(AsciiBootFilePath
) * sizeof(CHAR16
));
782 AsciiStrToUnicodeStr (AsciiBootFilePath
, BootFilePath
);
783 BootFilePathSize
= StrSize(BootFilePath
);
785 // Allocate the memory for the IPv4 + File Path Device Path Nodes
786 IPv4DevicePathNode
= (IPv4_DEVICE_PATH
*)AllocatePool(sizeof(IPv4_DEVICE_PATH
) + SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
788 // Create the IPv4 Device Path
789 IPv4DevicePathNode
->Header
.Type
= MESSAGING_DEVICE_PATH
;
790 IPv4DevicePathNode
->Header
.SubType
= MSG_IPv4_DP
;
791 SetDevicePathNodeLength (&IPv4DevicePathNode
->Header
, sizeof(IPv4_DEVICE_PATH
));
792 CopyMem (&IPv4DevicePathNode
->LocalIpAddress
, &LocalIp
.v4
, sizeof (EFI_IPv4_ADDRESS
));
793 CopyMem (&IPv4DevicePathNode
->RemoteIpAddress
, &RemoteIp
.v4
, sizeof (EFI_IPv4_ADDRESS
));
794 IPv4DevicePathNode
->LocalPort
= 0;
795 IPv4DevicePathNode
->RemotePort
= 0;
796 IPv4DevicePathNode
->Protocol
= EFI_IP_PROTO_TCP
;
797 IPv4DevicePathNode
->StaticIpAddress
= (IsDHCP
!= TRUE
);
799 // Create the FilePath Device Path node
800 FilePathDevicePath
= (FILEPATH_DEVICE_PATH
*)(IPv4DevicePathNode
+ 1);
801 FilePathDevicePath
->Header
.Type
= MEDIA_DEVICE_PATH
;
802 FilePathDevicePath
->Header
.SubType
= MEDIA_FILEPATH_DP
;
803 SetDevicePathNodeLength (FilePathDevicePath
, SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
804 CopyMem (FilePathDevicePath
->PathName
, BootFilePath
, BootFilePathSize
);
805 FreePool (BootFilePath
);
807 Status
= BootDeviceGetType (NULL
, BootType
, Attributes
);
808 if (EFI_ERROR(Status
)) {
809 FreePool (IPv4DevicePathNode
);
811 *DevicePathNode
= (EFI_DEVICE_PATH_PROTOCOL
*)IPv4DevicePathNode
;
818 BdsLoadOptionTftpUpdateDevicePath (
819 IN BDS_LOAD_OPTION
*BootOption
,
820 OUT EFI_DEVICE_PATH_PROTOCOL
** NewDevicePath
,
821 OUT BDS_LOADER_TYPE
*BootType
,
822 OUT UINT32
*Attributes
830 BdsLoadOptionTftpIsSupported (
831 IN BDS_LOAD_OPTION
* BdsLoadOption
836 EFI_DEVICE_PATH
*RemainingDevicePath
;
837 EFI_DEVICE_PATH
*NextDevicePath
;
838 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBcProtocol
;
840 Status
= BdsConnectDevicePath (BdsLoadOption
->FilePathList
, &Handle
, &RemainingDevicePath
);
841 if (EFI_ERROR(Status
)) {
845 // Validate the Remaining Device Path
846 if (IsDevicePathEnd(RemainingDevicePath
)) {
849 if (!IS_DEVICE_PATH_NODE(RemainingDevicePath
,MESSAGING_DEVICE_PATH
,MSG_IPv4_DP
) &&
850 !IS_DEVICE_PATH_NODE(RemainingDevicePath
,MESSAGING_DEVICE_PATH
,MSG_IPv6_DP
)) {
853 NextDevicePath
= NextDevicePathNode (RemainingDevicePath
);
854 if (IsDevicePathEnd(NextDevicePath
)) {
857 if (!IS_DEVICE_PATH_NODE(NextDevicePath
,MEDIA_DEVICE_PATH
,MEDIA_FILEPATH_DP
)) {
861 Status
= gBS
->HandleProtocol (Handle
, &gEfiPxeBaseCodeProtocolGuid
, (VOID
**)&PxeBcProtocol
);
862 if (EFI_ERROR (Status
)) {