]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPkg/Library/StandaloneMmMmuLib/AArch64/ArmMmuStandaloneMmLib.c
3095d7125dfe3bc1d331cf84f5ddc4b38ac70ee9
[mirror_edk2.git] / ArmPkg / Library / StandaloneMmMmuLib / AArch64 / ArmMmuStandaloneMmLib.c
1 /** @file
2 * File managing the MMU for ARMv8 architecture in S-EL0
3 *
4 * Copyright (c) 2017 - 2018, ARM Limited. All rights reserved.
5 *
6 * This program and the accompanying materials
7 * are licensed and made available under the terms and conditions of the BSD License
8 * which accompanies this distribution. The full text of the license may be found at
9 * http://opensource.org/licenses/bsd-license.php
10 *
11 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 *
14 **/
15
16 #include <Uefi.h>
17 #include <IndustryStandard/ArmMmSvc.h>
18
19 #include <Library/ArmLib.h>
20 #include <Library/ArmMmuLib.h>
21 #include <Library/ArmSvcLib.h>
22 #include <Library/BaseLib.h>
23 #include <Library/DebugLib.h>
24
25 STATIC
26 EFI_STATUS
27 GetMemoryPermissions (
28 IN EFI_PHYSICAL_ADDRESS BaseAddress,
29 OUT UINT32 *MemoryAttributes
30 )
31 {
32 ARM_SVC_ARGS GetMemoryPermissionsSvcArgs = {0};
33
34 GetMemoryPermissionsSvcArgs.Arg0 = ARM_SVC_ID_SP_GET_MEM_ATTRIBUTES_AARCH64;
35 GetMemoryPermissionsSvcArgs.Arg1 = BaseAddress;
36 GetMemoryPermissionsSvcArgs.Arg2 = 0;
37 GetMemoryPermissionsSvcArgs.Arg3 = 0;
38
39 ArmCallSvc (&GetMemoryPermissionsSvcArgs);
40 if (GetMemoryPermissionsSvcArgs.Arg0 == ARM_SVC_SPM_RET_INVALID_PARAMS) {
41 *MemoryAttributes = 0;
42 return EFI_INVALID_PARAMETER;
43 }
44
45 *MemoryAttributes = GetMemoryPermissionsSvcArgs.Arg0;
46 return EFI_SUCCESS;
47 }
48
49 STATIC
50 EFI_STATUS
51 RequestMemoryPermissionChange (
52 IN EFI_PHYSICAL_ADDRESS BaseAddress,
53 IN UINT64 Length,
54 IN UINTN Permissions
55 )
56 {
57 EFI_STATUS Status;
58 ARM_SVC_ARGS ChangeMemoryPermissionsSvcArgs = {0};
59
60 ChangeMemoryPermissionsSvcArgs.Arg0 = ARM_SVC_ID_SP_SET_MEM_ATTRIBUTES_AARCH64;
61 ChangeMemoryPermissionsSvcArgs.Arg1 = BaseAddress;
62 ChangeMemoryPermissionsSvcArgs.Arg2 = EFI_SIZE_TO_PAGES(Length);
63 ChangeMemoryPermissionsSvcArgs.Arg3 = Permissions;
64
65 ArmCallSvc (&ChangeMemoryPermissionsSvcArgs);
66
67 Status = ChangeMemoryPermissionsSvcArgs.Arg0;
68
69 switch (Status) {
70 case ARM_SVC_SPM_RET_SUCCESS:
71 Status = EFI_SUCCESS;
72 break;
73
74 case ARM_SVC_SPM_RET_NOT_SUPPORTED:
75 Status = EFI_UNSUPPORTED;
76 break;
77
78 case ARM_SVC_SPM_RET_INVALID_PARAMS:
79 Status = EFI_INVALID_PARAMETER;
80 break;
81
82 case ARM_SVC_SPM_RET_DENIED:
83 Status = EFI_ACCESS_DENIED;
84 break;
85
86 case ARM_SVC_SPM_RET_NO_MEMORY:
87 Status = EFI_BAD_BUFFER_SIZE;
88 break;
89
90 default:
91 Status = EFI_ACCESS_DENIED;
92 ASSERT (0);
93 }
94
95 return Status;
96 }
97
98 EFI_STATUS
99 ArmSetMemoryRegionNoExec (
100 IN EFI_PHYSICAL_ADDRESS BaseAddress,
101 IN UINT64 Length
102 )
103 {
104 EFI_STATUS Status;
105 UINT32 MemoryAttributes;
106 UINT32 CodePermission;
107
108 Status = GetMemoryPermissions (BaseAddress, &MemoryAttributes);
109 if (Status != EFI_INVALID_PARAMETER) {
110 CodePermission = SET_MEM_ATTR_CODE_PERM_XN << SET_MEM_ATTR_CODE_PERM_SHIFT;
111 return RequestMemoryPermissionChange (
112 BaseAddress,
113 Length,
114 MemoryAttributes | CodePermission
115 );
116 }
117 return EFI_INVALID_PARAMETER;
118 }
119
120 EFI_STATUS
121 ArmClearMemoryRegionNoExec (
122 IN EFI_PHYSICAL_ADDRESS BaseAddress,
123 IN UINT64 Length
124 )
125 {
126 EFI_STATUS Status;
127 UINT32 MemoryAttributes;
128 UINT32 CodePermission;
129
130 Status = GetMemoryPermissions (BaseAddress, &MemoryAttributes);
131 if (Status != EFI_INVALID_PARAMETER) {
132 CodePermission = SET_MEM_ATTR_CODE_PERM_XN << SET_MEM_ATTR_CODE_PERM_SHIFT;
133 return RequestMemoryPermissionChange (
134 BaseAddress,
135 Length,
136 MemoryAttributes & ~CodePermission
137 );
138 }
139 return EFI_INVALID_PARAMETER;
140 }
141
142 EFI_STATUS
143 ArmSetMemoryRegionReadOnly (
144 IN EFI_PHYSICAL_ADDRESS BaseAddress,
145 IN UINT64 Length
146 )
147 {
148 EFI_STATUS Status;
149 UINT32 MemoryAttributes;
150 UINT32 DataPermission;
151
152 Status = GetMemoryPermissions (BaseAddress, &MemoryAttributes);
153 if (Status != EFI_INVALID_PARAMETER) {
154 DataPermission = SET_MEM_ATTR_DATA_PERM_RO << SET_MEM_ATTR_DATA_PERM_SHIFT;
155 return RequestMemoryPermissionChange (
156 BaseAddress,
157 Length,
158 MemoryAttributes | DataPermission
159 );
160 }
161 return EFI_INVALID_PARAMETER;
162 }
163
164 EFI_STATUS
165 ArmClearMemoryRegionReadOnly (
166 IN EFI_PHYSICAL_ADDRESS BaseAddress,
167 IN UINT64 Length
168 )
169 {
170 EFI_STATUS Status;
171 UINT32 MemoryAttributes;
172 UINT32 PermissionRequest;
173
174 Status = GetMemoryPermissions (BaseAddress, &MemoryAttributes);
175 if (Status != EFI_INVALID_PARAMETER) {
176 PermissionRequest = SET_MEM_ATTR_MAKE_PERM_REQUEST (SET_MEM_ATTR_DATA_PERM_RW,
177 MemoryAttributes);
178 return RequestMemoryPermissionChange (
179 BaseAddress,
180 Length,
181 PermissionRequest
182 );
183 }
184 return EFI_INVALID_PARAMETER;
185 }