summaryrefslogtreecommitdiffstats
path: root/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
diff options
context:
space:
mode:
Diffstat (limited to 'UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c')
-rw-r--r--UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c653
1 files changed, 653 insertions, 0 deletions
diff --git a/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
new file mode 100644
index 0000000000..d2e7df4fbe
--- /dev/null
+++ b/UefiPayloadPkg/UefiPayloadEntry/FitUniversalPayloadEntry.c
@@ -0,0 +1,653 @@
+/** @file
+ Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include "UefiPayloadEntry.h"
+#include <Library/FdtLib.h>
+#include <Guid/UniversalPayloadBase.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;
+
+CHAR8 *mLineBuffer = NULL;
+
+/**
+ Print all HOBs info from the HOB list.
+ @return The pointer to the HOB list.
+**/
+VOID
+PrintHob (
+ IN CONST VOID *HobStart
+ );
+
+/**
+ Find the first substring.
+ @param String Point to the string where to find the substring.
+ @param CharSet Point to the string to be found.
+**/
+UINTN
+EFIAPI
+AsciiStrSpn (
+ IN CHAR8 *String,
+ IN CHAR8 *CharSet
+ )
+{
+ UINTN Count;
+ CHAR8 *Str1;
+ CHAR8 *Str2;
+
+ Count = 0;
+
+ for (Str1 = String; *Str1 != L'\0'; Str1++) {
+ for (Str2 = CharSet; *Str2 != L'\0'; Str2++) {
+ if (*Str1 == *Str2) {
+ break;
+ }
+ }
+
+ if (*Str2 == L'\0') {
+ return Count;
+ }
+
+ Count++;
+ }
+
+ return Count;
+}
+
+/**
+ Searches a string for the first occurrence of a character contained in a
+ specified buffer.
+ @param String Point to the string where to find the substring.
+ @param CharSet Point to the string to be found.
+**/
+CHAR8 *
+EFIAPI
+AsciiStrBrk (
+ IN CHAR8 *String,
+ IN CHAR8 *CharSet
+ )
+{
+ CHAR8 *Str1;
+ CHAR8 *Str2;
+
+ for (Str1 = String; *Str1 != L'\0'; Str1++) {
+ for (Str2 = CharSet; *Str2 != L'\0'; Str2++) {
+ if (*Str1 == *Str2) {
+ return (CHAR8 *)Str1;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ Find the next token after one or more specified characters.
+ @param String Point to the string where to find the substring.
+ @param CharSet Point to the string to be found.
+**/
+CHAR8 *
+EFIAPI
+AsciiStrTokenLine (
+ IN CHAR8 *String OPTIONAL,
+ IN CHAR8 *CharSet
+ )
+{
+ CHAR8 *Begin;
+ CHAR8 *End;
+
+ Begin = (String == NULL) ? mLineBuffer : String;
+ if (Begin == NULL) {
+ return NULL;
+ }
+
+ Begin += AsciiStrSpn (Begin, CharSet);
+ if (*Begin == L'\0') {
+ mLineBuffer = NULL;
+ return NULL;
+ }
+
+ End = AsciiStrBrk (Begin, CharSet);
+ if ((End != NULL) && (*End != L'\0')) {
+ *End = L'\0';
+ End++;
+ }
+
+ mLineBuffer = End;
+ return Begin;
+}
+
+/**
+ 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);
+
+ if (NewHob.Header != NULL) {
+ 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 Fv HOBs based on information from bootloaders.
+ @param[out] DxeFv The pointer to the DXE FV in memory.
+ @retval EFI_SUCCESS If it completed successfully.
+ @retval EFI_NOT_FOUND If it failed to find node in fit image.
+ @retval Others If it failed to build required HOBs.
+**/
+EFI_STATUS
+BuildFitLoadablesFvHob (
+ OUT EFI_FIRMWARE_VOLUME_HEADER **DxeFv
+ )
+{
+ EFI_STATUS Status;
+ VOID *Fdt;
+ UINT8 *GuidHob;
+ UNIVERSAL_PAYLOAD_BASE *PayloadBase;
+ INT32 ConfigNode;
+ INT32 Config1Node;
+ INT32 ImageNode;
+ INT32 FvNode;
+ INT32 Depth;
+ CONST FDT_PROPERTY *PropertyPtr;
+ INT32 TempLen;
+ CONST CHAR8 *Fvname;
+ UINT32 DataOffset;
+ UINT32 DataSize;
+ UINT32 *Data32;
+
+ GuidHob = GetFirstGuidHob (&gUniversalPayloadBaseGuid);
+ if (GuidHob != NULL) {
+ PayloadBase = (UNIVERSAL_PAYLOAD_BASE *)GET_GUID_HOB_DATA (GuidHob);
+ Fdt = (VOID *)(UINTN)PayloadBase->Entry;
+ DEBUG ((DEBUG_INFO, "PayloadBase Entry = 0x%08x\n", PayloadBase->Entry));
+ }
+
+ Status = FdtCheckHeader (Fdt);
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ ConfigNode = FdtSubnodeOffsetNameLen (Fdt, 0, "configurations", (INT32)AsciiStrLen ("configurations"));
+ if (ConfigNode <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ Config1Node = FdtSubnodeOffsetNameLen (Fdt, ConfigNode, "conf-1", (INT32)AsciiStrLen ("conf-1"));
+ if (Config1Node <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ ImageNode = FdtSubnodeOffsetNameLen (Fdt, 0, "images", (INT32)AsciiStrLen ("images"));
+ if (ImageNode <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ FvNode = FdtSubnodeOffsetNameLen (Fdt, ImageNode, "tianocore", (INT32)AsciiStrLen ("tianocore"));
+ Depth = FdtNodeDepth (Fdt, FvNode);
+ FvNode = FdtNextNode (Fdt, FvNode, &Depth);
+ Fvname = FdtGetName (Fdt, FvNode, &TempLen);
+ while ((AsciiStrCmp ((Fvname + AsciiStrLen (Fvname) - 2), "fv") == 0)) {
+ if (FvNode <= 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ PropertyPtr = FdtGetProperty (Fdt, FvNode, "data-offset", &TempLen);
+ Data32 = (UINT32 *)(PropertyPtr->Data);
+ DataOffset = SwapBytes32 (*Data32);
+
+ PropertyPtr = FdtGetProperty (Fdt, FvNode, "data-size", &TempLen);
+ Data32 = (UINT32 *)(PropertyPtr->Data);
+ DataSize = SwapBytes32 (*Data32);
+
+ if (AsciiStrCmp (Fvname, "uefi-fv") == 0) {
+ *DxeFv = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)PayloadBase->Entry + (UINTN)DataOffset);
+ ASSERT ((*DxeFv)->FvLength == DataSize);
+ } else {
+ BuildFvHob (((UINTN)PayloadBase->Entry + (UINTN)DataOffset), DataSize);
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "UPL Multiple fv[%a], Base=0x%08x, size=0x%08x\n",
+ Fvname,
+ ((UINTN)PayloadBase->Entry + (UINTN)DataOffset),
+ DataSize
+ ));
+ Depth = FdtNodeDepth (Fdt, FvNode);
+ FvNode = FdtNextNode (Fdt, FvNode, &Depth);
+ Fvname = FdtGetName (Fdt, FvNode, &TempLen);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ 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;
+ UINT8 *GuidHob;
+ EFI_HOB_FIRMWARE_VOLUME *FvHob;
+ UNIVERSAL_PAYLOAD_ACPI_TABLE *AcpiTable;
+ ACPI_BOARD_INFO *AcpiBoardInfo;
+ EFI_HOB_HANDOFF_INFO_TABLE *HobInfo;
+
+ 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);
+ }
+
+ BuildFitLoadablesFvHob (DxeFv);
+
+ //
+ // 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;
+}