/** @file | |
Copyright (c) 2011-2015, ARM Limited. All rights reserved. | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include <PiPei.h> | |
#include <Library/ArmMmuLib.h> | |
#include <Library/ArmPlatformLib.h> | |
#include <Library/DebugLib.h> | |
#include <Library/HobLib.h> | |
#include <Library/MemoryAllocationLib.h> | |
#include <Library/PcdLib.h> | |
VOID | |
BuildMemoryTypeInformationHob ( | |
VOID | |
); | |
STATIC | |
VOID | |
InitMmu ( | |
IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryTable | |
) | |
{ | |
VOID *TranslationTableBase; | |
UINTN TranslationTableSize; | |
RETURN_STATUS Status; | |
// Note: Because we called PeiServicesInstallPeiMemory() before to call InitMmu() the MMU Page Table resides in | |
// DRAM (even at the top of DRAM as it is the first permanent memory allocation) | |
Status = ArmConfigureMmu (MemoryTable, &TranslationTableBase, &TranslationTableSize); | |
if (EFI_ERROR (Status)) { | |
DEBUG ((DEBUG_ERROR, "Error: Failed to enable MMU\n")); | |
} | |
} | |
/*++ | |
Routine Description: | |
Arguments: | |
FileHandle - Handle of the file being invoked. | |
PeiServices - Describes the list of possible PEI Services. | |
Returns: | |
Status - EFI_SUCCESS if the boot mode could be set | |
--*/ | |
EFI_STATUS | |
EFIAPI | |
MemoryPeim ( | |
IN EFI_PHYSICAL_ADDRESS UefiMemoryBase, | |
IN UINT64 UefiMemorySize | |
) | |
{ | |
ARM_MEMORY_REGION_DESCRIPTOR *MemoryTable; | |
EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttributes; | |
UINT64 ResourceLength; | |
EFI_PEI_HOB_POINTERS NextHob; | |
EFI_PHYSICAL_ADDRESS FdTop; | |
EFI_PHYSICAL_ADDRESS SystemMemoryTop; | |
EFI_PHYSICAL_ADDRESS ResourceTop; | |
BOOLEAN Found; | |
// Get Virtual Memory Map from the Platform Library | |
ArmPlatformGetVirtualMemoryMap (&MemoryTable); | |
// Ensure PcdSystemMemorySize has been set | |
ASSERT (PcdGet64 (PcdSystemMemorySize) != 0); | |
// | |
// Now, the permanent memory has been installed, we can call AllocatePages() | |
// | |
ResourceAttributes = ( | |
EFI_RESOURCE_ATTRIBUTE_PRESENT | | |
EFI_RESOURCE_ATTRIBUTE_INITIALIZED | | |
EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | | |
EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | | |
EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE | | |
EFI_RESOURCE_ATTRIBUTE_TESTED | |
); | |
// | |
// Check if the resource for the main system memory has been declared | |
// | |
Found = FALSE; | |
NextHob.Raw = GetHobList (); | |
while ((NextHob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, NextHob.Raw)) != NULL) { | |
if ((NextHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) && | |
(PcdGet64 (PcdSystemMemoryBase) >= NextHob.ResourceDescriptor->PhysicalStart) && | |
(NextHob.ResourceDescriptor->PhysicalStart + NextHob.ResourceDescriptor->ResourceLength <= PcdGet64 (PcdSystemMemoryBase) + PcdGet64 (PcdSystemMemorySize))) | |
{ | |
Found = TRUE; | |
break; | |
} | |
NextHob.Raw = GET_NEXT_HOB (NextHob); | |
} | |
if (!Found) { | |
// Reserved the memory space occupied by the firmware volume | |
BuildResourceDescriptorHob ( | |
EFI_RESOURCE_SYSTEM_MEMORY, | |
ResourceAttributes, | |
PcdGet64 (PcdSystemMemoryBase), | |
PcdGet64 (PcdSystemMemorySize) | |
); | |
} | |
// | |
// Reserved the memory space occupied by the firmware volume | |
// | |
SystemMemoryTop = (EFI_PHYSICAL_ADDRESS)PcdGet64 (PcdSystemMemoryBase) + (EFI_PHYSICAL_ADDRESS)PcdGet64 (PcdSystemMemorySize); | |
FdTop = (EFI_PHYSICAL_ADDRESS)PcdGet64 (PcdFdBaseAddress) + (EFI_PHYSICAL_ADDRESS)PcdGet32 (PcdFdSize); | |
// EDK2 does not have the concept of boot firmware copied into DRAM. To avoid the DXE | |
// core to overwrite this area we must create a memory allocation HOB for the region, | |
// but this only works if we split off the underlying resource descriptor as well. | |
if ((PcdGet64 (PcdFdBaseAddress) >= PcdGet64 (PcdSystemMemoryBase)) && (FdTop <= SystemMemoryTop)) { | |
Found = FALSE; | |
// Search for System Memory Hob that contains the firmware | |
NextHob.Raw = GetHobList (); | |
while ((NextHob.Raw = GetNextHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, NextHob.Raw)) != NULL) { | |
if ((NextHob.ResourceDescriptor->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) && | |
(PcdGet64 (PcdFdBaseAddress) >= NextHob.ResourceDescriptor->PhysicalStart) && | |
(FdTop <= NextHob.ResourceDescriptor->PhysicalStart + NextHob.ResourceDescriptor->ResourceLength)) | |
{ | |
ResourceAttributes = NextHob.ResourceDescriptor->ResourceAttribute; | |
ResourceLength = NextHob.ResourceDescriptor->ResourceLength; | |
ResourceTop = NextHob.ResourceDescriptor->PhysicalStart + ResourceLength; | |
if (PcdGet64 (PcdFdBaseAddress) == NextHob.ResourceDescriptor->PhysicalStart) { | |
if (SystemMemoryTop != FdTop) { | |
// Create the System Memory HOB for the firmware | |
BuildResourceDescriptorHob ( | |
EFI_RESOURCE_SYSTEM_MEMORY, | |
ResourceAttributes, | |
PcdGet64 (PcdFdBaseAddress), | |
PcdGet32 (PcdFdSize) | |
); | |
// Top of the FD is system memory available for UEFI | |
NextHob.ResourceDescriptor->PhysicalStart += PcdGet32 (PcdFdSize); | |
NextHob.ResourceDescriptor->ResourceLength -= PcdGet32 (PcdFdSize); | |
} | |
} else { | |
// Create the System Memory HOB for the firmware | |
BuildResourceDescriptorHob ( | |
EFI_RESOURCE_SYSTEM_MEMORY, | |
ResourceAttributes, | |
PcdGet64 (PcdFdBaseAddress), | |
PcdGet32 (PcdFdSize) | |
); | |
// Update the HOB | |
NextHob.ResourceDescriptor->ResourceLength = PcdGet64 (PcdFdBaseAddress) - NextHob.ResourceDescriptor->PhysicalStart; | |
// If there is some memory available on the top of the FD then create a HOB | |
if (FdTop < NextHob.ResourceDescriptor->PhysicalStart + ResourceLength) { | |
// Create the System Memory HOB for the remaining region (top of the FD) | |
BuildResourceDescriptorHob ( | |
EFI_RESOURCE_SYSTEM_MEMORY, | |
ResourceAttributes, | |
FdTop, | |
ResourceTop - FdTop | |
); | |
} | |
} | |
// Mark the memory covering the Firmware Device as boot services data | |
BuildMemoryAllocationHob ( | |
PcdGet64 (PcdFdBaseAddress), | |
PcdGet32 (PcdFdSize), | |
EfiBootServicesData | |
); | |
Found = TRUE; | |
break; | |
} | |
NextHob.Raw = GET_NEXT_HOB (NextHob); | |
} | |
ASSERT (Found); | |
} | |
// Build Memory Allocation Hob | |
InitMmu (MemoryTable); | |
if (FeaturePcdGet (PcdPrePiProduceMemoryTypeInformationHob)) { | |
// Optional feature that helps prevent EFI memory map fragmentation. | |
BuildMemoryTypeInformationHob (); | |
} | |
return EFI_SUCCESS; | |
} |