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
571 CHAR8 AsciiStartingAddress
[BOOT_DEVICE_ADDRESS_MAX
];
572 CHAR8 AsciiEndingAddress
[BOOT_DEVICE_ADDRESS_MAX
];
573 MEMMAP_DEVICE_PATH
* EndingDevicePath
;
574 EFI_DEVICE_PATH
* DevicePath
;
576 DevicePath
= DuplicateDevicePath (BootOption
->FilePathList
);
577 EndingDevicePath
= (MEMMAP_DEVICE_PATH
*)GetLastDevicePathNode (DevicePath
);
579 Print(L
"Starting Address of the binary: ");
580 AsciiSPrint (AsciiStartingAddress
,BOOT_DEVICE_ADDRESS_MAX
,"0x%X",(UINTN
)EndingDevicePath
->StartingAddress
);
581 Status
= EditHIInputAscii (AsciiStartingAddress
,BOOT_DEVICE_ADDRESS_MAX
);
582 if (EFI_ERROR(Status
)) {
586 Print(L
"Ending Address of the binary: ");
587 AsciiSPrint (AsciiEndingAddress
,BOOT_DEVICE_ADDRESS_MAX
,"0x%X",(UINTN
)EndingDevicePath
->EndingAddress
);
588 Status
= EditHIInputAscii (AsciiEndingAddress
,BOOT_DEVICE_ADDRESS_MAX
);
589 if (EFI_ERROR(Status
)) {
593 EndingDevicePath
->StartingAddress
= AsciiStrHexToUint64 (AsciiStartingAddress
);
594 EndingDevicePath
->EndingAddress
= AsciiStrHexToUint64 (AsciiEndingAddress
);
596 Status
= BootDeviceGetType (NULL
, BootType
, Attributes
);
597 if (EFI_ERROR(Status
)) {
598 FreePool(DevicePath
);
600 *NewDevicePath
= DevicePath
;
607 BdsLoadOptionMemMapIsSupported (
608 IN BDS_LOAD_OPTION
* BdsLoadOption
611 EFI_DEVICE_PATH
* DevicePathNode
;
613 DevicePathNode
= GetLastDevicePathNode (BdsLoadOption
->FilePathList
);
615 return IS_DEVICE_PATH_NODE(DevicePathNode
,HARDWARE_DEVICE_PATH
,HW_MEMMAP_DP
);
619 BdsLoadOptionPxeList (
620 IN OUT LIST_ENTRY
* BdsLoadOptionList
625 EFI_HANDLE
*HandleBuffer
;
627 BDS_SUPPORTED_DEVICE
*SupportedDevice
;
628 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
629 EFI_SIMPLE_NETWORK_PROTOCOL
* SimpleNet
;
630 CHAR16 DeviceDescription
[BOOT_DEVICE_DESCRIPTION_MAX
];
631 EFI_MAC_ADDRESS
*Mac
;
633 // List all the PXE Protocols
634 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiPxeBaseCodeProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
635 if (EFI_ERROR (Status
)) {
639 for (Index
= 0; Index
< HandleCount
; Index
++) {
640 // We only select the handle WITH a Device Path AND the PXE Protocol
641 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
642 if (!EFI_ERROR(Status
)) {
643 // Allocate BDS Supported Device structure
644 SupportedDevice
= (BDS_SUPPORTED_DEVICE
*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE
));
646 Status
= gBS
->LocateProtocol (&gEfiSimpleNetworkProtocolGuid
, NULL
, (VOID
**)&SimpleNet
);
647 if (!EFI_ERROR(Status
)) {
648 Mac
= &SimpleNet
->Mode
->CurrentAddress
;
649 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]);
651 Status
= GenerateDeviceDescriptionName (HandleBuffer
[Index
], DeviceDescription
);
652 ASSERT_EFI_ERROR (Status
);
654 UnicodeSPrint (SupportedDevice
->Description
,BOOT_DEVICE_DESCRIPTION_MAX
,L
"PXE on %s",DeviceDescription
);
656 SupportedDevice
->DevicePathProtocol
= DevicePathProtocol
;
657 SupportedDevice
->Support
= &BdsLoadOptionSupportList
[BDS_DEVICE_PXE
];
659 InsertTailList (BdsLoadOptionList
,&SupportedDevice
->Link
);
667 BdsLoadOptionPxeCreateDevicePath (
668 IN BDS_SUPPORTED_DEVICE
* BdsLoadOption
,
669 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNode
,
670 OUT BDS_LOADER_TYPE
*BootType
,
671 OUT UINT32
*Attributes
674 *DevicePathNode
= (EFI_DEVICE_PATH_PROTOCOL
*) AllocatePool (END_DEVICE_PATH_LENGTH
);
675 SetDevicePathEndNode (*DevicePathNode
);
676 *BootType
= BDS_LOADER_EFI_APPLICATION
;
681 BdsLoadOptionPxeUpdateDevicePath (
682 IN BDS_LOAD_OPTION
*BootOption
,
683 OUT EFI_DEVICE_PATH_PROTOCOL
** NewDevicePath
,
684 OUT BDS_LOADER_TYPE
*BootType
,
685 OUT UINT32
*Attributes
693 BdsLoadOptionPxeIsSupported (
694 IN BDS_LOAD_OPTION
* BdsLoadOption
699 EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
;
700 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBcProtocol
;
702 Status
= BdsConnectDevicePath (BdsLoadOption
->FilePathList
, &Handle
, &RemainingDevicePath
);
703 if (EFI_ERROR(Status
)) {
707 if (!IsDevicePathEnd(RemainingDevicePath
)) {
711 Status
= gBS
->HandleProtocol (Handle
, &gEfiPxeBaseCodeProtocolGuid
, (VOID
**)&PxeBcProtocol
);
712 if (EFI_ERROR (Status
)) {
720 BdsLoadOptionTftpList (
721 IN OUT LIST_ENTRY
* BdsLoadOptionList
726 EFI_HANDLE
*HandleBuffer
;
728 BDS_SUPPORTED_DEVICE
*SupportedDevice
;
729 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
730 EFI_SIMPLE_NETWORK_PROTOCOL
* SimpleNet
;
731 CHAR16 DeviceDescription
[BOOT_DEVICE_DESCRIPTION_MAX
];
732 EFI_MAC_ADDRESS
*Mac
;
734 // List all the PXE Protocols
735 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiPxeBaseCodeProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
736 if (EFI_ERROR (Status
)) {
740 for (Index
= 0; Index
< HandleCount
; Index
++) {
741 // 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)
742 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
743 if (!EFI_ERROR(Status
)) {
744 // Allocate BDS Supported Device structure
745 SupportedDevice
= (BDS_SUPPORTED_DEVICE
*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE
));
747 Status
= gBS
->LocateProtocol (&gEfiSimpleNetworkProtocolGuid
, NULL
, (VOID
**)&SimpleNet
);
748 if (!EFI_ERROR(Status
)) {
749 Mac
= &SimpleNet
->Mode
->CurrentAddress
;
750 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]);
752 Status
= GenerateDeviceDescriptionName (HandleBuffer
[Index
], DeviceDescription
);
753 ASSERT_EFI_ERROR (Status
);
755 UnicodeSPrint (SupportedDevice
->Description
,BOOT_DEVICE_DESCRIPTION_MAX
,L
"TFP on %s",DeviceDescription
);
757 SupportedDevice
->DevicePathProtocol
= DevicePathProtocol
;
758 SupportedDevice
->Support
= &BdsLoadOptionSupportList
[BDS_DEVICE_TFTP
];
760 InsertTailList (BdsLoadOptionList
,&SupportedDevice
->Link
);
768 BdsLoadOptionTftpCreateDevicePath (
769 IN BDS_SUPPORTED_DEVICE
* BdsLoadOption
,
770 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNode
,
771 OUT BDS_LOADER_TYPE
*BootType
,
772 OUT UINT32
*Attributes
777 EFI_IP_ADDRESS LocalIp
;
778 EFI_IP_ADDRESS RemoteIp
;
779 IPv4_DEVICE_PATH
* IPv4DevicePathNode
;
780 FILEPATH_DEVICE_PATH
* FilePathDevicePath
;
781 CHAR8 AsciiBootFilePath
[BOOT_DEVICE_FILEPATH_MAX
];
782 CHAR16
* BootFilePath
;
783 UINTN BootFilePathSize
;
785 Print(L
"Get the IP address from DHCP: ");
786 Status
= GetHIInputBoolean (&IsDHCP
);
787 if (EFI_ERROR(Status
)) {
792 Print(L
"Get the static IP address: ");
793 Status
= GetHIInputIP (&LocalIp
);
794 if (EFI_ERROR(Status
)) {
799 Print(L
"Get the TFTP server IP address: ");
800 Status
= GetHIInputIP (&RemoteIp
);
801 if (EFI_ERROR(Status
)) {
805 Print(L
"File path of the EFI Application or the kernel: ");
806 Status
= GetHIInputAscii (AsciiBootFilePath
,BOOT_DEVICE_FILEPATH_MAX
);
807 if (EFI_ERROR(Status
)) {
811 // Convert Ascii into Unicode
812 BootFilePath
= (CHAR16
*)AllocatePool(AsciiStrSize(AsciiBootFilePath
) * sizeof(CHAR16
));
813 AsciiStrToUnicodeStr (AsciiBootFilePath
, BootFilePath
);
814 BootFilePathSize
= StrSize(BootFilePath
);
816 // Allocate the memory for the IPv4 + File Path Device Path Nodes
817 IPv4DevicePathNode
= (IPv4_DEVICE_PATH
*)AllocatePool(sizeof(IPv4_DEVICE_PATH
) + SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
819 // Create the IPv4 Device Path
820 IPv4DevicePathNode
->Header
.Type
= MESSAGING_DEVICE_PATH
;
821 IPv4DevicePathNode
->Header
.SubType
= MSG_IPv4_DP
;
822 SetDevicePathNodeLength (&IPv4DevicePathNode
->Header
, sizeof(IPv4_DEVICE_PATH
));
823 CopyMem (&IPv4DevicePathNode
->LocalIpAddress
, &LocalIp
.v4
, sizeof (EFI_IPv4_ADDRESS
));
824 CopyMem (&IPv4DevicePathNode
->RemoteIpAddress
, &RemoteIp
.v4
, sizeof (EFI_IPv4_ADDRESS
));
825 IPv4DevicePathNode
->LocalPort
= 0;
826 IPv4DevicePathNode
->RemotePort
= 0;
827 IPv4DevicePathNode
->Protocol
= EFI_IP_PROTO_TCP
;
828 IPv4DevicePathNode
->StaticIpAddress
= (IsDHCP
!= TRUE
);
830 // Create the FilePath Device Path node
831 FilePathDevicePath
= (FILEPATH_DEVICE_PATH
*)(IPv4DevicePathNode
+ 1);
832 FilePathDevicePath
->Header
.Type
= MEDIA_DEVICE_PATH
;
833 FilePathDevicePath
->Header
.SubType
= MEDIA_FILEPATH_DP
;
834 SetDevicePathNodeLength (FilePathDevicePath
, SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
835 CopyMem (FilePathDevicePath
->PathName
, BootFilePath
, BootFilePathSize
);
836 FreePool (BootFilePath
);
838 Status
= BootDeviceGetType (NULL
, BootType
, Attributes
);
839 if (EFI_ERROR(Status
)) {
840 FreePool (IPv4DevicePathNode
);
842 *DevicePathNode
= (EFI_DEVICE_PATH_PROTOCOL
*)IPv4DevicePathNode
;
849 BdsLoadOptionTftpUpdateDevicePath (
850 IN BDS_LOAD_OPTION
*BootOption
,
851 OUT EFI_DEVICE_PATH_PROTOCOL
** NewDevicePath
,
852 OUT BDS_LOADER_TYPE
*BootType
,
853 OUT UINT32
*Attributes
861 BdsLoadOptionTftpIsSupported (
862 IN BDS_LOAD_OPTION
* BdsLoadOption
867 EFI_DEVICE_PATH
*RemainingDevicePath
;
868 EFI_DEVICE_PATH
*NextDevicePath
;
869 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBcProtocol
;
871 Status
= BdsConnectDevicePath (BdsLoadOption
->FilePathList
, &Handle
, &RemainingDevicePath
);
872 if (EFI_ERROR(Status
)) {
876 // Validate the Remaining Device Path
877 if (IsDevicePathEnd(RemainingDevicePath
)) {
880 if (!IS_DEVICE_PATH_NODE(RemainingDevicePath
,MESSAGING_DEVICE_PATH
,MSG_IPv4_DP
) &&
881 !IS_DEVICE_PATH_NODE(RemainingDevicePath
,MESSAGING_DEVICE_PATH
,MSG_IPv6_DP
)) {
884 NextDevicePath
= NextDevicePathNode (RemainingDevicePath
);
885 if (IsDevicePathEnd(NextDevicePath
)) {
888 if (!IS_DEVICE_PATH_NODE(NextDevicePath
,MEDIA_DEVICE_PATH
,MEDIA_FILEPATH_DP
)) {
892 Status
= gBS
->HandleProtocol (Handle
, &gEfiPxeBaseCodeProtocolGuid
, (VOID
**)&PxeBcProtocol
);
893 if (EFI_ERROR (Status
)) {