]> git.proxmox.com Git - mirror_edk2.git/blame - Nt32Pkg/Library/PlatformBootManagerLib/PlatformBootManager.c
Nt32Pkg/PlatformBDS: Implement PlatformBootManagerUnableToBoot
[mirror_edk2.git] / Nt32Pkg / Library / PlatformBootManagerLib / PlatformBootManager.c
CommitLineData
123e9f62
RN
1/** @file\r
2 This file include all platform action which can be customized\r
3 by IBV/OEM.\r
4\r
11cf25f0 5Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
cf814093 6(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
123e9f62
RN
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
0b6dc68d
ED
19EFI_GUID mBootMenuFile = {\r
20 0xEEC25BDC, 0x67F2, 0x4D95, { 0xB1, 0xD5, 0xF8, 0x1B, 0x20, 0x39, 0xD1, 0x1D }\r
21};\r
22\r
8f227c2f 23/**\r
703da8b4
RN
24 Perform the platform diagnostic, such like test memory. OEM/IBV also\r
25 can customize this function to support specific platform diagnostic.\r
8f227c2f 26\r
703da8b4
RN
27 @param MemoryTestLevel The memory test intensive level\r
28 @param QuietBoot Indicate if need to enable the quiet boot\r
8f227c2f
RN
29\r
30**/\r
703da8b4
RN
31VOID\r
32PlatformBootManagerDiagnostics (\r
33 IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel,\r
34 IN BOOLEAN QuietBoot\r
8f227c2f
RN
35 )\r
36{\r
703da8b4
RN
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
67ce479a 46 BootLogoEnableLogo ();\r
8f227c2f 47\r
8f227c2f 48 //\r
703da8b4 49 // Perform system diagnostic\r
8f227c2f 50 //\r
703da8b4
RN
51 Status = PlatformBootManagerMemoryTest (MemoryTestLevel);\r
52 if (EFI_ERROR (Status)) {\r
859e75c4 53 BootLogoDisableLogo ();\r
8f227c2f 54 }\r
8f227c2f 55\r
703da8b4
RN
56 return;\r
57 }\r
8f227c2f 58\r
703da8b4
RN
59 //\r
60 // Perform system diagnostic\r
61 //\r
62 Status = PlatformBootManagerMemoryTest (MemoryTestLevel);\r
8f227c2f
RN
63}\r
64\r
123e9f62
RN
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
123e9f62
RN
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
cf814093
CS
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
7937bf2b
RN
127\r
128 //\r
129 // Dispatch deferred images after EndOfDxe event.\r
130 //\r
131 EfiBootManagerDispatchDeferredImages ();\r
123e9f62
RN
132}\r
133\r
3d8fab57
LG
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
0b6dc68d
ED
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
e9fec732
DB
290 OptionNumber = 0;\r
291\r
0b6dc68d
ED
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
123e9f62
RN
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
703da8b4
RN
329 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Black;\r
330 EFI_GRAPHICS_OUTPUT_BLT_PIXEL White;\r
e2e9b3b4
LG
331 EFI_INPUT_KEY Enter;\r
332 EFI_INPUT_KEY F2;\r
0b6dc68d 333 EFI_INPUT_KEY F7;\r
e2e9b3b4 334 EFI_BOOT_MANAGER_LOAD_OPTION BootOption;\r
0b6dc68d 335 UINTN OptionNumber;\r
703da8b4
RN
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
99eda885
ED
340 EfiBootManagerConnectAll ();\r
341 EfiBootManagerRefreshAllBootOption ();\r
703da8b4 342\r
e2e9b3b4
LG
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
0b6dc68d
ED
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
3d8fab57
LG
365 //\r
366 // Make Shell as the first boot option\r
367 //\r
368 EfiBootManagerSortLoadOptionVariable (LoadOptionTypeBoot, (SORT_COMPARE) CompareBootOption);\r
369\r
703da8b4 370 PlatformBootManagerDiagnostics (QUICK, TRUE);\r
0b6dc68d
ED
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
123e9f62
RN
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
ef3216eb
LE
388 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black;\r
389 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White;\r
390 UINT16 Timeout;\r
703da8b4
RN
391\r
392 Timeout = PcdGet16 (PcdPlatformBootTimeOut);\r
393\r
ef3216eb
LE
394 Black.Raw = 0x00000000;\r
395 White.Raw = 0x00FFFFFF;\r
703da8b4 396\r
859e75c4 397 BootLogoUpdateProgress (\r
ef3216eb
LE
398 White.Pixel,\r
399 Black.Pixel,\r
703da8b4 400 L"Start boot option",\r
ef3216eb 401 White.Pixel,\r
703da8b4
RN
402 (Timeout - TimeoutRemain) * 100 / Timeout,\r
403 0\r
404 );\r
123e9f62 405}\r
11cf25f0
RN
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