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