/** @file Copyright (c) 2011-2015, ARM Limited. All rights reserved. SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include #include #include 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; }