3 * Copyright (c) 2013, ARM Limited. All rights reserved.
5 * This program and the accompanying materials
6 * are licensed and made available under the terms and conditions of the BSD License
7 * which accompanies this distribution. The full text of the license may be found at
8 * http://opensource.org/licenses/bsd-license.php
10 * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 Searches memory descriptors covered by given memory range.
20 This function searches into the Gcd Memory Space for descriptors
21 (from StartIndex to EndIndex) that contains the memory range
22 specified by BaseAddress and Length.
24 @param MemorySpaceMap Gcd Memory Space Map as array.
25 @param NumberOfDescriptors Number of descriptors in map.
26 @param BaseAddress BaseAddress for the requested range.
27 @param Length Length for the requested range.
28 @param StartIndex Start index into the Gcd Memory Space Map.
29 @param EndIndex End index into the Gcd Memory Space Map.
31 @retval EFI_SUCCESS Search successfully.
32 @retval EFI_NOT_FOUND The requested descriptors does not exist.
36 SearchGcdMemorySpaces (
37 IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
,
38 IN UINTN NumberOfDescriptors
,
39 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
41 OUT UINTN
*StartIndex
,
49 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
50 if ((BaseAddress
>= MemorySpaceMap
[Index
].BaseAddress
) &&
51 (BaseAddress
< (MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
))) {
54 if (((BaseAddress
+ Length
- 1) >= MemorySpaceMap
[Index
].BaseAddress
) &&
55 ((BaseAddress
+ Length
- 1) < (MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
))) {
65 Sets the attributes for a specified range in Gcd Memory Space Map.
67 This function sets the attributes for a specified range in
70 @param MemorySpaceMap Gcd Memory Space Map as array
71 @param NumberOfDescriptors Number of descriptors in map
72 @param BaseAddress BaseAddress for the range
73 @param Length Length for the range
74 @param Attributes Attributes to set
76 @retval EFI_SUCCESS Memory attributes set successfully
77 @retval EFI_NOT_FOUND The specified range does not exist in Gcd Memory Space
81 SetGcdMemorySpaceAttributes (
82 IN EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
,
83 IN UINTN NumberOfDescriptors
,
84 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
93 EFI_PHYSICAL_ADDRESS RegionStart
;
96 DEBUG ((DEBUG_GCD
, "SetGcdMemorySpaceAttributes[0x%lX; 0x%lX] = 0x%lX\n",
97 BaseAddress
, BaseAddress
+ Length
, Attributes
));
99 // We do not support a smaller granularity than 4KB on ARM Architecture
100 if ((Length
& EFI_PAGE_MASK
) != 0) {
102 "Warning: We do not support smaller granularity than 4KB on ARM Architecture (passed length: 0x%lX).\n",
107 // Get all memory descriptors covered by the memory range
109 Status
= SearchGcdMemorySpaces (
117 if (EFI_ERROR (Status
)) {
122 // Go through all related descriptors and set attributes accordingly
124 for (Index
= StartIndex
; Index
<= EndIndex
; Index
++) {
125 if (MemorySpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
129 // Calculate the start and end address of the overlapping range
131 if (BaseAddress
>= MemorySpaceMap
[Index
].BaseAddress
) {
132 RegionStart
= BaseAddress
;
134 RegionStart
= MemorySpaceMap
[Index
].BaseAddress
;
136 if ((BaseAddress
+ Length
- 1) < (MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
)) {
137 RegionLength
= BaseAddress
+ Length
- RegionStart
;
139 RegionLength
= MemorySpaceMap
[Index
].BaseAddress
+ MemorySpaceMap
[Index
].Length
- RegionStart
;
142 // Set memory attributes according to MTRR attribute and the original attribute of descriptor
144 gDS
->SetMemorySpaceAttributes (
147 (MemorySpaceMap
[Index
].Attributes
& ~EFI_MEMORY_CACHETYPE_MASK
) | (MemorySpaceMap
[Index
].Capabilities
& Attributes
)
155 This function modifies the attributes for the memory region specified by BaseAddress and
156 Length from their current attributes to the attributes specified by Attributes.
158 @param This The EFI_CPU_ARCH_PROTOCOL instance.
159 @param BaseAddress The physical address that is the start address of a memory region.
160 @param Length The size in bytes of the memory region.
161 @param Attributes The bit mask of attributes to set for the memory region.
163 @retval EFI_SUCCESS The attributes were set for the memory region.
164 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
165 BaseAddress and Length cannot be modified.
166 @retval EFI_INVALID_PARAMETER Length is zero.
167 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
168 the memory resource range.
169 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
170 resource range specified by BaseAddress and Length.
171 The bit mask of attributes is not support for the memory resource
172 range specified by BaseAddress and Length.
177 CpuSetMemoryAttributes (
178 IN EFI_CPU_ARCH_PROTOCOL
*This
,
179 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
184 DEBUG ((EFI_D_PAGE
, "CpuSetMemoryAttributes(%lx, %lx, %lx)\n", BaseAddress
, Length
, Attributes
));
186 if ((BaseAddress
& (SIZE_4KB
- 1)) != 0) {
187 // Minimum granularity is SIZE_4KB (4KB on ARM)
188 DEBUG ((EFI_D_PAGE
, "CpuSetMemoryAttributes(%lx, %lx, %lx): Minimum ganularity is SIZE_4KB\n", BaseAddress
, Length
, Attributes
));
189 return EFI_UNSUPPORTED
;
192 return SetMemoryAttributes (BaseAddress
, Length
, Attributes
, 0);
197 CpuConvertPagesToUncachedVirtualAddress (
198 IN VIRTUAL_UNCACHED_PAGES_PROTOCOL
*This
,
199 IN EFI_PHYSICAL_ADDRESS Address
,
201 IN EFI_PHYSICAL_ADDRESS VirtualMask
,
202 OUT UINT64
*Attributes OPTIONAL
206 EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor
;
208 if (Attributes
!= NULL
) {
209 Status
= gDS
->GetMemorySpaceDescriptor (Address
, &GcdDescriptor
);
210 if (!EFI_ERROR (Status
)) {
211 *Attributes
= GcdDescriptor
.Attributes
;
216 // Make this address range page fault if accessed. If it is a DMA buffer than this would
217 // be the PCI address. Code should always use the CPU address, and we will or in VirtualMask
220 Status
= SetMemoryAttributes (Address
, Length
, EFI_MEMORY_WP
, 0);
221 if (!EFI_ERROR (Status
)) {
222 Status
= SetMemoryAttributes (Address
| VirtualMask
, Length
, EFI_MEMORY_UC
, VirtualMask
);
225 DEBUG ((DEBUG_INFO
| DEBUG_LOAD
, "CpuConvertPagesToUncachedVirtualAddress()\n Unmapped 0x%08lx Mapped 0x%08lx 0x%x bytes\n", Address
, Address
| VirtualMask
, Length
));
234 IN VIRTUAL_UNCACHED_PAGES_PROTOCOL
*This
,
235 IN EFI_PHYSICAL_ADDRESS Address
,
237 IN EFI_PHYSICAL_ADDRESS VirtualMask
,
243 DEBUG ((DEBUG_INFO
| DEBUG_LOAD
, "CpuReconvertPages(%lx, %x, %lx, %lx)\n", Address
, Length
, VirtualMask
, Attributes
));
246 // Unmap the aliased Address
248 Status
= SetMemoryAttributes (Address
| VirtualMask
, Length
, EFI_MEMORY_WP
, 0);
249 if (!EFI_ERROR (Status
)) {
251 // Restore atttributes
253 Status
= SetMemoryAttributes (Address
, Length
, Attributes
, 0);
260 VIRTUAL_UNCACHED_PAGES_PROTOCOL gVirtualUncachedPages
= {
261 CpuConvertPagesToUncachedVirtualAddress
,