Add SEC code for LoongArch virtual machine.

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4584

Cc: Ard Biesheuvel <ardb+tianoc...@kernel.org>
Cc: Jiewen Yao <jiewen....@intel.com>
Cc: Jordan Justen <jordan.l.jus...@intel.com>
Cc: Gerd Hoffmann <kra...@redhat.com>
Signed-off-by: Chao Li <lic...@loongson.cn>
Co-authored-by: Xianglai Li <lixiang...@loongson.cn>
Co-authored-by: Bibo Mao <maob...@loongson.cn>
---
 OvmfPkg/LoongArchVirt/Sec/LoongArch64/Start.S | 183 +++++++
 OvmfPkg/LoongArchVirt/Sec/SecMain.c           | 507 ++++++++++++++++++
 OvmfPkg/LoongArchVirt/Sec/SecMain.inf         |  53 ++
 3 files changed, 743 insertions(+)
 create mode 100644 OvmfPkg/LoongArchVirt/Sec/LoongArch64/Start.S
 create mode 100644 OvmfPkg/LoongArchVirt/Sec/SecMain.c
 create mode 100644 OvmfPkg/LoongArchVirt/Sec/SecMain.inf

diff --git a/OvmfPkg/LoongArchVirt/Sec/LoongArch64/Start.S 
b/OvmfPkg/LoongArchVirt/Sec/LoongArch64/Start.S
new file mode 100644
index 0000000000..145f8ffc59
--- /dev/null
+++ b/OvmfPkg/LoongArchVirt/Sec/LoongArch64/Start.S
@@ -0,0 +1,183 @@
+#------------------------------------------------------------------------------
+#
+# Start for Loongson LoongArch processor
+#
+# Copyright (c) 2024 Loongson Technology Corporation Limited. All rights 
reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#  @par Glossary:
+#    - CSR - CPU Status Register
+#    - EBASE - Exception Base Address
+#------------------------------------------------------------------------------
+#ifndef __ASSEMBLY__
+#define __ASSEMBLY__
+#endif
+
+#include <Library/BaseMemoryLib.h>
+#include <Register/LoongArch64/Csr.h>
+#include <Protocol/DebugSupport.h>
+
+#define BOOTCORE_ID 0
+
+//
+// For coding convenience, define the maximum valid
+// LoongArch exception.
+// Since UEFI V2.11, it will be present in DebugSupport.h.
+//
+#define MAX_LOONGARCH_EXCEPTION  64
+
+ASM_GLOBAL ASM_PFX(_ModuleEntryPoint)
+ASM_PFX(_ModuleEntryPoint):
+  /* Disable interrupt */
+  li.d     $t0, (1 << 2)
+  csrxchg  $zero, $t0, LOONGARCH_CSR_CRMD
+
+  /* Read physical cpu number id */
+  bl       GetApicId
+  li.d     $t0, BOOTCORE_ID  //0
+  bne      $a0, $t0, SlaveMain
+
+  /* Configure BSP reset ebase */
+  li.d     $a0, FixedPcdGet64(PcdCpuExceptionVectorBaseAddress)
+  bl       SetExceptionBaseAddress
+  move     $t1, $a0
+
+  /* Set BSP stack */
+  li.d     $t0, FixedPcdGet64(PcdOvmfSecPeiTempRamBase) + 
FixedPcdGet32(PcdOvmfSecPeiTempRamSize)  # stack base
+  move     $sp, $t0
+  addi.d   $sp, $sp, -0x8
+
+  /* Construct SEC and PEI step exception environment */
+  la.pcrel $a1, ExceptionEntryStart
+  la.pcrel $t0, ExceptionEntryEnd
+  sub.d    $a2, $t0, $a1
+  li.w     $t0, (MAX_LOONGARCH_EXCEPTION +  MAX_LOONGARCH_INTERRUPT) * 512
+  bgeu     $a2, $t0, DeadLoop
+  move     $a0, $t1
+  bl       CopyMem
+
+CallEntry:
+  /* Call C function make sure parameter true */
+  li.d     $a0, FixedPcdGet64(PcdOvmfFdBaseAddress) # FW base
+  addi.d   $a1, $sp, 0x8
+  bl       SecCoreStartupWithStack
+# End of _ModuleEntryPoint
+
+ASM_PFX(ClearMailBox):
+  /* Clear mailbox */
+  li.d      $t1, LOONGARCH_IOCSR_MBUF3
+  iocsrwr.d $zero, $t1
+  li.d      $t1, LOONGARCH_IOCSR_MBUF2
+  iocsrwr.d $zero, $t1
+  li.d      $t1, LOONGARCH_IOCSR_MBUF1
+  iocsrwr.d $zero, $t1
+  li.d      $t1, LOONGARCH_IOCSR_MBUF0
+  iocsrwr.d $zero, $t1
+  jirl      $zero, $ra, 0
+# End of ClearMailBox
+
+ASM_PFX(EnableIPI):
+  /* Enable IPI interrupt */
+  li.d      $t1, (1 << 12)
+  csrxchg   $t1, $t1, LOONGARCH_CSR_ECFG
+
+  addi.d    $t2, $zero, -1
+  li.d      $t1, LOONGARCH_IOCSR_IPI_EN
+  iocsrwr.w $t2, $t1
+  jirl      $zero, $ra, 0
+# End of EeableIPI
+
+#/**
+#   Get APIC ID for every CPU.
+#
+#   @param   NULL
+#   @return  APICID
+#
+#   UINTN
+#   EFI_API
+#   GetApicId (
+#     VOID
+#     )
+#**/
+ASM_PFX(GetApicId):
+  csrrd $a0, LOONGARCH_CSR_CPUNUM
+  andi  $a0, $a0, 0x3ff
+  jirl  $zero, $ra, 0
+# End of GetApicId
+
+ASM_PFX(ApInitStack):
+  li.d   $t1, SIZE_1KB 
+  csrrd  $t0, LOONGARCH_CSR_TMID
+  mul.d  $t1, $t0, $t1
+  li.d   $t2, FixedPcdGet32(PcdCpuMaxLogicalProcessorNumber)
+  bgeu   $t0, $t2, DeadLoop
+  li.d   $t0, FixedPcdGet64(PcdOvmfSecPeiTempRamBase) + 
FixedPcdGet32(PcdOvmfSecPeiTempRamSize) - SIZE_64KB
+  sub.d  $sp, $t0, $t1
+  addi.d $sp, $sp, -0x8
+  jirl   $zero, $ra, 0
+# End of ApInitStack
+
+ASM_PFX(SlaveMain):
+  /* Set AP exception handle in flash */
+  la.pcrel  $a0, ApException
+  bl        SetExceptionBaseAddress
+
+  /* Clean up local mail box and open INT */
+  bl        ClearMailBox
+  bl        EnableIPI
+  bl        EnableInterrupts
+
+WaitForWake:
+  /* Wait for wakeup */
+  bl        CpuSleep
+  li.d      $t1, LOONGARCH_IOCSR_MBUF0
+  iocsrrd.w $t2, $t1
+  beqz      $t2, WaitForWake
+
+  /* Disable global interrupt */
+  bl        DisableInterrupts
+
+  /* Disable IPI interrupt */
+  li.d      $t0, (1 << 12)
+  csrxchg   $zero, $t0, LOONGARCH_CSR_ECFG
+
+  /* Read mail buf and jump to specified entry */
+  li.d      $t1, LOONGARCH_IOCSR_MBUF0
+  iocsrrd.d $t0, $t1
+  li.d      $t1, LOONGARCH_IOCSR_MBUF3
+  iocsrrd.d $a1, $t1
+  bl        ClearMailBox
+  beqz      $a1, NoParameterCall
+
+  //
+  // If the parameters are not NULL, then calling happened in FW ENV.
+  // Set the EBASE to be the same as BSP.
+  //
+  li.d      $a0, FixedPcdGet64(PcdCpuExceptionVectorBaseAddress)
+  bl        SetExceptionBaseAddress
+
+  bl        ApInitStack
+  bl        GetApicId
+NoParameterCall:
+  move      $ra, $t0
+  jirl      $zero, $ra, 0x0
+# End of SlaveMain
+
+.align 12
+ASM_PFX(ApException):
+  csrrd     $t0, LOONGARCH_CSR_ESTAT
+  srli.d    $t0, $t0, 12
+  beqz      $t0, DeadLoop
+
+  li.d      $t0, LOONGARCH_IOCSR_IPI_STATUS
+  iocsrrd.w $t1, $t0
+  li.d      $t0, LOONGARCH_IOCSR_IPI_CLEAR
+  iocsrwr.w $t1, $t0
+  ertn
+# End of ApException
+
+ASM_PFX(DeadLoop):
+  b   DeadLoop
+# End of DeadLoop
+.end
diff --git a/OvmfPkg/LoongArchVirt/Sec/SecMain.c 
b/OvmfPkg/LoongArchVirt/Sec/SecMain.c
new file mode 100644
index 0000000000..a7f4324811
--- /dev/null
+++ b/OvmfPkg/LoongArchVirt/Sec/SecMain.c
@@ -0,0 +1,507 @@
+/** @file
+  Main SEC phase code.  Transitions to PEI.
+
+  Copyright (c) 2024 Loongson Technology Corporation Limited. All rights 
reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugAgentLib.h>
+#include <Library/DebugLib.h>
+#include <Library/ExtractGuidedSectionLib.h>
+#include <Library/IoLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeCoffLib.h>
+#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/PeCoffExtraActionLib.h>
+#include <Library/PeimEntryPoint.h>
+
+#include <Ppi/TemporaryRamSupport.h>
+
+/**
+  temporary memory to permanent memory and do stack switching.
+
+  @param[in]  PeiServices     Pointer to the PEI Services Table.
+  @param[in]  TemporaryMemoryBase    Temporary Memory Base address.
+  @param[in]  PermanentMemoryBase   Permanent Memory Base address.
+  @param[in]  CopySize   The size of memory that needs to be migrated.
+
+  @retval   EFI_SUCCESS  Migration successful.
+**/
+EFI_STATUS
+EFIAPI
+TemporaryRamMigration (
+  IN CONST EFI_PEI_SERVICES  **PeiServices,
+  IN EFI_PHYSICAL_ADDRESS    TemporaryMemoryBase,
+  IN EFI_PHYSICAL_ADDRESS    PermanentMemoryBase,
+  IN UINTN                   CopySize
+  );
+
+EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI  mTemporaryRamSupportPpi = {
+  TemporaryRamMigration
+};
+
+EFI_PEI_PPI_DESCRIPTOR  mPrivateDispatchTable[] = {
+  {
+    (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+    &gEfiTemporaryRamSupportPpiGuid,
+    &mTemporaryRamSupportPpi
+  },
+};
+
+/**
+  Locates a section within a series of sections
+  with the specified section type.
+
+  The Instance parameter indicates which instance of the section
+  type to return. (0 is first instance, 1 is second...)
+
+  @param[in]   Sections        The sections to search
+  @param[in]   SizeOfSections  Total size of all sections
+  @param[in]   SectionType     The section type to locate
+  @param[in]   Instance        The section instance number
+  @param[out]  FoundSection    The FFS section if found
+
+  @retval EFI_SUCCESS           The file and section was found
+  @retval EFI_NOT_FOUND         The file and section was not found
+  @retval EFI_VOLUME_CORRUPTED  The firmware volume was corrupted
+**/
+EFI_STATUS
+FindFfsSectionInstance (
+  IN  VOID                       *Sections,
+  IN  UINTN                      SizeOfSections,
+  IN  EFI_SECTION_TYPE           SectionType,
+  IN  UINTN                      Instance,
+  OUT EFI_COMMON_SECTION_HEADER  **FoundSection
+  )
+{
+  EFI_PHYSICAL_ADDRESS       CurrentAddress;
+  UINT32                     Size;
+  EFI_PHYSICAL_ADDRESS       EndOfSections;
+  EFI_COMMON_SECTION_HEADER  *Section;
+  EFI_PHYSICAL_ADDRESS       EndOfSection;
+
+  //
+  // Loop through the FFS file sections within the PEI Core FFS file
+  //
+  EndOfSection  = (EFI_PHYSICAL_ADDRESS)(UINTN)Sections;
+  EndOfSections = EndOfSection + SizeOfSections;
+  for ( ; ; ) {
+    if (EndOfSection == EndOfSections) {
+      break;
+    }
+
+    CurrentAddress = (EndOfSection + 3) & ~(3ULL);
+    if (CurrentAddress >= EndOfSections) {
+      return EFI_VOLUME_CORRUPTED;
+    }
+
+    Section = (EFI_COMMON_SECTION_HEADER *)(UINTN)CurrentAddress;
+
+    Size = SECTION_SIZE (Section);
+    if (Size < sizeof (*Section)) {
+      return EFI_VOLUME_CORRUPTED;
+    }
+
+    EndOfSection = CurrentAddress + Size;
+    if (EndOfSection > EndOfSections) {
+      return EFI_VOLUME_CORRUPTED;
+    }
+
+    //
+    // Look for the requested section type
+    //
+    if (Section->Type == SectionType) {
+      if (Instance == 0) {
+        *FoundSection = Section;
+        return EFI_SUCCESS;
+      } else {
+        Instance--;
+      }
+    }
+  }
+
+  return EFI_NOT_FOUND;
+}
+
+/**
+  Locates a section within a series of sections
+  with the specified section type.
+
+  @param[in]   Sections        The sections to search
+  @param[in]   SizeOfSections  Total size of all sections
+  @param[in]   SectionType     The section type to locate
+  @param[out]  FoundSection    The FFS section if found
+
+  @retval EFI_SUCCESS           The file and section was found
+  @retval EFI_NOT_FOUND         The file and section was not found
+  @retval EFI_VOLUME_CORRUPTED  The firmware volume was corrupted
+**/
+EFI_STATUS
+FindFfsSectionInSections (
+  IN  VOID                       *Sections,
+  IN  UINTN                      SizeOfSections,
+  IN  EFI_SECTION_TYPE           SectionType,
+  OUT EFI_COMMON_SECTION_HEADER  **FoundSection
+  )
+{
+  return FindFfsSectionInstance (
+           Sections,
+           SizeOfSections,
+           SectionType,
+           0,
+           FoundSection
+           );
+}
+
+/**
+  Locates a FFS file with the specified file type and a section
+  within that file with the specified section type.
+
+  @param[in]   Fv            The firmware volume to search
+  @param[in]   FileType      The file type to locate
+  @param[in]   SectionType   The section type to locate
+  @param[out]  FoundSection  The FFS section if found
+
+  @retval EFI_SUCCESS           The file and section was found
+  @retval EFI_NOT_FOUND         The file and section was not found
+  @retval EFI_VOLUME_CORRUPTED  The firmware volume was corrupted
+**/
+EFI_STATUS
+FindFfsFileAndSection (
+  IN  EFI_FIRMWARE_VOLUME_HEADER  *Fv,
+  IN  EFI_FV_FILETYPE             FileType,
+  IN  EFI_SECTION_TYPE            SectionType,
+  OUT EFI_COMMON_SECTION_HEADER   **FoundSection
+  )
+{
+  EFI_STATUS            Status;
+  EFI_PHYSICAL_ADDRESS  CurrentAddress;
+  EFI_PHYSICAL_ADDRESS  EndOfFirmwareVolume;
+  EFI_FFS_FILE_HEADER   *File;
+  UINT32                Size;
+  EFI_PHYSICAL_ADDRESS  EndOfFile;
+
+  if (Fv->Signature != EFI_FVH_SIGNATURE) {
+    DEBUG ((DEBUG_ERROR, "FV at %p does not have FV header signature\n", Fv));
+    return EFI_VOLUME_CORRUPTED;
+  }
+
+  CurrentAddress      = (EFI_PHYSICAL_ADDRESS)(UINTN)Fv;
+  EndOfFirmwareVolume = CurrentAddress + Fv->FvLength;
+
+  //
+  // Loop through the FFS files in the Boot Firmware Volume
+  //
+  for (EndOfFile = CurrentAddress + Fv->HeaderLength; ; ) {
+    CurrentAddress = (EndOfFile + 7) & ~(7ULL);
+    if (CurrentAddress > EndOfFirmwareVolume) {
+      return EFI_VOLUME_CORRUPTED;
+    }
+
+    File = (EFI_FFS_FILE_HEADER *)(UINTN)CurrentAddress;
+    Size = *(UINT32 *)File->Size & 0xffffff;
+    if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) {
+      return EFI_VOLUME_CORRUPTED;
+    }
+
+    EndOfFile = CurrentAddress + Size;
+    if (EndOfFile > EndOfFirmwareVolume) {
+      return EFI_VOLUME_CORRUPTED;
+    }
+
+    //
+    // Look for the request file type
+    //
+    if (File->Type != FileType) {
+      continue;
+    }
+
+    Status = FindFfsSectionInSections (
+               (VOID *)(File + 1),
+               (UINTN)EndOfFile - (UINTN)(File + 1),
+               SectionType,
+               FoundSection
+               );
+    if (!EFI_ERROR (Status) ||
+        (Status == EFI_VOLUME_CORRUPTED))
+    {
+      return Status;
+    }
+  }
+}
+
+/**
+  Locates the PEI Core entry point address
+
+  @param[in]  Fv                 The firmware volume to search
+  @param[out] PeiCoreEntryPoint  The entry point of the PEI Core image
+
+  @retval EFI_SUCCESS           The file and section was found
+  @retval EFI_NOT_FOUND         The file and section was not found
+  @retval EFI_VOLUME_CORRUPTED  The firmware volume was corrupted
+**/
+EFI_STATUS
+FindPeiCoreImageBaseInFv (
+  IN  EFI_FIRMWARE_VOLUME_HEADER  *Fv,
+  OUT  EFI_PHYSICAL_ADDRESS       *PeiCoreImageBase
+  )
+{
+  EFI_STATUS                 Status;
+  EFI_COMMON_SECTION_HEADER  *Section;
+
+  Status = FindFfsFileAndSection (
+             Fv,
+             EFI_FV_FILETYPE_PEI_CORE,
+             EFI_SECTION_PE32,
+             &Section
+             );
+  if (EFI_ERROR (Status)) {
+    Status = FindFfsFileAndSection (
+               Fv,
+               EFI_FV_FILETYPE_PEI_CORE,
+               EFI_SECTION_TE,
+               &Section
+               );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "Unable to find PEI Core image\n"));
+      return Status;
+    }
+  }
+
+  *PeiCoreImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(Section + 1);
+  return EFI_SUCCESS;
+}
+
+/**
+  Find and return Pei Core entry point.
+
+  It also find SEC and PEI Core file debug information. It will report them if
+  remote debug is enabled.
+**/
+VOID
+FindAndReportEntryPoints (
+  IN  EFI_FIRMWARE_VOLUME_HEADER  **BootFirmwareVolumePtr,
+  OUT EFI_PEI_CORE_ENTRY_POINT    *PeiCoreEntryPoint
+  )
+{
+  EFI_STATUS                    Status;
+  EFI_PHYSICAL_ADDRESS          PeiCoreImageBase = 0;
+  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
+
+  Status = FindPeiCoreImageBaseInFv (*BootFirmwareVolumePtr, 
&PeiCoreImageBase);
+  ASSERT (Status == EFI_SUCCESS);
+
+  ZeroMem ((VOID *)&ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
+
+  //
+  // Report PEI Core debug information when remote debug is enabled
+  //
+  ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageBase;
+  ImageContext.PdbPointer   = PeCoffLoaderGetPdbPointer ((VOID 
*)(UINTN)ImageContext.ImageAddress);
+  PeCoffLoaderRelocateImageExtraAction (&ImageContext);
+
+  //
+  // Find PEI Core entry point
+  //
+  Status = PeCoffLoaderGetEntryPoint ((VOID *)(UINTN)PeiCoreImageBase, (VOID 
**)PeiCoreEntryPoint);
+  if (EFI_ERROR (Status)) {
+    *PeiCoreEntryPoint = 0;
+  }
+
+  return;
+}
+
+/**
+  Find the peicore entry point and jump to the entry point to execute.
+
+  @param[in] Context    The first input parameter of InitializeDebugAgent().
+**/
+VOID
+EFIAPI
+SecStartupPhase2 (
+  IN VOID  *Context
+  )
+{
+  EFI_SEC_PEI_HAND_OFF        *SecCoreData;
+  EFI_FIRMWARE_VOLUME_HEADER  *BootFv;
+  EFI_PEI_CORE_ENTRY_POINT    PeiCoreEntryPoint;
+
+  SecCoreData = (EFI_SEC_PEI_HAND_OFF *)Context;
+
+  //
+  // Find PEI Core entry point. It will report SEC and Pei Core debug 
information if remote debug
+  // is enabled.
+  //
+  BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase;
+  FindAndReportEntryPoints (&BootFv, &PeiCoreEntryPoint);
+  SecCoreData->BootFirmwareVolumeBase = BootFv;
+  SecCoreData->BootFirmwareVolumeSize = (UINTN)BootFv->FvLength;
+
+  DEBUG ((DEBUG_INFO, "Find Pei EntryPoint=%p\n", PeiCoreEntryPoint));
+
+  //
+  // Transfer the control to the PEI core
+  //
+  DEBUG ((DEBUG_INFO, "SecStartupPhase2 %p\n", PeiCoreEntryPoint));
+
+  (*PeiCoreEntryPoint)(SecCoreData, (EFI_PEI_PPI_DESCRIPTOR 
*)&mPrivateDispatchTable);
+
+  //
+  // If we get here then the PEI Core returned, which is not recoverable.
+  //
+  ASSERT (FALSE);
+  CpuDeadLoop ();
+}
+
+/**
+  Entry point to the C language phase of SEC. initialize some temporary memory 
and set up the stack,
+  the control is transferred to this function.
+
+  @param[in]  BootFv   The pointer to the PEI FV in memory.
+  @param[in]  TopOfCurrentStack  Top of Current Stack.
+**/
+VOID
+EFIAPI
+SecCoreStartupWithStack (
+  IN EFI_FIRMWARE_VOLUME_HEADER  *BootFv,
+  IN VOID                        *TopOfCurrentStack
+  )
+{
+  EFI_SEC_PEI_HAND_OFF        SecCoreData;
+  EFI_FIRMWARE_VOLUME_HEADER  *BootPeiFv = (EFI_FIRMWARE_VOLUME_HEADER 
*)BootFv;
+
+  DEBUG ((DEBUG_INFO, "Entering C environment\n"));
+
+  ProcessLibraryConstructorList (NULL, NULL);
+
+  DEBUG ((
+    DEBUG_INFO,
+    "SecCoreStartupWithStack (0x%lx, 0x%lx)\n",
+    (UINTN)BootFv,
+    (UINTN)TopOfCurrentStack
+    ));
+  DEBUG ((
+    DEBUG_INFO,
+    "(0x%lx, 0x%lx)\n",
+    (UINTN)(FixedPcdGet64 (PcdOvmfSecPeiTempRamBase)),
+    (UINTN)(FixedPcdGet32 (PcdOvmfSecPeiTempRamSize))
+    ));
+
+  // |-------------|       <-- TopOfCurrentStack
+  // |  BSP Stack  | 32k
+  // |-------------|
+  // |  BSP Heap   | 32k
+  // |-------------|       <-- SecCoreData.TemporaryRamBase
+  // |  Ap Stack   | 384k
+  // |-------------|
+  // |  Exception  | 64k
+  // |-------------|       <-- PcdOvmfSecPeiTempRamBase
+
+  ASSERT (
+    (UINTN)(FixedPcdGet64 (PcdOvmfSecPeiTempRamBase) +
+            FixedPcdGet32 (PcdOvmfSecPeiTempRamSize)) ==
+    (UINTN)TopOfCurrentStack
+    );
+
+  //
+  // Initialize SEC hand-off state
+  //
+  SecCoreData.DataSize = sizeof (EFI_SEC_PEI_HAND_OFF);
+
+  SecCoreData.TemporaryRamSize = (UINTN)SIZE_64KB;
+  SecCoreData.TemporaryRamBase = (VOID *)(FixedPcdGet64 
(PcdOvmfSecPeiTempRamBase) + FixedPcdGet32 (PcdOvmfSecPeiTempRamSize) - 
SecCoreData.TemporaryRamSize);
+
+  SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase;
+  SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1;
+
+  SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + 
SecCoreData.PeiTemporaryRamSize;
+  SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1;
+
+  SecCoreData.BootFirmwareVolumeBase = BootPeiFv;
+  SecCoreData.BootFirmwareVolumeSize = (UINTN)BootPeiFv->FvLength;
+
+  DEBUG ((
+    DEBUG_INFO,
+    "&SecCoreData.BootFirmwareVolumeBase=%lx 
SecCoreData.BootFirmwareVolumeBase=%lx\n",
+    (UINT64)&(SecCoreData.BootFirmwareVolumeBase),
+    (UINT64)(SecCoreData.BootFirmwareVolumeBase)
+    ));
+  DEBUG ((
+    DEBUG_INFO,
+    "&SecCoreData.BootFirmwareVolumeSize=%lx 
SecCoreData.BootFirmwareVolumeSize=%lx\n",
+    (UINT64)&(SecCoreData.BootFirmwareVolumeSize),
+    (UINT64)(SecCoreData.BootFirmwareVolumeSize)
+    ));
+
+  //
+  // Initialize Debug Agent to support source level debug in SEC/PEI phases 
before memory ready.
+  //
+  InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, NULL, NULL);
+  SecStartupPhase2 (&SecCoreData);
+}
+
+/**
+  temporary memory to permanent memory and do stack switching.
+
+  @param[in]  PeiServices     Pointer to the PEI Services Table.
+  @param[in]  TemporaryMemoryBase    Temporary Memory Base address.
+  @param[in]  PermanentMemoryBase   Permanent Memory Base address.
+  @param[in]  CopySize   The size of memory that needs to be migrated.
+
+  @retval   EFI_SUCCESS  Migration successful.
+**/
+EFI_STATUS
+EFIAPI
+TemporaryRamMigration (
+  IN CONST EFI_PEI_SERVICES  **PeiServices,
+  IN EFI_PHYSICAL_ADDRESS    TemporaryMemoryBase,
+  IN EFI_PHYSICAL_ADDRESS    PermanentMemoryBase,
+  IN UINTN                   CopySize
+  )
+{
+  VOID                      *OldHeap;
+  VOID                      *NewHeap;
+  VOID                      *OldStack;
+  VOID                      *NewStack;
+  BASE_LIBRARY_JUMP_BUFFER  JumpBuffer;
+
+  DEBUG ((
+    DEBUG_INFO,
+    "TemporaryRamMigration (0x%Lx, 0x%Lx, 0x%Lx)\n",
+    TemporaryMemoryBase,
+    PermanentMemoryBase,
+    (UINT64)CopySize
+    ));
+
+  OldHeap = (VOID *)(UINTN)TemporaryMemoryBase;
+  NewHeap = (VOID *)((UINTN)PermanentMemoryBase + (CopySize >> 1));
+
+  OldStack = (VOID *)((UINTN)TemporaryMemoryBase + (CopySize >> 1));
+  NewStack = (VOID *)(UINTN)PermanentMemoryBase;
+
+  //
+  // Migrate Heap
+  //
+  CopyMem (NewHeap, OldHeap, CopySize >> 1);
+
+  //
+  // Migrate Stack
+  //
+  CopyMem (NewStack, OldStack, CopySize >> 1);
+
+  // Use SetJump ()/LongJump () to switch to a new stack.
+  //
+  if (SetJump (&JumpBuffer) == 0) {
+    JumpBuffer.SP = JumpBuffer.SP - (UINTN)OldStack + (UINTN)NewStack;
+    LongJump (&JumpBuffer, (UINTN)-1);
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/LoongArchVirt/Sec/SecMain.inf 
b/OvmfPkg/LoongArchVirt/Sec/SecMain.inf
new file mode 100644
index 0000000000..af29ba0551
--- /dev/null
+++ b/OvmfPkg/LoongArchVirt/Sec/SecMain.inf
@@ -0,0 +1,53 @@
+## @file
+#  SEC Driver
+#
+#  Copyright (c) 2024 Loongson Technology Corporation Limited. All rights 
reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = SecMain
+  FILE_GUID                      = 57d02d4f-5a5d-4bfa-b7d6-ba0a4d2c72ce
+  MODULE_TYPE                    = SEC
+  VERSION_STRING                 = 1.0
+
+#
+#  VALID_ARCHITECTURES           = LOONGARCH64
+#
+
+[Sources]
+  LoongArch64/Start.S
+  SecMain.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  OvmfPkg/OvmfPkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  CpuExceptionHandlerLib
+  DebugAgentLib
+  DebugLib
+  IoLib
+  PcdLib
+  PeCoffLib
+  PeCoffGetEntryPointLib
+  PeCoffExtraActionLib
+
+[Ppis]
+  gEfiTemporaryRamSupportPpiGuid                # PPI ALWAYS_PRODUCED
+
+[FixedPcd]
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
+
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuExceptionVectorBaseAddress
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber
+
+  gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress
-- 
2.27.0



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#112976): https://edk2.groups.io/g/devel/message/112976
Mute This Topic: https://groups.io/mt/103398640/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to