/**
  Implementation of the PlatformInformation2 service in EFI_SEC_PLATFORM_INFORMATION2_PPI.

  @param  PeiServices                The pointer to the PEI Services Table.
  @param  StructureSize              The pointer to the variable describing size of the input buffer.
  @param  PlatformInformationRecord2 The pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD2.

  @retval EFI_SUCCESS                The data was successfully returned.
  @retval EFI_BUFFER_TOO_SMALL       The buffer was too small. The current buffer size needed to
                                     hold the record is returned in StructureSize.

**/
EFI_STATUS
EFIAPI
SecPlatformInformation2 (
  IN CONST EFI_PEI_SERVICES                   **PeiServices,
  IN OUT UINT64                               *StructureSize,
     OUT EFI_SEC_PLATFORM_INFORMATION_RECORD2 *PlatformInformationRecord2
  )
{
  EFI_HOB_GUID_TYPE       *GuidHob;
  VOID                    *DataInHob;
  UINTN                   DataSize;

  GuidHob = GetFirstGuidHob (&gEfiSecPlatformInformation2PpiGuid);
  if (GuidHob == NULL) {
    *StructureSize = 0;
    return EFI_SUCCESS;
  }

  DataInHob = GET_GUID_HOB_DATA (GuidHob);
  DataSize  = GET_GUID_HOB_DATA_SIZE (GuidHob);

  //
  // return the information from BistHob
  //
  if ((*StructureSize) < (UINT64) DataSize) {
    *StructureSize = (UINT64) DataSize;
    return EFI_BUFFER_TOO_SMALL;
  }

  *StructureSize = (UINT64) DataSize;
  CopyMem (PlatformInformationRecord2, DataInHob, DataSize);
  return EFI_SUCCESS;
}
Esempio n. 2
0
File: PnvDxe.c Progetto: ozbenh/edk2
//
// Initialization
//
EFI_STATUS
EFIAPI
InitializePnvDxe (
  IN EFI_HANDLE           ImageHandle,
  IN EFI_SYSTEM_TABLE     *SystemTable
  )
{
  VOID                           *Hob;
  VOID                           *DeviceTreeBase;
  EFI_STATUS                     Status;
  //
  // Recover the DeviceTree HOB and install it in the configuration table
  //
  Hob = GetFirstGuidHob(&gFdtHobGuid);
  if (Hob == NULL || GET_GUID_HOB_DATA_SIZE (Hob) != sizeof (UINT64)) {
    DEBUG ((EFI_D_ERROR, "%a: No FDT HOB found\n", __FUNCTION__));
    return EFI_NOT_FOUND;
  }
  DeviceTreeBase = (VOID *)(UINTN)*(UINT64 *)GET_GUID_HOB_DATA (Hob);

  if (fdt_check_header (DeviceTreeBase) != 0) {
    DEBUG ((EFI_D_ERROR, "%a: DTB Invalid @ 0x%p\n", __FUNCTION__, DeviceTreeBase));
    return EFI_NOT_FOUND;
  }

  Status = gBS->InstallConfigurationTable (&gFdtTableGuid, DeviceTreeBase);
  ASSERT_EFI_ERROR (Status);
  
  DEBUG ((EFI_D_INFO, "%a: DTB @ 0x%p\n", __FUNCTION__, DeviceTreeBase));

  return EFI_SUCCESS;
}
Esempio n. 3
0
EFI_STATUS
PlatformHobCreateFromFsp (
  IN CONST EFI_PEI_SERVICES     **PeiServices,
  VOID                          *HobList
  )
{
  VOID       *HobData;
  VOID       *NewHobData;
  UINTN      DataSize;

  //
  // Other hob, todo: put this into FspWrapPlatformLib
  //
  if ((HobList = GetNextGuidHob (&gEfiMemoryConfigDataGuid, HobList)) != NULL) {
    HobData = GET_GUID_HOB_DATA (HobList);
    DataSize = GET_GUID_HOB_DATA_SIZE(HobList);
    DEBUG((EFI_D_ERROR, "gEfiMemoryConfigDataGuid Hob found: 0x%x.\n", DataSize));

    NewHobData = BuildGuidHob (&gEfiMemoryConfigDataGuid, DataSize);
    (*PeiServices)->CopyMem (
                      NewHobData,
                      HobData,
                      DataSize
                      );
  }

  return EFI_SUCCESS;
}
Esempio n. 4
0
/**
  Worker function to parse CPU BIST information from Guided HOB.

  @param[out] StructureSize     Pointer to the variable describing size of the input buffer.
  @param[out] StructureBuffer   Pointer to the buffer save CPU BIST information.

  @retval EFI_SUCCESS           The data was successfully returned.
  @retval EFI_BUFFER_TOO_SMALL  The buffer was too small.

**/
EFI_STATUS
GetBistFromHob (
  IN OUT UINT64           *StructureSize,
  IN OUT VOID             *StructureBuffer
  )
{
  EFI_HOB_GUID_TYPE       *GuidHob;
  VOID                    *DataInHob;
  UINTN                   DataSize;

  GuidHob = GetFirstGuidHob (&gEfiCallerIdGuid);
  if (GuidHob == NULL) {
    *StructureSize = 0;
    return EFI_SUCCESS;
  }

  DataInHob = GET_GUID_HOB_DATA (GuidHob);
  DataSize  = GET_GUID_HOB_DATA_SIZE (GuidHob);

  //
  // return the information from BistHob
  //
  if ((*StructureSize) < (UINT64) DataSize) {
    *StructureSize = (UINT64) DataSize;
    return EFI_BUFFER_TOO_SMALL;
  }

  *StructureSize = (UINT64) DataSize;
  CopyMem (StructureBuffer, DataInHob, DataSize);
  return EFI_SUCCESS;
}
/**
  Process FSP HOB list

  @param[in] FspHobList  Pointer to the HOB data structure produced by FSP.

**/
VOID
ProcessFspHobList (
  IN VOID                 *FspHobList
  )
{
  EFI_PEI_HOB_POINTERS  FspHob;

  FspHob.Raw = FspHobList;

  //
  // Add all the HOBs from FSP binary to FSP wrapper
  //
  while (!END_OF_HOB_LIST (FspHob)) {
    if (FspHob.Header->HobType == EFI_HOB_TYPE_GUID_EXTENSION) {
      //
      // Skip FSP binary creates PcdDataBaseHobGuid
      //
      if (!CompareGuid(&FspHob.Guid->Name, &gPcdDataBaseHobGuid)) { 
        BuildGuidDataHob (
          &FspHob.Guid->Name,
          GET_GUID_HOB_DATA(FspHob),
          GET_GUID_HOB_DATA_SIZE(FspHob)
        );
      }
    }
    FspHob.Raw = GET_NEXT_HOB (FspHob);
  }
}
Esempio n. 6
0
//
// Return list of cores in the system
//
EFI_STATUS
PrePeiCoreGetMpCoreInfo (
  OUT UINTN                   *ArmCoreCount,
  OUT ARM_CORE_INFO           **ArmCoreInfoTable
  )
{
  EFI_PEI_HOB_POINTERS    Hob;

  if (ArmIsMpCore()) {
    // Iterate through the HOBs and find if there is ARM PROCESSOR ENTRY HOB
    for (Hob.Raw = GetHobList (); !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) {
      // Check for Correct HOB type
      if ((GET_HOB_TYPE (Hob)) == EFI_HOB_TYPE_GUID_EXTENSION) {
        // Check for correct GUID type
        if (CompareGuid(&(Hob.Guid->Name), &gAmdStyxMpCoreInfoGuid)) {
          *ArmCoreInfoTable = (ARM_CORE_INFO *) GET_GUID_HOB_DATA(Hob);
          *ArmCoreCount = GET_GUID_HOB_DATA_SIZE(Hob)/sizeof(ARM_CORE_INFO);
          return EFI_SUCCESS;
        }
      }
    }
  }

  return EFI_UNSUPPORTED;
}
UINT64
GetPciExpressBaseAddressForRootBridge (
  IN UINTN    HostBridgeNumber,
  IN UINTN    RootBridgeNumber
  )
