mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-27 07:34:06 +02:00
OvmfPkg/LoongArchVirt: Support SEC phase
Add SEC code for LoongArch virtual machine. BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4584 Cc: Ard Biesheuvel <ardb+tianocore@kernel.org> Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Gerd Hoffmann <kraxel@redhat.com> Cc: Bibo Mao <maobibo@loongson.cn> Cc: Dongyan Qian <qiandongyan@loongson.cn> Signed-off-by: Chao Li <lichao@loongson.cn> Co-authored-by: Xianglai Li <lixianglai@loongson.cn> Co-authored-by: Bibo Mao <maobibo@loongson.cn>
This commit is contained in:
parent
c63d90085b
commit
9912434785
184
OvmfPkg/LoongArchVirt/Sec/LoongArch64/Start.S
Normal file
184
OvmfPkg/LoongArchVirt/Sec/LoongArch64/Start.S
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
#------------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
# 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 global interrupt */
|
||||||
|
bl DisableInterrupts
|
||||||
|
|
||||||
|
/* Disable all local interrupt */
|
||||||
|
li.w $a0, 0x1FFF
|
||||||
|
bl DisableLocalInterrupts
|
||||||
|
|
||||||
|
/* Read physical cpu number id */
|
||||||
|
bl GetApicId
|
||||||
|
li.d $t0, BOOTCORE_ID //0
|
||||||
|
bne $a0, $t0, SlaveMain
|
||||||
|
|
||||||
|
/* Set BSP stack */
|
||||||
|
li.d $t0, FixedPcdGet64(PcdOvmfSecPeiTempRamBase) + FixedPcdGet32(PcdOvmfSecPeiTempRamSize) # stack base
|
||||||
|
move $sp, $t0
|
||||||
|
addi.d $sp, $sp, -0x8
|
||||||
|
|
||||||
|
/* Load the exception vector base address */
|
||||||
|
li.d $s0, FixedPcdGet64(PcdLoongArchExceptionVectorBaseAddress)
|
||||||
|
|
||||||
|
/* 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, $s0
|
||||||
|
bl CopyMem
|
||||||
|
|
||||||
|
/* Configure BSP reset ebase */
|
||||||
|
move $a0, $s0
|
||||||
|
bl SetExceptionBaseAddress
|
||||||
|
|
||||||
|
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.w $t1, BIT12
|
||||||
|
csrxchg $t1, $t1, LOONGARCH_CSR_ECFG
|
||||||
|
|
||||||
|
li.w $t2, 0xFFFFFFFFU
|
||||||
|
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
|
||||||
|
b WaitForWake
|
||||||
|
# End of SlaveMain
|
||||||
|
|
||||||
|
.align 12
|
||||||
|
ASM_PFX(ApException):
|
||||||
|
csrrd $t0, LOONGARCH_CSR_ESTAT
|
||||||
|
srli.d $t0, $t0, 12
|
||||||
|
andi $t0, $t0, 0x1
|
||||||
|
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
|
||||||
|
|
||||||
|
/* Read mail buf and jump to specified entry */
|
||||||
|
li.d $t1, LOONGARCH_IOCSR_MBUF0
|
||||||
|
iocsrrd.d $t0, $t1
|
||||||
|
beqz $t0, OutOfException
|
||||||
|
csrwr $t0, LOONGARCH_CSR_ERA
|
||||||
|
li.d $t0, LOONGARCH_IOCSR_MBUF3
|
||||||
|
iocsrrd.d $a1, $t0
|
||||||
|
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(PcdLoongArchExceptionVectorBaseAddress)
|
||||||
|
bl SetExceptionBaseAddress
|
||||||
|
|
||||||
|
bl ApInitStack
|
||||||
|
bl GetApicId
|
||||||
|
b OutOfException
|
||||||
|
NoParameterCall:
|
||||||
|
li.w $t0, BIT2 // IE
|
||||||
|
csrxchg $zero, $t0, LOONGARCH_CSR_PRMD // Clean PIE
|
||||||
|
|
||||||
|
OutOfException:
|
||||||
|
ertn
|
||||||
|
# End of ApException
|
||||||
|
|
||||||
|
ASM_PFX(DeadLoop):
|
||||||
|
b DeadLoop
|
||||||
|
# End of DeadLoop
|
||||||
|
.end
|
512
OvmfPkg/LoongArchVirt/Sec/SecMain.c
Normal file
512
OvmfPkg/LoongArchVirt/Sec/SecMain.c
Normal file
@ -0,0 +1,512 @@
|
|||||||
|
/** @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/PcdLib.h>
|
||||||
|
#include <Library/PeCoffLib.h>
|
||||||
|
#include <Library/PeCoffGetEntryPointLib.h>
|
||||||
|
#include <Library/PeCoffExtraActionLib.h>
|
||||||
|
#include <Library/PeiServicesLib.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.
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
TemporaryRamMigration (
|
||||||
|
IN CONST EFI_PEI_SERVICES **PeiServices,
|
||||||
|
IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
|
||||||
|
IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
|
||||||
|
IN UINTN CopySize
|
||||||
|
);
|
||||||
|
|
||||||
|
STATIC EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi = {
|
||||||
|
TemporaryRamMigration
|
||||||
|
};
|
||||||
|
|
||||||
|
STATIC 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
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
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
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
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
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
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
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
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.
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
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().
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
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 ();
|
||||||
|
|
||||||
|
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.
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
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;
|
||||||
|
}
|
54
OvmfPkg/LoongArchVirt/Sec/SecMain.inf
Normal file
54
OvmfPkg/LoongArchVirt/Sec/SecMain.inf
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
## @file
|
||||||
|
# SEC Driver
|
||||||
|
#
|
||||||
|
# Copyright (c) 2024 Loongson Technology Corporation Limited. All rights reserved.<BR>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
#
|
||||||
|
##
|
||||||
|
|
||||||
|
[Defines]
|
||||||
|
INF_VERSION = 1.30
|
||||||
|
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
|
||||||
|
PeiServicesLib
|
||||||
|
|
||||||
|
[Ppis]
|
||||||
|
gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED
|
||||||
|
|
||||||
|
[FixedPcd]
|
||||||
|
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamBase
|
||||||
|
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfSecPeiTempRamSize
|
||||||
|
|
||||||
|
gUefiCpuPkgTokenSpaceGuid.PcdLoongArchExceptionVectorBaseAddress
|
||||||
|
gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber
|
||||||
|
|
||||||
|
gUefiOvmfPkgTokenSpaceGuid.PcdOvmfFdBaseAddress
|
Loading…
x
Reference in New Issue
Block a user