REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4166 Fix integer overflow in various CreateHob instances. Fixes: CVE-2022-36765 The CreateHob() function aligns the requested size to 8 performing the following operation: ``` HobLength = (UINT16)((HobLength + 0x7) & (~0x7)); ``` No checks are performed to ensure this value doesn't overflow, and could lead to CreateHob() returning a smaller HOB than requested, which could lead to OOB HOB accesses. Reported-by: Marc Beatove <mbeatove@google.com> Cc: Guo Dong <guo.dong@intel.com> Cc: Sean Rhodes <sean@starlabs.systems> Cc: James Lu <james.lu@intel.com> Reviewed-by: Gua Guo <gua.guo@intel.com> Cc: John Mathew <john.mathews@intel.com> Authored-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Gua Guo <gua.guo@intel.com>
		
			
				
	
	
		
			502 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			502 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
 | 
						|
  Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "UefiPayloadEntry.h"
 | 
						|
 | 
						|
#define MEMORY_ATTRIBUTE_MASK  (EFI_RESOURCE_ATTRIBUTE_PRESENT             |        \
 | 
						|
                                       EFI_RESOURCE_ATTRIBUTE_INITIALIZED         | \
 | 
						|
                                       EFI_RESOURCE_ATTRIBUTE_TESTED              | \
 | 
						|
                                       EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED      | \
 | 
						|
                                       EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED     | \
 | 
						|
                                       EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \
 | 
						|
                                       EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PROTECTED | \
 | 
						|
                                       EFI_RESOURCE_ATTRIBUTE_16_BIT_IO           | \
 | 
						|
                                       EFI_RESOURCE_ATTRIBUTE_32_BIT_IO           | \
 | 
						|
                                       EFI_RESOURCE_ATTRIBUTE_64_BIT_IO           | \
 | 
						|
                                       EFI_RESOURCE_ATTRIBUTE_PERSISTENT          )
 | 
						|
 | 
						|
#define TESTED_MEMORY_ATTRIBUTES  (EFI_RESOURCE_ATTRIBUTE_PRESENT     |     \
 | 
						|
                                       EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
 | 
						|
                                       EFI_RESOURCE_ATTRIBUTE_TESTED      )
 | 
						|
 | 
						|
extern VOID  *mHobList;
 | 
						|
 | 
						|
