blob: 281e4783cbe86b5c6421dd70bd0993f100b294d5 [file] [log] [blame]
/** @file
Memory Detection for RiscVVirt Machines.
Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2025, Ventana Micro Systems Inc. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "PlatformSecLib.h"
VOID
BuildMemoryTypeHob (
VOID
)
{
EFI_MEMORY_TYPE_INFORMATION Info[6];
Info[0].Type = EfiACPIReclaimMemory;
Info[0].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiACPIReclaimMemory);
Info[1].Type = EfiACPIMemoryNVS;
Info[1].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiACPIMemoryNVS);
Info[2].Type = EfiReservedMemoryType;
Info[2].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiReservedMemoryType);
Info[3].Type = EfiRuntimeServicesData;
Info[3].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiRuntimeServicesData);
Info[4].Type = EfiRuntimeServicesCode;
Info[4].NumberOfPages = PcdGet32 (PcdMemoryTypeEfiRuntimeServicesCode);
// Terminator for the list
Info[5].Type = EfiMaxMemoryType;
Info[5].NumberOfPages = 0;
BuildGuidDataHob (&gEfiMemoryTypeInformationGuid, &Info, sizeof (Info));
}
/**
Create memory range resource HOB using the memory base
address and size.
@param MemoryBase Memory range base address.
@param MemorySize Memory range size.
**/
STATIC
VOID
AddMemoryBaseSizeHob (
IN EFI_PHYSICAL_ADDRESS MemoryBase,
IN 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 resource HOB using memory base
address and top address of the memory range.
@param MemoryBase Memory range base address.
@param MemoryLimit Memory range size.
**/
STATIC
VOID
AddMemoryRangeHob (
IN EFI_PHYSICAL_ADDRESS MemoryBase,
IN EFI_PHYSICAL_ADDRESS MemoryLimit
)
{
AddMemoryBaseSizeHob (MemoryBase, (UINT64)(MemoryLimit - MemoryBase));
}
/**
Publish system RAM and reserve memory regions.
**/
STATIC
VOID
InitializeRamRegions (
IN EFI_PHYSICAL_ADDRESS SystemMemoryBase,
IN UINT64 SystemMemorySize
)
{
AddMemoryRangeHob (
SystemMemoryBase,
SystemMemoryBase + SystemMemorySize
);
}
/** Get the number of cells for a given property
@param[in] Fdt Pointer to Device Tree (DTB)
@param[in] Node Node
@param[in] Name Name of the property
@return Number of cells.
**/
STATIC
INT32
GetNumCells (
IN VOID *Fdt,
IN INT32 Node,
IN CONST CHAR8 *Name
)
{
CONST INT32 *Prop;
INT32 Len;
UINT32 Val;
Prop = FdtGetProp (Fdt, Node, Name, &Len);
if (Prop == NULL) {
return Len;
}
if (Len != sizeof (*Prop)) {
return -FDT_ERR_BADNCELLS;
}
Val = Fdt32ToCpu (*Prop);
if (Val > FDT_MAX_NCELLS) {
return -FDT_ERR_BADNCELLS;
}
return (INT32)Val;
}
/** Mark reserved memory ranges in the EFI memory map
* As per DT spec v0.4 Section 3.5.4,
* "Reserved regions with the no-map property must be listed in the
* memory map with type EfiReservedMemoryType. All other reserved
* regions must be listed with type EfiBootServicesData."
@param FdtPointer Pointer to FDT
**/
STATIC
VOID
AddReservedMemoryMap (
IN VOID *FdtPointer
)
{
CONST INT32 *RegProp;
INT32 Node;
INT32 SubNode;
INT32 Len;
EFI_PHYSICAL_ADDRESS Addr;
UINT64 Size;
INTN NumRsv, i;
INT32 NumAddrCells, NumSizeCells;
NumRsv = FdtGetNumberOfReserveMapEntries (FdtPointer);
/* Look for an existing entry and add it to the efi mem map. */
for (i = 0; i < NumRsv; i++) {
if (FdtGetReserveMapEntry (FdtPointer, i, &Addr, &Size) != 0) {
continue;
}
BuildMemoryAllocationHob (
Addr,
Size,
EfiReservedMemoryType
);
}
/* process reserved-memory */
Node = FdtSubnodeOffset (FdtPointer, 0, "reserved-memory");
if (Node >= 0) {
NumAddrCells = GetNumCells (FdtPointer, Node, "#address-cells");
if (NumAddrCells <= 0) {
return;
}
NumSizeCells = GetNumCells (FdtPointer, Node, "#size-cells");
if (NumSizeCells <= 0) {
return;
}
FdtForEachSubnode (SubNode, FdtPointer, Node) {
RegProp = FdtGetProp (FdtPointer, SubNode, "reg", &Len);
if ((RegProp != 0) && (Len == ((NumAddrCells + NumSizeCells) * sizeof (INT32)))) {
Addr = Fdt32ToCpu (RegProp[0]);
if (NumAddrCells > 1) {
Addr = (Addr << 32) | Fdt32ToCpu (RegProp[1]);
}
RegProp += NumAddrCells;
Size = Fdt32ToCpu (RegProp[0]);
if (NumSizeCells > 1) {
Size = (Size << 32) | Fdt32ToCpu (RegProp[1]);
}
DEBUG ((
DEBUG_INFO,
"%a: Adding Reserved Memory Addr = 0x%llx, Size = 0x%llx\n",
__func__,
Addr,
Size
));
if (FdtGetProp (FdtPointer, SubNode, "no-map", &Len)) {
BuildMemoryAllocationHob (
Addr,
Size,
EfiReservedMemoryType
);
} else {
BuildMemoryAllocationHob (
Addr,
Size,
EfiBootServicesData
);
}
}
}
}
}
/**
Perform Memory initialization.
@param FdtPointer The pointer to the device tree.
@return EFI_SUCCESS The platform initialized successfully.
@retval Others - As the error code indicates
**/
EFI_STATUS
EFIAPI
MemoryInitialization (
VOID *FdtPointer
)
{
CONST UINT64 *RegProp;
CONST CHAR8 *Type;
UINT64 CurBase, CurSize;
INT32 Node, Prev;
INT32 Len;
// Look for the lowest memory node
for (Prev = 0; ; Prev = Node) {
Node = FdtNextNode (FdtPointer, Prev, NULL);
if (Node < 0) {
break;
}
// Check for memory node
Type = FdtGetProp (FdtPointer, Node, "device_type", &Len);
if (Type && (AsciiStrnCmp (Type, "memory", Len) == 0)) {
// Get the 'reg' property of this node. For now, we will assume
// two 8 byte quantities for base and size, respectively.
RegProp = FdtGetProp (FdtPointer, Node, "reg", &Len);
if ((RegProp != 0) && (Len == (2 * sizeof (UINT64)))) {
CurBase = Fdt64ToCpu (ReadUnaligned64 (RegProp));
CurSize = Fdt64ToCpu (ReadUnaligned64 (RegProp + 1));
DEBUG ((
DEBUG_INFO,
"%a: System RAM @ 0x%lx - 0x%lx\n",
__func__,
CurBase,
CurBase + CurSize - 1
));
InitializeRamRegions (
CurBase,
CurSize
);
} else {
DEBUG ((
DEBUG_ERROR,
"%a: Failed to parse FDT memory node\n",
__func__
));
}
}
}
AddReservedMemoryMap (FdtPointer);
/* Make sure SEC is booting with bare mode */
ASSERT ((RiscVGetSupervisorAddressTranslationRegister () & SATP64_MODE) == (SATP_MODE_OFF << SATP64_MODE_SHIFT));
BuildMemoryTypeHob ();
return EFI_SUCCESS;
}