[PATCH 05/12] UefiPayloadPkg: Create separate Payload Entry for UniversalPayload


Zhiguang Liu
 

This patch create the UniversalPayload Entry based on the UefiPayload
Entry. It implements the logic to find a proper memory range to create the
new Hob and migrate the Hobs from Bootloader.
To make the change history clear, the logic to get the DxeCore will be in
the next patch.

Cc: Maurice Ma <maurice.ma@intel.com>
Cc: Guo Dong <guo.dong@intel.com>
Cc: Benjamin You <benjamin.you@intel.com>
Signed-off-by: Zhiguang Liu <zhiguang.liu@intel.com>
---
UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.c | 311 ++++++++++=
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf | 91 ++++++++++=
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=
++++++
2 files changed, 402 insertions(+)

diff --git a/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.c b/Uefi=
PayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.c
new file mode 100644
index 0000000000..66e87bcb9b
--- /dev/null
+++ b/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.c
@@ -0,0 +1,311 @@
+/** @file=0D
+=0D
+ Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>=0D
+ SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+=0D
+**/=0D
+=0D
+#include "UefiPayloadEntry.h"=0D
+=0D
+#define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT =
| \=0D
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED =
| \=0D
+ EFI_RESOURCE_ATTRIBUTE_TESTED =
| \=0D
+ EFI_RESOURCE_ATTRIBUTE_READ_PROTECT=
ED | \=0D
+ EFI_RESOURCE_ATTRIBUTE_WRITE_PROTEC=
TED | \=0D
+ EFI_RESOURCE_ATTRIBUTE_EXECUTION_PR=
OTECTED | \=0D
+ EFI_RESOURCE_ATTRIBUTE_READ_ONLY_PR=
OTECTED | \=0D
+ EFI_RESOURCE_ATTRIBUTE_16_BIT_IO =
| \=0D
+ EFI_RESOURCE_ATTRIBUTE_32_BIT_IO =
| \=0D
+ EFI_RESOURCE_ATTRIBUTE_64_BIT_IO =
| \=0D
+ EFI_RESOURCE_ATTRIBUTE_PERSISTENT =
)=0D
+=0D
+#define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT =
| \=0D
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED =
| \=0D
+ EFI_RESOURCE_ATTRIBUTE_TESTED =
)=0D
+=0D
+extern VOID *mHobList;=0D
+=0D
+/**=0D
+ Add HOB into HOB list=0D
+=0D
+ @param[in] Hob The HOB to be added into the HOB list.=0D
+**/=0D
+VOID=0D
+AddNewHob (=0D
+ IN EFI_PEI_HOB_POINTERS *Hob=0D
+ )=0D
+{=0D
+ EFI_PEI_HOB_POINTERS NewHob;=0D
+=0D
+ if (Hob->Raw =3D=3D NULL) {=0D
+ return;=0D
+ }=0D
+ NewHob.Header =3D CreateHob (Hob->Header->HobType, Hob->Header->HobLengt=
h);=0D
+=0D
+ if (NewHob.Header !=3D NULL) {=0D
+ CopyMem (NewHob.Header + 1, Hob->Header + 1, Hob->Header->HobLength - =
sizeof (EFI_HOB_GENERIC_HEADER));=0D
+ }=0D
+}=0D
+=0D
+/**=0D
+ Found the Resource Descriptor HOB that contains a range=0D
+=0D
+ @param[in] Base Memory start address=0D
+ @param[in] Top Memory Top.=0D
+=0D
+ @return The pointer to the Resource Descriptor HOB.=0D
+**/=0D
+EFI_HOB_RESOURCE_DESCRIPTOR *=0D
+FindResourceDescriptorByRange (=0D
+ VOID *HobList,=0D
+ EFI_PHYSICAL_ADDRESS Base,=0D
+ EFI_PHYSICAL_ADDRESS Top=0D
+ )=0D
+{=0D
+ EFI_PEI_HOB_POINTERS Hob;=0D
+ EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;=0D
+=0D
+ for (Hob.Raw =3D (UINT8 *) HobList; !END_OF_HOB_LIST(Hob); Hob.Raw =3D G=
ET_NEXT_HOB(Hob)) {=0D
+ //=0D
+ // Skip all HOBs except Resource Descriptor HOBs=0D
+ //=0D
+ if (GET_HOB_TYPE (Hob) !=3D EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {=0D
+ continue;=0D
+ }=0D
+=0D
+ //=0D
+ // Skip Resource Descriptor HOBs that do not describe tested system me=
mory=0D
+ //=0D
+ ResourceHob =3D Hob.ResourceDescriptor;=0D
+ if (ResourceHob->ResourceType !=3D EFI_RESOURCE_SYSTEM_MEMORY) {=0D
+ continue;=0D
+ }=0D
+ if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) !=3D TEST=
ED_MEMORY_ATTRIBUTES) {=0D
+ continue;=0D
+ }=0D
+=0D
+ //=0D
+ // Skip Resource Descriptor HOBs that do not contain the PHIT range Ef=
iFreeMemoryBottom..EfiFreeMemoryTop=0D
+ //=0D
+ if (Base < ResourceHob->PhysicalStart) {=0D
+ continue;=0D
+ }=0D
+ if (Top > (ResourceHob->PhysicalStart + ResourceHob->ResourceLength)) =
{=0D
+ continue;=0D
+ }=0D
+ return ResourceHob;=0D
+ }=0D
+ return NULL;=0D
+}=0D
+=0D
+/**=0D
+ Find the highest below 4G memory resource descriptor, except the input R=
esource Descriptor.=0D
+=0D
+ @param[in] HobList Hob start address=0D
+ @param[in] MinimalNeededSize Minimal needed size.=0D
+ @param[in] ExceptResourceHob Ignore this Resource Descriptor.=0D
+=0D
+ @return The pointer to the Resource Descriptor HOB.=0D
+**/=0D
+EFI_HOB_RESOURCE_DESCRIPTOR *=0D
+FindAnotherHighestBelow4GResourceDescriptor (=0D
+ IN VOID *HobList,=0D
+ IN UINTN MinimalNeededSize,=0D
+ IN EFI_HOB_RESOURCE_DESCRIPTOR *ExceptResourceHob=0D
+ )=0D
+{=0D
+ EFI_PEI_HOB_POINTERS Hob;=0D
+ EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;=0D
+ EFI_HOB_RESOURCE_DESCRIPTOR *ReturnResourceHob;=0D
+ ReturnResourceHob =3D NULL;=0D
+=0D
+ for (Hob.Raw =3D (UINT8 *) HobList; !END_OF_HOB_LIST(Hob); Hob.Raw =3D G=
ET_NEXT_HOB(Hob)) {=0D
+ //=0D
+ // Skip all HOBs except Resource Descriptor HOBs=0D
+ //=0D
+ if (GET_HOB_TYPE (Hob) !=3D EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {=0D
+ continue;=0D
+ }=0D
+=0D
+ //=0D
+ // Skip Resource Descriptor HOBs that do not describe tested system me=
mory=0D
+ //=0D
+ ResourceHob =3D Hob.ResourceDescriptor;=0D
+ if (ResourceHob->ResourceType !=3D EFI_RESOURCE_SYSTEM_MEMORY) {=0D
+ continue;=0D
+ }=0D
+ if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) !=3D TEST=
ED_MEMORY_ATTRIBUTES) {=0D
+ continue;=0D
+ }=0D
+=0D
+ //=0D
+ // Skip if the Resource Descriptor HOB equals to ExceptResourceHob=0D
+ //=0D
+ if (ResourceHob =3D=3D ExceptResourceHob) {=0D
+ continue;=0D
+ }=0D
+ //=0D
+ // Skip Resource Descriptor HOBs that are beyond 4G=0D
+ //=0D
+ if ((ResourceHob->PhysicalStart + ResourceHob->ResourceLength) > BASE_=
4GB) {=0D
+ continue;=0D
+ }=0D
+ //=0D
+ // Skip Resource Descriptor HOBs that are too small=0D
+ //=0D
+ if (ResourceHob->ResourceLength < MinimalNeededSize) {=0D
+ continue;=0D
+ }=0D
+=0D
+ //=0D
+ // Return the topest Resource Descriptor=0D
+ //=0D
+ if (ReturnResourceHob =3D=3D NULL) {=0D
+ ReturnResourceHob =3D ResourceHob;=0D
+ } else {=0D
+ if (ReturnResourceHob->PhysicalStart < ResourceHob->PhysicalStart) {=
=0D
+ ReturnResourceHob =3D ResourceHob;=0D
+ }=0D
+ }=0D
+ }=0D
+ return ReturnResourceHob;=0D
+}=0D
+=0D
+/**=0D
+ It will build HOBs based on information from bootloaders.=0D
+=0D
+ @retval EFI_SUCCESS If it completed successfully.=0D
+ @retval Others If it failed to build required HOBs.=0D
+**/=0D
+EFI_STATUS=0D
+BuildHobs (=0D
+ IN UINTN BootloaderParameter=0D
+ )=0D
+{=0D
+ EFI_PEI_HOB_POINTERS Hob;=0D
+ UINTN MinimalNeededSize;=0D
+ EFI_PHYSICAL_ADDRESS FreeMemoryBottom;=0D
+ EFI_PHYSICAL_ADDRESS FreeMemoryTop;=0D
+ EFI_PHYSICAL_ADDRESS MemoryBottom;=0D
+ EFI_PHYSICAL_ADDRESS MemoryTop;=0D
+ EFI_HOB_RESOURCE_DESCRIPTOR *PhitResourceHob;=0D
+ EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;=0D
+=0D
+ Hob.Raw =3D (UINT8 *) BootloaderParameter;=0D
+ MinimalNeededSize =3D FixedPcdGet32 (PcdSystemMemoryUefiRegionSize);=0D
+=0D
+ ASSERT (Hob.Raw !=3D NULL);=0D
+ ASSERT ((UINTN) Hob.HandoffInformationTable->EfiFreeMemoryTop =3D=3D Hob=
.HandoffInformationTable->EfiFreeMemoryTop);=0D
+ ASSERT ((UINTN) Hob.HandoffInformationTable->EfiMemoryTop =3D=3D Hob.Han=
doffInformationTable->EfiMemoryTop);=0D
+ ASSERT ((UINTN) Hob.HandoffInformationTable->EfiFreeMemoryBottom =3D=3D =
Hob.HandoffInformationTable->EfiFreeMemoryBottom);=0D
+ ASSERT ((UINTN) Hob.HandoffInformationTable->EfiMemoryBottom =3D=3D Hob.=
HandoffInformationTable->EfiMemoryBottom);=0D
+=0D
+=0D
+ //=0D
+ // Try to find Resource Descriptor HOB that contains Hob range EfiMemory=
Bottom..EfiMemoryTop=0D
+ //=0D
+ PhitResourceHob =3D FindResourceDescriptorByRange(Hob.Raw, Hob.HandoffIn=
formationTable->EfiMemoryBottom, Hob.HandoffInformationTable->EfiMemoryTop)=
;=0D
+ if (PhitResourceHob =3D=3D NULL) {=0D
+ //=0D
+ // Boot loader's Phit Hob is not in an available Resource Descriptor, =
find another Resource Descriptor for new Phit Hob=0D
+ //=0D
+ ResourceHob =3D FindAnotherHighestBelow4GResourceDescriptor(Hob.Raw, M=
inimalNeededSize, NULL);=0D
+ if (ResourceHob =3D=3D NULL) {=0D
+ return EFI_NOT_FOUND;=0D
+ }=0D
+=0D
+ MemoryBottom =3D ResourceHob->PhysicalStart + ResourceHob->Resourc=
eLength - MinimalNeededSize;=0D
+ FreeMemoryBottom =3D MemoryBottom;=0D
+ FreeMemoryTop =3D ResourceHob->PhysicalStart + ResourceHob->Resourc=
eLength;=0D
+ MemoryTop =3D FreeMemoryTop;=0D
+ } else if (PhitResourceHob->PhysicalStart + PhitResourceHob->ResourceLen=
gth - Hob.HandoffInformationTable->EfiMemoryTop >=3D MinimalNeededSize) {=0D
+ //=0D
+ // New availiable Memory range in new hob is right above memory top in=
old hob.=0D
+ //=0D
+ MemoryBottom =3D Hob.HandoffInformationTable->EfiFreeMemoryTop;=0D
+ FreeMemoryBottom =3D Hob.HandoffInformationTable->EfiMemoryTop;=0D
+ FreeMemoryTop =3D FreeMemoryBottom + MinimalNeededSize;=0D
+ MemoryTop =3D FreeMemoryTop;=0D
+ } else if (Hob.HandoffInformationTable->EfiMemoryBottom - PhitResourceHo=
b->PhysicalStart >=3D MinimalNeededSize) {=0D
+ //=0D
+ // New availiable Memory range in new hob is right below memory bottom=
in old hob.=0D
+ //=0D
+ MemoryBottom =3D Hob.HandoffInformationTable->EfiMemoryBottom - Mi=
nimalNeededSize;=0D
+ FreeMemoryBottom =3D MemoryBottom;=0D
+ FreeMemoryTop =3D Hob.HandoffInformationTable->EfiMemoryBottom;=0D
+ MemoryTop =3D Hob.HandoffInformationTable->EfiMemoryTop;=0D
+ } else {=0D
+ //=0D
+ // In the Resource Descriptor HOB contains boot loader Hob, there is n=
o enough free memory size for payload hob=0D
+ // Find another Resource Descriptor Hob=0D
+ //=0D
+ ResourceHob =3D FindAnotherHighestBelow4GResourceDescriptor(Hob.Raw, M=
inimalNeededSize, PhitResourceHob);=0D
+ if (ResourceHob =3D=3D NULL) {=0D
+ return EFI_NOT_FOUND;=0D
+ }=0D
+=0D
+ MemoryBottom =3D ResourceHob->PhysicalStart + ResourceHob->Resourc=
eLength - MinimalNeededSize;=0D
+ FreeMemoryBottom =3D MemoryBottom;=0D
+ FreeMemoryTop =3D ResourceHob->PhysicalStart + ResourceHob->Resourc=
eLength;=0D
+ MemoryTop =3D FreeMemoryTop;=0D
+ }=0D
+ HobConstructor ((VOID *) (UINTN) MemoryBottom, (VOID *) (UINTN) MemoryTo=
p, (VOID *) (UINTN) FreeMemoryBottom, (VOID *) (UINTN) FreeMemoryTop);=0D
+ //=0D
+ // From now on, mHobList will point to the new Hob range.=0D
+ //=0D
+=0D
+ //=0D
+ // Since payload created new Hob, move all hobs except PHIT from boot lo=
ader hob list.=0D
+ //=0D
+ while (!END_OF_HOB_LIST (Hob)) {=0D
+ if (Hob.Header->HobType !=3D EFI_HOB_TYPE_HANDOFF) {=0D
+ // Add this hob to payload HOB=0D
+ AddNewHob (&Hob);=0D
+ }=0D
+ Hob.Raw =3D GET_NEXT_HOB (Hob);=0D
+ }=0D
+=0D
+ return EFI_SUCCESS;=0D
+}=0D
+=0D
+/**=0D
+ Entry point to the C language phase of UEFI payload.=0D
+=0D
+ @retval It will not return if SUCCESS, and return error when passin=
g bootloader parameter.=0D
+**/=0D
+EFI_STATUS=0D
+EFIAPI=0D
+_ModuleEntryPoint (=0D
+ IN UINTN BootloaderParameter=0D
+ )=0D
+{=0D
+ EFI_STATUS Status;=0D
+ EFI_HOB_HANDOFF_INFO_TABLE *HandoffHobTable;=0D
+ EFI_PEI_HOB_POINTERS Hob;=0D
+=0D
+ mHobList =3D (VOID *) BootloaderParameter;=0D
+ // Call constructor for all libraries=0D
+ ProcessLibraryConstructorList ();=0D
+=0D
+ DEBUG ((DEBUG_INFO, "Entering Universal Payload...\n"));=0D
+ DEBUG ((DEBUG_INFO, "sizeof(UINTN) =3D 0x%x\n", sizeof(UINTN)));=0D
+=0D
+ // Initialize floating point operating environment to be compliant with =
UEFI spec.=0D
+ InitializeFloatingPointUnits ();=0D
+=0D
+ // Build HOB based on information from Bootloader=0D
+ Status =3D BuildHobs (BootloaderParameter);=0D
+=0D
+ //=0D
+ // Mask off all legacy 8259 interrupt sources=0D
+ //=0D
+ IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF);=0D
+ IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF);=0D
+=0D
+ HandoffHobTable =3D (EFI_HOB_HANDOFF_INFO_TABLE *) GetFirstHob(EFI_HOB_T=
YPE_HANDOFF);=0D
+ Hob.HandoffInformationTable =3D HandoffHobTable;=0D
+=0D
+ // Should not get here=0D
+ CpuDeadLoop ();=0D
+ return EFI_SUCCESS;=0D
+}=0D
diff --git a/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf b/Ue=
fiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
new file mode 100644
index 0000000000..58ff87d969
--- /dev/null
+++ b/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
@@ -0,0 +1,91 @@
+## @file=0D
+# This is the first module for UEFI payload.=0D
+#=0D
+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>=0D
+#=0D
+# SPDX-License-Identifier: BSD-2-Clause-Patent=0D
+#=0D
+##=0D
+=0D
+[Defines]=0D
+ INF_VERSION =3D 0x00010005=0D
+ BASE_NAME =3D UniversalPayloadEntry=0D
+ FILE_GUID =3D D4F0F269-1209-4A66-8039-C4D5A700EA4E=
=0D
+ MODULE_TYPE =3D SEC=0D
+ VERSION_STRING =3D 1.0=0D
+=0D
+#=0D
+# The following information is for reference only and not required by the =
build tools.=0D
+#=0D
+# VALID_ARCHITECTURES =3D IA32 X64=0D
+#=0D
+=0D
+[Sources]=0D
+ UniversalPayloadEntry.c=0D
+ LoadDxeCore.c=0D
+ MemoryAllocation.c=0D
+=0D
+[Sources.Ia32]=0D
+ X64/VirtualMemory.h=0D
+ X64/VirtualMemory.c=0D
+ Ia32/DxeLoadFunc.c=0D
+ Ia32/IdtVectorAsm.nasm=0D
+=0D
+[Sources.X64]=0D
+ X64/VirtualMemory.h=0D
+ X64/VirtualMemory.c=0D
+ X64/DxeLoadFunc.c=0D
+=0D
+[Packages]=0D
+ MdePkg/MdePkg.dec=0D
+ MdeModulePkg/MdeModulePkg.dec=0D
+ UefiCpuPkg/UefiCpuPkg.dec=0D
+ UefiPayloadPkg/UefiPayloadPkg.dec=0D
+=0D
+[LibraryClasses]=0D
+ BaseMemoryLib=0D
+ DebugLib=0D
+ BaseLib=0D
+ SerialPortLib=0D
+ IoLib=0D
+ HobLib=0D
+ PeCoffLib=0D
+ UefiCpuLib=0D
+=0D
+[Guids]=0D
+ gEfiMemoryTypeInformationGuid=0D
+ gEfiFirmwareFileSystem2Guid=0D
+ gUefiSystemTableInfoGuid=0D
+ gEfiGraphicsInfoHobGuid=0D
+ gEfiGraphicsDeviceInfoHobGuid=0D
+ gUefiAcpiBoardInfoGuid=0D
+ gEfiSmbiosTableGuid=0D
+ gEfiAcpiTableGuid=0D
+ gUefiSerialPortInfoGuid=0D
+=0D
+[FeaturePcd.IA32]=0D
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ## CONSUME=
S=0D
+=0D
+[FeaturePcd.X64]=0D
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplBuildPageTables ## CONSUME=
S=0D
+=0D
+=0D
+[Pcd.IA32,Pcd.X64]=0D
+ gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ##=
SOMETIMES_CONSUMES=0D
+ gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask ##=
CONSUMES=0D
+ gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask ##=
CONSUMES=0D
+ gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask ##=
CONSUMES=0D
+ gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ##=
CONSUMES=0D
+ gEfiMdeModulePkgTokenSpaceGuid.PcdUse5LevelPageTable ##=
SOMETIMES_CONSUMES=0D
+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ##=
CONSUMES=0D
+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize ##=
CONSUMES=0D
+=0D
+ gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase=0D
+ gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize=0D
+ gUefiPayloadPkgTokenSpaceGuid.PcdPayloadStackTop=0D
+ gUefiPayloadPkgTokenSpaceGuid.PcdSystemMemoryUefiRegionSize=0D
+=0D
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ## SOMETIM=
ES_CONSUMES=0D
+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy ## SOMETIM=
ES_CONSUMES=0D
+ gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy ## SOMETIM=
ES_CONSUMES=0D
+=0D
--=20
2.16.2.windows.1


