public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Sunil V L" <sunilvl@ventanamicro.com>
To: devel@edk2.groups.io
Cc: Jian J Wang <jian.j.wang@intel.com>,
	Liming Gao <gaoliming@byosoft.com.cn>,
	Eric Dong <eric.dong@intel.com>, Ray Ni <ray.ni@intel.com>,
	Rahul Kumar <rahul1.kumar@intel.com>,
	Debkumar De <debkumar.de@intel.com>,
	Catharine West <catharine.west@intel.com>,
	Daniel Schaefer <git@danielschaefer.me>,
	Abner Chang <Abner.Chang@amd.com>,
	Leif Lindholm <quic_llindhol@quicinc.com>,
	Andrew Fish <afish@apple.com>, Ard Biesheuvel <ardb@kernel.org>,
	Heinrich Schuchardt <heinrich.schuchardt@canonical.com>,
	Anup Patel <apatel@ventanamicro.com>,
	Sunil V L <sunilvl@ventanamicro.com>
Subject: [RFC PATCH V2 12/19] UefiCpuPkg/SecCore: Add SEC startup code for RISC-V
Date: Wed,  7 Sep 2022 17:06:19 +0530	[thread overview]
Message-ID: <20220907113626.540065-13-sunilvl@ventanamicro.com> (raw)
In-Reply-To: <20220907113626.540065-1-sunilvl@ventanamicro.com>

Generic RISC-V platforms will start in S-mode directly.
Previous M-mode firmware like opensbi will branch to the
entry point in this module. This module initializes the
firmware context pointer and branches to the PEI phase.

Signed-off-by: Sunil V L <sunilvl@ventanamicro.com>
---
 UefiCpuPkg/SecCore/SecCoreRiscV.inf   |  59 ++
 UefiCpuPkg/SecCore/RiscV64/SecMain.h  |  63 ++
 UefiCpuPkg/SecCore/RiscV64/SecMain.c  | 796 ++++++++++++++++++++
 UefiCpuPkg/SecCore/RiscV64/SecEntry.S |  23 +
 4 files changed, 941 insertions(+)

