mirror of
https://github.com/acidanthera/audk.git
synced 2025-08-30 14:08:09 +02:00
Platfrom PEI module for LoongArch platfrom initialization. BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4584 Cc: Ard Biesheuvel <ardb+tianocore@kernel.org> Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Gerd Hoffmann <kraxel@redhat.com> Cc: Bibo Mao <maobibo@loongson.cn> Cc: Dongyan Qian <qiandongyan@loongson.cn> Signed-off-by: Chao Li <lichao@loongson.cn> Co-authored-by: Xianglai Li <lixianglai@loongson.cn> Co-authored-by: Bibo Mao <maobibo@loongson.cn>
365 lines
8.2 KiB
C
365 lines
8.2 KiB
C
/** @file
|
|
Platform PEI driver
|
|
|
|
Copyright (c) 2024 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 <Guid/MemoryTypeInformation.h>
|
|
#include <Guid/FdtHob.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/CpuMmuInitLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/HobLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/MpInitLib.h>
|
|
#include <Library/PcdLib.h>
|
|
#include <Library/PeimEntryPoint.h>
|
|
#include <Library/PeiServicesLib.h>
|
|
#include <Library/PlatformHookLib.h>
|
|
#include <Library/QemuFwCfgLib.h>
|
|
#include <libfdt.h>
|
|
#include <Ppi/MasterBootMode.h>
|
|
#include <Register/LoongArch64/Cpucfg.h>
|
|
#include <Register/LoongArch64/Csr.h>
|
|
#include <Uefi/UefiSpec.h>
|
|
|
|
#include "Platform.h"
|
|
|
|
STATIC 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
|
|
};
|
|
|
|
STATIC EFI_BOOT_MODE mBootMode = BOOT_WITH_FULL_CONFIGURATION;
|
|
|
|
/**
|
|
Create system type memory range hand off block.
|
|
|
|
@param MemoryBase memory base address.
|
|
@param MemoryLimit memory length.
|
|
|
|
@return VOID
|
|
**/
|
|
STATIC
|
|
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));
|
|
}
|
|
|
|
STATIC
|
|
VOID
|
|
SaveRtcRegisterAddressHob (
|
|
UINT64 RtcRegisterBase
|
|
)
|
|
{
|
|
UINT64 Data64;
|
|
|
|
//
|
|
// Build location of RTC register base address buffer in HOB
|
|
//
|
|
Data64 = (UINT64)(UINTN)RtcRegisterBase;
|
|
|
|
BuildGuidDataHob (
|
|
&gRtcRegisterBaseAddressHobGuid,
|
|
(VOID *)&Data64,
|
|
sizeof (UINT64)
|
|
);
|
|
}
|
|
|
|
/**
|
|
Create memory type information hand off block.
|
|
|
|
@param VOID
|
|
|
|
@return VOID
|
|
**/
|
|
STATIC
|
|
VOID
|
|
MemMapInitialization (
|
|
VOID
|
|
)
|
|
{
|
|
DEBUG ((DEBUG_INFO, "==%a==\n", __func__));
|
|
//
|
|
// Create Memory Type Information HOB
|
|
//
|
|
BuildGuidDataHob (
|
|
&gEfiMemoryTypeInformationGuid,
|
|
mDefaultMemoryTypeInformation,
|
|
sizeof (mDefaultMemoryTypeInformation)
|
|
);
|
|
}
|
|
|
|
/** 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", __func__));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Misc Initialization.
|
|
|
|
@param VOID
|
|
|
|
@return VOID
|
|
**/
|
|
STATIC
|
|
VOID
|
|
MiscInitialization (
|
|
VOID
|
|
)
|
|
{
|
|
CPUCFG_REG1_INFO_DATA CpucfgReg1Data;
|
|
UINT8 CpuPhysMemAddressWidth;
|
|
|
|
DEBUG ((DEBUG_INFO, "==%a==\n", __func__));
|
|
|
|
//
|
|
// Get the the CPU physical memory address width.
|
|
//
|
|
AsmCpucfg (CPUCFG_REG1_INFO, &CpucfgReg1Data.Uint32);
|
|
|
|
CpuPhysMemAddressWidth = (UINT8)(CpucfgReg1Data.Bits.PALEN + 1);
|
|
|
|
//
|
|
// Creat CPU HOBs.
|
|
//
|
|
BuildCpuHob (CpuPhysMemAddressWidth, FixedPcdGet8 (PcdPrePiCpuIoSize));
|
|
}
|
|
|
|
/**
|
|
add fdt hand off block.
|
|
|
|
@param VOID
|
|
|
|
@return VOID
|
|
**/
|
|
STATIC
|
|
VOID
|
|
AddFdtHob (
|
|
VOID
|
|
)
|
|
{
|
|
VOID *Base;
|
|
VOID *NewBase;
|
|
UINTN FdtSize;
|
|
UINTN FdtPages;
|
|
UINT64 *FdtHobData;
|
|
UINT64 RtcBaseAddress;
|
|
RETURN_STATUS Status;
|
|
|
|
Base = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress);
|
|
ASSERT (Base != NULL);
|
|
|
|
Status = GetRtcAddress (Base, &RtcBaseAddress);
|
|
if (RETURN_ERROR (Status)) {
|
|
return;
|
|
}
|
|
|
|
SaveRtcRegisterAddressHob (RtcBaseAddress);
|
|
|
|
FdtSize = fdt_totalsize (Base) + PcdGet32 (PcdDeviceTreeAllocationPadding);
|
|
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
|
|
**/
|
|
STATIC
|
|
VOID
|
|
ReportSystemMemorySize (
|
|
VOID
|
|
)
|
|
{
|
|
UINT64 RamSize;
|
|
|
|
QemuFwCfgSelectItem (QemuFwCfgItemRamSize);
|
|
RamSize = QemuFwCfgRead64 ();
|
|
DEBUG ((
|
|
DEBUG_INFO,
|
|
"%a: QEMU reports %dM system memory\n",
|
|
__func__,
|
|
RamSize/1024/1024
|
|
));
|
|
}
|
|
|
|
/**
|
|
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;
|
|
EFI_MEMORY_DESCRIPTOR *MemoryTable;
|
|
|
|
DEBUG ((DEBUG_INFO, "Platform PEIM Loaded\n"));
|
|
|
|
Status = PeiServicesSetBootMode (mBootMode);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
Status = PeiServicesInstallPpi (&mPpiListBootMode);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
ReportSystemMemorySize ();
|
|
|
|
PublishPeiMemory ();
|
|
|
|
PeiFvInitialization ();
|
|
InitializeRamRegions ();
|
|
MemMapInitialization ();
|
|
|
|
Status = PlatformHookSerialPortInitialize ();
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
MiscInitialization ();
|
|
|
|
AddFdtHob ();
|
|
|
|
//
|
|
// Initialization MMU
|
|
//
|
|
GetMemoryMapPolicy (&MemoryTable);
|
|
Status = ConfigureMemoryManagementUnit (MemoryTable);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
MpInitLibInitialize ();
|
|
|
|
return EFI_SUCCESS;
|
|
}
|