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