| /** @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; | |
| } |