/*++

Routine Description:
  This routine is to get PciExpress Base Address for this RootBridge

Arguments:
  HostBridgeNumber - The number of HostBridge
  RootBridgeNumber - The number of RootBridge
    
Returns:
  UINT64 - PciExpressBaseAddress for this HostBridge and RootBridge

--*/
{
  EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION *PciExpressBaseAddressInfo;
  UINTN                                    BufferSize;
  UINT32                                   Index;
  UINT32                                   Number;
  EFI_PEI_HOB_POINTERS                     GuidHob;

  //
  // Get PciExpressAddressInfo Hob
  //
  PciExpressBaseAddressInfo = NULL;
  BufferSize                = 0;
  GuidHob.Raw = GetFirstGuidHob (&gEfiPciExpressBaseAddressGuid);
  if (GuidHob.Raw != NULL) {
    PciExpressBaseAddressInfo = GET_GUID_HOB_DATA (GuidHob.Guid);
    BufferSize                = GET_GUID_HOB_DATA_SIZE (GuidHob.Guid);
  } else {
    return 0;
  }

  //
  // Search the PciExpress Base Address in the Hob for current RootBridge
  //
  Number = (UINT32)(BufferSize / sizeof(EFI_PCI_EXPRESS_BASE_ADDRESS_INFORMATION));
  for (Index = 0; Index < Number; Index++) {
    if ((PciExpressBaseAddressInfo[Index].HostBridgeNumber == HostBridgeNumber) &&
        (PciExpressBaseAddressInfo[Index].RootBridgeNumber == RootBridgeNumber)) {
      return PciExpressBaseAddressInfo[Index].PciExpressBaseAddress;
    }
  }

  //
  // Do not find the PciExpress Base Address in the Hob
  //
  return 0;
}
Esempio n. 8
0
/**

  Program hardware of Serial port

  @return    RETURN_NOT_FOUND if no PL011 base address could be found
             Otherwise, result of PL011UartInitializePort () is returned

**/
RETURN_STATUS
EFIAPI
FdtPL011SerialPortLibInitialize (
  VOID
  )
{
  VOID                *Hob;
  CONST UINT64        *UartBase;
  UINT64              BaudRate;
  UINT32              ReceiveFifoDepth;
  EFI_PARITY_TYPE     Parity;
  UINT8               DataBits;
  EFI_STOP_BITS_TYPE  StopBits;

  Hob = GetFirstGuidHob (&gEarlyPL011BaseAddressGuid);
  if (Hob == NULL || GET_GUID_HOB_DATA_SIZE (Hob) != sizeof *UartBase) {
    return RETURN_NOT_FOUND;
  }
  UartBase = GET_GUID_HOB_DATA (Hob);

  mSerialBaseAddress = (UINTN)*UartBase;
  if (mSerialBaseAddress == 0) {
    return RETURN_NOT_FOUND;
  }

  BaudRate = (UINTN)PcdGet64 (PcdUartDefaultBaudRate);
  ReceiveFifoDepth = 0; // Use the default value for Fifo depth
  Parity = (EFI_PARITY_TYPE)PcdGet8 (PcdUartDefaultParity);
  DataBits = PcdGet8 (PcdUartDefaultDataBits);
  StopBits = (EFI_STOP_BITS_TYPE) PcdGet8 (PcdUartDefaultStopBits);

  return PL011UartInitializePort (
           mSerialBaseAddress,
           FixedPcdGet32 (PL011UartClkInHz),
           &BaudRate,
           &ReceiveFifoDepth,
           &Parity,
           &DataBits,
           &StopBits
           );
}
Esempio n. 9
0
void
GetTempRamStack (
  VOID         **TempRamStackPtr,
  uint16_t     *DataSize
  )
{

  EFI_GUID                FspBootloaderTemporaryMemoryHobGuid = FSP_BOOTLOADER_TEMPORARY_MEMORY_HOB_GUID;
  uint8_t                 *GuidHob;
  EFI_HOB_GENERIC_HEADER  *GuidHobHdr;

  GuidHob = GetFirstGuidHob(&FspBootloaderTemporaryMemoryHobGuid);
  if (!GuidHob) {
    *TempRamStackPtr = 0;
    *DataSize = 0;
  } else {
    *TempRamStackPtr = GET_GUID_HOB_DATA (GuidHob);
    GuidHobHdr = (EFI_HOB_GENERIC_HEADER *)GuidHob;
    *DataSize =  GET_GUID_HOB_DATA_SIZE (GuidHobHdr);
  }
}
Esempio n. 10
0
void
GetFspNVStorageMemory (
  VOID         **FspNVStorageHob,
  uint16_t     *DataSize
  )
{

  EFI_GUID                FspNVStorageHobGuid = FSP_NON_VOLATILE_STORAGE_HOB_GUID;
  uint8_t                 *GuidHob;
  EFI_HOB_GENERIC_HEADER  *GuidHobHdr;

  GuidHob = GetFirstGuidHob(&FspNVStorageHobGuid);
  if (!GuidHob) {
    *FspNVStorageHob = 0;
    *DataSize = 0;
  } else {
    *FspNVStorageHob = GET_GUID_HOB_DATA (GuidHob);
    GuidHobHdr = (EFI_HOB_GENERIC_HEADER *)GuidHob;
    *DataSize =  GET_GUID_HOB_DATA_SIZE (GuidHobHdr);
  }
}
/**
  Returns the debug print error level mask for the current module.

  @return  Debug print error level mask for the current module.

**/
UINT32
EFIAPI
GetDebugPrintErrorLevel (
  VOID
  )
{
  EFI_STATUS  Status;
  EFI_TPL     CurrentTpl;
  UINTN       Size;
  UINTN       GlobalErrorLevel;
  VOID        *Hob;

  //
  // If the constructor has not been executed yet, then just return the PCD value.
  // This case should only occur if debug print is generated by a library
  // constructor for this module
  //
  if (mSystemTable == NULL) {
    return PcdGet32 (PcdDebugPrintErrorLevel);
  }
  
  //
  // Check to see if an attempt has been made to retrieve the global debug print 
  // error level mask.  Since this library instance stores the global debug print
  // error level mask in an EFI Variable, the EFI Variable should only be accessed
  // once to reduce the overhead of reading the EFI Variable on every debug print
  //  
  if (!mGlobalErrorLevelInitialized) {
    //
    // Make sure the TPL Level is low enough for EFI Variable Services to be called
    //
    CurrentTpl = mSystemTable->BootServices->RaiseTPL (TPL_HIGH_LEVEL);
    mSystemTable->BootServices->RestoreTPL (CurrentTpl);
    if (CurrentTpl <= TPL_CALLBACK) {
      //
      // Attempt to retrieve the global debug print error level mask from the 
      // EFI Variable
      //
      Size = sizeof (GlobalErrorLevel);
      Status = mSystemTable->RuntimeServices->GetVariable (
                                       DEBUG_MASK_VARIABLE_NAME, 
                                       &gEfiGenericVariableGuid, 
                                       NULL, 
                                       &Size, 
                                       &GlobalErrorLevel
                                       );
      if (Status != EFI_NOT_AVAILABLE_YET) {
        //
        // If EFI Variable Services are available, then set a flag so the EFI
        // Variable will not be read again by this module.
        //
        mGlobalErrorLevelInitialized = TRUE;
        if (!EFI_ERROR (Status)) {
          //
          // If the EFI Varible exists, then set this module's module's mask to
          // the global debug print error level mask value.
          //
          mDebugPrintErrorLevel = (UINT32)GlobalErrorLevel;
        }
      } else {
        //
        // If variable services are not yet availible optionally get the global
        // debug print error level mask from a HOB.
        //
        Hob = GetFirstGuidHob (&gEfiGenericVariableGuid);
        if (Hob != NULL) {
          if (GET_GUID_HOB_DATA_SIZE (Hob) == sizeof (UINT32)) {
            mDebugPrintErrorLevel = *(UINT32 *)GET_GUID_HOB_DATA (Hob);
            mGlobalErrorLevelInitialized = TRUE;
          }
        }
      }
    }
  }

  //
  // Return the current mask value for this module.
  //
  return mDebugPrintErrorLevel;
}
Esempio n. 12
0
/**
  This routine adjust the memory information for different memory type and 
  save them into the variables for next boot.
**/
VOID
BdsSetMemoryTypeInformationVariable (
  VOID
  )
{
  EFI_STATUS                   Status;
  EFI_MEMORY_TYPE_INFORMATION  *PreviousMemoryTypeInformation;
  EFI_MEMORY_TYPE_INFORMATION  *CurrentMemoryTypeInformation;
  UINTN                        VariableSize;
  UINTN                        Index;
  UINTN                        Index1;
  UINT32                       Previous;
  UINT32                       Current;
  UINT32                       Next;
  EFI_HOB_GUID_TYPE            *GuidHob;
  BOOLEAN                      MemoryTypeInformationModified;
  BOOLEAN                      MemoryTypeInformationVariableExists;
  EFI_BOOT_MODE                BootMode;

  MemoryTypeInformationModified       = FALSE;
  MemoryTypeInformationVariableExists = FALSE;


  BootMode = GetBootModeHob ();
  //
  // In BOOT_IN_RECOVERY_MODE, Variable region is not reliable.
  //
  if (BootMode == BOOT_IN_RECOVERY_MODE) {
    return;
  }

  //
  // Only check the the Memory Type Information variable in the boot mode 
  // other than BOOT_WITH_DEFAULT_SETTINGS because the Memory Type
  // Information is not valid in this boot mode.
  //
  if (BootMode != BOOT_WITH_DEFAULT_SETTINGS) {
    VariableSize = 0;
    Status = gRT->GetVariable (
                    EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
                    &gEfiMemoryTypeInformationGuid,
                    NULL, 
                    &VariableSize, 
                    NULL
                    );
    if (Status == EFI_BUFFER_TOO_SMALL) {
      MemoryTypeInformationVariableExists = TRUE;
    }
  }

  //
  // Retrieve the current memory usage statistics.  If they are not found, then
  // no adjustments can be made to the Memory Type Information variable.
  //
  Status = EfiGetSystemConfigurationTable (
             &gEfiMemoryTypeInformationGuid,
             (VOID **) &CurrentMemoryTypeInformation
             );
  if (EFI_ERROR (Status) || CurrentMemoryTypeInformation == NULL) {
    return;
  }

  //
  // Get the Memory Type Information settings from Hob if they exist,
  // PEI is responsible for getting them from variable and build a Hob to save them.
  // If the previous Memory Type Information is not available, then set defaults
  //
  GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);
  if (GuidHob == NULL) {
    //
    // If Platform has not built Memory Type Info into the Hob, just return.
    //
    return;
  }
  PreviousMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob);
  VariableSize = GET_GUID_HOB_DATA_SIZE (GuidHob);

  //
  // Use a heuristic to adjust the Memory Type Information for the next boot
  //
