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