Guo Dong
 

Reviewed-by: Guo Dong <guo.dong@intel.com>

-----Original Message-----
From: Liu, Zhiguang <zhiguang.liu@intel.com>
Sent: Sunday, June 20, 2021 8:47 AM
To: devel@edk2.groups.io
Cc: Ma, Maurice <maurice.ma@intel.com>; Dong, Guo
<guo.dong@intel.com>; You, Benjamin <benjamin.you@intel.com>
Subject: [PATCH 05/12] UefiPayloadPkg: Create separate Payload Entry for
UniversalPayload

This patch create the UniversalPayload Entry based on the UefiPayload
Entry. It implements the logic to find a proper memory range to create the
new Hob and migrate the Hobs from Bootloader.
To make the change history clear, the logic to get the DxeCore will be in
the next patch.

Cc: Maurice Ma <maurice.ma@intel.com>
Cc: Guo Dong <guo.dong@intel.com>
Cc: Benjamin You <benjamin.you@intel.com>
Signed-off-by: Zhiguang Liu <zhiguang.liu@intel.com>
---
UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.c | 311
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++
UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf | 91
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++
2 files changed, 402 insertions(+)

diff --git a/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.c
b/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.c
new file mode 100644
index 0000000000..66e87bcb9b
--- /dev/null
+++ b/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.c
@@ -0,0 +1,311 @@
+/** @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;

+

+/**

+ 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

+

+ @param[in] Base Memory start address

+ @param[in] Top Memory Top.

+

+ @return The pointer to the Resource Descriptor HOB.

+**/

