/** @file Copyright (c) 2022, Arm Limited. All rights reserved. SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include #include #include #include #include #include "CloudHvVirtMemInfoLib.h" CLOUDHV_MEM_NODE_INFO CloudHvMemNode[CLOUDHV_MAX_MEM_NODE_NUM]; /** Get all of memory nodes info from DT. Store all of them into CloudHvMemNode which will be consumed by ArmVirtGetMemoryMap. @retval RETURN_SUCCESS Success. @retval EFI_NOT_FOUND DT or the first memory node not found. **/ RETURN_STATUS EFIAPI CloudHvVirtMemInfoPeiLibConstructor ( VOID ) { VOID *DeviceTreeBase; EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttributes; INT32 Node, Prev; UINT64 FirMemNodeBase, FirMemNodeSize; UINT64 CurBase, MemBase; UINT64 CurSize; CONST CHAR8 *Type; INT32 Len; CONST UINT64 *RegProp; RETURN_STATUS PcdStatus; UINT8 Index; ZeroMem (CloudHvMemNode, sizeof (CloudHvMemNode)); FirMemNodeBase = 0; FirMemNodeSize = 0; Index = 0; MemBase = FixedPcdGet64 (PcdSystemMemoryBase); ResourceAttributes = ( EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE | EFI_RESOURCE_ATTRIBUTE_TESTED ); DeviceTreeBase = (VOID *)(UINTN)PcdGet64 (PcdDeviceTreeInitialBaseAddress); if (DeviceTreeBase == NULL) { return EFI_NOT_FOUND; } // // Make sure we have a valid device tree blob // if (fdt_check_header (DeviceTreeBase) != 0) { return EFI_NOT_FOUND; } // // Look for the lowest memory node // for (Prev = 0; ; Prev = Node) { Node = fdt_next_node (DeviceTreeBase, Prev, NULL); if (Node < 0) { break; } // // Check for memory node // Type = fdt_getprop (DeviceTreeBase, Node, "device_type", &Len); if ((Type != 0) && (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 = fdt_getprop (DeviceTreeBase, Node, "reg", &Len); if ((RegProp != 0) && (Len == (2 * sizeof (UINT64)))) { CurBase = fdt64_to_cpu (ReadUnaligned64 (RegProp)); CurSize = fdt64_to_cpu (ReadUnaligned64 (RegProp + 1)); DEBUG (( DEBUG_INFO, "%a: System RAM @ 0x%lx - 0x%lx\n", __FUNCTION__, CurBase, CurBase + CurSize - 1 )); // We should build Hob seperately for the memory node except the first one if (CurBase != MemBase) { BuildResourceDescriptorHob ( EFI_RESOURCE_SYSTEM_MEMORY, ResourceAttributes, CurBase, CurSize ); } else { FirMemNodeBase = CurBase; FirMemNodeSize = CurSize; } CloudHvMemNode[Index].Base = CurBase; CloudHvMemNode[Index].Size = CurSize; Index++; if (Index >= CLOUDHV_MAX_MEM_NODE_NUM) { DEBUG (( DEBUG_WARN, "%a: memory node larger than %d will not be included into Memory System\n", __FUNCTION__, CLOUDHV_MAX_MEM_NODE_NUM )); break; } } else { DEBUG (( DEBUG_ERROR, "%a: Failed to parse FDT memory node\n", __FUNCTION__ )); } } } // // Make sure the start of DRAM matches our expectation // if (FixedPcdGet64 (PcdSystemMemoryBase) != FirMemNodeBase) { return EFI_NOT_FOUND; } PcdStatus = PcdSet64S (PcdSystemMemorySize, FirMemNodeSize); ASSERT_RETURN_ERROR (PcdStatus); ASSERT ( (((UINT64)PcdGet64 (PcdFdBaseAddress) + (UINT64)PcdGet32 (PcdFdSize)) <= FirMemNodeBase) || ((UINT64)PcdGet64 (PcdFdBaseAddress) >= (FirMemNodeBase + FirMemNodeSize)) ); return RETURN_SUCCESS; } /** Return the Virtual Memory Map of your platform This Virtual Memory Map is used by MemoryInitPei Module to initialize the MMU on your platform. @param[out] VirtualMemoryMap Array of ARM_MEMORY_REGION_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 ArmVirtGetMemoryMap ( OUT ARM_MEMORY_REGION_DESCRIPTOR **VirtualMemoryMap ) { ARM_MEMORY_REGION_DESCRIPTOR *VirtualMemoryTable; UINT8 Index, MemNodeIndex; ASSERT (VirtualMemoryMap != NULL); VirtualMemoryTable = AllocatePool ( sizeof (ARM_MEMORY_REGION_DESCRIPTOR) * MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS ); if (VirtualMemoryTable == NULL) { DEBUG ((DEBUG_ERROR, "%a: Error: Failed AllocatePool()\n", __FUNCTION__)); return; } Index = 0; MemNodeIndex = 0; // System DRAM while ((MemNodeIndex < CLOUDHV_MAX_MEM_NODE_NUM) && (CloudHvMemNode[MemNodeIndex].Size != 0)) { VirtualMemoryTable[Index].PhysicalBase = CloudHvMemNode[MemNodeIndex].Base; VirtualMemoryTable[Index].VirtualBase = CloudHvMemNode[MemNodeIndex].Base; VirtualMemoryTable[Index].Length = CloudHvMemNode[MemNodeIndex].Size; VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK; DEBUG (( DEBUG_INFO, "%a: Dumping System DRAM Memory Node%d Map:\n" "\tPhysicalBase: 0x%lX\n" "\tVirtualBase: 0x%lX\n" "\tLength: 0x%lX\n", __FUNCTION__, MemNodeIndex, VirtualMemoryTable[Index].PhysicalBase, VirtualMemoryTable[Index].VirtualBase, VirtualMemoryTable[Index].Length )); Index++; MemNodeIndex++; } // Memory mapped peripherals (UART, RTC, GIC, virtio-mmio, etc) VirtualMemoryTable[Index].PhysicalBase = MACH_VIRT_PERIPH_BASE; VirtualMemoryTable[Index].VirtualBase = MACH_VIRT_PERIPH_BASE; VirtualMemoryTable[Index].Length = MACH_VIRT_PERIPH_SIZE; VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE; Index++; // Map the FV region as normal executable memory VirtualMemoryTable[Index].PhysicalBase = PcdGet64 (PcdFvBaseAddress); VirtualMemoryTable[Index].VirtualBase = VirtualMemoryTable[Index].PhysicalBase; VirtualMemoryTable[Index].Length = FixedPcdGet32 (PcdFvSize); VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK; Index++; // Memory mapped for 32bit device (like TPM) VirtualMemoryTable[Index].PhysicalBase = TOP_32BIT_DEVICE_BASE; VirtualMemoryTable[Index].VirtualBase = TOP_32BIT_DEVICE_BASE; VirtualMemoryTable[Index].Length = TOP_32BIT_DEVICE_SIZE; VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE; Index++; // End of Table ZeroMem (&VirtualMemoryTable[Index], sizeof (ARM_MEMORY_REGION_DESCRIPTOR)); *VirtualMemoryMap = VirtualMemoryTable; }