]> git.proxmox.com Git - mirror_edk2.git/blame - ArmPlatformPkg/Bds/BootMenu.c
ArmPlatformPkg/Bds: Remove any use of the "Fdt" UEFI variable
[mirror_edk2.git] / ArmPlatformPkg / Bds / BootMenu.c
CommitLineData
ea46ebbe 1/** @file\r
2*\r
f2c730d3 3* Copyright (c) 2011 - 2015, ARM Limited. All rights reserved.\r
ea46ebbe 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
aeaf64d6 17#include <Guid/ArmGlobalVariableHob.h>\r
18\r
ea46ebbe 19extern BDS_LOAD_OPTION_SUPPORT *BdsLoadOptionSupportList;\r
20\r
019680b3
RC
21/**\r
22 Worker function that displays the list of boot options that is passed in.\r
23\r
24 The function loops over the entries of the list of boot options that is passed\r
25 in. For each entry, the boot option description is displayed on a single line\r
26 along with the position of the option in the list. In debug mode, the UEFI\r
27 device path and the arguments of the boot option are displayed as well in\r
28 subsequent lines.\r
29\r
30 @param[in] BootOptionsList List of the boot options\r
31\r
32**/\r
33STATIC\r
34VOID\r
35DisplayBootOptions (\r
36 IN LIST_ENTRY* BootOptionsList\r
37 )\r
38{\r
39 EFI_STATUS Status;\r
40 UINTN BootOptionCount;\r
41 LIST_ENTRY *Entry;\r
42 BDS_LOAD_OPTION *BdsLoadOption;\r
43 BOOLEAN IsUnicode;\r
44\r
45 BootOptionCount = 0 ;\r
46 for (Entry = GetFirstNode (BootOptionsList);\r
47 !IsNull (BootOptionsList, Entry);\r
48 Entry = GetNextNode (BootOptionsList, Entry)\r
49 ) {\r
50\r
51 BdsLoadOption = LOAD_OPTION_FROM_LINK (Entry);\r
52 Print (L"[%d] %s\n", ++BootOptionCount, BdsLoadOption->Description);\r
53\r
54 DEBUG_CODE_BEGIN ();\r
55 CHAR16* DevicePathTxt;\r
56 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;\r
57 ARM_BDS_LOADER_TYPE LoaderType;\r
58 ARM_BDS_LOADER_OPTIONAL_DATA* OptionalData;\r
59\r
60 Status = gBS->LocateProtocol (\r
61 &gEfiDevicePathToTextProtocolGuid,\r
62 NULL,\r
63 (VOID **)&DevicePathToTextProtocol\r
64 );\r
65 ASSERT_EFI_ERROR (Status);\r
66 DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (\r
67 BdsLoadOption->FilePathList,\r
68 TRUE,\r
69 TRUE\r
70 );\r
71 Print (L"\t- %s\n", DevicePathTxt);\r
72\r
73 OptionalData = BdsLoadOption->OptionalData;\r
74 if (IS_ARM_BDS_BOOTENTRY (BdsLoadOption)) {\r
75 LoaderType = (ARM_BDS_LOADER_TYPE)ReadUnaligned32 ((CONST UINT32*)&OptionalData->Header.LoaderType);\r
76 if ((LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) ||\r
77 (LoaderType == BDS_LOADER_KERNEL_LINUX_FDT ) ) {\r
78 Print (L"\t- Arguments: %a\n", &OptionalData->Arguments.LinuxArguments + 1);\r
79 }\r
80 } else if (OptionalData != NULL) {\r
81 if (IsPrintableString (OptionalData, &IsUnicode)) {\r
82 if (IsUnicode) {\r
83 Print (L"\t- Arguments: %s\n", OptionalData);\r
84 } else {\r
85 AsciiPrint ("\t- Arguments: %a\n", OptionalData);\r
86 }\r
87 }\r
88 }\r
89\r
90 FreePool (DevicePathTxt);\r
91 DEBUG_CODE_END ();\r
92 }\r
93}\r
94\r
95/**\r
96 Worker function that asks for a boot option to be selected and returns a\r
97 pointer to the structure describing the selected boot option.\r
98\r
99 @param[in] BootOptionsList List of the boot options\r
100\r
101 @retval EFI_SUCCESS Selection succeeded\r
102 @retval !EFI_SUCCESS Input error or input cancelled\r
103\r
104**/\r
105STATIC\r
106EFI_STATUS\r
107SelectBootOption (\r
108 IN LIST_ENTRY* BootOptionsList,\r
109 IN CONST CHAR16* InputStatement,\r
110 OUT BDS_LOAD_OPTION_ENTRY** BdsLoadOptionEntry\r
111 )\r
112{\r
113 EFI_STATUS Status;\r
114 UINTN BootOptionCount;\r
115 UINT16 *BootOrder;\r
116 LIST_ENTRY* Entry;\r
117 UINTN BootOptionSelected;\r
118 UINTN Index;\r
119\r
120 // Get the number of boot options\r
121 Status = GetGlobalEnvironmentVariable (\r
122 L"BootOrder", NULL, &BootOptionCount, (VOID**)&BootOrder\r
123 );\r
124 if (EFI_ERROR (Status)) {\r
125 goto ErrorExit;\r
126 }\r
127 FreePool (BootOrder);\r
128 BootOptionCount /= sizeof (UINT16);\r
129\r
130 // Check if a valid boot option(s) is found\r
131 if (BootOptionCount == 0) {\r
132 if (StrCmp (InputStatement, DELETE_BOOT_ENTRY) == 0) {\r
133 Print (L"Nothing to remove!\n");\r
134 } else if (StrCmp (InputStatement, UPDATE_BOOT_ENTRY) == 0) {\r
135 Print (L"Nothing to update!\n");\r
136 } else if (StrCmp (InputStatement, MOVE_BOOT_ENTRY) == 0) {\r
137 Print (L"Nothing to move!\n");\r
138 } else {\r
139 Print (L"No supported Boot Entry.\n");\r
140 }\r
141 return EFI_NOT_FOUND;\r
142 }\r
143\r
144 // Get the index of the boot device to delete\r
145 BootOptionSelected = 0;\r
146 while (BootOptionSelected == 0) {\r
147 Print (InputStatement);\r
148 Status = GetHIInputInteger (&BootOptionSelected);\r
149 if (EFI_ERROR (Status)) {\r
150 Print (L"\n");\r
151 goto ErrorExit;\r
152 } else if ((BootOptionSelected == 0) || (BootOptionSelected > BootOptionCount)) {\r
153 Print (L"Invalid input (max %d)\n", BootOptionCount);\r
154 BootOptionSelected = 0;\r
155 }\r
156 }\r
157\r
158 // Get the structure of the Boot device to delete\r
159 Index = 1;\r
160 for (Entry = GetFirstNode (BootOptionsList);\r
161 !IsNull (BootOptionsList, Entry);\r
162 Entry = GetNextNode (BootOptionsList,Entry)\r
163 )\r
164 {\r
165 if (Index == BootOptionSelected) {\r
166 *BdsLoadOptionEntry = LOAD_OPTION_ENTRY_FROM_LINK (Entry);\r
167 break;\r
168 }\r
169 Index++;\r
170 }\r
aeaf64d6 171\r
019680b3
RC
172ErrorExit:\r
173 return Status;\r
174}\r
175\r
176STATIC\r
ea46ebbe 177EFI_STATUS\r
656416bc 178SelectBootDevice (\r
179 OUT BDS_SUPPORTED_DEVICE** SupportedBootDevice\r
ea46ebbe 180 )\r
181{\r
656416bc 182 EFI_STATUS Status;\r
ea46ebbe 183 LIST_ENTRY SupportedDeviceList;\r
184 UINTN SupportedDeviceCount;\r
ea46ebbe 185 LIST_ENTRY* Entry;\r
186 UINTN SupportedDeviceSelected;\r
ea46ebbe 187 UINTN Index;\r
ea46ebbe 188\r
189 //\r
190 // List the Boot Devices supported\r
191 //\r
192\r
193 // Start all the drivers first\r
194 BdsConnectAllDrivers ();\r
195\r
196 // List the supported devices\r
197 Status = BootDeviceListSupportedInit (&SupportedDeviceList);\r
198 ASSERT_EFI_ERROR(Status);\r
199\r
200 SupportedDeviceCount = 0;\r
201 for (Entry = GetFirstNode (&SupportedDeviceList);\r
202 !IsNull (&SupportedDeviceList,Entry);\r
203 Entry = GetNextNode (&SupportedDeviceList,Entry)\r
204 )\r
205 {\r
656416bc 206 *SupportedBootDevice = SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry);\r
207 Print(L"[%d] %s\n",SupportedDeviceCount+1,(*SupportedBootDevice)->Description);\r
ea46ebbe 208\r
209 DEBUG_CODE_BEGIN();\r
210 CHAR16* DevicePathTxt;\r
211 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;\r
212\r
ff7666c5 213 Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);\r
ea46ebbe 214 ASSERT_EFI_ERROR(Status);\r
ff7666c5 215 DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText ((*SupportedBootDevice)->DevicePathProtocol,TRUE,TRUE);\r
ea46ebbe 216\r
217 Print(L"\t- %s\n",DevicePathTxt);\r
218\r
219 FreePool(DevicePathTxt);\r
220 DEBUG_CODE_END();\r
221\r
222 SupportedDeviceCount++;\r
223 }\r
224\r
225 if (SupportedDeviceCount == 0) {\r
226 Print(L"There is no supported device.\n");\r
227 Status = EFI_ABORTED;\r
228 goto EXIT;\r
229 }\r
230\r
231 //\r
232 // Select the Boot Device\r
233 //\r
234 SupportedDeviceSelected = 0;\r
235 while (SupportedDeviceSelected == 0) {\r
236 Print(L"Select the Boot Device: ");\r
237 Status = GetHIInputInteger (&SupportedDeviceSelected);\r
238 if (EFI_ERROR(Status)) {\r
239 Status = EFI_ABORTED;\r
240 goto EXIT;\r
241 } else if ((SupportedDeviceSelected == 0) || (SupportedDeviceSelected > SupportedDeviceCount)) {\r
ff7666c5 242 Print(L"Invalid input (max %d)\n",SupportedDeviceCount);\r
ea46ebbe 243 SupportedDeviceSelected = 0;\r
244 }\r
245 }\r
246\r
247 //\r
248 // Get the Device Path for the selected boot device\r
249 //\r
250 Index = 1;\r
251 for (Entry = GetFirstNode (&SupportedDeviceList);\r
252 !IsNull (&SupportedDeviceList,Entry);\r
253 Entry = GetNextNode (&SupportedDeviceList,Entry)\r
254 )\r
255 {\r
256 if (Index == SupportedDeviceSelected) {\r
656416bc 257 *SupportedBootDevice = SUPPORTED_BOOT_DEVICE_FROM_LINK(Entry);\r
ea46ebbe 258 break;\r
259 }\r
260 Index++;\r
261 }\r
aeaf64d6 262\r
656416bc 263EXIT:\r
264 BootDeviceListSupportedFree (&SupportedDeviceList, *SupportedBootDevice);\r
265 return Status;\r
266}\r
267\r
268EFI_STATUS\r
269BootMenuAddBootOption (\r
270 IN LIST_ENTRY *BootOptionsList\r
271 )\r
272{\r
2ccfb71e 273 EFI_STATUS Status;\r
274 BDS_SUPPORTED_DEVICE* SupportedBootDevice;\r
275 ARM_BDS_LOADER_ARGUMENTS* BootArguments;\r
74b96132 276 CHAR16 BootDescription[BOOT_DEVICE_DESCRIPTION_MAX];\r
06044819
OM
277 CHAR8 AsciiCmdLine[BOOT_DEVICE_OPTION_MAX];\r
278 CHAR16 CmdLine[BOOT_DEVICE_OPTION_MAX];\r
2ccfb71e 279 UINT32 Attributes;\r
280 ARM_BDS_LOADER_TYPE BootType;\r
a6e97d28 281 BDS_LOAD_OPTION_ENTRY *BdsLoadOptionEntry;\r
2ccfb71e 282 EFI_DEVICE_PATH *DevicePath;\r
ecc62d13 283 EFI_DEVICE_PATH_PROTOCOL *DevicePathNodes;\r
284 EFI_DEVICE_PATH_PROTOCOL *InitrdPathNodes;\r
2ccfb71e 285 EFI_DEVICE_PATH_PROTOCOL *InitrdPath;\r
286 UINTN CmdLineSize;\r
22a262c8 287 BOOLEAN InitrdSupport;\r
2ccfb71e 288 UINTN InitrdSize;\r
90a44ec4
OM
289 UINT8* OptionalData;\r
290 UINTN OptionalDataSize;\r
656416bc 291\r
292 Attributes = 0;\r
293 SupportedBootDevice = NULL;\r
294\r
295 // List the Boot Devices supported\r
2ccfb71e 296 Status = SelectBootDevice (&SupportedBootDevice);\r
656416bc 297 if (EFI_ERROR(Status)) {\r
298 Status = EFI_ABORTED;\r
299 goto EXIT;\r
300 }\r
ea46ebbe 301\r
302 // Create the specific device path node\r
889ac6a8 303 Status = SupportedBootDevice->Support->CreateDevicePathNode (L"EFI Application or the kernel", &DevicePathNodes);\r
ea46ebbe 304 if (EFI_ERROR(Status)) {\r
305 Status = EFI_ABORTED;\r
306 goto EXIT;\r
307 }\r
ecc62d13 308 // Append the Device Path to the selected device path\r
309 DevicePath = AppendDevicePath (SupportedBootDevice->DevicePathProtocol, (CONST EFI_DEVICE_PATH_PROTOCOL *)DevicePathNodes);\r
310 if (DevicePath == NULL) {\r
311 Status = EFI_OUT_OF_RESOURCES;\r
312 goto EXIT;\r
313 }\r
ea46ebbe 314\r
889ac6a8 315 if (SupportedBootDevice->Support->RequestBootType) {\r
55a9f75d
OM
316 Status = BootDeviceGetType (DevicePath, &BootType, &Attributes);\r
317 if (EFI_ERROR(Status)) {\r
318 Status = EFI_ABORTED;\r
319 goto EXIT;\r
320 }\r
321 } else {\r
322 BootType = BDS_LOADER_EFI_APPLICATION;\r
323 }\r
324\r
2ccfb71e 325 if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) {\r
22a262c8 326 Print(L"Add an initrd: ");\r
327 Status = GetHIInputBoolean (&InitrdSupport);\r
328 if (EFI_ERROR(Status)) {\r
656416bc 329 Status = EFI_ABORTED;\r
330 goto EXIT;\r
331 }\r
332\r
22a262c8 333 if (InitrdSupport) {\r
334 // Create the specific device path node\r
889ac6a8 335 Status = SupportedBootDevice->Support->CreateDevicePathNode (L"initrd", &InitrdPathNodes);\r
22a262c8 336 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
337 Status = EFI_ABORTED;\r
338 goto EXIT;\r
339 }\r
340\r
ecc62d13 341 if (InitrdPathNodes != NULL) {\r
342 // Append the Device Path to the selected device path\r
343 InitrdPath = AppendDevicePath (SupportedBootDevice->DevicePathProtocol, (CONST EFI_DEVICE_PATH_PROTOCOL *)InitrdPathNodes);\r
830e5b8c
OM
344 // Free the InitrdPathNodes created by Support->CreateDevicePathNode()\r
345 FreePool (InitrdPathNodes);\r
346\r
ecc62d13 347 if (InitrdPath == NULL) {\r
348 Status = EFI_OUT_OF_RESOURCES;\r
349 goto EXIT;\r
350 }\r
22a262c8 351 } else {\r
352 InitrdPath = NULL;\r
353 }\r
656416bc 354 } else {\r
2ccfb71e 355 InitrdPath = NULL;\r
656416bc 356 }\r
357\r
358 Print(L"Arguments to pass to the binary: ");\r
06044819 359 Status = GetHIInputAscii (AsciiCmdLine, BOOT_DEVICE_OPTION_MAX);\r
656416bc 360 if (EFI_ERROR(Status)) {\r
361 Status = EFI_ABORTED;\r
362 goto FREE_DEVICE_PATH;\r
363 }\r
2ccfb71e 364\r
06044819 365 CmdLineSize = AsciiStrSize (AsciiCmdLine);\r
2ccfb71e 366 InitrdSize = GetDevicePathSize (InitrdPath);\r
367\r
90a44ec4
OM
368 OptionalDataSize = sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize;\r
369 BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (OptionalDataSize);\r
aeaf64d6 370\r
2ccfb71e 371 BootArguments->LinuxArguments.CmdLineSize = CmdLineSize;\r
372 BootArguments->LinuxArguments.InitrdSize = InitrdSize;\r
5382a857 373 CopyMem ((VOID*)(&BootArguments->LinuxArguments + 1), AsciiCmdLine, CmdLineSize);\r
2ccfb71e 374 CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize), InitrdPath, InitrdSize);\r
90a44ec4
OM
375\r
376 OptionalData = (UINT8*)BootArguments;\r
2ccfb71e 377 } else {\r
06044819
OM
378 Print (L"Arguments to pass to the EFI Application: ");\r
379 Status = GetHIInputStr (CmdLine, BOOT_DEVICE_OPTION_MAX);\r
380 if (EFI_ERROR (Status)) {\r
381 Status = EFI_ABORTED;\r
382 goto EXIT;\r
383 }\r
384\r
385 OptionalData = (UINT8*)CmdLine;\r
386 OptionalDataSize = StrSize (CmdLine);\r
ea46ebbe 387 }\r
388\r
389 Print(L"Description for this new Entry: ");\r
74b96132 390 Status = GetHIInputStr (BootDescription, BOOT_DEVICE_DESCRIPTION_MAX);\r
ea46ebbe 391 if (EFI_ERROR(Status)) {\r
392 Status = EFI_ABORTED;\r
393 goto FREE_DEVICE_PATH;\r
394 }\r
395\r
ea46ebbe 396 // Create new entry\r
a6e97d28 397 BdsLoadOptionEntry = (BDS_LOAD_OPTION_ENTRY*)AllocatePool (sizeof(BDS_LOAD_OPTION_ENTRY));\r
90a44ec4 398 Status = BootOptionCreate (Attributes, BootDescription, DevicePath, BootType, OptionalData, OptionalDataSize, &BdsLoadOptionEntry->BdsLoadOption);\r
ea46ebbe 399 if (!EFI_ERROR(Status)) {\r
a6e97d28 400 InsertTailList (BootOptionsList, &BdsLoadOptionEntry->Link);\r
ea46ebbe 401 }\r
402\r
ea46ebbe 403FREE_DEVICE_PATH:\r
404 FreePool (DevicePath);\r
405\r
406EXIT:\r
656416bc 407 if (Status == EFI_ABORTED) {\r
408 Print(L"\n");\r
409 }\r
410 FreePool(SupportedBootDevice);\r
ea46ebbe 411 return Status;\r
412}\r
413\r
ea46ebbe 414EFI_STATUS\r
415BootMenuRemoveBootOption (\r
416 IN LIST_ENTRY *BootOptionsList\r
417 )\r
418{\r
a6e97d28 419 EFI_STATUS Status;\r
420 BDS_LOAD_OPTION_ENTRY* BootOptionEntry;\r
ea46ebbe 421\r
019680b3
RC
422 DisplayBootOptions (BootOptionsList);\r
423 Status = SelectBootOption (BootOptionsList, DELETE_BOOT_ENTRY, &BootOptionEntry);\r
424 if (EFI_ERROR (Status)) {\r
ea46ebbe 425 return Status;\r
426 }\r
427\r
a6e97d28 428 // If the Boot Option was attached to a list remove it\r
429 if (!IsListEmpty (&BootOptionEntry->Link)) {\r
430 // Remove the entry from the list\r
431 RemoveEntryList (&BootOptionEntry->Link);\r
432 }\r
433\r
ea46ebbe 434 // Delete the BDS Load option structures\r
a6e97d28 435 BootOptionDelete (BootOptionEntry->BdsLoadOption);\r
ea46ebbe 436\r
437 return EFI_SUCCESS;\r
438}\r
439\r
440EFI_STATUS\r
441BootMenuUpdateBootOption (\r
442 IN LIST_ENTRY *BootOptionsList\r
443 )\r
444{\r
2ccfb71e 445 EFI_STATUS Status;\r
a6e97d28 446 BDS_LOAD_OPTION_ENTRY *BootOptionEntry;\r
2ccfb71e 447 BDS_LOAD_OPTION *BootOption;\r
448 BDS_LOAD_OPTION_SUPPORT* DeviceSupport;\r
449 ARM_BDS_LOADER_ARGUMENTS* BootArguments;\r
74b96132 450 CHAR16 BootDescription[BOOT_DEVICE_DESCRIPTION_MAX];\r
2ccfb71e 451 CHAR8 CmdLine[BOOT_DEVICE_OPTION_MAX];\r
3b3b72d6 452 CHAR16 UnicodeCmdLine[BOOT_DEVICE_OPTION_MAX];\r
14238a61 453 EFI_DEVICE_PATH *DevicePath;\r
454 EFI_DEVICE_PATH *TempInitrdPath;\r
2ccfb71e 455 ARM_BDS_LOADER_TYPE BootType;\r
90a44ec4 456 ARM_BDS_LOADER_OPTIONAL_DATA* LoaderOptionalData;\r
2ccfb71e 457 ARM_BDS_LINUX_ARGUMENTS* LinuxArguments;\r
ecc62d13 458 EFI_DEVICE_PATH *InitrdPathNodes;\r
22a262c8 459 EFI_DEVICE_PATH *InitrdPath;\r
2ccfb71e 460 UINTN InitrdSize;\r
461 UINTN CmdLineSize;\r
22a262c8 462 BOOLEAN InitrdSupport;\r
90a44ec4
OM
463 UINT8* OptionalData;\r
464 UINTN OptionalDataSize;\r
3b3b72d6
OM
465 BOOLEAN IsPrintable;\r
466 BOOLEAN IsUnicode;\r
ea46ebbe 467\r
019680b3
RC
468 DisplayBootOptions (BootOptionsList);\r
469 Status = SelectBootOption (BootOptionsList, UPDATE_BOOT_ENTRY, &BootOptionEntry);\r
470 if (EFI_ERROR (Status)) {\r
ea46ebbe 471 return Status;\r
472 }\r
a6e97d28 473 BootOption = BootOptionEntry->BdsLoadOption;\r
ea46ebbe 474\r
475 // Get the device support for this Boot Option\r
22a262c8 476 Status = BootDeviceGetDeviceSupport (BootOption->FilePathList, &DeviceSupport);\r
ea46ebbe 477 if (EFI_ERROR(Status)) {\r
ff7666c5 478 Print(L"Not possible to retrieve the supported device for the update\n");\r
ea46ebbe 479 return EFI_UNSUPPORTED;\r
480 }\r
481\r
889ac6a8 482 Status = DeviceSupport->UpdateDevicePathNode (BootOption->FilePathList, L"EFI Application or the kernel", &DevicePath);\r
ea46ebbe 483 if (EFI_ERROR(Status)) {\r
484 Status = EFI_ABORTED;\r
485 goto EXIT;\r
486 }\r
487\r
889ac6a8 488 if (DeviceSupport->RequestBootType) {\r
55a9f75d
OM
489 Status = BootDeviceGetType (DevicePath, &BootType, &BootOption->Attributes);\r
490 if (EFI_ERROR(Status)) {\r
491 Status = EFI_ABORTED;\r
492 goto EXIT;\r
493 }\r
494 }\r
495\r
90a44ec4 496 LoaderOptionalData = BootOption->OptionalData;\r
3b3b72d6
OM
497 if (LoaderOptionalData != NULL) {\r
498 BootType = (ARM_BDS_LOADER_TYPE)ReadUnaligned32 ((UINT32 *)(&LoaderOptionalData->Header.LoaderType));\r
499 } else {\r
500 BootType = BDS_LOADER_EFI_APPLICATION;\r
501 }\r
656416bc 502\r
2ccfb71e 503 if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) {\r
90a44ec4 504 LinuxArguments = &LoaderOptionalData->Arguments.LinuxArguments;\r
2ccfb71e 505\r
506 CmdLineSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->CmdLineSize);\r
2ccfb71e 507\r
3e710183 508 InitrdSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->InitrdSize);\r
509 if (InitrdSize > 0) {\r
22a262c8 510 Print(L"Keep the initrd: ");\r
511 } else {\r
512 Print(L"Add an initrd: ");\r
513 }\r
514 Status = GetHIInputBoolean (&InitrdSupport);\r
515 if (EFI_ERROR(Status)) {\r
516 Status = EFI_ABORTED;\r
517 goto EXIT;\r
518 }\r
519\r
520 if (InitrdSupport) {\r
521 if (InitrdSize > 0) {\r
522 // Case we update the initrd device path\r
889ac6a8 523 Status = DeviceSupport->UpdateDevicePathNode ((EFI_DEVICE_PATH*)((UINTN)(LinuxArguments + 1) + CmdLineSize), L"initrd", &InitrdPath);\r
22a262c8 524 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
525 Status = EFI_ABORTED;\r
526 goto EXIT;\r
527 }\r
528 InitrdSize = GetDevicePathSize (InitrdPath);\r
529 } else {\r
530 // Case we create the initrd device path\r
531\r
889ac6a8 532 Status = DeviceSupport->CreateDevicePathNode (L"initrd", &InitrdPathNodes);\r
22a262c8 533 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
534 Status = EFI_ABORTED;\r
535 goto EXIT;\r
536 }\r
537\r
ecc62d13 538 if (InitrdPathNodes != NULL) {\r
22a262c8 539 // Duplicate Linux kernel Device Path\r
14238a61 540 TempInitrdPath = DuplicateDevicePath (BootOption->FilePathList);\r
22a262c8 541 // Replace Linux kernel Node by EndNode\r
14238a61 542 SetDevicePathEndNode (GetLastDevicePathNode (TempInitrdPath));\r
ecc62d13 543 // Append the Device Path to the selected device path\r
544 InitrdPath = AppendDevicePath (TempInitrdPath, (CONST EFI_DEVICE_PATH_PROTOCOL *)InitrdPathNodes);\r
14238a61 545 FreePool (TempInitrdPath);\r
830e5b8c
OM
546 // Free the InitrdPathNodes created by Support->CreateDevicePathNode()\r
547 FreePool (InitrdPathNodes);\r
ecc62d13 548 if (InitrdPath == NULL) {\r
549 Status = EFI_OUT_OF_RESOURCES;\r
550 goto EXIT;\r
551 }\r
14238a61 552 InitrdSize = GetDevicePathSize (InitrdPath);\r
22a262c8 553 } else {\r
554 InitrdPath = NULL;\r
555 }\r
3e710183 556 }\r
22a262c8 557 } else {\r
558 InitrdSize = 0;\r
656416bc 559 }\r
560\r
aeaf64d6 561 Print(L"Arguments to pass to the binary: ");\r
2ccfb71e 562 if (CmdLineSize > 0) {\r
4477336d
RC
563 AsciiStrnCpy (CmdLine, (CONST CHAR8*)(LinuxArguments + 1), sizeof (CmdLine));\r
564 CmdLine[sizeof (CmdLine) - 1] = '\0';\r
656416bc 565 } else {\r
2ccfb71e 566 CmdLine[0] = '\0';\r
656416bc 567 }\r
2ccfb71e 568 Status = EditHIInputAscii (CmdLine, BOOT_DEVICE_OPTION_MAX);\r
656416bc 569 if (EFI_ERROR(Status)) {\r
570 Status = EFI_ABORTED;\r
571 goto FREE_DEVICE_PATH;\r
572 }\r
2ccfb71e 573\r
574 CmdLineSize = AsciiStrSize (CmdLine);\r
2ccfb71e 575\r
90a44ec4
OM
576 OptionalDataSize = sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize;\r
577 BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (OptionalDataSize);\r
2ccfb71e 578 BootArguments->LinuxArguments.CmdLineSize = CmdLineSize;\r
579 BootArguments->LinuxArguments.InitrdSize = InitrdSize;\r
580 CopyMem (&BootArguments->LinuxArguments + 1, CmdLine, CmdLineSize);\r
49a25d84 581 CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize), InitrdPath, InitrdSize);\r
90a44ec4
OM
582\r
583 OptionalData = (UINT8*)BootArguments;\r
2ccfb71e 584 } else {\r
3b3b72d6
OM
585 Print (L"Arguments to pass to the EFI Application: ");\r
586\r
587 if (BootOption->OptionalDataSize > 0) {\r
588 IsPrintable = IsPrintableString (BootOption->OptionalData, &IsUnicode);\r
589 if (IsPrintable) {\r
4477336d
RC
590 //\r
591 // The size in bytes of the string, final zero included, should\r
592 // be equal to or at least lower than "BootOption->OptionalDataSize"\r
593 // and the "IsPrintableString()" has already tested that the length\r
594 // in number of characters is smaller than BOOT_DEVICE_OPTION_MAX,\r
595 // final '\0' included. We can thus copy the string for editing\r
596 // using "CopyMem()". Furthermore, note that in the case of an Unicode\r
597 // string "StrnCpy()" and "StrCpy()" can not be used to copy the\r
598 // string because the data pointed to by "BootOption->OptionalData"\r
599 // is not necessarily 2-byte aligned.\r
600 //\r
3b3b72d6 601 if (IsUnicode) {\r
4477336d
RC
602 CopyMem (\r
603 UnicodeCmdLine, BootOption->OptionalData,\r
604 MIN (sizeof (UnicodeCmdLine),\r
605 BootOption->OptionalDataSize)\r
606 );\r
3b3b72d6 607 } else {\r
4477336d
RC
608 CopyMem (\r
609 CmdLine, BootOption->OptionalData,\r
610 MIN (sizeof (CmdLine),\r
611 BootOption->OptionalDataSize)\r
612 );\r
3b3b72d6
OM
613 }\r
614 }\r
615 } else {\r
616 UnicodeCmdLine[0] = L'\0';\r
617 IsPrintable = TRUE;\r
618 IsUnicode = TRUE;\r
619 }\r
620\r
621 // We do not request arguments for OptionalData that cannot be printed\r
622 if (IsPrintable) {\r
623 if (IsUnicode) {\r
624 Status = EditHIInputStr (UnicodeCmdLine, BOOT_DEVICE_OPTION_MAX);\r
625 if (EFI_ERROR (Status)) {\r
626 Status = EFI_ABORTED;\r
627 goto FREE_DEVICE_PATH;\r
628 }\r
629\r
630 OptionalData = (UINT8*)UnicodeCmdLine;\r
631 OptionalDataSize = StrSize (UnicodeCmdLine);\r
632 } else {\r
633 Status = EditHIInputAscii (CmdLine, BOOT_DEVICE_OPTION_MAX);\r
634 if (EFI_ERROR (Status)) {\r
635 Status = EFI_ABORTED;\r
636 goto FREE_DEVICE_PATH;\r
637 }\r
638\r
639 OptionalData = (UINT8*)CmdLine;\r
640 OptionalDataSize = AsciiStrSize (CmdLine);\r
641 }\r
642 } else {\r
643 // We keep the former OptionalData\r
644 OptionalData = BootOption->OptionalData;\r
645 OptionalDataSize = BootOption->OptionalDataSize;\r
646 }\r
ea46ebbe 647 }\r
648\r
649 Print(L"Description for this new Entry: ");\r
3e710183 650 StrnCpy (BootDescription, BootOption->Description, BOOT_DEVICE_DESCRIPTION_MAX);\r
74b96132 651 Status = EditHIInputStr (BootDescription, BOOT_DEVICE_DESCRIPTION_MAX);\r
ea46ebbe 652 if (EFI_ERROR(Status)) {\r
653 Status = EFI_ABORTED;\r
654 goto FREE_DEVICE_PATH;\r
655 }\r
656\r
ea46ebbe 657 // Update the entry\r
90a44ec4 658 Status = BootOptionUpdate (BootOption, BootOption->Attributes, BootDescription, DevicePath, BootType, OptionalData, OptionalDataSize);\r
ea46ebbe 659\r
ea46ebbe 660FREE_DEVICE_PATH:\r
661 FreePool (DevicePath);\r
662\r
663EXIT:\r
326d1df9 664 if (Status == EFI_ABORTED) {\r
665 Print(L"\n");\r
666 }\r
ea46ebbe 667 return Status;\r
668}\r
669\r
019680b3
RC
670/**\r
671 Reorder boot options\r
672\r
673 Ask for the boot option to move and then move it when up or down arrows\r
674 are pressed. This function is called when the user selects the "Reorder Boot\r
675 Device Entries" entry in the boot manager menu.\r
676 The order of the boot options in BootOptionList and in the UEFI BootOrder\r
677 global variable are kept coherent until the user confirm his reordering (ie:\r
678 he does not exit by pressing escape).\r
679\r
680 @param[in] BootOptionsList List of the boot devices constructed in\r
681 BootMenuMain()\r
682\r
683 @retval EFI_SUCCESS No error encountered.\r
684 @retval !EFI_SUCCESS An error has occured either in the selection of the\r
685 boot option to move or while interacting with the user.\r
686\r
687**/\r
688STATIC\r
689EFI_STATUS\r
690BootMenuReorderBootOptions (\r
691 IN LIST_ENTRY *BootOptionsList\r
692 )\r
693{\r
694 EFI_STATUS Status;\r
695 BDS_LOAD_OPTION_ENTRY *BootOptionEntry;\r
696 LIST_ENTRY *SelectedEntry;\r
697 LIST_ENTRY *PrevEntry;\r
698 BOOLEAN Move;\r
699 BOOLEAN Save;\r
700 BOOLEAN Cancel;\r
701 UINTN WaitIndex;\r
702 EFI_INPUT_KEY Key;\r
703 LIST_ENTRY *SecondEntry;\r
704 UINTN BootOrderSize;\r
705 UINT16 *BootOrder;\r
706 LIST_ENTRY *Entry;\r
707 UINTN Index;\r
708\r
709 DisplayBootOptions (BootOptionsList);\r
710\r
711 // Ask to select the boot option to move\r
712 while (TRUE) {\r
713 Status = SelectBootOption (BootOptionsList, MOVE_BOOT_ENTRY, &BootOptionEntry);\r
714 if (EFI_ERROR (Status)) {\r
715 goto ErrorExit;\r
716 }\r
717\r
718 SelectedEntry = &BootOptionEntry->Link;\r
749d91f7 719 SecondEntry = NULL;\r
019680b3
RC
720 // Note down the previous entry in the list to be able to cancel changes\r
721 PrevEntry = GetPreviousNode (BootOptionsList, SelectedEntry);\r
722\r
723 // Start of interaction\r
724 while (TRUE) {\r
725 Print (\r
726 L"* Use up/down arrows to move the entry '%s'",\r
727 BootOptionEntry->BdsLoadOption->Description\r
728 );\r
729\r
730 // Wait for a move, save or cancel request\r
731 Move = FALSE;\r
732 Save = FALSE;\r
733 Cancel = FALSE;\r
734 do {\r
735 Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &WaitIndex);\r
736 if (!EFI_ERROR (Status)) {\r
737 Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
738 }\r
739 if (EFI_ERROR (Status)) {\r
740 Print (L"\n");\r
741 goto ErrorExit;\r
742 }\r
743\r
744 switch (Key.ScanCode) {\r
745 case SCAN_NULL:\r
746 Save = (Key.UnicodeChar == CHAR_LINEFEED) ||\r
747 (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) ||\r
748 (Key.UnicodeChar == 0x7f);\r
749 break;\r
750\r
751 case SCAN_UP:\r
752 SecondEntry = GetPreviousNode (BootOptionsList, SelectedEntry);\r
753 Move = SecondEntry != BootOptionsList;\r
754 break;\r
755\r
756 case SCAN_DOWN:\r
757 SecondEntry = GetNextNode (BootOptionsList, SelectedEntry);\r
758 Move = SecondEntry != BootOptionsList;\r
759 break;\r
760\r
761 case SCAN_ESC:\r
762 Cancel = TRUE;\r
763 break;\r
764 }\r
765 } while ((!Move) && (!Save) && (!Cancel));\r
766\r
767 if (Move) {\r
749d91f7
HL
768 if ((SelectedEntry != NULL) && (SecondEntry != NULL)) {\r
769 SwapListEntries (SelectedEntry, SecondEntry);\r
770 }\r
019680b3
RC
771 } else {\r
772 if (Save) {\r
773 Status = GetGlobalEnvironmentVariable (\r
774 L"BootOrder", NULL, &BootOrderSize, (VOID**)&BootOrder\r
775 );\r
776 BootOrderSize /= sizeof (UINT16);\r
777\r
778 if (!EFI_ERROR (Status)) {\r
779 // The order of the boot options in the 'BootOptionsList' is the\r
780 // new order that has been just defined by the user. Save this new\r
781 // order in "BootOrder" UEFI global variable.\r
782 Entry = GetFirstNode (BootOptionsList);\r
783 for (Index = 0; Index < BootOrderSize; Index++) {\r
784 BootOrder[Index] = (LOAD_OPTION_FROM_LINK (Entry))->LoadOptionIndex;\r
785 Entry = GetNextNode (BootOptionsList, Entry);\r
786 }\r
787 Status = gRT->SetVariable (\r
788 (CHAR16*)L"BootOrder",\r
789 &gEfiGlobalVariableGuid,\r
790 EFI_VARIABLE_NON_VOLATILE |\r
791 EFI_VARIABLE_BOOTSERVICE_ACCESS |\r
792 EFI_VARIABLE_RUNTIME_ACCESS,\r
793 BootOrderSize * sizeof (UINT16),\r
794 BootOrder\r
795 );\r
796 FreePool (BootOrder);\r
797 }\r
798\r
799 if (EFI_ERROR (Status)) {\r
800 Print (L"\nAn error occurred, move not completed!\n");\r
801 Cancel = TRUE;\r
802 }\r
803 }\r
804\r
805 if (Cancel) {\r
806 //\r
807 // Restore initial position of the selected boot option\r
808 //\r
809 RemoveEntryList (SelectedEntry);\r
810 InsertHeadList (PrevEntry, SelectedEntry);\r
811 }\r
812 }\r
813\r
814 Print (L"\n");\r
815 DisplayBootOptions (BootOptionsList);\r
816 // Saved or cancelled, back to the choice of boot option to move\r
817 if (!Move) {\r
818 break;\r
819 }\r
820 }\r
821 }\r
822\r
823ErrorExit:\r
824 return Status ;\r
825}\r
826\r
42de0937
RC
827/**\r
828 Set boot timeout\r
829\r
830 Ask for the boot timeout in seconds and if the input succeeds assign the\r
831 input value to the UEFI global variable "Timeout". This function is called\r
832 when the user selects the "Set Boot Timeout" of the boot manager menu.\r
833\r
834 @param[in] BootOptionsList List of the boot devices, not used here\r
835\r
836 @retval EFI_SUCCESS Boot timeout in second retrieved from the standard\r
837 input and assigned to the UEFI "Timeout" global\r
838 variable\r
839 @retval !EFI_SUCCESS Either the input or the setting of the UEFI global\r
840 variable "Timeout" has failed.\r
841**/\r
842EFI_STATUS\r
843STATIC\r
844BootMenuSetBootTimeout (\r
845 IN LIST_ENTRY *BootOptionsList\r
846 )\r
847{\r
848 EFI_STATUS Status;\r
849 UINTN Input;\r
850 UINT16 Timeout;\r
851\r
852 Print (L"Timeout duration (in seconds): ");\r
853 Status = GetHIInputInteger (&Input);\r
854 if (EFI_ERROR (Status)) {\r
855 Print (L"\n");\r
856 goto ErrorExit;\r
857 }\r
858\r
859 Timeout = Input;\r
860 Status = gRT->SetVariable (\r
861 (CHAR16*)L"Timeout",\r
862 &gEfiGlobalVariableGuid,\r
863 EFI_VARIABLE_NON_VOLATILE |\r
864 EFI_VARIABLE_BOOTSERVICE_ACCESS |\r
865 EFI_VARIABLE_RUNTIME_ACCESS,\r
866 sizeof (UINT16),\r
867 &Timeout\r
868 );\r
869 ASSERT_EFI_ERROR (Status);\r
870\r
871ErrorExit:\r
872 return Status;\r
873}\r
874\r
ea46ebbe 875struct BOOT_MANAGER_ENTRY {\r
876 CONST CHAR16* Description;\r
877 EFI_STATUS (*Callback) (IN LIST_ENTRY *BootOptionsList);\r
878} BootManagerEntries[] = {\r
879 { L"Add Boot Device Entry", BootMenuAddBootOption },\r
880 { L"Update Boot Device Entry", BootMenuUpdateBootOption },\r
881 { L"Remove Boot Device Entry", BootMenuRemoveBootOption },\r
019680b3 882 { L"Reorder Boot Device Entries", BootMenuReorderBootOptions },\r
42de0937 883 { L"Set Boot Timeout", BootMenuSetBootTimeout },\r
ea46ebbe 884};\r
885\r
886EFI_STATUS\r
887BootMenuManager (\r
888 IN LIST_ENTRY *BootOptionsList\r
889 )\r
890{\r
891 UINTN Index;\r
892 UINTN OptionSelected;\r
893 UINTN BootManagerEntryCount;\r
894 EFI_STATUS Status;\r
895\r
896 BootManagerEntryCount = sizeof(BootManagerEntries) / sizeof(struct BOOT_MANAGER_ENTRY);\r
897\r
898 while (TRUE) {\r
899 // Display Boot Manager menu\r
900 for (Index = 0; Index < BootManagerEntryCount; Index++) {\r
901 Print(L"[%d] %s\n",Index+1,BootManagerEntries[Index]);\r
902 }\r
903 Print(L"[%d] Return to main menu\n",Index+1);\r
904\r
905 // Select which entry to call\r
906 Print(L"Choice: ");\r
907 Status = GetHIInputInteger (&OptionSelected);\r
908 if (EFI_ERROR(Status) || (OptionSelected == (BootManagerEntryCount+1))) {\r
326d1df9 909 if (EFI_ERROR(Status)) {\r
910 Print(L"\n");\r
911 }\r
ea46ebbe 912 return EFI_SUCCESS;\r
913 } else if ((OptionSelected > 0) && (OptionSelected <= BootManagerEntryCount)) {\r
ff7666c5 914 BootManagerEntries[OptionSelected-1].Callback (BootOptionsList);\r
ea46ebbe 915 }\r
916 }\r
11c20f4e 917 // Should never go here\r
ea46ebbe 918}\r
919\r
920EFI_STATUS\r
8213627e 921BootShell (\r
ea46ebbe 922 IN LIST_ENTRY *BootOptionsList\r
923 )\r
924{\r
925 EFI_STATUS Status;\r
926\r
927 // Start EFI Shell\r
c3b6d975 928 Status = BdsLoadApplication (gImageHandle, L"Shell", 0, NULL);\r
ea46ebbe 929 if (Status == EFI_NOT_FOUND) {\r
930 Print (L"Error: EFI Application not found.\n");\r
931 } else if (EFI_ERROR(Status)) {\r
932 Print (L"Error: Status Code: 0x%X\n",(UINT32)Status);\r
933 }\r
934\r
935 return Status;\r
936}\r
937\r
938struct BOOT_MAIN_ENTRY {\r
939 CONST CHAR16* Description;\r
940 EFI_STATUS (*Callback) (IN LIST_ENTRY *BootOptionsList);\r
941} BootMainEntries[] = {\r
8213627e 942 { L"Shell", BootShell },\r
ea46ebbe 943 { L"Boot Manager", BootMenuManager },\r
944};\r
945\r
946\r
947EFI_STATUS\r
948BootMenuMain (\r
949 VOID\r
950 )\r
951{\r
2ccfb71e 952 LIST_ENTRY BootOptionsList;\r
953 UINTN OptionCount;\r
954 UINTN BootOptionCount;\r
955 EFI_STATUS Status;\r
956 LIST_ENTRY* Entry;\r
957 BDS_LOAD_OPTION* BootOption;\r
958 UINTN BootOptionSelected;\r
959 UINTN Index;\r
960 UINTN BootMainEntryCount;\r
5389972a 961 BOOLEAN IsUnicode;\r
ea46ebbe 962\r
5389972a 963 BootOption = NULL;\r
ea46ebbe 964 BootMainEntryCount = sizeof(BootMainEntries) / sizeof(struct BOOT_MAIN_ENTRY);\r
a6caee65 965\r
ea46ebbe 966 while (TRUE) {\r
a6e97d28 967 // Get Boot#### list\r
968 BootOptionList (&BootOptionsList);\r
969\r
ea46ebbe 970 OptionCount = 1;\r
971\r
972 // Display the Boot options\r
973 for (Entry = GetFirstNode (&BootOptionsList);\r
974 !IsNull (&BootOptionsList,Entry);\r
975 Entry = GetNextNode (&BootOptionsList,Entry)\r
976 )\r
977 {\r
978 BootOption = LOAD_OPTION_FROM_LINK(Entry);\r
979\r
ff7666c5 980 Print(L"[%d] %s\n", OptionCount, BootOption->Description);\r
ea46ebbe 981\r
982 DEBUG_CODE_BEGIN();\r
983 CHAR16* DevicePathTxt;\r
984 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL* DevicePathToTextProtocol;\r
2ccfb71e 985 ARM_BDS_LOADER_OPTIONAL_DATA* OptionalData;\r
986 UINTN CmdLineSize;\r
3e710183 987 ARM_BDS_LOADER_TYPE LoaderType;\r
ea46ebbe 988\r
ff7666c5 989 Status = gBS->LocateProtocol (&gEfiDevicePathToTextProtocolGuid, NULL, (VOID **)&DevicePathToTextProtocol);\r
aa95e2f7 990 if (EFI_ERROR(Status)) {\r
991 // You must provide an implementation of DevicePathToTextProtocol in your firmware (eg: DevicePathDxe)\r
992 DEBUG((EFI_D_ERROR,"Error: Bds requires DevicePathToTextProtocol\n"));\r
993 return Status;\r
994 }\r
ff7666c5 995 DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (BootOption->FilePathList, TRUE, TRUE);\r
ea46ebbe 996\r
997 Print(L"\t- %s\n",DevicePathTxt);\r
2ccfb71e 998\r
999 // If it is a supported BootEntry then print its details\r
1000 if (IS_ARM_BDS_BOOTENTRY (BootOption)) {\r
1001 OptionalData = BootOption->OptionalData;\r
1002 LoaderType = (ARM_BDS_LOADER_TYPE)ReadUnaligned32 ((CONST UINT32*)&OptionalData->Header.LoaderType);\r
1003 if ((LoaderType == BDS_LOADER_KERNEL_LINUX_ATAG) || (LoaderType == BDS_LOADER_KERNEL_LINUX_FDT)) {\r
1004 if (ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.InitrdSize) > 0) {\r
1005 CmdLineSize = ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.CmdLineSize);\r
1006 DevicePathTxt = DevicePathToTextProtocol->ConvertDevicePathToText (\r
1007 GetAlignedDevicePath ((EFI_DEVICE_PATH*)((UINTN)(&OptionalData->Arguments.LinuxArguments + 1) + CmdLineSize)), TRUE, TRUE);\r
1008 Print(L"\t- Initrd: %s\n", DevicePathTxt);\r
1009 }\r
5aecd343
OM
1010 if (ReadUnaligned16 (&OptionalData->Arguments.LinuxArguments.CmdLineSize) > 0) {\r
1011 Print(L"\t- Arguments: %a\n", (&OptionalData->Arguments.LinuxArguments + 1));\r
1012 }\r
ea46ebbe 1013 }\r
7135d76d 1014\r
1015 switch (LoaderType) {\r
1016 case BDS_LOADER_EFI_APPLICATION:\r
1017 Print(L"\t- LoaderType: EFI Application\n");\r
1018 break;\r
1019\r
1020 case BDS_LOADER_KERNEL_LINUX_ATAG:\r
1021 Print(L"\t- LoaderType: Linux kernel with ATAG support\n");\r
1022 break;\r
1023\r
1024 case BDS_LOADER_KERNEL_LINUX_FDT:\r
1025 Print(L"\t- LoaderType: Linux kernel with FDT support\n");\r
1026 break;\r
1027\r
1028 default:\r
1029 Print(L"\t- LoaderType: Not recognized (%d)\n", LoaderType);\r
1030 }\r
5389972a
OM
1031 } else if (BootOption->OptionalData != NULL) {\r
1032 if (IsPrintableString (BootOption->OptionalData, &IsUnicode)) {\r
1033 if (IsUnicode) {\r
1034 Print (L"\t- Arguments: %s\n", BootOption->OptionalData);\r
1035 } else {\r
1036 AsciiPrint ("\t- Arguments: %a\n", BootOption->OptionalData);\r
1037 }\r
1038 }\r
ea46ebbe 1039 }\r
ea46ebbe 1040 FreePool(DevicePathTxt);\r
1041 DEBUG_CODE_END();\r
1042\r
1043 OptionCount++;\r
1044 }\r
1045 BootOptionCount = OptionCount-1;\r
1046\r
1047 // Display the hardcoded Boot entries\r
1048 for (Index = 0; Index < BootMainEntryCount; Index++) {\r
1049 Print(L"[%d] %s\n",OptionCount,BootMainEntries[Index]);\r
1050 OptionCount++;\r
1051 }\r
1052\r
1053 // Request the boot entry from the user\r
1054 BootOptionSelected = 0;\r
1055 while (BootOptionSelected == 0) {\r
1056 Print(L"Start: ");\r
1057 Status = GetHIInputInteger (&BootOptionSelected);\r
1058 if (EFI_ERROR(Status) || (BootOptionSelected == 0) || (BootOptionSelected > OptionCount)) {\r
1059 Print(L"Invalid input (max %d)\n",(OptionCount-1));\r
1060 BootOptionSelected = 0;\r
1061 }\r
1062 }\r
1063\r
1064 // Start the selected entry\r
1065 if (BootOptionSelected > BootOptionCount) {\r
1066 // Start the hardcoded entry\r
1067 Status = BootMainEntries[BootOptionSelected - BootOptionCount - 1].Callback (&BootOptionsList);\r
1068 } else {\r
1069 // Find the selected entry from the Boot#### list\r
1070 Index = 1;\r
1071 for (Entry = GetFirstNode (&BootOptionsList);\r
1072 !IsNull (&BootOptionsList,Entry);\r
1073 Entry = GetNextNode (&BootOptionsList,Entry)\r
1074 )\r
1075 {\r
1076 if (Index == BootOptionSelected) {\r
1077 BootOption = LOAD_OPTION_FROM_LINK(Entry);\r
1078 break;\r
1079 }\r
1080 Index++;\r
1081 }\r
1082\r
1083 Status = BootOptionStart (BootOption);\r
1084 }\r
1085 }\r
11c20f4e 1086 // Should never go here\r
ea46ebbe 1087}\r