+EFI_HOB_RESOURCE_DESCRIPTOR *

+FindResourceDescriptorByRange (

+ VOID *HobList,

+ EFI_PHYSICAL_ADDRESS Base,

+ 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.

+

+ @return 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;

+}

+

+/**

+ It will build HOBs based on information from bootloaders.

+

+ @retval EFI_SUCCESS If it completed successfully.

+ @retval Others If it failed to build required HOBs.

+**/

+EFI_STATUS

+BuildHobs (

+ IN UINTN BootloaderParameter

+ )

+{

+ 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;

+

+ 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;

+ }

+ HobConstructor ((VOID *) (UINTN) MemoryBottom, (VOID *) (UINTN)
MemoryTop, (VOID *) (UINTN) FreeMemoryBottom, (VOID *) (UINTN)
FreeMemoryTop);

+ //

+ // From now on, mHobList will point to the new Hob range.

+ //

+

+ //

+ // Since payload created new Hob, move all hobs except PHIT from boot
loader hob list.

+ //

+ while (!END_OF_HOB_LIST (Hob)) {

+ if (Hob.Header->HobType != EFI_HOB_TYPE_HANDOFF) {

+ // Add this hob to payload HOB

+ AddNewHob (&Hob);

+ }

+ Hob.Raw = GET_NEXT_HOB (Hob);

+ }