diff --git a/UefiCpuPkg/SecCore/SecCoreRiscV.inf b/UefiCpuPkg/SecCore/SecCoreRiscV.inf
new file mode 100644
index 000000000000..8ba6400f5319
--- /dev/null
+++ b/UefiCpuPkg/SecCore/SecCoreRiscV.inf
@@ -0,0 +1,59 @@
+## @file
+#  RISC-V SEC module which boots in S-mode.
+#
+#  Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+#  Copyright (c) 2022, Ventana Micro Systems Inc. All rights reserved.<BR>
+#
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x0001001b
+  BASE_NAME                      = SecMain
+  FILE_GUID                      = 42C30D8E-BFAD-4E77-9041-E7DAAE88DF7A
+  MODULE_TYPE                    = SEC
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = SecMain
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = RISCV64
+#
+
+[Sources]
+  RiscV64/SecEntry.S
+  RiscV64/SecMain.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  UefiCpuPkg/UefiCpuPkg.dec
+
+[LibraryClasses]
+  BaseMemoryLib
+  DebugLib
+  PlatformSecLib
+  PcdLib
+  CpuLib
+  PeCoffGetEntryPointLib
+  PeCoffExtraActionLib
+  RiscVSbiLib
+
+[Ppis]
+  gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED
+  gEfiTemporaryRamDonePpiGuid    # PPI ALWAYS_PRODUCED
+
+[Pcd]
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSecMemFvBase
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSecMemFvSize
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPeiMemFvBase
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPeiMemFvSize
+  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeMemFvBase
+  gEfiMdeModulePkgTokenSpaceGuid.PcdDxeMemFvSize
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSecPeiTempRamBase
+  gEfiMdeModulePkgTokenSpaceGuid.PcdSecPeiTempRamSize
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  SecCoreExtra.uni
diff --git a/UefiCpuPkg/SecCore/RiscV64/SecMain.h b/UefiCpuPkg/SecCore/RiscV64/SecMain.h
new file mode 100644
index 000000000000..eeb368de02a2
--- /dev/null
+++ b/UefiCpuPkg/SecCore/RiscV64/SecMain.h
@@ -0,0 +1,63 @@
+/** @file
+  Master header file for SecCore.
+
+  Copyright (c) 2019-2022, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+  Copyright (c) 2022, Ventana Micro Systems Inc. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _SEC_MAIN_H_
+#define _SEC_MAIN_H_
+
+#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/HobLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeCoffExtraActionLib.h>
+#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/PeCoffLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PeiServicesTablePointerLib.h>
+#include <Library/DebugPrintErrorLevelLib.h>
+#include <Library/PrintLib.h>
+#include <Library/RiscVSbiLib.h>
+#include <Register/RiscV64/RiscVImpl.h>
+#include <Ppi/TemporaryRamDone.h>
+#include <Ppi/TemporaryRamSupport.h>
+
+/**
+  Entry point to the C language phase of SEC. After the SEC assembly
+  code has initialized some temporary memory and set up the stack,
+  the control is transferred to this function.
+
+  @param SizeOfRam           Size of the temporary memory available for use.
+  @param TempRamBase         Base address of temporary ram
+  @param BootFirmwareVolume  Base address of the Boot Firmware Volume.
+**/
+VOID
+NORETURN
+EFIAPI
+SecStartup (
+  IN  UINTN BootHartId,
+  IN  VOID *DeviceTreeAddress
+  );
+
+/**
+  Auto-generated function that calls the library constructors for all of the module's
+  dependent libraries.  This function must be called by the SEC Core once a stack has
+  been established.
+
+**/
+VOID
+EFIAPI
+ProcessLibraryConstructorList (
+  VOID
+  );
+
+#endif
diff --git a/UefiCpuPkg/SecCore/RiscV64/SecMain.c b/UefiCpuPkg/SecCore/RiscV64/SecMain.c
new file mode 100644
index 000000000000..d9dacce319dc
--- /dev/null
+++ b/UefiCpuPkg/SecCore/RiscV64/SecMain.c
@@ -0,0 +1,796 @@
+/** @file
+  RISC-V SEC phase module.
+
+  Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2021-2022, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+  Copyright (c) 2022, Ventana Micro Systems Inc. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SecMain.h"
+
+EFI_STATUS
+EFIAPI
+TemporaryRamMigration (
+  IN CONST EFI_PEI_SERVICES   **PeiServices,
+  IN EFI_PHYSICAL_ADDRESS     TemporaryMemoryBase,
+  IN EFI_PHYSICAL_ADDRESS     PermanentMemoryBase,
+  IN UINTN                    CopySize
+  );
+
+EFI_STATUS
+EFIAPI
+TemporaryRamDone (
+  VOID
+  );
+
+STATIC EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi = {
+  TemporaryRamMigration
+};
+
+STATIC EFI_PEI_TEMPORARY_RAM_DONE_PPI mTemporaryRamDonePpi = {
+  TemporaryRamDone
+};
+
+STATIC EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTable[] = {
+  {
+    EFI_PEI_PPI_DESCRIPTOR_PPI,
+    &gEfiTemporaryRamSupportPpiGuid,
+    &mTemporaryRamSupportPpi
+  },
+  {
+    (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+    &gEfiTemporaryRamDonePpiGuid,
+    &mTemporaryRamDonePpi
+  },
+};
+
+/** Temporary RAM migration function.
+
+  This function migrates the data from temporary RAM to permanent
+  memory.
+
+  @param[in]  PeiServices           PEI service
+  @param[in]  TemporaryMemoryBase   Temporary memory base address
+  @param[in]  PermanentMemoryBase   Permanent memory base address
+  @param[in]  CopySize              Size to copy
+
+**/
+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;
+  EFI_RISCV_FIRMWARE_CONTEXT *FirmwareContext;
+
+  DEBUG ((DEBUG_INFO,
+    "%a: Temp Mem Base:0x%Lx, Permanent Mem Base:0x%Lx, CopySize:0x%Lx\n",
+    __FUNCTION__,
+    TemporaryMemoryBase,
+    PermanentMemoryBase,
+    (UINT64)CopySize
+    ));
+
+  OldHeap = (VOID*)(UINTN)TemporaryMemoryBase;
+  NewHeap = (VOID*)((UINTN)PermanentMemoryBase + (CopySize >> 1));
+
+  OldStack = (VOID*)((UINTN)TemporaryMemoryBase + (CopySize >> 1));
+  NewStack = (VOID*)(UINTN)PermanentMemoryBase;
+
+  CopyMem (NewHeap, OldHeap, CopySize >> 1);   // Migrate Heap
+  CopyMem (NewStack, OldStack, CopySize >> 1); // Migrate Stack
+
+  //
+  // Reset firmware context pointer
+  //
+  GetFirmwareContextPointer (&FirmwareContext);
+  FirmwareContext = (VOID *)FirmwareContext + (unsigned long)((UINTN)NewStack - (UINTN)OldStack);
+  SetFirmwareContextPointer (FirmwareContext);
+
+  DEBUG ((DEBUG_INFO, "%a: Firmware Context is relocated to 0x%x\n", __FUNCTION__, FirmwareContext));
+
+  register UINTN  a0 asm ("a0") = (UINTN)((UINTN)NewStack - (UINTN)OldStack);
+  asm volatile ("add sp, sp, a0"::"r"(a0):);
+  return EFI_SUCCESS;
+}
+
+/** Temprary RAM done function.
+
+**/
+EFI_STATUS EFIAPI TemporaryRamDone (
+  VOID
+  )
+{
+  DEBUG ((DEBUG_INFO, "%a: 2nd time PEI core, temporary ram done.\n", __FUNCTION__));
+  return EFI_SUCCESS;
+}
+/** Return platform SEC PPI before PEI Core
+
+  @param[in,out]  ThisPpiList   Pointer to retrieve EFI_PEI_PPI_DESCRIPTOR.
+
+**/
+STATIC EFI_STATUS
+GetPlatformPrePeiCorePpiDescriptor (
+  IN OUT EFI_PEI_PPI_DESCRIPTOR  **ThisPpiList
+)
+{
+  *ThisPpiList = mPrivateDispatchTable;
+  return EFI_SUCCESS;
+}
+
+/**
+  Locates the main boot firmware volume.
+
+  @param[in,out]  BootFv  On input, the base of the BootFv
+                          On output, the decompressed main firmware volume
+
+  @retval EFI_SUCCESS    The main firmware volume was located and decompressed
+  @retval EFI_NOT_FOUND  The main firmware volume was not found
+
+**/
+EFI_STATUS
+FindMainFv (
+  IN OUT  EFI_FIRMWARE_VOLUME_HEADER  **BootFv
+  )
+{
+  EFI_FIRMWARE_VOLUME_HEADER  *Fv;
+  UINTN                       Distance;
+
+  ASSERT (((UINTN)*BootFv & EFI_PAGE_MASK) == 0);
+
+  Fv       = *BootFv;
+  Distance = (UINTN)(*BootFv)->FvLength;
+  do {
+    Fv        = (EFI_FIRMWARE_VOLUME_HEADER *)((UINT8 *)Fv + EFI_PAGE_SIZE);
+    Distance += EFI_PAGE_SIZE;
+    if (Distance > SIZE_32MB) {
+      return EFI_NOT_FOUND;
+    }
+
+    if (Fv->Signature != EFI_FVH_SIGNATURE) {
+      continue;
+    }
+
+    if ((UINTN)Fv->FvLength < Distance) {
+      continue;
+    }
+
+    *BootFv = Fv;
+    return EFI_SUCCESS;
+  } while (TRUE);
+}
+
+/**
+  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 = FFS_FILE_SIZE (File);
+    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 compressed main firmware volume and decompresses it.
+
+  @param[in,out]  Fv            On input, the firmware volume to search
+                                On output, the decompressed BOOT/PEI FV
+
+  @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
+DecompressMemFvs (
+  IN OUT EFI_FIRMWARE_VOLUME_HEADER  **Fv
+  )
+{
+  EFI_STATUS                  Status;
+  EFI_GUID_DEFINED_SECTION    *Section;
+  UINT32                      OutputBufferSize;
+  UINT32                      ScratchBufferSize;
+  UINT16                      SectionAttribute;
+  UINT32                      AuthenticationStatus;
+  VOID                        *OutputBuffer;
+  VOID                        *ScratchBuffer;
+  EFI_COMMON_SECTION_HEADER   *FvSection;
+  EFI_FIRMWARE_VOLUME_HEADER  *PeiMemFv;
+  EFI_FIRMWARE_VOLUME_HEADER  *DxeMemFv;
+  UINT32                      FvHeaderSize;
+  UINT32                      FvSectionSize;
+
+  FvSection = (EFI_COMMON_SECTION_HEADER *)NULL;
+
+  Status = FindFfsFileAndSection (
+             *Fv,
+             EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE,
+             EFI_SECTION_GUID_DEFINED,
+             (EFI_COMMON_SECTION_HEADER **)&Section
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Unable to find GUID defined section\n"));
+    return Status;
+  }
+
+  Status = ExtractGuidedSectionGetInfo (
+             Section,
+             &OutputBufferSize,
+             &ScratchBufferSize,
+             &SectionAttribute
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Unable to GetInfo for GUIDed section\n"));
+    return Status;
+  }
+
+  OutputBuffer  = (VOID *)((UINT8 *)(UINTN)PcdGet32 (PcdDxeMemFvBase) + SIZE_1MB);
+  ScratchBuffer = ALIGN_POINTER ((UINT8 *)OutputBuffer + OutputBufferSize, SIZE_1MB);
+
+  Status = ExtractGuidedSectionDecode (
+             Section,
+             &OutputBuffer,
+             ScratchBuffer,
+             &AuthenticationStatus
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Error during GUID section decode\n"));
+    return Status;
+  }
+
+  Status = FindFfsSectionInstance (
+             OutputBuffer,
+             OutputBufferSize,
+             EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
+             0,
+             &FvSection
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Unable to find PEI FV section\n"));
+    return Status;
+  }
+
+  ASSERT (
+    SECTION_SIZE (FvSection) ==
+    (PcdGet32 (PcdPeiMemFvSize) + sizeof (*FvSection))
+    );
+  ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE);
+
+  PeiMemFv = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32 (PcdPeiMemFvBase);
+  CopyMem (PeiMemFv, (VOID *)(FvSection + 1), PcdGet32 (PcdPeiMemFvSize));
+
+  if (PeiMemFv->Signature != EFI_FVH_SIGNATURE) {
+    DEBUG ((DEBUG_ERROR, "Extracted FV at %p does not have FV header signature\n", PeiMemFv));
+    CpuDeadLoop ();
+    return EFI_VOLUME_CORRUPTED;
+  }
+
+  Status = FindFfsSectionInstance (
+             OutputBuffer,
+             OutputBufferSize,
+             EFI_SECTION_FIRMWARE_VOLUME_IMAGE,
+             1,
+             &FvSection
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Unable to find DXE FV section\n"));
+    return Status;
+  }
+
+  ASSERT (FvSection->Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE);
+
+  if (IS_SECTION2 (FvSection)) {
+    FvSectionSize = SECTION2_SIZE (FvSection);
+    FvHeaderSize  = sizeof (EFI_COMMON_SECTION_HEADER2);
+  } else {
+    FvSectionSize = SECTION_SIZE (FvSection);
+    FvHeaderSize  = sizeof (EFI_COMMON_SECTION_HEADER);
+  }
+
+  ASSERT (FvSectionSize == (PcdGet32 (PcdDxeMemFvSize) + FvHeaderSize));
+
+  DxeMemFv = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)PcdGet32 (PcdDxeMemFvBase);
+  CopyMem (DxeMemFv, (VOID *)((UINTN)FvSection + FvHeaderSize), PcdGet32 (PcdDxeMemFvSize));
+
+  if (DxeMemFv->Signature != EFI_FVH_SIGNATURE) {
+    DEBUG ((DEBUG_ERROR, "Extracted FV at %p does not have FV header signature\n", DxeMemFv));
+    CpuDeadLoop ();
+    return EFI_VOLUME_CORRUPTED;
+  }
+  *Fv = PeiMemFv;
+  return EFI_SUCCESS;
+}
+
+/**
+  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;
+}
+
+/**
+  Locates the PEI Core entry point address
+
+  @param[in,out]  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
+
+**/
+VOID
+FindPeiCoreImageBase (
+  IN OUT  EFI_FIRMWARE_VOLUME_HEADER  **BootFv,
+  OUT  EFI_PHYSICAL_ADDRESS           *PeiCoreImageBase
+  )
+{
+
+  *PeiCoreImageBase = 0;
+
+  FindMainFv (BootFv);
+
+  DecompressMemFvs (BootFv);
+
+  FindPeiCoreImageBaseInFv (*BootFv, PeiCoreImageBase);
+}
+
+/**
+  Find core image base.
+
+**/
+EFI_STATUS
+FindImageBase (
+  IN  EFI_FIRMWARE_VOLUME_HEADER  *BootFirmwareVolumePtr,
+  OUT EFI_PHYSICAL_ADDRESS        *SecCoreImageBase
+  )
+{
+  EFI_PHYSICAL_ADDRESS       CurrentAddress;
+  EFI_PHYSICAL_ADDRESS       EndOfFirmwareVolume;
+  EFI_FFS_FILE_HEADER        *File;
+  UINT32                     Size;
+  EFI_PHYSICAL_ADDRESS       EndOfFile;
+  EFI_COMMON_SECTION_HEADER  *Section;
+  EFI_PHYSICAL_ADDRESS       EndOfSection;
+
+  *SecCoreImageBase = 0;
+
+  CurrentAddress      = (EFI_PHYSICAL_ADDRESS)(UINTN)BootFirmwareVolumePtr;
+  EndOfFirmwareVolume = CurrentAddress + BootFirmwareVolumePtr->FvLength;
+
+  //
+  // Loop through the FFS files in the Boot Firmware Volume
+  //
+  for (EndOfFile = CurrentAddress + BootFirmwareVolumePtr->HeaderLength; ; ) {
+    CurrentAddress = (EndOfFile + 7) & 0xfffffffffffffff8ULL;
+    if (CurrentAddress > EndOfFirmwareVolume) {
+      return EFI_NOT_FOUND;
+    }
+
+    File = (EFI_FFS_FILE_HEADER *)(UINTN)CurrentAddress;
+    Size = FFS_FILE_SIZE (File);
+    if (Size < sizeof (*File)) {
+      return EFI_NOT_FOUND;
+    }
+
+    EndOfFile = CurrentAddress + Size;
+    if (EndOfFile > EndOfFirmwareVolume) {
+      return EFI_NOT_FOUND;
+    }
+
+    //
+    // Look for SEC Core
+    //
+    if (File->Type != EFI_FV_FILETYPE_SECURITY_CORE) {
+      continue;
+    }
+
+    //
+    // Loop through the FFS file sections within the FFS file
+    //
+    EndOfSection = (EFI_PHYSICAL_ADDRESS)(UINTN)(File + 1);
+    for ( ; ;) {
+      CurrentAddress = (EndOfSection + 3) & 0xfffffffffffffffcULL;
+      Section        = (EFI_COMMON_SECTION_HEADER *)(UINTN)CurrentAddress;
+
+      Size = SECTION_SIZE (Section);
+      if (Size < sizeof (*Section)) {
+        return EFI_NOT_FOUND;
+      }
+
+      EndOfSection = CurrentAddress + Size;
+      if (EndOfSection > EndOfFile) {
+        return EFI_NOT_FOUND;
+      }
+
+      //
+      // Look for executable sections
+      //
+      if ((Section->Type == EFI_SECTION_PE32) || (Section->Type == EFI_SECTION_TE)) {
+        if (File->Type == EFI_FV_FILETYPE_SECURITY_CORE) {
+          *SecCoreImageBase = (PHYSICAL_ADDRESS)(UINTN)(Section + 1);
+        }
+
+        break;
+      }
+    }
+
+    //
+    // SEC Core image found
+    //
+    if (*SecCoreImageBase != 0) {
+      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          SecCoreImageBase;
+  EFI_PHYSICAL_ADDRESS          PeiCoreImageBase;
+  PE_COFF_LOADER_IMAGE_CONTEXT  ImageContext;
+
+  //
+  // Find SEC Core and PEI Core image base
+  //
+  Status = FindImageBase (*BootFirmwareVolumePtr, &SecCoreImageBase);
+  ASSERT_EFI_ERROR (Status);
+
+  FindPeiCoreImageBase (BootFirmwareVolumePtr, &PeiCoreImageBase);
+
+  ZeroMem ((VOID *)&ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
+  //
+  // Report SEC Core debug information when remote debug is enabled
+  //
+  ImageContext.ImageAddress = SecCoreImageBase;
+  ImageContext.PdbPointer   = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageContext.ImageAddress);
+  PeCoffLoaderRelocateImageExtraAction (&ImageContext);
+
+  //
+  // 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;
+}
+
+/**
+
+  Entry point to the C language phase of SEC. After the SEC assembly
+  code has initialized some temporary memory and set up the stack,
+  the control is transferred to this function.
+
+
+  @param[in]  BootHartId         Hardware thread ID of boot hart.
+  @param[in]  DeviceTreeAddress  Pointer to Device Tree (DTB)
+**/
+VOID
+NORETURN
+EFIAPI
+SecStartup (
+  IN  UINTN BootHartId,
+  IN  VOID *DeviceTreeAddress
+  )
+{
+  EFI_RISCV_FIRMWARE_CONTEXT FirmwareContext;
+  EFI_FIRMWARE_VOLUME_HEADER *BootFv;
+  EFI_PEI_CORE_ENTRY_POINT   PeiCoreEntryPoint;
+  EFI_PEI_PPI_DESCRIPTOR     *PpiList;
+  EFI_SEC_PEI_HAND_OFF       SecCoreData;
+  EFI_STATUS                 Status;
+
+  //
+  // Report Status Code to indicate entering SEC core
+  //
+  DEBUG ((
+    DEBUG_INFO,
+    "%a() BootHartId: 0x%x, DeviceTreeAddress=0x%x\n",
+    __FUNCTION__,
+    BootHartId,
+    DeviceTreeAddress
+    ));
+
+  //
+  // Process all libraries constructor function linked to SecCore.
+  //
+  ProcessLibraryConstructorList ();
+
+  BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)FixedPcdGet32 (PcdSecMemFvBase);
+
+  ASSERT(BootFv != NULL);
+  SecCoreData.DataSize               = (UINT16)sizeof (EFI_SEC_PEI_HAND_OFF);
+  SecCoreData.BootFirmwareVolumeBase = BootFv;
+  SecCoreData.BootFirmwareVolumeSize = (UINTN)FixedPcdGet32 (PcdSecMemFvSize);
+  SecCoreData.TemporaryRamBase       = (VOID *)(UINT64)FixedPcdGet32 (PcdSecPeiTempRamBase);
+  SecCoreData.TemporaryRamSize       = (UINTN)FixedPcdGet32 (PcdSecPeiTempRamSize);
+  SecCoreData.PeiTemporaryRamBase    = SecCoreData.TemporaryRamBase;
+  SecCoreData.PeiTemporaryRamSize    = SecCoreData.TemporaryRamSize >> 1;
+  SecCoreData.StackBase              = (UINT8 *)SecCoreData.TemporaryRamBase + (SecCoreData.TemporaryRamSize >> 1);
+  SecCoreData.StackSize              = SecCoreData.TemporaryRamSize >> 1;
+
+  DEBUG ((
+    DEBUG_INFO,
+    "%a() BFV Base: 0x%x, BFV Size: 0x%x, TempRAM Base: 0x%x, TempRAM Size: 0x%x, PeiTempRamBase: 0x%x, PeiTempRamSize: 0x%x, StackBase: 0x%x, StackSize: 0x%x\n",
+    __FUNCTION__,
+    SecCoreData.BootFirmwareVolumeBase,
+    SecCoreData.BootFirmwareVolumeSize,
+    SecCoreData.TemporaryRamBase,
+    SecCoreData.TemporaryRamSize,
+    SecCoreData.PeiTemporaryRamBase,
+    SecCoreData.PeiTemporaryRamSize,
+    SecCoreData.StackBase,
+    SecCoreData.StackSize
+    ));
+
+  FindAndReportEntryPoints (
+    &BootFv,
+    &PeiCoreEntryPoint
+    );
+  if (PeiCoreEntryPoint == NULL) {
+    CpuDeadLoop ();
+  }
+
+  SecCoreData.BootFirmwareVolumeBase = BootFv;
+  SecCoreData.BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;
+
+  Status = GetPlatformPrePeiCorePpiDescriptor (&PpiList);
+  if (EFI_ERROR (Status)) {
+    PpiList = NULL;
+  }
+
+  FirmwareContext.BootHartId = BootHartId;
+  FirmwareContext.FlattenedDeviceTree = (UINT64)DeviceTreeAddress;
+  SetFirmwareContextPointer (&FirmwareContext);
+
+  //
+  // Transfer the control to the PEI core
+  //
+  ASSERT (PeiCoreEntryPoint != NULL);
+  (*PeiCoreEntryPoint)(&SecCoreData, PpiList);
+
+  //
+  // Should not come here.
+  //
+  UNREACHABLE ();
+}
diff --git a/UefiCpuPkg/SecCore/RiscV64/SecEntry.S b/UefiCpuPkg/SecCore/RiscV64/SecEntry.S
new file mode 100644
index 000000000000..1bd0174e278e
--- /dev/null
+++ b/UefiCpuPkg/SecCore/RiscV64/SecEntry.S
@@ -0,0 +1,23 @@
+/*
+  Copyright (c) 2021-2022 , Hewlett Packard Enterprise Development LP. All rights reserved.
+  Copyright (c) 2019 Western Digital Corporation or its affiliates.
+  Copyright (c) 2022 Ventana Micro Systems Inc.
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ */
+
+#include "SecMain.h"
+
+.text
+.align 3
+
+ASM_FUNC (_ModuleEntryPoint)
+  /* Use Temp memory as the stack for calling to C code */
+  li    a4, FixedPcdGet32 (PcdSecPeiTempRamBase)
+  li    a5, FixedPcdGet32 (PcdSecPeiTempRamSize)
+
+  /* Use Temp memory as the stack for calling to C code */
+  add   sp, a4, a5
+
+  call SecStartup
-- 
2.25.1


  parent reply	other threads:[~2022-09-07 11:37 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-09-07 11:36 [RFC PATCH V2 00/19] Refactor and add RISC-V support in edk2 repo Sunil V L
2022-09-07 11:36 ` [RFC PATCH V2 01/19] MdePkg/Register: Add register definition header files for RISC-V Sunil V L
2022-09-07 11:36 ` [RFC PATCH V2 02/19] MdePkg/MdePkg.dec: Add RISCV_EFI_BOOT_PROTOCOL GUID Sunil V L
2022-12-08  1:21   ` Heinrich Schuchardt
2022-09-07 11:36 ` [RFC PATCH V2 03/19] MdePkg/Protocol: Add RiscVBootProtocol.h Sunil V L
2022-12-08  1:24   ` Heinrich Schuchardt
2022-09-07 11:36 ` [RFC PATCH V2 04/19] MdeModulePkg/MdeModulePkg.dec: Add PCD variables for RISC-V Sunil V L
2022-09-07 11:36 ` [RFC PATCH V2 05/19] UefiCpuPkg.dec: Add PCD variable " Sunil V L
2022-09-07 11:36 ` [RFC PATCH V2 06/19] MdePkg/BaseLib: RISC-V: Add generic CPU related functions Sunil V L
2022-12-08  1:43   ` Heinrich Schuchardt
2022-12-08  5:04     ` Sunil V L
2022-09-07 11:36 ` [RFC PATCH V2 07/19] MdePkg: Add ArchTimerLib library Sunil V L
2022-12-08  1:59   ` Heinrich Schuchardt
2022-09-07 11:36 ` [RFC PATCH V2 08/19] MdePkg: Add RiscVSbiLib Library for RISC-V Sunil V L
2022-12-08  2:22   ` Heinrich Schuchardt
2022-09-07 11:36 ` [RFC PATCH V2 09/19] UefiCpuPkg: Update Sources in DxeCpuExceptionHandlerLib.inf Sunil V L
2022-09-07 11:36 ` [RFC PATCH V2 10/19] UefiCpuPkg: Add RISC-V support in DxeCpuExceptionHandlerLib Sunil V L
2022-12-08  0:30   ` [edk2-devel] " Ni, Ray
2022-12-08  4:58     ` Sunil V L
2022-12-08  8:32       ` Ni, Ray
2022-12-14  9:38         ` Leif Lindholm
2022-12-14 12:37           ` Ni, Ray
2022-12-16  5:22             ` Sunil V L
2022-09-07 11:36 ` [RFC PATCH V2 11/19] MdePkg/Library: Add ResetSystemLib library Sunil V L
2022-09-07 11:36 ` Sunil V L [this message]
2022-09-07 11:36 ` [RFC PATCH V2 13/19] MdePkg: Add PlatformPeiLib library Sunil V L
2022-09-07 11:36 ` [RFC PATCH V2 14/19] MdeModulePkg/Universal: Add PlatformPei module for RISC-V Sunil V L
2022-09-07 11:36 ` [RFC PATCH V2 15/19] UefiCpuPkg/CpuDxe: Refactor to allow other CPU architectures Sunil V L
2022-09-07 11:36 ` [RFC PATCH V2 16/19] UefiCpuPkg/CpuDxe: Add RISC-V support in CpuDxe module Sunil V L
2022-09-07 11:36 ` [RFC PATCH V2 17/19] MdeModulePkg/Universal: Add TimerDxe module Sunil V L
2022-09-07 11:36 ` [RFC PATCH V2 18/19] RISC-V: Add Qemu Virt platform support Sunil V L
2022-12-08  2:33   ` Heinrich Schuchardt
  -- strict thread matches above, loose matches on Subject: below --
2022-09-07 11:11 [RFC PATCH V2 00/19] Refactor and add RISC-V support in edk2 repo Sunil V L
2022-09-07 11:11 ` [RFC PATCH V2 12/19] UefiCpuPkg/SecCore: Add SEC startup code for RISC-V Sunil V L

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=20220907113626.540065-13-sunilvl@ventanamicro.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