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