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