[edk2-staging/RiscV64QemuVirt PATCH V7 18/20] OvmfPkg/RiscVVirt: Add SEC module


Sunil V L
 

Add the SEC module for RISC-V Qemu virt machine support.
It uses the PEI less design.

Cc: Ard Biesheuvel <ardb+tianocore@...>
Cc: Jiewen Yao <jiewen.yao@...>
Cc: Jordan Justen <jordan.l.justen@...>
Cc: Gerd Hoffmann <kraxel@...>
Signed-off-by: Sunil V L <sunilvl@...>
Acked-by: Abner Chang <abner.chang@...>
---
OvmfPkg/RiscVVirt/Sec/SecMain.inf | 66 +++++
OvmfPkg/RiscVVirt/Sec/SecMain.h | 102 ++++++++
OvmfPkg/RiscVVirt/Sec/Cpu.c | 33 +++
OvmfPkg/RiscVVirt/Sec/Memory.c | 263 ++++++++++++++++++++
OvmfPkg/RiscVVirt/Sec/Platform.c | 84 +++++++
OvmfPkg/RiscVVirt/Sec/SecMain.c | 104 ++++++++
OvmfPkg/RiscVVirt/Sec/SecEntry.S | 21 ++
7 files changed, 673 insertions(+)

diff --git a/OvmfPkg/RiscVVirt/Sec/SecMain.inf b/OvmfPkg/RiscVVirt/Sec/SecMain.inf
new file mode 100644
index 000000000000..aed35d3af596
--- /dev/null
+++ b/OvmfPkg/RiscVVirt/Sec/SecMain.inf
@@ -0,0 +1,66 @@
+## @file
+# SEC Driver for RISC-V
+#
+# Copyright (c) 2022, Ventana Micro Systems Inc. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = SecMainRiscV64
+ FILE_GUID = 16740C0A-AA84-4F62-A06D-AE328057AE07
+ 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]
+ SecEntry.S
+ SecMain.c
+ SecMain.h
+ Cpu.c
+ Memory.c
+ Platform.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ OvmfPkg/OvmfPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ PcdLib
+ IoLib
+ PeCoffLib
+ LzmaDecompressLib
+ RiscVSbiLib
+ PrePiLib
+ FdtLib
+ MemoryAllocationLib
+ HobLib
+
+[Ppis]
+ gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED
+ gEfiTemporaryRamDonePpiGuid ## PRODUCES
+
+[Pcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress
+
+[Guids]
+ gFdtHobGuid
diff --git a/OvmfPkg/RiscVVirt/Sec/SecMain.h b/OvmfPkg/RiscVVirt/Sec/SecMain.h
new file mode 100644
index 000000000000..83a8058efe40
--- /dev/null
+++ b/OvmfPkg/RiscVVirt/Sec/SecMain.h
@@ -0,0 +1,102 @@
+/** @file
+ Master header file for SecCore.
+
+ 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/BaseRiscVSbiLib.h>
+#include <Library/PrePiLib.h>
+#include <Library/PlatformInitLib.h>
+#include <Library/PrePiHobListPointerLib.h>
+#include <Register/RiscV64/RiscVImpl.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
+ );
+
+/**
+ Perform Platform PEIM initialization.
+
+ @return EFI_SUCCESS The platform initialized successfully.
+ @retval Others - As the error code indicates
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformPeimInitialization (
+ VOID
+ );
+
+/**
+ Perform Memory PEIM initialization.
+
+ @return EFI_SUCCESS The platform initialized successfully.
+ @retval Others - As the error code indicates
+
+**/
+EFI_STATUS
+EFIAPI
+MemoryPeimInitialization (
+ VOID
+ );
+
+/**
+ Perform CPU PEIM initialization.
+
+ @return EFI_SUCCESS The platform initialized successfully.
+ @retval Others - As the error code indicates
+
+**/
+EFI_STATUS
+EFIAPI
+CpuPeimInitialization (
+ VOID
+ );
+
+#endif
diff --git a/OvmfPkg/RiscVVirt/Sec/Cpu.c b/OvmfPkg/RiscVVirt/Sec/Cpu.c
new file mode 100644
index 000000000000..2c16df697e37
--- /dev/null
+++ b/OvmfPkg/RiscVVirt/Sec/Cpu.c
@@ -0,0 +1,33 @@
+/** @file
+The library call to pass the device tree to DXE via HOB.
+
+Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+//
+//// The package level header files this module uses
+////
+#include <PiPei.h>
+
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+
+/**
+ Cpu Peim initialization.
+
+**/
+EFI_STATUS
+CpuPeimInitialization (
+ VOID
+ )
+{
+ //
+ // for MMU type >= sv39
+ //
+ BuildCpuHob (56, 32);
+
+ return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/RiscVVirt/Sec/Memory.c b/OvmfPkg/RiscVVirt/Sec/Memory.c
new file mode 100644
index 000000000000..70935b07b56b
--- /dev/null
+++ b/OvmfPkg/RiscVVirt/Sec/Memory.c
@@ -0,0 +1,263 @@
+/** @file
+ Memory Detection for Virtual Machines.
+
+ Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+ Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+Module Name:
+
+ MemDetect.c
+
+**/
+
+//
+// The package level header files this module uses
+//
+#include <PiPei.h>
+
+//
+// The Library classes this module consumes
+//
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/ResourcePublicationLib.h>
+#include <Library/BaseRiscVSbiLib.h>
+#include <Register/RiscV64/RiscVEncoding.h>
+#include <Library/PrePiLib.h>
+#include <libfdt.h>
+#include <Guid/FdtHob.h>
+
+VOID
+BuildMemoryTypeInformationHob (
+ VOID
+ );
+
+/**
+ Build reserved memory range resource HOB.
+
+ @param MemoryBase Reserved memory range base address.
+ @param MemorySize Reserved memory range size.
+
+**/
+STATIC
+VOID
+AddReservedMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ )
+{
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_MEMORY_RESERVED,
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_TESTED,
+ MemoryBase,
+ MemorySize
+ );
+}
+
+/**
+ Create memory range resource HOB using the memory base
+ address and size.
+
+ @param MemoryBase Memory range base address.
+ @param MemorySize Memory range size.
+
+**/
+STATIC
+VOID
+AddMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ )
+{
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_SYSTEM_MEMORY,
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_TESTED,
+ MemoryBase,
+ MemorySize
+ );
+}
+
+/**
+ Create memory range resource HOB using memory base
+ address and top address of the memory range.
+
+ @param MemoryBase Memory range base address.
+ @param MemoryLimit Memory range size.
+
+**/
+STATIC
+VOID
+AddMemoryRangeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ EFI_PHYSICAL_ADDRESS MemoryLimit
+ )
+{
+ AddMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));
+}
+
+/**
+ Configure MMU
+**/
+STATIC
+VOID
+InitMmu (
+ )
+{
+ //
+ // Set supervisor translation mode to Bare mode
+ //
+ RiscVSetSupervisorAddressTranslationRegister ((UINT64)SATP_MODE_OFF << 60);
+ DEBUG ((DEBUG_INFO, "%a: Set Supervisor address mode to bare-metal mode.\n", __FUNCTION__));
+}
+
+/**
+ Publish system RAM and reserve memory regions.
+
+**/
+STATIC
+VOID
+InitializeRamRegions (
+ EFI_PHYSICAL_ADDRESS SystemMemoryBase,
+ UINT64 SystemMemorySize,
+ EFI_PHYSICAL_ADDRESS MmodeResvBase,
+ UINT64 MmodeResvSize
+ )
+{
+ /*
+ * M-mode FW can be loaded anywhere in memory but should not overlap
+ * with the EDK2. This can happen if some other boot code loads the
+ * M-mode firmware.
+ *
+ * The M-mode firmware memory should be marked as reserved memory
+ * so that OS doesn't use it.
+ */
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: M-mode FW Memory Start:0x%lx End:0x%lx\n",
+ __FUNCTION__,
+ MmodeResvBase,
+ MmodeResvBase + MmodeResvSize
+ ));
+ AddReservedMemoryBaseSizeHob (MmodeResvBase, MmodeResvSize);
+
+ if (MmodeResvBase > SystemMemoryBase) {
+ AddMemoryRangeHob (SystemMemoryBase, MmodeResvBase);
+ }
+
+ AddMemoryRangeHob (
+ MmodeResvBase + MmodeResvSize,
+ SystemMemoryBase + SystemMemorySize
+ );
+}
+
+/**
+ Initialize memory hob based on the DTB information.
+
+ @return EFI_SUCCESS The memory hob added successfully.
+
+**/
+EFI_STATUS
+MemoryPeimInitialization (
+ VOID
+ )
+{
+ EFI_RISCV_FIRMWARE_CONTEXT *FirmwareContext;
+ CONST UINT64 *RegProp;
+ CONST CHAR8 *Type;
+ UINT64 CurBase, CurSize;
+ INT32 Node, Prev;
+ INT32 Len;
+ VOID *FdtPointer;
+ EFI_PHYSICAL_ADDRESS MmodeResvBase;
+ UINT64 MmodeResvSize;
+
+ FirmwareContext = NULL;
+ GetFirmwareContextPointer (&FirmwareContext);
+
+ if (FirmwareContext == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Firmware Context is NULL\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ FdtPointer = (VOID *)FirmwareContext->FlattenedDeviceTree;
+ if (FdtPointer == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Invalid FDT pointer\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ /* try to locate the reserved memory opensbi node */
+ Node = fdt_path_offset (FdtPointer, "/reserved-memory/mmode_resv0");
+ if (Node >= 0) {
+ RegProp = fdt_getprop (FdtPointer, Node, "reg", &Len);
+ if ((RegProp != 0) && (Len == (2 * sizeof (UINT64)))) {
+ MmodeResvBase = fdt64_to_cpu (ReadUnaligned64 (RegProp));
+ MmodeResvSize = fdt64_to_cpu (ReadUnaligned64 (RegProp + 1));
+ }
+ }
+
+ // Look for the lowest memory node
+ for (Prev = 0; ; Prev = Node) {
+ Node = fdt_next_node (FdtPointer, Prev, NULL);
+ if (Node < 0) {
+ break;
+ }
+
+ // Check for memory node
+ Type = fdt_getprop (FdtPointer, Node, "device_type", &Len);
+ if (Type && (AsciiStrnCmp (Type, "memory", Len) == 0)) {
+ // Get the 'reg' property of this node. For now, we will assume
+ // two 8 byte quantities for base and size, respectively.
+ RegProp = fdt_getprop (FdtPointer, Node, "reg", &Len);
+ if ((RegProp != 0) && (Len == (2 * sizeof (UINT64)))) {
+ CurBase = fdt64_to_cpu (ReadUnaligned64 (RegProp));
+ CurSize = fdt64_to_cpu (ReadUnaligned64 (RegProp + 1));
+
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: System RAM @ 0x%lx - 0x%lx\n",
+ __FUNCTION__,
+ CurBase,
+ CurBase + CurSize - 1
+ ));
+
+ if ((MmodeResvBase >= CurBase) && ((MmodeResvBase + MmodeResvSize) <= (CurBase + CurSize))) {
+ InitializeRamRegions (
+ CurBase,
+ CurSize,
+ MmodeResvBase,
+ MmodeResvSize
+ );
+ } else {
+ AddMemoryBaseSizeHob (CurBase, CurSize);
+ }
+ } else {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to parse FDT memory node\n",
+ __FUNCTION__
+ ));
+ }
+ }
+ }
+
+ InitMmu ();
+
+ BuildMemoryTypeInformationHob ();
+
+ return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/RiscVVirt/Sec/Platform.c b/OvmfPkg/RiscVVirt/Sec/Platform.c
new file mode 100644
index 000000000000..e8fd126cf800
--- /dev/null
+++ b/OvmfPkg/RiscVVirt/Sec/Platform.c
@@ -0,0 +1,84 @@
+/** @file
+The library call to pass the device tree to DXE via HOB.
+
+Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+//
+//// The package level header files this module uses
+////
+#include <PiPei.h>
+
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseRiscVSbiLib.h>
+#include <Library/PcdLib.h>
+#include <Include/Library/PrePiLib.h>
+#include <libfdt.h>
+#include <Guid/FdtHob.h>
+
+/**
+ @retval EFI_SUCCESS The address of FDT is passed in HOB.
+ EFI_UNSUPPORTED Can't locate FDT.
+**/
+EFI_STATUS
+EFIAPI
+PlatformPeimInitialization (
+ VOID
+ )
+{
+ EFI_RISCV_FIRMWARE_CONTEXT *FirmwareContext;
+ VOID *FdtPointer;
+ VOID *Base;
+ VOID *NewBase;
+ UINTN FdtSize;
+ UINTN FdtPages;
+ UINT64 *FdtHobData;
+
+ FirmwareContext = NULL;
+ GetFirmwareContextPointer (&FirmwareContext);
+
+ if (FirmwareContext == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Firmware Context is NULL\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ FdtPointer = (VOID *)FirmwareContext->FlattenedDeviceTree;
+ if (FdtPointer == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Invalid FDT pointer\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ DEBUG ((DEBUG_INFO, "%a: Build FDT HOB - FDT at address: 0x%x \n", __FUNCTION__, FdtPointer));
+ Base = FdtPointer;
+ if (fdt_check_header (Base) != 0) {
+ DEBUG ((DEBUG_ERROR, "%a: Corrupted DTB\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ FdtSize = fdt_totalsize (Base);
+ FdtPages = EFI_SIZE_TO_PAGES (FdtSize);
+ NewBase = AllocatePages (FdtPages);
+ if (NewBase == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Could not allocate memory for DTB\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ fdt_open_into (Base, NewBase, EFI_PAGES_TO_SIZE (FdtPages));
+
+ FdtHobData = BuildGuidHob (&gFdtHobGuid, sizeof *FdtHobData);
+ if (FdtHobData == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Could not build FDT Hob\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ *FdtHobData = (UINTN)NewBase;
+
+ BuildFvHob (PcdGet32 (PcdOvmfDxeMemFvBase), PcdGet32 (PcdOvmfDxeMemFvSize));
+
+ return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/RiscVVirt/Sec/SecMain.c b/OvmfPkg/RiscVVirt/Sec/SecMain.c
new file mode 100644
index 000000000000..054e49ef0c1e
--- /dev/null
+++ b/OvmfPkg/RiscVVirt/Sec/SecMain.c
@@ -0,0 +1,104 @@
+/** @file
+ RISC-V SEC phase module for Qemu Virt.
+
+ Copyright (c) 2008 - 2015, Intel Corporation. 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"
+
+STATIC
+EFI_STATUS
+EFIAPI
+SecInitializePlatform (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ MemoryPeimInitialization ();
+
+ CpuPeimInitialization ();
+
+ // Set the Boot Mode
+ SetBootMode (BOOT_WITH_FULL_CONFIGURATION);
+
+ Status = PlatformPeimInitialization ();
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ 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_HOB_HANDOFF_INFO_TABLE *HobList;
+ EFI_RISCV_FIRMWARE_CONTEXT FirmwareContext;
+ EFI_STATUS Status;
+ UINT64 UefiMemoryBase;
+ UINT64 StackBase;
+
+ //
+ // Report Status Code to indicate entering SEC core
+ //
+ DEBUG ((
+ DEBUG_INFO,
+ "%a() BootHartId: 0x%x, DeviceTreeAddress=0x%x\n",
+ __FUNCTION__,
+ BootHartId,
+ DeviceTreeAddress
+ ));
+
+ FirmwareContext.BootHartId = BootHartId;
+ FirmwareContext.FlattenedDeviceTree = (UINT64)DeviceTreeAddress;
+ SetFirmwareContextPointer (&FirmwareContext);
+
+ StackBase = (UINT64)FixedPcdGet32 (PcdOvmfSecPeiTempRamBase);
+ UefiMemoryBase = StackBase + FixedPcdGet32 (PcdOvmfSecPeiTempRamSize) - SIZE_32MB;
+
+ // Declare the PI/UEFI memory region
+ HobList = HobConstructor (
+ (VOID *)UefiMemoryBase,
+ SIZE_32MB,
+ (VOID *)UefiMemoryBase,
+ (VOID *)StackBase // The top of the UEFI Memory is reserved for the stacks
+ );
+ PrePeiSetHobList (HobList);
+
+ SecInitializePlatform ();
+
+ //
+ // Process all libraries constructor function linked to SecMain.
+ //
+ ProcessLibraryConstructorList ();
+
+ // Assume the FV that contains the SEC (our code) also contains a compressed FV.
+ Status = DecompressFirstFv ();
+ ASSERT_EFI_ERROR (Status);
+
+ // Load the DXE Core and transfer control to it
+ Status = LoadDxeCoreFromFv (NULL, 0);
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Should not come here.
+ //
+ UNREACHABLE ();
+}
diff --git a/OvmfPkg/RiscVVirt/Sec/SecEntry.S b/OvmfPkg/RiscVVirt/Sec/SecEntry.S
new file mode 100644
index 000000000000..e919a3cb0e80
--- /dev/null
+++ b/OvmfPkg/RiscVVirt/Sec/SecEntry.S
@@ -0,0 +1,21 @@
+/*
+ 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 (PcdOvmfSecPeiTempRamBase)
+ li a5, FixedPcdGet32 (PcdOvmfSecPeiTempRamSize)
+
+ /* Use Temp memory as the stack for calling to C code */
+ add sp, a4, a5
+
+ call SecStartup
--
2.38.0


Sunil V L
 

Hi Dhaval,

In general, I didn't not want to add many extra code/design  as part of this series to keep it simple  refactor and port from edk2-platforms patches. We are the first one to do this type of refactoring work and hence not easy to convince people. So, I am still keeping many things hardcoded as in edk2-platforms. Once this series gets merged, next set of patches will be mostly within RISC-V code which will be much easier to upstream.

Irrespective of SATP (>= sv39), the physical address space is 56 bits as per the priv spec. We don't plan to support RV32 with edk2 anyway.

Thanks

Sunil

On 30/01/23 10:47, dhaval@... wrote:

BuildCpuHob (56, 32); Can we find a better programmatic way of doing this? SATP register could be on method, or PCD? Also would help if you can clarify how we arrive at this value 56.


Dhaval Sharma
 

BuildCpuHob (56, 32);
Can we find a better programmatic way of doing this? SATP register could be on method, or PCD? Also would help if you can clarify how we arrive at this value 56.


Andrei Warkentin
 

Reviewed-by: Andrei Warkentin <andrei.warkentin@...>

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Sunil V L
Sent: Saturday, January 28, 2023 1:18 PM
To: devel@edk2.groups.io
Cc: Ard Biesheuvel <ardb+tianocore@...>; Yao, Jiewen <jiewen.yao@...>; Justen, Jordan L <jordan.l.justen@...>; Gerd Hoffmann <kraxel@...>; Abner Chang <abner.chang@...>
Subject: [edk2-devel] [edk2-staging/RiscV64QemuVirt PATCH V7 18/20] OvmfPkg/RiscVVirt: Add SEC module

Add the SEC module for RISC-V Qemu virt machine support.
It uses the PEI less design.

Cc: Ard Biesheuvel <ardb+tianocore@...>
Cc: Jiewen Yao <jiewen.yao@...>
Cc: Jordan Justen <jordan.l.justen@...>
Cc: Gerd Hoffmann <kraxel@...>
Signed-off-by: Sunil V L <sunilvl@...>
Acked-by: Abner Chang <abner.chang@...>
---
OvmfPkg/RiscVVirt/Sec/SecMain.inf | 66 +++++
OvmfPkg/RiscVVirt/Sec/SecMain.h | 102 ++++++++
OvmfPkg/RiscVVirt/Sec/Cpu.c | 33 +++
OvmfPkg/RiscVVirt/Sec/Memory.c | 263 ++++++++++++++++++++
OvmfPkg/RiscVVirt/Sec/Platform.c | 84 +++++++
OvmfPkg/RiscVVirt/Sec/SecMain.c | 104 ++++++++
OvmfPkg/RiscVVirt/Sec/SecEntry.S | 21 ++
7 files changed, 673 insertions(+)

diff --git a/OvmfPkg/RiscVVirt/Sec/SecMain.inf b/OvmfPkg/RiscVVirt/Sec/SecMain.inf
new file mode 100644
index 000000000000..aed35d3af596
--- /dev/null
+++ b/OvmfPkg/RiscVVirt/Sec/SecMain.inf
@@ -0,0 +1,66 @@
+## @file
+# SEC Driver for RISC-V
+#
+# Copyright (c) 2022, Ventana Micro Systems Inc. All rights
+reserved.<BR> # # SPDX-License-Identifier: BSD-2-Clause-Patent # ##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = SecMainRiscV64
+ FILE_GUID = 16740C0A-AA84-4F62-A06D-AE328057AE07
+ 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]
+ SecEntry.S
+ SecMain.c
+ SecMain.h
+ Cpu.c
+ Memory.c
+ Platform.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ UefiCpuPkg/UefiCpuPkg.dec
+ OvmfPkg/OvmfPkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ PcdLib
+ IoLib
+ PeCoffLib
+ LzmaDecompressLib
+ RiscVSbiLib
+ PrePiLib
+ FdtLib
+ MemoryAllocationLib
+ HobLib
+
+[Ppis]
+ gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED
+ gEfiTemporaryRamDonePpiGuid ## PRODUCES
+
+[Pcd]
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfDxeMemFvSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
+ gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress
+
+[Guids]
+ gFdtHobGuid
diff --git a/OvmfPkg/RiscVVirt/Sec/SecMain.h b/OvmfPkg/RiscVVirt/Sec/SecMain.h new file mode 100644 index 000000000000..83a8058efe40
--- /dev/null
+++ b/OvmfPkg/RiscVVirt/Sec/SecMain.h
@@ -0,0 +1,102 @@
+/** @file
+ Master header file for SecCore.
+
+ 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/BaseRiscVSbiLib.h>
+#include <Library/PrePiLib.h>
+#include <Library/PlatformInitLib.h>
+#include <Library/PrePiHobListPointerLib.h>
+#include <Register/RiscV64/RiscVImpl.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
+ );
+
+/**
+ Perform Platform PEIM initialization.
+
+ @return EFI_SUCCESS The platform initialized successfully.
+ @retval Others - As the error code indicates
+
+**/
+EFI_STATUS
+EFIAPI
+PlatformPeimInitialization (
+ VOID
+ );
+
+/**
+ Perform Memory PEIM initialization.
+
+ @return EFI_SUCCESS The platform initialized successfully.
+ @retval Others - As the error code indicates
+
+**/
+EFI_STATUS
+EFIAPI
+MemoryPeimInitialization (
+ VOID
+ );
+
+/**
+ Perform CPU PEIM initialization.
+
+ @return EFI_SUCCESS The platform initialized successfully.
+ @retval Others - As the error code indicates
+
+**/
+EFI_STATUS
+EFIAPI
+CpuPeimInitialization (
+ VOID
+ );
+
+#endif
diff --git a/OvmfPkg/RiscVVirt/Sec/Cpu.c b/OvmfPkg/RiscVVirt/Sec/Cpu.c new file mode 100644 index 000000000000..2c16df697e37
--- /dev/null
+++ b/OvmfPkg/RiscVVirt/Sec/Cpu.c
@@ -0,0 +1,33 @@
+/** @file
+The library call to pass the device tree to DXE via HOB.
+
+Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All
+rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+//
+//// The package level header files this module uses //// #include
+<PiPei.h>
+
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+
+/**
+ Cpu Peim initialization.
+
+**/
+EFI_STATUS
+CpuPeimInitialization (
+ VOID
+ )
+{
+ //
+ // for MMU type >= sv39
+ //
+ BuildCpuHob (56, 32);
+
+ return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/RiscVVirt/Sec/Memory.c b/OvmfPkg/RiscVVirt/Sec/Memory.c new file mode 100644 index 000000000000..70935b07b56b
--- /dev/null
+++ b/OvmfPkg/RiscVVirt/Sec/Memory.c
@@ -0,0 +1,263 @@
+/** @file
+ Memory Detection for Virtual Machines.
+
+ Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All
+ rights reserved.<BR> Copyright (c) 2006 - 2014, Intel Corporation.
+ All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+Module Name:
+
+ MemDetect.c
+
+**/
+
+//
+// The package level header files this module uses // #include
+<PiPei.h>
+
+//
+// The Library classes this module consumes // #include
+<Library/BaseMemoryLib.h> #include <Library/DebugLib.h> #include
+<Library/HobLib.h> #include <Library/IoLib.h> #include
+<Library/PcdLib.h> #include <Library/PeimEntryPoint.h> #include
+<Library/ResourcePublicationLib.h>
+#include <Library/BaseRiscVSbiLib.h>
+#include <Register/RiscV64/RiscVEncoding.h>
+#include <Library/PrePiLib.h>
+#include <libfdt.h>
+#include <Guid/FdtHob.h>
+
+VOID
+BuildMemoryTypeInformationHob (
+ VOID
+ );
+
+/**
+ Build reserved memory range resource HOB.
+
+ @param MemoryBase Reserved memory range base address.
+ @param MemorySize Reserved memory range size.
+
+**/
+STATIC
+VOID
+AddReservedMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ )
+{
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_MEMORY_RESERVED,
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_TESTED,
+ MemoryBase,
+ MemorySize
+ );
+}
+
+/**
+ Create memory range resource HOB using the memory base
+ address and size.
+
+ @param MemoryBase Memory range base address.
+ @param MemorySize Memory range size.
+
+**/
+STATIC
+VOID
+AddMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ )
+{
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_SYSTEM_MEMORY,
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_TESTED,
+ MemoryBase,
+ MemorySize
+ );
+}
+
+/**
+ Create memory range resource HOB using memory base
+ address and top address of the memory range.
+
+ @param MemoryBase Memory range base address.
+ @param MemoryLimit Memory range size.
+
+**/
+STATIC
+VOID
+AddMemoryRangeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ EFI_PHYSICAL_ADDRESS MemoryLimit
+ )
+{
+ AddMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit -
+MemoryBase)); }
+
+/**
+ Configure MMU
+**/
+STATIC
+VOID
+InitMmu (
+ )
+{
+ //
+ // Set supervisor translation mode to Bare mode
+ //
+ RiscVSetSupervisorAddressTranslationRegister ((UINT64)SATP_MODE_OFF
+<< 60);
+ DEBUG ((DEBUG_INFO, "%a: Set Supervisor address mode to bare-metal
+mode.\n", __FUNCTION__)); }
+
+/**
+ Publish system RAM and reserve memory regions.
+
+**/
+STATIC
+VOID
+InitializeRamRegions (
+ EFI_PHYSICAL_ADDRESS SystemMemoryBase,
+ UINT64 SystemMemorySize,
+ EFI_PHYSICAL_ADDRESS MmodeResvBase,
+ UINT64 MmodeResvSize
+ )
+{
+ /*
+ * M-mode FW can be loaded anywhere in memory but should not overlap
+ * with the EDK2. This can happen if some other boot code loads the
+ * M-mode firmware.
+ *
+ * The M-mode firmware memory should be marked as reserved memory
+ * so that OS doesn't use it.
+ */
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: M-mode FW Memory Start:0x%lx End:0x%lx\n",
+ __FUNCTION__,
+ MmodeResvBase,
+ MmodeResvBase + MmodeResvSize
+ ));
+ AddReservedMemoryBaseSizeHob (MmodeResvBase, MmodeResvSize);
+
+ if (MmodeResvBase > SystemMemoryBase) {
+ AddMemoryRangeHob (SystemMemoryBase, MmodeResvBase); }
+
+ AddMemoryRangeHob (
+ MmodeResvBase + MmodeResvSize,
+ SystemMemoryBase + SystemMemorySize
+ );
+}
+
+/**
+ Initialize memory hob based on the DTB information.
+
+ @return EFI_SUCCESS The memory hob added successfully.
+
+**/
+EFI_STATUS
+MemoryPeimInitialization (
+ VOID
+ )
+{
+ EFI_RISCV_FIRMWARE_CONTEXT *FirmwareContext;
+ CONST UINT64 *RegProp;
+ CONST CHAR8 *Type;
+ UINT64 CurBase, CurSize;
+ INT32 Node, Prev;
+ INT32 Len;
+ VOID *FdtPointer;
+ EFI_PHYSICAL_ADDRESS MmodeResvBase;
+ UINT64 MmodeResvSize;
+
+ FirmwareContext = NULL;
+ GetFirmwareContextPointer (&FirmwareContext);
+
+ if (FirmwareContext == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Firmware Context is NULL\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ FdtPointer = (VOID *)FirmwareContext->FlattenedDeviceTree;
+ if (FdtPointer == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Invalid FDT pointer\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ /* try to locate the reserved memory opensbi node */ Node =
+ fdt_path_offset (FdtPointer, "/reserved-memory/mmode_resv0"); if
+ (Node >= 0) {
+ RegProp = fdt_getprop (FdtPointer, Node, "reg", &Len);
+ if ((RegProp != 0) && (Len == (2 * sizeof (UINT64)))) {
+ MmodeResvBase = fdt64_to_cpu (ReadUnaligned64 (RegProp));
+ MmodeResvSize = fdt64_to_cpu (ReadUnaligned64 (RegProp + 1));
+ }
+ }
+
+ // Look for the lowest memory node
+ for (Prev = 0; ; Prev = Node) {
+ Node = fdt_next_node (FdtPointer, Prev, NULL);
+ if (Node < 0) {
+ break;
+ }
+
+ // Check for memory node
+ Type = fdt_getprop (FdtPointer, Node, "device_type", &Len);
+ if (Type && (AsciiStrnCmp (Type, "memory", Len) == 0)) {
+ // Get the 'reg' property of this node. For now, we will assume
+ // two 8 byte quantities for base and size, respectively.
+ RegProp = fdt_getprop (FdtPointer, Node, "reg", &Len);
+ if ((RegProp != 0) && (Len == (2 * sizeof (UINT64)))) {
+ CurBase = fdt64_to_cpu (ReadUnaligned64 (RegProp));
+ CurSize = fdt64_to_cpu (ReadUnaligned64 (RegProp + 1));
+
+ DEBUG ((
+ DEBUG_INFO,
+ "%a: System RAM @ 0x%lx - 0x%lx\n",
+ __FUNCTION__,
+ CurBase,
+ CurBase + CurSize - 1
+ ));
+
+ if ((MmodeResvBase >= CurBase) && ((MmodeResvBase + MmodeResvSize) <= (CurBase + CurSize))) {
+ InitializeRamRegions (
+ CurBase,
+ CurSize,
+ MmodeResvBase,
+ MmodeResvSize
+ );
+ } else {
+ AddMemoryBaseSizeHob (CurBase, CurSize);
+ }
+ } else {
+ DEBUG ((
+ DEBUG_ERROR,
+ "%a: Failed to parse FDT memory node\n",
+ __FUNCTION__
+ ));
+ }
+ }
+ }
+
+ InitMmu ();
+
+ BuildMemoryTypeInformationHob ();
+
+ return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/RiscVVirt/Sec/Platform.c b/OvmfPkg/RiscVVirt/Sec/Platform.c
new file mode 100644
index 000000000000..e8fd126cf800
--- /dev/null
+++ b/OvmfPkg/RiscVVirt/Sec/Platform.c
@@ -0,0 +1,84 @@
+/** @file
+The library call to pass the device tree to DXE via HOB.
+
+Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All
+rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+//
+//// The package level header files this module uses //// #include
+<PiPei.h>
+
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/MemoryAllocationLib.h> #include
+<Library/BaseRiscVSbiLib.h> #include <Library/PcdLib.h> #include
+<Include/Library/PrePiLib.h> #include <libfdt.h> #include
+<Guid/FdtHob.h>
+
+/**
+ @retval EFI_SUCCESS The address of FDT is passed in HOB.
+ EFI_UNSUPPORTED Can't locate FDT.
+**/
+EFI_STATUS
+EFIAPI
+PlatformPeimInitialization (
+ VOID
+ )
+{
+ EFI_RISCV_FIRMWARE_CONTEXT *FirmwareContext;
+ VOID *FdtPointer;
+ VOID *Base;
+ VOID *NewBase;
+ UINTN FdtSize;
+ UINTN FdtPages;
+ UINT64 *FdtHobData;
+
+ FirmwareContext = NULL;
+ GetFirmwareContextPointer (&FirmwareContext);
+
+ if (FirmwareContext == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Firmware Context is NULL\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ FdtPointer = (VOID *)FirmwareContext->FlattenedDeviceTree;
+ if (FdtPointer == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Invalid FDT pointer\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ DEBUG ((DEBUG_INFO, "%a: Build FDT HOB - FDT at address: 0x%x \n",
+ __FUNCTION__, FdtPointer)); Base = FdtPointer; if (fdt_check_header
+ (Base) != 0) {
+ DEBUG ((DEBUG_ERROR, "%a: Corrupted DTB\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ FdtSize = fdt_totalsize (Base);
+ FdtPages = EFI_SIZE_TO_PAGES (FdtSize); NewBase = AllocatePages
+ (FdtPages); if (NewBase == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Could not allocate memory for DTB\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ fdt_open_into (Base, NewBase, EFI_PAGES_TO_SIZE (FdtPages));
+
+ FdtHobData = BuildGuidHob (&gFdtHobGuid, sizeof *FdtHobData); if
+ (FdtHobData == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Could not build FDT Hob\n", __FUNCTION__));
+ return EFI_UNSUPPORTED;
+ }
+
+ *FdtHobData = (UINTN)NewBase;
+
+ BuildFvHob (PcdGet32 (PcdOvmfDxeMemFvBase), PcdGet32
+ (PcdOvmfDxeMemFvSize));
+
+ return EFI_SUCCESS;
+}
diff --git a/OvmfPkg/RiscVVirt/Sec/SecMain.c b/OvmfPkg/RiscVVirt/Sec/SecMain.c new file mode 100644 index 000000000000..054e49ef0c1e
--- /dev/null
+++ b/OvmfPkg/RiscVVirt/Sec/SecMain.c
@@ -0,0 +1,104 @@
+/** @file
+ RISC-V SEC phase module for Qemu Virt.
+
+ Copyright (c) 2008 - 2015, Intel Corporation. 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"
+
+STATIC
+EFI_STATUS
+EFIAPI
+SecInitializePlatform (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ MemoryPeimInitialization ();
+
+ CpuPeimInitialization ();
+
+ // Set the Boot Mode
+ SetBootMode (BOOT_WITH_FULL_CONFIGURATION);
+
+ Status = PlatformPeimInitialization (); ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+/**
+
+ 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_HOB_HANDOFF_INFO_TABLE *HobList;
+ EFI_RISCV_FIRMWARE_CONTEXT FirmwareContext;
+ EFI_STATUS Status;
+ UINT64 UefiMemoryBase;
+ UINT64 StackBase;
+
+ //
+ // Report Status Code to indicate entering SEC core // DEBUG ((
+ DEBUG_INFO,
+ "%a() BootHartId: 0x%x, DeviceTreeAddress=0x%x\n",
+ __FUNCTION__,
+ BootHartId,
+ DeviceTreeAddress
+ ));
+
+ FirmwareContext.BootHartId = BootHartId;
+ FirmwareContext.FlattenedDeviceTree = (UINT64)DeviceTreeAddress;
+ SetFirmwareContextPointer (&FirmwareContext);
+
+ StackBase = (UINT64)FixedPcdGet32 (PcdOvmfSecPeiTempRamBase);
+ UefiMemoryBase = StackBase + FixedPcdGet32
+ (PcdOvmfSecPeiTempRamSize) - SIZE_32MB;
+
+ // Declare the PI/UEFI memory region
+ HobList = HobConstructor (
+ (VOID *)UefiMemoryBase,
+ SIZE_32MB,
+ (VOID *)UefiMemoryBase,
+ (VOID *)StackBase // The top of the UEFI Memory is reserved for the stacks
+ );
+ PrePeiSetHobList (HobList);
+
+ SecInitializePlatform ();
+
+ //
+ // Process all libraries constructor function linked to SecMain.
+ //
+ ProcessLibraryConstructorList ();
+
+ // Assume the FV that contains the SEC (our code) also contains a compressed FV.
+ Status = DecompressFirstFv ();
+ ASSERT_EFI_ERROR (Status);
+
+ // Load the DXE Core and transfer control to it
+ Status = LoadDxeCoreFromFv (NULL, 0);
+ ASSERT_EFI_ERROR (Status);
+ //
+ // Should not come here.
+ //
+ UNREACHABLE ();
+}
diff --git a/OvmfPkg/RiscVVirt/Sec/SecEntry.S b/OvmfPkg/RiscVVirt/Sec/SecEntry.S
new file mode 100644
index 000000000000..e919a3cb0e80
--- /dev/null
+++ b/OvmfPkg/RiscVVirt/Sec/SecEntry.S
@@ -0,0 +1,21 @@
+/*
+ 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 (PcdOvmfSecPeiTempRamBase)
+ li a5, FixedPcdGet32 (PcdOvmfSecPeiTempRamSize)
+
+ /* Use Temp memory as the stack for calling to C code */
+ add sp, a4, a5
+
+ call SecStartup
--
2.38.0