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