]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - Nt32Pkg/Library/PlatformBootManagerLib/PlatformBootManager.c
Nt32Pkg/PlatformBDS: Implement PlatformBootManagerUnableToBoot
[mirror_edk2.git] / Nt32Pkg / Library / PlatformBootManagerLib / PlatformBootManager.c
... / ...
CommitLineData
1/** @file\r
2 This file include all platform action which can be customized\r
3 by IBV/OEM.\r
4\r
5Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
6(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
7This program and the accompanying materials\r
8are licensed and made available under the terms and conditions of the BSD License\r
9which accompanies this distribution. The full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include "PlatformBootManager.h"\r
18\r
19EFI_GUID mBootMenuFile = {\r
20 0xEEC25BDC, 0x67F2, 0x4D95, { 0xB1, 0xD5, 0xF8, 0x1B, 0x20, 0x39, 0xD1, 0x1D }\r
21};\r
22\r
23/**\r
24 Perform the platform diagnostic, such like test memory. OEM/IBV also\r
25 can customize this function to support specific platform diagnostic.\r
26\r
27 @param MemoryTestLevel The memory test intensive level\r
28 @param QuietBoot Indicate if need to enable the quiet boot\r
29\r
30**/\r
31VOID\r
32PlatformBootManagerDiagnostics (\r
33 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel,\r
34 IN BOOLEAN QuietBoot\r
35 )\r
36{\r
37 EFI_STATUS Status;\r
38\r
39 //\r
40 // Here we can decide if we need to show\r
41 // the diagnostics screen\r
42 // Notes: this quiet boot code should be remove\r
43 // from the graphic lib\r
44 //\r
45 if (QuietBoot) {\r
46 BootLogoEnableLogo ();\r
47\r
48 //\r
49 // Perform system diagnostic\r
50 //\r
51 Status = PlatformBootManagerMemoryTest (MemoryTestLevel);\r
52 if (EFI_ERROR (Status)) {\r
53 BootLogoDisableLogo ();\r
54 }\r
55\r
56 return;\r
57 }\r
58\r
59 //\r
60 // Perform system diagnostic\r
61 //\r
62 Status = PlatformBootManagerMemoryTest (MemoryTestLevel);\r
63}\r
64\r
65/**\r
66 Do the platform specific action before the console is connected.\r
67\r
68 Such as:\r
69 Update console variable;\r
70 Register new Driver#### or Boot####;\r
71 Signal ReadyToLock event.\r
72**/\r
73VOID\r
74EFIAPI\r
75PlatformBootManagerBeforeConsole (\r
76 VOID\r
77 )\r
78{\r
79 UINTN Index;\r
80 EFI_STATUS Status;\r
81 WIN_NT_SYSTEM_CONFIGURATION *Configuration;\r
82\r
83 GetVariable2 (L"Setup", &gEfiWinNtSystemConfigGuid, (VOID **) &Configuration, NULL);\r
84 if (Configuration != NULL) {\r
85 //\r
86 // SetupVariable is corrupt\r
87 //\r
88 Configuration->ConOutRow = PcdGet32 (PcdConOutColumn);\r
89 Configuration->ConOutColumn = PcdGet32 (PcdConOutRow);\r
90\r
91 Status = gRT->SetVariable (\r
92 L"Setup",\r
93 &gEfiWinNtSystemConfigGuid,\r
94 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,\r
95 sizeof (WIN_NT_SYSTEM_CONFIGURATION),\r
96 Configuration\r
97 );\r
98 if (EFI_ERROR (Status)) {\r
99 DEBUG ((EFI_D_ERROR, "Failed to save Setup Variable to non-volatile storage, Status = %r\n", Status));\r
100 }\r
101 FreePool (Configuration);\r
102 }\r
103\r
104 //\r
105 // Update the ocnsole variables.\r
106 //\r
107 for (Index = 0; gPlatformConsole[Index].DevicePath != NULL; Index++) {\r
108 if ((gPlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {\r
109 EfiBootManagerUpdateConsoleVariable (ConIn, gPlatformConsole[Index].DevicePath, NULL);\r
110 }\r
111\r
112 if ((gPlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {\r
113 EfiBootManagerUpdateConsoleVariable (ConOut, gPlatformConsole[Index].DevicePath, NULL);\r
114 }\r
115\r
116 if ((gPlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {\r
117 EfiBootManagerUpdateConsoleVariable (ErrOut, gPlatformConsole[Index].DevicePath, NULL);\r
118 }\r
119 }\r
120\r
121 //\r
122 // From PI spec vol2:\r
123 // Prior to invoking any UEFI drivers, applications, or connecting consoles, \r
124 // the platform should signal the event EFI_END_OF_DXE_EVENT_GUID\r
125 //\r
126 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);\r
127\r
128 //\r
129 // Dispatch deferred images after EndOfDxe event.\r
130 //\r
131 EfiBootManagerDispatchDeferredImages ();\r
132}\r
133\r
134/**\r
135 Returns the priority number.\r
136\r
137 @param BootOption\r
138**/\r
139UINTN\r
140BootOptionPriority (\r
141 CONST EFI_BOOT_MANAGER_LOAD_OPTION *BootOption\r
142 )\r
143{\r
144 //\r
145 // Make sure Shell is first\r
146 //\r
147 if (StrCmp (BootOption->Description, L"UEFI Shell") == 0) {\r
148 return 0;\r
149 }\r
150 return 100;\r
151}\r
152\r
153INTN\r
154EFIAPI\r
155CompareBootOption (\r
156 CONST EFI_BOOT_MANAGER_LOAD_OPTION *Left,\r
157 CONST EFI_BOOT_MANAGER_LOAD_OPTION *Right\r
158 )\r
159{\r
160 return BootOptionPriority (Left) - BootOptionPriority (Right);\r
161}\r
162\r
163/**\r
164 Generate device path include the input file guid info.\r
165\r
166 @param FileGuid Input file guid for the BootManagerMenuApp.\r
167\r
168 @retval DevicePath for BootManagerMenuApp.\r
169**/\r
170EFI_DEVICE_PATH *\r
171FvFilePath (\r
172 EFI_GUID *FileGuid\r
173 )\r
174{\r
175\r
176 EFI_STATUS Status;\r
177 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
178 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;\r
179\r
180 EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);\r
181\r
182 Status = gBS->HandleProtocol (\r
183 gImageHandle,\r
184 &gEfiLoadedImageProtocolGuid,\r
185 (VOID **) &LoadedImage\r
186 );\r
187 ASSERT_EFI_ERROR (Status);\r
188\r
189 return AppendDevicePathNode (\r
190 DevicePathFromHandle (LoadedImage->DeviceHandle),\r
191 (EFI_DEVICE_PATH_PROTOCOL *) &FileNode\r
192 );\r
193}\r
194\r
195/**\r
196 Create one boot option for BootManagerMenuApp.\r
197\r
198 @param FileGuid Input file guid for the BootManagerMenuApp.\r
199 @param Description Description of the BootManagerMenuApp boot option.\r
200 @param Position Position of the new load option to put in the ****Order variable.\r
201 @param IsBootCategory Whether this is a boot category.\r
202\r
203\r
204 @retval OptionNumber Return the option number info.\r
205\r
206**/\r
207UINTN\r
208RegisterBootManagerMenuAppBootOption (\r
209 EFI_GUID *FileGuid,\r
210 CHAR16 *Description,\r
211 UINTN Position,\r
212 BOOLEAN IsBootCategory\r
213 )\r
214{\r
215 EFI_STATUS Status;\r
216 EFI_BOOT_MANAGER_LOAD_OPTION NewOption;\r
217 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
218 UINTN OptionNumber;\r
219\r
220 DevicePath = FvFilePath (FileGuid);\r
221 Status = EfiBootManagerInitializeLoadOption (\r
222 &NewOption,\r
223 LoadOptionNumberUnassigned,\r
224 LoadOptionTypeBoot,\r
225 IsBootCategory ? LOAD_OPTION_ACTIVE : LOAD_OPTION_CATEGORY_APP,\r
226 Description,\r
227 DevicePath,\r
228 NULL,\r
229 0\r
230 );\r
231 ASSERT_EFI_ERROR (Status);\r
232 FreePool (DevicePath);\r
233\r
234 Status = EfiBootManagerAddLoadOptionVariable (&NewOption, Position);\r
235 ASSERT_EFI_ERROR (Status);\r
236\r
237 OptionNumber = NewOption.OptionNumber;\r
238\r
239 EfiBootManagerFreeLoadOption (&NewOption);\r
240\r
241 return OptionNumber;\r
242}\r
243\r
244/**\r
245 Check if it's a Device Path pointing to BootManagerMenuApp.\r
246\r
247 @param DevicePath Input device path.\r
248\r
249 @retval TRUE The device path is BootManagerMenuApp File Device Path.\r
250 @retval FALSE The device path is NOT BootManagerMenuApp File Device Path.\r
251**/\r
252BOOLEAN\r
253IsBootManagerMenuAppFilePath (\r
254 EFI_DEVICE_PATH_PROTOCOL *DevicePath\r
255)\r
256{\r
257 EFI_HANDLE FvHandle;\r
258 VOID *NameGuid;\r
259 EFI_STATUS Status;\r
260\r
261 Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &DevicePath, &FvHandle);\r
262 if (!EFI_ERROR (Status)) {\r
263 NameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) DevicePath);\r
264 if (NameGuid != NULL) {\r
265 return CompareGuid (NameGuid, &mBootMenuFile);\r
266 }\r
267 }\r
268\r
269 return FALSE;\r
270}\r
271\r
272/**\r
273 Return the boot option number to the BootManagerMenuApp.\r
274\r
275 If not found it in the current boot option, create a new one.\r
276\r
277 @retval OptionNumber Return the boot option number to the BootManagerMenuApp.\r
278\r
279**/\r
280UINTN\r
281GetBootManagerMenuAppOption (\r
282 VOID\r
283 )\r
284{\r
285 UINTN BootOptionCount;\r
286 EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
287 UINTN Index;\r
288 UINTN OptionNumber;\r
289\r
290 OptionNumber = 0;\r
291\r
292 BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
293\r
294 for (Index = 0; Index < BootOptionCount; Index++) {\r
295 if (IsBootManagerMenuAppFilePath (BootOptions[Index].FilePath)) {\r
296 OptionNumber = BootOptions[Index].OptionNumber;\r
297 break;\r
298 }\r
299 }\r
300\r
301 EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
302\r
303 if (Index >= BootOptionCount) {\r
304 //\r
305 // If not found the BootManagerMenuApp, create it.\r
306 //\r
307 OptionNumber = (UINT16) RegisterBootManagerMenuAppBootOption (&mBootMenuFile, L"UEFI BootManagerMenuApp", (UINTN) -1, FALSE);\r
308 }\r
309\r
310 return OptionNumber;\r
311}\r
312\r
313/**\r
314 Do the platform specific action after the console is connected.\r
315\r
316 Such as:\r
317 Dynamically switch output mode;\r
318 Signal console ready platform customized event;\r
319 Run diagnostics like memory testing;\r
320 Connect certain devices;\r
321 Dispatch aditional option roms.\r
322**/\r
323VOID\r
324EFIAPI\r
325PlatformBootManagerAfterConsole (\r
326 VOID\r
327 )\r
328{\r
329 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black;\r
330 EFI_GRAPHICS_OUTPUT_BLT_PIXEL White;\r
331 EFI_INPUT_KEY Enter;\r
332 EFI_INPUT_KEY F2;\r
333 EFI_INPUT_KEY F7;\r
334 EFI_BOOT_MANAGER_LOAD_OPTION BootOption;\r
335 UINTN OptionNumber;\r
336\r
337 Black.Blue = Black.Green = Black.Red = Black.Reserved = 0;\r
338 White.Blue = White.Green = White.Red = White.Reserved = 0xFF;\r
339\r
340 EfiBootManagerConnectAll ();\r
341 EfiBootManagerRefreshAllBootOption ();\r
342\r
343 //\r
344 // Register ENTER as CONTINUE key\r
345 //\r
346 Enter.ScanCode = SCAN_NULL;\r
347 Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;\r
348 EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);\r
349 //\r
350 // Map F2 to Boot Manager Menu\r
351 //\r
352 F2.ScanCode = SCAN_F2;\r
353 F2.UnicodeChar = CHAR_NULL;\r
354 EfiBootManagerGetBootManagerMenu (&BootOption);\r
355 EfiBootManagerAddKeyOptionVariable (NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL);\r
356\r
357 //\r
358 // 3. Boot Device List menu\r
359 //\r
360 F7.ScanCode = SCAN_F7;\r
361 F7.UnicodeChar = CHAR_NULL;\r
362 OptionNumber = GetBootManagerMenuAppOption ();\r
363 EfiBootManagerAddKeyOptionVariable (NULL, (UINT16)OptionNumber, 0, &F7, NULL);\r
364\r
365 //\r
366 // Make Shell as the first boot option\r
367 //\r
368 EfiBootManagerSortLoadOptionVariable (LoadOptionTypeBoot, (SORT_COMPARE) CompareBootOption);\r
369\r
370 PlatformBootManagerDiagnostics (QUICK, TRUE);\r
371\r
372 PrintXY (10, 10, &White, &Black, L"F2 to enter Setup. ");\r
373 PrintXY (10, 30, &White, &Black, L"F7 to enter Boot Manager Menu.");\r
374 PrintXY (10, 50, &White, &Black, L"Enter to boot directly.");\r
375}\r
376\r
377/**\r
378 This function is called each second during the boot manager waits the timeout.\r
379\r
380 @param TimeoutRemain The remaining timeout.\r
381**/\r
382VOID\r
383EFIAPI\r
384PlatformBootManagerWaitCallback (\r
385 UINT16 TimeoutRemain\r
386 )\r
387{\r
388 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black;\r
389 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White;\r
390 UINT16 Timeout;\r
391\r
392 Timeout = PcdGet16 (PcdPlatformBootTimeOut);\r
393\r
394 Black.Raw = 0x00000000;\r
395 White.Raw = 0x00FFFFFF;\r
396\r
397 BootLogoUpdateProgress (\r
398 White.Pixel,\r
399 Black.Pixel,\r
400 L"Start boot option",\r
401 White.Pixel,\r
402 (Timeout - TimeoutRemain) * 100 / Timeout,\r
403 0\r
404 );\r
405}\r
406\r
407/**\r
408 The function is called when no boot option could be launched,\r
409 including platform recovery options and options pointing to applications\r
410 built into firmware volumes.\r
411\r
412 If this function returns, BDS attempts to enter an infinite loop.\r
413**/\r
414VOID\r
415EFIAPI\r
416PlatformBootManagerUnableToBoot (\r
417 VOID\r
418 )\r
419{\r
420 return;\r
421}\r
422\r