]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - ArmPlatformPkg/Bds/BootMenu.c
ArmPlatformPkg/Bds: Get User inputs in Unicode
[mirror_edk2.git] / ArmPlatformPkg / Bds / BootMenu.c
... / ...
CommitLineData
1/** @file\r
2*\r
3* Copyright (c) 2011, ARM Limited. All rights reserved.\r
4*\r
5* This program and the accompanying materials\r
6* are licensed and made available under the terms and conditions of the BSD License\r
7* which accompanies this distribution. The full text of the license may be found at\r
8* http://opensource.org/licenses/bsd-license.php\r
9*\r
10* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12*\r
13**/\r
14\r
15#include "BdsInternal.h"\r
16\r
17extern EFI_HANDLE mImageHandle;\r
18extern BDS_LOAD_OPTION_SUPPORT *BdsLoadOptionSupportList;\r
19\r
20EFI_STATUS\r
21SelectBootDevice (\r
22 OUT BDS_SUPPORTED_DEVICE** SupportedBootDevice\r
23 )\r
24{\r
25 EFI_STATUS Status;\r
26 LIST_ENTRY SupportedDeviceList;\r
27 UINTN SupportedDeviceCount;\r
28 LIST_ENTRY* Entry;\r
29 UINTN SupportedDeviceSelected;\r
30 UINTN Index;\r
31\r
32 //\r
33 // List the Boot Devices supported\r
34 //\r
35\r
36 // Start all the drivers first\r
37 BdsConnectAllDrivers ();\r
38\r
39 // List the supported devices\r
40 Status = BootDeviceListSupportedInit (&SupportedDeviceList);\r
41 ASSERT_EFI_ERROR(Status);\r
42\r
43 SupportedDeviceCount = 0;\r
44 for (Entry = GetFirstNode (&SupportedDeviceList);\r
45 !IsNull (&SupportedDeviceList,Entry);\r
46 Entry = GetNextNode (&SupportedDeviceList,Entry)\r
47 )\r
48 {\r
49 *SupportedBootDevice = SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry);\r
50 Print(L"[%d] %s\n",SupportedDeviceCount+1,(*SupportedBootDevice)->Description);\r
51\r
52 DEBUG_CODE_BEGIN();\r
53 CHAR16* DevicePathTxt;\r
54 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;\r
55\r
56 Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);\r
57 ASSERT_EFI_ERROR(Status);\r
58 DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText((*SupportedBootDevice)->DevicePathProtocol,TRUE,TRUE);\r
59\r
60 Print(L"\t- %s\n",DevicePathTxt);\r
61\r
62 FreePool(DevicePathTxt);\r
63 DEBUG_CODE_END();\r
64\r
65 SupportedDeviceCount++;\r
66 }\r
67\r
68 if (SupportedDeviceCount == 0) {\r
69 Print(L"There is no supported device.\n");\r
70 Status = EFI_ABORTED;\r
71 goto EXIT;\r
72 }\r
73\r
74 //\r
75 // Select the Boot Device\r
76 //\r
77 SupportedDeviceSelected = 0;\r
78 while (SupportedDeviceSelected == 0) {\r
79 Print(L"Select the Boot Device: ");\r
80 Status = GetHIInputInteger (&SupportedDeviceSelected);\r
81 if (EFI_ERROR(Status)) {\r
82 Status = EFI_ABORTED;\r
83 goto EXIT;\r
84 } else if ((SupportedDeviceSelected == 0) || (SupportedDeviceSelected > SupportedDeviceCount)) {\r
85 Print(L"Invalid input (max %d)\n",SupportedDeviceSelected);\r
86 SupportedDeviceSelected = 0;\r
87 }\r
88 }\r
89\r
90 //\r
91 // Get the Device Path for the selected boot device\r
92 //\r
93 Index = 1;\r
94 for (Entry = GetFirstNode (&SupportedDeviceList);\r
95 !IsNull (&SupportedDeviceList,Entry);\r
96 Entry = GetNextNode (&SupportedDeviceList,Entry)\r
97 )\r
98 {\r
99 if (Index == SupportedDeviceSelected) {\r
100 *SupportedBootDevice = SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry);\r
101 break;\r
102 }\r
103 Index++;\r
104 }\r
105 \r
106EXIT:\r
107 BootDeviceListSupportedFree (&SupportedDeviceList, *SupportedBootDevice);\r
108 return Status;\r
109}\r
110\r
111EFI_STATUS\r
112BootMenuAddBootOption (\r
113 IN LIST_ENTRY *BootOptionsList\r
114 )\r
115{\r
116 EFI_STATUS Status;\r
117 BDS_SUPPORTED_DEVICE* SupportedBootDevice;\r
118 BDS_LOADER_ARGUMENTS BootArguments;\r
119 CHAR16 BootDescription[BOOT_DEVICE_DESCRIPTION_MAX];\r
120 UINT32 Attributes;\r
121 BDS_LOADER_TYPE BootType;\r
122 BDS_LOAD_OPTION *BdsLoadOption;\r
123 EFI_DEVICE_PATH *DevicePath;\r
124 EFI_DEVICE_PATH_PROTOCOL *DevicePathNode;\r
125 EFI_DEVICE_PATH_PROTOCOL *InitrdPathNode;\r
126\r
127 Attributes = 0;\r
128 SupportedBootDevice = NULL;\r
129\r
130 // List the Boot Devices supported\r
131 Status = SelectBootDevice(&SupportedBootDevice);\r
132 if (EFI_ERROR(Status)) {\r
133 Status = EFI_ABORTED;\r
134 goto EXIT;\r
135 }\r
136\r
137 // Create the specific device path node\r
138 Print(L"File path of the EFI Application or the kernel: ");\r
139 Status = SupportedBootDevice->Support->CreateDevicePathNode (SupportedBootDevice, &DevicePathNode, &BootType, &Attributes);\r
140 if (EFI_ERROR(Status)) {\r
141 Status = EFI_ABORTED;\r
142 goto EXIT;\r
143 }\r
144 // Append the Device Path node to the select device path\r
145 DevicePath = AppendDevicePathNode (SupportedBootDevice->DevicePathProtocol, (CONST EFI_DEVICE_PATH_PROTOCOL *)DevicePathNode);\r
146\r
147 if (BootType == BDS_LOADER_KERNEL_LINUX_ATAG) {\r
148 // Create the specific device path node\r
149 Print(L"File path of the initrd: ");\r
150 Status = SupportedBootDevice->Support->CreateDevicePathNode (SupportedBootDevice, &InitrdPathNode, NULL, NULL);\r
151 if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) { // EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd\r
152 Status = EFI_ABORTED;\r
153 goto EXIT;\r
154 }\r
155\r
156 if (InitrdPathNode != NULL) {\r
157 // Append the Device Path node to the select device path\r
158 BootArguments.LinuxAtagArguments.InitrdPathList = AppendDevicePathNode (SupportedBootDevice->DevicePathProtocol, (CONST EFI_DEVICE_PATH_PROTOCOL *)InitrdPathNode);\r
159 } else {\r
160 BootArguments.LinuxAtagArguments.InitrdPathList = NULL;\r
161 }\r
162\r
163 Print(L"Arguments to pass to the binary: ");\r
164 Status = GetHIInputAscii (BootArguments.LinuxAtagArguments.CmdLine,BOOT_DEVICE_OPTION_MAX);\r
165 if (EFI_ERROR(Status)) {\r
166 Status = EFI_ABORTED;\r
167 goto FREE_DEVICE_PATH;\r
168 }\r
169 BootArguments.LinuxAtagArguments.CmdLine[BOOT_DEVICE_OPTION_MAX]= '\0';\r
170 }\r
171\r
172 Print(L"Description for this new Entry: ");\r
173 Status = GetHIInputStr (BootDescription, BOOT_DEVICE_DESCRIPTION_MAX);\r
174 if (EFI_ERROR(Status)) {\r
175 Status = EFI_ABORTED;\r
176 goto FREE_DEVICE_PATH;\r
177 }\r
178\r
179 // Create new entry\r
180 Status = BootOptionCreate (Attributes, BootDescription, DevicePath, BootType, &BootArguments, &BdsLoadOption);\r
181 if (!EFI_ERROR(Status)) {\r
182 InsertTailList (BootOptionsList,&BdsLoadOption->Link);\r
183 }\r
184\r
185FREE_DEVICE_PATH:\r
186 FreePool (DevicePath);\r
187\r
188 \r
189EXIT:\r
190 if (Status == EFI_ABORTED) {\r
191 Print(L"\n");\r
192 }\r
193 FreePool(SupportedBootDevice);\r
194 return Status;\r
195}\r
196\r
197STATIC\r
198EFI_STATUS\r
199BootMenuSelectBootOption (\r
200 IN LIST_ENTRY *BootOptionsList,\r
201 IN CONST CHAR16* InputStatement,\r
202 OUT BDS_LOAD_OPTION **BdsLoadOption\r
203 )\r
204{\r
205 EFI_STATUS Status;\r
206 LIST_ENTRY* Entry;\r
207 BDS_LOAD_OPTION *BootOption;\r
208 UINTN BootOptionSelected;\r
209 UINTN BootOptionCount;\r
210 UINTN Index;\r
211\r
212 // Display the list of supported boot devices\r
213 BootOptionCount = 1;\r
214 for (Entry = GetFirstNode (BootOptionsList);\r
215 !IsNull (BootOptionsList,Entry);\r
216 Entry = GetNextNode (BootOptionsList,Entry)\r
217 )\r
218 {\r
219 BootOption = LOAD_OPTION_FROM_LINK(Entry);\r
220 Print(L"[%d] %s\n",BootOptionCount,BootOption->Description);\r
221\r
222 DEBUG_CODE_BEGIN();\r
223 CHAR16* DevicePathTxt;\r
224 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;\r
225\r
226 Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);\r
227 ASSERT_EFI_ERROR(Status);\r
228 DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText(BootOption->FilePathList,TRUE,TRUE);\r
229\r
230 Print(L"\t- %s\n",DevicePathTxt);\r
231 if ((BDS_LOADER_TYPE)ReadUnaligned32(&BootOption->OptionalData->LoaderType) == BDS_LOADER_KERNEL_LINUX_ATAG) {\r
232 Print(L"\t- Arguments: %a\n",BootOption->OptionalData->Arguments.LinuxAtagArguments.CmdLine);\r
233 }\r
234\r
235 FreePool(DevicePathTxt);\r
236 DEBUG_CODE_END();\r
237\r
238 BootOptionCount++;\r
239 }\r
240\r
241 // Get the index of the boot device to delete\r
242 BootOptionSelected = 0;\r
243 while (BootOptionSelected == 0) {\r
244 Print(InputStatement);\r
245 Status = GetHIInputInteger (&BootOptionSelected);\r
246 if (EFI_ERROR(Status)) {\r
247 return Status;\r
248 } else if ((BootOptionSelected == 0) || (BootOptionSelected >= BootOptionCount)) {\r
249 Print(L"Invalid input (max %d)\n",BootOptionCount-1);\r
250 BootOptionSelected = 0;\r
251 }\r
252 }\r
253\r
254 // Get the structure of the Boot device to delete\r
255 Index = 1;\r
256 for (Entry = GetFirstNode (BootOptionsList);\r
257 !IsNull (BootOptionsList,Entry);\r
258 Entry = GetNextNode (BootOptionsList,Entry)\r
259 )\r
260 {\r
261 if (Index == BootOptionSelected) {\r
262 *BdsLoadOption = LOAD_OPTION_FROM_LINK(Entry);\r
263 break;\r
264 }\r
265 Index++;\r
266 }\r
267\r
268 return EFI_SUCCESS;\r
269}\r
270\r
271EFI_STATUS\r
272BootMenuRemoveBootOption (\r
273 IN LIST_ENTRY *BootOptionsList\r
274 )\r
275{\r
276 EFI_STATUS Status;\r
277 BDS_LOAD_OPTION *BootOption;\r
278\r
279 Status = BootMenuSelectBootOption (BootOptionsList,L"Delete entry: ",&BootOption);\r
280 if (EFI_ERROR(Status)) {\r
281 return Status;\r
282 }\r
283\r
284 // Delete the BDS Load option structures\r
285 BootOptionDelete (BootOption);\r
286\r
287 return EFI_SUCCESS;\r
288}\r
289\r
290EFI_STATUS\r
291BootMenuUpdateBootOption (\r
292 IN LIST_ENTRY *BootOptionsList\r
293 )\r
294{\r
295 EFI_STATUS Status;\r
296 BDS_LOAD_OPTION *BootOption;\r
297 BDS_LOAD_OPTION_SUPPORT *DeviceSupport;\r
298 BDS_LOADER_ARGUMENTS BootArguments;\r
299 CHAR16 BootDescription[BOOT_DEVICE_DESCRIPTION_MAX];\r
300 EFI_DEVICE_PATH* DevicePath;\r
301 BDS_LOADER_TYPE BootType;\r
302\r
303 Status = BootMenuSelectBootOption (BootOptionsList,L"Update entry: ",&BootOption);\r
304 if (EFI_ERROR(Status)) {\r
305 return Status;\r
306 }\r
307\r
308 // Get the device support for this Boot Option\r
309 Status = BootDeviceGetDeviceSupport (BootOption,&DeviceSupport);\r
310 if (EFI_ERROR(Status)) {\r
311 Print(L"Impossible to retrieve the supported device for the update\n");\r
312 return EFI_UNSUPPORTED;\r
313 }\r
314\r
315 Print(L"File path of the EFI Application or the kernel: ");\r
316 Status = DeviceSupport->UpdateDevicePathNode (BootOption->FilePathList, &DevicePath, NULL, NULL);\r
317 if (EFI_ERROR(Status)) {\r
318 Status = EFI_ABORTED;\r
319 goto EXIT;\r
320 }\r
321\r
322 BootType = (BDS_LOADER_TYPE)ReadUnaligned32((UINT32 *)(&BootOption->OptionalData->LoaderType));\r
323\r
324 // TODO: Allow adding an initrd to a boot entry without one\r
325 if (BootType == BDS_LOADER_KERNEL_LINUX_ATAG) {\r
326 if (ReadUnaligned16(&BootOption->OptionalData->Arguments.LinuxAtagArguments.InitrdPathListLength) > 0\r
327 && (EFI_DEVICE_PATH_PROTOCOL *)ReadUnaligned32((UINT32 *)(&BootOption->OptionalData->Arguments.LinuxAtagArguments.InitrdPathList)) != NULL) {\r
328\r
329 Print(L"File path of the initrd: ");\r
330 Status = DeviceSupport->UpdateDevicePathNode (\r
331 (EFI_DEVICE_PATH_PROTOCOL *)ReadUnaligned32((UINT32 *)(&BootOption->OptionalData->Arguments.LinuxAtagArguments.InitrdPathList)),\r
332 &BootArguments.LinuxAtagArguments.InitrdPathList,\r
333 NULL,\r
334 NULL);\r
335 if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) {// EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd\r
336 Status = EFI_ABORTED;\r
337 goto EXIT;\r
338 }\r
339 } else {\r
340 BootArguments.LinuxAtagArguments.InitrdPathList = NULL;\r
341 BootArguments.LinuxAtagArguments.InitrdPathListLength = 0;\r
342 }\r
343\r
344 Print(L"Arguments to pass to the binary: ");\r
345 if (ReadUnaligned32((CONST UINT32*)&BootOption->OptionalData->Arguments.LinuxAtagArguments.CmdLine)) {\r
346 AsciiStrnCpy(BootArguments.LinuxAtagArguments.CmdLine,\r
347 BootOption->OptionalData->Arguments.LinuxAtagArguments.CmdLine,\r
348 BOOT_DEVICE_OPTION_MAX+1);\r
349 } else {\r
350 BootArguments.LinuxAtagArguments.CmdLine[0] = '\0';\r
351 }\r
352 Status = EditHIInputAscii (BootArguments.LinuxAtagArguments.CmdLine, BOOT_DEVICE_OPTION_MAX);\r
353 if (EFI_ERROR(Status)) {\r
354 Status = EFI_ABORTED;\r
355 goto FREE_DEVICE_PATH;\r
356 }\r
357 }\r
358\r
359 Print(L"Description for this new Entry: ");\r
360 Status = EditHIInputStr (BootDescription, BOOT_DEVICE_DESCRIPTION_MAX);\r
361 if (EFI_ERROR(Status)) {\r
362 Status = EFI_ABORTED;\r
363 goto FREE_DEVICE_PATH;\r
364 }\r
365\r
366 // Update the entry\r
367 Status = BootOptionUpdate (BootOption, BootOption->Attributes, BootDescription, DevicePath, BootType, &BootArguments);\r
368\r
369FREE_DEVICE_PATH:\r
370 FreePool (DevicePath);\r
371\r
372EXIT:\r
373 if (Status == EFI_ABORTED) {\r
374 Print(L"\n");\r
375 }\r
376 return Status;\r
377}\r
378\r
379struct BOOT_MANAGER_ENTRY {\r
380 CONST CHAR16* Description;\r
381 EFI_STATUS (*Callback) (IN LIST_ENTRY *BootOptionsList);\r
382} BootManagerEntries[] = {\r
383 { L"Add Boot Device Entry", BootMenuAddBootOption },\r
384 { L"Update Boot Device Entry", BootMenuUpdateBootOption },\r
385 { L"Remove Boot Device Entry", BootMenuRemoveBootOption },\r
386};\r
387\r
388EFI_STATUS\r
389BootMenuManager (\r
390 IN LIST_ENTRY *BootOptionsList\r
391 )\r
392{\r
393 UINTN Index;\r
394 UINTN OptionSelected;\r
395 UINTN BootManagerEntryCount;\r
396 EFI_STATUS Status;\r
397\r
398 BootManagerEntryCount = sizeof(BootManagerEntries) / sizeof(struct BOOT_MANAGER_ENTRY);\r
399\r
400 while (TRUE) {\r
401 // Display Boot Manager menu\r
402 for (Index = 0; Index < BootManagerEntryCount; Index++) {\r
403 Print(L"[%d] %s\n",Index+1,BootManagerEntries[Index]);\r
404 }\r
405 Print(L"[%d] Return to main menu\n",Index+1);\r
406\r
407 // Select which entry to call\r
408 Print(L"Choice: ");\r
409 Status = GetHIInputInteger (&OptionSelected);\r
410 if (EFI_ERROR(Status) || (OptionSelected == (BootManagerEntryCount+1))) {\r
411 if (EFI_ERROR(Status)) {\r
412 Print(L"\n");\r
413 }\r
414 return EFI_SUCCESS;\r
415 } else if ((OptionSelected > 0) && (OptionSelected <= BootManagerEntryCount)) {\r
416 Status = BootManagerEntries[OptionSelected-1].Callback (BootOptionsList);\r
417 }\r
418 }\r
419\r
420 return EFI_SUCCESS;\r
421}\r
422\r
423EFI_STATUS\r
424BootEBL (\r
425 IN LIST_ENTRY *BootOptionsList\r
426 )\r
427{\r
428 EFI_STATUS Status;\r
429\r
430 // Start EFI Shell\r
431 Status = BdsLoadApplication(mImageHandle, L"Ebl");\r
432 if (Status == EFI_NOT_FOUND) {\r
433 Print (L"Error: EFI Application not found.\n");\r
434 } else if (EFI_ERROR(Status)) {\r
435 Print (L"Error: Status Code: 0x%X\n",(UINT32)Status);\r
436 }\r
437\r
438 return Status;\r
439}\r
440\r
441struct BOOT_MAIN_ENTRY {\r
442 CONST CHAR16* Description;\r
443 EFI_STATUS (*Callback) (IN LIST_ENTRY *BootOptionsList);\r
444} BootMainEntries[] = {\r
445 { L"EBL", BootEBL },\r
446 { L"Boot Manager", BootMenuManager },\r
447};\r
448\r
449\r
450EFI_STATUS\r
451BootMenuMain (\r
452 VOID\r
453 )\r
454{\r
455 LIST_ENTRY BootOptionsList;\r
456 UINTN OptionCount;\r
457 UINTN BootOptionCount;\r
458 EFI_STATUS Status;\r
459 LIST_ENTRY *Entry;\r
460 BDS_LOAD_OPTION *BootOption;\r
461 UINTN BootOptionSelected;\r
462 UINTN Index;\r
463 UINTN BootMainEntryCount;\r
464\r
465 BootOption = NULL;\r
466 BootMainEntryCount = sizeof(BootMainEntries) / sizeof(struct BOOT_MAIN_ENTRY);\r
467\r
468 // Get Boot#### list\r
469 BootOptionList (&BootOptionsList);\r
470\r
471 while (TRUE) {\r
472 OptionCount = 1;\r
473\r
474 // Display the Boot options\r
475 for (Entry = GetFirstNode (&BootOptionsList);\r
476 !IsNull (&BootOptionsList,Entry);\r
477 Entry = GetNextNode (&BootOptionsList,Entry)\r
478 )\r
479 {\r
480 BootOption = LOAD_OPTION_FROM_LINK(Entry);\r
481\r
482 Print(L"[%d] %s\n",OptionCount,BootOption->Description);\r
483\r
484 DEBUG_CODE_BEGIN();\r
485 CHAR16* DevicePathTxt;\r
486 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;\r
487\r
488 Status = gBS->LocateProtocol(&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);\r
489 if (EFI_ERROR(Status)) {\r
490 // You must provide an implementation of DevicePathToTextProtocol in your firmware (eg: DevicePathDxe)\r
491 DEBUG((EFI_D_ERROR,"Error: Bds requires DevicePathToTextProtocol\n"));\r
492 return Status;\r
493 }\r
494 DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText(BootOption->FilePathList,TRUE,TRUE);\r
495\r
496 Print(L"\t- %s\n",DevicePathTxt);\r
497 if (ReadUnaligned32(&BootOption->OptionalData->LoaderType) == BDS_LOADER_KERNEL_LINUX_ATAG) {\r
498 if (ReadUnaligned16(&BootOption->OptionalData->Arguments.LinuxAtagArguments.InitrdPathListLength) > 0\r
499 && (EFI_DEVICE_PATH_PROTOCOL *)ReadUnaligned32((UINT32 *)(&BootOption->OptionalData->Arguments.LinuxAtagArguments.InitrdPathList)) != NULL) {\r
500 DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText((EFI_DEVICE_PATH_PROTOCOL *)ReadUnaligned32((UINT32 *)(&BootOption->OptionalData->Arguments.LinuxAtagArguments.InitrdPathList)),TRUE,TRUE);\r
501 Print(L"\t- Initrd: %s\n", DevicePathTxt);\r
502 }\r
503 \r
504 Print(L"\t- Arguments: %a\n", BootOption->OptionalData->Arguments.LinuxAtagArguments.CmdLine);\r
505 }\r
506\r
507 Print(L"\t- LoaderType: %d\n", ReadUnaligned32 (&BootOption->OptionalData->LoaderType));\r
508\r
509 FreePool(DevicePathTxt);\r
510 DEBUG_CODE_END();\r
511\r
512 OptionCount++;\r
513 }\r
514 BootOptionCount = OptionCount-1;\r
515\r
516 // Display the hardcoded Boot entries\r
517 for (Index = 0; Index < BootMainEntryCount; Index++) {\r
518 Print(L"[%d] %s\n",OptionCount,BootMainEntries[Index]);\r
519 OptionCount++;\r
520 }\r
521\r
522 // Request the boot entry from the user\r
523 BootOptionSelected = 0;\r
524 while (BootOptionSelected == 0) {\r
525 Print(L"Start: ");\r
526 Status = GetHIInputInteger (&BootOptionSelected);\r
527 if (EFI_ERROR(Status) || (BootOptionSelected == 0) || (BootOptionSelected > OptionCount)) {\r
528 Print(L"Invalid input (max %d)\n",(OptionCount-1));\r
529 BootOptionSelected = 0;\r
530 }\r
531 }\r
532\r
533 // Start the selected entry\r
534 if (BootOptionSelected > BootOptionCount) {\r
535 // Start the hardcoded entry\r
536 Status = BootMainEntries[BootOptionSelected - BootOptionCount - 1].Callback (&BootOptionsList);\r
537 } else {\r
538 // Find the selected entry from the Boot#### list\r
539 Index = 1;\r
540 for (Entry = GetFirstNode (&BootOptionsList);\r
541 !IsNull (&BootOptionsList,Entry);\r
542 Entry = GetNextNode (&BootOptionsList,Entry)\r
543 )\r
544 {\r
545 if (Index == BootOptionSelected) {\r
546 BootOption = LOAD_OPTION_FROM_LINK(Entry);\r
547 break;\r
548 }\r
549 Index++;\r
550 }\r
551\r
552 Status = BootOptionStart (BootOption);\r
553 }\r
554 }\r
555\r
556 return Status;\r
557}\r