//  DEBUG ((EFI_D_INFO, "Memory  Previous  Current    Next   \n"));
//  DEBUG ((EFI_D_INFO, " Type    Pages     Pages     Pages  \n"));
//  DEBUG ((EFI_D_INFO, "======  ========  ========  ========\n"));

  for (Index = 0; PreviousMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {

    for (Index1 = 0; CurrentMemoryTypeInformation[Index1].Type != EfiMaxMemoryType; Index1++) {
      if (PreviousMemoryTypeInformation[Index].Type == CurrentMemoryTypeInformation[Index1].Type) {
        break;
      }
    }
    if (CurrentMemoryTypeInformation[Index1].Type == EfiMaxMemoryType) {
      continue;
    }

    //
    // Previous is the number of pages pre-allocated
    // Current is the number of pages actually needed
    //
    Previous = PreviousMemoryTypeInformation[Index].NumberOfPages;
    Current  = CurrentMemoryTypeInformation[Index1].NumberOfPages;
    Next     = Previous;

    //
    // Inconsistent Memory Reserved across bootings may lead to S4 fail
    // Write next varible to 125% * current when the pre-allocated memory is:
    //  1. More than 150% of needed memory and boot mode is BOOT_WITH_DEFAULT_SETTING
    //  2. Less than the needed memory
    //
    if (Current < Previous) {
      if (BootMode == BOOT_WITH_DEFAULT_SETTINGS) {
        Next = Current + (Current >> 2);
      } else if (!MemoryTypeInformationVariableExists) {
        Next = MAX (Current + (Current >> 2), Previous);
      }
Esempio n. 13
0
EFI_STATUS
EFIAPI
SaveMemoryConfigEntryPoint (
  IN EFI_HANDLE         ImageHandle,
  IN EFI_SYSTEM_TABLE   *SystemTable
  )
/*++
  
  Routine Description:
    This is the standard EFI driver point that detects whether there is a
    MemoryConfigurationData HOB and, if so, saves its data to nvRAM.

  Arguments:
    ImageHandle   - Handle for the image of this driver
    SystemTable   - Pointer to the EFI System Table

  Returns:
    EFI_SUCCESS   - if the data is successfully saved or there was no data
    EFI_NOT_FOUND - if the HOB list could not be located.
    EFI_UNLOAD_IMAGE - It is not success
    
--*/
{
  EFI_STATUS  Status;
  VOID        *HobList;
  EFI_HOB_GUID_TYPE *GuidHob;
  VOID        *HobData;
  VOID        *VariableData;
  UINTN       DataSize;
  UINTN       BufferSize;

  DataSize      = 0;
  VariableData  = NULL;
  GuidHob = NULL;
  HobList = NULL;
  HobData = NULL;
  Status  = EFI_UNSUPPORTED;

  //
  // Get the HOB list.  If it is not present, then ASSERT.
  //
  HobList = GetHobList ();
  ASSERT (HobList != NULL);

  //
  // Search for the Memory Configuration GUID HOB.  If it is not present, then
  // there's nothing we can do. It may not exist on the update path.
  //
  GuidHob = GetNextGuidHob (&gEfiMemoryConfigDataGuid, HobList);
  if (GuidHob != NULL) {
    HobData = GET_GUID_HOB_DATA (GuidHob);
    DataSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
    //
    // Use the HOB to save Memory Configuration Data
    //
    BufferSize = DataSize;
    VariableData = AllocatePool (BufferSize);
    ASSERT (VariableData != NULL); 
    Status = gRT->GetVariable (
                    EFI_MEMORY_CONFIG_DATA_NAME,
                    &gEfiMemoryConfigDataGuid,
                    NULL,
                    &BufferSize,
                    VariableData
                    );
    if (Status == EFI_BUFFER_TOO_SMALL) {
      (gBS->FreePool)(VariableData);
      VariableData = AllocatePool (BufferSize);
      ASSERT (VariableData != NULL);      
      Status = gRT->GetVariable (
                      EFI_MEMORY_CONFIG_DATA_NAME,
                      &gEfiMemoryConfigDataGuid,
                      NULL,
                      &BufferSize,
                      VariableData
                      );
    }

    if ( (EFI_ERROR(Status)) || BufferSize != DataSize || 0 != CompareMem (HobData, VariableData, DataSize)) {
      if (Status != EFI_SUCCESS){
        Status = gRT->SetVariable (
                        EFI_MEMORY_CONFIG_DATA_NAME,
                        &gEfiMemoryConfigDataGuid,
                        (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS),
                        DataSize,
                        HobData
                        );
      }
      ASSERT((Status == EFI_SUCCESS) || (Status == EFI_OUT_OF_RESOURCES));

      DEBUG((EFI_D_INFO, "Restored Size is 0x%x\n", DataSize));
    }
    (gBS->FreePool)(VariableData);
  }
  //
  // This driver does not produce any protocol services, so always unload it.
  //
  return Status;
}
Esempio n. 14
0
/**

  This routine is a notification function for legacy boot or exit boot
  service event. It will adjust the memory information for different
  memory type and save them into the variables for next boot.


  @param Event           The event that triggered this notification function.
  @param Context         Pointer to the notification functions context.

**/
VOID
EFIAPI
BdsSetMemoryTypeInformationVariable (
  EFI_EVENT  Event,
  VOID       *Context
  )
{
  EFI_STATUS                   Status;
  EFI_MEMORY_TYPE_INFORMATION  *PreviousMemoryTypeInformation;
  EFI_MEMORY_TYPE_INFORMATION  *CurrentMemoryTypeInformation;
  UINTN                        VariableSize;
  BOOLEAN                      UpdateRequired;
  UINTN                        Index;
  UINTN                        Index1;
  UINT32                       Previous;
  UINT32                       Current;
  UINT32                       Next;
  EFI_HOB_GUID_TYPE            *GuidHob;

  UpdateRequired = FALSE;

  //
  // Retrieve the current memory usage statistics.  If they are not found, then
  // no adjustments can be made to the Memory Type Information variable.
  //
  Status = EfiGetSystemConfigurationTable (
             &gEfiMemoryTypeInformationGuid,
             (VOID **) &CurrentMemoryTypeInformation
             );
  if (EFI_ERROR (Status) || CurrentMemoryTypeInformation == NULL) {
    return;
  }

  //
  // Get the Memory Type Information settings from Hob if they exist,
  // PEI is responsible for getting them from variable and build a Hob to save them.
  // If the previous Memory Type Information is not available, then set defaults
  //
  GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid);
  if (GuidHob == NULL) {
    //
    // If Platform has not built Memory Type Info into the Hob, just return.
    //
    return;
  }
  PreviousMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob);
  VariableSize = GET_GUID_HOB_DATA_SIZE (GuidHob);

  //
  // Use a heuristic to adjust the Memory Type Information for the next boot
  //
  for (Index = 0; PreviousMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) {

    Current = 0;
    for (Index1 = 0; CurrentMemoryTypeInformation[Index1].Type != EfiMaxMemoryType; Index1++) {
      if (PreviousMemoryTypeInformation[Index].Type == CurrentMemoryTypeInformation[Index1].Type) {
        Current = CurrentMemoryTypeInformation[Index1].NumberOfPages;
        break;
      }
    }

    if (CurrentMemoryTypeInformation[Index1].Type == EfiMaxMemoryType) {
      continue;
    }

    Previous = PreviousMemoryTypeInformation[Index].NumberOfPages;

    //
    // Write next variable to 125% * current and Inconsistent Memory Reserved across bootings may lead to S4 fail
    //
    if (Current > Previous) {
      Next = Current + (Current >> 2);
    } else {