+

+ return EFI_SUCCESS;

+}

+

+/**

+ Entry point to the C language phase of UEFI payload.

+

+ @retval It will not return if SUCCESS, and return error when passing
bootloader parameter.

+**/

+EFI_STATUS

+EFIAPI

+_ModuleEntryPoint (

+ IN UINTN BootloaderParameter

+ )

+{

+ EFI_STATUS Status;

+ EFI_HOB_HANDOFF_INFO_TABLE *HandoffHobTable;

+ EFI_PEI_HOB_POINTERS Hob;

+

+ mHobList = (VOID *) BootloaderParameter;

+ // Call constructor for all libraries

+ ProcessLibraryConstructorList ();

+

+ DEBUG ((DEBUG_INFO, "Entering Universal Payload...\n"));

+ DEBUG ((DEBUG_INFO, "sizeof(UINTN) = 0x%x\n", sizeof(UINTN)));

+

+ // Initialize floating point operating environment to be compliant with UEFI
spec.

+ InitializeFloatingPointUnits ();

+

+ // Build HOB based on information from Bootloader

+ Status = BuildHobs (BootloaderParameter);

+

+ //

+ // Mask off all legacy 8259 interrupt sources

+ //

+ IoWrite8 (LEGACY_8259_MASK_REGISTER_MASTER, 0xFF);

+ IoWrite8 (LEGACY_8259_MASK_REGISTER_SLAVE, 0xFF);

+

+ HandoffHobTable = (EFI_HOB_HANDOFF_INFO_TABLE *)
GetFirstHob(EFI_HOB_TYPE_HANDOFF);

+ Hob.HandoffInformationTable = HandoffHobTable;

+

+ // Should not get here

+ CpuDeadLoop ();

+ return EFI_SUCCESS;

+}

