mirror of https://github.com/acidanthera/audk.git
238 lines
7.1 KiB
C
238 lines
7.1 KiB
C
/** @file
|
|
Memory Detection for Virtual Machines.
|
|
|
|
Copyright (c) 2024 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/DebugLib.h>
|
|
#include <Library/HobLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/PcdLib.h>
|
|
#include <Library/QemuFwCfgLib.h>
|
|
#include <Library/ResourcePublicationLib.h>
|
|
#include <Register/LoongArch64/Csr.h>
|
|
#include <Uefi/UefiSpec.h>
|
|
#include "Platform.h"
|
|
|
|
#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS (128)
|
|
#define LOONGARCH_FW_RAM_TOP BASE_256MB
|
|
|
|
/**
|
|
Publish PEI core memory
|
|
|
|
@return EFI_SUCCESS The PEIM initialized successfully.
|
|
**/
|
|
EFI_STATUS
|
|
PublishPeiMemory (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT64 Base;
|
|
UINT64 Size;
|
|
UINT64 RamTop;
|
|
FIRMWARE_CONFIG_ITEM FwCfgItem;
|
|
UINTN FwCfgSize;
|
|
UINTN Processed;
|
|
MEMMAP_ENTRY MemoryMapEntry;
|
|
|
|
//
|
|
// Determine the range of memory to use during PEI
|
|
//
|
|
Base = FixedPcdGet64 (PcdOvmfSecPeiTempRamBase) + FixedPcdGet32 (PcdOvmfSecPeiTempRamSize);
|
|
RamTop = 0;
|
|
|
|
Status = QemuFwCfgFindFile ("etc/memmap", &FwCfgItem, &FwCfgSize);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
if (FwCfgSize % sizeof MemoryMapEntry != 0) {
|
|
return EFI_PROTOCOL_ERROR;
|
|
}
|
|
|
|
QemuFwCfgSelectItem (FwCfgItem);
|
|
for (Processed = 0; Processed < FwCfgSize; Processed += sizeof MemoryMapEntry) {
|
|
QemuFwCfgReadBytes (sizeof MemoryMapEntry, &MemoryMapEntry);
|
|
if (MemoryMapEntry.Type != EfiAcpiAddressRangeMemory) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Find memory map entry where PEI temp stack is located
|
|
//
|
|
if ((MemoryMapEntry.BaseAddr <= Base) &&
|
|
(Base < (MemoryMapEntry.BaseAddr + MemoryMapEntry.Length)))
|
|
{
|
|
RamTop = MemoryMapEntry.BaseAddr + MemoryMapEntry.Length;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (RamTop == 0) {
|
|
DEBUG ((DEBUG_ERROR, "ERROR: No memory map entry contains temp stack \n"));
|
|
ASSERT (FALSE);
|
|
}
|
|
|
|
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;
|
|
MEMMAP_ENTRY MemoryMapEntry;
|
|
MEMMAP_ENTRY *StartEntry;
|
|
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);
|
|
}
|
|
|
|
//
|
|
// When 0 address protection is enabled,
|
|
// 0-4k memory needs to be preallocated to prevent UEFI applications from allocating use,
|
|
// such as grub
|
|
//
|
|
if (PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT0) {
|
|
BuildMemoryAllocationHob (
|
|
0,
|
|
EFI_PAGE_SIZE,
|
|
EfiBootServicesData
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Gets the Virtual Memory Map of corresponding platforms.
|
|
|
|
This Virtual Memory Map is used by initialize the MMU on corresponding
|
|
platforms.
|
|
|
|
@param[out] MemoryTable Array of EFI_MEMORY_DESCRIPTOR
|
|
describing a Physical-to-Virtual Memory
|
|
mapping. This array must be ended by a
|
|
zero-filled entry. The allocated memory
|
|
will not be freed.
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
GetMemoryMapPolicy (
|
|
OUT EFI_MEMORY_DESCRIPTOR **MemoryTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
FIRMWARE_CONFIG_ITEM FwCfgItem;
|
|
UINTN FwCfgSize;
|
|
MEMMAP_ENTRY MemoryMapEntry;
|
|
MEMMAP_ENTRY *StartEntry;
|
|
MEMMAP_ENTRY *pEntry;
|
|
UINTN Processed;
|
|
EFI_MEMORY_DESCRIPTOR *VirtualMemoryTable;
|
|
UINTN Index = 0;
|
|
|
|
ASSERT (MemoryTable != NULL);
|
|
|
|
VirtualMemoryTable = AllocatePool (
|
|
sizeof (EFI_MEMORY_DESCRIPTOR) *
|
|
MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS
|
|
);
|
|
|
|
//
|
|
// Add the 0x10000000-0x20000000. In the virtual machine, this area use for CPU UART, flash, PIC etc.
|
|
//
|
|
VirtualMemoryTable[Index].PhysicalStart = BASE_256MB;
|
|
VirtualMemoryTable[Index].VirtualStart = VirtualMemoryTable[Index].PhysicalStart;
|
|
VirtualMemoryTable[Index].NumberOfPages = EFI_SIZE_TO_PAGES (SIZE_256MB);
|
|
VirtualMemoryTable[Index].Attribute = EFI_MEMORY_UC;
|
|
++Index;
|
|
|
|
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));
|
|
ZeroMem (&VirtualMemoryTable[Index], sizeof (EFI_MEMORY_DESCRIPTOR));
|
|
*MemoryTable = VirtualMemoryTable;
|
|
return;
|
|
}
|
|
|
|
if (FwCfgSize % sizeof MemoryMapEntry != 0) {
|
|
DEBUG ((DEBUG_ERROR, "no MemoryMapEntry FwCfgSize:%d\n", FwCfgSize));
|
|
}
|
|
|
|
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));
|
|
VirtualMemoryTable[Index].PhysicalStart = pEntry->BaseAddr;
|
|
VirtualMemoryTable[Index].VirtualStart = VirtualMemoryTable[Index].PhysicalStart;
|
|
VirtualMemoryTable[Index].NumberOfPages = EFI_SIZE_TO_PAGES (pEntry->Length);
|
|
VirtualMemoryTable[Index].Attribute = EFI_MEMORY_WB;
|
|
++Index;
|
|
}
|
|
|
|
FreePages (StartEntry, EFI_SIZE_TO_PAGES (FwCfgSize));
|
|
// End of Table
|
|
ZeroMem (&VirtualMemoryTable[Index], sizeof (EFI_MEMORY_DESCRIPTOR));
|
|
*MemoryTable = VirtualMemoryTable;
|
|
}
|