From: "xianglai" <lixianglai@loongson.cn>
To: devel@edk2.groups.io
Subject: [edk2-platforms][PATCH V1 02/15] Platform/Loongson: Support SEC And Add Readme.md
Date: Wed, 2 Mar 2022 03:44:34 -0500 [thread overview]
Message-ID: <20220302084447.2991355-3-lixianglai@loongson.cn> (raw)
In-Reply-To: <20220302084447.2991355-1-lixianglai@loongson.cn>
Add SEC Code And Readme.md for LoongArchQemu
Signed-off-by: xianglai li <lixianglai@loongson.cn>
Signed-off-by: xianglai li <lixianglai@loongson.cn>
---
.../Include/LoongArchAsmMacro.h | 23 +
.../Loongson/LoongArchQemuPkg/Loongson.dec | 38 ++
.../Loongson/LoongArchQemuPkg/Loongson.dsc | 133 +++++
.../Loongson/LoongArchQemuPkg/Loongson.fdf | 53 ++
.../LoongArchQemuPkg/Loongson.fdf.inc | 21 +
Platform/Loongson/LoongArchQemuPkg/Readme.md | 53 ++
.../LoongArchQemuPkg/Sec/LoongArch64/Start.S | 76 +++
.../Loongson/LoongArchQemuPkg/Sec/SecMain.c | 510 ++++++++++++++++++
.../Loongson/LoongArchQemuPkg/Sec/SecMain.inf | 49 ++
Readme.md | 9 +
10 files changed, 965 insertions(+)
create mode 100644 Platform/Loongson/LoongArchQemuPkg/Include/LoongArchAsmMacro.h
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/Readme.md
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/LoongArchAsmMacro.h b/Platform/Loongson/LoongArchQemuPkg/Include/LoongArchAsmMacro.h
new file mode 100644
index 0000000000..366d4308e8
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Include/LoongArchAsmMacro.h
@@ -0,0 +1,23 @@
+/** @file
+ LoongArch ASM macro definition.
+
+ Copyright (c) 2021, Loongson Limited. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ **/
+
+#ifndef LOONGARCH_ASM_MACRO_H_
+#define LOONGARCH_ASM_MACRO_H_
+
+#include <Base.h>
+
+#define _ASM_FUNC(Name, Section) \
+ .global Name ; \
+ .section #Section, "ax" ; \
+ .type Name, %function ; \
+ Name:
+
+#define ASM_FUNC(Name) _ASM_FUNC(ASM_PFX(Name), .text. ## Name)
+
+#endif // __LOONGARCH_ASM_MACRO_H__
diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.dec b/Platform/Loongson/LoongArchQemuPkg/Loongson.dec
new file mode 100644
index 0000000000..248b668fd1
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.dec
@@ -0,0 +1,38 @@
+## @file
+#
+# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights reserved.<BR>
+#
+# 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 } }
+
+[PcdsFixedAtBuild, PcdsDynamic]
+ gLoongArchQemuPkgTokenSpaceGuid.PcdFlashPeiFvBase|0x0|UINT64|0x00000003
+ gLoongArchQemuPkgTokenSpaceGuid.PcdFlashPeiFvSize|0x0|UINT32|0x00000004
+ gLoongArchQemuPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize|0|UINT32|0x00000016
+ gLoongArchQemuPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress|0|UINT32|0x00000017
+ gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamBase|0|UINT64|0x0000001c
+ gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamSize|0|UINT32|0x0000001d
+ gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvBase|0x0|UINT64|0x00000028
+ gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvSize|0x0|UINT32|0x00000029
diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc b/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc
new file mode 100644
index 0000000000..f23fed77e6
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc
@@ -0,0 +1,133 @@
+## @file
+#
+# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights reserved.<BR>
+#
+# 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
+
+ DebugLib | MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.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
+
+ gEfiMdePkgTokenSpaceGuid.PcdGuidedExtractHandlerTableAddress | 0x90000000
+ gLoongArchQemuPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize | 0x10000
+ gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamBase | 0x90010000
+ 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..128b3843db
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf
@@ -0,0 +1,53 @@
+## @file
+#
+# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights reserved.<BR>
+#
+# 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..a1a2d537e3
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf.inc
@@ -0,0 +1,21 @@
+## @file
+#
+# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights reserved.<BR>
+#
+# 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/Readme.md b/Platform/Loongson/LoongArchQemuPkg/Readme.md
new file mode 100644
index 0000000000..809a199789
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Readme.md
@@ -0,0 +1,53 @@
+# Introduction
+
+ This document provides the guideline to build UEFI firmware for Qemu of LoongArch.
+
+ LoongArch is the general processor architecture of Loongson.
+
+ We can get the latest LoongArch documents or LoongArch tools at https://github.com/loongson/.
+
+# How to build (X86 Linux Environment)
+
+ 1. Install LoongArch cross-tools on X86 machines.
+ Download cross-tools from https://github.com/loongson/ ,Then config cross-tools env.
+ For Example:
+
+ $ wget https://github.com/loongson/build-tools/releases/latest/download/loongarch64-clfs-20211202-cross-tools.tar.xz
+ $ tar -vxf loongarch64-clfs-20211202-cross-tools.tar.xz -C /opt
+ $ export PATH=/opt/cross-tools/bin:$PATH
+
+
+ 2. Follow edk2-platforms/Readme.md to obtaining source code,And config build env.
+ For Example:
+
+ $ export WORKSPACE=/work/git/tianocore
+ $ mkdir -p $WORKSPACE
+ $ cd $WORKSPACE
+ $ git clone https://github.com/tianocore/edk2.git
+ $ git submodule update --init
+ $ git clone https://github.com/tianocore/edk2-platforms.git
+ $ git submodule update --init
+ $ git clone https://github.com/tianocore/edk2-non-osi.git
+ $ export PACKAGES_PATH=$PWD/edk2:$PWD/edk2-platforms:$PWD/edk2-non-osi
+
+
+ 3. Config cross compiler prefix.
+ For Example:
+
+ $ export GCC5_LOONGARCH64_PREFIX=loongarch64-unknown-linux-gnu-
+
+
+ 4.Set up the build environment And build BaseTool.
+ For Example:
+
+ $. edk2/edksetup.sh
+ $make -C edk2/BaseTools
+
+
+ 5.Build platform.
+ For Exmaple:
+
+ $build --buildtarget=DEBUG --tagname=GCC5 --arch=LOONGARCH64 --platform=Platform/Loongson/LoongArchQemuPkg/Loongson.dsc
+
+
+ After a successful build, the resulting images can be found in `Build/{Platform Name}/{TARGET}_{TOOL_CHAIN_TAG}/FV`.
diff --git a/Platform/Loongson/LoongArchQemuPkg/Sec/LoongArch64/Start.S b/Platform/Loongson/LoongArchQemuPkg/Sec/LoongArch64/Start.S
new file mode 100644
index 0000000000..48c044fe28
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Sec/LoongArch64/Start.S
@@ -0,0 +1,76 @@
+#------------------------------------------------------------------------------
+#
+# Start for LoongArch
+#
+# Copyright (c) 2021 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/Cpu.h>
+#include "LoongArchAsmMacro.h"
+
+ .text
+ .globl _ModuleEntryPoint
+_ModuleEntryPoint:
+
+ /* configure reset ebase */
+ li.d T0, 0x1c000000
+ 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
+
+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
diff --git a/Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.c b/Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.c
new file mode 100644
index 0000000000..73d3a2c1a3
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.c
@@ -0,0 +1,510 @@
+/** @file
+ Main SEC phase code. Transitions to PEI.
+
+ Copyright (c) 2021 Loongson Technology Corporation Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiPei.h>
+
+#include <Library/PeimEntryPoint.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PcdLib.h>
+#include <Library/DebugAgentLib.h>
+#include <Library/IoLib.h>
+#include <Library/PeCoffLib.h>
+#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/PeCoffExtraActionLib.h>
+#include <Library/ExtractGuidedSectionLib.h>
+
+#include <Ppi/TemporaryRamSupport.h>
+
+/**
+ temporary memory to permanent memory and do stack switching.
+
+ @param[in] PeiServices Pointer to the PEI Services Table.
+ @param[in] TemporaryMemoryBase Temporary Memory Base address.
+ @param[in] PermanentMemoryBase Permanent Memory Base address.
+ @param[in] CopySize The size of memory that needs to be migrated.
+
+ @retval EFI_SUCCESS Migration successful.
+**/
+EFI_STATUS
+EFIAPI
+TemporaryRamMigration (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PHYSICAL_ADDRESS TemporaryMemoryBase,
+ IN EFI_PHYSICAL_ADDRESS PermanentMemoryBase,
+ IN UINTN CopySize
+ );
+
+EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI mTemporaryRamSupportPpi = {
+ TemporaryRamMigration
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPrivateDispatchTable[] = {
+ {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiTemporaryRamSupportPpiGuid,
+ &mTemporaryRamSupportPpi
+ },
+};
+
+/**
+ Locates a section within a series of sections
+ with the specified section type.
+
+ The Instance parameter indicates which instance of the section
+ type to return. (0 is first instance, 1 is second...)
+
+ @param[in] Sections The sections to search
+ @param[in] SizeOfSections Total size of all sections
+ @param[in] SectionType The section type to locate
+ @param[in] Instance The section instance number
+ @param[out] FoundSection The FFS section if found
+
+ @retval EFI_SUCCESS The file and section was found
+ @retval EFI_NOT_FOUND The file and section was not found
+ @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
+
+**/
+EFI_STATUS
+FindFfsSectionInstance (
+ IN VOID *Sections,
+ IN UINTN SizeOfSections,
+ IN EFI_SECTION_TYPE SectionType,
+ IN UINTN Instance,
+ OUT EFI_COMMON_SECTION_HEADER **FoundSection
+ )
+{
+ EFI_PHYSICAL_ADDRESS CurrentAddress;
+ UINT32 Size;
+ EFI_PHYSICAL_ADDRESS EndOfSections;
+ EFI_COMMON_SECTION_HEADER *Section;
+ EFI_PHYSICAL_ADDRESS EndOfSection;
+
+ //
+ // Loop through the FFS file sections within the PEI Core FFS file
+ //
+ EndOfSection = (EFI_PHYSICAL_ADDRESS) (UINTN) Sections;
+ EndOfSections = EndOfSection + SizeOfSections;
+ for (;;) {
+ if (EndOfSection == EndOfSections) {
+ break;
+ }
+ CurrentAddress = (EndOfSection + 3) & ~(3ULL);
+ if (CurrentAddress >= EndOfSections) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ Section = (EFI_COMMON_SECTION_HEADER*) (UINTN) CurrentAddress;
+
+ Size = SECTION_SIZE (Section);
+ if (Size < sizeof (*Section)) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ EndOfSection = CurrentAddress + Size;
+ if (EndOfSection > EndOfSections) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ //
+ // Look for the requested section type
+ //
+ if (Section->Type == SectionType) {
+ if (Instance == 0) {
+ *FoundSection = Section;
+ return EFI_SUCCESS;
+ } else {
+ Instance--;
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Locates a section within a series of sections
+ with the specified section type.
+
+ @param[in] Sections The sections to search
+ @param[in] SizeOfSections Total size of all sections
+ @param[in] SectionType The section type to locate
+ @param[out] FoundSection The FFS section if found
+
+ @retval EFI_SUCCESS The file and section was found
+ @retval EFI_NOT_FOUND The file and section was not found
+ @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
+
+**/
+EFI_STATUS
+FindFfsSectionInSections (
+ IN VOID *Sections,
+ IN UINTN SizeOfSections,
+ IN EFI_SECTION_TYPE SectionType,
+ OUT EFI_COMMON_SECTION_HEADER **FoundSection
+ )
+{
+ return FindFfsSectionInstance (
+ Sections,
+ SizeOfSections,
+ SectionType,
+ 0,
+ FoundSection
+ );
+}
+
+/**
+ Locates a FFS file with the specified file type and a section
+ within that file with the specified section type.
+
+ @param[in] Fv The firmware volume to search
+ @param[in] FileType The file type to locate
+ @param[in] SectionType The section type to locate
+ @param[out] FoundSection The FFS section if found
+
+ @retval EFI_SUCCESS The file and section was found
+ @retval EFI_NOT_FOUND The file and section was not found
+ @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
+
+**/
+EFI_STATUS
+FindFfsFileAndSection (
+ IN EFI_FIRMWARE_VOLUME_HEADER *Fv,
+ IN EFI_FV_FILETYPE FileType,
+ IN EFI_SECTION_TYPE SectionType,
+ OUT EFI_COMMON_SECTION_HEADER **FoundSection
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS CurrentAddress;
+ EFI_PHYSICAL_ADDRESS EndOfFirmwareVolume;
+ EFI_FFS_FILE_HEADER *File;
+ UINT32 Size;
+ EFI_PHYSICAL_ADDRESS EndOfFile;
+
+ if (Fv->Signature != EFI_FVH_SIGNATURE) {
+ DEBUG ((DEBUG_ERROR, "FV at %p does not have FV header signature\n", Fv));
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ CurrentAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) Fv;
+ EndOfFirmwareVolume = CurrentAddress + Fv->FvLength;
+
+ //
+ // Loop through the FFS files in the Boot Firmware Volume
+ //
+ for (EndOfFile = CurrentAddress + Fv->HeaderLength; ; ) {
+
+ CurrentAddress = (EndOfFile + 7) & ~(7ULL);
+ if (CurrentAddress > EndOfFirmwareVolume) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ File = (EFI_FFS_FILE_HEADER*) (UINTN) CurrentAddress;
+ Size = *(UINT32*) File->Size & 0xffffff;
+ if (Size < (sizeof (*File) + sizeof (EFI_COMMON_SECTION_HEADER))) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ EndOfFile = CurrentAddress + Size;
+ if (EndOfFile > EndOfFirmwareVolume) {
+ return EFI_VOLUME_CORRUPTED;
+ }
+
+ //
+ // Look for the request file type
+ //
+ if (File->Type != FileType) {
+ continue;
+ }
+
+ Status = FindFfsSectionInSections (
+ (VOID*) (File + 1),
+ (UINTN) EndOfFile - (UINTN) (File + 1),
+ SectionType,
+ FoundSection
+ );
+ if (!EFI_ERROR (Status)
+ || (Status == EFI_VOLUME_CORRUPTED))
+ {
+ return Status;
+ }
+ }
+}
+
+/**
+ Locates the PEI Core entry point address
+
+ @param[in] Fv The firmware volume to search
+ @param[out] PeiCoreEntryPoint The entry point of the PEI Core image
+
+ @retval EFI_SUCCESS The file and section was found
+ @retval EFI_NOT_FOUND The file and section was not found
+ @retval EFI_VOLUME_CORRUPTED The firmware volume was corrupted
+
+**/
+EFI_STATUS
+FindPeiCoreImageBaseInFv (
+ IN EFI_FIRMWARE_VOLUME_HEADER *Fv,
+ OUT EFI_PHYSICAL_ADDRESS *PeiCoreImageBase
+ )
+{
+ EFI_STATUS Status;
+ EFI_COMMON_SECTION_HEADER *Section;
+
+ Status = FindFfsFileAndSection (
+ Fv,
+ EFI_FV_FILETYPE_PEI_CORE,
+ EFI_SECTION_PE32,
+ &Section
+ );
+ if (EFI_ERROR (Status)) {
+ Status = FindFfsFileAndSection (
+ Fv,
+ EFI_FV_FILETYPE_PEI_CORE,
+ EFI_SECTION_TE,
+ &Section
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Unable to find PEI Core image\n"));
+ return Status;
+ }
+ }
+
+ *PeiCoreImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)(Section + 1);
+ return EFI_SUCCESS;
+}
+
+/**
+ Find and return Pei Core entry point.
+
+ It also find SEC and PEI Core file debug information. It will report them if
+ remote debug is enabled.
+
+**/
+VOID
+FindAndReportEntryPoints (
+ IN EFI_FIRMWARE_VOLUME_HEADER **BootFirmwareVolumePtr,
+ OUT EFI_PEI_CORE_ENTRY_POINT *PeiCoreEntryPoint
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS PeiCoreImageBase = 0;
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+
+ Status = FindPeiCoreImageBaseInFv (*BootFirmwareVolumePtr, &PeiCoreImageBase);
+ ASSERT (Status == EFI_SUCCESS);
+
+ ZeroMem ((VOID *) &ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT));
+
+ //
+ // Report PEI Core debug information when remote debug is enabled
+ //
+ ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)PeiCoreImageBase;
+ ImageContext.PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageContext.ImageAddress);
+ PeCoffLoaderRelocateImageExtraAction (&ImageContext);
+
+ //
+ // Find PEI Core entry point
+ //
+ Status = PeCoffLoaderGetEntryPoint ((VOID *) (UINTN) PeiCoreImageBase, (VOID**) PeiCoreEntryPoint);
+ if (EFI_ERROR (Status)) {
+ *PeiCoreEntryPoint = 0;
+ }
+
+ return;
+}
+
+/**
+ Find the peicore entry point and jump to the entry point to execute.
+
+ @param[in] Context The first input parameter of InitializeDebugAgent().
+
+**/
+VOID
+EFIAPI
+SecStartupPhase2 (
+ IN VOID *Context
+ )
+{
+ EFI_SEC_PEI_HAND_OFF *SecCoreData;
+ EFI_FIRMWARE_VOLUME_HEADER *BootFv;
+ EFI_PEI_CORE_ENTRY_POINT PeiCoreEntryPoint;
+
+ SecCoreData = (EFI_SEC_PEI_HAND_OFF *) Context;
+
+ //
+ // Find PEI Core entry point. It will report SEC and Pei Core debug information if remote debug
+ // is enabled.
+ //
+ BootFv = (EFI_FIRMWARE_VOLUME_HEADER *)SecCoreData->BootFirmwareVolumeBase;
+ FindAndReportEntryPoints (&BootFv, &PeiCoreEntryPoint);
+ SecCoreData->BootFirmwareVolumeBase = BootFv;
+ SecCoreData->BootFirmwareVolumeSize = (UINTN) BootFv->FvLength;
+
+ DEBUG ((DEBUG_INFO, "Find Pei EntryPoint=%p\n", PeiCoreEntryPoint));
+
+ //
+ // Transfer the control to the PEI core
+ //
+ DEBUG ((DEBUG_INFO, "SecStartupPhase2 %p\n", PeiCoreEntryPoint));
+
+ (*PeiCoreEntryPoint) (SecCoreData, (EFI_PEI_PPI_DESCRIPTOR *)&mPrivateDispatchTable);
+
+ //
+ // If we get here then the PEI Core returned, which is not recoverable.
+ //
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+}
+/**
+ Entry point to the C language phase of SEC. initialize some temporary memory and set up the stack,
+ the control is transferred to this function.
+
+ @param[in] BootFv The pointer to the PEI FV in memory.
+ @param[in] TopOfCurrentStack Top of Current Stack.
+**/
+VOID
+EFIAPI
+SecCoreStartupWithStack (
+ IN EFI_FIRMWARE_VOLUME_HEADER *BootFv,
+ IN VOID *TopOfCurrentStack
+ )
+{
+ EFI_SEC_PEI_HAND_OFF SecCoreData;
+ EFI_FIRMWARE_VOLUME_HEADER *BootPeiFv = (EFI_FIRMWARE_VOLUME_HEADER*) BootFv;
+
+ DEBUG ((DEBUG_INFO, "Entering C environment\n"));
+
+ ProcessLibraryConstructorList (NULL, NULL);
+
+ DEBUG ((DEBUG_INFO,
+ "SecCoreStartupWithStack (0x%lx, 0x%lx)\n",
+ (UINTN)BootFv,
+ (UINTN)TopOfCurrentStack
+ ));
+ DEBUG ((DEBUG_INFO,
+ "(0x%lx, 0x%lx)\n",
+ (UINTN) (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;
+
+#if 0
+ DebugAgentContext.HeapMigrateOffset = (UINTN)NewHeap - (UINTN)OldHeap;
+ DebugAgentContext.StackMigrateOffset = (UINTN)NewStack - (UINTN)OldStack;
+
+ OldStatus = SaveAndSetDebugTimerInterrupt (FALSE);
+ InitializeDebugAgent (DEBUG_AGENT_INIT_POSTMEM_SEC, (VOID *) &DebugAgentContext, NULL);
+#endif
+
+ //
+ // 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);
+ }
+
+ //SaveAndSetDebugTimerInterrupt (OldStatus);
+
+ 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..03d4ea5b00
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.inf
@@ -0,0 +1,49 @@
+## @file
+# SEC Driver
+#
+# Copyright (c) 2021 Loongson Technology Corporation Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = SecMain
+ FILE_GUID = 57d02d4f-5a5d-4bfa-b7d6-ba0a4d2c72ce
+ MODULE_TYPE = SEC
+ VERSION_STRING = 1.0
+
+[Sources.LOONGARCH64]
+ 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.PcdGuidedExtractHandlerTableAddress
+ gLoongArchQemuPkgTokenSpaceGuid.PcdGuidedExtractHandlerTableSize
+
+ gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvBase
+ gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvSize
+ gLoongArchQemuPkgTokenSpaceGuid.PcdFlashPeiFvBase
+ gLoongArchQemuPkgTokenSpaceGuid.PcdFlashPeiFvSize
diff --git a/Readme.md b/Readme.md
index 62876b4b7d..825bd37edd 100644
--- a/Readme.md
+++ b/Readme.md
@@ -57,6 +57,7 @@ IA32 | i?86-linux-gnu-* _or_ x86_64-linux-gnu-
IPF | ia64-linux-gnu
X64 | x86_64-linux-gnu-
RISCV64 | riscv64-unknown-elf-
+LOONGARCH64 | loongarch64-linux-gnu-
\* i386, i486, i586 or i686
@@ -71,6 +72,11 @@ RISC-V open source community provides GCC toolchains for
[riscv64-unknown-elf](https://github.com/riscv/riscv-gnu-toolchain)
compiled to run on x86 Linux.
+### GCC for LoongArch
+Loonson open source community provides GCC toolchains for
+[loongarch64-unknown-elf](https://github.com/loongson/build-tools)
+compiled to run on x86 Linux
+
### clang
Clang does not require separate cross compilers, but it does need a
target-specific binutils. These are included with any prepackaged GCC toolchain
@@ -257,6 +263,9 @@ For more information, see the
##### Minnowboard Max/Turbot based on Intel Valleyview2 SoC
* [Minnowboard Max](Platform/Intel/Vlv2TbltDevicePkg)
+## Loongson
+* [LoongArchQemu](Platform/Loongson/LoongArchQemuPkg)
+
## Marvell
* [Armada 70x0](Platform/Marvell/Armada70x0Db)
* [Armada 80x0](Platform/Marvell/Armada80x0Db)
--
2.27.0
next prev parent reply other threads:[~2022-03-02 8:45 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-02 8:44 [edk2-platforms][PATCH V1 00/15] Platform: Add Loongson support xianglai
2022-03-02 8:44 ` [edk2-platforms][PATCH V1 01/15] Platform/Loongson: Add Serial Port library xianglai
2022-03-02 8:44 ` xianglai [this message]
2022-03-02 8:44 ` [edk2-platforms][PATCH V1 03/15] Platform/Loongson: Add PeiServicesTablePointerLib xianglai
2022-03-02 8:44 ` [edk2-platforms][PATCH V1 04/15] Platform/Loongson: Add QemuFwCfgLib xianglai
2022-03-02 8:44 ` [edk2-platforms][PATCH V1 05/15] Platform/Loongson: Add BpiLib xianglai
2022-03-02 8:44 ` [edk2-platforms][PATCH V1 06/15] Platform/Loongson: Add MmuLib xianglai
2022-03-02 8:44 ` [edk2-platforms][PATCH V1 07/15] Platform/Loongson: Add StableTimerLib xianglai
2022-03-02 8:44 ` [edk2-platforms][PATCH V1 08/15] Platform/Loongson: Support PEI phase xianglai
2022-03-02 8:44 ` [edk2-platforms][PATCH V1 09/15] Platform/Loongson: Add CPU DXE driver xianglai
2022-03-02 8:44 ` [edk2-platforms][PATCH V1 10/15] Platform/Loongson: Add PciCpuIoDxe driver xianglai
2022-03-02 8:44 ` [edk2-platforms][PATCH V1 11/15] Platform/Loongson: Add timer Dxe driver xianglai
2022-03-02 8:44 ` [edk2-platforms][PATCH V1 12/15] Platform/Loongson: Add RealTime Clock lib xianglai
2022-03-02 8:44 ` [edk2-platforms][PATCH V1 13/15] Platform/Loongson: Add Platform Boot Manager Lib xianglai
2022-03-02 8:44 ` [edk2-platforms][PATCH V1 14/15] Platform/Loongson: Add Reset System Lib xianglai
2022-03-02 8:44 ` [edk2-platforms][PATCH V1 15/15] Platform/Loongson: Support Dxe xianglai
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220302084447.2991355-3-lixianglai@loongson.cn \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox