[edk2-devel] [edk2-platforms][PATCH V3 02/16] Platform/Loongson: Support SEC And Add Readme.md

xianglai lixianglai at loongson.cn
Fri Oct 14 04:01:15 UTC 2022


Add SEC Code And Readme.md for LoongArchQemu

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4054

Signed-off-by: xianglai li  <lixianglai at loongson.cn>
---
 Maintainers.txt                               |   4 +
 .../Include/LoongArchAsmMacro.h               |  23 +
 .../Loongson/LoongArchQemuPkg/Loongson.dec    |  36 ++
 .../Loongson/LoongArchQemuPkg/Loongson.dsc    | 131 +++++
 .../Loongson/LoongArchQemuPkg/Loongson.fdf    |  53 ++
 .../LoongArchQemuPkg/Loongson.fdf.inc         |  21 +
 Platform/Loongson/LoongArchQemuPkg/Readme.md  |  59 ++
 .../LoongArchQemuPkg/Sec/LoongArch64/Start.S  |  76 +++
 .../Loongson/LoongArchQemuPkg/Sec/SecMain.c   | 510 ++++++++++++++++++
 .../Loongson/LoongArchQemuPkg/Sec/SecMain.inf |  47 ++
 Readme.md                                     |   9 +
 11 files changed, 969 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/Maintainers.txt b/Maintainers.txt
index 700ca0af60..8921d6b4e1 100644
--- a/Maintainers.txt
+++ b/Maintainers.txt
@@ -329,6 +329,10 @@ M: Bob Feng <bob.c.feng at intel.com>
 M: Liming Gao <gaoliming at byosoft.com.cn>
 R: Yuwei Chen <yuwei.chen at intel.com>
 
+Loongson platforms
+F: Platform/Loongson/
+M: xianglai li <lixianglai at loongson.cn>
+
 Marvell platforms and silicon
 F: Platform/Marvell/
 F: Platform/SolidRun/Armada80x0McBin/
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..8cfa63ee8a
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.dec
@@ -0,0 +1,36 @@
+## @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.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..52ab11de9a
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc
@@ -0,0 +1,131 @@
+## @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
+
+  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..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..b0d172f829
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Readme.md
@@ -0,0 +1,59 @@
+# 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/QEMU_EFI.fd`.
+
+  A compile script is provided here:
+
+    #!/bin/bash
+    export WORKSPACE=/work/git/tianocore
+    export PACKAGES_PATH=$WORKSPACE/edk2:$WORKSPACE/edk2-platforms
+    export GCC5_LOONGARCH64_PREFIX=loongarch64-unknown-linux-gnu-
+    . edk2/edksetup.sh
+    make -C edk2/BaseTools
+    build --buildtarget=DEBUG --tagname=GCC5 --arch=LOONGARCH64  --platform=Platform/Loongson/LoongArchQemuPkg/Loongson.dsc
+
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..eddd151a31
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.inf
@@ -0,0 +1,47 @@
+## @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.PcdFlashSecFvBase
+  gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvSize
+  gLoongArchQemuPkgTokenSpaceGuid.PcdFlashPeiFvBase
+  gLoongArchQemuPkgTokenSpaceGuid.PcdFlashPeiFvSize
diff --git a/Readme.md b/Readme.md
index 62876b4b7d..5ae58bca20 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-unknown-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.31.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#95173): https://edk2.groups.io/g/devel/message/95173
Mute This Topic: https://groups.io/mt/94320527/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-




More information about the edk2-devel-archive mailing list