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 (
37 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNode
,
38 OUT ARM_BDS_LOADER_TYPE
*BootType
,
39 OUT UINT32
*Attributes
43 BdsLoadOptionFileSystemUpdateDevicePath (
44 IN EFI_DEVICE_PATH
*OldDevicePath
,
46 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath
,
47 OUT ARM_BDS_LOADER_TYPE
*BootType
,
48 OUT UINT32
*Attributes
52 BdsLoadOptionFileSystemIsSupported (
53 IN EFI_DEVICE_PATH
*DevicePath
57 BdsLoadOptionMemMapList (
58 IN OUT LIST_ENTRY
* BdsLoadOptionList
62 BdsLoadOptionMemMapCreateDevicePath (
64 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNode
,
65 OUT ARM_BDS_LOADER_TYPE
*BootType
,
66 OUT UINT32
*Attributes
70 BdsLoadOptionMemMapUpdateDevicePath (
71 IN EFI_DEVICE_PATH
*OldDevicePath
,
73 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath
,
74 OUT ARM_BDS_LOADER_TYPE
*BootType
,
75 OUT UINT32
*Attributes
79 BdsLoadOptionMemMapIsSupported (
80 IN EFI_DEVICE_PATH
*DevicePath
84 BdsLoadOptionPxeList (
85 IN OUT LIST_ENTRY
* BdsLoadOptionList
89 BdsLoadOptionPxeCreateDevicePath (
91 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNode
,
92 OUT ARM_BDS_LOADER_TYPE
*BootType
,
93 OUT UINT32
*Attributes
97 BdsLoadOptionPxeUpdateDevicePath (
98 IN EFI_DEVICE_PATH
*OldDevicePath
,
100 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath
,
101 OUT ARM_BDS_LOADER_TYPE
*BootType
,
102 OUT UINT32
*Attributes
106 BdsLoadOptionPxeIsSupported (
107 IN EFI_DEVICE_PATH
*DevicePath
111 BdsLoadOptionTftpList (
112 IN OUT LIST_ENTRY
* BdsLoadOptionList
116 BdsLoadOptionTftpCreateDevicePath (
118 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNode
,
119 OUT ARM_BDS_LOADER_TYPE
*BootType
,
120 OUT UINT32
*Attributes
124 BdsLoadOptionTftpUpdateDevicePath (
125 IN EFI_DEVICE_PATH
*OldDevicePath
,
127 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath
,
128 OUT ARM_BDS_LOADER_TYPE
*BootType
,
129 OUT UINT32
*Attributes
133 BdsLoadOptionTftpIsSupported (
134 IN EFI_DEVICE_PATH
*DevicePath
137 BDS_LOAD_OPTION_SUPPORT BdsLoadOptionSupportList
[] = {
139 BDS_DEVICE_FILESYSTEM
,
140 BdsLoadOptionFileSystemList
,
141 BdsLoadOptionFileSystemIsSupported
,
142 BdsLoadOptionFileSystemCreateDevicePath
,
143 BdsLoadOptionFileSystemUpdateDevicePath
147 BdsLoadOptionMemMapList
,
148 BdsLoadOptionMemMapIsSupported
,
149 BdsLoadOptionMemMapCreateDevicePath
,
150 BdsLoadOptionMemMapUpdateDevicePath
154 BdsLoadOptionPxeList
,
155 BdsLoadOptionPxeIsSupported
,
156 BdsLoadOptionPxeCreateDevicePath
,
157 BdsLoadOptionPxeUpdateDevicePath
161 BdsLoadOptionTftpList
,
162 BdsLoadOptionTftpIsSupported
,
163 BdsLoadOptionTftpCreateDevicePath
,
164 BdsLoadOptionTftpUpdateDevicePath
169 BootDeviceListSupportedInit (
170 IN OUT LIST_ENTRY
*SupportedDeviceList
175 // Initialize list of supported devices
176 InitializeListHead (SupportedDeviceList
);
178 for (Index
= 0; Index
< BDS_DEVICE_MAX
; Index
++) {
179 BdsLoadOptionSupportList
[Index
].ListDevices (SupportedDeviceList
);
186 BootDeviceListSupportedFree (
187 IN LIST_ENTRY
*SupportedDeviceList
,
188 IN BDS_SUPPORTED_DEVICE
*Except
192 BDS_SUPPORTED_DEVICE
* SupportedDevice
;
194 Entry
= GetFirstNode (SupportedDeviceList
);
195 while (Entry
!= SupportedDeviceList
) {
196 SupportedDevice
= SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry
);
197 Entry
= RemoveEntryList (Entry
);
198 if (SupportedDevice
!= Except
) {
199 FreePool (SupportedDevice
);
207 BootDeviceGetDeviceSupport (
208 IN EFI_DEVICE_PATH
*DevicePath
,
209 OUT BDS_LOAD_OPTION_SUPPORT
**DeviceSupport
214 // Find which supported device is the most appropriate
215 for (Index
= 0; Index
< BDS_DEVICE_MAX
; Index
++) {
216 if (BdsLoadOptionSupportList
[Index
].IsSupported (DevicePath
)) {
217 *DeviceSupport
= &BdsLoadOptionSupportList
[Index
];
222 return EFI_UNSUPPORTED
;
229 OUT ARM_BDS_LOADER_TYPE
*BootType
,
230 OUT UINT32
*Attributes
235 BOOLEAN IsBootLoader
;
236 BOOLEAN HasFDTSupport
;
238 if (FileName
== NULL
) {
239 Print(L
"Is an EFI Application? ");
240 Status
= GetHIInputBoolean (&IsEfiApp
);
241 if (EFI_ERROR(Status
)) {
244 } else if (HasFilePathEfiExtension(FileName
)) {
251 Print(L
"Is your application is an OS loader? ");
252 Status
= GetHIInputBoolean (&IsBootLoader
);
253 if (EFI_ERROR(Status
)) {
257 *Attributes
|= LOAD_OPTION_CATEGORY_APP
;
259 *BootType
= BDS_LOADER_EFI_APPLICATION
;
261 Print(L
"Has FDT support? ");
262 Status
= GetHIInputBoolean (&HasFDTSupport
);
263 if (EFI_ERROR(Status
)) {
267 *BootType
= BDS_LOADER_KERNEL_LINUX_FDT
;
269 *BootType
= BDS_LOADER_KERNEL_LINUX_ATAG
;
277 BdsLoadOptionFileSystemList (
278 IN OUT LIST_ENTRY
* BdsLoadOptionList
283 EFI_HANDLE
*HandleBuffer
;
285 BDS_SUPPORTED_DEVICE
*SupportedDevice
;
286 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
* FileProtocol
;
289 EFI_FILE_SYSTEM_INFO
* FsInfo
;
290 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
292 // List all the Simple File System Protocols
293 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiSimpleFileSystemProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
294 if (EFI_ERROR (Status
)) {
298 for (Index
= 0; Index
< HandleCount
; Index
++) {
299 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
300 if (!EFI_ERROR(Status
)) {
301 // Allocate BDS Supported Device structure
302 SupportedDevice
= (BDS_SUPPORTED_DEVICE
*)AllocatePool (sizeof(BDS_SUPPORTED_DEVICE
));
305 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiSimpleFileSystemProtocolGuid
, (VOID
**)&FileProtocol
);
306 ASSERT_EFI_ERROR(Status
);
308 FileProtocol
->OpenVolume (FileProtocol
, &Fs
);
310 // Generate a Description from the file system
313 Status
= Fs
->GetInfo (Fs
, &gEfiFileSystemInfoGuid
, &Size
, FsInfo
);
314 if (Status
== EFI_BUFFER_TOO_SMALL
) {
315 FsInfo
= AllocatePool (Size
);
316 Status
= Fs
->GetInfo (Fs
, &gEfiFileSystemInfoGuid
, &Size
, FsInfo
);
318 UnicodeSPrint (SupportedDevice
->Description
,BOOT_DEVICE_DESCRIPTION_MAX
,L
"%s (%d MB)",FsInfo
->VolumeLabel
,(UINT32
)(FsInfo
->VolumeSize
/ (1024 * 1024)));
322 SupportedDevice
->DevicePathProtocol
= DevicePathProtocol
;
323 SupportedDevice
->Support
= &BdsLoadOptionSupportList
[BDS_DEVICE_FILESYSTEM
];
325 InsertTailList (BdsLoadOptionList
,&SupportedDevice
->Link
);
333 BdsLoadOptionFileSystemCreateDevicePath (
335 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNode
,
336 OUT ARM_BDS_LOADER_TYPE
*BootType
,
337 OUT UINT32
*Attributes
341 FILEPATH_DEVICE_PATH
* FilePathDevicePath
;
342 CHAR16 BootFilePath
[BOOT_DEVICE_FILEPATH_MAX
];
343 UINTN BootFilePathSize
;
345 Print(L
"File path of the %s: ", FileName
);
346 Status
= GetHIInputStr (BootFilePath
, BOOT_DEVICE_FILEPATH_MAX
);
347 if (EFI_ERROR(Status
)) {
351 BootFilePathSize
= StrSize (BootFilePath
);
352 if (BootFilePathSize
== 2) {
353 *DevicePathNode
= NULL
;
354 return EFI_NOT_FOUND
;
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
);
364 if (BootType
!= NULL
|| Attributes
!= NULL
) {
365 Status
= BootDeviceGetType (FilePathDevicePath
->PathName
, BootType
, Attributes
);
368 if (EFI_ERROR(Status
)) {
369 FreePool (FilePathDevicePath
);
371 *DevicePathNode
= (EFI_DEVICE_PATH_PROTOCOL
*)FilePathDevicePath
;
378 BdsLoadOptionFileSystemUpdateDevicePath (
379 IN EFI_DEVICE_PATH
*OldDevicePath
,
381 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath
,
382 OUT ARM_BDS_LOADER_TYPE
*BootType
,
383 OUT UINT32
*Attributes
387 CHAR16 BootFilePath
[BOOT_DEVICE_FILEPATH_MAX
];
388 UINTN BootFilePathSize
;
389 FILEPATH_DEVICE_PATH
* EndingDevicePath
;
390 FILEPATH_DEVICE_PATH
* FilePathDevicePath
;
391 EFI_DEVICE_PATH
* DevicePath
;
393 DevicePath
= DuplicateDevicePath (OldDevicePath
);
395 EndingDevicePath
= (FILEPATH_DEVICE_PATH
*)GetLastDevicePathNode (DevicePath
);
397 Print(L
"File path of the %s: ", FileName
);
398 StrnCpy (BootFilePath
, EndingDevicePath
->PathName
, BOOT_DEVICE_FILEPATH_MAX
);
399 Status
= EditHIInputStr (BootFilePath
, BOOT_DEVICE_FILEPATH_MAX
);
400 if (EFI_ERROR(Status
)) {
404 BootFilePathSize
= StrSize(BootFilePath
);
405 if (BootFilePathSize
== 2) {
406 *NewDevicePath
= NULL
;
407 return EFI_NOT_FOUND
;
410 // Create the FilePath Device Path node
411 FilePathDevicePath
= (FILEPATH_DEVICE_PATH
*)AllocatePool(SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
412 FilePathDevicePath
->Header
.Type
= MEDIA_DEVICE_PATH
;
413 FilePathDevicePath
->Header
.SubType
= MEDIA_FILEPATH_DP
;
414 SetDevicePathNodeLength (FilePathDevicePath
, SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
415 CopyMem (FilePathDevicePath
->PathName
, BootFilePath
, BootFilePathSize
);
417 // Generate the new Device Path by replacing the last node by the updated node
418 SetDevicePathEndNode (EndingDevicePath
);
419 *NewDevicePath
= AppendDevicePathNode (DevicePath
, (CONST EFI_DEVICE_PATH_PROTOCOL
*)FilePathDevicePath
);
420 FreePool(DevicePath
);
422 if (BootType
!= NULL
|| Attributes
!= NULL
) {
423 return BootDeviceGetType (FilePathDevicePath
->PathName
, BootType
, Attributes
);
430 BdsLoadOptionFileSystemIsSupported (
431 IN EFI_DEVICE_PATH
*DevicePath
434 EFI_DEVICE_PATH
* DevicePathNode
;
436 DevicePathNode
= GetLastDevicePathNode (DevicePath
);
438 return IS_DEVICE_PATH_NODE(DevicePathNode
,MEDIA_DEVICE_PATH
,MEDIA_FILEPATH_DP
);
444 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
445 IN EFI_DEVICE_PATH_PROTOCOL
*ChildDevicePath
451 ParentSize
= GetDevicePathSize (ParentDevicePath
);
452 ChildSize
= GetDevicePathSize (ChildDevicePath
);
454 if (ParentSize
> ChildSize
) {
458 if (CompareMem (ParentDevicePath
, ChildDevicePath
, ParentSize
- END_DEVICE_PATH_LENGTH
) != 0) {
466 BdsLoadOptionMemMapList (
467 IN OUT LIST_ENTRY
* BdsLoadOptionList
472 EFI_HANDLE
*HandleBuffer
;
473 UINTN DevicePathHandleCount
;
474 EFI_HANDLE
*DevicePathHandleBuffer
;
478 BDS_SUPPORTED_DEVICE
*SupportedDevice
;
479 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
480 EFI_DEVICE_PATH
* DevicePath
;
482 // List all the BlockIo Protocols
483 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiBlockIoProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
484 if (EFI_ERROR (Status
)) {
488 for (Index
= 0; Index
< HandleCount
; Index
++) {
489 // We only select the handle WITH a Device Path AND not part of Media (to avoid duplication with HardDisk, CDROM, etc)
490 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
491 if (!EFI_ERROR(Status
)) {
492 // BlockIo is not part of Media Device Path
493 DevicePath
= DevicePathProtocol
;
494 while (!IsDevicePathEndType (DevicePath
) && (DevicePathType (DevicePath
) != MEDIA_DEVICE_PATH
)) {
495 DevicePath
= NextDevicePathNode (DevicePath
);
497 if (DevicePathType (DevicePath
) == MEDIA_DEVICE_PATH
) {
501 // Open all the handle supporting the DevicePath protocol and verify this handle has not got any child
502 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiDevicePathProtocolGuid
, NULL
, &DevicePathHandleCount
, &DevicePathHandleBuffer
);
503 ASSERT_EFI_ERROR (Status
);
505 for (Index2
= 0; (Index2
< DevicePathHandleCount
) && !IsParent
; Index2
++) {
506 if (HandleBuffer
[Index
] != DevicePathHandleBuffer
[Index2
]) {
507 gBS
->HandleProtocol (DevicePathHandleBuffer
[Index2
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePath
);
508 if (IsParentDevicePath (DevicePathProtocol
, DevicePath
)) {
517 // Allocate BDS Supported Device structure
518 SupportedDevice
= (BDS_SUPPORTED_DEVICE
*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE
));
520 Status
= GenerateDeviceDescriptionName (HandleBuffer
[Index
], SupportedDevice
->Description
);
521 ASSERT_EFI_ERROR (Status
);
523 SupportedDevice
->DevicePathProtocol
= DevicePathProtocol
;
524 SupportedDevice
->Support
= &BdsLoadOptionSupportList
[BDS_DEVICE_MEMMAP
];
526 InsertTailList (BdsLoadOptionList
,&SupportedDevice
->Link
);
534 BdsLoadOptionMemMapCreateDevicePath (
536 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNode
,
537 OUT ARM_BDS_LOADER_TYPE
*BootType
,
538 OUT UINT32
*Attributes
542 MEMMAP_DEVICE_PATH
*MemMapDevicePath
;
543 CHAR16 StrStartingAddress
[BOOT_DEVICE_ADDRESS_MAX
];
544 CHAR16 StrEndingAddress
[BOOT_DEVICE_ADDRESS_MAX
];
546 Print(L
"Starting Address of the %s: ", FileName
);
547 Status
= GetHIInputStr (StrStartingAddress
, BOOT_DEVICE_ADDRESS_MAX
);
548 if (EFI_ERROR(Status
)) {
552 Print(L
"Ending Address of the %s: ", FileName
);
553 Status
= GetHIInputStr (StrEndingAddress
, BOOT_DEVICE_ADDRESS_MAX
);
554 if (EFI_ERROR(Status
)) {
558 // Create the MemMap Device Path Node
559 MemMapDevicePath
= (MEMMAP_DEVICE_PATH
*)AllocatePool (sizeof(MEMMAP_DEVICE_PATH
) + END_DEVICE_PATH_LENGTH
);
560 MemMapDevicePath
->Header
.Type
= HARDWARE_DEVICE_PATH
;
561 MemMapDevicePath
->Header
.SubType
= HW_MEMMAP_DP
;
562 SetDevicePathNodeLength (MemMapDevicePath
, sizeof(MEMMAP_DEVICE_PATH
));
563 MemMapDevicePath
->MemoryType
= EfiBootServicesData
;
564 MemMapDevicePath
->StartingAddress
= StrHexToUint64 (StrStartingAddress
);
565 MemMapDevicePath
->EndingAddress
= StrHexToUint64 (StrEndingAddress
);
567 // Set a Device Path End Node after the Memory Map Device Path Node
568 SetDevicePathEndNode (MemMapDevicePath
+ 1);
570 if (BootType
!= NULL
|| Attributes
!= NULL
) {
571 Status
= BootDeviceGetType (NULL
, BootType
, Attributes
);
574 if (EFI_ERROR(Status
)) {
575 FreePool (MemMapDevicePath
);
577 *DevicePathNode
= (EFI_DEVICE_PATH_PROTOCOL
*)MemMapDevicePath
;
584 BdsLoadOptionMemMapUpdateDevicePath (
585 IN EFI_DEVICE_PATH
*OldDevicePath
,
587 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath
,
588 OUT ARM_BDS_LOADER_TYPE
*BootType
,
589 OUT UINT32
*Attributes
593 CHAR16 StrStartingAddress
[BOOT_DEVICE_ADDRESS_MAX
];
594 CHAR16 StrEndingAddress
[BOOT_DEVICE_ADDRESS_MAX
];
595 MEMMAP_DEVICE_PATH
* EndingDevicePath
;
596 EFI_DEVICE_PATH
* DevicePath
;
598 DevicePath
= DuplicateDevicePath (OldDevicePath
);
599 EndingDevicePath
= (MEMMAP_DEVICE_PATH
*)GetLastDevicePathNode (DevicePath
);
601 Print(L
"Starting Address of the %s: ", FileName
);
602 UnicodeSPrint (StrStartingAddress
, BOOT_DEVICE_ADDRESS_MAX
, L
"0x%X", (UINTN
)EndingDevicePath
->StartingAddress
);
603 Status
= EditHIInputStr (StrStartingAddress
, BOOT_DEVICE_ADDRESS_MAX
);
604 if (EFI_ERROR(Status
)) {
608 Print(L
"Ending Address of the %s: ", FileName
);
609 UnicodeSPrint (StrEndingAddress
, BOOT_DEVICE_ADDRESS_MAX
, L
"0x%X", (UINTN
)EndingDevicePath
->EndingAddress
);
610 Status
= EditHIInputStr (StrEndingAddress
, BOOT_DEVICE_ADDRESS_MAX
);
611 if (EFI_ERROR(Status
)) {
615 EndingDevicePath
->StartingAddress
= StrHexToUint64 (StrStartingAddress
);
616 EndingDevicePath
->EndingAddress
= StrHexToUint64 (StrEndingAddress
);
618 if (BootType
!= NULL
|| Attributes
!= NULL
) {
619 Status
= BootDeviceGetType (NULL
, BootType
, Attributes
);
622 if (EFI_ERROR(Status
)) {
623 FreePool(DevicePath
);
625 *NewDevicePath
= DevicePath
;
632 BdsLoadOptionMemMapIsSupported (
633 IN EFI_DEVICE_PATH
*DevicePath
636 EFI_DEVICE_PATH
* DevicePathNode
;
638 DevicePathNode
= GetLastDevicePathNode (DevicePath
);
640 return IS_DEVICE_PATH_NODE(DevicePathNode
,HARDWARE_DEVICE_PATH
,HW_MEMMAP_DP
);
644 BdsLoadOptionPxeList (
645 IN OUT LIST_ENTRY
* BdsLoadOptionList
650 EFI_HANDLE
*HandleBuffer
;
652 BDS_SUPPORTED_DEVICE
*SupportedDevice
;
653 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
654 EFI_SIMPLE_NETWORK_PROTOCOL
* SimpleNet
;
655 CHAR16 DeviceDescription
[BOOT_DEVICE_DESCRIPTION_MAX
];
656 EFI_MAC_ADDRESS
*Mac
;
658 // List all the PXE Protocols
659 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiPxeBaseCodeProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
660 if (EFI_ERROR (Status
)) {
664 for (Index
= 0; Index
< HandleCount
; Index
++) {
665 // We only select the handle WITH a Device Path AND the PXE Protocol
666 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
667 if (!EFI_ERROR(Status
)) {
668 // Allocate BDS Supported Device structure
669 SupportedDevice
= (BDS_SUPPORTED_DEVICE
*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE
));
671 Status
= gBS
->LocateProtocol (&gEfiSimpleNetworkProtocolGuid
, NULL
, (VOID
**)&SimpleNet
);
672 if (!EFI_ERROR(Status
)) {
673 Mac
= &SimpleNet
->Mode
->CurrentAddress
;
674 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]);
676 Status
= GenerateDeviceDescriptionName (HandleBuffer
[Index
], DeviceDescription
);
677 ASSERT_EFI_ERROR (Status
);
679 UnicodeSPrint (SupportedDevice
->Description
,BOOT_DEVICE_DESCRIPTION_MAX
,L
"PXE on %s",DeviceDescription
);
681 SupportedDevice
->DevicePathProtocol
= DevicePathProtocol
;
682 SupportedDevice
->Support
= &BdsLoadOptionSupportList
[BDS_DEVICE_PXE
];
684 InsertTailList (BdsLoadOptionList
,&SupportedDevice
->Link
);
692 BdsLoadOptionPxeCreateDevicePath (
694 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNode
,
695 OUT ARM_BDS_LOADER_TYPE
*BootType
,
696 OUT UINT32
*Attributes
699 *DevicePathNode
= (EFI_DEVICE_PATH_PROTOCOL
*) AllocatePool (END_DEVICE_PATH_LENGTH
);
700 SetDevicePathEndNode (*DevicePathNode
);
701 *BootType
= BDS_LOADER_EFI_APPLICATION
;
706 BdsLoadOptionPxeUpdateDevicePath (
707 IN EFI_DEVICE_PATH
*OldDevicePath
,
709 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath
,
710 OUT ARM_BDS_LOADER_TYPE
*BootType
,
711 OUT UINT32
*Attributes
719 BdsLoadOptionPxeIsSupported (
720 IN EFI_DEVICE_PATH
*DevicePath
725 EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
;
726 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBcProtocol
;
728 Status
= BdsConnectDevicePath (DevicePath
, &Handle
, &RemainingDevicePath
);
729 if (EFI_ERROR(Status
)) {
733 if (!IsDevicePathEnd(RemainingDevicePath
)) {
737 Status
= gBS
->HandleProtocol (Handle
, &gEfiPxeBaseCodeProtocolGuid
, (VOID
**)&PxeBcProtocol
);
738 if (EFI_ERROR (Status
)) {
746 BdsLoadOptionTftpList (
747 IN OUT LIST_ENTRY
* BdsLoadOptionList
752 EFI_HANDLE
*HandleBuffer
;
754 BDS_SUPPORTED_DEVICE
*SupportedDevice
;
755 EFI_DEVICE_PATH_PROTOCOL
* DevicePathProtocol
;
756 EFI_SIMPLE_NETWORK_PROTOCOL
* SimpleNet
;
757 CHAR16 DeviceDescription
[BOOT_DEVICE_DESCRIPTION_MAX
];
758 EFI_MAC_ADDRESS
*Mac
;
760 // List all the PXE Protocols
761 Status
= gBS
->LocateHandleBuffer (ByProtocol
, &gEfiPxeBaseCodeProtocolGuid
, NULL
, &HandleCount
, &HandleBuffer
);
762 if (EFI_ERROR (Status
)) {
766 for (Index
= 0; Index
< HandleCount
; Index
++) {
767 // 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)
768 Status
= gBS
->HandleProtocol (HandleBuffer
[Index
], &gEfiDevicePathProtocolGuid
, (VOID
**)&DevicePathProtocol
);
769 if (!EFI_ERROR(Status
)) {
770 // Allocate BDS Supported Device structure
771 SupportedDevice
= (BDS_SUPPORTED_DEVICE
*)AllocatePool(sizeof(BDS_SUPPORTED_DEVICE
));
773 Status
= gBS
->LocateProtocol (&gEfiSimpleNetworkProtocolGuid
, NULL
, (VOID
**)&SimpleNet
);
774 if (!EFI_ERROR(Status
)) {
775 Mac
= &SimpleNet
->Mode
->CurrentAddress
;
776 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]);
778 Status
= GenerateDeviceDescriptionName (HandleBuffer
[Index
], DeviceDescription
);
779 ASSERT_EFI_ERROR (Status
);
781 UnicodeSPrint (SupportedDevice
->Description
,BOOT_DEVICE_DESCRIPTION_MAX
,L
"TFTP on %s",DeviceDescription
);
783 SupportedDevice
->DevicePathProtocol
= DevicePathProtocol
;
784 SupportedDevice
->Support
= &BdsLoadOptionSupportList
[BDS_DEVICE_TFTP
];
786 InsertTailList (BdsLoadOptionList
,&SupportedDevice
->Link
);
794 BdsLoadOptionTftpCreateDevicePath (
796 OUT EFI_DEVICE_PATH_PROTOCOL
**DevicePathNode
,
797 OUT ARM_BDS_LOADER_TYPE
*BootType
,
798 OUT UINT32
*Attributes
803 EFI_IP_ADDRESS LocalIp
;
804 EFI_IP_ADDRESS RemoteIp
;
805 IPv4_DEVICE_PATH
* IPv4DevicePathNode
;
806 FILEPATH_DEVICE_PATH
* FilePathDevicePath
;
807 CHAR16 BootFilePath
[BOOT_DEVICE_FILEPATH_MAX
];
808 UINTN BootFilePathSize
;
810 Print(L
"Get the IP address from DHCP: ");
811 Status
= GetHIInputBoolean (&IsDHCP
);
812 if (EFI_ERROR(Status
)) {
817 Print(L
"Get the static IP address: ");
818 Status
= GetHIInputIP (&LocalIp
);
819 if (EFI_ERROR(Status
)) {
824 Print(L
"Get the TFTP server IP address: ");
825 Status
= GetHIInputIP (&RemoteIp
);
826 if (EFI_ERROR(Status
)) {
830 Print(L
"File path of the %s : ", FileName
);
831 Status
= GetHIInputStr (BootFilePath
, BOOT_DEVICE_FILEPATH_MAX
);
832 if (EFI_ERROR(Status
)) {
836 BootFilePathSize
= StrSize(BootFilePath
);
837 if (BootFilePathSize
== 2) {
838 return EFI_NOT_FOUND
;
841 // Allocate the memory for the IPv4 + File Path Device Path Nodes
842 IPv4DevicePathNode
= (IPv4_DEVICE_PATH
*)AllocatePool(sizeof(IPv4_DEVICE_PATH
) + SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
844 // Create the IPv4 Device Path
845 IPv4DevicePathNode
->Header
.Type
= MESSAGING_DEVICE_PATH
;
846 IPv4DevicePathNode
->Header
.SubType
= MSG_IPv4_DP
;
847 SetDevicePathNodeLength (&IPv4DevicePathNode
->Header
, sizeof(IPv4_DEVICE_PATH
));
848 CopyMem (&IPv4DevicePathNode
->LocalIpAddress
, &LocalIp
.v4
, sizeof (EFI_IPv4_ADDRESS
));
849 CopyMem (&IPv4DevicePathNode
->RemoteIpAddress
, &RemoteIp
.v4
, sizeof (EFI_IPv4_ADDRESS
));
850 IPv4DevicePathNode
->LocalPort
= 0;
851 IPv4DevicePathNode
->RemotePort
= 0;
852 IPv4DevicePathNode
->Protocol
= EFI_IP_PROTO_TCP
;
853 IPv4DevicePathNode
->StaticIpAddress
= (IsDHCP
!= TRUE
);
855 // Create the FilePath Device Path node
856 FilePathDevicePath
= (FILEPATH_DEVICE_PATH
*)(IPv4DevicePathNode
+ 1);
857 FilePathDevicePath
->Header
.Type
= MEDIA_DEVICE_PATH
;
858 FilePathDevicePath
->Header
.SubType
= MEDIA_FILEPATH_DP
;
859 SetDevicePathNodeLength (FilePathDevicePath
, SIZE_OF_FILEPATH_DEVICE_PATH
+ BootFilePathSize
);
860 CopyMem (FilePathDevicePath
->PathName
, BootFilePath
, BootFilePathSize
);
862 if (BootType
!= NULL
|| Attributes
!= NULL
) {
863 Status
= BootDeviceGetType (NULL
, BootType
, Attributes
);
866 if (EFI_ERROR(Status
)) {
867 FreePool (IPv4DevicePathNode
);
869 *DevicePathNode
= (EFI_DEVICE_PATH_PROTOCOL
*)IPv4DevicePathNode
;
876 BdsLoadOptionTftpUpdateDevicePath (
877 IN EFI_DEVICE_PATH
*OldDevicePath
,
879 OUT EFI_DEVICE_PATH_PROTOCOL
**NewDevicePath
,
880 OUT ARM_BDS_LOADER_TYPE
*BootType
,
881 OUT UINT32
*Attributes
889 BdsLoadOptionTftpIsSupported (
890 IN EFI_DEVICE_PATH
*DevicePath
895 EFI_DEVICE_PATH
*RemainingDevicePath
;
896 EFI_DEVICE_PATH
*NextDevicePath
;
897 EFI_PXE_BASE_CODE_PROTOCOL
*PxeBcProtocol
;
899 Status
= BdsConnectDevicePath (DevicePath
, &Handle
, &RemainingDevicePath
);
900 if (EFI_ERROR(Status
)) {
904 // Validate the Remaining Device Path
905 if (IsDevicePathEnd(RemainingDevicePath
)) {
908 if (!IS_DEVICE_PATH_NODE(RemainingDevicePath
,MESSAGING_DEVICE_PATH
,MSG_IPv4_DP
) &&
909 !IS_DEVICE_PATH_NODE(RemainingDevicePath
,MESSAGING_DEVICE_PATH
,MSG_IPv6_DP
)) {
912 NextDevicePath
= NextDevicePathNode (RemainingDevicePath
);
913 if (IsDevicePathEnd(NextDevicePath
)) {
916 if (!IS_DEVICE_PATH_NODE(NextDevicePath
,MEDIA_DEVICE_PATH
,MEDIA_FILEPATH_DP
)) {
920 Status
= gBS
->HandleProtocol (Handle
, &gEfiPxeBaseCodeProtocolGuid
, (VOID
**)&PxeBcProtocol
);
921 if (EFI_ERROR (Status
)) {