3 * Copyright (c) 2011-2012, 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 extern EFI_HANDLE mImageHandle
;
18 extern BDS_LOAD_OPTION_SUPPORT
*BdsLoadOptionSupportList
;
22 OUT BDS_SUPPORTED_DEVICE
** SupportedBootDevice
26 LIST_ENTRY SupportedDeviceList
;
27 UINTN SupportedDeviceCount
;
29 UINTN SupportedDeviceSelected
;
33 // List the Boot Devices supported
36 // Start all the drivers first
37 BdsConnectAllDrivers ();
39 // List the supported devices
40 Status
= BootDeviceListSupportedInit (&SupportedDeviceList
);
41 ASSERT_EFI_ERROR(Status
);
43 SupportedDeviceCount
= 0;
44 for (Entry
= GetFirstNode (&SupportedDeviceList
);
45 !IsNull (&SupportedDeviceList
,Entry
);
46 Entry
= GetNextNode (&SupportedDeviceList
,Entry
)
49 *SupportedBootDevice
= SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry
);
50 Print(L
"[%d] %s\n",SupportedDeviceCount
+1,(*SupportedBootDevice
)->Description
);
53 CHAR16
* DevicePathTxt
;
54 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
* DevicePathToTextProtocol
;
56 Status
= gBS
->LocateProtocol (&gEfiDevicePathToTextProtocolGuid
, NULL
, (VOID
**)&DevicePathToTextProtocol
);
57 ASSERT_EFI_ERROR(Status
);
58 DevicePathTxt
= DevicePathToTextProtocol
->ConvertDevicePathToText ((*SupportedBootDevice
)->DevicePathProtocol
,TRUE
,TRUE
);
60 Print(L
"\t- %s\n",DevicePathTxt
);
62 FreePool(DevicePathTxt
);
65 SupportedDeviceCount
++;
68 if (SupportedDeviceCount
== 0) {
69 Print(L
"There is no supported device.\n");
75 // Select the Boot Device
77 SupportedDeviceSelected
= 0;
78 while (SupportedDeviceSelected
== 0) {
79 Print(L
"Select the Boot Device: ");
80 Status
= GetHIInputInteger (&SupportedDeviceSelected
);
81 if (EFI_ERROR(Status
)) {
84 } else if ((SupportedDeviceSelected
== 0) || (SupportedDeviceSelected
> SupportedDeviceCount
)) {
85 Print(L
"Invalid input (max %d)\n",SupportedDeviceCount
);
86 SupportedDeviceSelected
= 0;
91 // Get the Device Path for the selected boot device
94 for (Entry
= GetFirstNode (&SupportedDeviceList
);
95 !IsNull (&SupportedDeviceList
,Entry
);
96 Entry
= GetNextNode (&SupportedDeviceList
,Entry
)
99 if (Index
== SupportedDeviceSelected
) {
100 *SupportedBootDevice
= SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry
);
107 BootDeviceListSupportedFree (&SupportedDeviceList
, *SupportedBootDevice
);
112 BootMenuAddBootOption (
113 IN LIST_ENTRY
*BootOptionsList
117 BDS_SUPPORTED_DEVICE
* SupportedBootDevice
;
118 ARM_BDS_LOADER_ARGUMENTS
* BootArguments
;
119 CHAR16 BootDescription
[BOOT_DEVICE_DESCRIPTION_MAX
];
120 CHAR8 CmdLine
[BOOT_DEVICE_OPTION_MAX
];
122 ARM_BDS_LOADER_TYPE BootType
;
123 BDS_LOAD_OPTION_ENTRY
*BdsLoadOptionEntry
;
124 EFI_DEVICE_PATH
*DevicePath
;
125 EFI_DEVICE_PATH_PROTOCOL
*DevicePathNode
;
126 EFI_DEVICE_PATH_PROTOCOL
*InitrdPathNode
;
127 EFI_DEVICE_PATH_PROTOCOL
*InitrdPath
;
129 BOOLEAN InitrdSupport
;
133 SupportedBootDevice
= NULL
;
135 // List the Boot Devices supported
136 Status
= SelectBootDevice (&SupportedBootDevice
);
137 if (EFI_ERROR(Status
)) {
138 Status
= EFI_ABORTED
;
142 // Create the specific device path node
143 Status
= SupportedBootDevice
->Support
->CreateDevicePathNode (L
"EFI Application or the kernel", &DevicePathNode
, &BootType
, &Attributes
);
144 if (EFI_ERROR(Status
)) {
145 Status
= EFI_ABORTED
;
148 // Append the Device Path node to the select device path
149 DevicePath
= AppendDevicePathNode (SupportedBootDevice
->DevicePathProtocol
, (CONST EFI_DEVICE_PATH_PROTOCOL
*)DevicePathNode
);
151 if ((BootType
== BDS_LOADER_KERNEL_LINUX_ATAG
) || (BootType
== BDS_LOADER_KERNEL_LINUX_FDT
)) {
152 Print(L
"Add an initrd: ");
153 Status
= GetHIInputBoolean (&InitrdSupport
);
154 if (EFI_ERROR(Status
)) {
155 Status
= EFI_ABORTED
;
160 // Create the specific device path node
161 Status
= SupportedBootDevice
->Support
->CreateDevicePathNode (L
"initrd", &InitrdPathNode
, NULL
, NULL
);
162 if (EFI_ERROR(Status
) && Status
!= EFI_NOT_FOUND
) { // EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd
163 Status
= EFI_ABORTED
;
167 if (InitrdPathNode
!= NULL
) {
168 // Append the Device Path node to the select device path
169 InitrdPath
= AppendDevicePathNode (SupportedBootDevice
->DevicePathProtocol
, (CONST EFI_DEVICE_PATH_PROTOCOL
*)InitrdPathNode
);
177 Print(L
"Arguments to pass to the binary: ");
178 Status
= GetHIInputAscii (CmdLine
,BOOT_DEVICE_OPTION_MAX
);
179 if (EFI_ERROR(Status
)) {
180 Status
= EFI_ABORTED
;
181 goto FREE_DEVICE_PATH
;
184 CmdLineSize
= AsciiStrSize (CmdLine
);
185 InitrdSize
= GetDevicePathSize (InitrdPath
);
187 BootArguments
= (ARM_BDS_LOADER_ARGUMENTS
*)AllocatePool (sizeof(ARM_BDS_LOADER_ARGUMENTS
) + CmdLineSize
+ InitrdSize
);
189 BootArguments
->LinuxArguments
.CmdLineSize
= CmdLineSize
;
190 BootArguments
->LinuxArguments
.InitrdSize
= InitrdSize
;
191 CopyMem ((VOID
*)(&BootArguments
->LinuxArguments
+ 1), CmdLine
, CmdLineSize
);
192 CopyMem ((VOID
*)((UINTN
)(&BootArguments
->LinuxArguments
+ 1) + CmdLineSize
), InitrdPath
, InitrdSize
);
194 BootArguments
= NULL
;
197 Print(L
"Description for this new Entry: ");
198 Status
= GetHIInputStr (BootDescription
, BOOT_DEVICE_DESCRIPTION_MAX
);
199 if (EFI_ERROR(Status
)) {
200 Status
= EFI_ABORTED
;
201 goto FREE_DEVICE_PATH
;
205 BdsLoadOptionEntry
= (BDS_LOAD_OPTION_ENTRY
*)AllocatePool (sizeof(BDS_LOAD_OPTION_ENTRY
));
206 Status
= BootOptionCreate (Attributes
, BootDescription
, DevicePath
, BootType
, BootArguments
, &BdsLoadOptionEntry
->BdsLoadOption
);
207 if (!EFI_ERROR(Status
)) {
208 InsertTailList (BootOptionsList
, &BdsLoadOptionEntry
->Link
);
212 FreePool (DevicePath
);
216 if (Status
== EFI_ABORTED
) {
219 FreePool(SupportedBootDevice
);
225 BootMenuSelectBootOption (
226 IN LIST_ENTRY
* BootOptionsList
,
227 IN CONST CHAR16
* InputStatement
,
228 IN BOOLEAN OnlyArmBdsBootEntry
,
229 OUT BDS_LOAD_OPTION_ENTRY
** BdsLoadOptionEntry
234 BDS_LOAD_OPTION
* BdsLoadOption
;
235 UINTN BootOptionSelected
;
236 UINTN BootOptionCount
;
239 // Display the list of supported boot devices
241 for (Entry
= GetFirstNode (BootOptionsList
);
242 !IsNull (BootOptionsList
,Entry
);
243 Entry
= GetNextNode (BootOptionsList
, Entry
)
246 BdsLoadOption
= LOAD_OPTION_FROM_LINK(Entry
);
248 if (OnlyArmBdsBootEntry
&& !IS_ARM_BDS_BOOTENTRY (BdsLoadOption
)) {
252 Print (L
"[%d] %s\n", (BootOptionCount
+ 1), BdsLoadOption
->Description
);
255 CHAR16
* DevicePathTxt
;
256 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
* DevicePathToTextProtocol
;
257 ARM_BDS_LOADER_TYPE LoaderType
;
258 ARM_BDS_LOADER_OPTIONAL_DATA
* OptionalData
;
260 Status
= gBS
->LocateProtocol(&gEfiDevicePathToTextProtocolGuid
, NULL
, (VOID
**)&DevicePathToTextProtocol
);
261 ASSERT_EFI_ERROR(Status
);
262 DevicePathTxt
= DevicePathToTextProtocol
->ConvertDevicePathToText(BdsLoadOption
->FilePathList
,TRUE
,TRUE
);
264 Print(L
"\t- %s\n",DevicePathTxt
);
265 OptionalData
= BdsLoadOption
->OptionalData
;
266 LoaderType
= (ARM_BDS_LOADER_TYPE
)ReadUnaligned32 ((CONST UINT32
*)&OptionalData
->Header
.LoaderType
);
267 if ((LoaderType
== BDS_LOADER_KERNEL_LINUX_ATAG
) || (LoaderType
== BDS_LOADER_KERNEL_LINUX_FDT
)) {
268 Print (L
"\t- Arguments: %a\n",&OptionalData
->Arguments
.LinuxArguments
+ 1);
271 FreePool(DevicePathTxt
);
277 // Check if a valid boot option(s) is found
278 if (BootOptionCount
== 0) {
279 if (StrCmp (InputStatement
, DELETE_BOOT_ENTRY
) == 0) {
280 Print (L
"Nothing to remove!\n");
281 }else if (StrCmp (InputStatement
, UPDATE_BOOT_ENTRY
) == 0) {
282 Print (L
"Couldn't find valid boot entries\n");
284 Print (L
"No supported Boot Entry.\n");
287 return EFI_NOT_FOUND
;
290 // Get the index of the boot device to delete
291 BootOptionSelected
= 0;
292 while (BootOptionSelected
== 0) {
293 Print(InputStatement
);
294 Status
= GetHIInputInteger (&BootOptionSelected
);
295 if (EFI_ERROR(Status
)) {
297 } else if ((BootOptionSelected
== 0) || (BootOptionSelected
> BootOptionCount
)) {
298 Print(L
"Invalid input (max %d)\n",BootOptionCount
);
299 BootOptionSelected
= 0;
303 // Get the structure of the Boot device to delete
305 for (Entry
= GetFirstNode (BootOptionsList
);
306 !IsNull (BootOptionsList
, Entry
);
307 Entry
= GetNextNode (BootOptionsList
,Entry
)
310 if (Index
== BootOptionSelected
) {
311 *BdsLoadOptionEntry
= LOAD_OPTION_ENTRY_FROM_LINK(Entry
);
321 BootMenuRemoveBootOption (
322 IN LIST_ENTRY
*BootOptionsList
326 BDS_LOAD_OPTION_ENTRY
* BootOptionEntry
;
328 Status
= BootMenuSelectBootOption (BootOptionsList
, DELETE_BOOT_ENTRY
, FALSE
, &BootOptionEntry
);
329 if (EFI_ERROR(Status
)) {
333 // If the Boot Option was attached to a list remove it
334 if (!IsListEmpty (&BootOptionEntry
->Link
)) {
335 // Remove the entry from the list
336 RemoveEntryList (&BootOptionEntry
->Link
);
339 // Delete the BDS Load option structures
340 BootOptionDelete (BootOptionEntry
->BdsLoadOption
);
346 BootMenuUpdateBootOption (
347 IN LIST_ENTRY
*BootOptionsList
351 BDS_LOAD_OPTION_ENTRY
*BootOptionEntry
;
352 BDS_LOAD_OPTION
*BootOption
;
353 BDS_LOAD_OPTION_SUPPORT
* DeviceSupport
;
354 ARM_BDS_LOADER_ARGUMENTS
* BootArguments
;
355 CHAR16 BootDescription
[BOOT_DEVICE_DESCRIPTION_MAX
];
356 CHAR8 CmdLine
[BOOT_DEVICE_OPTION_MAX
];
357 EFI_DEVICE_PATH
*DevicePath
;
358 EFI_DEVICE_PATH
*TempInitrdPath
;
359 ARM_BDS_LOADER_TYPE BootType
;
360 ARM_BDS_LOADER_OPTIONAL_DATA
* OptionalData
;
361 ARM_BDS_LINUX_ARGUMENTS
* LinuxArguments
;
362 EFI_DEVICE_PATH
*InitrdPathNode
;
363 EFI_DEVICE_PATH
*InitrdPath
;
366 BOOLEAN InitrdSupport
;
368 Status
= BootMenuSelectBootOption (BootOptionsList
, UPDATE_BOOT_ENTRY
, TRUE
, &BootOptionEntry
);
369 if (EFI_ERROR(Status
)) {
372 BootOption
= BootOptionEntry
->BdsLoadOption
;
374 // Get the device support for this Boot Option
375 Status
= BootDeviceGetDeviceSupport (BootOption
->FilePathList
, &DeviceSupport
);
376 if (EFI_ERROR(Status
)) {
377 Print(L
"Not possible to retrieve the supported device for the update\n");
378 return EFI_UNSUPPORTED
;
381 Status
= DeviceSupport
->UpdateDevicePathNode (BootOption
->FilePathList
, L
"EFI Application or the kernel", &DevicePath
, NULL
, NULL
);
382 if (EFI_ERROR(Status
)) {
383 Status
= EFI_ABORTED
;
387 OptionalData
= BootOption
->OptionalData
;
388 BootType
= (ARM_BDS_LOADER_TYPE
)ReadUnaligned32 ((UINT32
*)(&OptionalData
->Header
.LoaderType
));
390 if ((BootType
== BDS_LOADER_KERNEL_LINUX_ATAG
) || (BootType
== BDS_LOADER_KERNEL_LINUX_FDT
)) {
391 LinuxArguments
= &OptionalData
->Arguments
.LinuxArguments
;
393 CmdLineSize
= ReadUnaligned16 ((CONST UINT16
*)&LinuxArguments
->CmdLineSize
);
395 InitrdSize
= ReadUnaligned16 ((CONST UINT16
*)&LinuxArguments
->InitrdSize
);
396 if (InitrdSize
> 0) {
397 Print(L
"Keep the initrd: ");
399 Print(L
"Add an initrd: ");
401 Status
= GetHIInputBoolean (&InitrdSupport
);
402 if (EFI_ERROR(Status
)) {
403 Status
= EFI_ABORTED
;
408 if (InitrdSize
> 0) {
409 // Case we update the initrd device path
410 Status
= DeviceSupport
->UpdateDevicePathNode ((EFI_DEVICE_PATH
*)((UINTN
)(LinuxArguments
+ 1) + CmdLineSize
), L
"initrd", &InitrdPath
, NULL
, NULL
);
411 if (EFI_ERROR(Status
) && Status
!= EFI_NOT_FOUND
) {// EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd
412 Status
= EFI_ABORTED
;
415 InitrdSize
= GetDevicePathSize (InitrdPath
);
417 // Case we create the initrd device path
419 Status
= DeviceSupport
->CreateDevicePathNode (L
"initrd", &InitrdPathNode
, NULL
, NULL
);
420 if (EFI_ERROR(Status
) && Status
!= EFI_NOT_FOUND
) { // EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd
421 Status
= EFI_ABORTED
;
425 if (InitrdPathNode
!= NULL
) {
426 // Duplicate Linux kernel Device Path
427 TempInitrdPath
= DuplicateDevicePath (BootOption
->FilePathList
);
428 // Replace Linux kernel Node by EndNode
429 SetDevicePathEndNode (GetLastDevicePathNode (TempInitrdPath
));
430 // Append the Device Path node to the select device path
431 InitrdPath
= AppendDevicePathNode (TempInitrdPath
, (CONST EFI_DEVICE_PATH_PROTOCOL
*)InitrdPathNode
);
432 FreePool (TempInitrdPath
);
433 InitrdSize
= GetDevicePathSize (InitrdPath
);
442 Print(L
"Arguments to pass to the binary: ");
443 if (CmdLineSize
> 0) {
444 AsciiStrnCpy(CmdLine
, (CONST CHAR8
*)(LinuxArguments
+ 1), CmdLineSize
);
448 Status
= EditHIInputAscii (CmdLine
, BOOT_DEVICE_OPTION_MAX
);
449 if (EFI_ERROR(Status
)) {
450 Status
= EFI_ABORTED
;
451 goto FREE_DEVICE_PATH
;
454 CmdLineSize
= AsciiStrSize (CmdLine
);
456 BootArguments
= (ARM_BDS_LOADER_ARGUMENTS
*)AllocatePool(sizeof(ARM_BDS_LOADER_ARGUMENTS
) + CmdLineSize
+ InitrdSize
);
457 BootArguments
->LinuxArguments
.CmdLineSize
= CmdLineSize
;
458 BootArguments
->LinuxArguments
.InitrdSize
= InitrdSize
;
459 CopyMem (&BootArguments
->LinuxArguments
+ 1, CmdLine
, CmdLineSize
);
460 CopyMem ((VOID
*)((UINTN
)(&BootArguments
->LinuxArguments
+ 1) + CmdLineSize
), InitrdPath
, InitrdSize
);
462 BootArguments
= NULL
;
465 Print(L
"Description for this new Entry: ");
466 StrnCpy (BootDescription
, BootOption
->Description
, BOOT_DEVICE_DESCRIPTION_MAX
);
467 Status
= EditHIInputStr (BootDescription
, BOOT_DEVICE_DESCRIPTION_MAX
);
468 if (EFI_ERROR(Status
)) {
469 Status
= EFI_ABORTED
;
470 goto FREE_DEVICE_PATH
;
474 Status
= BootOptionUpdate (BootOption
, BootOption
->Attributes
, BootDescription
, DevicePath
, BootType
, BootArguments
);
477 FreePool (DevicePath
);
480 if (Status
== EFI_ABORTED
) {
488 IN LIST_ENTRY
*BootOptionsList
492 UINTN FdtDevicePathSize
;
493 BDS_SUPPORTED_DEVICE
*SupportedBootDevice
;
494 EFI_DEVICE_PATH_PROTOCOL
*FdtDevicePathNode
;
495 EFI_DEVICE_PATH_PROTOCOL
*FdtDevicePath
;
497 Status
= SelectBootDevice (&SupportedBootDevice
);
498 if (EFI_ERROR(Status
)) {
499 Status
= EFI_ABORTED
;
503 // Create the specific device path node
504 Status
= SupportedBootDevice
->Support
->CreateDevicePathNode (L
"FDT blob", &FdtDevicePathNode
, NULL
, NULL
);
505 if (EFI_ERROR(Status
)) {
506 Status
= EFI_ABORTED
;
510 if (FdtDevicePathNode
!= NULL
) {
511 // Append the Device Path node to the select device path
512 FdtDevicePath
= AppendDevicePathNode (SupportedBootDevice
->DevicePathProtocol
, FdtDevicePathNode
);
513 FdtDevicePathSize
= GetDevicePathSize (FdtDevicePath
);
514 Status
= gRT
->SetVariable ((CHAR16
*)L
"Fdt", &gEfiGlobalVariableGuid
, (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
), FdtDevicePathSize
, FdtDevicePath
);
515 ASSERT_EFI_ERROR(Status
);
517 gRT
->SetVariable ((CHAR16
*)L
"Fdt", &gEfiGlobalVariableGuid
, (EFI_VARIABLE_RUNTIME_ACCESS
| EFI_VARIABLE_NON_VOLATILE
| EFI_VARIABLE_BOOTSERVICE_ACCESS
), 0, NULL
);
518 ASSERT_EFI_ERROR(Status
);
522 if (Status
== EFI_ABORTED
) {
525 FreePool(SupportedBootDevice
);
529 struct BOOT_MANAGER_ENTRY
{
530 CONST CHAR16
* Description
;
531 EFI_STATUS (*Callback
) (IN LIST_ENTRY
*BootOptionsList
);
532 } BootManagerEntries
[] = {
533 { L
"Add Boot Device Entry", BootMenuAddBootOption
},
534 { L
"Update Boot Device Entry", BootMenuUpdateBootOption
},
535 { L
"Remove Boot Device Entry", BootMenuRemoveBootOption
},
536 { L
"Update FDT path", UpdateFdtPath
},
541 IN LIST_ENTRY
*BootOptionsList
545 UINTN OptionSelected
;
546 UINTN BootManagerEntryCount
;
549 BootManagerEntryCount
= sizeof(BootManagerEntries
) / sizeof(struct BOOT_MANAGER_ENTRY
);
552 // Display Boot Manager menu
553 for (Index
= 0; Index
< BootManagerEntryCount
; Index
++) {
554 Print(L
"[%d] %s\n",Index
+1,BootManagerEntries
[Index
]);
556 Print(L
"[%d] Return to main menu\n",Index
+1);
558 // Select which entry to call
560 Status
= GetHIInputInteger (&OptionSelected
);
561 if (EFI_ERROR(Status
) || (OptionSelected
== (BootManagerEntryCount
+1))) {
562 if (EFI_ERROR(Status
)) {
566 } else if ((OptionSelected
> 0) && (OptionSelected
<= BootManagerEntryCount
)) {
567 BootManagerEntries
[OptionSelected
-1].Callback (BootOptionsList
);
570 // Should never go here
575 IN LIST_ENTRY
*BootOptionsList
581 Status
= BdsLoadApplication (mImageHandle
, L
"Shell", 0, NULL
);
582 if (Status
== EFI_NOT_FOUND
) {
583 Print (L
"Error: EFI Application not found.\n");
584 } else if (EFI_ERROR(Status
)) {
585 Print (L
"Error: Status Code: 0x%X\n",(UINT32
)Status
);
591 struct BOOT_MAIN_ENTRY
{
592 CONST CHAR16
* Description
;
593 EFI_STATUS (*Callback
) (IN LIST_ENTRY
*BootOptionsList
);
594 } BootMainEntries
[] = {
595 { L
"Shell", BootShell
},
596 { L
"Boot Manager", BootMenuManager
},
605 LIST_ENTRY BootOptionsList
;
607 UINTN BootOptionCount
;
610 BDS_LOAD_OPTION
* BootOption
;
611 UINTN BootOptionSelected
;
613 UINTN BootMainEntryCount
;
616 BootMainEntryCount
= sizeof(BootMainEntries
) / sizeof(struct BOOT_MAIN_ENTRY
);
620 BootOptionList (&BootOptionsList
);
624 // Display the Boot options
625 for (Entry
= GetFirstNode (&BootOptionsList
);
626 !IsNull (&BootOptionsList
,Entry
);
627 Entry
= GetNextNode (&BootOptionsList
,Entry
)
630 BootOption
= LOAD_OPTION_FROM_LINK(Entry
);
632 Print(L
"[%d] %s\n", OptionCount
, BootOption
->Description
);
635 CHAR16
* DevicePathTxt
;
636 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
* DevicePathToTextProtocol
;
637 ARM_BDS_LOADER_OPTIONAL_DATA
* OptionalData
;
639 ARM_BDS_LOADER_TYPE LoaderType
;
641 Status
= gBS
->LocateProtocol (&gEfiDevicePathToTextProtocolGuid
, NULL
, (VOID
**)&DevicePathToTextProtocol
);
642 if (EFI_ERROR(Status
)) {
643 // You must provide an implementation of DevicePathToTextProtocol in your firmware (eg: DevicePathDxe)
644 DEBUG((EFI_D_ERROR
,"Error: Bds requires DevicePathToTextProtocol\n"));
647 DevicePathTxt
= DevicePathToTextProtocol
->ConvertDevicePathToText (BootOption
->FilePathList
, TRUE
, TRUE
);
649 Print(L
"\t- %s\n",DevicePathTxt
);
651 // If it is a supported BootEntry then print its details
652 if (IS_ARM_BDS_BOOTENTRY (BootOption
)) {
653 OptionalData
= BootOption
->OptionalData
;
654 LoaderType
= (ARM_BDS_LOADER_TYPE
)ReadUnaligned32 ((CONST UINT32
*)&OptionalData
->Header
.LoaderType
);
655 if ((LoaderType
== BDS_LOADER_KERNEL_LINUX_ATAG
) || (LoaderType
== BDS_LOADER_KERNEL_LINUX_FDT
)) {
656 if (ReadUnaligned16 (&OptionalData
->Arguments
.LinuxArguments
.InitrdSize
) > 0) {
657 CmdLineSize
= ReadUnaligned16 (&OptionalData
->Arguments
.LinuxArguments
.CmdLineSize
);
658 DevicePathTxt
= DevicePathToTextProtocol
->ConvertDevicePathToText (
659 GetAlignedDevicePath ((EFI_DEVICE_PATH
*)((UINTN
)(&OptionalData
->Arguments
.LinuxArguments
+ 1) + CmdLineSize
)), TRUE
, TRUE
);
660 Print(L
"\t- Initrd: %s\n", DevicePathTxt
);
662 Print(L
"\t- Arguments: %a\n", (&OptionalData
->Arguments
.LinuxArguments
+ 1));
664 Print(L
"\t- LoaderType: %d\n", LoaderType
);
666 FreePool(DevicePathTxt
);
671 BootOptionCount
= OptionCount
-1;
673 // Display the hardcoded Boot entries
674 for (Index
= 0; Index
< BootMainEntryCount
; Index
++) {
675 Print(L
"[%d] %s\n",OptionCount
,BootMainEntries
[Index
]);
679 // Request the boot entry from the user
680 BootOptionSelected
= 0;
681 while (BootOptionSelected
== 0) {
683 Status
= GetHIInputInteger (&BootOptionSelected
);
684 if (EFI_ERROR(Status
) || (BootOptionSelected
== 0) || (BootOptionSelected
> OptionCount
)) {
685 Print(L
"Invalid input (max %d)\n",(OptionCount
-1));
686 BootOptionSelected
= 0;
690 // Start the selected entry
691 if (BootOptionSelected
> BootOptionCount
) {
692 // Start the hardcoded entry
693 Status
= BootMainEntries
[BootOptionSelected
- BootOptionCount
- 1].Callback (&BootOptionsList
);
695 // Find the selected entry from the Boot#### list
697 for (Entry
= GetFirstNode (&BootOptionsList
);
698 !IsNull (&BootOptionsList
,Entry
);
699 Entry
= GetNextNode (&BootOptionsList
,Entry
)
702 if (Index
== BootOptionSelected
) {
703 BootOption
= LOAD_OPTION_FROM_LINK(Entry
);
709 Status
= BootOptionStart (BootOption
);
712 // Should never go here