Reviewed-by: Chao Li Thanks, Chao -------- On 11月 11 2022, at 5:12 δΈ‹εˆ, xianglai li wrote: > Add SEC Code And Readme.md for LoongArchQemu > > > > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4054 > > > Cc: Bibo Mao > Cc: Chao Li > Cc: Leif Lindholm > Cc: Liming Gao > Cc: Michael D Kinney > Signed-off-by: xianglai li > Signed-off-by: xianglai li > --- > .../Include/LoongArchQemuPlatform.h | 2 +- > .../Loongson/LoongArchQemuPkg/Loongson.dec | 38 ++ > .../Loongson/LoongArchQemuPkg/Loongson.dsc | 122 +++++ > .../Loongson/LoongArchQemuPkg/Loongson.fdf | 53 ++ > .../LoongArchQemuPkg/Loongson.fdf.inc | 21 + > .../LoongArchQemuPkg/Sec/LoongArch64/Start.S | 84 +++ > .../Loongson/LoongArchQemuPkg/Sec/SecMain.c | 494 ++++++++++++++++++ > .../Loongson/LoongArchQemuPkg/Sec/SecMain.inf | 51 ++ > 8 files changed, 864 insertions(+), 1 deletion(-) > create mode 100644 Platform/Loongson/LoongArchQemuPkg/Loongson.dec > create mode 100644 Platform/Loongson/LoongArchQemuPkg/Loongson.dsc > create mode 100644 Platform/Loongson/LoongArchQemuPkg/Loongson.fdf > create mode 100644 Platform/Loongson/LoongArchQemuPkg/Loongson.fdf.inc > create mode 100644 Platform/Loongson/LoongArchQemuPkg/Sec/LoongArch64/Start.S > create mode 100644 Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.c > create mode 100644 Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.inf > > > diff --git a/Platform/Loongson/LoongArchQemuPkg/Include/LoongArchQemuPlatform.h b/Platform/Loongson/LoongArchQemuPkg/Include/LoongArchQemuPlatform.h > index e942e6a994..d003b9013d 100644 > --- a/Platform/Loongson/LoongArchQemuPkg/Include/LoongArchQemuPlatform.h > +++ b/Platform/Loongson/LoongArchQemuPkg/Include/LoongArchQemuPlatform.h > @@ -92,4 +92,4 @@ > #define UART_BASE_ADDRESS (0x1fe001e0) > #define UART_BPS (115200) > #define UART_WAIT_TIMOUT (1000000) > -#endif > +#endif // LOONGARCH_QEMU_PLATFORM_H_ > diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.dec b/Platform/Loongson/LoongArchQemuPkg/Loongson.dec > new file mode 100644 > index 0000000000..61f600b20d > --- /dev/null > +++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.dec > @@ -0,0 +1,38 @@ > +## @file > +# > +# Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.
> +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > + > +[Defines] > + DEC_SPECIFICATION = 0x00010005 > + PACKAGE_NAME = LoongArchQemuPkg > + PACKAGE_GUID = b51d765a-41da-45fc-a537-de3ee785c0f6 > + PACKAGE_VERSION = 0.1 > + > +################################################################################ > +# > +# Include Section - list of Include Paths that are provided by this package. > +# Comments are used for Keywords and Module Types. > +# > +# Supported Module Types: > +# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER > +# DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION > +# > +################################################################################ > +[Includes.common] > + Include # Root include for the package > + > +[Guids] > + gLoongArchQemuPkgTokenSpaceGuid = { 0x0e0383ce, 0x0151, 0x4d01, { 0x80, 0x0e, 0x3f, 0xef, 0x8b, 0x27, 0x6d, 0x52 } } > + > +## In the PcdsFixedAtBuild and PcdsDynamic areas, numbers start at 0x0. > +[PcdsFixedAtBuild, PcdsDynamic] > + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashPeiFvBase|0x0|UINT64|0x00000000 > + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashPeiFvSize|0x0|UINT32|0x00000001 > + gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamBase|0|UINT64|0x0000000b > + gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamSize|0|UINT32|0x0000000c > + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvBase|0x0|UINT64|0x0000000f > + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvSize|0x0|UINT32|0x00000010 > diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc b/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc > new file mode 100644 > index 0000000000..b506f70625 > --- /dev/null > +++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc > @@ -0,0 +1,122 @@ > +## @file > +# > +# Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.
> +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > + > +################################################################################ > +# > +# Defines Section - statements that will be processed to create a Makefile. > +# > +############################################################################### > +[Defines] > + PLATFORM_NAME = LoongArchQemu > + PLATFORMPKG_NAME = LoongArchQemu > + PLATFORM_GUID = 7926ea52-b0dc-4ee8-ac63-341eebd84ed4 > + PLATFORM_VERSION = 0.1 > + DSC_SPECIFICATION = 0x00010005 > + OUTPUT_DIRECTORY = Build/$(PLATFORM_NAME) > + SUPPORTED_ARCHITECTURES = LOONGARCH64 > + BUILD_TARGETS = DEBUG|RELEASE > + SKUID_IDENTIFIER = DEFAULT > + FLASH_DEFINITION = Platform/Loongson/LoongArchQemuPkg/Loongson.fdf > + TTY_TERMINAL = FALSE > + > +############################################################################ > +# > +# Defines for default states. These can be changed on the command line. > +# -D FLAG=VALUE > +############################################################################ > +[BuildOptions] > + GCC:RELEASE_*_*_CC_FLAGS = -DSPEEDUP > + > + # > + # Disable deprecated APIs. > + # > + GCC:*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES > + > +[BuildOptions.LOONGARCH64.EDKII.SEC] > + *_*_*_CC_FLAGS = > + > +[BuildOptions.common.EDKII.DXE_CORE,BuildOptions.common.EDKII.DXE_DRIVER,BuildOptions.common.EDKII.UEFI_DRIVER,BuildOptions.common.EDKII.UEFI_APPLICATION] > + GCC:*_*_*_DLINK_FLAGS = -z common-page-size=0x1000 > + > +[BuildOptions.common.EDKII.DXE_RUNTIME_DRIVER] > + GCC:*_*_LOONGARCH64_DLINK_FLAGS = -z common-page-size=0x10000 > + > +################################################################################ > +# > +# Library Class section - list of all Library Classes needed by this Platform. > +# > +################################################################################ > + > +!include MdePkg/MdeLibs.dsc.inc > + > +[LibraryClasses.common] > + PcdLib | MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf > + PrintLib | MdePkg/Library/BasePrintLib/BasePrintLib.inf > + BaseMemoryLib | MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf > + BaseLib | MdePkg/Library/BaseLib/BaseLib.inf > + PeCoffLib | MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf > + PeCoffGetEntryPointLib | MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf > + IoLib | MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf > + SerialPortLib | Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/SerialPortLib.inf > + DebugPrintErrorLevelLib | MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf > + PeCoffExtraActionLib | MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf > + DebugAgentLib | MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf > + > +################################################################################ > +# > +# Pcd Section - list of all EDK II PCD Entries defined by this Platform. > +# > +################################################################################ > +[PcdsFixedAtBuild] > +## BaseLib ## > + gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength | 1000000 > + gEfiMdePkgTokenSpaceGuid.PcdMaximumAsciiStringLength | 1000000 > + gEfiMdePkgTokenSpaceGuid.PcdMaximumLinkedListLength | 1000000 > + > + gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel | 0x8000004F > + # DEBUG_INIT 0x00000001 // Initialization > + # DEBUG_WARN 0x00000002 // Warnings > + # DEBUG_LOAD 0x00000004 // Load events > + # DEBUG_FS 0x00000008 // EFI File system > + # DEBUG_POOL 0x00000010 // Alloc & Free (pool) > + # DEBUG_PAGE 0x00000020 // Alloc & Free (page) > + # DEBUG_INFO 0x00000040 // Informational debug messages > + # DEBUG_DISPATCH 0x00000080 // PEI/DXE/SMM Dispatchers > + # DEBUG_VARIABLE 0x00000100 // Variable > + # DEBUG_BM 0x00000400 // Boot Manager > + # DEBUG_BLKIO 0x00001000 // BlkIo Driver > + # DEBUG_NET 0x00004000 // Network Io Driver > + # DEBUG_UNDI 0x00010000 // UNDI Driver > + # DEBUG_LOADFILE 0x00020000 // LoadFile > + # DEBUG_EVENT 0x00080000 // Event messages > + # DEBUG_GCD 0x00100000 // Global Coherency Database changes > + # DEBUG_CACHE 0x00200000 // Memory range cachability changes > + # DEBUG_VERBOSE 0x00400000 // Detailed debug messages that may > + # DEBUG_ERROR 0x80000000 // Error > + > +!if $(TARGET) == RELEASE > + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask | 0x21 > +!else > + gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask | 0x2f > +!endif > + # DEBUG_ASSERT_ENABLED 0x01 > + # DEBUG_PRINT_ENABLED 0x02 > + # DEBUG_CODE_ENABLED 0x04 > + # CLEAR_MEMORY_ENABLED 0x08 > + # ASSERT_BREAKPOINT_ENABLED 0x10 > + # ASSERT_DEADLOOP_ENABLED 0x20 > + > + gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamBase | 0x10000 > + gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamSize | 0x10000 > + > +[Components] > + > + # > + # SEC Phase modules > + # > + Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.inf > diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf b/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf > new file mode 100644 > index 0000000000..9685795cda > --- /dev/null > +++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf > @@ -0,0 +1,53 @@ > +## @file > +# > +# Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.
> +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > + > +##################################################################################################### > +[Defines] > +!include Loongson.fdf.inc > + > +##################################################################################################### > +[FD.QEMU_EFI] > +BaseAddress = $(FD_BASE_ADDRESS) > +Size = $(FD_SIZE) > +ErasePolarity = 1 > +BlockSize = $(BLOCK_SIZE) > +NumBlocks = $(FD_BLOCKS) > + > +$(SECFV_OFFSET)|$(SECFV_SIZE) > +gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvBase|gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvSize > +FV = SECFV > + > +##################################################################################################### > +[FV.SECFV] > +FvNameGuid = 587d4265-5e71-41da-9c35-4258551f1e22 > +BlockSize = $(BLOCK_SIZE) > +FvAlignment = 16 > +ERASE_POLARITY = 1 > +MEMORY_MAPPED = TRUE > +STICKY_WRITE = TRUE > +LOCK_CAP = TRUE > +LOCK_STATUS = TRUE > +WRITE_DISABLED_CAP = TRUE > +WRITE_ENABLED_CAP = TRUE > +WRITE_STATUS = TRUE > +WRITE_LOCK_CAP = TRUE > +WRITE_LOCK_STATUS = TRUE > +READ_DISABLED_CAP = TRUE > +READ_ENABLED_CAP = TRUE > +READ_STATUS = TRUE > +READ_LOCK_CAP = TRUE > +READ_LOCK_STATUS = TRUE > + > +INF Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.inf > + > +##################################################################################################### > +[Rule.Common.SEC] > + FILE SEC = $(NAMED_GUID) { > + TE TE Align = Auto $(INF_OUTPUT)/$(MODULE_NAME).efi > + UI STRING ="$(MODULE_NAME)" Optional > + } > diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf.inc b/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf.inc > new file mode 100644 > index 0000000000..6f17909748 > --- /dev/null > +++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf.inc > @@ -0,0 +1,21 @@ > +## @file > +# > +# Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.
> +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > + > +DEFINE BLOCK_SIZE = 0x1000 > + > +############################################################################ > +# fd total > +DEFINE FD_BASE_ADDRESS = 0x1c000000 > +DEFINE FD_BLOCKS = 0x400 > +DEFINE FD_SIZE = 0x400000 > + > +############################################################################ > +#flash code layout > +#Set Sec base address and size in flash > +DEFINE SECFV_OFFSET = 0x00000000 > +DEFINE SECFV_SIZE = 0x00010000 > diff --git a/Platform/Loongson/LoongArchQemuPkg/Sec/LoongArch64/Start.S b/Platform/Loongson/LoongArchQemuPkg/Sec/LoongArch64/Start.S > new file mode 100644 > index 0000000000..5d7ce313c0 > --- /dev/null > +++ b/Platform/Loongson/LoongArchQemuPkg/Sec/LoongArch64/Start.S > @@ -0,0 +1,84 @@ > +#------------------------------------------------------------------------------ > +# > +# Start for LoongArch > +# > +# Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.
> +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +# @par Glossary: > +# - CSR - CPU Status Register > +# - EBASE - Exception Base Address > +#------------------------------------------------------------------------------ > +#ifndef __ASSEMBLY__ > +#define __ASSEMBLY__ > +#endif > + > +#include > + > +ASM_GLOBAL ASM_PFX(_ModuleEntryPoint) > +ASM_GLOBAL ASM_PFX(DeadLoop) > + > +.text > +ASM_PFX(_ModuleEntryPoint): > + /* configure reset ebase */ > + la.pcrel T0, DeadLoop > + csrwr T0, LOONGARCH_CSR_EBASE > + > + /*disable interrupt*/ > + li.d T0, (1 << 2) > + csrxchg ZERO, T0, LOONGARCH_CSR_CRMD > + > + /* read physical cpu number id */ > + csrrd T0, LOONGARCH_CSR_CPUNUM > + andi T0, T0, 0x3ff > + li.d A0, BOOTCORE_ID //0 > + bne T0, A0, slave_main > + > +call_centry: > + /*call C function make sure parameter true*/ > + li.d A1, FixedPcdGet64(PcdSecPeiTempRamBase) + FixedPcdGet32(PcdSecPeiTempRamSize) # stack base > + li.d A0, FixedPcdGet64(PcdFlashPeiFvBase) # PEI Fv base > + move SP, A1 > + addi.d SP, SP, -0x8 > + bl SecCoreStartupWithStack > + > +slave_main: > + # clear mailbox > + li.d T1, LOONGSON_CSR_MAIL_BUF0 > + iocsrwr.d ZERO, T1 > + > + # enable IPI interrupt > + li.d T0, (1 << 12) > + csrxchg T0, T0, LOONGARCH_CSR_ECFG > + > + addi.d T0, ZERO, -1 > + li.d T1, LOONGSON_IOCSR_IPI_EN > + iocsrwr.w T0, T1 > + > +1: > + # wait for wakeup > + idle 0 > + nop > + iocsrrd.w T0, T1 > + beqz T0, 1b > + > + # read and clear ipi interrupt > + li.d T1, LOONGSON_IOCSR_IPI_STATUS > + iocsrrd.w T0, T1 > + li.d T1, LOONGSON_IOCSR_IPI_CLEAR > + iocsrwr.w T0, T1 > + > + # disable IPI interrupt > + li.d T0, (1 << 12) > + csrxchg ZERO, T0, LOONGARCH_CSR_ECFG > + > + # read mail buf and jump to specified entry > + li.d T1, LOONGSON_CSR_MAIL_BUF0 > + iocsrrd.d T0, T1 > + or RA, T0, ZERO > + jirl ZERO, RA, 0x0 > + > +.align 12 > +ASM_PFX(DeadLoop): > + b DeadLoop > diff --git a/Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.c b/Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.c > new file mode 100644 > index 0000000000..3f1998c48c > --- /dev/null > +++ b/Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.c > @@ -0,0 +1,494 @@ > +/** @file > + Main SEC phase code. Transitions to PEI. > + > + Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > + > +/** > + temporary memory to permanent memory and do stack switching. > + > + @param[in] PeiServices Pointer to the PEI Services Table. > + @param[in] TemporaryMemoryBase Temporary Memory Base address. > + @param[in] PermanentMemoryBase Permanent Memory Base address. > + @param[in] CopySize The size of memory that needs to be migrated. > + > + @retval EFI_SUCCESS Migration successful. > +**/ > +EFI_STATUS > +EFIAPI > +TemporaryRamMigration ( > + IN CONST EFI_PEI_SERVICES **PeiServices, > + IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, > + IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, > + IN UINTN CopySize > + ); > + > +EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi = { > + TemporaryRamMigration > +}; > + > +EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTable[] = { > + { > + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), > + &gEfiTemporaryRamSupportPpiGuid, > + &mTemporaryRamSupportPpi > + }, > +}; > + > +/** > + Locates a section within a series of sections > + with the specified section type. > + > + The Instance parameter indicates which instance of the section > + type to return. (0 is first instance, 1 is second...) > + > + @param[in] Sections The sections to search > + @param[in] SizeOfSections Total size of all sections > + @param[in] SectionType The section type to locate > + @param[in] Instance The section instance number > + @param[out] FoundSection The FFS section if found > + > + @retval EFI_SUCCESS The file and section was found > + @retval EFI_NOT_FOUND The file and section was not found > + @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted > +**/ > +EFI_STATUS > +FindFfsSectionInstance ( > + IN VOID *Sections, > + IN UINTN SizeOfSections, > + IN EFI_SECTION_TYPE SectionType, > + IN UINTN Instance, > + OUT EFI_COMMON_SECTION_HEADER **FoundSection > + ) > +{ > + EFI_PHYSICAL_ADDRESS CurrentAddress; > + UINT32 Size; > + EFI_PHYSICAL_ADDRESS EndOfSections; > + EFI_COMMON_SECTION_HEADER *Section; > + EFI_PHYSICAL_ADDRESS EndOfSection; > + > + // > + // Loop through the FFS file sections within the PEI Core FFS file > + // > + EndOfSection = (EFI_PHYSICAL_ADDRESS) (UINTN) Sections; > + EndOfSections = EndOfSection + SizeOfSections; > + for (;;) { > + if (EndOfSection == EndOfSections) { > + break; > + } > + CurrentAddress = (EndOfSection + 3) & ~(3ULL); > + if (CurrentAddress >= EndOfSections) { > + return EFI_VOLUME_CORRUPTED; > + } > + > + Section = (EFI_COMMON_SECTION_HEADER*) (UINTN) CurrentAddress; > + > + Size = SECTION_SIZE (Section); > + if (Size < sizeof (*Section)) { > + return EFI_VOLUME_CORRUPTED; > + } > + > + EndOfSection = CurrentAddress + Size; > + if (EndOfSection > EndOfSections) { > + return EFI_VOLUME_CORRUPTED; > + } > + > + // > + // Look for the requested section type > + // > + if (Section->Type == SectionType) { > + if (Instance == 0) { > + *FoundSection = Section; > + return EFI_SUCCESS; > + } else { > + Instance--; > + } > + } > + } > + > + return EFI_NOT_FOUND; > +} > + > +/** > + Locates a section within a series of sections > + with the specified section type. > + > + @param[in] Sections The sections to search > + @param[in] SizeOfSections Total size of all sections > + @param[in] SectionType The section type to locate > + @param[out] FoundSection The FFS section if found > + > + @retval EFI_SUCCESS The file and section was found > + @retval EFI_NOT_FOUND The file and section was not found > + @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted > +**/ > +EFI_STATUS > +FindFfsSectionInSections ( > + IN VOID *Sections, > + IN UINTN SizeOfSections, > + IN EFI_SECTION_TYPE SectionType, > + OUT EFI_COMMON_SECTION_HEADER **FoundSection > + ) > +{ > + return FindFfsSectionInstance ( > + Sections, > + SizeOfSections, > + SectionType, > + 0, > + FoundSection > + ); > +} > + > +/** > + Locates a FFS file with the specified file type and a section > + within that file with the specified section type. > + > + @param[in] Fv The firmware volume to search > + @param[in] FileType The file type to locate > + @param[in] SectionType The section type to locate > + @param[out] FoundSection The FFS section if found > + > + @retval EFI_SUCCESS The file and section was found > + @retval EFI_NOT_FOUND The file and section was not found > + @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted > +**/ > +EFI_STATUS > +FindFfsFileAndSection ( > + IN EFI_FIRMWARE_VOLUME_HEADER *Fv, > + IN EFI_FV_FILETYPE FileType, > + IN EFI_SECTION_TYPE SectionType, > + OUT EFI_COMMON_SECTION_HEADER **FoundSection > + ) > +{ > + EFI_STATUS Status; > + EFI_PHYSICAL_ADDRESS CurrentAddress; > + EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume; > + EFI_FFS_FILE_HEADER *File; > + UINT32 Size; > + EFI_PHYSICAL_ADDRESS EndOfFile; > + > + if (Fv->Signature != EFI_FVH_SIGNATURE) { > + DEBUG ((DEBUG_ERROR, "FV at %p does not have FV header signature\n", Fv)); > + return EFI_VOLUME_CORRUPTED; > + } > + > + CurrentAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) Fv; > + EndOfFirmwareVolume = CurrentAddress + Fv->FvLength; > + > + // > + // Loop through the FFS files in the Boot Firmware Volume > + // > + for (EndOfFile = CurrentAddress + Fv->HeaderLength; ; ) { > + > + CurrentAddress = (EndOfFile + 7) & ~(7ULL); > + if (CurrentAddress > EndOfFirmwareVolume) { > + return EFI_VOLUME_CORRUPTED; > + } > + > + File = (EFI_FFS_FILE_HEADER*) (UINTN) CurrentAddress; > + Size = *(UINT32*) File->Size & 0xffffff; > + if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) { > + return EFI_VOLUME_CORRUPTED; > + } > + > + EndOfFile = CurrentAddress + Size; > + if (EndOfFile > EndOfFirmwareVolume) { > + return EFI_VOLUME_CORRUPTED; > + } > + > + // > + // Look for the request file type > + // > + if (File->Type != FileType) { > + continue; > + } > + > + Status = FindFfsSectionInSections ( > + (VOID*) (File + 1), > + (UINTN) EndOfFile - (UINTN) (File + 1), > + SectionType, > + FoundSection > + ); > + if (!EFI_ERROR (Status) > + || (Status == EFI_VOLUME_CORRUPTED)) > + { > + return Status; > + } > + } > +} > + > +/** > + Locates the PEI Core entry point address > + > + @param[in] Fv The firmware volume to search > + @param[out] PeiCoreEntryPoint The entry point of the PEI Core image > + > + @retval EFI_SUCCESS The file and section was found > + @retval EFI_NOT_FOUND The file and section was not found > + @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted > +**/ > +EFI_STATUS > +FindPeiCoreImageBaseInFv ( > + IN EFI_FIRMWARE_VOLUME_HEADER *Fv, > + OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase > + ) > +{ > + EFI_STATUS Status; > + EFI_COMMON_SECTION_HEADER *Section; > + > + Status = FindFfsFileAndSection ( > + Fv, > + EFI_FV_FILETYPE_PEI_CORE, > + EFI_SECTION_PE32, > + &Section > + ); > + if (EFI_ERROR (Status)) { > + Status = FindFfsFileAndSection ( > + Fv, > + EFI_FV_FILETYPE_PEI_CORE, > + EFI_SECTION_TE, > + &Section > + ); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "Unable to find PEI Core image\n")); > + return Status; > + } > + } > + > + *PeiCoreImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(Section + 1); > + return EFI_SUCCESS; > +} > + > +/** > + Find and return Pei Core entry point. > + > + It also find SEC and PEI Core file debug information. It will report them if > + remote debug is enabled. > +**/ > +VOID > +FindAndReportEntryPoints ( > + IN EFI_FIRMWARE_VOLUME_HEADER **BootFirmwareVolumePtr, > + OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint > + ) > +{ > + EFI_STATUS Status; > + EFI_PHYSICAL_ADDRESS PeiCoreImageBase = 0; > + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; > + > + Status = FindPeiCoreImageBaseInFv (*BootFirmwareVolumePtr, &PeiCoreImageBase); > + ASSERT (Status == EFI_SUCCESS); > + > + ZeroMem ((VOID *) &ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT)); > + > + // > + // Report PEI Core debug information when remote debug is enabled > + // > + ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageBase; > + ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress); > + PeCoffLoaderRelocateImageExtraAction (&ImageContext); > + > + // > + // Find PEI Core entry point > + // > + Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, (VOID**) PeiCoreEntryPoint); > + if (EFI_ERROR (Status)) { > + *PeiCoreEntryPoint = 0; > + } > + > + return; > +} > + > +/** > + Find the peicore entry point and jump to the entry point to execute. > + > + @param[in] Context The first input parameter of InitializeDebugAgent(). > +**/ > +VOID > +EFIAPI > +SecStartupPhase2 ( > + IN VOID *Context > + ) > +{ > + EFI_SEC_PEI_HAND_OFF *SecCoreData; > + EFI_FIRMWARE_VOLUME_HEADER *BootFv; > + EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint; > + > + SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context; > + > + // > + // Find PEI Core entry point. It will report SEC and Pei Core debug information if remote debug > + // is enabled. > + // > + BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase; > + FindAndReportEntryPoints (&BootFv, &PeiCoreEntryPoint); > + SecCoreData->BootFirmwareVolumeBase = BootFv; > + SecCoreData->BootFirmwareVolumeSize = (UINTN) BootFv->FvLength; > + > + DEBUG ((DEBUG_INFO, "Find Pei EntryPoint=%p\n", PeiCoreEntryPoint)); > + > + // > + // Transfer the control to the PEI core > + // > + DEBUG ((DEBUG_INFO, "SecStartupPhase2 %p\n", PeiCoreEntryPoint)); > + > + (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTable); > + > + // > + // If we get here then the PEI Core returned, which is not recoverable. > + // > + ASSERT (FALSE); > + CpuDeadLoop (); > +} > +/** > + Entry point to the C language phase of SEC. initialize some temporary memory and set up the stack, > + the control is transferred to this function. > + > + @param[in] BootFv The pointer to the PEI FV in memory. > + @param[in] TopOfCurrentStack Top of Current Stack. > +**/ > +VOID > +EFIAPI > +SecCoreStartupWithStack ( > + IN EFI_FIRMWARE_VOLUME_HEADER *BootFv, > + IN VOID *TopOfCurrentStack > + ) > +{ > + EFI_SEC_PEI_HAND_OFF SecCoreData; > + EFI_FIRMWARE_VOLUME_HEADER *BootPeiFv = (EFI_FIRMWARE_VOLUME_HEADER*) BootFv; > + > + DEBUG ((DEBUG_INFO, "Entering C environment\n")); > + > + ProcessLibraryConstructorList (NULL, NULL); > + > + DEBUG ((DEBUG_INFO, > + "SecCoreStartupWithStack (0x%lx, 0x%lx)\n", > + (UINTN)BootFv, > + (UINTN)TopOfCurrentStack > + )); > + DEBUG ((DEBUG_INFO, > + "(0x%lx, 0x%lx)\n", > + (UINTN) (PcdGet64 (PcdSecPeiTempRamBase)), > + (UINTN) (PcdGet32 (PcdSecPeiTempRamSize)) > + )); > + > + // |-------------| <-- TopOfCurrentStack > + // | Stack | 32k > + // |-------------| > + // | Heap | 32k > + // |-------------| <-- SecCoreData.TemporaryRamBase > + // > + > + ASSERT ((UINTN) (PcdGet64 (PcdSecPeiTempRamBase) + > + PcdGet32 (PcdSecPeiTempRamSize)) == > + (UINTN) TopOfCurrentStack); > + > + // > + // Initialize SEC hand-off state > + // > + SecCoreData.DataSize = sizeof (EFI_SEC_PEI_HAND_OFF); > + > + SecCoreData.TemporaryRamSize = (UINTN) PcdGet32 (PcdSecPeiTempRamSize); > + SecCoreData.TemporaryRamBase = (VOID *) PcdGet64 (PcdSecPeiTempRamBase); > + > + SecCoreData.PeiTemporaryRamBase = SecCoreData.TemporaryRamBase; > + SecCoreData.PeiTemporaryRamSize = SecCoreData.TemporaryRamSize >> 1; > + > + SecCoreData.StackBase = (UINT8 *)SecCoreData.TemporaryRamBase + SecCoreData.PeiTemporaryRamSize; > + SecCoreData.StackSize = SecCoreData.TemporaryRamSize >> 1; > + > + SecCoreData.BootFirmwareVolumeBase = BootPeiFv; > + SecCoreData.BootFirmwareVolumeSize = (UINTN) BootPeiFv->FvLength; > + > + DEBUG ((DEBUG_INFO, > + "&SecCoreData.BootFirmwareVolumeBase=%lx SecCoreData.BootFirmwareVolumeBase=%lx\n", > + (UINT64)&(SecCoreData.BootFirmwareVolumeBase), > + (UINT64) (SecCoreData.BootFirmwareVolumeBase))); > + DEBUG ((DEBUG_INFO, > + "&SecCoreData.BootFirmwareVolumeSize=%lx SecCoreData.BootFirmwareVolumeSize=%lx\n", > + (UINT64)&(SecCoreData.BootFirmwareVolumeSize), > + (UINT64) (SecCoreData.BootFirmwareVolumeSize))); > + > + // > + // Initialize Debug Agent to support source level debug in SEC/PEI phases before memory ready. > + // > + InitializeDebugAgent (DEBUG_AGENT_INIT_PREMEM_SEC, NULL, NULL); > + SecStartupPhase2 (&SecCoreData); > +} > + > +/** > + temporary memory to permanent memory and do stack switching. > + > + @param[in] PeiServices Pointer to the PEI Services Table. > + @param[in] TemporaryMemoryBase Temporary Memory Base address. > + @param[in] PermanentMemoryBase Permanent Memory Base address. > + @param[in] CopySize The size of memory that needs to be migrated. > + > + @retval EFI_SUCCESS Migration successful. > +**/ > +EFI_STATUS > +EFIAPI > +TemporaryRamMigration ( > + IN CONST EFI_PEI_SERVICES **PeiServices, > + IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase, > + IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase, > + IN UINTN CopySize > + ) > +{ > + VOID *OldHeap; > + VOID *NewHeap; > + VOID *OldStack; > + VOID *NewStack; > + BASE_LIBRARY_JUMP_BUFFER JumpBuffer; > + > + DEBUG ((DEBUG_INFO, > + "TemporaryRamMigration (0x%Lx, 0x%Lx, 0x%Lx)\n", > + TemporaryMemoryBase, > + PermanentMemoryBase, > + (UINT64)CopySize > + )); > + > + OldHeap = (VOID*) (UINTN)TemporaryMemoryBase; > + NewHeap = (VOID*) ((UINTN)PermanentMemoryBase + (CopySize >> 1)); > + > + OldStack = (VOID*) ((UINTN)TemporaryMemoryBase + (CopySize >> 1)); > + NewStack = (VOID*) (UINTN)PermanentMemoryBase; > + > + // > + // Migrate Heap > + // > + CopyMem (NewHeap, OldHeap, CopySize >> 1); > + > + // > + // Migrate Stack > + // > + CopyMem (NewStack, OldStack, CopySize >> 1); > + > + // Use SetJump ()/LongJump () to switch to a new stack. > + // > + if (SetJump (&JumpBuffer) == 0) { > + JumpBuffer.SP = JumpBuffer.SP - (UINTN)OldStack + (UINTN)NewStack ; > + LongJump (&JumpBuffer, (UINTN)-1); > + } > + > + return EFI_SUCCESS; > +} > diff --git a/Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.inf b/Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.inf > new file mode 100644 > index 0000000000..c0d5439d53 > --- /dev/null > +++ b/Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.inf > @@ -0,0 +1,51 @@ > +## @file > +# SEC Driver > +# > +# Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.
> +# > +# SPDX-License-Identifier: BSD-2-Clause-Patent > +# > +## > + > +[Defines] > + INF_VERSION = 0x00010005 > + BASE_NAME = SecMain > + FILE_GUID = 57d02d4f-5a5d-4bfa-b7d6-ba0a4d2c72ce > + MODULE_TYPE = SEC > + VERSION_STRING = 1.0 > + > +# > +# VALID_ARCHITECTURES = LOONGARCH64 > +# > + > +[Sources] > + LoongArch64/Start.S > + SecMain.c > + > +[Packages] > + Platform/Loongson/LoongArchQemuPkg/Loongson.dec > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + > +[LibraryClasses] > + BaseLib > + DebugLib > + BaseMemoryLib > + PcdLib > + DebugAgentLib > + IoLib > + PeCoffLib > + PeCoffGetEntryPointLib > + PeCoffExtraActionLib > + > +[Ppis] > + gEfiTemporaryRamSupportPpiGuid # PPI ALWAYS_PRODUCED > + > +[FixedPcd] > + gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamBase > + gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamSize > + > + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvBase > + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvSize > + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashPeiFvBase > + gLoongArchQemuPkgTokenSpaceGuid.PcdFlashPeiFvSize > -- > 2.31.1