StandaloneMmPkg/MemLib: Add Standalone MM instance of memory check library.
[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
10 Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>\r
11\r
12 This program and the accompanying materials\r
13 are licensed and made available under the terms and conditions of the BSD License\r
14 which accompanies this distribution. The full text of the license may be found at\r
15 http://opensource.org/licenses/bsd-license.php\r
16\r
17 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
18 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
19\r
20**/\r
21\r
22\r
23#include <PiMm.h>\r
24\r
25#include <Library/BaseLib.h>\r
26#include <Library/BaseMemoryLib.h>\r
27#include <Library/DebugLib.h>\r
28\r
29EFI_MMRAM_DESCRIPTOR *mMmMemLibInternalMmramRanges;\r
30UINTN mMmMemLibInternalMmramCount;\r
31\r
32//\r
33// Maximum support address used to check input buffer\r
34//\r
35EFI_PHYSICAL_ADDRESS mMmMemLibInternalMaximumSupportAddress = 0;\r
36\r
37/**\r
38 Calculate and save the maximum support address.\r
39\r
40**/\r
41VOID\r
42MmMemLibInternalCalculateMaximumSupportAddress (\r
43 VOID\r
44 );\r
45\r
46/**\r
47 This function check if the buffer is valid per processor architecture and not overlap with MMRAM.\r
48\r
49 @param Buffer The buffer start address to be checked.\r
50 @param Length The buffer length to be checked.\r
51\r
52 @retval TRUE This buffer is valid per processor architecture and not overlap with MMRAM.\r
53 @retval FALSE This buffer is not valid per processor architecture or overlap with MMRAM.\r
54**/\r
55BOOLEAN\r
56EFIAPI\r
57MmIsBufferOutsideMmValid (\r
58 IN EFI_PHYSICAL_ADDRESS Buffer,\r
59 IN UINT64 Length\r
60 )\r
61{\r
62 UINTN Index;\r
63\r
64 //\r
65 // Check override.\r
66 // NOTE: (B:0->L:4G) is invalid for IA32, but (B:1->L:4G-1)/(B:4G-1->L:1) is valid.\r
67 //\r
68 if ((Length > mMmMemLibInternalMaximumSupportAddress) ||\r
69 (Buffer > mMmMemLibInternalMaximumSupportAddress) ||\r
70 ((Length != 0) && (Buffer > (mMmMemLibInternalMaximumSupportAddress - (Length - 1)))) ) {\r
71 //\r
72 // Overflow happen\r
73 //\r
74 DEBUG ((\r
75 DEBUG_ERROR,\r
76 "MmIsBufferOutsideMmValid: Overflow: Buffer (0x%lx) - Length (0x%lx), MaximumSupportAddress (0x%lx)\n",\r
77 Buffer,\r
78 Length,\r
79 mMmMemLibInternalMaximumSupportAddress\r
80 ));\r
81 return FALSE;\r
82 }\r
83\r
84 for (Index = 0; Index < mMmMemLibInternalMmramCount; Index ++) {\r
85 if (((Buffer >= mMmMemLibInternalMmramRanges[Index].CpuStart) &&\r
86 (Buffer < mMmMemLibInternalMmramRanges[Index].CpuStart + mMmMemLibInternalMmramRanges[Index].PhysicalSize)) ||\r
87 ((mMmMemLibInternalMmramRanges[Index].CpuStart >= Buffer) &&\r
88 (mMmMemLibInternalMmramRanges[Index].CpuStart < Buffer + Length))) {\r
89 DEBUG ((\r
90 DEBUG_ERROR,\r
91 "MmIsBufferOutsideMmValid: Overlap: Buffer (0x%lx) - Length (0x%lx), ",\r
92 Buffer,\r
93 Length\r
94 ));\r
95 DEBUG ((\r
96 DEBUG_ERROR,\r
97 "CpuStart (0x%lx) - PhysicalSize (0x%lx)\n",\r
98 mMmMemLibInternalMmramRanges[Index].CpuStart,\r
99 mMmMemLibInternalMmramRanges[Index].PhysicalSize\r
100 ));\r
101 return FALSE;\r
102 }\r
103 }\r
104\r
105 return TRUE;\r
106}\r
107\r
108/**\r
109 Copies a source buffer (non-MMRAM) to a destination buffer (MMRAM).\r
110\r
111 This function copies a source buffer (non-MMRAM) to a destination buffer (MMRAM).\r
112 It checks if source buffer is valid per processor architecture and not overlap with MMRAM.\r
113 If the check passes, it copies memory and returns EFI_SUCCESS.\r
114 If the check fails, it return EFI_SECURITY_VIOLATION.\r
115 The implementation must be reentrant.\r
116\r
117 @param DestinationBuffer The pointer to the destination buffer of the memory copy.\r
118 @param SourceBuffer The pointer to the source buffer of the memory copy.\r
119 @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer.\r
120\r
121 @retval EFI_SECURITY_VIOLATION The SourceBuffer is invalid per processor architecture or overlap with MMRAM.\r
122 @retval EFI_SUCCESS Memory is copied.\r
123\r
124**/\r
125EFI_STATUS\r
126EFIAPI\r
127MmCopyMemToMmram (\r
128 OUT VOID *DestinationBuffer,\r
129 IN CONST VOID *SourceBuffer,\r
130 IN UINTN Length\r
131 )\r
132{\r
133 if (!MmIsBufferOutsideMmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)SourceBuffer, Length)) {\r
134 DEBUG ((DEBUG_ERROR, "MmCopyMemToMmram: Security Violation: Source (0x%x), Length (0x%x)\n", SourceBuffer, Length));\r
135 return EFI_SECURITY_VIOLATION;\r
136 }\r
137 CopyMem (DestinationBuffer, SourceBuffer, Length);\r
138 return EFI_SUCCESS;\r
139}\r
140\r
141/**\r
142 Copies a source buffer (MMRAM) to a destination buffer (NON-MMRAM).\r
143\r
144 This function copies a source buffer (non-MMRAM) to a destination buffer (MMRAM).\r
145 It checks if destination buffer is valid per processor architecture and not overlap with MMRAM.\r
146 If the check passes, it copies memory and returns EFI_SUCCESS.\r
147 If the check fails, it returns EFI_SECURITY_VIOLATION.\r
148 The implementation must be reentrant.\r
149\r
150 @param DestinationBuffer The pointer to the destination buffer of the memory copy.\r
151 @param SourceBuffer The pointer to the source buffer of the memory copy.\r
152 @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer.\r
153\r
154 @retval EFI_SECURITY_VIOLATION The DesinationBuffer is invalid per processor architecture or overlap with MMRAM.\r
155 @retval EFI_SUCCESS Memory is copied.\r
156\r
157**/\r
158EFI_STATUS\r
159EFIAPI\r
160MmCopyMemFromMmram (\r
161 OUT VOID *DestinationBuffer,\r
162 IN CONST VOID *SourceBuffer,\r
163 IN UINTN Length\r
164 )\r
165{\r
166 if (!MmIsBufferOutsideMmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)DestinationBuffer, Length)) {\r
167 DEBUG ((DEBUG_ERROR, "MmCopyMemFromMmram: Security Violation: Destination (0x%x), Length (0x%x)\n",\r
168 DestinationBuffer, Length));\r
169 return EFI_SECURITY_VIOLATION;\r
170 }\r
171 CopyMem (DestinationBuffer, SourceBuffer, Length);\r
172 return EFI_SUCCESS;\r
173}\r
174\r
175/**\r
176 Copies a source buffer (NON-MMRAM) to a destination buffer (NON-MMRAM).\r
177\r
178 This function copies a source buffer (non-MMRAM) to a destination buffer (MMRAM).\r
179 It checks if source buffer and destination buffer are valid per processor architecture and not overlap with MMRAM.\r
180 If the check passes, it copies memory and returns EFI_SUCCESS.\r
181 If the check fails, it returns EFI_SECURITY_VIOLATION.\r
182 The implementation must be reentrant, and it must handle the case where source buffer overlaps destination buffer.\r
183\r
184 @param DestinationBuffer The pointer to the destination buffer of the memory copy.\r
185 @param SourceBuffer The pointer to the source buffer of the memory copy.\r
186 @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer.\r
187\r
188 @retval EFI_SECURITY_VIOLATION The DesinationBuffer is invalid per processor architecture or overlap with MMRAM.\r
189 @retval EFI_SECURITY_VIOLATION The SourceBuffer is invalid per processor architecture or overlap with MMRAM.\r
190 @retval EFI_SUCCESS Memory is copied.\r
191\r
192**/\r
193EFI_STATUS\r
194EFIAPI\r
195MmCopyMem (\r
196 OUT VOID *DestinationBuffer,\r
197 IN CONST VOID *SourceBuffer,\r
198 IN UINTN Length\r
199 )\r
200{\r
201 if (!MmIsBufferOutsideMmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)DestinationBuffer, Length)) {\r
202 DEBUG ((DEBUG_ERROR, "MmCopyMem: Security Violation: Destination (0x%x), Length (0x%x)\n",\r
203 DestinationBuffer, Length));\r
204 return EFI_SECURITY_VIOLATION;\r
205 }\r
206 if (!MmIsBufferOutsideMmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)SourceBuffer, Length)) {\r
207 DEBUG ((DEBUG_ERROR, "MmCopyMem: Security Violation: Source (0x%x), Length (0x%x)\n", SourceBuffer, Length));\r
208 return EFI_SECURITY_VIOLATION;\r
209 }\r
210 CopyMem (DestinationBuffer, SourceBuffer, Length);\r
211 return EFI_SUCCESS;\r
212}\r
213\r
214/**\r
215 Fills a target buffer (NON-MMRAM) with a byte value.\r
216\r
217 This function fills a target buffer (non-MMRAM) with a byte value.\r
218 It checks if target buffer is valid per processor architecture and not overlap with MMRAM.\r
219 If the check passes, it fills memory and returns EFI_SUCCESS.\r
220 If the check fails, it returns EFI_SECURITY_VIOLATION.\r
221\r
222 @param Buffer The memory to set.\r
223 @param Length The number of bytes to set.\r
224 @param Value The value with which to fill Length bytes of Buffer.\r
225\r
226 @retval EFI_SECURITY_VIOLATION The Buffer is invalid per processor architecture or overlap with MMRAM.\r
227 @retval EFI_SUCCESS Memory is set.\r
228\r
229**/\r
230EFI_STATUS\r
231EFIAPI\r
232MmSetMem (\r
233 OUT VOID *Buffer,\r
234 IN UINTN Length,\r
235 IN UINT8 Value\r
236 )\r
237{\r
238 if (!MmIsBufferOutsideMmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, Length)) {\r
239 DEBUG ((DEBUG_ERROR, "MmSetMem: Security Violation: Source (0x%x), Length (0x%x)\n", Buffer, Length));\r
240 return EFI_SECURITY_VIOLATION;\r
241 }\r
242 SetMem (Buffer, Length, Value);\r
243 return EFI_SUCCESS;\r
244}\r
245\r
246/**\r
247 The constructor function initializes the Mm Mem library\r
248\r
249 @param ImageHandle The firmware allocated handle for the EFI image.\r
250 @param SystemTable A pointer to the EFI System Table.\r
251\r
252 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.\r
253\r
254**/\r
255EFI_STATUS\r
256EFIAPI\r
257MemLibConstructor (\r
258 IN EFI_HANDLE ImageHandle,\r
259 IN EFI_MM_SYSTEM_TABLE *MmSystemTable\r
260 )\r
261{\r
262\r
263 //\r
264 // Calculate and save maximum support address\r
265 //\r
266 MmMemLibInternalCalculateMaximumSupportAddress ();\r
267\r
268 return EFI_SUCCESS;\r
269}\r