Home | History | Annotate | Download | only in PlatformBdsLib
      1 /** @file
      2   Platform BDS customizations.
      3 
      4   Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
      5   This program and the accompanying materials
      6   are licensed and made available under the terms and conditions of the BSD License
      7   which accompanies this distribution.  The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "BdsPlatform.h"
     16 #include <Library/QemuBootOrderLib.h>
     17 
     18 
     19 //
     20 // Global data
     21 //
     22 
     23 VOID          *mEfiDevPathNotifyReg;
     24 EFI_EVENT     mEfiDevPathEvent;
     25 VOID          *mEmuVariableEventReg;
     26 EFI_EVENT     mEmuVariableEvent;
     27 BOOLEAN       mDetectVgaOnly;
     28 UINT16        mHostBridgeDevId;
     29 
     30 //
     31 // Table of host IRQs matching PCI IRQs A-D
     32 // (for configuring PCI Interrupt Line register)
     33 //
     34 CONST UINT8 PciHostIrqs[] = {
     35   0x0a, 0x0a, 0x0b, 0x0b
     36 };
     37 
     38 //
     39 // Array Size macro
     40 //
     41 #define ARRAY_SIZE(array) (sizeof (array) / sizeof (array[0]))
     42 
     43 //
     44 // Type definitions
     45 //
     46 
     47 typedef
     48 EFI_STATUS
     49 (EFIAPI *PROTOCOL_INSTANCE_CALLBACK)(
     50   IN EFI_HANDLE           Handle,
     51   IN VOID                 *Instance,
     52   IN VOID                 *Context
     53   );
     54 
     55 /**
     56   @param[in]  Handle - Handle of PCI device instance
     57   @param[in]  PciIo - PCI IO protocol instance
     58   @param[in]  Pci - PCI Header register block
     59 **/
     60 typedef
     61 EFI_STATUS
     62 (EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)(
     63   IN EFI_HANDLE           Handle,
     64   IN EFI_PCI_IO_PROTOCOL  *PciIo,
     65   IN PCI_TYPE00           *Pci
     66   );
     67 
     68 
     69 //
     70 // Function prototypes
     71 //
     72 
     73 EFI_STATUS
     74 VisitAllInstancesOfProtocol (
     75   IN EFI_GUID                    *Id,
     76   IN PROTOCOL_INSTANCE_CALLBACK  CallBackFunction,
     77   IN VOID                        *Context
     78   );
     79 
     80 EFI_STATUS
     81 VisitAllPciInstancesOfProtocol (
     82   IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
     83   );
     84 
     85 VOID
     86 InstallDevicePathCallback (
     87   VOID
     88   );
     89 
     90 //
     91 // BDS Platform Functions
     92 //
     93 VOID
     94 EFIAPI
     95 PlatformBdsInit (
     96   VOID
     97   )
     98 /*++
     99 
    100 Routine Description:
    101 
    102   Platform Bds init. Incude the platform firmware vendor, revision
    103   and so crc check.
    104 
    105 Arguments:
    106 
    107 Returns:
    108 
    109   None.
    110 
    111 --*/
    112 {
    113   DEBUG ((EFI_D_INFO, "PlatformBdsInit\n"));
    114   InstallDevicePathCallback ();
    115 }
    116 
    117 
    118 EFI_STATUS
    119 EFIAPI
    120 ConnectRootBridge (
    121   IN EFI_HANDLE  RootBridgeHandle,
    122   IN VOID        *Instance,
    123   IN VOID        *Context
    124   )
    125 {
    126   EFI_STATUS Status;
    127 
    128   //
    129   // Make the PCI bus driver connect the root bridge, non-recursively. This
    130   // will produce a number of child handles with PciIo on them.
    131   //
    132   Status = gBS->ConnectController (
    133                   RootBridgeHandle, // ControllerHandle
    134                   NULL,             // DriverImageHandle
    135                   NULL,             // RemainingDevicePath -- produce all
    136                                     //   children
    137                   FALSE             // Recursive
    138                   );
    139   return Status;
    140 }
    141 
    142 
    143 EFI_STATUS
    144 PrepareLpcBridgeDevicePath (
    145   IN EFI_HANDLE                DeviceHandle
    146   )
    147 /*++
    148 
    149 Routine Description:
    150 
    151   Add IsaKeyboard to ConIn,
    152   add IsaSerial to ConOut, ConIn, ErrOut.
    153   LPC Bridge: 06 01 00
    154 
    155 Arguments:
    156 
    157   DeviceHandle            - Handle of PCIIO protocol.
    158 
    159 Returns:
    160 
    161   EFI_SUCCESS             - LPC bridge is added to ConOut, ConIn, and ErrOut.
    162   EFI_STATUS              - No LPC bridge is added.
    163 
    164 --*/
    165 {
    166   EFI_STATUS                Status;
    167   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
    168   EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
    169   CHAR16                    *DevPathStr;
    170 
    171   DevicePath = NULL;
    172   Status = gBS->HandleProtocol (
    173                   DeviceHandle,
    174                   &gEfiDevicePathProtocolGuid,
    175                   (VOID*)&DevicePath
    176                   );
    177   if (EFI_ERROR (Status)) {
    178     return Status;
    179   }
    180   TempDevicePath = DevicePath;
    181 
    182   //
    183   // Register Keyboard
    184   //
    185   DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);
    186 
    187   BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
    188 
    189   //
    190   // Register COM1
    191   //
    192   DevicePath = TempDevicePath;
    193   gPnp16550ComPortDeviceNode.UID = 0;
    194 
    195   DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
    196   DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
    197   DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
    198 
    199   //
    200   // Print Device Path
    201   //
    202   DevPathStr = DevicePathToStr(DevicePath);
    203   if (DevPathStr != NULL) {
    204     DEBUG((
    205       EFI_D_INFO,
    206       "BdsPlatform.c+%d: COM%d DevPath: %s\n",
    207       __LINE__,
    208       gPnp16550ComPortDeviceNode.UID + 1,
    209       DevPathStr
    210       ));
    211     FreePool(DevPathStr);
    212   }
    213 
    214   BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
    215   BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
    216   BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);
    217 
    218   //
    219   // Register COM2
    220   //
    221   DevicePath = TempDevicePath;
    222   gPnp16550ComPortDeviceNode.UID = 1;
    223 
    224   DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
    225   DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
    226   DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
    227 
    228   //
    229   // Print Device Path
    230   //
    231   DevPathStr = DevicePathToStr(DevicePath);
    232   if (DevPathStr != NULL) {
    233     DEBUG((
    234       EFI_D_INFO,
    235       "BdsPlatform.c+%d: COM%d DevPath: %s\n",
    236       __LINE__,
    237       gPnp16550ComPortDeviceNode.UID + 1,
    238       DevPathStr
    239       ));
    240     FreePool(DevPathStr);
    241   }
    242 
    243   BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
    244   BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
    245   BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);
    246 
    247   return EFI_SUCCESS;
    248 }
    249 
    250 EFI_STATUS
    251 GetGopDevicePath (
    252    IN  EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,
    253    OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath
    254    )
    255 {
    256   UINTN                           Index;
    257   EFI_STATUS                      Status;
    258   EFI_HANDLE                      PciDeviceHandle;
    259   EFI_DEVICE_PATH_PROTOCOL        *TempDevicePath;
    260   EFI_DEVICE_PATH_PROTOCOL        *TempPciDevicePath;
    261   UINTN                           GopHandleCount;
    262   EFI_HANDLE                      *GopHandleBuffer;
    263 
    264   if (PciDevicePath == NULL || GopDevicePath == NULL) {
    265     return EFI_INVALID_PARAMETER;
    266   }
    267 
    268   //
    269   // Initialize the GopDevicePath to be PciDevicePath
    270   //
    271   *GopDevicePath    = PciDevicePath;
    272   TempPciDevicePath = PciDevicePath;
    273 
    274   Status = gBS->LocateDevicePath (
    275                   &gEfiDevicePathProtocolGuid,
    276                   &TempPciDevicePath,
    277                   &PciDeviceHandle
    278                   );
    279   if (EFI_ERROR (Status)) {
    280     return Status;
    281   }
    282 
    283   //
    284   // Try to connect this handle, so that GOP dirver could start on this
    285   // device and create child handles with GraphicsOutput Protocol installed
    286   // on them, then we get device paths of these child handles and select
    287   // them as possible console device.
    288   //
    289   gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);
    290 
    291   Status = gBS->LocateHandleBuffer (
    292                   ByProtocol,
    293                   &gEfiGraphicsOutputProtocolGuid,
    294                   NULL,
    295                   &GopHandleCount,
    296                   &GopHandleBuffer
    297                   );
    298   if (!EFI_ERROR (Status)) {
    299     //
    300     // Add all the child handles as possible Console Device
    301     //
    302     for (Index = 0; Index < GopHandleCount; Index++) {
    303       Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);
    304       if (EFI_ERROR (Status)) {
    305         continue;
    306       }
    307       if (CompareMem (
    308             PciDevicePath,
    309             TempDevicePath,
    310             GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH
    311             ) == 0) {
    312         //
    313         // In current implementation, we only enable one of the child handles
    314         // as console device, i.e. sotre one of the child handle's device
    315         // path to variable "ConOut"
    316         // In futhure, we could select all child handles to be console device
    317         //
    318 
    319         *GopDevicePath = TempDevicePath;
    320 
    321         //
    322         // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
    323         // Add the integrity GOP device path.
    324         //
    325         BdsLibUpdateConsoleVariable (VarConsoleOutDev, NULL, PciDevicePath);
    326         BdsLibUpdateConsoleVariable (VarConsoleOutDev, TempDevicePath, NULL);
    327       }
    328     }
    329     gBS->FreePool (GopHandleBuffer);
    330   }
    331 
    332   return EFI_SUCCESS;
    333 }
    334 
    335 EFI_STATUS
    336 PreparePciVgaDevicePath (
    337   IN EFI_HANDLE                DeviceHandle
    338   )
    339 /*++
    340 
    341 Routine Description:
    342 
    343   Add PCI VGA to ConOut.
    344   PCI VGA: 03 00 00
    345 
    346 Arguments:
    347 
    348   DeviceHandle            - Handle of PCIIO protocol.
    349 
    350 Returns:
    351 
    352   EFI_SUCCESS             - PCI VGA is added to ConOut.
    353   EFI_STATUS              - No PCI VGA device is added.
    354 
    355 --*/
    356 {
    357   EFI_STATUS                Status;
    358   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
    359   EFI_DEVICE_PATH_PROTOCOL  *GopDevicePath;
    360 
    361   DevicePath    = NULL;
    362   GopDevicePath = NULL;
    363   Status = gBS->HandleProtocol (
    364                   DeviceHandle,
    365                   &gEfiDevicePathProtocolGuid,
    366                   (VOID*)&DevicePath
    367                   );
    368   if (EFI_ERROR (Status)) {
    369     return Status;
    370   }
    371 
    372   GetGopDevicePath (DevicePath, &GopDevicePath);
    373   DevicePath = GopDevicePath;
    374 
    375   BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
    376 
    377   return EFI_SUCCESS;
    378 }
    379 
    380 EFI_STATUS
    381 PreparePciSerialDevicePath (
    382   IN EFI_HANDLE                DeviceHandle
    383   )
    384 /*++
    385 
    386 Routine Description:
    387 
    388   Add PCI Serial to ConOut, ConIn, ErrOut.
    389   PCI Serial: 07 00 02
    390 
    391 Arguments:
    392 
    393   DeviceHandle            - Handle of PCIIO protocol.
    394 
    395 Returns:
    396 
    397   EFI_SUCCESS             - PCI Serial is added to ConOut, ConIn, and ErrOut.
    398   EFI_STATUS              - No PCI Serial device is added.
    399 
    400 --*/
    401 {
    402   EFI_STATUS                Status;
    403   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
    404 
    405   DevicePath = NULL;
    406   Status = gBS->HandleProtocol (
    407                   DeviceHandle,
    408                   &gEfiDevicePathProtocolGuid,
    409                   (VOID*)&DevicePath
    410                   );
    411   if (EFI_ERROR (Status)) {
    412     return Status;
    413   }
    414 
    415   DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
    416   DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
    417 
    418   BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
    419   BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
    420   BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);
    421 
    422   return EFI_SUCCESS;
    423 }
    424 
    425 EFI_STATUS
    426 VisitAllInstancesOfProtocol (
    427   IN EFI_GUID                    *Id,
    428   IN PROTOCOL_INSTANCE_CALLBACK  CallBackFunction,
    429   IN VOID                        *Context
    430   )
    431 {
    432   EFI_STATUS                Status;
    433   UINTN                     HandleCount;
    434   EFI_HANDLE                *HandleBuffer;
    435   UINTN                     Index;
    436   VOID                      *Instance;
    437 
    438   //
    439   // Start to check all the PciIo to find all possible device
    440   //
    441   HandleCount = 0;
    442   HandleBuffer = NULL;
    443   Status = gBS->LocateHandleBuffer (
    444                   ByProtocol,
    445                   Id,
    446                   NULL,
    447                   &HandleCount,
    448                   &HandleBuffer
    449                   );
    450   if (EFI_ERROR (Status)) {
    451     return Status;
    452   }
    453 
    454   for (Index = 0; Index < HandleCount; Index++) {
    455     Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);
    456     if (EFI_ERROR (Status)) {
    457       continue;
    458     }
    459 
    460     Status = (*CallBackFunction) (
    461                HandleBuffer[Index],
    462                Instance,
    463                Context
    464                );
    465   }
    466 
    467   gBS->FreePool (HandleBuffer);
    468 
    469   return EFI_SUCCESS;
    470 }
    471 
    472 
    473 EFI_STATUS
    474 EFIAPI
    475 VisitingAPciInstance (
    476   IN EFI_HANDLE  Handle,
    477   IN VOID        *Instance,
    478   IN VOID        *Context
    479   )
    480 {
    481   EFI_STATUS                Status;
    482   EFI_PCI_IO_PROTOCOL       *PciIo;
    483   PCI_TYPE00                Pci;
    484 
    485   PciIo = (EFI_PCI_IO_PROTOCOL*) Instance;
    486 
    487   //
    488   // Check for all PCI device
    489   //
    490   Status = PciIo->Pci.Read (
    491                     PciIo,
    492                     EfiPciIoWidthUint32,
    493                     0,
    494                     sizeof (Pci) / sizeof (UINT32),
    495                     &Pci
    496                     );
    497   if (EFI_ERROR (Status)) {
    498     return Status;
    499   }
    500 
    501   return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) (
    502            Handle,
    503            PciIo,
    504            &Pci
    505            );
    506 
    507 }
    508 
    509 
    510 
    511 EFI_STATUS
    512 VisitAllPciInstances (
    513   IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
    514   )
    515 {
    516   return VisitAllInstancesOfProtocol (
    517            &gEfiPciIoProtocolGuid,
    518            VisitingAPciInstance,
    519            (VOID*)(UINTN) CallBackFunction
    520            );
    521 }
    522 
    523 
    524 /**
    525   Do platform specific PCI Device check and add them to
    526   ConOut, ConIn, ErrOut.
    527 
    528   @param[in]  Handle - Handle of PCI device instance
    529   @param[in]  PciIo - PCI IO protocol instance
    530   @param[in]  Pci - PCI Header register block
    531 
    532   @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
    533   @retval EFI_STATUS - PCI Device check or Console variable update fail.
    534 
    535 **/
    536 EFI_STATUS
    537 EFIAPI
    538 DetectAndPreparePlatformPciDevicePath (
    539   IN EFI_HANDLE           Handle,
    540   IN EFI_PCI_IO_PROTOCOL  *PciIo,
    541   IN PCI_TYPE00           *Pci
    542   )
    543 {
    544   EFI_STATUS                Status;
    545 
    546   Status = PciIo->Attributes (
    547     PciIo,
    548     EfiPciIoAttributeOperationEnable,
    549     EFI_PCI_DEVICE_ENABLE,
    550     NULL
    551     );
    552   ASSERT_EFI_ERROR (Status);
    553 
    554   if (!mDetectVgaOnly) {
    555     //
    556     // Here we decide whether it is LPC Bridge
    557     //
    558     if ((IS_PCI_LPC (Pci)) ||
    559         ((IS_PCI_ISA_PDECODE (Pci)) &&
    560          (Pci->Hdr.VendorId == 0x8086) &&
    561          (Pci->Hdr.DeviceId == 0x7000)
    562         )
    563        ) {
    564       //
    565       // Add IsaKeyboard to ConIn,
    566       // add IsaSerial to ConOut, ConIn, ErrOut
    567       //
    568       DEBUG ((EFI_D_INFO, "Found LPC Bridge device\n"));
    569       PrepareLpcBridgeDevicePath (Handle);
    570       return EFI_SUCCESS;
    571     }
    572     //
    573     // Here we decide which Serial device to enable in PCI bus
    574     //
    575     if (IS_PCI_16550SERIAL (Pci)) {
    576       //
    577       // Add them to ConOut, ConIn, ErrOut.
    578       //
    579       DEBUG ((EFI_D_INFO, "Found PCI 16550 SERIAL device\n"));
    580       PreparePciSerialDevicePath (Handle);
    581       return EFI_SUCCESS;
    582     }
    583   }
    584 
    585   //
    586   // Here we decide which VGA device to enable in PCI bus
    587   //
    588   if (IS_PCI_VGA (Pci)) {
    589     //
    590     // Add them to ConOut.
    591     //
    592     DEBUG ((EFI_D_INFO, "Found PCI VGA device\n"));
    593     PreparePciVgaDevicePath (Handle);
    594     return EFI_SUCCESS;
    595   }
    596 
    597   return Status;
    598 }
    599 
    600 
    601 /**
    602   Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
    603 
    604   @param[in]  DetectVgaOnly - Only detect VGA device if it's TRUE.
    605 
    606   @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
    607   @retval EFI_STATUS - PCI Device check or Console variable update fail.
    608 
    609 **/
    610 EFI_STATUS
    611 DetectAndPreparePlatformPciDevicePaths (
    612   BOOLEAN DetectVgaOnly
    613   )
    614 {
    615   mDetectVgaOnly = DetectVgaOnly;
    616   return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);
    617 }
    618 
    619 
    620 EFI_STATUS
    621 PlatformBdsConnectConsole (
    622   IN BDS_CONSOLE_CONNECT_ENTRY   *PlatformConsole
    623   )
    624 /*++
    625 
    626 Routine Description:
    627 
    628   Connect the predefined platform default console device. Always try to find
    629   and enable the vga device if have.
    630 
    631 Arguments:
    632 
    633   PlatformConsole         - Predfined platform default console device array.
    634 
    635 Returns:
    636 
    637   EFI_SUCCESS             - Success connect at least one ConIn and ConOut
    638                             device, there must have one ConOut device is
    639                             active vga device.
    640 
    641   EFI_STATUS              - Return the status of
    642                             BdsLibConnectAllDefaultConsoles ()
    643 
    644 --*/
    645 {
    646   EFI_STATUS                         Status;
    647   UINTN                              Index;
    648   EFI_DEVICE_PATH_PROTOCOL           *VarConout;
    649   EFI_DEVICE_PATH_PROTOCOL           *VarConin;
    650   UINTN                              DevicePathSize;
    651 
    652   //
    653   // Connect RootBridge
    654   //
    655   VarConout = BdsLibGetVariableAndSize (
    656                 VarConsoleOut,
    657                 &gEfiGlobalVariableGuid,
    658                 &DevicePathSize
    659                 );
    660   VarConin = BdsLibGetVariableAndSize (
    661                VarConsoleInp,
    662                &gEfiGlobalVariableGuid,
    663                &DevicePathSize
    664                );
    665 
    666   if (VarConout == NULL || VarConin == NULL) {
    667     //
    668     // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
    669     //
    670     DetectAndPreparePlatformPciDevicePaths (FALSE);
    671 
    672     //
    673     // Have chance to connect the platform default console,
    674     // the platform default console is the minimue device group
    675     // the platform should support
    676     //
    677     for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {
    678       //
    679       // Update the console variable with the connect type
    680       //
    681       if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
    682         BdsLibUpdateConsoleVariable (VarConsoleInp, PlatformConsole[Index].DevicePath, NULL);
    683       }
    684       if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
    685         BdsLibUpdateConsoleVariable (VarConsoleOut, PlatformConsole[Index].DevicePath, NULL);
    686       }
    687       if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
    688         BdsLibUpdateConsoleVariable (VarErrorOut, PlatformConsole[Index].DevicePath, NULL);
    689       }
    690     }
    691   } else {
    692     //
    693     // Only detect VGA device and add them to ConOut
    694     //
    695     DetectAndPreparePlatformPciDevicePaths (TRUE);
    696   }
    697 
    698   //
    699   // Connect the all the default console with current cosole variable
    700   //
    701   Status = BdsLibConnectAllDefaultConsoles ();
    702   if (EFI_ERROR (Status)) {
    703     return Status;
    704   }
    705 
    706   return EFI_SUCCESS;
    707 }
    708 
    709 
    710 /**
    711   Configure PCI Interrupt Line register for applicable devices
    712   Ported from SeaBIOS, src/fw/pciinit.c, *_pci_slot_get_irq()
    713 
    714   @param[in]  Handle - Handle of PCI device instance
    715   @param[in]  PciIo - PCI IO protocol instance
    716   @param[in]  PciHdr - PCI Header register block
    717 
    718   @retval EFI_SUCCESS - PCI Interrupt Line register configured successfully.
    719 
    720 **/
    721 EFI_STATUS
    722 EFIAPI
    723 SetPciIntLine (
    724   IN EFI_HANDLE           Handle,
    725   IN EFI_PCI_IO_PROTOCOL  *PciIo,
    726   IN PCI_TYPE00           *PciHdr
    727   )
    728 {
    729   EFI_DEVICE_PATH_PROTOCOL  *DevPathNode;
    730   EFI_DEVICE_PATH_PROTOCOL  *DevPath;
    731   UINTN                     RootSlot;
    732   UINTN                     Idx;
    733   UINT8                     IrqLine;
    734   EFI_STATUS                Status;
    735   UINT32                    RootBusNumber;
    736 
    737   Status = EFI_SUCCESS;
    738 
    739   if (PciHdr->Device.InterruptPin != 0) {
    740 
    741     DevPathNode = DevicePathFromHandle (Handle);
    742     ASSERT (DevPathNode != NULL);
    743     DevPath = DevPathNode;
    744 
    745     RootBusNumber = 0;
    746     if (DevicePathType (DevPathNode) == ACPI_DEVICE_PATH &&
    747         DevicePathSubType (DevPathNode) == ACPI_DP &&
    748         ((ACPI_HID_DEVICE_PATH *)DevPathNode)->HID == EISA_PNP_ID(0x0A03)) {
    749       RootBusNumber = ((ACPI_HID_DEVICE_PATH *)DevPathNode)->UID;
    750     }
    751 
    752     //
    753     // Compute index into PciHostIrqs[] table by walking
    754     // the device path and adding up all device numbers
    755     //
    756     Status = EFI_NOT_FOUND;
    757     RootSlot = 0;
    758     Idx = PciHdr->Device.InterruptPin - 1;
    759     while (!IsDevicePathEnd (DevPathNode)) {
    760       if (DevicePathType (DevPathNode) == HARDWARE_DEVICE_PATH &&
    761           DevicePathSubType (DevPathNode) == HW_PCI_DP) {
    762 
    763         Idx += ((PCI_DEVICE_PATH *)DevPathNode)->Device;
    764 
    765         //
    766         // Unlike SeaBIOS, which starts climbing from the leaf device
    767         // up toward the root, we traverse the device path starting at
    768         // the root moving toward the leaf node.
    769         // The slot number of the top-level parent bridge is needed for
    770         // Q35 cases with more than 24 slots on the root bus.
    771         //
    772         if (Status != EFI_SUCCESS) {
    773           Status = EFI_SUCCESS;
    774           RootSlot = ((PCI_DEVICE_PATH *)DevPathNode)->Device;
    775         }
    776       }
    777 
    778       DevPathNode = NextDevicePathNode (DevPathNode);
    779     }
    780     if (EFI_ERROR (Status)) {
    781       return Status;
    782     }
    783     if (RootBusNumber == 0 && RootSlot == 0) {
    784       DEBUG((
    785         EFI_D_ERROR,
    786         "%a: PCI host bridge (00:00.0) should have no interrupts!\n",
    787         __FUNCTION__
    788         ));
    789       ASSERT (FALSE);
    790     }
    791 
    792     //
    793     // Final PciHostIrqs[] index calculation depends on the platform
    794     // and should match SeaBIOS src/fw/pciinit.c *_pci_slot_get_irq()
    795     //
    796     switch (mHostBridgeDevId) {
    797       case INTEL_82441_DEVICE_ID:
    798         Idx -= 1;
    799         break;
    800       case INTEL_Q35_MCH_DEVICE_ID:
    801         //
    802         // SeaBIOS contains the following comment:
    803         // "Slots 0-24 rotate slot:pin mapping similar to piix above, but
    804         //  with a different starting index - see q35-acpi-dsdt.dsl.
    805         //
    806         //  Slots 25-31 all use LNKA mapping (or LNKE, but A:D = E:H)"
    807         //
    808         if (RootSlot > 24) {
    809           //
    810           // in this case, subtract back out RootSlot from Idx
    811           // (SeaBIOS never adds it to begin with, but that would make our
    812           //  device path traversal loop above too awkward)
    813           //
    814           Idx -= RootSlot;
    815         }
    816         break;
    817       default:
    818         ASSERT (FALSE); // should never get here
    819     }
    820     Idx %= ARRAY_SIZE (PciHostIrqs);
    821     IrqLine = PciHostIrqs[Idx];
    822 
    823     DEBUG_CODE_BEGIN ();
    824     {
    825       CHAR16        *DevPathString;
    826       STATIC CHAR16 Fallback[] = L"<failed to convert>";
    827       UINTN         Segment, Bus, Device, Function;
    828 
    829       DevPathString = ConvertDevicePathToText (DevPath, FALSE, FALSE);
    830       if (DevPathString == NULL) {
    831         DevPathString = Fallback;
    832       }
    833       Status = PciIo->GetLocation (PciIo, &Segment, &Bus, &Device, &Function);
    834       ASSERT_EFI_ERROR (Status);
    835 
    836       DEBUG ((EFI_D_VERBOSE, "%a: [%02x:%02x.%x] %s -> 0x%02x\n", __FUNCTION__,
    837         (UINT32)Bus, (UINT32)Device, (UINT32)Function, DevPathString,
    838         IrqLine));
    839 
    840       if (DevPathString != Fallback) {
    841         FreePool (DevPathString);
    842       }
    843     }
    844     DEBUG_CODE_END ();
    845 
    846     //
    847     // Set PCI Interrupt Line register for this device to PciHostIrqs[Idx]
    848     //
    849     Status = PciIo->Pci.Write (
    850                PciIo,
    851                EfiPciIoWidthUint8,
    852                PCI_INT_LINE_OFFSET,
    853                1,
    854                &IrqLine
    855                );
    856   }
    857 
    858   return Status;
    859 }
    860 
    861 
    862 VOID
    863 PciAcpiInitialization (
    864   )
    865 {
    866   UINTN  Pmba;
    867 
    868   //
    869   // Query Host Bridge DID to determine platform type
    870   //
    871   mHostBridgeDevId = PcdGet16 (PcdOvmfHostBridgePciDevId);
    872   switch (mHostBridgeDevId) {
    873     case INTEL_82441_DEVICE_ID:
    874       Pmba = POWER_MGMT_REGISTER_PIIX4 (PIIX4_PMBA);
    875       //
    876       // 00:01.0 ISA Bridge (PIIX4) LNK routing targets
    877       //
    878       PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x60), 0x0b); // A
    879       PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x61), 0x0b); // B
    880       PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x62), 0x0a); // C
    881       PciWrite8 (PCI_LIB_ADDRESS (0, 1, 0, 0x63), 0x0a); // D
    882       break;
    883     case INTEL_Q35_MCH_DEVICE_ID:
    884       Pmba = POWER_MGMT_REGISTER_Q35 (ICH9_PMBASE);
    885       //
    886       // 00:1f.0 LPC Bridge (Q35) LNK routing targets
    887       //
    888       PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x60), 0x0a); // A
    889       PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x61), 0x0a); // B
    890       PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x62), 0x0b); // C
    891       PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x63), 0x0b); // D
    892       PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x68), 0x0a); // E
    893       PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x69), 0x0a); // F
    894       PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6a), 0x0b); // G
    895       PciWrite8 (PCI_LIB_ADDRESS (0, 0x1f, 0, 0x6b), 0x0b); // H
    896       break;
    897     default:
    898       DEBUG ((EFI_D_ERROR, "%a: Unknown Host Bridge Device ID: 0x%04x\n",
    899         __FUNCTION__, mHostBridgeDevId));
    900       ASSERT (FALSE);
    901       return;
    902   }
    903 
    904   //
    905   // Initialize PCI_INTERRUPT_LINE for applicable present PCI devices
    906   //
    907   VisitAllPciInstances (SetPciIntLine);
    908 
    909   //
    910   // Set ACPI SCI_EN bit in PMCNTRL
    911   //
    912   IoOr16 ((PciRead32 (Pmba) & ~BIT0) + 4, BIT0);
    913 }
    914 
    915 
    916 EFI_STATUS
    917 EFIAPI
    918 ConnectRecursivelyIfPciMassStorage (
    919   IN EFI_HANDLE           Handle,
    920   IN EFI_PCI_IO_PROTOCOL  *Instance,
    921   IN PCI_TYPE00           *PciHeader
    922   )
    923 {
    924   EFI_STATUS                Status;
    925   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
    926   CHAR16                    *DevPathStr;
    927 
    928   if (IS_CLASS1 (PciHeader, PCI_CLASS_MASS_STORAGE)) {
    929     DevicePath = NULL;
    930     Status = gBS->HandleProtocol (
    931                     Handle,
    932                     &gEfiDevicePathProtocolGuid,
    933                     (VOID*)&DevicePath
    934                     );
    935     if (EFI_ERROR (Status)) {
    936       return Status;
    937     }
    938 
    939     //
    940     // Print Device Path
    941     //
    942     DevPathStr = DevicePathToStr (DevicePath);
    943     if (DevPathStr != NULL) {
    944       DEBUG((
    945         EFI_D_INFO,
    946         "Found Mass Storage device: %s\n",
    947         DevPathStr
    948         ));
    949       FreePool(DevPathStr);
    950     }
    951 
    952     Status = gBS->ConnectController (Handle, NULL, NULL, TRUE);
    953     if (EFI_ERROR (Status)) {
    954       return Status;
    955     }
    956 
    957   }
    958 
    959   return EFI_SUCCESS;
    960 }
    961 
    962 
    963 /**
    964   This notification function is invoked when the
    965   EMU Variable FVB has been changed.
    966 
    967   @param  Event                 The event that occured
    968   @param  Context               For EFI compatiblity.  Not used.
    969 
    970 **/
    971 VOID
    972 EFIAPI
    973 EmuVariablesUpdatedCallback (
    974   IN  EFI_EVENT Event,
    975   IN  VOID      *Context
    976   )
    977 {
    978   DEBUG ((EFI_D_INFO, "EmuVariablesUpdatedCallback\n"));
    979   UpdateNvVarsOnFileSystem ();
    980 }
    981 
    982 
    983 EFI_STATUS
    984 EFIAPI
    985 VisitingFileSystemInstance (
    986   IN EFI_HANDLE  Handle,
    987   IN VOID        *Instance,
    988   IN VOID        *Context
    989   )
    990 {
    991   EFI_STATUS      Status;
    992   STATIC BOOLEAN  ConnectedToFileSystem = FALSE;
    993 
    994   if (ConnectedToFileSystem) {
    995     return EFI_ALREADY_STARTED;
    996   }
    997 
    998   Status = ConnectNvVarsToFileSystem (Handle);
    999   if (EFI_ERROR (Status)) {
   1000     return Status;
   1001   }
   1002 
   1003   ConnectedToFileSystem = TRUE;
   1004   mEmuVariableEvent =
   1005     EfiCreateProtocolNotifyEvent (
   1006       &gEfiDevicePathProtocolGuid,
   1007       TPL_CALLBACK,
   1008       EmuVariablesUpdatedCallback,
   1009       NULL,
   1010       &mEmuVariableEventReg
   1011       );
   1012   PcdSet64 (PcdEmuVariableEvent, (UINT64)(UINTN) mEmuVariableEvent);
   1013 
   1014   return EFI_SUCCESS;
   1015 }
   1016 
   1017 
   1018 VOID
   1019 PlatformBdsRestoreNvVarsFromHardDisk (
   1020   )
   1021 {
   1022   VisitAllPciInstances (ConnectRecursivelyIfPciMassStorage);
   1023   VisitAllInstancesOfProtocol (
   1024     &gEfiSimpleFileSystemProtocolGuid,
   1025     VisitingFileSystemInstance,
   1026     NULL
   1027     );
   1028 
   1029 }
   1030 
   1031 
   1032 VOID
   1033 PlatformBdsConnectSequence (
   1034   VOID
   1035   )
   1036 /*++
   1037 
   1038 Routine Description:
   1039 
   1040   Connect with predeined platform connect sequence,
   1041   the OEM/IBV can customize with their own connect sequence.
   1042 
   1043 Arguments:
   1044 
   1045   None.
   1046 
   1047 Returns:
   1048 
   1049   None.
   1050 
   1051 --*/
   1052 {
   1053   UINTN Index;
   1054 
   1055   DEBUG ((EFI_D_INFO, "PlatformBdsConnectSequence\n"));
   1056 
   1057   Index = 0;
   1058 
   1059   //
   1060   // Here we can get the customized platform connect sequence
   1061   // Notes: we can connect with new variable which record the
   1062   // last time boots connect device path sequence
   1063   //
   1064   while (gPlatformConnectSequence[Index] != NULL) {
   1065     //
   1066     // Build the platform boot option
   1067     //
   1068     BdsLibConnectDevicePath (gPlatformConnectSequence[Index]);
   1069     Index++;
   1070   }
   1071 
   1072   //
   1073   // Just use the simple policy to connect all devices
   1074   //
   1075   BdsLibConnectAll ();
   1076 
   1077   PciAcpiInitialization ();
   1078 
   1079   //
   1080   // Clear the logo after all devices are connected.
   1081   //
   1082   gST->ConOut->ClearScreen (gST->ConOut);
   1083 }
   1084 
   1085 VOID
   1086 PlatformBdsGetDriverOption (
   1087   IN OUT LIST_ENTRY              *BdsDriverLists
   1088   )
   1089 /*++
   1090 
   1091 Routine Description:
   1092 
   1093   Load the predefined driver option, OEM/IBV can customize this
   1094   to load their own drivers
   1095 
   1096 Arguments:
   1097 
   1098   BdsDriverLists  - The header of the driver option link list.
   1099 
   1100 Returns:
   1101 
   1102   None.
   1103 
   1104 --*/
   1105 {
   1106   DEBUG ((EFI_D_INFO, "PlatformBdsGetDriverOption\n"));
   1107   return;
   1108 }
   1109 
   1110 VOID
   1111 PlatformBdsDiagnostics (
   1112   IN EXTENDMEM_COVERAGE_LEVEL    MemoryTestLevel,
   1113   IN BOOLEAN                     QuietBoot,
   1114   IN BASEM_MEMORY_TEST           BaseMemoryTest
   1115   )
   1116 /*++
   1117 
   1118 Routine Description:
   1119 
   1120   Perform the platform diagnostic, such like test memory. OEM/IBV also
   1121   can customize this fuction to support specific platform diagnostic.
   1122 
   1123 Arguments:
   1124 
   1125   MemoryTestLevel  - The memory test intensive level
   1126 
   1127   QuietBoot        - Indicate if need to enable the quiet boot
   1128 
   1129   BaseMemoryTest   - A pointer to BaseMemoryTest()
   1130 
   1131 Returns:
   1132 
   1133   None.
   1134 
   1135 --*/
   1136 {
   1137   EFI_STATUS  Status;
   1138 
   1139   DEBUG ((EFI_D_INFO, "PlatformBdsDiagnostics\n"));
   1140 
   1141   //
   1142   // Here we can decide if we need to show
   1143   // the diagnostics screen
   1144   // Notes: this quiet boot code should be remove
   1145   // from the graphic lib
   1146   //
   1147   if (QuietBoot) {
   1148     EnableQuietBoot (PcdGetPtr(PcdLogoFile));
   1149     //
   1150     // Perform system diagnostic
   1151     //
   1152     Status = BaseMemoryTest (MemoryTestLevel);
   1153     if (EFI_ERROR (Status)) {
   1154       DisableQuietBoot ();
   1155     }
   1156 
   1157     return ;
   1158   }
   1159   //
   1160   // Perform system diagnostic
   1161   //
   1162   Status = BaseMemoryTest (MemoryTestLevel);
   1163 }
   1164 
   1165 
   1166 /**
   1167   Empty callback function executed when the EndOfDxe event group is signaled.
   1168 
   1169   We only need this function because we'd like to signal EndOfDxe, and for that
   1170   we need to create an event, with a callback function.
   1171 
   1172   @param[in] Event    Event whose notification function is being invoked.
   1173   @param[in] Context  The pointer to the notification function's context, which
   1174                       is implementation-dependent.
   1175 **/
   1176 STATIC
   1177 VOID
   1178 EFIAPI
   1179 OnEndOfDxe (
   1180   IN EFI_EVENT Event,
   1181   IN VOID      *Context
   1182   )
   1183 {
   1184 }
   1185 
   1186 
   1187 /**
   1188   Save the S3 boot script.
   1189 
   1190   Note that we trigger DxeSmmReadyToLock here -- otherwise the script wouldn't
   1191   be saved actually. Triggering this protocol installation event in turn locks
   1192   down SMM, so no further changes to LockBoxes or SMRAM are possible
   1193   afterwards.
   1194 **/
   1195 STATIC
   1196 VOID
   1197 SaveS3BootScript (
   1198   VOID
   1199   )
   1200 {
   1201   EFI_STATUS                 Status;
   1202   EFI_S3_SAVE_STATE_PROTOCOL *BootScript;
   1203   EFI_HANDLE                 Handle;
   1204   STATIC CONST UINT8         Info[] = { 0xDE, 0xAD, 0xBE, 0xEF };
   1205 
   1206   Status = gBS->LocateProtocol (&gEfiS3SaveStateProtocolGuid, NULL,
   1207                   (VOID **) &BootScript);
   1208   ASSERT_EFI_ERROR (Status);
   1209 
   1210   //
   1211   // Despite the opcode documentation in the PI spec, the protocol
   1212   // implementation embeds a deep copy of the info in the boot script, rather
   1213   // than storing just a pointer to runtime or NVS storage.
   1214   //
   1215   Status = BootScript->Write(BootScript, EFI_BOOT_SCRIPT_INFORMATION_OPCODE,
   1216                          (UINT32) sizeof Info,
   1217                          (EFI_PHYSICAL_ADDRESS)(UINTN) &Info);
   1218   ASSERT_EFI_ERROR (Status);
   1219 
   1220   Handle = NULL;
   1221   Status = gBS->InstallProtocolInterface (&Handle,
   1222                   &gEfiDxeSmmReadyToLockProtocolGuid, EFI_NATIVE_INTERFACE,
   1223                   NULL);
   1224   ASSERT_EFI_ERROR (Status);
   1225 }
   1226 
   1227 
   1228 VOID
   1229 EFIAPI
   1230 PlatformBdsPolicyBehavior (
   1231   IN OUT LIST_ENTRY                  *DriverOptionList,
   1232   IN OUT LIST_ENTRY                  *BootOptionList,
   1233   IN PROCESS_CAPSULES                ProcessCapsules,
   1234   IN BASEM_MEMORY_TEST               BaseMemoryTest
   1235   )
   1236 /*++
   1237 
   1238 Routine Description:
   1239 
   1240   The function will excute with as the platform policy, current policy
   1241   is driven by boot mode. IBV/OEM can customize this code for their specific
   1242   policy action.
   1243 
   1244 Arguments:
   1245 
   1246   DriverOptionList - The header of the driver option link list
   1247 
   1248   BootOptionList   - The header of the boot option link list
   1249 
   1250   ProcessCapsules  - A pointer to ProcessCapsules()
   1251 
   1252   BaseMemoryTest   - A pointer to BaseMemoryTest()
   1253 
   1254 Returns:
   1255 
   1256   None.
   1257 
   1258 --*/
   1259 {
   1260   EFI_STATUS                         Status;
   1261   EFI_BOOT_MODE                      BootMode;
   1262   EFI_EVENT                          EndOfDxeEvent;
   1263 
   1264   DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior\n"));
   1265 
   1266   VisitAllInstancesOfProtocol (&gEfiPciRootBridgeIoProtocolGuid,
   1267     ConnectRootBridge, NULL);
   1268 
   1269   //
   1270   // We can't signal End-of-Dxe earlier than this. Namely, End-of-Dxe triggers
   1271   // the preparation of S3 system information. That logic has a hard dependency
   1272   // on the presence of the FACS ACPI table. Since our ACPI tables are only
   1273   // installed after PCI enumeration completes, we must not trigger the S3 save
   1274   // earlier, hence we can't signal End-of-Dxe earlier.
   1275   //
   1276   Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, OnEndOfDxe,
   1277                   NULL /* NotifyContext */, &gEfiEndOfDxeEventGroupGuid,
   1278                   &EndOfDxeEvent);
   1279   if (!EFI_ERROR (Status)) {
   1280     gBS->SignalEvent (EndOfDxeEvent);
   1281     gBS->CloseEvent (EndOfDxeEvent);
   1282   }
   1283 
   1284   if (QemuFwCfgS3Enabled ()) {
   1285     //
   1286     // Save the boot script too. Note that this requires/includes emitting the
   1287     // DxeSmmReadyToLock event, which in turn locks down SMM.
   1288     //
   1289     SaveS3BootScript ();
   1290   }
   1291 
   1292   if (PcdGetBool (PcdOvmfFlashVariablesEnable)) {
   1293     DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior: not restoring NvVars "
   1294       "from disk since flash variables appear to be supported.\n"));
   1295   } else {
   1296     //
   1297     // Try to restore variables from the hard disk early so
   1298     // they can be used for the other BDS connect operations.
   1299     //
   1300     PlatformBdsRestoreNvVarsFromHardDisk ();
   1301   }
   1302 
   1303   //
   1304   // Load the driver option as the driver option list
   1305   //
   1306   PlatformBdsGetDriverOption (DriverOptionList);
   1307 
   1308   //
   1309   // Get current Boot Mode
   1310   //
   1311   Status = BdsLibGetBootMode (&BootMode);
   1312   DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode));
   1313 
   1314   //
   1315   // Go the different platform policy with different boot mode
   1316   // Notes: this part code can be change with the table policy
   1317   //
   1318   ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);
   1319   //
   1320   // Connect platform console
   1321   //
   1322   Status = PlatformBdsConnectConsole (gPlatformConsole);
   1323   if (EFI_ERROR (Status)) {
   1324     //
   1325     // Here OEM/IBV can customize with defined action
   1326     //
   1327     PlatformBdsNoConsoleAction ();
   1328   }
   1329 
   1330   //
   1331   // Memory test and Logo show
   1332   //
   1333   PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest);
   1334 
   1335   //
   1336   // Perform some platform specific connect sequence
   1337   //
   1338   PlatformBdsConnectSequence ();
   1339 
   1340   //
   1341   // Process QEMU's -kernel command line option
   1342   //
   1343   TryRunningQemuKernel ();
   1344 
   1345   DEBUG ((EFI_D_INFO, "BdsLibConnectAll\n"));
   1346   BdsLibConnectAll ();
   1347   BdsLibEnumerateAllBootOption (BootOptionList);
   1348 
   1349   SetBootOrderFromQemu (BootOptionList);
   1350   //
   1351   // The BootOrder variable may have changed, reload the in-memory list with
   1352   // it.
   1353   //
   1354   BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");
   1355 
   1356   PlatformBdsEnterFrontPage (GetFrontPageTimeoutFromQemu(), TRUE);
   1357 }
   1358 
   1359 VOID
   1360 EFIAPI
   1361 PlatformBdsBootSuccess (
   1362   IN  BDS_COMMON_OPTION   *Option
   1363   )
   1364 /*++
   1365 
   1366 Routine Description:
   1367 
   1368   Hook point after a boot attempt succeeds. We don't expect a boot option to
   1369   return, so the EFI 1.0 specification defines that you will default to an
   1370   interactive mode and stop processing the BootOrder list in this case. This
   1371   is alos a platform implementation and can be customized by IBV/OEM.
   1372 
   1373 Arguments:
   1374 
   1375   Option - Pointer to Boot Option that succeeded to boot.
   1376 
   1377 Returns:
   1378 
   1379   None.
   1380 
   1381 --*/
   1382 {
   1383   CHAR16  *TmpStr;
   1384 
   1385   DEBUG ((EFI_D_INFO, "PlatformBdsBootSuccess\n"));
   1386   //
   1387   // If Boot returned with EFI_SUCCESS and there is not in the boot device
   1388   // select loop then we need to pop up a UI and wait for user input.
   1389   //
   1390   TmpStr = Option->StatusString;
   1391   if (TmpStr != NULL) {
   1392     BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
   1393     FreePool (TmpStr);
   1394   }
   1395 }
   1396 
   1397 VOID
   1398 EFIAPI
   1399 PlatformBdsBootFail (
   1400   IN  BDS_COMMON_OPTION  *Option,
   1401   IN  EFI_STATUS         Status,
   1402   IN  CHAR16             *ExitData,
   1403   IN  UINTN              ExitDataSize
   1404   )
   1405 /*++
   1406 
   1407 Routine Description:
   1408 
   1409   Hook point after a boot attempt fails.
   1410 
   1411 Arguments:
   1412 
   1413   Option - Pointer to Boot Option that failed to boot.
   1414 
   1415   Status - Status returned from failed boot.
   1416 
   1417   ExitData - Exit data returned from failed boot.
   1418 
   1419   ExitDataSize - Exit data size returned from failed boot.
   1420 
   1421 Returns:
   1422 
   1423   None.
   1424 
   1425 --*/
   1426 {
   1427   CHAR16  *TmpStr;
   1428 
   1429   DEBUG ((EFI_D_INFO, "PlatformBdsBootFail\n"));
   1430 
   1431   //
   1432   // If Boot returned with failed status then we need to pop up a UI and wait
   1433   // for user input.
   1434   //
   1435   TmpStr = Option->StatusString;
   1436   if (TmpStr != NULL) {
   1437     BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
   1438     FreePool (TmpStr);
   1439   }
   1440 }
   1441 
   1442 EFI_STATUS
   1443 PlatformBdsNoConsoleAction (
   1444   VOID
   1445   )
   1446 /*++
   1447 
   1448 Routine Description:
   1449 
   1450   This function is remained for IBV/OEM to do some platform action,
   1451   if there no console device can be connected.
   1452 
   1453 Arguments:
   1454 
   1455   None.
   1456 
   1457 Returns:
   1458 
   1459   EFI_SUCCESS      - Direct return success now.
   1460 
   1461 --*/
   1462 {
   1463   DEBUG ((EFI_D_INFO, "PlatformBdsNoConsoleAction\n"));
   1464   return EFI_SUCCESS;
   1465 }
   1466 
   1467 VOID
   1468 EFIAPI
   1469 PlatformBdsLockNonUpdatableFlash (
   1470   VOID
   1471   )
   1472 {
   1473   DEBUG ((EFI_D_INFO, "PlatformBdsLockNonUpdatableFlash\n"));
   1474   return;
   1475 }
   1476 
   1477 
   1478 /**
   1479   This notification function is invoked when an instance of the
   1480   EFI_DEVICE_PATH_PROTOCOL is produced.
   1481 
   1482   @param  Event                 The event that occured
   1483   @param  Context               For EFI compatiblity.  Not used.
   1484 
   1485 **/
   1486 VOID
   1487 EFIAPI
   1488 NotifyDevPath (
   1489   IN  EFI_EVENT Event,
   1490   IN  VOID      *Context
   1491   )
   1492 {
   1493   EFI_HANDLE                            Handle;
   1494   EFI_STATUS                            Status;
   1495   UINTN                                 BufferSize;
   1496   EFI_DEVICE_PATH_PROTOCOL             *DevPathNode;
   1497   ATAPI_DEVICE_PATH                    *Atapi;
   1498 
   1499   //
   1500   // Examine all new handles
   1501   //
   1502   for (;;) {
   1503     //
   1504     // Get the next handle
   1505     //
   1506     BufferSize = sizeof (Handle);
   1507     Status = gBS->LocateHandle (
   1508               ByRegisterNotify,
   1509               NULL,
   1510               mEfiDevPathNotifyReg,
   1511               &BufferSize,
   1512               &Handle
   1513               );
   1514 
   1515     //
   1516     // If not found, we're done
   1517     //
   1518     if (EFI_NOT_FOUND == Status) {
   1519       break;
   1520     }
   1521 
   1522     if (EFI_ERROR (Status)) {
   1523       continue;
   1524     }
   1525 
   1526     //
   1527     // Get the DevicePath protocol on that handle
   1528     //
   1529     Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&DevPathNode);
   1530     ASSERT_EFI_ERROR (Status);
   1531 
   1532     while (!IsDevicePathEnd (DevPathNode)) {
   1533       //
   1534       // Find the handler to dump this device path node
   1535       //
   1536       if (
   1537            (DevicePathType(DevPathNode) == MESSAGING_DEVICE_PATH) &&
   1538            (DevicePathSubType(DevPathNode) == MSG_ATAPI_DP)
   1539          ) {
   1540         Atapi = (ATAPI_DEVICE_PATH*) DevPathNode;
   1541         PciOr16 (
   1542           PCI_LIB_ADDRESS (
   1543             0,
   1544             1,
   1545             1,
   1546             (Atapi->PrimarySecondary == 1) ? 0x42: 0x40
   1547             ),
   1548           BIT15
   1549           );
   1550       }
   1551 
   1552       //
   1553       // Next device path node
   1554       //
   1555       DevPathNode = NextDevicePathNode (DevPathNode);
   1556     }
   1557   }
   1558 
   1559   return;
   1560 }
   1561 
   1562 
   1563 VOID
   1564 InstallDevicePathCallback (
   1565   VOID
   1566   )
   1567 {
   1568   DEBUG ((EFI_D_INFO, "Registered NotifyDevPath Event\n"));
   1569   mEfiDevPathEvent = EfiCreateProtocolNotifyEvent (
   1570                           &gEfiDevicePathProtocolGuid,
   1571                           TPL_CALLBACK,
   1572                           NotifyDevPath,
   1573                           NULL,
   1574                           &mEfiDevPathNotifyReg
   1575                           );
   1576 }
   1577 
   1578 /**
   1579   Lock the ConsoleIn device in system table. All key
   1580   presses will be ignored until the Password is typed in. The only way to
   1581   disable the password is to type it in to a ConIn device.
   1582 
   1583   @param  Password        Password used to lock ConIn device.
   1584 
   1585   @retval EFI_SUCCESS     lock the Console In Spliter virtual handle successfully.
   1586   @retval EFI_UNSUPPORTED Password not found
   1587 
   1588 **/
   1589 EFI_STATUS
   1590 EFIAPI
   1591 LockKeyboards (
   1592   IN  CHAR16    *Password
   1593   )
   1594 {
   1595     return EFI_UNSUPPORTED;
   1596 }
   1597 
   1598