diff --git a/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
b/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
new file mode 100644
index 0000000000..58ff87d969
--- /dev/null
+++ b/UefiPayloadPkg/UefiPayloadEntry/UniversalPayloadEntry.inf
@@ -0,0 +1,91 @@
+## @file

+# This is the first module for UEFI payload.

+#

+# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR>

+#

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

+

+[Defines]

+ INF_VERSION = 0x00010005

+ BASE_NAME = UniversalPayloadEntry

+ FILE_GUID = D4F0F269-1209-4A66-8039-C4D5A700EA4E

+ MODULE_TYPE = SEC

+ VERSION_STRING = 1.0

+

+#

+# The following information is for reference only and not required by the
build tools.

+#

+# VALID_ARCHITECTURES = IA32 X64

+#

+

+[Sources]

+ UniversalPayloadEntry.c

+ LoadDxeCore.c

+ MemoryAllocation.c

+

+[Sources.Ia32]

+ X64/VirtualMemory.h

+ X64/VirtualMemory.c

+ Ia32/DxeLoadFunc.c

+ Ia32/IdtVectorAsm.nasm

+

+[Sources.X64]

+ X64/VirtualMemory.h

+ X64/VirtualMemory.c

+ X64/DxeLoadFunc.c

+

+[Packages]

+ MdePkg/MdePkg.dec

