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