mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-11-25 11:55:28 +01:00
Merge branch 'master' of https://github.com/CloverHackyColor/CloverBootloader
This commit is contained in:
commit
9c3e895a1a
243
ArmPkg/ArmPkg.ci.yaml
Normal file
243
ArmPkg/ArmPkg.ci.yaml
Normal file
@ -0,0 +1,243 @@
|
||||
## @file
|
||||
# CI configuration for ArmPkg
|
||||
#
|
||||
# Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
{
|
||||
## options defined .pytool/Plugin/LicenseCheck
|
||||
"LicenseCheck": {
|
||||
"IgnoreFiles": []
|
||||
},
|
||||
|
||||
"EccCheck": {
|
||||
## Exception sample looks like below:
|
||||
## "ExceptionList": [
|
||||
## "<ErrorID>", "<KeyWord>"
|
||||
## ]
|
||||
"ExceptionList": [
|
||||
],
|
||||
## Both file path and directory path are accepted.
|
||||
"IgnoreFiles": [
|
||||
"Library/ArmSoftFloatLib/berkeley-softfloat-3",
|
||||
"Library/ArmSoftFloatLib/ArmSoftFloatLib.c",
|
||||
"Library/CompilerIntrinsicsLib",
|
||||
"Universal/Smbios/SmbiosMiscDxe"
|
||||
]
|
||||
},
|
||||
|
||||
## options defined .pytool/Plugin/CompilerPlugin
|
||||
"CompilerPlugin": {
|
||||
"DscPath": "ArmPkg.dsc"
|
||||
},
|
||||
|
||||
## options defined .pytool/Plugin/HostUnitTestCompilerPlugin
|
||||
"HostUnitTestCompilerPlugin": {
|
||||
"DscPath": "" # Don't support this test
|
||||
},
|
||||
|
||||
## options defined .pytool/Plugin/CharEncodingCheck
|
||||
"CharEncodingCheck": {
|
||||
"IgnoreFiles": []
|
||||
},
|
||||
|
||||
## options defined .pytool/Plugin/DependencyCheck
|
||||
"DependencyCheck": {
|
||||
"AcceptableDependencies": [
|
||||
"ArmPlatformPkg/ArmPlatformPkg.dec",
|
||||
"ArmPkg/ArmPkg.dec",
|
||||
"EmbeddedPkg/EmbeddedPkg.dec",
|
||||
"MdeModulePkg/MdeModulePkg.dec",
|
||||
"MdePkg/MdePkg.dec",
|
||||
"ShellPkg/ShellPkg.dec"
|
||||
],
|
||||
# For host based unit tests
|
||||
"AcceptableDependencies-HOST_APPLICATION":[
|
||||
"UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec"
|
||||
],
|
||||
# For UEFI shell based apps
|
||||
"AcceptableDependencies-UEFI_APPLICATION":[],
|
||||
"IgnoreInf": []
|
||||
},
|
||||
|
||||
## options defined .pytool/Plugin/DscCompleteCheck
|
||||
"DscCompleteCheck": {
|
||||
"IgnoreInf": [],
|
||||
"DscPath": "ArmPkg.dsc"
|
||||
},
|
||||
|
||||
## options defined .pytool/Plugin/HostUnitTestDscCompleteCheck
|
||||
"HostUnitTestDscCompleteCheck": {
|
||||
"IgnoreInf": [""],
|
||||
"DscPath": "" # Don't support this test
|
||||
},
|
||||
|
||||
## options defined .pytool/Plugin/GuidCheck
|
||||
"GuidCheck": {
|
||||
"IgnoreGuidName": [],
|
||||
"IgnoreGuidValue": [],
|
||||
"IgnoreFoldersAndFiles": [],
|
||||
"IgnoreDuplicates": [],
|
||||
},
|
||||
|
||||
## options defined .pytool/Plugin/LibraryClassCheck
|
||||
"LibraryClassCheck": {
|
||||
"IgnoreHeaderFile": []
|
||||
},
|
||||
|
||||
## options defined .pytool/Plugin/SpellCheck
|
||||
"SpellCheck": {
|
||||
"AuditOnly": True,
|
||||
"IgnoreFiles": [
|
||||
"Library/ArmSoftFloatLib/berkeley-softfloat-3/**"
|
||||
], # use gitignore syntax to ignore errors
|
||||
# in matching files
|
||||
"ExtendWords": [
|
||||
"api's",
|
||||
"ackintid",
|
||||
"actlr",
|
||||
"aeabi",
|
||||
"asedis",
|
||||
"ashldi",
|
||||
"ashrdi",
|
||||
"baddr",
|
||||
"ccidx",
|
||||
"ccsidr",
|
||||
"clidr",
|
||||
"clrex",
|
||||
"clzsi",
|
||||
"cnthctl",
|
||||
"cortexa",
|
||||
"cpacr",
|
||||
"cpuactlr",
|
||||
"csselr",
|
||||
"ctzsi",
|
||||
"cygdrive",
|
||||
"cygpaths",
|
||||
"datas",
|
||||
"dcmpeq",
|
||||
"dcmpge",
|
||||
"dcmpgt",
|
||||
"dcmple",
|
||||
"dcmplt",
|
||||
"ddisable",
|
||||
"divdi",
|
||||
"divsi",
|
||||
"dmdepkg",
|
||||
"dpref",
|
||||
"drsub",
|
||||
"fcmpeq",
|
||||
"fcmpge",
|
||||
"fcmpgt",
|
||||
"fcmple",
|
||||
"fcmplt",
|
||||
"ffreestanding",
|
||||
"frsub",
|
||||
"hisilicon",
|
||||
"iccabpr",
|
||||
"iccbpr",
|
||||
"icciar",
|
||||
"iccicr",
|
||||
"icciidr",
|
||||
"iccpir",
|
||||
"iccpmr",
|
||||
"iccrpr",
|
||||
"icdabr",
|
||||
"icdicer",
|
||||
"icdicfr",
|
||||
"icdicpr",
|
||||
"icdictr",
|
||||
"icdiidr",
|
||||
"icdiser",
|
||||
"icdisr",
|
||||
"icdppisr",
|
||||
"icdsgir",
|
||||
"icdspr",
|
||||
"icenabler",
|
||||
"intid",
|
||||
"ipriority",
|
||||
"irouter",
|
||||
"isenabler",
|
||||
"istatus",
|
||||
"itargets",
|
||||
"lable",
|
||||
"ldivmod",
|
||||
"ldmdb",
|
||||
"ldmia",
|
||||
"ldrbt",
|
||||
"ldrex",
|
||||
"ldrexb",
|
||||
"ldrexd",
|
||||
"ldrexh",
|
||||
"ldrhbt",
|
||||
"ldrht",
|
||||
"ldrsb",
|
||||
"ldrsbt",
|
||||
"ldrsh",
|
||||
"lshrdi",
|
||||
"moddi",
|
||||
"modsi",
|
||||
"mpcore",
|
||||
"mpidr",
|
||||
"muldi",
|
||||
"mullu",
|
||||
"nonshareable",
|
||||
"nsacr",
|
||||
"nsasedis",
|
||||
"nuvia",
|
||||
"oldit",
|
||||
"pcten",
|
||||
"plpis",
|
||||
"procno",
|
||||
"readc",
|
||||
"revsh",
|
||||
"rfedb",
|
||||
"sctlr",
|
||||
"smccc",
|
||||
"smlabb",
|
||||
"smlabt",
|
||||
"smlad",
|
||||
"smladx",
|
||||
"smlatb",
|
||||
"smlatt",
|
||||
"smlawb",
|
||||
"smlawt",
|
||||
"smlsd",
|
||||
"smlsdx",
|
||||
"smmla",
|
||||
"smmlar",
|
||||
"smmls",
|
||||
"smmlsr",
|
||||
"sourcery",
|
||||
"srsdb",
|
||||
"ssacr",
|
||||
"stmdb",
|
||||
"stmia",
|
||||
"strbt",
|
||||
"strexb",
|
||||
"strexd",
|
||||
"strexh",
|
||||
"strht",
|
||||
"switchu",
|
||||
"tpidrurw",
|
||||
"ttbcr",
|
||||
"typer",
|
||||
"ucmpdi",
|
||||
"udivdi",
|
||||
"udivmoddi",
|
||||
"udivsi",
|
||||
"uefi's",
|
||||
"uldiv",
|
||||
"umoddi",
|
||||
"umodsi",
|
||||
"usada",
|
||||
"vlpis",
|
||||
"writec"
|
||||
], # words to extend to the dictionary for this package
|
||||
"IgnoreStandardPaths": [ # Standard Plugin defined paths that
|
||||
"*.asm", "*.s" # should be ignore
|
||||
],
|
||||
"AdditionalIncludePaths": [] # Additional paths to spell check
|
||||
# (wildcards supported)
|
||||
}
|
||||
}
|
401
ArmPkg/ArmPkg.dec
Normal file
401
ArmPkg/ArmPkg.dec
Normal file
@ -0,0 +1,401 @@
|
||||
#/** @file
|
||||
# ARM processor package.
|
||||
#
|
||||
# Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.<BR>
|
||||
# Copyright (c) 2011 - 2022, ARM Limited. All rights reserved.
|
||||
# Copyright (c) 2021, Ampere Computing LLC. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
#**/
|
||||
|
||||
[Defines]
|
||||
DEC_SPECIFICATION = 0x00010005
|
||||
PACKAGE_NAME = ArmPkg
|
||||
PACKAGE_GUID = 5CFBD99E-3C43-4E7F-8054-9CDEAFF7710F
|
||||
PACKAGE_VERSION = 0.1
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Include Section - list of Include Paths that are provided by this package.
|
||||
# Comments are used for Keywords and Module Types.
|
||||
#
|
||||
# Supported Module Types:
|
||||
# BASE SEC PEI_CORE PEIM DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER DXE_SAL_DRIVER UEFI_DRIVER UEFI_APPLICATION
|
||||
#
|
||||
################################################################################
|
||||
[Includes.common]
|
||||
Include # Root include for the package
|
||||
|
||||
[LibraryClasses.common]
|
||||
## @libraryclass Convert Arm instructions to a human readable format.
|
||||
#
|
||||
ArmDisassemblerLib|Include/Library/ArmDisassemblerLib.h
|
||||
|
||||
## @libraryclass Provides an interface to Arm generic counters.
|
||||
#
|
||||
ArmGenericTimerCounterLib|Include/Library/ArmGenericTimerCounterLib.h
|
||||
|
||||
## @libraryclass Provides an interface to initialize a
|
||||
# Generic Interrupt Controller (GIC).
|
||||
#
|
||||
ArmGicArchLib|Include/Library/ArmGicArchLib.h
|
||||
|
||||
## @libraryclass Provides a Generic Interrupt Controller (GIC)
|
||||
# configuration interface.
|
||||
#
|
||||
ArmGicLib|Include/Library/ArmGicLib.h
|
||||
|
||||
## @libraryclass Provides a HyperVisor Call (HVC) interface.
|
||||
#
|
||||
ArmHvcLib|Include/Library/ArmHvcLib.h
|
||||
|
||||
## @libraryclass Provides an interface to Arm registers.
|
||||
#
|
||||
ArmLib|Include/Library/ArmLib.h
|
||||
|
||||
## @libraryclass Provides a Mmu interface.
|
||||
#
|
||||
ArmMmuLib|Include/Library/ArmMmuLib.h
|
||||
|
||||
## @libraryclass Provides a Mailbox Transport Layer (MTL) interface
|
||||
# for the System Control and Management Interface (SCMI).
|
||||
#
|
||||
ArmMtlLib|Include/Library/ArmMtlLib.h
|
||||
|
||||
## @libraryclass Provides a System Monitor Call (SMC) interface.
|
||||
#
|
||||
ArmSmcLib|Include/Library/ArmSmcLib.h
|
||||
|
||||
## @libraryclass Provides a SuperVisor Call (SVC) interface.
|
||||
#
|
||||
ArmSvcLib|Include/Library/ArmSvcLib.h
|
||||
|
||||
## @libraryclass Provides a Monitor Call interface that will use the
|
||||
# default conduit (HVC or SMC).
|
||||
#
|
||||
ArmMonitorLib|Include/Library/ArmMonitorLib.h
|
||||
|
||||
## @libraryclass Provides a default exception handler.
|
||||
#
|
||||
DefaultExceptionHandlerLib|Include/Library/DefaultExceptionHandlerLib.h
|
||||
|
||||
## @libraryclass Provides an interface to query miscellaneous OEM
|
||||
# information.
|
||||
#
|
||||
OemMiscLib|Include/Library/OemMiscLib.h
|
||||
|
||||
## @libraryclass Provides an OpTee interface.
|
||||
#
|
||||
OpteeLib|Include/Library/OpteeLib.h
|
||||
|
||||
## @libraryclass Provides a semihosting interface.
|
||||
#
|
||||
SemihostLib|Include/Library/SemihostLib.h
|
||||
|
||||
## @libraryclass Provides an interface for a StandaloneMm Mmu.
|
||||
#
|
||||
StandaloneMmMmuLib|Include/Library/StandaloneMmMmuLib.h
|
||||
|
||||
[Guids.common]
|
||||
gArmTokenSpaceGuid = { 0xBB11ECFE, 0x820F, 0x4968, { 0xBB, 0xA6, 0xF7, 0x6A, 0xFE, 0x30, 0x25, 0x96 } }
|
||||
|
||||
## ARM MPCore table
|
||||
# Include/Guid/ArmMpCoreInfo.h
|
||||
gArmMpCoreInfoGuid = { 0xa4ee0728, 0xe5d7, 0x4ac5, {0xb2, 0x1e, 0x65, 0x8e, 0xd8, 0x57, 0xe8, 0x34} }
|
||||
|
||||
gArmMmuReplaceLiveTranslationEntryFuncGuid = { 0xa8b50ff3, 0x08ec, 0x4dd3, {0xbf, 0x04, 0x28, 0xbf, 0x71, 0x75, 0xc7, 0x4a} }
|
||||
|
||||
[Protocols.common]
|
||||
## Arm System Control and Management Interface(SCMI) Base protocol
|
||||
## ArmPkg/Include/Protocol/ArmScmiBaseProtocol.h
|
||||
gArmScmiBaseProtocolGuid = { 0xd7e5abe9, 0x33ab, 0x418e, { 0x9f, 0x91, 0x72, 0xda, 0xe2, 0xba, 0x8e, 0x2f } }
|
||||
|
||||
## Arm System Control and Management Interface(SCMI) Clock management protocol
|
||||
## ArmPkg/Include/Protocol/ArmScmiClockProtocol.h
|
||||
gArmScmiClockProtocolGuid = { 0x91ce67a8, 0xe0aa, 0x4012, { 0xb9, 0x9f, 0xb6, 0xfc, 0xf3, 0x4, 0x8e, 0xaa } }
|
||||
gArmScmiClock2ProtocolGuid = { 0xb8d8caf2, 0x9e94, 0x462c, { 0xa8, 0x34, 0x6c, 0x99, 0xfc, 0x05, 0xef, 0xcf } }
|
||||
|
||||
## Arm System Control and Management Interface(SCMI) Clock management protocol
|
||||
## ArmPkg/Include/Protocol/ArmScmiPerformanceProtocol.h
|
||||
gArmScmiPerformanceProtocolGuid = { 0x9b8ba84, 0x3dd3, 0x49a6, { 0xa0, 0x5a, 0x31, 0x34, 0xa5, 0xf0, 0x7b, 0xad } }
|
||||
|
||||
[Ppis]
|
||||
## Include/Ppi/ArmMpCoreInfo.h
|
||||
gArmMpCoreInfoPpiGuid = { 0x6847cc74, 0xe9ec, 0x4f8f, {0xa2, 0x9d, 0xab, 0x44, 0xe7, 0x54, 0xa8, 0xfc} }
|
||||
|
||||
[PcdsFeatureFlag.common]
|
||||
gArmTokenSpaceGuid.PcdCpuDxeProduceDebugSupport|FALSE|BOOLEAN|0x00000001
|
||||
|
||||
# On ARM Architecture with the Security Extension, the address for the
|
||||
# Vector Table can be mapped anywhere in the memory map. It means we can
|
||||
# point the Exception Vector Table to its location in CpuDxe.
|
||||
# By default we copy the Vector Table at PcdGet64(PcdCpuVectorBaseAddress)
|
||||
gArmTokenSpaceGuid.PcdRelocateVectorTable|TRUE|BOOLEAN|0x00000022
|
||||
# Set this PCD to TRUE if the Exception Vector is changed to add debugger support before
|
||||
# it has been configured by the CPU DXE
|
||||
gArmTokenSpaceGuid.PcdDebuggerExceptionSupport|FALSE|BOOLEAN|0x00000032
|
||||
|
||||
# Define if the GICv3 controller should use the GICv2 legacy
|
||||
gArmTokenSpaceGuid.PcdArmGicV3WithV2Legacy|FALSE|BOOLEAN|0x00000042
|
||||
|
||||
## Define the conduit to use for monitor calls.
|
||||
# Default PcdMonitorConduitHvc = FALSE, conduit = SMC
|
||||
# If PcdMonitorConduitHvc = TRUE, conduit = HVC
|
||||
gArmTokenSpaceGuid.PcdMonitorConduitHvc|FALSE|BOOLEAN|0x00000047
|
||||
|
||||
[PcdsFeatureFlag.ARM]
|
||||
# Whether to map normal memory as non-shareable. FALSE is the safe choice, but
|
||||
# TRUE may be appropriate to fix performance problems if you don't care about
|
||||
# hardware coherency (i.e., no virtualization or cache coherent DMA)
|
||||
gArmTokenSpaceGuid.PcdNormalMemoryNonshareableOverride|FALSE|BOOLEAN|0x00000043
|
||||
|
||||
[PcdsFeatureFlag.AARCH64, PcdsFeatureFlag.ARM]
|
||||
## Used to select method for requesting services from S-EL1.<BR><BR>
|
||||
# TRUE - Selects FF-A calls for communication between S-EL0 and SPMC.<BR>
|
||||
# FALSE - Selects SVC calls for communication between S-EL0 and SPMC.<BR>
|
||||
# @Prompt Enable FF-A support.
|
||||
gArmTokenSpaceGuid.PcdFfaEnable|FALSE|BOOLEAN|0x0000005B
|
||||
|
||||
[PcdsFixedAtBuild.common]
|
||||
gArmTokenSpaceGuid.PcdTrustzoneSupport|FALSE|BOOLEAN|0x00000006
|
||||
|
||||
# This PCD should be a FeaturePcd. But we used this PCD as an '#if' in an ASM file.
|
||||
# Using a FeaturePcd make a '(BOOLEAN) casting for its value which is not understood by the preprocessor.
|
||||
gArmTokenSpaceGuid.PcdVFPEnabled|0|UINT32|0x00000024
|
||||
|
||||
gArmTokenSpaceGuid.PcdCpuVectorBaseAddress|0xffff0000|UINT64|0x00000004
|
||||
gArmTokenSpaceGuid.PcdCpuResetAddress|0x00000000|UINT32|0x00000005
|
||||
|
||||
#
|
||||
# ARM Secure Firmware PCDs
|
||||
#
|
||||
gArmTokenSpaceGuid.PcdSecureFdBaseAddress|0|UINT64|0x00000015
|
||||
gArmTokenSpaceGuid.PcdSecureFdSize|0|UINT32|0x00000016
|
||||
gArmTokenSpaceGuid.PcdSecureFvBaseAddress|0x0|UINT64|0x0000002F
|
||||
gArmTokenSpaceGuid.PcdSecureFvSize|0x0|UINT32|0x00000030
|
||||
|
||||
#
|
||||
# ARM Hypervisor Firmware PCDs
|
||||
#
|
||||
gArmTokenSpaceGuid.PcdHypFdBaseAddress|0|UINT32|0x0000003A
|
||||
gArmTokenSpaceGuid.PcdHypFdSize|0|UINT32|0x0000003B
|
||||
gArmTokenSpaceGuid.PcdHypFvBaseAddress|0|UINT32|0x0000003C
|
||||
gArmTokenSpaceGuid.PcdHypFvSize|0|UINT32|0x0000003D
|
||||
|
||||
# Use ClusterId + CoreId to identify the PrimaryCore
|
||||
gArmTokenSpaceGuid.PcdArmPrimaryCoreMask|0xF03|UINT32|0x00000031
|
||||
# The Primary Core is ClusterId[0] & CoreId[0]
|
||||
gArmTokenSpaceGuid.PcdArmPrimaryCore|0|UINT32|0x00000037
|
||||
|
||||
#
|
||||
# SMBIOS PCDs
|
||||
#
|
||||
gArmTokenSpaceGuid.PcdSystemProductName|L""|VOID*|0x30000053
|
||||
gArmTokenSpaceGuid.PcdSystemVersion|L""|VOID*|0x30000054
|
||||
gArmTokenSpaceGuid.PcdBaseBoardManufacturer|L""|VOID*|0x30000055
|
||||
gArmTokenSpaceGuid.PcdBaseBoardProductName|L""|VOID*|0x30000056
|
||||
gArmTokenSpaceGuid.PcdBaseBoardVersion|L""|VOID*|0x30000057
|
||||
gArmTokenSpaceGuid.PcdProcessorManufacturer|L""|VOID*|0x30000071
|
||||
gArmTokenSpaceGuid.PcdProcessorVersion|L""|VOID*|0x30000072
|
||||
gArmTokenSpaceGuid.PcdProcessorSerialNumber|L""|VOID*|0x30000073
|
||||
gArmTokenSpaceGuid.PcdProcessorAssetTag|L""|VOID*|0x30000074
|
||||
gArmTokenSpaceGuid.PcdProcessorPartNumber|L""|VOID*|0x30000075
|
||||
|
||||
#
|
||||
# ARM L2x0 PCDs
|
||||
#
|
||||
gArmTokenSpaceGuid.PcdL2x0ControllerBase|0|UINT32|0x0000001B
|
||||
|
||||
#
|
||||
# ARM Normal (or Non Secure) Firmware PCDs
|
||||
#
|
||||
gArmTokenSpaceGuid.PcdFdSize|0|UINT32|0x0000002C
|
||||
gArmTokenSpaceGuid.PcdFvSize|0|UINT32|0x0000002E
|
||||
|
||||
#
|
||||
# Value to add to a host address to obtain a device address, using
|
||||
# unsigned 64-bit integer arithmetic on both ARM and AArch64. This
|
||||
# means we can rely on truncation on overflow to specify negative
|
||||
# offsets.
|
||||
#
|
||||
gArmTokenSpaceGuid.PcdArmDmaDeviceOffset|0x0|UINT64|0x0000044
|
||||
|
||||
[PcdsFixedAtBuild.common, PcdsPatchableInModule.common]
|
||||
gArmTokenSpaceGuid.PcdFdBaseAddress|0|UINT64|0x0000002B
|
||||
gArmTokenSpaceGuid.PcdFvBaseAddress|0|UINT64|0x0000002D
|
||||
|
||||
[PcdsFixedAtBuild.ARM]
|
||||
#
|
||||
# ARM Security Extension
|
||||
#
|
||||
|
||||
# Secure Configuration Register
|
||||
# - BIT0 : NS - Non Secure bit
|
||||
# - BIT1 : IRQ Handler
|
||||
# - BIT2 : FIQ Handler
|
||||
# - BIT3 : EA - External Abort
|
||||
# - BIT4 : FW - F bit writable
|
||||
# - BIT5 : AW - A bit writable
|
||||
# - BIT6 : nET - Not Early Termination
|
||||
# - BIT7 : SCD - Secure Monitor Call Disable
|
||||
# - BIT8 : HCE - Hyp Call enable
|
||||
# - BIT9 : SIF - Secure Instruction Fetch
|
||||
# 0x31 = NS | EA | FW
|
||||
gArmTokenSpaceGuid.PcdArmScr|0x31|UINT32|0x00000038
|
||||
|
||||
# By default we do not do a transition to non-secure mode
|
||||
gArmTokenSpaceGuid.PcdArmNonSecModeTransition|0x0|UINT32|0x0000003E
|
||||
|
||||
# Non Secure Access Control Register
|
||||
# - BIT15 : NSASEDIS - Disable Non-secure Advanced SIMD functionality
|
||||
# - BIT14 : NSD32DIS - Disable Non-secure use of D16-D31
|
||||
# - BIT11 : cp11 - Non-secure access to coprocessor 11 enable
|
||||
# - BIT10 : cp10 - Non-secure access to coprocessor 10 enable
|
||||
# 0xC00 = cp10 | cp11
|
||||
gArmTokenSpaceGuid.PcdArmNsacr|0xC00|UINT32|0x00000039
|
||||
|
||||
[PcdsFixedAtBuild.AARCH64]
|
||||
#
|
||||
# AArch64 Security Extension
|
||||
#
|
||||
|
||||
# Secure Configuration Register
|
||||
# - BIT0 : NS - Non Secure bit
|
||||
# - BIT1 : IRQ Handler
|
||||
# - BIT2 : FIQ Handler
|
||||
# - BIT3 : EA - External Abort
|
||||
# - BIT4 : FW - F bit writable
|
||||
# - BIT5 : AW - A bit writable
|
||||
# - BIT6 : nET - Not Early Termination
|
||||
# - BIT7 : SCD - Secure Monitor Call Disable
|
||||
# - BIT8 : HCE - Hyp Call enable
|
||||
# - BIT9 : SIF - Secure Instruction Fetch
|
||||
# - BIT10: RW - Register width control for lower exception levels
|
||||
# - BIT11: SIF - Enables Secure EL1 access to EL1 Architectural Timer
|
||||
# - BIT12: TWI - Trap WFI
|
||||
# - BIT13: TWE - Trap WFE
|
||||
# 0x501 = NS | HCE | RW
|
||||
gArmTokenSpaceGuid.PcdArmScr|0x501|UINT32|0x00000038
|
||||
|
||||
# By default we do transition to EL2 non-secure mode with Stack for EL2.
|
||||
# Mode Description Bits
|
||||
# NS EL2 SP2 all interrupts disabled = 0x3c9
|
||||
# NS EL1 SP1 all interrupts disabled = 0x3c5
|
||||
# Other modes include using SP0 or switching to Aarch32, but these are
|
||||
# not currently supported.
|
||||
gArmTokenSpaceGuid.PcdArmNonSecModeTransition|0x3c9|UINT32|0x0000003E
|
||||
|
||||
|
||||
#
|
||||
# These PCDs are also defined as 'PcdsDynamic' or 'PcdsPatchableInModule' to be
|
||||
# redefined when using UEFI in a context of virtual machine.
|
||||
#
|
||||
[PcdsFixedAtBuild.common, PcdsDynamic.common, PcdsPatchableInModule.common]
|
||||
|
||||
# System Memory (DRAM): These PCDs define the region of in-built system memory
|
||||
# Some platforms can get DRAM extensions, these additional regions may be
|
||||
# declared to UEFI using separate resource descriptor HOBs
|
||||
gArmTokenSpaceGuid.PcdSystemMemoryBase|0|UINT64|0x00000029
|
||||
gArmTokenSpaceGuid.PcdSystemMemorySize|0|UINT64|0x0000002A
|
||||
|
||||
gArmTokenSpaceGuid.PcdMmBufferBase|0|UINT64|0x00000045
|
||||
gArmTokenSpaceGuid.PcdMmBufferSize|0|UINT64|0x00000046
|
||||
|
||||
gArmTokenSpaceGuid.PcdSystemBiosRelease|0xFFFF|UINT16|0x30000058
|
||||
gArmTokenSpaceGuid.PcdEmbeddedControllerFirmwareRelease|0xFFFF|UINT16|0x30000059
|
||||
|
||||
[PcdsFixedAtBuild.common, PcdsDynamic.common]
|
||||
#
|
||||
# ARM Architectural Timer
|
||||
#
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz|0|UINT32|0x00000034
|
||||
|
||||
# ARM Architectural Timer Interrupt(GIC PPI) numbers
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerSecIntrNum|29|UINT32|0x00000035
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerIntrNum|30|UINT32|0x00000036
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerHypIntrNum|26|UINT32|0x00000040
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerVirtIntrNum|27|UINT32|0x00000041
|
||||
|
||||
#
|
||||
# ARM Generic Watchdog
|
||||
#
|
||||
|
||||
gArmTokenSpaceGuid.PcdGenericWatchdogControlBase|0x2A440000|UINT64|0x00000007
|
||||
gArmTokenSpaceGuid.PcdGenericWatchdogRefreshBase|0x2A450000|UINT64|0x00000008
|
||||
gArmTokenSpaceGuid.PcdGenericWatchdogEl2IntrNum|93|UINT32|0x00000009
|
||||
|
||||
#
|
||||
# ARM Generic Interrupt Controller
|
||||
#
|
||||
gArmTokenSpaceGuid.PcdGicDistributorBase|0|UINT64|0x0000000C
|
||||
# Base address for the GIC Redistributor region that contains the boot CPU
|
||||
gArmTokenSpaceGuid.PcdGicRedistributorsBase|0|UINT64|0x0000000E
|
||||
gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase|0|UINT64|0x0000000D
|
||||
gArmTokenSpaceGuid.PcdGicSgiIntId|0|UINT32|0x00000025
|
||||
|
||||
#
|
||||
# Bases, sizes and translation offsets of IO and MMIO spaces, respectively.
|
||||
# Note that "IO" is just another MMIO range that simulates IO space; there
|
||||
# are no special instructions to access it.
|
||||
#
|
||||
# The base addresses PcdPciIoBase, PcdPciMmio32Base and PcdPciMmio64Base are
|
||||
# specific to their containing address spaces. In order to get the physical
|
||||
# address for the CPU, for a given access, the respective translation value
|
||||
# has to be added.
|
||||
#
|
||||
# The translations always have to be initialized like this, using UINT64:
|
||||
#
|
||||
# UINT64 IoCpuBase; // mapping target in 64-bit cpu-physical space
|
||||
# UINT64 Mmio32CpuBase; // mapping target in 64-bit cpu-physical space
|
||||
# UINT64 Mmio64CpuBase; // mapping target in 64-bit cpu-physical space
|
||||
#
|
||||
# gEfiMdePkgTokenSpaceGuid.PcdPciIoTranslation = IoCpuBase - PcdPciIoBase;
|
||||
# gEfiMdePkgTokenSpaceGuid.PcdPciMmio32Translation = Mmio32CpuBase - (UINT64)PcdPciMmio32Base;
|
||||
# gEfiMdePkgTokenSpaceGuid.PcdPciMmio64Translation = Mmio64CpuBase - PcdPciMmio64Base;
|
||||
#
|
||||
# because (a) the target address space (ie. the cpu-physical space) is
|
||||
# 64-bit, and (b) the translation values are meant as offsets for *modular*
|
||||
# arithmetic.
|
||||
#
|
||||
# Accordingly, the translation itself needs to be implemented as:
|
||||
#
|
||||
# UINT64 UntranslatedIoAddress; // input parameter
|
||||
# UINT32 UntranslatedMmio32Address; // input parameter
|
||||
# UINT64 UntranslatedMmio64Address; // input parameter
|
||||
#
|
||||
# UINT64 TranslatedIoAddress; // output parameter
|
||||
# UINT64 TranslatedMmio32Address; // output parameter
|
||||
# UINT64 TranslatedMmio64Address; // output parameter
|
||||
#
|
||||
# TranslatedIoAddress = UntranslatedIoAddress +
|
||||
# gEfiMdePkgTokenSpaceGuid.PcdPciIoTranslation;
|
||||
# TranslatedMmio32Address = (UINT64)UntranslatedMmio32Address +
|
||||
# gEfiMdePkgTokenSpaceGuid.PcdPciMmio32Translation;
|
||||
# TranslatedMmio64Address = UntranslatedMmio64Address +
|
||||
# gEfiMdePkgTokenSpaceGuid.PcdPciMmio64Translation;
|
||||
#
|
||||
# The modular arithmetic performed in UINT64 ensures that the translation
|
||||
# works correctly regardless of the relation between IoCpuBase and
|
||||
# PcdPciIoBase, Mmio32CpuBase and PcdPciMmio32Base, and Mmio64CpuBase and
|
||||
# PcdPciMmio64Base.
|
||||
#
|
||||
gArmTokenSpaceGuid.PcdPciIoBase|0x0|UINT64|0x00000050
|
||||
gArmTokenSpaceGuid.PcdPciIoSize|0x0|UINT64|0x00000051
|
||||
gArmTokenSpaceGuid.PcdPciMmio32Base|0x0|UINT32|0x00000053
|
||||
gArmTokenSpaceGuid.PcdPciMmio32Size|0x0|UINT32|0x00000054
|
||||
gArmTokenSpaceGuid.PcdPciMmio64Base|0x0|UINT64|0x00000056
|
||||
gArmTokenSpaceGuid.PcdPciMmio64Size|0x0|UINT64|0x00000057
|
||||
|
||||
#
|
||||
# Inclusive range of allowed PCI buses.
|
||||
#
|
||||
gArmTokenSpaceGuid.PcdPciBusMin|0x0|UINT32|0x00000059
|
||||
gArmTokenSpaceGuid.PcdPciBusMax|0x0|UINT32|0x0000005A
|
||||
|
||||
[PcdsDynamicEx]
|
||||
#
|
||||
# This dynamic PCD hold the GUID of a firmware FFS which contains
|
||||
# the LinuxBoot payload.
|
||||
#
|
||||
gArmTokenSpaceGuid.PcdLinuxBootFileGuid|{0x0}|VOID*|0x0000005C
|
171
ArmPkg/ArmPkg.dsc
Normal file
171
ArmPkg/ArmPkg.dsc
Normal file
@ -0,0 +1,171 @@
|
||||
#/** @file
|
||||
# ARM processor package.
|
||||
#
|
||||
# Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.<BR>
|
||||
# Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.<BR>
|
||||
# Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
|
||||
# Copyright (c) Microsoft Corporation.<BR>
|
||||
# Copyright (c) 2021, Ampere Computing LLC. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
#**/
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Defines Section - statements that will be processed to create a Makefile.
|
||||
#
|
||||
################################################################################
|
||||
[Defines]
|
||||
PLATFORM_NAME = ArmPkg
|
||||
PLATFORM_GUID = 5CFBD99E-3C43-4E7F-8054-9CDEAFF7710F
|
||||
PLATFORM_VERSION = 0.1
|
||||
DSC_SPECIFICATION = 0x00010005
|
||||
OUTPUT_DIRECTORY = Build/Arm
|
||||
SUPPORTED_ARCHITECTURES = ARM|AARCH64
|
||||
BUILD_TARGETS = DEBUG|RELEASE|NOOPT
|
||||
SKUID_IDENTIFIER = DEFAULT
|
||||
|
||||
[BuildOptions]
|
||||
RELEASE_*_*_CC_FLAGS = -DMDEPKG_NDEBUG
|
||||
*_*_*_CC_FLAGS = -DDISABLE_NEW_DEPRECATED_INTERFACES
|
||||
|
||||
[PcdsFixedAtBuild]
|
||||
gEfiMdePkgTokenSpaceGuid.PcdDefaultTerminalType|4
|
||||
|
||||
!include MdePkg/MdeLibs.dsc.inc
|
||||
|
||||
[LibraryClasses.common]
|
||||
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
|
||||
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
|
||||
BootLogoLib|MdeModulePkg/Library/BootLogoLib/BootLogoLib.inf
|
||||
CacheMaintenanceLib|ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf
|
||||
CapsuleLib|MdeModulePkg/Library/DxeCapsuleLibNull/DxeCapsuleLibNull.inf
|
||||
DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
|
||||
DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
|
||||
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
|
||||
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
|
||||
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
|
||||
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
|
||||
TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
|
||||
UefiBootManagerLib|MdeModulePkg/Library/UefiBootManagerLib/UefiBootManagerLib.inf
|
||||
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
|
||||
UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
|
||||
UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
|
||||
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
|
||||
UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
|
||||
PeCoffLib|MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
|
||||
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
|
||||
PeCoffExtraActionLib|MdePkg/Library/BasePeCoffExtraActionLibNull/BasePeCoffExtraActionLibNull.inf
|
||||
|
||||
UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
|
||||
HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
|
||||
|
||||
SemihostLib|ArmPkg/Library/SemihostLib/SemihostLib.inf
|
||||
DxeServicesTableLib|MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.inf
|
||||
DefaultExceptionHandlerLib|ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLib.inf
|
||||
CpuExceptionHandlerLib|ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.inf
|
||||
|
||||
CpuLib|MdePkg/Library/BaseCpuLib/BaseCpuLib.inf
|
||||
ArmGicLib|ArmPkg/Drivers/ArmGic/ArmGicLib.inf
|
||||
ArmGicArchLib|ArmPkg/Library/ArmGicArchLib/ArmGicArchLib.inf
|
||||
ArmGenericTimerCounterLib|ArmPkg/Library/ArmGenericTimerPhyCounterLib/ArmGenericTimerPhyCounterLib.inf
|
||||
ArmSmcLib|ArmPkg/Library/ArmSmcLib/ArmSmcLib.inf
|
||||
ArmDisassemblerLib|ArmPkg/Library/ArmDisassemblerLib/ArmDisassemblerLib.inf
|
||||
OpteeLib|ArmPkg/Library/OpteeLib/OpteeLib.inf
|
||||
|
||||
UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
|
||||
PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
|
||||
SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf
|
||||
|
||||
FdtLib|EmbeddedPkg/Library/FdtLib/FdtLib.inf
|
||||
|
||||
ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
|
||||
FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
|
||||
SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
|
||||
|
||||
IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
|
||||
|
||||
ArmLib|ArmPkg/Library/ArmLib/ArmBaseLib.inf
|
||||
ArmMmuLib|ArmPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf
|
||||
|
||||
ArmMtlLib|ArmPkg/Library/ArmMtlNullLib/ArmMtlNullLib.inf
|
||||
|
||||
OemMiscLib|ArmPkg/Universal/Smbios/OemMiscLibNull/OemMiscLibNull.inf
|
||||
|
||||
[LibraryClasses.common.PEIM]
|
||||
HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
|
||||
PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
|
||||
MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
|
||||
PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
|
||||
PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
|
||||
|
||||
[LibraryClasses.ARM, LibraryClasses.AARCH64]
|
||||
NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
|
||||
|
||||
# Add support for GCC stack protector
|
||||
NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
|
||||
|
||||
[Components.common]
|
||||
ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.inf
|
||||
ArmPkg/Library/ArmDisassemblerLib/ArmDisassemblerLib.inf
|
||||
ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
|
||||
ArmPkg/Library/DebugAgentSymbolsBaseLib/DebugAgentSymbolsBaseLib.inf
|
||||
ArmPkg/Library/DebugPeCoffExtraActionLib/DebugPeCoffExtraActionLib.inf
|
||||
ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLib.inf
|
||||
ArmPkg/Library/RvdPeCoffExtraActionLib/RvdPeCoffExtraActionLib.inf
|
||||
ArmPkg/Library/SemiHostingDebugLib/SemiHostingDebugLib.inf
|
||||
ArmPkg/Library/SemiHostingSerialPortLib/SemiHostingSerialPortLib.inf
|
||||
ArmPkg/Library/SemihostLib/SemihostLib.inf
|
||||
ArmPkg/Library/ArmPsciResetSystemLib/ArmPsciResetSystemLib.inf
|
||||
ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.inf
|
||||
ArmPkg/Library/ArmExceptionLib/ArmRelocateExceptionLib.inf
|
||||
|
||||
ArmPkg/Drivers/CpuDxe/CpuDxe.inf
|
||||
ArmPkg/Drivers/CpuPei/CpuPei.inf
|
||||
ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
|
||||
ArmPkg/Drivers/ArmGic/ArmGicLib.inf
|
||||
ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.inf
|
||||
ArmPkg/Drivers/TimerDxe/TimerDxe.inf
|
||||
|
||||
ArmPkg/Library/ArmGenericTimerPhyCounterLib/ArmGenericTimerPhyCounterLib.inf
|
||||
ArmPkg/Library/ArmGenericTimerVirtCounterLib/ArmGenericTimerVirtCounterLib.inf
|
||||
|
||||
ArmPkg/Library/ArmTrngLib/ArmTrngLib.inf
|
||||
ArmPkg/Library/ArmHvcLib/ArmHvcLib.inf
|
||||
ArmPkg/Library/ArmHvcLibNull/ArmHvcLibNull.inf
|
||||
ArmPkg/Library/ArmMonitorLib/ArmMonitorLib.inf
|
||||
ArmPkg/Library/ArmSmcLib/ArmSmcLib.inf
|
||||
ArmPkg/Library/ArmSmcLibNull/ArmSmcLibNull.inf
|
||||
ArmPkg/Library/ArmSvcLib/ArmSvcLib.inf
|
||||
ArmPkg/Library/OpteeLib/OpteeLib.inf
|
||||
|
||||
ArmPkg/Filesystem/SemihostFs/SemihostFs.inf
|
||||
|
||||
ArmPkg/Library/ArmMmuLib/ArmMmuBaseLib.inf
|
||||
|
||||
ArmPkg/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf
|
||||
ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf
|
||||
ArmPkg/Library/ArmGicArchLib/ArmGicArchLib.inf
|
||||
ArmPkg/Library/ArmGicArchSecLib/ArmGicArchSecLib.inf
|
||||
ArmPkg/Library/ArmLib/ArmBaseLib.inf
|
||||
ArmPkg/Library/ArmMtlNullLib/ArmMtlNullLib.inf
|
||||
ArmPkg/Library/ArmSoftFloatLib/ArmSoftFloatLib.inf
|
||||
ArmPkg/Library/ArmSmcPsciResetSystemLib/ArmSmcPsciResetSystemLib.inf
|
||||
ArmPkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
|
||||
ArmPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
|
||||
ArmPkg/Library/LinuxBootBootManagerLib/LinuxBootBootManagerLib.inf
|
||||
|
||||
ArmPkg/Drivers/ArmCrashDumpDxe/ArmCrashDumpDxe.inf
|
||||
ArmPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf
|
||||
|
||||
ArmPkg/Universal/Smbios/ProcessorSubClassDxe/ProcessorSubClassDxe.inf
|
||||
ArmPkg/Universal/Smbios/SmbiosMiscDxe/SmbiosMiscDxe.inf
|
||||
ArmPkg/Universal/Smbios/OemMiscLibNull/OemMiscLibNull.inf
|
||||
|
||||
[Components.AARCH64]
|
||||
ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
|
||||
ArmPkg/Library/ArmMmuLib/ArmMmuPeiLib.inf
|
||||
|
||||
[Components.AARCH64, Components.ARM]
|
||||
ArmPkg/Library/StandaloneMmMmuLib/ArmMmuStandaloneMmLib.inf
|
34
ArmPkg/Drivers/ArmCrashDumpDxe/ArmCrashDumpDxe.c
Normal file
34
ArmPkg/Drivers/ArmCrashDumpDxe/ArmCrashDumpDxe.c
Normal file
@ -0,0 +1,34 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2017, Linaro, Ltd. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include <PiDxe.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/DefaultExceptionHandlerLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Protocol/Cpu.h>
|
||||
|
||||
STATIC EFI_CPU_ARCH_PROTOCOL *mCpu;
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArmCrashDumpDxeInitialize (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&mCpu);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
return mCpu->RegisterInterruptHandler (
|
||||
mCpu,
|
||||
EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS,
|
||||
&DefaultExceptionHandler
|
||||
);
|
||||
}
|
50
ArmPkg/Drivers/ArmCrashDumpDxe/ArmCrashDumpDxe.dsc
Normal file
50
ArmPkg/Drivers/ArmCrashDumpDxe/ArmCrashDumpDxe.dsc
Normal file
@ -0,0 +1,50 @@
|
||||
#/** @file
|
||||
#
|
||||
# Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
#**/
|
||||
|
||||
################################################################################
|
||||
#
|
||||
# Defines Section - statements that will be processed to create a Makefile.
|
||||
#
|
||||
################################################################################
|
||||
[Defines]
|
||||
PLATFORM_NAME = ArmCrashDumpDxe
|
||||
PLATFORM_GUID = 8dc3c2f8-988e-4e32-8fb7-0df43f6d0d8a
|
||||
PLATFORM_VERSION = 0.1
|
||||
DSC_SPECIFICATION = 0x00010019
|
||||
OUTPUT_DIRECTORY = Build/ArmCrashDumpDxe
|
||||
SUPPORTED_ARCHITECTURES = AARCH64
|
||||
BUILD_TARGETS = DEBUG
|
||||
SKUID_IDENTIFIER = DEFAULT
|
||||
|
||||
[PcdsFixedAtBuild]
|
||||
gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8000004F
|
||||
gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x27
|
||||
|
||||
[LibraryClasses]
|
||||
ArmDisassemblerLib|ArmPkg/Library/ArmDisassemblerLib/ArmDisassemblerLib.inf
|
||||
BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
|
||||
BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
|
||||
DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
|
||||
DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
|
||||
DefaultExceptionHandlerLib|ArmPkg/Library/DefaultExceptionHandlerLib/DefaultExceptionHandlerLib.inf
|
||||
DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf
|
||||
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
|
||||
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
|
||||
PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
|
||||
PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
|
||||
SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf
|
||||
UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
|
||||
UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
|
||||
UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
|
||||
UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
|
||||
|
||||
NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
|
||||
NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
|
||||
|
||||
[Components.common]
|
||||
ArmPkg/Drivers/ArmCrashDumpDxe/ArmCrashDumpDxe.inf
|
34
ArmPkg/Drivers/ArmCrashDumpDxe/ArmCrashDumpDxe.inf
Normal file
34
ArmPkg/Drivers/ArmCrashDumpDxe/ArmCrashDumpDxe.inf
Normal file
@ -0,0 +1,34 @@
|
||||
#/** @file
|
||||
#
|
||||
# Copyright (c) 2017, Linaro, Ltd. All rights reserved.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
#**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010018
|
||||
BASE_NAME = ArmCrashDumpDxe
|
||||
FILE_GUID = 0bda00b0-05d6-4bb8-bfc7-058ad13615cf
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = ArmCrashDumpDxeInitialize
|
||||
|
||||
[Sources]
|
||||
ArmCrashDumpDxe.c
|
||||
|
||||
[Packages]
|
||||
ArmPkg/ArmPkg.dec
|
||||
MdePkg/MdePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
DebugLib
|
||||
DefaultExceptionHandlerLib
|
||||
UefiBootServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
|
||||
[Protocols]
|
||||
gEfiCpuArchProtocolGuid
|
||||
|
||||
[Depex]
|
||||
gEfiCpuArchProtocolGuid
|
215
ArmPkg/Drivers/ArmGic/ArmGicCommonDxe.c
Normal file
215
ArmPkg/Drivers/ArmGic/ArmGicCommonDxe.c
Normal file
@ -0,0 +1,215 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2013-2017, ARM Ltd. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
--*/
|
||||
|
||||
#include "ArmGicDxe.h"
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
IrqInterruptHandler (
|
||||
IN EFI_EXCEPTION_TYPE InterruptType,
|
||||
IN EFI_SYSTEM_CONTEXT SystemContext
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ExitBootServicesEvent (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
);
|
||||
|
||||
// Making this global saves a few bytes in image size
|
||||
EFI_HANDLE gHardwareInterruptHandle = NULL;
|
||||
|
||||
// Notifications
|
||||
EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL;
|
||||
|
||||
// Maximum Number of Interrupts
|
||||
UINTN mGicNumInterrupts = 0;
|
||||
|
||||
HARDWARE_INTERRUPT_HANDLER *gRegisteredInterruptHandlers = NULL;
|
||||
|
||||
/**
|
||||
Calculate GICD_ICFGRn base address and corresponding bit
|
||||
field Int_config[1] of the GIC distributor register.
|
||||
|
||||
@param Source Hardware source of the interrupt.
|
||||
@param RegAddress Corresponding GICD_ICFGRn base address.
|
||||
@param Config1Bit Bit number of F Int_config[1] bit in the register.
|
||||
|
||||
@retval EFI_SUCCESS Source interrupt supported.
|
||||
@retval EFI_UNSUPPORTED Source interrupt is not supported.
|
||||
**/
|
||||
EFI_STATUS
|
||||
GicGetDistributorIcfgBaseAndBit (
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source,
|
||||
OUT UINTN *RegAddress,
|
||||
OUT UINTN *Config1Bit
|
||||
)
|
||||
{
|
||||
UINTN RegIndex;
|
||||
UINTN Field;
|
||||
|
||||
if (Source >= mGicNumInterrupts) {
|
||||
ASSERT (Source < mGicNumInterrupts);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
RegIndex = Source / ARM_GIC_ICDICFR_F_STRIDE; // NOTE: truncation is significant
|
||||
Field = Source % ARM_GIC_ICDICFR_F_STRIDE;
|
||||
*RegAddress = PcdGet64 (PcdGicDistributorBase)
|
||||
+ ARM_GIC_ICDICFR
|
||||
+ (ARM_GIC_ICDICFR_BYTES * RegIndex);
|
||||
*Config1Bit = ((Field * ARM_GIC_ICDICFR_F_WIDTH)
|
||||
+ ARM_GIC_ICDICFR_F_CONFIG1_BIT);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Register Handler for the specified interrupt source.
|
||||
|
||||
@param This Instance pointer for this protocol
|
||||
@param Source Hardware source of the interrupt
|
||||
@param Handler Callback for interrupt. NULL to unregister
|
||||
|
||||
@retval EFI_SUCCESS Source was updated to support Handler.
|
||||
@retval EFI_DEVICE_ERROR Hardware could not be programmed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
RegisterInterruptSource (
|
||||
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source,
|
||||
IN HARDWARE_INTERRUPT_HANDLER Handler
|
||||
)
|
||||
{
|
||||
if (Source >= mGicNumInterrupts) {
|
||||
ASSERT (FALSE);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if ((Handler == NULL) && (gRegisteredInterruptHandlers[Source] == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ((Handler != NULL) && (gRegisteredInterruptHandlers[Source] != NULL)) {
|
||||
return EFI_ALREADY_STARTED;
|
||||
}
|
||||
|
||||
gRegisteredInterruptHandlers[Source] = Handler;
|
||||
|
||||
// If the interrupt handler is unregistered then disable the interrupt
|
||||
if (NULL == Handler) {
|
||||
return This->DisableInterruptSource (This, Source);
|
||||
} else {
|
||||
return This->EnableInterruptSource (This, Source);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC VOID *mCpuArchProtocolNotifyEventRegistration;
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
EFIAPI
|
||||
CpuArchEventProtocolNotify (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
EFI_CPU_ARCH_PROTOCOL *Cpu;
|
||||
EFI_STATUS Status;
|
||||
|
||||
// Get the CPU protocol that this driver requires.
|
||||
Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&Cpu);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Unregister the default exception handler.
|
||||
Status = Cpu->RegisterInterruptHandler (Cpu, ARM_ARCH_EXCEPTION_IRQ, NULL);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"%a: Cpu->RegisterInterruptHandler() - %r\n",
|
||||
__FUNCTION__,
|
||||
Status
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
||||
// Register to receive interrupts
|
||||
Status = Cpu->RegisterInterruptHandler (
|
||||
Cpu,
|
||||
ARM_ARCH_EXCEPTION_IRQ,
|
||||
Context
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"%a: Cpu->RegisterInterruptHandler() - %r\n",
|
||||
__FUNCTION__,
|
||||
Status
|
||||
));
|
||||
}
|
||||
|
||||
gBS->CloseEvent (Event);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
InstallAndRegisterInterruptService (
|
||||
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *InterruptProtocol,
|
||||
IN EFI_HARDWARE_INTERRUPT2_PROTOCOL *Interrupt2Protocol,
|
||||
IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler,
|
||||
IN EFI_EVENT_NOTIFY ExitBootServicesEvent
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
CONST UINTN RihArraySize =
|
||||
(sizeof (HARDWARE_INTERRUPT_HANDLER) * mGicNumInterrupts);
|
||||
|
||||
// Initialize the array for the Interrupt Handlers
|
||||
gRegisteredInterruptHandlers = AllocateZeroPool (RihArraySize);
|
||||
if (gRegisteredInterruptHandlers == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&gHardwareInterruptHandle,
|
||||
&gHardwareInterruptProtocolGuid,
|
||||
InterruptProtocol,
|
||||
&gHardwareInterrupt2ProtocolGuid,
|
||||
Interrupt2Protocol,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Install the interrupt handler as soon as the CPU arch protocol appears.
|
||||
//
|
||||
EfiCreateProtocolNotifyEvent (
|
||||
&gEfiCpuArchProtocolGuid,
|
||||
TPL_CALLBACK,
|
||||
CpuArchEventProtocolNotify,
|
||||
InterruptHandler,
|
||||
&mCpuArchProtocolNotifyEventRegistration
|
||||
);
|
||||
|
||||
// Register for an ExitBootServicesEvent
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_SIGNAL_EXIT_BOOT_SERVICES,
|
||||
TPL_NOTIFY,
|
||||
ExitBootServicesEvent,
|
||||
NULL,
|
||||
&EfiExitBootServicesEvent
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
53
ArmPkg/Drivers/ArmGic/ArmGicDxe.c
Normal file
53
ArmPkg/Drivers/ArmGic/ArmGicDxe.c
Normal file
@ -0,0 +1,53 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2013-2014, ARM Ltd. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
Module Name:
|
||||
|
||||
ArmGicDxe.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Driver implementing the GIC interrupt controller protocol
|
||||
|
||||
--*/
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include "ArmGicDxe.h"
|
||||
|
||||
/**
|
||||
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
|
||||
@retval EFI_UNSUPPORTED GIC version not supported
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
InterruptDxeInitialize (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
ARM_GIC_ARCH_REVISION Revision;
|
||||
|
||||
Revision = ArmGicGetSupportedArchRevision ();
|
||||
|
||||
if (Revision == ARM_GIC_ARCH_REVISION_2) {
|
||||
Status = GicV2DxeInitialize (ImageHandle, SystemTable);
|
||||
} else if (Revision == ARM_GIC_ARCH_REVISION_3) {
|
||||
Status = GicV3DxeInitialize (ImageHandle, SystemTable);
|
||||
} else {
|
||||
Status = EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
78
ArmPkg/Drivers/ArmGic/ArmGicDxe.h
Normal file
78
ArmPkg/Drivers/ArmGic/ArmGicDxe.h
Normal file
@ -0,0 +1,78 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2013-2017, ARM Ltd. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef ARM_GIC_DXE_H_
|
||||
#define ARM_GIC_DXE_H_
|
||||
|
||||
#include <Library/ArmGicLib.h>
|
||||
#include <Library/ArmLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
|
||||
#include <Protocol/Cpu.h>
|
||||
#include <Protocol/HardwareInterrupt.h>
|
||||
#include <Protocol/HardwareInterrupt2.h>
|
||||
|
||||
extern UINTN mGicNumInterrupts;
|
||||
extern HARDWARE_INTERRUPT_HANDLER *gRegisteredInterruptHandlers;
|
||||
|
||||
// Common API
|
||||
EFI_STATUS
|
||||
InstallAndRegisterInterruptService (
|
||||
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *InterruptProtocol,
|
||||
IN EFI_HARDWARE_INTERRUPT2_PROTOCOL *Interrupt2Protocol,
|
||||
IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler,
|
||||
IN EFI_EVENT_NOTIFY ExitBootServicesEvent
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
RegisterInterruptSource (
|
||||
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source,
|
||||
IN HARDWARE_INTERRUPT_HANDLER Handler
|
||||
);
|
||||
|
||||
// GicV2 API
|
||||
EFI_STATUS
|
||||
GicV2DxeInitialize (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
);
|
||||
|
||||
// GicV3 API
|
||||
EFI_STATUS
|
||||
GicV3DxeInitialize (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
);
|
||||
|
||||
// Shared code
|
||||
|
||||
/**
|
||||
Calculate GICD_ICFGRn base address and corresponding bit
|
||||
field Int_config[1] of the GIC distributor register.
|
||||
|
||||
@param Source Hardware source of the interrupt.
|
||||
@param RegAddress Corresponding GICD_ICFGRn base address.
|
||||
@param Config1Bit Bit number of F Int_config[1] bit in the register.
|
||||
|
||||
@retval EFI_SUCCESS Source interrupt supported.
|
||||
@retval EFI_UNSUPPORTED Source interrupt is not supported.
|
||||
**/
|
||||
EFI_STATUS
|
||||
GicGetDistributorIcfgBaseAndBit (
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source,
|
||||
OUT UINTN *RegAddress,
|
||||
OUT UINTN *Config1Bit
|
||||
);
|
||||
|
||||
#endif // ARM_GIC_DXE_H_
|
57
ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
Normal file
57
ArmPkg/Drivers/ArmGic/ArmGicDxe.inf
Normal file
@ -0,0 +1,57 @@
|
||||
#/** @file
|
||||
#
|
||||
# Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
|
||||
# Copyright (c) 2012 - 2017, ARM Ltd. All rights reserved.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
#**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = ArmGicDxe
|
||||
FILE_GUID = DE371F7C-DEC4-4D21-ADF1-593ABCC15882
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
|
||||
ENTRY_POINT = InterruptDxeInitialize
|
||||
|
||||
[Sources.common]
|
||||
ArmGicDxe.h
|
||||
ArmGicDxe.c
|
||||
ArmGicCommonDxe.c
|
||||
|
||||
GicV2/ArmGicV2Dxe.c
|
||||
GicV3/ArmGicV3Dxe.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
EmbeddedPkg/EmbeddedPkg.dec
|
||||
ArmPkg/ArmPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
ArmGicLib
|
||||
BaseLib
|
||||
UefiLib
|
||||
UefiBootServicesTableLib
|
||||
DebugLib
|
||||
PrintLib
|
||||
MemoryAllocationLib
|
||||
UefiDriverEntryPoint
|
||||
IoLib
|
||||
PcdLib
|
||||
UefiLib
|
||||
|
||||
[Protocols]
|
||||
gHardwareInterruptProtocolGuid ## PRODUCES
|
||||
gHardwareInterrupt2ProtocolGuid ## PRODUCES
|
||||
gEfiCpuArchProtocolGuid ## CONSUMES ## NOTIFY
|
||||
|
||||
[Pcd.common]
|
||||
gArmTokenSpaceGuid.PcdGicDistributorBase
|
||||
gArmTokenSpaceGuid.PcdGicRedistributorsBase
|
||||
gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase
|
||||
gArmTokenSpaceGuid.PcdArmGicV3WithV2Legacy
|
||||
|
||||
[Depex]
|
||||
TRUE
|
434
ArmPkg/Drivers/ArmGic/ArmGicLib.c
Normal file
434
ArmPkg/Drivers/ArmGic/ArmGicLib.c
Normal file
@ -0,0 +1,434 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2011-2021, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#include <Base.h>
|
||||
#include <Library/ArmGicLib.h>
|
||||
#include <Library/ArmLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
|
||||
// In GICv3, there are 2 x 64KB frames:
|
||||
// Redistributor control frame + SGI Control & Generation frame
|
||||
#define GIC_V3_REDISTRIBUTOR_GRANULARITY (ARM_GICR_CTLR_FRAME_SIZE \
|
||||
+ ARM_GICR_SGI_PPI_FRAME_SIZE)
|
||||
|
||||
// In GICv4, there are 2 additional 64KB frames:
|
||||
// VLPI frame + Reserved page frame
|
||||
#define GIC_V4_REDISTRIBUTOR_GRANULARITY (GIC_V3_REDISTRIBUTOR_GRANULARITY \
|
||||
+ ARM_GICR_SGI_VLPI_FRAME_SIZE \
|
||||
+ ARM_GICR_SGI_RESERVED_FRAME_SIZE)
|
||||
|
||||
#define ISENABLER_ADDRESS(base, offset) ((base) +\
|
||||
ARM_GICR_CTLR_FRAME_SIZE + ARM_GICR_ISENABLER + 4 * (offset))
|
||||
|
||||
#define ICENABLER_ADDRESS(base, offset) ((base) +\
|
||||
ARM_GICR_CTLR_FRAME_SIZE + ARM_GICR_ICENABLER + 4 * (offset))
|
||||
|
||||
#define IPRIORITY_ADDRESS(base, offset) ((base) +\
|
||||
ARM_GICR_CTLR_FRAME_SIZE + ARM_GIC_ICDIPR + 4 * (offset))
|
||||
|
||||
/**
|
||||
*
|
||||
* Return whether the Source interrupt index refers to a shared interrupt (SPI)
|
||||
*/
|
||||
STATIC
|
||||
BOOLEAN
|
||||
SourceIsSpi (
|
||||
IN UINTN Source
|
||||
)
|
||||
{
|
||||
return Source >= 32 && Source < 1020;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the base address of the GIC redistributor for the current CPU
|
||||
*
|
||||
* @param Revision GIC Revision. The GIC redistributor might have a different
|
||||
* granularity following the GIC revision.
|
||||
*
|
||||
* @retval Base address of the associated GIC Redistributor
|
||||
*/
|
||||
STATIC
|
||||
UINTN
|
||||
GicGetCpuRedistributorBase (
|
||||
IN UINTN GicRedistributorBase,
|
||||
IN ARM_GIC_ARCH_REVISION Revision
|
||||
)
|
||||
{
|
||||
UINTN MpId;
|
||||
UINTN CpuAffinity;
|
||||
UINTN Affinity;
|
||||
UINTN GicCpuRedistributorBase;
|
||||
UINT64 TypeRegister;
|
||||
|
||||
MpId = ArmReadMpidr ();
|
||||
// Define CPU affinity as:
|
||||
// Affinity0[0:8], Affinity1[9:15], Affinity2[16:23], Affinity3[24:32]
|
||||
// whereas Affinity3 is defined at [32:39] in MPIDR
|
||||
CpuAffinity = (MpId & (ARM_CORE_AFF0 | ARM_CORE_AFF1 | ARM_CORE_AFF2)) |
|
||||
((MpId & ARM_CORE_AFF3) >> 8);
|
||||
|
||||
if (Revision < ARM_GIC_ARCH_REVISION_3) {
|
||||
ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
GicCpuRedistributorBase = GicRedistributorBase;
|
||||
|
||||
do {
|
||||
TypeRegister = MmioRead64 (GicCpuRedistributorBase + ARM_GICR_TYPER);
|
||||
Affinity = ARM_GICR_TYPER_GET_AFFINITY (TypeRegister);
|
||||
if (Affinity == CpuAffinity) {
|
||||
return GicCpuRedistributorBase;
|
||||
}
|
||||
|
||||
// Move to the next GIC Redistributor frame.
|
||||
// The GIC specification does not forbid a mixture of redistributors
|
||||
// with or without support for virtual LPIs, so we test Virtual LPIs
|
||||
// Support (VLPIS) bit for each frame to decide the granularity.
|
||||
// Note: The assumption here is that the redistributors are adjacent
|
||||
// for all CPUs. However this may not be the case for NUMA systems.
|
||||
GicCpuRedistributorBase += (((ARM_GICR_TYPER_VLPIS & TypeRegister) != 0)
|
||||
? GIC_V4_REDISTRIBUTOR_GRANULARITY
|
||||
: GIC_V3_REDISTRIBUTOR_GRANULARITY);
|
||||
} while ((TypeRegister & ARM_GICR_TYPER_LAST) == 0);
|
||||
|
||||
// The Redistributor has not been found for the current CPU
|
||||
ASSERT_EFI_ERROR (EFI_NOT_FOUND);
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmGicGetInterfaceIdentification (
|
||||
IN INTN GicInterruptInterfaceBase
|
||||
)
|
||||
{
|
||||
// Read the GIC Identification Register
|
||||
return MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCIIDR);
|
||||
}
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmGicGetMaxNumInterrupts (
|
||||
IN INTN GicDistributorBase
|
||||
)
|
||||
{
|
||||
UINTN ItLines;
|
||||
|
||||
ItLines = MmioRead32 (GicDistributorBase + ARM_GIC_ICDICTR) & 0x1F;
|
||||
|
||||
//
|
||||
// Interrupt ID 1020-1023 are reserved.
|
||||
//
|
||||
return (ItLines == 0x1f) ? 1020 : 32 * (ItLines + 1);
|
||||
}
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicSendSgiTo (
|
||||
IN INTN GicDistributorBase,
|
||||
IN INTN TargetListFilter,
|
||||
IN INTN CPUTargetList,
|
||||
IN INTN SgiId
|
||||
)
|
||||
{
|
||||
MmioWrite32 (
|
||||
GicDistributorBase + ARM_GIC_ICDSGIR,
|
||||
((TargetListFilter & 0x3) << 24) | ((CPUTargetList & 0xFF) << 16) | SgiId
|
||||
);
|
||||
}
|
||||
|
||||
/*
|
||||
* Acknowledge and return the value of the Interrupt Acknowledge Register
|
||||
*
|
||||
* InterruptId is returned separately from the register value because in
|
||||
* the GICv2 the register value contains the CpuId and InterruptId while
|
||||
* in the GICv3 the register value is only the InterruptId.
|
||||
*
|
||||
* @param GicInterruptInterfaceBase Base Address of the GIC CPU Interface
|
||||
* @param InterruptId InterruptId read from the Interrupt
|
||||
* Acknowledge Register
|
||||
*
|
||||
* @retval value returned by the Interrupt Acknowledge Register
|
||||
*
|
||||
*/
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmGicAcknowledgeInterrupt (
|
||||
IN UINTN GicInterruptInterfaceBase,
|
||||
OUT UINTN *InterruptId
|
||||
)
|
||||
{
|
||||
UINTN Value;
|
||||
ARM_GIC_ARCH_REVISION Revision;
|
||||
|
||||
Revision = ArmGicGetSupportedArchRevision ();
|
||||
if (Revision == ARM_GIC_ARCH_REVISION_2) {
|
||||
Value = ArmGicV2AcknowledgeInterrupt (GicInterruptInterfaceBase);
|
||||
// InterruptId is required for the caller to know if a valid or spurious
|
||||
// interrupt has been read
|
||||
ASSERT (InterruptId != NULL);
|
||||
if (InterruptId != NULL) {
|
||||
*InterruptId = Value & ARM_GIC_ICCIAR_ACKINTID;
|
||||
}
|
||||
} else if (Revision == ARM_GIC_ARCH_REVISION_3) {
|
||||
Value = ArmGicV3AcknowledgeInterrupt ();
|
||||
} else {
|
||||
ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
|
||||
// Report Spurious interrupt which is what the above controllers would
|
||||
// return if no interrupt was available
|
||||
Value = 1023;
|
||||
}
|
||||
|
||||
return Value;
|
||||
}
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicEndOfInterrupt (
|
||||
IN UINTN GicInterruptInterfaceBase,
|
||||
IN UINTN Source
|
||||
)
|
||||
{
|
||||
ARM_GIC_ARCH_REVISION Revision;
|
||||
|
||||
Revision = ArmGicGetSupportedArchRevision ();
|
||||
if (Revision == ARM_GIC_ARCH_REVISION_2) {
|
||||
ArmGicV2EndOfInterrupt (GicInterruptInterfaceBase, Source);
|
||||
} else if (Revision == ARM_GIC_ARCH_REVISION_3) {
|
||||
ArmGicV3EndOfInterrupt (Source);
|
||||
} else {
|
||||
ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicSetInterruptPriority (
|
||||
IN UINTN GicDistributorBase,
|
||||
IN UINTN GicRedistributorBase,
|
||||
IN UINTN Source,
|
||||
IN UINTN Priority
|
||||
)
|
||||
{
|
||||
UINT32 RegOffset;
|
||||
UINTN RegShift;
|
||||
ARM_GIC_ARCH_REVISION Revision;
|
||||
UINTN GicCpuRedistributorBase;
|
||||
|
||||
// Calculate register offset and bit position
|
||||
RegOffset = Source / 4;
|
||||
RegShift = (Source % 4) * 8;
|
||||
|
||||
Revision = ArmGicGetSupportedArchRevision ();
|
||||
if ((Revision == ARM_GIC_ARCH_REVISION_2) ||
|
||||
FeaturePcdGet (PcdArmGicV3WithV2Legacy) ||
|
||||
SourceIsSpi (Source))
|
||||
{
|
||||
MmioAndThenOr32 (
|
||||
GicDistributorBase + ARM_GIC_ICDIPR + (4 * RegOffset),
|
||||
~(0xff << RegShift),
|
||||
Priority << RegShift
|
||||
);
|
||||
} else {
|
||||
GicCpuRedistributorBase = GicGetCpuRedistributorBase (
|
||||
GicRedistributorBase,
|
||||
Revision
|
||||
);
|
||||
if (GicCpuRedistributorBase == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
MmioAndThenOr32 (
|
||||
IPRIORITY_ADDRESS (GicCpuRedistributorBase, RegOffset),
|
||||
~(0xff << RegShift),
|
||||
Priority << RegShift
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicEnableInterrupt (
|
||||
IN UINTN GicDistributorBase,
|
||||
IN UINTN GicRedistributorBase,
|
||||
IN UINTN Source
|
||||
)
|
||||
{
|
||||
UINT32 RegOffset;
|
||||
UINTN RegShift;
|
||||
ARM_GIC_ARCH_REVISION Revision;
|
||||
UINTN GicCpuRedistributorBase;
|
||||
|
||||
// Calculate enable register offset and bit position
|
||||
RegOffset = Source / 32;
|
||||
RegShift = Source % 32;
|
||||
|
||||
Revision = ArmGicGetSupportedArchRevision ();
|
||||
if ((Revision == ARM_GIC_ARCH_REVISION_2) ||
|
||||
FeaturePcdGet (PcdArmGicV3WithV2Legacy) ||
|
||||
SourceIsSpi (Source))
|
||||
{
|
||||
// Write set-enable register
|
||||
MmioWrite32 (
|
||||
GicDistributorBase + ARM_GIC_ICDISER + (4 * RegOffset),
|
||||
1 << RegShift
|
||||
);
|
||||
} else {
|
||||
GicCpuRedistributorBase = GicGetCpuRedistributorBase (
|
||||
GicRedistributorBase,
|
||||
Revision
|
||||
);
|
||||
if (GicCpuRedistributorBase == 0) {
|
||||
ASSERT_EFI_ERROR (EFI_NOT_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
// Write set-enable register
|
||||
MmioWrite32 (
|
||||
ISENABLER_ADDRESS (GicCpuRedistributorBase, RegOffset),
|
||||
1 << RegShift
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicDisableInterrupt (
|
||||
IN UINTN GicDistributorBase,
|
||||
IN UINTN GicRedistributorBase,
|
||||
IN UINTN Source
|
||||
)
|
||||
{
|
||||
UINT32 RegOffset;
|
||||
UINTN RegShift;
|
||||
ARM_GIC_ARCH_REVISION Revision;
|
||||
UINTN GicCpuRedistributorBase;
|
||||
|
||||
// Calculate enable register offset and bit position
|
||||
RegOffset = Source / 32;
|
||||
RegShift = Source % 32;
|
||||
|
||||
Revision = ArmGicGetSupportedArchRevision ();
|
||||
if ((Revision == ARM_GIC_ARCH_REVISION_2) ||
|
||||
FeaturePcdGet (PcdArmGicV3WithV2Legacy) ||
|
||||
SourceIsSpi (Source))
|
||||
{
|
||||
// Write clear-enable register
|
||||
MmioWrite32 (
|
||||
GicDistributorBase + ARM_GIC_ICDICER + (4 * RegOffset),
|
||||
1 << RegShift
|
||||
);
|
||||
} else {
|
||||
GicCpuRedistributorBase = GicGetCpuRedistributorBase (
|
||||
GicRedistributorBase,
|
||||
Revision
|
||||
);
|
||||
if (GicCpuRedistributorBase == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Write clear-enable register
|
||||
MmioWrite32 (
|
||||
ICENABLER_ADDRESS (GicCpuRedistributorBase, RegOffset),
|
||||
1 << RegShift
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
ArmGicIsInterruptEnabled (
|
||||
IN UINTN GicDistributorBase,
|
||||
IN UINTN GicRedistributorBase,
|
||||
IN UINTN Source
|
||||
)
|
||||
{
|
||||
UINT32 RegOffset;
|
||||
UINTN RegShift;
|
||||
ARM_GIC_ARCH_REVISION Revision;
|
||||
UINTN GicCpuRedistributorBase;
|
||||
UINT32 Interrupts;
|
||||
|
||||
// Calculate enable register offset and bit position
|
||||
RegOffset = Source / 32;
|
||||
RegShift = Source % 32;
|
||||
|
||||
Revision = ArmGicGetSupportedArchRevision ();
|
||||
if ((Revision == ARM_GIC_ARCH_REVISION_2) ||
|
||||
FeaturePcdGet (PcdArmGicV3WithV2Legacy) ||
|
||||
SourceIsSpi (Source))
|
||||
{
|
||||
Interrupts = MmioRead32 (
|
||||
GicDistributorBase + ARM_GIC_ICDISER + (4 * RegOffset)
|
||||
);
|
||||
} else {
|
||||
GicCpuRedistributorBase = GicGetCpuRedistributorBase (
|
||||
GicRedistributorBase,
|
||||
Revision
|
||||
);
|
||||
if (GicCpuRedistributorBase == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read set-enable register
|
||||
Interrupts = MmioRead32 (
|
||||
ISENABLER_ADDRESS (GicCpuRedistributorBase, RegOffset)
|
||||
);
|
||||
}
|
||||
|
||||
return ((Interrupts & (1 << RegShift)) != 0);
|
||||
}
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicDisableDistributor (
|
||||
IN INTN GicDistributorBase
|
||||
)
|
||||
{
|
||||
// Disable Gic Distributor
|
||||
MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 0x0);
|
||||
}
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicEnableInterruptInterface (
|
||||
IN INTN GicInterruptInterfaceBase
|
||||
)
|
||||
{
|
||||
ARM_GIC_ARCH_REVISION Revision;
|
||||
|
||||
Revision = ArmGicGetSupportedArchRevision ();
|
||||
if (Revision == ARM_GIC_ARCH_REVISION_2) {
|
||||
ArmGicV2EnableInterruptInterface (GicInterruptInterfaceBase);
|
||||
} else if (Revision == ARM_GIC_ARCH_REVISION_3) {
|
||||
ArmGicV3EnableInterruptInterface ();
|
||||
} else {
|
||||
ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicDisableInterruptInterface (
|
||||
IN INTN GicInterruptInterfaceBase
|
||||
)
|
||||
{
|
||||
ARM_GIC_ARCH_REVISION Revision;
|
||||
|
||||
Revision = ArmGicGetSupportedArchRevision ();
|
||||
if (Revision == ARM_GIC_ARCH_REVISION_2) {
|
||||
ArmGicV2DisableInterruptInterface (GicInterruptInterfaceBase);
|
||||
} else if (Revision == ARM_GIC_ARCH_REVISION_3) {
|
||||
ArmGicV3DisableInterruptInterface ();
|
||||
} else {
|
||||
ASSERT_EFI_ERROR (EFI_UNSUPPORTED);
|
||||
}
|
||||
}
|
41
ArmPkg/Drivers/ArmGic/ArmGicLib.inf
Normal file
41
ArmPkg/Drivers/ArmGic/ArmGicLib.inf
Normal file
@ -0,0 +1,41 @@
|
||||
#/* @file
|
||||
# Copyright (c) 2011-2018, ARM Limited. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
#*/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = ArmGicLib
|
||||
FILE_GUID = 03d05ee4-cdeb-458c-9dfc-993f09bdf405
|
||||
MODULE_TYPE = SEC
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = ArmGicLib
|
||||
|
||||
[Sources]
|
||||
ArmGicLib.c
|
||||
ArmGicNonSecLib.c
|
||||
|
||||
GicV2/ArmGicV2Lib.c
|
||||
GicV2/ArmGicV2NonSecLib.c
|
||||
|
||||
[Sources.ARM]
|
||||
GicV3/Arm/ArmGicV3.S | GCC
|
||||
|
||||
[Sources.AARCH64]
|
||||
GicV3/AArch64/ArmGicV3.S
|
||||
|
||||
[LibraryClasses]
|
||||
ArmLib
|
||||
DebugLib
|
||||
IoLib
|
||||
ArmGicArchLib
|
||||
|
||||
[Packages]
|
||||
ArmPkg/ArmPkg.dec
|
||||
ArmPlatformPkg/ArmPlatformPkg.dec
|
||||
MdePkg/MdePkg.dec
|
||||
|
||||
[FeaturePcd]
|
||||
gArmTokenSpaceGuid.PcdArmGicV3WithV2Legacy
|
35
ArmPkg/Drivers/ArmGic/ArmGicNonSecLib.c
Normal file
35
ArmPkg/Drivers/ArmGic/ArmGicNonSecLib.c
Normal file
@ -0,0 +1,35 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2011-2015, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#include <Uefi.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/ArmGicLib.h>
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicEnableDistributor (
|
||||
IN INTN GicDistributorBase
|
||||
)
|
||||
{
|
||||
ARM_GIC_ARCH_REVISION Revision;
|
||||
|
||||
/*
|
||||
* Enable GIC distributor in Non-Secure world.
|
||||
* Note: The ICDDCR register is banked when Security extensions are implemented
|
||||
*/
|
||||
Revision = ArmGicGetSupportedArchRevision ();
|
||||
if (Revision == ARM_GIC_ARCH_REVISION_2) {
|
||||
MmioWrite32 (GicDistributorBase + ARM_GIC_ICDDCR, 0x1);
|
||||
} else {
|
||||
if (MmioRead32 (GicDistributorBase + ARM_GIC_ICDDCR) & ARM_GIC_ICDDCR_ARE) {
|
||||
MmioOr32 (GicDistributorBase + ARM_GIC_ICDDCR, 0x2);
|
||||
} else {
|
||||
MmioOr32 (GicDistributorBase + ARM_GIC_ICDDCR, 0x1);
|
||||
}
|
||||
}
|
||||
}
|
464
ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Dxe.c
Normal file
464
ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Dxe.c
Normal file
@ -0,0 +1,464 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2009, Hewlett-Packard Company. All rights reserved.<BR>
|
||||
Portions copyright (c) 2010, Apple Inc. All rights reserved.<BR>
|
||||
Portions copyright (c) 2011-2017, ARM Ltd. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
Module Name:
|
||||
|
||||
GicV2/ArmGicV2Dxe.c
|
||||
|
||||
Abstract:
|
||||
|
||||
Driver implementing the GicV2 interrupt controller protocol
|
||||
|
||||
--*/
|
||||
|
||||
#include <Library/ArmGicLib.h>
|
||||
|
||||
#include "ArmGicDxe.h"
|
||||
|
||||
#define ARM_GIC_DEFAULT_PRIORITY 0x80
|
||||
|
||||
extern EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptV2Protocol;
|
||||
extern EFI_HARDWARE_INTERRUPT2_PROTOCOL gHardwareInterrupt2V2Protocol;
|
||||
|
||||
STATIC UINT32 mGicInterruptInterfaceBase;
|
||||
STATIC UINT32 mGicDistributorBase;
|
||||
|
||||
/**
|
||||
Enable interrupt source Source.
|
||||
|
||||
@param This Instance pointer for this protocol
|
||||
@param Source Hardware source of the interrupt
|
||||
|
||||
@retval EFI_SUCCESS Source interrupt enabled.
|
||||
@retval EFI_UNSUPPORTED Source interrupt is not supported
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV2EnableInterruptSource (
|
||||
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source
|
||||
)
|
||||
{
|
||||
if (Source >= mGicNumInterrupts) {
|
||||
ASSERT (FALSE);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
ArmGicEnableInterrupt (mGicDistributorBase, 0, Source);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Disable interrupt source Source.
|
||||
|
||||
@param This Instance pointer for this protocol
|
||||
@param Source Hardware source of the interrupt
|
||||
|
||||
@retval EFI_SUCCESS Source interrupt disabled.
|
||||
@retval EFI_UNSUPPORTED Source interrupt is not supported
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV2DisableInterruptSource (
|
||||
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source
|
||||
)
|
||||
{
|
||||
if (Source >= mGicNumInterrupts) {
|
||||
ASSERT (FALSE);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
ArmGicDisableInterrupt (mGicDistributorBase, 0, Source);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Return current state of interrupt source Source.
|
||||
|
||||
@param This Instance pointer for this protocol
|
||||
@param Source Hardware source of the interrupt
|
||||
@param InterruptState TRUE: source enabled, FALSE: source disabled.
|
||||
|
||||
@retval EFI_SUCCESS InterruptState is valid
|
||||
@retval EFI_UNSUPPORTED Source interrupt is not supported
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV2GetInterruptSourceState (
|
||||
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source,
|
||||
IN BOOLEAN *InterruptState
|
||||
)
|
||||
{
|
||||
if (Source >= mGicNumInterrupts) {
|
||||
ASSERT (FALSE);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
*InterruptState = ArmGicIsInterruptEnabled (mGicDistributorBase, 0, Source);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Signal to the hardware that the End Of Interrupt state
|
||||
has been reached.
|
||||
|
||||
@param This Instance pointer for this protocol
|
||||
@param Source Hardware source of the interrupt
|
||||
|
||||
@retval EFI_SUCCESS Source interrupt ended successfully.
|
||||
@retval EFI_UNSUPPORTED Source interrupt is not supported
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV2EndOfInterrupt (
|
||||
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source
|
||||
)
|
||||
{
|
||||
if (Source >= mGicNumInterrupts) {
|
||||
ASSERT (FALSE);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
ArmGicV2EndOfInterrupt (mGicInterruptInterfaceBase, Source);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs.
|
||||
|
||||
@param InterruptType Defines the type of interrupt or exception that
|
||||
occurred on the processor.This parameter is
|
||||
processor architecture specific.
|
||||
@param SystemContext A pointer to the processor context when
|
||||
the interrupt occurred on the processor.
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
EFIAPI
|
||||
GicV2IrqInterruptHandler (
|
||||
IN EFI_EXCEPTION_TYPE InterruptType,
|
||||
IN EFI_SYSTEM_CONTEXT SystemContext
|
||||
)
|
||||
{
|
||||
UINT32 GicInterrupt;
|
||||
HARDWARE_INTERRUPT_HANDLER InterruptHandler;
|
||||
|
||||
GicInterrupt = ArmGicV2AcknowledgeInterrupt (mGicInterruptInterfaceBase);
|
||||
|
||||
// Special Interrupts (ID1020-ID1023) have an Interrupt ID greater than the
|
||||
// number of interrupt (ie: Spurious interrupt).
|
||||
if ((GicInterrupt & ARM_GIC_ICCIAR_ACKINTID) >= mGicNumInterrupts) {
|
||||
// The special interrupts do not need to be acknowledged
|
||||
return;
|
||||
}
|
||||
|
||||
InterruptHandler = gRegisteredInterruptHandlers[GicInterrupt];
|
||||
if (InterruptHandler != NULL) {
|
||||
// Call the registered interrupt handler.
|
||||
InterruptHandler (GicInterrupt, SystemContext);
|
||||
} else {
|
||||
DEBUG ((DEBUG_ERROR, "Spurious GIC interrupt: 0x%x\n", GicInterrupt));
|
||||
GicV2EndOfInterrupt (&gHardwareInterruptV2Protocol, GicInterrupt);
|
||||
}
|
||||
}
|
||||
|
||||
// The protocol instance produced by this driver
|
||||
EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptV2Protocol = {
|
||||
RegisterInterruptSource,
|
||||
GicV2EnableInterruptSource,
|
||||
GicV2DisableInterruptSource,
|
||||
GicV2GetInterruptSourceState,
|
||||
GicV2EndOfInterrupt
|
||||
};
|
||||
|
||||
/**
|
||||
Get interrupt trigger type of an interrupt
|
||||
|
||||
@param This Instance pointer for this protocol
|
||||
@param Source Hardware source of the interrupt.
|
||||
@param TriggerType Returns interrupt trigger type.
|
||||
|
||||
@retval EFI_SUCCESS Source interrupt supported.
|
||||
@retval EFI_UNSUPPORTED Source interrupt is not supported.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV2GetTriggerType (
|
||||
IN EFI_HARDWARE_INTERRUPT2_PROTOCOL *This,
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source,
|
||||
OUT EFI_HARDWARE_INTERRUPT2_TRIGGER_TYPE *TriggerType
|
||||
)
|
||||
{
|
||||
UINTN RegAddress;
|
||||
UINTN Config1Bit;
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = GicGetDistributorIcfgBaseAndBit (
|
||||
Source,
|
||||
&RegAddress,
|
||||
&Config1Bit
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
if ((MmioRead32 (RegAddress) & (1 << Config1Bit)) == 0) {
|
||||
*TriggerType = EFI_HARDWARE_INTERRUPT2_TRIGGER_LEVEL_HIGH;
|
||||
} else {
|
||||
*TriggerType = EFI_HARDWARE_INTERRUPT2_TRIGGER_EDGE_RISING;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Set interrupt trigger type of an interrupt
|
||||
|
||||
@param This Instance pointer for this protocol
|
||||
@param Source Hardware source of the interrupt.
|
||||
@param TriggerType Interrupt trigger type.
|
||||
|
||||
@retval EFI_SUCCESS Source interrupt supported.
|
||||
@retval EFI_UNSUPPORTED Source interrupt is not supported.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV2SetTriggerType (
|
||||
IN EFI_HARDWARE_INTERRUPT2_PROTOCOL *This,
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source,
|
||||
IN EFI_HARDWARE_INTERRUPT2_TRIGGER_TYPE TriggerType
|
||||
)
|
||||
{
|
||||
UINTN RegAddress;
|
||||
UINTN Config1Bit;
|
||||
UINT32 Value;
|
||||
EFI_STATUS Status;
|
||||
BOOLEAN SourceEnabled;
|
||||
|
||||
if ( (TriggerType != EFI_HARDWARE_INTERRUPT2_TRIGGER_EDGE_RISING)
|
||||
&& (TriggerType != EFI_HARDWARE_INTERRUPT2_TRIGGER_LEVEL_HIGH))
|
||||
{
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"Invalid interrupt trigger type: %d\n", \
|
||||
TriggerType
|
||||
));
|
||||
ASSERT (FALSE);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Status = GicGetDistributorIcfgBaseAndBit (
|
||||
Source,
|
||||
&RegAddress,
|
||||
&Config1Bit
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = GicV2GetInterruptSourceState (
|
||||
(EFI_HARDWARE_INTERRUPT_PROTOCOL *)This,
|
||||
Source,
|
||||
&SourceEnabled
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Value = (TriggerType == EFI_HARDWARE_INTERRUPT2_TRIGGER_EDGE_RISING)
|
||||
? ARM_GIC_ICDICFR_EDGE_TRIGGERED
|
||||
: ARM_GIC_ICDICFR_LEVEL_TRIGGERED;
|
||||
|
||||
// Before changing the value, we must disable the interrupt,
|
||||
// otherwise GIC behavior is UNPREDICTABLE.
|
||||
if (SourceEnabled) {
|
||||
GicV2DisableInterruptSource (
|
||||
(EFI_HARDWARE_INTERRUPT_PROTOCOL *)This,
|
||||
Source
|
||||
);
|
||||
}
|
||||
|
||||
MmioAndThenOr32 (
|
||||
RegAddress,
|
||||
~(0x1 << Config1Bit),
|
||||
Value << Config1Bit
|
||||
);
|
||||
|
||||
// Restore interrupt state
|
||||
if (SourceEnabled) {
|
||||
GicV2EnableInterruptSource (
|
||||
(EFI_HARDWARE_INTERRUPT_PROTOCOL *)This,
|
||||
Source
|
||||
);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_HARDWARE_INTERRUPT2_PROTOCOL gHardwareInterrupt2V2Protocol = {
|
||||
(HARDWARE_INTERRUPT2_REGISTER)RegisterInterruptSource,
|
||||
(HARDWARE_INTERRUPT2_ENABLE)GicV2EnableInterruptSource,
|
||||
(HARDWARE_INTERRUPT2_DISABLE)GicV2DisableInterruptSource,
|
||||
(HARDWARE_INTERRUPT2_INTERRUPT_STATE)GicV2GetInterruptSourceState,
|
||||
(HARDWARE_INTERRUPT2_END_OF_INTERRUPT)GicV2EndOfInterrupt,
|
||||
GicV2GetTriggerType,
|
||||
GicV2SetTriggerType
|
||||
};
|
||||
|
||||
/**
|
||||
Shutdown our hardware
|
||||
|
||||
DXE Core will disable interrupts and turn off the timer and disable
|
||||
interrupts after all the event handlers have run.
|
||||
|
||||
@param[in] Event The Event that is being processed
|
||||
@param[in] Context Event Context
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
EFIAPI
|
||||
GicV2ExitBootServicesEvent (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
UINT32 GicInterrupt;
|
||||
|
||||
// Disable all the interrupts
|
||||
for (Index = 0; Index < mGicNumInterrupts; Index++) {
|
||||
GicV2DisableInterruptSource (&gHardwareInterruptV2Protocol, Index);
|
||||
}
|
||||
|
||||
// Acknowledge all pending interrupts
|
||||
do {
|
||||
GicInterrupt = ArmGicV2AcknowledgeInterrupt (mGicInterruptInterfaceBase);
|
||||
|
||||
if ((GicInterrupt & ARM_GIC_ICCIAR_ACKINTID) < mGicNumInterrupts) {
|
||||
GicV2EndOfInterrupt (&gHardwareInterruptV2Protocol, GicInterrupt);
|
||||
}
|
||||
} while (!ARM_GIC_IS_SPECIAL_INTERRUPTS (GicInterrupt));
|
||||
|
||||
// Disable Gic Interface
|
||||
ArmGicV2DisableInterruptInterface (mGicInterruptInterfaceBase);
|
||||
|
||||
// Disable Gic Distributor
|
||||
ArmGicDisableDistributor (mGicDistributorBase);
|
||||
}
|
||||
|
||||
/**
|
||||
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
|
||||
GicV2DxeInitialize (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN Index;
|
||||
UINT32 RegOffset;
|
||||
UINTN RegShift;
|
||||
UINT32 CpuTarget;
|
||||
|
||||
// Make sure the Interrupt Controller Protocol is not already installed in
|
||||
// the system.
|
||||
ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gHardwareInterruptProtocolGuid);
|
||||
|
||||
mGicInterruptInterfaceBase = PcdGet64 (PcdGicInterruptInterfaceBase);
|
||||
mGicDistributorBase = PcdGet64 (PcdGicDistributorBase);
|
||||
mGicNumInterrupts = ArmGicGetMaxNumInterrupts (mGicDistributorBase);
|
||||
|
||||
for (Index = 0; Index < mGicNumInterrupts; Index++) {
|
||||
GicV2DisableInterruptSource (&gHardwareInterruptV2Protocol, 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
|
||||
|
||||
// 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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Set binary point reg to 0x7 (no preemption)
|
||||
MmioWrite32 (mGicInterruptInterfaceBase + ARM_GIC_ICCBPR, 0x7);
|
||||
|
||||
// Set priority mask reg to 0xff to allow all priorities through
|
||||
MmioWrite32 (mGicInterruptInterfaceBase + ARM_GIC_ICCPMR, 0xff);
|
||||
|
||||
// Enable gic cpu interface
|
||||
ArmGicEnableInterruptInterface (mGicInterruptInterfaceBase);
|
||||
|
||||
// Enable gic distributor
|
||||
ArmGicEnableDistributor (mGicDistributorBase);
|
||||
|
||||
Status = InstallAndRegisterInterruptService (
|
||||
&gHardwareInterruptV2Protocol,
|
||||
&gHardwareInterrupt2V2Protocol,
|
||||
GicV2IrqInterruptHandler,
|
||||
GicV2ExitBootServicesEvent
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
30
ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Lib.c
Normal file
30
ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2Lib.c
Normal file
@ -0,0 +1,30 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2013-2014, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#include <Library/ArmGicLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmGicV2AcknowledgeInterrupt (
|
||||
IN UINTN GicInterruptInterfaceBase
|
||||
)
|
||||
{
|
||||
// Read the Interrupt Acknowledge Register
|
||||
return MmioRead32 (GicInterruptInterfaceBase + ARM_GIC_ICCIAR);
|
||||
}
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicV2EndOfInterrupt (
|
||||
IN UINTN GicInterruptInterfaceBase,
|
||||
IN UINTN Source
|
||||
)
|
||||
{
|
||||
MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCEIOR, Source);
|
||||
}
|
35
ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2NonSecLib.c
Normal file
35
ArmPkg/Drivers/ArmGic/GicV2/ArmGicV2NonSecLib.c
Normal file
@ -0,0 +1,35 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2011-2014, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#include <Uefi.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/ArmGicLib.h>
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicV2EnableInterruptInterface (
|
||||
IN INTN GicInterruptInterfaceBase
|
||||
)
|
||||
{
|
||||
/*
|
||||
* Enable the CPU interface in Non-Secure world
|
||||
* Note: The ICCICR register is banked when Security extensions are implemented
|
||||
*/
|
||||
MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR, 0x1);
|
||||
}
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicV2DisableInterruptInterface (
|
||||
IN INTN GicInterruptInterfaceBase
|
||||
)
|
||||
{
|
||||
// Disable Gic Interface
|
||||
MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCICR, 0x0);
|
||||
MmioWrite32 (GicInterruptInterfaceBase + ARM_GIC_ICCPMR, 0x0);
|
||||
}
|
106
ArmPkg/Drivers/ArmGic/GicV3/AArch64/ArmGicV3.S
Normal file
106
ArmPkg/Drivers/ArmGic/GicV3/AArch64/ArmGicV3.S
Normal file
@ -0,0 +1,106 @@
|
||||
#
|
||||
# Copyright (c) 2014, ARM Limited. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
#
|
||||
|
||||
#include <AsmMacroIoLibV8.h>
|
||||
|
||||
#if !defined(__clang__)
|
||||
|
||||
//
|
||||
// Clang versions before v3.6 do not support the GNU extension that allows
|
||||
// system registers outside of the IMPLEMENTATION DEFINED range to be specified
|
||||
// using the generic notation below. However, clang knows these registers by
|
||||
// their architectural names, so it has no need for these aliases anyway.
|
||||
//
|
||||
#define ICC_SRE_EL1 S3_0_C12_C12_5
|
||||
#define ICC_SRE_EL2 S3_4_C12_C9_5
|
||||
#define ICC_SRE_EL3 S3_6_C12_C12_5
|
||||
#define ICC_IGRPEN1_EL1 S3_0_C12_C12_7
|
||||
#define ICC_EOIR1_EL1 S3_0_C12_C12_1
|
||||
#define ICC_IAR1_EL1 S3_0_C12_C12_0
|
||||
#define ICC_PMR_EL1 S3_0_C4_C6_0
|
||||
#define ICC_BPR1_EL1 S3_0_C12_C12_3
|
||||
|
||||
#endif
|
||||
|
||||
//UINT32
|
||||
//EFIAPI
|
||||
//ArmGicV3GetControlSystemRegisterEnable (
|
||||
// VOID
|
||||
// );
|
||||
ASM_FUNC(ArmGicV3GetControlSystemRegisterEnable)
|
||||
EL1_OR_EL2_OR_EL3(x1)
|
||||
1: mrs x0, ICC_SRE_EL1
|
||||
b 4f
|
||||
2: mrs x0, ICC_SRE_EL2
|
||||
b 4f
|
||||
3: mrs x0, ICC_SRE_EL3
|
||||
4: ret
|
||||
|
||||
//VOID
|
||||
//EFIAPI
|
||||
//ArmGicV3SetControlSystemRegisterEnable (
|
||||
// IN UINT32 ControlSystemRegisterEnable
|
||||
// );
|
||||
ASM_FUNC(ArmGicV3SetControlSystemRegisterEnable)
|
||||
EL1_OR_EL2_OR_EL3(x1)
|
||||
1: msr ICC_SRE_EL1, x0
|
||||
b 4f
|
||||
2: msr ICC_SRE_EL2, x0
|
||||
b 4f
|
||||
3: msr ICC_SRE_EL3, x0
|
||||
4: isb
|
||||
ret
|
||||
|
||||
//VOID
|
||||
//ArmGicV3EnableInterruptInterface (
|
||||
// VOID
|
||||
// );
|
||||
ASM_FUNC(ArmGicV3EnableInterruptInterface)
|
||||
mov x0, #1
|
||||
msr ICC_IGRPEN1_EL1, x0
|
||||
ret
|
||||
|
||||
//VOID
|
||||
//ArmGicV3DisableInterruptInterface (
|
||||
// VOID
|
||||
// );
|
||||
ASM_FUNC(ArmGicV3DisableInterruptInterface)
|
||||
mov x0, #0
|
||||
msr ICC_IGRPEN1_EL1, x0
|
||||
ret
|
||||
|
||||
//VOID
|
||||
//ArmGicV3EndOfInterrupt (
|
||||
// IN UINTN InterruptId
|
||||
// );
|
||||
ASM_FUNC(ArmGicV3EndOfInterrupt)
|
||||
msr ICC_EOIR1_EL1, x0
|
||||
ret
|
||||
|
||||
//UINTN
|
||||
//ArmGicV3AcknowledgeInterrupt (
|
||||
// VOID
|
||||
// );
|
||||
ASM_FUNC(ArmGicV3AcknowledgeInterrupt)
|
||||
mrs x0, ICC_IAR1_EL1
|
||||
ret
|
||||
|
||||
//VOID
|
||||
//ArmGicV3SetPriorityMask (
|
||||
// IN UINTN Priority
|
||||
// );
|
||||
ASM_FUNC(ArmGicV3SetPriorityMask)
|
||||
msr ICC_PMR_EL1, x0
|
||||
ret
|
||||
|
||||
//VOID
|
||||
//ArmGicV3SetBinaryPointer (
|
||||
// IN UINTN BinaryPoint
|
||||
// );
|
||||
ASM_FUNC(ArmGicV3SetBinaryPointer)
|
||||
msr ICC_BPR1_EL1, x0
|
||||
ret
|
80
ArmPkg/Drivers/ArmGic/GicV3/Arm/ArmGicV3.S
Normal file
80
ArmPkg/Drivers/ArmGic/GicV3/Arm/ArmGicV3.S
Normal file
@ -0,0 +1,80 @@
|
||||
#
|
||||
# Copyright (c) 2014, ARM Limited. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
#
|
||||
|
||||
#include <AsmMacroIoLib.h>
|
||||
#include <Library/ArmLib.h>
|
||||
|
||||
// For the moment we assume this will run in SVC mode on ARMv7
|
||||
|
||||
//UINT32
|
||||
//EFIAPI
|
||||
//ArmGicGetControlSystemRegisterEnable (
|
||||
// VOID
|
||||
// );
|
||||
ASM_FUNC(ArmGicV3GetControlSystemRegisterEnable)
|
||||
mrc p15, 0, r0, c12, c12, 5 // ICC_SRE
|
||||
bx lr
|
||||
|
||||
//VOID
|
||||
//EFIAPI
|
||||
//ArmGicSetControlSystemRegisterEnable (
|
||||
// IN UINT32 ControlSystemRegisterEnable
|
||||
// );
|
||||
ASM_FUNC(ArmGicV3SetControlSystemRegisterEnable)
|
||||
mcr p15, 0, r0, c12, c12, 5 // ICC_SRE
|
||||
isb
|
||||
bx lr
|
||||
|
||||
//VOID
|
||||
//ArmGicV3EnableInterruptInterface (
|
||||
// VOID
|
||||
// );
|
||||
ASM_FUNC(ArmGicV3EnableInterruptInterface)
|
||||
mov r0, #1
|
||||
mcr p15, 0, r0, c12, c12, 7 // ICC_IGRPEN1
|
||||
bx lr
|
||||
|
||||
//VOID
|
||||
//ArmGicV3DisableInterruptInterface (
|
||||
// VOID
|
||||
// );
|
||||
ASM_FUNC(ArmGicV3DisableInterruptInterface)
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c12, c12, 7 // ICC_IGRPEN1
|
||||
bx lr
|
||||
|
||||
//VOID
|
||||
//ArmGicV3EndOfInterrupt (
|
||||
// IN UINTN InterruptId
|
||||
// );
|
||||
ASM_FUNC(ArmGicV3EndOfInterrupt)
|
||||
mcr p15, 0, r0, c12, c12, 1 //ICC_EOIR1
|
||||
bx lr
|
||||
|
||||
//UINTN
|
||||
//ArmGicV3AcknowledgeInterrupt (
|
||||
// VOID
|
||||
// );
|
||||
ASM_FUNC(ArmGicV3AcknowledgeInterrupt)
|
||||
mrc p15, 0, r0, c12, c12, 0 //ICC_IAR1
|
||||
bx lr
|
||||
|
||||
//VOID
|
||||
//ArmGicV3SetPriorityMask (
|
||||
// IN UINTN Priority
|
||||
// );
|
||||
ASM_FUNC(ArmGicV3SetPriorityMask)
|
||||
mcr p15, 0, r0, c4, c6, 0 //ICC_PMR
|
||||
bx lr
|
||||
|
||||
//VOID
|
||||
//ArmGicV3SetBinaryPointer (
|
||||
// IN UINTN BinaryPoint
|
||||
// );
|
||||
ASM_FUNC(ArmGicV3SetBinaryPointer)
|
||||
mcr p15, 0, r0, c12, c12, 3 //ICC_BPR1
|
||||
bx lr
|
488
ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Dxe.c
Normal file
488
ArmPkg/Drivers/ArmGic/GicV3/ArmGicV3Dxe.c
Normal file
@ -0,0 +1,488 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2011-2018, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#include <Library/ArmGicLib.h>
|
||||
|
||||
#include "ArmGicDxe.h"
|
||||
|
||||
#define ARM_GIC_DEFAULT_PRIORITY 0x80
|
||||
|
||||
extern EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptV3Protocol;
|
||||
extern EFI_HARDWARE_INTERRUPT2_PROTOCOL gHardwareInterrupt2V3Protocol;
|
||||
|
||||
STATIC UINTN mGicDistributorBase;
|
||||
STATIC UINTN mGicRedistributorsBase;
|
||||
|
||||
/**
|
||||
Enable interrupt source Source.
|
||||
|
||||
@param This Instance pointer for this protocol
|
||||
@param Source Hardware source of the interrupt
|
||||
|
||||
@retval EFI_SUCCESS Source interrupt enabled.
|
||||
@retval EFI_DEVICE_ERROR Hardware could not be programmed.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV3EnableInterruptSource (
|
||||
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source
|
||||
)
|
||||
{
|
||||
if (Source >= mGicNumInterrupts) {
|
||||
ASSERT (FALSE);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
ArmGicEnableInterrupt (mGicDistributorBase, mGicRedistributorsBase, Source);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Disable interrupt source Source.
|
||||
|
||||
@param This Instance pointer for this protocol
|
||||
@param Source Hardware source of the interrupt
|
||||
|
||||
@retval EFI_SUCCESS Source interrupt disabled.
|
||||
@retval EFI_DEVICE_ERROR Hardware could not be programmed.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV3DisableInterruptSource (
|
||||
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source
|
||||
)
|
||||
{
|
||||
if (Source >= mGicNumInterrupts) {
|
||||
ASSERT (FALSE);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
ArmGicDisableInterrupt (mGicDistributorBase, mGicRedistributorsBase, Source);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Return current state of interrupt source Source.
|
||||
|
||||
@param This Instance pointer for this protocol
|
||||
@param Source Hardware source of the interrupt
|
||||
@param InterruptState TRUE: source enabled, FALSE: source disabled.
|
||||
|
||||
@retval EFI_SUCCESS InterruptState is valid
|
||||
@retval EFI_DEVICE_ERROR InterruptState is not valid
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV3GetInterruptSourceState (
|
||||
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source,
|
||||
IN BOOLEAN *InterruptState
|
||||
)
|
||||
{
|
||||
if (Source >= mGicNumInterrupts) {
|
||||
ASSERT (FALSE);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
*InterruptState = ArmGicIsInterruptEnabled (
|
||||
mGicDistributorBase,
|
||||
mGicRedistributorsBase,
|
||||
Source
|
||||
);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Signal to the hardware that the End Of Interrupt state
|
||||
has been reached.
|
||||
|
||||
@param This Instance pointer for this protocol
|
||||
@param Source Hardware source of the interrupt
|
||||
|
||||
@retval EFI_SUCCESS Source interrupt ended successfully.
|
||||
@retval EFI_DEVICE_ERROR Hardware could not be programmed.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV3EndOfInterrupt (
|
||||
IN EFI_HARDWARE_INTERRUPT_PROTOCOL *This,
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source
|
||||
)
|
||||
{
|
||||
if (Source >= mGicNumInterrupts) {
|
||||
ASSERT (FALSE);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
ArmGicV3EndOfInterrupt (Source);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs.
|
||||
|
||||
@param InterruptType Defines the type of interrupt or exception that
|
||||
occurred on the processor. This parameter is
|
||||
processor architecture specific.
|
||||
@param SystemContext A pointer to the processor context when
|
||||
the interrupt occurred on the processor.
|
||||
|
||||
@return None
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
EFIAPI
|
||||
GicV3IrqInterruptHandler (
|
||||
IN EFI_EXCEPTION_TYPE InterruptType,
|
||||
IN EFI_SYSTEM_CONTEXT SystemContext
|
||||
)
|
||||
{
|
||||
UINT32 GicInterrupt;
|
||||
HARDWARE_INTERRUPT_HANDLER InterruptHandler;
|
||||
|
||||
GicInterrupt = ArmGicV3AcknowledgeInterrupt ();
|
||||
|
||||
// Special Interrupts (ID1020-ID1023) have an Interrupt ID greater than the
|
||||
// number of interrupt (ie: Spurious interrupt).
|
||||
if ((GicInterrupt & ARM_GIC_ICCIAR_ACKINTID) >= mGicNumInterrupts) {
|
||||
// The special interrupt do not need to be acknowledge
|
||||
return;
|
||||
}
|
||||
|
||||
InterruptHandler = gRegisteredInterruptHandlers[GicInterrupt];
|
||||
if (InterruptHandler != NULL) {
|
||||
// Call the registered interrupt handler.
|
||||
InterruptHandler (GicInterrupt, SystemContext);
|
||||
} else {
|
||||
DEBUG ((DEBUG_ERROR, "Spurious GIC interrupt: 0x%x\n", GicInterrupt));
|
||||
GicV3EndOfInterrupt (&gHardwareInterruptV3Protocol, GicInterrupt);
|
||||
}
|
||||
}
|
||||
|
||||
// The protocol instance produced by this driver
|
||||
EFI_HARDWARE_INTERRUPT_PROTOCOL gHardwareInterruptV3Protocol = {
|
||||
RegisterInterruptSource,
|
||||
GicV3EnableInterruptSource,
|
||||
GicV3DisableInterruptSource,
|
||||
GicV3GetInterruptSourceState,
|
||||
GicV3EndOfInterrupt
|
||||
};
|
||||
|
||||
/**
|
||||
Get interrupt trigger type of an interrupt
|
||||
|
||||
@param This Instance pointer for this protocol
|
||||
@param Source Hardware source of the interrupt.
|
||||
@param TriggerType Returns interrupt trigger type.
|
||||
|
||||
@retval EFI_SUCCESS Source interrupt supported.
|
||||
@retval EFI_UNSUPPORTED Source interrupt is not supported.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV3GetTriggerType (
|
||||
IN EFI_HARDWARE_INTERRUPT2_PROTOCOL *This,
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source,
|
||||
OUT EFI_HARDWARE_INTERRUPT2_TRIGGER_TYPE *TriggerType
|
||||
)
|
||||
{
|
||||
UINTN RegAddress;
|
||||
UINTN Config1Bit;
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = GicGetDistributorIcfgBaseAndBit (
|
||||
Source,
|
||||
&RegAddress,
|
||||
&Config1Bit
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
if ((MmioRead32 (RegAddress) & (1 << Config1Bit)) == 0) {
|
||||
*TriggerType = EFI_HARDWARE_INTERRUPT2_TRIGGER_LEVEL_HIGH;
|
||||
} else {
|
||||
*TriggerType = EFI_HARDWARE_INTERRUPT2_TRIGGER_EDGE_RISING;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Set interrupt trigger type of an interrupt
|
||||
|
||||
@param This Instance pointer for this protocol
|
||||
@param Source Hardware source of the interrupt.
|
||||
@param TriggerType Interrupt trigger type.
|
||||
|
||||
@retval EFI_SUCCESS Source interrupt supported.
|
||||
@retval EFI_UNSUPPORTED Source interrupt is not supported.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GicV3SetTriggerType (
|
||||
IN EFI_HARDWARE_INTERRUPT2_PROTOCOL *This,
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source,
|
||||
IN EFI_HARDWARE_INTERRUPT2_TRIGGER_TYPE TriggerType
|
||||
)
|
||||
{
|
||||
UINTN RegAddress;
|
||||
UINTN Config1Bit;
|
||||
UINT32 Value;
|
||||
EFI_STATUS Status;
|
||||
BOOLEAN SourceEnabled;
|
||||
|
||||
if ( (TriggerType != EFI_HARDWARE_INTERRUPT2_TRIGGER_EDGE_RISING)
|
||||
&& (TriggerType != EFI_HARDWARE_INTERRUPT2_TRIGGER_LEVEL_HIGH))
|
||||
{
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"Invalid interrupt trigger type: %d\n", \
|
||||
TriggerType
|
||||
));
|
||||
ASSERT (FALSE);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Status = GicGetDistributorIcfgBaseAndBit (
|
||||
Source,
|
||||
&RegAddress,
|
||||
&Config1Bit
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = GicV3GetInterruptSourceState (
|
||||
(EFI_HARDWARE_INTERRUPT_PROTOCOL *)This,
|
||||
Source,
|
||||
&SourceEnabled
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Value = (TriggerType == EFI_HARDWARE_INTERRUPT2_TRIGGER_EDGE_RISING)
|
||||
? ARM_GIC_ICDICFR_EDGE_TRIGGERED
|
||||
: ARM_GIC_ICDICFR_LEVEL_TRIGGERED;
|
||||
|
||||
// Before changing the value, we must disable the interrupt,
|
||||
// otherwise GIC behavior is UNPREDICTABLE.
|
||||
if (SourceEnabled) {
|
||||
GicV3DisableInterruptSource (
|
||||
(EFI_HARDWARE_INTERRUPT_PROTOCOL *)This,
|
||||
Source
|
||||
);
|
||||
}
|
||||
|
||||
MmioAndThenOr32 (
|
||||
RegAddress,
|
||||
~(0x1 << Config1Bit),
|
||||
Value << Config1Bit
|
||||
);
|
||||
// Restore interrupt state
|
||||
if (SourceEnabled) {
|
||||
GicV3EnableInterruptSource (
|
||||
(EFI_HARDWARE_INTERRUPT_PROTOCOL *)This,
|
||||
Source
|
||||
);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_HARDWARE_INTERRUPT2_PROTOCOL gHardwareInterrupt2V3Protocol = {
|
||||
(HARDWARE_INTERRUPT2_REGISTER)RegisterInterruptSource,
|
||||
(HARDWARE_INTERRUPT2_ENABLE)GicV3EnableInterruptSource,
|
||||
(HARDWARE_INTERRUPT2_DISABLE)GicV3DisableInterruptSource,
|
||||
(HARDWARE_INTERRUPT2_INTERRUPT_STATE)GicV3GetInterruptSourceState,
|
||||
(HARDWARE_INTERRUPT2_END_OF_INTERRUPT)GicV3EndOfInterrupt,
|
||||
GicV3GetTriggerType,
|
||||
GicV3SetTriggerType
|
||||
};
|
||||
|
||||
/**
|
||||
Shutdown our hardware
|
||||
|
||||
DXE Core will disable interrupts and turn off the timer and disable interrupts
|
||||
after all the event handlers have run.
|
||||
|
||||
@param[in] Event The Event that is being processed
|
||||
@param[in] Context Event Context
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
GicV3ExitBootServicesEvent (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
|
||||
// Acknowledge all pending interrupts
|
||||
for (Index = 0; Index < mGicNumInterrupts; Index++) {
|
||||
GicV3DisableInterruptSource (&gHardwareInterruptV3Protocol, Index);
|
||||
}
|
||||
|
||||
// Disable Gic Interface
|
||||
ArmGicV3DisableInterruptInterface ();
|
||||
|
||||
// Disable Gic Distributor
|
||||
ArmGicDisableDistributor (mGicDistributorBase);
|
||||
}
|
||||
|
||||
/**
|
||||
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;
|
||||
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
|
||||
ArmGicSetInterruptPriority (
|
||||
mGicDistributorBase,
|
||||
mGicRedistributorsBase,
|
||||
Index,
|
||||
ARM_GIC_DEFAULT_PRIORITY
|
||||
);
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
556
ArmPkg/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.c
Normal file
556
ArmPkg/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.c
Normal file
@ -0,0 +1,556 @@
|
||||
/** @file
|
||||
Produces the CPU I/O 2 Protocol.
|
||||
|
||||
Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Protocol/CpuIo2.h>
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
|
||||
#define MAX_IO_PORT_ADDRESS 0xFFFF
|
||||
|
||||
//
|
||||
// Handle for the CPU I/O 2 Protocol
|
||||
//
|
||||
STATIC EFI_HANDLE mHandle = NULL;
|
||||
|
||||
//
|
||||
// Lookup table for increment values based on transfer widths
|
||||
//
|
||||
STATIC CONST UINT8 mInStride[] = {
|
||||
1, // EfiCpuIoWidthUint8
|
||||
2, // EfiCpuIoWidthUint16
|
||||
4, // EfiCpuIoWidthUint32
|
||||
8, // EfiCpuIoWidthUint64
|
||||
0, // EfiCpuIoWidthFifoUint8
|
||||
0, // EfiCpuIoWidthFifoUint16
|
||||
0, // EfiCpuIoWidthFifoUint32
|
||||
0, // EfiCpuIoWidthFifoUint64
|
||||
1, // EfiCpuIoWidthFillUint8
|
||||
2, // EfiCpuIoWidthFillUint16
|
||||
4, // EfiCpuIoWidthFillUint32
|
||||
8 // EfiCpuIoWidthFillUint64
|
||||
};
|
||||
|
||||
//
|
||||
// Lookup table for increment values based on transfer widths
|
||||
//
|
||||
STATIC CONST UINT8 mOutStride[] = {
|
||||
1, // EfiCpuIoWidthUint8
|
||||
2, // EfiCpuIoWidthUint16
|
||||
4, // EfiCpuIoWidthUint32
|
||||
8, // EfiCpuIoWidthUint64
|
||||
1, // EfiCpuIoWidthFifoUint8
|
||||
2, // EfiCpuIoWidthFifoUint16
|
||||
4, // EfiCpuIoWidthFifoUint32
|
||||
8, // EfiCpuIoWidthFifoUint64
|
||||
0, // EfiCpuIoWidthFillUint8
|
||||
0, // EfiCpuIoWidthFillUint16
|
||||
0, // EfiCpuIoWidthFillUint32
|
||||
0 // EfiCpuIoWidthFillUint64
|
||||
};
|
||||
|
||||
/**
|
||||
Check parameters to a CPU I/O 2 Protocol service request.
|
||||
|
||||
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.
|
||||
|
||||
@param[in] MmioOperation TRUE for an MMIO operation, FALSE for I/O Port operation.
|
||||
@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 parameters for this request pass the checks.
|
||||
@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
|
||||
CpuIoCheckParameter (
|
||||
IN BOOLEAN MmioOperation,
|
||||
IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
|
||||
IN UINT64 Address,
|
||||
IN UINTN Count,
|
||||
IN VOID *Buffer
|
||||
)
|
||||
{
|
||||
UINT64 MaxCount;
|
||||
UINT64 Limit;
|
||||
|
||||
//
|
||||
// Check to see if Buffer is NULL
|
||||
//
|
||||
if (Buffer == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Check to see if Width is in the valid range
|
||||
//
|
||||
if ((UINT32)Width >= EfiCpuIoWidthMaximum) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// For FIFO type, the target address won't increase during the access,
|
||||
// so treat Count as 1
|
||||
//
|
||||
if ((Width >= EfiCpuIoWidthFifoUint8) && (Width <= EfiCpuIoWidthFifoUint64)) {
|
||||
Count = 1;
|
||||
}
|
||||
|
||||
//
|
||||
// Check to see if Width is in the valid range for I/O Port operations
|
||||
//
|
||||
Width = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);
|
||||
if (!MmioOperation && (Width == EfiCpuIoWidthUint64)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Check to see if Address is aligned
|
||||
//
|
||||
if ((Address & (UINT64)(mInStride[Width] - 1)) != 0) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Check to see if any address associated with this transfer exceeds the maximum
|
||||
// allowed address. The maximum address implied by the parameters passed in is
|
||||
// Address + Size * Count. If the following condition is met, then the transfer
|
||||
// is not supported.
|
||||
//
|
||||
// Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1
|
||||
//
|
||||
// Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count
|
||||
// can also be the maximum integer value supported by the CPU, this range
|
||||
// check must be adjusted to avoid all overflow conditions.
|
||||
//
|
||||
// The following form of the range check is equivalent but assumes that
|
||||
// MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1).
|
||||
//
|
||||
Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS);
|
||||
if (Count == 0) {
|
||||
if (Address > Limit) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
} else {
|
||||
MaxCount = RShiftU64 (Limit, Width);
|
||||
if (MaxCount < (Count - 1)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Check to see if Buffer is aligned
|
||||
//
|
||||
if (((UINTN)Buffer & ((MIN (sizeof (UINTN), mInStride[Width]) - 1))) != 0) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Reads 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[out] 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
|
||||
CpuMemoryServiceRead (
|
||||
IN EFI_CPU_IO2_PROTOCOL *This,
|
||||
IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
|
||||
IN UINT64 Address,
|
||||
IN UINTN Count,
|
||||
OUT 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) {
|
||||
*Uint8Buffer = MmioRead8 ((UINTN)Address);
|
||||
} else if (OperationWidth == EfiCpuIoWidthUint16) {
|
||||
*((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
|
||||
} else if (OperationWidth == EfiCpuIoWidthUint32) {
|
||||
*((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
|
||||
} else if (OperationWidth == EfiCpuIoWidthUint64) {
|
||||
*((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
Reads I/O 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[out] 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
|
||||
CpuIoServiceRead (
|
||||
IN EFI_CPU_IO2_PROTOCOL *This,
|
||||
IN EFI_CPU_IO_PROTOCOL_WIDTH Width,
|
||||
IN UINT64 Address,
|
||||
IN UINTN Count,
|
||||
OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT8 InStride;
|
||||
UINT8 OutStride;
|
||||
EFI_CPU_IO_PROTOCOL_WIDTH OperationWidth;
|
||||
UINT8 *Uint8Buffer;
|
||||
|
||||
Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Address += PcdGet64 (PcdPciIoTranslation);
|
||||
|
||||
//
|
||||
// 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) {
|
||||
*Uint8Buffer = MmioRead8 ((UINTN)Address);
|
||||
} else if (OperationWidth == EfiCpuIoWidthUint16) {
|
||||
*((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
|
||||
} else if (OperationWidth == EfiCpuIoWidthUint32) {
|
||||
*((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Write I/O 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
|
||||
CpuIoServiceWrite (
|
||||
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;
|
||||
|
||||
//
|
||||
// Make sure the parameters are valid
|
||||
//
|
||||
Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Address += PcdGet64 (PcdPciIoTranslation);
|
||||
|
||||
//
|
||||
// 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 = (UINT8 *)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));
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// CPU I/O 2 Protocol instance
|
||||
//
|
||||
STATIC EFI_CPU_IO2_PROTOCOL mCpuIo2 = {
|
||||
{
|
||||
CpuMemoryServiceRead,
|
||||
CpuMemoryServiceWrite
|
||||
},
|
||||
{
|
||||
CpuIoServiceRead,
|
||||
CpuIoServiceWrite
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
The user Entry Point for module CpuIo2Dxe. The user code starts with this function.
|
||||
|
||||
@param[in] ImageHandle The firmware allocated handle for the EFI image.
|
||||
@param[in] SystemTable A pointer to the EFI System Table.
|
||||
|
||||
@retval EFI_SUCCESS The entry point is executed successfully.
|
||||
@retval other Some error occurs when executing this entry point.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArmPciCpuIo2Initialize (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiCpuIo2ProtocolGuid);
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&mHandle,
|
||||
&gEfiCpuIo2ProtocolGuid,
|
||||
&mCpuIo2,
|
||||
NULL
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
return Status;
|
||||
}
|
47
ArmPkg/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf
Normal file
47
ArmPkg/Drivers/ArmPciCpuIo2Dxe/ArmPciCpuIo2Dxe.inf
Normal file
@ -0,0 +1,47 @@
|
||||
## @file
|
||||
# Produces the CPU I/O 2 Protocol by using the services of the I/O Library.
|
||||
#
|
||||
# Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = ArmPciCpuIo2Dxe
|
||||
FILE_GUID = 168D1A6E-F4A5-448A-9E95-795661BB3067
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = ArmPciCpuIo2Initialize
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = ARM AARCH64
|
||||
#
|
||||
|
||||
[Sources]
|
||||
ArmPciCpuIo2Dxe.c
|
||||
|
||||
[Packages]
|
||||
ArmPkg/ArmPkg.dec
|
||||
MdePkg/MdePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
UefiDriverEntryPoint
|
||||
BaseLib
|
||||
DebugLib
|
||||
IoLib
|
||||
PcdLib
|
||||
UefiBootServicesTableLib
|
||||
|
||||
[Pcd]
|
||||
gEfiMdePkgTokenSpaceGuid.PcdPciIoTranslation
|
||||
|
||||
[Protocols]
|
||||
gEfiCpuIo2ProtocolGuid ## PRODUCES
|
||||
|
||||
[Depex]
|
||||
TRUE
|
40
ArmPkg/Drivers/ArmScmiDxe/ArmScmiBaseProtocolPrivate.h
Normal file
40
ArmPkg/Drivers/ArmScmiDxe/ArmScmiBaseProtocolPrivate.h
Normal file
@ -0,0 +1,40 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2017-2018, Arm Limited. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
System Control and Management Interface V1.0
|
||||
http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/
|
||||
DEN0056A_System_Control_and_Management_Interface.pdf
|
||||
**/
|
||||
|
||||
#ifndef ARM_SCMI_BASE_PROTOCOL_PRIVATE_H_
|
||||
#define ARM_SCMI_BASE_PROTOCOL_PRIVATE_H_
|
||||
|
||||
// Return values of BASE_DISCOVER_LIST_PROTOCOLS command.
|
||||
typedef struct {
|
||||
UINT32 NumProtocols;
|
||||
|
||||
// Array of four protocols in each element
|
||||
// Total elements = 1 + (NumProtocols-1)/4
|
||||
|
||||
// NOTE: Since EDK2 does not allow flexible array member [] we declare
|
||||
// here array of 1 element length. However below is used as a variable
|
||||
// length array.
|
||||
UINT8 Protocols[1];
|
||||
} BASE_DISCOVER_LIST;
|
||||
|
||||
/** Initialize Base protocol and install protocol on a given handle.
|
||||
|
||||
@param[in] Handle Handle to install Base protocol.
|
||||
|
||||
@retval EFI_SUCCESS Base protocol interface installed
|
||||
successfully.
|
||||
**/
|
||||
EFI_STATUS
|
||||
ScmiBaseProtocolInit (
|
||||
IN OUT EFI_HANDLE *Handle
|
||||
);
|
||||
|
||||
#endif /* ARM_SCMI_BASE_PROTOCOL_PRIVATE_H_ */
|
84
ArmPkg/Drivers/ArmScmiDxe/ArmScmiClockProtocolPrivate.h
Normal file
84
ArmPkg/Drivers/ArmScmiDxe/ArmScmiClockProtocolPrivate.h
Normal file
@ -0,0 +1,84 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2017-2018, Arm Limited. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
System Control and Management Interface V1.0
|
||||
http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/
|
||||
DEN0056A_System_Control_and_Management_Interface.pdf
|
||||
**/
|
||||
|
||||
#ifndef ARM_SCMI_CLOCK_PROTOCOL_PRIVATE_H_
|
||||
#define ARM_SCMI_CLOCK_PROTOCOL_PRIVATE_H_
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
// Clock rate in two 32bit words.
|
||||
typedef struct {
|
||||
UINT32 Low;
|
||||
UINT32 High;
|
||||
} CLOCK_RATE_DWORD;
|
||||
|
||||
// Format of the returned rate array. Linear or Non-linear,.RatesFlag Bit[12]
|
||||
#define RATE_FORMAT_SHIFT 12
|
||||
#define RATE_FORMAT_MASK 0x0001
|
||||
#define RATE_FORMAT(RatesFlags) ((RatesFlags >> RATE_FORMAT_SHIFT) \
|
||||
& RATE_FORMAT_MASK)
|
||||
|
||||
// Number of remaining rates after a call to the SCP, RatesFlag Bits[31:16]
|
||||
#define NUM_REMAIN_RATES_SHIFT 16
|
||||
#define NUM_REMAIN_RATES(RatesFlags) ((RatesFlags >> NUM_REMAIN_RATES_SHIFT))
|
||||
|
||||
// Number of rates that are returned by a call.to the SCP, RatesFlag Bits[11:0]
|
||||
#define NUM_RATES_MASK 0x0FFF
|
||||
#define NUM_RATES(RatesFlags) (RatesFlags & NUM_RATES_MASK)
|
||||
|
||||
// Return values for the CLOCK_DESCRIBER_RATE command.
|
||||
typedef struct {
|
||||
UINT32 NumRatesFlags;
|
||||
|
||||
// NOTE: Since EDK2 does not allow flexible array member [] we declare
|
||||
// here array of 1 element length. However below is used as a variable
|
||||
// length array.
|
||||
CLOCK_RATE_DWORD Rates[1];
|
||||
} CLOCK_DESCRIBE_RATES;
|
||||
|
||||
#define CLOCK_SET_DEFAULT_FLAGS 0
|
||||
|
||||
// Message parameters for CLOCK_RATE_SET command.
|
||||
typedef struct {
|
||||
UINT32 Flags;
|
||||
UINT32 ClockId;
|
||||
CLOCK_RATE_DWORD Rate;
|
||||
} CLOCK_RATE_SET_ATTRIBUTES;
|
||||
|
||||
// Message parameters for CLOCK_CONFIG_SET command.
|
||||
typedef struct {
|
||||
UINT32 ClockId;
|
||||
UINT32 Attributes;
|
||||
} CLOCK_CONFIG_SET_ATTRIBUTES;
|
||||
|
||||
// if ClockAttr Bit[0] is set then clock device is enabled.
|
||||
#define CLOCK_ENABLE_MASK 0x1
|
||||
#define CLOCK_ENABLED(ClockAttr) ((ClockAttr & CLOCK_ENABLE_MASK) == 1)
|
||||
|
||||
typedef struct {
|
||||
UINT32 Attributes;
|
||||
UINT8 ClockName[SCMI_MAX_STR_LEN];
|
||||
} CLOCK_ATTRIBUTES;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
/** Initialize clock management protocol and install protocol on a given handle.
|
||||
|
||||
@param[in] Handle Handle to install clock management protocol.
|
||||
|
||||
@retval EFI_SUCCESS Clock protocol interface installed successfully.
|
||||
**/
|
||||
EFI_STATUS
|
||||
ScmiClockProtocolInit (
|
||||
IN EFI_HANDLE *Handle
|
||||
);
|
||||
|
||||
#endif /* ARM_SCMI_CLOCK_PROTOCOL_PRIVATE_H_ */
|
53
ArmPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf
Normal file
53
ArmPkg/Drivers/ArmScmiDxe/ArmScmiDxe.inf
Normal file
@ -0,0 +1,53 @@
|
||||
#/** @file
|
||||
#
|
||||
# Copyright (c) 2017-2021, Arm Limited. All rights reserved.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
# System Control and Management Interface V1.0
|
||||
# http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/
|
||||
# DEN0056A_System_Control_and_Management_Interface.pdf
|
||||
#**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010019
|
||||
BASE_NAME = ArmScmiDxe
|
||||
FILE_GUID = 9585984C-F027-45E9-AFDF-ADAA6DFAAAC7
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = ArmScmiDxeEntryPoint
|
||||
|
||||
[Sources.common]
|
||||
ArmScmiBaseProtocolPrivate.h
|
||||
ArmScmiClockProtocolPrivate.h
|
||||
ArmScmiPerformanceProtocolPrivate.h
|
||||
ScmiBaseProtocol.c
|
||||
Scmi.c
|
||||
ScmiClockProtocol.c
|
||||
ScmiDxe.c
|
||||
ScmiDxe.h
|
||||
ScmiPerformanceProtocol.c
|
||||
ScmiPrivate.h
|
||||
|
||||
[Packages]
|
||||
ArmPkg/ArmPkg.dec
|
||||
ArmPlatformPkg/ArmPlatformPkg.dec
|
||||
MdePkg/MdePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
ArmLib
|
||||
ArmMtlLib
|
||||
DebugLib
|
||||
IoLib
|
||||
UefiBootServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
|
||||
[Protocols]
|
||||
gArmScmiBaseProtocolGuid
|
||||
gArmScmiClockProtocolGuid
|
||||
gArmScmiClock2ProtocolGuid
|
||||
gArmScmiPerformanceProtocolGuid
|
||||
|
||||
[Depex]
|
||||
TRUE
|
||||
|
@ -0,0 +1,49 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2017-2021, Arm Limited. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
System Control and Management Interface V1.0
|
||||
http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/
|
||||
DEN0056A_System_Control_and_Management_Interface.pdf
|
||||
**/
|
||||
|
||||
#ifndef ARM_SCMI_PERFORMANCE_PROTOCOL_PRIVATE_H_
|
||||
#define ARM_SCMI_PERFORMANCE_PROTOCOL_PRIVATE_H_
|
||||
|
||||
#include <Protocol/ArmScmiPerformanceProtocol.h>
|
||||
|
||||
// Number of performance levels returned by a call to the SCP, Lvls Bits[11:0]
|
||||
#define NUM_PERF_LEVELS_MASK 0x0FFF
|
||||
#define NUM_PERF_LEVELS(Lvls) (Lvls & NUM_PERF_LEVELS_MASK)
|
||||
|
||||
// Number of performance levels remaining after a call to the SCP, Lvls Bits[31:16]
|
||||
#define NUM_REMAIN_PERF_LEVELS_SHIFT 16
|
||||
#define NUM_REMAIN_PERF_LEVELS(Lvls) (Lvls >> NUM_REMAIN_PERF_LEVELS_SHIFT)
|
||||
|
||||
/** Return values for ScmiMessageIdPerformanceDescribeLevels command.
|
||||
SCMI Spec section 4.5.2.5
|
||||
**/
|
||||
typedef struct {
|
||||
UINT32 NumLevels;
|
||||
|
||||
// NOTE: Since EDK2 does not allow flexible array member [] we declare
|
||||
// here array of 1 element length. However below is used as a variable
|
||||
// length array.
|
||||
SCMI_PERFORMANCE_LEVEL PerfLevel[1]; // Offset to array of performance levels
|
||||
} PERF_DESCRIBE_LEVELS;
|
||||
|
||||
/** Initialize performance management protocol and install on a given Handle.
|
||||
|
||||
@param[in] Handle Handle to install performance management
|
||||
protocol.
|
||||
|
||||
@retval EFI_SUCCESS Performance protocol installed successfully.
|
||||
**/
|
||||
EFI_STATUS
|
||||
ScmiPerformanceProtocolInit (
|
||||
IN EFI_HANDLE *Handle
|
||||
);
|
||||
|
||||
#endif /* ARM_SCMI_PERFORMANCE_PROTOCOL_PRIVATE_H_ */
|
254
ArmPkg/Drivers/ArmScmiDxe/Scmi.c
Normal file
254
ArmPkg/Drivers/ArmScmiDxe/Scmi.c
Normal file
@ -0,0 +1,254 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2017-2021, Arm Limited. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
System Control and Management Interface V1.0
|
||||
http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/
|
||||
DEN0056A_System_Control_and_Management_Interface.pdf
|
||||
**/
|
||||
|
||||
#include <Library/ArmMtlLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
|
||||
#include "ScmiPrivate.h"
|
||||
|
||||
// Arbitrary timeout value 20ms.
|
||||
#define RESPONSE_TIMEOUT 20000
|
||||
|
||||
/** Return a pointer to the message payload.
|
||||
|
||||
@param[out] Payload Holds pointer to the message payload.
|
||||
|
||||
@retval EFI_SUCCESS Payload holds a valid message payload pointer.
|
||||
@retval EFI_TIMEOUT Time out error if MTL channel is busy.
|
||||
@retval EFI_UNSUPPORTED If MTL channel is unsupported.
|
||||
**/
|
||||
EFI_STATUS
|
||||
ScmiCommandGetPayload (
|
||||
OUT UINT32 **Payload
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
MTL_CHANNEL *Channel;
|
||||
|
||||
// Get handle to the Channel.
|
||||
Status = MtlGetChannel (MTL_CHANNEL_TYPE_LOW, &Channel);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Payload will not be populated until channel is free.
|
||||
Status = MtlWaitUntilChannelFree (Channel, RESPONSE_TIMEOUT);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Get the address of the payload.
|
||||
*Payload = MtlGetChannelPayload (Channel);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/** Execute a SCMI command and receive a response.
|
||||
|
||||
This function uses a MTL channel to transfer message to SCP
|
||||
and waits for a response.
|
||||
|
||||
@param[in] Command Pointer to the SCMI command (Protocol ID
|
||||
and Message ID)
|
||||
|
||||
@param[in,out] PayloadLength SCMI command message length.
|
||||
|
||||
@param[out] OPTIONAL ReturnValues Pointer to SCMI response.
|
||||
|
||||
@retval OUT EFI_SUCCESS Command sent and message received successfully.
|
||||
@retval OUT EFI_UNSUPPORTED Channel not supported.
|
||||
@retval OUT EFI_TIMEOUT Timeout on the channel.
|
||||
@retval OUT EFI_DEVICE_ERROR Channel not ready.
|
||||
@retval OUT EFI_DEVICE_ERROR Message Header corrupted.
|
||||
@retval OUT EFI_DEVICE_ERROR SCMI error.
|
||||
**/
|
||||
EFI_STATUS
|
||||
ScmiCommandExecute (
|
||||
IN SCMI_COMMAND *Command,
|
||||
IN OUT UINT32 *PayloadLength,
|
||||
OUT UINT32 **ReturnValues OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
SCMI_MESSAGE_RESPONSE *Response;
|
||||
UINT32 MessageHeader;
|
||||
UINT32 ResponseHeader;
|
||||
MTL_CHANNEL *Channel;
|
||||
|
||||
ASSERT (PayloadLength != NULL);
|
||||
|
||||
Status = MtlGetChannel (MTL_CHANNEL_TYPE_LOW, &Channel);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Fill in message header.
|
||||
MessageHeader = SCMI_MESSAGE_HEADER (
|
||||
Command->MessageId,
|
||||
ScmiMessageTypeCommand,
|
||||
Command->ProtocolId
|
||||
);
|
||||
|
||||
// Send payload using MTL channel.
|
||||
Status = MtlSendMessage (
|
||||
Channel,
|
||||
MessageHeader,
|
||||
*PayloadLength
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Wait for the response on the channel.
|
||||
Status = MtlReceiveMessage (Channel, &ResponseHeader, PayloadLength);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
// SCMI must return MessageHeader unmodified.
|
||||
if (MessageHeader != ResponseHeader) {
|
||||
ASSERT (FALSE);
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
Response = (SCMI_MESSAGE_RESPONSE *)MtlGetChannelPayload (Channel);
|
||||
|
||||
if (Response->Status != ScmiSuccess) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"SCMI error: ProtocolId = 0x%x, MessageId = 0x%x, error = %d\n",
|
||||
Command->ProtocolId,
|
||||
Command->MessageId,
|
||||
Response->Status
|
||||
));
|
||||
|
||||
ASSERT (FALSE);
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
if (ReturnValues != NULL) {
|
||||
*ReturnValues = Response->ReturnValues;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/** Internal common function useful for common protocol discovery messages.
|
||||
|
||||
@param[in] ProtocolId Protocol Id of the protocol.
|
||||
@param[in] MessageId Message Id of the message.
|
||||
|
||||
@param[out] ReturnValues SCMI response return values.
|
||||
|
||||
@retval EFI_SUCCESS Success with valid return values.
|
||||
@retval EFI_DEVICE_ERROR SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
ScmiProtocolDiscoveryCommon (
|
||||
IN SCMI_PROTOCOL_ID ProtocolId,
|
||||
IN SCMI_MESSAGE_ID MessageId,
|
||||
OUT UINT32 **ReturnValues
|
||||
)
|
||||
{
|
||||
SCMI_COMMAND Command;
|
||||
UINT32 PayloadLength;
|
||||
|
||||
PayloadLength = 0;
|
||||
Command.ProtocolId = ProtocolId;
|
||||
Command.MessageId = MessageId;
|
||||
|
||||
return ScmiCommandExecute (
|
||||
&Command,
|
||||
&PayloadLength,
|
||||
ReturnValues
|
||||
);
|
||||
}
|
||||
|
||||
/** Return protocol version from SCP for a given protocol ID.
|
||||
|
||||
@param[in] Protocol ID Protocol ID.
|
||||
@param[out] Version Pointer to version of the protocol.
|
||||
|
||||
@retval EFI_SUCCESS Version holds a valid version received
|
||||
from the SCP.
|
||||
@retval EFI_DEVICE_ERROR SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
EFI_STATUS
|
||||
ScmiGetProtocolVersion (
|
||||
IN SCMI_PROTOCOL_ID ProtocolId,
|
||||
OUT UINT32 *Version
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 *ProtocolVersion;
|
||||
|
||||
Status = ScmiProtocolDiscoveryCommon (
|
||||
ProtocolId,
|
||||
ScmiMessageIdProtocolVersion,
|
||||
(UINT32 **)&ProtocolVersion
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
*Version = *ProtocolVersion;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/** Return protocol attributes from SCP for a given protocol ID.
|
||||
|
||||
@param[in] Protocol ID Protocol ID.
|
||||
@param[out] ReturnValues Pointer to attributes of the protocol.
|
||||
|
||||
@retval EFI_SUCCESS ReturnValues points to protocol attributes.
|
||||
@retval EFI_DEVICE_ERROR SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
EFI_STATUS
|
||||
ScmiGetProtocolAttributes (
|
||||
IN SCMI_PROTOCOL_ID ProtocolId,
|
||||
OUT UINT32 **ReturnValues
|
||||
)
|
||||
{
|
||||
return ScmiProtocolDiscoveryCommon (
|
||||
ProtocolId,
|
||||
ScmiMessageIdProtocolAttributes,
|
||||
ReturnValues
|
||||
);
|
||||
}
|
||||
|
||||
/** Return protocol message attributes from SCP for a given protocol ID.
|
||||
|
||||
@param[in] Protocol ID Protocol ID.
|
||||
@param[out] Attributes Pointer to attributes of the protocol.
|
||||
|
||||
@retval EFI_SUCCESS ReturnValues points to protocol message attributes.
|
||||
@retval EFI_DEVICE_ERROR SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
EFI_STATUS
|
||||
ScmiGetProtocolMessageAttributes (
|
||||
IN SCMI_PROTOCOL_ID ProtocolId,
|
||||
OUT UINT32 **ReturnValues
|
||||
)
|
||||
{
|
||||
return ScmiProtocolDiscoveryCommon (
|
||||
ProtocolId,
|
||||
ScmiMessageIdProtocolMessageAttributes,
|
||||
ReturnValues
|
||||
);
|
||||
}
|
311
ArmPkg/Drivers/ArmScmiDxe/ScmiBaseProtocol.c
Normal file
311
ArmPkg/Drivers/ArmScmiDxe/ScmiBaseProtocol.c
Normal file
@ -0,0 +1,311 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2017-2021, Arm Limited. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
System Control and Management Interface V1.0
|
||||
http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/
|
||||
DEN0056A_System_Control_and_Management_Interface.pdf
|
||||
**/
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Protocol/ArmScmiBaseProtocol.h>
|
||||
|
||||
#include "ArmScmiBaseProtocolPrivate.h"
|
||||
#include "ScmiPrivate.h"
|
||||
|
||||
/** Return version of the Base protocol supported by SCP firmware.
|
||||
|
||||
@param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance.
|
||||
|
||||
@param[out] Version Version of the supported SCMI Base protocol.
|
||||
|
||||
@retval EFI_SUCCESS The version of the protocol is returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
BaseGetVersion (
|
||||
IN SCMI_BASE_PROTOCOL *This,
|
||||
OUT UINT32 *Version
|
||||
)
|
||||
{
|
||||
return ScmiGetProtocolVersion (ScmiProtocolIdBase, Version);
|
||||
}
|
||||
|
||||
/** Return total number of SCMI protocols supported by the SCP firmware.
|
||||
|
||||
@param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance.
|
||||
|
||||
@param[out] TotalProtocols Total number of SCMI protocols supported.
|
||||
|
||||
@retval EFI_SUCCESS Total number of protocols supported are returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns a SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
BaseGetTotalProtocols (
|
||||
IN SCMI_BASE_PROTOCOL *This,
|
||||
OUT UINT32 *TotalProtocols
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 *ReturnValues;
|
||||
|
||||
Status = ScmiGetProtocolAttributes (ScmiProtocolIdBase, &ReturnValues);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
*TotalProtocols = SCMI_TOTAL_PROTOCOLS (ReturnValues[0]);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/** Common function which returns vendor details.
|
||||
|
||||
@param[in] MessageId ScmiMessageIdBaseDiscoverVendor
|
||||
OR
|
||||
ScmiMessageIdBaseDiscoverSubVendor
|
||||
|
||||
@param[out] VendorIdentifier ASCII name of the vendor/subvendor.
|
||||
|
||||
@retval EFI_SUCCESS VendorIdentifier is returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
BaseDiscoverVendorDetails (
|
||||
IN SCMI_MESSAGE_ID_BASE MessageId,
|
||||
OUT UINT8 VendorIdentifier[SCMI_MAX_STR_LEN]
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 *ReturnValues;
|
||||
SCMI_COMMAND Cmd;
|
||||
UINT32 PayloadLength;
|
||||
|
||||
Cmd.ProtocolId = ScmiProtocolIdBase;
|
||||
Cmd.MessageId = MessageId;
|
||||
|
||||
PayloadLength = 0;
|
||||
|
||||
Status = ScmiCommandExecute (
|
||||
&Cmd,
|
||||
&PayloadLength,
|
||||
&ReturnValues
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
AsciiStrCpyS (
|
||||
(CHAR8 *)VendorIdentifier,
|
||||
SCMI_MAX_STR_LEN,
|
||||
(CONST CHAR8 *)ReturnValues
|
||||
);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/** Return vendor name.
|
||||
|
||||
@param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance.
|
||||
|
||||
@param[out] VendorIdentifier Null terminated ASCII string of up to
|
||||
16 bytes with a vendor name.
|
||||
|
||||
@retval EFI_SUCCESS VendorIdentifier is returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns a SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
BaseDiscoverVendor (
|
||||
IN SCMI_BASE_PROTOCOL *This,
|
||||
OUT UINT8 VendorIdentifier[SCMI_MAX_STR_LEN]
|
||||
)
|
||||
{
|
||||
return BaseDiscoverVendorDetails (
|
||||
ScmiMessageIdBaseDiscoverVendor,
|
||||
VendorIdentifier
|
||||
);
|
||||
}
|
||||
|
||||
/** Return sub vendor name.
|
||||
|
||||
@param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance.
|
||||
|
||||
@param[out] VendorIdentifier Null terminated ASCII string of up to
|
||||
16 bytes with a sub vendor name.
|
||||
|
||||
@retval EFI_SUCCESS VendorIdentifier is returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns a SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
EFI_STATUS
|
||||
BaseDiscoverSubVendor (
|
||||
IN SCMI_BASE_PROTOCOL *This,
|
||||
OUT UINT8 VendorIdentifier[SCMI_MAX_STR_LEN]
|
||||
)
|
||||
{
|
||||
return BaseDiscoverVendorDetails (
|
||||
ScmiMessageIdBaseDiscoverSubVendor,
|
||||
VendorIdentifier
|
||||
);
|
||||
}
|
||||
|
||||
/** Return implementation version.
|
||||
|
||||
@param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance.
|
||||
|
||||
@param[out] ImplementationVersion Vendor specific implementation version.
|
||||
|
||||
@retval EFI_SUCCESS Implementation version is returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns a SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
BaseDiscoverImplVersion (
|
||||
IN SCMI_BASE_PROTOCOL *This,
|
||||
OUT UINT32 *ImplementationVersion
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 *ReturnValues;
|
||||
SCMI_COMMAND Cmd;
|
||||
UINT32 PayloadLength;
|
||||
|
||||
Cmd.ProtocolId = ScmiProtocolIdBase;
|
||||
Cmd.MessageId = ScmiMessageIdBaseDiscoverImplementationVersion;
|
||||
|
||||
PayloadLength = 0;
|
||||
|
||||
Status = ScmiCommandExecute (
|
||||
&Cmd,
|
||||
&PayloadLength,
|
||||
&ReturnValues
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
*ImplementationVersion = ReturnValues[0];
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/** Return list of protocols.
|
||||
|
||||
@param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance.
|
||||
|
||||
@param[out] ProtocolListSize Size of the ProtocolList.
|
||||
|
||||
@param[out] ProtocolList Protocol list.
|
||||
|
||||
@retval EFI_SUCCESS List of protocols is returned.
|
||||
@retval EFI_BUFFER_TOO_SMALL ProtocolListSize is too small for the result.
|
||||
It has been updated to the size needed.
|
||||
@retval EFI_DEVICE_ERROR SCP returns a SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
BaseDiscoverListProtocols (
|
||||
IN SCMI_BASE_PROTOCOL *This,
|
||||
IN OUT UINT32 *ProtocolListSize,
|
||||
OUT UINT8 *ProtocolList
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 TotalProtocols;
|
||||
UINT32 *MessageParams;
|
||||
BASE_DISCOVER_LIST *DiscoverList;
|
||||
UINT32 Skip;
|
||||
UINT32 Index;
|
||||
SCMI_COMMAND Cmd;
|
||||
UINT32 PayloadLength;
|
||||
UINT32 RequiredSize;
|
||||
|
||||
Status = BaseGetTotalProtocols (This, &TotalProtocols);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = ScmiCommandGetPayload (&MessageParams);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
RequiredSize = sizeof (UINT8) * TotalProtocols;
|
||||
if (*ProtocolListSize < RequiredSize) {
|
||||
*ProtocolListSize = RequiredSize;
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
Cmd.ProtocolId = ScmiProtocolIdBase;
|
||||
Cmd.MessageId = ScmiMessageIdBaseDiscoverListProtocols;
|
||||
|
||||
Skip = 0;
|
||||
|
||||
while (Skip < TotalProtocols) {
|
||||
*MessageParams = Skip;
|
||||
|
||||
// Note PayloadLength is a IN/OUT parameter.
|
||||
PayloadLength = sizeof (Skip);
|
||||
|
||||
Status = ScmiCommandExecute (
|
||||
&Cmd,
|
||||
&PayloadLength,
|
||||
(UINT32 **)&DiscoverList
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < DiscoverList->NumProtocols; Index++) {
|
||||
ProtocolList[Skip++] = DiscoverList->Protocols[Index];
|
||||
}
|
||||
}
|
||||
|
||||
*ProtocolListSize = RequiredSize;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
// Instance of the SCMI Base protocol.
|
||||
STATIC CONST SCMI_BASE_PROTOCOL BaseProtocol = {
|
||||
BaseGetVersion,
|
||||
BaseGetTotalProtocols,
|
||||
BaseDiscoverVendor,
|
||||
BaseDiscoverSubVendor,
|
||||
BaseDiscoverImplVersion,
|
||||
BaseDiscoverListProtocols
|
||||
};
|
||||
|
||||
/** Initialize Base protocol and install protocol on a given handle.
|
||||
|
||||
@param[in] Handle Handle to install Base protocol.
|
||||
|
||||
@retval EFI_SUCCESS Base protocol interface installed
|
||||
successfully.
|
||||
**/
|
||||
EFI_STATUS
|
||||
ScmiBaseProtocolInit (
|
||||
IN OUT EFI_HANDLE *Handle
|
||||
)
|
||||
{
|
||||
return gBS->InstallMultipleProtocolInterfaces (
|
||||
Handle,
|
||||
&gArmScmiBaseProtocolGuid,
|
||||
&BaseProtocol,
|
||||
NULL
|
||||
);
|
||||
}
|
480
ArmPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c
Normal file
480
ArmPkg/Drivers/ArmScmiDxe/ScmiClockProtocol.c
Normal file
@ -0,0 +1,480 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2017-2021, Arm Limited. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
System Control and Management Interface V1.0
|
||||
http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/
|
||||
DEN0056A_System_Control_and_Management_Interface.pdf
|
||||
**/
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Protocol/ArmScmiClockProtocol.h>
|
||||
#include <Protocol/ArmScmiClock2Protocol.h>
|
||||
|
||||
#include "ArmScmiClockProtocolPrivate.h"
|
||||
#include "ScmiPrivate.h"
|
||||
|
||||
/** Convert to 64 bit value from two 32 bit words.
|
||||
|
||||
@param[in] Low Lower 32 bits.
|
||||
@param[in] High Higher 32 bits.
|
||||
|
||||
@retval UINT64 64 bit value.
|
||||
**/
|
||||
STATIC
|
||||
UINT64
|
||||
ConvertTo64Bit (
|
||||
IN UINT32 Low,
|
||||
IN UINT32 High
|
||||
)
|
||||
{
|
||||
return (Low | ((UINT64)High << 32));
|
||||
}
|
||||
|
||||
/** Return version of the clock management protocol supported by SCP firmware.
|
||||
|
||||
@param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance.
|
||||
|
||||
@param[out] Version Version of the supported SCMI Clock management protocol.
|
||||
|
||||
@retval EFI_SUCCESS The version is returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
ClockGetVersion (
|
||||
IN SCMI_CLOCK_PROTOCOL *This,
|
||||
OUT UINT32 *Version
|
||||
)
|
||||
{
|
||||
return ScmiGetProtocolVersion (ScmiProtocolIdClock, Version);
|
||||
}
|
||||
|
||||
/** Return total number of clock devices supported by the clock management
|
||||
protocol.
|
||||
|
||||
@param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance.
|
||||
|
||||
@param[out] TotalClocks Total number of clocks supported.
|
||||
|
||||
@retval EFI_SUCCESS Total number of clocks supported is returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
ClockGetTotalClocks (
|
||||
IN SCMI_CLOCK_PROTOCOL *This,
|
||||
OUT UINT32 *TotalClocks
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 *ReturnValues;
|
||||
|
||||
Status = ScmiGetProtocolAttributes (ScmiProtocolIdClock, &ReturnValues);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
*TotalClocks = SCMI_CLOCK_PROTOCOL_TOTAL_CLKS (ReturnValues[0]);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/** Return attributes of a clock device.
|
||||
|
||||
@param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance.
|
||||
@param[in] ClockId Identifier for the clock device.
|
||||
|
||||
@param[out] Enabled If TRUE, the clock device is enabled.
|
||||
@param[out] ClockAsciiName A NULL terminated ASCII string with the clock
|
||||
name, of up to 16 bytes.
|
||||
|
||||
@retval EFI_SUCCESS Clock device attributes are returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
ClockGetClockAttributes (
|
||||
IN SCMI_CLOCK_PROTOCOL *This,
|
||||
IN UINT32 ClockId,
|
||||
OUT BOOLEAN *Enabled,
|
||||
OUT CHAR8 *ClockAsciiName
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
UINT32 *MessageParams;
|
||||
CLOCK_ATTRIBUTES *ClockAttributes;
|
||||
SCMI_COMMAND Cmd;
|
||||
UINT32 PayloadLength;
|
||||
|
||||
Status = ScmiCommandGetPayload (&MessageParams);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
*MessageParams = ClockId;
|
||||
|
||||
Cmd.ProtocolId = ScmiProtocolIdClock;
|
||||
Cmd.MessageId = ScmiMessageIdClockAttributes;
|
||||
|
||||
PayloadLength = sizeof (ClockId);
|
||||
|
||||
Status = ScmiCommandExecute (
|
||||
&Cmd,
|
||||
&PayloadLength,
|
||||
(UINT32 **)&ClockAttributes
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
// TRUE if bit 0 of ClockAttributes->Attributes is set.
|
||||
*Enabled = CLOCK_ENABLED (ClockAttributes->Attributes);
|
||||
|
||||
AsciiStrCpyS (
|
||||
ClockAsciiName,
|
||||
SCMI_MAX_STR_LEN,
|
||||
(CONST CHAR8 *)ClockAttributes->ClockName
|
||||
);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/** Return list of rates supported by a given clock device.
|
||||
|
||||
@param[in] This A pointer to SCMI_CLOCK_PROTOCOL Instance.
|
||||
@param[in] ClockId Identifier for the clock device.
|
||||
|
||||
@param[out] Format ScmiClockRateFormatDiscrete: Clock device
|
||||
supports range of clock rates which are non-linear.
|
||||
|
||||
ScmiClockRateFormatLinear: Clock device supports
|
||||
range of linear clock rates from Min to Max in steps.
|
||||
|
||||
@param[out] TotalRates Total number of rates.
|
||||
|
||||
@param[in,out] RateArraySize Size of the RateArray.
|
||||
|
||||
@param[out] RateArray List of clock rates.
|
||||
|
||||
@retval EFI_SUCCESS List of clock rates is returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval EFI_BUFFER_TOO_SMALL RateArraySize is too small for the result.
|
||||
It has been updated to the size needed.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
ClockDescribeRates (
|
||||
IN SCMI_CLOCK_PROTOCOL *This,
|
||||
IN UINT32 ClockId,
|
||||
OUT SCMI_CLOCK_RATE_FORMAT *Format,
|
||||
OUT UINT32 *TotalRates,
|
||||
IN OUT UINT32 *RateArraySize,
|
||||
OUT SCMI_CLOCK_RATE *RateArray
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
UINT32 PayloadLength;
|
||||
SCMI_COMMAND Cmd;
|
||||
UINT32 *MessageParams;
|
||||
CLOCK_DESCRIBE_RATES *DescribeRates;
|
||||
CLOCK_RATE_DWORD *Rate;
|
||||
|
||||
UINT32 RequiredArraySize;
|
||||
UINT32 RateIndex;
|
||||
UINT32 RateNo;
|
||||
UINT32 RateOffset;
|
||||
|
||||
*TotalRates = 0;
|
||||
RequiredArraySize = 0;
|
||||
RateIndex = 0;
|
||||
|
||||
Status = ScmiCommandGetPayload (&MessageParams);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Cmd.ProtocolId = ScmiProtocolIdClock;
|
||||
Cmd.MessageId = ScmiMessageIdClockDescribeRates;
|
||||
|
||||
*MessageParams++ = ClockId;
|
||||
|
||||
do {
|
||||
*MessageParams = RateIndex;
|
||||
|
||||
// Set Payload length, note PayloadLength is a IN/OUT parameter.
|
||||
PayloadLength = sizeof (ClockId) + sizeof (RateIndex);
|
||||
|
||||
// Execute and wait for response on a SCMI channel.
|
||||
Status = ScmiCommandExecute (
|
||||
&Cmd,
|
||||
&PayloadLength,
|
||||
(UINT32 **)&DescribeRates
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (*TotalRates == 0) {
|
||||
// In the first iteration we will get number of returned rates and number
|
||||
// of remaining rates. With this information calculate required size
|
||||
// for rate array. If provided RateArraySize is less, return an
|
||||
// error.
|
||||
|
||||
*Format = RATE_FORMAT (DescribeRates->NumRatesFlags);
|
||||
|
||||
*TotalRates = NUM_RATES (DescribeRates->NumRatesFlags)
|
||||
+ NUM_REMAIN_RATES (DescribeRates->NumRatesFlags);
|
||||
|
||||
if (*Format == ScmiClockRateFormatDiscrete) {
|
||||
RequiredArraySize = (*TotalRates) * sizeof (UINT64);
|
||||
} else {
|
||||
// We need to return triplet of 64 bit value for each rate
|
||||
RequiredArraySize = (*TotalRates) * 3 * sizeof (UINT64);
|
||||
}
|
||||
|
||||
if (RequiredArraySize > (*RateArraySize)) {
|
||||
*RateArraySize = RequiredArraySize;
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
}
|
||||
|
||||
RateOffset = 0;
|
||||
|
||||
if (*Format == ScmiClockRateFormatDiscrete) {
|
||||
for (RateNo = 0; RateNo < NUM_RATES (DescribeRates->NumRatesFlags); RateNo++) {
|
||||
Rate = &DescribeRates->Rates[RateOffset++];
|
||||
// Non-linear discrete rates.
|
||||
RateArray[RateIndex++].DiscreteRate.Rate =
|
||||
ConvertTo64Bit (Rate->Low, Rate->High);
|
||||
}
|
||||
} else {
|
||||
for (RateNo = 0; RateNo < NUM_RATES (DescribeRates->NumRatesFlags); RateNo++) {
|
||||
// Linear clock rates from minimum to maximum in steps
|
||||
// Minimum clock rate.
|
||||
Rate = &DescribeRates->Rates[RateOffset++];
|
||||
RateArray[RateIndex].ContinuousRate.Min =
|
||||
ConvertTo64Bit (Rate->Low, Rate->High);
|
||||
|
||||
Rate = &DescribeRates->Rates[RateOffset++];
|
||||
// Maximum clock rate.
|
||||
RateArray[RateIndex].ContinuousRate.Max =
|
||||
ConvertTo64Bit (Rate->Low, Rate->High);
|
||||
|
||||
Rate = &DescribeRates->Rates[RateOffset++];
|
||||
// Step.
|
||||
RateArray[RateIndex++].ContinuousRate.Step =
|
||||
ConvertTo64Bit (Rate->Low, Rate->High);
|
||||
}
|
||||
}
|
||||
} while (NUM_REMAIN_RATES (DescribeRates->NumRatesFlags) != 0);
|
||||
|
||||
// Update RateArraySize with RequiredArraySize.
|
||||
*RateArraySize = RequiredArraySize;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/** Get clock rate.
|
||||
|
||||
@param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance.
|
||||
@param[in] ClockId Identifier for the clock device.
|
||||
|
||||
@param[out] Rate Clock rate.
|
||||
|
||||
@retval EFI_SUCCESS Clock rate is returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
ClockRateGet (
|
||||
IN SCMI_CLOCK_PROTOCOL *This,
|
||||
IN UINT32 ClockId,
|
||||
OUT UINT64 *Rate
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
UINT32 *MessageParams;
|
||||
CLOCK_RATE_DWORD *ClockRate;
|
||||
SCMI_COMMAND Cmd;
|
||||
|
||||
UINT32 PayloadLength;
|
||||
|
||||
Status = ScmiCommandGetPayload (&MessageParams);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Fill arguments for clock protocol command.
|
||||
*MessageParams = ClockId;
|
||||
|
||||
Cmd.ProtocolId = ScmiProtocolIdClock;
|
||||
Cmd.MessageId = ScmiMessageIdClockRateGet;
|
||||
|
||||
PayloadLength = sizeof (ClockId);
|
||||
|
||||
// Execute and wait for response on a SCMI channel.
|
||||
Status = ScmiCommandExecute (
|
||||
&Cmd,
|
||||
&PayloadLength,
|
||||
(UINT32 **)&ClockRate
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
*Rate = ConvertTo64Bit (ClockRate->Low, ClockRate->High);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/** Set clock rate.
|
||||
|
||||
@param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance.
|
||||
@param[in] ClockId Identifier for the clock device.
|
||||
@param[in] Rate Clock rate.
|
||||
|
||||
@retval EFI_SUCCESS Clock rate set success.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
ClockRateSet (
|
||||
IN SCMI_CLOCK_PROTOCOL *This,
|
||||
IN UINT32 ClockId,
|
||||
IN UINT64 Rate
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
CLOCK_RATE_SET_ATTRIBUTES *ClockRateSetAttributes;
|
||||
SCMI_COMMAND Cmd;
|
||||
UINT32 PayloadLength;
|
||||
|
||||
Status = ScmiCommandGetPayload ((UINT32 **)&ClockRateSetAttributes);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Fill arguments for clock protocol command.
|
||||
ClockRateSetAttributes->ClockId = ClockId;
|
||||
ClockRateSetAttributes->Flags = CLOCK_SET_DEFAULT_FLAGS;
|
||||
ClockRateSetAttributes->Rate.Low = (UINT32)Rate;
|
||||
ClockRateSetAttributes->Rate.High = (UINT32)(Rate >> 32);
|
||||
|
||||
Cmd.ProtocolId = ScmiProtocolIdClock;
|
||||
Cmd.MessageId = ScmiMessageIdClockRateSet;
|
||||
|
||||
PayloadLength = sizeof (CLOCK_RATE_SET_ATTRIBUTES);
|
||||
|
||||
// Execute and wait for response on a SCMI channel.
|
||||
Status = ScmiCommandExecute (
|
||||
&Cmd,
|
||||
&PayloadLength,
|
||||
NULL
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/** Enable/Disable specified clock.
|
||||
|
||||
@param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance.
|
||||
@param[in] ClockId Identifier for the clock device.
|
||||
@param[in] Enable TRUE to enable, FALSE to disable.
|
||||
|
||||
@retval EFI_SUCCESS Clock enable/disable successful.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
ClockEnable (
|
||||
IN SCMI_CLOCK2_PROTOCOL *This,
|
||||
IN UINT32 ClockId,
|
||||
IN BOOLEAN Enable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
CLOCK_CONFIG_SET_ATTRIBUTES *ClockConfigSetAttributes;
|
||||
SCMI_COMMAND Cmd;
|
||||
UINT32 PayloadLength;
|
||||
|
||||
Status = ScmiCommandGetPayload ((UINT32 **)&ClockConfigSetAttributes);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Fill arguments for clock protocol command.
|
||||
ClockConfigSetAttributes->ClockId = ClockId;
|
||||
ClockConfigSetAttributes->Attributes = Enable ? BIT0 : 0;
|
||||
|
||||
Cmd.ProtocolId = ScmiProtocolIdClock;
|
||||
Cmd.MessageId = ScmiMessageIdClockConfigSet;
|
||||
|
||||
PayloadLength = sizeof (CLOCK_CONFIG_SET_ATTRIBUTES);
|
||||
|
||||
// Execute and wait for response on a SCMI channel.
|
||||
Status = ScmiCommandExecute (
|
||||
&Cmd,
|
||||
&PayloadLength,
|
||||
NULL
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Instance of the SCMI clock management protocol.
|
||||
STATIC CONST SCMI_CLOCK_PROTOCOL ScmiClockProtocol = {
|
||||
ClockGetVersion,
|
||||
ClockGetTotalClocks,
|
||||
ClockGetClockAttributes,
|
||||
ClockDescribeRates,
|
||||
ClockRateGet,
|
||||
ClockRateSet
|
||||
};
|
||||
|
||||
// Instance of the SCMI clock management protocol.
|
||||
STATIC CONST SCMI_CLOCK2_PROTOCOL ScmiClock2Protocol = {
|
||||
(SCMI_CLOCK2_GET_VERSION)ClockGetVersion,
|
||||
(SCMI_CLOCK2_GET_TOTAL_CLOCKS)ClockGetTotalClocks,
|
||||
(SCMI_CLOCK2_GET_CLOCK_ATTRIBUTES)ClockGetClockAttributes,
|
||||
(SCMI_CLOCK2_DESCRIBE_RATES)ClockDescribeRates,
|
||||
(SCMI_CLOCK2_RATE_GET)ClockRateGet,
|
||||
(SCMI_CLOCK2_RATE_SET)ClockRateSet,
|
||||
SCMI_CLOCK2_PROTOCOL_VERSION,
|
||||
ClockEnable
|
||||
};
|
||||
|
||||
/** Initialize clock management protocol and install protocol on a given handle.
|
||||
|
||||
@param[in] Handle Handle to install clock management protocol.
|
||||
|
||||
@retval EFI_SUCCESS Clock protocol interface installed successfully.
|
||||
**/
|
||||
EFI_STATUS
|
||||
ScmiClockProtocolInit (
|
||||
IN EFI_HANDLE *Handle
|
||||
)
|
||||
{
|
||||
return gBS->InstallMultipleProtocolInterfaces (
|
||||
Handle,
|
||||
&gArmScmiClockProtocolGuid,
|
||||
&ScmiClockProtocol,
|
||||
&gArmScmiClock2ProtocolGuid,
|
||||
&ScmiClock2Protocol,
|
||||
NULL
|
||||
);
|
||||
}
|
152
ArmPkg/Drivers/ArmScmiDxe/ScmiDxe.c
Normal file
152
ArmPkg/Drivers/ArmScmiDxe/ScmiDxe.c
Normal file
@ -0,0 +1,152 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2017-2021, Arm Limited. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
@par Specification Reference:
|
||||
- Arm System Control and Management Interface - Platform Design Document
|
||||
(https://developer.arm.com/documentation/den0056/)
|
||||
**/
|
||||
|
||||
#include <Base.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Protocol/ArmScmiBaseProtocol.h>
|
||||
#include <Protocol/ArmScmiClockProtocol.h>
|
||||
#include <Protocol/ArmScmiPerformanceProtocol.h>
|
||||
|
||||
#include "ArmScmiBaseProtocolPrivate.h"
|
||||
#include "ArmScmiClockProtocolPrivate.h"
|
||||
#include "ArmScmiPerformanceProtocolPrivate.h"
|
||||
#include "ScmiDxe.h"
|
||||
#include "ScmiPrivate.h"
|
||||
|
||||
STATIC CONST SCMI_PROTOCOL_ENTRY Protocols[] = {
|
||||
{ ScmiProtocolIdBase, ScmiBaseProtocolInit },
|
||||
{ ScmiProtocolIdPerformance, ScmiPerformanceProtocolInit },
|
||||
{ ScmiProtocolIdClock, ScmiClockProtocolInit }
|
||||
};
|
||||
|
||||
/** ARM SCMI driver entry point function.
|
||||
|
||||
This function installs the SCMI Base protocol and a list of other
|
||||
protocols is queried using the Base protocol. If protocol is supported,
|
||||
driver will call each protocol init function to install the protocol on
|
||||
the ImageHandle.
|
||||
|
||||
@param[in] ImageHandle Handle to this EFI Image which will be used to
|
||||
install Base, Clock and Performance protocols.
|
||||
@param[in] SystemTable A pointer to boot time system table.
|
||||
|
||||
@retval EFI_SUCCESS Driver initalized successfully.
|
||||
@retval EFI_UNSUPPORTED If SCMI base protocol version is not supported.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArmScmiDxeEntryPoint (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
SCMI_BASE_PROTOCOL *BaseProtocol;
|
||||
UINT32 Version;
|
||||
UINT32 Index;
|
||||
UINT32 NumProtocols;
|
||||
UINT32 ProtocolIndex;
|
||||
UINT8 *SupportedList;
|
||||
UINT32 SupportedListSize;
|
||||
|
||||
// Every SCMI implementation must implement the base protocol.
|
||||
ASSERT (Protocols[0].Id == ScmiProtocolIdBase);
|
||||
|
||||
Status = ScmiBaseProtocolInit (&ImageHandle);
|
||||
if (EFI_ERROR (Status)) {
|
||||
ASSERT (FALSE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = gBS->LocateProtocol (
|
||||
&gArmScmiBaseProtocolGuid,
|
||||
NULL,
|
||||
(VOID **)&BaseProtocol
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
ASSERT (FALSE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Get SCMI Base protocol version.
|
||||
Status = BaseProtocol->GetVersion (BaseProtocol, &Version);
|
||||
if (EFI_ERROR (Status)) {
|
||||
ASSERT (FALSE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Accept any version between SCMI v1.0 and SCMI v2.0
|
||||
if ((Version < BASE_PROTOCOL_VERSION_V1) ||
|
||||
(Version > BASE_PROTOCOL_VERSION_V2))
|
||||
{
|
||||
ASSERT (FALSE);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
// Apart from Base protocol, SCMI may implement various other protocols,
|
||||
// query total protocols implemented by the SCP firmware.
|
||||
NumProtocols = 0;
|
||||
Status = BaseProtocol->GetTotalProtocols (BaseProtocol, &NumProtocols);
|
||||
if (EFI_ERROR (Status)) {
|
||||
ASSERT (FALSE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
ASSERT (NumProtocols != 0);
|
||||
|
||||
SupportedListSize = (NumProtocols * sizeof (*SupportedList));
|
||||
|
||||
Status = gBS->AllocatePool (
|
||||
EfiBootServicesData,
|
||||
SupportedListSize,
|
||||
(VOID **)&SupportedList
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
ASSERT (FALSE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Get the list of protocols supported by SCP firmware on the platform.
|
||||
Status = BaseProtocol->DiscoverListProtocols (
|
||||
BaseProtocol,
|
||||
&SupportedListSize,
|
||||
SupportedList
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
gBS->FreePool (SupportedList);
|
||||
ASSERT (FALSE);
|
||||
return Status;
|
||||
}
|
||||
|
||||
// Install supported protocol on ImageHandle.
|
||||
for (ProtocolIndex = 1; ProtocolIndex < ARRAY_SIZE (Protocols);
|
||||
ProtocolIndex++)
|
||||
{
|
||||
for (Index = 0; Index < NumProtocols; Index++) {
|
||||
if (Protocols[ProtocolIndex].Id == SupportedList[Index]) {
|
||||
Status = Protocols[ProtocolIndex].InitFn (&ImageHandle);
|
||||
if (EFI_ERROR (Status)) {
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gBS->FreePool (SupportedList);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
37
ArmPkg/Drivers/ArmScmiDxe/ScmiDxe.h
Normal file
37
ArmPkg/Drivers/ArmScmiDxe/ScmiDxe.h
Normal file
@ -0,0 +1,37 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2017-2018, Arm Limited. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
System Control and Management Interface V1.0
|
||||
http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/
|
||||
DEN0056A_System_Control_and_Management_Interface.pdf
|
||||
**/
|
||||
|
||||
#ifndef SCMI_DXE_H_
|
||||
#define SCMI_DXE_H_
|
||||
|
||||
#include "ScmiPrivate.h"
|
||||
|
||||
#define MAX_VENDOR_LEN SCMI_MAX_STR_LEN
|
||||
|
||||
/** Pointer to protocol initialization function.
|
||||
|
||||
@param[in] Handle A pointer to the EFI_HANDLE on which the protocol
|
||||
interface is to be installed.
|
||||
|
||||
@retval EFI_SUCCESS Protocol interface installed successfully.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_PROTOCOL_INIT_FXN)(
|
||||
IN EFI_HANDLE *Handle
|
||||
);
|
||||
|
||||
typedef struct {
|
||||
SCMI_PROTOCOL_ID Id; // Protocol Id.
|
||||
SCMI_PROTOCOL_INIT_FXN InitFn; // Protocol init function.
|
||||
} SCMI_PROTOCOL_ENTRY;
|
||||
|
||||
#endif /* SCMI_DXE_H_ */
|
449
ArmPkg/Drivers/ArmScmiDxe/ScmiPerformanceProtocol.c
Normal file
449
ArmPkg/Drivers/ArmScmiDxe/ScmiPerformanceProtocol.c
Normal file
@ -0,0 +1,449 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2017-2021, Arm Limited. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
System Control and Management Interface V1.0
|
||||
http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/
|
||||
DEN0056A_System_Control_and_Management_Interface.pdf
|
||||
**/
|
||||
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Protocol/ArmScmiPerformanceProtocol.h>
|
||||
|
||||
#include "ArmScmiPerformanceProtocolPrivate.h"
|
||||
#include "ScmiPrivate.h"
|
||||
|
||||
/** Return version of the performance management protocol supported by SCP.
|
||||
firmware.
|
||||
|
||||
@param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
|
||||
|
||||
@param[out] Version Version of the supported SCMI performance management
|
||||
protocol.
|
||||
|
||||
@retval EFI_SUCCESS The version is returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
PerformanceGetVersion (
|
||||
IN SCMI_PERFORMANCE_PROTOCOL *This,
|
||||
OUT UINT32 *Version
|
||||
)
|
||||
{
|
||||
return ScmiGetProtocolVersion (ScmiProtocolIdPerformance, Version);
|
||||
}
|
||||
|
||||
/** Return protocol attributes of the performance management protocol.
|
||||
|
||||
@param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
|
||||
|
||||
@param[out] Attributes Protocol attributes.
|
||||
|
||||
@retval EFI_SUCCESS Protocol attributes are returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
PerformanceGetAttributes (
|
||||
IN SCMI_PERFORMANCE_PROTOCOL *This,
|
||||
OUT SCMI_PERFORMANCE_PROTOCOL_ATTRIBUTES *Attributes
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 *ReturnValues;
|
||||
|
||||
Status = ScmiGetProtocolAttributes (
|
||||
ScmiProtocolIdPerformance,
|
||||
&ReturnValues
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
CopyMem (
|
||||
Attributes,
|
||||
ReturnValues,
|
||||
sizeof (SCMI_PERFORMANCE_PROTOCOL_ATTRIBUTES)
|
||||
);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/** Return performance domain attributes.
|
||||
|
||||
@param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
|
||||
@param[in] DomainId Identifier for the performance domain.
|
||||
|
||||
@param[out] Attributes Performance domain attributes.
|
||||
|
||||
@retval EFI_SUCCESS Domain attributes are returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
PerformanceDomainAttributes (
|
||||
IN SCMI_PERFORMANCE_PROTOCOL *This,
|
||||
IN UINT32 DomainId,
|
||||
OUT SCMI_PERFORMANCE_DOMAIN_ATTRIBUTES *DomainAttributes
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 *MessageParams;
|
||||
UINT32 *ReturnValues;
|
||||
UINT32 PayloadLength;
|
||||
SCMI_COMMAND Cmd;
|
||||
|
||||
Status = ScmiCommandGetPayload (&MessageParams);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
*MessageParams = DomainId;
|
||||
|
||||
Cmd.ProtocolId = ScmiProtocolIdPerformance;
|
||||
Cmd.MessageId = ScmiMessageIdPerformanceDomainAttributes;
|
||||
|
||||
PayloadLength = sizeof (DomainId);
|
||||
|
||||
Status = ScmiCommandExecute (
|
||||
&Cmd,
|
||||
&PayloadLength,
|
||||
&ReturnValues
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
CopyMem (
|
||||
DomainAttributes,
|
||||
ReturnValues,
|
||||
sizeof (SCMI_PERFORMANCE_DOMAIN_ATTRIBUTES)
|
||||
);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/** Return list of performance domain levels of a given domain.
|
||||
|
||||
@param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
|
||||
@param[in] DomainId Identifier for the performance domain.
|
||||
|
||||
@param[out] NumLevels Total number of levels a domain can support.
|
||||
|
||||
@param[in,out] LevelArraySize Size of the performance level array.
|
||||
|
||||
@param[out] LevelArray Array of the performance levels.
|
||||
|
||||
@retval EFI_SUCCESS Domain levels are returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval EFI_BUFFER_TOO_SMALL LevelArraySize is too small for the result.
|
||||
It has been updated to the size needed.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
PerformanceDescribeLevels (
|
||||
IN SCMI_PERFORMANCE_PROTOCOL *This,
|
||||
IN UINT32 DomainId,
|
||||
OUT UINT32 *NumLevels,
|
||||
IN OUT UINT32 *LevelArraySize,
|
||||
OUT SCMI_PERFORMANCE_LEVEL *LevelArray
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 PayloadLength;
|
||||
SCMI_COMMAND Cmd;
|
||||
UINT32 *MessageParams;
|
||||
UINT32 LevelIndex;
|
||||
UINT32 RequiredSize;
|
||||
UINT32 LevelNo;
|
||||
UINT32 ReturnNumLevels;
|
||||
UINT32 ReturnRemainNumLevels;
|
||||
|
||||
PERF_DESCRIBE_LEVELS *Levels;
|
||||
|
||||
Status = ScmiCommandGetPayload (&MessageParams);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
LevelIndex = 0;
|
||||
RequiredSize = 0;
|
||||
|
||||
*MessageParams++ = DomainId;
|
||||
|
||||
Cmd.ProtocolId = ScmiProtocolIdPerformance;
|
||||
Cmd.MessageId = ScmiMessageIdPerformanceDescribeLevels;
|
||||
|
||||
do {
|
||||
*MessageParams = LevelIndex;
|
||||
|
||||
// Note, PayloadLength is an IN/OUT parameter.
|
||||
PayloadLength = sizeof (DomainId) + sizeof (LevelIndex);
|
||||
|
||||
Status = ScmiCommandExecute (
|
||||
&Cmd,
|
||||
&PayloadLength,
|
||||
(UINT32 **)&Levels
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
ReturnNumLevels = NUM_PERF_LEVELS (Levels->NumLevels);
|
||||
ReturnRemainNumLevels = NUM_REMAIN_PERF_LEVELS (Levels->NumLevels);
|
||||
|
||||
if (RequiredSize == 0) {
|
||||
*NumLevels = ReturnNumLevels + ReturnRemainNumLevels;
|
||||
|
||||
RequiredSize = (*NumLevels) * sizeof (SCMI_PERFORMANCE_LEVEL);
|
||||
if (RequiredSize > (*LevelArraySize)) {
|
||||
// Update LevelArraySize with required size.
|
||||
*LevelArraySize = RequiredSize;
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
}
|
||||
}
|
||||
|
||||
for (LevelNo = 0; LevelNo < ReturnNumLevels; LevelNo++) {
|
||||
CopyMem (
|
||||
&LevelArray[LevelIndex++],
|
||||
&Levels->PerfLevel[LevelNo],
|
||||
sizeof (SCMI_PERFORMANCE_LEVEL)
|
||||
);
|
||||
}
|
||||
} while (ReturnRemainNumLevels != 0);
|
||||
|
||||
*LevelArraySize = RequiredSize;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/** Set performance limits of a domain.
|
||||
|
||||
@param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
|
||||
@param[in] DomainId Identifier for the performance domain.
|
||||
@param[in] Limit Performance limit to set.
|
||||
|
||||
@retval EFI_SUCCESS Performance limits set successfully.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
EFI_STATUS
|
||||
PerformanceLimitsSet (
|
||||
IN SCMI_PERFORMANCE_PROTOCOL *This,
|
||||
IN UINT32 DomainId,
|
||||
IN SCMI_PERFORMANCE_LIMITS *Limits
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 PayloadLength;
|
||||
SCMI_COMMAND Cmd;
|
||||
UINT32 *MessageParams;
|
||||
|
||||
Status = ScmiCommandGetPayload (&MessageParams);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
*MessageParams++ = DomainId;
|
||||
*MessageParams++ = Limits->RangeMax;
|
||||
*MessageParams = Limits->RangeMin;
|
||||
|
||||
Cmd.ProtocolId = ScmiProtocolIdPerformance;
|
||||
Cmd.MessageId = ScmiMessageIdPerformanceLimitsSet;
|
||||
|
||||
PayloadLength = sizeof (DomainId) + sizeof (SCMI_PERFORMANCE_LIMITS);
|
||||
|
||||
Status = ScmiCommandExecute (
|
||||
&Cmd,
|
||||
&PayloadLength,
|
||||
NULL
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/** Get performance limits of a domain.
|
||||
|
||||
@param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
|
||||
@param[in] DomainId Identifier for the performance domain.
|
||||
|
||||
@param[out] Limit Performance Limits of the domain.
|
||||
|
||||
@retval EFI_SUCCESS Performance limits are returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
EFI_STATUS
|
||||
PerformanceLimitsGet (
|
||||
SCMI_PERFORMANCE_PROTOCOL *This,
|
||||
UINT32 DomainId,
|
||||
SCMI_PERFORMANCE_LIMITS *Limits
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 PayloadLength;
|
||||
SCMI_COMMAND Cmd;
|
||||
UINT32 *MessageParams;
|
||||
|
||||
SCMI_PERFORMANCE_LIMITS *ReturnValues;
|
||||
|
||||
Status = ScmiCommandGetPayload (&MessageParams);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
*MessageParams = DomainId;
|
||||
|
||||
Cmd.ProtocolId = ScmiProtocolIdPerformance;
|
||||
Cmd.MessageId = ScmiMessageIdPerformanceLimitsGet;
|
||||
|
||||
PayloadLength = sizeof (DomainId);
|
||||
|
||||
Status = ScmiCommandExecute (
|
||||
&Cmd,
|
||||
&PayloadLength,
|
||||
(UINT32 **)&ReturnValues
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Limits->RangeMax = ReturnValues->RangeMax;
|
||||
Limits->RangeMin = ReturnValues->RangeMin;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/** Set performance level of a domain.
|
||||
|
||||
@param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
|
||||
@param[in] DomainId Identifier for the performance domain.
|
||||
@param[in] Level Performance level of the domain.
|
||||
|
||||
@retval EFI_SUCCESS Performance level set successfully.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
EFI_STATUS
|
||||
PerformanceLevelSet (
|
||||
IN SCMI_PERFORMANCE_PROTOCOL *This,
|
||||
IN UINT32 DomainId,
|
||||
IN UINT32 Level
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 PayloadLength;
|
||||
SCMI_COMMAND Cmd;
|
||||
UINT32 *MessageParams;
|
||||
|
||||
Status = ScmiCommandGetPayload (&MessageParams);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
*MessageParams++ = DomainId;
|
||||
*MessageParams = Level;
|
||||
|
||||
Cmd.ProtocolId = ScmiProtocolIdPerformance;
|
||||
Cmd.MessageId = ScmiMessageIdPerformanceLevelSet;
|
||||
|
||||
PayloadLength = sizeof (DomainId) + sizeof (Level);
|
||||
|
||||
Status = ScmiCommandExecute (
|
||||
&Cmd,
|
||||
&PayloadLength,
|
||||
NULL
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/** Get performance level of a domain.
|
||||
|
||||
@param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
|
||||
@param[in] DomainId Identifier for the performance domain.
|
||||
|
||||
@param[out] Level Performance level of the domain.
|
||||
|
||||
@retval EFI_SUCCESS Performance level got successfully.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
EFI_STATUS
|
||||
PerformanceLevelGet (
|
||||
IN SCMI_PERFORMANCE_PROTOCOL *This,
|
||||
IN UINT32 DomainId,
|
||||
OUT UINT32 *Level
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 PayloadLength;
|
||||
SCMI_COMMAND Cmd;
|
||||
UINT32 *ReturnValues;
|
||||
UINT32 *MessageParams;
|
||||
|
||||
Status = ScmiCommandGetPayload (&MessageParams);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
*MessageParams = DomainId;
|
||||
|
||||
Cmd.ProtocolId = ScmiProtocolIdPerformance;
|
||||
Cmd.MessageId = ScmiMessageIdPerformanceLevelGet;
|
||||
|
||||
PayloadLength = sizeof (DomainId);
|
||||
|
||||
Status = ScmiCommandExecute (
|
||||
&Cmd,
|
||||
&PayloadLength,
|
||||
&ReturnValues
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
*Level = *ReturnValues;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
// Instance of the SCMI performance management protocol.
|
||||
STATIC CONST SCMI_PERFORMANCE_PROTOCOL PerformanceProtocol = {
|
||||
PerformanceGetVersion,
|
||||
PerformanceGetAttributes,
|
||||
PerformanceDomainAttributes,
|
||||
PerformanceDescribeLevels,
|
||||
PerformanceLimitsSet,
|
||||
PerformanceLimitsGet,
|
||||
PerformanceLevelSet,
|
||||
PerformanceLevelGet
|
||||
};
|
||||
|
||||
/** Initialize performance management protocol and install on a given Handle.
|
||||
|
||||
@param[in] Handle Handle to install performance management
|
||||
protocol.
|
||||
|
||||
@retval EFI_SUCCESS Performance protocol installed successfully.
|
||||
**/
|
||||
EFI_STATUS
|
||||
ScmiPerformanceProtocolInit (
|
||||
IN EFI_HANDLE *Handle
|
||||
)
|
||||
{
|
||||
return gBS->InstallMultipleProtocolInterfaces (
|
||||
Handle,
|
||||
&gArmScmiPerformanceProtocolGuid,
|
||||
&PerformanceProtocol,
|
||||
NULL
|
||||
);
|
||||
}
|
169
ArmPkg/Drivers/ArmScmiDxe/ScmiPrivate.h
Normal file
169
ArmPkg/Drivers/ArmScmiDxe/ScmiPrivate.h
Normal file
@ -0,0 +1,169 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2017-2021, Arm Limited. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
System Control and Management Interface V1.0
|
||||
http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/
|
||||
DEN0056A_System_Control_and_Management_Interface.pdf
|
||||
**/
|
||||
|
||||
#ifndef SCMI_PRIVATE_H_
|
||||
#define SCMI_PRIVATE_H_
|
||||
|
||||
// SCMI protocol IDs.
|
||||
typedef enum {
|
||||
ScmiProtocolIdBase = 0x10,
|
||||
ScmiProtocolIdPowerDomain = 0x11,
|
||||
ScmiProtocolIdSystemPower = 0x12,
|
||||
ScmiProtocolIdPerformance = 0x13,
|
||||
ScmiProtocolIdClock = 0x14,
|
||||
ScmiProtocolIdSensor = 0x15
|
||||
} SCMI_PROTOCOL_ID;
|
||||
|
||||
// SCMI message types.
|
||||
typedef enum {
|
||||
ScmiMessageTypeCommand = 0,
|
||||
ScmiMessageTypeDelayedResponse = 2, // Skipping 1 is deliberate.
|
||||
ScmiMessageTypeNotification = 3
|
||||
} SCMI_MESSAGE_TYPE;
|
||||
|
||||
// SCMI response error codes.
|
||||
typedef enum {
|
||||
ScmiSuccess = 0,
|
||||
ScmiNotSupported = -1,
|
||||
ScmiInvalidParameters = -2,
|
||||
ScmiDenied = -3,
|
||||
ScmiNotFound = -4,
|
||||
ScmiOutOfRange = -5,
|
||||
ScmiBusy = -6,
|
||||
ScmiCommsError = -7,
|
||||
ScmiGenericError = -8,
|
||||
ScmiHardwareError = -9,
|
||||
ScmiProtocolError = -10
|
||||
} SCMI_STATUS;
|
||||
|
||||
// SCMI message IDs common to all protocols.
|
||||
typedef enum {
|
||||
ScmiMessageIdProtocolVersion = 0x0,
|
||||
ScmiMessageIdProtocolAttributes = 0x1,
|
||||
ScmiMessageIdProtocolMessageAttributes = 0x2
|
||||
} SCMI_MESSAGE_ID;
|
||||
|
||||
// Not defined in SCMI specification but will help to identify a message.
|
||||
typedef struct {
|
||||
SCMI_PROTOCOL_ID ProtocolId;
|
||||
UINT32 MessageId;
|
||||
} SCMI_COMMAND;
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
// Response to a SCMI command.
|
||||
typedef struct {
|
||||
INT32 Status;
|
||||
UINT32 ReturnValues[];
|
||||
} SCMI_MESSAGE_RESPONSE;
|
||||
|
||||
// Message header. MsgId[7:0], MsgType[9:8], ProtocolId[17:10]
|
||||
#define MESSAGE_TYPE_SHIFT 8
|
||||
#define PROTOCOL_ID_SHIFT 10
|
||||
#define SCMI_MESSAGE_HEADER(MsgId, MsgType, ProtocolId) ( \
|
||||
MsgType << MESSAGE_TYPE_SHIFT | \
|
||||
ProtocolId << PROTOCOL_ID_SHIFT | \
|
||||
MsgId \
|
||||
)
|
||||
// SCMI message header.
|
||||
typedef struct {
|
||||
UINT32 MessageHeader;
|
||||
} SCMI_MESSAGE_HEADER;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
/** Return a pointer to the message payload.
|
||||
|
||||
@param[out] Payload Holds pointer to the message payload.
|
||||
|
||||
@retval EFI_SUCCESS Payload holds a valid message payload pointer.
|
||||
@retval EFI_TIMEOUT Time out error if MTL channel is busy.
|
||||
@retval EFI_UNSUPPORTED If MTL channel is unsupported.
|
||||
**/
|
||||
EFI_STATUS
|
||||
ScmiCommandGetPayload (
|
||||
OUT UINT32 **Payload
|
||||
);
|
||||
|
||||
/** Execute a SCMI command and receive a response.
|
||||
|
||||
This function uses a MTL channel to transfer message to SCP
|
||||
and waits for a response.
|
||||
|
||||
@param[in] Command Pointer to the SCMI command (Protocol ID
|
||||
and Message ID)
|
||||
|
||||
@param[in,out] PayloadLength SCMI command message length.
|
||||
|
||||
@param[out] OPTIONAL ReturnValues Pointer to SCMI response.
|
||||
|
||||
@retval OUT EFI_SUCCESS Command sent and message received successfully.
|
||||
@retval OUT EFI_UNSUPPORTED Channel not supported.
|
||||
@retval OUT EFI_TIMEOUT Timeout on the channel.
|
||||
@retval OUT EFI_DEVICE_ERROR Channel not ready.
|
||||
@retval OUT EFI_DEVICE_ERROR Message Header corrupted.
|
||||
@retval OUT EFI_DEVICE_ERROR SCMI error.
|
||||
**/
|
||||
EFI_STATUS
|
||||
ScmiCommandExecute (
|
||||
IN SCMI_COMMAND *Command,
|
||||
IN OUT UINT32 *PayloadLength,
|
||||
OUT UINT32 **ReturnValues OPTIONAL
|
||||
);
|
||||
|
||||
/** Return protocol version from SCP for a given protocol ID.
|
||||
|
||||
@param[in] Protocol ID Protocol ID.
|
||||
@param[out] Version Pointer to version of the protocol.
|
||||
|
||||
@retval EFI_SUCCESS Version holds a valid version received
|
||||
from the SCP.
|
||||
@retval EFI_DEVICE_ERROR SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
EFI_STATUS
|
||||
ScmiGetProtocolVersion (
|
||||
IN SCMI_PROTOCOL_ID ProtocolId,
|
||||
OUT UINT32 *Version
|
||||
);
|
||||
|
||||
/** Return protocol attributes from SCP for a given protocol ID.
|
||||
|
||||
@param[in] Protocol ID Protocol ID.
|
||||
@param[out] ReturnValues Pointer to attributes of the protocol.
|
||||
|
||||
@retval EFI_SUCCESS ReturnValues points to protocol attributes.
|
||||
@retval EFI_DEVICE_ERROR SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
EFI_STATUS
|
||||
ScmiGetProtocolAttributes (
|
||||
IN SCMI_PROTOCOL_ID ProtocolId,
|
||||
OUT UINT32 **ReturnValues
|
||||
);
|
||||
|
||||
/** Return protocol message attributes from SCP for a given protocol ID.
|
||||
|
||||
@param[in] Protocol ID Protocol ID.
|
||||
|
||||
@param[out] Attributes Pointer to attributes of the protocol.
|
||||
|
||||
@retval EFI_SUCCESS ReturnValues points to protocol message attributes.
|
||||
@retval EFI_DEVICE_ERROR SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
EFI_STATUS
|
||||
ScmiGetProtocolMessageAttributes (
|
||||
IN SCMI_PROTOCOL_ID ProtocolId,
|
||||
OUT UINT32 **ReturnValues
|
||||
);
|
||||
|
||||
#endif /* SCMI_PRIVATE_H_ */
|
433
ArmPkg/Drivers/CpuDxe/AArch64/Mmu.c
Normal file
433
ArmPkg/Drivers/CpuDxe/AArch64/Mmu.c
Normal file
@ -0,0 +1,433 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2009, Hewlett-Packard Company. All rights reserved.<BR>
|
||||
Portions copyright (c) 2010, Apple Inc. All rights reserved.<BR>
|
||||
Portions copyright (c) 2011-2021, Arm Limited. All rights reserved.<BR>
|
||||
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include "CpuDxe.h"
|
||||
|
||||
#define INVALID_ENTRY ((UINT32)~0)
|
||||
|
||||
#define MIN_T0SZ 16
|
||||
#define BITS_PER_LEVEL 9
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
GetRootTranslationTableInfo (
|
||||
IN UINTN T0SZ,
|
||||
OUT UINTN *RootTableLevel,
|
||||
OUT UINTN *RootTableEntryCount
|
||||
)
|
||||
{
|
||||
*RootTableLevel = (T0SZ - MIN_T0SZ) / BITS_PER_LEVEL;
|
||||
*RootTableEntryCount = TT_ENTRY_COUNT >> (T0SZ - MIN_T0SZ) % BITS_PER_LEVEL;
|
||||
}
|
||||
|
||||
STATIC
|
||||
UINT64
|
||||
PageAttributeToGcdAttribute (
|
||||
IN UINT64 PageAttributes
|
||||
)
|
||||
{
|
||||
UINT64 GcdAttributes;
|
||||
|
||||
switch (PageAttributes & TT_ATTR_INDX_MASK) {
|
||||
case TT_ATTR_INDX_DEVICE_MEMORY:
|
||||
GcdAttributes = EFI_MEMORY_UC;
|
||||
break;
|
||||
case TT_ATTR_INDX_MEMORY_NON_CACHEABLE:
|
||||
GcdAttributes = EFI_MEMORY_WC;
|
||||
break;
|
||||
case TT_ATTR_INDX_MEMORY_WRITE_THROUGH:
|
||||
GcdAttributes = EFI_MEMORY_WT;
|
||||
break;
|
||||
case TT_ATTR_INDX_MEMORY_WRITE_BACK:
|
||||
GcdAttributes = EFI_MEMORY_WB;
|
||||
break;
|
||||
default:
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"PageAttributeToGcdAttribute: PageAttributes:0x%lX not supported.\n",
|
||||
PageAttributes
|
||||
));
|
||||
ASSERT (0);
|
||||
// The Global Coherency Domain (GCD) value is defined as a bit set.
|
||||
// Returning 0 means no attribute has been set.
|
||||
GcdAttributes = 0;
|
||||
}
|
||||
|
||||
// Determine protection attributes
|
||||
if (((PageAttributes & TT_AP_MASK) == TT_AP_NO_RO) ||
|
||||
((PageAttributes & TT_AP_MASK) == TT_AP_RO_RO))
|
||||
{
|
||||
// Read only cases map to write-protect
|
||||
GcdAttributes |= EFI_MEMORY_RO;
|
||||
}
|
||||
|
||||
// Process eXecute Never attribute
|
||||
if ((PageAttributes & (TT_PXN_MASK | TT_UXN_MASK)) != 0) {
|
||||
GcdAttributes |= EFI_MEMORY_XP;
|
||||
}
|
||||
|
||||
return GcdAttributes;
|
||||
}
|
||||
|
||||
STATIC
|
||||
UINT64
|
||||
GetFirstPageAttribute (
|
||||
IN UINT64 *FirstLevelTableAddress,
|
||||
IN UINTN TableLevel
|
||||
)
|
||||
{
|
||||
UINT64 FirstEntry;
|
||||
|
||||
// Get the first entry of the table
|
||||
FirstEntry = *FirstLevelTableAddress;
|
||||
|
||||
if ((TableLevel != 3) && ((FirstEntry & TT_TYPE_MASK) == TT_TYPE_TABLE_ENTRY)) {
|
||||
// Only valid for Levels 0, 1 and 2
|
||||
|
||||
// Get the attribute of the subsequent table
|
||||
return GetFirstPageAttribute ((UINT64 *)(FirstEntry & TT_ADDRESS_MASK_DESCRIPTION_TABLE), TableLevel + 1);
|
||||
} else if (((FirstEntry & TT_TYPE_MASK) == TT_TYPE_BLOCK_ENTRY) ||
|
||||
((TableLevel == 3) && ((FirstEntry & TT_TYPE_MASK) == TT_TYPE_BLOCK_ENTRY_LEVEL3)))
|
||||
{
|
||||
return FirstEntry & TT_ATTR_INDX_MASK;
|
||||
} else {
|
||||
return INVALID_ENTRY;
|
||||
}
|
||||
}
|
||||
|
||||
STATIC
|
||||
UINT64
|
||||
GetNextEntryAttribute (
|
||||
IN UINT64 *TableAddress,
|
||||
IN UINTN EntryCount,
|
||||
IN UINTN TableLevel,
|
||||
IN UINT64 BaseAddress,
|
||||
IN OUT UINT32 *PrevEntryAttribute,
|
||||
IN OUT UINT64 *StartGcdRegion
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
UINT64 Entry;
|
||||
UINT32 EntryAttribute;
|
||||
UINT32 EntryType;
|
||||
EFI_STATUS Status;
|
||||
UINTN NumberOfDescriptors;
|
||||
EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
|
||||
|
||||
// Get the memory space map from GCD
|
||||
MemorySpaceMap = NULL;
|
||||
Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
// We cannot get more than 3-level page table
|
||||
ASSERT (TableLevel <= 3);
|
||||
|
||||
// While the top level table might not contain TT_ENTRY_COUNT entries;
|
||||
// the subsequent ones should be filled up
|
||||
for (Index = 0; Index < EntryCount; Index++) {
|
||||
Entry = TableAddress[Index];
|
||||
EntryType = Entry & TT_TYPE_MASK;
|
||||
EntryAttribute = Entry & TT_ATTR_INDX_MASK;
|
||||
|
||||
// If Entry is a Table Descriptor type entry then go through the sub-level table
|
||||
if ((EntryType == TT_TYPE_BLOCK_ENTRY) ||
|
||||
((TableLevel == 3) && (EntryType == TT_TYPE_BLOCK_ENTRY_LEVEL3)))
|
||||
{
|
||||
if ((*PrevEntryAttribute == INVALID_ENTRY) || (EntryAttribute != *PrevEntryAttribute)) {
|
||||
if (*PrevEntryAttribute != INVALID_ENTRY) {
|
||||
// Update GCD with the last region
|
||||
SetGcdMemorySpaceAttributes (
|
||||
MemorySpaceMap,
|
||||
NumberOfDescriptors,
|
||||
*StartGcdRegion,
|
||||
(BaseAddress + (Index * TT_ADDRESS_AT_LEVEL (TableLevel))) - *StartGcdRegion,
|
||||
PageAttributeToGcdAttribute (*PrevEntryAttribute)
|
||||
);
|
||||
}
|
||||
|
||||
// Start of the new region
|
||||
*StartGcdRegion = BaseAddress + (Index * TT_ADDRESS_AT_LEVEL (TableLevel));
|
||||
*PrevEntryAttribute = EntryAttribute;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
} else if (EntryType == TT_TYPE_TABLE_ENTRY) {
|
||||
// Table Entry type is only valid for Level 0, 1, 2
|
||||
ASSERT (TableLevel < 3);
|
||||
|
||||
// Increase the level number and scan the sub-level table
|
||||
GetNextEntryAttribute (
|
||||
(UINT64 *)(Entry & TT_ADDRESS_MASK_DESCRIPTION_TABLE),
|
||||
TT_ENTRY_COUNT,
|
||||
TableLevel + 1,
|
||||
(BaseAddress + (Index * TT_ADDRESS_AT_LEVEL (TableLevel))),
|
||||
PrevEntryAttribute,
|
||||
StartGcdRegion
|
||||
);
|
||||
} else {
|
||||
if (*PrevEntryAttribute != INVALID_ENTRY) {
|
||||
// Update GCD with the last region
|
||||
SetGcdMemorySpaceAttributes (
|
||||
MemorySpaceMap,
|
||||
NumberOfDescriptors,
|
||||
*StartGcdRegion,
|
||||
(BaseAddress + (Index * TT_ADDRESS_AT_LEVEL (TableLevel))) - *StartGcdRegion,
|
||||
PageAttributeToGcdAttribute (*PrevEntryAttribute)
|
||||
);
|
||||
|
||||
// Start of the new region
|
||||
*StartGcdRegion = BaseAddress + (Index * TT_ADDRESS_AT_LEVEL (TableLevel));
|
||||
*PrevEntryAttribute = INVALID_ENTRY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FreePool (MemorySpaceMap);
|
||||
|
||||
return BaseAddress + (EntryCount * TT_ADDRESS_AT_LEVEL (TableLevel));
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
SyncCacheConfig (
|
||||
IN EFI_CPU_ARCH_PROTOCOL *CpuProtocol
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 PageAttribute;
|
||||
UINT64 *FirstLevelTableAddress;
|
||||
UINTN TableLevel;
|
||||
UINTN TableCount;
|
||||
UINTN NumberOfDescriptors;
|
||||
EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
|
||||
UINTN Tcr;
|
||||
UINTN T0SZ;
|
||||
UINT64 BaseAddressGcdRegion;
|
||||
UINT64 EndAddressGcdRegion;
|
||||
|
||||
// This code assumes MMU is enabled and filed with section translations
|
||||
ASSERT (ArmMmuEnabled ());
|
||||
|
||||
//
|
||||
// Get the memory space map from GCD
|
||||
//
|
||||
MemorySpaceMap = NULL;
|
||||
Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
// The GCD implementation maintains its own copy of the state of memory space attributes. GCD needs
|
||||
// to know what the initial memory space attributes are. The CPU Arch. Protocol does not provide a
|
||||
// GetMemoryAttributes function for GCD to get this so we must resort to calling GCD (as if we were
|
||||
// a client) to update its copy of the attributes. This is bad architecture and should be replaced
|
||||
// with a way for GCD to query the CPU Arch. driver of the existing memory space attributes instead.
|
||||
|
||||
// Obtain page table base
|
||||
FirstLevelTableAddress = (UINT64 *)(ArmGetTTBR0BaseAddress ());
|
||||
|
||||
// Get Translation Control Register value
|
||||
Tcr = ArmGetTCR ();
|
||||
// Get Address Region Size
|
||||
T0SZ = Tcr & TCR_T0SZ_MASK;
|
||||
|
||||
// Get the level of the first table for the indicated Address Region Size
|
||||
GetRootTranslationTableInfo (T0SZ, &TableLevel, &TableCount);
|
||||
|
||||
// First Attribute of the Page Tables
|
||||
PageAttribute = GetFirstPageAttribute (FirstLevelTableAddress, TableLevel);
|
||||
|
||||
// We scan from the start of the memory map (ie: at the address 0x0)
|
||||
BaseAddressGcdRegion = 0x0;
|
||||
EndAddressGcdRegion = GetNextEntryAttribute (
|
||||
FirstLevelTableAddress,
|
||||
TableCount,
|
||||
TableLevel,
|
||||
BaseAddressGcdRegion,
|
||||
&PageAttribute,
|
||||
&BaseAddressGcdRegion
|
||||
);
|
||||
|
||||
// Update GCD with the last region if valid
|
||||
if (PageAttribute != INVALID_ENTRY) {
|
||||
SetGcdMemorySpaceAttributes (
|
||||
MemorySpaceMap,
|
||||
NumberOfDescriptors,
|
||||
BaseAddressGcdRegion,
|
||||
EndAddressGcdRegion - BaseAddressGcdRegion,
|
||||
PageAttributeToGcdAttribute (PageAttribute)
|
||||
);
|
||||
}
|
||||
|
||||
FreePool (MemorySpaceMap);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
UINT64
|
||||
EfiAttributeToArmAttribute (
|
||||
IN UINT64 EfiAttributes
|
||||
)
|
||||
{
|
||||
UINT64 ArmAttributes;
|
||||
|
||||
switch (EfiAttributes & EFI_MEMORY_CACHETYPE_MASK) {
|
||||
case EFI_MEMORY_UC:
|
||||
if (ArmReadCurrentEL () == AARCH64_EL2) {
|
||||
ArmAttributes = TT_ATTR_INDX_DEVICE_MEMORY | TT_XN_MASK;
|
||||
} else {
|
||||
ArmAttributes = TT_ATTR_INDX_DEVICE_MEMORY | TT_UXN_MASK | TT_PXN_MASK;
|
||||
}
|
||||
|
||||
break;
|
||||
case EFI_MEMORY_WC:
|
||||
ArmAttributes = TT_ATTR_INDX_MEMORY_NON_CACHEABLE;
|
||||
break;
|
||||
case EFI_MEMORY_WT:
|
||||
ArmAttributes = TT_ATTR_INDX_MEMORY_WRITE_THROUGH | TT_SH_INNER_SHAREABLE;
|
||||
break;
|
||||
case EFI_MEMORY_WB:
|
||||
ArmAttributes = TT_ATTR_INDX_MEMORY_WRITE_BACK | TT_SH_INNER_SHAREABLE;
|
||||
break;
|
||||
default:
|
||||
ArmAttributes = TT_ATTR_INDX_MASK;
|
||||
}
|
||||
|
||||
// Set the access flag to match the block attributes
|
||||
ArmAttributes |= TT_AF;
|
||||
|
||||
// Determine protection attributes
|
||||
if ((EfiAttributes & EFI_MEMORY_RO) != 0) {
|
||||
ArmAttributes |= TT_AP_NO_RO;
|
||||
}
|
||||
|
||||
// Process eXecute Never attribute
|
||||
if ((EfiAttributes & EFI_MEMORY_XP) != 0) {
|
||||
ArmAttributes |= TT_PXN_MASK;
|
||||
}
|
||||
|
||||
return ArmAttributes;
|
||||
}
|
||||
|
||||
// This function will recursively go down the page table to find the first block address linked to 'BaseAddress'.
|
||||
// And then the function will identify the size of the region that has the same page table attribute.
|
||||
EFI_STATUS
|
||||
GetMemoryRegionRec (
|
||||
IN UINT64 *TranslationTable,
|
||||
IN UINTN TableLevel,
|
||||
IN UINT64 *LastBlockEntry,
|
||||
IN OUT UINTN *BaseAddress,
|
||||
OUT UINTN *RegionLength,
|
||||
OUT UINTN *RegionAttributes
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT64 *NextTranslationTable;
|
||||
UINT64 *BlockEntry;
|
||||
UINT64 BlockEntryType;
|
||||
UINT64 EntryType;
|
||||
|
||||
if (TableLevel != 3) {
|
||||
BlockEntryType = TT_TYPE_BLOCK_ENTRY;
|
||||
} else {
|
||||
BlockEntryType = TT_TYPE_BLOCK_ENTRY_LEVEL3;
|
||||
}
|
||||
|
||||
// Find the block entry linked to the Base Address
|
||||
BlockEntry = (UINT64 *)TT_GET_ENTRY_FOR_ADDRESS (TranslationTable, TableLevel, *BaseAddress);
|
||||
EntryType = *BlockEntry & TT_TYPE_MASK;
|
||||
|
||||
if ((TableLevel < 3) && (EntryType == TT_TYPE_TABLE_ENTRY)) {
|
||||
NextTranslationTable = (UINT64 *)(*BlockEntry & TT_ADDRESS_MASK_DESCRIPTION_TABLE);
|
||||
|
||||
// The entry is a page table, so we go to the next level
|
||||
Status = GetMemoryRegionRec (
|
||||
NextTranslationTable, // Address of the next level page table
|
||||
TableLevel + 1, // Next Page Table level
|
||||
(UINTN *)TT_LAST_BLOCK_ADDRESS (NextTranslationTable, TT_ENTRY_COUNT),
|
||||
BaseAddress,
|
||||
RegionLength,
|
||||
RegionAttributes
|
||||
);
|
||||
|
||||
// In case of 'Success', it means the end of the block region has been found into the upper
|
||||
// level translation table
|
||||
if (!EFI_ERROR (Status)) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
// Now we processed the table move to the next entry
|
||||
BlockEntry++;
|
||||
} else if (EntryType == BlockEntryType) {
|
||||
// We have found the BlockEntry attached to the address. We save its start address (the start
|
||||
// address might be before the 'BaseAddress') and attributes
|
||||
*BaseAddress = *BaseAddress & ~(TT_ADDRESS_AT_LEVEL (TableLevel) - 1);
|
||||
*RegionLength = 0;
|
||||
*RegionAttributes = *BlockEntry & TT_ATTRIBUTES_MASK;
|
||||
} else {
|
||||
// We have an 'Invalid' entry
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
while (BlockEntry <= LastBlockEntry) {
|
||||
if ((*BlockEntry & TT_ATTRIBUTES_MASK) == *RegionAttributes) {
|
||||
*RegionLength = *RegionLength + TT_BLOCK_ENTRY_SIZE_AT_LEVEL (TableLevel);
|
||||
} else {
|
||||
// In case we have found the end of the region we return success
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
BlockEntry++;
|
||||
}
|
||||
|
||||
// If we have reached the end of the TranslationTable and we have not found the end of the region then
|
||||
// we return EFI_NOT_FOUND.
|
||||
// The caller will continue to look for the memory region at its level
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
GetMemoryRegion (
|
||||
IN OUT UINTN *BaseAddress,
|
||||
OUT UINTN *RegionLength,
|
||||
OUT UINTN *RegionAttributes
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT64 *TranslationTable;
|
||||
UINTN TableLevel;
|
||||
UINTN EntryCount;
|
||||
UINTN T0SZ;
|
||||
|
||||
ASSERT ((BaseAddress != NULL) && (RegionLength != NULL) && (RegionAttributes != NULL));
|
||||
|
||||
TranslationTable = ArmGetTTBR0BaseAddress ();
|
||||
|
||||
T0SZ = ArmGetTCR () & TCR_T0SZ_MASK;
|
||||
// Get the Table info from T0SZ
|
||||
GetRootTranslationTableInfo (T0SZ, &TableLevel, &EntryCount);
|
||||
|
||||
Status = GetMemoryRegionRec (
|
||||
TranslationTable,
|
||||
TableLevel,
|
||||
(UINTN *)TT_LAST_BLOCK_ADDRESS (TranslationTable, EntryCount),
|
||||
BaseAddress,
|
||||
RegionLength,
|
||||
RegionAttributes
|
||||
);
|
||||
|
||||
// If the region continues up to the end of the root table then GetMemoryRegionRec()
|
||||
// will return EFI_NOT_FOUND
|
||||
if (Status == EFI_NOT_FOUND) {
|
||||
return EFI_SUCCESS;
|
||||
} else {
|
||||
return Status;
|
||||
}
|
||||
}
|
518
ArmPkg/Drivers/CpuDxe/Arm/Mmu.c
Normal file
518
ArmPkg/Drivers/CpuDxe/Arm/Mmu.c
Normal file
@ -0,0 +1,518 @@
|
||||
/*++
|
||||
|
||||
Copyright (c) 2009, Hewlett-Packard Company. All rights reserved.<BR>
|
||||
Portions copyright (c) 2010, Apple Inc. All rights reserved.<BR>
|
||||
Portions copyright (c) 2013-2021, Arm Limited. All rights reserved.<BR>
|
||||
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include "CpuDxe.h"
|
||||
|
||||
EFI_STATUS
|
||||
SectionToGcdAttributes (
|
||||
IN UINT32 SectionAttributes,
|
||||
OUT UINT64 *GcdAttributes
|
||||
)
|
||||
{
|
||||
*GcdAttributes = 0;
|
||||
|
||||
// determine cacheability attributes
|
||||
switch (SectionAttributes & TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK) {
|
||||
case TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED:
|
||||
*GcdAttributes |= EFI_MEMORY_UC;
|
||||
break;
|
||||
case TT_DESCRIPTOR_SECTION_CACHE_POLICY_SHAREABLE_DEVICE:
|
||||
*GcdAttributes |= EFI_MEMORY_UC;
|
||||
break;
|
||||
case TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC:
|
||||
*GcdAttributes |= EFI_MEMORY_WT;
|
||||
break;
|
||||
case TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_NO_ALLOC:
|
||||
*GcdAttributes |= EFI_MEMORY_WB;
|
||||
break;
|
||||
case TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE:
|
||||
*GcdAttributes |= EFI_MEMORY_WC;
|
||||
break;
|
||||
case TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC:
|
||||
*GcdAttributes |= EFI_MEMORY_WB;
|
||||
break;
|
||||
case TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_SHAREABLE_DEVICE:
|
||||
*GcdAttributes |= EFI_MEMORY_UC;
|
||||
break;
|
||||
default:
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
// determine protection attributes
|
||||
switch (SectionAttributes & TT_DESCRIPTOR_SECTION_AP_MASK) {
|
||||
case TT_DESCRIPTOR_SECTION_AP_NO_NO: // no read, no write
|
||||
// *GcdAttributes |= EFI_MEMORY_RO | EFI_MEMORY_RP;
|
||||
break;
|
||||
|
||||
case TT_DESCRIPTOR_SECTION_AP_RW_NO:
|
||||
case TT_DESCRIPTOR_SECTION_AP_RW_RW:
|
||||
// normal read/write access, do not add additional attributes
|
||||
break;
|
||||
|
||||
// read only cases map to write-protect
|
||||
case TT_DESCRIPTOR_SECTION_AP_RO_NO:
|
||||
case TT_DESCRIPTOR_SECTION_AP_RO_RO:
|
||||
*GcdAttributes |= EFI_MEMORY_RO;
|
||||
break;
|
||||
|
||||
default:
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
// now process eXectue Never attribute
|
||||
if ((SectionAttributes & TT_DESCRIPTOR_SECTION_XN_MASK) != 0 ) {
|
||||
*GcdAttributes |= EFI_MEMORY_XP;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
PageToGcdAttributes (
|
||||
IN UINT32 PageAttributes,
|
||||
OUT UINT64 *GcdAttributes
|
||||
)
|
||||
{
|
||||
*GcdAttributes = 0;
|
||||
|
||||
// determine cacheability attributes
|
||||
switch (PageAttributes & TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK) {
|
||||
case TT_DESCRIPTOR_PAGE_CACHE_POLICY_STRONGLY_ORDERED:
|
||||
*GcdAttributes |= EFI_MEMORY_UC;
|
||||
break;
|
||||
case TT_DESCRIPTOR_PAGE_CACHE_POLICY_SHAREABLE_DEVICE:
|
||||
*GcdAttributes |= EFI_MEMORY_UC;
|
||||
break;
|
||||
case TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC:
|
||||
*GcdAttributes |= EFI_MEMORY_WT;
|
||||
break;
|
||||
case TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_NO_ALLOC:
|
||||
*GcdAttributes |= EFI_MEMORY_WB;
|
||||
break;
|
||||
case TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE:
|
||||
*GcdAttributes |= EFI_MEMORY_WC;
|
||||
break;
|
||||
case TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_ALLOC:
|
||||
*GcdAttributes |= EFI_MEMORY_WB;
|
||||
break;
|
||||
case TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_SHAREABLE_DEVICE:
|
||||
*GcdAttributes |= EFI_MEMORY_UC;
|
||||
break;
|
||||
default:
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
// determine protection attributes
|
||||
switch (PageAttributes & TT_DESCRIPTOR_PAGE_AP_MASK) {
|
||||
case TT_DESCRIPTOR_PAGE_AP_NO_NO: // no read, no write
|
||||
// *GcdAttributes |= EFI_MEMORY_RO | EFI_MEMORY_RP;
|
||||
break;
|
||||
|
||||
case TT_DESCRIPTOR_PAGE_AP_RW_NO:
|
||||
case TT_DESCRIPTOR_PAGE_AP_RW_RW:
|
||||
// normal read/write access, do not add additional attributes
|
||||
break;
|
||||
|
||||
// read only cases map to write-protect
|
||||
case TT_DESCRIPTOR_PAGE_AP_RO_NO:
|
||||
case TT_DESCRIPTOR_PAGE_AP_RO_RO:
|
||||
*GcdAttributes |= EFI_MEMORY_RO;
|
||||
break;
|
||||
|
||||
default:
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
// now process eXectue Never attribute
|
||||
if ((PageAttributes & TT_DESCRIPTOR_PAGE_XN_MASK) != 0 ) {
|
||||
*GcdAttributes |= EFI_MEMORY_XP;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
SyncCacheConfigPage (
|
||||
IN UINT32 SectionIndex,
|
||||
IN UINT32 FirstLevelDescriptor,
|
||||
IN UINTN NumberOfDescriptors,
|
||||
IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,
|
||||
IN OUT EFI_PHYSICAL_ADDRESS *NextRegionBase,
|
||||
IN OUT UINT64 *NextRegionLength,
|
||||
IN OUT UINT32 *NextSectionAttributes
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 i;
|
||||
volatile ARM_PAGE_TABLE_ENTRY *SecondLevelTable;
|
||||
UINT32 NextPageAttributes;
|
||||
UINT32 PageAttributes;
|
||||
UINT32 BaseAddress;
|
||||
UINT64 GcdAttributes;
|
||||
|
||||
// Get the Base Address from FirstLevelDescriptor;
|
||||
BaseAddress = TT_DESCRIPTOR_PAGE_BASE_ADDRESS (SectionIndex << TT_DESCRIPTOR_SECTION_BASE_SHIFT);
|
||||
|
||||
// Convert SectionAttributes into PageAttributes
|
||||
NextPageAttributes =
|
||||
TT_DESCRIPTOR_CONVERT_TO_PAGE_CACHE_POLICY (*NextSectionAttributes, 0) |
|
||||
TT_DESCRIPTOR_CONVERT_TO_PAGE_AP (*NextSectionAttributes);
|
||||
|
||||
// obtain page table base
|
||||
SecondLevelTable = (ARM_PAGE_TABLE_ENTRY *)(FirstLevelDescriptor & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK);
|
||||
|
||||
for (i = 0; i < TRANSLATION_TABLE_PAGE_COUNT; i++) {
|
||||
if ((SecondLevelTable[i] & TT_DESCRIPTOR_PAGE_TYPE_MASK) == TT_DESCRIPTOR_PAGE_TYPE_PAGE) {
|
||||
// extract attributes (cacheability and permissions)
|
||||
PageAttributes = SecondLevelTable[i] & (TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK | TT_DESCRIPTOR_PAGE_AP_MASK);
|
||||
|
||||
if (NextPageAttributes == 0) {
|
||||
// start on a new region
|
||||
*NextRegionLength = 0;
|
||||
*NextRegionBase = BaseAddress | (i << TT_DESCRIPTOR_PAGE_BASE_SHIFT);
|
||||
NextPageAttributes = PageAttributes;
|
||||
} else if (PageAttributes != NextPageAttributes) {
|
||||
// Convert Section Attributes into GCD Attributes
|
||||
Status = PageToGcdAttributes (NextPageAttributes, &GcdAttributes);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
// update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)
|
||||
SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, *NextRegionBase, *NextRegionLength, GcdAttributes);
|
||||
|
||||
// start on a new region
|
||||
*NextRegionLength = 0;
|
||||
*NextRegionBase = BaseAddress | (i << TT_DESCRIPTOR_PAGE_BASE_SHIFT);
|
||||
NextPageAttributes = PageAttributes;
|
||||
}
|
||||
} else if (NextPageAttributes != 0) {
|
||||
// Convert Page Attributes into GCD Attributes
|
||||
Status = PageToGcdAttributes (NextPageAttributes, &GcdAttributes);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
// update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)
|
||||
SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, *NextRegionBase, *NextRegionLength, GcdAttributes);
|
||||
|
||||
*NextRegionLength = 0;
|
||||
*NextRegionBase = BaseAddress | (i << TT_DESCRIPTOR_PAGE_BASE_SHIFT);
|
||||
NextPageAttributes = 0;
|
||||
}
|
||||
|
||||
*NextRegionLength += TT_DESCRIPTOR_PAGE_SIZE;
|
||||
}
|
||||
|
||||
// Convert back PageAttributes into SectionAttributes
|
||||
*NextSectionAttributes =
|
||||
TT_DESCRIPTOR_CONVERT_TO_SECTION_CACHE_POLICY (NextPageAttributes, 0) |
|
||||
TT_DESCRIPTOR_CONVERT_TO_SECTION_AP (NextPageAttributes);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
SyncCacheConfig (
|
||||
IN EFI_CPU_ARCH_PROTOCOL *CpuProtocol
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 i;
|
||||
EFI_PHYSICAL_ADDRESS NextRegionBase;
|
||||
UINT64 NextRegionLength;
|
||||
UINT32 NextSectionAttributes;
|
||||
UINT32 SectionAttributes;
|
||||
UINT64 GcdAttributes;
|
||||
volatile ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;
|
||||
UINTN NumberOfDescriptors;
|
||||
EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
|
||||
|
||||
DEBUG ((DEBUG_PAGE, "SyncCacheConfig()\n"));
|
||||
|
||||
// This code assumes MMU is enabled and filed with section translations
|
||||
ASSERT (ArmMmuEnabled ());
|
||||
|
||||
//
|
||||
// Get the memory space map from GCD
|
||||
//
|
||||
MemorySpaceMap = NULL;
|
||||
Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
// The GCD implementation maintains its own copy of the state of memory space attributes. GCD needs
|
||||
// to know what the initial memory space attributes are. The CPU Arch. Protocol does not provide a
|
||||
// GetMemoryAttributes function for GCD to get this so we must resort to calling GCD (as if we were
|
||||
// a client) to update its copy of the attributes. This is bad architecture and should be replaced
|
||||
// with a way for GCD to query the CPU Arch. driver of the existing memory space attributes instead.
|
||||
|
||||
// obtain page table base
|
||||
FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)(ArmGetTTBR0BaseAddress ());
|
||||
|
||||
// Get the first region
|
||||
NextSectionAttributes = FirstLevelTable[0] & (TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK | TT_DESCRIPTOR_SECTION_AP_MASK);
|
||||
|
||||
// iterate through each 1MB descriptor
|
||||
NextRegionBase = NextRegionLength = 0;
|
||||
for (i = 0; i < TRANSLATION_TABLE_SECTION_COUNT; i++) {
|
||||
if ((FirstLevelTable[i] & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SECTION) {
|
||||
// extract attributes (cacheability and permissions)
|
||||
SectionAttributes = FirstLevelTable[i] & (TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK | TT_DESCRIPTOR_SECTION_AP_MASK);
|
||||
|
||||
if (NextSectionAttributes == 0) {
|
||||
// start on a new region
|
||||
NextRegionLength = 0;
|
||||
NextRegionBase = TT_DESCRIPTOR_SECTION_BASE_ADDRESS (i << TT_DESCRIPTOR_SECTION_BASE_SHIFT);
|
||||
NextSectionAttributes = SectionAttributes;
|
||||
} else if (SectionAttributes != NextSectionAttributes) {
|
||||
// Convert Section Attributes into GCD Attributes
|
||||
Status = SectionToGcdAttributes (NextSectionAttributes, &GcdAttributes);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
// update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)
|
||||
SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, NextRegionBase, NextRegionLength, GcdAttributes);
|
||||
|
||||
// start on a new region
|
||||
NextRegionLength = 0;
|
||||
NextRegionBase = TT_DESCRIPTOR_SECTION_BASE_ADDRESS (i << TT_DESCRIPTOR_SECTION_BASE_SHIFT);
|
||||
NextSectionAttributes = SectionAttributes;
|
||||
}
|
||||
|
||||
NextRegionLength += TT_DESCRIPTOR_SECTION_SIZE;
|
||||
} else if (TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE (FirstLevelTable[i])) {
|
||||
// In this case any bits set in the 'NextSectionAttributes' are garbage and were set from
|
||||
// bits that are actually part of the pagetable address. We clear it out to zero so that
|
||||
// the SyncCacheConfigPage will use the page attributes instead of trying to convert the
|
||||
// section attributes into page attributes
|
||||
NextSectionAttributes = 0;
|
||||
Status = SyncCacheConfigPage (
|
||||
i,
|
||||
FirstLevelTable[i],
|
||||
NumberOfDescriptors,
|
||||
MemorySpaceMap,
|
||||
&NextRegionBase,
|
||||
&NextRegionLength,
|
||||
&NextSectionAttributes
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
} else {
|
||||
// We do not support yet 16MB sections
|
||||
ASSERT ((FirstLevelTable[i] & TT_DESCRIPTOR_SECTION_TYPE_MASK) != TT_DESCRIPTOR_SECTION_TYPE_SUPERSECTION);
|
||||
|
||||
// start on a new region
|
||||
if (NextSectionAttributes != 0) {
|
||||
// Convert Section Attributes into GCD Attributes
|
||||
Status = SectionToGcdAttributes (NextSectionAttributes, &GcdAttributes);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
// update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)
|
||||
SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, NextRegionBase, NextRegionLength, GcdAttributes);
|
||||
|
||||
NextRegionLength = 0;
|
||||
NextRegionBase = TT_DESCRIPTOR_SECTION_BASE_ADDRESS (i << TT_DESCRIPTOR_SECTION_BASE_SHIFT);
|
||||
NextSectionAttributes = 0;
|
||||
}
|
||||
|
||||
NextRegionLength += TT_DESCRIPTOR_SECTION_SIZE;
|
||||
}
|
||||
} // section entry loop
|
||||
|
||||
if (NextSectionAttributes != 0) {
|
||||
// Convert Section Attributes into GCD Attributes
|
||||
Status = SectionToGcdAttributes (NextSectionAttributes, &GcdAttributes);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
// update GCD with these changes (this will recurse into our own CpuSetMemoryAttributes below which is OK)
|
||||
SetGcdMemorySpaceAttributes (MemorySpaceMap, NumberOfDescriptors, NextRegionBase, NextRegionLength, GcdAttributes);
|
||||
}
|
||||
|
||||
FreePool (MemorySpaceMap);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
UINT64
|
||||
EfiAttributeToArmAttribute (
|
||||
IN UINT64 EfiAttributes
|
||||
)
|
||||
{
|
||||
UINT64 ArmAttributes;
|
||||
|
||||
switch (EfiAttributes & EFI_MEMORY_CACHETYPE_MASK) {
|
||||
case EFI_MEMORY_UC:
|
||||
// Map to strongly ordered
|
||||
ArmAttributes = TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED; // TEX[2:0] = 0, C=0, B=0
|
||||
break;
|
||||
|
||||
case EFI_MEMORY_WC:
|
||||
// Map to normal non-cacheable
|
||||
ArmAttributes = TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE; // TEX [2:0]= 001 = 0x2, B=0, C=0
|
||||
break;
|
||||
|
||||
case EFI_MEMORY_WT:
|
||||
// Write through with no-allocate
|
||||
ArmAttributes = TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC; // TEX [2:0] = 0, C=1, B=0
|
||||
break;
|
||||
|
||||
case EFI_MEMORY_WB:
|
||||
// Write back (with allocate)
|
||||
ArmAttributes = TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC; // TEX [2:0] = 001, C=1, B=1
|
||||
break;
|
||||
|
||||
case EFI_MEMORY_UCE:
|
||||
default:
|
||||
ArmAttributes = TT_DESCRIPTOR_SECTION_TYPE_FAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
// Determine protection attributes
|
||||
if ((EfiAttributes & EFI_MEMORY_RO) != 0) {
|
||||
ArmAttributes |= TT_DESCRIPTOR_SECTION_AP_RO_RO;
|
||||
} else {
|
||||
ArmAttributes |= TT_DESCRIPTOR_SECTION_AP_RW_RW;
|
||||
}
|
||||
|
||||
// Determine eXecute Never attribute
|
||||
if ((EfiAttributes & EFI_MEMORY_XP) != 0) {
|
||||
ArmAttributes |= TT_DESCRIPTOR_SECTION_XN_MASK;
|
||||
}
|
||||
|
||||
return ArmAttributes;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
GetMemoryRegionPage (
|
||||
IN UINT32 *PageTable,
|
||||
IN OUT UINTN *BaseAddress,
|
||||
OUT UINTN *RegionLength,
|
||||
OUT UINTN *RegionAttributes
|
||||
)
|
||||
{
|
||||
UINT32 PageAttributes;
|
||||
UINT32 TableIndex;
|
||||
UINT32 PageDescriptor;
|
||||
|
||||
// Convert the section attributes into page attributes
|
||||
PageAttributes = ConvertSectionAttributesToPageAttributes (*RegionAttributes, 0);
|
||||
|
||||
// Calculate index into first level translation table for start of modification
|
||||
TableIndex = ((*BaseAddress) & TT_DESCRIPTOR_PAGE_INDEX_MASK) >> TT_DESCRIPTOR_PAGE_BASE_SHIFT;
|
||||
ASSERT (TableIndex < TRANSLATION_TABLE_PAGE_COUNT);
|
||||
|
||||
// Go through the page table to find the end of the section
|
||||
for ( ; TableIndex < TRANSLATION_TABLE_PAGE_COUNT; TableIndex++) {
|
||||
// Get the section at the given index
|
||||
PageDescriptor = PageTable[TableIndex];
|
||||
|
||||
if ((PageDescriptor & TT_DESCRIPTOR_PAGE_TYPE_MASK) == TT_DESCRIPTOR_PAGE_TYPE_FAULT) {
|
||||
// Case: End of the boundary of the region
|
||||
return EFI_SUCCESS;
|
||||
} else if ((PageDescriptor & TT_DESCRIPTOR_PAGE_TYPE_PAGE) == TT_DESCRIPTOR_PAGE_TYPE_PAGE) {
|
||||
if ((PageDescriptor & TT_DESCRIPTOR_PAGE_ATTRIBUTE_MASK) == PageAttributes) {
|
||||
*RegionLength = *RegionLength + TT_DESCRIPTOR_PAGE_SIZE;
|
||||
} else {
|
||||
// Case: End of the boundary of the region
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
} else {
|
||||
// We do not support Large Page yet. We return EFI_SUCCESS that means end of the region.
|
||||
ASSERT (0);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
GetMemoryRegion (
|
||||
IN OUT UINTN *BaseAddress,
|
||||
OUT UINTN *RegionLength,
|
||||
OUT UINTN *RegionAttributes
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 TableIndex;
|
||||
UINT32 PageAttributes;
|
||||
UINT32 PageTableIndex;
|
||||
UINT32 SectionDescriptor;
|
||||
ARM_FIRST_LEVEL_DESCRIPTOR *FirstLevelTable;
|
||||
UINT32 *PageTable;
|
||||
|
||||
// Initialize the arguments
|
||||
*RegionLength = 0;
|
||||
|
||||
// Obtain page table base
|
||||
FirstLevelTable = (ARM_FIRST_LEVEL_DESCRIPTOR *)ArmGetTTBR0BaseAddress ();
|
||||
|
||||
// Calculate index into first level translation table for start of modification
|
||||
TableIndex = TT_DESCRIPTOR_SECTION_BASE_ADDRESS (*BaseAddress) >> TT_DESCRIPTOR_SECTION_BASE_SHIFT;
|
||||
ASSERT (TableIndex < TRANSLATION_TABLE_SECTION_COUNT);
|
||||
|
||||
// Get the section at the given index
|
||||
SectionDescriptor = FirstLevelTable[TableIndex];
|
||||
if (!SectionDescriptor) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
// If 'BaseAddress' belongs to the section then round it to the section boundary
|
||||
if (((SectionDescriptor & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SECTION) ||
|
||||
((SectionDescriptor & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SUPERSECTION))
|
||||
{
|
||||
*BaseAddress = (*BaseAddress) & TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK;
|
||||
*RegionAttributes = SectionDescriptor & TT_DESCRIPTOR_SECTION_ATTRIBUTE_MASK;
|
||||
} else {
|
||||
// Otherwise, we round it to the page boundary
|
||||
*BaseAddress = (*BaseAddress) & TT_DESCRIPTOR_PAGE_BASE_ADDRESS_MASK;
|
||||
|
||||
// Get the attribute at the page table level (Level 2)
|
||||
PageTable = (UINT32 *)(SectionDescriptor & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK);
|
||||
|
||||
// Calculate index into first level translation table for start of modification
|
||||
PageTableIndex = ((*BaseAddress) & TT_DESCRIPTOR_PAGE_INDEX_MASK) >> TT_DESCRIPTOR_PAGE_BASE_SHIFT;
|
||||
ASSERT (PageTableIndex < TRANSLATION_TABLE_PAGE_COUNT);
|
||||
|
||||
PageAttributes = PageTable[PageTableIndex] & TT_DESCRIPTOR_PAGE_ATTRIBUTE_MASK;
|
||||
*RegionAttributes = TT_DESCRIPTOR_CONVERT_TO_SECTION_CACHE_POLICY (PageAttributes, 0) |
|
||||
TT_DESCRIPTOR_CONVERT_TO_SECTION_AP (PageAttributes);
|
||||
}
|
||||
|
||||
for ( ; TableIndex < TRANSLATION_TABLE_SECTION_COUNT; TableIndex++) {
|
||||
// Get the section at the given index
|
||||
SectionDescriptor = FirstLevelTable[TableIndex];
|
||||
|
||||
// If the entry is a level-2 page table then we scan it to find the end of the region
|
||||
if (TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE (SectionDescriptor)) {
|
||||
// Extract the page table location from the descriptor
|
||||
PageTable = (UINT32 *)(SectionDescriptor & TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK);
|
||||
|
||||
// Scan the page table to find the end of the region.
|
||||
Status = GetMemoryRegionPage (PageTable, BaseAddress, RegionLength, RegionAttributes);
|
||||
|
||||
// If we have found the end of the region (Status == EFI_SUCCESS) then we exit the for-loop
|
||||
if (Status == EFI_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
} else if (((SectionDescriptor & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SECTION) ||
|
||||
((SectionDescriptor & TT_DESCRIPTOR_SECTION_TYPE_MASK) == TT_DESCRIPTOR_SECTION_TYPE_SUPERSECTION))
|
||||
{
|
||||
if ((SectionDescriptor & TT_DESCRIPTOR_SECTION_ATTRIBUTE_MASK) != *RegionAttributes) {
|
||||
// If the attributes of the section differ from the one targeted then we exit the loop
|
||||
break;
|
||||
} else {
|
||||
*RegionLength = *RegionLength + TT_DESCRIPTOR_SECTION_SIZE;
|
||||
}
|
||||
} else {
|
||||
// If we are on an invalid section then it means it is the end of our section.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
273
ArmPkg/Drivers/CpuDxe/CpuDxe.c
Normal file
273
ArmPkg/Drivers/CpuDxe/CpuDxe.c
Normal file
@ -0,0 +1,273 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
|
||||
Copyright (c) 2011, ARM Limited. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "CpuDxe.h"
|
||||
|
||||
#include <Guid/IdleLoopEvent.h>
|
||||
|
||||
BOOLEAN mIsFlushingGCD;
|
||||
|
||||
/**
|
||||
This function flushes the range of addresses from Start to Start+Length
|
||||
from the processor's data cache. If Start is not aligned to a cache line
|
||||
boundary, then the bytes before Start to the preceding cache line boundary
|
||||
are also flushed. If Start+Length is not aligned to a cache line boundary,
|
||||
then the bytes past Start+Length to the end of the next cache line boundary
|
||||
are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be
|
||||
supported. If the data cache is fully coherent with all DMA operations, then
|
||||
this function can just return EFI_SUCCESS. If the processor does not support
|
||||
flushing a range of the data cache, then the entire data cache can be flushed.
|
||||
|
||||
@param This The EFI_CPU_ARCH_PROTOCOL instance.
|
||||
@param Start The beginning physical address to flush from the processor's data
|
||||
cache.
|
||||
@param Length The number of bytes to flush from the processor's data cache. This
|
||||
function may flush more bytes than Length specifies depending upon
|
||||
the granularity of the flush operation that the processor supports.
|
||||
@param FlushType Specifies the type of flush operation to perform.
|
||||
|
||||
@retval EFI_SUCCESS The address range from Start to Start+Length was flushed from
|
||||
the processor's data cache.
|
||||
@retval EFI_UNSUPPORTED The processor does not support the cache flush type specified
|
||||
by FlushType.
|
||||
@retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed
|
||||
from the processor's data cache.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
CpuFlushCpuDataCache (
|
||||
IN EFI_CPU_ARCH_PROTOCOL *This,
|
||||
IN EFI_PHYSICAL_ADDRESS Start,
|
||||
IN UINT64 Length,
|
||||
IN EFI_CPU_FLUSH_TYPE FlushType
|
||||
)
|
||||
{
|
||||
switch (FlushType) {
|
||||
case EfiCpuFlushTypeWriteBack:
|
||||
WriteBackDataCacheRange ((VOID *)(UINTN)Start, (UINTN)Length);
|
||||
break;
|
||||
case EfiCpuFlushTypeInvalidate:
|
||||
InvalidateDataCacheRange ((VOID *)(UINTN)Start, (UINTN)Length);
|
||||
break;
|
||||
case EfiCpuFlushTypeWriteBackInvalidate:
|
||||
WriteBackInvalidateDataCacheRange ((VOID *)(UINTN)Start, (UINTN)Length);
|
||||
break;
|
||||
default:
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
This function enables interrupt processing by the processor.
|
||||
|
||||
@param This The EFI_CPU_ARCH_PROTOCOL instance.
|
||||
|
||||
@retval EFI_SUCCESS Interrupts are enabled on the processor.
|
||||
@retval EFI_DEVICE_ERROR Interrupts could not be enabled on the processor.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
CpuEnableInterrupt (
|
||||
IN EFI_CPU_ARCH_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
ArmEnableInterrupts ();
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
This function disables interrupt processing by the processor.
|
||||
|
||||
@param This The EFI_CPU_ARCH_PROTOCOL instance.
|
||||
|
||||
@retval EFI_SUCCESS Interrupts are disabled on the processor.
|
||||
@retval EFI_DEVICE_ERROR Interrupts could not be disabled on the processor.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
CpuDisableInterrupt (
|
||||
IN EFI_CPU_ARCH_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
ArmDisableInterrupts ();
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
This function retrieves the processor's current interrupt state a returns it in
|
||||
State. If interrupts are currently enabled, then TRUE is returned. If interrupts
|
||||
are currently disabled, then FALSE is returned.
|
||||
|
||||
@param This The EFI_CPU_ARCH_PROTOCOL instance.
|
||||
@param State A pointer to the processor's current interrupt state. Set to TRUE if
|
||||
interrupts are enabled and FALSE if interrupts are disabled.
|
||||
|
||||
@retval EFI_SUCCESS The processor's current interrupt state was returned in State.
|
||||
@retval EFI_INVALID_PARAMETER State is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
CpuGetInterruptState (
|
||||
IN EFI_CPU_ARCH_PROTOCOL *This,
|
||||
OUT BOOLEAN *State
|
||||
)
|
||||
{
|
||||
if (State == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*State = ArmGetInterruptState ();
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
This function generates an INIT on the processor. If this function succeeds, then the
|
||||
processor will be reset, and control will not be returned to the caller. If InitType is
|
||||
not supported by this processor, or the processor cannot programmatically generate an
|
||||
INIT without help from external hardware, then EFI_UNSUPPORTED is returned. If an error
|
||||
occurs attempting to generate an INIT, then EFI_DEVICE_ERROR is returned.
|
||||
|
||||
@param This The EFI_CPU_ARCH_PROTOCOL instance.
|
||||
@param InitType The type of processor INIT to perform.
|
||||
|
||||
@retval EFI_SUCCESS The processor INIT was performed. This return code should never be seen.
|
||||
@retval EFI_UNSUPPORTED The processor INIT operation specified by InitType is not supported
|
||||
by this processor.
|
||||
@retval EFI_DEVICE_ERROR The processor INIT failed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
CpuInit (
|
||||
IN EFI_CPU_ARCH_PROTOCOL *This,
|
||||
IN EFI_CPU_INIT_TYPE InitType
|
||||
)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
CpuRegisterInterruptHandler (
|
||||
IN EFI_CPU_ARCH_PROTOCOL *This,
|
||||
IN EFI_EXCEPTION_TYPE InterruptType,
|
||||
IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
|
||||
)
|
||||
{
|
||||
return RegisterInterruptHandler (InterruptType, InterruptHandler);
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
CpuGetTimerValue (
|
||||
IN EFI_CPU_ARCH_PROTOCOL *This,
|
||||
IN UINT32 TimerIndex,
|
||||
OUT UINT64 *TimerValue,
|
||||
OUT UINT64 *TimerPeriod OPTIONAL
|
||||
)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
Callback function for idle events.
|
||||
|
||||
@param Event Event whose notification function is being invoked.
|
||||
@param Context The pointer to the notification function's context,
|
||||
which is implementation-dependent.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
IdleLoopEventCallback (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
CpuSleep ();
|
||||
}
|
||||
|
||||
//
|
||||
// Globals used to initialize the protocol
|
||||
//
|
||||
EFI_HANDLE mCpuHandle = NULL;
|
||||
EFI_CPU_ARCH_PROTOCOL mCpu = {
|
||||
CpuFlushCpuDataCache,
|
||||
CpuEnableInterrupt,
|
||||
CpuDisableInterrupt,
|
||||
CpuGetInterruptState,
|
||||
CpuInit,
|
||||
CpuRegisterInterruptHandler,
|
||||
CpuGetTimerValue,
|
||||
CpuSetMemoryAttributes,
|
||||
0, // NumberOfTimers
|
||||
2048, // DmaBufferAlignment
|
||||
};
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
InitializeDma (
|
||||
IN OUT EFI_CPU_ARCH_PROTOCOL *CpuArchProtocol
|
||||
)
|
||||
{
|
||||
CpuArchProtocol->DmaBufferAlignment = ArmCacheWritebackGranule ();
|
||||
}
|
||||
|
||||
EFI_STATUS
|
||||
CpuDxeInitialize (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_EVENT IdleLoopEvent;
|
||||
|
||||
InitializeExceptions (&mCpu);
|
||||
|
||||
InitializeDma (&mCpu);
|
||||
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&mCpuHandle,
|
||||
&gEfiCpuArchProtocolGuid,
|
||||
&mCpu,
|
||||
NULL
|
||||
);
|
||||
|
||||
//
|
||||
// Make sure GCD and MMU settings match. This API calls gDS->SetMemorySpaceAttributes ()
|
||||
// and that calls EFI_CPU_ARCH_PROTOCOL.SetMemoryAttributes, so this code needs to go
|
||||
// after the protocol is installed
|
||||
//
|
||||
mIsFlushingGCD = TRUE;
|
||||
SyncCacheConfig (&mCpu);
|
||||
mIsFlushingGCD = FALSE;
|
||||
|
||||
//
|
||||
// Setup a callback for idle events
|
||||
//
|
||||
Status = gBS->CreateEventEx (
|
||||
EVT_NOTIFY_SIGNAL,
|
||||
TPL_NOTIFY,
|
||||
IdleLoopEventCallback,
|
||||
NULL,
|
||||
&gIdleLoopEventGuid,
|
||||
&IdleLoopEvent
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
return Status;
|
||||
}
|
129
ArmPkg/Drivers/CpuDxe/CpuDxe.h
Normal file
129
ArmPkg/Drivers/CpuDxe/CpuDxe.h
Normal file
@ -0,0 +1,129 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
|
||||
Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef CPU_DXE_H_
|
||||
#define CPU_DXE_H_
|
||||
|
||||
#include <Uefi.h>
|
||||
|
||||
#include <Library/ArmLib.h>
|
||||
#include <Library/ArmMmuLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/DxeServicesTableLib.h>
|
||||
#include <Library/CacheMaintenanceLib.h>
|
||||
#include <Library/PeCoffGetEntryPointLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/CpuLib.h>
|
||||
#include <Library/DefaultExceptionHandlerLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
|
||||
#include <Guid/DebugImageInfoTable.h>
|
||||
#include <Protocol/Cpu.h>
|
||||
#include <Protocol/DebugSupport.h>
|
||||
#include <Protocol/LoadedImage.h>
|
||||
|
||||
extern BOOLEAN mIsFlushingGCD;
|
||||
|
||||
/**
|
||||
This function registers and enables the handler specified by InterruptHandler for a processor
|
||||
interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
|
||||
handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
|
||||
The installed handler is called once for each processor interrupt or exception.
|
||||
|
||||
@param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
|
||||
are enabled and FALSE if interrupts are disabled.
|
||||
@param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
|
||||
when a processor interrupt occurs. If this parameter is NULL, then the handler
|
||||
will be uninstalled.
|
||||
|
||||
@retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
|
||||
@retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
|
||||
previously installed.
|
||||
@retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
|
||||
previously installed.
|
||||
@retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
RegisterInterruptHandler (
|
||||
IN EFI_EXCEPTION_TYPE InterruptType,
|
||||
IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
|
||||
);
|
||||
|
||||
/**
|
||||
This function registers and enables the handler specified by InterruptHandler for a processor
|
||||
interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
|
||||
handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
|
||||
The installed handler is called once for each processor interrupt or exception.
|
||||
|
||||
@param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
|
||||
are enabled and FALSE if interrupts are disabled.
|
||||
@param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
|
||||
when a processor interrupt occurs. If this parameter is NULL, then the handler
|
||||
will be uninstalled.
|
||||
|
||||
@retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
|
||||
@retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
|
||||
previously installed.
|
||||
@retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
|
||||
previously installed.
|
||||
@retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
RegisterDebuggerInterruptHandler (
|
||||
IN EFI_EXCEPTION_TYPE InterruptType,
|
||||
IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
CpuSetMemoryAttributes (
|
||||
IN EFI_CPU_ARCH_PROTOCOL *This,
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length,
|
||||
IN UINT64 Attributes
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
InitializeExceptions (
|
||||
IN EFI_CPU_ARCH_PROTOCOL *Cpu
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
SyncCacheConfig (
|
||||
IN EFI_CPU_ARCH_PROTOCOL *CpuProtocol
|
||||
);
|
||||
|
||||
// The ARM Attributes might be defined on 64-bit (case of the long format description table)
|
||||
UINT64
|
||||
EfiAttributeToArmAttribute (
|
||||
IN UINT64 EfiAttributes
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
GetMemoryRegion (
|
||||
IN OUT UINTN *BaseAddress,
|
||||
OUT UINTN *RegionLength,
|
||||
OUT UINTN *RegionAttributes
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
SetGcdMemorySpaceAttributes (
|
||||
IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,
|
||||
IN UINTN NumberOfDescriptors,
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length,
|
||||
IN UINT64 Attributes
|
||||
);
|
||||
|
||||
#endif // CPU_DXE_H_
|
70
ArmPkg/Drivers/CpuDxe/CpuDxe.inf
Normal file
70
ArmPkg/Drivers/CpuDxe/CpuDxe.inf
Normal file
@ -0,0 +1,70 @@
|
||||
#/** @file
|
||||
#
|
||||
# DXE CPU driver
|
||||
#
|
||||
# Copyright (c) 2009, Apple Inc. All rights reserved.<BR>
|
||||
# Copyright (c) 2011-2013, ARM Limited. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
#**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = ArmCpuDxe
|
||||
FILE_GUID = B8D9777E-D72A-451F-9BDB-BAFB52A68415
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
|
||||
ENTRY_POINT = CpuDxeInitialize
|
||||
|
||||
[Sources.Common]
|
||||
CpuDxe.c
|
||||
CpuDxe.h
|
||||
CpuMmuCommon.c
|
||||
Exception.c
|
||||
|
||||
[Sources.ARM]
|
||||
Arm/Mmu.c
|
||||
|
||||
[Sources.AARCH64]
|
||||
AArch64/Mmu.c
|
||||
|
||||
[Packages]
|
||||
ArmPkg/ArmPkg.dec
|
||||
EmbeddedPkg/EmbeddedPkg.dec
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
ArmLib
|
||||
ArmMmuLib
|
||||
BaseMemoryLib
|
||||
CacheMaintenanceLib
|
||||
CpuLib
|
||||
CpuExceptionHandlerLib
|
||||
DebugLib
|
||||
DefaultExceptionHandlerLib
|
||||
DxeServicesTableLib
|
||||
HobLib
|
||||
PeCoffGetEntryPointLib
|
||||
UefiDriverEntryPoint
|
||||
UefiLib
|
||||
|
||||
[Protocols]
|
||||
gEfiCpuArchProtocolGuid
|
||||
|
||||
[Guids]
|
||||
gEfiDebugImageInfoTableGuid
|
||||
gArmMpCoreInfoGuid
|
||||
gIdleLoopEventGuid
|
||||
gEfiVectorHandoffTableGuid
|
||||
|
||||
[Pcd.common]
|
||||
gArmTokenSpaceGuid.PcdVFPEnabled
|
||||
|
||||
[FeaturePcd.common]
|
||||
gArmTokenSpaceGuid.PcdDebuggerExceptionSupport
|
||||
|
||||
[Depex]
|
||||
gHardwareInterruptProtocolGuid OR gHardwareInterrupt2ProtocolGuid
|
224
ArmPkg/Drivers/CpuDxe/CpuMmuCommon.c
Normal file
224
ArmPkg/Drivers/CpuDxe/CpuMmuCommon.c
Normal file
@ -0,0 +1,224 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2013, ARM Limited. All rights reserved.
|
||||
* Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#include "CpuDxe.h"
|
||||
|
||||
/**
|
||||
Searches memory descriptors covered by given memory range.
|
||||
|
||||
This function searches into the Gcd Memory Space for descriptors
|
||||
(from StartIndex to EndIndex) that contains the memory range
|
||||
specified by BaseAddress and Length.
|
||||
|
||||
@param MemorySpaceMap Gcd Memory Space Map as array.
|
||||
@param NumberOfDescriptors Number of descriptors in map.
|
||||
@param BaseAddress BaseAddress for the requested range.
|
||||
@param Length Length for the requested range.
|
||||
@param StartIndex Start index into the Gcd Memory Space Map.
|
||||
@param EndIndex End index into the Gcd Memory Space Map.
|
||||
|
||||
@retval EFI_SUCCESS Search successfully.
|
||||
@retval EFI_NOT_FOUND The requested descriptors does not exist.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SearchGcdMemorySpaces (
|
||||
IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,
|
||||
IN UINTN NumberOfDescriptors,
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length,
|
||||
OUT UINTN *StartIndex,
|
||||
OUT UINTN *EndIndex
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
|
||||
*StartIndex = 0;
|
||||
*EndIndex = 0;
|
||||
for (Index = 0; Index < NumberOfDescriptors; Index++) {
|
||||
if ((BaseAddress >= MemorySpaceMap[Index].BaseAddress) &&
|
||||
(BaseAddress < (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length)))
|
||||
{
|
||||
*StartIndex = Index;
|
||||
}
|
||||
|
||||
if (((BaseAddress + Length - 1) >= MemorySpaceMap[Index].BaseAddress) &&
|
||||
((BaseAddress + Length - 1) < (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length)))
|
||||
{
|
||||
*EndIndex = Index;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
/**
|
||||
Sets the attributes for a specified range in Gcd Memory Space Map.
|
||||
|
||||
This function sets the attributes for a specified range in
|
||||
Gcd Memory Space Map.
|
||||
|
||||
@param MemorySpaceMap Gcd Memory Space Map as array
|
||||
@param NumberOfDescriptors Number of descriptors in map
|
||||
@param BaseAddress BaseAddress for the range
|
||||
@param Length Length for the range
|
||||
@param Attributes Attributes to set
|
||||
|
||||
@retval EFI_SUCCESS Memory attributes set successfully
|
||||
@retval EFI_NOT_FOUND The specified range does not exist in Gcd Memory Space
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SetGcdMemorySpaceAttributes (
|
||||
IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap,
|
||||
IN UINTN NumberOfDescriptors,
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length,
|
||||
IN UINT64 Attributes
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN Index;
|
||||
UINTN StartIndex;
|
||||
UINTN EndIndex;
|
||||
EFI_PHYSICAL_ADDRESS RegionStart;
|
||||
UINT64 RegionLength;
|
||||
|
||||
DEBUG ((
|
||||
DEBUG_GCD,
|
||||
"SetGcdMemorySpaceAttributes[0x%lX; 0x%lX] = 0x%lX\n",
|
||||
BaseAddress,
|
||||
BaseAddress + Length,
|
||||
Attributes
|
||||
));
|
||||
|
||||
// We do not support a smaller granularity than 4KB on ARM Architecture
|
||||
if ((Length & EFI_PAGE_MASK) != 0) {
|
||||
DEBUG ((
|
||||
DEBUG_WARN,
|
||||
"Warning: We do not support smaller granularity than 4KB on ARM Architecture (passed length: 0x%lX).\n",
|
||||
Length
|
||||
));
|
||||
}
|
||||
|
||||
//
|
||||
// Get all memory descriptors covered by the memory range
|
||||
//
|
||||
Status = SearchGcdMemorySpaces (
|
||||
MemorySpaceMap,
|
||||
NumberOfDescriptors,
|
||||
BaseAddress,
|
||||
Length,
|
||||
&StartIndex,
|
||||
&EndIndex
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Go through all related descriptors and set attributes accordingly
|
||||
//
|
||||
for (Index = StartIndex; Index <= EndIndex; Index++) {
|
||||
if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate the start and end address of the overlapping range
|
||||
//
|
||||
if (BaseAddress >= MemorySpaceMap[Index].BaseAddress) {
|
||||
RegionStart = BaseAddress;
|
||||
} else {
|
||||
RegionStart = MemorySpaceMap[Index].BaseAddress;
|
||||
}
|
||||
|
||||
if ((BaseAddress + Length - 1) < (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length)) {
|
||||
RegionLength = BaseAddress + Length - RegionStart;
|
||||
} else {
|
||||
RegionLength = MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - RegionStart;
|
||||
}
|
||||
|
||||
//
|
||||
// Set memory attributes according to MTRR attribute and the original attribute of descriptor
|
||||
//
|
||||
gDS->SetMemorySpaceAttributes (
|
||||
RegionStart,
|
||||
RegionLength,
|
||||
(MemorySpaceMap[Index].Attributes & ~EFI_MEMORY_CACHETYPE_MASK) | (MemorySpaceMap[Index].Capabilities & Attributes)
|
||||
);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
This function modifies the attributes for the memory region specified by BaseAddress and
|
||||
Length from their current attributes to the attributes specified by Attributes.
|
||||
|
||||
@param This The EFI_CPU_ARCH_PROTOCOL instance.
|
||||
@param BaseAddress The physical address that is the start address of a memory region.
|
||||
@param Length The size in bytes of the memory region.
|
||||
@param Attributes The bit mask of attributes to set for the memory region.
|
||||
|
||||
@retval EFI_SUCCESS The attributes were set for the memory region.
|
||||
@retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
|
||||
BaseAddress and Length cannot be modified.
|
||||
@retval EFI_INVALID_PARAMETER Length is zero.
|
||||
@retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
|
||||
the memory resource range.
|
||||
@retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
|
||||
resource range specified by BaseAddress and Length.
|
||||
The bit mask of attributes is not support for the memory resource
|
||||
range specified by BaseAddress and Length.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
CpuSetMemoryAttributes (
|
||||
IN EFI_CPU_ARCH_PROTOCOL *This,
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length,
|
||||
IN UINT64 EfiAttributes
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN ArmAttributes;
|
||||
UINTN RegionBaseAddress;
|
||||
UINTN RegionLength;
|
||||
UINTN RegionArmAttributes;
|
||||
|
||||
if (mIsFlushingGCD) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
if ((BaseAddress & (SIZE_4KB - 1)) != 0) {
|
||||
// Minimum granularity is SIZE_4KB (4KB on ARM)
|
||||
DEBUG ((DEBUG_PAGE, "CpuSetMemoryAttributes(%lx, %lx, %lx): Minimum granularity is SIZE_4KB\n", BaseAddress, Length, EfiAttributes));
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
// Convert the 'Attribute' into ARM Attribute
|
||||
ArmAttributes = EfiAttributeToArmAttribute (EfiAttributes);
|
||||
|
||||
// Get the region starting from 'BaseAddress' and its 'Attribute'
|
||||
RegionBaseAddress = BaseAddress;
|
||||
Status = GetMemoryRegion (&RegionBaseAddress, &RegionLength, &RegionArmAttributes);
|
||||
|
||||
// Data & Instruction Caches are flushed when we set new memory attributes.
|
||||
// So, we only set the attributes if the new region is different.
|
||||
if (EFI_ERROR (Status) || (RegionArmAttributes != ArmAttributes) ||
|
||||
((BaseAddress + Length) > (RegionBaseAddress + RegionLength)))
|
||||
{
|
||||
return ArmSetMemoryAttributes (BaseAddress, Length, EfiAttributes);
|
||||
} else {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
100
ArmPkg/Drivers/CpuDxe/Exception.c
Normal file
100
ArmPkg/Drivers/CpuDxe/Exception.c
Normal file
@ -0,0 +1,100 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
|
||||
Portions Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "CpuDxe.h"
|
||||
#include <Library/CpuExceptionHandlerLib.h>
|
||||
#include <Guid/VectorHandoffTable.h>
|
||||
|
||||
EFI_STATUS
|
||||
InitializeExceptions (
|
||||
IN EFI_CPU_ARCH_PROTOCOL *Cpu
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_VECTOR_HANDOFF_INFO *VectorInfoList;
|
||||
EFI_VECTOR_HANDOFF_INFO *VectorInfo;
|
||||
BOOLEAN IrqEnabled;
|
||||
BOOLEAN FiqEnabled;
|
||||
|
||||
VectorInfo = (EFI_VECTOR_HANDOFF_INFO *)NULL;
|
||||
Status = EfiGetSystemConfigurationTable (&gEfiVectorHandoffTableGuid, (VOID **)&VectorInfoList);
|
||||
if ((Status == EFI_SUCCESS) && (VectorInfoList != NULL)) {
|
||||
VectorInfo = VectorInfoList;
|
||||
}
|
||||
|
||||
// initialize the CpuExceptionHandlerLib so we take over the exception vector table from the DXE Core
|
||||
InitializeCpuExceptionHandlers (VectorInfo);
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
//
|
||||
// Disable interrupts
|
||||
//
|
||||
Cpu->GetInterruptState (Cpu, &IrqEnabled);
|
||||
Cpu->DisableInterrupt (Cpu);
|
||||
|
||||
//
|
||||
// EFI does not use the FIQ, but a debugger might so we must disable
|
||||
// as we take over the exception vectors.
|
||||
//
|
||||
FiqEnabled = ArmGetFiqState ();
|
||||
ArmDisableFiq ();
|
||||
|
||||
if (FiqEnabled) {
|
||||
ArmEnableFiq ();
|
||||
}
|
||||
|
||||
if (IrqEnabled) {
|
||||
//
|
||||
// Restore interrupt state
|
||||
//
|
||||
Status = Cpu->EnableInterrupt (Cpu);
|
||||
}
|
||||
|
||||
//
|
||||
// On a DEBUG build, unmask SErrors so they are delivered right away rather
|
||||
// than when the OS unmasks them. This gives us a better chance of figuring
|
||||
// out the cause.
|
||||
//
|
||||
DEBUG_CODE (
|
||||
ArmEnableAsynchronousAbort ();
|
||||
);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
This function registers and enables the handler specified by InterruptHandler for a processor
|
||||
interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the
|
||||
handler for the processor interrupt or exception type specified by InterruptType is uninstalled.
|
||||
The installed handler is called once for each processor interrupt or exception.
|
||||
|
||||
@param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts
|
||||
are enabled and FALSE if interrupts are disabled.
|
||||
@param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called
|
||||
when a processor interrupt occurs. If this parameter is NULL, then the handler
|
||||
will be uninstalled.
|
||||
|
||||
@retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled.
|
||||
@retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was
|
||||
previously installed.
|
||||
@retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not
|
||||
previously installed.
|
||||
@retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
RegisterInterruptHandler (
|
||||
IN EFI_EXCEPTION_TYPE InterruptType,
|
||||
IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler
|
||||
)
|
||||
{
|
||||
// pass down to CpuExceptionHandlerLib
|
||||
return (EFI_STATUS)RegisterCpuInterruptHandler (InterruptType, InterruptHandler);
|
||||
}
|
83
ArmPkg/Drivers/CpuPei/CpuPei.c
Normal file
83
ArmPkg/Drivers/CpuPei/CpuPei.c
Normal file
@ -0,0 +1,83 @@
|
||||
/**@file
|
||||
|
||||
Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2011 Hewlett Packard Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2011-2013, ARM Limited. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
Module Name:
|
||||
|
||||
MemoryInit.c
|
||||
|
||||
Abstract:
|
||||
|
||||
PEIM to provide fake memory init
|
||||
|
||||
**/
|
||||
|
||||
//
|
||||
// The package level header files this module uses
|
||||
//
|
||||
#include <PiPei.h>
|
||||
//
|
||||
// The protocols, PPI and GUID definitions for this module
|
||||
//
|
||||
#include <Ppi/ArmMpCoreInfo.h>
|
||||
|
||||
//
|
||||
// The Library classes this module consumes
|
||||
//
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/PeimEntryPoint.h>
|
||||
#include <Library/PeiServicesLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/HobLib.h>
|
||||
#include <Library/ArmLib.h>
|
||||
|
||||
/*++
|
||||
|
||||
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
|
||||
InitializeCpuPeim (
|
||||
IN EFI_PEI_FILE_HANDLE FileHandle,
|
||||
IN CONST EFI_PEI_SERVICES **PeiServices
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
ARM_MP_CORE_INFO_PPI *ArmMpCoreInfoPpi;
|
||||
UINTN ArmCoreCount;
|
||||
ARM_CORE_INFO *ArmCoreInfoTable;
|
||||
|
||||
// Enable program flow prediction, if supported.
|
||||
ArmEnableBranchPrediction ();
|
||||
|
||||
// Publish the CPU memory and io spaces sizes
|
||||
BuildCpuHob (ArmGetPhysicalAddressBits (), PcdGet8 (PcdPrePiCpuIoSize));
|
||||
|
||||
// Only MP Core platform need to produce gArmMpCoreInfoPpiGuid
|
||||
Status = PeiServicesLocatePpi (&gArmMpCoreInfoPpiGuid, 0, NULL, (VOID **)&ArmMpCoreInfoPpi);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
// Build the MP Core Info Table
|
||||
ArmCoreCount = 0;
|
||||
Status = ArmMpCoreInfoPpi->GetMpCoreInfo (&ArmCoreCount, &ArmCoreInfoTable);
|
||||
if (!EFI_ERROR (Status) && (ArmCoreCount > 0)) {
|
||||
// Build MPCore Info HOB
|
||||
BuildGuidDataHob (&gArmMpCoreInfoGuid, ArmCoreInfoTable, sizeof (ARM_CORE_INFO) * ArmCoreCount);
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
52
ArmPkg/Drivers/CpuPei/CpuPei.inf
Normal file
52
ArmPkg/Drivers/CpuPei/CpuPei.inf
Normal file
@ -0,0 +1,52 @@
|
||||
## @file
|
||||
# Component description file for BootMode module
|
||||
#
|
||||
# This module provides platform specific function to detect boot mode.
|
||||
# Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = CpuPei
|
||||
FILE_GUID = 2FD8B7AD-F8FA-4021-9FC0-0AA572147CDC
|
||||
MODULE_TYPE = PEIM
|
||||
VERSION_STRING = 1.0
|
||||
|
||||
ENTRY_POINT = InitializeCpuPeim
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = ARM
|
||||
#
|
||||
|
||||
[Sources]
|
||||
CpuPei.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
EmbeddedPkg/EmbeddedPkg.dec
|
||||
ArmPkg/ArmPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
PeimEntryPoint
|
||||
DebugLib
|
||||
HobLib
|
||||
ArmLib
|
||||
|
||||
[Ppis]
|
||||
gArmMpCoreInfoPpiGuid
|
||||
|
||||
[Guids]
|
||||
gArmMpCoreInfoGuid
|
||||
|
||||
[FixedPcd]
|
||||
gEmbeddedTokenSpaceGuid.PcdPrePiCpuIoSize
|
||||
|
||||
[Depex]
|
||||
gEfiPeiMemoryDiscoveredPpiGuid
|
||||
|
25
ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdog.h
Normal file
25
ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdog.h
Normal file
@ -0,0 +1,25 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2013-2017, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef GENERIC_WATCHDOG_H_
|
||||
#define GENERIC_WATCHDOG_H_
|
||||
|
||||
// Refresh Frame:
|
||||
#define GENERIC_WDOG_REFRESH_REG ((UINTN)FixedPcdGet64 (PcdGenericWatchdogRefreshBase) + 0x000)
|
||||
|
||||
// Control Frame:
|
||||
#define GENERIC_WDOG_CONTROL_STATUS_REG ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x000)
|
||||
#define GENERIC_WDOG_OFFSET_REG ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x008)
|
||||
#define GENERIC_WDOG_COMPARE_VALUE_REG_LOW ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x010)
|
||||
#define GENERIC_WDOG_COMPARE_VALUE_REG_HIGH ((UINTN)FixedPcdGet64 (PcdGenericWatchdogControlBase) + 0x014)
|
||||
|
||||
// Values of bit 0 of the Control/Status Register
|
||||
#define GENERIC_WDOG_ENABLED 1
|
||||
#define GENERIC_WDOG_DISABLED 0
|
||||
|
||||
#endif // GENERIC_WATCHDOG_H_
|
383
ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c
Normal file
383
ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.c
Normal file
@ -0,0 +1,383 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2013-2018, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/ArmGenericTimerCounterLib.h>
|
||||
|
||||
#include <Protocol/HardwareInterrupt2.h>
|
||||
#include <Protocol/WatchdogTimer.h>
|
||||
|
||||
#include "GenericWatchdog.h"
|
||||
|
||||
/* The number of 100ns periods (the unit of time passed to these functions)
|
||||
in a second */
|
||||
#define TIME_UNITS_PER_SECOND 10000000
|
||||
|
||||
// Tick frequency of the generic timer basis of the generic watchdog.
|
||||
STATIC UINTN mTimerFrequencyHz = 0;
|
||||
|
||||
/* In cases where the compare register was set manually, information about
|
||||
how long the watchdog was asked to wait cannot be retrieved from hardware.
|
||||
It is therefore stored here. 0 means the timer is not running. */
|
||||
STATIC UINT64 mNumTimerTicks = 0;
|
||||
|
||||
STATIC EFI_HARDWARE_INTERRUPT2_PROTOCOL *mInterruptProtocol;
|
||||
STATIC EFI_WATCHDOG_TIMER_NOTIFY mWatchdogNotify;
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
WatchdogWriteOffsetRegister (
|
||||
UINT32 Value
|
||||
)
|
||||
{
|
||||
MmioWrite32 (GENERIC_WDOG_OFFSET_REG, Value);
|
||||
}
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
WatchdogWriteCompareRegister (
|
||||
UINT64 Value
|
||||
)
|
||||
{
|
||||
MmioWrite32 (GENERIC_WDOG_COMPARE_VALUE_REG_LOW, Value & MAX_UINT32);
|
||||
MmioWrite32 (GENERIC_WDOG_COMPARE_VALUE_REG_HIGH, (Value >> 32) & MAX_UINT32);
|
||||
}
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
WatchdogEnable (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
MmioWrite32 (GENERIC_WDOG_CONTROL_STATUS_REG, GENERIC_WDOG_ENABLED);
|
||||
}
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
WatchdogDisable (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
MmioWrite32 (GENERIC_WDOG_CONTROL_STATUS_REG, GENERIC_WDOG_DISABLED);
|
||||
}
|
||||
|
||||
/** On exiting boot services we must make sure the Watchdog Timer
|
||||
is stopped.
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
EFIAPI
|
||||
WatchdogExitBootServicesEvent (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
WatchdogDisable ();
|
||||
mNumTimerTicks = 0;
|
||||
}
|
||||
|
||||
/* This function is called when the watchdog's first signal (WS0) goes high.
|
||||
It uses the ResetSystem Runtime Service to reset the board.
|
||||
*/
|
||||
STATIC
|
||||
VOID
|
||||
EFIAPI
|
||||
WatchdogInterruptHandler (
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source,
|
||||
IN EFI_SYSTEM_CONTEXT SystemContext
|
||||
)
|
||||
{
|
||||
STATIC CONST CHAR16 ResetString[] = L"The generic watchdog timer ran out.";
|
||||
UINT64 TimerPeriod;
|
||||
|
||||
WatchdogDisable ();
|
||||
|
||||
mInterruptProtocol->EndOfInterrupt (mInterruptProtocol, Source);
|
||||
|
||||
//
|
||||
// The notify function should be called with the elapsed number of ticks
|
||||
// since the watchdog was armed, which should exceed the timer period.
|
||||
// We don't actually know the elapsed number of ticks, so let's return
|
||||
// the timer period plus 1.
|
||||
//
|
||||
if (mWatchdogNotify != NULL) {
|
||||
TimerPeriod = ((TIME_UNITS_PER_SECOND / mTimerFrequencyHz) * mNumTimerTicks);
|
||||
mWatchdogNotify (TimerPeriod + 1);
|
||||
}
|
||||
|
||||
gRT->ResetSystem (
|
||||
EfiResetCold,
|
||||
EFI_TIMEOUT,
|
||||
StrSize (ResetString),
|
||||
(CHAR16 *)ResetString
|
||||
);
|
||||
|
||||
// If we got here then the reset didn't work
|
||||
ASSERT (FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
This function registers the handler NotifyFunction so it is called every time
|
||||
the watchdog timer expires. It also passes the amount of time since the last
|
||||
handler call to the NotifyFunction.
|
||||
If NotifyFunction is not NULL and a handler is not already registered,
|
||||
then the new handler is registered and EFI_SUCCESS is returned.
|
||||
If NotifyFunction is NULL, and a handler is already registered,
|
||||
then that handler is unregistered.
|
||||
If an attempt is made to register a handler when a handler is already
|
||||
registered, then EFI_ALREADY_STARTED is returned.
|
||||
If an attempt is made to unregister a handler when a handler is not
|
||||
registered, then EFI_INVALID_PARAMETER is returned.
|
||||
|
||||
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
|
||||
@param NotifyFunction The function to call when a timer interrupt fires.
|
||||
This function executes at TPL_HIGH_LEVEL. The DXE
|
||||
Core will register a handler for the timer interrupt,
|
||||
so it can know how much time has passed. This
|
||||
information is used to signal timer based events.
|
||||
NULL will unregister the handler.
|
||||
|
||||
@retval EFI_UNSUPPORTED The code does not support NotifyFunction.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
WatchdogRegisterHandler (
|
||||
IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This,
|
||||
IN EFI_WATCHDOG_TIMER_NOTIFY NotifyFunction
|
||||
)
|
||||
{
|
||||
if ((mWatchdogNotify == NULL) && (NotifyFunction == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ((mWatchdogNotify != NULL) && (NotifyFunction != NULL)) {
|
||||
return EFI_ALREADY_STARTED;
|
||||
}
|
||||
|
||||
mWatchdogNotify = NotifyFunction;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
This function sets the amount of time to wait before firing the watchdog
|
||||
timer to TimerPeriod 100ns units. If TimerPeriod is 0, then the watchdog
|
||||
timer is disabled.
|
||||
|
||||
@param This The EFI_WATCHDOG_TIMER_ARCH_PROTOCOL instance.
|
||||
@param TimerPeriod The amount of time in 100ns units to wait before
|
||||
the watchdog timer is fired. If TimerPeriod is zero,
|
||||
then the watchdog timer is disabled.
|
||||
|
||||
@retval EFI_SUCCESS The watchdog timer has been programmed to fire
|
||||
in TimerPeriod 100ns units.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
WatchdogSetTimerPeriod (
|
||||
IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This,
|
||||
IN UINT64 TimerPeriod // In 100ns units
|
||||
)
|
||||
{
|
||||
UINTN SystemCount;
|
||||
|
||||
// if TimerPeriod is 0, this is a request to stop the watchdog.
|
||||
if (TimerPeriod == 0) {
|
||||
mNumTimerTicks = 0;
|
||||
WatchdogDisable ();
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
// Work out how many timer ticks will equate to TimerPeriod
|
||||
mNumTimerTicks = (mTimerFrequencyHz * TimerPeriod) / TIME_UNITS_PER_SECOND;
|
||||
|
||||
/* If the number of required ticks is greater than the max the watchdog's
|
||||
offset register (WOR) can hold, we need to manually compute and set
|
||||
the compare register (WCV) */
|
||||
if (mNumTimerTicks > MAX_UINT32) {
|
||||
/* We need to enable the watchdog *before* writing to the compare register,
|
||||
because enabling the watchdog causes an "explicit refresh", which
|
||||
clobbers the compare register (WCV). In order to make sure this doesn't
|
||||
trigger an interrupt, set the offset to max. */
|
||||
WatchdogWriteOffsetRegister (MAX_UINT32);
|
||||
WatchdogEnable ();
|
||||
SystemCount = ArmGenericTimerGetSystemCount ();
|
||||
WatchdogWriteCompareRegister (SystemCount + mNumTimerTicks);
|
||||
} else {
|
||||
WatchdogWriteOffsetRegister ((UINT32)mNumTimerTicks);
|
||||
WatchdogEnable ();
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
This function retrieves the period of timer interrupts in 100ns units,
|
||||
returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod
|
||||
is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is
|
||||
returned, then the timer is currently disabled.
|
||||
|
||||
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
|
||||
@param TimerPeriod A pointer to the timer period to retrieve in
|
||||
100ns units. If 0 is returned, then the timer is
|
||||
currently disabled.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS The timer period was returned in TimerPeriod.
|
||||
@retval EFI_INVALID_PARAMETER TimerPeriod is NULL.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
WatchdogGetTimerPeriod (
|
||||
IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This,
|
||||
OUT UINT64 *TimerPeriod
|
||||
)
|
||||
{
|
||||
if (TimerPeriod == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*TimerPeriod = ((TIME_UNITS_PER_SECOND / mTimerFrequencyHz) * mNumTimerTicks);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Interface structure for the Watchdog Architectural Protocol.
|
||||
|
||||
@par Protocol Description:
|
||||
This protocol provides a service to set the amount of time to wait
|
||||
before firing the watchdog timer, and it also provides a service to
|
||||
register a handler that is invoked when the watchdog timer fires.
|
||||
|
||||
@par When the watchdog timer fires, control will be passed to a handler
|
||||
if one has been registered. If no handler has been registered,
|
||||
or the registered handler returns, then the system will be
|
||||
reset by calling the Runtime Service ResetSystem().
|
||||
|
||||
@param RegisterHandler
|
||||
Registers a handler that will be called each time the
|
||||
watchdogtimer interrupt fires. TimerPeriod defines the minimum
|
||||
time between timer interrupts, so TimerPeriod will also
|
||||
be the minimum time between calls to the registered
|
||||
handler.
|
||||
NOTE: If the watchdog resets the system in hardware, then
|
||||
this function will not have any chance of executing.
|
||||
|
||||
@param SetTimerPeriod
|
||||
Sets the period of the timer interrupt in 100ns units.
|
||||
This function is optional, and may return EFI_UNSUPPORTED.
|
||||
If this function is supported, then the timer period will
|
||||
be rounded up to the nearest supported timer period.
|
||||
|
||||
@param GetTimerPeriod
|
||||
Retrieves the period of the timer interrupt in 100ns units.
|
||||
|
||||
**/
|
||||
STATIC EFI_WATCHDOG_TIMER_ARCH_PROTOCOL mWatchdogTimer = {
|
||||
WatchdogRegisterHandler,
|
||||
WatchdogSetTimerPeriod,
|
||||
WatchdogGetTimerPeriod
|
||||
};
|
||||
|
||||
STATIC EFI_EVENT mEfiExitBootServicesEvent;
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GenericWatchdogEntry (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_HANDLE Handle;
|
||||
|
||||
Status = gBS->LocateProtocol (
|
||||
&gHardwareInterrupt2ProtocolGuid,
|
||||
NULL,
|
||||
(VOID **)&mInterruptProtocol
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
/* Make sure the Watchdog Timer Architectural Protocol has not been installed
|
||||
in the system yet.
|
||||
This will avoid conflicts with the universal watchdog */
|
||||
ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiWatchdogTimerArchProtocolGuid);
|
||||
|
||||
mTimerFrequencyHz = ArmGenericTimerGetTimerFreq ();
|
||||
ASSERT (mTimerFrequencyHz != 0);
|
||||
|
||||
// Install interrupt handler
|
||||
Status = mInterruptProtocol->RegisterInterruptSource (
|
||||
mInterruptProtocol,
|
||||
FixedPcdGet32 (PcdGenericWatchdogEl2IntrNum),
|
||||
WatchdogInterruptHandler
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = mInterruptProtocol->SetTriggerType (
|
||||
mInterruptProtocol,
|
||||
FixedPcdGet32 (PcdGenericWatchdogEl2IntrNum),
|
||||
EFI_HARDWARE_INTERRUPT2_TRIGGER_EDGE_RISING
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto UnregisterHandler;
|
||||
}
|
||||
|
||||
// Install the Timer Architectural Protocol onto a new handle
|
||||
Handle = NULL;
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&Handle,
|
||||
&gEfiWatchdogTimerArchProtocolGuid,
|
||||
&mWatchdogTimer,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto UnregisterHandler;
|
||||
}
|
||||
|
||||
// Register for an ExitBootServicesEvent
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_SIGNAL_EXIT_BOOT_SERVICES,
|
||||
TPL_NOTIFY,
|
||||
WatchdogExitBootServicesEvent,
|
||||
NULL,
|
||||
&mEfiExitBootServicesEvent
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
mNumTimerTicks = 0;
|
||||
WatchdogDisable ();
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
UnregisterHandler:
|
||||
// Unregister the handler
|
||||
mInterruptProtocol->RegisterInterruptSource (
|
||||
mInterruptProtocol,
|
||||
FixedPcdGet32 (PcdGenericWatchdogEl2IntrNum),
|
||||
NULL
|
||||
);
|
||||
return Status;
|
||||
}
|
47
ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.inf
Normal file
47
ArmPkg/Drivers/GenericWatchdogDxe/GenericWatchdogDxe.inf
Normal file
@ -0,0 +1,47 @@
|
||||
#
|
||||
# Copyright (c) 2013-2021, Arm Limited. All rights reserved.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010016
|
||||
BASE_NAME = GenericWatchdogDxe
|
||||
FILE_GUID = 0619f5c2-4858-4caa-a86a-73a21a18df6b
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = GenericWatchdogEntry
|
||||
|
||||
[Sources.common]
|
||||
GenericWatchdog.h
|
||||
GenericWatchdogDxe.c
|
||||
|
||||
[Packages]
|
||||
ArmPkg/ArmPkg.dec
|
||||
ArmPlatformPkg/ArmPlatformPkg.dec
|
||||
EmbeddedPkg/EmbeddedPkg.dec
|
||||
MdePkg/MdePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
ArmGenericTimerCounterLib
|
||||
BaseLib
|
||||
BaseMemoryLib
|
||||
DebugLib
|
||||
IoLib
|
||||
PcdLib
|
||||
UefiLib
|
||||
UefiBootServicesTableLib
|
||||
UefiDriverEntryPoint
|
||||
UefiRuntimeServicesTableLib
|
||||
|
||||
[Pcd.common]
|
||||
gArmTokenSpaceGuid.PcdGenericWatchdogControlBase
|
||||
gArmTokenSpaceGuid.PcdGenericWatchdogRefreshBase
|
||||
gArmTokenSpaceGuid.PcdGenericWatchdogEl2IntrNum
|
||||
|
||||
[Protocols]
|
||||
gEfiWatchdogTimerArchProtocolGuid ## ALWAYS_PRODUCES
|
||||
gHardwareInterrupt2ProtocolGuid ## ALWAYS_CONSUMES
|
||||
|
||||
[Depex]
|
||||
gHardwareInterrupt2ProtocolGuid
|
22
ArmPkg/Drivers/MmCommunicationDxe/MmCommunicate.h
Normal file
22
ArmPkg/Drivers/MmCommunicationDxe/MmCommunicate.h
Normal file
@ -0,0 +1,22 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2016-2021, Arm Limited. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef MM_COMMUNICATE_H_
|
||||
#define MM_COMMUNICATE_H_
|
||||
|
||||
#define MM_MAJOR_VER_MASK 0xEFFF0000
|
||||
#define MM_MINOR_VER_MASK 0x0000FFFF
|
||||
#define MM_MAJOR_VER_SHIFT 16
|
||||
|
||||
#define MM_MAJOR_VER(x) (((x) & MM_MAJOR_VER_MASK) >> MM_MAJOR_VER_SHIFT)
|
||||
#define MM_MINOR_VER(x) ((x) & MM_MINOR_VER_MASK)
|
||||
|
||||
#define MM_CALLER_MAJOR_VER 0x1UL
|
||||
#define MM_CALLER_MINOR_VER 0x0
|
||||
|
||||
#endif /* MM_COMMUNICATE_H_ */
|
458
ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.c
Normal file
458
ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.c
Normal file
@ -0,0 +1,458 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2016-2021, Arm Limited. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include <Library/ArmLib.h>
|
||||
#include <Library/ArmSmcLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/DxeServicesTableLib.h>
|
||||
#include <Library/HobLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
|
||||
#include <Protocol/MmCommunication2.h>
|
||||
|
||||
#include <IndustryStandard/ArmStdSmc.h>
|
||||
|
||||
#include "MmCommunicate.h"
|
||||
|
||||
//
|
||||
// Address, Length of the pre-allocated buffer for communication with the secure
|
||||
// world.
|
||||
//
|
||||
STATIC ARM_MEMORY_REGION_DESCRIPTOR mNsCommBuffMemRegion;
|
||||
|
||||
// Notification event when virtual address map is set.
|
||||
STATIC EFI_EVENT mSetVirtualAddressMapEvent;
|
||||
|
||||
//
|
||||
// Handle to install the MM Communication Protocol
|
||||
//
|
||||
STATIC EFI_HANDLE mMmCommunicateHandle;
|
||||
|
||||
/**
|
||||
Communicates with a registered handler.
|
||||
|
||||
This function provides a service to send and receive messages from a registered UEFI service.
|
||||
|
||||
@param[in] This The EFI_MM_COMMUNICATION_PROTOCOL instance.
|
||||
@param[in, out] CommBufferPhysical Physical address of the MM communication buffer
|
||||
@param[in, out] CommBufferVirtual Virtual address of the MM communication buffer
|
||||
@param[in, out] CommSize The size of the data buffer being passed in. On input,
|
||||
when not omitted, the buffer should cover EFI_MM_COMMUNICATE_HEADER
|
||||
and the value of MessageLength field. On exit, the size
|
||||
of data being returned. Zero if the handler does not
|
||||
wish to reply with any data. This parameter is optional
|
||||
and may be NULL.
|
||||
|
||||
@retval EFI_SUCCESS The message was successfully posted.
|
||||
@retval EFI_INVALID_PARAMETER CommBufferPhysical or CommBufferVirtual was NULL, or
|
||||
integer value pointed by CommSize does not cover
|
||||
EFI_MM_COMMUNICATE_HEADER and the value of MessageLength
|
||||
field.
|
||||
@retval EFI_BAD_BUFFER_SIZE The buffer is too large for the MM implementation.
|
||||
If this error is returned, the MessageLength field
|
||||
in the CommBuffer header or the integer pointed by
|
||||
CommSize, are updated to reflect the maximum payload
|
||||
size the implementation can accommodate.
|
||||
@retval EFI_ACCESS_DENIED The CommunicateBuffer parameter or CommSize parameter,
|
||||
if not omitted, are in address range that cannot be
|
||||
accessed by the MM environment.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
MmCommunication2Communicate (
|
||||
IN CONST EFI_MM_COMMUNICATION2_PROTOCOL *This,
|
||||
IN OUT VOID *CommBufferPhysical,
|
||||
IN OUT VOID *CommBufferVirtual,
|
||||
IN OUT UINTN *CommSize OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_MM_COMMUNICATE_HEADER *CommunicateHeader;
|
||||
ARM_SMC_ARGS CommunicateSmcArgs;
|
||||
EFI_STATUS Status;
|
||||
UINTN BufferSize;
|
||||
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
BufferSize = 0;
|
||||
|
||||
ZeroMem (&CommunicateSmcArgs, sizeof (ARM_SMC_ARGS));
|
||||
|
||||
//
|
||||
// Check parameters
|
||||
//
|
||||
if ((CommBufferVirtual == NULL) || (CommBufferPhysical == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
CommunicateHeader = CommBufferVirtual;
|
||||
// CommBuffer is a mandatory parameter. Hence, Rely on
|
||||
// MessageLength + Header to ascertain the
|
||||
// total size of the communication payload rather than
|
||||
// rely on optional CommSize parameter
|
||||
BufferSize = CommunicateHeader->MessageLength +
|
||||
sizeof (CommunicateHeader->HeaderGuid) +
|
||||
sizeof (CommunicateHeader->MessageLength);
|
||||
|
||||
// If CommSize is not omitted, perform size inspection before proceeding.
|
||||
if (CommSize != NULL) {
|
||||
// This case can be used by the consumer of this driver to find out the
|
||||
// max size that can be used for allocating CommBuffer.
|
||||
if ((*CommSize == 0) ||
|
||||
(*CommSize > mNsCommBuffMemRegion.Length))
|
||||
{
|
||||
*CommSize = mNsCommBuffMemRegion.Length;
|
||||
Status = EFI_BAD_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
//
|
||||
// CommSize should cover at least MessageLength + sizeof (EFI_MM_COMMUNICATE_HEADER);
|
||||
//
|
||||
if (*CommSize < BufferSize) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If the message length is 0 or greater than what can be tolerated by the MM
|
||||
// environment then return the expected size.
|
||||
//
|
||||
if ((CommunicateHeader->MessageLength == 0) ||
|
||||
(BufferSize > mNsCommBuffMemRegion.Length))
|
||||
{
|
||||
CommunicateHeader->MessageLength = mNsCommBuffMemRegion.Length -
|
||||
sizeof (CommunicateHeader->HeaderGuid) -
|
||||
sizeof (CommunicateHeader->MessageLength);
|
||||
Status = EFI_BAD_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
// MessageLength or CommSize check has failed, return here.
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
// SMC Function ID
|
||||
CommunicateSmcArgs.Arg0 = ARM_SMC_ID_MM_COMMUNICATE_AARCH64;
|
||||
|
||||
// Cookie
|
||||
CommunicateSmcArgs.Arg1 = 0;
|
||||
|
||||
// Copy Communication Payload
|
||||
CopyMem ((VOID *)mNsCommBuffMemRegion.VirtualBase, CommBufferVirtual, BufferSize);
|
||||
|
||||
// comm_buffer_address (64-bit physical address)
|
||||
CommunicateSmcArgs.Arg2 = (UINTN)mNsCommBuffMemRegion.PhysicalBase;
|
||||
|
||||
// comm_size_address (not used, indicated by setting to zero)
|
||||
CommunicateSmcArgs.Arg3 = 0;
|
||||
|
||||
// Call the Standalone MM environment.
|
||||
ArmCallSmc (&CommunicateSmcArgs);
|
||||
|
||||
switch (CommunicateSmcArgs.Arg0) {
|
||||
case ARM_SMC_MM_RET_SUCCESS:
|
||||
ZeroMem (CommBufferVirtual, BufferSize);
|
||||
// On successful return, the size of data being returned is inferred from
|
||||
// MessageLength + Header.
|
||||
CommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)mNsCommBuffMemRegion.VirtualBase;
|
||||
BufferSize = CommunicateHeader->MessageLength +
|
||||
sizeof (CommunicateHeader->HeaderGuid) +
|
||||
sizeof (CommunicateHeader->MessageLength);
|
||||
|
||||
CopyMem (
|
||||
CommBufferVirtual,
|
||||
(VOID *)mNsCommBuffMemRegion.VirtualBase,
|
||||
BufferSize
|
||||
);
|
||||
Status = EFI_SUCCESS;
|
||||
break;
|
||||
|
||||
case ARM_SMC_MM_RET_INVALID_PARAMS:
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
break;
|
||||
|
||||
case ARM_SMC_MM_RET_DENIED:
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
break;
|
||||
|
||||
case ARM_SMC_MM_RET_NO_MEMORY:
|
||||
// Unexpected error since the CommSize was checked for zero length
|
||||
// prior to issuing the SMC
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
ASSERT (0);
|
||||
break;
|
||||
|
||||
default:
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
ASSERT (0);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// MM Communication Protocol instance
|
||||
//
|
||||
STATIC EFI_MM_COMMUNICATION2_PROTOCOL mMmCommunication2 = {
|
||||
MmCommunication2Communicate
|
||||
};
|
||||
|
||||
/**
|
||||
Notification callback on SetVirtualAddressMap event.
|
||||
|
||||
This function notifies the MM communication protocol interface on
|
||||
SetVirtualAddressMap event and converts pointers used in this driver
|
||||
from physical to virtual address.
|
||||
|
||||
@param Event SetVirtualAddressMap event.
|
||||
@param Context A context when the SetVirtualAddressMap triggered.
|
||||
|
||||
@retval EFI_SUCCESS The function executed successfully.
|
||||
@retval Other Some error occurred when executing this function.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
EFIAPI
|
||||
NotifySetVirtualAddressMap (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = gRT->ConvertPointer (
|
||||
EFI_OPTIONAL_PTR,
|
||||
(VOID **)&mNsCommBuffMemRegion.VirtualBase
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"NotifySetVirtualAddressMap():"
|
||||
" Unable to convert MM runtime pointer. Status:0x%r\n",
|
||||
Status
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
GetMmCompatibility (
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 MmVersion;
|
||||
ARM_SMC_ARGS MmVersionArgs;
|
||||
|
||||
// MM_VERSION uses SMC32 calling conventions
|
||||
MmVersionArgs.Arg0 = ARM_SMC_ID_MM_VERSION_AARCH32;
|
||||
|
||||
ArmCallSmc (&MmVersionArgs);
|
||||
|
||||
MmVersion = MmVersionArgs.Arg0;
|
||||
|
||||
if ((MM_MAJOR_VER (MmVersion) == MM_CALLER_MAJOR_VER) &&
|
||||
(MM_MINOR_VER (MmVersion) >= MM_CALLER_MINOR_VER))
|
||||
{
|
||||
DEBUG ((
|
||||
DEBUG_INFO,
|
||||
"MM Version: Major=0x%x, Minor=0x%x\n",
|
||||
MM_MAJOR_VER (MmVersion),
|
||||
MM_MINOR_VER (MmVersion)
|
||||
));
|
||||
Status = EFI_SUCCESS;
|
||||
} else {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"Incompatible MM Versions.\n Current Version: Major=0x%x, Minor=0x%x.\n Expected: Major=0x%x, Minor>=0x%x.\n",
|
||||
MM_MAJOR_VER (MmVersion),
|
||||
MM_MINOR_VER (MmVersion),
|
||||
MM_CALLER_MAJOR_VER,
|
||||
MM_CALLER_MINOR_VER
|
||||
));
|
||||
Status = EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
STATIC EFI_GUID *CONST mGuidedEventGuid[] = {
|
||||
&gEfiEndOfDxeEventGroupGuid,
|
||||
&gEfiEventExitBootServicesGuid,
|
||||
&gEfiEventReadyToBootGuid,
|
||||
};
|
||||
|
||||
STATIC EFI_EVENT mGuidedEvent[ARRAY_SIZE (mGuidedEventGuid)];
|
||||
|
||||
/**
|
||||
Event notification that is fired when GUIDed Event Group is signaled.
|
||||
|
||||
@param Event The Event that is being processed, not used.
|
||||
@param Context Event Context, not used.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
VOID
|
||||
EFIAPI
|
||||
MmGuidedEventNotify (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
EFI_MM_COMMUNICATE_HEADER Header;
|
||||
UINTN Size;
|
||||
|
||||
//
|
||||
// Use Guid to initialize EFI_SMM_COMMUNICATE_HEADER structure
|
||||
//
|
||||
CopyGuid (&Header.HeaderGuid, Context);
|
||||
Header.MessageLength = 1;
|
||||
Header.Data[0] = 0;
|
||||
|
||||
Size = sizeof (Header);
|
||||
MmCommunication2Communicate (&mMmCommunication2, &Header, &Header, &Size);
|
||||
}
|
||||
|
||||
/**
|
||||
The Entry Point for MM Communication
|
||||
|
||||
This function installs the MM communication protocol interface and finds out
|
||||
what type of buffer management will be required prior to invoking the
|
||||
communication SMC.
|
||||
|
||||
@param ImageHandle The firmware allocated handle for the EFI image.
|
||||
@param SystemTable A pointer to the EFI System Table.
|
||||
|
||||
@retval EFI_SUCCESS The entry point is executed successfully.
|
||||
@retval Other Some error occurred when executing this entry point.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
MmCommunication2Initialize (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN Index;
|
||||
|
||||
// Check if we can make the MM call
|
||||
Status = GetMmCompatibility ();
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto ReturnErrorStatus;
|
||||
}
|
||||
|
||||
mNsCommBuffMemRegion.PhysicalBase = PcdGet64 (PcdMmBufferBase);
|
||||
// During boot , Virtual and Physical are same
|
||||
mNsCommBuffMemRegion.VirtualBase = mNsCommBuffMemRegion.PhysicalBase;
|
||||
mNsCommBuffMemRegion.Length = PcdGet64 (PcdMmBufferSize);
|
||||
|
||||
ASSERT (mNsCommBuffMemRegion.PhysicalBase != 0);
|
||||
|
||||
ASSERT (mNsCommBuffMemRegion.Length != 0);
|
||||
|
||||
Status = gDS->AddMemorySpace (
|
||||
EfiGcdMemoryTypeReserved,
|
||||
mNsCommBuffMemRegion.PhysicalBase,
|
||||
mNsCommBuffMemRegion.Length,
|
||||
EFI_MEMORY_WB |
|
||||
EFI_MEMORY_XP |
|
||||
EFI_MEMORY_RUNTIME
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"MmCommunicateInitialize: "
|
||||
"Failed to add MM-NS Buffer Memory Space\n"
|
||||
));
|
||||
goto ReturnErrorStatus;
|
||||
}
|
||||
|
||||
Status = gDS->SetMemorySpaceAttributes (
|
||||
mNsCommBuffMemRegion.PhysicalBase,
|
||||
mNsCommBuffMemRegion.Length,
|
||||
EFI_MEMORY_WB | EFI_MEMORY_XP | EFI_MEMORY_RUNTIME
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"MmCommunicateInitialize: "
|
||||
"Failed to set MM-NS Buffer Memory attributes\n"
|
||||
));
|
||||
goto CleanAddedMemorySpace;
|
||||
}
|
||||
|
||||
// Install the communication protocol
|
||||
Status = gBS->InstallProtocolInterface (
|
||||
&mMmCommunicateHandle,
|
||||
&gEfiMmCommunication2ProtocolGuid,
|
||||
EFI_NATIVE_INTERFACE,
|
||||
&mMmCommunication2
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"MmCommunicationInitialize: "
|
||||
"Failed to install MM communication protocol\n"
|
||||
));
|
||||
goto CleanAddedMemorySpace;
|
||||
}
|
||||
|
||||
// Register notification callback when virtual address is associated
|
||||
// with the physical address.
|
||||
// Create a Set Virtual Address Map event.
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE,
|
||||
TPL_NOTIFY,
|
||||
NotifySetVirtualAddressMap,
|
||||
NULL,
|
||||
&mSetVirtualAddressMapEvent
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
for (Index = 0; Index < ARRAY_SIZE (mGuidedEventGuid); Index++) {
|
||||
Status = gBS->CreateEventEx (
|
||||
EVT_NOTIFY_SIGNAL,
|
||||
TPL_CALLBACK,
|
||||
MmGuidedEventNotify,
|
||||
mGuidedEventGuid[Index],
|
||||
mGuidedEventGuid[Index],
|
||||
&mGuidedEvent[Index]
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
if (EFI_ERROR (Status)) {
|
||||
while (Index-- > 0) {
|
||||
gBS->CloseEvent (mGuidedEvent[Index]);
|
||||
}
|
||||
|
||||
goto UninstallProtocol;
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
|
||||
UninstallProtocol:
|
||||
gBS->UninstallProtocolInterface (
|
||||
mMmCommunicateHandle,
|
||||
&gEfiMmCommunication2ProtocolGuid,
|
||||
&mMmCommunication2
|
||||
);
|
||||
|
||||
CleanAddedMemorySpace:
|
||||
gDS->RemoveMemorySpace (
|
||||
mNsCommBuffMemRegion.PhysicalBase,
|
||||
mNsCommBuffMemRegion.Length
|
||||
);
|
||||
|
||||
ReturnErrorStatus:
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
56
ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
Normal file
56
ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
Normal file
@ -0,0 +1,56 @@
|
||||
#/** @file
|
||||
#
|
||||
# DXE MM Communicate driver
|
||||
#
|
||||
# Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
#**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x0001001A
|
||||
BASE_NAME = ArmMmCommunication
|
||||
FILE_GUID = 09EE81D3-F15E-43F4-85B4-CB9873DA5D6B
|
||||
MODULE_TYPE = DXE_RUNTIME_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = MmCommunication2Initialize
|
||||
|
||||
#
|
||||
# The following is for reference only and not required by
|
||||
# build tools
|
||||
#
|
||||
# VALID_ARCHITECTURES = AARCH64
|
||||
#
|
||||
|
||||
[Sources.AARCH64]
|
||||
MmCommunicate.h
|
||||
MmCommunication.c
|
||||
|
||||
[Packages]
|
||||
ArmPkg/ArmPkg.dec
|
||||
MdePkg/MdePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
ArmLib
|
||||
ArmSmcLib
|
||||
BaseMemoryLib
|
||||
DebugLib
|
||||
DxeServicesTableLib
|
||||
HobLib
|
||||
UefiDriverEntryPoint
|
||||
|
||||
[Protocols]
|
||||
gEfiMmCommunication2ProtocolGuid ## PRODUCES
|
||||
|
||||
[Guids]
|
||||
gEfiEndOfDxeEventGroupGuid
|
||||
gEfiEventExitBootServicesGuid
|
||||
gEfiEventReadyToBootGuid
|
||||
|
||||
[Pcd.common]
|
||||
gArmTokenSpaceGuid.PcdMmBufferBase
|
||||
gArmTokenSpaceGuid.PcdMmBufferSize
|
||||
|
||||
[Depex]
|
||||
gEfiCpuArchProtocolGuid
|
427
ArmPkg/Drivers/TimerDxe/TimerDxe.c
Normal file
427
ArmPkg/Drivers/TimerDxe/TimerDxe.c
Normal file
@ -0,0 +1,427 @@
|
||||
/** @file
|
||||
Timer Architecture Protocol driver of the ARM flavor
|
||||
|
||||
Copyright (c) 2011-2021, Arm Limited. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Library/ArmLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/ArmGenericTimerCounterLib.h>
|
||||
|
||||
#include <Protocol/Timer.h>
|
||||
#include <Protocol/HardwareInterrupt.h>
|
||||
|
||||
// The notification function to call on every timer interrupt.
|
||||
EFI_TIMER_NOTIFY mTimerNotifyFunction = (EFI_TIMER_NOTIFY)NULL;
|
||||
EFI_EVENT EfiExitBootServicesEvent = (EFI_EVENT)NULL;
|
||||
|
||||
// The current period of the timer interrupt
|
||||
UINT64 mTimerPeriod = 0;
|
||||
// The latest Timer Tick calculated for mTimerPeriod
|
||||
UINT64 mTimerTicks = 0;
|
||||
// Number of elapsed period since the last Timer interrupt
|
||||
UINT64 mElapsedPeriod = 1;
|
||||
|
||||
// Cached copy of the Hardware Interrupt protocol instance
|
||||
EFI_HARDWARE_INTERRUPT_PROTOCOL *gInterrupt = NULL;
|
||||
|
||||
/**
|
||||
This function registers the handler NotifyFunction so it is called every time
|
||||
the timer interrupt fires. It also passes the amount of time since the last
|
||||
handler call to the NotifyFunction. If NotifyFunction is NULL, then the
|
||||
handler is unregistered. If the handler is registered, then EFI_SUCCESS is
|
||||
returned. If the CPU does not support registering a timer interrupt handler,
|
||||
then EFI_UNSUPPORTED is returned. If an attempt is made to register a handler
|
||||
when a handler is already registered, then EFI_ALREADY_STARTED is returned.
|
||||
If an attempt is made to unregister a handler when a handler is not registered,
|
||||
then EFI_INVALID_PARAMETER is returned. If an error occurs attempting to
|
||||
register the NotifyFunction with the timer interrupt, then EFI_DEVICE_ERROR
|
||||
is returned.
|
||||
|
||||
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
|
||||
@param NotifyFunction The function to call when a timer interrupt fires. This
|
||||
function executes at TPL_HIGH_LEVEL. The DXE Core will
|
||||
register a handler for the timer interrupt, so it can know
|
||||
how much time has passed. This information is used to
|
||||
signal timer based events. NULL will unregister the handler.
|
||||
@retval EFI_SUCCESS The timer handler was registered.
|
||||
@retval EFI_UNSUPPORTED The platform does not support timer interrupts.
|
||||
@retval EFI_ALREADY_STARTED NotifyFunction is not NULL, and a handler is already
|
||||
registered.
|
||||
@retval EFI_INVALID_PARAMETER NotifyFunction is NULL, and a handler was not
|
||||
previously registered.
|
||||
@retval EFI_DEVICE_ERROR The timer handler could not be registered.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TimerDriverRegisterHandler (
|
||||
IN EFI_TIMER_ARCH_PROTOCOL *This,
|
||||
IN EFI_TIMER_NOTIFY NotifyFunction
|
||||
)
|
||||
{
|
||||
if ((NotifyFunction == NULL) && (mTimerNotifyFunction == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ((NotifyFunction != NULL) && (mTimerNotifyFunction != NULL)) {
|
||||
return EFI_ALREADY_STARTED;
|
||||
}
|
||||
|
||||
mTimerNotifyFunction = NotifyFunction;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Disable the timer
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ExitBootServicesEvent (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
ArmGenericTimerDisableTimer ();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
This function adjusts the period of timer interrupts to the value specified
|
||||
by TimerPeriod. If the timer period is updated, then the selected timer
|
||||
period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If
|
||||
the timer hardware is not programmable, then EFI_UNSUPPORTED is returned.
|
||||
If an error occurs while attempting to update the timer period, then the
|
||||
timer hardware will be put back in its state prior to this call, and
|
||||
EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt
|
||||
is disabled. This is not the same as disabling the CPU's interrupts.
|
||||
Instead, it must either turn off the timer hardware, or it must adjust the
|
||||
interrupt controller so that a CPU interrupt is not generated when the timer
|
||||
interrupt fires.
|
||||
|
||||
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
|
||||
@param TimerPeriod The rate to program the timer interrupt in 100 nS units. If
|
||||
the timer hardware is not programmable, then EFI_UNSUPPORTED is
|
||||
returned. If the timer is programmable, then the timer period
|
||||
will be rounded up to the nearest timer period that is supported
|
||||
by the timer hardware. If TimerPeriod is set to 0, then the
|
||||
timer interrupts will be disabled.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS The timer period was changed.
|
||||
@retval EFI_UNSUPPORTED The platform cannot change the period of the timer interrupt.
|
||||
@retval EFI_DEVICE_ERROR The timer period could not be changed due to a device error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TimerDriverSetTimerPeriod (
|
||||
IN EFI_TIMER_ARCH_PROTOCOL *This,
|
||||
IN UINT64 TimerPeriod
|
||||
)
|
||||
{
|
||||
UINT64 CounterValue;
|
||||
UINT64 TimerTicks;
|
||||
EFI_TPL OriginalTPL;
|
||||
|
||||
// Always disable the timer
|
||||
ArmGenericTimerDisableTimer ();
|
||||
|
||||
if (TimerPeriod != 0) {
|
||||
// mTimerTicks = TimerPeriod in 1ms unit x Frequency.10^-3
|
||||
// = TimerPeriod.10^-4 x Frequency.10^-3
|
||||
// = (TimerPeriod x Frequency) x 10^-7
|
||||
TimerTicks = MultU64x32 (TimerPeriod, ArmGenericTimerGetTimerFreq ());
|
||||
TimerTicks = DivU64x32 (TimerTicks, 10000000U);
|
||||
|
||||
// Raise TPL to update the mTimerTicks and mTimerPeriod to ensure these values
|
||||
// are coherent in the interrupt handler
|
||||
OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
|
||||
|
||||
mTimerTicks = TimerTicks;
|
||||
mTimerPeriod = TimerPeriod;
|
||||
mElapsedPeriod = 1;
|
||||
|
||||
gBS->RestoreTPL (OriginalTPL);
|
||||
|
||||
// Get value of the current timer
|
||||
CounterValue = ArmGenericTimerGetSystemCount ();
|
||||
// Set the interrupt in Current Time + mTimerTick
|
||||
ArmGenericTimerSetCompareVal (CounterValue + mTimerTicks);
|
||||
|
||||
// Enable the timer
|
||||
ArmGenericTimerEnableTimer ();
|
||||
} else {
|
||||
// Save the new timer period
|
||||
mTimerPeriod = TimerPeriod;
|
||||
// Reset the elapsed period
|
||||
mElapsedPeriod = 1;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
This function retrieves the period of timer interrupts in 100 ns units,
|
||||
returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod
|
||||
is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is
|
||||
returned, then the timer is currently disabled.
|
||||
|
||||
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
|
||||
@param TimerPeriod A pointer to the timer period to retrieve in 100 ns units. If
|
||||
0 is returned, then the timer is currently disabled.
|
||||
|
||||
|
||||
@retval EFI_SUCCESS The timer period was returned in TimerPeriod.
|
||||
@retval EFI_INVALID_PARAMETER TimerPeriod is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TimerDriverGetTimerPeriod (
|
||||
IN EFI_TIMER_ARCH_PROTOCOL *This,
|
||||
OUT UINT64 *TimerPeriod
|
||||
)
|
||||
{
|
||||
if (TimerPeriod == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*TimerPeriod = mTimerPeriod;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
This function generates a soft timer interrupt. If the platform does not support soft
|
||||
timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCESS is returned.
|
||||
If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.RegisterHandler()
|
||||
service, then a soft timer interrupt will be generated. If the timer interrupt is
|
||||
enabled when this service is called, then the registered handler will be invoked. The
|
||||
registered handler should not be able to distinguish a hardware-generated timer
|
||||
interrupt from a software-generated timer interrupt.
|
||||
|
||||
@param This The EFI_TIMER_ARCH_PROTOCOL instance.
|
||||
|
||||
@retval EFI_SUCCESS The soft timer interrupt was generated.
|
||||
@retval EFI_UNSUPPORTED The platform does not support the generation of soft timer interrupts.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
TimerDriverGenerateSoftInterrupt (
|
||||
IN EFI_TIMER_ARCH_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
Interface structure for the Timer Architectural Protocol.
|
||||
|
||||
@par Protocol Description:
|
||||
This protocol provides the services to initialize a periodic timer
|
||||
interrupt, and to register a handler that is called each time the timer
|
||||
interrupt fires. It may also provide a service to adjust the rate of the
|
||||
periodic timer interrupt. When a timer interrupt occurs, the handler is
|
||||
passed the amount of time that has passed since the previous timer
|
||||
interrupt.
|
||||
|
||||
@param RegisterHandler
|
||||
Registers a handler that will be called each time the
|
||||
timer interrupt fires. TimerPeriod defines the minimum
|
||||
time between timer interrupts, so TimerPeriod will also
|
||||
be the minimum time between calls to the registered
|
||||
handler.
|
||||
|
||||
@param SetTimerPeriod
|
||||
Sets the period of the timer interrupt in 100 nS units.
|
||||
This function is optional, and may return EFI_UNSUPPORTED.
|
||||
If this function is supported, then the timer period will
|
||||
be rounded up to the nearest supported timer period.
|
||||
|
||||
|
||||
@param GetTimerPeriod
|
||||
Retrieves the period of the timer interrupt in 100 nS units.
|
||||
|
||||
@param GenerateSoftInterrupt
|
||||
Generates a soft timer interrupt that simulates the firing of
|
||||
the timer interrupt. This service can be used to invoke the registered handler if the timer interrupt has been masked for
|
||||
a period of time.
|
||||
|
||||
**/
|
||||
EFI_TIMER_ARCH_PROTOCOL gTimer = {
|
||||
TimerDriverRegisterHandler,
|
||||
TimerDriverSetTimerPeriod,
|
||||
TimerDriverGetTimerPeriod,
|
||||
TimerDriverGenerateSoftInterrupt
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
C Interrupt Handler called in the interrupt context when Source interrupt is active.
|
||||
|
||||
|
||||
@param Source Source of the interrupt. Hardware routing off a specific platform defines
|
||||
what source means.
|
||||
|
||||
@param SystemContext Pointer to system register context. Mostly used by debuggers and will
|
||||
update the system context after the return from the interrupt if
|
||||
modified. Don't change these values unless you know what you are doing
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
TimerInterruptHandler (
|
||||
IN HARDWARE_INTERRUPT_SOURCE Source,
|
||||
IN EFI_SYSTEM_CONTEXT SystemContext
|
||||
)
|
||||
{
|
||||
EFI_TPL OriginalTPL;
|
||||
UINT64 CurrentValue;
|
||||
UINT64 CompareValue;
|
||||
|
||||
//
|
||||
// DXE core uses this callback for the EFI timer tick. The DXE core uses locks
|
||||
// that raise to TPL_HIGH and then restore back to current level. Thus we need
|
||||
// to make sure TPL level is set to TPL_HIGH while we are handling the timer tick.
|
||||
//
|
||||
OriginalTPL = gBS->RaiseTPL (TPL_HIGH_LEVEL);
|
||||
|
||||
// Signal end of interrupt early to help avoid losing subsequent ticks
|
||||
// from long duration handlers
|
||||
gInterrupt->EndOfInterrupt (gInterrupt, Source);
|
||||
|
||||
// Check if the timer interrupt is active
|
||||
if ((ArmGenericTimerGetTimerCtrlReg ()) & ARM_ARCH_TIMER_ISTATUS) {
|
||||
if (mTimerNotifyFunction != 0) {
|
||||
mTimerNotifyFunction (mTimerPeriod * mElapsedPeriod);
|
||||
}
|
||||
|
||||
//
|
||||
// Reload the Timer
|
||||
//
|
||||
|
||||
// Get current counter value
|
||||
CurrentValue = ArmGenericTimerGetSystemCount ();
|
||||
// Get the counter value to compare with
|
||||
CompareValue = ArmGenericTimerGetCompareVal ();
|
||||
|
||||
// This loop is needed in case we missed interrupts (eg: case when the interrupt handling
|
||||
// has taken longer than mTickPeriod).
|
||||
// Note: Physical Counter is counting up
|
||||
mElapsedPeriod = 0;
|
||||
do {
|
||||
CompareValue += mTimerTicks;
|
||||
mElapsedPeriod++;
|
||||
} while (CompareValue < CurrentValue);
|
||||
|
||||
// Set next compare value
|
||||
ArmGenericTimerSetCompareVal (CompareValue);
|
||||
ArmGenericTimerReenableTimer ();
|
||||
ArmInstructionSynchronizationBarrier ();
|
||||
}
|
||||
|
||||
gBS->RestoreTPL (OriginalTPL);
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize the state information for the Timer Architectural Protocol and
|
||||
the Timer Debug support protocol that allows the debugger to break into a
|
||||
running program.
|
||||
|
||||
@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
|
||||
EFIAPI
|
||||
TimerInitialize (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_HANDLE Handle;
|
||||
EFI_STATUS Status;
|
||||
UINTN TimerCtrlReg;
|
||||
UINT32 TimerHypIntrNum;
|
||||
|
||||
if (ArmIsArchTimerImplemented () == 0) {
|
||||
DEBUG ((DEBUG_ERROR, "ARM Architectural Timer is not available in the CPU, hence can't use this Driver \n"));
|
||||
ASSERT (0);
|
||||
}
|
||||
|
||||
// Find the interrupt controller protocol. ASSERT if not found.
|
||||
Status = gBS->LocateProtocol (&gHardwareInterruptProtocolGuid, NULL, (VOID **)&gInterrupt);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
// Disable the timer
|
||||
TimerCtrlReg = ArmGenericTimerGetTimerCtrlReg ();
|
||||
TimerCtrlReg |= ARM_ARCH_TIMER_IMASK;
|
||||
TimerCtrlReg &= ~ARM_ARCH_TIMER_ENABLE;
|
||||
ArmGenericTimerSetTimerCtrlReg (TimerCtrlReg);
|
||||
Status = TimerDriverSetTimerPeriod (&gTimer, 0);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
// Install secure and Non-secure interrupt handlers
|
||||
// Note: Because it is not possible to determine the security state of the
|
||||
// CPU dynamically, we just install interrupt handler for both sec and non-sec
|
||||
// timer PPI
|
||||
Status = gInterrupt->RegisterInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerVirtIntrNum), TimerInterruptHandler);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// The hypervisor timer interrupt may be omitted by implementations that
|
||||
// execute under virtualization.
|
||||
//
|
||||
TimerHypIntrNum = PcdGet32 (PcdArmArchTimerHypIntrNum);
|
||||
if (TimerHypIntrNum != 0) {
|
||||
Status = gInterrupt->RegisterInterruptSource (gInterrupt, TimerHypIntrNum, TimerInterruptHandler);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
}
|
||||
|
||||
Status = gInterrupt->RegisterInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerSecIntrNum), TimerInterruptHandler);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
Status = gInterrupt->RegisterInterruptSource (gInterrupt, PcdGet32 (PcdArmArchTimerIntrNum), TimerInterruptHandler);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
// Set up default timer
|
||||
Status = TimerDriverSetTimerPeriod (&gTimer, FixedPcdGet32 (PcdTimerPeriod)); // TIMER_DEFAULT_PERIOD
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
Handle = NULL;
|
||||
// Install the Timer Architectural Protocol onto a new handle
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&Handle,
|
||||
&gEfiTimerArchProtocolGuid,
|
||||
&gTimer,
|
||||
NULL
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
// Everything is ready, unmask and enable timer interrupts
|
||||
TimerCtrlReg = ARM_ARCH_TIMER_ENABLE;
|
||||
ArmGenericTimerSetTimerCtrlReg (TimerCtrlReg);
|
||||
|
||||
// Register for an ExitBootServicesEvent
|
||||
Status = gBS->CreateEvent (EVT_SIGNAL_EXIT_BOOT_SERVICES, TPL_NOTIFY, ExitBootServicesEvent, NULL, &EfiExitBootServicesEvent);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
return Status;
|
||||
}
|
54
ArmPkg/Drivers/TimerDxe/TimerDxe.inf
Normal file
54
ArmPkg/Drivers/TimerDxe/TimerDxe.inf
Normal file
@ -0,0 +1,54 @@
|
||||
#/** @file
|
||||
#
|
||||
# Component description file for Timer DXE module
|
||||
#
|
||||
# Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.<BR>
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
#**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = ArmTimerDxe
|
||||
FILE_GUID = 49ea041e-6752-42ca-b0b1-7344fe2546b7
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
|
||||
ENTRY_POINT = TimerInitialize
|
||||
|
||||
[Sources.common]
|
||||
TimerDxe.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
EmbeddedPkg/EmbeddedPkg.dec
|
||||
ArmPkg/ArmPkg.dec
|
||||
ArmPlatformPkg/ArmPlatformPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
ArmLib
|
||||
BaseLib
|
||||
UefiRuntimeServicesTableLib
|
||||
UefiLib
|
||||
UefiBootServicesTableLib
|
||||
BaseMemoryLib
|
||||
DebugLib
|
||||
UefiDriverEntryPoint
|
||||
IoLib
|
||||
ArmGenericTimerCounterLib
|
||||
|
||||
[Guids]
|
||||
|
||||
[Protocols]
|
||||
gEfiTimerArchProtocolGuid
|
||||
gHardwareInterruptProtocolGuid
|
||||
|
||||
[Pcd.common]
|
||||
gEmbeddedTokenSpaceGuid.PcdTimerPeriod
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerSecIntrNum
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerIntrNum
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerVirtIntrNum
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerHypIntrNum
|
||||
|
||||
[Depex]
|
||||
gHardwareInterruptProtocolGuid
|
1233
ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.c
Normal file
1233
ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.c
Normal file
File diff suppressed because it is too large
Load Diff
245
ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.h
Normal file
245
ArmPkg/Filesystem/SemihostFs/Arm/SemihostFs.h
Normal file
@ -0,0 +1,245 @@
|
||||
/** @file
|
||||
Support a Semi Host file system over a debuggers JTAG
|
||||
|
||||
Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef SEMIHOST_FS_H_
|
||||
#define SEMIHOST_FS_H_
|
||||
|
||||
EFI_STATUS
|
||||
VolumeOpen (
|
||||
IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
|
||||
OUT EFI_FILE **Root
|
||||
);
|
||||
|
||||
/**
|
||||
Open a file on the host system by means of the semihosting interface.
|
||||
|
||||
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is
|
||||
the file handle to source location.
|
||||
@param[out] NewHandle A pointer to the location to return the opened
|
||||
handle for the new file.
|
||||
@param[in] FileName The Null-terminated string of the name of the file
|
||||
to be opened.
|
||||
@param[in] OpenMode The mode to open the file : Read or Read/Write or
|
||||
Read/Write/Create
|
||||
@param[in] Attributes Only valid for EFI_FILE_MODE_CREATE, in which case these
|
||||
are the attribute bits for the newly created file. The
|
||||
mnemonics of the attribute bits are : EFI_FILE_READ_ONLY,
|
||||
EFI_FILE_HIDDEN, EFI_FILE_SYSTEM, EFI_FILE_RESERVED,
|
||||
EFI_FILE_DIRECTORY and EFI_FILE_ARCHIVE.
|
||||
|
||||
@retval EFI_SUCCESS The file was open.
|
||||
@retval EFI_NOT_FOUND The specified file could not be found.
|
||||
@retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed.
|
||||
@retval EFI_WRITE_PROTECTED Attempt to create a directory. This is not possible
|
||||
with the semi-hosting interface.
|
||||
@retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file.
|
||||
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
FileOpen (
|
||||
IN EFI_FILE *This,
|
||||
OUT EFI_FILE **NewHandle,
|
||||
IN CHAR16 *FileName,
|
||||
IN UINT64 OpenMode,
|
||||
IN UINT64 Attributes
|
||||
);
|
||||
|
||||
/**
|
||||
Close a specified file handle.
|
||||
|
||||
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the file
|
||||
handle to close.
|
||||
|
||||
@retval EFI_SUCCESS The file was closed.
|
||||
@retval EFI_INVALID_PARAMETER The parameter "This" is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
FileClose (
|
||||
IN EFI_FILE *This
|
||||
);
|
||||
|
||||
/**
|
||||
Close and delete a file.
|
||||
|
||||
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is the file
|
||||
handle to delete.
|
||||
|
||||
@retval EFI_SUCCESS The file was closed and deleted.
|
||||
@retval EFI_WARN_DELETE_FAILURE The handle was closed, but the file was not deleted.
|
||||
@retval EFI_INVALID_PARAMETER The parameter "This" is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
FileDelete (
|
||||
IN EFI_FILE *This
|
||||
);
|
||||
|
||||
/**
|
||||
Read data from an open file.
|
||||
|
||||
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that
|
||||
is the file handle to read data from.
|
||||
@param[in out] BufferSize On input, the size of the Buffer. On output, the
|
||||
amount of data returned in Buffer. In both cases,
|
||||
the size is measured in bytes.
|
||||
@param[out] Buffer The buffer into which the data is read.
|
||||
|
||||
@retval EFI_SUCCESS The data was read.
|
||||
@retval EFI_DEVICE_ERROR On entry, the current file position is
|
||||
beyond the end of the file, or the semi-hosting
|
||||
interface reported an error while performing the
|
||||
read operation.
|
||||
@retval EFI_INVALID_PARAMETER The parameter "This" or the parameter "Buffer"
|
||||
is NULL.
|
||||
**/
|
||||
EFI_STATUS
|
||||
FileRead (
|
||||
IN EFI_FILE *This,
|
||||
IN OUT UINTN *BufferSize,
|
||||
OUT VOID *Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
Write data to an open file.
|
||||
|
||||
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that
|
||||
is the file handle to write data to.
|
||||
@param[in out] BufferSize On input, the size of the Buffer. On output, the
|
||||
size of the data actually written. In both cases,
|
||||
the size is measured in bytes.
|
||||
@param[in] Buffer The buffer of data to write.
|
||||
|
||||
@retval EFI_SUCCESS The data was written.
|
||||
@retval EFI_ACCESS_DENIED Attempt to write into a read only file or
|
||||
in a file opened in read only mode.
|
||||
@retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed.
|
||||
@retval EFI_INVALID_PARAMETER The parameter "This" or the parameter "Buffer"
|
||||
is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
FileWrite (
|
||||
IN EFI_FILE *This,
|
||||
IN OUT UINTN *BufferSize,
|
||||
IN VOID *Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
Return a file's current position.
|
||||
|
||||
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is
|
||||
the file handle to get the current position on.
|
||||
@param[out] Position The address to return the file's current position value.
|
||||
|
||||
@retval EFI_SUCCESS The position was returned.
|
||||
@retval EFI_INVALID_PARAMETER Position is a NULL pointer.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
FileGetPosition (
|
||||
IN EFI_FILE *File,
|
||||
OUT UINT64 *Position
|
||||
);
|
||||
|
||||
/**
|
||||
Set a file's current position.
|
||||
|
||||
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that is
|
||||
the file handle to set the requested position on.
|
||||
@param[in] Position The byte position from the start of the file to set.
|
||||
|
||||
@retval EFI_SUCCESS The position was set.
|
||||
@retval EFI_DEVICE_ERROR The semi-hosting positioning operation failed.
|
||||
@retval EFI_UNSUPPORTED The seek request for nonzero is not valid on open
|
||||
directories.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
FileSetPosition (
|
||||
IN EFI_FILE *File,
|
||||
IN UINT64 Position
|
||||
);
|
||||
|
||||
/**
|
||||
Return information about a file or a file system.
|
||||
|
||||
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that
|
||||
is the file handle the requested information is for.
|
||||
@param[in] InformationType The type identifier for the information being requested :
|
||||
EFI_FILE_INFO_ID or EFI_FILE_SYSTEM_INFO_ID or
|
||||
EFI_FILE_SYSTEM_VOLUME_LABEL_ID
|
||||
@param[in out] BufferSize The size, in bytes, of Buffer.
|
||||
@param[out] Buffer A pointer to the data buffer to return. The type of the
|
||||
data inside the buffer is indicated by InformationType.
|
||||
|
||||
@retval EFI_SUCCESS The information was returned.
|
||||
@retval EFI_UNSUPPORTED The InformationType is not known.
|
||||
@retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to return the information.
|
||||
BufferSize has been updated with the size needed to
|
||||
complete the request.
|
||||
@retval EFI_INVALID_PARAMETER The parameter "This" or the parameter "Buffer"
|
||||
is NULL.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
FileGetInfo (
|
||||
IN EFI_FILE *This,
|
||||
IN EFI_GUID *InformationType,
|
||||
IN OUT UINTN *BufferSize,
|
||||
OUT VOID *Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
Set information about a file or a file system.
|
||||
|
||||
@param[in] This A pointer to the EFI_FILE_PROTOCOL instance that
|
||||
is the file handle the information is for.
|
||||
@param[in] InformationType The type identifier for the information being set :
|
||||
EFI_FILE_INFO_ID or EFI_FILE_SYSTEM_INFO_ID or
|
||||
EFI_FILE_SYSTEM_VOLUME_LABEL_ID
|
||||
@param[in] BufferSize The size, in bytes, of Buffer.
|
||||
@param[in] Buffer A pointer to the data buffer to write. The type of the
|
||||
data inside the buffer is indicated by InformationType.
|
||||
|
||||
@retval EFI_SUCCESS The information was set.
|
||||
@retval EFI_UNSUPPORTED The InformationType is not known.
|
||||
@retval EFI_DEVICE_ERROR The last issued semi-hosting operation failed.
|
||||
@retval EFI_ACCESS_DENIED An attempt is being made to change the
|
||||
EFI_FILE_DIRECTORY Attribute.
|
||||
@retval EFI_ACCESS_DENIED InformationType is EFI_FILE_INFO_ID and
|
||||
the file is a read-only file or has been
|
||||
opened in read-only mode and an attempt is
|
||||
being made to modify a field other than
|
||||
Attribute.
|
||||
@retval EFI_ACCESS_DENIED An attempt is made to change the name of a file
|
||||
to a file that is already present.
|
||||
@retval EFI_WRITE_PROTECTED An attempt is being made to modify a
|
||||
read-only attribute.
|
||||
@retval EFI_BAD_BUFFER_SIZE The size of the buffer is lower than that indicated by
|
||||
the data inside the buffer.
|
||||
@retval EFI_OUT_OF_RESOURCES An allocation needed to process the request failed.
|
||||
@retval EFI_INVALID_PARAMETER At least one of the parameters is invalid.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
FileSetInfo (
|
||||
IN EFI_FILE *This,
|
||||
IN EFI_GUID *InformationType,
|
||||
IN UINTN BufferSize,
|
||||
IN VOID *Buffer
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
FileFlush (
|
||||
IN EFI_FILE *File
|
||||
);
|
||||
|
||||
#endif // SEMIHOST_FS_H_
|
42
ArmPkg/Filesystem/SemihostFs/SemihostFs.inf
Normal file
42
ArmPkg/Filesystem/SemihostFs/SemihostFs.inf
Normal file
@ -0,0 +1,42 @@
|
||||
#/** @file
|
||||
# Support a Semi Host file system over a debuggers JTAG
|
||||
#
|
||||
# Copyright (c) 2009, Apple Inc. All rights reserved.<BR>
|
||||
# Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
#**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = SemihostFs
|
||||
FILE_GUID = C5B9C74A-6D72-4719-99AB-C59F199091EB
|
||||
MODULE_TYPE = UEFI_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
|
||||
ENTRY_POINT = SemihostFsEntryPoint
|
||||
|
||||
[Sources.ARM, Sources.AARCH64]
|
||||
Arm/SemihostFs.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
ArmPkg/ArmPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
MemoryAllocationLib
|
||||
SemihostLib
|
||||
UefiDriverEntryPoint
|
||||
UefiLib
|
||||
|
||||
[Guids]
|
||||
gEfiFileSystemInfoGuid
|
||||
gEfiFileInfoGuid
|
||||
gEfiFileSystemVolumeLabelInfoIdGuid
|
||||
|
||||
[Protocols]
|
||||
gEfiSimpleFileSystemProtocolGuid
|
||||
gEfiDevicePathProtocolGuid
|
||||
|
38
ArmPkg/Include/AsmMacroIoLib.h
Normal file
38
ArmPkg/Include/AsmMacroIoLib.h
Normal file
@ -0,0 +1,38 @@
|
||||
/** @file
|
||||
Macros to work around lack of Apple support for LDR register, =expr
|
||||
|
||||
Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
|
||||
Copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR>
|
||||
Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef ASM_MACRO_IO_LIB_H_
|
||||
#define ASM_MACRO_IO_LIB_H_
|
||||
|
||||
#define _ASM_FUNC(Name, Section) \
|
||||
.global Name ; \
|
||||
.section #Section, "ax" ; \
|
||||
.type Name, %function ; \
|
||||
.p2align 2 ; \
|
||||
Name:
|
||||
|
||||
#define ASM_FUNC(Name) _ASM_FUNC(ASM_PFX(Name), .text. ## Name)
|
||||
|
||||
#define MOV32(Reg, Val) \
|
||||
movw Reg, #(Val) & 0xffff ; \
|
||||
movt Reg, #(Val) >> 16
|
||||
|
||||
#define ADRL(Reg, Sym) \
|
||||
movw Reg, #:lower16:(Sym) - (. + 16) ; \
|
||||
movt Reg, #:upper16:(Sym) - (. + 12) ; \
|
||||
add Reg, Reg, pc
|
||||
|
||||
#define LDRL(Reg, Sym) \
|
||||
movw Reg, #:lower16:(Sym) - (. + 16) ; \
|
||||
movt Reg, #:upper16:(Sym) - (. + 12) ; \
|
||||
ldr Reg, [pc, Reg]
|
||||
|
||||
#endif // ASM_MACRO_IO_LIB_H_
|
33
ArmPkg/Include/AsmMacroIoLib.inc
Normal file
33
ArmPkg/Include/AsmMacroIoLib.inc
Normal file
@ -0,0 +1,33 @@
|
||||
;%HEADER%
|
||||
;/** @file
|
||||
; Macros to work around lack of Apple support for LDR register, =expr
|
||||
;
|
||||
; Copyright (c) 2009, Apple Inc. All rights reserved.<BR>
|
||||
; Copyright (c) 2011-2012, ARM Ltd. All rights reserved.<BR>
|
||||
;
|
||||
; SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
;
|
||||
;**/
|
||||
|
||||
|
||||
MACRO
|
||||
adrll $Reg, $Symbol
|
||||
add $Reg, pc, #-8
|
||||
RELOC R_ARM_ALU_PC_G0_NC, $Symbol
|
||||
add $Reg, $Reg, #-4
|
||||
RELOC R_ARM_ALU_PC_G1_NC, $Symbol
|
||||
add $Reg, $Reg, #0
|
||||
RELOC R_ARM_ALU_PC_G2, $Symbol
|
||||
MEND
|
||||
|
||||
MACRO
|
||||
ldrl $Reg, $Symbol
|
||||
add $Reg, pc, #-8
|
||||
RELOC R_ARM_ALU_PC_G0_NC, $Symbol
|
||||
add $Reg, $Reg, #-4
|
||||
RELOC R_ARM_ALU_PC_G1_NC, $Symbol
|
||||
ldr $Reg, [$Reg, #0]
|
||||
RELOC R_ARM_LDR_PC_G2, $Symbol
|
||||
MEND
|
||||
|
||||
END
|
55
ArmPkg/Include/AsmMacroIoLibV8.h
Normal file
55
ArmPkg/Include/AsmMacroIoLibV8.h
Normal file
@ -0,0 +1,55 @@
|
||||
/** @file
|
||||
Macros to work around lack of Clang support for LDR register, =expr
|
||||
|
||||
Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
|
||||
Portions copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
|
||||
Copyright (c) 2016, Linaro Ltd. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef ASM_MACRO_IO_LIBV8_H_
|
||||
#define ASM_MACRO_IO_LIBV8_H_
|
||||
|
||||
// CurrentEL : 0xC = EL3; 8 = EL2; 4 = EL1
|
||||
// This only selects between EL1 and EL2, else we die.
|
||||
// Provide the Macro with a safe temp xreg to use.
|
||||
#define EL1_OR_EL2(SAFE_XREG) \
|
||||
mrs SAFE_XREG, CurrentEL ;\
|
||||
cmp SAFE_XREG, #0x8 ;\
|
||||
b.gt . ;\
|
||||
b.eq 2f ;\
|
||||
cbnz SAFE_XREG, 1f ;\
|
||||
b . ;// We should never get here
|
||||
|
||||
// CurrentEL : 0xC = EL3; 8 = EL2; 4 = EL1
|
||||
// This only selects between EL1 and EL2 and EL3, else we die.
|
||||
// Provide the Macro with a safe temp xreg to use.
|
||||
#define EL1_OR_EL2_OR_EL3(SAFE_XREG) \
|
||||
mrs SAFE_XREG, CurrentEL ;\
|
||||
cmp SAFE_XREG, #0x8 ;\
|
||||
b.gt 3f ;\
|
||||
b.eq 2f ;\
|
||||
cbnz SAFE_XREG, 1f ;\
|
||||
b . ;// We should never get here
|
||||
|
||||
#define _ASM_FUNC(Name, Section) \
|
||||
.global Name ; \
|
||||
.section #Section, "ax" ; \
|
||||
.type Name, %function ; \
|
||||
Name:
|
||||
|
||||
#define ASM_FUNC(Name) _ASM_FUNC(ASM_PFX(Name), .text. ## Name)
|
||||
|
||||
#define MOV32(Reg, Val) \
|
||||
movz Reg, (Val) >> 16, lsl #16 ; \
|
||||
movk Reg, (Val) & 0xffff
|
||||
|
||||
#define MOV64(Reg, Val) \
|
||||
movz Reg, (Val) >> 48, lsl #48 ; \
|
||||
movk Reg, ((Val) >> 32) & 0xffff, lsl #32 ; \
|
||||
movk Reg, ((Val) >> 16) & 0xffff, lsl #16 ; \
|
||||
movk Reg, (Val) & 0xffff
|
||||
|
||||
#endif // ASM_MACRO_IO_LIBV8_H_
|
241
ArmPkg/Include/Chipset/AArch64.h
Normal file
241
ArmPkg/Include/Chipset/AArch64.h
Normal file
@ -0,0 +1,241 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
|
||||
Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef AARCH64_H_
|
||||
#define AARCH64_H_
|
||||
|
||||
#include <Chipset/AArch64Mmu.h>
|
||||
|
||||
// ARM Interrupt ID in Exception Table
|
||||
#define ARM_ARCH_EXCEPTION_IRQ EXCEPT_AARCH64_IRQ
|
||||
|
||||
// CPACR - Coprocessor Access Control Register definitions
|
||||
#define CPACR_TTA_EN (1UL << 28)
|
||||
#define CPACR_FPEN_EL1 (1UL << 20)
|
||||
#define CPACR_FPEN_FULL (3UL << 20)
|
||||
#define CPACR_CP_FULL_ACCESS 0x300000
|
||||
|
||||
// Coprocessor Trap Register (CPTR)
|
||||
#define AARCH64_CPTR_TFP (1 << 10)
|
||||
|
||||
// ID_AA64PFR0 - AArch64 Processor Feature Register 0 definitions
|
||||
#define AARCH64_PFR0_FP (0xF << 16)
|
||||
#define AARCH64_PFR0_GIC (0xF << 24)
|
||||
|
||||
// SCR - Secure Configuration Register definitions
|
||||
#define SCR_NS (1 << 0)
|
||||
#define SCR_IRQ (1 << 1)
|
||||
#define SCR_FIQ (1 << 2)
|
||||
#define SCR_EA (1 << 3)
|
||||
#define SCR_FW (1 << 4)
|
||||
#define SCR_AW (1 << 5)
|
||||
|
||||
// MIDR - Main ID Register definitions
|
||||
#define ARM_CPU_TYPE_SHIFT 4
|
||||
#define ARM_CPU_TYPE_MASK 0xFFF
|
||||
#define ARM_CPU_TYPE_AEMV8 0xD0F
|
||||
#define ARM_CPU_TYPE_A53 0xD03
|
||||
#define ARM_CPU_TYPE_A57 0xD07
|
||||
#define ARM_CPU_TYPE_A72 0xD08
|
||||
#define ARM_CPU_TYPE_A15 0xC0F
|
||||
#define ARM_CPU_TYPE_A9 0xC09
|
||||
#define ARM_CPU_TYPE_A7 0xC07
|
||||
#define ARM_CPU_TYPE_A5 0xC05
|
||||
|
||||
#define ARM_CPU_REV_MASK ((0xF << 20) | (0xF) )
|
||||
#define ARM_CPU_REV(rn, pn) ((((rn) & 0xF) << 20) | ((pn) & 0xF))
|
||||
|
||||
// Hypervisor Configuration Register
|
||||
#define ARM_HCR_FMO BIT3
|
||||
#define ARM_HCR_IMO BIT4
|
||||
#define ARM_HCR_AMO BIT5
|
||||
#define ARM_HCR_TSC BIT19
|
||||
#define ARM_HCR_TGE BIT27
|
||||
|
||||
// Exception Syndrome Register
|
||||
#define AARCH64_ESR_EC(Ecr) ((0x3F << 26) & (Ecr))
|
||||
#define AARCH64_ESR_ISS(Ecr) ((0x1FFFFFF) & (Ecr))
|
||||
|
||||
#define AARCH64_ESR_EC_SMC32 (0x13 << 26)
|
||||
#define AARCH64_ESR_EC_SMC64 (0x17 << 26)
|
||||
|
||||
// AArch64 Exception Level
|
||||
#define AARCH64_EL3 0xC
|
||||
#define AARCH64_EL2 0x8
|
||||
#define AARCH64_EL1 0x4
|
||||
|
||||
// Saved Program Status Register definitions
|
||||
#define SPSR_A BIT8
|
||||
#define SPSR_I BIT7
|
||||
#define SPSR_F BIT6
|
||||
|
||||
#define SPSR_AARCH32 BIT4
|
||||
|
||||
#define SPSR_AARCH32_MODE_USER 0x0
|
||||
#define SPSR_AARCH32_MODE_FIQ 0x1
|
||||
#define SPSR_AARCH32_MODE_IRQ 0x2
|
||||
#define SPSR_AARCH32_MODE_SVC 0x3
|
||||
#define SPSR_AARCH32_MODE_ABORT 0x7
|
||||
#define SPSR_AARCH32_MODE_UNDEF 0xB
|
||||
#define SPSR_AARCH32_MODE_SYS 0xF
|
||||
|
||||
// Counter-timer Hypervisor Control register definitions
|
||||
#define CNTHCTL_EL2_EL1PCTEN BIT0
|
||||
#define CNTHCTL_EL2_EL1PCEN BIT1
|
||||
|
||||
#define ARM_VECTOR_TABLE_ALIGNMENT ((1 << 11)-1)
|
||||
|
||||
// Vector table offset definitions
|
||||
#define ARM_VECTOR_CUR_SP0_SYNC 0x000
|
||||
#define ARM_VECTOR_CUR_SP0_IRQ 0x080
|
||||
#define ARM_VECTOR_CUR_SP0_FIQ 0x100
|
||||
#define ARM_VECTOR_CUR_SP0_SERR 0x180
|
||||
|
||||
#define ARM_VECTOR_CUR_SPX_SYNC 0x200
|
||||
#define ARM_VECTOR_CUR_SPX_IRQ 0x280
|
||||
#define ARM_VECTOR_CUR_SPX_FIQ 0x300
|
||||
#define ARM_VECTOR_CUR_SPX_SERR 0x380
|
||||
|
||||
#define ARM_VECTOR_LOW_A64_SYNC 0x400
|
||||
#define ARM_VECTOR_LOW_A64_IRQ 0x480
|
||||
#define ARM_VECTOR_LOW_A64_FIQ 0x500
|
||||
#define ARM_VECTOR_LOW_A64_SERR 0x580
|
||||
|
||||
#define ARM_VECTOR_LOW_A32_SYNC 0x600
|
||||
#define ARM_VECTOR_LOW_A32_IRQ 0x680
|
||||
#define ARM_VECTOR_LOW_A32_FIQ 0x700
|
||||
#define ARM_VECTOR_LOW_A32_SERR 0x780
|
||||
|
||||
// The ID_AA64MMFR2_EL1 register was added in ARMv8.2. Since we
|
||||
// build for ARMv8.0, we need to define the register here.
|
||||
#define ID_AA64MMFR2_EL1 S3_0_C0_C7_2
|
||||
|
||||
#define VECTOR_BASE(tbl) \
|
||||
.section .text.##tbl##,"ax"; \
|
||||
.align 11; \
|
||||
.org 0x0; \
|
||||
GCC_ASM_EXPORT(tbl); \
|
||||
ASM_PFX(tbl): \
|
||||
|
||||
#define VECTOR_ENTRY(tbl, off) \
|
||||
.org off
|
||||
|
||||
#define VECTOR_END(tbl) \
|
||||
.org 0x800; \
|
||||
.previous
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmEnableSWPInstruction (
|
||||
VOID
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmReadCbar (
|
||||
VOID
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmReadTpidrurw (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmWriteTpidrurw (
|
||||
UINTN Value
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmGetTCR (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmSetTCR (
|
||||
UINTN Value
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmGetMAIR (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmSetMAIR (
|
||||
UINTN Value
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmDisableAlignmentCheck (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmEnableAlignmentCheck (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmDisableStackAlignmentCheck (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmEnableStackAlignmentCheck (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmDisableAllExceptions (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
ArmWriteHcr (
|
||||
IN UINTN Hcr
|
||||
);
|
||||
|
||||
UINTN
|
||||
ArmReadHcr (
|
||||
VOID
|
||||
);
|
||||
|
||||
UINTN
|
||||
ArmReadCurrentEL (
|
||||
VOID
|
||||
);
|
||||
|
||||
UINTN
|
||||
ArmWriteCptr (
|
||||
IN UINT64 Cptr
|
||||
);
|
||||
|
||||
UINT32
|
||||
ArmReadCntHctl (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
ArmWriteCntHctl (
|
||||
IN UINT32 CntHctl
|
||||
);
|
||||
|
||||
#endif // AARCH64_H_
|
195
ArmPkg/Include/Chipset/AArch64Mmu.h
Normal file
195
ArmPkg/Include/Chipset/AArch64Mmu.h
Normal file
@ -0,0 +1,195 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2011-2021, Arm Limited. All rights reserved.<BR>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef AARCH64_MMU_H_
|
||||
#define AARCH64_MMU_H_
|
||||
|
||||
//
|
||||
// Memory Attribute Indirection register Definitions
|
||||
//
|
||||
#define MAIR_ATTR_DEVICE_MEMORY 0x0ULL
|
||||
#define MAIR_ATTR_NORMAL_MEMORY_NON_CACHEABLE 0x44ULL
|
||||
#define MAIR_ATTR_NORMAL_MEMORY_WRITE_THROUGH 0xBBULL
|
||||
#define MAIR_ATTR_NORMAL_MEMORY_WRITE_BACK 0xFFULL
|
||||
|
||||
#define MAIR_ATTR(n, value) ((value) << (((n) >> 2)*8))
|
||||
|
||||
//
|
||||
// Long-descriptor Translation Table format
|
||||
//
|
||||
|
||||
// Return the smallest offset from the table level.
|
||||
// The first offset starts at 12bit. There are 4 levels of 9-bit address range from level 3 to level 0
|
||||
#define TT_ADDRESS_OFFSET_AT_LEVEL(TableLevel) (12 + ((3 - (TableLevel)) * 9))
|
||||
|
||||
#define TT_BLOCK_ENTRY_SIZE_AT_LEVEL(Level) (1ULL << TT_ADDRESS_OFFSET_AT_LEVEL(Level))
|
||||
|
||||
// Get the associated entry in the given Translation Table
|
||||
#define TT_GET_ENTRY_FOR_ADDRESS(TranslationTable, Level, Address) \
|
||||
((UINTN)(TranslationTable) + ((((UINTN)(Address) >> TT_ADDRESS_OFFSET_AT_LEVEL(Level)) & (BIT9-1)) * sizeof(UINT64)))
|
||||
|
||||
// Return the smallest address granularity from the table level.
|
||||
// The first offset starts at 12bit. There are 4 levels of 9-bit address range from level 3 to level 0
|
||||
#define TT_ADDRESS_AT_LEVEL(TableLevel) (1ULL << TT_ADDRESS_OFFSET_AT_LEVEL(TableLevel))
|
||||
|
||||
#define TT_LAST_BLOCK_ADDRESS(TranslationTable, EntryCount) \
|
||||
((UINT64*)((EFI_PHYSICAL_ADDRESS)(TranslationTable) + (((EntryCount) - 1) * sizeof(UINT64))))
|
||||
|
||||
// There are 512 entries per table when 4K Granularity
|
||||
#define TT_ENTRY_COUNT 512
|
||||
#define TT_ALIGNMENT_BLOCK_ENTRY BIT12
|
||||
#define TT_ALIGNMENT_DESCRIPTION_TABLE BIT12
|
||||
|
||||
#define TT_ADDRESS_MASK_BLOCK_ENTRY (0xFFFFFFFFFULL << 12)
|
||||
#define TT_ADDRESS_MASK_DESCRIPTION_TABLE (0xFFFFFFFFFULL << 12)
|
||||
|
||||
#define TT_TYPE_MASK 0x3
|
||||
#define TT_TYPE_TABLE_ENTRY 0x3
|
||||
#define TT_TYPE_BLOCK_ENTRY 0x1
|
||||
#define TT_TYPE_BLOCK_ENTRY_LEVEL3 0x3
|
||||
|
||||
#define TT_ATTR_INDX_MASK (0x7 << 2)
|
||||
#define TT_ATTR_INDX_DEVICE_MEMORY (0x0 << 2)
|
||||
#define TT_ATTR_INDX_MEMORY_NON_CACHEABLE (0x1 << 2)
|
||||
#define TT_ATTR_INDX_MEMORY_WRITE_THROUGH (0x2 << 2)
|
||||
#define TT_ATTR_INDX_MEMORY_WRITE_BACK (0x3 << 2)
|
||||
|
||||
#define TT_AP_MASK (0x3UL << 6)
|
||||
#define TT_AP_NO_RW (0x0UL << 6)
|
||||
#define TT_AP_RW_RW (0x1UL << 6)
|
||||
#define TT_AP_NO_RO (0x2UL << 6)
|
||||
#define TT_AP_RO_RO (0x3UL << 6)
|
||||
|
||||
#define TT_NS BIT5
|
||||
#define TT_AF BIT10
|
||||
|
||||
#define TT_SH_NON_SHAREABLE (0x0 << 8)
|
||||
#define TT_SH_OUTER_SHAREABLE (0x2 << 8)
|
||||
#define TT_SH_INNER_SHAREABLE (0x3 << 8)
|
||||
#define TT_SH_MASK (0x3 << 8)
|
||||
|
||||
#define TT_PXN_MASK BIT53
|
||||
#define TT_UXN_MASK BIT54 // EL1&0
|
||||
#define TT_XN_MASK BIT54 // EL2 / EL3
|
||||
|
||||
#define TT_ATTRIBUTES_MASK ((0xFFFULL << 52) | (0x3FFULL << 2))
|
||||
|
||||
#define TT_TABLE_PXN BIT59
|
||||
#define TT_TABLE_UXN BIT60 // EL1&0
|
||||
#define TT_TABLE_XN BIT60 // EL2 / EL3
|
||||
#define TT_TABLE_NS BIT63
|
||||
|
||||
#define TT_TABLE_AP_MASK (BIT62 | BIT61)
|
||||
#define TT_TABLE_AP_NO_PERMISSION (0x0ULL << 61)
|
||||
#define TT_TABLE_AP_EL0_NO_ACCESS (0x1ULL << 61)
|
||||
#define TT_TABLE_AP_NO_WRITE_ACCESS (0x2ULL << 61)
|
||||
|
||||
//
|
||||
// Translation Control Register
|
||||
//
|
||||
#define TCR_T0SZ_MASK 0x3FUL
|
||||
|
||||
#define TCR_PS_4GB (0UL << 16)
|
||||
#define TCR_PS_64GB (1UL << 16)
|
||||
#define TCR_PS_1TB (2UL << 16)
|
||||
#define TCR_PS_4TB (3UL << 16)
|
||||
#define TCR_PS_16TB (4UL << 16)
|
||||
#define TCR_PS_256TB (5UL << 16)
|
||||
|
||||
#define TCR_TG0_4KB (0UL << 14)
|
||||
#define TCR_TG1_4KB (2UL << 30)
|
||||
|
||||
#define TCR_IPS_4GB (0ULL << 32)
|
||||
#define TCR_IPS_64GB (1ULL << 32)
|
||||
#define TCR_IPS_1TB (2ULL << 32)
|
||||
#define TCR_IPS_4TB (3ULL << 32)
|
||||
#define TCR_IPS_16TB (4ULL << 32)
|
||||
#define TCR_IPS_256TB (5ULL << 32)
|
||||
|
||||
#define TCR_EPD1 (1UL << 23)
|
||||
|
||||
#define TTBR_ASID_FIELD (48)
|
||||
#define TTBR_ASID_MASK (0xFF << TTBR_ASID_FIELD)
|
||||
#define TTBR_BADDR_MASK (0xFFFFFFFFFFFF ) // The width of this field depends on the values in TxSZ. Addr occupies bottom 48bits
|
||||
|
||||
#define TCR_EL1_T0SZ_FIELD (0)
|
||||
#define TCR_EL1_EPD0_FIELD (7)
|
||||
#define TCR_EL1_IRGN0_FIELD (8)
|
||||
#define TCR_EL1_ORGN0_FIELD (10)
|
||||
#define TCR_EL1_SH0_FIELD (12)
|
||||
#define TCR_EL1_TG0_FIELD (14)
|
||||
#define TCR_EL1_T1SZ_FIELD (16)
|
||||
#define TCR_EL1_A1_FIELD (22)
|
||||
#define TCR_EL1_EPD1_FIELD (23)
|
||||
#define TCR_EL1_IRGN1_FIELD (24)
|
||||
#define TCR_EL1_ORGN1_FIELD (26)
|
||||
#define TCR_EL1_SH1_FIELD (28)
|
||||
#define TCR_EL1_TG1_FIELD (30)
|
||||
#define TCR_EL1_IPS_FIELD (32)
|
||||
#define TCR_EL1_AS_FIELD (36)
|
||||
#define TCR_EL1_TBI0_FIELD (37)
|
||||
#define TCR_EL1_TBI1_FIELD (38)
|
||||
#define TCR_EL1_T0SZ_MASK (0x1FUL << TCR_EL1_T0SZ_FIELD)
|
||||
#define TCR_EL1_EPD0_MASK (0x01UL << TCR_EL1_EPD0_FIELD)
|
||||
#define TCR_EL1_IRGN0_MASK (0x03UL << TCR_EL1_IRGN0_FIELD)
|
||||
#define TCR_EL1_ORGN0_MASK (0x03UL << TCR_EL1_ORGN0_FIELD)
|
||||
#define TCR_EL1_SH0_MASK (0x03UL << TCR_EL1_SH0_FIELD)
|
||||
#define TCR_EL1_TG0_MASK (0x01UL << TCR_EL1_TG0_FIELD)
|
||||
#define TCR_EL1_T1SZ_MASK (0x1FUL << TCR_EL1_T1SZ_FIELD)
|
||||
#define TCR_EL1_A1_MASK (0x01UL << TCR_EL1_A1_FIELD)
|
||||
#define TCR_EL1_EPD1_MASK (0x01UL << TCR_EL1_EPD1_FIELD)
|
||||
#define TCR_EL1_IRGN1_MASK (0x03UL << TCR_EL1_IRGN1_FIELD)
|
||||
#define TCR_EL1_ORGN1_MASK (0x03UL << TCR_EL1_ORGN1_FIELD)
|
||||
#define TCR_EL1_SH1_MASK (0x03UL << TCR_EL1_SH1_FIELD)
|
||||
#define TCR_EL1_TG1_MASK (0x01UL << TCR_EL1_TG1_FIELD)
|
||||
#define TCR_EL1_IPS_MASK (0x07UL << TCR_EL1_IPS_FIELD)
|
||||
#define TCR_EL1_AS_MASK (0x01UL << TCR_EL1_AS_FIELD)
|
||||
#define TCR_EL1_TBI0_MASK (0x01UL << TCR_EL1_TBI0_FIELD)
|
||||
#define TCR_EL1_TBI1_MASK (0x01UL << TCR_EL1_TBI1_FIELD)
|
||||
|
||||
#define TCR_EL23_T0SZ_FIELD (0)
|
||||
#define TCR_EL23_IRGN0_FIELD (8)
|
||||
#define TCR_EL23_ORGN0_FIELD (10)
|
||||
#define TCR_EL23_SH0_FIELD (12)
|
||||
#define TCR_EL23_TG0_FIELD (14)
|
||||
#define TCR_EL23_PS_FIELD (16)
|
||||
#define TCR_EL23_T0SZ_MASK (0x1FUL << TCR_EL23_T0SZ_FIELD)
|
||||
#define TCR_EL23_IRGN0_MASK (0x03UL << TCR_EL23_IRGN0_FIELD)
|
||||
#define TCR_EL23_ORGN0_MASK (0x03UL << TCR_EL23_ORGN0_FIELD)
|
||||
#define TCR_EL23_SH0_MASK (0x03UL << TCR_EL23_SH0_FIELD)
|
||||
#define TCR_EL23_TG0_MASK (0x01UL << TCR_EL23_TG0_FIELD)
|
||||
#define TCR_EL23_PS_MASK (0x07UL << TCR_EL23_PS_FIELD)
|
||||
|
||||
#define TCR_RGN_OUTER_NON_CACHEABLE (0x0UL << 10)
|
||||
#define TCR_RGN_OUTER_WRITE_BACK_ALLOC (0x1UL << 10)
|
||||
#define TCR_RGN_OUTER_WRITE_THROUGH (0x2UL << 10)
|
||||
#define TCR_RGN_OUTER_WRITE_BACK_NO_ALLOC (0x3UL << 10)
|
||||
|
||||
#define TCR_RGN_INNER_NON_CACHEABLE (0x0UL << 8)
|
||||
#define TCR_RGN_INNER_WRITE_BACK_ALLOC (0x1UL << 8)
|
||||
#define TCR_RGN_INNER_WRITE_THROUGH (0x2UL << 8)
|
||||
#define TCR_RGN_INNER_WRITE_BACK_NO_ALLOC (0x3UL << 8)
|
||||
|
||||
#define TCR_SH_NON_SHAREABLE (0x0UL << 12)
|
||||
#define TCR_SH_OUTER_SHAREABLE (0x2UL << 12)
|
||||
#define TCR_SH_INNER_SHAREABLE (0x3UL << 12)
|
||||
|
||||
#define TCR_PASZ_32BITS_4GB (0x0UL)
|
||||
#define TCR_PASZ_36BITS_64GB (0x1UL)
|
||||
#define TCR_PASZ_40BITS_1TB (0x2UL)
|
||||
#define TCR_PASZ_42BITS_4TB (0x3UL)
|
||||
#define TCR_PASZ_44BITS_16TB (0x4UL)
|
||||
#define TCR_PASZ_48BITS_256TB (0x5UL)
|
||||
|
||||
// The value written to the T*SZ fields are defined as 2^(64-T*SZ). So a 39Bit
|
||||
// Virtual address range for 512GB of virtual space sets T*SZ to 25
|
||||
#define INPUT_ADDRESS_SIZE_TO_TXSZ(a) (64 - a)
|
||||
|
||||
// Uses LPAE Page Table format
|
||||
|
||||
#endif // AARCH64_MMU_H_
|
44
ArmPkg/Include/Chipset/ArmCortexA5x.h
Normal file
44
ArmPkg/Include/Chipset/ArmCortexA5x.h
Normal file
@ -0,0 +1,44 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2012 - 2021, Arm Limited. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef ARM_CORTEX_A5X_H_
|
||||
#define ARM_CORTEX_A5X_H_
|
||||
|
||||
//
|
||||
// Cortex A5x feature bit definitions
|
||||
//
|
||||
#define A5X_FEATURE_SMP (1 << 6)
|
||||
|
||||
//
|
||||
// Helper functions to access CPU Extended Control Register
|
||||
//
|
||||
UINT64
|
||||
EFIAPI
|
||||
ArmReadCpuExCr (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmWriteCpuExCr (
|
||||
IN UINT64 Val
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmSetCpuExCrBit (
|
||||
IN UINT64 Bits
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmUnsetCpuExCrBit (
|
||||
IN UINT64 Bits
|
||||
);
|
||||
|
||||
#endif // ARM_CORTEX_A5X_H_
|
57
ArmPkg/Include/Chipset/ArmCortexA9.h
Normal file
57
ArmPkg/Include/Chipset/ArmCortexA9.h
Normal file
@ -0,0 +1,57 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2011, ARM Limited. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef ARM_CORTEX_A9_H_
|
||||
#define ARM_CORTEX_A9_H_
|
||||
|
||||
#include <Chipset/ArmV7.h>
|
||||
|
||||
//
|
||||
// Cortex A9 feature bit definitions
|
||||
//
|
||||
#define A9_FEATURE_PARITY (1<<9)
|
||||
#define A9_FEATURE_AOW (1<<8)
|
||||
#define A9_FEATURE_EXCL (1<<7)
|
||||
#define A9_FEATURE_SMP (1<<6)
|
||||
#define A9_FEATURE_FOZ (1<<3)
|
||||
#define A9_FEATURE_DPREF (1<<2)
|
||||
#define A9_FEATURE_HINT (1<<1)
|
||||
#define A9_FEATURE_FWD (1<<0)
|
||||
|
||||
//
|
||||
// Cortex A9 Watchdog
|
||||
//
|
||||
#define ARM_A9_WATCHDOG_REGION 0x600
|
||||
|
||||
#define ARM_A9_WATCHDOG_LOAD_REGISTER 0x20
|
||||
#define ARM_A9_WATCHDOG_CONTROL_REGISTER 0x28
|
||||
|
||||
#define ARM_A9_WATCHDOG_WATCHDOG_MODE (1 << 3)
|
||||
#define ARM_A9_WATCHDOG_TIMER_MODE (0 << 3)
|
||||
#define ARM_A9_WATCHDOG_SINGLE_SHOT (0 << 1)
|
||||
#define ARM_A9_WATCHDOG_AUTORELOAD (1 << 1)
|
||||
#define ARM_A9_WATCHDOG_ENABLE 1
|
||||
|
||||
//
|
||||
// SCU register offsets & masks
|
||||
//
|
||||
#define A9_SCU_CONTROL_OFFSET 0x0
|
||||
#define A9_SCU_CONFIG_OFFSET 0x4
|
||||
#define A9_SCU_INVALL_OFFSET 0xC
|
||||
#define A9_SCU_FILT_START_OFFSET 0x40
|
||||
#define A9_SCU_FILT_END_OFFSET 0x44
|
||||
#define A9_SCU_SACR_OFFSET 0x50
|
||||
#define A9_SCU_SSACR_OFFSET 0x54
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmGetScuBaseAddress (
|
||||
VOID
|
||||
);
|
||||
|
||||
#endif // ARM_CORTEX_A9_H_
|
122
ArmPkg/Include/Chipset/ArmV7.h
Normal file
122
ArmPkg/Include/Chipset/ArmV7.h
Normal file
@ -0,0 +1,122 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
|
||||
Copyright (c) 2011-2021, Arm Limited. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef ARM_V7_H_
|
||||
#define ARM_V7_H_
|
||||
|
||||
#include <Chipset/ArmV7Mmu.h>
|
||||
|
||||
// ARM Interrupt ID in Exception Table
|
||||
#define ARM_ARCH_EXCEPTION_IRQ EXCEPT_ARM_IRQ
|
||||
|
||||
// ID_PFR1 - ARM Processor Feature Register 1 definitions
|
||||
#define ARM_PFR1_SEC (0xFUL << 4)
|
||||
#define ARM_PFR1_TIMER (0xFUL << 16)
|
||||
#define ARM_PFR1_GIC (0xFUL << 28)
|
||||
|
||||
// Domain Access Control Register
|
||||
#define DOMAIN_ACCESS_CONTROL_MASK(a) (3UL << (2 * (a)))
|
||||
#define DOMAIN_ACCESS_CONTROL_NONE(a) (0UL << (2 * (a)))
|
||||
#define DOMAIN_ACCESS_CONTROL_CLIENT(a) (1UL << (2 * (a)))
|
||||
#define DOMAIN_ACCESS_CONTROL_RESERVED(a) (2UL << (2 * (a)))
|
||||
#define DOMAIN_ACCESS_CONTROL_MANAGER(a) (3UL << (2 * (a)))
|
||||
|
||||
// CPSR - Coprocessor Status Register definitions
|
||||
#define CPSR_MODE_USER 0x10
|
||||
#define CPSR_MODE_FIQ 0x11
|
||||
#define CPSR_MODE_IRQ 0x12
|
||||
#define CPSR_MODE_SVC 0x13
|
||||
#define CPSR_MODE_ABORT 0x17
|
||||
#define CPSR_MODE_HYP 0x1A
|
||||
#define CPSR_MODE_UNDEFINED 0x1B
|
||||
#define CPSR_MODE_SYSTEM 0x1F
|
||||
#define CPSR_MODE_MASK 0x1F
|
||||
#define CPSR_ASYNC_ABORT (1 << 8)
|
||||
#define CPSR_IRQ (1 << 7)
|
||||
#define CPSR_FIQ (1 << 6)
|
||||
|
||||
// CPACR - Coprocessor Access Control Register definitions
|
||||
#define CPACR_CP_DENIED(cp) 0x00
|
||||
#define CPACR_CP_PRIV(cp) ((0x1 << ((cp) << 1)) & 0x0FFFFFFF)
|
||||
#define CPACR_CP_FULL(cp) ((0x3 << ((cp) << 1)) & 0x0FFFFFFF)
|
||||
#define CPACR_ASEDIS (1 << 31)
|
||||
#define CPACR_D32DIS (1 << 30)
|
||||
#define CPACR_CP_FULL_ACCESS 0x0FFFFFFF
|
||||
|
||||
// NSACR - Non-Secure Access Control Register definitions
|
||||
#define NSACR_CP(cp) ((1 << (cp)) & 0x3FFF)
|
||||
#define NSACR_NSD32DIS (1 << 14)
|
||||
#define NSACR_NSASEDIS (1 << 15)
|
||||
#define NSACR_PLE (1 << 16)
|
||||
#define NSACR_TL (1 << 17)
|
||||
#define NSACR_NS_SMP (1 << 18)
|
||||
#define NSACR_RFR (1 << 19)
|
||||
|
||||
// SCR - Secure Configuration Register definitions
|
||||
#define SCR_NS (1 << 0)
|
||||
#define SCR_IRQ (1 << 1)
|
||||
#define SCR_FIQ (1 << 2)
|
||||
#define SCR_EA (1 << 3)
|
||||
#define SCR_FW (1 << 4)
|
||||
#define SCR_AW (1 << 5)
|
||||
|
||||
// MIDR - Main ID Register definitions
|
||||
#define ARM_CPU_TYPE_SHIFT 4
|
||||
#define ARM_CPU_TYPE_MASK 0xFFF
|
||||
#define ARM_CPU_TYPE_AEMV8 0xD0F
|
||||
#define ARM_CPU_TYPE_A53 0xD03
|
||||
#define ARM_CPU_TYPE_A57 0xD07
|
||||
#define ARM_CPU_TYPE_A15 0xC0F
|
||||
#define ARM_CPU_TYPE_A12 0xC0D
|
||||
#define ARM_CPU_TYPE_A9 0xC09
|
||||
#define ARM_CPU_TYPE_A7 0xC07
|
||||
#define ARM_CPU_TYPE_A5 0xC05
|
||||
|
||||
#define ARM_CPU_REV_MASK ((0xF << 20) | (0xF) )
|
||||
#define ARM_CPU_REV(rn, pn) ((((rn) & 0xF) << 20) | ((pn) & 0xF))
|
||||
|
||||
#define ARM_VECTOR_TABLE_ALIGNMENT ((1 << 5)-1)
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmEnableSWPInstruction (
|
||||
VOID
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmReadCbar (
|
||||
VOID
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmReadTpidrurw (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmWriteTpidrurw (
|
||||
UINTN Value
|
||||
);
|
||||
|
||||
UINT32
|
||||
EFIAPI
|
||||
ArmReadNsacr (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmWriteNsacr (
|
||||
IN UINT32 Nsacr
|
||||
);
|
||||
|
||||
#endif // ARM_V7_H_
|
237
ArmPkg/Include/Chipset/ArmV7Mmu.h
Normal file
237
ArmPkg/Include/Chipset/ArmV7Mmu.h
Normal file
@ -0,0 +1,237 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2011-2013, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef ARMV7_MMU_H_
|
||||
#define ARMV7_MMU_H_
|
||||
|
||||
#define TTBR_NOT_OUTER_SHAREABLE BIT5
|
||||
#define TTBR_RGN_OUTER_NON_CACHEABLE 0
|
||||
#define TTBR_RGN_OUTER_WRITE_BACK_ALLOC BIT3
|
||||
#define TTBR_RGN_OUTER_WRITE_THROUGH BIT4
|
||||
#define TTBR_RGN_OUTER_WRITE_BACK_NO_ALLOC (BIT3|BIT4)
|
||||
#define TTBR_SHAREABLE BIT1
|
||||
#define TTBR_NON_SHAREABLE 0
|
||||
#define TTBR_INNER_CACHEABLE BIT0
|
||||
#define TTBR_INNER_NON_CACHEABLE 0
|
||||
#define TTBR_RGN_INNER_NON_CACHEABLE 0
|
||||
#define TTBR_RGN_INNER_WRITE_BACK_ALLOC BIT6
|
||||
#define TTBR_RGN_INNER_WRITE_THROUGH BIT0
|
||||
#define TTBR_RGN_INNER_WRITE_BACK_NO_ALLOC (BIT0|BIT6)
|
||||
|
||||
#define TTBR_WRITE_THROUGH ( TTBR_RGN_OUTER_WRITE_THROUGH | TTBR_INNER_CACHEABLE | TTBR_SHAREABLE)
|
||||
#define TTBR_WRITE_BACK_NO_ALLOC ( TTBR_RGN_OUTER_WRITE_BACK_NO_ALLOC | TTBR_INNER_CACHEABLE | TTBR_SHAREABLE)
|
||||
#define TTBR_NON_CACHEABLE ( TTBR_RGN_OUTER_NON_CACHEABLE | TTBR_INNER_NON_CACHEABLE )
|
||||
#define TTBR_WRITE_BACK_ALLOC ( TTBR_RGN_OUTER_WRITE_BACK_ALLOC | TTBR_INNER_CACHEABLE | TTBR_SHAREABLE)
|
||||
|
||||
#define TTBR_MP_WRITE_THROUGH ( TTBR_RGN_OUTER_WRITE_THROUGH | TTBR_RGN_INNER_WRITE_THROUGH | TTBR_SHAREABLE)
|
||||
#define TTBR_MP_WRITE_BACK_NO_ALLOC ( TTBR_RGN_OUTER_WRITE_BACK_NO_ALLOC | TTBR_RGN_INNER_WRITE_BACK_NO_ALLOC | TTBR_SHAREABLE)
|
||||
#define TTBR_MP_NON_CACHEABLE ( TTBR_RGN_OUTER_NON_CACHEABLE | TTBR_RGN_INNER_NON_CACHEABLE )
|
||||
#define TTBR_MP_WRITE_BACK_ALLOC ( TTBR_RGN_OUTER_WRITE_BACK_ALLOC | TTBR_RGN_INNER_WRITE_BACK_ALLOC | TTBR_SHAREABLE)
|
||||
|
||||
#define TRANSLATION_TABLE_SECTION_COUNT 4096
|
||||
#define TRANSLATION_TABLE_SECTION_SIZE (sizeof(UINT32) * TRANSLATION_TABLE_SECTION_COUNT)
|
||||
#define TRANSLATION_TABLE_SECTION_ALIGNMENT (sizeof(UINT32) * TRANSLATION_TABLE_SECTION_COUNT)
|
||||
#define TRANSLATION_TABLE_SECTION_ALIGNMENT_MASK (TRANSLATION_TABLE_SECTION_ALIGNMENT - 1)
|
||||
|
||||
#define TRANSLATION_TABLE_PAGE_COUNT 256
|
||||
#define TRANSLATION_TABLE_PAGE_SIZE (sizeof(UINT32) * TRANSLATION_TABLE_PAGE_COUNT)
|
||||
#define TRANSLATION_TABLE_PAGE_ALIGNMENT (sizeof(UINT32) * TRANSLATION_TABLE_PAGE_COUNT)
|
||||
#define TRANSLATION_TABLE_PAGE_ALIGNMENT_MASK (TRANSLATION_TABLE_PAGE_ALIGNMENT - 1)
|
||||
|
||||
#define TRANSLATION_TABLE_ENTRY_FOR_VIRTUAL_ADDRESS(table, address) ((UINT32 *)(table) + (((UINTN)(address)) >> 20))
|
||||
|
||||
// Translation table descriptor types
|
||||
#define TT_DESCRIPTOR_SECTION_TYPE_MASK ((1UL << 18) | (3UL << 0))
|
||||
#define TT_DESCRIPTOR_SECTION_TYPE_FAULT (0UL << 0)
|
||||
#define TT_DESCRIPTOR_SECTION_TYPE_PAGE_TABLE (1UL << 0)
|
||||
#define TT_DESCRIPTOR_SECTION_TYPE_SECTION ((0UL << 18) | (2UL << 0))
|
||||
#define TT_DESCRIPTOR_SECTION_TYPE_SUPERSECTION ((1UL << 18) | (2UL << 0))
|
||||
#define TT_DESCRIPTOR_SECTION_TYPE_IS_PAGE_TABLE(Desc) (((Desc) & 3UL) == TT_DESCRIPTOR_SECTION_TYPE_PAGE_TABLE)
|
||||
|
||||
// Translation table descriptor types
|
||||
#define TT_DESCRIPTOR_PAGE_TYPE_MASK (3UL << 0)
|
||||
#define TT_DESCRIPTOR_PAGE_TYPE_FAULT (0UL << 0)
|
||||
#define TT_DESCRIPTOR_PAGE_TYPE_PAGE (2UL << 0)
|
||||
#define TT_DESCRIPTOR_PAGE_TYPE_PAGE_XN (3UL << 0)
|
||||
#define TT_DESCRIPTOR_PAGE_TYPE_LARGEPAGE (1UL << 0)
|
||||
|
||||
// Section descriptor definitions
|
||||
#define TT_DESCRIPTOR_SECTION_SIZE (0x00100000)
|
||||
|
||||
#define TT_DESCRIPTOR_SECTION_NS_MASK (1UL << 19)
|
||||
#define TT_DESCRIPTOR_SECTION_NS (1UL << 19)
|
||||
|
||||
#define TT_DESCRIPTOR_SECTION_NG_MASK (1UL << 17)
|
||||
#define TT_DESCRIPTOR_SECTION_NG_GLOBAL (0UL << 17)
|
||||
#define TT_DESCRIPTOR_SECTION_NG_LOCAL (1UL << 17)
|
||||
|
||||
#define TT_DESCRIPTOR_PAGE_NG_MASK (1UL << 11)
|
||||
#define TT_DESCRIPTOR_PAGE_NG_GLOBAL (0UL << 11)
|
||||
#define TT_DESCRIPTOR_PAGE_NG_LOCAL (1UL << 11)
|
||||
|
||||
#define TT_DESCRIPTOR_SECTION_S_MASK (1UL << 16)
|
||||
#define TT_DESCRIPTOR_SECTION_S_NOT_SHARED (0UL << 16)
|
||||
#define TT_DESCRIPTOR_SECTION_S_SHARED (1UL << 16)
|
||||
|
||||
#define TT_DESCRIPTOR_PAGE_S_MASK (1UL << 10)
|
||||
#define TT_DESCRIPTOR_PAGE_S_NOT_SHARED (0UL << 10)
|
||||
#define TT_DESCRIPTOR_PAGE_S_SHARED (1UL << 10)
|
||||
|
||||
#define TT_DESCRIPTOR_SECTION_AP_MASK ((1UL << 15) | (3UL << 10))
|
||||
#define TT_DESCRIPTOR_SECTION_AP_NO_NO ((0UL << 15) | (0UL << 10))
|
||||
#define TT_DESCRIPTOR_SECTION_AP_RW_NO ((0UL << 15) | (1UL << 10))
|
||||
#define TT_DESCRIPTOR_SECTION_AP_RW_RO ((0UL << 15) | (2UL << 10))
|
||||
#define TT_DESCRIPTOR_SECTION_AP_RW_RW ((0UL << 15) | (3UL << 10))
|
||||
#define TT_DESCRIPTOR_SECTION_AP_RO_NO ((1UL << 15) | (1UL << 10))
|
||||
#define TT_DESCRIPTOR_SECTION_AP_RO_RO ((1UL << 15) | (3UL << 10))
|
||||
|
||||
#define TT_DESCRIPTOR_PAGE_AP_MASK ((1UL << 9) | (3UL << 4))
|
||||
#define TT_DESCRIPTOR_PAGE_AP_NO_NO ((0UL << 9) | (0UL << 4))
|
||||
#define TT_DESCRIPTOR_PAGE_AP_RW_NO ((0UL << 9) | (1UL << 4))
|
||||
#define TT_DESCRIPTOR_PAGE_AP_RW_RO ((0UL << 9) | (2UL << 4))
|
||||
#define TT_DESCRIPTOR_PAGE_AP_RW_RW ((0UL << 9) | (3UL << 4))
|
||||
#define TT_DESCRIPTOR_PAGE_AP_RO_NO ((1UL << 9) | (1UL << 4))
|
||||
#define TT_DESCRIPTOR_PAGE_AP_RO_RO ((1UL << 9) | (3UL << 4))
|
||||
|
||||
#define TT_DESCRIPTOR_SECTION_XN_MASK (0x1UL << 4)
|
||||
#define TT_DESCRIPTOR_PAGE_XN_MASK (0x1UL << 0)
|
||||
#define TT_DESCRIPTOR_LARGEPAGE_XN_MASK (0x1UL << 15)
|
||||
|
||||
#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK ((3UL << 12) | (1UL << 3) | (1UL << 2))
|
||||
#define TT_DESCRIPTOR_SECTION_CACHEABLE_MASK (1UL << 3)
|
||||
#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_STRONGLY_ORDERED ((0UL << 12) | (0UL << 3) | (0UL << 2))
|
||||
#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_SHAREABLE_DEVICE ((0UL << 12) | (0UL << 3) | (1UL << 2))
|
||||
#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC ((0UL << 12) | (1UL << 3) | (0UL << 2))
|
||||
#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_NO_ALLOC ((0UL << 12) | (1UL << 3) | (1UL << 2))
|
||||
#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE ((1UL << 12) | (0UL << 3) | (0UL << 2))
|
||||
#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC ((1UL << 12) | (1UL << 3) | (1UL << 2))
|
||||
#define TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_SHAREABLE_DEVICE ((2UL << 12) | (0UL << 3) | (0UL << 2))
|
||||
|
||||
#define TT_DESCRIPTOR_PAGE_SIZE (0x00001000)
|
||||
|
||||
#define TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK ((3UL << 6) | (1UL << 3) | (1UL << 2))
|
||||
#define TT_DESCRIPTOR_PAGE_CACHEABLE_MASK (1UL << 3)
|
||||
#define TT_DESCRIPTOR_PAGE_CACHE_POLICY_STRONGLY_ORDERED ((0UL << 6) | (0UL << 3) | (0UL << 2))
|
||||
#define TT_DESCRIPTOR_PAGE_CACHE_POLICY_SHAREABLE_DEVICE ((0UL << 6) | (0UL << 3) | (1UL << 2))
|
||||
#define TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC ((0UL << 6) | (1UL << 3) | (0UL << 2))
|
||||
#define TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_NO_ALLOC ((0UL << 6) | (1UL << 3) | (1UL << 2))
|
||||
#define TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE ((1UL << 6) | (0UL << 3) | (0UL << 2))
|
||||
#define TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_ALLOC ((1UL << 6) | (1UL << 3) | (1UL << 2))
|
||||
#define TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_SHAREABLE_DEVICE ((2UL << 6) | (0UL << 3) | (0UL << 2))
|
||||
|
||||
#define TT_DESCRIPTOR_LARGEPAGE_CACHE_POLICY_MASK ((3UL << 12) | (1UL << 3) | (1UL << 2))
|
||||
#define TT_DESCRIPTOR_LARGEPAGE_CACHE_POLICY_STRONGLY_ORDERED ((0UL << 12) | (0UL << 3) | (0UL << 2))
|
||||
#define TT_DESCRIPTOR_LARGEPAGE_CACHE_POLICY_SHAREABLE_DEVICE ((0UL << 12) | (0UL << 3) | (1UL << 2))
|
||||
#define TT_DESCRIPTOR_LARGEPAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC ((0UL << 12) | (1UL << 3) | (0UL << 2))
|
||||
#define TT_DESCRIPTOR_LARGEPAGE_CACHE_POLICY_WRITE_BACK_NO_ALLOC ((0UL << 12) | (1UL << 3) | (1UL << 2))
|
||||
#define TT_DESCRIPTOR_LARGEPAGE_CACHE_POLICY_NON_CACHEABLE ((1UL << 12) | (0UL << 3) | (0UL << 2))
|
||||
#define TT_DESCRIPTOR_LARGEPAGE_CACHE_POLICY_WRITE_BACK_ALLOC ((1UL << 12) | (1UL << 3) | (1UL << 2))
|
||||
#define TT_DESCRIPTOR_LARGEPAGE_CACHE_POLICY_NON_SHAREABLE_DEVICE ((2UL << 12) | (0UL << 3) | (0UL << 2))
|
||||
|
||||
#define TT_DESCRIPTOR_CONVERT_TO_PAGE_AP(Desc) ((((Desc) & TT_DESCRIPTOR_SECTION_AP_MASK) >> 6) & TT_DESCRIPTOR_PAGE_AP_MASK)
|
||||
#define TT_DESCRIPTOR_CONVERT_TO_PAGE_NG(Desc) ((((Desc) & TT_DESCRIPTOR_SECTION_NG_MASK) >> 6) & TT_DESCRIPTOR_PAGE_NG_MASK)
|
||||
#define TT_DESCRIPTOR_CONVERT_TO_PAGE_S(Desc) ((((Desc) & TT_DESCRIPTOR_SECTION_S_MASK) >> 6) & TT_DESCRIPTOR_PAGE_S_MASK)
|
||||
#define TT_DESCRIPTOR_CONVERT_TO_PAGE_XN(Desc, IsLargePage) ((IsLargePage)?\
|
||||
((((Desc) & TT_DESCRIPTOR_SECTION_XN_MASK) << 11) & TT_DESCRIPTOR_LARGEPAGE_XN_MASK): \
|
||||
((((Desc) & TT_DESCRIPTOR_SECTION_XN_MASK) >> 4) & TT_DESCRIPTOR_PAGE_XN_MASK))
|
||||
#define TT_DESCRIPTOR_CONVERT_TO_PAGE_CACHE_POLICY(Desc, IsLargePage) (IsLargePage? \
|
||||
(((Desc) & TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK) & TT_DESCRIPTOR_LARGEPAGE_CACHE_POLICY_MASK): \
|
||||
(((((Desc) & (0x3 << 12)) >> 6) | (Desc & (0x3 << 2)))))
|
||||
|
||||
#define TT_DESCRIPTOR_CONVERT_TO_SECTION_AP(Desc) ((((Desc) & TT_DESCRIPTOR_PAGE_AP_MASK) << 6) & TT_DESCRIPTOR_SECTION_AP_MASK)
|
||||
|
||||
#define TT_DESCRIPTOR_CONVERT_TO_SECTION_CACHE_POLICY(Desc, IsLargePage) (IsLargePage? \
|
||||
(((Desc) & TT_DESCRIPTOR_LARGEPAGE_CACHE_POLICY_MASK) & TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK): \
|
||||
(((((Desc) & (0x3 << 6)) << 6) | (Desc & (0x3 << 2)))))
|
||||
|
||||
#define TT_DESCRIPTOR_SECTION_ATTRIBUTE_MASK (TT_DESCRIPTOR_SECTION_NS_MASK | TT_DESCRIPTOR_SECTION_NG_MASK | \
|
||||
TT_DESCRIPTOR_SECTION_S_MASK | TT_DESCRIPTOR_SECTION_AP_MASK | \
|
||||
TT_DESCRIPTOR_SECTION_XN_MASK | TT_DESCRIPTOR_SECTION_CACHE_POLICY_MASK)
|
||||
|
||||
#define TT_DESCRIPTOR_PAGE_ATTRIBUTE_MASK (TT_DESCRIPTOR_PAGE_NG_MASK | TT_DESCRIPTOR_PAGE_S_MASK | \
|
||||
TT_DESCRIPTOR_PAGE_AP_MASK | TT_DESCRIPTOR_PAGE_XN_MASK | \
|
||||
TT_DESCRIPTOR_PAGE_CACHE_POLICY_MASK)
|
||||
|
||||
#define TT_DESCRIPTOR_SECTION_DOMAIN_MASK (0x0FUL << 5)
|
||||
#define TT_DESCRIPTOR_SECTION_DOMAIN(a) (((a) & 0x0FUL) << 5)
|
||||
|
||||
#define TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK (0xFFF00000)
|
||||
#define TT_DESCRIPTOR_SECTION_PAGETABLE_ADDRESS_MASK (0xFFFFFC00)
|
||||
#define TT_DESCRIPTOR_SECTION_BASE_ADDRESS(a) ((a) & TT_DESCRIPTOR_SECTION_BASE_ADDRESS_MASK)
|
||||
#define TT_DESCRIPTOR_SECTION_BASE_SHIFT 20
|
||||
|
||||
#define TT_DESCRIPTOR_PAGE_BASE_ADDRESS_MASK (0xFFFFF000)
|
||||
#define TT_DESCRIPTOR_PAGE_INDEX_MASK (0x000FF000)
|
||||
#define TT_DESCRIPTOR_PAGE_BASE_ADDRESS(a) ((a) & TT_DESCRIPTOR_PAGE_BASE_ADDRESS_MASK)
|
||||
#define TT_DESCRIPTOR_PAGE_BASE_SHIFT 12
|
||||
|
||||
#define TT_DESCRIPTOR_SECTION_WRITE_BACK(NonSecure) (TT_DESCRIPTOR_SECTION_TYPE_SECTION | \
|
||||
((NonSecure) ? TT_DESCRIPTOR_SECTION_NS : 0) | \
|
||||
TT_DESCRIPTOR_SECTION_NG_GLOBAL | \
|
||||
TT_DESCRIPTOR_SECTION_S_SHARED | \
|
||||
TT_DESCRIPTOR_SECTION_DOMAIN(0) | \
|
||||
TT_DESCRIPTOR_SECTION_AP_RW_RW | \
|
||||
TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_BACK_ALLOC)
|
||||
#define TT_DESCRIPTOR_SECTION_WRITE_THROUGH(NonSecure) (TT_DESCRIPTOR_SECTION_TYPE_SECTION | \
|
||||
((NonSecure) ? TT_DESCRIPTOR_SECTION_NS : 0) | \
|
||||
TT_DESCRIPTOR_SECTION_NG_GLOBAL | \
|
||||
TT_DESCRIPTOR_SECTION_S_SHARED | \
|
||||
TT_DESCRIPTOR_SECTION_DOMAIN(0) | \
|
||||
TT_DESCRIPTOR_SECTION_AP_RW_RW | \
|
||||
TT_DESCRIPTOR_SECTION_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC)
|
||||
#define TT_DESCRIPTOR_SECTION_DEVICE(NonSecure) (TT_DESCRIPTOR_SECTION_TYPE_SECTION | \
|
||||
((NonSecure) ? TT_DESCRIPTOR_SECTION_NS : 0) | \
|
||||
TT_DESCRIPTOR_SECTION_NG_GLOBAL | \
|
||||
TT_DESCRIPTOR_SECTION_S_NOT_SHARED | \
|
||||
TT_DESCRIPTOR_SECTION_DOMAIN(0) | \
|
||||
TT_DESCRIPTOR_SECTION_AP_RW_RW | \
|
||||
TT_DESCRIPTOR_SECTION_XN_MASK | \
|
||||
TT_DESCRIPTOR_SECTION_CACHE_POLICY_SHAREABLE_DEVICE)
|
||||
#define TT_DESCRIPTOR_SECTION_UNCACHED(NonSecure) (TT_DESCRIPTOR_SECTION_TYPE_SECTION | \
|
||||
((NonSecure) ? TT_DESCRIPTOR_SECTION_NS : 0) | \
|
||||
TT_DESCRIPTOR_SECTION_NG_GLOBAL | \
|
||||
TT_DESCRIPTOR_SECTION_S_NOT_SHARED | \
|
||||
TT_DESCRIPTOR_SECTION_DOMAIN(0) | \
|
||||
TT_DESCRIPTOR_SECTION_AP_RW_RW | \
|
||||
TT_DESCRIPTOR_SECTION_CACHE_POLICY_NON_CACHEABLE)
|
||||
|
||||
#define TT_DESCRIPTOR_PAGE_WRITE_BACK (TT_DESCRIPTOR_PAGE_TYPE_PAGE | \
|
||||
TT_DESCRIPTOR_PAGE_NG_GLOBAL | \
|
||||
TT_DESCRIPTOR_PAGE_S_SHARED | \
|
||||
TT_DESCRIPTOR_PAGE_AP_RW_RW | \
|
||||
TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_BACK_ALLOC)
|
||||
#define TT_DESCRIPTOR_PAGE_WRITE_THROUGH (TT_DESCRIPTOR_PAGE_TYPE_PAGE | \
|
||||
TT_DESCRIPTOR_PAGE_NG_GLOBAL | \
|
||||
TT_DESCRIPTOR_PAGE_S_SHARED | \
|
||||
TT_DESCRIPTOR_PAGE_AP_RW_RW | \
|
||||
TT_DESCRIPTOR_PAGE_CACHE_POLICY_WRITE_THROUGH_NO_ALLOC)
|
||||
#define TT_DESCRIPTOR_PAGE_DEVICE (TT_DESCRIPTOR_PAGE_TYPE_PAGE | \
|
||||
TT_DESCRIPTOR_PAGE_NG_GLOBAL | \
|
||||
TT_DESCRIPTOR_PAGE_S_NOT_SHARED | \
|
||||
TT_DESCRIPTOR_PAGE_AP_RW_RW | \
|
||||
TT_DESCRIPTOR_PAGE_XN_MASK | \
|
||||
TT_DESCRIPTOR_PAGE_CACHE_POLICY_SHAREABLE_DEVICE)
|
||||
#define TT_DESCRIPTOR_PAGE_UNCACHED (TT_DESCRIPTOR_PAGE_TYPE_PAGE | \
|
||||
TT_DESCRIPTOR_PAGE_NG_GLOBAL | \
|
||||
TT_DESCRIPTOR_PAGE_S_NOT_SHARED | \
|
||||
TT_DESCRIPTOR_PAGE_AP_RW_RW | \
|
||||
TT_DESCRIPTOR_PAGE_CACHE_POLICY_NON_CACHEABLE)
|
||||
|
||||
// First Level Descriptors
|
||||
typedef UINT32 ARM_FIRST_LEVEL_DESCRIPTOR;
|
||||
|
||||
// Second Level Descriptors
|
||||
typedef UINT32 ARM_PAGE_TABLE_ENTRY;
|
||||
|
||||
UINT32
|
||||
ConvertSectionAttributesToPageAttributes (
|
||||
IN UINT32 SectionAttributes,
|
||||
IN BOOLEAN IsLargePage
|
||||
);
|
||||
|
||||
#endif // ARMV7_MMU_H_
|
31
ArmPkg/Include/Guid/ArmMpCoreInfo.h
Normal file
31
ArmPkg/Include/Guid/ArmMpCoreInfo.h
Normal file
@ -0,0 +1,31 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2011, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef ARM_MP_CORE_INFO_GUID_H_
|
||||
#define ARM_MP_CORE_INFO_GUID_H_
|
||||
|
||||
#define MAX_CPUS_PER_MPCORE_SYSTEM 0x04
|
||||
#define SCU_CONFIG_REG_OFFSET 0x04
|
||||
#define MPIDR_U_BIT_MASK 0x40000000
|
||||
|
||||
typedef struct {
|
||||
UINT64 Mpidr;
|
||||
|
||||
// MP Core Mailbox
|
||||
EFI_PHYSICAL_ADDRESS MailboxSetAddress;
|
||||
EFI_PHYSICAL_ADDRESS MailboxGetAddress;
|
||||
EFI_PHYSICAL_ADDRESS MailboxClearAddress;
|
||||
UINT64 MailboxClearValue;
|
||||
} ARM_CORE_INFO;
|
||||
|
||||
#define ARM_MP_CORE_INFO_GUID \
|
||||
{ 0xa4ee0728, 0xe5d7, 0x4ac5, {0xb2, 0x1e, 0x65, 0x8e, 0xd8, 0x57, 0xe8, 0x34} }
|
||||
|
||||
extern EFI_GUID gArmMpCoreInfoGuid;
|
||||
|
||||
#endif /* ARM_MP_CORE_INFO_GUID_H_ */
|
111
ArmPkg/Include/IndustryStandard/ArmCache.h
Normal file
111
ArmPkg/Include/IndustryStandard/ArmCache.h
Normal file
@ -0,0 +1,111 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2020 - 2021, NUVIA Inc. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef ARM_CACHE_H_
|
||||
#define ARM_CACHE_H_
|
||||
|
||||
#include <Uefi/UefiBaseType.h>
|
||||
|
||||
// The ARM Architecture Reference Manual for ARMv8-A defines up
|
||||
// to 7 levels of cache, L1 through L7.
|
||||
#define MAX_ARM_CACHE_LEVEL 7
|
||||
|
||||
/// Defines the structure of the CSSELR (Cache Size Selection) register
|
||||
typedef union {
|
||||
struct {
|
||||
UINT32 InD : 1; ///< Instruction not Data bit
|
||||
UINT32 Level : 3; ///< Cache level (zero based)
|
||||
UINT32 TnD : 1; ///< Allocation not Data bit
|
||||
UINT32 Reserved : 27; ///< Reserved, RES0
|
||||
} Bits; ///< Bitfield definition of the register
|
||||
UINT32 Data; ///< The entire 32-bit value
|
||||
} CSSELR_DATA;
|
||||
|
||||
/// The cache type values for the InD field of the CSSELR register
|
||||
typedef enum {
|
||||
/// Select the data or unified cache
|
||||
CsselrCacheTypeDataOrUnified = 0,
|
||||
/// Select the instruction cache
|
||||
CsselrCacheTypeInstruction,
|
||||
CsselrCacheTypeMax
|
||||
} CSSELR_CACHE_TYPE;
|
||||
|
||||
/// Defines the structure of the CCSIDR (Current Cache Size ID) register
|
||||
typedef union {
|
||||
struct {
|
||||
UINT64 LineSize : 3; ///< Line size (Log2(Num bytes in cache) - 4)
|
||||
UINT64 Associativity : 10; ///< Associativity - 1
|
||||
UINT64 NumSets : 15; ///< Number of sets in the cache -1
|
||||
UINT64 Unknown : 4; ///< Reserved, UNKNOWN
|
||||
UINT64 Reserved : 32; ///< Reserved, RES0
|
||||
} BitsNonCcidx; ///< Bitfield definition of the register when FEAT_CCIDX is not supported.
|
||||
struct {
|
||||
UINT64 LineSize : 3; ///< Line size (Log2(Num bytes in cache) - 4)
|
||||
UINT64 Associativity : 21; ///< Associativity - 1
|
||||
UINT64 Reserved1 : 8; ///< Reserved, RES0
|
||||
UINT64 NumSets : 24; ///< Number of sets in the cache -1
|
||||
UINT64 Reserved2 : 8; ///< Reserved, RES0
|
||||
} BitsCcidxAA64; ///< Bitfield definition of the register when FEAT_IDX is supported.
|
||||
struct {
|
||||
UINT64 LineSize : 3;
|
||||
UINT64 Associativity : 21;
|
||||
UINT64 Reserved : 8;
|
||||
UINT64 Unallocated : 32;
|
||||
} BitsCcidxAA32;
|
||||
UINT64 Data; ///< The entire 64-bit value
|
||||
} CCSIDR_DATA;
|
||||
|
||||
/// Defines the structure of the AARCH32 CCSIDR2 register.
|
||||
typedef union {
|
||||
struct {
|
||||
UINT32 NumSets : 24; ///< Number of sets in the cache - 1
|
||||
UINT32 Reserved : 8; ///< Reserved, RES0
|
||||
} Bits; ///< Bitfield definition of the register
|
||||
UINT32 Data; ///< The entire 32-bit value
|
||||
} CCSIDR2_DATA;
|
||||
|
||||
/** Defines the structure of the CLIDR (Cache Level ID) register.
|
||||
*
|
||||
* The lower 32 bits are the same for both AARCH32 and AARCH64
|
||||
* so we can use the same structure for both.
|
||||
**/
|
||||
typedef union {
|
||||
struct {
|
||||
UINT32 Ctype1 : 3; ///< Level 1 cache type
|
||||
UINT32 Ctype2 : 3; ///< Level 2 cache type
|
||||
UINT32 Ctype3 : 3; ///< Level 3 cache type
|
||||
UINT32 Ctype4 : 3; ///< Level 4 cache type
|
||||
UINT32 Ctype5 : 3; ///< Level 5 cache type
|
||||
UINT32 Ctype6 : 3; ///< Level 6 cache type
|
||||
UINT32 Ctype7 : 3; ///< Level 7 cache type
|
||||
UINT32 LoUIS : 3; ///< Level of Unification Inner Shareable
|
||||
UINT32 LoC : 3; ///< Level of Coherency
|
||||
UINT32 LoUU : 3; ///< Level of Unification Uniprocessor
|
||||
UINT32 Icb : 3; ///< Inner Cache Boundary
|
||||
} Bits; ///< Bitfield definition of the register
|
||||
UINT32 Data; ///< The entire 32-bit value
|
||||
} CLIDR_DATA;
|
||||
|
||||
/// The cache types reported in the CLIDR register.
|
||||
typedef enum {
|
||||
/// No cache is present
|
||||
ClidrCacheTypeNone = 0,
|
||||
/// There is only an instruction cache
|
||||
ClidrCacheTypeInstructionOnly,
|
||||
/// There is only a data cache
|
||||
ClidrCacheTypeDataOnly,
|
||||
/// There are separate data and instruction caches
|
||||
ClidrCacheTypeSeparate,
|
||||
/// There is a unified cache
|
||||
ClidrCacheTypeUnified,
|
||||
ClidrCacheTypeMax
|
||||
} CLIDR_CACHE_TYPE;
|
||||
|
||||
#define CLIDR_GET_CACHE_TYPE(x, level) ((x >> (3 * (level))) & 0b111)
|
||||
|
||||
#endif /* ARM_CACHE_H_ */
|
56
ArmPkg/Include/IndustryStandard/ArmFfaSvc.h
Normal file
56
ArmPkg/Include/IndustryStandard/ArmFfaSvc.h
Normal file
@ -0,0 +1,56 @@
|
||||
/** @file
|
||||
Header file for FF-A ABI's that will be used for
|
||||
communication between S-EL0 and the Secure Partition
|
||||
Manager(SPM)
|
||||
|
||||
Copyright (c) 2020, ARM Limited. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
@par Revision Reference:
|
||||
- FF-A Version 1.0
|
||||
|
||||
|
||||
**/
|
||||
|
||||
#ifndef ARM_FFA_SVC_H_
|
||||
#define ARM_FFA_SVC_H_
|
||||
|
||||
#define ARM_SVC_ID_FFA_VERSION_AARCH32 0x84000063
|
||||
#define ARM_SVC_ID_FFA_MSG_SEND_DIRECT_REQ_AARCH32 0x8400006F
|
||||
#define ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP_AARCH32 0x84000070
|
||||
#define ARM_SVC_ID_FFA_MSG_SEND_DIRECT_REQ_AARCH64 0xC400006F
|
||||
#define ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP_AARCH64 0xC4000070
|
||||
|
||||
/* Generic IDs when using AArch32 or AArch64 execution state */
|
||||
#ifdef MDE_CPU_AARCH64
|
||||
#define ARM_SVC_ID_FFA_MSG_SEND_DIRECT_REQ ARM_SVC_ID_FFA_MSG_SEND_DIRECT_REQ_AARCH64
|
||||
#define ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP_AARCH64
|
||||
#endif
|
||||
#ifdef MDE_CPU_ARM
|
||||
#define ARM_SVC_ID_FFA_MSG_SEND_DIRECT_REQ ARM_SVC_ID_FFA_MSG_SEND_DIRECT_REQ_AARCH32
|
||||
#define ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP ARM_SVC_ID_FFA_MSG_SEND_DIRECT_RESP_AARCH32
|
||||
#endif
|
||||
|
||||
#define SPM_MAJOR_VERSION_FFA 1
|
||||
#define SPM_MINOR_VERSION_FFA 0
|
||||
|
||||
#define ARM_FFA_SPM_RET_SUCCESS 0
|
||||
#define ARM_FFA_SPM_RET_NOT_SUPPORTED -1
|
||||
#define ARM_FFA_SPM_RET_INVALID_PARAMETERS -2
|
||||
#define ARM_FFA_SPM_RET_NO_MEMORY -3
|
||||
#define ARM_FFA_SPM_RET_BUSY -4
|
||||
#define ARM_FFA_SPM_RET_INTERRUPTED -5
|
||||
#define ARM_FFA_SPM_RET_DENIED -6
|
||||
#define ARM_FFA_SPM_RET_RETRY -7
|
||||
#define ARM_FFA_SPM_RET_ABORTED -8
|
||||
|
||||
// For now, the destination id to be used in the FF-A calls
|
||||
// is being hard-coded. Subsequently, support will be added
|
||||
// to get the endpoint id's dynamically
|
||||
// This is the endpoint id used by the optee os's implementation
|
||||
// of the spmc.
|
||||
// https://github.com/OP-TEE/optee_os/blob/master/core/arch/arm/kernel/stmm_sp.c#L66
|
||||
#define ARM_FFA_DESTINATION_ENDPOINT_ID 3
|
||||
|
||||
#endif // ARM_FFA_SVC_H_
|
62
ArmPkg/Include/IndustryStandard/ArmMmSvc.h
Normal file
62
ArmPkg/Include/IndustryStandard/ArmMmSvc.h
Normal file
@ -0,0 +1,62 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2012-2017, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef ARM_MM_SVC_H_
|
||||
#define ARM_MM_SVC_H_
|
||||
|
||||
/*
|
||||
* SVC IDs to allow the MM secure partition to initialise itself, handle
|
||||
* delegated events and request the Secure partition manager to perform
|
||||
* privileged operations on its behalf.
|
||||
*/
|
||||
#define ARM_SVC_ID_SPM_VERSION_AARCH32 0x84000060
|
||||
#define ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH32 0x84000061
|
||||
#define ARM_SVC_ID_SP_GET_MEM_ATTRIBUTES_AARCH32 0x84000064
|
||||
#define ARM_SVC_ID_SP_SET_MEM_ATTRIBUTES_AARCH32 0x84000065
|
||||
#define ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64 0xC4000061
|
||||
#define ARM_SVC_ID_SP_GET_MEM_ATTRIBUTES_AARCH64 0xC4000064
|
||||
#define ARM_SVC_ID_SP_SET_MEM_ATTRIBUTES_AARCH64 0xC4000065
|
||||
|
||||
/* Generic IDs when using AArch32 or AArch64 execution state */
|
||||
#ifdef MDE_CPU_AARCH64
|
||||
#define ARM_SVC_ID_SP_EVENT_COMPLETE ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH64
|
||||
#define ARM_SVC_ID_SP_GET_MEM_ATTRIBUTES ARM_SVC_ID_SP_GET_MEM_ATTRIBUTES_AARCH64
|
||||
#define ARM_SVC_ID_SP_SET_MEM_ATTRIBUTES ARM_SVC_ID_SP_SET_MEM_ATTRIBUTES_AARCH64
|
||||
#endif
|
||||
#ifdef MDE_CPU_ARM
|
||||
#define ARM_SVC_ID_SP_EVENT_COMPLETE ARM_SVC_ID_SP_EVENT_COMPLETE_AARCH32
|
||||
#define ARM_SVC_ID_SP_GET_MEM_ATTRIBUTES ARM_SVC_ID_SP_GET_MEM_ATTRIBUTES_AARCH32
|
||||
#define ARM_SVC_ID_SP_SET_MEM_ATTRIBUTES ARM_SVC_ID_SP_SET_MEM_ATTRIBUTES_AARCH32
|
||||
#endif
|
||||
|
||||
#define SET_MEM_ATTR_DATA_PERM_MASK 0x3
|
||||
#define SET_MEM_ATTR_DATA_PERM_SHIFT 0
|
||||
#define SET_MEM_ATTR_DATA_PERM_NO_ACCESS 0
|
||||
#define SET_MEM_ATTR_DATA_PERM_RW 1
|
||||
#define SET_MEM_ATTR_DATA_PERM_RO 3
|
||||
|
||||
#define SET_MEM_ATTR_CODE_PERM_MASK 0x1
|
||||
#define SET_MEM_ATTR_CODE_PERM_SHIFT 2
|
||||
#define SET_MEM_ATTR_CODE_PERM_X 0
|
||||
#define SET_MEM_ATTR_CODE_PERM_XN 1
|
||||
|
||||
#define SET_MEM_ATTR_MAKE_PERM_REQUEST(d_perm, c_perm) \
|
||||
((((c_perm) & SET_MEM_ATTR_CODE_PERM_MASK) << SET_MEM_ATTR_CODE_PERM_SHIFT) | \
|
||||
(( (d_perm) & SET_MEM_ATTR_DATA_PERM_MASK) << SET_MEM_ATTR_DATA_PERM_SHIFT))
|
||||
|
||||
/* MM SVC Return error codes */
|
||||
#define ARM_SVC_SPM_RET_SUCCESS 0
|
||||
#define ARM_SVC_SPM_RET_NOT_SUPPORTED -1
|
||||
#define ARM_SVC_SPM_RET_INVALID_PARAMS -2
|
||||
#define ARM_SVC_SPM_RET_DENIED -3
|
||||
#define ARM_SVC_SPM_RET_NO_MEMORY -5
|
||||
|
||||
#define SPM_MAJOR_VERSION 0
|
||||
#define SPM_MINOR_VERSION 1
|
||||
|
||||
#endif // ARM_MM_SVC_H_
|
247
ArmPkg/Include/IndustryStandard/ArmStdSmc.h
Normal file
247
ArmPkg/Include/IndustryStandard/ArmStdSmc.h
Normal file
@ -0,0 +1,247 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2020, NUVIA Inc. All rights reserved.<BR>
|
||||
* Copyright (c) 2012 - 2022, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
* @par Revision Reference:
|
||||
* - [1] SMC Calling Convention version 1.2
|
||||
* (https://developer.arm.com/documentation/den0028/c/?lang=en)
|
||||
* - [2] Arm True Random Number Generator Firmware, Interface 1.0,
|
||||
* Platform Design Document.
|
||||
* (https://developer.arm.com/documentation/den0098/latest/)
|
||||
*
|
||||
* @par Glossary:
|
||||
* - TRNG - True Random Number Generator
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef ARM_STD_SMC_H_
|
||||
#define ARM_STD_SMC_H_
|
||||
|
||||
/*
|
||||
* SMC function IDs for Standard Service queries
|
||||
*/
|
||||
|
||||
#define ARM_SMC_ID_STD_CALL_COUNT 0x8400ff00
|
||||
#define ARM_SMC_ID_STD_UID 0x8400ff01
|
||||
/* 0x8400ff02 is reserved */
|
||||
#define ARM_SMC_ID_STD_REVISION 0x8400ff03
|
||||
|
||||
/*
|
||||
* The 'Standard Service Call UID' is supposed to return the Standard
|
||||
* Service UUID. This is a 128-bit value.
|
||||
*/
|
||||
#define ARM_SMC_STD_UUID0 0x108d905b
|
||||
#define ARM_SMC_STD_UUID1 0x47e8f863
|
||||
#define ARM_SMC_STD_UUID2 0xfbc02dae
|
||||
#define ARM_SMC_STD_UUID3 0xe2f64156
|
||||
|
||||
/*
|
||||
* ARM Standard Service Calls revision numbers
|
||||
* The current revision is: 0.1
|
||||
*/
|
||||
#define ARM_SMC_STD_REVISION_MAJOR 0x0
|
||||
#define ARM_SMC_STD_REVISION_MINOR 0x1
|
||||
|
||||
/*
|
||||
* Management Mode (MM) calls cover a subset of the Standard Service Call range.
|
||||
* The list below is not exhaustive.
|
||||
*/
|
||||
#define ARM_SMC_ID_MM_VERSION_AARCH32 0x84000040
|
||||
#define ARM_SMC_ID_MM_VERSION_AARCH64 0xC4000040
|
||||
|
||||
// Request service from secure standalone MM environment
|
||||
#define ARM_SMC_ID_MM_COMMUNICATE_AARCH32 0x84000041
|
||||
#define ARM_SMC_ID_MM_COMMUNICATE_AARCH64 0xC4000041
|
||||
|
||||
/* Generic ID when using AArch32 or AArch64 execution state */
|
||||
#ifdef MDE_CPU_AARCH64
|
||||
#define ARM_SMC_ID_MM_COMMUNICATE ARM_SMC_ID_MM_COMMUNICATE_AARCH64
|
||||
#endif
|
||||
#ifdef MDE_CPU_ARM
|
||||
#define ARM_SMC_ID_MM_COMMUNICATE ARM_SMC_ID_MM_COMMUNICATE_AARCH32
|
||||
#endif
|
||||
|
||||
/* MM return error codes */
|
||||
#define ARM_SMC_MM_RET_SUCCESS 0
|
||||
#define ARM_SMC_MM_RET_NOT_SUPPORTED -1
|
||||
#define ARM_SMC_MM_RET_INVALID_PARAMS -2
|
||||
#define ARM_SMC_MM_RET_DENIED -3
|
||||
#define ARM_SMC_MM_RET_NO_MEMORY -4
|
||||
|
||||
// ARM Architecture Calls
|
||||
#define SMCCC_VERSION 0x80000000
|
||||
#define SMCCC_ARCH_FEATURES 0x80000001
|
||||
#define SMCCC_ARCH_SOC_ID 0x80000002
|
||||
#define SMCCC_ARCH_WORKAROUND_1 0x80008000
|
||||
#define SMCCC_ARCH_WORKAROUND_2 0x80007FFF
|
||||
|
||||
#define SMC_ARCH_CALL_SUCCESS 0
|
||||
#define SMC_ARCH_CALL_NOT_SUPPORTED -1
|
||||
#define SMC_ARCH_CALL_NOT_REQUIRED -2
|
||||
#define SMC_ARCH_CALL_INVALID_PARAMETER -3
|
||||
|
||||
/*
|
||||
* Power State Coordination Interface (PSCI) calls cover a subset of the
|
||||
* Standard Service Call range.
|
||||
* The list below is not exhaustive.
|
||||
*/
|
||||
#define ARM_SMC_ID_PSCI_VERSION 0x84000000
|
||||
#define ARM_SMC_ID_PSCI_CPU_SUSPEND_AARCH64 0xc4000001
|
||||
#define ARM_SMC_ID_PSCI_CPU_SUSPEND_AARCH32 0x84000001
|
||||
#define ARM_SMC_ID_PSCI_CPU_OFF 0x84000002
|
||||
#define ARM_SMC_ID_PSCI_CPU_ON_AARCH64 0xc4000003
|
||||
#define ARM_SMC_ID_PSCI_CPU_ON_AARCH32 0x84000003
|
||||
#define ARM_SMC_ID_PSCI_AFFINITY_INFO_AARCH64 0xc4000004
|
||||
#define ARM_SMC_ID_PSCI_AFFINITY_INFO_AARCH32 0x84000004
|
||||
#define ARM_SMC_ID_PSCI_MIGRATE_AARCH64 0xc4000005
|
||||
#define ARM_SMC_ID_PSCI_MIGRATE_AARCH32 0x84000005
|
||||
#define ARM_SMC_ID_PSCI_SYSTEM_OFF 0x84000008
|
||||
#define ARM_SMC_ID_PSCI_SYSTEM_RESET 0x84000009
|
||||
#define ARM_SMC_ID_PSCI_FEATURES 0x8400000A
|
||||
#define ARM_SMC_ID_PSCI_SYSTEM_RESET2_AARCH64 0xC4000012
|
||||
|
||||
/* The current PSCI version is: 0.2 */
|
||||
#define ARM_SMC_PSCI_VERSION_MAJOR 0
|
||||
#define ARM_SMC_PSCI_VERSION_MINOR 2
|
||||
#define ARM_SMC_PSCI_VERSION \
|
||||
((ARM_SMC_PSCI_VERSION_MAJOR << 16) | ARM_SMC_PSCI_VERSION_MINOR)
|
||||
|
||||
/* PSCI return error codes */
|
||||
#define ARM_SMC_PSCI_RET_SUCCESS 0
|
||||
#define ARM_SMC_PSCI_RET_NOT_SUPPORTED -1
|
||||
#define ARM_SMC_PSCI_RET_INVALID_PARAMS -2
|
||||
#define ARM_SMC_PSCI_RET_DENIED -3
|
||||
#define ARM_SMC_PSCI_RET_ALREADY_ON -4
|
||||
#define ARM_SMC_PSCI_RET_ON_PENDING -5
|
||||
#define ARM_SMC_PSCI_RET_INTERN_FAIL -6
|
||||
#define ARM_SMC_PSCI_RET_NOT_PRESENT -7
|
||||
#define ARM_SMC_PSCI_RET_DISABLED -8
|
||||
|
||||
#define ARM_SMC_PSCI_TARGET_CPU32(Aff2, Aff1, Aff0) \
|
||||
((((Aff2) & 0xFF) << 16) | (((Aff1) & 0xFF) << 8) | ((Aff0) & 0xFF))
|
||||
|
||||
#define ARM_SMC_PSCI_TARGET_CPU64(Aff3, Aff2, Aff1, Aff0) \
|
||||
((((Aff3) & 0xFFULL) << 32) | (((Aff2) & 0xFF) << 16) | (((Aff1) & 0xFF) << 8) | ((Aff0) & 0xFF))
|
||||
|
||||
#define ARM_SMC_PSCI_TARGET_GET_AFF0(TargetId) ((TargetId) & 0xFF)
|
||||
#define ARM_SMC_PSCI_TARGET_GET_AFF1(TargetId) (((TargetId) >> 8) & 0xFF)
|
||||
|
||||
#define ARM_SMC_ID_PSCI_AFFINITY_LEVEL_0 0
|
||||
#define ARM_SMC_ID_PSCI_AFFINITY_LEVEL_1 1
|
||||
#define ARM_SMC_ID_PSCI_AFFINITY_LEVEL_2 2
|
||||
#define ARM_SMC_ID_PSCI_AFFINITY_LEVEL_3 3
|
||||
|
||||
#define ARM_SMC_ID_PSCI_AFFINITY_INFO_ON 0
|
||||
#define ARM_SMC_ID_PSCI_AFFINITY_INFO_OFF 1
|
||||
#define ARM_SMC_ID_PSCI_AFFINITY_INFO_ON_PENDING 2
|
||||
|
||||
/*
|
||||
* SMC function IDs for Trusted OS Service queries
|
||||
*/
|
||||
#define ARM_SMC_ID_TOS_CALL_COUNT 0xbf00ff00
|
||||
#define ARM_SMC_ID_TOS_UID 0xbf00ff01
|
||||
/* 0xbf00ff02 is reserved */
|
||||
#define ARM_SMC_ID_TOS_REVISION 0xbf00ff03
|
||||
|
||||
// Firmware TRNG interface Function IDs
|
||||
|
||||
/*
|
||||
SMC/HVC call to get the version of the TRNG backend,
|
||||
Cf. [2], 2.1 TRNG_VERSION
|
||||
Input values:
|
||||
W0 0x8400_0050
|
||||
W1-W7 Reserved (MBZ)
|
||||
Return values:
|
||||
Success (W0 > 0) W0[31] MBZ
|
||||
W0[30:16] Major revision
|
||||
W0[15:0] Minor revision
|
||||
W1 - W3 Reserved (MBZ)
|
||||
Error (W0 < 0)
|
||||
NOT_SUPPORTED Function not implemented
|
||||
*/
|
||||
#define ARM_SMC_ID_TRNG_VERSION 0x84000050
|
||||
|
||||
/*
|
||||
SMC/HVC call to check if a TRNG function ID is implemented by the backend,
|
||||
Cf. [2], Section 2.2 TRNG_FEATURES
|
||||
Input Values
|
||||
W0 0x8400_0051
|
||||
W1 trng_func_id
|
||||
W2-W7 Reserved (MBZ)
|
||||
Return values:
|
||||
Success (W0 >= 0):
|
||||
SUCCESS Function is implemented.
|
||||
> 0 Function is implemented and
|
||||
has specific capabilities,
|
||||
see function definition.
|
||||
Error (W0 < 0)
|
||||
NOT_SUPPORTED Function with FID=trng_func_id
|
||||
is not implemented
|
||||
*/
|
||||
#define ARM_SMC_ID_TRNG_FEATURES 0x84000051
|
||||
|
||||
/*
|
||||
SMC/HVC call to get the UUID of the TRNG backend,
|
||||
Cf. [2], Section 2.3 TRNG_GET_UUID
|
||||
Input Values:
|
||||
W0 0x8400_0052
|
||||
W1-W7 Reserved (MBZ)
|
||||
Return Values:
|
||||
Success (W0 != -1)
|
||||
W0 UUID[31:0]
|
||||
W1 UUID[63:32]
|
||||
W2 UUID[95:64]
|
||||
W3 UUID[127:96]
|
||||
Error (W0 = -1)
|
||||
W0 NOT_SUPPORTED
|
||||
*/
|
||||
#define ARM_SMC_ID_TRNG_GET_UUID 0x84000052
|
||||
|
||||
/*
|
||||
AARCH32 SMC/HVC call to get entropy bits, Cf. [2], Section 2.4 TRNG_RND.
|
||||
Input values:
|
||||
W0 0x8400_0053
|
||||
W2-W7 Reserved (MBZ)
|
||||
Return values:
|
||||
Success (W0 = 0):
|
||||
W0 MBZ
|
||||
W1 Entropy[95:64]
|
||||
W2 Entropy[63:32]
|
||||
W3 Entropy[31:0]
|
||||
Error (W0 < 0)
|
||||
W0 NOT_SUPPORTED
|
||||
NO_ENTROPY
|
||||
INVALID_PARAMETERS
|
||||
W1 - W3 Reserved (MBZ)
|
||||
*/
|
||||
#define ARM_SMC_ID_TRNG_RND_AARCH32 0x84000053
|
||||
|
||||
/*
|
||||
AARCH64 SMC/HVC call to get entropy bits, Cf. [2], Section 2.4 TRNG_RND.
|
||||
Input values:
|
||||
X0 0xC400_0053
|
||||
X2-X7 Reserved (MBZ)
|
||||
Return values:
|
||||
Success (X0 = 0):
|
||||
X0 MBZ
|
||||
X1 Entropy[191:128]
|
||||
X2 Entropy[127:64]
|
||||
X3 Entropy[63:0]
|
||||
Error (X0 < 0)
|
||||
X0 NOT_SUPPORTED
|
||||
NO_ENTROPY
|
||||
INVALID_PARAMETERS
|
||||
X1 - X3 Reserved (MBZ)
|
||||
*/
|
||||
#define ARM_SMC_ID_TRNG_RND_AARCH64 0xC4000053
|
||||
|
||||
// Firmware TRNG status codes
|
||||
#define TRNG_STATUS_SUCCESS (INT32)(0)
|
||||
#define TRNG_STATUS_NOT_SUPPORTED (INT32)(-1)
|
||||
#define TRNG_STATUS_INVALID_PARAMETER (INT32)(-2)
|
||||
#define TRNG_STATUS_NO_ENTROPY (INT32)(-3)
|
||||
|
||||
#endif // ARM_STD_SMC_H_
|
37
ArmPkg/Include/Library/ArmDisassemblerLib.h
Normal file
37
ArmPkg/Include/Library/ArmDisassemblerLib.h
Normal file
@ -0,0 +1,37 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef ARM_DISASSEMBLER_LIB_H_
|
||||
#define ARM_DISASSEMBLER_LIB_H_
|
||||
|
||||
/**
|
||||
Place a disassembly of **OpCodePtr into buffer, and update OpCodePtr to
|
||||
point to next instruction.
|
||||
|
||||
We cheat and only decode instructions that access
|
||||
memory. If the instruction is not found we dump the instruction in hex.
|
||||
|
||||
@param OpCodePtrPtr Pointer to pointer of ARM Thumb instruction to disassemble.
|
||||
@param Thumb TRUE for Thumb(2), FALSE for ARM instruction stream
|
||||
@param Extended TRUE dump hex for instruction too.
|
||||
@param ItBlock Size of IT Block
|
||||
@param Buf Buffer to sprintf disassembly into.
|
||||
@param Size Size of Buf in bytes.
|
||||
|
||||
**/
|
||||
VOID
|
||||
DisassembleInstruction (
|
||||
IN UINT8 **OpCodePtr,
|
||||
IN BOOLEAN Thumb,
|
||||
IN BOOLEAN Extended,
|
||||
IN OUT UINT32 *ItBlock,
|
||||
OUT CHAR8 *Buf,
|
||||
OUT UINTN Size
|
||||
);
|
||||
|
||||
#endif // ARM_DISASSEMBLER_LIB_H_
|
85
ArmPkg/Include/Library/ArmGenericTimerCounterLib.h
Normal file
85
ArmPkg/Include/Library/ArmGenericTimerCounterLib.h
Normal file
@ -0,0 +1,85 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2011 - 2014, ARM Ltd. All rights reserved.<BR>
|
||||
Copyright (c) 2014, Linaro Ltd. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef ARM_GENERIC_TIMER_COUNTER_LIB_H_
|
||||
#define ARM_GENERIC_TIMER_COUNTER_LIB_H_
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGenericTimerEnableTimer (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGenericTimerReenableTimer (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGenericTimerDisableTimer (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGenericTimerSetTimerFreq (
|
||||
IN UINTN FreqInHz
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmGenericTimerGetTimerFreq (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGenericTimerSetTimerVal (
|
||||
IN UINTN Value
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmGenericTimerGetTimerVal (
|
||||
VOID
|
||||
);
|
||||
|
||||
UINT64
|
||||
EFIAPI
|
||||
ArmGenericTimerGetSystemCount (
|
||||
VOID
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmGenericTimerGetTimerCtrlReg (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGenericTimerSetTimerCtrlReg (
|
||||
UINTN Value
|
||||
);
|
||||
|
||||
UINT64
|
||||
EFIAPI
|
||||
ArmGenericTimerGetCompareVal (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGenericTimerSetCompareVal (
|
||||
IN UINT64 Value
|
||||
);
|
||||
|
||||
#endif // ARM_GENERIC_TIMER_COUNTER_LIB_H_
|
26
ArmPkg/Include/Library/ArmGicArchLib.h
Normal file
26
ArmPkg/Include/Library/ArmGicArchLib.h
Normal file
@ -0,0 +1,26 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2015, Linaro Ltd. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef ARM_GIC_ARCH_LIB_H_
|
||||
#define ARM_GIC_ARCH_LIB_H_
|
||||
|
||||
//
|
||||
// GIC definitions
|
||||
//
|
||||
typedef enum {
|
||||
ARM_GIC_ARCH_REVISION_2,
|
||||
ARM_GIC_ARCH_REVISION_3
|
||||
} ARM_GIC_ARCH_REVISION;
|
||||
|
||||
ARM_GIC_ARCH_REVISION
|
||||
EFIAPI
|
||||
ArmGicGetSupportedArchRevision (
|
||||
VOID
|
||||
);
|
||||
|
||||
#endif // ARM_GIC_ARCH_LIB_H_
|
335
ArmPkg/Include/Library/ArmGicLib.h
Normal file
335
ArmPkg/Include/Library/ArmGicLib.h
Normal file
@ -0,0 +1,335 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2011-2021, Arm Limited. All rights reserved.<BR>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef ARMGIC_H_
|
||||
#define ARMGIC_H_
|
||||
|
||||
#include <Library/ArmGicArchLib.h>
|
||||
|
||||
// GIC Distributor
|
||||
#define ARM_GIC_ICDDCR 0x000 // Distributor Control Register
|
||||
#define ARM_GIC_ICDICTR 0x004 // Interrupt Controller Type Register
|
||||
#define ARM_GIC_ICDIIDR 0x008 // Implementer Identification Register
|
||||
|
||||
// Each reg base below repeats for Number of interrupts / 4 (see GIC spec)
|
||||
#define ARM_GIC_ICDISR 0x080 // Interrupt Security Registers
|
||||
#define ARM_GIC_ICDISER 0x100 // Interrupt Set-Enable Registers
|
||||
#define ARM_GIC_ICDICER 0x180 // Interrupt Clear-Enable Registers
|
||||
#define ARM_GIC_ICDSPR 0x200 // Interrupt Set-Pending Registers
|
||||
#define ARM_GIC_ICDICPR 0x280 // Interrupt Clear-Pending Registers
|
||||
#define ARM_GIC_ICDABR 0x300 // Active Bit Registers
|
||||
|
||||
// Each reg base below repeats for Number of interrupts / 4
|
||||
#define ARM_GIC_ICDIPR 0x400 // Interrupt Priority Registers
|
||||
|
||||
// Each reg base below repeats for Number of interrupts
|
||||
#define ARM_GIC_ICDIPTR 0x800 // Interrupt Processor Target Registers
|
||||
#define ARM_GIC_ICDICFR 0xC00 // Interrupt Configuration Registers
|
||||
|
||||
#define ARM_GIC_ICDPPISR 0xD00 // PPI Status register
|
||||
|
||||
// just one of these
|
||||
#define ARM_GIC_ICDSGIR 0xF00 // Software Generated Interrupt Register
|
||||
|
||||
// GICv3 specific registers
|
||||
#define ARM_GICD_IROUTER 0x6100 // Interrupt Routing Registers
|
||||
|
||||
// GICD_CTLR bits
|
||||
#define ARM_GIC_ICDDCR_ARE (1 << 4) // Affinity Routing Enable (ARE)
|
||||
#define ARM_GIC_ICDDCR_DS (1 << 6) // Disable Security (DS)
|
||||
|
||||
// GICD_ICDICFR bits
|
||||
#define ARM_GIC_ICDICFR_WIDTH 32 // ICDICFR is a 32 bit register
|
||||
#define ARM_GIC_ICDICFR_BYTES (ARM_GIC_ICDICFR_WIDTH / 8)
|
||||
#define ARM_GIC_ICDICFR_F_WIDTH 2 // Each F field is 2 bits
|
||||
#define ARM_GIC_ICDICFR_F_STRIDE 16 // (32/2) F fields per register
|
||||
#define ARM_GIC_ICDICFR_F_CONFIG1_BIT 1 // Bit number within F field
|
||||
#define ARM_GIC_ICDICFR_LEVEL_TRIGGERED 0x0 // Level triggered interrupt
|
||||
#define ARM_GIC_ICDICFR_EDGE_TRIGGERED 0x1 // Edge triggered interrupt
|
||||
|
||||
// GIC Redistributor
|
||||
#define ARM_GICR_CTLR_FRAME_SIZE SIZE_64KB
|
||||
#define ARM_GICR_SGI_PPI_FRAME_SIZE SIZE_64KB
|
||||
#define ARM_GICR_SGI_VLPI_FRAME_SIZE SIZE_64KB
|
||||
#define ARM_GICR_SGI_RESERVED_FRAME_SIZE SIZE_64KB
|
||||
|
||||
// GIC Redistributor Control frame
|
||||
#define ARM_GICR_TYPER 0x0008 // Redistributor Type Register
|
||||
|
||||
// GIC Redistributor TYPER bit assignments
|
||||
#define ARM_GICR_TYPER_PLPIS (1 << 0) // Physical LPIs
|
||||
#define ARM_GICR_TYPER_VLPIS (1 << 1) // Virtual LPIs
|
||||
#define ARM_GICR_TYPER_DIRECTLPI (1 << 3) // Direct LPIs
|
||||
#define ARM_GICR_TYPER_LAST (1 << 4) // Last Redistributor in series
|
||||
#define ARM_GICR_TYPER_DPGS (1 << 5) // Disable Processor Group
|
||||
// Selection Support
|
||||
#define ARM_GICR_TYPER_PROCNO (0xFFFF << 8) // Processor Number
|
||||
#define ARM_GICR_TYPER_COMMONLPIAFF (0x3 << 24) // Common LPI Affinity
|
||||
#define ARM_GICR_TYPER_AFFINITY (0xFFFFFFFFULL << 32) // Redistributor Affinity
|
||||
|
||||
#define ARM_GICR_TYPER_GET_AFFINITY(TypeReg) (((TypeReg) & \
|
||||
ARM_GICR_TYPER_AFFINITY) >> 32)
|
||||
|
||||
// GIC SGI & PPI Redistributor frame
|
||||
#define ARM_GICR_ISENABLER 0x0100 // Interrupt Set-Enable Registers
|
||||
#define ARM_GICR_ICENABLER 0x0180 // Interrupt Clear-Enable Registers
|
||||
|
||||
// GIC Cpu interface
|
||||
#define ARM_GIC_ICCICR 0x00 // CPU Interface Control Register
|
||||
#define ARM_GIC_ICCPMR 0x04 // Interrupt Priority Mask Register
|
||||
#define ARM_GIC_ICCBPR 0x08 // Binary Point Register
|
||||
#define ARM_GIC_ICCIAR 0x0C // Interrupt Acknowledge Register
|
||||
#define ARM_GIC_ICCEIOR 0x10 // End Of Interrupt Register
|
||||
#define ARM_GIC_ICCRPR 0x14 // Running Priority Register
|
||||
#define ARM_GIC_ICCPIR 0x18 // Highest Pending Interrupt Register
|
||||
#define ARM_GIC_ICCABPR 0x1C // Aliased Binary Point Register
|
||||
#define ARM_GIC_ICCIIDR 0xFC // Identification Register
|
||||
|
||||
#define ARM_GIC_ICDSGIR_FILTER_TARGETLIST 0x0
|
||||
#define ARM_GIC_ICDSGIR_FILTER_EVERYONEELSE 0x1
|
||||
#define ARM_GIC_ICDSGIR_FILTER_ITSELF 0x2
|
||||
|
||||
// Bit-masks to configure the CPU Interface Control register
|
||||
#define ARM_GIC_ICCICR_ENABLE_SECURE 0x01
|
||||
#define ARM_GIC_ICCICR_ENABLE_NS 0x02
|
||||
#define ARM_GIC_ICCICR_ACK_CTL 0x04
|
||||
#define ARM_GIC_ICCICR_SIGNAL_SECURE_TO_FIQ 0x08
|
||||
#define ARM_GIC_ICCICR_USE_SBPR 0x10
|
||||
|
||||
// Bit Mask for GICC_IIDR
|
||||
#define ARM_GIC_ICCIIDR_GET_PRODUCT_ID(IccIidr) (((IccIidr) >> 20) & 0xFFF)
|
||||
#define ARM_GIC_ICCIIDR_GET_ARCH_VERSION(IccIidr) (((IccIidr) >> 16) & 0xF)
|
||||
#define ARM_GIC_ICCIIDR_GET_REVISION(IccIidr) (((IccIidr) >> 12) & 0xF)
|
||||
#define ARM_GIC_ICCIIDR_GET_IMPLEMENTER(IccIidr) ((IccIidr) & 0xFFF)
|
||||
|
||||
// Bit Mask for
|
||||
#define ARM_GIC_ICCIAR_ACKINTID 0x3FF
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmGicGetInterfaceIdentification (
|
||||
IN INTN GicInterruptInterfaceBase
|
||||
);
|
||||
|
||||
// GIC Secure interfaces
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicSetupNonSecure (
|
||||
IN UINTN MpId,
|
||||
IN INTN GicDistributorBase,
|
||||
IN INTN GicInterruptInterfaceBase
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicSetSecureInterrupts (
|
||||
IN UINTN GicDistributorBase,
|
||||
IN UINTN *GicSecureInterruptMask,
|
||||
IN UINTN GicSecureInterruptMaskSize
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicEnableInterruptInterface (
|
||||
IN INTN GicInterruptInterfaceBase
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicDisableInterruptInterface (
|
||||
IN INTN GicInterruptInterfaceBase
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicEnableDistributor (
|
||||
IN INTN GicDistributorBase
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicDisableDistributor (
|
||||
IN INTN GicDistributorBase
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmGicGetMaxNumInterrupts (
|
||||
IN INTN GicDistributorBase
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicSendSgiTo (
|
||||
IN INTN GicDistributorBase,
|
||||
IN INTN TargetListFilter,
|
||||
IN INTN CPUTargetList,
|
||||
IN INTN SgiId
|
||||
);
|
||||
|
||||
/*
|
||||
* Acknowledge and return the value of the Interrupt Acknowledge Register
|
||||
*
|
||||
* InterruptId is returned separately from the register value because in
|
||||
* the GICv2 the register value contains the CpuId and InterruptId while
|
||||
* in the GICv3 the register value is only the InterruptId.
|
||||
*
|
||||
* @param GicInterruptInterfaceBase Base Address of the GIC CPU Interface
|
||||
* @param InterruptId InterruptId read from the Interrupt
|
||||
* Acknowledge Register
|
||||
*
|
||||
* @retval value returned by the Interrupt Acknowledge Register
|
||||
*
|
||||
*/
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmGicAcknowledgeInterrupt (
|
||||
IN UINTN GicInterruptInterfaceBase,
|
||||
OUT UINTN *InterruptId
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicEndOfInterrupt (
|
||||
IN UINTN GicInterruptInterfaceBase,
|
||||
IN UINTN Source
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmGicSetPriorityMask (
|
||||
IN INTN GicInterruptInterfaceBase,
|
||||
IN INTN PriorityMask
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicSetInterruptPriority (
|
||||
IN UINTN GicDistributorBase,
|
||||
IN UINTN GicRedistributorBase,
|
||||
IN UINTN Source,
|
||||
IN UINTN Priority
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicEnableInterrupt (
|
||||
IN UINTN GicDistributorBase,
|
||||
IN UINTN GicRedistributorBase,
|
||||
IN UINTN Source
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicDisableInterrupt (
|
||||
IN UINTN GicDistributorBase,
|
||||
IN UINTN GicRedistributorBase,
|
||||
IN UINTN Source
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
ArmGicIsInterruptEnabled (
|
||||
IN UINTN GicDistributorBase,
|
||||
IN UINTN GicRedistributorBase,
|
||||
IN UINTN Source
|
||||
);
|
||||
|
||||
// GIC revision 2 specific declarations
|
||||
|
||||
// Interrupts from 1020 to 1023 are considered as special interrupts
|
||||
// (eg: spurious interrupts)
|
||||
#define ARM_GIC_IS_SPECIAL_INTERRUPTS(Interrupt) \
|
||||
(((Interrupt) >= 1020) && ((Interrupt) <= 1023))
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicV2SetupNonSecure (
|
||||
IN UINTN MpId,
|
||||
IN INTN GicDistributorBase,
|
||||
IN INTN GicInterruptInterfaceBase
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicV2EnableInterruptInterface (
|
||||
IN INTN GicInterruptInterfaceBase
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicV2DisableInterruptInterface (
|
||||
IN INTN GicInterruptInterfaceBase
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmGicV2AcknowledgeInterrupt (
|
||||
IN UINTN GicInterruptInterfaceBase
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicV2EndOfInterrupt (
|
||||
IN UINTN GicInterruptInterfaceBase,
|
||||
IN UINTN Source
|
||||
);
|
||||
|
||||
// GIC revision 3 specific declarations
|
||||
|
||||
#define ICC_SRE_EL2_SRE (1 << 0)
|
||||
|
||||
#define ARM_GICD_IROUTER_IRM BIT31
|
||||
|
||||
UINT32
|
||||
EFIAPI
|
||||
ArmGicV3GetControlSystemRegisterEnable (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicV3SetControlSystemRegisterEnable (
|
||||
IN UINT32 ControlSystemRegisterEnable
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicV3EnableInterruptInterface (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicV3DisableInterruptInterface (
|
||||
VOID
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmGicV3AcknowledgeInterrupt (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmGicV3EndOfInterrupt (
|
||||
IN UINTN Source
|
||||
);
|
||||
|
||||
VOID
|
||||
ArmGicV3SetBinaryPointer (
|
||||
IN UINTN BinaryPoint
|
||||
);
|
||||
|
||||
VOID
|
||||
ArmGicV3SetPriorityMask (
|
||||
IN UINTN Priority
|
||||
);
|
||||
|
||||
#endif // ARMGIC_H_
|
40
ArmPkg/Include/Library/ArmHvcLib.h
Normal file
40
ArmPkg/Include/Library/ArmHvcLib.h
Normal file
@ -0,0 +1,40 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2012-2014, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef ARM_HVC_LIB_H_
|
||||
#define ARM_HVC_LIB_H_
|
||||
|
||||
/**
|
||||
* The size of the HVC arguments are different between AArch64 and AArch32.
|
||||
* The native size is used for the arguments.
|
||||
*/
|
||||
typedef struct {
|
||||
UINTN Arg0;
|
||||
UINTN Arg1;
|
||||
UINTN Arg2;
|
||||
UINTN Arg3;
|
||||
UINTN Arg4;
|
||||
UINTN Arg5;
|
||||
UINTN Arg6;
|
||||
UINTN Arg7;
|
||||
} ARM_HVC_ARGS;
|
||||
|
||||
/**
|
||||
Trigger an HVC call
|
||||
|
||||
HVC calls can take up to 8 arguments and return up to 4 return values.
|
||||
Therefore, the 4 first fields in the ARM_HVC_ARGS structure are used
|
||||
for both input and output values.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ArmCallHvc (
|
||||
IN OUT ARM_HVC_ARGS *Args
|
||||
);
|
||||
|
||||
#endif // ARM_HVC_LIB_H_
|
791
ArmPkg/Include/Library/ArmLib.h
Normal file
791
ArmPkg/Include/Library/ArmLib.h
Normal file
@ -0,0 +1,791 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
|
||||
Copyright (c) 2011 - 2016, ARM Ltd. All rights reserved.<BR>
|
||||
Copyright (c) 2020 - 2021, NUVIA Inc. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef ARM_LIB_H_
|
||||
#define ARM_LIB_H_
|
||||
|
||||
#include <Uefi/UefiBaseType.h>
|
||||
|
||||
#ifdef MDE_CPU_ARM
|
||||
#include <Chipset/ArmV7.h>
|
||||
#elif defined (MDE_CPU_AARCH64)
|
||||
#include <Chipset/AArch64.h>
|
||||
#else
|
||||
#error "Unknown chipset."
|
||||
#endif
|
||||
|
||||
#define EFI_MEMORY_CACHETYPE_MASK (EFI_MEMORY_UC | EFI_MEMORY_WC | \
|
||||
EFI_MEMORY_WT | EFI_MEMORY_WB | \
|
||||
EFI_MEMORY_UCE)
|
||||
|
||||
/**
|
||||
* The UEFI firmware must not use the ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_* attributes.
|
||||
*
|
||||
* The Non Secure memory attribute (ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_*) should only
|
||||
* be used in Secure World to distinguished Secure to Non-Secure memory.
|
||||
*/
|
||||
typedef enum {
|
||||
ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED = 0,
|
||||
ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_UNCACHED_UNBUFFERED,
|
||||
ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK,
|
||||
ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_WRITE_BACK,
|
||||
|
||||
// On some platforms, memory mapped flash region is designed as not supporting
|
||||
// shareable attribute, so WRITE_BACK_NONSHAREABLE is added for such special
|
||||
// need.
|
||||
// Do NOT use below two attributes if you are not sure.
|
||||
ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK_NONSHAREABLE,
|
||||
ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_WRITE_BACK_NONSHAREABLE,
|
||||
|
||||
ARM_MEMORY_REGION_ATTRIBUTE_WRITE_THROUGH,
|
||||
ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_WRITE_THROUGH,
|
||||
ARM_MEMORY_REGION_ATTRIBUTE_DEVICE,
|
||||
ARM_MEMORY_REGION_ATTRIBUTE_NONSECURE_DEVICE
|
||||
} ARM_MEMORY_REGION_ATTRIBUTES;
|
||||
|
||||
#define IS_ARM_MEMORY_REGION_ATTRIBUTES_SECURE(attr) ((UINT32)(attr) & 1)
|
||||
|
||||
typedef struct {
|
||||
EFI_PHYSICAL_ADDRESS PhysicalBase;
|
||||
EFI_VIRTUAL_ADDRESS VirtualBase;
|
||||
UINT64 Length;
|
||||
ARM_MEMORY_REGION_ATTRIBUTES Attributes;
|
||||
} ARM_MEMORY_REGION_DESCRIPTOR;
|
||||
|
||||
typedef VOID (*CACHE_OPERATION)(
|
||||
VOID
|
||||
);
|
||||
typedef VOID (*LINE_OPERATION)(
|
||||
UINTN
|
||||
);
|
||||
|
||||
//
|
||||
// ARM Processor Mode
|
||||
//
|
||||
typedef enum {
|
||||
ARM_PROCESSOR_MODE_USER = 0x10,
|
||||
ARM_PROCESSOR_MODE_FIQ = 0x11,
|
||||
ARM_PROCESSOR_MODE_IRQ = 0x12,
|
||||
ARM_PROCESSOR_MODE_SUPERVISOR = 0x13,
|
||||
ARM_PROCESSOR_MODE_ABORT = 0x17,
|
||||
ARM_PROCESSOR_MODE_HYP = 0x1A,
|
||||
ARM_PROCESSOR_MODE_UNDEFINED = 0x1B,
|
||||
ARM_PROCESSOR_MODE_SYSTEM = 0x1F,
|
||||
ARM_PROCESSOR_MODE_MASK = 0x1F
|
||||
} ARM_PROCESSOR_MODE;
|
||||
|
||||
//
|
||||
// ARM Cpu IDs
|
||||
//
|
||||
#define ARM_CPU_IMPLEMENTER_MASK (0xFFU << 24)
|
||||
#define ARM_CPU_IMPLEMENTER_ARMLTD (0x41U << 24)
|
||||
#define ARM_CPU_IMPLEMENTER_DEC (0x44U << 24)
|
||||
#define ARM_CPU_IMPLEMENTER_MOT (0x4DU << 24)
|
||||
#define ARM_CPU_IMPLEMENTER_QUALCOMM (0x51U << 24)
|
||||
#define ARM_CPU_IMPLEMENTER_MARVELL (0x56U << 24)
|
||||
|
||||
#define ARM_CPU_PRIMARY_PART_MASK (0xFFF << 4)
|
||||
#define ARM_CPU_PRIMARY_PART_CORTEXA5 (0xC05 << 4)
|
||||
#define ARM_CPU_PRIMARY_PART_CORTEXA7 (0xC07 << 4)
|
||||
#define ARM_CPU_PRIMARY_PART_CORTEXA8 (0xC08 << 4)
|
||||
#define ARM_CPU_PRIMARY_PART_CORTEXA9 (0xC09 << 4)
|
||||
#define ARM_CPU_PRIMARY_PART_CORTEXA15 (0xC0F << 4)
|
||||
|
||||
//
|
||||
// ARM MP Core IDs
|
||||
//
|
||||
#define ARM_CORE_AFF0 0xFF
|
||||
#define ARM_CORE_AFF1 (0xFF << 8)
|
||||
#define ARM_CORE_AFF2 (0xFF << 16)
|
||||
#define ARM_CORE_AFF3 (0xFFULL << 32)
|
||||
|
||||
#define ARM_CORE_MASK ARM_CORE_AFF0
|
||||
#define ARM_CLUSTER_MASK ARM_CORE_AFF1
|
||||
#define GET_CORE_ID(MpId) ((MpId) & ARM_CORE_MASK)
|
||||
#define GET_CLUSTER_ID(MpId) (((MpId) & ARM_CLUSTER_MASK) >> 8)
|
||||
#define GET_MPID(ClusterId, CoreId) (((ClusterId) << 8) | (CoreId))
|
||||
#define GET_MPIDR_AFF0(MpId) ((MpId) & ARM_CORE_AFF0)
|
||||
#define GET_MPIDR_AFF1(MpId) (((MpId) & ARM_CORE_AFF1) >> 8)
|
||||
#define GET_MPIDR_AFF2(MpId) (((MpId) & ARM_CORE_AFF2) >> 16)
|
||||
#define GET_MPIDR_AFF3(MpId) (((MpId) & ARM_CORE_AFF3) >> 32)
|
||||
#define PRIMARY_CORE_ID (PcdGet32(PcdArmPrimaryCore) & ARM_CORE_MASK)
|
||||
|
||||
/** Reads the CCSIDR register for the specified cache.
|
||||
|
||||
@param CSSELR The CSSELR cache selection register value.
|
||||
|
||||
@return The contents of the CCSIDR_EL1 register for the specified cache, when in AARCH64 mode.
|
||||
Returns the contents of the CCSIDR register in AARCH32 mode.
|
||||
**/
|
||||
UINTN
|
||||
ReadCCSIDR (
|
||||
IN UINT32 CSSELR
|
||||
);
|
||||
|
||||
/** Reads the CCSIDR2 for the specified cache.
|
||||
|
||||
@param CSSELR The CSSELR cache selection register value
|
||||
|
||||
@return The contents of the CCSIDR2 register for the specified cache.
|
||||
**/
|
||||
UINT32
|
||||
ReadCCSIDR2 (
|
||||
IN UINT32 CSSELR
|
||||
);
|
||||
|
||||
/** Reads the Cache Level ID (CLIDR) register.
|
||||
|
||||
@return The contents of the CLIDR_EL1 register.
|
||||
**/
|
||||
UINT32
|
||||
ReadCLIDR (
|
||||
VOID
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmDataCacheLineLength (
|
||||
VOID
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmInstructionCacheLineLength (
|
||||
VOID
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmCacheWritebackGranule (
|
||||
VOID
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmIsArchTimerImplemented (
|
||||
VOID
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmCacheInfo (
|
||||
VOID
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
ArmIsMpCore (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmInvalidateDataCache (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmCleanInvalidateDataCache (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmCleanDataCache (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmInvalidateInstructionCache (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmInvalidateDataCacheEntryByMVA (
|
||||
IN UINTN Address
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmCleanDataCacheEntryToPoUByMVA (
|
||||
IN UINTN Address
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmInvalidateInstructionCacheEntryToPoUByMVA (
|
||||
IN UINTN Address
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmCleanDataCacheEntryByMVA (
|
||||
IN UINTN Address
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmCleanInvalidateDataCacheEntryByMVA (
|
||||
IN UINTN Address
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmEnableDataCache (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmDisableDataCache (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmEnableInstructionCache (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmDisableInstructionCache (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmEnableMmu (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmDisableMmu (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmEnableCachesAndMmu (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmDisableCachesAndMmu (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmEnableInterrupts (
|
||||
VOID
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmDisableInterrupts (
|
||||
VOID
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
ArmGetInterruptState (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmEnableAsynchronousAbort (
|
||||
VOID
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmDisableAsynchronousAbort (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmEnableIrq (
|
||||
VOID
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmDisableIrq (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmEnableFiq (
|
||||
VOID
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmDisableFiq (
|
||||
VOID
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
ArmGetFiqState (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
* Invalidate Data and Instruction TLBs
|
||||
*/
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmInvalidateTlb (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmUpdateTranslationTableEntry (
|
||||
IN VOID *TranslationTableEntry,
|
||||
IN VOID *Mva
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmSetDomainAccessControl (
|
||||
IN UINT32 Domain
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmSetTTBR0 (
|
||||
IN VOID *TranslationTableBase
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmSetTTBCR (
|
||||
IN UINT32 Bits
|
||||
);
|
||||
|
||||
VOID *
|
||||
EFIAPI
|
||||
ArmGetTTBR0BaseAddress (
|
||||
VOID
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
ArmMmuEnabled (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmEnableBranchPrediction (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmDisableBranchPrediction (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmSetLowVectors (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmSetHighVectors (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmDataMemoryBarrier (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmDataSynchronizationBarrier (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmInstructionSynchronizationBarrier (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmWriteVBar (
|
||||
IN UINTN VectorBase
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmReadVBar (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmWriteAuxCr (
|
||||
IN UINT32 Bit
|
||||
);
|
||||
|
||||
UINT32
|
||||
EFIAPI
|
||||
ArmReadAuxCr (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmSetAuxCrBit (
|
||||
IN UINT32 Bits
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmUnsetAuxCrBit (
|
||||
IN UINT32 Bits
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmCallSEV (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmCallWFE (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmCallWFI (
|
||||
|
||||
VOID
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmReadMpidr (
|
||||
VOID
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmReadMidr (
|
||||
VOID
|
||||
);
|
||||
|
||||
UINT32
|
||||
EFIAPI
|
||||
ArmReadCpacr (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmWriteCpacr (
|
||||
IN UINT32 Access
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmEnableVFP (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Get the Secure Configuration Register value
|
||||
|
||||
@return Value read from the Secure Configuration Register
|
||||
|
||||
**/
|
||||
UINT32
|
||||
EFIAPI
|
||||
ArmReadScr (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Set the Secure Configuration Register
|
||||
|
||||
@param Value Value to write to the Secure Configuration Register
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmWriteScr (
|
||||
IN UINT32 Value
|
||||
);
|
||||
|
||||
UINT32
|
||||
EFIAPI
|
||||
ArmReadMVBar (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmWriteMVBar (
|
||||
IN UINT32 VectorMonitorBase
|
||||
);
|
||||
|
||||
UINT32
|
||||
EFIAPI
|
||||
ArmReadSctlr (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmWriteSctlr (
|
||||
IN UINT32 Value
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmReadHVBar (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmWriteHVBar (
|
||||
IN UINTN HypModeVectorBase
|
||||
);
|
||||
|
||||
//
|
||||
// Helper functions for accessing CPU ACTLR
|
||||
//
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmReadCpuActlr (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmWriteCpuActlr (
|
||||
IN UINTN Val
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmSetCpuActlrBit (
|
||||
IN UINTN Bits
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmUnsetCpuActlrBit (
|
||||
IN UINTN Bits
|
||||
);
|
||||
|
||||
//
|
||||
// Accessors for the architected generic timer registers
|
||||
//
|
||||
|
||||
#define ARM_ARCH_TIMER_ENABLE (1 << 0)
|
||||
#define ARM_ARCH_TIMER_IMASK (1 << 1)
|
||||
#define ARM_ARCH_TIMER_ISTATUS (1 << 2)
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmReadCntFrq (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmWriteCntFrq (
|
||||
UINTN FreqInHz
|
||||
);
|
||||
|
||||
UINT64
|
||||
EFIAPI
|
||||
ArmReadCntPct (
|
||||
VOID
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmReadCntkCtl (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmWriteCntkCtl (
|
||||
UINTN Val
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmReadCntpTval (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmWriteCntpTval (
|
||||
UINTN Val
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmReadCntpCtl (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmWriteCntpCtl (
|
||||
UINTN Val
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmReadCntvTval (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmWriteCntvTval (
|
||||
UINTN Val
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmReadCntvCtl (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmWriteCntvCtl (
|
||||
UINTN Val
|
||||
);
|
||||
|
||||
UINT64
|
||||
EFIAPI
|
||||
ArmReadCntvCt (
|
||||
VOID
|
||||
);
|
||||
|
||||
UINT64
|
||||
EFIAPI
|
||||
ArmReadCntpCval (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmWriteCntpCval (
|
||||
UINT64 Val
|
||||
);
|
||||
|
||||
UINT64
|
||||
EFIAPI
|
||||
ArmReadCntvCval (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmWriteCntvCval (
|
||||
UINT64 Val
|
||||
);
|
||||
|
||||
UINT64
|
||||
EFIAPI
|
||||
ArmReadCntvOff (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmWriteCntvOff (
|
||||
UINT64 Val
|
||||
);
|
||||
|
||||
UINTN
|
||||
EFIAPI
|
||||
ArmGetPhysicalAddressBits (
|
||||
VOID
|
||||
);
|
||||
|
||||
///
|
||||
/// ID Register Helper functions
|
||||
///
|
||||
|
||||
/**
|
||||
Check whether the CPU supports the GIC system register interface (any version)
|
||||
|
||||
@return Whether GIC System Register Interface is supported
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
ArmHasGicSystemRegisters (
|
||||
VOID
|
||||
);
|
||||
|
||||
/** Checks if CCIDX is implemented.
|
||||
|
||||
@retval TRUE CCIDX is implemented.
|
||||
@retval FALSE CCIDX is not implemented.
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
ArmHasCcidx (
|
||||
VOID
|
||||
);
|
||||
|
||||
#ifdef MDE_CPU_ARM
|
||||
///
|
||||
/// AArch32-only ID Register Helper functions
|
||||
///
|
||||
|
||||
/**
|
||||
Check whether the CPU supports the Security extensions
|
||||
|
||||
@return Whether the Security extensions are implemented
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
ArmHasSecurityExtensions (
|
||||
VOID
|
||||
);
|
||||
|
||||
#endif // MDE_CPU_ARM
|
||||
|
||||
#endif // ARM_LIB_H_
|
68
ArmPkg/Include/Library/ArmMmuLib.h
Normal file
68
ArmPkg/Include/Library/ArmMmuLib.h
Normal file
@ -0,0 +1,68 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2015 - 2016, Linaro Ltd. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef ARM_MMU_LIB_H_
|
||||
#define ARM_MMU_LIB_H_
|
||||
|
||||
#include <Uefi/UefiBaseType.h>
|
||||
|
||||
#include <Library/ArmLib.h>
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArmConfigureMmu (
|
||||
IN ARM_MEMORY_REGION_DESCRIPTOR *MemoryTable,
|
||||
OUT VOID **TranslationTableBase OPTIONAL,
|
||||
OUT UINTN *TranslationTableSize OPTIONAL
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArmSetMemoryRegionNoExec (
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArmClearMemoryRegionNoExec (
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArmSetMemoryRegionReadOnly (
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
ArmClearMemoryRegionReadOnly (
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length
|
||||
);
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmReplaceLiveTranslationEntry (
|
||||
IN UINT64 *Entry,
|
||||
IN UINT64 Value,
|
||||
IN UINT64 RegionStart,
|
||||
IN BOOLEAN DisableMmu
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
ArmSetMemoryAttributes (
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length,
|
||||
IN UINT64 Attributes
|
||||
);
|
||||
|
||||
#endif // ARM_MMU_LIB_H_
|
42
ArmPkg/Include/Library/ArmMonitorLib.h
Normal file
42
ArmPkg/Include/Library/ArmMonitorLib.h
Normal file
@ -0,0 +1,42 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2022, Arm Limited. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef ARM_MONITOR_LIB_H_
|
||||
#define ARM_MONITOR_LIB_H_
|
||||
|
||||
/** The size of the SMC arguments is different between AArch64 and AArch32.
|
||||
|
||||
The native size is used for the arguments.
|
||||
It will be casted to either HVC or SMC args.
|
||||
*/
|
||||
typedef struct {
|
||||
UINTN Arg0;
|
||||
UINTN Arg1;
|
||||
UINTN Arg2;
|
||||
UINTN Arg3;
|
||||
UINTN Arg4;
|
||||
UINTN Arg5;
|
||||
UINTN Arg6;
|
||||
UINTN Arg7;
|
||||
} ARM_MONITOR_ARGS;
|
||||
|
||||
/** Monitor call.
|
||||
|
||||
An HyperVisor Call (HVC) or System Monitor Call (SMC) will be issued
|
||||
depending on the default conduit. PcdMonitorConduitHvc determines the type
|
||||
of the call: if true, do an HVC.
|
||||
|
||||
@param [in,out] Args Arguments for the HVC/SMC.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ArmMonitorCall (
|
||||
IN OUT ARM_MONITOR_ARGS *Args
|
||||
);
|
||||
|
||||
#endif // ARM_MONITOR_LIB_H_
|
130
ArmPkg/Include/Library/ArmMtlLib.h
Normal file
130
ArmPkg/Include/Library/ArmMtlLib.h
Normal file
@ -0,0 +1,130 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2017-2018, Arm Limited. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
System Control and Management Interface V1.0
|
||||
http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/
|
||||
DEN0056A_System_Control_and_Management_Interface.pdf
|
||||
**/
|
||||
|
||||
#ifndef ARM_MTL_LIB_H_
|
||||
#define ARM_MTL_LIB_H_
|
||||
|
||||
#include <Uefi/UefiBaseType.h>
|
||||
|
||||
// Ideally we don't need packed struct. However we can't rely on compilers.
|
||||
#pragma pack(1)
|
||||
|
||||
typedef struct {
|
||||
UINT32 Reserved1;
|
||||
UINT32 ChannelStatus;
|
||||
UINT64 Reserved2;
|
||||
UINT32 Flags;
|
||||
UINT32 Length;
|
||||
UINT32 MessageHeader;
|
||||
|
||||
// NOTE: Since EDK2 does not allow flexible array member [] we declare
|
||||
// here array of 1 element length. However below is used as a variable
|
||||
// length array.
|
||||
UINT32 Payload[1]; // size less object gives offset to payload.
|
||||
} MTL_MAILBOX;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
// Channel Type, Low-priority, and High-priority
|
||||
typedef enum {
|
||||
MTL_CHANNEL_TYPE_LOW = 0,
|
||||
MTL_CHANNEL_TYPE_HIGH = 1
|
||||
} MTL_CHANNEL_TYPE;
|
||||
|
||||
typedef struct {
|
||||
UINT64 PhysicalAddress;
|
||||
UINT32 ModifyMask;
|
||||
UINT32 PreserveMask;
|
||||
} MTL_DOORBELL;
|
||||
|
||||
typedef struct {
|
||||
MTL_CHANNEL_TYPE ChannelType;
|
||||
MTL_MAILBOX *CONST MailBox;
|
||||
MTL_DOORBELL DoorBell;
|
||||
} MTL_CHANNEL;
|
||||
|
||||
/** Wait until channel is free.
|
||||
|
||||
@param[in] Channel Pointer to a channel.
|
||||
@param[in] TimeOutInMicroSeconds Time out in micro seconds.
|
||||
|
||||
@retval EFI_SUCCESS Channel is free.
|
||||
@retval EFI_TIMEOUT Time out error.
|
||||
**/
|
||||
EFI_STATUS
|
||||
MtlWaitUntilChannelFree (
|
||||
IN MTL_CHANNEL *Channel,
|
||||
IN UINTN TimeOutInMicroSeconds
|
||||
);
|
||||
|
||||
/** Return the address of the message payload.
|
||||
|
||||
@param[in] Channel Pointer to a channel.
|
||||
|
||||
@retval UINT32* Pointer to the payload.
|
||||
**/
|
||||
UINT32 *
|
||||
MtlGetChannelPayload (
|
||||
IN MTL_CHANNEL *Channel
|
||||
);
|
||||
|
||||
/** Return pointer to a channel for the requested channel type.
|
||||
|
||||
@param[in] ChannelType ChannelType, Low or High priority channel.
|
||||
MTL_CHANNEL_TYPE_LOW or
|
||||
MTL_CHANNEL_TYPE_HIGH
|
||||
|
||||
@param[out] Channel Holds pointer to the channel.
|
||||
|
||||
@retval EFI_SUCCESS Pointer to channel is returned.
|
||||
@retval EFI_UNSUPPORTED Requested channel type not supported.
|
||||
**/
|
||||
EFI_STATUS
|
||||
MtlGetChannel (
|
||||
IN MTL_CHANNEL_TYPE ChannelType,
|
||||
OUT MTL_CHANNEL **Channel
|
||||
);
|
||||
|
||||
/** Mark the channel busy and ring the doorbell.
|
||||
|
||||
@param[in] Channel Pointer to a channel.
|
||||
@param[in] MessageHeader Message header.
|
||||
|
||||
@param[out] PayloadLength Message length.
|
||||
|
||||
@retval EFI_SUCCESS Message sent successfully.
|
||||
@retval EFI_DEVICE_ERROR Channel is busy.
|
||||
**/
|
||||
EFI_STATUS
|
||||
MtlSendMessage (
|
||||
IN MTL_CHANNEL *Channel,
|
||||
IN UINT32 MessageHeader,
|
||||
OUT UINT32 PayloadLength
|
||||
);
|
||||
|
||||
/** Wait for a response on a channel.
|
||||
|
||||
If channel is free after sending message, it implies SCP responded
|
||||
with a response on the channel.
|
||||
|
||||
@param[in] Channel Pointer to a channel.
|
||||
|
||||
@retval EFI_SUCCESS Message received successfully.
|
||||
@retval EFI_TIMEOUT Time out error.
|
||||
**/
|
||||
EFI_STATUS
|
||||
MtlReceiveMessage (
|
||||
IN MTL_CHANNEL *Channel,
|
||||
OUT UINT32 *MessageHeader,
|
||||
OUT UINT32 *PayloadLength
|
||||
);
|
||||
|
||||
#endif /* ARM_MTL_LIB_H_ */
|
113
ArmPkg/Include/Library/ArmSmcLib.h
Normal file
113
ArmPkg/Include/Library/ArmSmcLib.h
Normal file
@ -0,0 +1,113 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
|
||||
* Copyright (c) 2012-2014, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef ARM_SMC_LIB_H_
|
||||
#define ARM_SMC_LIB_H_
|
||||
|
||||
/**
|
||||
* The size of the SMC arguments are different between AArch64 and AArch32.
|
||||
* The native size is used for the arguments.
|
||||
*/
|
||||
typedef struct {
|
||||
UINTN Arg0;
|
||||
UINTN Arg1;
|
||||
UINTN Arg2;
|
||||
UINTN Arg3;
|
||||
UINTN Arg4;
|
||||
UINTN Arg5;
|
||||
UINTN Arg6;
|
||||
UINTN Arg7;
|
||||
} ARM_SMC_ARGS;
|
||||
|
||||
/**
|
||||
Trigger an SMC call
|
||||
|
||||
SMC calls can take up to 7 arguments and return up to 4 return values.
|
||||
Therefore, the 4 first fields in the ARM_SMC_ARGS structure are used
|
||||
for both input and output values.
|
||||
|
||||
**/
|
||||
VOID
|
||||
ArmCallSmc (
|
||||
IN OUT ARM_SMC_ARGS *Args
|
||||
);
|
||||
|
||||
/** Trigger an SMC call with 3 arguments.
|
||||
|
||||
@param Function The SMC function.
|
||||
@param Arg1 Argument/result.
|
||||
@param Arg2 Argument/result.
|
||||
@param Arg3 Argument/result.
|
||||
|
||||
@return The SMC error code.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
ArmCallSmc3 (
|
||||
IN UINTN Function,
|
||||
IN OUT UINTN *Arg1 OPTIONAL,
|
||||
IN OUT UINTN *Arg2 OPTIONAL,
|
||||
IN OUT UINTN *Arg3 OPTIONAL
|
||||
);
|
||||
|
||||
/** Trigger an SMC call with 2 arguments.
|
||||
|
||||
@param Function The SMC function.
|
||||
@param Arg1 Argument/result.
|
||||
@param Arg2 Argument/result.
|
||||
@param Arg3 Result.
|
||||
|
||||
@return The SMC error code.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
ArmCallSmc2 (
|
||||
IN UINTN Function,
|
||||
IN OUT UINTN *Arg1 OPTIONAL,
|
||||
IN OUT UINTN *Arg2 OPTIONAL,
|
||||
OUT UINTN *Arg3 OPTIONAL
|
||||
);
|
||||
|
||||
/** Trigger an SMC call with 1 argument.
|
||||
|
||||
@param Function The SMC function.
|
||||
@param Arg1 Argument/result.
|
||||
@param Arg2 Result.
|
||||
@param Arg3 Result.
|
||||
|
||||
@return The SMC error code.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
ArmCallSmc1 (
|
||||
IN UINTN Function,
|
||||
IN OUT UINTN *Arg1 OPTIONAL,
|
||||
OUT UINTN *Arg2 OPTIONAL,
|
||||
OUT UINTN *Arg3 OPTIONAL
|
||||
);
|
||||
|
||||
/** Trigger an SMC call with 0 arguments.
|
||||
|
||||
@param Function The SMC function.
|
||||
@param Arg1 Result.
|
||||
@param Arg2 Result.
|
||||
@param Arg3 Result.
|
||||
|
||||
@return The SMC error code.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
ArmCallSmc0 (
|
||||
IN UINTN Function,
|
||||
OUT UINTN *Arg1 OPTIONAL,
|
||||
OUT UINTN *Arg2 OPTIONAL,
|
||||
OUT UINTN *Arg3 OPTIONAL
|
||||
);
|
||||
|
||||
#endif // ARM_SMC_LIB_H_
|
46
ArmPkg/Include/Library/ArmSvcLib.h
Normal file
46
ArmPkg/Include/Library/ArmSvcLib.h
Normal file
@ -0,0 +1,46 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2016 - 2017, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef ARM_SVC_LIB_H_
|
||||
#define ARM_SVC_LIB_H_
|
||||
|
||||
/**
|
||||
* The size of the SVC arguments are different between AArch64 and AArch32.
|
||||
* The native size is used for the arguments.
|
||||
*/
|
||||
typedef struct {
|
||||
UINTN Arg0;
|
||||
UINTN Arg1;
|
||||
UINTN Arg2;
|
||||
UINTN Arg3;
|
||||
UINTN Arg4;
|
||||
UINTN Arg5;
|
||||
UINTN Arg6;
|
||||
UINTN Arg7;
|
||||
} ARM_SVC_ARGS;
|
||||
|
||||
/**
|
||||
Trigger an SVC call
|
||||
|
||||
SVC calls can take up to 8 arguments and return up to 8 return values.
|
||||
Therefore, the 8 first fields in the ARM_SVC_ARGS structure are used
|
||||
for both input and output values.
|
||||
|
||||
@param[in, out] Args Arguments to be passed as part of the SVC call
|
||||
The return values of the SVC call are also placed
|
||||
in the same structure
|
||||
|
||||
@retval None
|
||||
|
||||
**/
|
||||
VOID
|
||||
ArmCallSvc (
|
||||
IN OUT ARM_SVC_ARGS *Args
|
||||
);
|
||||
|
||||
#endif // ARM_SVC_LIB_H_
|
25
ArmPkg/Include/Library/DefaultExceptionHandlerLib.h
Normal file
25
ArmPkg/Include/Library/DefaultExceptionHandlerLib.h
Normal file
@ -0,0 +1,25 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef DEFAULT_EXCEPTION_HANDLER_LIB_H_
|
||||
#define DEFAULT_EXCEPTION_HANDLER_LIB_H_
|
||||
|
||||
/**
|
||||
This is the default action to take on an unexpected exception
|
||||
|
||||
@param ExceptionType Type of the exception
|
||||
@param SystemContext Register state at the time of the Exception
|
||||
|
||||
**/
|
||||
VOID
|
||||
DefaultExceptionHandler (
|
||||
IN EFI_EXCEPTION_TYPE ExceptionType,
|
||||
IN OUT EFI_SYSTEM_CONTEXT SystemContext
|
||||
);
|
||||
|
||||
#endif // DEFAULT_EXCEPTION_HANDLER_LIB_H_
|
271
ArmPkg/Include/Library/OemMiscLib.h
Normal file
271
ArmPkg/Include/Library/OemMiscLib.h
Normal file
@ -0,0 +1,271 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2022, Ampere Computing LLC. All rights reserved.
|
||||
* Copyright (c) 2021, NUVIA Inc. All rights reserved.
|
||||
* Copyright (c) 2015, Hisilicon Limited. All rights reserved.
|
||||
* Copyright (c) 2015, Linaro Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef OEM_MISC_LIB_H_
|
||||
#define OEM_MISC_LIB_H_
|
||||
|
||||
#include <Uefi.h>
|
||||
#include <IndustryStandard/SmBios.h>
|
||||
|
||||
typedef enum {
|
||||
CpuCacheL1 = 1,
|
||||
CpuCacheL2,
|
||||
CpuCacheL3,
|
||||
CpuCacheL4,
|
||||
CpuCacheL5,
|
||||
CpuCacheL6,
|
||||
CpuCacheL7,
|
||||
CpuCacheLevelMax
|
||||
} OEM_MISC_CPU_CACHE_LEVEL;
|
||||
|
||||
typedef struct {
|
||||
UINT8 Voltage; ///< Processor voltage
|
||||
UINT16 CurrentSpeed; ///< Current clock speed in MHz
|
||||
UINT16 MaxSpeed; ///< Maximum clock speed in MHz
|
||||
UINT16 ExternalClock; ///< External clock speed in MHz
|
||||
UINT16 CoreCount; ///< Number of cores available
|
||||
UINT16 CoresEnabled; ///< Number of cores enabled
|
||||
UINT16 ThreadCount; ///< Number of threads per processor
|
||||
} OEM_MISC_PROCESSOR_DATA;
|
||||
|
||||
typedef enum {
|
||||
BiosVersionType00,
|
||||
ProductNameType01,
|
||||
SerialNumType01,
|
||||
UuidType01,
|
||||
SystemManufacturerType01,
|
||||
VersionType01,
|
||||
SkuNumberType01,
|
||||
FamilyType01,
|
||||
AssetTagType02,
|
||||
SerialNumberType02,
|
||||
BoardManufacturerType02,
|
||||
ProductNameType02,
|
||||
VersionType02,
|
||||
SkuNumberType02,
|
||||
ChassisLocationType02,
|
||||
AssetTagType03,
|
||||
SerialNumberType03,
|
||||
VersionType03,
|
||||
ChassisTypeType03,
|
||||
ManufacturerType03,
|
||||
SkuNumberType03,
|
||||
ProcessorPartNumType04,
|
||||
ProcessorSerialNumType04,
|
||||
ProcessorVersionType04,
|
||||
SmbiosHiiStringFieldMax
|
||||
} OEM_MISC_SMBIOS_HII_STRING_FIELD;
|
||||
|
||||
/*
|
||||
* The following are functions that the each platform needs to
|
||||
* implement in its OemMiscLib library.
|
||||
*/
|
||||
|
||||
/** Gets the CPU frequency of the specified processor.
|
||||
|
||||
@param ProcessorIndex Index of the processor to get the frequency for.
|
||||
|
||||
@return CPU frequency in Hz
|
||||
**/
|
||||
UINTN
|
||||
EFIAPI
|
||||
OemGetCpuFreq (
|
||||
IN UINT8 ProcessorIndex
|
||||
);
|
||||
|
||||
/** Gets information about the specified processor and stores it in
|
||||
the structures provided.
|
||||
|
||||
@param ProcessorIndex Index of the processor to get the information for.
|
||||
@param ProcessorStatus Processor status.
|
||||
@param ProcessorCharacteristics Processor characteritics.
|
||||
@param MiscProcessorData Miscellaneous processor information.
|
||||
|
||||
@return TRUE on success, FALSE on failure.
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
OemGetProcessorInformation (
|
||||
IN UINTN ProcessorIndex,
|
||||
IN OUT PROCESSOR_STATUS_DATA *ProcessorStatus,
|
||||
IN OUT PROCESSOR_CHARACTERISTIC_FLAGS *ProcessorCharacteristics,
|
||||
IN OUT OEM_MISC_PROCESSOR_DATA *MiscProcessorData
|
||||
);
|
||||
|
||||
/** Gets information about the cache at the specified cache level.
|
||||
|
||||
@param ProcessorIndex The processor to get information for.
|
||||
@param CacheLevel The cache level to get information for.
|
||||
@param DataCache Whether the cache is a data cache.
|
||||
@param UnifiedCache Whether the cache is a unified cache.
|
||||
@param SmbiosCacheTable The SMBIOS Type7 cache information structure.
|
||||
|
||||
@return TRUE on success, FALSE on failure.
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
OemGetCacheInformation (
|
||||
IN UINT8 ProcessorIndex,
|
||||
IN UINT8 CacheLevel,
|
||||
IN BOOLEAN DataCache,
|
||||
IN BOOLEAN UnifiedCache,
|
||||
IN OUT SMBIOS_TABLE_TYPE7 *SmbiosCacheTable
|
||||
);
|
||||
|
||||
/** Gets the maximum number of processors supported by the platform.
|
||||
|
||||
@return The maximum number of processors.
|
||||
**/
|
||||
UINT8
|
||||
EFIAPI
|
||||
OemGetMaxProcessors (
|
||||
VOID
|
||||
);
|
||||
|
||||
/** Gets the type of chassis for the system.
|
||||
|
||||
@retval The type of the chassis.
|
||||
**/
|
||||
MISC_CHASSIS_TYPE
|
||||
EFIAPI
|
||||
OemGetChassisType (
|
||||
VOID
|
||||
);
|
||||
|
||||
/** Returns whether the specified processor is present or not.
|
||||
|
||||
@param ProcessIndex The processor index to check.
|
||||
|
||||
@return TRUE is the processor is present, FALSE otherwise.
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
OemIsProcessorPresent (
|
||||
IN UINTN ProcessorIndex
|
||||
);
|
||||
|
||||
/** Updates the HII string for the specified field.
|
||||
|
||||
@param HiiHandle The HII handle.
|
||||
@param TokenToUpdate The string to update.
|
||||
@param Field The field to get information about.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
OemUpdateSmbiosInfo (
|
||||
IN EFI_HII_HANDLE HiiHandle,
|
||||
IN EFI_STRING_ID TokenToUpdate,
|
||||
IN OEM_MISC_SMBIOS_HII_STRING_FIELD Field
|
||||
);
|
||||
|
||||
/** Fetches the Type 32 boot information status.
|
||||
|
||||
@return Boot status.
|
||||
**/
|
||||
MISC_BOOT_INFORMATION_STATUS_DATA_TYPE
|
||||
EFIAPI
|
||||
OemGetBootStatus (
|
||||
VOID
|
||||
);
|
||||
|
||||
/** Fetches the chassis status when it was last booted.
|
||||
|
||||
@return Chassis status.
|
||||
**/
|
||||
MISC_CHASSIS_STATE
|
||||
EFIAPI
|
||||
OemGetChassisBootupState (
|
||||
VOID
|
||||
);
|
||||
|
||||
/** Fetches the chassis power supply/supplies status when last booted.
|
||||
|
||||
@return Chassis power supply/supplies status.
|
||||
**/
|
||||
MISC_CHASSIS_STATE
|
||||
EFIAPI
|
||||
OemGetChassisPowerSupplyState (
|
||||
VOID
|
||||
);
|
||||
|
||||
/** Fetches the chassis thermal status when last booted.
|
||||
|
||||
@return Chassis thermal status.
|
||||
**/
|
||||
MISC_CHASSIS_STATE
|
||||
EFIAPI
|
||||
OemGetChassisThermalState (
|
||||
VOID
|
||||
);
|
||||
|
||||
/** Fetches the chassis security status when last booted.
|
||||
|
||||
@return Chassis security status.
|
||||
**/
|
||||
MISC_CHASSIS_SECURITY_STATE
|
||||
EFIAPI
|
||||
OemGetChassisSecurityStatus (
|
||||
VOID
|
||||
);
|
||||
|
||||
/** Fetches the chassis height in RMUs (Rack Mount Units).
|
||||
|
||||
@return The height of the chassis.
|
||||
**/
|
||||
UINT8
|
||||
EFIAPI
|
||||
OemGetChassisHeight (
|
||||
VOID
|
||||
);
|
||||
|
||||
/** Fetches the number of power cords.
|
||||
|
||||
@return The number of power cords.
|
||||
**/
|
||||
UINT8
|
||||
EFIAPI
|
||||
OemGetChassisNumPowerCords (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Fetches the system UUID.
|
||||
|
||||
@param[out] SystemUuid The pointer to the buffer to store the System UUID.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
OemGetSystemUuid (
|
||||
OUT GUID *SystemUuid
|
||||
);
|
||||
|
||||
/** Fetches the BIOS release.
|
||||
|
||||
@return The BIOS release.
|
||||
**/
|
||||
UINT16
|
||||
EFIAPI
|
||||
OemGetBiosRelease (
|
||||
VOID
|
||||
);
|
||||
|
||||
/** Fetches the embedded controller firmware release.
|
||||
|
||||
@return The embedded controller firmware release.
|
||||
**/
|
||||
UINT16
|
||||
EFIAPI
|
||||
OemGetEmbeddedControllerFirmwareRelease (
|
||||
VOID
|
||||
);
|
||||
|
||||
#endif // OEM_MISC_LIB_H_
|
120
ArmPkg/Include/Library/OpteeLib.h
Normal file
120
ArmPkg/Include/Library/OpteeLib.h
Normal file
@ -0,0 +1,120 @@
|
||||
/** @file
|
||||
OP-TEE specific header file.
|
||||
|
||||
Copyright (c) 2018, Linaro Ltd. All rights reserved.<BR>
|
||||
Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef OPTEE_LIB_H_
|
||||
#define OPTEE_LIB_H_
|
||||
|
||||
/*
|
||||
* The 'Trusted OS Call UID' is supposed to return the following UUID for
|
||||
* OP-TEE OS. This is a 128-bit value.
|
||||
*/
|
||||
#define OPTEE_OS_UID0 0x384fb3e0
|
||||
#define OPTEE_OS_UID1 0xe7f811e3
|
||||
#define OPTEE_OS_UID2 0xaf630002
|
||||
#define OPTEE_OS_UID3 0xa5d5c51b
|
||||
|
||||
#define OPTEE_MESSAGE_ATTRIBUTE_TYPE_NONE 0x0
|
||||
#define OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INPUT 0x1
|
||||
#define OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_OUTPUT 0x2
|
||||
#define OPTEE_MESSAGE_ATTRIBUTE_TYPE_VALUE_INOUT 0x3
|
||||
#define OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INPUT 0x9
|
||||
#define OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_OUTPUT 0xa
|
||||
#define OPTEE_MESSAGE_ATTRIBUTE_TYPE_MEMORY_INOUT 0xb
|
||||
|
||||
#define OPTEE_MESSAGE_ATTRIBUTE_TYPE_MASK 0xff
|
||||
|
||||
#define OPTEE_SUCCESS 0x00000000
|
||||
#define OPTEE_ORIGIN_COMMUNICATION 0x00000002
|
||||
#define OPTEE_ERROR_COMMUNICATION 0xFFFF000E
|
||||
|
||||
typedef struct {
|
||||
UINT64 BufferAddress;
|
||||
UINT64 Size;
|
||||
UINT64 SharedMemoryReference;
|
||||
} OPTEE_MESSAGE_PARAM_MEMORY;
|
||||
|
||||
typedef struct {
|
||||
UINT64 A;
|
||||
UINT64 B;
|
||||
UINT64 C;
|
||||
} OPTEE_MESSAGE_PARAM_VALUE;
|
||||
|
||||
typedef union {
|
||||
OPTEE_MESSAGE_PARAM_MEMORY Memory;
|
||||
OPTEE_MESSAGE_PARAM_VALUE Value;
|
||||
} OPTEE_MESSAGE_PARAM_UNION;
|
||||
|
||||
typedef struct {
|
||||
UINT64 Attribute;
|
||||
OPTEE_MESSAGE_PARAM_UNION Union;
|
||||
} OPTEE_MESSAGE_PARAM;
|
||||
|
||||
#define OPTEE_MAX_CALL_PARAMS 4
|
||||
|
||||
typedef struct {
|
||||
UINT32 Command;
|
||||
UINT32 Function;
|
||||
UINT32 Session;
|
||||
UINT32 CancelId;
|
||||
UINT32 Pad;
|
||||
UINT32 Return;
|
||||
UINT32 ReturnOrigin;
|
||||
UINT32 NumParams;
|
||||
|
||||
// NumParams tells the actual number of element in Params
|
||||
OPTEE_MESSAGE_PARAM Params[OPTEE_MAX_CALL_PARAMS];
|
||||
} OPTEE_MESSAGE_ARG;
|
||||
|
||||
typedef struct {
|
||||
EFI_GUID Uuid; // [in] GUID/UUID of the Trusted Application
|
||||
UINT32 Session; // [out] Session id
|
||||
UINT32 Return; // [out] Return value
|
||||
UINT32 ReturnOrigin; // [out] Origin of the return value
|
||||
} OPTEE_OPEN_SESSION_ARG;
|
||||
|
||||
typedef struct {
|
||||
UINT32 Function; // [in] Trusted Application function, specific to the TA
|
||||
UINT32 Session; // [in] Session id
|
||||
UINT32 Return; // [out] Return value
|
||||
UINT32 ReturnOrigin; // [out] Origin of the return value
|
||||
OPTEE_MESSAGE_PARAM Params[OPTEE_MAX_CALL_PARAMS]; // Params for function to be invoked
|
||||
} OPTEE_INVOKE_FUNCTION_ARG;
|
||||
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
IsOpteePresent (
|
||||
VOID
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
OpteeInit (
|
||||
VOID
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
OpteeOpenSession (
|
||||
IN OUT OPTEE_OPEN_SESSION_ARG *OpenSessionArg
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
OpteeCloseSession (
|
||||
IN UINT32 Session
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
OpteeInvokeFunction (
|
||||
IN OUT OPTEE_INVOKE_FUNCTION_ARG *InvokeFunctionArg
|
||||
);
|
||||
|
||||
#endif // OPTEE_LIB_H_
|
132
ArmPkg/Include/Library/SemihostLib.h
Normal file
132
ArmPkg/Include/Library/SemihostLib.h
Normal file
@ -0,0 +1,132 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
|
||||
Portions copyright (c) 2011, 2012, ARM Ltd. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef SEMIHOSTING_LIB_H_
|
||||
#define SEMIHOSTING_LIB_H_
|
||||
|
||||
/*
|
||||
*
|
||||
* Please refer to ARM RVDS 3.0 Compiler and Libraries Guide for more information
|
||||
* about the semihosting interface.
|
||||
*
|
||||
*/
|
||||
|
||||
#define SEMIHOST_FILE_MODE_READ (0 << 2)
|
||||
#define SEMIHOST_FILE_MODE_WRITE (1 << 2)
|
||||
#define SEMIHOST_FILE_MODE_APPEND (2 << 2)
|
||||
#define SEMIHOST_FILE_MODE_UPDATE (1 << 1)
|
||||
#define SEMIHOST_FILE_MODE_BINARY (1 << 0)
|
||||
#define SEMIHOST_FILE_MODE_ASCII (0 << 0)
|
||||
|
||||
BOOLEAN
|
||||
SemihostConnectionSupported (
|
||||
VOID
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
SemihostFileOpen (
|
||||
IN CHAR8 *FileName,
|
||||
IN UINT32 Mode,
|
||||
OUT UINTN *FileHandle
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
SemihostFileSeek (
|
||||
IN UINTN FileHandle,
|
||||
IN UINTN Offset
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
SemihostFileRead (
|
||||
IN UINTN FileHandle,
|
||||
IN OUT UINTN *Length,
|
||||
OUT VOID *Buffer
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
SemihostFileWrite (
|
||||
IN UINTN FileHandle,
|
||||
IN OUT UINTN *Length,
|
||||
IN VOID *Buffer
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
SemihostFileClose (
|
||||
IN UINTN FileHandle
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
SemihostFileLength (
|
||||
IN UINTN FileHandle,
|
||||
OUT UINTN *Length
|
||||
);
|
||||
|
||||
/**
|
||||
Get a temporary name for a file from the host running the debug agent.
|
||||
|
||||
@param[out] Buffer Pointer to the buffer where the temporary name has to
|
||||
be stored
|
||||
@param[in] Identifier File name identifier (integer in the range 0 to 255)
|
||||
@param[in] Length Length of the buffer to store the temporary name
|
||||
|
||||
@retval RETURN_SUCCESS Temporary name returned
|
||||
@retval RETURN_INVALID_PARAMETER Invalid buffer address
|
||||
@retval RETURN_ABORTED Temporary name not returned
|
||||
|
||||
**/
|
||||
RETURN_STATUS
|
||||
SemihostFileTmpName (
|
||||
OUT VOID *Buffer,
|
||||
IN UINT8 Identifier,
|
||||
IN UINTN Length
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
SemihostFileRemove (
|
||||
IN CHAR8 *FileName
|
||||
);
|
||||
|
||||
/**
|
||||
Rename a specified file.
|
||||
|
||||
@param[in] FileName Name of the file to rename.
|
||||
@param[in] NewFileName The new name of the file.
|
||||
|
||||
@retval RETURN_SUCCESS File Renamed
|
||||
@retval RETURN_INVALID_PARAMETER Either the current or the new name is not specified
|
||||
@retval RETURN_ABORTED Rename failed
|
||||
|
||||
**/
|
||||
RETURN_STATUS
|
||||
SemihostFileRename (
|
||||
IN CHAR8 *FileName,
|
||||
IN CHAR8 *NewFileName
|
||||
);
|
||||
|
||||
CHAR8
|
||||
SemihostReadCharacter (
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
SemihostWriteCharacter (
|
||||
IN CHAR8 Character
|
||||
);
|
||||
|
||||
VOID
|
||||
SemihostWriteString (
|
||||
IN CHAR8 *String
|
||||
);
|
||||
|
||||
UINT32
|
||||
SemihostSystem (
|
||||
IN CHAR8 *CommandLine
|
||||
);
|
||||
|
||||
#endif // SEMIHOSTING_LIB_H_
|
36
ArmPkg/Include/Library/StandaloneMmMmuLib.h
Normal file
36
ArmPkg/Include/Library/StandaloneMmMmuLib.h
Normal file
@ -0,0 +1,36 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2018, ARM Ltd. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef STANDALONE_MM_MMU_LIB_
|
||||
#define STANDALONE_MM_MMU_LIB_
|
||||
|
||||
EFI_STATUS
|
||||
ArmSetMemoryRegionNoExec (
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
ArmClearMemoryRegionNoExec (
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
ArmSetMemoryRegionReadOnly (
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length
|
||||
);
|
||||
|
||||
EFI_STATUS
|
||||
ArmClearMemoryRegionReadOnly (
|
||||
IN EFI_PHYSICAL_ADDRESS BaseAddress,
|
||||
IN UINT64 Length
|
||||
);
|
||||
|
||||
#endif /* STANDALONE_MM_MMU_LIB_ */
|
52
ArmPkg/Include/Ppi/ArmMpCoreInfo.h
Normal file
52
ArmPkg/Include/Ppi/ArmMpCoreInfo.h
Normal file
@ -0,0 +1,52 @@
|
||||
/** @file
|
||||
*
|
||||
* Copyright (c) 2011, ARM Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#ifndef ARM_MP_CORE_INFO_PPI_H_
|
||||
#define ARM_MP_CORE_INFO_PPI_H_
|
||||
|
||||
#include <Guid/ArmMpCoreInfo.h>
|
||||
|
||||
#define ARM_MP_CORE_INFO_PPI_GUID \
|
||||
{ 0x6847cc74, 0xe9ec, 0x4f8f, {0xa2, 0x9d, 0xab, 0x44, 0xe7, 0x54, 0xa8, 0xfc} }
|
||||
|
||||
/**
|
||||
This service of the EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI that migrates temporary RAM into
|
||||
permanent memory.
|
||||
|
||||
@param PeiServices Pointer to the PEI Services Table.
|
||||
@param TemporaryMemoryBase Source Address in temporary memory from which the SEC or PEIM will copy the
|
||||
Temporary RAM contents.
|
||||
@param PermanentMemoryBase Destination Address in permanent memory into which the SEC or PEIM will copy the
|
||||
Temporary RAM contents.
|
||||
@param CopySize Amount of memory to migrate from temporary to permanent memory.
|
||||
|
||||
@retval EFI_SUCCESS The data was successfully returned.
|
||||
@retval EFI_INVALID_PARAMETER PermanentMemoryBase + CopySize > TemporaryMemoryBase when
|
||||
TemporaryMemoryBase > PermanentMemoryBase.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *ARM_MP_CORE_INFO_GET)(
|
||||
OUT UINTN *ArmCoreCount,
|
||||
OUT ARM_CORE_INFO **ArmCoreTable
|
||||
);
|
||||
|
||||
///
|
||||
/// This service abstracts the ability to migrate contents of the platform early memory store.
|
||||
/// Note: The name EFI_PEI_TEMPORARY_RAM_SUPPORT_PPI is different from the current PI 1.2 spec.
|
||||
/// This PPI was optional.
|
||||
///
|
||||
typedef struct {
|
||||
ARM_MP_CORE_INFO_GET GetMpCoreInfo;
|
||||
} ARM_MP_CORE_INFO_PPI;
|
||||
|
||||
extern EFI_GUID gArmMpCoreInfoPpiGuid;
|
||||
extern EFI_GUID gArmMpCoreInfoGuid;
|
||||
|
||||
#endif // ARM_MP_CORE_INFO_PPI_H_
|
20
ArmPkg/Include/Protocol/ArmScmi.h
Normal file
20
ArmPkg/Include/Protocol/ArmScmi.h
Normal file
@ -0,0 +1,20 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2017-2018, Arm Limited. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
System Control and Management Interface V1.0
|
||||
http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/
|
||||
DEN0056A_System_Control_and_Management_Interface.pdf
|
||||
**/
|
||||
|
||||
#ifndef ARM_SCMI_H_
|
||||
#define ARM_SCMI_H_
|
||||
|
||||
/* As per SCMI specification, maximum allowed ASCII string length
|
||||
for various return values/parameters of a SCMI message.
|
||||
*/
|
||||
#define SCMI_MAX_STR_LEN 16
|
||||
|
||||
#endif /* ARM_SCMI_H_ */
|
168
ArmPkg/Include/Protocol/ArmScmiBaseProtocol.h
Normal file
168
ArmPkg/Include/Protocol/ArmScmiBaseProtocol.h
Normal file
@ -0,0 +1,168 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2017-2021, Arm Limited. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
@par Specification Reference:
|
||||
- Arm System Control and Management Interface - Platform Design Document
|
||||
(https://developer.arm.com/documentation/den0056/)
|
||||
**/
|
||||
|
||||
#ifndef ARM_SCMI_BASE_PROTOCOL_H_
|
||||
#define ARM_SCMI_BASE_PROTOCOL_H_
|
||||
|
||||
#include <Protocol/ArmScmi.h>
|
||||
|
||||
#define BASE_PROTOCOL_VERSION_V1 0x10000
|
||||
#define BASE_PROTOCOL_VERSION_V2 0x20000
|
||||
|
||||
#define NUM_PROTOCOL_MASK 0xFFU
|
||||
#define NUM_AGENT_MASK 0xFFU
|
||||
|
||||
#define NUM_AGENT_SHIFT 0x8
|
||||
|
||||
/** Returns total number of protocols that are
|
||||
implemented (excluding the Base protocol)
|
||||
*/
|
||||
#define SCMI_TOTAL_PROTOCOLS(Attr) (Attr & NUM_PROTOCOL_MASK)
|
||||
|
||||
// Returns total number of agents in the system.
|
||||
#define SCMI_TOTAL_AGENTS(Attr) ((Attr >> NUM_AGENT_SHIFT) & NUM_AGENT_MASK)
|
||||
|
||||
#define ARM_SCMI_BASE_PROTOCOL_GUID { \
|
||||
0xd7e5abe9, 0x33ab, 0x418e, {0x9f, 0x91, 0x72, 0xda, 0xe2, 0xba, 0x8e, 0x2f} \
|
||||
}
|
||||
|
||||
extern EFI_GUID gArmScmiBaseProtocolGuid;
|
||||
|
||||
typedef struct _SCMI_BASE_PROTOCOL SCMI_BASE_PROTOCOL;
|
||||
|
||||
/** Return version of the Base protocol supported by SCP firmware.
|
||||
|
||||
@param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance.
|
||||
|
||||
@param[out] Version Version of the supported SCMI Base protocol.
|
||||
|
||||
@retval EFI_SUCCESS The version of the protocol is returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_BASE_GET_VERSION)(
|
||||
IN SCMI_BASE_PROTOCOL *This,
|
||||
OUT UINT32 *Version
|
||||
);
|
||||
|
||||
/** Return total number of SCMI protocols supported by the SCP firmware.
|
||||
|
||||
@param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance.
|
||||
|
||||
@param[out] TotalProtocols Total number of SCMI protocols supported.
|
||||
|
||||
@retval EFI_SUCCESS Total number of protocols supported are returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns a SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_BASE_GET_TOTAL_PROTOCOLS)(
|
||||
IN SCMI_BASE_PROTOCOL *This,
|
||||
OUT UINT32 *TotalProtocols
|
||||
);
|
||||
|
||||
/** Return vendor name.
|
||||
|
||||
@param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance.
|
||||
|
||||
@param[out] VendorIdentifier Null terminated ASCII string of up to
|
||||
16 bytes with a vendor name.
|
||||
|
||||
@retval EFI_SUCCESS VendorIdentifier is returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns a SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_BASE_DISCOVER_VENDOR)(
|
||||
IN SCMI_BASE_PROTOCOL *This,
|
||||
OUT UINT8 VendorIdentifier[SCMI_MAX_STR_LEN]
|
||||
);
|
||||
|
||||
/** Return sub vendor name.
|
||||
|
||||
@param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance.
|
||||
|
||||
@param[out] VendorIdentifier Null terminated ASCII string of up to
|
||||
16 bytes with a vendor name.
|
||||
|
||||
@retval EFI_SUCCESS VendorIdentifier is returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns a SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_BASE_DISCOVER_SUB_VENDOR)(
|
||||
IN SCMI_BASE_PROTOCOL *This,
|
||||
OUT UINT8 VendorIdentifier[SCMI_MAX_STR_LEN]
|
||||
);
|
||||
|
||||
/** Return implementation version.
|
||||
|
||||
@param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance.
|
||||
|
||||
@param[out] ImplementationVersion Vendor specific implementation version.
|
||||
|
||||
@retval EFI_SUCCESS Implementation version is returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns a SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION)(
|
||||
IN SCMI_BASE_PROTOCOL *This,
|
||||
OUT UINT32 *ImplementationVersion
|
||||
);
|
||||
|
||||
/** Return list of protocols.
|
||||
|
||||
@param[in] This A Pointer to SCMI_BASE_PROTOCOL Instance.
|
||||
|
||||
@param[out] ProtocolListSize Size of the ProtocolList.
|
||||
|
||||
@param[out] ProtocolList Protocol list.
|
||||
|
||||
@retval EFI_SUCCESS List of protocols is returned.
|
||||
@retval EFI_BUFFER_TOO_SMALL ProtocolListSize is too small for the result.
|
||||
It has been updated to the size needed.
|
||||
@retval EFI_DEVICE_ERROR SCP returns a SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_BASE_DISCOVER_LIST_PROTOCOLS)(
|
||||
IN SCMI_BASE_PROTOCOL *This,
|
||||
IN OUT UINT32 *ProtocolListSize,
|
||||
OUT UINT8 *ProtocolList
|
||||
);
|
||||
|
||||
// Base protocol.
|
||||
typedef struct _SCMI_BASE_PROTOCOL {
|
||||
SCMI_BASE_GET_VERSION GetVersion;
|
||||
SCMI_BASE_GET_TOTAL_PROTOCOLS GetTotalProtocols;
|
||||
SCMI_BASE_DISCOVER_VENDOR DiscoverVendor;
|
||||
SCMI_BASE_DISCOVER_SUB_VENDOR DiscoverSubVendor;
|
||||
SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION DiscoverImplementationVersion;
|
||||
SCMI_BASE_DISCOVER_LIST_PROTOCOLS DiscoverListProtocols;
|
||||
} SCMI_BASE_PROTOCOL;
|
||||
|
||||
// SCMI Message IDs for Base protocol.
|
||||
typedef enum {
|
||||
ScmiMessageIdBaseDiscoverVendor = 0x3,
|
||||
ScmiMessageIdBaseDiscoverSubVendor = 0x4,
|
||||
ScmiMessageIdBaseDiscoverImplementationVersion = 0x5,
|
||||
ScmiMessageIdBaseDiscoverListProtocols = 0x6
|
||||
} SCMI_MESSAGE_ID_BASE;
|
||||
|
||||
#endif /* ARM_SCMI_BASE_PROTOCOL_H_ */
|
191
ArmPkg/Include/Protocol/ArmScmiClock2Protocol.h
Normal file
191
ArmPkg/Include/Protocol/ArmScmiClock2Protocol.h
Normal file
@ -0,0 +1,191 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2017-2021, Arm Limited. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
System Control and Management Interface V1.0
|
||||
http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/
|
||||
DEN0056A_System_Control_and_Management_Interface.pdf
|
||||
**/
|
||||
|
||||
#ifndef ARM_SCMI_CLOCK2_PROTOCOL_H_
|
||||
#define ARM_SCMI_CLOCK2_PROTOCOL_H_
|
||||
|
||||
#include <Protocol/ArmScmi.h>
|
||||
#include <Protocol/ArmScmiClockProtocol.h>
|
||||
|
||||
#define ARM_SCMI_CLOCK2_PROTOCOL_GUID {\
|
||||
0xb8d8caf2, 0x9e94, 0x462c, { 0xa8, 0x34, 0x6c, 0x99, 0xfc, 0x05, 0xef, 0xcf } \
|
||||
}
|
||||
|
||||
extern EFI_GUID gArmScmiClock2ProtocolGuid;
|
||||
|
||||
#define SCMI_CLOCK2_PROTOCOL_VERSION 1
|
||||
|
||||
typedef struct _SCMI_CLOCK2_PROTOCOL SCMI_CLOCK2_PROTOCOL;
|
||||
|
||||
// Protocol Interface functions.
|
||||
|
||||
/** Return version of the clock management protocol supported by SCP firmware.
|
||||
|
||||
@param[in] This A Pointer to SCMI_CLOCK2_PROTOCOL Instance.
|
||||
|
||||
@param[out] Version Version of the supported SCMI Clock management protocol.
|
||||
|
||||
@retval EFI_SUCCESS The version is returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_CLOCK2_GET_VERSION)(
|
||||
IN SCMI_CLOCK2_PROTOCOL *This,
|
||||
OUT UINT32 *Version
|
||||
);
|
||||
|
||||
/** Return total number of clock devices supported by the clock management
|
||||
protocol.
|
||||
|
||||
@param[in] This A Pointer to SCMI_CLOCK2_PROTOCOL Instance.
|
||||
|
||||
@param[out] TotalClocks Total number of clocks supported.
|
||||
|
||||
@retval EFI_SUCCESS Total number of clocks supported is returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_CLOCK2_GET_TOTAL_CLOCKS)(
|
||||
IN SCMI_CLOCK2_PROTOCOL *This,
|
||||
OUT UINT32 *TotalClocks
|
||||
);
|
||||
|
||||
/** Return attributes of a clock device.
|
||||
|
||||
@param[in] This A Pointer to SCMI_CLOCK2_PROTOCOL Instance.
|
||||
@param[in] ClockId Identifier for the clock device.
|
||||
|
||||
@param[out] Enabled If TRUE, the clock device is enabled.
|
||||
@param[out] ClockAsciiName A NULL terminated ASCII string with the clock
|
||||
name, of up to 16 bytes.
|
||||
|
||||
@retval EFI_SUCCESS Clock device attributes are returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_CLOCK2_GET_CLOCK_ATTRIBUTES)(
|
||||
IN SCMI_CLOCK2_PROTOCOL *This,
|
||||
IN UINT32 ClockId,
|
||||
OUT BOOLEAN *Enabled,
|
||||
OUT CHAR8 *ClockAsciiName
|
||||
);
|
||||
|
||||
/** Return list of rates supported by a given clock device.
|
||||
|
||||
@param[in] This A pointer to SCMI_CLOCK2_PROTOCOL Instance.
|
||||
@param[in] ClockId Identifier for the clock device.
|
||||
|
||||
@param[out] Format ScmiClockRateFormatDiscrete: Clock device
|
||||
supports range of clock rates which are non-linear.
|
||||
|
||||
ScmiClockRateFormatLinear: Clock device supports
|
||||
range of linear clock rates from Min to Max in steps.
|
||||
|
||||
@param[out] TotalRates Total number of rates.
|
||||
|
||||
@param[in,out] RateArraySize Size of the RateArray.
|
||||
|
||||
@param[out] RateArray List of clock rates.
|
||||
|
||||
@retval EFI_SUCCESS List of clock rates are returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval EFI_BUFFER_TOO_SMALL RateArraySize is too small for the result.
|
||||
It has been updated to the size needed.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_CLOCK2_DESCRIBE_RATES)(
|
||||
IN SCMI_CLOCK2_PROTOCOL *This,
|
||||
IN UINT32 ClockId,
|
||||
OUT SCMI_CLOCK_RATE_FORMAT *Format,
|
||||
OUT UINT32 *TotalRates,
|
||||
IN OUT UINT32 *RateArraySize,
|
||||
OUT SCMI_CLOCK_RATE *RateArray
|
||||
);
|
||||
|
||||
/** Get clock rate.
|
||||
|
||||
@param[in] This A Pointer to SCMI_CLOCK2_PROTOCOL Instance.
|
||||
@param[in] ClockId Identifier for the clock device.
|
||||
|
||||
@param[out] Rate Clock rate.
|
||||
|
||||
@retval EFI_SUCCESS Clock rate is returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_CLOCK2_RATE_GET)(
|
||||
IN SCMI_CLOCK2_PROTOCOL *This,
|
||||
IN UINT32 ClockId,
|
||||
OUT UINT64 *Rate
|
||||
);
|
||||
|
||||
/** Set clock rate.
|
||||
|
||||
@param[in] This A Pointer to SCMI_CLOCK2_PROTOCOL Instance.
|
||||
@param[in] ClockId Identifier for the clock device.
|
||||
@param[in] Rate Clock rate.
|
||||
|
||||
@retval EFI_SUCCESS Clock rate set success.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_CLOCK2_RATE_SET)(
|
||||
IN SCMI_CLOCK2_PROTOCOL *This,
|
||||
IN UINT32 ClockId,
|
||||
IN UINT64 Rate
|
||||
);
|
||||
|
||||
/** Enable/Disable specified clock.
|
||||
Function is only available under gArmScmiClock2ProtocolGuid
|
||||
|
||||
@param[in] This A Pointer to SCMI_CLOCK2_PROTOCOL Instance.
|
||||
@param[in] ClockId Identifier for the clock device.
|
||||
@param[in] Enable TRUE to enable, FALSE to disable.
|
||||
|
||||
@retval EFI_SUCCESS Clock enable/disable successful.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_CLOCK2_ENABLE)(
|
||||
IN SCMI_CLOCK2_PROTOCOL *This,
|
||||
IN UINT32 ClockId,
|
||||
IN BOOLEAN Enable
|
||||
);
|
||||
|
||||
typedef struct _SCMI_CLOCK2_PROTOCOL {
|
||||
SCMI_CLOCK2_GET_VERSION GetVersion;
|
||||
SCMI_CLOCK2_GET_TOTAL_CLOCKS GetTotalClocks;
|
||||
SCMI_CLOCK2_GET_CLOCK_ATTRIBUTES GetClockAttributes;
|
||||
SCMI_CLOCK2_DESCRIBE_RATES DescribeRates;
|
||||
SCMI_CLOCK2_RATE_GET RateGet;
|
||||
SCMI_CLOCK2_RATE_SET RateSet;
|
||||
|
||||
// Extension to original ClockProtocol, added here so SCMI_CLOCK2_PROTOCOL
|
||||
// can be cast to SCMI_CLOCK_PROTOCOL
|
||||
UINTN Version; // For future expandability
|
||||
SCMI_CLOCK2_ENABLE Enable;
|
||||
} SCMI_CLOCK2_PROTOCOL;
|
||||
|
||||
#endif /* ARM_SCMI_CLOCK2_PROTOCOL_H_ */
|
217
ArmPkg/Include/Protocol/ArmScmiClockProtocol.h
Normal file
217
ArmPkg/Include/Protocol/ArmScmiClockProtocol.h
Normal file
@ -0,0 +1,217 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2017-2021, Arm Limited. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
System Control and Management Interface V1.0
|
||||
http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/
|
||||
DEN0056A_System_Control_and_Management_Interface.pdf
|
||||
**/
|
||||
|
||||
#ifndef ARM_SCMI_CLOCK_PROTOCOL_H_
|
||||
#define ARM_SCMI_CLOCK_PROTOCOL_H_
|
||||
|
||||
#include <Protocol/ArmScmi.h>
|
||||
|
||||
#define ARM_SCMI_CLOCK_PROTOCOL_GUID {\
|
||||
0x91ce67a8, 0xe0aa, 0x4012, {0xb9, 0x9f, 0xb6, 0xfc, 0xf3, 0x4, 0x8e, 0xaa} \
|
||||
}
|
||||
|
||||
extern EFI_GUID gArmScmiClockProtocolGuid;
|
||||
|
||||
// Message Type for clock management protocol.
|
||||
typedef enum {
|
||||
ScmiMessageIdClockAttributes = 0x3,
|
||||
ScmiMessageIdClockDescribeRates = 0x4,
|
||||
ScmiMessageIdClockRateSet = 0x5,
|
||||
ScmiMessageIdClockRateGet = 0x6,
|
||||
ScmiMessageIdClockConfigSet = 0x7
|
||||
} SCMI_MESSAGE_ID_CLOCK;
|
||||
|
||||
typedef enum {
|
||||
ScmiClockRateFormatDiscrete, // Non-linear range.
|
||||
ScmiClockRateFormatLinear // Linear range.
|
||||
} SCMI_CLOCK_RATE_FORMAT;
|
||||
|
||||
// Clock management protocol version.
|
||||
#define SCMI_CLOCK_PROTOCOL_VERSION 0x10000
|
||||
|
||||
#define SCMI_CLOCK_PROTOCOL_PENDING_ASYNC_RATES_MASK 0xFFU
|
||||
#define SCMI_CLOCK_PROTOCOL_PENDING_ASYNC_RATES_SHIFT 16
|
||||
#define SCMI_CLOCK_PROTOCOL_NUM_CLOCKS_MASK 0xFFFFU
|
||||
|
||||
/** Total number of pending asynchronous clock rates changes
|
||||
supported by the SCP, Attr Bits[23:16]
|
||||
*/
|
||||
#define SCMI_CLOCK_PROTOCOL_MAX_ASYNC_CLK_RATES(Attr) ( \
|
||||
(Attr >> SCMI_CLOCK_PROTOCOL_PENDING_ASYNC_RATES_SHIFT) && \
|
||||
SCMI_CLOCK_PROTOCOL_PENDING_ASYNC_RATES_MASK)
|
||||
|
||||
// Total of clock devices supported by the SCP, Attr Bits[15:0]
|
||||
#define SCMI_CLOCK_PROTOCOL_TOTAL_CLKS(Attr) (Attr & SCMI_CLOCK_PROTOCOL_NUM_CLOCKS_MASK)
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
/* Depending on the format (linear/non-linear) supported by a clock device
|
||||
either Rate or Min/Max/Step triplet is valid.
|
||||
*/
|
||||
typedef struct {
|
||||
UINT64 Min;
|
||||
UINT64 Max;
|
||||
UINT64 Step;
|
||||
} SCMI_CLOCK_RATE_CONTINUOUS;
|
||||
|
||||
typedef struct {
|
||||
UINT64 Rate;
|
||||
} SCMI_CLOCK_RATE_DISCRETE;
|
||||
|
||||
typedef union {
|
||||
SCMI_CLOCK_RATE_CONTINUOUS ContinuousRate;
|
||||
SCMI_CLOCK_RATE_DISCRETE DiscreteRate;
|
||||
} SCMI_CLOCK_RATE;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
typedef struct _SCMI_CLOCK_PROTOCOL SCMI_CLOCK_PROTOCOL;
|
||||
|
||||
// Protocol Interface functions.
|
||||
|
||||
/** Return version of the clock management protocol supported by SCP firmware.
|
||||
|
||||
@param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance.
|
||||
|
||||
@param[out] Version Version of the supported SCMI Clock management protocol.
|
||||
|
||||
@retval EFI_SUCCESS The version is returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_CLOCK_GET_VERSION)(
|
||||
IN SCMI_CLOCK_PROTOCOL *This,
|
||||
OUT UINT32 *Version
|
||||
);
|
||||
|
||||
/** Return total number of clock devices supported by the clock management
|
||||
protocol.
|
||||
|
||||
@param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance.
|
||||
|
||||
@param[out] TotalClocks Total number of clocks supported.
|
||||
|
||||
@retval EFI_SUCCESS Total number of clocks supported is returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_CLOCK_GET_TOTAL_CLOCKS)(
|
||||
IN SCMI_CLOCK_PROTOCOL *This,
|
||||
OUT UINT32 *TotalClocks
|
||||
);
|
||||
|
||||
/** Return attributes of a clock device.
|
||||
|
||||
@param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance.
|
||||
@param[in] ClockId Identifier for the clock device.
|
||||
|
||||
@param[out] Enabled If TRUE, the clock device is enabled.
|
||||
@param[out] ClockAsciiName A NULL terminated ASCII string with the clock
|
||||
name, of up to 16 bytes.
|
||||
|
||||
@retval EFI_SUCCESS Clock device attributes are returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_CLOCK_GET_CLOCK_ATTRIBUTES)(
|
||||
IN SCMI_CLOCK_PROTOCOL *This,
|
||||
IN UINT32 ClockId,
|
||||
OUT BOOLEAN *Enabled,
|
||||
OUT CHAR8 *ClockAsciiName
|
||||
);
|
||||
|
||||
/** Return list of rates supported by a given clock device.
|
||||
|
||||
@param[in] This A pointer to SCMI_CLOCK_PROTOCOL Instance.
|
||||
@param[in] ClockId Identifier for the clock device.
|
||||
|
||||
@param[out] Format ScmiClockRateFormatDiscrete: Clock device
|
||||
supports range of clock rates which are non-linear.
|
||||
|
||||
ScmiClockRateFormatLinear: Clock device supports
|
||||
range of linear clock rates from Min to Max in steps.
|
||||
|
||||
@param[out] TotalRates Total number of rates.
|
||||
|
||||
@param[in,out] RateArraySize Size of the RateArray.
|
||||
|
||||
@param[out] RateArray List of clock rates.
|
||||
|
||||
@retval EFI_SUCCESS List of clock rates are returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval EFI_BUFFER_TOO_SMALL RateArraySize is too small for the result.
|
||||
It has been updated to the size needed.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_CLOCK_DESCRIBE_RATES)(
|
||||
IN SCMI_CLOCK_PROTOCOL *This,
|
||||
IN UINT32 ClockId,
|
||||
OUT SCMI_CLOCK_RATE_FORMAT *Format,
|
||||
OUT UINT32 *TotalRates,
|
||||
IN OUT UINT32 *RateArraySize,
|
||||
OUT SCMI_CLOCK_RATE *RateArray
|
||||
);
|
||||
|
||||
/** Get clock rate.
|
||||
|
||||
@param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance.
|
||||
@param[in] ClockId Identifier for the clock device.
|
||||
|
||||
@param[out] Rate Clock rate.
|
||||
|
||||
@retval EFI_SUCCESS Clock rate is returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_CLOCK_RATE_GET)(
|
||||
IN SCMI_CLOCK_PROTOCOL *This,
|
||||
IN UINT32 ClockId,
|
||||
OUT UINT64 *Rate
|
||||
);
|
||||
|
||||
/** Set clock rate.
|
||||
|
||||
@param[in] This A Pointer to SCMI_CLOCK_PROTOCOL Instance.
|
||||
@param[in] ClockId Identifier for the clock device.
|
||||
@param[in] Rate Clock rate.
|
||||
|
||||
@retval EFI_SUCCESS Clock rate set success.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_CLOCK_RATE_SET)(
|
||||
IN SCMI_CLOCK_PROTOCOL *This,
|
||||
IN UINT32 ClockId,
|
||||
IN UINT64 Rate
|
||||
);
|
||||
|
||||
typedef struct _SCMI_CLOCK_PROTOCOL {
|
||||
SCMI_CLOCK_GET_VERSION GetVersion;
|
||||
SCMI_CLOCK_GET_TOTAL_CLOCKS GetTotalClocks;
|
||||
SCMI_CLOCK_GET_CLOCK_ATTRIBUTES GetClockAttributes;
|
||||
SCMI_CLOCK_DESCRIBE_RATES DescribeRates;
|
||||
SCMI_CLOCK_RATE_GET RateGet;
|
||||
SCMI_CLOCK_RATE_SET RateSet;
|
||||
} SCMI_CLOCK_PROTOCOL;
|
||||
|
||||
#endif /* ARM_SCMI_CLOCK_PROTOCOL_H_ */
|
258
ArmPkg/Include/Protocol/ArmScmiPerformanceProtocol.h
Normal file
258
ArmPkg/Include/Protocol/ArmScmiPerformanceProtocol.h
Normal file
@ -0,0 +1,258 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2017-2021, Arm Limited. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
System Control and Management Interface V1.0
|
||||
http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/
|
||||
DEN0056A_System_Control_and_Management_Interface.pdf
|
||||
**/
|
||||
|
||||
#ifndef ARM_SCMI_PERFORMANCE_PROTOCOL_H_
|
||||
#define ARM_SCMI_PERFORMANCE_PROTOCOL_H_
|
||||
|
||||
#include <Protocol/ArmScmi.h>
|
||||
|
||||
#define PERFORMANCE_PROTOCOL_VERSION 0x10000
|
||||
|
||||
#define ARM_SCMI_PERFORMANCE_PROTOCOL_GUID { \
|
||||
0x9b8ba84, 0x3dd3, 0x49a6, {0xa0, 0x5a, 0x31, 0x34, 0xa5, 0xf0, 0x7b, 0xad} \
|
||||
}
|
||||
|
||||
extern EFI_GUID gArmScmiPerformanceProtocolGuid;
|
||||
|
||||
typedef struct _SCMI_PERFORMANCE_PROTOCOL SCMI_PERFORMANCE_PROTOCOL;
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
#define POWER_IN_MW_SHIFT 16
|
||||
#define POWER_IN_MW_MASK 0x1
|
||||
#define NUM_PERF_DOMAINS_MASK 0xFFFF
|
||||
|
||||
// Total number of performance domains, Attr Bits [15:0]
|
||||
#define SCMI_PERF_TOTAL_DOMAINS(Attr) (Attr & NUM_PERF_DOMAINS_MASK)
|
||||
|
||||
// A flag to express power values in mW or platform specific way, Attr Bit [16]
|
||||
#define SCMI_PERF_POWER_IN_MW(Attr) ((Attr >> POWER_IN_MW_SHIFT) & \
|
||||
POWER_IN_MW_MASK)
|
||||
|
||||
// Performance protocol attributes return values.
|
||||
typedef struct {
|
||||
UINT32 Attributes;
|
||||
UINT64 StatisticsAddress;
|
||||
UINT32 StatisticsLen;
|
||||
} SCMI_PERFORMANCE_PROTOCOL_ATTRIBUTES;
|
||||
|
||||
#define SCMI_PERF_SUPPORT_LVL_CHANGE_NOTIFY(Attr) ((Attr >> 28) & 0x1)
|
||||
#define SCMI_PERF_SUPPORT_LIM_CHANGE_NOTIFY(Attr) ((Attr >> 29) & 0x1)
|
||||
#define SCMI_PERF_SUPPORT_SET_LVL(Attr) ((Attr >> 30) & 0x1)
|
||||
#define SCMI_PERF_SUPPORT_SET_LIM(Attr) ((Attr >> 31) & 0x1)
|
||||
#define SCMI_PERF_RATE_LIMIT(RateLimit) (RateLimit & 0xFFF)
|
||||
|
||||
// Performance protocol domain attributes.
|
||||
typedef struct {
|
||||
UINT32 Attributes;
|
||||
UINT32 RateLimit;
|
||||
UINT32 SustainedFreq;
|
||||
UINT32 SustainedPerfLevel;
|
||||
UINT8 Name[SCMI_MAX_STR_LEN];
|
||||
} SCMI_PERFORMANCE_DOMAIN_ATTRIBUTES;
|
||||
|
||||
// Worst case latency in microseconds, Bits[15:0]
|
||||
#define PERF_LATENCY_MASK 0xFFFF
|
||||
#define SCMI_PERFORMANCE_PROTOCOL_LATENCY(Latency) (Latency & PERF_LATENCY_MASK)
|
||||
|
||||
// Performance protocol performance level.
|
||||
typedef struct {
|
||||
UINT32 Level;
|
||||
UINT32 PowerCost;
|
||||
UINT32 Latency;
|
||||
} SCMI_PERFORMANCE_LEVEL;
|
||||
|
||||
// Performance protocol performance limit.
|
||||
typedef struct {
|
||||
UINT32 RangeMax;
|
||||
UINT32 RangeMin;
|
||||
} SCMI_PERFORMANCE_LIMITS;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
/** Return version of the performance management protocol supported by SCP.
|
||||
firmware.
|
||||
|
||||
@param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
|
||||
|
||||
@param[out] Version Version of the supported SCMI performance management
|
||||
protocol.
|
||||
|
||||
@retval EFI_SUCCESS The version is returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_PERFORMANCE_GET_VERSION)(
|
||||
IN SCMI_PERFORMANCE_PROTOCOL *This,
|
||||
OUT UINT32 *Version
|
||||
);
|
||||
|
||||
/** Return protocol attributes of the performance management protocol.
|
||||
|
||||
@param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
|
||||
|
||||
@param[out] Attributes Protocol attributes.
|
||||
|
||||
@retval EFI_SUCCESS Protocol attributes are returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_PERFORMANCE_GET_ATTRIBUTES)(
|
||||
IN SCMI_PERFORMANCE_PROTOCOL *This,
|
||||
OUT SCMI_PERFORMANCE_PROTOCOL_ATTRIBUTES *Attributes
|
||||
|
||||
);
|
||||
|
||||
/** Return performance domain attributes.
|
||||
|
||||
@param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
|
||||
@param[in] DomainId Identifier for the performance domain.
|
||||
|
||||
@param[out] Attributes Performance domain attributes.
|
||||
|
||||
@retval EFI_SUCCESS Domain attributes are returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_PERFORMANCE_GET_DOMAIN_ATTRIBUTES)(
|
||||
IN SCMI_PERFORMANCE_PROTOCOL *This,
|
||||
IN UINT32 DomainId,
|
||||
OUT SCMI_PERFORMANCE_DOMAIN_ATTRIBUTES *DomainAttributes
|
||||
);
|
||||
|
||||
/** Return list of performance domain levels of a given domain.
|
||||
|
||||
@param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
|
||||
@param[in] DomainId Identifier for the performance domain.
|
||||
|
||||
@param[out] NumLevels Total number of levels a domain can support.
|
||||
|
||||
@param[in,out] LevelArraySize Size of the performance level array.
|
||||
|
||||
@param[out] LevelArray Array of the performance levels.
|
||||
|
||||
@retval EFI_SUCCESS Domain levels are returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval EFI_BUFFER_TOO_SMALL LevelArraySize is too small for the result.
|
||||
It has been updated to the size needed.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_PERFORMANCE_DESCRIBE_LEVELS)(
|
||||
IN SCMI_PERFORMANCE_PROTOCOL *This,
|
||||
IN UINT32 DomainId,
|
||||
OUT UINT32 *NumLevels,
|
||||
IN OUT UINT32 *LevelArraySize,
|
||||
OUT SCMI_PERFORMANCE_LEVEL *LevelArray
|
||||
);
|
||||
|
||||
/** Set performance limits of a domain.
|
||||
|
||||
@param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
|
||||
@param[in] DomainId Identifier for the performance domain.
|
||||
@param[in] Limit Performance limit to set.
|
||||
|
||||
@retval EFI_SUCCESS Performance limits set successfully.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_PERFORMANCE_LIMITS_SET)(
|
||||
IN SCMI_PERFORMANCE_PROTOCOL *This,
|
||||
IN UINT32 DomainId,
|
||||
IN SCMI_PERFORMANCE_LIMITS *Limits
|
||||
);
|
||||
|
||||
/** Get performance limits of a domain.
|
||||
|
||||
@param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
|
||||
@param[in] DomainId Identifier for the performance domain.
|
||||
|
||||
@param[out] Limit Performance Limits of the domain.
|
||||
|
||||
@retval EFI_SUCCESS Performance limits are returned.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_PERFORMANCE_LIMITS_GET)(
|
||||
SCMI_PERFORMANCE_PROTOCOL *This,
|
||||
UINT32 DomainId,
|
||||
SCMI_PERFORMANCE_LIMITS *Limits
|
||||
);
|
||||
|
||||
/** Set performance level of a domain.
|
||||
|
||||
@param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
|
||||
@param[in] DomainId Identifier for the performance domain.
|
||||
@param[in] Level Performance level of the domain.
|
||||
|
||||
@retval EFI_SUCCESS Performance level set successfully.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_PERFORMANCE_LEVEL_SET)(
|
||||
IN SCMI_PERFORMANCE_PROTOCOL *This,
|
||||
IN UINT32 DomainId,
|
||||
IN UINT32 Level
|
||||
);
|
||||
|
||||
/** Get performance level of a domain.
|
||||
|
||||
@param[in] This A Pointer to SCMI_PERFORMANCE_PROTOCOL Instance.
|
||||
@param[in] DomainId Identifier for the performance domain.
|
||||
|
||||
@param[out] Level Performance level of the domain.
|
||||
|
||||
@retval EFI_SUCCESS Performance level got successfully.
|
||||
@retval EFI_DEVICE_ERROR SCP returns an SCMI error.
|
||||
@retval !(EFI_SUCCESS) Other errors.
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *SCMI_PERFORMANCE_LEVEL_GET)(
|
||||
IN SCMI_PERFORMANCE_PROTOCOL *This,
|
||||
IN UINT32 DomainId,
|
||||
OUT UINT32 *Level
|
||||
);
|
||||
|
||||
typedef struct _SCMI_PERFORMANCE_PROTOCOL {
|
||||
SCMI_PERFORMANCE_GET_VERSION GetVersion;
|
||||
SCMI_PERFORMANCE_GET_ATTRIBUTES GetProtocolAttributes;
|
||||
SCMI_PERFORMANCE_GET_DOMAIN_ATTRIBUTES GetDomainAttributes;
|
||||
SCMI_PERFORMANCE_DESCRIBE_LEVELS DescribeLevels;
|
||||
SCMI_PERFORMANCE_LIMITS_SET LimitsSet;
|
||||
SCMI_PERFORMANCE_LIMITS_GET LimitsGet;
|
||||
SCMI_PERFORMANCE_LEVEL_SET LevelSet;
|
||||
SCMI_PERFORMANCE_LEVEL_GET LevelGet;
|
||||
} SCMI_PERFORMANCE_PROTOCOL;
|
||||
|
||||
typedef enum {
|
||||
ScmiMessageIdPerformanceDomainAttributes = 0x3,
|
||||
ScmiMessageIdPerformanceDescribeLevels = 0x4,
|
||||
ScmiMessageIdPerformanceLimitsSet = 0x5,
|
||||
ScmiMessageIdPerformanceLimitsGet = 0x6,
|
||||
ScmiMessageIdPerformanceLevelSet = 0x7,
|
||||
ScmiMessageIdPerformanceLevelGet = 0x8,
|
||||
} SCMI_MESSAGE_ID_PERFORMANCE;
|
||||
|
||||
#endif /* ARM_SCMI_PERFORMANCE_PROTOCOL_H_ */
|
284
ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.c
Normal file
284
ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.c
Normal file
@ -0,0 +1,284 @@
|
||||
/** @file
|
||||
Generic ARM implementation of TimerLib.h
|
||||
|
||||
Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include <Base.h>
|
||||
#include <Library/ArmLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/TimerLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/ArmGenericTimerCounterLib.h>
|
||||
|
||||
#define TICKS_PER_MICRO_SEC (PcdGet32 (PcdArmArchTimerFreqInHz)/1000000U)
|
||||
|
||||
// Select appropriate multiply function for platform architecture.
|
||||
#ifdef MDE_CPU_ARM
|
||||
#define MULT_U64_X_N MultU64x32
|
||||
#else
|
||||
#define MULT_U64_X_N MultU64x64
|
||||
#endif
|
||||
|
||||
RETURN_STATUS
|
||||
EFIAPI
|
||||
TimerConstructor (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
//
|
||||
// Check if the ARM Generic Timer Extension is implemented.
|
||||
//
|
||||
if (ArmIsArchTimerImplemented ()) {
|
||||
//
|
||||
// Check if Architectural Timer frequency is pre-determined by the platform
|
||||
// (ie. nonzero).
|
||||
//
|
||||
if (PcdGet32 (PcdArmArchTimerFreqInHz) != 0) {
|
||||
//
|
||||
// Check if ticks/uS is not 0. The Architectural timer runs at constant
|
||||
// frequency, irrespective of CPU frequency. According to Generic Timer
|
||||
// Ref manual, lower bound of the frequency is in the range of 1-10MHz.
|
||||
//
|
||||
ASSERT (TICKS_PER_MICRO_SEC);
|
||||
|
||||
#ifdef MDE_CPU_ARM
|
||||
//
|
||||
// Only set the frequency for ARMv7. We expect the secure firmware to
|
||||
// have already done it.
|
||||
// If the security extension is not implemented, set Timer Frequency
|
||||
// here.
|
||||
//
|
||||
if (ArmHasSecurityExtensions ()) {
|
||||
ArmGenericTimerSetTimerFreq (PcdGet32 (PcdArmArchTimerFreqInHz));
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// Architectural Timer Frequency must be set in Secure privileged
|
||||
// mode (if secure extension is supported).
|
||||
// If the reset value (0) is returned, just ASSERT.
|
||||
//
|
||||
ASSERT (ArmGenericTimerGetTimerFreq () != 0);
|
||||
} else {
|
||||
DEBUG ((DEBUG_ERROR, "ARM Architectural Timer is not available in the CPU, hence this library cannot be used.\n"));
|
||||
ASSERT (0);
|
||||
}
|
||||
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
A local utility function that returns the PCD value, if specified.
|
||||
Otherwise it defaults to ArmGenericTimerGetTimerFreq.
|
||||
|
||||
@return The timer frequency.
|
||||
|
||||
**/
|
||||
STATIC
|
||||
UINTN
|
||||
EFIAPI
|
||||
GetPlatformTimerFreq (
|
||||
)
|
||||
{
|
||||
UINTN TimerFreq;
|
||||
|
||||
TimerFreq = PcdGet32 (PcdArmArchTimerFreqInHz);
|
||||
if (TimerFreq == 0) {
|
||||
TimerFreq = ArmGenericTimerGetTimerFreq ();
|
||||
}
|
||||
|
||||
return TimerFreq;
|
||||
}
|
||||
|
||||
/**
|
||||
Stalls the CPU for the number of microseconds specified by MicroSeconds.
|
||||
|
||||
@param MicroSeconds The minimum number of microseconds to delay.
|
||||
|
||||
@return The value of MicroSeconds input.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
EFIAPI
|
||||
MicroSecondDelay (
|
||||
IN UINTN MicroSeconds
|
||||
)
|
||||
{
|
||||
UINT64 TimerTicks64;
|
||||
UINT64 SystemCounterVal;
|
||||
|
||||
// Calculate counter ticks that represent requested delay:
|
||||
// = MicroSeconds x TICKS_PER_MICRO_SEC
|
||||
// = MicroSeconds x Frequency.10^-6
|
||||
TimerTicks64 = DivU64x32 (
|
||||
MULT_U64_X_N (
|
||||
MicroSeconds,
|
||||
GetPlatformTimerFreq ()
|
||||
),
|
||||
1000000U
|
||||
);
|
||||
|
||||
// Read System Counter value
|
||||
SystemCounterVal = ArmGenericTimerGetSystemCount ();
|
||||
|
||||
TimerTicks64 += SystemCounterVal;
|
||||
|
||||
// Wait until delay count expires.
|
||||
while (SystemCounterVal < TimerTicks64) {
|
||||
SystemCounterVal = ArmGenericTimerGetSystemCount ();
|
||||
}
|
||||
|
||||
return MicroSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
Stalls the CPU for at least the given number of nanoseconds.
|
||||
|
||||
Stalls the CPU for the number of nanoseconds specified by NanoSeconds.
|
||||
|
||||
When the timer frequency is 1MHz, each tick corresponds to 1 microsecond.
|
||||
Therefore, the nanosecond delay will be rounded up to the nearest 1 microsecond.
|
||||
|
||||
@param NanoSeconds The minimum number of nanoseconds to delay.
|
||||
|
||||
@return The value of NanoSeconds inputted.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
EFIAPI
|
||||
NanoSecondDelay (
|
||||
IN UINTN NanoSeconds
|
||||
)
|
||||
{
|
||||
UINTN MicroSeconds;
|
||||
|
||||
// Round up to 1us Tick Number
|
||||
MicroSeconds = NanoSeconds / 1000;
|
||||
MicroSeconds += ((NanoSeconds % 1000) == 0) ? 0 : 1;
|
||||
|
||||
MicroSecondDelay (MicroSeconds);
|
||||
|
||||
return NanoSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
Retrieves the current value of a 64-bit free running performance counter.
|
||||
|
||||
The counter can either count up by 1 or count down by 1. If the physical
|
||||
performance counter counts by a larger increment, then the counter values
|
||||
must be translated. The properties of the counter can be retrieved from
|
||||
GetPerformanceCounterProperties().
|
||||
|
||||
@return The current value of the free running performance counter.
|
||||
|
||||
**/
|
||||
UINT64
|
||||
EFIAPI
|
||||
GetPerformanceCounter (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
// Just return the value of system count
|
||||
return ArmGenericTimerGetSystemCount ();
|
||||
}
|
||||
|
||||
/**
|
||||
Retrieves the 64-bit frequency in Hz and the range of performance counter
|
||||
values.
|
||||
|
||||
If StartValue is not NULL, then the value that the performance counter starts
|
||||
with immediately after is it rolls over is returned in StartValue. If
|
||||
EndValue is not NULL, then the value that the performance counter end with
|
||||
immediately before it rolls over is returned in EndValue. The 64-bit
|
||||
frequency of the performance counter in Hz is always returned. If StartValue
|
||||
is less than EndValue, then the performance counter counts up. If StartValue
|
||||
is greater than EndValue, then the performance counter counts down. For
|
||||
example, a 64-bit free running counter that counts up would have a StartValue
|
||||
of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter
|
||||
that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0.
|
||||
|
||||
@param StartValue The value the performance counter starts with when it
|
||||
rolls over.
|
||||
@param EndValue The value that the performance counter ends with before
|
||||
it rolls over.
|
||||
|
||||
@return The frequency in Hz.
|
||||
|
||||
**/
|
||||
UINT64
|
||||
EFIAPI
|
||||
GetPerformanceCounterProperties (
|
||||
OUT UINT64 *StartValue OPTIONAL,
|
||||
OUT UINT64 *EndValue OPTIONAL
|
||||
)
|
||||
{
|
||||
if (StartValue != NULL) {
|
||||
// Timer starts at 0
|
||||
*StartValue = (UINT64)0ULL;
|
||||
}
|
||||
|
||||
if (EndValue != NULL) {
|
||||
// Timer counts up.
|
||||
*EndValue = 0xFFFFFFFFFFFFFFFFUL;
|
||||
}
|
||||
|
||||
return (UINT64)ArmGenericTimerGetTimerFreq ();
|
||||
}
|
||||
|
||||
/**
|
||||
Converts elapsed ticks of performance counter to time in nanoseconds.
|
||||
|
||||
This function converts the elapsed ticks of running performance counter to
|
||||
time value in unit of nanoseconds.
|
||||
|
||||
@param Ticks The number of elapsed ticks of running performance counter.
|
||||
|
||||
@return The elapsed time in nanoseconds.
|
||||
|
||||
**/
|
||||
UINT64
|
||||
EFIAPI
|
||||
GetTimeInNanoSecond (
|
||||
IN UINT64 Ticks
|
||||
)
|
||||
{
|
||||
UINT64 NanoSeconds;
|
||||
UINT32 Remainder;
|
||||
UINT32 TimerFreq;
|
||||
|
||||
TimerFreq = GetPlatformTimerFreq ();
|
||||
//
|
||||
// Ticks
|
||||
// Time = --------- x 1,000,000,000
|
||||
// Frequency
|
||||
//
|
||||
NanoSeconds = MULT_U64_X_N (
|
||||
DivU64x32Remainder (
|
||||
Ticks,
|
||||
TimerFreq,
|
||||
&Remainder
|
||||
),
|
||||
1000000000U
|
||||
);
|
||||
|
||||
//
|
||||
// Frequency < 0x100000000, so Remainder < 0x100000000, then (Remainder * 1,000,000,000)
|
||||
// will not overflow 64-bit.
|
||||
//
|
||||
NanoSeconds += DivU64x32 (
|
||||
MULT_U64_X_N (
|
||||
(UINT64)Remainder,
|
||||
1000000000U
|
||||
),
|
||||
TimerFreq
|
||||
);
|
||||
|
||||
return NanoSeconds;
|
||||
}
|
32
ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf
Normal file
32
ArmPkg/Library/ArmArchTimerLib/ArmArchTimerLib.inf
Normal file
@ -0,0 +1,32 @@
|
||||
#/** @file
|
||||
#
|
||||
# Copyright (c) 2011 - 2014, ARM Limited. All rights reserved.<BR>
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
#**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = ArmArchTimerLib
|
||||
FILE_GUID = 82da1b44-d2d6-4a7d-bbf0-a0cb67964034
|
||||
MODULE_TYPE = BASE
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = TimerLib
|
||||
CONSTRUCTOR = TimerConstructor
|
||||
|
||||
[Sources.common]
|
||||
ArmArchTimerLib.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
EmbeddedPkg/EmbeddedPkg.dec
|
||||
ArmPkg/ArmPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
DebugLib
|
||||
ArmLib
|
||||
BaseLib
|
||||
ArmGenericTimerCounterLib
|
||||
|
||||
[Pcd]
|
||||
gArmTokenSpaceGuid.PcdArmArchTimerFreqInHz
|
148
ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.c
Normal file
148
ArmPkg/Library/ArmCacheMaintenanceLib/ArmCacheMaintenanceLib.c
Normal file
@ -0,0 +1,148 @@
|
||||
/** @file
|
||||
|
||||
Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
|
||||
Copyright (c) 2011 - 2021, ARM Limited. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
#include <Base.h>
|
||||
#include <Library/ArmLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
CacheRangeOperation (
|
||||
IN VOID *Start,
|
||||
IN UINTN Length,
|
||||
IN LINE_OPERATION LineOperation,
|
||||
IN UINTN LineLength
|
||||
)
|
||||
{
|
||||
UINTN ArmCacheLineAlignmentMask;
|
||||
// Align address (rounding down)
|
||||
UINTN AlignedAddress;
|
||||
UINTN EndAddress;
|
||||
|
||||
ArmCacheLineAlignmentMask = LineLength - 1;
|
||||
AlignedAddress = (UINTN)Start - ((UINTN)Start & ArmCacheLineAlignmentMask);
|
||||
EndAddress = (UINTN)Start + Length;
|
||||
|
||||
// Perform the line operation on an address in each cache line
|
||||
while (AlignedAddress < EndAddress) {
|
||||
LineOperation (AlignedAddress);
|
||||
AlignedAddress += LineLength;
|
||||
}
|
||||
|
||||
ArmDataSynchronizationBarrier ();
|
||||
}
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
InvalidateInstructionCache (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
ASSERT (FALSE);
|
||||
}
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
InvalidateDataCache (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
ASSERT (FALSE);
|
||||
}
|
||||
|
||||
VOID *
|
||||
EFIAPI
|
||||
InvalidateInstructionCacheRange (
|
||||
IN VOID *Address,
|
||||
IN UINTN Length
|
||||
)
|
||||
{
|
||||
CacheRangeOperation (
|
||||
Address,
|
||||
Length,
|
||||
ArmCleanDataCacheEntryToPoUByMVA,
|
||||
ArmDataCacheLineLength ()
|
||||
);
|
||||
CacheRangeOperation (
|
||||
Address,
|
||||
Length,
|
||||
ArmInvalidateInstructionCacheEntryToPoUByMVA,
|
||||
ArmInstructionCacheLineLength ()
|
||||
);
|
||||
|
||||
ArmInstructionSynchronizationBarrier ();
|
||||
|
||||
return Address;
|
||||
}
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
WriteBackInvalidateDataCache (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
ASSERT (FALSE);
|
||||
}
|
||||
|
||||
VOID *
|
||||
EFIAPI
|
||||
WriteBackInvalidateDataCacheRange (
|
||||
IN VOID *Address,
|
||||
IN UINTN Length
|
||||
)
|
||||
{
|
||||
CacheRangeOperation (
|
||||
Address,
|
||||
Length,
|
||||
ArmCleanInvalidateDataCacheEntryByMVA,
|
||||
ArmDataCacheLineLength ()
|
||||
);
|
||||
return Address;
|
||||
}
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
WriteBackDataCache (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
ASSERT (FALSE);
|
||||
}
|
||||
|
||||
VOID *
|
||||
EFIAPI
|
||||
WriteBackDataCacheRange (
|
||||
IN VOID *Address,
|
||||
IN UINTN Length
|
||||
)
|
||||
{
|
||||
CacheRangeOperation (
|
||||
Address,
|
||||
Length,
|
||||
ArmCleanDataCacheEntryByMVA,
|
||||
ArmDataCacheLineLength ()
|
||||
);
|
||||
return Address;
|
||||
}
|
||||
|
||||
VOID *
|
||||
EFIAPI
|
||||
InvalidateDataCacheRange (
|
||||
IN VOID *Address,
|
||||
IN UINTN Length
|
||||
)
|
||||
{
|
||||
CacheRangeOperation (
|
||||
Address,
|
||||
Length,
|
||||
ArmInvalidateDataCacheEntryByMVA,
|
||||
ArmDataCacheLineLength ()
|
||||
);
|
||||
return Address;
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
#/** @file
|
||||
# Implement CacheMaintenanceLib for ARM architectures
|
||||
#
|
||||
# Copyright (c) 2008, Apple Inc. All rights reserved.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
#
|
||||
#**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = ArmCacheMaintenanceLib
|
||||
FILE_GUID = 1A20BE1F-33AD-450C-B49A-7123FCA8B7F9
|
||||
MODULE_TYPE = BASE
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = CacheMaintenanceLib
|
||||
|
||||
[Sources.common]
|
||||
ArmCacheMaintenanceLib.c
|
||||
|
||||
[Packages]
|
||||
ArmPkg/ArmPkg.dec
|
||||
MdePkg/MdePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
ArmLib
|
||||
BaseLib
|
42
ArmPkg/Library/ArmDisassemblerLib/Aarch64Disassembler.c
Normal file
42
ArmPkg/Library/ArmDisassemblerLib/Aarch64Disassembler.c
Normal file
@ -0,0 +1,42 @@
|
||||
/** @file
|
||||
Default exception handler
|
||||
|
||||
Copyright (c) 2014, ARM Limited. All rights reserved.
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include <Base.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/PrintLib.h>
|
||||
#include <Library/ArmDisassemblerLib.h>
|
||||
|
||||
/**
|
||||
Place a disassembly of **OpCodePtr into buffer, and update OpCodePtr to
|
||||
point to next instruction.
|
||||
|
||||
@param OpCodePtrPtr Pointer to pointer of instruction to disassemble.
|
||||
@param Thumb TRUE for Thumb(2), FALSE for ARM instruction stream
|
||||
@param Extended TRUE dump hex for instruction too.
|
||||
@param ItBlock Size of IT Block
|
||||
@param Buf Buffer to sprintf disassembly into.
|
||||
@param Size Size of Buf in bytes.
|
||||
|
||||
**/
|
||||
VOID
|
||||
DisassembleInstruction (
|
||||
IN UINT8 **OpCodePtr,
|
||||
IN BOOLEAN Thumb,
|
||||
IN BOOLEAN Extended,
|
||||
IN OUT UINT32 *ItBlock,
|
||||
OUT CHAR8 *Buf,
|
||||
OUT UINTN Size
|
||||
)
|
||||
{
|
||||
// Not yet supported for AArch64.
|
||||
// Put error in the buffer as we have no return code and the buffer may be
|
||||
// printed directly so needs a '\0'.
|
||||
AsciiSPrint (Buf, Size, "AArch64 not supported");
|
||||
return;
|
||||
}
|
465
ArmPkg/Library/ArmDisassemblerLib/ArmDisassembler.c
Normal file
465
ArmPkg/Library/ArmDisassemblerLib/ArmDisassembler.c
Normal file
@ -0,0 +1,465 @@
|
||||
/** @file
|
||||
Default exception handler
|
||||
|
||||
Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
|
||||
Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include <Base.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/PrintLib.h>
|
||||
#include <Library/ArmDisassemblerLib.h>
|
||||
|
||||
CHAR8 *gCondition[] = {
|
||||
"EQ",
|
||||
"NE",
|
||||
"CS",
|
||||
"CC",
|
||||
"MI",
|
||||
"PL",
|
||||
"VS",
|
||||
"VC",
|
||||
"HI",
|
||||
"LS",
|
||||
"GE",
|
||||
"LT",
|
||||
"GT",
|
||||
"LE",
|
||||
"",
|
||||
"2"
|
||||
};
|
||||
|
||||
#define COND(_a) gCondition[((_a) >> 28)]
|
||||
|
||||
CHAR8 *gReg[] = {
|
||||
"r0",
|
||||
"r1",
|
||||
"r2",
|
||||
"r3",
|
||||
"r4",
|
||||
"r5",
|
||||
"r6",
|
||||
"r7",
|
||||
"r8",
|
||||
"r9",
|
||||
"r10",
|
||||
"r11",
|
||||
"r12",
|
||||
"sp",
|
||||
"lr",
|
||||
"pc"
|
||||
};
|
||||
|
||||
CHAR8 *gLdmAdr[] = {
|
||||
"DA",
|
||||
"IA",
|
||||
"DB",
|
||||
"IB"
|
||||
};
|
||||
|
||||
CHAR8 *gLdmStack[] = {
|
||||
"FA",
|
||||
"FD",
|
||||
"EA",
|
||||
"ED"
|
||||
};
|
||||
|
||||
#define LDM_EXT(_reg, _off) ((_reg == 13) ? gLdmStack[(_off)] : gLdmAdr[(_off)])
|
||||
|
||||
#define SIGN(_U) ((_U) ? "" : "-")
|
||||
#define WRITE(_Write) ((_Write) ? "!" : "")
|
||||
#define BYTE(_B) ((_B) ? "B":"")
|
||||
#define USER(_B) ((_B) ? "^" : "")
|
||||
|
||||
CHAR8 mMregListStr[4*15 + 1];
|
||||
|
||||
CHAR8 *
|
||||
MRegList (
|
||||
UINT32 OpCode
|
||||
)
|
||||
{
|
||||
UINTN Index, Start, End;
|
||||
BOOLEAN First;
|
||||
|
||||
mMregListStr[0] = '\0';
|
||||
AsciiStrCatS (mMregListStr, sizeof mMregListStr, "{");
|
||||
for (Index = 0, First = TRUE; Index <= 15; Index++) {
|
||||
if ((OpCode & (1 << Index)) != 0) {
|
||||
Start = End = Index;
|
||||
for (Index++; ((OpCode & (1 << Index)) != 0) && Index <= 15; Index++) {
|
||||
End = Index;
|
||||
}
|
||||
|
||||
if (!First) {
|
||||
AsciiStrCatS (mMregListStr, sizeof mMregListStr, ",");
|
||||
} else {
|
||||
First = FALSE;
|
||||
}
|
||||
|
||||
if (Start == End) {
|
||||
AsciiStrCatS (mMregListStr, sizeof mMregListStr, gReg[Start]);
|
||||
AsciiStrCatS (mMregListStr, sizeof mMregListStr, ", ");
|
||||
} else {
|
||||
AsciiStrCatS (mMregListStr, sizeof mMregListStr, gReg[Start]);
|
||||
AsciiStrCatS (mMregListStr, sizeof mMregListStr, "-");
|
||||
AsciiStrCatS (mMregListStr, sizeof mMregListStr, gReg[End]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (First) {
|
||||
AsciiStrCatS (mMregListStr, sizeof mMregListStr, "ERROR");
|
||||
}
|
||||
|
||||
AsciiStrCatS (mMregListStr, sizeof mMregListStr, "}");
|
||||
|
||||
// BugBug: Make caller pass in buffer it is cleaner
|
||||
return mMregListStr;
|
||||
}
|
||||
|
||||
CHAR8 *
|
||||
FieldMask (
|
||||
IN UINT32 Mask
|
||||
)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
UINT32
|
||||
RotateRight (
|
||||
IN UINT32 Op,
|
||||
IN UINT32 Shift
|
||||
)
|
||||
{
|
||||
return (Op >> Shift) | (Op << (32 - Shift));
|
||||
}
|
||||
|
||||
/**
|
||||
Place a disassembly of **OpCodePtr into buffer, and update OpCodePtr to
|
||||
point to next instruction.
|
||||
|
||||
We cheat and only decode instructions that access
|
||||
memory. If the instruction is not found we dump the instruction in hex.
|
||||
|
||||
@param OpCodePtr Pointer to pointer of ARM instruction to disassemble.
|
||||
@param Buf Buffer to sprintf disassembly into.
|
||||
@param Size Size of Buf in bytes.
|
||||
@param Extended TRUE dump hex for instruction too.
|
||||
|
||||
**/
|
||||
VOID
|
||||
DisassembleArmInstruction (
|
||||
IN UINT32 **OpCodePtr,
|
||||
OUT CHAR8 *Buf,
|
||||
OUT UINTN Size,
|
||||
IN BOOLEAN Extended
|
||||
)
|
||||
{
|
||||
UINT32 OpCode;
|
||||
CHAR8 *Type;
|
||||
CHAR8 *Root;
|
||||
BOOLEAN Imm, Pre, Up, WriteBack, Write, Load, Sign, Half;
|
||||
UINT32 Rn, Rd, Rm;
|
||||
UINT32 IMod, Offset8, Offset12;
|
||||
UINT32 Index;
|
||||
UINT32 ShiftImm, Shift;
|
||||
|
||||
OpCode = **OpCodePtr;
|
||||
|
||||
Imm = (OpCode & BIT25) == BIT25; // I
|
||||
Pre = (OpCode & BIT24) == BIT24; // P
|
||||
Up = (OpCode & BIT23) == BIT23; // U
|
||||
WriteBack = (OpCode & BIT22) == BIT22; // B, also called S
|
||||
Write = (OpCode & BIT21) == BIT21; // W
|
||||
Load = (OpCode & BIT20) == BIT20; // L
|
||||
Sign = (OpCode & BIT6) == BIT6; // S
|
||||
Half = (OpCode & BIT5) == BIT5; // H
|
||||
Rn = (OpCode >> 16) & 0xf;
|
||||
Rd = (OpCode >> 12) & 0xf;
|
||||
Rm = (OpCode & 0xf);
|
||||
|
||||
if (Extended) {
|
||||
Index = AsciiSPrint (Buf, Size, "0x%08x ", OpCode);
|
||||
Buf += Index;
|
||||
Size -= Index;
|
||||
}
|
||||
|
||||
// LDREX, STREX
|
||||
if ((OpCode & 0x0fe000f0) == 0x01800090) {
|
||||
if (Load) {
|
||||
// A4.1.27 LDREX{<cond>} <Rd>, [<Rn>]
|
||||
AsciiSPrint (Buf, Size, "LDREX%a %a, [%a]", COND (OpCode), gReg[Rd], gReg[Rn]);
|
||||
} else {
|
||||
// A4.1.103 STREX{<cond>} <Rd>, <Rm>, [<Rn>]
|
||||
AsciiSPrint (Buf, Size, "STREX%a %a, %a, [%a]", COND (OpCode), gReg[Rd], gReg[Rn], gReg[Rn]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// LDM/STM
|
||||
if ((OpCode & 0x0e000000) == 0x08000000) {
|
||||
if (Load) {
|
||||
// A4.1.20 LDM{<cond>}<addressing_mode> <Rn>{!}, <registers>
|
||||
// A4.1.21 LDM{<cond>}<addressing_mode> <Rn>, <registers_without_pc>^
|
||||
// A4.1.22 LDM{<cond>}<addressing_mode> <Rn>{!}, <registers_and_pc>^
|
||||
AsciiSPrint (Buf, Size, "LDM%a%a, %a%a, %a", COND (OpCode), LDM_EXT (Rn, (OpCode >> 23) & 3), gReg[Rn], WRITE (Write), MRegList (OpCode), USER (WriteBack));
|
||||
} else {
|
||||
// A4.1.97 STM{<cond>}<addressing_mode> <Rn>{!}, <registers>
|
||||
// A4.1.98 STM{<cond>}<addressing_mode> <Rn>, <registers>^
|
||||
AsciiSPrint (Buf, Size, "STM%a%a, %a%a, %a", COND (OpCode), LDM_EXT (Rn, (OpCode >> 23) & 3), gReg[Rn], WRITE (Write), MRegList (OpCode), USER (WriteBack));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// LDR/STR Address Mode 2
|
||||
if (((OpCode & 0x0c000000) == 0x04000000) || ((OpCode & 0xfd70f000) == 0xf550f000)) {
|
||||
Offset12 = OpCode & 0xfff;
|
||||
if ((OpCode & 0xfd70f000) == 0xf550f000) {
|
||||
Index = AsciiSPrint (Buf, Size, "PLD");
|
||||
} else {
|
||||
Index = AsciiSPrint (Buf, Size, "%a%a%a%a %a, ", Load ? "LDR" : "STR", COND (OpCode), BYTE (WriteBack), (!(Pre) && Write) ? "T" : "", gReg[Rd]);
|
||||
}
|
||||
|
||||
if (Pre) {
|
||||
if (!Imm) {
|
||||
// A5.2.2 [<Rn>, #+/-<offset_12>]
|
||||
// A5.2.5 [<Rn>, #+/-<offset_12>]
|
||||
AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a0x%x]%a", gReg[Rn], SIGN (Up), Offset12, WRITE (Write));
|
||||
} else if ((OpCode & 0x03000ff0) == 0x03000000) {
|
||||
// A5.2.3 [<Rn>, +/-<Rm>]
|
||||
// A5.2.6 [<Rn>, +/-<Rm>]!
|
||||
AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a%a]%a", gReg[Rn], SIGN (Up), WRITE (Write));
|
||||
} else {
|
||||
// A5.2.4 [<Rn>, +/-<Rm>, LSL #<shift_imm>]
|
||||
// A5.2.7 [<Rn>, +/-<Rm>, LSL #<shift_imm>]!
|
||||
ShiftImm = (OpCode >> 7) & 0x1f;
|
||||
Shift = (OpCode >> 5) & 0x3;
|
||||
if (Shift == 0x0) {
|
||||
Type = "LSL";
|
||||
} else if (Shift == 0x1) {
|
||||
Type = "LSR";
|
||||
if (ShiftImm == 0) {
|
||||
ShiftImm = 32;
|
||||
}
|
||||
} else if (Shift == 0x2) {
|
||||
Type = "ASR";
|
||||
} else if (ShiftImm == 0) {
|
||||
AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a%a, %a, RRX]%a", gReg[Rn], SIGN (Up), gReg[Rm], WRITE (Write));
|
||||
return;
|
||||
} else {
|
||||
Type = "ROR";
|
||||
}
|
||||
|
||||
AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a%a, %a, #%d]%a", gReg[Rn], SIGN (Up), gReg[Rm], Type, ShiftImm, WRITE (Write));
|
||||
}
|
||||
} else {
|
||||
// !Pre
|
||||
if (!Imm) {
|
||||
// A5.2.8 [<Rn>], #+/-<offset_12>
|
||||
AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a0x%x", gReg[Rn], SIGN (Up), Offset12);
|
||||
} else if ((OpCode & 0x03000ff0) == 0x03000000) {
|
||||
// A5.2.9 [<Rn>], +/-<Rm>
|
||||
AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a%a", gReg[Rn], SIGN (Up), gReg[Rm]);
|
||||
} else {
|
||||
// A5.2.10 [<Rn>], +/-<Rm>, LSL #<shift_imm>
|
||||
ShiftImm = (OpCode >> 7) & 0x1f;
|
||||
Shift = (OpCode >> 5) & 0x3;
|
||||
|
||||
if (Shift == 0x0) {
|
||||
Type = "LSL";
|
||||
} else if (Shift == 0x1) {
|
||||
Type = "LSR";
|
||||
if (ShiftImm == 0) {
|
||||
ShiftImm = 32;
|
||||
}
|
||||
} else if (Shift == 0x2) {
|
||||
Type = "ASR";
|
||||
} else if (ShiftImm == 0) {
|
||||
AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a%a, %a, RRX", gReg[Rn], SIGN (Up), gReg[Rm]);
|
||||
// FIx me
|
||||
return;
|
||||
} else {
|
||||
Type = "ROR";
|
||||
}
|
||||
|
||||
AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a%a, %a, #%d", gReg[Rn], SIGN (Up), gReg[Rm], Type, ShiftImm);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ((OpCode & 0x0e000000) == 0x00000000) {
|
||||
// LDR/STR address mode 3
|
||||
// LDR|STR{<cond>}H|SH|SB|D <Rd>, <addressing_mode>
|
||||
if (Load) {
|
||||
if (!Sign) {
|
||||
Root = "LDR%aH %a, ";
|
||||
} else if (!Half) {
|
||||
Root = "LDR%aSB %a, ";
|
||||
} else {
|
||||
Root = "LDR%aSH %a, ";
|
||||
}
|
||||
} else {
|
||||
if (!Sign) {
|
||||
Root = "STR%aH %a ";
|
||||
} else if (!Half) {
|
||||
Root = "LDR%aD %a ";
|
||||
} else {
|
||||
Root = "STR%aD %a ";
|
||||
}
|
||||
}
|
||||
|
||||
Index = AsciiSPrint (Buf, Size, Root, COND (OpCode), gReg[Rd]);
|
||||
|
||||
Sign = (OpCode & BIT6) == BIT6;
|
||||
Half = (OpCode & BIT5) == BIT5;
|
||||
Offset8 = ((OpCode >> 4) | (OpCode * 0xf)) & 0xff;
|
||||
if (Pre & !Write) {
|
||||
// Immediate offset/index
|
||||
if (WriteBack) {
|
||||
// A5.3.2 [<Rn>, #+/-<offset_8>]
|
||||
// A5.3.4 [<Rn>, #+/-<offset_8>]!
|
||||
AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a%d]%a", gReg[Rn], SIGN (Up), Offset8, WRITE (Write));
|
||||
} else {
|
||||
// A5.3.3 [<Rn>, +/-<Rm>]
|
||||
// A5.3.5 [<Rn>, +/-<Rm>]!
|
||||
AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a%]a", gReg[Rn], SIGN (Up), gReg[Rm], WRITE (Write));
|
||||
}
|
||||
} else {
|
||||
// Register offset/index
|
||||
if (WriteBack) {
|
||||
// A5.3.6 [<Rn>], #+/-<offset_8>
|
||||
AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a%d", gReg[Rn], SIGN (Up), Offset8);
|
||||
} else {
|
||||
// A5.3.7 [<Rn>], +/-<Rm>
|
||||
AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a%a", gReg[Rn], SIGN (Up), gReg[Rm]);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ((OpCode & 0x0fb000f0) == 0x01000050) {
|
||||
// A4.1.108 SWP SWP{<cond>}B <Rd>, <Rm>, [<Rn>]
|
||||
// A4.1.109 SWPB SWP{<cond>}B <Rd>, <Rm>, [<Rn>]
|
||||
AsciiSPrint (Buf, Size, "SWP%a%a %a, %a, [%a]", COND (OpCode), BYTE (WriteBack), gReg[Rd], gReg[Rm], gReg[Rn]);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((OpCode & 0xfe5f0f00) == 0xf84d0500) {
|
||||
// A4.1.90 SRS SRS<addressing_mode> #<mode>{!}
|
||||
AsciiSPrint (Buf, Size, "SRS%a #0x%x%a", gLdmStack[(OpCode >> 23) & 3], OpCode & 0x1f, WRITE (Write));
|
||||
return;
|
||||
}
|
||||
|
||||
if ((OpCode & 0xfe500f00) == 0xf8100500) {
|
||||
// A4.1.59 RFE<addressing_mode> <Rn>{!}
|
||||
AsciiSPrint (Buf, Size, "RFE%a %a", gLdmStack[(OpCode >> 23) & 3], gReg[Rn], WRITE (Write));
|
||||
return;
|
||||
}
|
||||
|
||||
if ((OpCode & 0xfff000f0) == 0xe1200070) {
|
||||
// A4.1.7 BKPT <immed_16>
|
||||
AsciiSPrint (Buf, Size, "BKPT %x", ((OpCode >> 8) | (OpCode & 0xf)) & 0xffff);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((OpCode & 0xfff10020) == 0xf1000000) {
|
||||
// A4.1.16 CPS<effect> <iflags> {, #<mode>}
|
||||
if (((OpCode >> 6) & 0x7) == 0) {
|
||||
AsciiSPrint (Buf, Size, "CPS #0x%x", (OpCode & 0x2f));
|
||||
} else {
|
||||
IMod = (OpCode >> 18) & 0x3;
|
||||
Index = AsciiSPrint (
|
||||
Buf,
|
||||
Size,
|
||||
"CPS%a %a%a%a",
|
||||
(IMod == 3) ? "ID" : "IE",
|
||||
((OpCode & BIT8) != 0) ? "A" : "",
|
||||
((OpCode & BIT7) != 0) ? "I" : "",
|
||||
((OpCode & BIT6) != 0) ? "F" : ""
|
||||
);
|
||||
if ((OpCode & BIT17) != 0) {
|
||||
AsciiSPrint (&Buf[Index], Size - Index, ", #0x%x", OpCode & 0x1f);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ((OpCode & 0x0f000000) == 0x0f000000) {
|
||||
// A4.1.107 SWI{<cond>} <immed_24>
|
||||
AsciiSPrint (Buf, Size, "SWI%a %x", COND (OpCode), OpCode & 0x00ffffff);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((OpCode & 0x0fb00000) == 0x01000000) {
|
||||
// A4.1.38 MRS{<cond>} <Rd>, CPSR MRS{<cond>} <Rd>, SPSR
|
||||
AsciiSPrint (Buf, Size, "MRS%a %a, %a", COND (OpCode), gReg[Rd], WriteBack ? "SPSR" : "CPSR");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((OpCode & 0x0db00000) == 0x01200000) {
|
||||
// A4.1.38 MSR{<cond>} CPSR_<fields>, #<immediate> MSR{<cond>} CPSR_<fields>, <Rm>
|
||||
if (Imm) {
|
||||
// MSR{<cond>} CPSR_<fields>, #<immediate>
|
||||
AsciiSPrint (Buf, Size, "MRS%a %a_%a, #0x%x", COND (OpCode), WriteBack ? "SPSR" : "CPSR", FieldMask ((OpCode >> 16) & 0xf), RotateRight (OpCode & 0xf, ((OpCode >> 8) & 0xf) *2));
|
||||
} else {
|
||||
// MSR{<cond>} CPSR_<fields>, <Rm>
|
||||
AsciiSPrint (Buf, Size, "MRS%a %a_%a, %a", COND (OpCode), WriteBack ? "SPSR" : "CPSR", gReg[Rd]);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ((OpCode & 0xff000010) == 0xfe000000) {
|
||||
// A4.1.13 CDP{<cond>} <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
|
||||
AsciiSPrint (Buf, Size, "CDP%a 0x%x, 0x%x, CR%d, CR%d, CR%d, 0x%x", COND (OpCode), (OpCode >> 8) & 0xf, (OpCode >> 20) & 0xf, Rn, Rd, Rm, (OpCode >> 5) &0x7);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((OpCode & 0x0e000000) == 0x0c000000) {
|
||||
// A4.1.19 LDC and A4.1.96 SDC
|
||||
if ((OpCode & 0xf0000000) == 0xf0000000) {
|
||||
Index = AsciiSPrint (Buf, Size, "%a2 0x%x, CR%d, ", Load ? "LDC" : "SDC", (OpCode >> 8) & 0xf, Rd);
|
||||
} else {
|
||||
Index = AsciiSPrint (Buf, Size, "%a%a 0x%x, CR%d, ", Load ? "LDC" : "SDC", COND (OpCode), (OpCode >> 8) & 0xf, Rd);
|
||||
}
|
||||
|
||||
if (!Pre) {
|
||||
if (!Write) {
|
||||
// A5.5.5.5 [<Rn>], <option>
|
||||
AsciiSPrint (&Buf[Index], Size - Index, "[%a], {0x%x}", gReg[Rn], OpCode & 0xff);
|
||||
} else {
|
||||
// A.5.5.4 [<Rn>], #+/-<offset_8>*4
|
||||
AsciiSPrint (&Buf[Index], Size - Index, "[%a], #%a0x%x*4", gReg[Rn], SIGN (Up), OpCode & 0xff);
|
||||
}
|
||||
} else {
|
||||
// A5.5.5.2 [<Rn>, #+/-<offset_8>*4 ]!
|
||||
AsciiSPrint (&Buf[Index], Size - Index, "[%a, #%a0x%x*4]%a", gReg[Rn], SIGN (Up), OpCode & 0xff, WRITE (Write));
|
||||
}
|
||||
}
|
||||
|
||||
if ((OpCode & 0x0f000010) == 0x0e000010) {
|
||||
// A4.1.32 MRC2, MCR2
|
||||
AsciiSPrint (Buf, Size, "%a%a 0x%x, 0x%x, %a, CR%d, CR%d, 0x%x", Load ? "MRC" : "MCR", COND (OpCode), (OpCode >> 8) & 0xf, (OpCode >> 20) & 0xf, gReg[Rd], Rn, Rm, (OpCode >> 5) &0x7);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((OpCode & 0x0ff00000) == 0x0c400000) {
|
||||
// A4.1.33 MRRC2, MCRR2
|
||||
AsciiSPrint (Buf, Size, "%a%a 0x%x, 0x%x, %a, %a, CR%d", Load ? "MRRC" : "MCRR", COND (OpCode), (OpCode >> 4) & 0xf, (OpCode >> 20) & 0xf, gReg[Rd], gReg[Rn], Rm);
|
||||
return;
|
||||
}
|
||||
|
||||
AsciiSPrint (Buf, Size, "Faulting OpCode 0x%08x", OpCode);
|
||||
|
||||
*OpCodePtr += 1;
|
||||
return;
|
||||
}
|
35
ArmPkg/Library/ArmDisassemblerLib/ArmDisassemblerLib.inf
Normal file
35
ArmPkg/Library/ArmDisassemblerLib/ArmDisassemblerLib.inf
Normal file
@ -0,0 +1,35 @@
|
||||
#/** @file
|
||||
# ARM Disassembler library
|
||||
#
|
||||
# Copyright (c) 2008, Apple Inc. All rights reserved.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
#
|
||||
#**/
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = ArmDisassemblerLib
|
||||
FILE_GUID = 7ACEC173-F15D-426C-8F2F-BD86B4183EF1
|
||||
MODULE_TYPE = BASE
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = ArmDisassemblerLib
|
||||
|
||||
|
||||
[Sources.ARM]
|
||||
ArmDisassembler.c
|
||||
ThumbDisassembler.c
|
||||
|
||||
[Sources.AARCH64]
|
||||
Aarch64Disassembler.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
ArmPkg/ArmPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
PrintLib
|
||||
DebugLib
|
||||
PeCoffGetEntryPointLib
|
1073
ArmPkg/Library/ArmDisassemblerLib/ThumbDisassembler.c
Normal file
1073
ArmPkg/Library/ArmDisassemblerLib/ThumbDisassembler.c
Normal file
File diff suppressed because it is too large
Load Diff
53
ArmPkg/Library/ArmExceptionLib/AArch64/AArch64Exception.c
Normal file
53
ArmPkg/Library/ArmExceptionLib/AArch64/AArch64Exception.c
Normal file
@ -0,0 +1,53 @@
|
||||
/** @file
|
||||
* Exception Handling support specific for AArch64
|
||||
*
|
||||
* Copyright (c) 2016 HP Development Company, L.P.
|
||||
* Copyright (c) 2021, Arm Limited. All rights reserved.<BR>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#include <Uefi.h>
|
||||
|
||||
#include <Chipset/AArch64.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Protocol/DebugSupport.h> // for MAX_AARCH64_EXCEPTION
|
||||
|
||||
UINTN gMaxExceptionNumber = MAX_AARCH64_EXCEPTION;
|
||||
EFI_EXCEPTION_CALLBACK gExceptionHandlers[MAX_AARCH64_EXCEPTION + 1] = { 0 };
|
||||
EFI_EXCEPTION_CALLBACK gDebuggerExceptionHandlers[MAX_AARCH64_EXCEPTION + 1] = { 0 };
|
||||
PHYSICAL_ADDRESS gExceptionVectorAlignmentMask = ARM_VECTOR_TABLE_ALIGNMENT;
|
||||
UINTN gDebuggerNoHandlerValue = 0; // todo: define for AArch64
|
||||
|
||||
#define EL0_STACK_SIZE EFI_PAGES_TO_SIZE(2)
|
||||
STATIC UINTN mNewStackBase[EL0_STACK_SIZE / sizeof (UINTN)];
|
||||
|
||||
VOID
|
||||
RegisterEl0Stack (
|
||||
IN VOID *Stack
|
||||
);
|
||||
|
||||
RETURN_STATUS
|
||||
ArchVectorConfig (
|
||||
IN UINTN VectorBaseAddress
|
||||
)
|
||||
{
|
||||
UINTN HcrReg;
|
||||
|
||||
// Round down sp by 16 bytes alignment
|
||||
RegisterEl0Stack (
|
||||
(VOID *)(((UINTN)mNewStackBase + EL0_STACK_SIZE) & ~0xFUL)
|
||||
);
|
||||
|
||||
if (ArmReadCurrentEL () == AARCH64_EL2) {
|
||||
HcrReg = ArmReadHcr ();
|
||||
|
||||
// Trap General Exceptions. All exceptions that would be routed to EL1 are routed to EL2
|
||||
HcrReg |= ARM_HCR_TGE;
|
||||
|
||||
ArmWriteHcr (HcrReg);
|
||||
}
|
||||
|
||||
return RETURN_SUCCESS;
|
||||
}
|
392
ArmPkg/Library/ArmExceptionLib/AArch64/ExceptionSupport.S
Normal file
392
ArmPkg/Library/ArmExceptionLib/AArch64/ExceptionSupport.S
Normal file
@ -0,0 +1,392 @@
|
||||
//
|
||||
// Copyright (c) 2011 - 2021, Arm Limited. All rights reserved.<BR>
|
||||
// Portion of Copyright (c) 2014 NVIDIA Corporation. All rights reserved.<BR>
|
||||
// Copyright (c) 2016 HP Development Company, L.P.
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#include <Chipset/AArch64.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <AsmMacroIoLibV8.h>
|
||||
#include <Protocol/DebugSupport.h> // for exception type definitions
|
||||
|
||||
/*
|
||||
This is the stack constructed by the exception handler (low address to high address).
|
||||
X0 to FAR makes up the EFI_SYSTEM_CONTEXT for AArch64.
|
||||
|
||||
UINT64 X0; 0x000
|
||||
UINT64 X1; 0x008
|
||||
UINT64 X2; 0x010
|
||||
UINT64 X3; 0x018
|
||||
UINT64 X4; 0x020
|
||||
UINT64 X5; 0x028
|
||||
UINT64 X6; 0x030
|
||||
UINT64 X7; 0x038
|
||||
UINT64 X8; 0x040
|
||||
UINT64 X9; 0x048
|
||||
UINT64 X10; 0x050
|
||||
UINT64 X11; 0x058
|
||||
UINT64 X12; 0x060
|
||||
UINT64 X13; 0x068
|
||||
UINT64 X14; 0x070
|
||||
UINT64 X15; 0x078
|
||||
UINT64 X16; 0x080
|
||||
UINT64 X17; 0x088
|
||||
UINT64 X18; 0x090
|
||||
UINT64 X19; 0x098
|
||||
UINT64 X20; 0x0a0
|
||||
UINT64 X21; 0x0a8
|
||||
UINT64 X22; 0x0b0
|
||||
UINT64 X23; 0x0b8
|
||||
UINT64 X24; 0x0c0
|
||||
UINT64 X25; 0x0c8
|
||||
UINT64 X26; 0x0d0
|
||||
UINT64 X27; 0x0d8
|
||||
UINT64 X28; 0x0e0
|
||||
UINT64 FP; 0x0e8 // x29 - Frame Pointer
|
||||
UINT64 LR; 0x0f0 // x30 - Link Register
|
||||
UINT64 SP; 0x0f8 // x31 - Stack Pointer
|
||||
|
||||
// FP/SIMD Registers. 128bit if used as Q-regs.
|
||||
UINT64 V0[2]; 0x100
|
||||
UINT64 V1[2]; 0x110
|
||||
UINT64 V2[2]; 0x120
|
||||
UINT64 V3[2]; 0x130
|
||||
UINT64 V4[2]; 0x140
|
||||
UINT64 V5[2]; 0x150
|
||||
UINT64 V6[2]; 0x160
|
||||
UINT64 V7[2]; 0x170
|
||||
UINT64 V8[2]; 0x180
|
||||
UINT64 V9[2]; 0x190
|
||||
UINT64 V10[2]; 0x1a0
|
||||
UINT64 V11[2]; 0x1b0
|
||||
UINT64 V12[2]; 0x1c0
|
||||
UINT64 V13[2]; 0x1d0
|
||||
UINT64 V14[2]; 0x1e0
|
||||
UINT64 V15[2]; 0x1f0
|
||||
UINT64 V16[2]; 0x200
|
||||
UINT64 V17[2]; 0x210
|
||||
UINT64 V18[2]; 0x220
|
||||
UINT64 V19[2]; 0x230
|
||||
UINT64 V20[2]; 0x240
|
||||
UINT64 V21[2]; 0x250
|
||||
UINT64 V22[2]; 0x260
|
||||
UINT64 V23[2]; 0x270
|
||||
UINT64 V24[2]; 0x280
|
||||
UINT64 V25[2]; 0x290
|
||||
UINT64 V26[2]; 0x2a0
|
||||
UINT64 V27[2]; 0x2b0
|
||||
UINT64 V28[2]; 0x2c0
|
||||
UINT64 V29[2]; 0x2d0
|
||||
UINT64 V30[2]; 0x2e0
|
||||
UINT64 V31[2]; 0x2f0
|
||||
|
||||
// System Context
|
||||
UINT64 ELR; 0x300 // Exception Link Register
|
||||
UINT64 SPSR; 0x308 // Saved Processor Status Register
|
||||
UINT64 FPSR; 0x310 // Floating Point Status Register
|
||||
UINT64 ESR; 0x318 // Exception syndrome register
|
||||
UINT64 FAR; 0x320 // Fault Address Register
|
||||
UINT64 Padding;0x328 // Required for stack alignment
|
||||
*/
|
||||
|
||||
GCC_ASM_EXPORT(ExceptionHandlersEnd)
|
||||
GCC_ASM_EXPORT(CommonCExceptionHandler)
|
||||
GCC_ASM_EXPORT(RegisterEl0Stack)
|
||||
|
||||
.text
|
||||
|
||||
#define GP_CONTEXT_SIZE (32 * 8)
|
||||
#define FP_CONTEXT_SIZE (32 * 16)
|
||||
#define SYS_CONTEXT_SIZE ( 6 * 8) // 5 SYS regs + Alignment requirement (ie: the stack must be aligned on 0x10)
|
||||
|
||||
//
|
||||
// There are two methods for installing AArch64 exception vectors:
|
||||
// 1. Install a copy of the vectors to a location specified by a PCD
|
||||
// 2. Write VBAR directly, requiring that vectors have proper alignment (2K)
|
||||
// The conditional below adjusts the alignment requirement based on which
|
||||
// exception vector initialization method is used.
|
||||
//
|
||||
|
||||
#if defined(ARM_RELOCATE_VECTORS)
|
||||
GCC_ASM_EXPORT(ExceptionHandlersStart)
|
||||
ASM_PFX(ExceptionHandlersStart):
|
||||
#else
|
||||
VECTOR_BASE(ExceptionHandlersStart)
|
||||
#endif
|
||||
|
||||
.macro ExceptionEntry, val, sp=SPx
|
||||
//
|
||||
// Our backtrace and register dump code is written in C and so it requires
|
||||
// a stack. This makes it difficult to produce meaningful diagnostics when
|
||||
// the stack pointer has been corrupted. So in such cases (i.e., when taking
|
||||
// synchronous exceptions), this macro is expanded with \sp set to SP0, in
|
||||
// which case we switch to the SP_EL0 stack pointer, which has been
|
||||
// initialized to point to a buffer that has been set aside for this purpose.
|
||||
//
|
||||
// Since 'sp' may no longer refer to the stack frame that was active when
|
||||
// the exception was taken, we may have to switch back and forth between
|
||||
// SP_EL0 and SP_ELx to record the correct value for SP in the context struct.
|
||||
//
|
||||
.ifnc \sp, SPx
|
||||
msr SPsel, xzr
|
||||
.endif
|
||||
|
||||
// Move the stackpointer so we can reach our structure with the str instruction.
|
||||
sub sp, sp, #(FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE)
|
||||
|
||||
// Push the GP registers so we can record the exception context
|
||||
stp x0, x1, [sp, #-GP_CONTEXT_SIZE]!
|
||||
stp x2, x3, [sp, #0x10]
|
||||
stp x4, x5, [sp, #0x20]
|
||||
stp x6, x7, [sp, #0x30]
|
||||
stp x8, x9, [sp, #0x40]
|
||||
stp x10, x11, [sp, #0x50]
|
||||
stp x12, x13, [sp, #0x60]
|
||||
stp x14, x15, [sp, #0x70]
|
||||
stp x16, x17, [sp, #0x80]
|
||||
stp x18, x19, [sp, #0x90]
|
||||
stp x20, x21, [sp, #0xa0]
|
||||
stp x22, x23, [sp, #0xb0]
|
||||
stp x24, x25, [sp, #0xc0]
|
||||
stp x26, x27, [sp, #0xd0]
|
||||
stp x28, x29, [sp, #0xe0]
|
||||
add x28, sp, #(GP_CONTEXT_SIZE + FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE)
|
||||
|
||||
.ifnc \sp, SPx
|
||||
msr SPsel, #1
|
||||
mov x7, sp
|
||||
msr SPsel, xzr
|
||||
.else
|
||||
mov x7, x28
|
||||
.endif
|
||||
|
||||
stp x30, x7, [sp, #0xf0]
|
||||
|
||||
// Record the type of exception that occurred.
|
||||
mov x0, #\val
|
||||
|
||||
// Jump to our general handler to deal with all the common parts and process the exception.
|
||||
#if defined(ARM_RELOCATE_VECTORS)
|
||||
ldr x1, =ASM_PFX(CommonExceptionEntry)
|
||||
br x1
|
||||
.ltorg
|
||||
#else
|
||||
b ASM_PFX(CommonExceptionEntry)
|
||||
#endif
|
||||
.endm
|
||||
|
||||
//
|
||||
// Current EL with SP0 : 0x0 - 0x180
|
||||
//
|
||||
VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SP0_SYNC)
|
||||
ASM_PFX(SynchronousExceptionSP0):
|
||||
ExceptionEntry EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS
|
||||
|
||||
VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SP0_IRQ)
|
||||
ASM_PFX(IrqSP0):
|
||||
ExceptionEntry EXCEPT_AARCH64_IRQ
|
||||
|
||||
VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SP0_FIQ)
|
||||
ASM_PFX(FiqSP0):
|
||||
ExceptionEntry EXCEPT_AARCH64_FIQ
|
||||
|
||||
VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SP0_SERR)
|
||||
ASM_PFX(SErrorSP0):
|
||||
ExceptionEntry EXCEPT_AARCH64_SERROR
|
||||
|
||||
//
|
||||
// Current EL with SPx: 0x200 - 0x380
|
||||
//
|
||||
VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SPX_SYNC)
|
||||
ASM_PFX(SynchronousExceptionSPx):
|
||||
ExceptionEntry EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS, SP0
|
||||
|
||||
VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SPX_IRQ)
|
||||
ASM_PFX(IrqSPx):
|
||||
ExceptionEntry EXCEPT_AARCH64_IRQ
|
||||
|
||||
VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SPX_FIQ)
|
||||
ASM_PFX(FiqSPx):
|
||||
ExceptionEntry EXCEPT_AARCH64_FIQ
|
||||
|
||||
VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_CUR_SPX_SERR)
|
||||
ASM_PFX(SErrorSPx):
|
||||
ExceptionEntry EXCEPT_AARCH64_SERROR
|
||||
|
||||
//
|
||||
// Lower EL using AArch64 : 0x400 - 0x580
|
||||
//
|
||||
VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A64_SYNC)
|
||||
ASM_PFX(SynchronousExceptionA64):
|
||||
ExceptionEntry EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS
|
||||
|
||||
VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A64_IRQ)
|
||||
ASM_PFX(IrqA64):
|
||||
ExceptionEntry EXCEPT_AARCH64_IRQ
|
||||
|
||||
VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A64_FIQ)
|
||||
ASM_PFX(FiqA64):
|
||||
ExceptionEntry EXCEPT_AARCH64_FIQ
|
||||
|
||||
VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A64_SERR)
|
||||
ASM_PFX(SErrorA64):
|
||||
ExceptionEntry EXCEPT_AARCH64_SERROR
|
||||
|
||||
//
|
||||
// Lower EL using AArch32 : 0x600 - 0x780
|
||||
//
|
||||
VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A32_SYNC)
|
||||
ASM_PFX(SynchronousExceptionA32):
|
||||
ExceptionEntry EXCEPT_AARCH64_SYNCHRONOUS_EXCEPTIONS
|
||||
|
||||
VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A32_IRQ)
|
||||
ASM_PFX(IrqA32):
|
||||
ExceptionEntry EXCEPT_AARCH64_IRQ
|
||||
|
||||
VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A32_FIQ)
|
||||
ASM_PFX(FiqA32):
|
||||
ExceptionEntry EXCEPT_AARCH64_FIQ
|
||||
|
||||
VECTOR_ENTRY(ExceptionHandlersStart, ARM_VECTOR_LOW_A32_SERR)
|
||||
ASM_PFX(SErrorA32):
|
||||
ExceptionEntry EXCEPT_AARCH64_SERROR
|
||||
|
||||
VECTOR_END(ExceptionHandlersStart)
|
||||
|
||||
ASM_PFX(ExceptionHandlersEnd):
|
||||
|
||||
|
||||
ASM_PFX(CommonExceptionEntry):
|
||||
|
||||
EL1_OR_EL2_OR_EL3(x1)
|
||||
1:mrs x2, elr_el1 // Exception Link Register
|
||||
mrs x3, spsr_el1 // Saved Processor Status Register 32bit
|
||||
mrs x5, esr_el1 // EL1 Exception syndrome register 32bit
|
||||
mrs x6, far_el1 // EL1 Fault Address Register
|
||||
b 4f
|
||||
|
||||
2:mrs x2, elr_el2 // Exception Link Register
|
||||
mrs x3, spsr_el2 // Saved Processor Status Register 32bit
|
||||
mrs x5, esr_el2 // EL2 Exception syndrome register 32bit
|
||||
mrs x6, far_el2 // EL2 Fault Address Register
|
||||
b 4f
|
||||
|
||||
3:mrs x2, elr_el3 // Exception Link Register
|
||||
mrs x3, spsr_el3 // Saved Processor Status Register 32bit
|
||||
mrs x5, esr_el3 // EL3 Exception syndrome register 32bit
|
||||
mrs x6, far_el3 // EL3 Fault Address Register
|
||||
|
||||
4:mrs x4, fpsr // Floating point Status Register 32bit
|
||||
|
||||
// Save the SYS regs
|
||||
stp x2, x3, [x28, #-SYS_CONTEXT_SIZE]!
|
||||
stp x4, x5, [x28, #0x10]
|
||||
str x6, [x28, #0x20]
|
||||
|
||||
// Push FP regs to Stack.
|
||||
stp q0, q1, [x28, #-FP_CONTEXT_SIZE]!
|
||||
stp q2, q3, [x28, #0x20]
|
||||
stp q4, q5, [x28, #0x40]
|
||||
stp q6, q7, [x28, #0x60]
|
||||
stp q8, q9, [x28, #0x80]
|
||||
stp q10, q11, [x28, #0xa0]
|
||||
stp q12, q13, [x28, #0xc0]
|
||||
stp q14, q15, [x28, #0xe0]
|
||||
stp q16, q17, [x28, #0x100]
|
||||
stp q18, q19, [x28, #0x120]
|
||||
stp q20, q21, [x28, #0x140]
|
||||
stp q22, q23, [x28, #0x160]
|
||||
stp q24, q25, [x28, #0x180]
|
||||
stp q26, q27, [x28, #0x1a0]
|
||||
stp q28, q29, [x28, #0x1c0]
|
||||
stp q30, q31, [x28, #0x1e0]
|
||||
|
||||
// x0 still holds the exception type.
|
||||
// Set x1 to point to the top of our struct on the Stack
|
||||
mov x1, sp
|
||||
|
||||
// CommonCExceptionHandler (
|
||||
// IN EFI_EXCEPTION_TYPE ExceptionType, R0
|
||||
// IN OUT EFI_SYSTEM_CONTEXT SystemContext R1
|
||||
// )
|
||||
|
||||
// Call the handler as defined above
|
||||
|
||||
// For now we spin in the handler if we received an abort of some kind.
|
||||
// We do not try to recover.
|
||||
bl ASM_PFX(CommonCExceptionHandler) // Call exception handler
|
||||
|
||||
// Pop as many GP regs as we can before entering the critical section below
|
||||
ldp x2, x3, [sp, #0x10]
|
||||
ldp x4, x5, [sp, #0x20]
|
||||
ldp x6, x7, [sp, #0x30]
|
||||
ldp x8, x9, [sp, #0x40]
|
||||
ldp x10, x11, [sp, #0x50]
|
||||
ldp x12, x13, [sp, #0x60]
|
||||
ldp x14, x15, [sp, #0x70]
|
||||
ldp x16, x17, [sp, #0x80]
|
||||
ldp x18, x19, [sp, #0x90]
|
||||
ldp x20, x21, [sp, #0xa0]
|
||||
ldp x22, x23, [sp, #0xb0]
|
||||
ldp x24, x25, [sp, #0xc0]
|
||||
ldp x26, x27, [sp, #0xd0]
|
||||
ldp x0, x1, [sp], #0xe0
|
||||
|
||||
// Pop FP regs from Stack.
|
||||
ldp q2, q3, [x28, #0x20]
|
||||
ldp q4, q5, [x28, #0x40]
|
||||
ldp q6, q7, [x28, #0x60]
|
||||
ldp q8, q9, [x28, #0x80]
|
||||
ldp q10, q11, [x28, #0xa0]
|
||||
ldp q12, q13, [x28, #0xc0]
|
||||
ldp q14, q15, [x28, #0xe0]
|
||||
ldp q16, q17, [x28, #0x100]
|
||||
ldp q18, q19, [x28, #0x120]
|
||||
ldp q20, q21, [x28, #0x140]
|
||||
ldp q22, q23, [x28, #0x160]
|
||||
ldp q24, q25, [x28, #0x180]
|
||||
ldp q26, q27, [x28, #0x1a0]
|
||||
ldp q28, q29, [x28, #0x1c0]
|
||||
ldp q30, q31, [x28, #0x1e0]
|
||||
ldp q0, q1, [x28], #FP_CONTEXT_SIZE
|
||||
|
||||
// Pop the SYS regs we need
|
||||
ldp x29, x30, [x28]
|
||||
ldr x28, [x28, #0x10]
|
||||
msr fpsr, x28
|
||||
|
||||
//
|
||||
// Disable interrupt(IRQ and FIQ) before restoring context,
|
||||
// or else the context will be corrupted by interrupt reentrance.
|
||||
// Interrupt mask will be restored from spsr by hardware when we call eret
|
||||
//
|
||||
msr daifset, #3
|
||||
isb
|
||||
|
||||
EL1_OR_EL2_OR_EL3(x28)
|
||||
1:msr elr_el1, x29 // Exception Link Register
|
||||
msr spsr_el1, x30 // Saved Processor Status Register 32bit
|
||||
b 4f
|
||||
2:msr elr_el2, x29 // Exception Link Register
|
||||
msr spsr_el2, x30 // Saved Processor Status Register 32bit
|
||||
b 4f
|
||||
3:msr elr_el3, x29 // Exception Link Register
|
||||
msr spsr_el3, x30 // Saved Processor Status Register 32bit
|
||||
4:
|
||||
|
||||
// pop remaining GP regs and return from exception.
|
||||
ldr x30, [sp, #0xf0 - 0xe0]
|
||||
ldp x28, x29, [sp], #GP_CONTEXT_SIZE - 0xe0
|
||||
|
||||
// Adjust SP to be where we started from when we came into the handler.
|
||||
// The handler can not change the SP.
|
||||
add sp, sp, #FP_CONTEXT_SIZE + SYS_CONTEXT_SIZE
|
||||
|
||||
eret
|
||||
|
||||
ASM_PFX(RegisterEl0Stack):
|
||||
msr sp_el0, x0
|
||||
ret
|
44
ArmPkg/Library/ArmExceptionLib/Arm/ArmException.c
Normal file
44
ArmPkg/Library/ArmExceptionLib/Arm/ArmException.c
Normal file
@ -0,0 +1,44 @@
|
||||
/** @file
|
||||
* Exception handling support specific for ARM
|
||||
*
|
||||
* Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
|
||||
* Copyright (c) 2014 - 2021, Arm Limited. All rights reserved.<BR>
|
||||
* Copyright (c) 2016 HP Development Company, L.P.<BR>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
*
|
||||
**/
|
||||
|
||||
#include <Uefi.h>
|
||||
|
||||
#include <Chipset/ArmV7.h>
|
||||
|
||||
#include <Library/ArmLib.h>
|
||||
|
||||
#include <Protocol/DebugSupport.h> // for MAX_ARM_EXCEPTION
|
||||
|
||||
UINTN gMaxExceptionNumber = MAX_ARM_EXCEPTION;
|
||||
EFI_EXCEPTION_CALLBACK gExceptionHandlers[MAX_ARM_EXCEPTION + 1] = { 0 };
|
||||
EFI_EXCEPTION_CALLBACK gDebuggerExceptionHandlers[MAX_ARM_EXCEPTION + 1] = { 0 };
|
||||
PHYSICAL_ADDRESS gExceptionVectorAlignmentMask = ARM_VECTOR_TABLE_ALIGNMENT;
|
||||
|
||||
// Exception handler contains branch to vector location (jmp $) so no handler
|
||||
// NOTE: This code assumes vectors are ARM and not Thumb code
|
||||
UINTN gDebuggerNoHandlerValue = 0xEAFFFFFE;
|
||||
|
||||
RETURN_STATUS
|
||||
ArchVectorConfig (
|
||||
IN UINTN VectorBaseAddress
|
||||
)
|
||||
{
|
||||
// if the vector address corresponds to high vectors
|
||||
if (VectorBaseAddress == 0xFFFF0000) {
|
||||
// set SCTLR.V to enable high vectors
|
||||
ArmSetHighVectors ();
|
||||
} else {
|
||||
// Set SCTLR.V to 0 to enable VBAR to be used
|
||||
ArmSetLowVectors ();
|
||||
}
|
||||
|
||||
return RETURN_SUCCESS;
|
||||
}
|
299
ArmPkg/Library/ArmExceptionLib/Arm/ExceptionSupport.S
Normal file
299
ArmPkg/Library/ArmExceptionLib/Arm/ExceptionSupport.S
Normal file
@ -0,0 +1,299 @@
|
||||
#------------------------------------------------------------------------------
|
||||
#
|
||||
# Use ARMv6 instruction to operate on a single stack
|
||||
#
|
||||
# Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
|
||||
# Copyright (c) 2014, ARM Limited. All rights reserved.<BR>
|
||||
# Copyright (c) 2016 HP Development Company, L.P.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
#include <Library/PcdLib.h>
|
||||
|
||||
/*
|
||||
|
||||
This is the stack constructed by the exception handler (low address to high address)
|
||||
# R0 - IFAR is EFI_SYSTEM_CONTEXT for ARM
|
||||
Reg Offset
|
||||
=== ======
|
||||
R0 0x00 # stmfd SP!,{R0-R12}
|
||||
R1 0x04
|
||||
R2 0x08
|
||||
R3 0x0c
|
||||
R4 0x10
|
||||
R5 0x14
|
||||
R6 0x18
|
||||
R7 0x1c
|
||||
R8 0x20
|
||||
R9 0x24
|
||||
R10 0x28
|
||||
R11 0x2c
|
||||
R12 0x30
|
||||
SP 0x34 # reserved via subtraction 0x20 (32) from SP
|
||||
LR 0x38
|
||||
PC 0x3c
|
||||
CPSR 0x40
|
||||
DFSR 0x44
|
||||
DFAR 0x48
|
||||
IFSR 0x4c
|
||||
IFAR 0x50
|
||||
|
||||
LR 0x54 # SVC Link register (we need to restore it)
|
||||
|
||||
LR 0x58 # pushed by srsfd
|
||||
CPSR 0x5c
|
||||
|
||||
*/
|
||||
|
||||
|
||||
GCC_ASM_EXPORT(ExceptionHandlersStart)
|
||||
GCC_ASM_EXPORT(ExceptionHandlersEnd)
|
||||
GCC_ASM_EXPORT(CommonExceptionEntry)
|
||||
GCC_ASM_EXPORT(AsmCommonExceptionEntry)
|
||||
GCC_ASM_EXPORT(CommonCExceptionHandler)
|
||||
|
||||
.text
|
||||
.syntax unified
|
||||
#if !defined(__APPLE__)
|
||||
.fpu neon @ makes vpush/vpop assemble
|
||||
#endif
|
||||
.align 5
|
||||
|
||||
|
||||
//
|
||||
// This code gets copied to the ARM vector table
|
||||
// ExceptionHandlersStart - ExceptionHandlersEnd gets copied
|
||||
//
|
||||
ASM_PFX(ExceptionHandlersStart):
|
||||
|
||||
ASM_PFX(Reset):
|
||||
b ASM_PFX(ResetEntry)
|
||||
|
||||
ASM_PFX(UndefinedInstruction):
|
||||
b ASM_PFX(UndefinedInstructionEntry)
|
||||
|
||||
ASM_PFX(SoftwareInterrupt):
|
||||
b ASM_PFX(SoftwareInterruptEntry)
|
||||
|
||||
ASM_PFX(PrefetchAbort):
|
||||
b ASM_PFX(PrefetchAbortEntry)
|
||||
|
||||
ASM_PFX(DataAbort):
|
||||
b ASM_PFX(DataAbortEntry)
|
||||
|
||||
ASM_PFX(ReservedException):
|
||||
b ASM_PFX(ReservedExceptionEntry)
|
||||
|
||||
ASM_PFX(Irq):
|
||||
b ASM_PFX(IrqEntry)
|
||||
|
||||
ASM_PFX(Fiq):
|
||||
b ASM_PFX(FiqEntry)
|
||||
|
||||
ASM_PFX(ResetEntry):
|
||||
srsdb #0x13! @ Store return state on SVC stack
|
||||
@ We are already in SVC mode
|
||||
|
||||
stmfd SP!,{LR} @ Store the link register for the current mode
|
||||
sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
|
||||
stmfd SP!,{R0-R12} @ Store the register state
|
||||
|
||||
mov R0,#0 @ ExceptionType
|
||||
ldr R1,ASM_PFX(CommonExceptionEntry)
|
||||
bx R1
|
||||
|
||||
ASM_PFX(UndefinedInstructionEntry):
|
||||
sub LR, LR, #4 @ Only -2 for Thumb, adjust in CommonExceptionEntry
|
||||
srsdb #0x13! @ Store return state on SVC stack
|
||||
cps #0x13 @ Switch to SVC for common stack
|
||||
stmfd SP!,{LR} @ Store the link register for the current mode
|
||||
sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
|
||||
stmfd SP!,{R0-R12} @ Store the register state
|
||||
|
||||
mov R0,#1 @ ExceptionType
|
||||
ldr R1,ASM_PFX(CommonExceptionEntry)
|
||||
bx R1
|
||||
|
||||
ASM_PFX(SoftwareInterruptEntry):
|
||||
srsdb #0x13! @ Store return state on SVC stack
|
||||
@ We are already in SVC mode
|
||||
stmfd SP!,{LR} @ Store the link register for the current mode
|
||||
sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
|
||||
stmfd SP!,{R0-R12} @ Store the register state
|
||||
|
||||
mov R0,#2 @ ExceptionType
|
||||
ldr R1,ASM_PFX(CommonExceptionEntry)
|
||||
bx R1
|
||||
|
||||
ASM_PFX(PrefetchAbortEntry):
|
||||
sub LR,LR,#4
|
||||
srsdb #0x13! @ Store return state on SVC stack
|
||||
cps #0x13 @ Switch to SVC for common stack
|
||||
stmfd SP!,{LR} @ Store the link register for the current mode
|
||||
sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
|
||||
stmfd SP!,{R0-R12} @ Store the register state
|
||||
|
||||
mov R0,#3 @ ExceptionType
|
||||
ldr R1,ASM_PFX(CommonExceptionEntry)
|
||||
bx R1
|
||||
|
||||
ASM_PFX(DataAbortEntry):
|
||||
sub LR,LR,#8
|
||||
srsdb #0x13! @ Store return state on SVC stack
|
||||
cps #0x13 @ Switch to SVC for common stack
|
||||
stmfd SP!,{LR} @ Store the link register for the current mode
|
||||
sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
|
||||
stmfd SP!,{R0-R12} @ Store the register state
|
||||
|
||||
mov R0,#4
|
||||
ldr R1,ASM_PFX(CommonExceptionEntry)
|
||||
bx R1
|
||||
|
||||
ASM_PFX(ReservedExceptionEntry):
|
||||
srsdb #0x13! @ Store return state on SVC stack
|
||||
cps #0x13 @ Switch to SVC for common stack
|
||||
stmfd SP!,{LR} @ Store the link register for the current mode
|
||||
sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
|
||||
stmfd SP!,{R0-R12} @ Store the register state
|
||||
|
||||
mov R0,#5
|
||||
ldr R1,ASM_PFX(CommonExceptionEntry)
|
||||
bx R1
|
||||
|
||||
ASM_PFX(IrqEntry):
|
||||
sub LR,LR,#4
|
||||
srsdb #0x13! @ Store return state on SVC stack
|
||||
cps #0x13 @ Switch to SVC for common stack
|
||||
stmfd SP!,{LR} @ Store the link register for the current mode
|
||||
sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
|
||||
stmfd SP!,{R0-R12} @ Store the register state
|
||||
|
||||
mov R0,#6 @ ExceptionType
|
||||
ldr R1,ASM_PFX(CommonExceptionEntry)
|
||||
bx R1
|
||||
|
||||
ASM_PFX(FiqEntry):
|
||||
sub LR,LR,#4
|
||||
srsdb #0x13! @ Store return state on SVC stack
|
||||
cps #0x13 @ Switch to SVC for common stack
|
||||
stmfd SP!,{LR} @ Store the link register for the current mode
|
||||
sub SP,SP,#0x20 @ Save space for SP, LR, PC, IFAR - CPSR
|
||||
stmfd SP!,{R0-R12} @ Store the register state
|
||||
@ Since we have already switch to SVC R8_fiq - R12_fiq
|
||||
@ never get used or saved
|
||||
mov R0,#7 @ ExceptionType
|
||||
ldr R1,ASM_PFX(CommonExceptionEntry)
|
||||
bx R1
|
||||
|
||||
//
|
||||
// This gets patched by the C code that patches in the vector table
|
||||
//
|
||||
ASM_PFX(CommonExceptionEntry):
|
||||
.word ASM_PFX(AsmCommonExceptionEntry)
|
||||
|
||||
ASM_PFX(ExceptionHandlersEnd):
|
||||
|
||||
//
|
||||
// This code runs from CpuDxe driver loaded address. It is patched into
|
||||
// CommonExceptionEntry.
|
||||
//
|
||||
ASM_PFX(AsmCommonExceptionEntry):
|
||||
mrc p15, 0, R1, c6, c0, 2 @ Read IFAR
|
||||
str R1, [SP, #0x50] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFAR
|
||||
|
||||
mrc p15, 0, R1, c5, c0, 1 @ Read IFSR
|
||||
str R1, [SP, #0x4c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.IFSR
|
||||
|
||||
mrc p15, 0, R1, c6, c0, 0 @ Read DFAR
|
||||
str R1, [SP, #0x48] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFAR
|
||||
|
||||
mrc p15, 0, R1, c5, c0, 0 @ Read DFSR
|
||||
str R1, [SP, #0x44] @ Store it in EFI_SYSTEM_CONTEXT_ARM.DFSR
|
||||
|
||||
ldr R1, [SP, #0x5c] @ srsdb saved pre-exception CPSR on the stack
|
||||
str R1, [SP, #0x40] @ Store it in EFI_SYSTEM_CONTEXT_ARM.CPSR
|
||||
|
||||
add R2, SP, #0x38 @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
|
||||
and R3, R1, #0x1f @ Check CPSR to see if User or System Mode
|
||||
cmp R3, #0x1f @ if ((CPSR == 0x10) || (CPSR == 0x1f))
|
||||
cmpne R3, #0x10 @
|
||||
stmdaeq R2, {lr}^ @ save unbanked lr
|
||||
@ else
|
||||
stmdane R2, {lr} @ save SVC lr
|
||||
|
||||
|
||||
ldr R5, [SP, #0x58] @ PC is the LR pushed by srsfd
|
||||
@ Check to see if we have to adjust for Thumb entry
|
||||
sub r4, r0, #1 @ if (ExceptionType == 1 || ExceptionType == 2)) {
|
||||
cmp r4, #1 @ // UND & SVC have different LR adjust for Thumb
|
||||
bhi NoAdjustNeeded
|
||||
|
||||
tst r1, #0x20 @ if ((CPSR & T)) == T) { // Thumb Mode on entry
|
||||
addne R5, R5, #2 @ PC += 2;
|
||||
strne R5,[SP,#0x58] @ Update LR value pushed by srsfd
|
||||
|
||||
NoAdjustNeeded:
|
||||
|
||||
str R5, [SP, #0x3c] @ Store it in EFI_SYSTEM_CONTEXT_ARM.PC
|
||||
|
||||
add R1, SP, #0x60 @ We pushed 0x60 bytes on the stack
|
||||
str R1, [SP, #0x34] @ Store it in EFI_SYSTEM_CONTEXT_ARM.SP
|
||||
|
||||
@ R0 is ExceptionType
|
||||
mov R1,SP @ R1 is SystemContext
|
||||
|
||||
#if (FixedPcdGet32(PcdVFPEnabled))
|
||||
vpush {d0-d15} @ save vstm registers in case they are used in optimizations
|
||||
#endif
|
||||
|
||||
mov R4, SP @ Save current SP
|
||||
tst R4, #4
|
||||
subne SP, SP, #4 @ Adjust SP if not 8-byte aligned
|
||||
|
||||
/*
|
||||
VOID
|
||||
EFIAPI
|
||||
CommonCExceptionHandler (
|
||||
IN EFI_EXCEPTION_TYPE ExceptionType, R0
|
||||
IN OUT EFI_SYSTEM_CONTEXT SystemContext R1
|
||||
)
|
||||
|
||||
*/
|
||||
blx ASM_PFX(CommonCExceptionHandler) @ Call exception handler
|
||||
|
||||
mov SP, R4 @ Restore SP
|
||||
|
||||
#if (FixedPcdGet32(PcdVFPEnabled))
|
||||
vpop {d0-d15}
|
||||
#endif
|
||||
|
||||
ldr R1, [SP, #0x4c] @ Restore EFI_SYSTEM_CONTEXT_ARM.IFSR
|
||||
mcr p15, 0, R1, c5, c0, 1 @ Write IFSR
|
||||
|
||||
ldr R1, [SP, #0x44] @ Restore EFI_SYSTEM_CONTEXT_ARM.DFSR
|
||||
mcr p15, 0, R1, c5, c0, 0 @ Write DFSR
|
||||
|
||||
ldr R1,[SP,#0x3c] @ EFI_SYSTEM_CONTEXT_ARM.PC
|
||||
str R1,[SP,#0x58] @ Store it back to srsfd stack slot so it can be restored
|
||||
|
||||
ldr R1,[SP,#0x40] @ EFI_SYSTEM_CONTEXT_ARM.CPSR
|
||||
str R1,[SP,#0x5c] @ Store it back to srsfd stack slot so it can be restored
|
||||
|
||||
add R3, SP, #0x54 @ Make R3 point to SVC LR saved on entry
|
||||
add R2, SP, #0x38 @ Make R2 point to EFI_SYSTEM_CONTEXT_ARM.LR
|
||||
and R1, R1, #0x1f @ Check to see if User or System Mode
|
||||
cmp R1, #0x1f @ if ((CPSR == 0x10) || (CPSR == 0x1f))
|
||||
cmpne R1, #0x10 @
|
||||
ldmibeq R2, {lr}^ @ restore unbanked lr
|
||||
@ else
|
||||
ldmibne R3, {lr} @ restore SVC lr, via ldmfd SP!, {LR}
|
||||
|
||||
ldmfd SP!,{R0-R12} @ Restore general purpose registers
|
||||
@ Exception handler can not change SP
|
||||
|
||||
add SP,SP,#0x20 @ Clear out the remaining stack space
|
||||
ldmfd SP!,{LR} @ restore the link register for this context
|
||||
rfefd SP! @ return from exception via srsfd stack slot
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user