3 * Copyright (c) 2011 - 2014, 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 AsciiCmdLine
[BOOT_DEVICE_OPTION_MAX
];
124 CHAR16 CmdLine
[BOOT_DEVICE_OPTION_MAX
];
126 ARM_BDS_LOADER_TYPE BootType
;
127 BDS_LOAD_OPTION_ENTRY
*BdsLoadOptionEntry
;
128 EFI_DEVICE_PATH
*DevicePath
;
129 EFI_DEVICE_PATH_PROTOCOL
*DevicePathNodes
;
130 EFI_DEVICE_PATH_PROTOCOL
*InitrdPathNodes
;
131 EFI_DEVICE_PATH_PROTOCOL
*InitrdPath
;
133 BOOLEAN InitrdSupport
;
136 UINTN OptionalDataSize
;
139 SupportedBootDevice
= NULL
;
141 // List the Boot Devices supported
142 Status
= SelectBootDevice (&SupportedBootDevice
);
143 if (EFI_ERROR(Status
)) {
144 Status
= EFI_ABORTED
;
148 // Create the specific device path node
149 Status
= SupportedBootDevice
->Support
->CreateDevicePathNode (L
"EFI Application or the kernel", &DevicePathNodes
);
150 if (EFI_ERROR(Status
)) {
151 Status
= EFI_ABORTED
;
154 // Append the Device Path to the selected device path
155 DevicePath
= AppendDevicePath (SupportedBootDevice
->DevicePathProtocol
, (CONST EFI_DEVICE_PATH_PROTOCOL
*)DevicePathNodes
);
156 if (DevicePath
== NULL
) {
157 Status
= EFI_OUT_OF_RESOURCES
;
161 if (SupportedBootDevice
->Support
->RequestBootType
) {
162 Status
= BootDeviceGetType (DevicePath
, &BootType
, &Attributes
);
163 if (EFI_ERROR(Status
)) {
164 Status
= EFI_ABORTED
;
168 BootType
= BDS_LOADER_EFI_APPLICATION
;
171 if ((BootType
== BDS_LOADER_KERNEL_LINUX_ATAG
) || (BootType
== BDS_LOADER_KERNEL_LINUX_FDT
)) {
172 Print(L
"Add an initrd: ");
173 Status
= GetHIInputBoolean (&InitrdSupport
);
174 if (EFI_ERROR(Status
)) {
175 Status
= EFI_ABORTED
;
180 // Create the specific device path node
181 Status
= SupportedBootDevice
->Support
->CreateDevicePathNode (L
"initrd", &InitrdPathNodes
);
182 if (EFI_ERROR(Status
) && Status
!= EFI_NOT_FOUND
) { // EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd
183 Status
= EFI_ABORTED
;
187 if (InitrdPathNodes
!= NULL
) {
188 // Append the Device Path to the selected device path
189 InitrdPath
= AppendDevicePath (SupportedBootDevice
->DevicePathProtocol
, (CONST EFI_DEVICE_PATH_PROTOCOL
*)InitrdPathNodes
);
190 if (InitrdPath
== NULL
) {
191 Status
= EFI_OUT_OF_RESOURCES
;
201 Print(L
"Arguments to pass to the binary: ");
202 Status
= GetHIInputAscii (AsciiCmdLine
, BOOT_DEVICE_OPTION_MAX
);
203 if (EFI_ERROR(Status
)) {
204 Status
= EFI_ABORTED
;
205 goto FREE_DEVICE_PATH
;
208 CmdLineSize
= AsciiStrSize (AsciiCmdLine
);
209 InitrdSize
= GetDevicePathSize (InitrdPath
);
211 OptionalDataSize
= sizeof(ARM_BDS_LOADER_ARGUMENTS
) + CmdLineSize
+ InitrdSize
;
212 BootArguments
= (ARM_BDS_LOADER_ARGUMENTS
*)AllocatePool (OptionalDataSize
);
214 BootArguments
->LinuxArguments
.CmdLineSize
= CmdLineSize
;
215 BootArguments
->LinuxArguments
.InitrdSize
= InitrdSize
;
216 CopyMem ((VOID
*)(&BootArguments
->LinuxArguments
+ 1), AsciiCmdLine
, CmdLineSize
);
217 CopyMem ((VOID
*)((UINTN
)(&BootArguments
->LinuxArguments
+ 1) + CmdLineSize
), InitrdPath
, InitrdSize
);
219 OptionalData
= (UINT8
*)BootArguments
;
221 Print (L
"Arguments to pass to the EFI Application: ");
222 Status
= GetHIInputStr (CmdLine
, BOOT_DEVICE_OPTION_MAX
);
223 if (EFI_ERROR (Status
)) {
224 Status
= EFI_ABORTED
;
228 OptionalData
= (UINT8
*)CmdLine
;
229 OptionalDataSize
= StrSize (CmdLine
);
232 Print(L
"Description for this new Entry: ");
233 Status
= GetHIInputStr (BootDescription
, BOOT_DEVICE_DESCRIPTION_MAX
);
234 if (EFI_ERROR(Status
)) {
235 Status
= EFI_ABORTED
;
236 goto FREE_DEVICE_PATH
;
240 BdsLoadOptionEntry
= (BDS_LOAD_OPTION_ENTRY
*)AllocatePool (sizeof(BDS_LOAD_OPTION_ENTRY
));
241 Status
= BootOptionCreate (Attributes
, BootDescription
, DevicePath
, BootType
, OptionalData
, OptionalDataSize
, &BdsLoadOptionEntry
->BdsLoadOption
);
242 if (!EFI_ERROR(Status
)) {
243 InsertTailList (BootOptionsList
, &BdsLoadOptionEntry
->Link
);
247 FreePool (DevicePath
);
250 if (Status
== EFI_ABORTED
) {
253 FreePool(SupportedBootDevice
);
259 BootMenuSelectBootOption (
260 IN LIST_ENTRY
* BootOptionsList
,
261 IN CONST CHAR16
* InputStatement
,
262 OUT BDS_LOAD_OPTION_ENTRY
** BdsLoadOptionEntry
267 BDS_LOAD_OPTION
* BdsLoadOption
;
268 UINTN BootOptionSelected
;
269 UINTN BootOptionCount
;
273 // Display the list of supported boot devices
275 for (Entry
= GetFirstNode (BootOptionsList
);
276 !IsNull (BootOptionsList
,Entry
);
277 Entry
= GetNextNode (BootOptionsList
, Entry
)
280 BdsLoadOption
= LOAD_OPTION_FROM_LINK(Entry
);
282 Print (L
"[%d] %s\n", (BootOptionCount
+ 1), BdsLoadOption
->Description
);
285 CHAR16
* DevicePathTxt
;
286 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
* DevicePathToTextProtocol
;
287 ARM_BDS_LOADER_TYPE LoaderType
;
288 ARM_BDS_LOADER_OPTIONAL_DATA
* OptionalData
;
290 Status
= gBS
->LocateProtocol(&gEfiDevicePathToTextProtocolGuid
, NULL
, (VOID
**)&DevicePathToTextProtocol
);
291 ASSERT_EFI_ERROR(Status
);
292 DevicePathTxt
= DevicePathToTextProtocol
->ConvertDevicePathToText(BdsLoadOption
->FilePathList
,TRUE
,TRUE
);
294 Print(L
"\t- %s\n",DevicePathTxt
);
295 OptionalData
= BdsLoadOption
->OptionalData
;
296 if (IS_ARM_BDS_BOOTENTRY (BdsLoadOption
)) {
297 LoaderType
= (ARM_BDS_LOADER_TYPE
)ReadUnaligned32 ((CONST UINT32
*)&OptionalData
->Header
.LoaderType
);
298 if ((LoaderType
== BDS_LOADER_KERNEL_LINUX_ATAG
) || (LoaderType
== BDS_LOADER_KERNEL_LINUX_FDT
)) {
299 Print (L
"\t- Arguments: %a\n",&OptionalData
->Arguments
.LinuxArguments
+ 1);
301 } else if (OptionalData
!= NULL
) {
302 if (IsPrintableString (OptionalData
, &IsUnicode
)) {
304 Print (L
"\t- Arguments: %s\n", OptionalData
);
306 AsciiPrint ("\t- Arguments: %a\n", OptionalData
);
311 FreePool(DevicePathTxt
);
317 // Check if a valid boot option(s) is found
318 if (BootOptionCount
== 0) {
319 if (StrCmp (InputStatement
, DELETE_BOOT_ENTRY
) == 0) {
320 Print (L
"Nothing to remove!\n");
321 } else if (StrCmp (InputStatement
, UPDATE_BOOT_ENTRY
) == 0) {
322 Print (L
"Couldn't find valid boot entries\n");
324 Print (L
"No supported Boot Entry.\n");
327 return EFI_NOT_FOUND
;
330 // Get the index of the boot device to delete
331 BootOptionSelected
= 0;
332 while (BootOptionSelected
== 0) {
333 Print(InputStatement
);
334 Status
= GetHIInputInteger (&BootOptionSelected
);
335 if (EFI_ERROR(Status
)) {
337 } else if ((BootOptionSelected
== 0) || (BootOptionSelected
> BootOptionCount
)) {
338 Print(L
"Invalid input (max %d)\n",BootOptionCount
);
339 BootOptionSelected
= 0;
343 // Get the structure of the Boot device to delete
345 for (Entry
= GetFirstNode (BootOptionsList
);
346 !IsNull (BootOptionsList
, Entry
);
347 Entry
= GetNextNode (BootOptionsList
,Entry
)
350 if (Index
== BootOptionSelected
) {
351 *BdsLoadOptionEntry
= LOAD_OPTION_ENTRY_FROM_LINK(Entry
);
361 BootMenuRemoveBootOption (
362 IN LIST_ENTRY
*BootOptionsList
366 BDS_LOAD_OPTION_ENTRY
* BootOptionEntry
;
368 Status
= BootMenuSelectBootOption (BootOptionsList
, DELETE_BOOT_ENTRY
, &BootOptionEntry
);
369 if (EFI_ERROR(Status
)) {
373 // If the Boot Option was attached to a list remove it
374 if (!IsListEmpty (&BootOptionEntry
->Link
)) {
375 // Remove the entry from the list
376 RemoveEntryList (&BootOptionEntry
->Link
);
379 // Delete the BDS Load option structures
380 BootOptionDelete (BootOptionEntry
->BdsLoadOption
);
386 BootMenuUpdateBootOption (
387 IN LIST_ENTRY
*BootOptionsList
391 BDS_LOAD_OPTION_ENTRY
*BootOptionEntry
;
392 BDS_LOAD_OPTION
*BootOption
;
393 BDS_LOAD_OPTION_SUPPORT
* DeviceSupport
;
394 ARM_BDS_LOADER_ARGUMENTS
* BootArguments
;
395 CHAR16 BootDescription
[BOOT_DEVICE_DESCRIPTION_MAX
];
396 CHAR8 CmdLine
[BOOT_DEVICE_OPTION_MAX
];
397 CHAR16 UnicodeCmdLine
[BOOT_DEVICE_OPTION_MAX
];
398 EFI_DEVICE_PATH
*DevicePath
;
399 EFI_DEVICE_PATH
*TempInitrdPath
;
400 ARM_BDS_LOADER_TYPE BootType
;
401 ARM_BDS_LOADER_OPTIONAL_DATA
* LoaderOptionalData
;
402 ARM_BDS_LINUX_ARGUMENTS
* LinuxArguments
;
403 EFI_DEVICE_PATH
*InitrdPathNodes
;
404 EFI_DEVICE_PATH
*InitrdPath
;
407 BOOLEAN InitrdSupport
;
409 UINTN OptionalDataSize
;
413 Status
= BootMenuSelectBootOption (BootOptionsList
, UPDATE_BOOT_ENTRY
, &BootOptionEntry
);
414 if (EFI_ERROR(Status
)) {
417 BootOption
= BootOptionEntry
->BdsLoadOption
;
419 // Get the device support for this Boot Option
420 Status
= BootDeviceGetDeviceSupport (BootOption
->FilePathList
, &DeviceSupport
);
421 if (EFI_ERROR(Status
)) {
422 Print(L
"Not possible to retrieve the supported device for the update\n");
423 return EFI_UNSUPPORTED
;
426 Status
= DeviceSupport
->UpdateDevicePathNode (BootOption
->FilePathList
, L
"EFI Application or the kernel", &DevicePath
);
427 if (EFI_ERROR(Status
)) {
428 Status
= EFI_ABORTED
;
432 if (DeviceSupport
->RequestBootType
) {
433 Status
= BootDeviceGetType (DevicePath
, &BootType
, &BootOption
->Attributes
);
434 if (EFI_ERROR(Status
)) {
435 Status
= EFI_ABORTED
;
440 LoaderOptionalData
= BootOption
->OptionalData
;
441 if (LoaderOptionalData
!= NULL
) {
442 BootType
= (ARM_BDS_LOADER_TYPE
)ReadUnaligned32 ((UINT32
*)(&LoaderOptionalData
->Header
.LoaderType
));
444 BootType
= BDS_LOADER_EFI_APPLICATION
;
447 if ((BootType
== BDS_LOADER_KERNEL_LINUX_ATAG
) || (BootType
== BDS_LOADER_KERNEL_LINUX_FDT
)) {
448 LinuxArguments
= &LoaderOptionalData
->Arguments
.LinuxArguments
;
450 CmdLineSize
= ReadUnaligned16 ((CONST UINT16
*)&LinuxArguments
->CmdLineSize
);
452 InitrdSize
= ReadUnaligned16 ((CONST UINT16
*)&LinuxArguments
->InitrdSize
);
453 if (InitrdSize
> 0) {
454 Print(L
"Keep the initrd: ");
456 Print(L
"Add an initrd: ");
458 Status
= GetHIInputBoolean (&InitrdSupport
);
459 if (EFI_ERROR(Status
)) {
460 Status
= EFI_ABORTED
;
465 if (InitrdSize
> 0) {
466 // Case we update the initrd device path
467 Status
= DeviceSupport
->UpdateDevicePathNode ((EFI_DEVICE_PATH
*)((UINTN
)(LinuxArguments
+ 1) + CmdLineSize
), L
"initrd", &InitrdPath
);
468 if (EFI_ERROR(Status
) && Status
!= EFI_NOT_FOUND
) {// EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd
469 Status
= EFI_ABORTED
;
472 InitrdSize
= GetDevicePathSize (InitrdPath
);
474 // Case we create the initrd device path
476 Status
= DeviceSupport
->CreateDevicePathNode (L
"initrd", &InitrdPathNodes
);
477 if (EFI_ERROR(Status
) && Status
!= EFI_NOT_FOUND
) { // EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd
478 Status
= EFI_ABORTED
;
482 if (InitrdPathNodes
!= NULL
) {
483 // Duplicate Linux kernel Device Path
484 TempInitrdPath
= DuplicateDevicePath (BootOption
->FilePathList
);
485 // Replace Linux kernel Node by EndNode
486 SetDevicePathEndNode (GetLastDevicePathNode (TempInitrdPath
));
487 // Append the Device Path to the selected device path
488 InitrdPath
= AppendDevicePath (TempInitrdPath
, (CONST EFI_DEVICE_PATH_PROTOCOL
*)InitrdPathNodes
);
489 FreePool (TempInitrdPath
);
490 if (InitrdPath
== NULL
) {
491 Status
= EFI_OUT_OF_RESOURCES
;
494 InitrdSize
= GetDevicePathSize (InitrdPath
);
503 Print(L
"Arguments to pass to the binary: ");
504 if (CmdLineSize
> 0) {
505 AsciiStrnCpy(CmdLine
, (CONST CHAR8
*)(LinuxArguments
+ 1), CmdLineSize
);
509 Status
= EditHIInputAscii (CmdLine
, BOOT_DEVICE_OPTION_MAX
);
510 if (EFI_ERROR(Status
)) {
511 Status
= EFI_ABORTED
;
512 goto FREE_DEVICE_PATH
;
515 CmdLineSize
= AsciiStrSize (CmdLine
);
517 OptionalDataSize
= sizeof(ARM_BDS_LOADER_ARGUMENTS
) + CmdLineSize
+ InitrdSize
;
518 BootArguments
= (ARM_BDS_LOADER_ARGUMENTS
*)AllocatePool (OptionalDataSize
);
519 BootArguments
->LinuxArguments
.CmdLineSize
= CmdLineSize
;
520 BootArguments
->LinuxArguments
.InitrdSize
= InitrdSize
;
521 CopyMem (&BootArguments
->LinuxArguments
+ 1, CmdLine
, CmdLineSize
);
522 CopyMem ((VOID
*)((UINTN
)(&BootArguments
->LinuxArguments
+ 1) + CmdLineSize
), InitrdPath
, InitrdSize
);
524 OptionalData
= (UINT8
*)BootArguments
;
526 Print (L
"Arguments to pass to the EFI Application: ");
528 if (BootOption
->OptionalDataSize
> 0) {
529 IsPrintable
= IsPrintableString (BootOption
->OptionalData
, &IsUnicode
);
532 StrnCpy (UnicodeCmdLine
, BootOption
->OptionalData
, BootOption
->OptionalDataSize
/ 2);
534 AsciiStrnCpy (CmdLine
, BootOption
->OptionalData
, BootOption
->OptionalDataSize
);
538 UnicodeCmdLine
[0] = L
'\0';
543 // We do not request arguments for OptionalData that cannot be printed
546 Status
= EditHIInputStr (UnicodeCmdLine
, BOOT_DEVICE_OPTION_MAX
);
547 if (EFI_ERROR (Status
)) {
548 Status
= EFI_ABORTED
;
549 goto FREE_DEVICE_PATH
;
552 OptionalData
= (UINT8
*)UnicodeCmdLine
;
553 OptionalDataSize
= StrSize (UnicodeCmdLine
);
555 Status
= EditHIInputAscii (CmdLine
, BOOT_DEVICE_OPTION_MAX
);
556 if (EFI_ERROR (Status
)) {
557 Status
= EFI_ABORTED
;
558 goto FREE_DEVICE_PATH
;
561 OptionalData
= (UINT8
*)CmdLine
;
562 OptionalDataSize
= AsciiStrSize (CmdLine
);
565 // We keep the former OptionalData
566 OptionalData
= BootOption
->OptionalData
;
567 OptionalDataSize
= BootOption
->OptionalDataSize
;
571 Print(L
"Description for this new Entry: ");
572 StrnCpy (BootDescription
, BootOption
->Description
, BOOT_DEVICE_DESCRIPTION_MAX
);
573 Status
= EditHIInputStr (BootDescription
, BOOT_DEVICE_DESCRIPTION_MAX
);
574 if (EFI_ERROR(Status
)) {
575 Status
= EFI_ABORTED
;
576 goto FREE_DEVICE_PATH
;
580 Status
= BootOptionUpdate (BootOption
, BootOption
->Attributes
, BootDescription
, DevicePath
, BootType
, OptionalData
, OptionalDataSize
);
583 FreePool (DevicePath
);
586 if (Status
== EFI_ABORTED
) {
594 IN LIST_ENTRY
*BootOptionsList
598 UINTN FdtDevicePathSize
;
599 BDS_SUPPORTED_DEVICE
*SupportedBootDevice
;
600 EFI_DEVICE_PATH_PROTOCOL
*FdtDevicePathNodes
;
601 EFI_DEVICE_PATH_PROTOCOL
*FdtDevicePath
;
603 Status
= SelectBootDevice (&SupportedBootDevice
);
604 if (EFI_ERROR(Status
)) {
605 Status
= EFI_ABORTED
;
609 // Create the specific device path node
610 Status
= SupportedBootDevice
->Support
->CreateDevicePathNode (L
"FDT blob", &FdtDevicePathNodes
);
611 if (EFI_ERROR(Status
)) {
612 Status
= EFI_ABORTED
;
616 if (FdtDevicePathNodes
!= NULL
) {
617 // Append the Device Path node to the select device path
618 FdtDevicePath
= AppendDevicePath (SupportedBootDevice
->DevicePathProtocol
, FdtDevicePathNodes
);
619 FdtDevicePathSize
= GetDevicePathSize (FdtDevicePath
);
620 Status
= gRT
->SetVariable (
622 &gArmGlobalVariableGuid
,
623 EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
627 ASSERT_EFI_ERROR(Status
);
631 &gArmGlobalVariableGuid
,
632 EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
,
636 ASSERT_EFI_ERROR(Status
);
640 if (Status
== EFI_ABORTED
) {
643 FreePool(SupportedBootDevice
);
650 Ask for the boot timeout in seconds and if the input succeeds assign the
651 input value to the UEFI global variable "Timeout". This function is called
652 when the user selects the "Set Boot Timeout" of the boot manager menu.
654 @param[in] BootOptionsList List of the boot devices, not used here
656 @retval EFI_SUCCESS Boot timeout in second retrieved from the standard
657 input and assigned to the UEFI "Timeout" global
659 @retval !EFI_SUCCESS Either the input or the setting of the UEFI global
660 variable "Timeout" has failed.
664 BootMenuSetBootTimeout (
665 IN LIST_ENTRY
*BootOptionsList
672 Print (L
"Timeout duration (in seconds): ");
673 Status
= GetHIInputInteger (&Input
);
674 if (EFI_ERROR (Status
)) {
680 Status
= gRT
->SetVariable (
682 &gEfiGlobalVariableGuid
,
683 EFI_VARIABLE_NON_VOLATILE
|
684 EFI_VARIABLE_BOOTSERVICE_ACCESS
|
685 EFI_VARIABLE_RUNTIME_ACCESS
,
689 ASSERT_EFI_ERROR (Status
);
695 struct BOOT_MANAGER_ENTRY
{
696 CONST CHAR16
* Description
;
697 EFI_STATUS (*Callback
) (IN LIST_ENTRY
*BootOptionsList
);
698 } BootManagerEntries
[] = {
699 { L
"Add Boot Device Entry", BootMenuAddBootOption
},
700 { L
"Update Boot Device Entry", BootMenuUpdateBootOption
},
701 { L
"Remove Boot Device Entry", BootMenuRemoveBootOption
},
702 { L
"Update FDT path", UpdateFdtPath
},
703 { L
"Set Boot Timeout", BootMenuSetBootTimeout
},
708 IN LIST_ENTRY
*BootOptionsList
712 UINTN OptionSelected
;
713 UINTN BootManagerEntryCount
;
716 BootManagerEntryCount
= sizeof(BootManagerEntries
) / sizeof(struct BOOT_MANAGER_ENTRY
);
719 // Display Boot Manager menu
720 for (Index
= 0; Index
< BootManagerEntryCount
; Index
++) {
721 Print(L
"[%d] %s\n",Index
+1,BootManagerEntries
[Index
]);
723 Print(L
"[%d] Return to main menu\n",Index
+1);
725 // Select which entry to call
727 Status
= GetHIInputInteger (&OptionSelected
);
728 if (EFI_ERROR(Status
) || (OptionSelected
== (BootManagerEntryCount
+1))) {
729 if (EFI_ERROR(Status
)) {
733 } else if ((OptionSelected
> 0) && (OptionSelected
<= BootManagerEntryCount
)) {
734 BootManagerEntries
[OptionSelected
-1].Callback (BootOptionsList
);
737 // Should never go here
742 IN LIST_ENTRY
*BootOptionsList
748 Status
= BdsLoadApplication (mImageHandle
, L
"Shell", 0, NULL
);
749 if (Status
== EFI_NOT_FOUND
) {
750 Print (L
"Error: EFI Application not found.\n");
751 } else if (EFI_ERROR(Status
)) {
752 Print (L
"Error: Status Code: 0x%X\n",(UINT32
)Status
);
758 struct BOOT_MAIN_ENTRY
{
759 CONST CHAR16
* Description
;
760 EFI_STATUS (*Callback
) (IN LIST_ENTRY
*BootOptionsList
);
761 } BootMainEntries
[] = {
762 { L
"Shell", BootShell
},
763 { L
"Boot Manager", BootMenuManager
},
772 LIST_ENTRY BootOptionsList
;
774 UINTN BootOptionCount
;
777 BDS_LOAD_OPTION
* BootOption
;
778 UINTN BootOptionSelected
;
780 UINTN BootMainEntryCount
;
784 BootMainEntryCount
= sizeof(BootMainEntries
) / sizeof(struct BOOT_MAIN_ENTRY
);
788 BootOptionList (&BootOptionsList
);
792 // Display the Boot options
793 for (Entry
= GetFirstNode (&BootOptionsList
);
794 !IsNull (&BootOptionsList
,Entry
);
795 Entry
= GetNextNode (&BootOptionsList
,Entry
)
798 BootOption
= LOAD_OPTION_FROM_LINK(Entry
);
800 Print(L
"[%d] %s\n", OptionCount
, BootOption
->Description
);
803 CHAR16
* DevicePathTxt
;
804 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
* DevicePathToTextProtocol
;
805 ARM_BDS_LOADER_OPTIONAL_DATA
* OptionalData
;
807 ARM_BDS_LOADER_TYPE LoaderType
;
809 Status
= gBS
->LocateProtocol (&gEfiDevicePathToTextProtocolGuid
, NULL
, (VOID
**)&DevicePathToTextProtocol
);
810 if (EFI_ERROR(Status
)) {
811 // You must provide an implementation of DevicePathToTextProtocol in your firmware (eg: DevicePathDxe)
812 DEBUG((EFI_D_ERROR
,"Error: Bds requires DevicePathToTextProtocol\n"));
815 DevicePathTxt
= DevicePathToTextProtocol
->ConvertDevicePathToText (BootOption
->FilePathList
, TRUE
, TRUE
);
817 Print(L
"\t- %s\n",DevicePathTxt
);
819 // If it is a supported BootEntry then print its details
820 if (IS_ARM_BDS_BOOTENTRY (BootOption
)) {
821 OptionalData
= BootOption
->OptionalData
;
822 LoaderType
= (ARM_BDS_LOADER_TYPE
)ReadUnaligned32 ((CONST UINT32
*)&OptionalData
->Header
.LoaderType
);
823 if ((LoaderType
== BDS_LOADER_KERNEL_LINUX_ATAG
) || (LoaderType
== BDS_LOADER_KERNEL_LINUX_FDT
)) {
824 if (ReadUnaligned16 (&OptionalData
->Arguments
.LinuxArguments
.InitrdSize
) > 0) {
825 CmdLineSize
= ReadUnaligned16 (&OptionalData
->Arguments
.LinuxArguments
.CmdLineSize
);
826 DevicePathTxt
= DevicePathToTextProtocol
->ConvertDevicePathToText (
827 GetAlignedDevicePath ((EFI_DEVICE_PATH
*)((UINTN
)(&OptionalData
->Arguments
.LinuxArguments
+ 1) + CmdLineSize
)), TRUE
, TRUE
);
828 Print(L
"\t- Initrd: %s\n", DevicePathTxt
);
830 if (ReadUnaligned16 (&OptionalData
->Arguments
.LinuxArguments
.CmdLineSize
) > 0) {
831 Print(L
"\t- Arguments: %a\n", (&OptionalData
->Arguments
.LinuxArguments
+ 1));
835 switch (LoaderType
) {
836 case BDS_LOADER_EFI_APPLICATION
:
837 Print(L
"\t- LoaderType: EFI Application\n");
840 case BDS_LOADER_KERNEL_LINUX_ATAG
:
841 Print(L
"\t- LoaderType: Linux kernel with ATAG support\n");
844 case BDS_LOADER_KERNEL_LINUX_FDT
:
845 Print(L
"\t- LoaderType: Linux kernel with FDT support\n");
849 Print(L
"\t- LoaderType: Not recognized (%d)\n", LoaderType
);
851 } else if (BootOption
->OptionalData
!= NULL
) {
852 if (IsPrintableString (BootOption
->OptionalData
, &IsUnicode
)) {
854 Print (L
"\t- Arguments: %s\n", BootOption
->OptionalData
);
856 AsciiPrint ("\t- Arguments: %a\n", BootOption
->OptionalData
);
860 FreePool(DevicePathTxt
);
865 BootOptionCount
= OptionCount
-1;
867 // Display the hardcoded Boot entries
868 for (Index
= 0; Index
< BootMainEntryCount
; Index
++) {
869 Print(L
"[%d] %s\n",OptionCount
,BootMainEntries
[Index
]);
873 // Request the boot entry from the user
874 BootOptionSelected
= 0;
875 while (BootOptionSelected
== 0) {
877 Status
= GetHIInputInteger (&BootOptionSelected
);
878 if (EFI_ERROR(Status
) || (BootOptionSelected
== 0) || (BootOptionSelected
> OptionCount
)) {
879 Print(L
"Invalid input (max %d)\n",(OptionCount
-1));
880 BootOptionSelected
= 0;
884 // Start the selected entry
885 if (BootOptionSelected
> BootOptionCount
) {
886 // Start the hardcoded entry
887 Status
= BootMainEntries
[BootOptionSelected
- BootOptionCount
- 1].Callback (&BootOptionsList
);
889 // Find the selected entry from the Boot#### list
891 for (Entry
= GetFirstNode (&BootOptionsList
);
892 !IsNull (&BootOptionsList
,Entry
);
893 Entry
= GetNextNode (&BootOptionsList
,Entry
)
896 if (Index
== BootOptionSelected
) {
897 BootOption
= LOAD_OPTION_FROM_LINK(Entry
);
903 Status
= BootOptionStart (BootOption
);
906 // Should never go here