Home | History | Annotate | Download | only in PlatformBdsLib
      1 /** @file
      2   This file include all platform action which can be customized by IBV/OEM.
      3 
      4 Copyright (c) 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 
     17 //
     18 // Global data
     19 //
     20 BOOLEAN       mDetectVgaOnly;
     21 
     22 
     23 //
     24 // Type definitions
     25 //
     26 
     27 typedef
     28 EFI_STATUS
     29 (EFIAPI *PROTOCOL_INSTANCE_CALLBACK)(
     30   IN EFI_HANDLE           Handle,
     31   IN VOID                 *Instance,
     32   IN VOID                 *Context
     33   );
     34 
     35 /**
     36   @param[in]  Handle - Handle of PCI device instance
     37   @param[in]  PciIo - PCI IO protocol instance
     38   @param[in]  Pci - PCI Header register block
     39 **/
     40 typedef
     41 EFI_STATUS
     42 (EFIAPI *VISIT_PCI_INSTANCE_CALLBACK)(
     43   IN EFI_HANDLE           Handle,
     44   IN EFI_PCI_IO_PROTOCOL  *PciIo,
     45   IN PCI_TYPE00           *Pci
     46   );
     47 
     48 
     49 //
     50 // Function prototypes
     51 //
     52 
     53 EFI_STATUS
     54 VisitAllInstancesOfProtocol (
     55   IN EFI_GUID                    *Id,
     56   IN PROTOCOL_INSTANCE_CALLBACK  CallBackFunction,
     57   IN VOID                        *Context
     58   );
     59 
     60 EFI_STATUS
     61 VisitAllPciInstancesOfProtocol (
     62   IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
     63   );
     64 
     65 
     66 //
     67 // BDS Platform Functions
     68 //
     69 
     70 /**
     71   Platform Bds init. Include the platform firmware vendor, revision
     72   and so crc check.
     73 
     74 **/
     75 VOID
     76 EFIAPI
     77 PlatformBdsInit (
     78   VOID
     79   )
     80 {
     81 }
     82 
     83 
     84 EFI_STATUS
     85 PrepareLpcBridgeDevicePath (
     86   IN EFI_HANDLE                DeviceHandle
     87   )
     88 /*++
     89 
     90 Routine Description:
     91 
     92   Add IsaKeyboard to ConIn,
     93   add IsaSerial to ConOut, ConIn, ErrOut.
     94   LPC Bridge: 06 01 00
     95 
     96 Arguments:
     97 
     98   DeviceHandle            - Handle of PCIIO protocol.
     99 
    100 Returns:
    101 
    102   EFI_SUCCESS             - LPC bridge is added to ConOut, ConIn, and ErrOut.
    103   EFI_STATUS              - No LPC bridge is added.
    104 
    105 --*/
    106 {
    107   EFI_STATUS                Status;
    108   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
    109   EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
    110   CHAR16                    *DevPathStr;
    111 
    112   DevicePath = NULL;
    113   Status = gBS->HandleProtocol (
    114                   DeviceHandle,
    115                   &gEfiDevicePathProtocolGuid,
    116                   (VOID*)&DevicePath
    117                   );
    118   if (EFI_ERROR (Status)) {
    119     return Status;
    120   }
    121   TempDevicePath = DevicePath;
    122 
    123   //
    124   // Register COM1
    125   //
    126   DevicePath = AppendDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *)NULL, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceVenderNode);
    127   DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
    128   DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
    129 
    130   //
    131   // Print Device Path
    132   //
    133   DevPathStr = DevicePathToStr(DevicePath);
    134   DEBUG((
    135     EFI_D_INFO,
    136     "BdsPlatform.c+%d: COM%d DevPath: %s\n",
    137     __LINE__,
    138     gPnp16550ComPortDeviceNode.UID + 1,
    139     DevPathStr
    140     ));
    141   FreePool(DevPathStr);
    142 
    143   BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
    144   BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
    145   BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);
    146 
    147   return EFI_SUCCESS;
    148 }
    149 
    150 EFI_STATUS
    151 GetGopDevicePath (
    152    IN  EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,
    153    OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath
    154    )
    155 {
    156   UINTN                           Index;
    157   EFI_STATUS                      Status;
    158   EFI_HANDLE                      PciDeviceHandle;
    159   EFI_DEVICE_PATH_PROTOCOL        *TempDevicePath;
    160   EFI_DEVICE_PATH_PROTOCOL        *TempPciDevicePath;
    161   UINTN                           GopHandleCount;
    162   EFI_HANDLE                      *GopHandleBuffer;
    163 
    164   if (PciDevicePath == NULL || GopDevicePath == NULL) {
    165     return EFI_INVALID_PARAMETER;
    166   }
    167 
    168   //
    169   // Initialize the GopDevicePath to be PciDevicePath
    170   //
    171   *GopDevicePath    = PciDevicePath;
    172   TempPciDevicePath = PciDevicePath;
    173 
    174   Status = gBS->LocateDevicePath (
    175                   &gEfiDevicePathProtocolGuid,
    176                   &TempPciDevicePath,
    177                   &PciDeviceHandle
    178                   );
    179   if (EFI_ERROR (Status)) {
    180     return Status;
    181   }
    182 
    183   //
    184   // Try to connect this handle, so that GOP dirver could start on this
    185   // device and create child handles with GraphicsOutput Protocol installed
    186   // on them, then we get device paths of these child handles and select
    187   // them as possible console device.
    188   //
    189 #if 0
    190   gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);
    191 #else
    192   {
    193     ACPI_ADR_DEVICE_PATH         AcpiAdr;
    194     EFI_DEVICE_PATH_PROTOCOL  *MyDevicePath = NULL;
    195 
    196     AcpiAdr.Header.Type     = ACPI_DEVICE_PATH;
    197     AcpiAdr.Header.SubType  = ACPI_ADR_DP;
    198     //AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA, 6, 0);    //on bayleybay, CRT Device
    199     AcpiAdr.ADR= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_INTERNAL_DIGITAL, 8, 0); ; // on rambi, eDP C
    200 
    201     SetDevicePathNodeLength (&AcpiAdr.Header, sizeof (ACPI_ADR_DEVICE_PATH));
    202 
    203     MyDevicePath = AppendDevicePathNode(MyDevicePath, (EFI_DEVICE_PATH_PROTOCOL*)&AcpiAdr);
    204 
    205     gBS->ConnectController (PciDeviceHandle, NULL, MyDevicePath, FALSE);
    206 
    207     FreePool(MyDevicePath);
    208   }
    209 #endif
    210 
    211   Status = gBS->LocateHandleBuffer (
    212                   ByProtocol,
    213                   &gEfiGraphicsOutputProtocolGuid,
    214                   NULL,
    215                   &GopHandleCount,
    216                   &GopHandleBuffer
    217                   );
    218   if (!EFI_ERROR (Status)) {
    219     //
    220     // Add all the child handles as possible Console Device
    221     //
    222     for (Index = 0; Index < GopHandleCount; Index++) {
    223       Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);
    224       if (EFI_ERROR (Status)) {
    225         continue;
    226       }
    227       if (CompareMem (
    228             PciDevicePath,
    229             TempDevicePath,
    230             GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH
    231             ) == 0) {
    232         //
    233         // In current implementation, we only enable one of the child handles
    234         // as console device, i.e. sotre one of the child handle's device
    235         // path to variable "ConOut"
    236         // In futhure, we could select all child handles to be console device
    237         //
    238 
    239         *GopDevicePath = TempDevicePath;
    240 
    241         //
    242         // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
    243         // Add the integrity GOP device path.
    244         //
    245         BdsLibUpdateConsoleVariable (VarConsoleOutDev, NULL, PciDevicePath);
    246         BdsLibUpdateConsoleVariable (VarConsoleOutDev, TempDevicePath, NULL);
    247       }
    248     }
    249     gBS->FreePool (GopHandleBuffer);
    250   }
    251 
    252   return EFI_SUCCESS;
    253 }
    254 
    255 EFI_STATUS
    256 PreparePciVgaDevicePath (
    257   IN EFI_HANDLE                DeviceHandle
    258   )
    259 /*++
    260 
    261 Routine Description:
    262 
    263   Add PCI VGA to ConOut.
    264   PCI VGA: 03 00 00
    265 
    266 Arguments:
    267 
    268   DeviceHandle            - Handle of PCIIO protocol.
    269 
    270 Returns:
    271 
    272   EFI_SUCCESS             - PCI VGA is added to ConOut.
    273   EFI_STATUS              - No PCI VGA device is added.
    274 
    275 --*/
    276 {
    277   EFI_STATUS                Status;
    278   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
    279   EFI_DEVICE_PATH_PROTOCOL  *GopDevicePath;
    280 
    281   DevicePath = NULL;
    282   Status = gBS->HandleProtocol (
    283                   DeviceHandle,
    284                   &gEfiDevicePathProtocolGuid,
    285                   (VOID*)&DevicePath
    286                   );
    287   if (EFI_ERROR (Status)) {
    288     return Status;
    289   }
    290 
    291   GetGopDevicePath (DevicePath, &GopDevicePath);
    292   DevicePath = GopDevicePath;
    293 
    294   BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
    295 
    296   return EFI_SUCCESS;
    297 }
    298 
    299 EFI_STATUS
    300 PreparePciSerialDevicePath (
    301   IN EFI_HANDLE                DeviceHandle
    302   )
    303 /*++
    304 
    305 Routine Description:
    306 
    307   Add PCI Serial to ConOut, ConIn, ErrOut.
    308   PCI Serial: 07 00 02
    309 
    310 Arguments:
    311 
    312   DeviceHandle            - Handle of PCIIO protocol.
    313 
    314 Returns:
    315 
    316   EFI_SUCCESS             - PCI Serial is added to ConOut, ConIn, and ErrOut.
    317   EFI_STATUS              - No PCI Serial device is added.
    318 
    319 --*/
    320 {
    321   EFI_STATUS                Status;
    322   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
    323 
    324   DevicePath = NULL;
    325   Status = gBS->HandleProtocol (
    326                   DeviceHandle,
    327                   &gEfiDevicePathProtocolGuid,
    328                   (VOID*)&DevicePath
    329                   );
    330   if (EFI_ERROR (Status)) {
    331     return Status;
    332   }
    333 
    334   DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
    335   DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
    336 
    337   BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
    338   BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
    339   BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);
    340 
    341   return EFI_SUCCESS;
    342 }
    343 
    344 EFI_STATUS
    345 VisitAllInstancesOfProtocol (
    346   IN EFI_GUID                    *Id,
    347   IN PROTOCOL_INSTANCE_CALLBACK  CallBackFunction,
    348   IN VOID                        *Context
    349   )
    350 {
    351   EFI_STATUS                Status;
    352   UINTN                     HandleCount;
    353   EFI_HANDLE                *HandleBuffer;
    354   UINTN                     Index;
    355   VOID                      *Instance;
    356 
    357   //
    358   // Start to check all the PciIo to find all possible device
    359   //
    360   HandleCount = 0;
    361   HandleBuffer = NULL;
    362   Status = gBS->LocateHandleBuffer (
    363                   ByProtocol,
    364                   Id,
    365                   NULL,
    366                   &HandleCount,
    367                   &HandleBuffer
    368                   );
    369   if (EFI_ERROR (Status)) {
    370     return Status;
    371   }
    372 
    373   for (Index = 0; Index < HandleCount; Index++) {
    374     Status = gBS->HandleProtocol (HandleBuffer[Index], Id, &Instance);
    375     if (EFI_ERROR (Status)) {
    376       continue;
    377     }
    378 
    379     Status = (*CallBackFunction) (
    380                HandleBuffer[Index],
    381                Instance,
    382                Context
    383                );
    384   }
    385 
    386   gBS->FreePool (HandleBuffer);
    387 
    388   return EFI_SUCCESS;
    389 }
    390 
    391 
    392 EFI_STATUS
    393 EFIAPI
    394 VisitingAPciInstance (
    395   IN EFI_HANDLE  Handle,
    396   IN VOID        *Instance,
    397   IN VOID        *Context
    398   )
    399 {
    400   EFI_STATUS                Status;
    401   EFI_PCI_IO_PROTOCOL       *PciIo;
    402   PCI_TYPE00                Pci;
    403 
    404   PciIo = (EFI_PCI_IO_PROTOCOL*) Instance;
    405 
    406   //
    407   // Check for all PCI device
    408   //
    409   Status = PciIo->Pci.Read (
    410                     PciIo,
    411                     EfiPciIoWidthUint32,
    412                     0,
    413                     sizeof (Pci) / sizeof (UINT32),
    414                     &Pci
    415                     );
    416   if (EFI_ERROR (Status)) {
    417     return Status;
    418   }
    419 
    420   return (*(VISIT_PCI_INSTANCE_CALLBACK)(UINTN) Context) (
    421            Handle,
    422            PciIo,
    423            &Pci
    424            );
    425 
    426 }
    427 
    428 
    429 
    430 EFI_STATUS
    431 VisitAllPciInstances (
    432   IN VISIT_PCI_INSTANCE_CALLBACK CallBackFunction
    433   )
    434 {
    435   return VisitAllInstancesOfProtocol (
    436            &gEfiPciIoProtocolGuid,
    437            VisitingAPciInstance,
    438            (VOID*)(UINTN) CallBackFunction
    439            );
    440 }
    441 
    442 
    443 /**
    444   Do platform specific PCI Device check and add them to
    445   ConOut, ConIn, ErrOut.
    446 
    447   @param[in]  Handle - Handle of PCI device instance
    448   @param[in]  PciIo - PCI IO protocol instance
    449   @param[in]  Pci - PCI Header register block
    450 
    451   @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
    452   @retval EFI_STATUS - PCI Device check or Console variable update fail.
    453 
    454 **/
    455 EFI_STATUS
    456 EFIAPI
    457 DetectAndPreparePlatformPciDevicePath (
    458   IN EFI_HANDLE           Handle,
    459   IN EFI_PCI_IO_PROTOCOL  *PciIo,
    460   IN PCI_TYPE00           *Pci
    461   )
    462 {
    463   EFI_STATUS                Status;
    464 
    465   Status = PciIo->Attributes (
    466     PciIo,
    467     EfiPciIoAttributeOperationEnable,
    468     EFI_PCI_DEVICE_ENABLE,
    469     NULL
    470     );
    471   ASSERT_EFI_ERROR (Status);
    472 
    473   if (!mDetectVgaOnly) {
    474     //
    475     // Here we decide whether it is LPC Bridge
    476     //
    477     if ((IS_PCI_LPC (Pci)) ||
    478         ((IS_PCI_ISA_PDECODE (Pci)) &&
    479          (Pci->Hdr.VendorId == 0x8086)
    480         )
    481        ) {
    482       //
    483       // Add IsaKeyboard to ConIn,
    484       // add IsaSerial to ConOut, ConIn, ErrOut
    485       //
    486       DEBUG ((EFI_D_INFO, "Found LPC Bridge device\n"));
    487       PrepareLpcBridgeDevicePath (Handle);
    488       return EFI_SUCCESS;
    489     }
    490     //
    491     // Here we decide which Serial device to enable in PCI bus
    492     //
    493     if (IS_PCI_16550SERIAL (Pci)) {
    494       //
    495       // Add them to ConOut, ConIn, ErrOut.
    496       //
    497       DEBUG ((EFI_D_INFO, "Found PCI 16550 SERIAL device\n"));
    498       PreparePciSerialDevicePath (Handle);
    499       return EFI_SUCCESS;
    500     }
    501   }
    502 
    503   //
    504   // Here we decide which VGA device to enable in PCI bus
    505   //
    506   if (IS_PCI_VGA (Pci)) {
    507     //
    508     // Add them to ConOut.
    509     //
    510     DEBUG ((EFI_D_INFO, "Found PCI VGA device\n"));
    511     PreparePciVgaDevicePath (Handle);
    512     return EFI_SUCCESS;
    513   }
    514 
    515   return Status;
    516 }
    517 
    518 
    519 /**
    520   Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
    521 
    522   @param[in]  DetectVgaOnly - Only detect VGA device if it's TRUE.
    523 
    524   @retval EFI_SUCCESS - PCI Device check and Console variable update successfully.
    525   @retval EFI_STATUS - PCI Device check or Console variable update fail.
    526 
    527 **/
    528 EFI_STATUS
    529 DetectAndPreparePlatformPciDevicePaths (
    530   BOOLEAN DetectVgaOnly
    531   )
    532 {
    533   mDetectVgaOnly = DetectVgaOnly;
    534   return VisitAllPciInstances (DetectAndPreparePlatformPciDevicePath);
    535 }
    536 
    537 /**
    538   Connect the predefined platform default console device. Always try to find
    539   and enable the vga device if have.
    540 
    541   @param PlatformConsole          Predefined platform default console device array.
    542 
    543   @retval EFI_SUCCESS             Success connect at least one ConIn and ConOut
    544                                   device, there must have one ConOut device is
    545                                   active vga device.
    546   @return Return the status of BdsLibConnectAllDefaultConsoles ()
    547 
    548 **/
    549 EFI_STATUS
    550 PlatformBdsConnectConsole (
    551   IN BDS_CONSOLE_CONNECT_ENTRY   *PlatformConsole
    552   )
    553 {
    554   EFI_STATUS                         Status;
    555   UINTN                              Index;
    556   EFI_DEVICE_PATH_PROTOCOL           *VarConout;
    557   EFI_DEVICE_PATH_PROTOCOL           *VarConin;
    558   UINTN                              DevicePathSize;
    559 
    560   //
    561   // Connect RootBridge
    562   //
    563   VarConout = BdsLibGetVariableAndSize (
    564                 VarConsoleOut,
    565                 &gEfiGlobalVariableGuid,
    566                 &DevicePathSize
    567                 );
    568   VarConin = BdsLibGetVariableAndSize (
    569                VarConsoleInp,
    570                &gEfiGlobalVariableGuid,
    571                &DevicePathSize
    572                );
    573 
    574   if (VarConout == NULL || VarConin == NULL) {
    575     //
    576     // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
    577     //
    578     DetectAndPreparePlatformPciDevicePaths (FALSE);
    579 
    580     //
    581     // Have chance to connect the platform default console,
    582     // the platform default console is the minimue device group
    583     // the platform should support
    584     //
    585     for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {
    586       //
    587       // Update the console variable with the connect type
    588       //
    589       if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
    590         BdsLibUpdateConsoleVariable (VarConsoleInp, PlatformConsole[Index].DevicePath, NULL);
    591       }
    592       if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
    593         BdsLibUpdateConsoleVariable (VarConsoleOut, PlatformConsole[Index].DevicePath, NULL);
    594       }
    595       if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
    596         BdsLibUpdateConsoleVariable (VarErrorOut, PlatformConsole[Index].DevicePath, NULL);
    597       }
    598     }
    599   } else {
    600     //
    601     // Only detect VGA device and add them to ConOut
    602     //
    603     DetectAndPreparePlatformPciDevicePaths (TRUE);
    604   }
    605 
    606   //
    607   // Connect the all the default console with current cosole variable
    608   //
    609   Status = BdsLibConnectAllDefaultConsoles ();
    610   if (EFI_ERROR (Status)) {
    611     return Status;
    612   }
    613 
    614   return EFI_SUCCESS;
    615 }
    616 
    617 /**
    618   Connect with predefined platform connect sequence,
    619   the OEM/IBV can customize with their own connect sequence.
    620 **/
    621 VOID
    622 PlatformBdsConnectSequence (
    623   VOID
    624   )
    625 {
    626 	UINTN Index;
    627 
    628   DEBUG ((EFI_D_INFO, "PlatformBdsConnectSequence\n"));
    629   Index = 0;
    630 
    631   //
    632   // Here we can get the customized platform connect sequence
    633   // Notes: we can connect with new variable which record the
    634   // last time boots connect device path sequence
    635   //
    636   while (gPlatformConnectSequence[Index] != NULL) {
    637     //
    638     // Build the platform boot option
    639     //
    640     BdsLibConnectDevicePath (gPlatformConnectSequence[Index]);
    641     Index++;
    642   }
    643 }
    644 
    645 /**
    646   Load the predefined driver option, OEM/IBV can customize this
    647   to load their own drivers
    648 
    649   @param BdsDriverLists  - The header of the driver option link list.
    650 
    651 **/
    652 VOID
    653 PlatformBdsGetDriverOption (
    654   IN OUT LIST_ENTRY              *BdsDriverLists
    655   )
    656 {
    657 	UINTN                              Index;
    658 
    659   Index = 0;
    660 
    661   DEBUG ((EFI_D_INFO, "PlatformBdsGetDriverOption\n"));
    662 
    663 
    664   //
    665   // Here we can get the customized platform driver option
    666   //
    667   while (gPlatformDriverOption[Index] != NULL) {
    668 
    669     //
    670     // Build the platform boot option
    671     //
    672     BdsLibRegisterNewOption (BdsDriverLists, gPlatformDriverOption[Index], NULL, L"DriverOrder");
    673     Index ++;
    674   }
    675 }
    676 
    677 /**
    678   Perform the platform diagnostic, such like test memory. OEM/IBV also
    679   can customize this function to support specific platform diagnostic.
    680 
    681   @param MemoryTestLevel  The memory test intensive level
    682   @param QuietBoot        Indicate if need to enable the quiet boot
    683   @param BaseMemoryTest   A pointer to BdsMemoryTest()
    684 
    685 **/
    686 VOID
    687 PlatformBdsDiagnostics (
    688   IN EXTENDMEM_COVERAGE_LEVEL    MemoryTestLevel,
    689   IN BOOLEAN                     QuietBoot,
    690   IN BASEM_MEMORY_TEST           BaseMemoryTest
    691   )
    692 {
    693 	EFI_STATUS                     Status;
    694 
    695   DEBUG ((EFI_D_INFO, "PlatformBdsDiagnostics\n"));
    696   //
    697   // Here we can decide if we need to show
    698   // the diagnostics screen
    699   // Notes: this quiet boot code should be remove
    700   // from the graphic lib
    701   //
    702   if (QuietBoot) {
    703     EnableQuietBoot (PcdGetPtr(PcdLogoFile));
    704 
    705     //
    706     // Perform system diagnostic
    707     //
    708     Status = BaseMemoryTest (MemoryTestLevel);
    709     if (EFI_ERROR (Status)) {
    710       DisableQuietBoot ();
    711     }
    712 
    713     return;
    714   }
    715 
    716   //
    717   // Perform system diagnostic
    718   //
    719   Status = BaseMemoryTest (MemoryTestLevel);
    720 }
    721 
    722 
    723 /**
    724   The function will connect root bridge
    725 
    726    @return EFI_SUCCESS      Connect RootBridge successfully.
    727 
    728 **/
    729 EFI_STATUS
    730 ConnectRootBridge (
    731   VOID
    732   )
    733 {
    734   EFI_STATUS                Status;
    735   EFI_HANDLE                RootHandle;
    736 
    737   //
    738   // Make all the PCI_IO protocols on PCI Seg 0 show up
    739   //
    740   BdsLibConnectDevicePath (gPlatformRootBridges[0]);
    741 
    742   Status = gBS->LocateDevicePath (
    743                   &gEfiDevicePathProtocolGuid,
    744                   &gPlatformRootBridges[0],
    745                   &RootHandle
    746                   );
    747   if (EFI_ERROR (Status)) {
    748     return Status;
    749   }
    750 
    751   Status = gBS->ConnectController (RootHandle, NULL, NULL, FALSE);
    752   if (EFI_ERROR (Status)) {
    753     return Status;
    754   }
    755 
    756   return EFI_SUCCESS;
    757 }
    758 
    759 /**
    760   The function will execute with as the platform policy, current policy
    761   is driven by boot mode. IBV/OEM can customize this code for their specific
    762   policy action.
    763 
    764   @param  DriverOptionList        The header of the driver option link list
    765   @param  BootOptionList          The header of the boot option link list
    766   @param  ProcessCapsules         A pointer to ProcessCapsules()
    767   @param  BaseMemoryTest          A pointer to BaseMemoryTest()
    768 
    769 **/
    770 VOID
    771 EFIAPI
    772 PlatformBdsPolicyBehavior (
    773   IN LIST_ENTRY                      *DriverOptionList,
    774   IN LIST_ENTRY                      *BootOptionList,
    775   IN PROCESS_CAPSULES                ProcessCapsules,
    776   IN BASEM_MEMORY_TEST               BaseMemoryTest
    777   )
    778 {
    779 	  EFI_STATUS                         Status;
    780   UINT16                             Timeout;
    781   EFI_EVENT                          UserInputDurationTime;
    782   LIST_ENTRY                     *Link;
    783   BDS_COMMON_OPTION                  *BootOption;
    784   UINTN                              Index;
    785   EFI_INPUT_KEY                      Key;
    786   EFI_TPL                            OldTpl;
    787   EFI_BOOT_MODE                      BootMode;
    788 
    789   DEBUG ((EFI_D_INFO, "PlatformBdsPolicyBehavior\n"));
    790 
    791   ConnectRootBridge ();
    792 
    793   //
    794   // Init the time out value
    795   //
    796   Timeout = PcdGet16 (PcdPlatformBootTimeOut);
    797 
    798   //
    799   // Load the driver option as the driver option list
    800   //
    801   PlatformBdsGetDriverOption (DriverOptionList);
    802 
    803   //
    804   // Get current Boot Mode
    805   //
    806   Status = BdsLibGetBootMode (&BootMode);
    807   DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode));
    808 
    809   //
    810   // Go the different platform policy with different boot mode
    811   // Notes: this part code can be change with the table policy
    812   //
    813   ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);
    814   //
    815   // Connect platform console
    816   //
    817   Status = PlatformBdsConnectConsole (gPlatformConsole);
    818   if (EFI_ERROR (Status)) {
    819     //
    820     // Here OEM/IBV can customize with defined action
    821     //
    822     PlatformBdsNoConsoleAction ();
    823   }
    824   //
    825   // Create a 300ms duration event to ensure user has enough input time to enter Setup
    826   //
    827   Status = gBS->CreateEvent (
    828                   EVT_TIMER,
    829                   0,
    830                   NULL,
    831                   NULL,
    832                   &UserInputDurationTime
    833                   );
    834   ASSERT (Status == EFI_SUCCESS);
    835   Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 3000000);
    836   ASSERT (Status == EFI_SUCCESS);
    837   //
    838   // Memory test and Logo show
    839   //
    840   PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest);
    841 
    842   //
    843   // Perform some platform specific connect sequence
    844   //
    845   PlatformBdsConnectSequence ();
    846 
    847   //
    848   // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device
    849   // and do enumerate all the default boot options. But in development system board, the boot mode
    850   // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box
    851   // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot.
    852   //
    853   Status = BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");
    854   if (EFI_ERROR(Status)) {
    855     //
    856     // If cannot find "BootOrder" variable,  it may be first boot.
    857     // Try to connect all devices and enumerate all boot options here.
    858     //
    859     BdsLibConnectAll ();
    860     BdsLibEnumerateAllBootOption (BootOptionList);
    861   }
    862 
    863   //
    864   // To give the User a chance to enter Setup here, if user set TimeOut is 0.
    865   // BDS should still give user a chance to enter Setup
    866   //
    867   // Connect first boot option, and then check user input before exit
    868   //
    869   for (Link = BootOptionList->ForwardLink; Link != BootOptionList;Link = Link->ForwardLink) {
    870     BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE);
    871     if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) {
    872       //
    873       // skip the header of the link list, becuase it has no boot option
    874       //
    875       continue;
    876     } else {
    877       //
    878       // Make sure the boot option device path connected, but ignore the BBS device path
    879       //
    880       if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) {
    881         BdsLibConnectDevicePath (BootOption->DevicePath);
    882       }
    883       break;
    884     }
    885   }
    886 
    887   //
    888   // Check whether the user input after the duration time has expired
    889   //
    890   OldTpl = EfiGetCurrentTpl();
    891   gBS->RestoreTPL (TPL_APPLICATION);
    892   gBS->WaitForEvent (1, &UserInputDurationTime, &Index);
    893   gBS->CloseEvent (UserInputDurationTime);
    894   Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
    895   gBS->RaiseTPL (OldTpl);
    896 
    897   if (!EFI_ERROR (Status)) {
    898     //
    899     // Enter Setup if user input
    900     //
    901     Timeout = 0xffff;
    902     PlatformBdsEnterFrontPage (Timeout, FALSE);
    903   }
    904 }
    905 
    906 /**
    907   Hook point after a boot attempt succeeds. We don't expect a boot option to
    908   return, so the UEFI 2.0 specification defines that you will default to an
    909   interactive mode and stop processing the BootOrder list in this case. This
    910   is also a platform implementation and can be customized by IBV/OEM.
    911 
    912   @param  Option                  Pointer to Boot Option that succeeded to boot.
    913 
    914 **/
    915 VOID
    916 EFIAPI
    917 PlatformBdsBootSuccess (
    918   IN  BDS_COMMON_OPTION *Option
    919   )
    920 {
    921 	CHAR16  *TmpStr;
    922   DEBUG ((EFI_D_INFO, "PlatformBdsBootSuccess\n"));
    923 
    924   //
    925   // If Boot returned with EFI_SUCCESS and there is not in the boot device
    926   // select loop then we need to pop up a UI and wait for user input.
    927   //
    928   TmpStr = Option->StatusString;
    929   if (TmpStr != NULL) {
    930     BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
    931     FreePool (TmpStr);
    932   }
    933 }
    934 
    935 /**
    936   Hook point after a boot attempt fails.
    937 
    938   @param  Option                  Pointer to Boot Option that failed to boot.
    939   @param  Status                  Status returned from failed boot.
    940   @param  ExitData                Exit data returned from failed boot.
    941   @param  ExitDataSize            Exit data size returned from failed boot.
    942 
    943 **/
    944 VOID
    945 EFIAPI
    946 PlatformBdsBootFail (
    947   IN  BDS_COMMON_OPTION  *Option,
    948   IN  EFI_STATUS         Status,
    949   IN  CHAR16             *ExitData,
    950   IN  UINTN              ExitDataSize
    951   )
    952 {
    953 	CHAR16  *TmpStr;
    954   DEBUG ((EFI_D_INFO, "PlatformBdsBootFail\n"));
    955 
    956   //
    957   // If Boot returned with failed status then we need to pop up a UI and wait
    958   // for user input.
    959   //
    960   TmpStr = Option->StatusString;
    961   if (TmpStr != NULL) {
    962     BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
    963     FreePool (TmpStr);
    964   }
    965 }
    966 
    967 /**
    968   This function is remained for IBV/OEM to do some platform action,
    969   if there no console device can be connected.
    970 
    971   @return EFI_SUCCESS      Direct return success now.
    972 
    973 **/
    974 EFI_STATUS
    975 PlatformBdsNoConsoleAction (
    976   VOID
    977   )
    978 {
    979   DEBUG ((EFI_D_INFO, "PlatformBdsNoConsoleAction\n"));
    980   return EFI_SUCCESS;
    981 }
    982 
    983 /**
    984   This function locks platform flash that is not allowed to be updated during normal boot path.
    985   The flash layout is platform specific.
    986 **/
    987 VOID
    988 EFIAPI
    989 PlatformBdsLockNonUpdatableFlash (
    990   VOID
    991   )
    992 {
    993   DEBUG ((EFI_D_INFO, "PlatformBdsLockNonUpdatableFlash\n"));
    994   return ;
    995 }
    996 
    997 
    998 /**
    999   Lock the ConsoleIn device in system table. All key
   1000   presses will be ignored until the Password is typed in. The only way to
   1001   disable the password is to type it in to a ConIn device.
   1002 
   1003   @param  Password        Password used to lock ConIn device.
   1004 
   1005   @retval EFI_SUCCESS     lock the Console In Spliter virtual handle successfully.
   1006   @retval EFI_UNSUPPORTED Password not found
   1007 
   1008 **/
   1009 EFI_STATUS
   1010 EFIAPI
   1011 LockKeyboards (
   1012   IN  CHAR16    *Password
   1013   )
   1014 {
   1015     return EFI_UNSUPPORTED;
   1016 }
   1017