+ MdeModulePkg/MdeModulePkg.dec

+ UefiCpuPkg/UefiCpuPkg.dec

+ UefiPayloadPkg/UefiPayloadPkg.dec

+

+[LibraryClasses]

+ BaseMemoryLib

+ DebugLib

+ BaseLib

+ SerialPortLib

+ IoLib

+ HobLib

+ PeCoffLib

+ UefiCpuLib

+

+[Guids]

+ gEfiMemoryTypeInformationGuid

+ gEfiFirmwareFileSystem2Guid

+ gUefiSystemTableInfoGuid

+ gEfiGraphicsInfoHobGuid

+ gEfiGraphicsDeviceInfoHobGuid

+ gUefiAcpiBoardInfoGuid

+ gEfiSmbiosTableGuid

+ gEfiAcpiTableGuid

+ gUefiSerialPortInfoGuid

+

+[FeaturePcd.IA32]

+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplSwitchToLongMode ##
CONSUMES

+

+[FeaturePcd.X64]

+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeIplBuildPageTables ##
CONSUMES

+

+

+[Pcd.IA32,Pcd.X64]

+ gEfiMdeModulePkgTokenSpaceGuid.PcdUse1GPageTable ##
SOMETIMES_CONSUMES

+
gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrM
ask ## CONSUMES

+
gEfiMdeModulePkgTokenSpaceGuid.PcdNullPointerDetectionPropertyMask
## CONSUMES

+ gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask
## CONSUMES

+ gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ##
CONSUMES

+ gEfiMdeModulePkgTokenSpaceGuid.PcdUse5LevelPageTable ##
SOMETIMES_CONSUMES

+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase ##
CONSUMES

+ gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize ##
CONSUMES

+

+ gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemBase

+ gUefiPayloadPkgTokenSpaceGuid.PcdPayloadFdMemSize

+ gUefiPayloadPkgTokenSpaceGuid.PcdPayloadStackTop

+ gUefiPayloadPkgTokenSpaceGuid.PcdSystemMemoryUefiRegionSize

+

+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack ##
SOMETIMES_CONSUMES

+ gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy
## SOMETIMES_CONSUMES

+ gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy ##
SOMETIMES_CONSUMES

+

--
2.16.2.windows.1