/** @file * * Copyright (c) 2011-2015, ARM Limited. All rights reserved. * Copyright (c) 2017, Linaro, Ltd. All rights reserved. * * This program and the accompanying materials * are licensed and made available under the terms and conditions of the BSD License * which accompanies this distribution. The full text of the license may be found at * http://opensource.org/licenses/bsd-license.php * * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. * **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #define ARM_MEMORY_REGION(Base, Size) \ { (Base), (Base), (Size), ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK } #define ARM_UNCACHED_REGION(Base, Size) \ { (Base), (Base), (Size), ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED } #define ARM_DEVICE_REGION(Base, Size) \ { (Base), (Base), (Size), ARM_MEMORY_REGION_ATTRIBUTE_DEVICE } #define ARM_CACHED_DEVICE_REGION(Base, Size) \ { (Base), (Base), (Size), ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK_NONSHAREABLE } VOID BuildMemoryTypeInformationHob ( VOID ); STATIC CONST EFI_RESOURCE_ATTRIBUTE_TYPE mDramResourceAttributes = 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; STATIC CONST ARM_MEMORY_REGION_DESCRIPTOR mVirtualMemoryTable[] = { // Memory mapped SPI NOR flash ARM_CACHED_DEVICE_REGION (FixedPcdGet64 (PcdFdBaseAddress), FixedPcdGet32 (PcdFdSize)), // SynQuacer OnChip peripherals ARM_DEVICE_REGION (SYNQUACER_PERIPHERALS_BASE, SYNQUACER_PERIPHERALS_SZ), // SynQuacer OnChip non-secure SRAM ARM_CACHED_DEVICE_REGION (SYNQUACER_NON_SECURE_SRAM_BASE, SYNQUACER_NON_SECURE_SRAM_SZ), // SynQuacer GIC-500 ARM_DEVICE_REGION (SYNQUACER_GIC500_DIST_BASE, SYNQUACER_GIC500_DIST_SIZE), ARM_DEVICE_REGION (SYNQUACER_GIC500_RDIST_BASE, SYNQUACER_GIC500_RDIST_SIZE), // SynQuacer eMMC(SDH30) ARM_DEVICE_REGION (SYNQUACER_EMMC_BASE, SYNQUACER_EMMC_BASE_SZ), // SynQuacer GPIO block ARM_DEVICE_REGION (SYNQUACER_GPIO_BASE, SYNQUACER_GPIO_SIZE), // SynQuacer EEPROM - could point to NOR flash as well ARM_CACHED_DEVICE_REGION (FixedPcdGet32 (PcdNetsecEepromBase), SYNQUACER_EEPROM_BASE_SZ), // SynQuacer I2C ARM_DEVICE_REGION (SYNQUACER_I2C0_BASE, SYNQUACER_I2C0_SIZE), ARM_DEVICE_REGION (SYNQUACER_I2C1_BASE, SYNQUACER_I2C1_SIZE), // SynQuacer NETSEC ARM_DEVICE_REGION (SYNQUACER_NETSEC1_BASE, SYNQUACER_NETSEC1_BASE_SZ), // PCIe control registers ARM_DEVICE_REGION (SYNQUACER_PCIE_BASE, SYNQUACER_PCIE_SIZE), // PCIe config space ARM_DEVICE_REGION (SYNQUACER_PCI_SEG0_CONFIG_BASE, SYNQUACER_PCI_SEG0_CONFIG_SIZE), ARM_DEVICE_REGION (SYNQUACER_PCI_SEG1_CONFIG_BASE, SYNQUACER_PCI_SEG1_CONFIG_SIZE), // PCIe I/O space ARM_DEVICE_REGION (SYNQUACER_PCI_SEG0_PORTIO_MEMBASE, SYNQUACER_PCI_SEG0_PORTIO_MEMSIZE), ARM_DEVICE_REGION (SYNQUACER_PCI_SEG1_PORTIO_MEMBASE, SYNQUACER_PCI_SEG1_PORTIO_MEMSIZE), // variable store ARM_DEVICE_REGION (FixedPcdGet32 (PcdFip006DxeRegBaseAddress), EFI_PAGE_SIZE), ARM_DEVICE_REGION (FixedPcdGet32 (PcdFip006DxeMemBaseAddress), EFI_PAGE_SIZE), ARM_DEVICE_REGION (FixedPcdGet32 (PcdFlashNvStorageVariableBase), FixedPcdGet32 (PcdFlashNvStorageVariableSize)), ARM_DEVICE_REGION (FixedPcdGet32 (PcdFlashNvStorageFtwWorkingBase), FixedPcdGet32 (PcdFlashNvStorageFtwWorkingSize)), ARM_DEVICE_REGION (FixedPcdGet32 (PcdFlashNvStorageFtwSpareBase), FixedPcdGet32 (PcdFlashNvStorageFtwSpareSize)), // NETSEC/eMMC SMMU ARM_DEVICE_REGION (SYNQUACER_SCB_SMMU_BASE, SYNQUACER_SCB_SMMU_SIZE), // DesignWare FUART ARM_DEVICE_REGION (SYNQUACER_UART1_BASE, SYNQUACER_UART1_SIZE), }; STATIC EFI_STATUS DeclareDram ( OUT ARM_MEMORY_REGION_DESCRIPTOR **VirtualMemoryTable ) { SYNQUACER_DRAM_INFO_PPI *DramInfo; EFI_STATUS Status; UINTN Idx; UINTN RegionCount; UINT64 Base; UINT64 Size; ARM_MEMORY_REGION_DESCRIPTOR *DramDescriptor; Status = PeiServicesLocatePpi (&gSynQuacerDramInfoPpiGuid, 0, NULL, (VOID **)&DramInfo); if (EFI_ERROR (Status)) { return Status; } Status = DramInfo->GetRegionCount (&RegionCount); if (EFI_ERROR (Status)) { return Status; } *VirtualMemoryTable = AllocatePool (sizeof (mVirtualMemoryTable) + (RegionCount + 1) * sizeof (ARM_MEMORY_REGION_DESCRIPTOR)); if (*VirtualMemoryTable == NULL) { return EFI_OUT_OF_RESOURCES; } CopyMem (*VirtualMemoryTable, mVirtualMemoryTable, sizeof (mVirtualMemoryTable)); DramDescriptor = *VirtualMemoryTable + ARRAY_SIZE (mVirtualMemoryTable); for (Idx = 0; Idx < RegionCount; Idx++) { Status = DramInfo->GetRegion (Idx, &Base, &Size); ASSERT_EFI_ERROR (Status); DramDescriptor->PhysicalBase = Base; DramDescriptor->Length = MIN (Size, MAX_ALLOC_ADDRESS - Base + 1); DramDescriptor->Attributes = ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK; if (Base < PcdGet64 (PcdSystemMemoryBase)) { DEBUG ((DEBUG_WARN, "%a: remapping system memory below PcdSystemMemoryBase for non-identity mapped DMA\n", __FUNCTION__)); Base += FixedPcdGet64 (PcdNonIdMappedDmaOffset); BuildMemoryAllocationHob (Base, Size, EfiReservedMemoryType); } DramDescriptor->VirtualBase = Base; BuildResourceDescriptorHob (EFI_RESOURCE_SYSTEM_MEMORY, mDramResourceAttributes, Base, Size); if (Base > MAX_ALLOC_ADDRESS - Size + 1) { continue; } DramDescriptor++; } DramDescriptor->PhysicalBase = 0; DramDescriptor->VirtualBase = 0; DramDescriptor->Length = 0; DramDescriptor->Attributes = 0; return EFI_SUCCESS; } STATIC BOOLEAN CheckCapsule ( IN EFI_PEI_SERVICES **PeiServices, IN PEI_CAPSULE_PPI *Capsule, IN EFI_PHYSICAL_ADDRESS UefiMemoryBase, OUT VOID **CapsuleBuffer, OUT UINTN *CapsuleBufferLength ) { EFI_STATUS Status; Status = Capsule->CheckCapsuleUpdate (PeiServices); if (!EFI_ERROR (Status)) { // // Coalesce the capsule into unused memory. CreateState() below will copy // it to a properly allocated buffer. // *CapsuleBuffer = (VOID *)(UINTN)PcdGet64 (PcdSystemMemoryBase); *CapsuleBufferLength = UefiMemoryBase - PcdGet64 (PcdSystemMemoryBase); PeiServicesSetBootMode (BOOT_ON_FLASH_UPDATE); Status = Capsule->Coalesce (PeiServices, CapsuleBuffer, CapsuleBufferLength); if (!EFI_ERROR (Status)) { DEBUG ((DEBUG_INFO, "%a: Coalesced capsule @ %p (0x%lx)\n", __FUNCTION__, *CapsuleBuffer, *CapsuleBufferLength)); return TRUE; } else { DEBUG ((DEBUG_WARN, "%a: failed to coalesce() capsule (Status == %r)\n", __FUNCTION__, Status)); } } return FALSE; } EFI_STATUS EFIAPI MemoryPeim ( IN EFI_PHYSICAL_ADDRESS UefiMemoryBase, IN UINT64 UefiMemorySize ) { EFI_STATUS Status; ARM_MEMORY_REGION_DESCRIPTOR *VirtualMemoryTable; EFI_PEI_SERVICES **PeiServices; PEI_CAPSULE_PPI *Capsule; VOID *CapsuleBuffer; UINTN CapsuleBufferLength; BOOLEAN HaveCapsule; EFI_BOOT_MODE BootMode; Status = DeclareDram (&VirtualMemoryTable); ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { return Status; } PeiServices = (EFI_PEI_SERVICES **) GetPeiServicesTablePointer (); ASSERT (PeiServices != NULL); Status = PeiServicesLocatePpi (&gPeiCapsulePpiGuid, 0, NULL, (VOID **)&Capsule); ASSERT_EFI_ERROR (Status); // // Check for persistent capsules, unless we are booting with default // settings. // Status = PeiServicesGetBootMode (&BootMode); if (!EFI_ERROR (Status) && BootMode != BOOT_WITH_DEFAULT_SETTINGS) { HaveCapsule = CheckCapsule (PeiServices, Capsule, UefiMemoryBase, &CapsuleBuffer, &CapsuleBufferLength); } else { HaveCapsule = FALSE; } Status = ArmConfigureMmu (VirtualMemoryTable, NULL, NULL); ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { return Status; } if (HaveCapsule) { Status = Capsule->CreateState (PeiServices, CapsuleBuffer, CapsuleBufferLength); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_WARN, "%a: Capsule->CreateState failed (Status == %r)\n", __FUNCTION__, Status)); } } if (FeaturePcdGet (PcdPrePiProduceMemoryTypeInformationHob)) { // Optional feature that helps prevent EFI memory map fragmentation. BuildMemoryTypeInformationHob (); } return EFI_SUCCESS; }