Platform PEI module for LoongArch platform initialization.
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4054
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Bibo Mao <maobibo@loongson.cn>
Cc: Chao Li <lichao@loongson.cn>
Cc: Leif Lindholm <quic_llindhol@quicinc.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Signed-off-by: xianglai li <lixianglai@loongson.cn>
Reviewed-by: Chao Li <lichao@loongson.cn>
---
.../Loongson/LoongArchQemuPkg/Loongson.dec | 25 +
.../Loongson/LoongArchQemuPkg/Loongson.dsc | 69 +++
.../Loongson/LoongArchQemuPkg/Loongson.fdf | 51 +++
.../LoongArchQemuPkg/PlatformPei/Fv.c | 58 +++
.../LoongArchQemuPkg/PlatformPei/MemDetect.c | 104 +++++
.../LoongArchQemuPkg/PlatformPei/Platform.c | 433 ++++++++++++++++++
.../LoongArchQemuPkg/PlatformPei/Platform.h | 86 ++++
.../PlatformPei/PlatformPei.inf | 74 +++
8 files changed, 900 insertions(+)
create mode 100644 Platform/Loongson/LoongArchQemuPkg/PlatformPei/Fv.c
create mode 100644 Platform/Loongson/LoongArchQemuPkg/PlatformPei/MemDetect.c
create mode 100644 Platform/Loongson/LoongArchQemuPkg/PlatformPei/Platform.c
create mode 100644 Platform/Loongson/LoongArchQemuPkg/PlatformPei/Platform.h
create mode 100644 Platform/Loongson/LoongArchQemuPkg/PlatformPei/PlatformPei.inf
diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.dec b/Platform/Loongson/LoongArchQemuPkg/Loongson.dec
index 61f600b20d..023df1dd2a 100644
--- a/Platform/Loongson/LoongArchQemuPkg/Loongson.dec
+++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.dec
@@ -27,12 +27,37 @@
[Guids]
gLoongArchQemuPkgTokenSpaceGuid = { 0x0e0383ce, 0x0151, 0x4d01, { 0x80, 0x0e, 0x3f, 0xef, 0x8b, 0x27, 0x6d, 0x52 } }
+ gEarly16550UartBaseAddressGuid = { 0xea67ca3e, 0x1f54, 0x436b, { 0x97, 0x88, 0xd4, 0xeb, 0x29, 0xc3, 0x42, 0x67 } }
## In the PcdsFixedAtBuild and PcdsDynamic areas, numbers start at 0x0.
[PcdsFixedAtBuild, PcdsDynamic]
gLoongArchQemuPkgTokenSpaceGuid.PcdFlashPeiFvBase|0x0|UINT64|0x00000000
gLoongArchQemuPkgTokenSpaceGuid.PcdFlashPeiFvSize|0x0|UINT32|0x00000001
+ gLoongArchQemuPkgTokenSpaceGuid.PcdFlashDxeFvBase|0x0|UINT64|0x00000003
+ gLoongArchQemuPkgTokenSpaceGuid.PcdFlashDxeFvSize|0x0|UINT32|0x00000004
+ gLoongArchQemuPkgTokenSpaceGuid.PcdDeviceTreeBase|0x0|UINT64|0x00000009
+ gLoongArchQemuPkgTokenSpaceGuid.PcdDeviceTreePadding|256|UINT32|0x0000000a
+
gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamBase|0|UINT64|0x0000000b
gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamSize|0|UINT32|0x0000000c
+ gLoongArchQemuPkgTokenSpaceGuid.PcdUefiRamTop|0x0|UINT64|0x0000000d
+ gLoongArchQemuPkgTokenSpaceGuid.PcdRamRegionsBottom|0x0|UINT64|0x0000000e
gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvBase|0x0|UINT64|0x0000000f
gLoongArchQemuPkgTokenSpaceGuid.PcdFlashSecFvSize|0x0|UINT32|0x00000010
+
+## In the PcdsFixedAtBuild.LOONGARCH64 area, numbers start at 0x10000.
+[PcdsFixedAtBuild.LOONGARCH64]
+ gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize|32|UINT8|0x00010000
+ gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize|0|UINT8|0x00010001
+
+## In the PcdsDynamic area, numbers start at 0x20000.
+[PcdsDynamic]
+ gLoongArchQemuPkgTokenSpaceGuid.PcdRamSize|0x40000000|UINT64|0x00020000
+ gLoongArchQemuPkgTokenSpaceGuid.PcdFwCfgSelectorAddress|0x0|UINT64|0x00020001
+ gLoongArchQemuPkgTokenSpaceGuid.PcdFwCfgDataAddress|0x0|UINT64|0x00020002
+ gLoongArchQemuPkgTokenSpaceGuid.PcdSwapPageDir|0x0|UINT64|0x00020003
+ gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPgd|0x0|UINT64|0x00020004
+ gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPud|0x0|UINT64|0x00020005
+ gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPmd|0x0|UINT64|0x00020006
+ gLoongArchQemuPkgTokenSpaceGuid.PcdInvalidPte|0x0|UINT64|0x00020007
+ gLoongArchQemuPkgTokenSpaceGuid.PcdRtcBaseAddress|0x00000000|UINT64|0x00020008
diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc b/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc
index 049be907dd..8d196ae8c1 100644
--- a/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc
+++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.dsc
@@ -56,17 +56,59 @@
[LibraryClasses.common]
PcdLib | MdePkg/Library/DxePcdLib/DxePcdLib.inf
+ TimerLib | Platform/Loongson/LoongArchQemuPkg/Library/StableTimerLib/TimerLib.inf
PrintLib | MdePkg/Library/BasePrintLib/BasePrintLib.inf
BaseMemoryLib | MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
BaseLib | MdePkg/Library/BaseLib/BaseLib.inf
+ PerformanceLib | MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
PeCoffLib | MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+ CacheMaintenanceLib | MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
+ UefiDecompressLib | MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
PeCoffGetEntryPointLib | MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
IoLib | MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
PlatformHookLib | Platform/Loongson/LoongArchQemuPkg/Library/Fdt16550SerialPortHookLib/Fdt16550SerialPortHookLib.inf
SerialPortLib | MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf
DebugPrintErrorLevelLib | MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+ FdtLib | EmbeddedPkg/Library/FdtLib/FdtLib.inf
PeCoffExtraActionLib | MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
DebugAgentLib | MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
+ PeiServicesLib | MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+
+[LibraryClasses.common.SEC]
+ PcdLib | MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ ReportStatusCodeLib | MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+ HobLib | MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ MemoryAllocationLib | MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ SerialPortLib | Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/EarlySerialPortLib16550.inf
+
+[LibraryClasses.common.PEI_CORE]
+ PcdLib | MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+ HobLib | MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ PeiServicesTablePointerLib | Platform/Loongson/LoongArchQemuPkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
+ MemoryAllocationLib | MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ PeiCoreEntryPoint | MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
+ ReportStatusCodeLib | MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+ OemHookStatusCodeLib | MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
+ PeCoffGetEntryPointLib | MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+ QemuFwCfgLib | Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf
+ MmuLib | Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuBaseLibPei.inf
+ SerialPortLib | Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/EarlySerialPortLib16550.inf
+
+[LibraryClasses.common.PEIM]
+ HobLib | MdePkg/Library/PeiHobLib/PeiHobLib.inf
+ PeiServicesTablePointerLib | Platform/Loongson/LoongArchQemuPkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
+ MemoryAllocationLib | MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+ PeimEntryPoint | MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
+ ReportStatusCodeLib | MdeModulePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.inf
+ OemHookStatusCodeLib | MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
+ PeCoffGetEntryPointLib | MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+ PeiResourcePublicationLib | MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.inf
+ ExtractGuidedSectionLib | MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
+ PcdLib | MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+ QemuFwCfgS3Lib | OvmfPkg/Library/QemuFwCfgS3Lib/PeiQemuFwCfgS3LibFwCfg.inf
+ QemuFwCfgLib | Platform/Loongson/LoongArchQemuPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf
+ MmuLib | Platform/Loongson/LoongArchQemuPkg/Library/MmuLib/MmuBaseLibPei.inf
+ SerialPortLib | Platform/Loongson/LoongArchQemuPkg/Library/SerialPortLib/EarlySerialPortLib16550.inf
################################################################################
#
@@ -118,8 +160,16 @@
# ASSERT_BREAKPOINT_ENABLED 0x10
# ASSERT_DEADLOOP_ENABLED 0x20
+#######################################################################################
gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamBase | 0x10000
gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamSize | 0x10000
+ gLoongArchQemuPkgTokenSpaceGuid.PcdDeviceTreeBase | 0x100000
+ #
+ # minimal memory for uefi bios should be 512M
+ # 0x00000000 - 0x10000000
+ # 0x90000000 - 0xA0000000
+ #
+ gLoongArchQemuPkgTokenSpaceGuid.PcdUefiRamTop | 0x10000000
[PcdsPatchableInModule.common]
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase|0x0
@@ -130,3 +180,22 @@
# SEC Phase modules
#
Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.inf
+
+ #
+ # PEI Phase modules
+ #
+ MdeModulePkg/Core/Pei/PeiMain.inf
+ MdeModulePkg/Universal/PCD/Pei/Pcd.inf {
+ <LibraryClasses>
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ }
+ MdePkg/Library/PeiExtractGuidedSectionLib/PeiExtractGuidedSectionLib.inf
+ MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf {
+ <LibraryClasses>
+ NULL|MdeModulePkg/Library/LzmaCustomDecompressLib/LzmaCustomDecompressLib.inf
+ }
+
+ Platform/Loongson/LoongArchQemuPkg/PlatformPei/PlatformPei.inf {
+ <LibraryClasses>
+ PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+ }
diff --git a/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf b/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf
index 9685795cda..8e257f2392 100644
--- a/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf
+++ b/Platform/Loongson/LoongArchQemuPkg/Loongson.fdf
@@ -45,9 +45,60 @@ READ_LOCK_STATUS = TRUE
INF Platform/Loongson/LoongArchQemuPkg/Sec/SecMain.inf
+#####################################################################################################
+[FV.PEIFV]
+FvNameGuid = 6f856a84-de7d-4af9-93a3-342b4ecb46eb
+BlockSize = $(BLOCK_SIZE)
+FvAlignment = 16
+ERASE_POLARITY = 1
+MEMORY_MAPPED = TRUE
+STICKY_WRITE = TRUE
+LOCK_CAP = TRUE
+LOCK_STATUS = TRUE
+READ_DISABLED_CAP = TRUE
+READ_ENABLED_CAP = TRUE
+READ_STATUS = TRUE
+READ_LOCK_CAP = TRUE
+READ_LOCK_STATUS = TRUE
+WRITE_DISABLED_CAP = TRUE
+WRITE_ENABLED_CAP = TRUE
+WRITE_STATUS = TRUE
+WRITE_LOCK_CAP = TRUE
+WRITE_LOCK_STATUS = TRUE
+
+APRIORI PEI {
+ INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
+}
+
+#
+# PEI Phase modules
+#
+
+INF MdeModulePkg/Core/Pei/PeiMain.inf
+INF MdeModulePkg/Universal/PCD/Pei/Pcd.inf
+INF MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
+INF Platform/Loongson/LoongArchQemuPkg/PlatformPei/PlatformPei.inf
+
#####################################################################################################
[Rule.Common.SEC]
FILE SEC = $(NAMED_GUID) {
TE TE Align = Auto $(INF_OUTPUT)/$(MODULE_NAME).efi
UI STRING ="$(MODULE_NAME)" Optional
}
+
+#####################################################################################################
+[Rule.Common.PEI_CORE]
+ FILE PEI_CORE = $(NAMED_GUID) {
+ TE TE Align=Auto $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING ="$(MODULE_NAME)" Optional
+ }
+
+#####################################################################################################
+[Rule.Common.PEIM]
+ FILE PEIM = $(NAMED_GUID) {
+ PEI_DEPEX PEI_DEPEX Optional $(INF_OUTPUT)/$(MODULE_NAME).depex
+ PE32 PE32 Align=Auto $(INF_OUTPUT)/$(MODULE_NAME).efi
+ UI STRING="$(MODULE_NAME)" Optional
+ }
+
+#####################################################################################################
diff --git a/Platform/Loongson/LoongArchQemuPkg/PlatformPei/Fv.c b/Platform/Loongson/LoongArchQemuPkg/PlatformPei/Fv.c
new file mode 100644
index 0000000000..06b2807d6c
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/PlatformPei/Fv.c
@@ -0,0 +1,58 @@
+/** @file
+ Build FV related hobs for platform.
+
+ Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "PiPei.h"
+#include "Platform.h"
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/PcdLib.h>
+
+/**
+ Publish PEI & DXE (Decompressed) Memory based FVs to let PEI
+ and DXE know about them.
+
+ @retval EFI_SUCCESS Platform PEI FVs were initialized successfully.
+**/
+EFI_STATUS
+PeiFvInitialization (
+ VOID
+ )
+{
+ DEBUG ((DEBUG_INFO, "Platform PEI Firmware Volume Initialization\n"));
+
+ //
+ // Create a memory allocation HOB for the PEI FV.
+ //
+ BuildMemoryAllocationHob (
+ PcdGet64 (PcdSecPeiTempRamBase),
+ PcdGet32 (PcdSecPeiTempRamSize),
+ EfiBootServicesData
+ );
+
+ //
+ // Let DXE know about the DXE FV
+ //
+ BuildFvHob (PcdGet64 (PcdFlashDxeFvBase), PcdGet32 (PcdFlashDxeFvSize));
+
+ //
+ // Let PEI know about the DXE FV so it can find the DXE Core
+ //
+ DEBUG ((DEBUG_INFO, "DXEFV base:%p size:%x\n", (VOID *) (UINTN)PcdGet64 (PcdFlashDxeFvBase),
+ PcdGet32 (PcdFlashDxeFvSize)));
+ PeiServicesInstallFvInfoPpi (
+ NULL,
+ (VOID *) (UINTN)PcdGet64 (PcdFlashDxeFvBase),
+ PcdGet32 (PcdFlashDxeFvSize),
+ NULL,
+ NULL
+ );
+
+ return EFI_SUCCESS;
+}
diff --git a/Platform/Loongson/LoongArchQemuPkg/PlatformPei/MemDetect.c b/Platform/Loongson/LoongArchQemuPkg/PlatformPei/MemDetect.c
new file mode 100644
index 0000000000..fad4cff8d8
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/PlatformPei/MemDetect.c
@@ -0,0 +1,104 @@
+/** @file
+ Memory Detection for Virtual Machines.
+
+ Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+//
+// The package level header files this module uses
+//
+#include <PiPei.h>
+
+//
+// The Library classes this module consumes
+//
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/IoLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/ResourcePublicationLib.h>
+#include <Library/QemuFwCfgLib.h>
+#include "Platform.h"
+
+/**
+ Publish PEI core memory
+
+ @return EFI_SUCCESS The PEIM initialized successfully.
+**/
+EFI_STATUS
+PublishPeiMemory (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT64 Base;
+ UINT64 Size;
+ UINT64 RamTop;
+
+ //
+ // Determine the range of memory to use during PEI
+ //
+ Base = PcdGet64 (PcdSecPeiTempRamBase) + PcdGet32 (PcdSecPeiTempRamSize);
+ RamTop = PcdGet64 (PcdUefiRamTop);
+ Size = RamTop - Base;
+
+ //
+ // Publish this memory to the PEI Core
+ //
+ Status = PublishSystemMemory (Base, Size);
+ ASSERT_EFI_ERROR (Status);
+
+ DEBUG ((DEBUG_INFO, "Publish Memory Initialize done.\n"));
+ return Status;
+}
+
+/**
+ Peform Memory Detection
+ Publish system RAM and reserve memory regions
+**/
+VOID
+InitializeRamRegions (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ FIRMWARE_CONFIG_ITEM FwCfgItem;
+ UINTN FwCfgSize;
+ LOONGARCH_MEMMAP_ENTRY MemoryMapEntry;
+ LOONGARCH_MEMMAP_ENTRY *StartEntry;
+ LOONGARCH_MEMMAP_ENTRY *pEntry;
+ UINTN Processed;
+
+ Status = QemuFwCfgFindFile ("etc/memmap", &FwCfgItem, &FwCfgSize);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a %d read etc/memmap error Status %d \n", __func__, __LINE__, Status));
+ return ;
+ }
+ if (FwCfgSize % sizeof MemoryMapEntry != 0) {
+ DEBUG ((DEBUG_ERROR, "no MemoryMapEntry FwCfgSize:%d\n", FwCfgSize));
+ return ;
+ }
+
+ QemuFwCfgSelectItem (FwCfgItem);
+ StartEntry = AllocatePages (EFI_SIZE_TO_PAGES (FwCfgSize));
+ QemuFwCfgReadBytes (FwCfgSize, StartEntry);
+ for (Processed = 0; Processed < (FwCfgSize / sizeof MemoryMapEntry); Processed++) {
+ pEntry = StartEntry + Processed;
+ if (pEntry->Length == 0) {
+ continue;
+ }
+
+ DEBUG ((DEBUG_INFO, "MemmapEntry Base %p length %p type %d\n", pEntry->BaseAddr, pEntry->Length, pEntry->Type));
+ if (pEntry->Type != EfiAcpiAddressRangeMemory) {
+ continue;
+ }
+
+ AddMemoryRangeHob ( pEntry->BaseAddr, pEntry->BaseAddr + pEntry->Length);
+ }
+}
diff --git a/Platform/Loongson/LoongArchQemuPkg/PlatformPei/Platform.c b/Platform/Loongson/LoongArchQemuPkg/PlatformPei/Platform.c
new file mode 100644
index 0000000000..32b6518f8f
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/PlatformPei/Platform.c
@@ -0,0 +1,433 @@
+/** @file
+ Platform PEI driver
+
+ Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ @par Glossary:
+ - Mem - Memory
+**/
+
+//
+// The package level header files this module uses
+//
+#include <PiPei.h>
+//
+// The Library classes this module consumes
+//
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PeimEntryPoint.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/ResourcePublicationLib.h>
+#include <Guid/MemoryTypeInformation.h>
+#include <Library/QemuFwCfgLib.h>
+#include <Library/MmuLib.h>
+#include <Guid/FdtHob.h>
+#include <libfdt.h>
+#include <Ppi/MasterBootMode.h>
+
+#include "Platform.h"
+
+/* TODO */
+EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = {
+ { EfiReservedMemoryType, 0x004 },
+ { EfiRuntimeServicesData, 0x024 },
+ { EfiRuntimeServicesCode, 0x030 },
+ { EfiBootServicesCode, 0x180 },
+ { EfiBootServicesData, 0xF00 },
+ { EfiMaxMemoryType, 0x000 }
+};
+
+//
+// Module globals
+//
+CONST EFI_PEI_PPI_DESCRIPTOR mPpiListBootMode = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiPeiMasterBootModePpiGuid,
+ NULL
+};
+
+/**
+ Create Reserved type memory range hand off block.
+
+ @param MemoryBase memory base address.
+ @param MemoryLimit memory length.
+
+ @return VOID
+**/
+VOID
+AddReservedMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ )
+{
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_MEMORY_RESERVED,
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_TESTED,
+ MemoryBase,
+ MemorySize
+ );
+}
+/**
+ Create system type memory range hand off block.
+
+ @param MemoryBase memory base address.
+ @param MemoryLimit memory length.
+
+ @return VOID
+**/
+VOID
+AddMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ )
+{
+ BuildResourceDescriptorHob (
+ EFI_RESOURCE_SYSTEM_MEMORY,
+ EFI_RESOURCE_ATTRIBUTE_PRESENT |
+ EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
+ EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE |
+ EFI_RESOURCE_ATTRIBUTE_TESTED,
+ MemoryBase,
+ MemorySize
+ );
+}
+
+/**
+ Create memory range hand off block.
+
+ @param MemoryBase memory base address.
+ @param MemoryLimit memory length.
+
+ @return VOID
+**/
+VOID
+AddMemoryRangeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ EFI_PHYSICAL_ADDRESS MemoryLimit
+ )
+{
+ AddMemoryBaseSizeHob (MemoryBase, (UINT64) (MemoryLimit - MemoryBase));
+}
+/**
+ Create memory type information hand off block.
+
+ @param VOID
+
+ @return VOID
+**/
+VOID
+MemMapInitialization (
+ VOID
+ )
+{
+ DEBUG ((DEBUG_INFO, "==%a==\n", __func__));
+ //
+ // Create Memory Type Information HOB
+ //
+ BuildGuidDataHob (
+ &gEfiMemoryTypeInformationGuid,
+ mDefaultMemoryTypeInformation,
+ sizeof (mDefaultMemoryTypeInformation)
+ );
+}
+/** Get the UART base address of the console serial-port from the DT.
+
+ This function fetches the node referenced in the "stdout-path"
+ property of the "chosen" node and returns the base address of
+ the console UART.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree (Fdt).
+ @param [out] SerialConsoleAddress If success, contains the base address
+ of the console serial-port.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_NOT_FOUND Console serial-port info not found in DT.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GetSerialConsolePortAddress (
+ IN CONST VOID *Fdt,
+ OUT UINT64 *SerialConsoleAddress
+ )
+{
+ CONST CHAR8 *Prop;
+ INT32 PropSize;
+ CONST CHAR8 *Path;
+ INT32 PathLen;
+ INT32 ChosenNode;
+ INT32 SerialConsoleNode;
+ INT32 Len;
+ CONST CHAR8 *NodeStatus;
+ CONST UINT64 *RegProperty;
+
+ if ((Fdt == NULL) || (fdt_check_header (Fdt) != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // The "chosen" node resides at the root of the DT. Fetch it.
+ ChosenNode = fdt_path_offset (Fdt, "/chosen");
+ if (ChosenNode < 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ Prop = fdt_getprop (Fdt, ChosenNode, "stdout-path", &PropSize);
+ if (PropSize < 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ // Determine the actual path length, as a colon terminates the path.
+ Path = ScanMem8 (Prop, ':', PropSize);
+ if (Path == NULL) {
+ PathLen = AsciiStrLen (Prop);
+ } else {
+ PathLen = Path - Prop;
+ }
+
+ // Aliases cannot start with a '/', so it must be the actual path.
+ if (Prop[0] == '/') {
+ SerialConsoleNode = fdt_path_offset_namelen (Fdt, Prop, PathLen);
+ } else {
+ // Lookup the alias, as this contains the actual path.
+ Path = fdt_get_alias_namelen (Fdt, Prop, PathLen);
+ if (Path == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ SerialConsoleNode = fdt_path_offset (Fdt, Path);
+ }
+
+ NodeStatus = fdt_getprop (Fdt, SerialConsoleNode, "status", &Len);
+ if ((NodeStatus != NULL) && (AsciiStrCmp (NodeStatus, "okay") != 0)) {
+ return EFI_NOT_FOUND;
+ }
+
+ RegProperty = fdt_getprop (Fdt, SerialConsoleNode, "reg", &Len);
+ if (Len != 16) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *SerialConsoleAddress = fdt64_to_cpu (ReadUnaligned64 (RegProperty));
+
+ return EFI_SUCCESS;
+}
+
+/** Get the Rtc base address from the DT.
+
+ This function fetches the node referenced in the "loongson,ls7a-rtc"
+ property of the "reg" node and returns the base address of
+ the RTC.
+
+ @param [in] Fdt Pointer to a Flattened Device Tree (Fdt).
+ @param [out] RtcBaseAddress If success, contains the base address
+ of the Rtc.
+
+ @retval EFI_SUCCESS The function completed successfully.
+ @retval EFI_NOT_FOUND RTC info not found in DT.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+GetRtcAddress (
+ IN CONST VOID *Fdt,
+ OUT UINT64 *RtcBaseAddress
+ )
+{
+ INT32 Node;
+ INT32 Prev;
+ CONST CHAR8 *Type;
+ INT32 Len;
+ CONST UINT64 *RegProp;
+ EFI_STATUS Status;
+
+ if ((Fdt == NULL) || (fdt_check_header (Fdt) != 0)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = EFI_NOT_FOUND;
+ for (Prev = 0;; Prev = Node) {
+ Node = fdt_next_node (Fdt, Prev, NULL);
+ if (Node < 0) {
+ break;
+ }
+
+ //
+ // Check for memory node
+ //
+ Type = fdt_getprop (Fdt, Node, "compatible", &Len);
+ if ((Type)
+ && (AsciiStrnCmp (Type, "loongson,ls7a-rtc", Len) == 0))
+ {
+ //
+ // Get the 'reg' property of this node. For now, we will assume
+ // two 8 byte quantities for base and size, respectively.
+ //
+ RegProp = fdt_getprop (Fdt, Node, "reg", &Len);
+ if ((RegProp != 0)
+ && (Len == (2 * sizeof (UINT64))))
+ {
+ *RtcBaseAddress = SwapBytes64 (RegProp[0]);
+ Status = RETURN_SUCCESS;
+ DEBUG ((DEBUG_INFO, "%a Len %d RtcBase %llx\n",__func__, Len, *RtcBaseAddress));
+ break;
+ } else {
+ DEBUG ((DEBUG_ERROR, "%a: Failed to parse FDT rtc node\n",
+ __FUNCTION__));
+ break;
+ }
+ }
+ }
+
+ return Status;
+}
+/**
+ Misc Initialization.
+
+ @param VOID
+
+ @return VOID
+**/
+VOID
+MiscInitialization (
+ VOID
+ )
+{
+ DEBUG ((DEBUG_INFO, "==%a==\n", __func__));
+ //
+ // Creat CPU HOBs.
+ //
+ BuildCpuHob (PcdGet8 (PcdPrePiCpuMemorySize), PcdGet8 (PcdPrePiCpuIoSize));
+}
+/**
+ add fdt hand off block.
+
+ @param VOID
+
+ @return VOID
+**/
+VOID
+AddFdtHob (VOID)
+{
+ VOID *Base;
+ VOID *NewBase;
+ UINTN FdtSize;
+ UINTN FdtPages;
+ UINT64 *FdtHobData;
+ UINT64 *UartHobData;
+ UINT64 SerialConsoleAddress;
+ UINT64 RtcBaseAddress;
+ RETURN_STATUS Status;
+
+ Base = (VOID*)(UINTN)PcdGet64 (PcdDeviceTreeBase);
+ ASSERT (Base != NULL);
+
+ Status = GetSerialConsolePortAddress (Base, &SerialConsoleAddress);
+ if (RETURN_ERROR (Status)) {
+ return;
+ }
+ UartHobData = BuildGuidHob (&gEarly16550UartBaseAddressGuid, sizeof *UartHobData);
+ ASSERT (UartHobData != NULL);
+ *UartHobData = SerialConsoleAddress;
+
+ Status = GetRtcAddress(Base, &RtcBaseAddress);
+ if (RETURN_ERROR (Status)) {
+ return;
+ }
+ Status = PcdSet64S (PcdRtcBaseAddress, RtcBaseAddress);
+ if (RETURN_ERROR (Status)) {
+ return;
+ }
+
+ FdtSize = fdt_totalsize (Base) + PcdGet32 (PcdDeviceTreePadding);
+ FdtPages = EFI_SIZE_TO_PAGES (FdtSize);
+ NewBase = AllocatePages (FdtPages);
+ ASSERT (NewBase != NULL);
+ fdt_open_into (Base, NewBase, EFI_PAGES_TO_SIZE (FdtPages));
+
+ FdtHobData = BuildGuidHob (&gFdtHobGuid, sizeof *FdtHobData);
+ ASSERT (FdtHobData != NULL);
+ *FdtHobData = (UINTN)NewBase;
+}
+
+/**
+ Fetch the size of system memory from QEMU.
+
+ @param VOID
+
+ @return VOID
+**/
+VOID
+SystemMemorySizeInitialization (
+ VOID
+ )
+{
+ UINT64 RamSize;
+ RETURN_STATUS PcdStatus;
+
+ QemuFwCfgSelectItem (QemuFwCfgItemRamSize);
+ RamSize= QemuFwCfgRead64 ();
+ DEBUG ((DEBUG_INFO, "%a: QEMU reports %dM system memory\n", __FUNCTION__,
+ RamSize/1024/1024));
+
+ //
+ // If the fw_cfg key or fw_cfg entirely is unavailable, no change to PCD.
+ //
+ if (RamSize == 0) {
+ return;
+ }
+
+ //
+ // Otherwise, set RamSize to PCD.
+ //
+ PcdStatus = PcdSet64S (PcdRamSize, RamSize);
+ ASSERT_RETURN_ERROR (PcdStatus);
+}
+
+/**
+ Perform Platform PEI initialization.
+
+ @param FileHandle Handle of the file being invoked.
+ @param PeiServices Describes the list of possible PEI Services.
+
+ @return EFI_SUCCESS The PEIM initialized successfully.
+**/
+EFI_STATUS
+EFIAPI
+InitializePlatform (
+ IN EFI_PEI_FILE_HANDLE FileHandle,
+ IN CONST EFI_PEI_SERVICES **PeiServices
+ )
+{
+ EFI_STATUS Status;
+
+ DEBUG ((DEBUG_INFO, "Platform PEIM Loaded\n"));
+
+ Status = PeiServicesInstallPpi (&mPpiListBootMode);
+ ASSERT_EFI_ERROR (Status);
+
+ SystemMemorySizeInitialization ();
+ PublishPeiMemory ();
+ PeiFvInitialization ();
+ InitializeRamRegions ();
+ MemMapInitialization ();
+ MiscInitialization ();
+ AddFdtHob ();
+ ConfigureMmu ();
+
+ return EFI_SUCCESS;
+}
diff --git a/Platform/Loongson/LoongArchQemuPkg/PlatformPei/Platform.h b/Platform/Loongson/LoongArchQemuPkg/PlatformPei/Platform.h
new file mode 100644
index 0000000000..38d358b335
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/PlatformPei/Platform.h
@@ -0,0 +1,86 @@
+/** @file
+ Platform PEI module include file.
+
+ Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PLATFORM_H_
+#define PLATFORM_H_
+
+#include <IndustryStandard/Pci22.h>
+
+/**
+ Create system type memory range hand off block.
+
+ @param MemoryBase memory base address.
+ @param MemoryLimit memory length.
+
+ @return VOID
+**/
+VOID
+AddMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ );
+
+/**
+ Create memory range hand off block.
+
+ @param MemoryBase memory base address.
+ @param MemoryLimit memory length.
+
+ @return VOID
+**/
+VOID
+AddMemoryRangeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ EFI_PHYSICAL_ADDRESS MemoryLimit
+ );
+
+/**
+ Create Reserved type memory range hand off block.
+
+ @param MemoryBase memory base address.
+ @param MemoryLimit memory length.
+
+ @return VOID
+**/
+VOID
+AddReservedMemoryBaseSizeHob (
+ EFI_PHYSICAL_ADDRESS MemoryBase,
+ UINT64 MemorySize
+ );
+/**
+ Publish PEI core memory
+
+ @return EFI_SUCCESS The PEIM initialized successfully.
+**/
+EFI_STATUS
+PublishPeiMemory (
+ VOID
+ );
+/**
+ Publish system RAM and reserve memory regions
+
+ @return VOID
+**/
+VOID
+InitializeRamRegions (
+ VOID
+ );
+
+/**
+ Publish PEI & DXE (Decompressed) Memory based FVs to let PEI
+ and DXE know about them.
+
+ @retval EFI_SUCCESS Platform PEI FVs were initialized successfully.
+**/
+EFI_STATUS
+PeiFvInitialization (
+ VOID
+ );
+
+#endif // PLATFORM_H_
diff --git a/Platform/Loongson/LoongArchQemuPkg/PlatformPei/PlatformPei.inf b/Platform/Loongson/LoongArchQemuPkg/PlatformPei/PlatformPei.inf
new file mode 100644
index 0000000000..268efac585
--- /dev/null
+++ b/Platform/Loongson/LoongArchQemuPkg/PlatformPei/PlatformPei.inf
@@ -0,0 +1,74 @@
+## @file
+# Platform PEI driver
+#
+# Copyright (c) 2022 Loongson Technology Corporation Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = PlatformPei
+ FILE_GUID = 4c0e81e5-e8e3-4eef-b24b-19b686e9ab53
+ MODULE_TYPE = PEIM
+ VERSION_STRING = 1.0
+ ENTRY_POINT = InitializePlatform
+
+#
+# VALID_ARCHITECTURES = LOONGARCH64
+#
+
+[Sources]
+ Fv.c
+ MemDetect.c
+ Platform.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ EmbeddedPkg/EmbeddedPkg.dec
+ Platform/Loongson/LoongArchQemuPkg/Loongson.dec
+ OvmfPkg/OvmfPkg.dec
+
+[Ppis]
+ gEfiPeiMasterBootModePpiGuid
+
+[Guids]
+ gEfiMemoryTypeInformationGuid
+ gEarly16550UartBaseAddressGuid
+ gFdtHobGuid
+
+[LibraryClasses]
+ DebugLib
+ BaseMemoryLib
+ HobLib
+ IoLib
+ PeiResourcePublicationLib
+ PeiServicesLib
+ PeiServicesTablePointerLib
+ PeimEntryPoint
+ QemuFwCfgLib
+ PcdLib
+ TimerLib
+ MmuLib
+ MemoryAllocationLib
+
+[Pcd]
+ gLoongArchQemuPkgTokenSpaceGuid.PcdRamSize
+ gLoongArchQemuPkgTokenSpaceGuid.PcdDeviceTreeBase
+ gLoongArchQemuPkgTokenSpaceGuid.PcdDeviceTreePadding
+ gLoongArchQemuPkgTokenSpaceGuid.PcdRtcBaseAddress
+
+[FixedPcd]
+ gLoongArchQemuPkgTokenSpaceGuid.PcdFlashDxeFvBase
+ gLoongArchQemuPkgTokenSpaceGuid.PcdFlashDxeFvSize
+ gLoongArchQemuPkgTokenSpaceGuid.PcdRamRegionsBottom
+ gLoongArchQemuPkgTokenSpaceGuid.PcdUefiRamTop
+ gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamBase
+ gLoongArchQemuPkgTokenSpaceGuid.PcdSecPeiTempRamSize
+ gEmbeddedTokenSpaceGuid.PcdPrePiCpuMemorySize
+ gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize
+
+[Depex]
+ TRUE
--
2.31.1
-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#96455): https://edk2.groups.io/g/devel/message/96455
Mute This Topic: https://groups.io/mt/95082594/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
© 2016 - 2024 Red Hat, Inc.