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 extern EFI_HANDLE mImageHandle
;
18 extern BDS_LOAD_OPTION_SUPPORT
*BdsLoadOptionSupportList
;
21 BootMenuAddBootOption (
22 IN LIST_ENTRY
*BootOptionsList
26 LIST_ENTRY SupportedDeviceList
;
27 UINTN SupportedDeviceCount
;
28 BDS_SUPPORTED_DEVICE
* SupportedBootDevice
;
30 UINTN SupportedDeviceSelected
;
31 CHAR8 AsciiBootOption
[BOOT_DEVICE_OPTION_MAX
];
32 CHAR8 AsciiBootDescription
[BOOT_DEVICE_DESCRIPTION_MAX
];
33 CHAR16
*BootDescription
;
35 BDS_LOADER_TYPE BootType
;
37 BDS_LOAD_OPTION
*BdsLoadOption
;
38 EFI_DEVICE_PATH
* DevicePath
;
39 EFI_DEVICE_PATH_PROTOCOL
*DevicePathNode
;
44 // List the Boot Devices supported
47 // Start all the drivers first
48 BdsConnectAllDrivers ();
50 // List the supported devices
51 Status
= BootDeviceListSupportedInit (&SupportedDeviceList
);
52 ASSERT_EFI_ERROR(Status
);
54 SupportedDeviceCount
= 0;
55 for (Entry
= GetFirstNode (&SupportedDeviceList
);
56 !IsNull (&SupportedDeviceList
,Entry
);
57 Entry
= GetNextNode (&SupportedDeviceList
,Entry
)
60 SupportedBootDevice
= SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry
);
61 Print(L
"[%d] %s\n",SupportedDeviceCount
+1,SupportedBootDevice
->Description
);
64 CHAR16
* DevicePathTxt
;
65 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
* DevicePathToTextProtocol
;
67 Status
= gBS
->LocateProtocol(&gEfiDevicePathToTextProtocolGuid
, NULL
, (VOID
**)&DevicePathToTextProtocol
);
68 ASSERT_EFI_ERROR(Status
);
69 DevicePathTxt
= DevicePathToTextProtocol
->ConvertDevicePathToText(SupportedBootDevice
->DevicePathProtocol
,TRUE
,TRUE
);
71 Print(L
"\t- %s\n",DevicePathTxt
);
73 FreePool(DevicePathTxt
);
76 SupportedDeviceCount
++;
79 if (SupportedDeviceCount
== 0) {
80 Print(L
"There is no supported device.\n");
86 // Select the Boot Device
88 SupportedDeviceSelected
= 0;
89 while (SupportedDeviceSelected
== 0) {
90 Print(L
"Select the Boot Device: ");
91 Status
= GetHIInputInteger (&SupportedDeviceSelected
);
92 if (EFI_ERROR(Status
)) {
95 } else if ((SupportedDeviceSelected
== 0) || (SupportedDeviceSelected
> SupportedDeviceCount
)) {
96 Print(L
"Invalid input (max %d)\n",SupportedDeviceSelected
);
97 SupportedDeviceSelected
= 0;
102 // Get the Device Path for the selected boot device
105 for (Entry
= GetFirstNode (&SupportedDeviceList
);
106 !IsNull (&SupportedDeviceList
,Entry
);
107 Entry
= GetNextNode (&SupportedDeviceList
,Entry
)
110 if (Index
== SupportedDeviceSelected
) {
111 SupportedBootDevice
= SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry
);
117 // Create the specific device path node
118 Status
= SupportedBootDevice
->Support
->CreateDevicePathNode (SupportedBootDevice
, &DevicePathNode
, &BootType
, &Attributes
);
119 if (EFI_ERROR(Status
)) {
120 Status
= EFI_ABORTED
;
123 // Append the Device Path node to the select device path
124 DevicePath
= AppendDevicePathNode (SupportedBootDevice
->DevicePathProtocol
, (CONST EFI_DEVICE_PATH_PROTOCOL
*)DevicePathNode
);
126 Print(L
"Arguments to pass to the binary: ");
127 Status
= GetHIInputAscii (AsciiBootOption
,BOOT_DEVICE_OPTION_MAX
);
128 if (EFI_ERROR(Status
)) {
129 Status
= EFI_ABORTED
;
130 goto FREE_DEVICE_PATH
;
133 Print(L
"Description for this new Entry: ");
134 Status
= GetHIInputAscii (AsciiBootDescription
,BOOT_DEVICE_DESCRIPTION_MAX
);
135 if (EFI_ERROR(Status
)) {
136 Status
= EFI_ABORTED
;
137 goto FREE_DEVICE_PATH
;
140 // Convert Ascii into Unicode
141 BootDescription
= (CHAR16
*)AllocatePool(AsciiStrSize(AsciiBootDescription
) * sizeof(CHAR16
));
142 AsciiStrToUnicodeStr (AsciiBootDescription
, BootDescription
);
145 Status
= BootOptionCreate (Attributes
, BootDescription
, DevicePath
, BootType
, AsciiBootOption
, &BdsLoadOption
);
146 if (!EFI_ERROR(Status
)) {
147 InsertTailList (BootOptionsList
,&BdsLoadOption
->Link
);
150 FreePool (BootDescription
);
153 FreePool (DevicePath
);
156 BootDeviceListSupportedFree (&SupportedDeviceList
);
162 BootMenuSelectBootOption (
163 IN LIST_ENTRY
*BootOptionsList
,
164 IN CONST CHAR16
* InputStatement
,
165 OUT BDS_LOAD_OPTION
**BdsLoadOption
170 BDS_LOAD_OPTION
*BootOption
;
171 UINTN BootOptionSelected
;
172 UINTN BootOptionCount
;
175 // Display the list of supported boot devices
177 for (Entry
= GetFirstNode (BootOptionsList
);
178 !IsNull (BootOptionsList
,Entry
);
179 Entry
= GetNextNode (BootOptionsList
,Entry
)
182 BootOption
= LOAD_OPTION_FROM_LINK(Entry
);
183 Print(L
"[%d] %s\n",BootOptionCount
,BootOption
->Description
);
186 CHAR16
* DevicePathTxt
;
187 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
* DevicePathToTextProtocol
;
189 Status
= gBS
->LocateProtocol(&gEfiDevicePathToTextProtocolGuid
, NULL
, (VOID
**)&DevicePathToTextProtocol
);
190 ASSERT_EFI_ERROR(Status
);
191 DevicePathTxt
= DevicePathToTextProtocol
->ConvertDevicePathToText(BootOption
->FilePathList
,TRUE
,TRUE
);
193 Print(L
"\t- %s\n",DevicePathTxt
);
194 if ((BootOption
->OptionalData
!= NULL
) && (BootOption
->OptionalData
->Arguments
!= NULL
)) {
195 Print(L
"\t- Arguments: %a\n",BootOption
->OptionalData
->Arguments
);
198 FreePool(DevicePathTxt
);
204 // Get the index of the boot device to delete
205 BootOptionSelected
= 0;
206 while (BootOptionSelected
== 0) {
207 Print(InputStatement
);
208 Status
= GetHIInputInteger (&BootOptionSelected
);
209 if (EFI_ERROR(Status
)) {
211 } else if ((BootOptionSelected
== 0) || (BootOptionSelected
>= BootOptionCount
)) {
212 Print(L
"Invalid input (max %d)\n",BootOptionCount
);
213 BootOptionSelected
= 0;
217 // Get the structure of the Boot device to delete
219 for (Entry
= GetFirstNode (BootOptionsList
);
220 !IsNull (BootOptionsList
,Entry
);
221 Entry
= GetNextNode (BootOptionsList
,Entry
)
224 if (Index
== BootOptionSelected
) {
225 *BdsLoadOption
= LOAD_OPTION_FROM_LINK(Entry
);
235 BootMenuRemoveBootOption (
236 IN LIST_ENTRY
*BootOptionsList
240 BDS_LOAD_OPTION
*BootOption
;
242 Status
= BootMenuSelectBootOption (BootOptionsList
,L
"Delete entry: ",&BootOption
);
243 if (EFI_ERROR(Status
)) {
247 // Delete the BDS Load option structures
248 BootOptionDelete (BootOption
);
254 BootMenuUpdateBootOption (
255 IN LIST_ENTRY
*BootOptionsList
259 BDS_LOAD_OPTION
*BootOption
;
260 BDS_LOAD_OPTION_SUPPORT
* DeviceSupport
;
261 CHAR8 AsciiBootOption
[BOOT_DEVICE_OPTION_MAX
];
262 CHAR8 AsciiBootDescription
[BOOT_DEVICE_DESCRIPTION_MAX
];
263 CHAR16
*BootDescription
;
264 EFI_DEVICE_PATH
* DevicePath
;
266 BDS_LOADER_TYPE BootType
;
268 Status
= BootMenuSelectBootOption (BootOptionsList
,L
"Update entry: ",&BootOption
);
269 if (EFI_ERROR(Status
)) {
273 // Get the device support for this Boot Option
274 Status
= BootDeviceGetDeviceSupport (BootOption
,&DeviceSupport
);
275 if (EFI_ERROR(Status
)) {
276 Print(L
"Impossible to retrieve the supported device for the update\n");
277 return EFI_UNSUPPORTED
;
280 Status
= DeviceSupport
->UpdateDevicePathNode (BootOption
,&DevicePath
,&BootType
,&Attributes
);
281 if (EFI_ERROR(Status
)) {
282 Status
= EFI_ABORTED
;
286 Print(L
"Arguments to pass to the binary: ");
287 if (BootOption
->OptionalData
) {
288 AsciiStrnCpy(AsciiBootOption
,BootOption
->OptionalData
->Arguments
,BOOT_DEVICE_FILEPATH_MAX
);
290 AsciiBootOption
[0] = '\0';
292 Status
= EditHIInputAscii (AsciiBootOption
,BOOT_DEVICE_OPTION_MAX
);
293 if (EFI_ERROR(Status
)) {
294 Status
= EFI_ABORTED
;
295 goto FREE_DEVICE_PATH
;
298 Print(L
"Description for this new Entry: ");
299 UnicodeStrToAsciiStr (BootOption
->Description
,AsciiBootDescription
);
300 Status
= EditHIInputAscii (AsciiBootDescription
,BOOT_DEVICE_DESCRIPTION_MAX
);
301 if (EFI_ERROR(Status
)) {
302 Status
= EFI_ABORTED
;
303 goto FREE_DEVICE_PATH
;
306 // Convert Ascii into Unicode
307 BootDescription
= (CHAR16
*)AllocatePool(AsciiStrSize(AsciiBootDescription
) * sizeof(CHAR16
));
308 AsciiStrToUnicodeStr (AsciiBootDescription
, BootDescription
);
311 Status
= BootOptionUpdate (BootOption
, Attributes
, BootDescription
, DevicePath
, BootType
, AsciiBootOption
);
313 FreePool (BootDescription
);
316 FreePool (DevicePath
);
322 struct BOOT_MANAGER_ENTRY
{
323 CONST CHAR16
* Description
;
324 EFI_STATUS (*Callback
) (IN LIST_ENTRY
*BootOptionsList
);
325 } BootManagerEntries
[] = {
326 { L
"Add Boot Device Entry", BootMenuAddBootOption
},
327 { L
"Update Boot Device Entry", BootMenuUpdateBootOption
},
328 { L
"Remove Boot Device Entry", BootMenuRemoveBootOption
},
333 IN LIST_ENTRY
*BootOptionsList
337 UINTN OptionSelected
;
338 UINTN BootManagerEntryCount
;
341 BootManagerEntryCount
= sizeof(BootManagerEntries
) / sizeof(struct BOOT_MANAGER_ENTRY
);
344 // Display Boot Manager menu
345 for (Index
= 0; Index
< BootManagerEntryCount
; Index
++) {
346 Print(L
"[%d] %s\n",Index
+1,BootManagerEntries
[Index
]);
348 Print(L
"[%d] Return to main menu\n",Index
+1);
350 // Select which entry to call
352 Status
= GetHIInputInteger (&OptionSelected
);
353 if (EFI_ERROR(Status
) || (OptionSelected
== (BootManagerEntryCount
+1))) {
355 } else if ((OptionSelected
> 0) && (OptionSelected
<= BootManagerEntryCount
)) {
356 Status
= BootManagerEntries
[OptionSelected
-1].Callback (BootOptionsList
);
365 IN LIST_ENTRY
*BootOptionsList
371 Status
= BdsLoadApplication(mImageHandle
, L
"Ebl");
372 if (Status
== EFI_NOT_FOUND
) {
373 Print (L
"Error: EFI Application not found.\n");
374 } else if (EFI_ERROR(Status
)) {
375 Print (L
"Error: Status Code: 0x%X\n",(UINT32
)Status
);
381 struct BOOT_MAIN_ENTRY
{
382 CONST CHAR16
* Description
;
383 EFI_STATUS (*Callback
) (IN LIST_ENTRY
*BootOptionsList
);
384 } BootMainEntries
[] = {
386 { L
"Boot Manager", BootMenuManager
},
395 LIST_ENTRY BootOptionsList
;
397 UINTN BootOptionCount
;
400 BDS_LOAD_OPTION
*BootOption
;
401 UINTN BootOptionSelected
;
403 UINTN BootMainEntryCount
;
405 BootMainEntryCount
= sizeof(BootMainEntries
) / sizeof(struct BOOT_MAIN_ENTRY
);
408 BootOptionList (&BootOptionsList
);
413 // Display the Boot options
414 for (Entry
= GetFirstNode (&BootOptionsList
);
415 !IsNull (&BootOptionsList
,Entry
);
416 Entry
= GetNextNode (&BootOptionsList
,Entry
)
419 BootOption
= LOAD_OPTION_FROM_LINK(Entry
);
421 Print(L
"[%d] %s\n",OptionCount
,BootOption
->Description
);
424 CHAR16
* DevicePathTxt
;
425 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
* DevicePathToTextProtocol
;
427 Status
= gBS
->LocateProtocol(&gEfiDevicePathToTextProtocolGuid
, NULL
, (VOID
**)&DevicePathToTextProtocol
);
428 ASSERT_EFI_ERROR(Status
);
429 DevicePathTxt
= DevicePathToTextProtocol
->ConvertDevicePathToText(BootOption
->FilePathList
,TRUE
,TRUE
);
431 Print(L
"\t- %s\n",DevicePathTxt
);
432 if (BootOption
->OptionalData
!= NULL
) {
433 Print(L
"\t- LoaderType: %d\n",BootOption
->OptionalData
->LoaderType
);
434 if (BootOption
->OptionalData
->Arguments
!= NULL
) {
435 Print(L
"\t- Arguments: %a\n",BootOption
->OptionalData
->Arguments
);
439 FreePool(DevicePathTxt
);
444 BootOptionCount
= OptionCount
-1;
446 // Display the hardcoded Boot entries
447 for (Index
= 0; Index
< BootMainEntryCount
; Index
++) {
448 Print(L
"[%d] %s\n",OptionCount
,BootMainEntries
[Index
]);
452 // Request the boot entry from the user
453 BootOptionSelected
= 0;
454 while (BootOptionSelected
== 0) {
456 Status
= GetHIInputInteger (&BootOptionSelected
);
457 if (EFI_ERROR(Status
) || (BootOptionSelected
== 0) || (BootOptionSelected
> OptionCount
)) {
458 Print(L
"Invalid input (max %d)\n",(OptionCount
-1));
459 BootOptionSelected
= 0;
463 // Start the selected entry
464 if (BootOptionSelected
> BootOptionCount
) {
465 // Start the hardcoded entry
466 Status
= BootMainEntries
[BootOptionSelected
- BootOptionCount
- 1].Callback (&BootOptionsList
);
468 // Find the selected entry from the Boot#### list
470 for (Entry
= GetFirstNode (&BootOptionsList
);
471 !IsNull (&BootOptionsList
,Entry
);
472 Entry
= GetNextNode (&BootOptionsList
,Entry
)
475 if (Index
== BootOptionSelected
) {
476 BootOption
= LOAD_OPTION_FROM_LINK(Entry
);
482 Status
= BootOptionStart (BootOption
);