public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Zhiguang Liu" <zhiguang.liu@intel.com>
To: devel@edk2.groups.io
Cc: Maurice Ma <maurice.ma@intel.com>, Guo Dong <guo.dong@intel.com>,
	Benjamin You <benjamin.you@intel.com>
Subject: [Patch V2 05/12] UefiPayloadPkg: Create separate Payload Entry for UniversalPayload
Date: Wed, 23 Jun 2021 10:52:28 +0800	[thread overview]
Message-ID: <20210623025235.3311-6-zhiguang.liu@intel.com> (raw)
In-Reply-To: <20210623025235.3311-1-zhiguang.liu@intel.com>

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>
Reviewed-by: Guo Dong <guo.dong@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.PcdPteMemoryEncryptionAddressOrMask    ## 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.30.0.windows.2


  parent reply	other threads:[~2021-06-23  2:52 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-23  2:52 [Patch V2 00/12] Enable Universal Payload in UefiPayloadPkg Zhiguang Liu
2021-06-23  2:52 ` [Patch V2 01/12] UefiPayloadPkg: Add HobLib for UniversalPayload Zhiguang Liu
2021-06-23 23:45   ` Guo Dong
2021-06-23  2:52 ` [Patch V2 02/12] MdeModulePkg: Add new structure for the Universal Payload Serial Port Info Zhiguang Liu
2021-06-23  2:52 ` [Patch V2 03/12] UefiPayloadPkg: Add a separate PlatformHookLib for Universal Payload Zhiguang Liu
2021-06-23  2:52 ` [Patch V2 04/12] UefiPayloadPkg: Update the function definition of HobConstructor Zhiguang Liu
2021-06-23  2:52 ` Zhiguang Liu [this message]
2021-06-23  2:52 ` [Patch V2 06/12] UefiPayloadPkg: Get and enter DxeCore for Universal Payload Zhiguang Liu
2021-06-23  2:52 ` [Patch V2 07/12] UefiPayloadPkg: Fix up UPL Pcd database Zhiguang Liu
2021-06-23 23:45   ` Guo Dong
2021-06-23  2:52 ` [Patch V2 08/12] UefiPayloadPkg: Include UniversalPayLoad modules in UefiPayloadPkg.dsc Zhiguang Liu
2021-06-23  2:52 ` [Patch V2 09/12] UefiPayloadPkg: Remove assert when reserve MMIO/IO resource for devices Zhiguang Liu
2021-06-23  2:52 ` [Patch V2 10/12] UefiPayloadPkg: Add macro to disable some drivers Zhiguang Liu
2021-06-23 23:48   ` Guo Dong
2021-06-23  2:52 ` [Patch V2 11/12] UefiPayloadPkg: Add PcdInstallAcpiSdtProtocol feature in UefiPayloadPkg Zhiguang Liu
2021-06-23  2:52 ` [Patch V2 12/12] UefiPayloadPkg: Add PcdResetOnMemoryTypeInformationChange " Zhiguang Liu
     [not found] ` <168B167444E9F647.3239@groups.io>
2021-06-23  8:50   ` [edk2-devel] [Patch V2 10/12] UefiPayloadPkg: Add macro to disable some drivers Zhiguang Liu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210623025235.3311-6-zhiguang.liu@intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox