diff --git a/ArmPkg/ArmPkg.dec b/ArmPkg/ArmPkg.dec index 0db7aa9d30..d99eb6769f 100644 --- a/ArmPkg/ArmPkg.dec +++ b/ArmPkg/ArmPkg.dec @@ -42,6 +42,7 @@ ArmMtlLib|ArmPlatformPkg/Include/Library/ArmMtlLib.h ArmSvcLib|Include/Library/ArmSvcLib.h OpteeLib|Include/Library/OpteeLib.h + StandaloneMmMmuLib|Include/Library/StandaloneMmMmuLib.h [Guids.common] gArmTokenSpaceGuid = { 0xBB11ECFE, 0x820F, 0x4968, { 0xBB, 0xA6, 0xF7, 0x6A, 0xFE, 0x30, 0x25, 0x96 } } diff --git a/ArmPkg/ArmPkg.dsc b/ArmPkg/ArmPkg.dsc index 810caaff62..acf679651d 100644 --- a/ArmPkg/ArmPkg.dsc +++ b/ArmPkg/ArmPkg.dsc @@ -117,6 +117,7 @@ ArmPkg/Library/ArmPsciResetSystemLib/ArmPsciResetSystemLib.inf ArmPkg/Library/ArmExceptionLib/ArmExceptionLib.inf ArmPkg/Library/ArmExceptionLib/ArmRelocateExceptionLib.inf + ArmPkg/Library/StandaloneMmMmuLib/ArmMmuStandaloneMmLib.inf ArmPkg/Drivers/CpuDxe/CpuDxe.inf ArmPkg/Drivers/CpuPei/CpuPei.inf diff --git a/ArmPkg/Include/Library/StandaloneMmMmuLib.h b/ArmPkg/Include/Library/StandaloneMmMmuLib.h new file mode 100644 index 0000000000..1f7653d004 --- /dev/null +++ b/ArmPkg/Include/Library/StandaloneMmMmuLib.h @@ -0,0 +1,42 @@ +/** @file + + Copyright (c) 2018, ARM Ltd. All rights reserved. + + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +**/ + +#ifndef __STANDALONEMM_MMU_LIB__ +#define __STANDALONEMM_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 /* __STANDALONEMM_MMU_LIB__ */ diff --git a/ArmPkg/Library/StandaloneMmMmuLib/Aarch64/ArmMmuStandaloneMmLib.c b/ArmPkg/Library/StandaloneMmMmuLib/Aarch64/ArmMmuStandaloneMmLib.c new file mode 100644 index 0000000000..3095d7125d --- /dev/null +++ b/ArmPkg/Library/StandaloneMmMmuLib/Aarch64/ArmMmuStandaloneMmLib.c @@ -0,0 +1,185 @@ +/** @file +* File managing the MMU for ARMv8 architecture in S-EL0 +* +* Copyright (c) 2017 - 2018, ARM Limited. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#include +#include + +#include +#include +#include +#include +#include + +STATIC +EFI_STATUS +GetMemoryPermissions ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + OUT UINT32 *MemoryAttributes + ) +{ + ARM_SVC_ARGS GetMemoryPermissionsSvcArgs = {0}; + + GetMemoryPermissionsSvcArgs.Arg0 = ARM_SVC_ID_SP_GET_MEM_ATTRIBUTES_AARCH64; + GetMemoryPermissionsSvcArgs.Arg1 = BaseAddress; + GetMemoryPermissionsSvcArgs.Arg2 = 0; + GetMemoryPermissionsSvcArgs.Arg3 = 0; + + ArmCallSvc (&GetMemoryPermissionsSvcArgs); + if (GetMemoryPermissionsSvcArgs.Arg0 == ARM_SVC_SPM_RET_INVALID_PARAMS) { + *MemoryAttributes = 0; + return EFI_INVALID_PARAMETER; + } + + *MemoryAttributes = GetMemoryPermissionsSvcArgs.Arg0; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +RequestMemoryPermissionChange ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINTN Permissions + ) +{ + EFI_STATUS Status; + ARM_SVC_ARGS ChangeMemoryPermissionsSvcArgs = {0}; + + ChangeMemoryPermissionsSvcArgs.Arg0 = ARM_SVC_ID_SP_SET_MEM_ATTRIBUTES_AARCH64; + ChangeMemoryPermissionsSvcArgs.Arg1 = BaseAddress; + ChangeMemoryPermissionsSvcArgs.Arg2 = EFI_SIZE_TO_PAGES(Length); + ChangeMemoryPermissionsSvcArgs.Arg3 = Permissions; + + ArmCallSvc (&ChangeMemoryPermissionsSvcArgs); + + Status = ChangeMemoryPermissionsSvcArgs.Arg0; + + switch (Status) { + case ARM_SVC_SPM_RET_SUCCESS: + Status = EFI_SUCCESS; + break; + + case ARM_SVC_SPM_RET_NOT_SUPPORTED: + Status = EFI_UNSUPPORTED; + break; + + case ARM_SVC_SPM_RET_INVALID_PARAMS: + Status = EFI_INVALID_PARAMETER; + break; + + case ARM_SVC_SPM_RET_DENIED: + Status = EFI_ACCESS_DENIED; + break; + + case ARM_SVC_SPM_RET_NO_MEMORY: + Status = EFI_BAD_BUFFER_SIZE; + break; + + default: + Status = EFI_ACCESS_DENIED; + ASSERT (0); + } + + return Status; +} + +EFI_STATUS +ArmSetMemoryRegionNoExec ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + EFI_STATUS Status; + UINT32 MemoryAttributes; + UINT32 CodePermission; + + Status = GetMemoryPermissions (BaseAddress, &MemoryAttributes); + if (Status != EFI_INVALID_PARAMETER) { + CodePermission = SET_MEM_ATTR_CODE_PERM_XN << SET_MEM_ATTR_CODE_PERM_SHIFT; + return RequestMemoryPermissionChange ( + BaseAddress, + Length, + MemoryAttributes | CodePermission + ); + } + return EFI_INVALID_PARAMETER; +} + +EFI_STATUS +ArmClearMemoryRegionNoExec ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + EFI_STATUS Status; + UINT32 MemoryAttributes; + UINT32 CodePermission; + + Status = GetMemoryPermissions (BaseAddress, &MemoryAttributes); + if (Status != EFI_INVALID_PARAMETER) { + CodePermission = SET_MEM_ATTR_CODE_PERM_XN << SET_MEM_ATTR_CODE_PERM_SHIFT; + return RequestMemoryPermissionChange ( + BaseAddress, + Length, + MemoryAttributes & ~CodePermission + ); + } + return EFI_INVALID_PARAMETER; +} + +EFI_STATUS +ArmSetMemoryRegionReadOnly ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + EFI_STATUS Status; + UINT32 MemoryAttributes; + UINT32 DataPermission; + + Status = GetMemoryPermissions (BaseAddress, &MemoryAttributes); + if (Status != EFI_INVALID_PARAMETER) { + DataPermission = SET_MEM_ATTR_DATA_PERM_RO << SET_MEM_ATTR_DATA_PERM_SHIFT; + return RequestMemoryPermissionChange ( + BaseAddress, + Length, + MemoryAttributes | DataPermission + ); + } + return EFI_INVALID_PARAMETER; +} + +EFI_STATUS +ArmClearMemoryRegionReadOnly ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + EFI_STATUS Status; + UINT32 MemoryAttributes; + UINT32 PermissionRequest; + + Status = GetMemoryPermissions (BaseAddress, &MemoryAttributes); + if (Status != EFI_INVALID_PARAMETER) { + PermissionRequest = SET_MEM_ATTR_MAKE_PERM_REQUEST (SET_MEM_ATTR_DATA_PERM_RW, + MemoryAttributes); + return RequestMemoryPermissionChange ( + BaseAddress, + Length, + PermissionRequest + ); + } + return EFI_INVALID_PARAMETER; +} diff --git a/ArmPkg/Library/StandaloneMmMmuLib/ArmMmuStandaloneMmLib.inf b/ArmPkg/Library/StandaloneMmMmuLib/ArmMmuStandaloneMmLib.inf new file mode 100644 index 0000000000..d589b23603 --- /dev/null +++ b/ArmPkg/Library/StandaloneMmMmuLib/ArmMmuStandaloneMmLib.inf @@ -0,0 +1,36 @@ +#/** @file +# +# Copyright (c) 2017 - 2018, ARM Limited. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# +#**/ + +[Defines] + INF_VERSION = 0x0001001A + BASE_NAME = ArmMmuStandaloneMmCoreLib + FILE_GUID = da8f0232-fb14-42f0-922c-63104d2c70bd + MODULE_TYPE = MM_CORE_STANDALONE + VERSION_STRING = 1.0 + LIBRARY_CLASS = StandaloneMmMmuLib + PI_SPECIFICATION_VERSION = 0x00010032 + +[Sources.AARCH64] + Aarch64/ArmMmuStandaloneMmLib.c + +[Packages] + ArmPkg/ArmPkg.dec + MdePkg/MdePkg.dec + +[LibraryClasses] + ArmLib + CacheMaintenanceLib + MemoryAllocationLib + +