Home | History | Annotate | Download | only in DuetBdsLib
      1 /*++
      2 
      3 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
      4 This program and the accompanying materials
      5 are licensed and made available under the terms and conditions of the BSD License
      6 which accompanies this distribution.  The full text of the license may be found at
      7 http://opensource.org/licenses/bsd-license.php
      8 
      9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 
     12 Module Name:
     13 
     14   BdsPlatform.c
     15 
     16 Abstract:
     17 
     18   This file include all platform action which can be customized
     19   by IBV/OEM.
     20 
     21 --*/
     22 
     23 #include "BdsPlatform.h"
     24 
     25 #define IS_PCI_ISA_PDECODE(_p)        IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA_PDECODE, 0)
     26 
     27 extern BOOLEAN  gConnectAllHappened;
     28 extern USB_CLASS_FORMAT_DEVICE_PATH gUsbClassKeyboardDevicePath;
     29 
     30 EFI_GUID                    *gTableGuidArray[] = {
     31     &gEfiAcpi20TableGuid, &gEfiAcpiTableGuid, &gEfiSmbiosTableGuid, &gEfiMpsTableGuid
     32   };
     33 
     34 //
     35 // BDS Platform Functions
     36 //
     37 
     38 VOID
     39 GetSystemTablesFromHob (
     40   VOID
     41   )
     42 /*++
     43 
     44 Routine Description:
     45   Find GUID'ed HOBs that contain EFI_PHYSICAL_ADDRESS of ACPI, SMBIOS, MPs tables
     46 
     47 Arguments:
     48   None
     49 
     50 Returns:
     51   None.
     52 
     53 --*/
     54 {
     55   EFI_PEI_HOB_POINTERS        GuidHob;
     56   EFI_PEI_HOB_POINTERS        HobStart;
     57   EFI_PHYSICAL_ADDRESS        *Table;
     58   UINTN                       Index;
     59 
     60   //
     61   // Get Hob List
     62   //
     63   HobStart.Raw = GetHobList ();
     64   //
     65   // Iteratively add ACPI Table, SMBIOS Table, MPS Table to EFI System Table
     66   //
     67   for (Index = 0; Index < ARRAY_SIZE (gTableGuidArray); ++Index) {
     68     GuidHob.Raw = GetNextGuidHob (gTableGuidArray[Index], HobStart.Raw);
     69     if (GuidHob.Raw != NULL) {
     70       Table = GET_GUID_HOB_DATA (GuidHob.Guid);
     71       if (Table != NULL) {
     72         //
     73         // Check if Mps Table/Smbios Table/Acpi Table exists in E/F seg,
     74         // According to UEFI Spec, we should make sure Smbios table,
     75         // ACPI table and Mps tables kept in memory of specified type
     76         //
     77         ConvertSystemTable(gTableGuidArray[Index], (VOID**)&Table);
     78         gBS->InstallConfigurationTable (gTableGuidArray[Index], (VOID *)Table);
     79       }
     80     }
     81   }
     82 
     83   return ;
     84 }
     85 
     86 #if 0
     87 VOID
     88 PrintMemoryMap (
     89   VOID
     90   )
     91 {
     92   EFI_MEMORY_DESCRIPTOR       *MemMap;
     93   EFI_MEMORY_DESCRIPTOR       *MemMapPtr;
     94   UINTN                       MemMapSize;
     95   UINTN                       MapKey, DescriptorSize;
     96   UINTN                       Index;
     97   UINT32                      DescriptorVersion;
     98   UINT64                      Bytes;
     99   EFI_STATUS                  Status;
    100 
    101   MemMapSize = 0;
    102   MemMap     = NULL;
    103   Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize, &DescriptorVersion);
    104   ASSERT (Status == EFI_BUFFER_TOO_SMALL);
    105   MemMapSize += EFI_PAGE_SIZE;
    106   Status = gBS->AllocatePool (EfiBootServicesData, MemMapSize, &MemMap);
    107   ASSERT (Status == EFI_SUCCESS);
    108   Status = gBS->GetMemoryMap (&MemMapSize, MemMap, &MapKey, &DescriptorSize, &DescriptorVersion);
    109   ASSERT (Status == EFI_SUCCESS);
    110   MemMapPtr = MemMap;
    111 
    112   ASSERT (DescriptorVersion == EFI_MEMORY_DESCRIPTOR_VERSION);
    113 
    114   for (Index = 0; Index < MemMapSize / DescriptorSize; Index ++) {
    115     Bytes = LShiftU64 (MemMap->NumberOfPages, 12);
    116     DEBUG ((EFI_D_ERROR, "%lX-%lX  %lX %lX %X\n",
    117           MemMap->PhysicalStart,
    118           MemMap->PhysicalStart + Bytes - 1,
    119           MemMap->NumberOfPages,
    120           MemMap->Attribute,
    121           (UINTN)MemMap->Type));
    122     MemMap = (EFI_MEMORY_DESCRIPTOR *)((UINTN)MemMap + DescriptorSize);
    123   }
    124 
    125   gBS->FreePool (MemMapPtr);
    126 }
    127 #endif
    128 
    129 VOID
    130 UpdateMemoryMap (
    131   VOID
    132   )
    133 {
    134   EFI_STATUS                      Status;
    135   EFI_PEI_HOB_POINTERS            GuidHob;
    136   VOID                            *Table;
    137   MEMORY_DESC_HOB                 MemoryDescHob;
    138   UINTN                           Index;
    139   EFI_PHYSICAL_ADDRESS            Memory;
    140   EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;
    141 
    142   GuidHob.Raw = GetFirstGuidHob (&gLdrMemoryDescriptorGuid);
    143   if (GuidHob.Raw == NULL) {
    144     DEBUG ((EFI_D_ERROR, "Fail to get gEfiLdrMemoryDescriptorGuid from GUID HOB LIST!\n"));
    145     return;
    146   }
    147   Table = GET_GUID_HOB_DATA (GuidHob.Guid);
    148   if (Table == NULL) {
    149     DEBUG ((EFI_D_ERROR, "Fail to get gEfiLdrMemoryDescriptorGuid from GUID HOB LIST!\n"));
    150     return;
    151   }
    152   MemoryDescHob.MemDescCount = *(UINTN *)Table;
    153   MemoryDescHob.MemDesc      = *(EFI_MEMORY_DESCRIPTOR **)((UINTN)Table + sizeof(UINTN));
    154 
    155   //
    156   // Add ACPINVS, ACPIReclaim, and Reserved memory to MemoryMap
    157   //
    158   for (Index = 0; Index < MemoryDescHob.MemDescCount; Index++) {
    159     if (MemoryDescHob.MemDesc[Index].PhysicalStart < 0x100000) {
    160       continue;
    161     }
    162     if (MemoryDescHob.MemDesc[Index].PhysicalStart >= 0x100000000ULL) {
    163       continue;
    164     }
    165     if ((MemoryDescHob.MemDesc[Index].Type == EfiReservedMemoryType) ||
    166         (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesData) ||
    167         (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesCode) ||
    168         (MemoryDescHob.MemDesc[Index].Type == EfiACPIReclaimMemory) ||
    169         (MemoryDescHob.MemDesc[Index].Type == EfiACPIMemoryNVS)) {
    170       DEBUG ((EFI_D_ERROR, "PhysicalStart - 0x%016lx, ", MemoryDescHob.MemDesc[Index].PhysicalStart));
    171       DEBUG ((EFI_D_ERROR, "PageNumber    - 0x%016lx, ", MemoryDescHob.MemDesc[Index].NumberOfPages));
    172       DEBUG ((EFI_D_ERROR, "Attribute     - 0x%016lx, ", MemoryDescHob.MemDesc[Index].Attribute));
    173       DEBUG ((EFI_D_ERROR, "Type          - 0x%08x\n", MemoryDescHob.MemDesc[Index].Type));
    174       if ((MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesData) ||
    175           (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesCode)) {
    176         //
    177         // For RuntimeSevicesData and RuntimeServicesCode, they are BFV or DxeCore.
    178         // The memory type is assigned in EfiLdr
    179         //
    180         Status = gDS->GetMemorySpaceDescriptor (MemoryDescHob.MemDesc[Index].PhysicalStart, &Descriptor);
    181         if (EFI_ERROR (Status)) {
    182           continue;
    183         }
    184         if (Descriptor.GcdMemoryType != EfiGcdMemoryTypeReserved) {
    185           //
    186           // BFV or tested DXE core
    187           //
    188           continue;
    189         }
    190         //
    191         // Untested DXE Core region, free and remove
    192         //
    193         Status = gDS->FreeMemorySpace (
    194                         MemoryDescHob.MemDesc[Index].PhysicalStart,
    195                         LShiftU64 (MemoryDescHob.MemDesc[Index].NumberOfPages, EFI_PAGE_SHIFT)
    196                         );
    197         if (EFI_ERROR (Status)) {
    198           DEBUG ((EFI_D_ERROR, "FreeMemorySpace fail - %r!\n", Status));
    199           continue;
    200         }
    201         Status = gDS->RemoveMemorySpace (
    202                         MemoryDescHob.MemDesc[Index].PhysicalStart,
    203                         LShiftU64 (MemoryDescHob.MemDesc[Index].NumberOfPages, EFI_PAGE_SHIFT)
    204                         );
    205         if (EFI_ERROR (Status)) {
    206           DEBUG ((EFI_D_ERROR, "RemoveMemorySpace fail - %r!\n", Status));
    207           continue;
    208         }
    209 
    210         //
    211         // Convert Runtime type to BootTime type
    212         //
    213         if (MemoryDescHob.MemDesc[Index].Type == EfiRuntimeServicesData) {
    214           MemoryDescHob.MemDesc[Index].Type = EfiBootServicesData;
    215         } else {
    216           MemoryDescHob.MemDesc[Index].Type = EfiBootServicesCode;
    217         }
    218 
    219         //
    220         // PassThrough, let below code add and alloate.
    221         //
    222       }
    223       //
    224       // ACPI or reserved memory
    225       //
    226       Status = gDS->AddMemorySpace (
    227                       EfiGcdMemoryTypeSystemMemory,
    228                       MemoryDescHob.MemDesc[Index].PhysicalStart,
    229                       LShiftU64 (MemoryDescHob.MemDesc[Index].NumberOfPages, EFI_PAGE_SHIFT),
    230                       MemoryDescHob.MemDesc[Index].Attribute
    231                       );
    232       if (EFI_ERROR (Status)) {
    233         DEBUG ((EFI_D_ERROR, "AddMemorySpace fail - %r!\n", Status));
    234         if ((MemoryDescHob.MemDesc[Index].Type == EfiACPIReclaimMemory) ||
    235             (MemoryDescHob.MemDesc[Index].Type == EfiACPIMemoryNVS)) {
    236           //
    237           // For EfiACPIReclaimMemory and EfiACPIMemoryNVS, it must success.
    238           // For EfiReservedMemoryType, there maybe overlap. So skip check here.
    239           //
    240 //          ASSERT_EFI_ERROR (Status);
    241         }
    242         continue;
    243       }
    244 
    245       Memory = MemoryDescHob.MemDesc[Index].PhysicalStart;
    246       Status = gBS->AllocatePages (
    247                       AllocateAddress,
    248                       (EFI_MEMORY_TYPE)MemoryDescHob.MemDesc[Index].Type,
    249                       (UINTN)MemoryDescHob.MemDesc[Index].NumberOfPages,
    250                       &Memory
    251                       );
    252       if (EFI_ERROR (Status)) {
    253         DEBUG ((EFI_D_ERROR, "AllocatePages fail - %r!\n", Status));
    254         //
    255         // For the page added, it must be allocated.
    256         //
    257 //        ASSERT_EFI_ERROR (Status);
    258         continue;
    259       }
    260     }
    261   }
    262 
    263 }
    264 
    265 EFI_STATUS
    266 DisableUsbLegacySupport(
    267   void
    268   )
    269 /*++
    270 
    271 Routine Description:
    272   Disabble the USB legacy Support in all Ehci and Uhci.
    273   This function assume all PciIo handles have been created in system.
    274 
    275 Arguments:
    276   None
    277 
    278 Returns:
    279   EFI_SUCCESS
    280   EFI_NOT_FOUND
    281 --*/
    282 {
    283   EFI_STATUS                            Status;
    284   EFI_HANDLE                            *HandleArray;
    285   UINTN                                 HandleArrayCount;
    286   UINTN                                 Index;
    287   EFI_PCI_IO_PROTOCOL                   *PciIo;
    288   UINT8                                 Class[3];
    289   UINT16                                Command;
    290   UINT32                                HcCapParams;
    291   UINT32                                ExtendCap;
    292   UINT32                                Value;
    293   UINT32                                TimeOut;
    294 
    295   //
    296   // Find the usb host controller
    297   //
    298   Status = gBS->LocateHandleBuffer (
    299                   ByProtocol,
    300                   &gEfiPciIoProtocolGuid,
    301                   NULL,
    302                   &HandleArrayCount,
    303                   &HandleArray
    304                   );
    305   if (!EFI_ERROR (Status)) {
    306     for (Index = 0; Index < HandleArrayCount; Index++) {
    307       Status = gBS->HandleProtocol (
    308                       HandleArray[Index],
    309                       &gEfiPciIoProtocolGuid,
    310                       (VOID **)&PciIo
    311                       );
    312       if (!EFI_ERROR (Status)) {
    313         //
    314         // Find the USB host controller controller
    315         //
    316         Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);
    317         if (!EFI_ERROR (Status)) {
    318           if ((PCI_CLASS_SERIAL == Class[2]) &&
    319               (PCI_CLASS_SERIAL_USB == Class[1])) {
    320             if (PCI_IF_UHCI == Class[0]) {
    321               //
    322               // Found the UHCI, then disable the legacy support
    323               //
    324               Command = 0;
    325               Status = PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0xC0, 1, &Command);
    326             } else if (PCI_IF_EHCI == Class[0]) {
    327               //
    328               // Found the EHCI, then disable the legacy support
    329               //
    330               Status = PciIo->Mem.Read (
    331                                    PciIo,
    332                                    EfiPciIoWidthUint32,
    333                                    0,                   //EHC_BAR_INDEX
    334                                    (UINT64) 0x08,       //EHC_HCCPARAMS_OFFSET
    335                                    1,
    336                                    &HcCapParams
    337                                    );
    338 
    339               ExtendCap = (HcCapParams >> 8) & 0xFF;
    340               //
    341               // Disable the SMI in USBLEGCTLSTS firstly
    342               //
    343               PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap + 0x4, 1, &Value);
    344               Value &= 0xFFFF0000;
    345               PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, ExtendCap + 0x4, 1, &Value);
    346 
    347               //
    348               // Get EHCI Ownership from legacy bios
    349               //
    350               PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);
    351               Value |= (0x1 << 24);
    352               PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);
    353 
    354               TimeOut = 40;
    355               while (TimeOut--) {
    356                 gBS->Stall (500);
    357 
    358                 PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ExtendCap, 1, &Value);
    359 
    360                 if ((Value & 0x01010000) == 0x01000000) {
    361                   break;
    362                 }
    363               }
    364             }
    365           }
    366         }
    367       }
    368     }
    369   } else {
    370     return Status;
    371   }
    372   gBS->FreePool (HandleArray);
    373   return EFI_SUCCESS;
    374 }
    375 
    376 
    377 VOID
    378 EFIAPI
    379 PlatformBdsInit (
    380   VOID
    381   )
    382 /*++
    383 
    384 Routine Description:
    385 
    386   Platform Bds init. Include the platform firmware vendor, revision
    387   and so crc check.
    388 
    389 Arguments:
    390 
    391 Returns:
    392 
    393   None.
    394 
    395 --*/
    396 {
    397   GetSystemTablesFromHob ();
    398 
    399   UpdateMemoryMap ();
    400 
    401   //
    402   // Append Usb Keyboard short form DevicePath into "ConInDev"
    403   //
    404   BdsLibUpdateConsoleVariable (
    405     VarConsoleInpDev,
    406     (EFI_DEVICE_PATH_PROTOCOL *) &gUsbClassKeyboardDevicePath,
    407     NULL
    408     );
    409 }
    410 
    411 UINT64
    412 GetPciExpressBaseAddressForRootBridge (
    413   IN UINTN    HostBridgeNumber,
    414   IN UINTN    RootBridgeNumber
    415   )
    416 /*++
    417 
    418 Routine Description:
    419   This routine is to get PciExpress Base Address for this RootBridge
    420 
    421 Arguments:
    422   HostBridgeNumber - The number of HostBridge
    423   RootBridgeNumber - The number of RootBridge
    424 
    425 Returns:
    426   UINT64 - PciExpressBaseAddress for this HostBridge and RootBridge
    427 
    428 --*/
    429 {
    430   EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION *PciExpressBaseAddressInfo;
    431   UINTN                                    BufferSize;
    432   UINT32                                   Index;
    433   UINT32                                   Number;
    434   EFI_PEI_HOB_POINTERS                     GuidHob;
    435 
    436   //
    437   // Get PciExpressAddressInfo Hob
    438   //
    439   PciExpressBaseAddressInfo = NULL;
    440   BufferSize                = 0;
    441   GuidHob.Raw = GetFirstGuidHob (&gEfiPciExpressBaseAddressGuid);
    442   if (GuidHob.Raw != NULL) {
    443     PciExpressBaseAddressInfo = GET_GUID_HOB_DATA (GuidHob.Guid);
    444     BufferSize                = GET_GUID_HOB_DATA_SIZE (GuidHob.Guid);
    445   } else {
    446     return 0;
    447   }
    448 
    449   //
    450   // Search the PciExpress Base Address in the Hob for current RootBridge
    451   //
    452   Number = (UINT32)(BufferSize / sizeof(EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION));
    453   for (Index = 0; Index < Number; Index++) {
    454     if ((PciExpressBaseAddressInfo[Index].HostBridgeNumber == HostBridgeNumber) &&
    455         (PciExpressBaseAddressInfo[Index].RootBridgeNumber == RootBridgeNumber)) {
    456       return PciExpressBaseAddressInfo[Index].PciExpressBaseAddress;
    457     }
    458   }
    459 
    460   //
    461   // Do not find the PciExpress Base Address in the Hob
    462   //
    463   return 0;
    464 }
    465 
    466 VOID
    467 PatchPciRootBridgeDevicePath (
    468   IN UINTN    HostBridgeNumber,
    469   IN UINTN    RootBridgeNumber,
    470   IN PLATFORM_ROOT_BRIDGE_DEVICE_PATH  *RootBridge
    471   )
    472 {
    473   UINT64  PciExpressBase;
    474 
    475   PciExpressBase = GetPciExpressBaseAddressForRootBridge (HostBridgeNumber, RootBridgeNumber);
    476 
    477   DEBUG ((EFI_D_INFO, "Get PciExpress Address from Hob: 0x%X\n", PciExpressBase));
    478 
    479   if (PciExpressBase != 0) {
    480     RootBridge->PciRootBridge.HID = EISA_PNP_ID(0x0A08);
    481   }
    482 }
    483 
    484 EFI_STATUS
    485 ConnectRootBridge (
    486   VOID
    487   )
    488 /*++
    489 
    490 Routine Description:
    491 
    492   Connect RootBridge
    493 
    494 Arguments:
    495 
    496   None.
    497 
    498 Returns:
    499 
    500   EFI_SUCCESS             - Connect RootBridge successfully.
    501   EFI_STATUS              - Connect RootBridge fail.
    502 
    503 --*/
    504 {
    505   EFI_STATUS                Status;
    506   EFI_HANDLE                RootHandle;
    507 
    508   //
    509   // Patch Pci Root Bridge Device Path
    510   //
    511   PatchPciRootBridgeDevicePath (0, 0, &gPlatformRootBridge0);
    512 
    513   //
    514   // Make all the PCI_IO protocols on PCI Seg 0 show up
    515   //
    516   BdsLibConnectDevicePath (gPlatformRootBridges[0]);
    517 
    518   Status = gBS->LocateDevicePath (
    519                   &gEfiDevicePathProtocolGuid,
    520                   &gPlatformRootBridges[0],
    521                   &RootHandle
    522                   );
    523   DEBUG ((EFI_D_INFO, "Pci Root bridge handle is 0x%X\n", RootHandle));
    524 
    525   if (EFI_ERROR (Status)) {
    526     return Status;
    527   }
    528 
    529   Status = gBS->ConnectController (RootHandle, NULL, NULL, FALSE);
    530   if (EFI_ERROR (Status)) {
    531     return Status;
    532   }
    533 
    534   return EFI_SUCCESS;
    535 }
    536 
    537 EFI_STATUS
    538 PrepareLpcBridgeDevicePath (
    539   IN EFI_HANDLE                DeviceHandle
    540   )
    541 /*++
    542 
    543 Routine Description:
    544 
    545   Add IsaKeyboard to ConIn,
    546   add IsaSerial to ConOut, ConIn, ErrOut.
    547   LPC Bridge: 06 01 00
    548 
    549 Arguments:
    550 
    551   DeviceHandle            - Handle of PCIIO protocol.
    552 
    553 Returns:
    554 
    555   EFI_SUCCESS             - LPC bridge is added to ConOut, ConIn, and ErrOut.
    556   EFI_STATUS              - No LPC bridge is added.
    557 
    558 --*/
    559 {
    560   EFI_STATUS                Status;
    561   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
    562   EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
    563 
    564   DevicePath = NULL;
    565   Status = gBS->HandleProtocol (
    566                   DeviceHandle,
    567                   &gEfiDevicePathProtocolGuid,
    568                   (VOID*)&DevicePath
    569                   );
    570   if (EFI_ERROR (Status)) {
    571     return Status;
    572   }
    573   TempDevicePath = DevicePath;
    574 
    575   //
    576   // Register Keyboard
    577   //
    578   DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnpPs2KeyboardDeviceNode);
    579 
    580   BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
    581 
    582   //
    583   // Register COM1
    584   //
    585   DevicePath = TempDevicePath;
    586   gPnp16550ComPortDeviceNode.UID = 0;
    587 
    588   DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
    589   DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
    590   DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
    591 
    592   BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
    593   BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
    594   BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);
    595 
    596   //
    597   // Register COM2
    598   //
    599   DevicePath = TempDevicePath;
    600   gPnp16550ComPortDeviceNode.UID = 1;
    601 
    602   DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gPnp16550ComPortDeviceNode);
    603   DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
    604   DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
    605 
    606   BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
    607   BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
    608   BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);
    609 
    610   return EFI_SUCCESS;
    611 }
    612 
    613 EFI_STATUS
    614 GetGopDevicePath (
    615    IN  EFI_DEVICE_PATH_PROTOCOL *PciDevicePath,
    616    OUT EFI_DEVICE_PATH_PROTOCOL **GopDevicePath
    617    )
    618 {
    619   UINTN                           Index;
    620   EFI_STATUS                      Status;
    621   EFI_HANDLE                      PciDeviceHandle;
    622   EFI_DEVICE_PATH_PROTOCOL        *TempDevicePath;
    623   EFI_DEVICE_PATH_PROTOCOL        *TempPciDevicePath;
    624   UINTN                           GopHandleCount;
    625   EFI_HANDLE                      *GopHandleBuffer;
    626 
    627   if (PciDevicePath == NULL || GopDevicePath == NULL) {
    628     return EFI_INVALID_PARAMETER;
    629   }
    630 
    631   //
    632   // Initialize the GopDevicePath to be PciDevicePath
    633   //
    634   *GopDevicePath    = PciDevicePath;
    635   TempPciDevicePath = PciDevicePath;
    636 
    637   Status = gBS->LocateDevicePath (
    638                   &gEfiDevicePathProtocolGuid,
    639                   &TempPciDevicePath,
    640                   &PciDeviceHandle
    641                   );
    642   if (EFI_ERROR (Status)) {
    643     return Status;
    644   }
    645 
    646   //
    647   // Try to connect this handle, so that GOP driver could start on this
    648   // device and create child handles with GraphicsOutput Protocol installed
    649   // on them, then we get device paths of these child handles and select
    650   // them as possible console device.
    651   //
    652   gBS->ConnectController (PciDeviceHandle, NULL, NULL, FALSE);
    653 
    654   Status = gBS->LocateHandleBuffer (
    655                   ByProtocol,
    656                   &gEfiGraphicsOutputProtocolGuid,
    657                   NULL,
    658                   &GopHandleCount,
    659                   &GopHandleBuffer
    660                   );
    661   if (!EFI_ERROR (Status)) {
    662     //
    663     // Add all the child handles as possible Console Device
    664     //
    665     for (Index = 0; Index < GopHandleCount; Index++) {
    666       Status = gBS->HandleProtocol (GopHandleBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID*)&TempDevicePath);
    667       if (EFI_ERROR (Status)) {
    668         continue;
    669       }
    670       if (CompareMem (
    671             PciDevicePath,
    672             TempDevicePath,
    673             GetDevicePathSize (PciDevicePath) - END_DEVICE_PATH_LENGTH
    674             ) == 0) {
    675         //
    676         // In current implementation, we only enable one of the child handles
    677         // as console device, i.e. sotre one of the child handle's device
    678         // path to variable "ConOut"
    679         // In future, we could select all child handles to be console device
    680         //
    681 
    682         *GopDevicePath = TempDevicePath;
    683 
    684         //
    685         // Delete the PCI device's path that added by GetPlugInPciVgaDevicePath()
    686         // Add the integrity GOP device path.
    687         //
    688         BdsLibUpdateConsoleVariable (VarConsoleOutDev, NULL, PciDevicePath);
    689         BdsLibUpdateConsoleVariable (VarConsoleOutDev, TempDevicePath, NULL);
    690       }
    691     }
    692     gBS->FreePool (GopHandleBuffer);
    693   }
    694 
    695   return EFI_SUCCESS;
    696 }
    697 
    698 EFI_STATUS
    699 PreparePciVgaDevicePath (
    700   IN EFI_HANDLE                DeviceHandle
    701   )
    702 /*++
    703 
    704 Routine Description:
    705 
    706   Add PCI VGA to ConOut.
    707   PCI VGA: 03 00 00
    708 
    709 Arguments:
    710 
    711   DeviceHandle            - Handle of PCIIO protocol.
    712 
    713 Returns:
    714 
    715   EFI_SUCCESS             - PCI VGA is added to ConOut.
    716   EFI_STATUS              - No PCI VGA device is added.
    717 
    718 --*/
    719 {
    720   EFI_STATUS                Status;
    721   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
    722   EFI_DEVICE_PATH_PROTOCOL  *GopDevicePath;
    723 
    724   DevicePath    = NULL;
    725   GopDevicePath = NULL;
    726   Status = gBS->HandleProtocol (
    727                   DeviceHandle,
    728                   &gEfiDevicePathProtocolGuid,
    729                   (VOID*)&DevicePath
    730                   );
    731   if (EFI_ERROR (Status)) {
    732     return Status;
    733   }
    734 
    735   GetGopDevicePath (DevicePath, &GopDevicePath);
    736   DevicePath = GopDevicePath;
    737 
    738   BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
    739 
    740   return EFI_SUCCESS;
    741 }
    742 
    743 EFI_STATUS
    744 PreparePciSerialDevicePath (
    745   IN EFI_HANDLE                DeviceHandle
    746   )
    747 /*++
    748 
    749 Routine Description:
    750 
    751   Add PCI Serial to ConOut, ConIn, ErrOut.
    752   PCI Serial: 07 00 02
    753 
    754 Arguments:
    755 
    756   DeviceHandle            - Handle of PCIIO protocol.
    757 
    758 Returns:
    759 
    760   EFI_SUCCESS             - PCI Serial is added to ConOut, ConIn, and ErrOut.
    761   EFI_STATUS              - No PCI Serial device is added.
    762 
    763 --*/
    764 {
    765   EFI_STATUS                Status;
    766   EFI_DEVICE_PATH_PROTOCOL  *DevicePath;
    767 
    768   DevicePath = NULL;
    769   Status = gBS->HandleProtocol (
    770                   DeviceHandle,
    771                   &gEfiDevicePathProtocolGuid,
    772                   (VOID*)&DevicePath
    773                   );
    774   if (EFI_ERROR (Status)) {
    775     return Status;
    776   }
    777 
    778   DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode);
    779   DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode);
    780 
    781   BdsLibUpdateConsoleVariable (VarConsoleOut, DevicePath, NULL);
    782   BdsLibUpdateConsoleVariable (VarConsoleInp, DevicePath, NULL);
    783   BdsLibUpdateConsoleVariable (VarErrorOut, DevicePath, NULL);
    784 
    785   return EFI_SUCCESS;
    786 }
    787 
    788 EFI_STATUS
    789 DetectAndPreparePlatformPciDevicePath (
    790   BOOLEAN DetectVgaOnly
    791   )
    792 /*++
    793 
    794 Routine Description:
    795 
    796   Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
    797 
    798 Arguments:
    799 
    800   DetectVgaOnly           - Only detect VGA device if it's TRUE.
    801 
    802 Returns:
    803 
    804   EFI_SUCCESS             - PCI Device check and Console variable update successfully.
    805   EFI_STATUS              - PCI Device check or Console variable update fail.
    806 
    807 --*/
    808 {
    809   EFI_STATUS                Status;
    810   UINTN                     HandleCount;
    811   EFI_HANDLE                *HandleBuffer;
    812   UINTN                     Index;
    813   EFI_PCI_IO_PROTOCOL       *PciIo;
    814   PCI_TYPE00                Pci;
    815 
    816   //
    817   // Start to check all the PciIo to find all possible device
    818   //
    819   HandleCount = 0;
    820   HandleBuffer = NULL;
    821   Status = gBS->LocateHandleBuffer (
    822                   ByProtocol,
    823                   &gEfiPciIoProtocolGuid,
    824                   NULL,
    825                   &HandleCount,
    826                   &HandleBuffer
    827                   );
    828   if (EFI_ERROR (Status)) {
    829     return Status;
    830   }
    831 
    832   for (Index = 0; Index < HandleCount; Index++) {
    833     Status = gBS->HandleProtocol (HandleBuffer[Index], &gEfiPciIoProtocolGuid, (VOID*)&PciIo);
    834     if (EFI_ERROR (Status)) {
    835       continue;
    836     }
    837 
    838     //
    839     // Check for all PCI device
    840     //
    841     Status = PciIo->Pci.Read (
    842                       PciIo,
    843                       EfiPciIoWidthUint32,
    844                       0,
    845                       sizeof (Pci) / sizeof (UINT32),
    846                       &Pci
    847                       );
    848     if (EFI_ERROR (Status)) {
    849       continue;
    850     }
    851 
    852     if (!DetectVgaOnly) {
    853       //
    854       // Here we decide whether it is LPC Bridge
    855       //
    856       if ((IS_PCI_LPC (&Pci)) ||
    857           ((IS_PCI_ISA_PDECODE (&Pci)) && (Pci.Hdr.VendorId == 0x8086) && (Pci.Hdr.DeviceId == 0x7110))) {
    858         //
    859         // Add IsaKeyboard to ConIn,
    860         // add IsaSerial to ConOut, ConIn, ErrOut
    861         //
    862         DEBUG ((EFI_D_INFO, "Find the LPC Bridge device\n"));
    863         PrepareLpcBridgeDevicePath (HandleBuffer[Index]);
    864         continue;
    865       }
    866       //
    867       // Here we decide which Serial device to enable in PCI bus
    868       //
    869       if (IS_PCI_16550SERIAL (&Pci)) {
    870         //
    871         // Add them to ConOut, ConIn, ErrOut.
    872         //
    873         DEBUG ((EFI_D_INFO, "Find the 16550 SERIAL device\n"));
    874         PreparePciSerialDevicePath (HandleBuffer[Index]);
    875         continue;
    876       }
    877     }
    878 
    879     //
    880     // Here we decide which VGA device to enable in PCI bus
    881     //
    882     if (IS_PCI_VGA (&Pci)) {
    883       //
    884       // Add them to ConOut.
    885       //
    886       DEBUG ((EFI_D_INFO, "Find the VGA device\n"));
    887       PreparePciVgaDevicePath (HandleBuffer[Index]);
    888       continue;
    889     }
    890   }
    891 
    892   gBS->FreePool (HandleBuffer);
    893 
    894   return EFI_SUCCESS;
    895 }
    896 
    897 EFI_STATUS
    898 PlatformBdsConnectConsole (
    899   IN BDS_CONSOLE_CONNECT_ENTRY   *PlatformConsole
    900   )
    901 /*++
    902 
    903 Routine Description:
    904 
    905   Connect the predefined platform default console device. Always try to find
    906   and enable the vga device if have.
    907 
    908 Arguments:
    909 
    910   PlatformConsole         - Predefined platform default console device array.
    911 
    912 Returns:
    913 
    914   EFI_SUCCESS             - Success connect at least one ConIn and ConOut
    915                             device, there must have one ConOut device is
    916                             active vga device.
    917 
    918   EFI_STATUS              - Return the status of
    919                             BdsLibConnectAllDefaultConsoles ()
    920 
    921 --*/
    922 {
    923   EFI_STATUS                         Status;
    924   UINTN                              Index;
    925   EFI_DEVICE_PATH_PROTOCOL           *VarConout;
    926   EFI_DEVICE_PATH_PROTOCOL           *VarConin;
    927   UINTN                              DevicePathSize;
    928 
    929   //
    930   // Connect RootBridge
    931   //
    932   ConnectRootBridge ();
    933 
    934   VarConout = BdsLibGetVariableAndSize (
    935                 VarConsoleOut,
    936                 &gEfiGlobalVariableGuid,
    937                 &DevicePathSize
    938                 );
    939   VarConin = BdsLibGetVariableAndSize (
    940                VarConsoleInp,
    941                &gEfiGlobalVariableGuid,
    942                &DevicePathSize
    943                );
    944 
    945   if (VarConout == NULL || VarConin == NULL) {
    946     //
    947     // Do platform specific PCI Device check and add them to ConOut, ConIn, ErrOut
    948     //
    949     DetectAndPreparePlatformPciDevicePath (FALSE);
    950 
    951     //
    952     // Have chance to connect the platform default console,
    953     // the platform default console is the minimum device group
    954     // the platform should support
    955     //
    956     for (Index = 0; PlatformConsole[Index].DevicePath != NULL; ++Index) {
    957       //
    958       // Update the console variable with the connect type
    959       //
    960       if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) {
    961         BdsLibUpdateConsoleVariable (VarConsoleInp, PlatformConsole[Index].DevicePath, NULL);
    962       }
    963       if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) {
    964         BdsLibUpdateConsoleVariable (VarConsoleOut, PlatformConsole[Index].DevicePath, NULL);
    965       }
    966       if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) {
    967         BdsLibUpdateConsoleVariable (VarErrorOut, PlatformConsole[Index].DevicePath, NULL);
    968       }
    969     }
    970   } else {
    971     //
    972     // Only detect VGA device and add them to ConOut
    973     //
    974     DetectAndPreparePlatformPciDevicePath (TRUE);
    975   }
    976 
    977   //
    978   // The ConIn devices connection will start the USB bus, should disable all
    979   // Usb legacy support firstly.
    980   // Caution: Must ensure the PCI bus driver has been started. Since the
    981   // ConnectRootBridge() will create all the PciIo protocol, it's safe here now
    982   //
    983   Status = DisableUsbLegacySupport();
    984 
    985   //
    986   // Connect the all the default console with current cosole variable
    987   //
    988   Status = BdsLibConnectAllDefaultConsoles ();
    989   if (EFI_ERROR (Status)) {
    990     return Status;
    991   }
    992 
    993   return EFI_SUCCESS;
    994 }
    995 
    996 VOID
    997 PlatformBdsConnectSequence (
    998   VOID
    999   )
   1000 /*++
   1001 
   1002 Routine Description:
   1003 
   1004   Connect with predefined platform connect sequence,
   1005   the OEM/IBV can customize with their own connect sequence.
   1006 
   1007 Arguments:
   1008 
   1009   None.
   1010 
   1011 Returns:
   1012 
   1013   None.
   1014 
   1015 --*/
   1016 {
   1017   UINTN Index;
   1018 
   1019   Index = 0;
   1020 
   1021   //
   1022   // Here we can get the customized platform connect sequence
   1023   // Notes: we can connect with new variable which record the
   1024   // last time boots connect device path sequence
   1025   //
   1026   while (gPlatformConnectSequence[Index] != NULL) {
   1027     //
   1028     // Build the platform boot option
   1029     //
   1030     BdsLibConnectDevicePath (gPlatformConnectSequence[Index]);
   1031     Index++;
   1032   }
   1033 
   1034 }
   1035 
   1036 VOID
   1037 PlatformBdsGetDriverOption (
   1038   IN OUT LIST_ENTRY              *BdsDriverLists
   1039   )
   1040 /*++
   1041 
   1042 Routine Description:
   1043 
   1044   Load the predefined driver option, OEM/IBV can customize this
   1045   to load their own drivers
   1046 
   1047 Arguments:
   1048 
   1049   BdsDriverLists  - The header of the driver option link list.
   1050 
   1051 Returns:
   1052 
   1053   None.
   1054 
   1055 --*/
   1056 {
   1057   UINTN Index;
   1058 
   1059   Index = 0;
   1060 
   1061   //
   1062   // Here we can get the customized platform driver option
   1063   //
   1064   while (gPlatformDriverOption[Index] != NULL) {
   1065     //
   1066     // Build the platform boot option
   1067     //
   1068     BdsLibRegisterNewOption (BdsDriverLists, gPlatformDriverOption[Index], NULL, L"DriverOrder");
   1069     Index++;
   1070   }
   1071 
   1072 }
   1073 
   1074 VOID
   1075 PlatformBdsDiagnostics (
   1076   IN EXTENDMEM_COVERAGE_LEVEL    MemoryTestLevel,
   1077   IN BOOLEAN                     QuietBoot,
   1078   IN BASEM_MEMORY_TEST           BaseMemoryTest
   1079   )
   1080 /*++
   1081 
   1082 Routine Description:
   1083 
   1084   Perform the platform diagnostic, such like test memory. OEM/IBV also
   1085   can customize this fuction to support specific platform diagnostic.
   1086 
   1087 Arguments:
   1088 
   1089   MemoryTestLevel  - The memory test intensive level
   1090 
   1091   QuietBoot        - Indicate if need to enable the quiet boot
   1092 
   1093   BaseMemoryTest   - A pointer to BdsMemoryTest()
   1094 
   1095 Returns:
   1096 
   1097   None.
   1098 
   1099 --*/
   1100 {
   1101   EFI_STATUS  Status;
   1102 
   1103   //
   1104   // Here we can decide if we need to show
   1105   // the diagnostics screen
   1106   // Notes: this quiet boot code should be remove
   1107   // from the graphic lib
   1108   //
   1109   if (QuietBoot) {
   1110     Status = EnableQuietBoot (PcdGetPtr(PcdLogoFile));
   1111     if (EFI_ERROR (Status)) {
   1112       DisableQuietBoot ();
   1113       return;
   1114     }
   1115 
   1116     //
   1117     // Perform system diagnostic
   1118     //
   1119     Status = BaseMemoryTest (MemoryTestLevel);
   1120     if (EFI_ERROR (Status)) {
   1121       DisableQuietBoot ();
   1122     }
   1123 
   1124     return ;
   1125   }
   1126   //
   1127   // Perform system diagnostic
   1128   //
   1129   Status = BaseMemoryTest (MemoryTestLevel);
   1130 }
   1131 
   1132 VOID
   1133 EFIAPI
   1134 PlatformBdsPolicyBehavior (
   1135   IN OUT LIST_ENTRY              *DriverOptionList,
   1136   IN OUT LIST_ENTRY              *BootOptionList,
   1137   IN PROCESS_CAPSULES            ProcessCapsules,
   1138   IN BASEM_MEMORY_TEST           BaseMemoryTest
   1139   )
   1140 /*++
   1141 
   1142 Routine Description:
   1143 
   1144   The function will execute with as the platform policy, current policy
   1145   is driven by boot mode. IBV/OEM can customize this code for their specific
   1146   policy action.
   1147 
   1148 Arguments:
   1149 
   1150   DriverOptionList - The header of the driver option link list
   1151 
   1152   BootOptionList   - The header of the boot option link list
   1153 
   1154 Returns:
   1155 
   1156   None.
   1157 
   1158 --*/
   1159 {
   1160   EFI_STATUS                         Status;
   1161   UINT16                             Timeout;
   1162   EFI_EVENT                          UserInputDurationTime;
   1163   UINTN                              Index;
   1164   EFI_INPUT_KEY                      Key;
   1165   EFI_BOOT_MODE                      BootMode;
   1166 
   1167   //
   1168   // Init the time out value
   1169   //
   1170   Timeout = PcdGet16 (PcdPlatformBootTimeOut);
   1171 
   1172   //
   1173   // Load the driver option as the driver option list
   1174   //
   1175   PlatformBdsGetDriverOption (DriverOptionList);
   1176 
   1177   //
   1178   // Get current Boot Mode
   1179   //
   1180   Status = BdsLibGetBootMode (&BootMode);
   1181   DEBUG ((EFI_D_ERROR, "Boot Mode:%x\n", BootMode));
   1182 
   1183   //
   1184   // Go the different platform policy with different boot mode
   1185   // Notes: this part code can be change with the table policy
   1186   //
   1187   ASSERT (BootMode == BOOT_WITH_FULL_CONFIGURATION);
   1188   //
   1189   // Connect platform console
   1190   //
   1191   Status = PlatformBdsConnectConsole (gPlatformConsole);
   1192   if (EFI_ERROR (Status)) {
   1193     //
   1194     // Here OEM/IBV can customize with defined action
   1195     //
   1196     PlatformBdsNoConsoleAction ();
   1197   }
   1198   //
   1199   // Create a 300ms duration event to ensure user has enough input time to enter Setup
   1200   //
   1201   Status = gBS->CreateEvent (
   1202                   EVT_TIMER,
   1203                   0,
   1204                   NULL,
   1205                   NULL,
   1206                   &UserInputDurationTime
   1207                   );
   1208   ASSERT (Status == EFI_SUCCESS);
   1209   Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 3000000);
   1210   ASSERT (Status == EFI_SUCCESS);
   1211   //
   1212   // Memory test and Logo show
   1213   //
   1214   PlatformBdsDiagnostics (IGNORE, TRUE, BaseMemoryTest);
   1215 
   1216   //
   1217   // Perform some platform specific connect sequence
   1218   //
   1219   PlatformBdsConnectSequence ();
   1220 
   1221   //
   1222   // Give one chance to enter the setup if we
   1223   // have the time out
   1224   //
   1225   // BUGBUG: hard code timeout to 5 second to show logo in graphic mode.
   1226   Timeout = 5;
   1227   if (Timeout != 0) {
   1228     PlatformBdsEnterFrontPage (Timeout, FALSE);
   1229   }
   1230 
   1231   //
   1232   //BdsLibConnectAll ();
   1233   //BdsLibEnumerateAllBootOption (BootOptionList);
   1234 
   1235   //
   1236   // Please uncomment above ConnectAll and EnumerateAll code and remove following first boot
   1237   // checking code in real production tip.
   1238   //
   1239   // In BOOT_WITH_FULL_CONFIGURATION boot mode, should always connect every device
   1240   // and do enumerate all the default boot options. But in development system board, the boot mode
   1241   // cannot be BOOT_ASSUMING_NO_CONFIGURATION_CHANGES because the machine box
   1242   // is always open. So the following code only do the ConnectAll and EnumerateAll at first boot.
   1243   //
   1244   Status = BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder");
   1245   if (EFI_ERROR(Status)) {
   1246     //
   1247     // If cannot find "BootOrder" variable,  it may be first boot.
   1248     // Try to connect all devices and enumerate all boot options here.
   1249     //
   1250     BdsLibConnectAll ();
   1251     BdsLibEnumerateAllBootOption (BootOptionList);
   1252   }
   1253 
   1254   //
   1255   // To give the User a chance to enter Setup here, if user set TimeOut is 0.
   1256   // BDS should still give user a chance to enter Setup
   1257   // Check whether the user input after the duration time has expired
   1258   //
   1259   gBS->WaitForEvent (1, &UserInputDurationTime, &Index);
   1260   gBS->CloseEvent (UserInputDurationTime);
   1261   Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
   1262 
   1263   if (!EFI_ERROR (Status)) {
   1264     //
   1265     // Enter Setup if user input
   1266     //
   1267     Timeout = 0xffff;
   1268     PlatformBdsEnterFrontPage (Timeout, FALSE);
   1269   }
   1270 
   1271   return ;
   1272 
   1273 }
   1274 
   1275 VOID
   1276 EFIAPI
   1277 PlatformBdsBootSuccess (
   1278   IN  BDS_COMMON_OPTION *Option
   1279   )
   1280 /*++
   1281 
   1282 Routine Description:
   1283 
   1284   Hook point after a boot attempt succeeds. We don't expect a boot option to
   1285   return, so the EFI 1.0 specification defines that you will default to an
   1286   interactive mode and stop processing the BootOrder list in this case. This
   1287   is alos a platform implementation and can be customized by IBV/OEM.
   1288 
   1289 Arguments:
   1290 
   1291   Option - Pointer to Boot Option that succeeded to boot.
   1292 
   1293 Returns:
   1294 
   1295   None.
   1296 
   1297 --*/
   1298 {
   1299   CHAR16  *TmpStr;
   1300 
   1301   //
   1302   // If Boot returned with EFI_SUCCESS and there is not in the boot device
   1303   // select loop then we need to pop up a UI and wait for user input.
   1304   //
   1305   TmpStr = Option->StatusString;
   1306   if (TmpStr != NULL) {
   1307     BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
   1308     gBS->FreePool (TmpStr);
   1309   }
   1310 }
   1311 
   1312 VOID
   1313 EFIAPI
   1314 PlatformBdsBootFail (
   1315   IN  BDS_COMMON_OPTION  *Option,
   1316   IN  EFI_STATUS         Status,
   1317   IN  CHAR16             *ExitData,
   1318   IN  UINTN              ExitDataSize
   1319   )
   1320 /*++
   1321 
   1322 Routine Description:
   1323 
   1324   Hook point after a boot attempt fails.
   1325 
   1326 Arguments:
   1327 
   1328   Option - Pointer to Boot Option that failed to boot.
   1329 
   1330   Status - Status returned from failed boot.
   1331 
   1332   ExitData - Exit data returned from failed boot.
   1333 
   1334   ExitDataSize - Exit data size returned from failed boot.
   1335 
   1336 Returns:
   1337 
   1338   None.
   1339 
   1340 --*/
   1341 {
   1342   CHAR16  *TmpStr;
   1343 
   1344   //
   1345   // If Boot returned with failed status then we need to pop up a UI and wait
   1346   // for user input.
   1347   //
   1348   TmpStr = Option->StatusString;
   1349   if (TmpStr != NULL) {
   1350     BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL);
   1351     gBS->FreePool (TmpStr);
   1352   }
   1353 
   1354 }
   1355 
   1356 EFI_STATUS
   1357 PlatformBdsNoConsoleAction (
   1358   VOID
   1359   )
   1360 /*++
   1361 
   1362 Routine Description:
   1363 
   1364   This function is remained for IBV/OEM to do some platform action,
   1365   if there no console device can be connected.
   1366 
   1367 Arguments:
   1368 
   1369   None.
   1370 
   1371 Returns:
   1372 
   1373   EFI_SUCCESS      - Direct return success now.
   1374 
   1375 --*/
   1376 {
   1377   return EFI_SUCCESS;
   1378 }
   1379 
   1380 EFI_STATUS
   1381 ConvertSystemTable (
   1382   IN     EFI_GUID        *TableGuid,
   1383   IN OUT VOID            **Table
   1384   )
   1385 /*++
   1386 
   1387 Routine Description:
   1388   Convert ACPI Table /Smbios Table /MP Table if its location is lower than Address:0x100000
   1389   Assumption here:
   1390    As in legacy Bios, ACPI/Smbios/MP table is required to place in E/F Seg,
   1391    So here we just check if the range is E/F seg,
   1392    and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS
   1393 
   1394 Arguments:
   1395   TableGuid - Guid of the table
   1396   Table     - pointer to the table
   1397 
   1398 Returns:
   1399   EFI_SUCEESS - Convert Table successfully
   1400   Other       - Failed
   1401 
   1402 --*/
   1403 {
   1404   EFI_STATUS      Status;
   1405   VOID            *AcpiHeader;
   1406   UINTN           AcpiTableLen;
   1407 
   1408   //
   1409   // If match acpi guid (1.0, 2.0, or later), Convert ACPI table according to version.
   1410   //
   1411   AcpiHeader = (VOID*)(UINTN)(*(UINT64 *)(*Table));
   1412 
   1413   if (CompareGuid(TableGuid, &gEfiAcpiTableGuid) || CompareGuid(TableGuid, &gEfiAcpi20TableGuid)){
   1414     if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Reserved == 0x00){
   1415       //
   1416       // If Acpi 1.0 Table, then RSDP structure doesn't contain Length field, use structure size
   1417       //
   1418       AcpiTableLen = sizeof (EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER);
   1419     } else if (((EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Reserved >= 0x02){
   1420       //
   1421       // If Acpi 2.0 or later, use RSDP Length fied.
   1422       //
   1423       AcpiTableLen = ((EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)AcpiHeader)->Length;
   1424     } else {
   1425       //
   1426       // Invalid Acpi Version, return
   1427       //
   1428       return EFI_UNSUPPORTED;
   1429     }
   1430     Status = ConvertAcpiTable (AcpiTableLen, Table);
   1431     return Status;
   1432   }
   1433 
   1434   //
   1435   // If matches smbios guid, convert Smbios table.
   1436   //
   1437   if (CompareGuid(TableGuid, &gEfiSmbiosTableGuid)){
   1438     Status = ConvertSmbiosTable (Table);
   1439     return Status;
   1440   }
   1441 
   1442   //
   1443   // If the table is MP table?
   1444   //
   1445   if (CompareGuid(TableGuid, &gEfiMpsTableGuid)){
   1446     Status = ConvertMpsTable (Table);
   1447     return Status;
   1448   }
   1449 
   1450   return EFI_UNSUPPORTED;
   1451 }
   1452 
   1453 
   1454 EFI_STATUS
   1455 ConvertAcpiTable (
   1456   IN     UINTN                       TableLen,
   1457   IN OUT VOID                        **Table
   1458   )
   1459 /*++
   1460 
   1461 Routine Description:
   1462   Convert RSDP of ACPI Table if its location is lower than Address:0x100000
   1463   Assumption here:
   1464    As in legacy Bios, ACPI table is required to place in E/F Seg,
   1465    So here we just check if the range is E/F seg,
   1466    and if Not, assume the Memory type is EfiACPIReclaimMemory/EfiACPIMemoryNVS
   1467 
   1468 Arguments:
   1469   TableLen  - Acpi RSDP length
   1470   Table     - pointer to the table
   1471 
   1472 Returns:
   1473   EFI_SUCEESS - Convert Table successfully
   1474   Other       - Failed
   1475 
   1476 --*/
   1477 {
   1478   VOID                  *AcpiTableOri;
   1479   VOID                  *AcpiTableNew;
   1480   EFI_STATUS            Status;
   1481   EFI_PHYSICAL_ADDRESS  BufferPtr;
   1482 
   1483 
   1484   AcpiTableOri    =  (VOID *)(UINTN)(*(UINT64*)(*Table));
   1485   if (((UINTN)AcpiTableOri < 0x100000) && ((UINTN)AcpiTableOri > 0xE0000)) {
   1486     BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;
   1487     Status = gBS->AllocatePages (
   1488                     AllocateMaxAddress,
   1489                     EfiACPIMemoryNVS,
   1490                     EFI_SIZE_TO_PAGES(TableLen),
   1491                     &BufferPtr
   1492                     );
   1493     ASSERT_EFI_ERROR (Status);
   1494     AcpiTableNew = (VOID *)(UINTN)BufferPtr;
   1495     CopyMem (AcpiTableNew, AcpiTableOri, TableLen);
   1496   } else {
   1497     AcpiTableNew = AcpiTableOri;
   1498   }
   1499   //
   1500   // Change configuration table Pointer
   1501   //
   1502   *Table = AcpiTableNew;
   1503 
   1504   return EFI_SUCCESS;
   1505 }
   1506 
   1507 EFI_STATUS
   1508 ConvertSmbiosTable (
   1509   IN OUT VOID        **Table
   1510   )
   1511 /*++
   1512 
   1513 Routine Description:
   1514 
   1515   Convert Smbios Table if the Location of the SMBios Table is lower than Addres 0x100000
   1516   Assumption here:
   1517    As in legacy Bios, Smbios table is required to place in E/F Seg,
   1518    So here we just check if the range is F seg,
   1519    and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData
   1520 Arguments:
   1521   Table     - pointer to the table
   1522 
   1523 Returns:
   1524   EFI_SUCEESS - Convert Table successfully
   1525   Other       - Failed
   1526 
   1527 --*/
   1528 {
   1529   SMBIOS_TABLE_ENTRY_POINT *SmbiosTableNew;
   1530   SMBIOS_TABLE_ENTRY_POINT *SmbiosTableOri;
   1531   EFI_STATUS               Status;
   1532   UINT32                   SmbiosEntryLen;
   1533   UINT32                   BufferLen;
   1534   EFI_PHYSICAL_ADDRESS     BufferPtr;
   1535 
   1536   SmbiosTableNew  = NULL;
   1537   SmbiosTableOri  = NULL;
   1538 
   1539   //
   1540   // Get Smibos configuration Table
   1541   //
   1542   SmbiosTableOri =  (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)(*(UINT64*)(*Table));
   1543 
   1544   if ((SmbiosTableOri == NULL) ||
   1545       ((UINTN)SmbiosTableOri > 0x100000) ||
   1546       ((UINTN)SmbiosTableOri < 0xF0000)){
   1547     return EFI_SUCCESS;
   1548   }
   1549   //
   1550   // Relocate the Smibos memory
   1551   //
   1552   BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;
   1553   if (SmbiosTableOri->SmbiosBcdRevision != 0x21) {
   1554     SmbiosEntryLen  = SmbiosTableOri->EntryPointLength;
   1555   } else {
   1556     //
   1557     // According to Smbios Spec 2.4, we should set entry point length as 0x1F if version is 2.1
   1558     //
   1559     SmbiosEntryLen = 0x1F;
   1560   }
   1561   BufferLen = SmbiosEntryLen + SYS_TABLE_PAD(SmbiosEntryLen) + SmbiosTableOri->TableLength;
   1562   Status = gBS->AllocatePages (
   1563                   AllocateMaxAddress,
   1564                   EfiACPIMemoryNVS,
   1565                   EFI_SIZE_TO_PAGES(BufferLen),
   1566                   &BufferPtr
   1567                   );
   1568   ASSERT_EFI_ERROR (Status);
   1569   SmbiosTableNew = (SMBIOS_TABLE_ENTRY_POINT *)(UINTN)BufferPtr;
   1570   CopyMem (
   1571     SmbiosTableNew,
   1572     SmbiosTableOri,
   1573     SmbiosEntryLen
   1574     );
   1575   //
   1576   // Get Smbios Structure table address, and make sure the start address is 32-bit align
   1577   //
   1578   BufferPtr += SmbiosEntryLen + SYS_TABLE_PAD(SmbiosEntryLen);
   1579   CopyMem (
   1580     (VOID *)(UINTN)BufferPtr,
   1581     (VOID *)(UINTN)(SmbiosTableOri->TableAddress),
   1582     SmbiosTableOri->TableLength
   1583     );
   1584   SmbiosTableNew->TableAddress = (UINT32)BufferPtr;
   1585   SmbiosTableNew->IntermediateChecksum = 0;
   1586   SmbiosTableNew->IntermediateChecksum =
   1587           CalculateCheckSum8 ((UINT8*)SmbiosTableNew + 0x10, SmbiosEntryLen -0x10);
   1588   //
   1589   // Change the SMBIOS pointer
   1590   //
   1591   *Table = SmbiosTableNew;
   1592 
   1593   return EFI_SUCCESS;
   1594 }
   1595 
   1596 EFI_STATUS
   1597 ConvertMpsTable (
   1598   IN OUT VOID          **Table
   1599   )
   1600 /*++
   1601 
   1602 Routine Description:
   1603 
   1604   Convert MP Table if the Location of the SMBios Table is lower than Addres 0x100000
   1605   Assumption here:
   1606    As in legacy Bios, MP table is required to place in E/F Seg,
   1607    So here we just check if the range is E/F seg,
   1608    and if Not, assume the Memory type is EfiACPIMemoryNVS/EfiRuntimeServicesData
   1609 Arguments:
   1610   Table     - pointer to the table
   1611 
   1612 Returns:
   1613   EFI_SUCEESS - Convert Table successfully
   1614   Other       - Failed
   1615 
   1616 --*/
   1617 {
   1618   UINT32                                       Data32;
   1619   UINT32                                       FPLength;
   1620   EFI_LEGACY_MP_TABLE_FLOATING_POINTER         *MpsFloatingPointerOri;
   1621   EFI_LEGACY_MP_TABLE_FLOATING_POINTER         *MpsFloatingPointerNew;
   1622   EFI_LEGACY_MP_TABLE_HEADER                   *MpsTableOri;
   1623   EFI_LEGACY_MP_TABLE_HEADER                   *MpsTableNew;
   1624   VOID                                         *OemTableOri;
   1625   VOID                                         *OemTableNew;
   1626   EFI_STATUS                                   Status;
   1627   EFI_PHYSICAL_ADDRESS                         BufferPtr;
   1628 
   1629   //
   1630   // Get MP configuration Table
   1631   //
   1632   MpsFloatingPointerOri = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)(UINTN)(*(UINT64*)(*Table));
   1633   if (!(((UINTN)MpsFloatingPointerOri <= 0x100000) &&
   1634         ((UINTN)MpsFloatingPointerOri >= 0xF0000))){
   1635     return EFI_SUCCESS;
   1636   }
   1637   //
   1638   // Get Floating pointer structure length
   1639   //
   1640   FPLength = MpsFloatingPointerOri->Length * 16;
   1641   Data32   = FPLength + SYS_TABLE_PAD (FPLength);
   1642   MpsTableOri = (EFI_LEGACY_MP_TABLE_HEADER *)(UINTN)(MpsFloatingPointerOri->PhysicalAddress);
   1643   if (MpsTableOri != NULL) {
   1644     Data32 += MpsTableOri->BaseTableLength;
   1645     Data32 += MpsTableOri->ExtendedTableLength;
   1646     if (MpsTableOri->OemTablePointer != 0x00) {
   1647       Data32 += SYS_TABLE_PAD (Data32);
   1648       Data32 += MpsTableOri->OemTableSize;
   1649     }
   1650   } else {
   1651     return EFI_SUCCESS;
   1652   }
   1653   //
   1654   // Relocate memory
   1655   //
   1656   BufferPtr = EFI_SYSTEM_TABLE_MAX_ADDRESS;
   1657   Status = gBS->AllocatePages (
   1658                   AllocateMaxAddress,
   1659                   EfiACPIMemoryNVS,
   1660                   EFI_SIZE_TO_PAGES(Data32),
   1661                   &BufferPtr
   1662                   );
   1663   ASSERT_EFI_ERROR (Status);
   1664   MpsFloatingPointerNew = (EFI_LEGACY_MP_TABLE_FLOATING_POINTER *)(UINTN)BufferPtr;
   1665   CopyMem (MpsFloatingPointerNew, MpsFloatingPointerOri, FPLength);
   1666   //
   1667   // If Mp Table exists
   1668   //
   1669   if (MpsTableOri != NULL) {
   1670     //
   1671     // Get Mps table length, including Ext table
   1672     //
   1673     BufferPtr = BufferPtr + FPLength + SYS_TABLE_PAD (FPLength);
   1674     MpsTableNew = (EFI_LEGACY_MP_TABLE_HEADER *)(UINTN)BufferPtr;
   1675     CopyMem (MpsTableNew, MpsTableOri, MpsTableOri->BaseTableLength + MpsTableOri->ExtendedTableLength);
   1676 
   1677     if ((MpsTableOri->OemTableSize != 0x0000) && (MpsTableOri->OemTablePointer != 0x0000)){
   1678         BufferPtr += MpsTableOri->BaseTableLength + MpsTableOri->ExtendedTableLength;
   1679         BufferPtr += SYS_TABLE_PAD (BufferPtr);
   1680         OemTableNew = (VOID *)(UINTN)BufferPtr;
   1681         OemTableOri = (VOID *)(UINTN)MpsTableOri->OemTablePointer;
   1682         CopyMem (OemTableNew, OemTableOri, MpsTableOri->OemTableSize);
   1683         MpsTableNew->OemTablePointer = (UINT32)(UINTN)OemTableNew;
   1684     }
   1685     MpsTableNew->Checksum = 0;
   1686     MpsTableNew->Checksum = CalculateCheckSum8 ((UINT8*)MpsTableNew, MpsTableOri->BaseTableLength);
   1687     MpsFloatingPointerNew->PhysicalAddress = (UINT32)(UINTN)MpsTableNew;
   1688     MpsFloatingPointerNew->Checksum = 0;
   1689     MpsFloatingPointerNew->Checksum = CalculateCheckSum8 ((UINT8*)MpsFloatingPointerNew, FPLength);
   1690   }
   1691   //
   1692   // Change the pointer
   1693   //
   1694   *Table = MpsFloatingPointerNew;
   1695 
   1696   return EFI_SUCCESS;
   1697 }
   1698 
   1699 /**
   1700   Lock the ConsoleIn device in system table. All key
   1701   presses will be ignored until the Password is typed in. The only way to
   1702   disable the password is to type it in to a ConIn device.
   1703 
   1704   @param  Password        Password used to lock ConIn device.
   1705 
   1706   @retval EFI_SUCCESS     lock the Console In Spliter virtual handle successfully.
   1707   @retval EFI_UNSUPPORTED Password not found
   1708 
   1709 **/
   1710 EFI_STATUS
   1711 EFIAPI
   1712 LockKeyboards (
   1713   IN  CHAR16    *Password
   1714   )
   1715 {
   1716     return EFI_UNSUPPORTED;
   1717 }
   1718 
   1719 /**
   1720   This function locks platform flash that is not allowed to be updated during normal boot path.
   1721   The flash layout is platform specific.
   1722 
   1723   **/
   1724 VOID
   1725 EFIAPI
   1726 PlatformBdsLockNonUpdatableFlash (
   1727   VOID
   1728   )
   1729 {
   1730   return;
   1731 }
   1732