/** Writes memory-mapped registers. @param[in] PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. @param[in] This Pointer to local data for the interface. @param[in] Width The width of the access. Enumerated in bytes. @param[in] Address The physical address of the access. @param[in] Count The number of accesses to perform. @param[in] Buffer A pointer to the buffer of data. @retval EFI_SUCCESS The function completed successfully. @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system. @retval EFI_INVALID_PARAMETER Buffer is NULL. @retval EFI_UNSUPPORTED The address range specified by Address, Width, and Count is not valid for this EFI system. **/ EFI_STATUS EFIAPI CpuMemoryServiceWrite ( IN CONST EFI_PEI_SERVICES **PeiServices, IN CONST EFI_PEI_CPU_IO_PPI *This, IN EFI_PEI_CPU_IO_PPI_WIDTH Width, IN UINT64 Address, IN UINTN Count, IN VOID *Buffer ) { EFI_STATUS Status; UINT8 InStride; UINT8 OutStride; EFI_PEI_CPU_IO_PPI_WIDTH OperationWidth; BOOLEAN Aligned; UINT8 *Uint8Buffer; Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer); if (EFI_ERROR (Status)) { return Status; } // // Select loop based on the width of the transfer // InStride = mInStride[Width]; OutStride = mOutStride[Width]; OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03); Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00); for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) { if (OperationWidth == EfiPeiCpuIoWidthUint8) { MmioWrite8 ((UINTN)Address, *Uint8Buffer); } else if (OperationWidth == EfiPeiCpuIoWidthUint16) { if (Aligned) { MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer)); } else { MmioWrite16 ((UINTN)Address, ReadUnaligned16 ((UINT16 *)Uint8Buffer)); } } else if (OperationWidth == EfiPeiCpuIoWidthUint32) { if (Aligned) { MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer)); } else { MmioWrite32 ((UINTN)Address, ReadUnaligned32 ((UINT32 *)Uint8Buffer)); } } else if (OperationWidth == EfiPeiCpuIoWidthUint64) { if (Aligned) { MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer)); } else { MmioWrite64 ((UINTN)Address, ReadUnaligned64 ((UINT64 *)Uint8Buffer)); } } } return EFI_SUCCESS; }
EFIAPI MmioWriteBuffer64 ( IN UINTN StartAddress, IN UINTN Length, IN CONST UINT64 *Buffer ) { UINT64 *ReturnBuffer; ASSERT ((StartAddress & (sizeof (UINT64) - 1)) == 0); ASSERT ((Length - 1) <= (MAX_ADDRESS - StartAddress)); ASSERT ((Length - 1) <= (MAX_ADDRESS - (UINTN) Buffer)); ASSERT ((Length & (sizeof (UINT64) - 1)) == 0); ASSERT (((UINTN) Buffer & (sizeof (UINT64) - 1)) == 0); ReturnBuffer = (UINT64 *) Buffer; while (Length > 0) { MmioWrite64 (StartAddress, *(Buffer++)); StartAddress += sizeof (UINT64); Length -= sizeof (UINT64); } return ReturnBuffer; }
/** 64-bit memory write operations. @param[in] PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. @param[in] This Pointer to local data for the interface. @param[in] Address The physical address of the access. @param[in] Data The data to write. **/ VOID EFIAPI CpuMemWrite64 ( IN CONST EFI_PEI_SERVICES **PeiServices, IN CONST EFI_PEI_CPU_IO_PPI *This, IN UINT64 Address, IN UINT64 Data ) { MmioWrite64 ((UINTN)Address, Data); }
EFI_STATUS EFIAPI EarlyConfigEntry ( IN EFI_PEI_FILE_HANDLE FileHandle, IN CONST EFI_PEI_SERVICES **PeiServices ) { DEBUG((EFI_D_ERROR,"SMMU CONFIG.........")); SmmuConfigForOS(); DEBUG((EFI_D_ERROR,"Done\n")); DEBUG((EFI_D_ERROR,"ITS CONFIG.........")); ITSCONFIG(); DEBUG((EFI_D_ERROR,"Done\n")); DEBUG((EFI_D_ERROR,"AP CONFIG.........")); MmioWrite64(FixedPcdGet64(PcdMailBoxAddress), 0x0); (void)WriteBackInvalidateDataCacheRange((VOID *) FixedPcdGet64(PcdMailBoxAddress), 8); asm("DSB SY"); asm("ISB"); CoreSelectBoot(); DEBUG((EFI_D_ERROR,"Done\n")); DEBUG((EFI_D_ERROR,"MN CONFIG.........")); MN_CONFIG (); DEBUG((EFI_D_ERROR,"Done\n")); DEBUG((EFI_D_ERROR,"RTC CONFIG.........")); MmioWrite32(0xA00021F0, 0xF); DEBUG((EFI_D_ERROR,"Done\n")); DEBUG((EFI_D_ERROR,"Tsensor CONFIG.........")); MmioWrite32(0x80010000 + 0x5000, 0x1); *(volatile UINT32*)0xA0000A8C = 0x1f; DEBUG((EFI_D_ERROR,"Done\n")); DEBUG((EFI_D_ERROR,"Timer CONFIG.........")); PlatformTimerStart (); DEBUG((EFI_D_ERROR,"Done\n")); return EFI_SUCCESS; }
/** Writes memory-mapped registers. The I/O operations are carried out exactly as requested. The caller is responsible for satisfying any alignment and I/O width restrictions that a PI System on a platform might require. For example on some platforms, width requests of EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will be handled by the driver. If Width is EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, EfiCpuIoWidthUint32, or EfiCpuIoWidthUint64, then both Address and Buffer are incremented for each of the Count operations that is performed. If Width is EfiCpuIoWidthFifoUint8, EfiCpuIoWidthFifoUint16, EfiCpuIoWidthFifoUint32, or EfiCpuIoWidthFifoUint64, then only Buffer is incremented for each of the Count operations that is performed. The read or write operation is performed Count times on the same Address. If Width is EfiCpuIoWidthFillUint8, EfiCpuIoWidthFillUint16, EfiCpuIoWidthFillUint32, or EfiCpuIoWidthFillUint64, then only Address is incremented for each of the Count operations that is performed. The read or write operation is performed Count times from the first element of Buffer. @param[in] This A pointer to the EFI_CPU_IO2_PROTOCOL instance. @param[in] Width Signifies the width of the I/O or Memory operation. @param[in] Address The base address of the I/O operation. @param[in] Count The number of I/O operations to perform. The number of bytes moved is Width size * Count, starting at Address. @param[in] Buffer For read operations, the destination buffer to store the results. For write operations, the source buffer from which to write data. @retval EFI_SUCCESS The data was read from or written to the PI system. @retval EFI_INVALID_PARAMETER Width is invalid for this PI system. @retval EFI_INVALID_PARAMETER Buffer is NULL. @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. @retval EFI_UNSUPPORTED The address range specified by Address, Width, and Count is not valid for this PI system. **/ STATIC EFI_STATUS EFIAPI CpuMemoryServiceWrite ( IN EFI_CPU_IO2_PROTOCOL *This, IN EFI_CPU_IO_PROTOCOL_WIDTH Width, IN UINT64 Address, IN UINTN Count, IN VOID *Buffer ) { EFI_STATUS Status; UINT8 InStride; UINT8 OutStride; EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth; UINT8 *Uint8Buffer; Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer); if (EFI_ERROR (Status)) { return Status; } // // Select loop based on the width of the transfer // InStride = mInStride[Width]; OutStride = mOutStride[Width]; OperationWidth = (EFI_CPU_IO_PROTOCOL_WIDTH) (Width & 0x03); for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) { if (OperationWidth == EfiCpuIoWidthUint8) { MmioWrite8 ((UINTN)Address, *Uint8Buffer); } else if (OperationWidth == EfiCpuIoWidthUint16) { MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer)); } else if (OperationWidth == EfiCpuIoWidthUint32) { MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer)); } else if (OperationWidth == EfiCpuIoWidthUint64) { MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer)); } } return EFI_SUCCESS; }
/** Writes memory-mapped registers. The I/O operations are carried out exactly as requested. The caller is responsible for any alignment and I/O width issues that the bus, device, platform, or type of I/O might require. @param[in] This The EFI_SMM_CPU_IO2_PROTOCOL instance. @param[in] Width Signifies the width of the I/O operations. @param[in] Address The base address of the I/O operations. The caller is responsible for aligning the Address if required. @param[in] Count The number of I/O operations to perform. @param[in] Buffer For read operations, the destination buffer to store the results. For write operations, the source buffer from which to write data. @retval EFI_SUCCESS The data was read from or written to the device. @retval EFI_UNSUPPORTED The Address is not valid for this system. @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources **/ EFI_STATUS EFIAPI CpuMemoryServiceWrite ( IN CONST EFI_SMM_CPU_IO2_PROTOCOL *This, IN EFI_SMM_IO_WIDTH Width, IN UINT64 Address, IN UINTN Count, IN VOID *Buffer ) { EFI_STATUS Status; UINT8 Stride; UINT8 *Uint8Buffer; Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer); if (EFI_ERROR (Status)) { return Status; } // // Select loop based on the width of the transfer // Stride = mStride[Width]; for (Uint8Buffer = Buffer; Count > 0; Address += Stride, Uint8Buffer += Stride, Count--) { if (Width == SMM_IO_UINT8) { MmioWrite8 ((UINTN)Address, *Uint8Buffer); } else if (Width == SMM_IO_UINT16) { MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer)); } else if (Width == SMM_IO_UINT32) { MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer)); } else if (Width == SMM_IO_UINT64) { MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer)); } } return EFI_SUCCESS; }
/** Initialize the state information for the CPU Architectural Protocol @param ImageHandle of the loaded driver @param SystemTable Pointer to the System Table @retval EFI_SUCCESS Protocol registered @retval EFI_OUT_OF_RESOURCES Cannot allocate protocol data structure @retval EFI_DEVICE_ERROR Hardware problems **/ EFI_STATUS GicV3DxeInitialize ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; UINTN Index; UINT32 RegOffset; UINTN RegShift; UINT64 CpuTarget; UINT64 MpId; // Make sure the Interrupt Controller Protocol is not already installed in // the system. ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid); mGicDistributorBase = PcdGet64 (PcdGicDistributorBase); mGicRedistributorsBase = PcdGet64 (PcdGicRedistributorsBase); mGicNumInterrupts = ArmGicGetMaxNumInterrupts (mGicDistributorBase); // We will be driving this GIC in native v3 mode, i.e., with Affinity // Routing enabled. So ensure that the ARE bit is set. if (!FeaturePcdGet (PcdArmGicV3WithV2Legacy)) { MmioOr32 (mGicDistributorBase + ARM_GIC_ICDDCR, ARM_GIC_ICDDCR_ARE); } for (Index = 0; Index < mGicNumInterrupts; Index++) { GicV3DisableInterruptSource (&gHardwareInterruptV3Protocol, Index); // Set Priority RegOffset = Index / 4; RegShift = (Index % 4) * 8; MmioAndThenOr32 ( mGicDistributorBase + ARM_GIC_ICDIPR + (4 * RegOffset), ~(0xff << RegShift), ARM_GIC_DEFAULT_PRIORITY << RegShift ); } // Targets the interrupts to the Primary Cpu if (FeaturePcdGet (PcdArmGicV3WithV2Legacy)) { // Only Primary CPU will run this code. We can identify our GIC CPU ID by // reading the GIC Distributor Target register. The 8 first // GICD_ITARGETSRn are banked to each connected CPU. These 8 registers // hold the CPU targets fields for interrupts 0-31. More Info in the GIC // Specification about "Interrupt Processor Targets Registers" // Read the first Interrupt Processor Targets Register (that corresponds // to the 4 first SGIs) CpuTarget = MmioRead32 (mGicDistributorBase + ARM_GIC_ICDIPTR); // The CPU target is a bit field mapping each CPU to a GIC CPU Interface. // This value is 0 when we run on a uniprocessor platform. if (CpuTarget != 0) { // The 8 first Interrupt Processor Targets Registers are read-only for (Index = 8; Index < (mGicNumInterrupts / 4); Index++) { MmioWrite32 ( mGicDistributorBase + ARM_GIC_ICDIPTR + (Index * 4), CpuTarget ); } } } else { MpId = ArmReadMpidr (); CpuTarget = MpId & (ARM_CORE_AFF0 | ARM_CORE_AFF1 | ARM_CORE_AFF2 | ARM_CORE_AFF3); if ((MmioRead32 ( mGicDistributorBase + ARM_GIC_ICDDCR ) & ARM_GIC_ICDDCR_DS) != 0) { // If the Disable Security (DS) control bit is set, we are dealing with a // GIC that has only one security state. In this case, let's assume we are // executing in non-secure state (which is appropriate for DXE modules) // and that no other firmware has performed any configuration on the GIC. // This means we need to reconfigure all interrupts to non-secure Group 1 // first. MmioWrite32 ( mGicRedistributorsBase + ARM_GICR_CTLR_FRAME_SIZE + ARM_GIC_ICDISR, 0xffffffff ); for (Index = 32; Index < mGicNumInterrupts; Index += 32) { MmioWrite32 ( mGicDistributorBase + ARM_GIC_ICDISR + Index / 8, 0xffffffff ); } } // Route the SPIs to the primary CPU. SPIs start at the INTID 32 for (Index = 0; Index < (mGicNumInterrupts - 32); Index++) { MmioWrite64 ( mGicDistributorBase + ARM_GICD_IROUTER + (Index * 8), CpuTarget ); } } // Set binary point reg to 0x7 (no preemption) ArmGicV3SetBinaryPointer (0x7); // Set priority mask reg to 0xff to allow all priorities through ArmGicV3SetPriorityMask (0xff); // Enable gic cpu interface ArmGicV3EnableInterruptInterface (); // Enable gic distributor ArmGicEnableDistributor (mGicDistributorBase); Status = InstallAndRegisterInterruptService ( &gHardwareInterruptV3Protocol, &gHardwareInterrupt2V3Protocol, GicV3IrqInterruptHandler, GicV3ExitBootServicesEvent ); return Status; }
EFI_STATUS IgdPmHook ( IN EFI_HANDLE ImageHandle, IN DXE_VLV_PLATFORM_POLICY_PROTOCOL *DxePlatformSaPolicy ) { EFI_EVENT mConOutEvent; VOID *gConOutNotifyReg; EFI_STATUS Status; EFI_PHYSICAL_ADDRESS MemBaseAddress; UINT32 LoGTBaseAddress; UINT32 HiGTBaseAddress; GTTMMADR = 0; Status = EFI_SUCCESS; // // If device 0:2:0 (Internal Graphics Device, or GT) is enabled, then Program GTTMMADR, // if (PciRead16(PCI_LIB_ADDRESS(0, IGD_DEV, 0, IGD_R_VID)) != 0xFFFF) { ASSERT (gDS!=NULL); // // Enable Bus Master, I/O and Memory access on 0:2:0 // PciOr8(PCI_LIB_ADDRESS(0, IGD_DEV, 0, IGD_R_CMD), (BIT2 | BIT1 | BIT0)); // // Means Allocate 4MB for GTTMADDR // MemBaseAddress = 0x0ffffffff; Status = gDS->AllocateMemorySpace ( EfiGcdAllocateMaxAddressSearchBottomUp, EfiGcdMemoryTypeMemoryMappedIo, GTT_MEM_ALIGN, GTTMMADR_SIZE_4MB, &MemBaseAddress, ImageHandle, NULL ); ASSERT_EFI_ERROR (Status); // // Program GT PM Settings if GTTMMADR allocation is Successful // GTTMMADR = (UINTN) MemBaseAddress; LoGTBaseAddress = (UINT32) (MemBaseAddress & 0xFFFFFFFF); HiGTBaseAddress = (UINT32) RShiftU64 ((MemBaseAddress & 0xFFFFFFFF00000000), 32); PciWrite32 (PCI_LIB_ADDRESS(0, IGD_DEV, 0, IGD_R_GTTMMADR), LoGTBaseAddress); PciWrite32 (PCI_LIB_ADDRESS(0, IGD_DEV, 0, IGD_R_GTTMMADR+4), HiGTBaseAddress); S3PciRead32(PCI_LIB_ADDRESS(0, IGD_DEV, 0, IGD_R_GTTMMADR)); S3MmioRead32(IGD_R_GTTMMADR + 4); S3PciRead8(PCI_LIB_ADDRESS(0, IGD_DEV, 0, IGD_R_CMD)); // // Do POST GT PM Init Steps after VBIOS Initialization in DoPostPmInitCallBack // Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, TPL_CALLBACK, (EFI_EVENT_NOTIFY)PostPmInitCallBack, NULL, &mConOutEvent ); ASSERT_EFI_ERROR (Status); if (EFI_ERROR (Status)) { return Status; } Status = gBS->RegisterProtocolNotify ( &gEfiGraphicsOutputProtocolGuid, mConOutEvent, &gConOutNotifyReg ); MmioWrite64 (IGD_R_GTTMMADR, 0); // // Free allocated resources // gDS->FreeMemorySpace ( MemBaseAddress, GTTMMADR_SIZE_4MB ); } return EFI_SUCCESS; }