/**
 | 
						|
  Print all HOBs info from the HOB list.
 | 
						|
 | 
						|
  @return The pointer to the HOB list.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
PrintHob (
 | 
						|
  IN CONST VOID  *HobStart
 | 
						|
  );
 | 
						|
 | 
						|
/**
 | 
						|
  Some bootloader may pass a pcd database, and UPL also contain a PCD database.
 | 
						|
  Dxe PCD driver has the assumption that the two PCD database can be catenated and
 | 
						|
  the local token number should be successive.
 | 
						|
  This function will fix up the UPL PCD database to meet that assumption.
 | 
						|
 | 
						|
  @param[in]   DxeFv         The FV where to find the Universal PCD database.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS        If it completed successfully.
 | 
						|
  @retval other              Failed to fix up.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
FixUpPcdDatabase (
 | 
						|
  IN  EFI_FIRMWARE_VOLUME_HEADER  *DxeFv
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS           Status;
 | 
						|
  EFI_FFS_FILE_HEADER  *FileHeader;
 | 
						|
  VOID                 *PcdRawData;
 | 
						|
  PEI_PCD_DATABASE     *PeiDatabase;
 | 
						|
  PEI_PCD_DATABASE     *UplDatabase;
 | 
						|
  EFI_HOB_GUID_TYPE    *GuidHob;
 | 
						|
  DYNAMICEX_MAPPING    *ExMapTable;
 | 
						|
  UINTN                Index;
 | 
						|
 | 
						|
  GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid);
 | 
						|
  if (GuidHob == NULL) {
 | 
						|
    //
 | 
						|
    // No fix-up is needed.
 | 
						|
    //
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  PeiDatabase = (PEI_PCD_DATABASE *)GET_GUID_HOB_DATA (GuidHob);
 | 
						|
  DEBUG ((DEBUG_INFO, "Find the Pei PCD data base, the total local token number is %d\n", PeiDatabase->LocalTokenCount));
 | 
						|
 | 
						|
  Status = FvFindFileByTypeGuid (DxeFv, EFI_FV_FILETYPE_DRIVER, PcdGetPtr (PcdPcdDriverFile), &FileHeader);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = FileFindSection (FileHeader, EFI_SECTION_RAW, &PcdRawData);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  UplDatabase = (PEI_PCD_DATABASE *)PcdRawData;
 | 
						|
  ExMapTable  = (DYNAMICEX_MAPPING *)(UINTN)((UINTN)PcdRawData + UplDatabase->ExMapTableOffset);
 | 
						|
 | 
						|
  for (Index = 0; Index < UplDatabase->ExTokenCount; Index++) {
 | 
						|
    ExMapTable[Index].TokenNumber += PeiDatabase->LocalTokenCount;
 | 
						|
  }
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "Fix up UPL PCD database successfully\n"));
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Add HOB into HOB list
 | 
						|
 | 
						|
  @param[in]  Hob    The HOB to be added into the HOB list.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
AddNewHob (
 | 
						|
  IN EFI_PEI_HOB_POINTERS  *Hob
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_PEI_HOB_POINTERS  NewHob;
 | 
						|
 | 
						|
  if (Hob->Raw == NULL) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  NewHob.Header = CreateHob (Hob->Header->HobType, Hob->Header->HobLength);
 | 
						|
  ASSERT (NewHob.Header != NULL);
 | 
						|
  if (NewHob.Header == NULL) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem (NewHob.Header + 1, Hob->Header + 1, Hob->Header->HobLength - sizeof (EFI_HOB_GENERIC_HEADER));
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Found the Resource Descriptor HOB that contains a range (Base, Top)
 | 
						|
 | 
						|
  @param[in] HobList    Hob start address
 | 
						|
  @param[in] Base       Memory start address
 | 
						|
  @param[in] Top        Memory end address.
 | 
						|
 | 
						|
  @retval     The pointer to the Resource Descriptor HOB.
 | 
						|
**/
 | 
						|
EFI_HOB_RESOURCE_DESCRIPTOR *
 | 
						|
