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