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