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