]> git.proxmox.com Git - mirror_edk2.git/blame - ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.c
OvmfPkg: Fix typos in comments
[mirror_edk2.git] / ArmVirtPkg / Library / PlatformBootManagerLib / PlatformBm.c
CommitLineData
8d620322
LE
1/** @file\r
2 Implementation for PlatformBootManagerLib library class interfaces.\r
3\r
4 Copyright (C) 2015-2016, Red Hat, Inc.\r
5 Copyright (c) 2014, ARM Ltd. All rights reserved.<BR>\r
793b3b5b 6 Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>\r
8d620322
LE
7\r
8 This program and the accompanying materials are licensed and made available\r
9 under the terms and conditions of the BSD License which accompanies this\r
10 distribution. The full text of the license may be found at\r
11 http://opensource.org/licenses/bsd-license.php\r
12\r
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT\r
14 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
15\r
16**/\r
17\r
18#include <IndustryStandard/Pci22.h>\r
2c8805bc 19#include <Library/BootLogoLib.h>\r
8d620322
LE
20#include <Library/DevicePathLib.h>\r
21#include <Library/PcdLib.h>\r
8d620322 22#include <Library/QemuBootOrderLib.h>\r
2c5c33cd 23#include <Library/UefiBootManagerLib.h>\r
8d620322
LE
24#include <Protocol/DevicePath.h>\r
25#include <Protocol/GraphicsOutput.h>\r
793b3b5b 26#include <Protocol/LoadedImage.h>\r
8d620322
LE
27#include <Protocol/PciIo.h>\r
28#include <Protocol/PciRootBridgeIo.h>\r
29#include <Guid/EventGroup.h>\r
30#include <Guid/RootBridgesConnectedEventGroup.h>\r
31\r
32#include "PlatformBm.h"\r
33\r
34#define DP_NODE_LEN(Type) { (UINT8)sizeof (Type), (UINT8)(sizeof (Type) >> 8) }\r
35\r
36\r
37#pragma pack (1)\r
38typedef struct {\r
39 VENDOR_DEVICE_PATH SerialDxe;\r
40 UART_DEVICE_PATH Uart;\r
41 VENDOR_DEFINED_DEVICE_PATH TermType;\r
42 EFI_DEVICE_PATH_PROTOCOL End;\r
43} PLATFORM_SERIAL_CONSOLE;\r
44#pragma pack ()\r
45\r
46#define SERIAL_DXE_FILE_GUID { \\r
47 0xD3987D4B, 0x971A, 0x435F, \\r
48 { 0x8C, 0xAF, 0x49, 0x67, 0xEB, 0x62, 0x72, 0x41 } \\r
49 }\r
50\r
51STATIC PLATFORM_SERIAL_CONSOLE mSerialConsole = {\r
52 //\r
53 // VENDOR_DEVICE_PATH SerialDxe\r
54 //\r
55 {\r
56 { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, DP_NODE_LEN (VENDOR_DEVICE_PATH) },\r
57 SERIAL_DXE_FILE_GUID\r
58 },\r
59\r
60 //\r
61 // UART_DEVICE_PATH Uart\r
62 //\r
63 {\r
64 { MESSAGING_DEVICE_PATH, MSG_UART_DP, DP_NODE_LEN (UART_DEVICE_PATH) },\r
65 0, // Reserved\r
66 FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate\r
67 FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits\r
68 FixedPcdGet8 (PcdUartDefaultParity), // Parity\r
69 FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits\r
70 },\r
71\r
72 //\r
73 // VENDOR_DEFINED_DEVICE_PATH TermType\r
74 //\r
75 {\r
76 {\r
77 MESSAGING_DEVICE_PATH, MSG_VENDOR_DP,\r
78 DP_NODE_LEN (VENDOR_DEFINED_DEVICE_PATH)\r
79 }\r
80 //\r
81 // Guid to be filled in dynamically\r
82 //\r
83 },\r
84\r
85 //\r
86 // EFI_DEVICE_PATH_PROTOCOL End\r
87 //\r
88 {\r
89 END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
90 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)\r
91 }\r
92};\r
93\r
94\r
95#pragma pack (1)\r
96typedef struct {\r
97 USB_CLASS_DEVICE_PATH Keyboard;\r
98 EFI_DEVICE_PATH_PROTOCOL End;\r
99} PLATFORM_USB_KEYBOARD;\r
100#pragma pack ()\r
101\r
102STATIC PLATFORM_USB_KEYBOARD mUsbKeyboard = {\r
103 //\r
104 // USB_CLASS_DEVICE_PATH Keyboard\r
105 //\r
106 {\r
107 {\r
108 MESSAGING_DEVICE_PATH, MSG_USB_CLASS_DP,\r
109 DP_NODE_LEN (USB_CLASS_DEVICE_PATH)\r
110 },\r
111 0xFFFF, // VendorId: any\r
112 0xFFFF, // ProductId: any\r
113 3, // DeviceClass: HID\r
114 1, // DeviceSubClass: boot\r
115 1 // DeviceProtocol: keyboard\r
116 },\r
117\r
118 //\r
119 // EFI_DEVICE_PATH_PROTOCOL End\r
120 //\r
121 {\r
122 END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
123 DP_NODE_LEN (EFI_DEVICE_PATH_PROTOCOL)\r
124 }\r
125};\r
126\r
8d620322
LE
127\r
128/**\r
129 Check if the handle satisfies a particular condition.\r
130\r
131 @param[in] Handle The handle to check.\r
132 @param[in] ReportText A caller-allocated string passed in for reporting\r
133 purposes. It must never be NULL.\r
134\r
135 @retval TRUE The condition is satisfied.\r
136 @retval FALSE Otherwise. This includes the case when the condition could not\r
137 be fully evaluated due to an error.\r
138**/\r
139typedef\r
140BOOLEAN\r
141(EFIAPI *FILTER_FUNCTION) (\r
142 IN EFI_HANDLE Handle,\r
143 IN CONST CHAR16 *ReportText\r
144 );\r
145\r
146\r
147/**\r
148 Process a handle.\r
149\r
150 @param[in] Handle The handle to process.\r
151 @param[in] ReportText A caller-allocated string passed in for reporting\r
152 purposes. It must never be NULL.\r
153**/\r
154typedef\r
155VOID\r
156(EFIAPI *CALLBACK_FUNCTION) (\r
157 IN EFI_HANDLE Handle,\r
158 IN CONST CHAR16 *ReportText\r
159 );\r
160\r
161/**\r
162 Locate all handles that carry the specified protocol, filter them with a\r
163 callback function, and pass each handle that passes the filter to another\r
164 callback.\r
165\r
166 @param[in] ProtocolGuid The protocol to look for.\r
167\r
168 @param[in] Filter The filter function to pass each handle to. If this\r
169 parameter is NULL, then all handles are processed.\r
170\r
171 @param[in] Process The callback function to pass each handle to that\r
172 clears the filter.\r
173**/\r
174STATIC\r
175VOID\r
176FilterAndProcess (\r
177 IN EFI_GUID *ProtocolGuid,\r
178 IN FILTER_FUNCTION Filter OPTIONAL,\r
179 IN CALLBACK_FUNCTION Process\r
180 )\r
181{\r
182 EFI_STATUS Status;\r
183 EFI_HANDLE *Handles;\r
184 UINTN NoHandles;\r
185 UINTN Idx;\r
186\r
187 Status = gBS->LocateHandleBuffer (ByProtocol, ProtocolGuid,\r
188 NULL /* SearchKey */, &NoHandles, &Handles);\r
189 if (EFI_ERROR (Status)) {\r
190 //\r
191 // This is not an error, just an informative condition.\r
192 //\r
193 DEBUG ((EFI_D_VERBOSE, "%a: %g: %r\n", __FUNCTION__, ProtocolGuid,\r
194 Status));\r
195 return;\r
196 }\r
197\r
198 ASSERT (NoHandles > 0);\r
199 for (Idx = 0; Idx < NoHandles; ++Idx) {\r
200 CHAR16 *DevicePathText;\r
201 STATIC CHAR16 Fallback[] = L"<device path unavailable>";\r
202\r
203 //\r
204 // The ConvertDevicePathToText() function handles NULL input transparently.\r
205 //\r
206 DevicePathText = ConvertDevicePathToText (\r
207 DevicePathFromHandle (Handles[Idx]),\r
208 FALSE, // DisplayOnly\r
209 FALSE // AllowShortcuts\r
210 );\r
211 if (DevicePathText == NULL) {\r
212 DevicePathText = Fallback;\r
213 }\r
214\r
215 if (Filter == NULL || Filter (Handles[Idx], DevicePathText)) {\r
216 Process (Handles[Idx], DevicePathText);\r
217 }\r
218\r
219 if (DevicePathText != Fallback) {\r
220 FreePool (DevicePathText);\r
221 }\r
222 }\r
223 gBS->FreePool (Handles);\r
224}\r
225\r
226\r
227/**\r
228 This FILTER_FUNCTION checks if a handle corresponds to a PCI display device.\r
229**/\r
230STATIC\r
231BOOLEAN\r
232EFIAPI\r
233IsPciDisplay (\r
234 IN EFI_HANDLE Handle,\r
235 IN CONST CHAR16 *ReportText\r
236 )\r
237{\r
238 EFI_STATUS Status;\r
239 EFI_PCI_IO_PROTOCOL *PciIo;\r
240 PCI_TYPE00 Pci;\r
241\r
242 Status = gBS->HandleProtocol (Handle, &gEfiPciIoProtocolGuid,\r
243 (VOID**)&PciIo);\r
244 if (EFI_ERROR (Status)) {\r
245 //\r
246 // This is not an error worth reporting.\r
247 //\r
248 return FALSE;\r
249 }\r
250\r
251 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0 /* Offset */,\r
252 sizeof Pci / sizeof (UINT32), &Pci);\r
253 if (EFI_ERROR (Status)) {\r
254 DEBUG ((EFI_D_ERROR, "%a: %s: %r\n", __FUNCTION__, ReportText, Status));\r
255 return FALSE;\r
256 }\r
257\r
258 return IS_PCI_DISPLAY (&Pci);\r
259}\r
260\r
261\r
262/**\r
263 This CALLBACK_FUNCTION attempts to connect a handle non-recursively, asking\r
264 the matching driver to produce all first-level child handles.\r
265**/\r
266STATIC\r
267VOID\r
268EFIAPI\r
269Connect (\r
270 IN EFI_HANDLE Handle,\r
271 IN CONST CHAR16 *ReportText\r
272 )\r
273{\r
274 EFI_STATUS Status;\r
275\r
276 Status = gBS->ConnectController (\r
277 Handle, // ControllerHandle\r
278 NULL, // DriverImageHandle\r
279 NULL, // RemainingDevicePath -- produce all children\r
280 FALSE // Recursive\r
281 );\r
282 DEBUG ((EFI_ERROR (Status) ? EFI_D_ERROR : EFI_D_VERBOSE, "%a: %s: %r\n",\r
283 __FUNCTION__, ReportText, Status));\r
284}\r
285\r
286\r
287/**\r
288 This CALLBACK_FUNCTION retrieves the EFI_DEVICE_PATH_PROTOCOL from the\r
289 handle, and adds it to ConOut and ErrOut.\r
290**/\r
291STATIC\r
292VOID\r
293EFIAPI\r
294AddOutput (\r
295 IN EFI_HANDLE Handle,\r
296 IN CONST CHAR16 *ReportText\r
297 )\r
298{\r
299 EFI_STATUS Status;\r
300 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
301\r
302 DevicePath = DevicePathFromHandle (Handle);\r
303 if (DevicePath == NULL) {\r
304 DEBUG ((EFI_D_ERROR, "%a: %s: handle %p: device path not found\n",\r
305 __FUNCTION__, ReportText, Handle));\r
306 return;\r
307 }\r
308\r
b7a33aff 309 Status = EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL);\r
8d620322
LE
310 if (EFI_ERROR (Status)) {\r
311 DEBUG ((EFI_D_ERROR, "%a: %s: adding to ConOut: %r\n", __FUNCTION__,\r
312 ReportText, Status));\r
313 return;\r
314 }\r
315\r
b7a33aff 316 Status = EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL);\r
8d620322
LE
317 if (EFI_ERROR (Status)) {\r
318 DEBUG ((EFI_D_ERROR, "%a: %s: adding to ErrOut: %r\n", __FUNCTION__,\r
319 ReportText, Status));\r
320 return;\r
321 }\r
322\r
323 DEBUG ((EFI_D_VERBOSE, "%a: %s: added to ConOut and ErrOut\n", __FUNCTION__,\r
324 ReportText));\r
325}\r
326\r
793b3b5b
LE
327STATIC\r
328VOID\r
329PlatformRegisterFvBootOption (\r
330 EFI_GUID *FileGuid,\r
331 CHAR16 *Description,\r
332 UINT32 Attributes\r
333 )\r
334{\r
335 EFI_STATUS Status;\r
336 INTN OptionIndex;\r
337 EFI_BOOT_MANAGER_LOAD_OPTION NewOption;\r
338 EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
339 UINTN BootOptionCount;\r
340 MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;\r
341 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
342 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
343\r
344 Status = gBS->HandleProtocol (\r
345 gImageHandle,\r
346 &gEfiLoadedImageProtocolGuid,\r
347 (VOID **) &LoadedImage\r
348 );\r
349 ASSERT_EFI_ERROR (Status);\r
350\r
351 EfiInitializeFwVolDevicepathNode (&FileNode, FileGuid);\r
352 DevicePath = DevicePathFromHandle (LoadedImage->DeviceHandle);\r
353 ASSERT (DevicePath != NULL);\r
354 DevicePath = AppendDevicePathNode (\r
355 DevicePath,\r
356 (EFI_DEVICE_PATH_PROTOCOL *) &FileNode\r
357 );\r
358 ASSERT (DevicePath != NULL);\r
359\r
360 Status = EfiBootManagerInitializeLoadOption (\r
361 &NewOption,\r
362 LoadOptionNumberUnassigned,\r
363 LoadOptionTypeBoot,\r
364 Attributes,\r
365 Description,\r
366 DevicePath,\r
367 NULL,\r
368 0\r
369 );\r
370 ASSERT_EFI_ERROR (Status);\r
371 FreePool (DevicePath);\r
372\r
373 BootOptions = EfiBootManagerGetLoadOptions (\r
374 &BootOptionCount, LoadOptionTypeBoot\r
375 );\r
376\r
377 OptionIndex = EfiBootManagerFindLoadOption (\r
378 &NewOption, BootOptions, BootOptionCount\r
379 );\r
380\r
381 if (OptionIndex == -1) {\r
382 Status = EfiBootManagerAddLoadOptionVariable (&NewOption, MAX_UINTN);\r
383 ASSERT_EFI_ERROR (Status);\r
384 }\r
385 EfiBootManagerFreeLoadOption (&NewOption);\r
386 EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
387}\r
388\r
389\r
390STATIC\r
391VOID\r
392PlatformRegisterOptionsAndKeys (\r
393 VOID\r
394 )\r
395{\r
396 EFI_STATUS Status;\r
397 EFI_INPUT_KEY Enter;\r
398 EFI_INPUT_KEY F2;\r
399 EFI_INPUT_KEY Esc;\r
400 EFI_BOOT_MANAGER_LOAD_OPTION BootOption;\r
401\r
402 //\r
403 // Register ENTER as CONTINUE key\r
404 //\r
405 Enter.ScanCode = SCAN_NULL;\r
406 Enter.UnicodeChar = CHAR_CARRIAGE_RETURN;\r
407 Status = EfiBootManagerRegisterContinueKeyOption (0, &Enter, NULL);\r
408 ASSERT_EFI_ERROR (Status);\r
409\r
410 //\r
411 // Map F2 and ESC to Boot Manager Menu\r
412 //\r
413 F2.ScanCode = SCAN_F2;\r
414 F2.UnicodeChar = CHAR_NULL;\r
415 Esc.ScanCode = SCAN_ESC;\r
416 Esc.UnicodeChar = CHAR_NULL;\r
417 Status = EfiBootManagerGetBootManagerMenu (&BootOption);\r
418 ASSERT_EFI_ERROR (Status);\r
419 Status = EfiBootManagerAddKeyOptionVariable (\r
420 NULL, (UINT16) BootOption.OptionNumber, 0, &F2, NULL\r
421 );\r
422 ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);\r
423 Status = EfiBootManagerAddKeyOptionVariable (\r
424 NULL, (UINT16) BootOption.OptionNumber, 0, &Esc, NULL\r
425 );\r
426 ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED);\r
427 //\r
428 // Register UEFI Shell\r
429 //\r
430 PlatformRegisterFvBootOption (\r
431 PcdGetPtr (PcdShellFile), L"EFI Internal Shell", LOAD_OPTION_ACTIVE\r
432 );\r
433}\r
434\r
8d620322 435\r
e2a193b7
LE
436//\r
437// BDS Platform Functions\r
438//\r
8d620322 439/**\r
e2a193b7
LE
440 Do the platform init, can be customized by OEM/IBV\r
441 Possible things that can be done in PlatformBootManagerBeforeConsole:\r
442 > Update console variable: 1. include hot-plug devices;\r
443 > 2. Clear ConIn and add SOL for AMT\r
444 > Register new Driver#### or Boot####\r
445 > Register new Key####: e.g.: F12\r
446 > Signal ReadyToLock event\r
447 > Authentication action: 1. connect Auth devices;\r
448 > 2. Identify auto logon user.\r
8d620322
LE
449**/\r
450VOID\r
451EFIAPI\r
e2a193b7 452PlatformBootManagerBeforeConsole (\r
e3fe3c0f 453 VOID\r
8d620322
LE
454 )\r
455{\r
e2a193b7
LE
456 //\r
457 // Signal EndOfDxe PI Event\r
458 //\r
459 EfiEventGroupSignal (&gEfiEndOfDxeEventGroupGuid);\r
460\r
8d620322
LE
461 //\r
462 // Locate the PCI root bridges and make the PCI bus driver connect each,\r
463 // non-recursively. This will produce a number of child handles with PciIo on\r
464 // them.\r
465 //\r
466 FilterAndProcess (&gEfiPciRootBridgeIoProtocolGuid, NULL, Connect);\r
467\r
468 //\r
469 // Signal the ACPI platform driver that it can download QEMU ACPI tables.\r
470 //\r
471 EfiEventGroupSignal (&gRootBridgesConnectedEventGroupGuid);\r
472\r
473 //\r
474 // Find all display class PCI devices (using the handles from the previous\r
475 // step), and connect them non-recursively. This should produce a number of\r
476 // child handles with GOPs on them.\r
477 //\r
478 FilterAndProcess (&gEfiPciIoProtocolGuid, IsPciDisplay, Connect);\r
479\r
480 //\r
481 // Now add the device path of all handles with GOP on them to ConOut and\r
482 // ErrOut.\r
483 //\r
484 FilterAndProcess (&gEfiGraphicsOutputProtocolGuid, NULL, AddOutput);\r
485\r
486 //\r
487 // Add the hardcoded short-form USB keyboard device path to ConIn.\r
488 //\r
b7a33aff 489 EfiBootManagerUpdateConsoleVariable (ConIn,\r
8d620322
LE
490 (EFI_DEVICE_PATH_PROTOCOL *)&mUsbKeyboard, NULL);\r
491\r
492 //\r
493 // Add the hardcoded serial console device path to ConIn, ConOut, ErrOut.\r
494 //\r
495 CopyGuid (&mSerialConsole.TermType.Guid,\r
496 PcdGetPtr (PcdTerminalTypeGuidBuffer));\r
b7a33aff 497 EfiBootManagerUpdateConsoleVariable (ConIn,\r
8d620322 498 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);\r
b7a33aff 499 EfiBootManagerUpdateConsoleVariable (ConOut,\r
8d620322 500 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);\r
b7a33aff 501 EfiBootManagerUpdateConsoleVariable (ErrOut,\r
8d620322 502 (EFI_DEVICE_PATH_PROTOCOL *)&mSerialConsole, NULL);\r
48799ab2
LE
503\r
504 //\r
505 // Set the front page timeout from the QEMU configuration.\r
506 //\r
507 PcdSet16 (PcdPlatformBootTimeOut, GetFrontPageTimeoutFromQemu ());\r
793b3b5b
LE
508\r
509 //\r
510 // Register platform-specific boot options and keyboard shortcuts.\r
511 //\r
512 PlatformRegisterOptionsAndKeys ();\r
e2a193b7 513}\r
8d620322 514\r
e2a193b7
LE
515/**\r
516 Do the platform specific action after the console is ready\r
517 Possible things that can be done in PlatformBootManagerAfterConsole:\r
518 > Console post action:\r
519 > Dynamically switch output mode from 100x31 to 80x25 for certain senarino\r
520 > Signal console ready platform customized event\r
521 > Run diagnostics like memory testing\r
522 > Connect certain devices\r
523 > Dispatch aditional option roms\r
524 > Special boot: e.g.: USB boot, enter UI\r
525**/\r
526VOID\r
527EFIAPI\r
528PlatformBootManagerAfterConsole (\r
529 VOID\r
530 )\r
531{\r
8d620322
LE
532 //\r
533 // Show the splash screen.\r
534 //\r
2c8805bc
LE
535 BootLogoEnableLogo (\r
536 ImageFormatBmp, // ImageFormat\r
537 PcdGetPtr (PcdLogoFile), // Logo\r
538 EdkiiPlatformLogoDisplayAttributeCenter, // Attribute\r
539 0, // OffsetX\r
540 0 // OffsetY\r
541 );\r
8d620322
LE
542\r
543 //\r
544 // Connect the rest of the devices.\r
545 //\r
fa0f1954 546 EfiBootManagerConnectAll ();\r
8d620322
LE
547\r
548 //\r
549 // Process QEMU's -kernel command line option. Note that the kernel booted\r
550 // this way should receive ACPI tables, which is why we connect all devices\r
551 // first (see above) -- PCI enumeration blocks ACPI table installation, if\r
552 // there is a PCI host.\r
553 //\r
554 TryRunningQemuKernel ();\r
555\r
8d620322 556 //\r
afa456de
LE
557 // Enumerate all possible boot options, then filter and reorder them based on\r
558 // the QEMU configuration.\r
8d620322 559 //\r
afa456de 560 EfiBootManagerRefreshAllBootOption ();\r
2542feea 561 SetBootOrderFromQemu ();\r
8d620322
LE
562}\r
563\r
e3fe3c0f
LE
564/**\r
565 This function is called each second during the boot manager waits the\r
566 timeout.\r
567\r
568 @param TimeoutRemain The remaining timeout.\r
569**/\r
570VOID\r
571EFIAPI\r
572PlatformBootManagerWaitCallback (\r
573 UINT16 TimeoutRemain\r
574 )\r
575{\r
be266b10
LE
576 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black;\r
577 EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White;\r
578 UINT16 Timeout;\r
579\r
580 Timeout = PcdGet16 (PcdPlatformBootTimeOut);\r
581\r
582 Black.Raw = 0x00000000;\r
583 White.Raw = 0x00FFFFFF;\r
584\r
585 BootLogoUpdateProgress (\r
586 White.Pixel,\r
587 Black.Pixel,\r
588 L"Start boot option",\r
589 White.Pixel,\r
590 (Timeout - TimeoutRemain) * 100 / Timeout,\r
591 0\r
592 );\r
e3fe3c0f 593}\r