]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/SmmMemLib/SmmMemLib.c
MdePkg/Library/Smm: Fix various typos
[mirror_edk2.git] / MdePkg / Library / SmmMemLib / SmmMemLib.c
CommitLineData
d425764e
JY
1/** @file\r
2 Instance of SMM memory check library.\r
3\r
4 SMM memory check library library implementation. This library consumes SMM_ACCESS2_PROTOCOL\r
5 to get SMRAM information. In order to use this library instance, the platform should produce\r
6 all SMRAM range via SMM_ACCESS2_PROTOCOL, including the range for firmware (like SMM Core\r
7 and SMM driver) and/or specific dedicated hardware.\r
8\r
9095d37b 9 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
9344f092 10 SPDX-License-Identifier: BSD-2-Clause-Patent\r
d425764e
JY
11\r
12**/\r
13\r
14\r
15#include <PiSmm.h>\r
16\r
17#include <Library/BaseLib.h>\r
18#include <Library/BaseMemoryLib.h>\r
19#include <Library/DebugLib.h>\r
20#include <Library/MemoryAllocationLib.h>\r
21#include <Library/UefiBootServicesTableLib.h>\r
233ffa90 22#include <Library/DxeServicesTableLib.h>\r
d425764e 23#include <Library/SmmServicesTableLib.h>\r
68096272 24#include <Library/UefiLib.h>\r
d425764e
JY
25#include <Library/HobLib.h>\r
26#include <Protocol/SmmAccess2.h>\r
91f51fcc
JY
27#include <Protocol/SmmReadyToLock.h>\r
28#include <Protocol/SmmEndOfDxe.h>\r
68096272 29#include <Guid/MemoryAttributesTable.h>\r
91f51fcc 30\r
233ffa90
JY
31//\r
32// attributes for reserved memory before it is promoted to system memory\r
33//\r
34#define EFI_MEMORY_PRESENT 0x0100000000000000ULL\r
35#define EFI_MEMORY_INITIALIZED 0x0200000000000000ULL\r
36#define EFI_MEMORY_TESTED 0x0400000000000000ULL\r
37\r
d425764e
JY
38EFI_SMRAM_DESCRIPTOR *mSmmMemLibInternalSmramRanges;\r
39UINTN mSmmMemLibInternalSmramCount;\r
40\r
41//\r
42// Maximum support address used to check input buffer\r
43//\r
44EFI_PHYSICAL_ADDRESS mSmmMemLibInternalMaximumSupportAddress = 0;\r
45\r
91f51fcc
JY
46UINTN mMemoryMapEntryCount;\r
47EFI_MEMORY_DESCRIPTOR *mMemoryMap;\r
48UINTN mDescriptorSize;\r
49\r
233ffa90
JY
50EFI_GCD_MEMORY_SPACE_DESCRIPTOR *mSmmMemLibGcdMemSpace = NULL;\r
51UINTN mSmmMemLibGcdMemNumberOfDesc = 0;\r
52\r
68096272
JY
53EFI_MEMORY_ATTRIBUTES_TABLE *mSmmMemLibMemoryAttributesTable = NULL;\r
54\r
91f51fcc
JY
55VOID *mRegistrationEndOfDxe;\r
56VOID *mRegistrationReadyToLock;\r
57\r
233ffa90 58BOOLEAN mSmmMemLibSmmReadyToLock = FALSE;\r
91f51fcc 59\r
d425764e 60/**\r
2a93f2c3 61 Calculate and save the maximum support address.\r
d425764e
JY
62\r
63**/\r
64VOID\r
2a93f2c3 65SmmMemLibInternalCalculateMaximumSupportAddress (\r
d425764e
JY
66 VOID\r
67 )\r
68{\r
69 VOID *Hob;\r
70 UINT32 RegEax;\r
71 UINT8 PhysicalAddressBits;\r
72\r
73 //\r
74 // Get physical address bits supported.\r
75 //\r
76 Hob = GetFirstHob (EFI_HOB_TYPE_CPU);\r
77 if (Hob != NULL) {\r
78 PhysicalAddressBits = ((EFI_HOB_CPU *) Hob)->SizeOfMemorySpace;\r
79 } else {\r
80 AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL);\r
81 if (RegEax >= 0x80000008) {\r
82 AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL);\r
83 PhysicalAddressBits = (UINT8) RegEax;\r
84 } else {\r
85 PhysicalAddressBits = 36;\r
86 }\r
87 }\r
88 //\r
89 // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses.\r
90 //\r
91 ASSERT (PhysicalAddressBits <= 52);\r
92 if (PhysicalAddressBits > 48) {\r
93 PhysicalAddressBits = 48;\r
94 }\r
9095d37b 95\r
d425764e 96 //\r
9095d37b 97 // Save the maximum support address in one global variable\r
d425764e
JY
98 //\r
99 mSmmMemLibInternalMaximumSupportAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)(LShiftU64 (1, PhysicalAddressBits) - 1);\r
100 DEBUG ((EFI_D_INFO, "mSmmMemLibInternalMaximumSupportAddress = 0x%lx\n", mSmmMemLibInternalMaximumSupportAddress));\r
101}\r
102\r
103/**\r
104 This function check if the buffer is valid per processor architecture and not overlap with SMRAM.\r
105\r
106 @param Buffer The buffer start address to be checked.\r
107 @param Length The buffer length to be checked.\r
108\r
109 @retval TRUE This buffer is valid per processor architecture and not overlap with SMRAM.\r
110 @retval FALSE This buffer is not valid per processor architecture or overlap with SMRAM.\r
111**/\r
112BOOLEAN\r
113EFIAPI\r
114SmmIsBufferOutsideSmmValid (\r
115 IN EFI_PHYSICAL_ADDRESS Buffer,\r
116 IN UINT64 Length\r
117 )\r
118{\r
119 UINTN Index;\r
9095d37b 120\r
d425764e
JY
121 //\r
122 // Check override.\r
123 // NOTE: (B:0->L:4G) is invalid for IA32, but (B:1->L:4G-1)/(B:4G-1->L:1) is valid.\r
124 //\r
125 if ((Length > mSmmMemLibInternalMaximumSupportAddress) ||\r
126 (Buffer > mSmmMemLibInternalMaximumSupportAddress) ||\r
127 ((Length != 0) && (Buffer > (mSmmMemLibInternalMaximumSupportAddress - (Length - 1)))) ) {\r
128 //\r
129 // Overflow happen\r
130 //\r
131 DEBUG ((\r
132 EFI_D_ERROR,\r
133 "SmmIsBufferOutsideSmmValid: Overflow: Buffer (0x%lx) - Length (0x%lx), MaximumSupportAddress (0x%lx)\n",\r
134 Buffer,\r
135 Length,\r
136 mSmmMemLibInternalMaximumSupportAddress\r
137 ));\r
138 return FALSE;\r
139 }\r
9095d37b 140\r
d425764e
JY
141 for (Index = 0; Index < mSmmMemLibInternalSmramCount; Index ++) {\r
142 if (((Buffer >= mSmmMemLibInternalSmramRanges[Index].CpuStart) && (Buffer < mSmmMemLibInternalSmramRanges[Index].CpuStart + mSmmMemLibInternalSmramRanges[Index].PhysicalSize)) ||\r
143 ((mSmmMemLibInternalSmramRanges[Index].CpuStart >= Buffer) && (mSmmMemLibInternalSmramRanges[Index].CpuStart < Buffer + Length))) {\r
144 DEBUG ((\r
145 EFI_D_ERROR,\r
146 "SmmIsBufferOutsideSmmValid: Overlap: Buffer (0x%lx) - Length (0x%lx), ",\r
147 Buffer,\r
148 Length\r
149 ));\r
150 DEBUG ((\r
151 EFI_D_ERROR,\r
152 "CpuStart (0x%lx) - PhysicalSize (0x%lx)\n",\r
153 mSmmMemLibInternalSmramRanges[Index].CpuStart,\r
154 mSmmMemLibInternalSmramRanges[Index].PhysicalSize\r
155 ));\r
156 return FALSE;\r
157 }\r
158 }\r
159\r
91f51fcc
JY
160 //\r
161 // Check override for Valid Communication Region\r
162 //\r
233ffa90 163 if (mSmmMemLibSmmReadyToLock) {\r
91f51fcc
JY
164 EFI_MEMORY_DESCRIPTOR *MemoryMap;\r
165 BOOLEAN InValidCommunicationRegion;\r
9095d37b 166\r
91f51fcc
JY
167 InValidCommunicationRegion = FALSE;\r
168 MemoryMap = mMemoryMap;\r
169 for (Index = 0; Index < mMemoryMapEntryCount; Index++) {\r
170 if ((Buffer >= MemoryMap->PhysicalStart) &&\r
171 (Buffer + Length <= MemoryMap->PhysicalStart + LShiftU64 (MemoryMap->NumberOfPages, EFI_PAGE_SHIFT))) {\r
172 InValidCommunicationRegion = TRUE;\r
173 }\r
174 MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, mDescriptorSize);\r
175 }\r
176\r
177 if (!InValidCommunicationRegion) {\r
178 DEBUG ((\r
179 EFI_D_ERROR,\r
233ffa90 180 "SmmIsBufferOutsideSmmValid: Not in ValidCommunicationRegion: Buffer (0x%lx) - Length (0x%lx)\n",\r
91f51fcc
JY
181 Buffer,\r
182 Length\r
183 ));\r
91f51fcc
JY
184 return FALSE;\r
185 }\r
233ffa90
JY
186\r
187 //\r
188 // Check untested memory as invalid communication buffer.\r
189 //\r
190 for (Index = 0; Index < mSmmMemLibGcdMemNumberOfDesc; Index++) {\r
191 if (((Buffer >= mSmmMemLibGcdMemSpace[Index].BaseAddress) && (Buffer < mSmmMemLibGcdMemSpace[Index].BaseAddress + mSmmMemLibGcdMemSpace[Index].Length)) ||\r
192 ((mSmmMemLibGcdMemSpace[Index].BaseAddress >= Buffer) && (mSmmMemLibGcdMemSpace[Index].BaseAddress < Buffer + Length))) {\r
193 DEBUG ((\r
194 EFI_D_ERROR,\r
195 "SmmIsBufferOutsideSmmValid: In Untested Memory Region: Buffer (0x%lx) - Length (0x%lx)\n",\r
196 Buffer,\r
197 Length\r
198 ));\r
199 return FALSE;\r
200 }\r
201 }\r
68096272
JY
202\r
203 //\r
204 // Check UEFI runtime memory with EFI_MEMORY_RO as invalid communication buffer.\r
205 //\r
206 if (mSmmMemLibMemoryAttributesTable != NULL) {\r
207 EFI_MEMORY_DESCRIPTOR *Entry;\r
208\r
209 Entry = (EFI_MEMORY_DESCRIPTOR *)(mSmmMemLibMemoryAttributesTable + 1);\r
210 for (Index = 0; Index < mSmmMemLibMemoryAttributesTable->NumberOfEntries; Index++) {\r
211 if (Entry->Type == EfiRuntimeServicesCode || Entry->Type == EfiRuntimeServicesData) {\r
212 if ((Entry->Attribute & EFI_MEMORY_RO) != 0) {\r
213 if (((Buffer >= Entry->PhysicalStart) && (Buffer < Entry->PhysicalStart + LShiftU64 (Entry->NumberOfPages, EFI_PAGE_SHIFT))) ||\r
214 ((Entry->PhysicalStart >= Buffer) && (Entry->PhysicalStart < Buffer + Length))) {\r
215 DEBUG ((\r
216 EFI_D_ERROR,\r
217 "SmmIsBufferOutsideSmmValid: In RuntimeCode Region: Buffer (0x%lx) - Length (0x%lx)\n",\r
218 Buffer,\r
219 Length\r
220 ));\r
221 return FALSE;\r
222 }\r
223 }\r
224 }\r
225 Entry = NEXT_MEMORY_DESCRIPTOR (Entry, mSmmMemLibMemoryAttributesTable->DescriptorSize);\r
226 }\r
227 }\r
91f51fcc 228 }\r
d425764e
JY
229 return TRUE;\r
230}\r
231\r
232/**\r
233 Copies a source buffer (non-SMRAM) to a destination buffer (SMRAM).\r
234\r
235 This function copies a source buffer (non-SMRAM) to a destination buffer (SMRAM).\r
236 It checks if source buffer is valid per processor architecture and not overlap with SMRAM.\r
237 If the check passes, it copies memory and returns EFI_SUCCESS.\r
238 If the check fails, it return EFI_SECURITY_VIOLATION.\r
239 The implementation must be reentrant.\r
240\r
241 @param DestinationBuffer The pointer to the destination buffer of the memory copy.\r
242 @param SourceBuffer The pointer to the source buffer of the memory copy.\r
243 @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer.\r
244\r
245 @retval EFI_SECURITY_VIOLATION The SourceBuffer is invalid per processor architecture or overlap with SMRAM.\r
246 @retval EFI_SUCCESS Memory is copied.\r
247\r
248**/\r
249EFI_STATUS\r
250EFIAPI\r
251SmmCopyMemToSmram (\r
252 OUT VOID *DestinationBuffer,\r
253 IN CONST VOID *SourceBuffer,\r
254 IN UINTN Length\r
255 )\r
256{\r
257 if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)SourceBuffer, Length)) {\r
258 DEBUG ((EFI_D_ERROR, "SmmCopyMemToSmram: Security Violation: Source (0x%x), Length (0x%x)\n", SourceBuffer, Length));\r
259 return EFI_SECURITY_VIOLATION;\r
260 }\r
261 CopyMem (DestinationBuffer, SourceBuffer, Length);\r
262 return EFI_SUCCESS;\r
263}\r
264\r
265/**\r
266 Copies a source buffer (SMRAM) to a destination buffer (NON-SMRAM).\r
267\r
268 This function copies a source buffer (non-SMRAM) to a destination buffer (SMRAM).\r
269 It checks if destination buffer is valid per processor architecture and not overlap with SMRAM.\r
270 If the check passes, it copies memory and returns EFI_SUCCESS.\r
271 If the check fails, it returns EFI_SECURITY_VIOLATION.\r
272 The implementation must be reentrant.\r
9095d37b 273\r
d425764e
JY
274 @param DestinationBuffer The pointer to the destination buffer of the memory copy.\r
275 @param SourceBuffer The pointer to the source buffer of the memory copy.\r
276 @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer.\r
277\r
fae43d06 278 @retval EFI_SECURITY_VIOLATION The DestinationBuffer is invalid per processor architecture or overlap with SMRAM.\r
d425764e
JY
279 @retval EFI_SUCCESS Memory is copied.\r
280\r
281**/\r
282EFI_STATUS\r
283EFIAPI\r
284SmmCopyMemFromSmram (\r
285 OUT VOID *DestinationBuffer,\r
286 IN CONST VOID *SourceBuffer,\r
287 IN UINTN Length\r
288 )\r
289{\r
290 if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)DestinationBuffer, Length)) {\r
291 DEBUG ((EFI_D_ERROR, "SmmCopyMemFromSmram: Security Violation: Destination (0x%x), Length (0x%x)\n", DestinationBuffer, Length));\r
292 return EFI_SECURITY_VIOLATION;\r
293 }\r
294 CopyMem (DestinationBuffer, SourceBuffer, Length);\r
295 return EFI_SUCCESS;\r
296}\r
297\r
298/**\r
299 Copies a source buffer (NON-SMRAM) to a destination buffer (NON-SMRAM).\r
300\r
301 This function copies a source buffer (non-SMRAM) to a destination buffer (SMRAM).\r
302 It checks if source buffer and destination buffer are valid per processor architecture and not overlap with SMRAM.\r
303 If the check passes, it copies memory and returns EFI_SUCCESS.\r
304 If the check fails, it returns EFI_SECURITY_VIOLATION.\r
305 The implementation must be reentrant, and it must handle the case where source buffer overlaps destination buffer.\r
9095d37b 306\r
d425764e
JY
307 @param DestinationBuffer The pointer to the destination buffer of the memory copy.\r
308 @param SourceBuffer The pointer to the source buffer of the memory copy.\r
309 @param Length The number of bytes to copy from SourceBuffer to DestinationBuffer.\r
310\r
fae43d06 311 @retval EFI_SECURITY_VIOLATION The DestinationBuffer is invalid per processor architecture or overlap with SMRAM.\r
d425764e
JY
312 @retval EFI_SECURITY_VIOLATION The SourceBuffer is invalid per processor architecture or overlap with SMRAM.\r
313 @retval EFI_SUCCESS Memory is copied.\r
314\r
315**/\r
316EFI_STATUS\r
317EFIAPI\r
318SmmCopyMem (\r
319 OUT VOID *DestinationBuffer,\r
320 IN CONST VOID *SourceBuffer,\r
321 IN UINTN Length\r
322 )\r
323{\r
324 if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)DestinationBuffer, Length)) {\r
325 DEBUG ((EFI_D_ERROR, "SmmCopyMem: Security Violation: Destination (0x%x), Length (0x%x)\n", DestinationBuffer, Length));\r
326 return EFI_SECURITY_VIOLATION;\r
327 }\r
328 if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)SourceBuffer, Length)) {\r
329 DEBUG ((EFI_D_ERROR, "SmmCopyMem: Security Violation: Source (0x%x), Length (0x%x)\n", SourceBuffer, Length));\r
330 return EFI_SECURITY_VIOLATION;\r
331 }\r
332 CopyMem (DestinationBuffer, SourceBuffer, Length);\r
333 return EFI_SUCCESS;\r
334}\r
335\r
336/**\r
337 Fills a target buffer (NON-SMRAM) with a byte value.\r
338\r
339 This function fills a target buffer (non-SMRAM) with a byte value.\r
340 It checks if target buffer is valid per processor architecture and not overlap with SMRAM.\r
341 If the check passes, it fills memory and returns EFI_SUCCESS.\r
342 If the check fails, it returns EFI_SECURITY_VIOLATION.\r
9095d37b 343\r
d425764e
JY
344 @param Buffer The memory to set.\r
345 @param Length The number of bytes to set.\r
346 @param Value The value with which to fill Length bytes of Buffer.\r
9095d37b 347\r
d425764e
JY
348 @retval EFI_SECURITY_VIOLATION The Buffer is invalid per processor architecture or overlap with SMRAM.\r
349 @retval EFI_SUCCESS Memory is set.\r
350\r
351**/\r
352EFI_STATUS\r
353EFIAPI\r
354SmmSetMem (\r
355 OUT VOID *Buffer,\r
356 IN UINTN Length,\r
357 IN UINT8 Value\r
358 )\r
359{\r
360 if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, Length)) {\r
361 DEBUG ((EFI_D_ERROR, "SmmSetMem: Security Violation: Source (0x%x), Length (0x%x)\n", Buffer, Length));\r
362 return EFI_SECURITY_VIOLATION;\r
363 }\r
364 SetMem (Buffer, Length, Value);\r
365 return EFI_SUCCESS;\r
366}\r
367\r
233ffa90
JY
368/**\r
369 Get GCD memory map.\r
370 Only record untested memory as invalid communication buffer.\r
371**/\r
372VOID\r
373SmmMemLibInternalGetGcdMemoryMap (\r
374 VOID\r
375 )\r
376{\r
377 UINTN NumberOfDescriptors;\r
378 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemSpaceMap;\r
379 EFI_STATUS Status;\r
380 UINTN Index;\r
381\r
382 Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemSpaceMap);\r
383 if (EFI_ERROR (Status)) {\r
384 return ;\r
385 }\r
386\r
387 mSmmMemLibGcdMemNumberOfDesc = 0;\r
388 for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
389 if (MemSpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeReserved &&\r
390 (MemSpaceMap[Index].Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) ==\r
391 (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED)\r
392 ) {\r
393 mSmmMemLibGcdMemNumberOfDesc++;\r
394 }\r
395 }\r
396\r
397 mSmmMemLibGcdMemSpace = AllocateZeroPool (mSmmMemLibGcdMemNumberOfDesc * sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR));\r
398 ASSERT (mSmmMemLibGcdMemSpace != NULL);\r
399 if (mSmmMemLibGcdMemSpace == NULL) {\r
400 mSmmMemLibGcdMemNumberOfDesc = 0;\r
401 gBS->FreePool (MemSpaceMap);\r
402 return ;\r
403 }\r
404\r
405 mSmmMemLibGcdMemNumberOfDesc = 0;\r
406 for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
407 if (MemSpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeReserved &&\r
408 (MemSpaceMap[Index].Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) ==\r
409 (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED)\r
410 ) {\r
411 CopyMem (\r
412 &mSmmMemLibGcdMemSpace[mSmmMemLibGcdMemNumberOfDesc],\r
413 &MemSpaceMap[Index],\r
414 sizeof(EFI_GCD_MEMORY_SPACE_DESCRIPTOR)\r
415 );\r
416 mSmmMemLibGcdMemNumberOfDesc++;\r
417 }\r
418 }\r
419\r
420 gBS->FreePool (MemSpaceMap);\r
421}\r
422\r
68096272
JY
423/**\r
424 Get UEFI MemoryAttributesTable.\r
425**/\r
426VOID\r
427SmmMemLibInternalGetUefiMemoryAttributesTable (\r
428 VOID\r
429 )\r
430{\r
431 EFI_STATUS Status;\r
432 EFI_MEMORY_ATTRIBUTES_TABLE *MemoryAttributesTable;\r
433 UINTN MemoryAttributesTableSize;\r
434\r
435 Status = EfiGetSystemConfigurationTable (&gEfiMemoryAttributesTableGuid, (VOID **)&MemoryAttributesTable);\r
264914a5 436 if (!EFI_ERROR (Status) && (MemoryAttributesTable != NULL)) {\r
68096272
JY
437 MemoryAttributesTableSize = sizeof(EFI_MEMORY_ATTRIBUTES_TABLE) + MemoryAttributesTable->DescriptorSize * MemoryAttributesTable->NumberOfEntries;\r
438 mSmmMemLibMemoryAttributesTable = AllocateCopyPool (MemoryAttributesTableSize, MemoryAttributesTable);\r
439 ASSERT (mSmmMemLibMemoryAttributesTable != NULL);\r
440 }\r
441}\r
442\r
91f51fcc
JY
443/**\r
444 Notification for SMM EndOfDxe protocol.\r
445\r
446 @param[in] Protocol Points to the protocol's unique identifier.\r
447 @param[in] Interface Points to the interface instance.\r
448 @param[in] Handle The handle on which the interface was installed.\r
449\r
450 @retval EFI_SUCCESS Notification runs successfully.\r
451**/\r
452EFI_STATUS\r
453EFIAPI\r
454SmmLibInternalEndOfDxeNotify (\r
455 IN CONST EFI_GUID *Protocol,\r
456 IN VOID *Interface,\r
457 IN EFI_HANDLE Handle\r
458 )\r
459{\r
460 EFI_STATUS Status;\r
461 UINTN MapKey;\r
462 UINTN MemoryMapSize;\r
463 EFI_MEMORY_DESCRIPTOR *MemoryMap;\r
464 EFI_MEMORY_DESCRIPTOR *MemoryMapStart;\r
465 EFI_MEMORY_DESCRIPTOR *SmmMemoryMapStart;\r
466 UINTN MemoryMapEntryCount;\r
467 UINTN DescriptorSize;\r
468 UINT32 DescriptorVersion;\r
469 UINTN Index;\r
470\r
471 MemoryMapSize = 0;\r
472 MemoryMap = NULL;\r
473 Status = gBS->GetMemoryMap (\r
474 &MemoryMapSize,\r
475 MemoryMap,\r
476 &MapKey,\r
477 &DescriptorSize,\r
478 &DescriptorVersion\r
479 );\r
480 ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
481\r
482 do {\r
483 Status = gBS->AllocatePool (EfiBootServicesData, MemoryMapSize, (VOID **)&MemoryMap);\r
484 ASSERT (MemoryMap != NULL);\r
9095d37b 485\r
91f51fcc
JY
486 Status = gBS->GetMemoryMap (\r
487 &MemoryMapSize,\r
488 MemoryMap,\r
489 &MapKey,\r
490 &DescriptorSize,\r
491 &DescriptorVersion\r
492 );\r
493 if (EFI_ERROR (Status)) {\r
494 gBS->FreePool (MemoryMap);\r
495 }\r
496 } while (Status == EFI_BUFFER_TOO_SMALL);\r
497\r
498 //\r
499 // Get Count\r
500 //\r
501 mDescriptorSize = DescriptorSize;\r
502 MemoryMapEntryCount = MemoryMapSize/DescriptorSize;\r
503 MemoryMapStart = MemoryMap;\r
504 mMemoryMapEntryCount = 0;\r
505 for (Index = 0; Index < MemoryMapEntryCount; Index++) {\r
506 switch (MemoryMap->Type) {\r
507 case EfiReservedMemoryType:\r
508 case EfiRuntimeServicesCode:\r
509 case EfiRuntimeServicesData:\r
510 case EfiACPIMemoryNVS:\r
511 mMemoryMapEntryCount++;\r
512 break;\r
513 }\r
514 MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, DescriptorSize);\r
515 }\r
516 MemoryMap = MemoryMapStart;\r
9095d37b 517\r
91f51fcc
JY
518 //\r
519 // Get Data\r
520 //\r
521 mMemoryMap = AllocatePool (mMemoryMapEntryCount*DescriptorSize);\r
522 ASSERT (mMemoryMap != NULL);\r
523 SmmMemoryMapStart = mMemoryMap;\r
524 for (Index = 0; Index < MemoryMapEntryCount; Index++) {\r
525 switch (MemoryMap->Type) {\r
526 case EfiReservedMemoryType:\r
527 case EfiRuntimeServicesCode:\r
528 case EfiRuntimeServicesData:\r
529 case EfiACPIMemoryNVS:\r
530 CopyMem (mMemoryMap, MemoryMap, DescriptorSize);\r
531 mMemoryMap = NEXT_MEMORY_DESCRIPTOR(mMemoryMap, DescriptorSize);\r
532 break;\r
533 }\r
534 MemoryMap = NEXT_MEMORY_DESCRIPTOR(MemoryMap, DescriptorSize);\r
535 }\r
536 mMemoryMap = SmmMemoryMapStart;\r
537 MemoryMap = MemoryMapStart;\r
9095d37b 538\r
91f51fcc
JY
539 gBS->FreePool (MemoryMap);\r
540\r
233ffa90
JY
541 //\r
542 // Get additional information from GCD memory map.\r
543 //\r
544 SmmMemLibInternalGetGcdMemoryMap ();\r
545\r
68096272
JY
546 //\r
547 // Get UEFI memory attributes table.\r
548 //\r
549 SmmMemLibInternalGetUefiMemoryAttributesTable ();\r
550\r
91f51fcc
JY
551 return EFI_SUCCESS;\r
552}\r
553\r
91f51fcc
JY
554/**\r
555 Notification for SMM ReadyToLock protocol.\r
556\r
557 @param[in] Protocol Points to the protocol's unique identifier.\r
558 @param[in] Interface Points to the interface instance.\r
559 @param[in] Handle The handle on which the interface was installed.\r
560\r
561 @retval EFI_SUCCESS Notification runs successfully.\r
562**/\r
563EFI_STATUS\r
564EFIAPI\r
565SmmLibInternalReadyToLockNotify (\r
566 IN CONST EFI_GUID *Protocol,\r
567 IN VOID *Interface,\r
568 IN EFI_HANDLE Handle\r
569 )\r
570{\r
233ffa90 571 mSmmMemLibSmmReadyToLock = TRUE;\r
91f51fcc
JY
572 return EFI_SUCCESS;\r
573}\r
d425764e
JY
574/**\r
575 The constructor function initializes the Smm Mem library\r
576\r
577 @param ImageHandle The firmware allocated handle for the EFI image.\r
578 @param SystemTable A pointer to the EFI System Table.\r
579\r
580 @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.\r
581\r
582**/\r
583EFI_STATUS\r
584EFIAPI\r
585SmmMemLibConstructor (\r
586 IN EFI_HANDLE ImageHandle,\r
587 IN EFI_SYSTEM_TABLE *SystemTable\r
588 )\r
589{\r
590 EFI_STATUS Status;\r
591 EFI_SMM_ACCESS2_PROTOCOL *SmmAccess;\r
592 UINTN Size;\r
9095d37b 593\r
d425764e
JY
594 //\r
595 // Get SMRAM information\r
596 //\r
597 Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **)&SmmAccess);\r
598 ASSERT_EFI_ERROR (Status);\r
599\r
600 Size = 0;\r
601 Status = SmmAccess->GetCapabilities (SmmAccess, &Size, NULL);\r
602 ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
603\r
604 mSmmMemLibInternalSmramRanges = AllocatePool (Size);\r
605 ASSERT (mSmmMemLibInternalSmramRanges != NULL);\r
606\r
607 Status = SmmAccess->GetCapabilities (SmmAccess, &Size, mSmmMemLibInternalSmramRanges);\r
608 ASSERT_EFI_ERROR (Status);\r
609\r
610 mSmmMemLibInternalSmramCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);\r
611\r
612 //\r
2a93f2c3 613 // Calculate and save maximum support address\r
d425764e 614 //\r
2a93f2c3 615 SmmMemLibInternalCalculateMaximumSupportAddress ();\r
d425764e 616\r
91f51fcc
JY
617 //\r
618 // Register EndOfDxe to get UEFI memory map\r
619 //\r
620 Status = gSmst->SmmRegisterProtocolNotify (&gEfiSmmEndOfDxeProtocolGuid, SmmLibInternalEndOfDxeNotify, &mRegistrationEndOfDxe);\r
621 ASSERT_EFI_ERROR (Status);\r
622\r
623 //\r
624 // Register ready to lock so that we can know when to check valid SMRAM region\r
625 //\r
626 Status = gSmst->SmmRegisterProtocolNotify (&gEfiSmmReadyToLockProtocolGuid, SmmLibInternalReadyToLockNotify, &mRegistrationReadyToLock);\r
627 ASSERT_EFI_ERROR (Status);\r
628\r
d425764e
JY
629 return EFI_SUCCESS;\r
630}\r
631\r
632/**\r
633 The destructor function frees resource used in the Smm Mem library\r
634\r
635 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
636 @param[in] SystemTable A pointer to the EFI System Table.\r
637\r
638 @retval EFI_SUCCESS The deconstructor always returns EFI_SUCCESS.\r
639**/\r
640EFI_STATUS\r
641EFIAPI\r
642SmmMemLibDestructor (\r
643 IN EFI_HANDLE ImageHandle,\r
644 IN EFI_SYSTEM_TABLE *SystemTable\r
645 )\r
646{\r
647 FreePool (mSmmMemLibInternalSmramRanges);\r
648\r
91f51fcc
JY
649 gSmst->SmmRegisterProtocolNotify (&gEfiSmmEndOfDxeProtocolGuid, NULL, &mRegistrationEndOfDxe);\r
650 gSmst->SmmRegisterProtocolNotify (&gEfiSmmReadyToLockProtocolGuid, NULL, &mRegistrationReadyToLock);\r
d425764e
JY
651 return EFI_SUCCESS;\r
652}\r