3 * Copyright (c) 2011-2013, 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 <Guid/ArmGlobalVariableHob.h>
19 extern EFI_HANDLE mImageHandle
;
20 extern BDS_LOAD_OPTION_SUPPORT
*BdsLoadOptionSupportList
;
25 OUT BDS_SUPPORTED_DEVICE
** SupportedBootDevice
29 LIST_ENTRY SupportedDeviceList
;
30 UINTN SupportedDeviceCount
;
32 UINTN SupportedDeviceSelected
;
36 // List the Boot Devices supported
39 // Start all the drivers first
40 BdsConnectAllDrivers ();
42 // List the supported devices
43 Status
= BootDeviceListSupportedInit (&SupportedDeviceList
);
44 ASSERT_EFI_ERROR(Status
);
46 SupportedDeviceCount
= 0;
47 for (Entry
= GetFirstNode (&SupportedDeviceList
);
48 !IsNull (&SupportedDeviceList
,Entry
);
49 Entry
= GetNextNode (&SupportedDeviceList
,Entry
)
52 *SupportedBootDevice
= SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry
);
53 Print(L
"[%d] %s\n",SupportedDeviceCount
+1,(*SupportedBootDevice
)->Description
);
56 CHAR16
* DevicePathTxt
;
57 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
* DevicePathToTextProtocol
;
59 Status
= gBS
->LocateProtocol (&gEfiDevicePathToTextProtocolGuid
, NULL
, (VOID
**)&DevicePathToTextProtocol
);
60 ASSERT_EFI_ERROR(Status
);
61 DevicePathTxt
= DevicePathToTextProtocol
->ConvertDevicePathToText ((*SupportedBootDevice
)->DevicePathProtocol
,TRUE
,TRUE
);
63 Print(L
"\t- %s\n",DevicePathTxt
);
65 FreePool(DevicePathTxt
);
68 SupportedDeviceCount
++;
71 if (SupportedDeviceCount
== 0) {
72 Print(L
"There is no supported device.\n");
78 // Select the Boot Device
80 SupportedDeviceSelected
= 0;
81 while (SupportedDeviceSelected
== 0) {
82 Print(L
"Select the Boot Device: ");
83 Status
= GetHIInputInteger (&SupportedDeviceSelected
);
84 if (EFI_ERROR(Status
)) {
87 } else if ((SupportedDeviceSelected
== 0) || (SupportedDeviceSelected
> SupportedDeviceCount
)) {
88 Print(L
"Invalid input (max %d)\n",SupportedDeviceCount
);
89 SupportedDeviceSelected
= 0;
94 // Get the Device Path for the selected boot device
97 for (Entry
= GetFirstNode (&SupportedDeviceList
);
98 !IsNull (&SupportedDeviceList
,Entry
);
99 Entry
= GetNextNode (&SupportedDeviceList
,Entry
)
102 if (Index
== SupportedDeviceSelected
) {
103 *SupportedBootDevice
= SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry
);
110 BootDeviceListSupportedFree (&SupportedDeviceList
, *SupportedBootDevice
);
115 BootMenuAddBootOption (
116 IN LIST_ENTRY
*BootOptionsList
120 BDS_SUPPORTED_DEVICE
* SupportedBootDevice
;
121 ARM_BDS_LOADER_ARGUMENTS
* BootArguments
;
122 CHAR16 BootDescription
[BOOT_DEVICE_DESCRIPTION_MAX
];
123 CHAR8 CmdLine
[BOOT_DEVICE_OPTION_MAX
];
125 ARM_BDS_LOADER_TYPE BootType
;
126 BDS_LOAD_OPTION_ENTRY
*BdsLoadOptionEntry
;
127 EFI_DEVICE_PATH
*DevicePath
;
128 EFI_DEVICE_PATH_PROTOCOL
*DevicePathNode
;
129 EFI_DEVICE_PATH_PROTOCOL
*InitrdPathNode
;
130 EFI_DEVICE_PATH_PROTOCOL
*InitrdPath
;
132 BOOLEAN InitrdSupport
;
136 SupportedBootDevice
= NULL
;
138 // List the Boot Devices supported
139 Status
= SelectBootDevice (&SupportedBootDevice
);
140 if (EFI_ERROR(Status
)) {
141 Status
= EFI_ABORTED
;
145 // Create the specific device path node
146 Status
= SupportedBootDevice
->Support
->CreateDevicePathNode (L
"EFI Application or the kernel", &DevicePathNode
, &BootType
, &Attributes
);
147 if (EFI_ERROR(Status
)) {
148 Status
= EFI_ABORTED
;
151 // Append the Device Path node to the select device path
152 DevicePath
= AppendDevicePathNode (SupportedBootDevice
->DevicePathProtocol
, (CONST EFI_DEVICE_PATH_PROTOCOL
*)DevicePathNode
);
154 if ((BootType
== BDS_LOADER_KERNEL_LINUX_ATAG
) || (BootType
== BDS_LOADER_KERNEL_LINUX_FDT
)) {
155 Print(L
"Add an initrd: ");
156 Status
= GetHIInputBoolean (&InitrdSupport
);
157 if (EFI_ERROR(Status
)) {
158 Status
= EFI_ABORTED
;
163 // Create the specific device path node
164 Status
= SupportedBootDevice
->Support
->CreateDevicePathNode (L
"initrd", &InitrdPathNode
, NULL
, NULL
);
165 if (EFI_ERROR(Status
) && Status
!= EFI_NOT_FOUND
) { // EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd
166 Status
= EFI_ABORTED
;
170 if (InitrdPathNode
!= NULL
) {
171 // Append the Device Path node to the select device path
172 InitrdPath
= AppendDevicePathNode (SupportedBootDevice
->DevicePathProtocol
, (CONST EFI_DEVICE_PATH_PROTOCOL
*)InitrdPathNode
);
180 Print(L
"Arguments to pass to the binary: ");
181 Status
= GetHIInputAscii (CmdLine
,BOOT_DEVICE_OPTION_MAX
);
182 if (EFI_ERROR(Status
)) {
183 Status
= EFI_ABORTED
;
184 goto FREE_DEVICE_PATH
;
187 CmdLineSize
= AsciiStrSize (CmdLine
);
188 InitrdSize
= GetDevicePathSize (InitrdPath
);
190 BootArguments
= (ARM_BDS_LOADER_ARGUMENTS
*)AllocatePool (sizeof(ARM_BDS_LOADER_ARGUMENTS
) + CmdLineSize
+ InitrdSize
);
192 BootArguments
->LinuxArguments
.CmdLineSize
= CmdLineSize
;
193 BootArguments
->LinuxArguments
.InitrdSize
= InitrdSize
;
194 CopyMem ((VOID
*)(&BootArguments
->LinuxArguments
+ 1), CmdLine
, CmdLineSize
);
195 CopyMem ((VOID
*)((UINTN
)(&BootArguments
->LinuxArguments
+ 1) + CmdLineSize
), InitrdPath
, InitrdSize
);
197 BootArguments
= NULL
;
200 Print(L
"Description for this new Entry: ");
201 Status
= GetHIInputStr (BootDescription
, BOOT_DEVICE_DESCRIPTION_MAX
);
202 if (EFI_ERROR(Status
)) {
203 Status
= EFI_ABORTED
;
204 goto FREE_DEVICE_PATH
;
208 BdsLoadOptionEntry
= (BDS_LOAD_OPTION_ENTRY
*)AllocatePool (sizeof(BDS_LOAD_OPTION_ENTRY
));
209 Status
= BootOptionCreate (Attributes
, BootDescription
, DevicePath
, BootType
, BootArguments
, &BdsLoadOptionEntry
->BdsLoadOption
);
210 if (!EFI_ERROR(Status
)) {
211 InsertTailList (BootOptionsList
, &BdsLoadOptionEntry
->Link
);
215 FreePool (DevicePath
);
219 if (Status
== EFI_ABORTED
) {
222 FreePool(SupportedBootDevice
);
228 BootMenuSelectBootOption (
229 IN LIST_ENTRY
* BootOptionsList
,
230 IN CONST CHAR16
* InputStatement
,
231 IN BOOLEAN OnlyArmBdsBootEntry
,
232 OUT BDS_LOAD_OPTION_ENTRY
** BdsLoadOptionEntry
237 BDS_LOAD_OPTION
* BdsLoadOption
;
238 UINTN BootOptionSelected
;
239 UINTN BootOptionCount
;
242 // Display the list of supported boot devices
244 for (Entry
= GetFirstNode (BootOptionsList
);
245 !IsNull (BootOptionsList
,Entry
);
246 Entry
= GetNextNode (BootOptionsList
, Entry
)
249 BdsLoadOption
= LOAD_OPTION_FROM_LINK(Entry
);
251 if (OnlyArmBdsBootEntry
&& !IS_ARM_BDS_BOOTENTRY (BdsLoadOption
)) {
255 Print (L
"[%d] %s\n", (BootOptionCount
+ 1), BdsLoadOption
->Description
);
258 CHAR16
* DevicePathTxt
;
259 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
* DevicePathToTextProtocol
;
260 ARM_BDS_LOADER_TYPE LoaderType
;
261 ARM_BDS_LOADER_OPTIONAL_DATA
* OptionalData
;
263 Status
= gBS
->LocateProtocol(&gEfiDevicePathToTextProtocolGuid
, NULL
, (VOID
**)&DevicePathToTextProtocol
);
264 ASSERT_EFI_ERROR(Status
);
265 DevicePathTxt
= DevicePathToTextProtocol
->ConvertDevicePathToText(BdsLoadOption
->FilePathList
,TRUE
,TRUE
);
267 Print(L
"\t- %s\n",DevicePathTxt
);
268 OptionalData
= BdsLoadOption
->OptionalData
;
269 LoaderType
= (ARM_BDS_LOADER_TYPE
)ReadUnaligned32 ((CONST UINT32
*)&OptionalData
->Header
.LoaderType
);
270 if ((LoaderType
== BDS_LOADER_KERNEL_LINUX_ATAG
) || (LoaderType
== BDS_LOADER_KERNEL_LINUX_FDT
)) {
271 Print (L
"\t- Arguments: %a\n",&OptionalData
->Arguments
.LinuxArguments
+ 1);
274 FreePool(DevicePathTxt
);
280 // Check if a valid boot option(s) is found
281 if (BootOptionCount
== 0) {
282 if (StrCmp (InputStatement
, DELETE_BOOT_ENTRY
) == 0) {
283 Print (L
"Nothing to remove!\n");
284 }else if (StrCmp (InputStatement
, UPDATE_BOOT_ENTRY
) == 0) {
285 Print (L
"Couldn't find valid boot entries\n");
287 Print (L
"No supported Boot Entry.\n");
290 return EFI_NOT_FOUND
;
293 // Get the index of the boot device to delete
294 BootOptionSelected
= 0;
295 while (BootOptionSelected
== 0) {
296 Print(InputStatement
);
297 Status
= GetHIInputInteger (&BootOptionSelected
);
298 if (EFI_ERROR(Status
)) {
300 } else if ((BootOptionSelected
== 0) || (BootOptionSelected
> BootOptionCount
)) {
301 Print(L
"Invalid input (max %d)\n",BootOptionCount
);
302 BootOptionSelected
= 0;
306 // Get the structure of the Boot device to delete
308 for (Entry
= GetFirstNode (BootOptionsList
);
309 !IsNull (BootOptionsList
, Entry
);
310 Entry
= GetNextNode (BootOptionsList
,Entry
)
313 if (Index
== BootOptionSelected
) {
314 *BdsLoadOptionEntry
= LOAD_OPTION_ENTRY_FROM_LINK(Entry
);
324 BootMenuRemoveBootOption (
325 IN LIST_ENTRY
*BootOptionsList
329 BDS_LOAD_OPTION_ENTRY
* BootOptionEntry
;
331 Status
= BootMenuSelectBootOption (BootOptionsList
, DELETE_BOOT_ENTRY
, FALSE
, &BootOptionEntry
);
332 if (EFI_ERROR(Status
)) {
336 // If the Boot Option was attached to a list remove it
337 if (!IsListEmpty (&BootOptionEntry
->Link
)) {
338 // Remove the entry from the list
339 RemoveEntryList (&BootOptionEntry
->Link
);
342 // Delete the BDS Load option structures
343 BootOptionDelete (BootOptionEntry
->BdsLoadOption
);
349 BootMenuUpdateBootOption (
350 IN LIST_ENTRY
*BootOptionsList
354 BDS_LOAD_OPTION_ENTRY
*BootOptionEntry
;
355 BDS_LOAD_OPTION
*BootOption
;
356 BDS_LOAD_OPTION_SUPPORT
* DeviceSupport
;
357 ARM_BDS_LOADER_ARGUMENTS
* BootArguments
;
358 CHAR16 BootDescription
[BOOT_DEVICE_DESCRIPTION_MAX
];
359 CHAR8 CmdLine
[BOOT_DEVICE_OPTION_MAX
];
360 EFI_DEVICE_PATH
*DevicePath
;
361 EFI_DEVICE_PATH
*TempInitrdPath
;
362 ARM_BDS_LOADER_TYPE BootType
;
363 ARM_BDS_LOADER_OPTIONAL_DATA
* OptionalData
;
364 ARM_BDS_LINUX_ARGUMENTS
* LinuxArguments
;
365 EFI_DEVICE_PATH
*InitrdPathNode
;
366 EFI_DEVICE_PATH
*InitrdPath
;
369 BOOLEAN InitrdSupport
;
371 Status
= BootMenuSelectBootOption (BootOptionsList
, UPDATE_BOOT_ENTRY
, TRUE
, &BootOptionEntry
);
372 if (EFI_ERROR(Status
)) {
375 BootOption
= BootOptionEntry
->BdsLoadOption
;
377 // Get the device support for this Boot Option
378 Status
= BootDeviceGetDeviceSupport (BootOption
->FilePathList
, &DeviceSupport
);
379 if (EFI_ERROR(Status
)) {
380 Print(L
"Not possible to retrieve the supported device for the update\n");
381 return EFI_UNSUPPORTED
;
384 Status
= DeviceSupport
->UpdateDevicePathNode (BootOption
->FilePathList
, L
"EFI Application or the kernel", &DevicePath
, NULL
, NULL
);
385 if (EFI_ERROR(Status
)) {
386 Status
= EFI_ABORTED
;
390 OptionalData
= BootOption
->OptionalData
;
391 BootType
= (ARM_BDS_LOADER_TYPE
)ReadUnaligned32 ((UINT32
*)(&OptionalData
->Header
.LoaderType
));
393 if ((BootType
== BDS_LOADER_KERNEL_LINUX_ATAG
) || (BootType
== BDS_LOADER_KERNEL_LINUX_FDT
)) {
394 LinuxArguments
= &OptionalData
->Arguments
.LinuxArguments
;
396 CmdLineSize
= ReadUnaligned16 ((CONST UINT16
*)&LinuxArguments
->CmdLineSize
);
398 InitrdSize
= ReadUnaligned16 ((CONST UINT16
*)&LinuxArguments
->InitrdSize
);
399 if (InitrdSize
> 0) {
400 Print(L
"Keep the initrd: ");
402 Print(L
"Add an initrd: ");
404 Status
= GetHIInputBoolean (&InitrdSupport
);
405 if (EFI_ERROR(Status
)) {
406 Status
= EFI_ABORTED
;
411 if (InitrdSize
> 0) {
412 // Case we update the initrd device path
413 Status
= DeviceSupport
->UpdateDevicePathNode ((EFI_DEVICE_PATH
*)((UINTN
)(LinuxArguments
+ 1) + CmdLineSize
), L
"initrd", &InitrdPath
, NULL
, NULL
);
414 if (EFI_ERROR(Status
) && Status
!= EFI_NOT_FOUND
) {// EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd
415 Status
= EFI_ABORTED
;
418 InitrdSize
= GetDevicePathSize (InitrdPath
);
420 // Case we create the initrd device path
422 Status
= DeviceSupport
->CreateDevicePathNode (L
"initrd", &InitrdPathNode
, NULL
, NULL
);
423 if (EFI_ERROR(Status
) && Status
!= EFI_NOT_FOUND
) { // EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd
424 Status
= EFI_ABORTED
;
428 if (InitrdPathNode
!= NULL
) {
429 // Duplicate Linux kernel Device Path
430 TempInitrdPath
= DuplicateDevicePath (BootOption
->FilePathList
);
431 // Replace Linux kernel Node by EndNode
432 SetDevicePathEndNode (GetLastDevicePathNode (TempInitrdPath
));
433 // Append the Device Path node to the select device path
434 InitrdPath
= AppendDevicePathNode (TempInitrdPath
, (CONST EFI_DEVICE_PATH_PROTOCOL
*)InitrdPathNode
);
435 FreePool (TempInitrdPath
);
436 InitrdSize
= GetDevicePathSize (InitrdPath
);
445 Print(L
"Arguments to pass to the binary: ");
446 if (CmdLineSize
> 0) {
447 AsciiStrnCpy(CmdLine
, (CONST CHAR8
*)(LinuxArguments
+ 1), CmdLineSize
);
451 Status
= EditHIInputAscii (CmdLine
, BOOT_DEVICE_OPTION_MAX
);
452 if (EFI_ERROR(Status
)) {
453 Status
= EFI_ABORTED
;
454 goto FREE_DEVICE_PATH
;
457 CmdLineSize
= AsciiStrSize (CmdLine
);
459 BootArguments
= (ARM_BDS_LOADER_ARGUMENTS
*)AllocatePool(sizeof(ARM_BDS_LOADER_ARGUMENTS
) + CmdLineSize
+ InitrdSize
);
460 BootArguments
->LinuxArguments
.CmdLineSize
= CmdLineSize
;
461 BootArguments
->LinuxArguments
.InitrdSize
= InitrdSize
;
462 CopyMem (&BootArguments
->LinuxArguments
+ 1, CmdLine
, CmdLineSize
);
463 CopyMem ((VOID
*)((UINTN
)(&BootArguments
->LinuxArguments
+ 1) + CmdLineSize
), InitrdPath
, InitrdSize
);
465 BootArguments
= NULL
;
468 Print(L
"Description for this new Entry: ");
469 StrnCpy (BootDescription
, BootOption
->Description
, BOOT_DEVICE_DESCRIPTION_MAX
);
470 Status
= EditHIInputStr (BootDescription
, BOOT_DEVICE_DESCRIPTION_MAX
);
471 if (EFI_ERROR(Status
)) {
472 Status
= EFI_ABORTED
;
473 goto FREE_DEVICE_PATH
;
477 Status
= BootOptionUpdate (BootOption
, BootOption
->Attributes
, BootDescription
, DevicePath
, BootType
, BootArguments
);
480 FreePool (DevicePath
);
483 if (Status
== EFI_ABORTED
) {
491 IN LIST_ENTRY
*BootOptionsList
495 UINTN FdtDevicePathSize
;
496 BDS_SUPPORTED_DEVICE
*SupportedBootDevice
;
497 EFI_DEVICE_PATH_PROTOCOL
*FdtDevicePathNode
;
498 EFI_DEVICE_PATH_PROTOCOL
*FdtDevicePath
;
500 Status
= SelectBootDevice (&SupportedBootDevice
);
501 if (EFI_ERROR(Status
)) {
502 Status
= EFI_ABORTED
;
506 // Create the specific device path node
507 Status
= SupportedBootDevice
->Support
->CreateDevicePathNode (L
"FDT blob", &FdtDevicePathNode
, NULL
, NULL
);
508 if (EFI_ERROR(Status
)) {
509 Status
= EFI_ABORTED
;
513 if (FdtDevicePathNode
!= NULL
) {
514 // Append the Device Path node to the select device path
515 FdtDevicePath
= AppendDevicePathNode (SupportedBootDevice
->DevicePathProtocol
, FdtDevicePathNode
);
516 FdtDevicePathSize
= GetDevicePathSize (FdtDevicePath
);
517 Status
= gRT
->SetVariable (
519 &gArmGlobalVariableGuid
,
520 EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
524 ASSERT_EFI_ERROR(Status
);
528 &gArmGlobalVariableGuid
,
529 EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
533 ASSERT_EFI_ERROR(Status
);
537 if (Status
== EFI_ABORTED
) {
540 FreePool(SupportedBootDevice
);
544 struct BOOT_MANAGER_ENTRY
{
545 CONST CHAR16
* Description
;
546 EFI_STATUS (*Callback
) (IN LIST_ENTRY
*BootOptionsList
);
547 } BootManagerEntries
[] = {
548 { L
"Add Boot Device Entry", BootMenuAddBootOption
},
549 { L
"Update Boot Device Entry", BootMenuUpdateBootOption
},
550 { L
"Remove Boot Device Entry", BootMenuRemoveBootOption
},
551 { L
"Update FDT path", UpdateFdtPath
},
556 IN LIST_ENTRY
*BootOptionsList
560 UINTN OptionSelected
;
561 UINTN BootManagerEntryCount
;
564 BootManagerEntryCount
= sizeof(BootManagerEntries
) / sizeof(struct BOOT_MANAGER_ENTRY
);
567 // Display Boot Manager menu
568 for (Index
= 0; Index
< BootManagerEntryCount
; Index
++) {
569 Print(L
"[%d] %s\n",Index
+1,BootManagerEntries
[Index
]);
571 Print(L
"[%d] Return to main menu\n",Index
+1);
573 // Select which entry to call
575 Status
= GetHIInputInteger (&OptionSelected
);
576 if (EFI_ERROR(Status
) || (OptionSelected
== (BootManagerEntryCount
+1))) {
577 if (EFI_ERROR(Status
)) {
581 } else if ((OptionSelected
> 0) && (OptionSelected
<= BootManagerEntryCount
)) {
582 BootManagerEntries
[OptionSelected
-1].Callback (BootOptionsList
);
585 // Should never go here
590 IN LIST_ENTRY
*BootOptionsList
596 Status
= BdsLoadApplication (mImageHandle
, L
"Shell", 0, NULL
);
597 if (Status
== EFI_NOT_FOUND
) {
598 Print (L
"Error: EFI Application not found.\n");
599 } else if (EFI_ERROR(Status
)) {
600 Print (L
"Error: Status Code: 0x%X\n",(UINT32
)Status
);
606 struct BOOT_MAIN_ENTRY
{
607 CONST CHAR16
* Description
;
608 EFI_STATUS (*Callback
) (IN LIST_ENTRY
*BootOptionsList
);
609 } BootMainEntries
[] = {
610 { L
"Shell", BootShell
},
611 { L
"Boot Manager", BootMenuManager
},
620 LIST_ENTRY BootOptionsList
;
622 UINTN BootOptionCount
;
625 BDS_LOAD_OPTION
* BootOption
;
626 UINTN BootOptionSelected
;
628 UINTN BootMainEntryCount
;
631 BootMainEntryCount
= sizeof(BootMainEntries
) / sizeof(struct BOOT_MAIN_ENTRY
);
635 BootOptionList (&BootOptionsList
);
639 // Display the Boot options
640 for (Entry
= GetFirstNode (&BootOptionsList
);
641 !IsNull (&BootOptionsList
,Entry
);
642 Entry
= GetNextNode (&BootOptionsList
,Entry
)
645 BootOption
= LOAD_OPTION_FROM_LINK(Entry
);
647 Print(L
"[%d] %s\n", OptionCount
, BootOption
->Description
);
650 CHAR16
* DevicePathTxt
;
651 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
* DevicePathToTextProtocol
;
652 ARM_BDS_LOADER_OPTIONAL_DATA
* OptionalData
;
654 ARM_BDS_LOADER_TYPE LoaderType
;
656 Status
= gBS
->LocateProtocol (&gEfiDevicePathToTextProtocolGuid
, NULL
, (VOID
**)&DevicePathToTextProtocol
);
657 if (EFI_ERROR(Status
)) {
658 // You must provide an implementation of DevicePathToTextProtocol in your firmware (eg: DevicePathDxe)
659 DEBUG((EFI_D_ERROR
,"Error: Bds requires DevicePathToTextProtocol\n"));
662 DevicePathTxt
= DevicePathToTextProtocol
->ConvertDevicePathToText (BootOption
->FilePathList
, TRUE
, TRUE
);
664 Print(L
"\t- %s\n",DevicePathTxt
);
666 // If it is a supported BootEntry then print its details
667 if (IS_ARM_BDS_BOOTENTRY (BootOption
)) {
668 OptionalData
= BootOption
->OptionalData
;
669 LoaderType
= (ARM_BDS_LOADER_TYPE
)ReadUnaligned32 ((CONST UINT32
*)&OptionalData
->Header
.LoaderType
);
670 if ((LoaderType
== BDS_LOADER_KERNEL_LINUX_ATAG
) || (LoaderType
== BDS_LOADER_KERNEL_LINUX_FDT
)) {
671 if (ReadUnaligned16 (&OptionalData
->Arguments
.LinuxArguments
.InitrdSize
) > 0) {
672 CmdLineSize
= ReadUnaligned16 (&OptionalData
->Arguments
.LinuxArguments
.CmdLineSize
);
673 DevicePathTxt
= DevicePathToTextProtocol
->ConvertDevicePathToText (
674 GetAlignedDevicePath ((EFI_DEVICE_PATH
*)((UINTN
)(&OptionalData
->Arguments
.LinuxArguments
+ 1) + CmdLineSize
)), TRUE
, TRUE
);
675 Print(L
"\t- Initrd: %s\n", DevicePathTxt
);
677 Print(L
"\t- Arguments: %a\n", (&OptionalData
->Arguments
.LinuxArguments
+ 1));
679 Print(L
"\t- LoaderType: %d\n", LoaderType
);
681 FreePool(DevicePathTxt
);
686 BootOptionCount
= OptionCount
-1;
688 // Display the hardcoded Boot entries
689 for (Index
= 0; Index
< BootMainEntryCount
; Index
++) {
690 Print(L
"[%d] %s\n",OptionCount
,BootMainEntries
[Index
]);
694 // Request the boot entry from the user
695 BootOptionSelected
= 0;
696 while (BootOptionSelected
== 0) {
698 Status
= GetHIInputInteger (&BootOptionSelected
);
699 if (EFI_ERROR(Status
) || (BootOptionSelected
== 0) || (BootOptionSelected
> OptionCount
)) {
700 Print(L
"Invalid input (max %d)\n",(OptionCount
-1));
701 BootOptionSelected
= 0;
705 // Start the selected entry
706 if (BootOptionSelected
> BootOptionCount
) {
707 // Start the hardcoded entry
708 Status
= BootMainEntries
[BootOptionSelected
- BootOptionCount
- 1].Callback (&BootOptionsList
);
710 // Find the selected entry from the Boot#### list
712 for (Entry
= GetFirstNode (&BootOptionsList
);
713 !IsNull (&BootOptionsList
,Entry
);
714 Entry
= GetNextNode (&BootOptionsList
,Entry
)
717 if (Index
== BootOptionSelected
) {
718 BootOption
= LOAD_OPTION_FROM_LINK(Entry
);
724 Status
= BootOptionStart (BootOption
);
727 // Should never go here