]> git.proxmox.com Git - mirror_edk2.git/blob - StandaloneMmPkg/Library/StandaloneMmMemLib/StandaloneMmMemLib.c
2737f95315eb6f39e9fc06668812f1e7be406a23
[mirror_edk2.git] / StandaloneMmPkg / Library / StandaloneMmMemLib / StandaloneMmMemLib.c
1 /** @file
2 Instance of MM memory check library.
3
4 MM memory check library library implementation. This library consumes MM_ACCESS_PROTOCOL
5 to get MMRAM information. In order to use this library instance, the platform should produce
6 all MMRAM range via MM_ACCESS_PROTOCOL, including the range for firmware (like MM Core
7 and MM driver) and/or specific dedicated hardware.
8
9 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
10 Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.<BR>
11
12 SPDX-License-Identifier: BSD-2-Clause-Patent
13
14 **/
15
16
17 #include <PiMm.h>
18
19 #include <Library/BaseLib.h>
20 #include <Library/BaseMemoryLib.h>
21 #include <Library/DebugLib.h>
22
23 EFI_MMRAM_DESCRIPTOR *mMmMemLibInternalMmramRanges;
24 UINTN mMmMemLibInternalMmramCount;
25
26 //
27 // Maximum support address used to check input buffer
28 //
29 EFI_PHYSICAL_ADDRESS mMmMemLibInternalMaximumSupportAddress = 0;
30
31 /**
32 Calculate and save the maximum support address.
33
34 **/
35 VOID
36 MmMemLibInternalCalculateMaximumSupportAddress (
37 VOID
38 );
39
40 /**
41 Initialize cached Mmram Ranges from HOB.
42
43 @retval EFI_UNSUPPORTED The routine is unable to extract MMRAM information.
44 @retval EFI_SUCCESS MmRanges are populated successfully.
45
46 **/
47 EFI_STATUS
48 MmMemLibInternalPopulateMmramRanges (
49 VOID
50 );
51
52 /**
53 Deinitialize cached Mmram Ranges.
54
55 **/
56 VOID
57 MmMemLibInternalFreeMmramRanges (
58 VOID
59 );
60
61 /**
62 This function check if the buffer is valid per processor architecture and not overlap with MMRAM.
63
64 @param Buffer The buffer start address to be checked.
65 @param Length The buffer length to be checked.
66
67 @retval TRUE This buffer is valid per processor architecture and not overlap with MMRAM.
68 @retval FALSE This buffer is not valid per processor architecture or overlap with MMRAM.
69 **/
70 BOOLEAN
71 EFIAPI
72 MmIsBufferOutsideMmValid (
73 IN EFI_PHYSICAL_ADDRESS Buffer,
74 IN UINT64 Length
75 )
76 {
77 UINTN Index;
78
79 //
80 // Check override.
81 // NOTE: (B:0->L:4G) is invalid for IA32, but (B:1->L:4G-1)/(B:4G-1->L:1) is valid.
82 //
83 if ((Length > mMmMemLibInternalMaximumSupportAddress) ||
84 (Buffer > mMmMemLibInternalMaximumSupportAddress) ||
85 ((Length != 0) && (Buffer > (mMmMemLibInternalMaximumSupportAddress - (Length - 1)))) ) {
86 //
87 // Overflow happen
88 //
89 DEBUG ((
90 DEBUG_ERROR,
91 "MmIsBufferOutsideMmValid: Overflow: Buffer (0x%lx) - Length (0x%lx), MaximumSupportAddress (0x%lx)\n",
92 Buffer,
93 Length,
94 mMmMemLibInternalMaximumSupportAddress
95 ));
96 return FALSE;
97 }
98
99 for (Index = 0; Index < mMmMemLibInternalMmramCount; Index ++) {
100 if (((Buffer >= mMmMemLibInternalMmramRanges[Index].CpuStart) &&
101 (Buffer < mMmMemLibInternalMmramRanges[Index].CpuStart + mMmMemLibInternalMmramRanges[Index].PhysicalSize)) ||
102 ((mMmMemLibInternalMmramRanges[Index].CpuStart >= Buffer) &&
103 (mMmMemLibInternalMmramRanges[Index].CpuStart < Buffer + Length))) {
104 DEBUG ((
105 DEBUG_ERROR,
106 "MmIsBufferOutsideMmValid: Overlap: Buffer (0x%lx) - Length (0x%lx), ",
107 Buffer,
108 Length
109 ));
110 DEBUG ((
111 DEBUG_ERROR,
112 "CpuStart (0x%lx) - PhysicalSize (0x%lx)\n",
113 mMmMemLibInternalMmramRanges[Index].CpuStart,
114 mMmMemLibInternalMmramRanges[Index].PhysicalSize
115 ));
116 return FALSE;
117 }
118 }
119
120 return TRUE;
121 }
122
123 /**
124 Copies a source buffer (non-MMRAM) to a destination buffer (MMRAM).
125
126 This function copies a source buffer (non-MMRAM) to a destination buffer (MMRAM).
127 It checks if source buffer is valid per processor architecture and not overlap with MMRAM.
128 If the check passes, it copies memory and returns EFI_SUCCESS.
129 If the check fails, it return EFI_SECURITY_VIOLATION.
130 The implementation must be reentrant.
131
132 @param DestinationBuffer The pointer to the destination buffer of the memory copy.
133 @param SourceBuffer The pointer to the source buffer of the memory copy.
134 @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer.
135
136 @retval EFI_SECURITY_VIOLATION The SourceBuffer is invalid per processor architecture or overlap with MMRAM.
137 @retval EFI_SUCCESS Memory is copied.
138
139 **/
140 EFI_STATUS
141 EFIAPI
142 MmCopyMemToMmram (
143 OUT VOID *DestinationBuffer,
144 IN CONST VOID *SourceBuffer,
145 IN UINTN Length
146 )
147 {
148 if (!MmIsBufferOutsideMmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)SourceBuffer, Length)) {
149 DEBUG ((DEBUG_ERROR, "MmCopyMemToMmram: Security Violation: Source (0x%x), Length (0x%x)\n", SourceBuffer, Length));
150 return EFI_SECURITY_VIOLATION;
151 }
152 CopyMem (DestinationBuffer, SourceBuffer, Length);
153 return EFI_SUCCESS;
154 }
155
156 /**
157 Copies a source buffer (MMRAM) to a destination buffer (NON-MMRAM).
158
159 This function copies a source buffer (non-MMRAM) to a destination buffer (MMRAM).
160 It checks if destination buffer is valid per processor architecture and not overlap with MMRAM.
161 If the check passes, it copies memory and returns EFI_SUCCESS.
162 If the check fails, it returns EFI_SECURITY_VIOLATION.
163 The implementation must be reentrant.
164
165 @param DestinationBuffer The pointer to the destination buffer of the memory copy.
166 @param SourceBuffer The pointer to the source buffer of the memory copy.
167 @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer.
168
169 @retval EFI_SECURITY_VIOLATION The DestinationBuffer is invalid per processor architecture or overlap with MMRAM.
170 @retval EFI_SUCCESS Memory is copied.
171
172 **/
173 EFI_STATUS
174 EFIAPI
175 MmCopyMemFromMmram (
176 OUT VOID *DestinationBuffer,
177 IN CONST VOID *SourceBuffer,
178 IN UINTN Length
179 )
180 {
181 if (!MmIsBufferOutsideMmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)DestinationBuffer, Length)) {
182 DEBUG ((DEBUG_ERROR, "MmCopyMemFromMmram: Security Violation: Destination (0x%x), Length (0x%x)\n",
183 DestinationBuffer, Length));
184 return EFI_SECURITY_VIOLATION;
185 }
186 CopyMem (DestinationBuffer, SourceBuffer, Length);
187 return EFI_SUCCESS;
188 }
189
190 /**
191 Copies a source buffer (NON-MMRAM) to a destination buffer (NON-MMRAM).
192
193 This function copies a source buffer (non-MMRAM) to a destination buffer (MMRAM).
194 It checks if source buffer and destination buffer are valid per processor architecture and not overlap with MMRAM.
195 If the check passes, it copies memory and returns EFI_SUCCESS.
196 If the check fails, it returns EFI_SECURITY_VIOLATION.
197 The implementation must be reentrant, and it must handle the case where source buffer overlaps destination buffer.
198
199 @param DestinationBuffer The pointer to the destination buffer of the memory copy.
200 @param SourceBuffer The pointer to the source buffer of the memory copy.
201 @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer.
202
203 @retval EFI_SECURITY_VIOLATION The DestinationBuffer is invalid per processor architecture or overlap with MMRAM.
204 @retval EFI_SECURITY_VIOLATION The SourceBuffer is invalid per processor architecture or overlap with MMRAM.
205 @retval EFI_SUCCESS Memory is copied.
206
207 **/
208 EFI_STATUS
209 EFIAPI
210 MmCopyMem (
211 OUT VOID *DestinationBuffer,
212 IN CONST VOID *SourceBuffer,
213 IN UINTN Length
214 )
215 {
216 if (!MmIsBufferOutsideMmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)DestinationBuffer, Length)) {
217 DEBUG ((DEBUG_ERROR, "MmCopyMem: Security Violation: Destination (0x%x), Length (0x%x)\n",
218 DestinationBuffer, Length));
219 return EFI_SECURITY_VIOLATION;
220 }
221 if (!MmIsBufferOutsideMmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)SourceBuffer, Length)) {
222 DEBUG ((DEBUG_ERROR, "MmCopyMem: Security Violation: Source (0x%x), Length (0x%x)\n", SourceBuffer, Length));
223 return EFI_SECURITY_VIOLATION;
224 }
225 CopyMem (DestinationBuffer, SourceBuffer, Length);
226 return EFI_SUCCESS;
227 }
228
229 /**
230 Fills a target buffer (NON-MMRAM) with a byte value.
231
232 This function fills a target buffer (non-MMRAM) with a byte value.
233 It checks if target buffer is valid per processor architecture and not overlap with MMRAM.
234 If the check passes, it fills memory and returns EFI_SUCCESS.
235 If the check fails, it returns EFI_SECURITY_VIOLATION.
236
237 @param Buffer The memory to set.
238 @param Length The number of bytes to set.
239 @param Value The value with which to fill Length bytes of Buffer.
240
241 @retval EFI_SECURITY_VIOLATION The Buffer is invalid per processor architecture or overlap with MMRAM.
242 @retval EFI_SUCCESS Memory is set.
243
244 **/
245 EFI_STATUS
246 EFIAPI
247 MmSetMem (
248 OUT VOID *Buffer,
249 IN UINTN Length,
250 IN UINT8 Value
251 )
252 {
253 if (!MmIsBufferOutsideMmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, Length)) {
254 DEBUG ((DEBUG_ERROR, "MmSetMem: Security Violation: Source (0x%x), Length (0x%x)\n", Buffer, Length));
255 return EFI_SECURITY_VIOLATION;
256 }
257 SetMem (Buffer, Length, Value);
258 return EFI_SUCCESS;
259 }
260
261 /**
262 The constructor function initializes the Mm Mem library
263
264 @param [in] ImageHandle The firmware allocated handle for the EFI image.
265 @param [in] MmSystemTable A pointer to the EFI System Table.
266
267 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
268
269 **/
270 EFI_STATUS
271 EFIAPI
272 MemLibConstructor (
273 IN EFI_HANDLE ImageHandle,
274 IN EFI_MM_SYSTEM_TABLE *MmSystemTable
275 )
276 {
277 EFI_STATUS Status;
278
279 //
280 // Calculate and save maximum support address
281 //
282 MmMemLibInternalCalculateMaximumSupportAddress ();
283
284 //
285 // Initialize cached Mmram Ranges from HOB.
286 //
287 Status = MmMemLibInternalPopulateMmramRanges ();
288
289 return Status;
290 }
291
292 /**
293 Destructor for Mm Mem library.
294
295 @param ImageHandle The image handle of the process.
296 @param MmSystemTable The EFI System Table pointer.
297
298 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
299
300 **/
301 EFI_STATUS
302 EFIAPI
303 MemLibDestructor (
304 IN EFI_HANDLE ImageHandle,
305 IN EFI_MM_SYSTEM_TABLE *MmSystemTable
306 )
307 {
308
309 //
310 // Deinitialize cached Mmram Ranges.
311 //
312 MmMemLibInternalFreeMmramRanges ();
313
314 return EFI_SUCCESS;
315 }