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