]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiPayloadPkg/BlSupportPei/BlSupportPei.c
UefiPayloadPkg: Enhance UEFI payload for coreboot and Slim Bootloader
[mirror_edk2.git] / UefiPayloadPkg / BlSupportPei / BlSupportPei.c
diff --git a/UefiPayloadPkg/BlSupportPei/BlSupportPei.c b/UefiPayloadPkg/BlSupportPei/BlSupportPei.c
new file mode 100644 (file)
index 0000000..90433b6
--- /dev/null
@@ -0,0 +1,566 @@
+/** @file\r
+  This PEIM will parse bootloader information and report resource information into pei core.\r
+  This file contains the main entrypoint of the PEIM.\r
+\r
+Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+#include "BlSupportPei.h"\r
+\r
+#define LEGACY_8259_MASK_REGISTER_MASTER  0x21\r
+#define LEGACY_8259_MASK_REGISTER_SLAVE   0xA1\r
+\r
+EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = {\r
+  { EfiACPIReclaimMemory,   FixedPcdGet32 (PcdMemoryTypeEfiACPIReclaimMemory) },\r
+  { EfiACPIMemoryNVS,       FixedPcdGet32 (PcdMemoryTypeEfiACPIMemoryNVS) },\r
+  { EfiReservedMemoryType,  FixedPcdGet32 (PcdMemoryTypeEfiReservedMemoryType) },\r
+  { EfiRuntimeServicesData, FixedPcdGet32 (PcdMemoryTypeEfiRuntimeServicesData) },\r
+  { EfiRuntimeServicesCode, FixedPcdGet32 (PcdMemoryTypeEfiRuntimeServicesCode) },\r
+  { EfiMaxMemoryType,       0     }\r
+};\r
+\r
+EFI_PEI_PPI_DESCRIPTOR   mPpiBootMode[] = {\r
+  {\r
+    EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
+    &gEfiPeiMasterBootModePpiGuid,\r
+    NULL\r
+  }\r
+};\r
+\r
+EFI_PEI_GRAPHICS_DEVICE_INFO_HOB mDefaultGraphicsDeviceInfo = {\r
+  MAX_UINT16, MAX_UINT16, MAX_UINT16, MAX_UINT16, MAX_UINT8,  MAX_UINT8\r
+};\r
+\r
+/**\r
+  Create memory mapped io resource hob.\r
+\r
+  @param  MmioBase    Base address of the memory mapped io range\r
+  @param  MmioSize    Length of the memory mapped io range\r
+\r
+**/\r
+VOID\r
+BuildMemoryMappedIoRangeHob (\r
+  EFI_PHYSICAL_ADDRESS        MmioBase,\r
+  UINT64                      MmioSize\r
+  )\r
+{\r
+  BuildResourceDescriptorHob (\r
+    EFI_RESOURCE_MEMORY_MAPPED_IO,\r
+    (EFI_RESOURCE_ATTRIBUTE_PRESENT    |\r
+    EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r
+    EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |\r
+    EFI_RESOURCE_ATTRIBUTE_TESTED),\r
+    MmioBase,\r
+    MmioSize\r
+    );\r
+\r
+  BuildMemoryAllocationHob (\r
+    MmioBase,\r
+    MmioSize,\r
+    EfiMemoryMappedIO\r
+    );\r
+}\r
+\r
+/**\r
+  Check the integrity of firmware volume header\r
+\r
+  @param[in]  FwVolHeader   A pointer to a firmware volume header\r
+\r
+  @retval     TRUE          The firmware volume is consistent\r
+  @retval     FALSE         The firmware volume has corrupted.\r
+\r
+**/\r
+STATIC\r
+BOOLEAN\r
+IsFvHeaderValid (\r
+  IN EFI_FIRMWARE_VOLUME_HEADER    *FwVolHeader\r
+  )\r
+{\r
+  UINT16 Checksum;\r
+\r
+  // Skip nv storage fv\r
+  if (CompareMem (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystem2Guid, sizeof(EFI_GUID)) != 0 ) {\r
+    return FALSE;\r
+  }\r
+\r
+  if ( (FwVolHeader->Revision != EFI_FVH_REVISION)   ||\r
+     (FwVolHeader->Signature != EFI_FVH_SIGNATURE) ||\r
+     (FwVolHeader->FvLength == ((UINTN) -1))       ||\r
+     ((FwVolHeader->HeaderLength & 0x01 ) !=0) )  {\r
+    return FALSE;\r
+  }\r
+\r
+  Checksum = CalculateCheckSum16 ((UINT16 *) FwVolHeader, FwVolHeader->HeaderLength);\r
+  if (Checksum != 0) {\r
+    DEBUG (( DEBUG_ERROR,\r
+              "ERROR - Invalid Firmware Volume Header Checksum, change 0x%04x to 0x%04x\r\n",\r
+              FwVolHeader->Checksum,\r
+              (UINT16)( Checksum + FwVolHeader->Checksum )));\r
+    return TRUE; //FALSE; Need update UEFI build tool when patching entrypoin @start of fd.\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Install FvInfo PPI and create fv hobs for remained fvs\r
+\r
+**/\r
+VOID\r
+PeiReportRemainedFvs (\r
+  VOID\r
+  )\r
+{\r
+  UINT8*  TempPtr;\r
+  UINT8*  EndPtr;\r
+\r
+  TempPtr = (UINT8* )(UINTN) PcdGet32 (PcdPayloadFdMemBase);\r
+  EndPtr = (UINT8* )(UINTN) (PcdGet32 (PcdPayloadFdMemBase) + PcdGet32 (PcdPayloadFdMemSize));\r
+\r
+  for (;TempPtr < EndPtr;) {\r
+    if (IsFvHeaderValid ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)) {\r
+      if (TempPtr != (UINT8* )(UINTN) PcdGet32 (PcdPayloadFdMemBase))  {\r
+        // Skip the PEI FV\r
+        DEBUG((DEBUG_INFO, "Found one valid fv : 0x%lx.\n", TempPtr, ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength));\r
+\r
+        PeiServicesInstallFvInfoPpi (\r
+          NULL,\r
+          (VOID *) (UINTN) TempPtr,\r
+          (UINT32) (UINTN) ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength,\r
+          NULL,\r
+          NULL\r
+          );\r
+        BuildFvHob ((EFI_PHYSICAL_ADDRESS)(UINTN) TempPtr, ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength);\r
+      }\r
+    }\r
+    TempPtr += ((EFI_FIRMWARE_VOLUME_HEADER* )TempPtr)->FvLength;\r
+  }\r
+}\r
+\r
+\r
+/**\r
+  Find the board related info from ACPI table\r
+\r
+  @param  AcpiTableBase          ACPI table start address in memory\r
+  @param  AcpiBoardInfo          Pointer to the acpi board info strucutre\r
+\r
+  @retval RETURN_SUCCESS     Successfully find out all the required information.\r
+  @retval RETURN_NOT_FOUND   Failed to find the required info.\r
+\r
+**/\r
+RETURN_STATUS\r
+ParseAcpiInfo (\r
+  IN   UINT64                                   AcpiTableBase,\r
+  OUT  ACPI_BOARD_INFO                          *AcpiBoardInfo\r
+  )\r
+{\r
+  EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER  *Rsdp;\r
+  EFI_ACPI_DESCRIPTION_HEADER                   *Rsdt;\r
+  UINT32                                        *Entry32;\r
+  UINTN                                         Entry32Num;\r
+  EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE     *Fadt;\r
+  EFI_ACPI_DESCRIPTION_HEADER                   *Xsdt;\r
+  UINT64                                        *Entry64;\r
+  UINTN                                         Entry64Num;\r
+  UINTN                                         Idx;\r
+  EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER *MmCfgHdr;\r
+  EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *MmCfgBase;\r
+\r
+  Rsdp = (EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER *)(UINTN)AcpiTableBase;\r
+  DEBUG ((DEBUG_INFO, "Rsdp at 0x%p\n", Rsdp));\r
+  DEBUG ((DEBUG_INFO, "Rsdt at 0x%x, Xsdt at 0x%lx\n", Rsdp->RsdtAddress, Rsdp->XsdtAddress));\r
+\r
+  //\r
+  // Search Rsdt First\r
+  //\r
+  Fadt     = NULL;\r
+  MmCfgHdr = NULL;\r
+  Rsdt     = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)(Rsdp->RsdtAddress);\r
+  if (Rsdt != NULL) {\r
+    Entry32  = (UINT32 *)(Rsdt + 1);\r
+    Entry32Num = (Rsdt->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER)) >> 2;\r
+    for (Idx = 0; Idx < Entry32Num; Idx++) {\r
+      if (*(UINT32 *)(UINTN)(Entry32[Idx]) == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {\r
+        Fadt = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)(UINTN)(Entry32[Idx]);\r
+        DEBUG ((DEBUG_INFO, "Found Fadt in Rsdt\n"));\r
+      }\r
+\r
+      if (*(UINT32 *)(UINTN)(Entry32[Idx]) == EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE) {\r
+        MmCfgHdr = (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER *)(UINTN)(Entry32[Idx]);\r
+        DEBUG ((DEBUG_INFO, "Found MM config address in Rsdt\n"));\r
+      }\r
+\r
+      if ((Fadt != NULL) && (MmCfgHdr != NULL)) {\r
+        goto Done;\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Search Xsdt Second\r
+  //\r
+  Xsdt     = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN)(Rsdp->XsdtAddress);\r
+  if (Xsdt != NULL) {\r
+    Entry64  = (UINT64 *)(Xsdt + 1);\r
+    Entry64Num = (Xsdt->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER)) >> 3;\r
+    for (Idx = 0; Idx < Entry64Num; Idx++) {\r
+      if (*(UINT32 *)(UINTN)(Entry64[Idx]) == EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {\r
+        Fadt = (EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE *)(UINTN)(Entry64[Idx]);\r
+        DEBUG ((DEBUG_INFO, "Found Fadt in Xsdt\n"));\r
+      }\r
+\r
+      if (*(UINT32 *)(UINTN)(Entry64[Idx]) == EFI_ACPI_5_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE) {\r
+        MmCfgHdr = (EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_BASE_ADDRESS_TABLE_HEADER *)(UINTN)(Entry32[Idx]);\r
+        DEBUG ((DEBUG_INFO, "Found MM config address in Xsdt\n"));\r
+      }\r
+\r
+      if ((Fadt != NULL) && (MmCfgHdr != NULL)) {\r
+        goto Done;\r
+      }\r
+    }\r
+  }\r
+\r
+  if (Fadt == NULL) {\r
+    return RETURN_NOT_FOUND;\r
+  }\r
+\r
+Done:\r
+\r
+  AcpiBoardInfo->PmCtrlRegBase   = Fadt->Pm1aCntBlk;\r
+  AcpiBoardInfo->PmTimerRegBase  = Fadt->PmTmrBlk;\r
+  AcpiBoardInfo->ResetRegAddress = Fadt->ResetReg.Address;\r
+  AcpiBoardInfo->ResetValue      = Fadt->ResetValue;\r
+  AcpiBoardInfo->PmEvtBase       = Fadt->Pm1aEvtBlk;\r
+  AcpiBoardInfo->PmGpeEnBase     = Fadt->Gpe0Blk + Fadt->Gpe0BlkLen / 2;\r
+\r
+  if (MmCfgHdr != NULL) {\r
+    MmCfgBase = (EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE *)((UINT8*) MmCfgHdr + sizeof (*MmCfgHdr));\r
+    AcpiBoardInfo->PcieBaseAddress = MmCfgBase->BaseAddress;\r
+  } else {\r
+    AcpiBoardInfo->PcieBaseAddress = 0;\r
+  }\r
+  DEBUG ((DEBUG_INFO, "PmCtrl  Reg 0x%lx\n",  AcpiBoardInfo->PmCtrlRegBase));\r
+  DEBUG ((DEBUG_INFO, "PmTimer Reg 0x%lx\n",  AcpiBoardInfo->PmTimerRegBase));\r
+  DEBUG ((DEBUG_INFO, "Reset   Reg 0x%lx\n",  AcpiBoardInfo->ResetRegAddress));\r
+  DEBUG ((DEBUG_INFO, "Reset   Value 0x%x\n", AcpiBoardInfo->ResetValue));\r
+  DEBUG ((DEBUG_INFO, "PmEvt   Reg 0x%lx\n",  AcpiBoardInfo->PmEvtBase));\r
+  DEBUG ((DEBUG_INFO, "PmGpeEn Reg 0x%lx\n",  AcpiBoardInfo->PmGpeEnBase));\r
+  DEBUG ((DEBUG_INFO, "PcieBaseAddr 0x%lx\n", AcpiBoardInfo->PcieBaseAddress));\r
+\r
+  //\r
+  // Verify values for proper operation\r
+  //\r
+  ASSERT(Fadt->Pm1aCntBlk != 0);\r
+  ASSERT(Fadt->PmTmrBlk != 0);\r
+  ASSERT(Fadt->ResetReg.Address != 0);\r
+  ASSERT(Fadt->Pm1aEvtBlk != 0);\r
+  ASSERT(Fadt->Gpe0Blk != 0);\r
+\r
+  DEBUG_CODE_BEGIN ();\r
+    BOOLEAN    SciEnabled;\r
+\r
+    //\r
+    // Check the consistency of SCI enabling\r
+    //\r
+\r
+    //\r
+    // Get SCI_EN value\r
+    //\r
+   if (Fadt->Pm1CntLen == 4) {\r
+      SciEnabled = (IoRead32 (Fadt->Pm1aCntBlk) & BIT0)? TRUE : FALSE;\r
+    } else {\r
+      //\r
+      // if (Pm1CntLen == 2), use 16 bit IO read;\r
+      // if (Pm1CntLen != 2 && Pm1CntLen != 4), use 16 bit IO read as a fallback\r
+      //\r
+      SciEnabled = (IoRead16 (Fadt->Pm1aCntBlk) & BIT0)? TRUE : FALSE;\r
+    }\r
+\r
+    if (!(Fadt->Flags & EFI_ACPI_5_0_HW_REDUCED_ACPI) &&\r
+        (Fadt->SmiCmd == 0) &&\r
+       !SciEnabled) {\r
+      //\r
+      // The ACPI enabling status is inconsistent: SCI is not enabled but ACPI\r
+      // table does not provide a means to enable it through FADT->SmiCmd\r
+      //\r
+      DEBUG ((DEBUG_ERROR, "ERROR: The ACPI enabling status is inconsistent: SCI is not"\r
+        " enabled but the ACPI table does not provide a means to enable it through FADT->SmiCmd."\r
+        " This may cause issues in OS.\n"));\r
+    }\r
+  DEBUG_CODE_END ();\r
+\r
+  return RETURN_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+MemInfoCallback (\r
+  IN MEMROY_MAP_ENTRY             *MemoryMapEntry,\r
+  IN VOID                         *Params\r
+  )\r
+{\r
+  PAYLOAD_MEM_INFO        *MemInfo;\r
+  UINTN                   Attribue;\r
+  EFI_PHYSICAL_ADDRESS    Base;\r
+  EFI_RESOURCE_TYPE       Type;\r
+  UINT64                  Size;\r
+  UINT32                  SystemLowMemTop;\r
+\r
+  Attribue = EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
+             EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r
+             EFI_RESOURCE_ATTRIBUTE_TESTED |\r
+             EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |\r
+             EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |\r
+             EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |\r
+             EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE;\r
+\r
+  MemInfo = (PAYLOAD_MEM_INFO *)Params;\r
+  Type    = (MemoryMapEntry->Type == 1) ? EFI_RESOURCE_SYSTEM_MEMORY : EFI_RESOURCE_MEMORY_RESERVED;\r
+  Base    = MemoryMapEntry->Base;\r
+  Size    = MemoryMapEntry->Size;\r
+\r
+  if ((Base  < 0x100000) && ((Base + Size) > 0x100000)) {\r
+    Size -= (0x100000 - Base);\r
+    Base  = 0x100000;\r
+  }\r
+\r
+  if (Base >= 0x100000) {\r
+    if (Type == EFI_RESOURCE_SYSTEM_MEMORY) {\r
+      if (Base < 0x100000000ULL) {\r
+        MemInfo->UsableLowMemTop = (UINT32)(Base + Size);\r
+      } else {\r
+        Attribue &= ~EFI_RESOURCE_ATTRIBUTE_TESTED;\r
+      }\r
+      BuildResourceDescriptorHob (\r
+        EFI_RESOURCE_SYSTEM_MEMORY,\r
+        Attribue,\r
+        (EFI_PHYSICAL_ADDRESS)Base,\r
+        Size\r
+        );\r
+    } else if (Type == EFI_RESOURCE_MEMORY_RESERVED) {\r
+      BuildResourceDescriptorHob (\r
+        EFI_RESOURCE_MEMORY_RESERVED,\r
+        Attribue,\r
+        (EFI_PHYSICAL_ADDRESS)Base,\r
+        Size\r
+        );\r
+      if (Base < 0x100000000ULL) {\r
+        SystemLowMemTop = ((UINT32)(Base + Size) + 0x0FFFFFFF) & 0xF0000000;\r
+        if (SystemLowMemTop > MemInfo->SystemLowMemTop) {\r
+          MemInfo->SystemLowMemTop = SystemLowMemTop;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  This is the entrypoint of PEIM\r
+\r
+  @param  FileHandle  Handle of the file being invoked.\r
+  @param  PeiServices Describes the list of possible PEI Services.\r
+\r
+  @retval EFI_SUCCESS if it completed successfully.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+BlPeiEntryPoint (\r
+  IN       EFI_PEI_FILE_HANDLE     FileHandle,\r
+  IN CONST EFI_PEI_SERVICES        **PeiServices\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  UINT64                           LowMemorySize;\r
+  UINT64                           PeiMemSize = SIZE_64MB;\r
+  EFI_PHYSICAL_ADDRESS             PeiMemBase = 0;\r
+  UINT32                           RegEax;\r
+  UINT8                            PhysicalAddressBits;\r
+  PAYLOAD_MEM_INFO                 PldMemInfo;\r
+  SYSTEM_TABLE_INFO                SysTableInfo;\r
+  SYSTEM_TABLE_INFO                *NewSysTableInfo;\r
+  ACPI_BOARD_INFO                  AcpiBoardInfo;\r
+  ACPI_BOARD_INFO                  *NewAcpiBoardInfo;\r
+  EFI_PEI_GRAPHICS_INFO_HOB        GfxInfo;\r
+  EFI_PEI_GRAPHICS_INFO_HOB        *NewGfxInfo;\r
+  EFI_PEI_GRAPHICS_DEVICE_INFO_HOB GfxDeviceInfo;\r
+  EFI_PEI_GRAPHICS_DEVICE_INFO_HOB *NewGfxDeviceInfo;\r
+\r
+\r
+  //\r
+  // Report lower 640KB of RAM. Attribute EFI_RESOURCE_ATTRIBUTE_TESTED\r
+  // is intentionally omitted to prevent erasing of the coreboot header\r
+  // record before it is processed by ParseMemoryInfo.\r
+  //\r
+  BuildResourceDescriptorHob (\r
+    EFI_RESOURCE_SYSTEM_MEMORY,\r
+    (\r
+    EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
+    EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r
+    EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |\r
+    EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |\r
+    EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |\r
+    EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE\r
+    ),\r
+    (EFI_PHYSICAL_ADDRESS)(0),\r
+    (UINT64)(0xA0000)\r
+    );\r
+\r
+  BuildResourceDescriptorHob (\r
+    EFI_RESOURCE_MEMORY_RESERVED,\r
+    (\r
+    EFI_RESOURCE_ATTRIBUTE_PRESENT |\r
+    EFI_RESOURCE_ATTRIBUTE_INITIALIZED |\r
+    EFI_RESOURCE_ATTRIBUTE_TESTED |\r
+    EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |\r
+    EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |\r
+    EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |\r
+    EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE\r
+    ),\r
+    (EFI_PHYSICAL_ADDRESS)(0xA0000),\r
+    (UINT64)(0x60000)\r
+    );\r
+\r
+\r
+  //\r
+  // Parse memory info\r
+  //\r
+  ZeroMem (&PldMemInfo, sizeof(PldMemInfo));\r
+  Status = ParseMemoryInfo (MemInfoCallback, &PldMemInfo);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Install memory\r
+  //\r
+  LowMemorySize = PldMemInfo.UsableLowMemTop;\r
+  PeiMemBase = (LowMemorySize - PeiMemSize) & (~(BASE_64KB - 1));\r
+  DEBUG ((DEBUG_INFO, "Low memory 0x%lx\n", LowMemorySize));\r
+  DEBUG ((DEBUG_INFO, "SystemLowMemTop 0x%x\n", PldMemInfo.SystemLowMemTop));\r
+  DEBUG ((DEBUG_INFO, "PeiMemBase: 0x%lx.\n", PeiMemBase));\r
+  DEBUG ((DEBUG_INFO, "PeiMemSize: 0x%lx.\n", PeiMemSize));\r
+  Status = PeiServicesInstallPeiMemory (PeiMemBase, PeiMemSize);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Set cache on the physical memory\r
+  //\r
+  MtrrSetMemoryAttribute (BASE_1MB, LowMemorySize - BASE_1MB, CacheWriteBack);\r
+  MtrrSetMemoryAttribute (0, 0xA0000, CacheWriteBack);\r
+\r
+  //\r
+  // Create Memory Type Information HOB\r
+  //\r
+  BuildGuidDataHob (\r
+    &gEfiMemoryTypeInformationGuid,\r
+    mDefaultMemoryTypeInformation,\r
+    sizeof(mDefaultMemoryTypeInformation)\r
+    );\r
+\r
+  //\r
+  // Create Fv hob\r
+  //\r
+  PeiReportRemainedFvs ();\r
+\r
+  BuildMemoryAllocationHob (\r
+    PcdGet32 (PcdPayloadFdMemBase),\r
+    PcdGet32 (PcdPayloadFdMemSize),\r
+    EfiBootServicesData\r
+    );\r
+\r
+  //\r
+  // Build CPU memory space and IO space hob\r
+  //\r
+  AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
+  if (RegEax >= 0x80000008) {\r
+    AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
+    PhysicalAddressBits = (UINT8) RegEax;\r
+  } else {\r
+    PhysicalAddressBits  = 36;\r
+  }\r
+\r
+  //\r
+  // Create a CPU hand-off information\r
+  //\r
+  BuildCpuHob (PhysicalAddressBits, 16);\r
+\r
+  //\r
+  // Report Local APIC range\r
+  //\r
+  BuildMemoryMappedIoRangeHob (0xFEC80000, SIZE_512KB);\r
+\r
+  //\r
+  // Boot mode\r
+  //\r
+  Status = PeiServicesSetBootMode (BOOT_WITH_FULL_CONFIGURATION);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  Status = PeiServicesInstallPpi (mPpiBootMode);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  //\r
+  // Create guid hob for frame buffer information\r
+  //\r
+  Status = ParseGfxInfo (&GfxInfo);\r
+  if (!EFI_ERROR (Status)) {\r
+    NewGfxInfo = BuildGuidHob (&gEfiGraphicsInfoHobGuid, sizeof (GfxInfo));\r
+    ASSERT (NewGfxInfo != NULL);\r
+    CopyMem (NewGfxInfo, &GfxInfo, sizeof (GfxInfo));\r
+    DEBUG ((DEBUG_INFO, "Created graphics info hob\n"));\r
+  }\r
+\r
+\r
+  Status = ParseGfxDeviceInfo (&GfxDeviceInfo);\r
+  if (!EFI_ERROR (Status)) {\r
+    NewGfxDeviceInfo = BuildGuidHob (&gEfiGraphicsDeviceInfoHobGuid, sizeof (GfxDeviceInfo));\r
+    ASSERT (NewGfxDeviceInfo != NULL);\r
+    CopyMem (NewGfxDeviceInfo, &GfxDeviceInfo, sizeof (GfxDeviceInfo));\r
+    DEBUG ((DEBUG_INFO, "Created graphics device info hob\n"));\r
+  }\r
+\r
+\r
+  //\r
+  // Create guid hob for system tables like acpi table and smbios table\r
+  //\r
+  Status = ParseSystemTable(&SysTableInfo);\r
+  ASSERT_EFI_ERROR (Status);\r
+  if (!EFI_ERROR (Status)) {\r
+    NewSysTableInfo = BuildGuidHob (&gUefiSystemTableInfoGuid, sizeof (SYSTEM_TABLE_INFO));\r
+    ASSERT (NewSysTableInfo != NULL);\r
+    CopyMem (NewSysTableInfo, &SysTableInfo, sizeof (SYSTEM_TABLE_INFO));\r
+    DEBUG ((DEBUG_INFO, "Detected Acpi Table at 0x%lx, length 0x%x\n", SysTableInfo.AcpiTableBase, SysTableInfo.AcpiTableSize));\r
+    DEBUG ((DEBUG_INFO, "Detected Smbios Table at 0x%lx, length 0x%x\n", SysTableInfo.SmbiosTableBase, SysTableInfo.SmbiosTableSize));\r
+  }\r
+\r
+  //\r
+  // Create guid hob for acpi board information\r
+  //\r
+  Status = ParseAcpiInfo (SysTableInfo.AcpiTableBase, &AcpiBoardInfo);\r
+  ASSERT_EFI_ERROR (Status);\r
+  if (!EFI_ERROR (Status)) {\r
+    NewAcpiBoardInfo = BuildGuidHob (&gUefiAcpiBoardInfoGuid, sizeof (ACPI_BOARD_INFO));\r
+    ASSERT (NewAcpiBoardInfo != NULL);\r
+    CopyMem (NewAcpiBoardInfo, &AcpiBoardInfo, sizeof (ACPI_BOARD_INFO));\r
+    DEBUG ((DEBUG_INFO, "Create acpi board info guid hob\n"));\r
+  }\r
+\r
+  //\r
+  // Parse platform specific information.\r
+  //\r
+  Status = ParsePlatformInfo ();\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((DEBUG_ERROR, "Error when parsing platform info, Status = %r\n", Status));\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Mask off all legacy 8259 interrupt sources\r
+  //\r
+  IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF);\r
+  IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE,  0xFF);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r