Home | History | Annotate | Download | only in PlatformBootManagerLib
      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     PcdGetPtr (PcdShellFile), 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 }
    731