FindResourceDescriptorByRange (
 | 
						|
  IN VOID                  *HobList,
 | 
						|
  IN EFI_PHYSICAL_ADDRESS  Base,
 | 
						|
  IN EFI_PHYSICAL_ADDRESS  Top
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_PEI_HOB_POINTERS         Hob;
 | 
						|
  EFI_HOB_RESOURCE_DESCRIPTOR  *ResourceHob;
 | 
						|
 | 
						|
  for (Hob.Raw = (UINT8 *)HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
 | 
						|
    //
 | 
						|
    // Skip all HOBs except Resource Descriptor HOBs
 | 
						|
    //
 | 
						|
    if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Skip Resource Descriptor HOBs that do not describe tested system memory
 | 
						|
    //
 | 
						|
    ResourceHob = Hob.ResourceDescriptor;
 | 
						|
    if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Skip Resource Descriptor HOBs that do not contain the PHIT range EfiFreeMemoryBottom..EfiFreeMemoryTop
 | 
						|
    //
 | 
						|
    if (Base < ResourceHob->PhysicalStart) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    if (Top > (ResourceHob->PhysicalStart + ResourceHob->ResourceLength)) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    return ResourceHob;
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Find the highest below 4G memory resource descriptor, except the input Resource Descriptor.
 | 
						|
 | 
						|
  @param[in] HobList                 Hob start address
 | 
						|
  @param[in] MinimalNeededSize       Minimal needed size.
 | 
						|
  @param[in] ExceptResourceHob       Ignore this Resource Descriptor.
 | 
						|
 | 
						|
  @retval     The pointer to the Resource Descriptor HOB.
 | 
						|
**/
 | 
						|
EFI_HOB_RESOURCE_DESCRIPTOR *
 | 
						|
FindAnotherHighestBelow4GResourceDescriptor (
 | 
						|
  IN VOID                         *HobList,
 | 
						|
  IN UINTN                        MinimalNeededSize,
 | 
						|
  IN EFI_HOB_RESOURCE_DESCRIPTOR  *ExceptResourceHob
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_PEI_HOB_POINTERS         Hob;
 | 
						|
  EFI_HOB_RESOURCE_DESCRIPTOR  *ResourceHob;
 | 
						|
  EFI_HOB_RESOURCE_DESCRIPTOR  *ReturnResourceHob;
 | 
						|
 | 
						|
  ReturnResourceHob = NULL;
 | 
						|
 | 
						|
  for (Hob.Raw = (UINT8 *)HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
 | 
						|
    //
 | 
						|
    // Skip all HOBs except Resource Descriptor HOBs
 | 
						|
    //
 | 
						|
    if (GET_HOB_TYPE (Hob) != EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Skip Resource Descriptor HOBs that do not describe tested system memory
 | 
						|
    //
 | 
						|
    ResourceHob = Hob.ResourceDescriptor;
 | 
						|
    if (ResourceHob->ResourceType != EFI_RESOURCE_SYSTEM_MEMORY) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) != TESTED_MEMORY_ATTRIBUTES) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Skip if the Resource Descriptor HOB equals to ExceptResourceHob
 | 
						|
    //
 | 
						|
    if (ResourceHob == ExceptResourceHob) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Skip Resource Descriptor HOBs that are beyond 4G
 | 
						|
    //
 | 
						|
    if ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) > BASE_4GB) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Skip Resource Descriptor HOBs that are too small
 | 
						|
    //
 | 
						|
    if (ResourceHob->ResourceLength < MinimalNeededSize) {
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Return the topest Resource Descriptor
 | 
						|
    //
 | 
						|
    if (ReturnResourceHob == NULL) {
 | 
						|
      ReturnResourceHob = ResourceHob;
 | 
						|
    } else {
 | 
						|
      if (ReturnResourceHob->PhysicalStart < ResourceHob->PhysicalStart) {
 | 
						|
        ReturnResourceHob = ResourceHob;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return ReturnResourceHob;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Check the HOB and decide if it is need inside Payload
 | 
						|
 | 
						|
  Payload maintainer may make decision which HOB is need or needn't
 | 
						|
  Then add the check logic in the function.
 | 
						|
 | 
						|
  @param[in] Hob The HOB to check
 | 
						|
 | 
						|
  @retval TRUE  If HOB is need inside Payload
 | 
						|
  @retval FALSE If HOB is needn't inside Payload
 | 
						|
**/
 | 
						|
BOOLEAN
 | 
						|
IsHobNeed (
 | 
						|
  EFI_PEI_HOB_POINTERS  Hob
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (Hob.Header->HobType == EFI_HOB_TYPE_HANDOFF) {
 | 
						|
    return FALSE;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Hob.Header->HobType == EFI_HOB_TYPE_MEMORY_ALLOCATION) {
 | 
						|
    if (CompareGuid (&Hob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid)) {
 | 
						|
      return FALSE;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Arrive here mean the HOB is need
 | 
						|
  return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  It will build HOBs based on information from bootloaders.
 | 
						|
 | 
						|
  @param[in]  BootloaderParameter   The starting memory address of bootloader parameter block.
 | 
						|
  @param[out] DxeFv                 The pointer to the DXE FV in memory.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS        If it completed successfully.
 | 
						|
  @retval Others             If it failed to build required HOBs.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
BuildHobs (
 | 
						|
  IN  UINTN                       BootloaderParameter,
 | 
						|
  OUT EFI_FIRMWARE_VOLUME_HEADER  **DxeFv
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_PEI_HOB_POINTERS          Hob;
 | 
						|
  UINTN                         MinimalNeededSize;
 | 
						|
  EFI_PHYSICAL_ADDRESS          FreeMemoryBottom;
 | 
						|
  EFI_PHYSICAL_ADDRESS          FreeMemoryTop;
 | 
						|
  EFI_PHYSICAL_ADDRESS          MemoryBottom;
 | 
						|
  EFI_PHYSICAL_ADDRESS          MemoryTop;
 | 
						|
  EFI_HOB_RESOURCE_DESCRIPTOR   *PhitResourceHob;
 | 
						|
  EFI_HOB_RESOURCE_DESCRIPTOR   *ResourceHob;
 | 
						|
  UNIVERSAL_PAYLOAD_EXTRA_DATA  *ExtraData;
 | 
						|
  UINT8                         *GuidHob;
 | 
						|
  EFI_HOB_FIRMWARE_VOLUME       *FvHob;
 | 
						|
  UNIVERSAL_PAYLOAD_ACPI_TABLE  *AcpiTable;
 | 
						|
  ACPI_BOARD_INFO               *AcpiBoardInfo;
 | 
						|
  EFI_HOB_HANDOFF_INFO_TABLE    *HobInfo;
 | 
						|
  UINT8                         Idx;
 | 
						|
 | 
						|
  Hob.Raw           = (UINT8 *)BootloaderParameter;
 | 
						|
  MinimalNeededSize = FixedPcdGet32 (PcdSystemMemoryUefiRegionSize);
 | 
						|
 | 
						|
  ASSERT (Hob.Raw != NULL);
 | 
						|
  ASSERT ((UINTN)Hob.HandoffInformationTable->EfiFreeMemoryTop == Hob.HandoffInformationTable->EfiFreeMemoryTop);
 | 
						|
  ASSERT ((UINTN)Hob.HandoffInformationTable->EfiMemoryTop == Hob.HandoffInformationTable->EfiMemoryTop);
 | 
						|
  ASSERT ((UINTN)Hob.HandoffInformationTable->EfiFreeMemoryBottom == Hob.HandoffInformationTable->EfiFreeMemoryBottom);
 | 
						|
  ASSERT ((UINTN)Hob.HandoffInformationTable->EfiMemoryBottom == Hob.HandoffInformationTable->EfiMemoryBottom);
 | 
						|
 | 
						|
  //
 | 
						|
  // Try to find Resource Descriptor HOB that contains Hob range EfiMemoryBottom..EfiMemoryTop
 | 
						|
  //
 | 
						|
  PhitResourceHob = FindResourceDescriptorByRange (Hob.Raw, Hob.HandoffInformationTable->EfiMemoryBottom, Hob.HandoffInformationTable->EfiMemoryTop);
 | 
						|
  if (PhitResourceHob == NULL) {
 | 
						|
    //
 | 
						|
    // Boot loader's Phit Hob is not in an available Resource Descriptor, find another Resource Descriptor for new Phit Hob
 | 
						|
    //
 | 
						|
    ResourceHob = FindAnotherHighestBelow4GResourceDescriptor (Hob.Raw, MinimalNeededSize, NULL);
 | 
						|
    if (ResourceHob == NULL) {
 | 
						|
      return EFI_NOT_FOUND;
 | 
						|
    }
 | 
						|
 | 
						|
    MemoryBottom     = ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MinimalNeededSize;
 | 
						|
    FreeMemoryBottom = MemoryBottom;
 | 
						|
    FreeMemoryTop    = ResourceHob->PhysicalStart + ResourceHob->ResourceLength;
 | 
						|
    MemoryTop        = FreeMemoryTop;
 | 
						|
  } else if (PhitResourceHob->PhysicalStart + PhitResourceHob->ResourceLength - Hob.HandoffInformationTable->EfiMemoryTop >= MinimalNeededSize) {
 | 
						|
    //
 | 
						|
    // New availiable Memory range in new hob is right above memory top in old hob.
 | 
						|
    //
 | 
						|
    MemoryBottom     = Hob.HandoffInformationTable->EfiFreeMemoryTop;
 | 
						|
    FreeMemoryBottom = Hob.HandoffInformationTable->EfiMemoryTop;
 | 
						|
    FreeMemoryTop    = FreeMemoryBottom + MinimalNeededSize;
 | 
						|
    MemoryTop        = FreeMemoryTop;
 | 
						|
  } else if (Hob.HandoffInformationTable->EfiMemoryBottom - PhitResourceHob->PhysicalStart >= MinimalNeededSize) {
 | 
						|
    //
 | 
						|
    // New availiable Memory range in new hob is right below memory bottom in old hob.
 | 
						|
    //
 | 
						|
    MemoryBottom     = Hob.HandoffInformationTable->EfiMemoryBottom - MinimalNeededSize;
 | 
						|
    FreeMemoryBottom = MemoryBottom;
 | 
						|
    FreeMemoryTop    = Hob.HandoffInformationTable->EfiMemoryBottom;
 | 
						|
    MemoryTop        = Hob.HandoffInformationTable->EfiMemoryTop;
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // In the Resource Descriptor HOB contains boot loader Hob, there is no enough free memory size for payload hob
 | 
						|
    // Find another Resource Descriptor Hob
 | 
						|
    //
 | 
						|
    ResourceHob = FindAnotherHighestBelow4GResourceDescriptor (Hob.Raw, MinimalNeededSize, PhitResourceHob);
 | 
						|
    if (ResourceHob == NULL) {
 | 
						|
      return EFI_NOT_FOUND;
 | 
						|
    }
 | 
						|
 | 
						|
    MemoryBottom     = ResourceHob->PhysicalStart + ResourceHob->ResourceLength - MinimalNeededSize;
 | 
						|
    FreeMemoryBottom = MemoryBottom;
 | 
						|
    FreeMemoryTop    = ResourceHob->PhysicalStart + ResourceHob->ResourceLength;
 | 
						|
    MemoryTop        = FreeMemoryTop;
 | 
						|
  }
 | 
						|
 | 
						|
  HobInfo           = HobConstructor ((VOID *)(UINTN)MemoryBottom, (VOID *)(UINTN)MemoryTop, (VOID *)(UINTN)FreeMemoryBottom, (VOID *)(UINTN)FreeMemoryTop);
 | 
						|
  HobInfo->BootMode = Hob.HandoffInformationTable->BootMode;
 | 
						|
  //
 | 
						|
  // From now on, mHobList will point to the new Hob range.
 | 
						|
  //
 | 
						|
 | 
						|
  //
 | 
						|
  // Create an empty FvHob for the DXE FV that contains DXE core.
 | 
						|
  //
 | 
						|
  BuildFvHob ((EFI_PHYSICAL_ADDRESS)0, 0);
 | 
						|
  //
 | 
						|
  // Since payload created new Hob, move all hobs except PHIT from boot loader hob list.
 | 
						|
  //
 | 
						|
  while (!END_OF_HOB_LIST (Hob)) {
 | 
						|
    if (IsHobNeed (Hob)) {
 | 
						|
      // Add this hob to payload HOB
 | 
						|
      AddNewHob (&Hob);
 | 
						|
    }
 | 
						|
 | 
						|
    Hob.Raw = GET_NEXT_HOB (Hob);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get DXE FV location
 | 
						|
  //
 | 
						|
  GuidHob = GetFirstGuidHob (&gUniversalPayloadExtraDataGuid);
 | 
						|
  ASSERT (GuidHob != NULL);
 | 
						|
  ExtraData = (UNIVERSAL_PAYLOAD_EXTRA_DATA *)GET_GUID_HOB_DATA (GuidHob);
 | 
						|
  DEBUG ((DEBUG_INFO, "Multiple Fv Count=%d\n", ExtraData->Count));
 | 
						|
  ASSERT (AsciiStrCmp (ExtraData->Entry[0].Identifier, "uefi_fv") == 0);
 | 
						|
 | 
						|
  *DxeFv = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)ExtraData->Entry[0].Base;
 | 
						|
  ASSERT ((*DxeFv)->FvLength == ExtraData->Entry[0].Size);
 | 
						|
  //
 | 
						|
  // support multiple FVs provided by UPL
 | 
						|
  //
 | 
						|
  for (Idx = 1; Idx < ExtraData->Count; Idx++) {
 | 
						|
    BuildFvHob (ExtraData->Entry[Idx].Base, ExtraData->Entry[Idx].Size);
 | 
						|
    DEBUG ((
 | 
						|
      DEBUG_INFO,
 | 
						|
      "UPL Multiple fv[%d], Base=0x%x, size=0x%x\n",
 | 
						|
      Idx,
 | 
						|
      ExtraData->Entry[Idx].Base,
 | 
						|
      ExtraData->Entry[Idx].Size
 | 
						|
      ));
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Create guid hob for acpi board information
 | 
						|
  //
 | 
						|
  GuidHob = GetFirstGuidHob (&gUniversalPayloadAcpiTableGuid);
 | 
						|
  if (GuidHob != NULL) {
 | 
						|
    AcpiTable = (UNIVERSAL_PAYLOAD_ACPI_TABLE *)GET_GUID_HOB_DATA (GuidHob);
 | 
						|
    GuidHob   = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid);
 | 
						|
    if (GuidHob == NULL) {
 | 
						|
      AcpiBoardInfo = BuildHobFromAcpi ((UINT64)AcpiTable->Rsdp);
 | 
						|
      ASSERT (AcpiBoardInfo != NULL);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Update DXE FV information to first fv hob in the hob list, which
 | 
						|
  // is the empty FvHob created before.
 | 
						|
  //
 | 
						|
  FvHob              = GetFirstHob (EFI_HOB_TYPE_FV);
 | 
						|
  FvHob->BaseAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)*DxeFv;
 | 
						|
  FvHob->Length      = (*DxeFv)->FvLength;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Entry point to the C language phase of UEFI payload.
 | 
						|
 | 
						|
  @param[in]   BootloaderParameter    The starting address of bootloader parameter block.
 | 
						|
 | 
						|
  @retval      It will not return if SUCCESS, and return error when passing bootloader parameter.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
_ModuleEntryPoint (
 | 
						|
  IN UINTN  BootloaderParameter
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                  Status;
 | 
						|
  PHYSICAL_ADDRESS            DxeCoreEntryPoint;
 | 
						|
  EFI_PEI_HOB_POINTERS        Hob;
 | 
						|
  EFI_FIRMWARE_VOLUME_HEADER  *DxeFv;
 | 
						|
 | 
						|
  mHobList = (VOID *)BootloaderParameter;
 | 
						|
  DxeFv    = NULL;
 | 
						|
  // Call constructor for all libraries
 | 
						|
  ProcessLibraryConstructorList ();
 | 
						|
 | 
						|
  DEBUG ((DEBUG_INFO, "Entering Universal Payload...\n"));
 | 
						|
  DEBUG ((DEBUG_INFO, "sizeof(UINTN) = 0x%x\n", sizeof (UINTN)));
 | 
						|
 | 
						|
  DEBUG_CODE (
 | 
						|
    //
 | 
						|
    // Dump the Hobs from boot loader
 | 
						|
    //
 | 
						|
    PrintHob (mHobList);
 | 
						|
    );
 | 
						|
 | 
						|
  // Initialize floating point operating environment to be compliant with UEFI spec.
 | 
						|
  InitializeFloatingPointUnits ();
 | 
						|
 | 
						|
  // Build HOB based on information from Bootloader
 | 
						|
  Status = BuildHobs (BootloaderParameter, &DxeFv);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  FixUpPcdDatabase (DxeFv);
 | 
						|
  Status = UniversalLoadDxeCore (DxeFv, &DxeCoreEntryPoint);
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
 | 
						|
  //
 | 
						|
  // Mask off all legacy 8259 interrupt sources
 | 
						|
  //
 | 
						|
  IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF);
 | 
						|
  IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF);
 | 
						|
 | 
						|
  Hob.HandoffInformationTable = (EFI_HOB_HANDOFF_INFO_TABLE *)GetFirstHob (EFI_HOB_TYPE_HANDOFF);
 | 
						|
  HandOffToDxeCore (DxeCoreEntryPoint, Hob);
 | 
						|
 | 
						|
  // Should not get here
 | 
						|
  CpuDeadLoop ();
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 |