]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/PiSmmCore/HeapGuard.c
c7a1408562d7cc63f1040eb31854e52dc5671276
[mirror_edk2.git] / MdeModulePkg / Core / PiSmmCore / HeapGuard.c
1 /** @file
2 UEFI Heap Guard functions.
3
4 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "HeapGuard.h"
16
17 //
18 // Global to avoid infinite reentrance of memory allocation when updating
19 // page table attributes, which may need allocating pages for new PDE/PTE.
20 //
21 GLOBAL_REMOVE_IF_UNREFERENCED BOOLEAN mOnGuarding = FALSE;
22
23 //
24 // Pointer to table tracking the Guarded memory with bitmap, in which '1'
25 // is used to indicate memory guarded. '0' might be free memory or Guard
26 // page itself, depending on status of memory adjacent to it.
27 //
28 GLOBAL_REMOVE_IF_UNREFERENCED UINT64 mGuardedMemoryMap = 0;
29
30 //
31 // Current depth level of map table pointed by mGuardedMemoryMap.
32 // mMapLevel must be initialized at least by 1. It will be automatically
33 // updated according to the address of memory just tracked.
34 //
35 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mMapLevel = 1;
36
37 //
38 // Shift and mask for each level of map table
39 //
40 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mLevelShift[GUARDED_HEAP_MAP_TABLE_DEPTH]
41 = GUARDED_HEAP_MAP_TABLE_DEPTH_SHIFTS;
42 GLOBAL_REMOVE_IF_UNREFERENCED UINTN mLevelMask[GUARDED_HEAP_MAP_TABLE_DEPTH]
43 = GUARDED_HEAP_MAP_TABLE_DEPTH_MASKS;
44
45 //
46 // SMM memory attribute protocol
47 //
48 EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL *mSmmMemoryAttribute = NULL;
49
50 /**
51 Set corresponding bits in bitmap table to 1 according to the address.
52
53 @param[in] Address Start address to set for.
54 @param[in] BitNumber Number of bits to set.
55 @param[in] BitMap Pointer to bitmap which covers the Address.
56
57 @return VOID
58 **/
59 STATIC
60 VOID
61 SetBits (
62 IN EFI_PHYSICAL_ADDRESS Address,
63 IN UINTN BitNumber,
64 IN UINT64 *BitMap
65 )
66 {
67 UINTN Lsbs;
68 UINTN Qwords;
69 UINTN Msbs;
70 UINTN StartBit;
71 UINTN EndBit;
72
73 StartBit = (UINTN)GUARDED_HEAP_MAP_ENTRY_BIT_INDEX (Address);
74 EndBit = (StartBit + BitNumber - 1) % GUARDED_HEAP_MAP_ENTRY_BITS;
75
76 if ((StartBit + BitNumber) > GUARDED_HEAP_MAP_ENTRY_BITS) {
77 Msbs = (GUARDED_HEAP_MAP_ENTRY_BITS - StartBit) %
78 GUARDED_HEAP_MAP_ENTRY_BITS;
79 Lsbs = (EndBit + 1) % GUARDED_HEAP_MAP_ENTRY_BITS;
80 Qwords = (BitNumber - Msbs) / GUARDED_HEAP_MAP_ENTRY_BITS;
81 } else {
82 Msbs = BitNumber;
83 Lsbs = 0;
84 Qwords = 0;
85 }
86
87 if (Msbs > 0) {
88 *BitMap |= LShiftU64 (LShiftU64 (1, Msbs) - 1, StartBit);
89 BitMap += 1;
90 }
91
92 if (Qwords > 0) {
93 SetMem64 ((VOID *)BitMap, Qwords * GUARDED_HEAP_MAP_ENTRY_BYTES,
94 (UINT64)-1);
95 BitMap += Qwords;
96 }
97
98 if (Lsbs > 0) {
99 *BitMap |= (LShiftU64 (1, Lsbs) - 1);
100 }
101 }
102
103 /**
104 Set corresponding bits in bitmap table to 0 according to the address.
105
106 @param[in] Address Start address to set for.
107 @param[in] BitNumber Number of bits to set.
108 @param[in] BitMap Pointer to bitmap which covers the Address.
109
110 @return VOID.
111 **/
112 STATIC
113 VOID
114 ClearBits (
115 IN EFI_PHYSICAL_ADDRESS Address,
116 IN UINTN BitNumber,
117 IN UINT64 *BitMap
118 )
119 {
120 UINTN Lsbs;
121 UINTN Qwords;
122 UINTN Msbs;
123 UINTN StartBit;
124 UINTN EndBit;
125
126 StartBit = (UINTN)GUARDED_HEAP_MAP_ENTRY_BIT_INDEX (Address);
127 EndBit = (StartBit + BitNumber - 1) % GUARDED_HEAP_MAP_ENTRY_BITS;
128
129 if ((StartBit + BitNumber) > GUARDED_HEAP_MAP_ENTRY_BITS) {
130 Msbs = (GUARDED_HEAP_MAP_ENTRY_BITS - StartBit) %
131 GUARDED_HEAP_MAP_ENTRY_BITS;
132 Lsbs = (EndBit + 1) % GUARDED_HEAP_MAP_ENTRY_BITS;
133 Qwords = (BitNumber - Msbs) / GUARDED_HEAP_MAP_ENTRY_BITS;
134 } else {
135 Msbs = BitNumber;
136 Lsbs = 0;
137 Qwords = 0;
138 }
139
140 if (Msbs > 0) {
141 *BitMap &= ~LShiftU64 (LShiftU64 (1, Msbs) - 1, StartBit);
142 BitMap += 1;
143 }
144
145 if (Qwords > 0) {
146 SetMem64 ((VOID *)BitMap, Qwords * GUARDED_HEAP_MAP_ENTRY_BYTES, 0);
147 BitMap += Qwords;
148 }
149
150 if (Lsbs > 0) {
151 *BitMap &= ~(LShiftU64 (1, Lsbs) - 1);
152 }
153 }
154
155 /**
156 Get corresponding bits in bitmap table according to the address.
157
158 The value of bit 0 corresponds to the status of memory at given Address.
159 No more than 64 bits can be retrieved in one call.
160
161 @param[in] Address Start address to retrieve bits for.
162 @param[in] BitNumber Number of bits to get.
163 @param[in] BitMap Pointer to bitmap which covers the Address.
164
165 @return An integer containing the bits information.
166 **/
167 STATIC
168 UINT64
169 GetBits (
170 IN EFI_PHYSICAL_ADDRESS Address,
171 IN UINTN BitNumber,
172 IN UINT64 *BitMap
173 )
174 {
175 UINTN StartBit;
176 UINTN EndBit;
177 UINTN Lsbs;
178 UINTN Msbs;
179 UINT64 Result;
180
181 ASSERT (BitNumber <= GUARDED_HEAP_MAP_ENTRY_BITS);
182
183 StartBit = (UINTN)GUARDED_HEAP_MAP_ENTRY_BIT_INDEX (Address);
184 EndBit = (StartBit + BitNumber - 1) % GUARDED_HEAP_MAP_ENTRY_BITS;
185
186 if ((StartBit + BitNumber) > GUARDED_HEAP_MAP_ENTRY_BITS) {
187 Msbs = GUARDED_HEAP_MAP_ENTRY_BITS - StartBit;
188 Lsbs = (EndBit + 1) % GUARDED_HEAP_MAP_ENTRY_BITS;
189 } else {
190 Msbs = BitNumber;
191 Lsbs = 0;
192 }
193
194 Result = RShiftU64 ((*BitMap), StartBit) & (LShiftU64 (1, Msbs) - 1);
195 if (Lsbs > 0) {
196 BitMap += 1;
197 Result |= LShiftU64 ((*BitMap) & (LShiftU64 (1, Lsbs) - 1), Msbs);
198 }
199
200 return Result;
201 }
202
203 /**
204 Helper function to allocate pages without Guard for internal uses.
205
206 @param[in] Pages Page number.
207
208 @return Address of memory allocated.
209 **/
210 VOID *
211 PageAlloc (
212 IN UINTN Pages
213 )
214 {
215 EFI_STATUS Status;
216 EFI_PHYSICAL_ADDRESS Memory;
217
218 Status = SmmInternalAllocatePages (AllocateAnyPages, EfiRuntimeServicesData,
219 Pages, &Memory, FALSE);
220 if (EFI_ERROR (Status)) {
221 Memory = 0;
222 }
223
224 return (VOID *)(UINTN)Memory;
225 }
226
227 /**
228 Locate the pointer of bitmap from the guarded memory bitmap tables, which
229 covers the given Address.
230
231 @param[in] Address Start address to search the bitmap for.
232 @param[in] AllocMapUnit Flag to indicate memory allocation for the table.
233 @param[out] BitMap Pointer to bitmap which covers the Address.
234
235 @return The bit number from given Address to the end of current map table.
236 **/
237 UINTN
238 FindGuardedMemoryMap (
239 IN EFI_PHYSICAL_ADDRESS Address,
240 IN BOOLEAN AllocMapUnit,
241 OUT UINT64 **BitMap
242 )
243 {
244 UINTN Level;
245 UINT64 *GuardMap;
246 UINT64 MapMemory;
247 UINTN Index;
248 UINTN Size;
249 UINTN BitsToUnitEnd;
250
251 //
252 // Adjust current map table depth according to the address to access
253 //
254 while (mMapLevel < GUARDED_HEAP_MAP_TABLE_DEPTH
255 &&
256 RShiftU64 (
257 Address,
258 mLevelShift[GUARDED_HEAP_MAP_TABLE_DEPTH - mMapLevel - 1]
259 ) != 0) {
260
261 if (mGuardedMemoryMap != 0) {
262 Size = (mLevelMask[GUARDED_HEAP_MAP_TABLE_DEPTH - mMapLevel - 1] + 1)
263 * GUARDED_HEAP_MAP_ENTRY_BYTES;
264 MapMemory = (UINT64)(UINTN)PageAlloc (EFI_SIZE_TO_PAGES (Size));
265 ASSERT (MapMemory != 0);
266
267 SetMem ((VOID *)(UINTN)MapMemory, Size, 0);
268
269 *(UINT64 *)(UINTN)MapMemory = mGuardedMemoryMap;
270 mGuardedMemoryMap = MapMemory;
271 }
272
273 mMapLevel++;
274
275 }
276
277 GuardMap = &mGuardedMemoryMap;
278 for (Level = GUARDED_HEAP_MAP_TABLE_DEPTH - mMapLevel;
279 Level < GUARDED_HEAP_MAP_TABLE_DEPTH;
280 ++Level) {
281
282 if (*GuardMap == 0) {
283 if (!AllocMapUnit) {
284 GuardMap = NULL;
285 break;
286 }
287
288 Size = (mLevelMask[Level] + 1) * GUARDED_HEAP_MAP_ENTRY_BYTES;
289 MapMemory = (UINT64)(UINTN)PageAlloc (EFI_SIZE_TO_PAGES (Size));
290 ASSERT (MapMemory != 0);
291
292 SetMem ((VOID *)(UINTN)MapMemory, Size, 0);
293 *GuardMap = MapMemory;
294 }
295
296 Index = (UINTN)RShiftU64 (Address, mLevelShift[Level]);
297 Index &= mLevelMask[Level];
298 GuardMap = (UINT64 *)(UINTN)((*GuardMap) + Index * sizeof (UINT64));
299
300 }
301
302 BitsToUnitEnd = GUARDED_HEAP_MAP_BITS - GUARDED_HEAP_MAP_BIT_INDEX (Address);
303 *BitMap = GuardMap;
304
305 return BitsToUnitEnd;
306 }
307
308 /**
309 Set corresponding bits in bitmap table to 1 according to given memory range.
310
311 @param[in] Address Memory address to guard from.
312 @param[in] NumberOfPages Number of pages to guard.
313
314 @return VOID
315 **/
316 VOID
317 EFIAPI
318 SetGuardedMemoryBits (
319 IN EFI_PHYSICAL_ADDRESS Address,
320 IN UINTN NumberOfPages
321 )
322 {
323 UINT64 *BitMap;
324 UINTN Bits;
325 UINTN BitsToUnitEnd;
326
327 while (NumberOfPages > 0) {
328 BitsToUnitEnd = FindGuardedMemoryMap (Address, TRUE, &BitMap);
329 ASSERT (BitMap != NULL);
330
331 if (NumberOfPages > BitsToUnitEnd) {
332 // Cross map unit
333 Bits = BitsToUnitEnd;
334 } else {
335 Bits = NumberOfPages;
336 }
337
338 SetBits (Address, Bits, BitMap);
339
340 NumberOfPages -= Bits;
341 Address += EFI_PAGES_TO_SIZE (Bits);
342 }
343 }
344
345 /**
346 Clear corresponding bits in bitmap table according to given memory range.
347
348 @param[in] Address Memory address to unset from.
349 @param[in] NumberOfPages Number of pages to unset guard.
350
351 @return VOID
352 **/
353 VOID
354 EFIAPI
355 ClearGuardedMemoryBits (
356 IN EFI_PHYSICAL_ADDRESS Address,
357 IN UINTN NumberOfPages
358 )
359 {
360 UINT64 *BitMap;
361 UINTN Bits;
362 UINTN BitsToUnitEnd;
363
364 while (NumberOfPages > 0) {
365 BitsToUnitEnd = FindGuardedMemoryMap (Address, TRUE, &BitMap);
366 ASSERT (BitMap != NULL);
367
368 if (NumberOfPages > BitsToUnitEnd) {
369 // Cross map unit
370 Bits = BitsToUnitEnd;
371 } else {
372 Bits = NumberOfPages;
373 }
374
375 ClearBits (Address, Bits, BitMap);
376
377 NumberOfPages -= Bits;
378 Address += EFI_PAGES_TO_SIZE (Bits);
379 }
380 }
381
382 /**
383 Retrieve corresponding bits in bitmap table according to given memory range.
384
385 @param[in] Address Memory address to retrieve from.
386 @param[in] NumberOfPages Number of pages to retrieve.
387
388 @return An integer containing the guarded memory bitmap.
389 **/
390 UINTN
391 GetGuardedMemoryBits (
392 IN EFI_PHYSICAL_ADDRESS Address,
393 IN UINTN NumberOfPages
394 )
395 {
396 UINT64 *BitMap;
397 UINTN Bits;
398 UINTN Result;
399 UINTN Shift;
400 UINTN BitsToUnitEnd;
401
402 ASSERT (NumberOfPages <= GUARDED_HEAP_MAP_ENTRY_BITS);
403
404 Result = 0;
405 Shift = 0;
406 while (NumberOfPages > 0) {
407 BitsToUnitEnd = FindGuardedMemoryMap (Address, FALSE, &BitMap);
408
409 if (NumberOfPages > BitsToUnitEnd) {
410 // Cross map unit
411 Bits = BitsToUnitEnd;
412 } else {
413 Bits = NumberOfPages;
414 }
415
416 if (BitMap != NULL) {
417 Result |= LShiftU64 (GetBits (Address, Bits, BitMap), Shift);
418 }
419
420 Shift += Bits;
421 NumberOfPages -= Bits;
422 Address += EFI_PAGES_TO_SIZE (Bits);
423 }
424
425 return Result;
426 }
427
428 /**
429 Get bit value in bitmap table for the given address.
430
431 @param[in] Address The address to retrieve for.
432
433 @return 1 or 0.
434 **/
435 UINTN
436 EFIAPI
437 GetGuardMapBit (
438 IN EFI_PHYSICAL_ADDRESS Address
439 )
440 {
441 UINT64 *GuardMap;
442
443 FindGuardedMemoryMap (Address, FALSE, &GuardMap);
444 if (GuardMap != NULL) {
445 if (RShiftU64 (*GuardMap,
446 GUARDED_HEAP_MAP_ENTRY_BIT_INDEX (Address)) & 1) {
447 return 1;
448 }
449 }
450
451 return 0;
452 }
453
454 /**
455 Set the bit in bitmap table for the given address.
456
457 @param[in] Address The address to set for.
458
459 @return VOID.
460 **/
461 VOID
462 EFIAPI
463 SetGuardMapBit (
464 IN EFI_PHYSICAL_ADDRESS Address
465 )
466 {
467 UINT64 *GuardMap;
468 UINT64 BitMask;
469
470 FindGuardedMemoryMap (Address, TRUE, &GuardMap);
471 if (GuardMap != NULL) {
472 BitMask = LShiftU64 (1, GUARDED_HEAP_MAP_ENTRY_BIT_INDEX (Address));
473 *GuardMap |= BitMask;
474 }
475 }
476
477 /**
478 Clear the bit in bitmap table for the given address.
479
480 @param[in] Address The address to clear for.
481
482 @return VOID.
483 **/
484 VOID
485 EFIAPI
486 ClearGuardMapBit (
487 IN EFI_PHYSICAL_ADDRESS Address
488 )
489 {
490 UINT64 *GuardMap;
491 UINT64 BitMask;
492
493 FindGuardedMemoryMap (Address, TRUE, &GuardMap);
494 if (GuardMap != NULL) {
495 BitMask = LShiftU64 (1, GUARDED_HEAP_MAP_ENTRY_BIT_INDEX (Address));
496 *GuardMap &= ~BitMask;
497 }
498 }
499
500 /**
501 Check to see if the page at the given address is a Guard page or not.
502
503 @param[in] Address The address to check for.
504
505 @return TRUE The page at Address is a Guard page.
506 @return FALSE The page at Address is not a Guard page.
507 **/
508 BOOLEAN
509 EFIAPI
510 IsGuardPage (
511 IN EFI_PHYSICAL_ADDRESS Address
512 )
513 {
514 UINTN BitMap;
515
516 //
517 // There must be at least one guarded page before and/or after given
518 // address if it's a Guard page. The bitmap pattern should be one of
519 // 001, 100 and 101
520 //
521 BitMap = GetGuardedMemoryBits (Address - EFI_PAGE_SIZE, 3);
522 return ((BitMap == BIT0) || (BitMap == BIT2) || (BitMap == (BIT2 | BIT0)));
523 }
524
525 /**
526 Check to see if the page at the given address is a head Guard page or not.
527
528 @param[in] Address The address to check for.
529
530 @return TRUE The page at Address is a head Guard page.
531 @return FALSE The page at Address is not a head Guard page.
532 **/
533 BOOLEAN
534 EFIAPI
535 IsHeadGuard (
536 IN EFI_PHYSICAL_ADDRESS Address
537 )
538 {
539 return (GetGuardedMemoryBits (Address, 2) == BIT1);
540 }
541
542 /**
543 Check to see if the page at the given address is a tail Guard page or not.
544
545 @param[in] Address The address to check for.
546
547 @return TRUE The page at Address is a tail Guard page.
548 @return FALSE The page at Address is not a tail Guard page.
549 **/
550 BOOLEAN
551 EFIAPI
552 IsTailGuard (
553 IN EFI_PHYSICAL_ADDRESS Address
554 )
555 {
556 return (GetGuardedMemoryBits (Address - EFI_PAGE_SIZE, 2) == BIT0);
557 }
558
559 /**
560 Check to see if the page at the given address is guarded or not.
561
562 @param[in] Address The address to check for.
563
564 @return TRUE The page at Address is guarded.
565 @return FALSE The page at Address is not guarded.
566 **/
567 BOOLEAN
568 EFIAPI
569 IsMemoryGuarded (
570 IN EFI_PHYSICAL_ADDRESS Address
571 )
572 {
573 return (GetGuardMapBit (Address) == 1);
574 }
575
576 /**
577 Set the page at the given address to be a Guard page.
578
579 This is done by changing the page table attribute to be NOT PRSENT.
580
581 @param[in] BaseAddress Page address to Guard at.
582
583 @return VOID.
584 **/
585 VOID
586 EFIAPI
587 SetGuardPage (
588 IN EFI_PHYSICAL_ADDRESS BaseAddress
589 )
590 {
591 if (mSmmMemoryAttribute != NULL) {
592 mOnGuarding = TRUE;
593 mSmmMemoryAttribute->SetMemoryAttributes (
594 mSmmMemoryAttribute,
595 BaseAddress,
596 EFI_PAGE_SIZE,
597 EFI_MEMORY_RP
598 );
599 mOnGuarding = FALSE;
600 }
601 }
602
603 /**
604 Unset the Guard page at the given address to the normal memory.
605
606 This is done by changing the page table attribute to be PRSENT.
607
608 @param[in] BaseAddress Page address to Guard at.
609
610 @return VOID.
611 **/
612 VOID
613 EFIAPI
614 UnsetGuardPage (
615 IN EFI_PHYSICAL_ADDRESS BaseAddress
616 )
617 {
618 if (mSmmMemoryAttribute != NULL) {
619 mOnGuarding = TRUE;
620 mSmmMemoryAttribute->ClearMemoryAttributes (
621 mSmmMemoryAttribute,
622 BaseAddress,
623 EFI_PAGE_SIZE,
624 EFI_MEMORY_RP
625 );
626 mOnGuarding = FALSE;
627 }
628 }
629
630 /**
631 Check to see if the memory at the given address should be guarded or not.
632
633 @param[in] MemoryType Memory type to check.
634 @param[in] AllocateType Allocation type to check.
635 @param[in] PageOrPool Indicate a page allocation or pool allocation.
636
637
638 @return TRUE The given type of memory should be guarded.
639 @return FALSE The given type of memory should not be guarded.
640 **/
641 BOOLEAN
642 IsMemoryTypeToGuard (
643 IN EFI_MEMORY_TYPE MemoryType,
644 IN EFI_ALLOCATE_TYPE AllocateType,
645 IN UINT8 PageOrPool
646 )
647 {
648 UINT64 TestBit;
649 UINT64 ConfigBit;
650
651 if ((PcdGet8 (PcdHeapGuardPropertyMask) & PageOrPool) == 0
652 || mOnGuarding
653 || AllocateType == AllocateAddress) {
654 return FALSE;
655 }
656
657 ConfigBit = 0;
658 if ((PageOrPool & GUARD_HEAP_TYPE_POOL) != 0) {
659 ConfigBit |= PcdGet64 (PcdHeapGuardPoolType);
660 }
661
662 if ((PageOrPool & GUARD_HEAP_TYPE_PAGE) != 0) {
663 ConfigBit |= PcdGet64 (PcdHeapGuardPageType);
664 }
665
666 if (MemoryType == EfiRuntimeServicesData ||
667 MemoryType == EfiRuntimeServicesCode) {
668 TestBit = LShiftU64 (1, MemoryType);
669 } else if (MemoryType == EfiMaxMemoryType) {
670 TestBit = (UINT64)-1;
671 } else {
672 TestBit = 0;
673 }
674
675 return ((ConfigBit & TestBit) != 0);
676 }
677
678 /**
679 Check to see if the pool at the given address should be guarded or not.
680
681 @param[in] MemoryType Pool type to check.
682
683
684 @return TRUE The given type of pool should be guarded.
685 @return FALSE The given type of pool should not be guarded.
686 **/
687 BOOLEAN
688 IsPoolTypeToGuard (
689 IN EFI_MEMORY_TYPE MemoryType
690 )
691 {
692 return IsMemoryTypeToGuard (MemoryType, AllocateAnyPages,
693 GUARD_HEAP_TYPE_POOL);
694 }
695
696 /**
697 Check to see if the page at the given address should be guarded or not.
698
699 @param[in] MemoryType Page type to check.
700 @param[in] AllocateType Allocation type to check.
701
702 @return TRUE The given type of page should be guarded.
703 @return FALSE The given type of page should not be guarded.
704 **/
705 BOOLEAN
706 IsPageTypeToGuard (
707 IN EFI_MEMORY_TYPE MemoryType,
708 IN EFI_ALLOCATE_TYPE AllocateType
709 )
710 {
711 return IsMemoryTypeToGuard (MemoryType, AllocateType, GUARD_HEAP_TYPE_PAGE);
712 }
713
714 /**
715 Check to see if the heap guard is enabled for page and/or pool allocation.
716
717 @return TRUE/FALSE.
718 **/
719 BOOLEAN
720 IsHeapGuardEnabled (
721 VOID
722 )
723 {
724 return IsMemoryTypeToGuard (EfiMaxMemoryType, AllocateAnyPages,
725 GUARD_HEAP_TYPE_POOL|GUARD_HEAP_TYPE_PAGE);
726 }
727
728 /**
729 Set head Guard and tail Guard for the given memory range.
730
731 @param[in] Memory Base address of memory to set guard for.
732 @param[in] NumberOfPages Memory size in pages.
733
734 @return VOID.
735 **/
736 VOID
737 SetGuardForMemory (
738 IN EFI_PHYSICAL_ADDRESS Memory,
739 IN UINTN NumberOfPages
740 )
741 {
742 EFI_PHYSICAL_ADDRESS GuardPage;
743
744 //
745 // Set tail Guard
746 //
747 GuardPage = Memory + EFI_PAGES_TO_SIZE (NumberOfPages);
748 if (!IsGuardPage (GuardPage)) {
749 SetGuardPage (GuardPage);
750 }
751
752 // Set head Guard
753 GuardPage = Memory - EFI_PAGES_TO_SIZE (1);
754 if (!IsGuardPage (GuardPage)) {
755 SetGuardPage (GuardPage);
756 }
757
758 //
759 // Mark the memory range as Guarded
760 //
761 SetGuardedMemoryBits (Memory, NumberOfPages);
762 }
763
764 /**
765 Unset head Guard and tail Guard for the given memory range.
766
767 @param[in] Memory Base address of memory to unset guard for.
768 @param[in] NumberOfPages Memory size in pages.
769
770 @return VOID.
771 **/
772 VOID
773 UnsetGuardForMemory (
774 IN EFI_PHYSICAL_ADDRESS Memory,
775 IN UINTN NumberOfPages
776 )
777 {
778 EFI_PHYSICAL_ADDRESS GuardPage;
779
780 if (NumberOfPages == 0) {
781 return;
782 }
783
784 //
785 // Head Guard must be one page before, if any.
786 //
787 GuardPage = Memory - EFI_PAGES_TO_SIZE (1);
788 if (IsHeadGuard (GuardPage)) {
789 if (!IsMemoryGuarded (GuardPage - EFI_PAGES_TO_SIZE (1))) {
790 //
791 // If the head Guard is not a tail Guard of adjacent memory block,
792 // unset it.
793 //
794 UnsetGuardPage (GuardPage);
795 }
796 } else if (IsMemoryGuarded (GuardPage)) {
797 //
798 // Pages before memory to free are still in Guard. It's a partial free
799 // case. Turn first page of memory block to free into a new Guard.
800 //
801 SetGuardPage (Memory);
802 }
803
804 //
805 // Tail Guard must be the page after this memory block to free, if any.
806 //
807 GuardPage = Memory + EFI_PAGES_TO_SIZE (NumberOfPages);
808 if (IsTailGuard (GuardPage)) {
809 if (!IsMemoryGuarded (GuardPage + EFI_PAGES_TO_SIZE (1))) {
810 //
811 // If the tail Guard is not a head Guard of adjacent memory block,
812 // free it; otherwise, keep it.
813 //
814 UnsetGuardPage (GuardPage);
815 }
816 } else if (IsMemoryGuarded (GuardPage)) {
817 //
818 // Pages after memory to free are still in Guard. It's a partial free
819 // case. We need to keep one page to be a head Guard.
820 //
821 SetGuardPage (GuardPage - EFI_PAGES_TO_SIZE (1));
822 }
823
824 //
825 // No matter what, we just clear the mark of the Guarded memory.
826 //
827 ClearGuardedMemoryBits(Memory, NumberOfPages);
828 }
829
830 /**
831 Adjust address of free memory according to existing and/or required Guard.
832
833 This function will check if there're existing Guard pages of adjacent
834 memory blocks, and try to use it as the Guard page of the memory to be
835 allocated.
836
837 @param[in] Start Start address of free memory block.
838 @param[in] Size Size of free memory block.
839 @param[in] SizeRequested Size of memory to allocate.
840
841 @return The end address of memory block found.
842 @return 0 if no enough space for the required size of memory and its Guard.
843 **/
844 UINT64
845 AdjustMemoryS (
846 IN UINT64 Start,
847 IN UINT64 Size,
848 IN UINT64 SizeRequested
849 )
850 {
851 UINT64 Target;
852
853 Target = Start + Size - SizeRequested;
854
855 //
856 // At least one more page needed for Guard page.
857 //
858 if (Size < (SizeRequested + EFI_PAGES_TO_SIZE (1))) {
859 return 0;
860 }
861
862 if (!IsGuardPage (Start + Size)) {
863 // No Guard at tail to share. One more page is needed.
864 Target -= EFI_PAGES_TO_SIZE (1);
865 }
866
867 // Out of range?
868 if (Target < Start) {
869 return 0;
870 }
871
872 // At the edge?
873 if (Target == Start) {
874 if (!IsGuardPage (Target - EFI_PAGES_TO_SIZE (1))) {
875 // No enough space for a new head Guard if no Guard at head to share.
876 return 0;
877 }
878 }
879
880 // OK, we have enough pages for memory and its Guards. Return the End of the
881 // free space.
882 return Target + SizeRequested - 1;
883 }
884
885 /**
886 Adjust the start address and number of pages to free according to Guard.
887
888 The purpose of this function is to keep the shared Guard page with adjacent
889 memory block if it's still in guard, or free it if no more sharing. Another
890 is to reserve pages as Guard pages in partial page free situation.
891
892 @param[in,out] Memory Base address of memory to free.
893 @param[in,out] NumberOfPages Size of memory to free.
894
895 @return VOID.
896 **/
897 VOID
898 AdjustMemoryF (
899 IN OUT EFI_PHYSICAL_ADDRESS *Memory,
900 IN OUT UINTN *NumberOfPages
901 )
902 {
903 EFI_PHYSICAL_ADDRESS Start;
904 EFI_PHYSICAL_ADDRESS MemoryToTest;
905 UINTN PagesToFree;
906
907 if (Memory == NULL || NumberOfPages == NULL || *NumberOfPages == 0) {
908 return;
909 }
910
911 Start = *Memory;
912 PagesToFree = *NumberOfPages;
913
914 //
915 // Head Guard must be one page before, if any.
916 //
917 MemoryToTest = Start - EFI_PAGES_TO_SIZE (1);
918 if (IsHeadGuard (MemoryToTest)) {
919 if (!IsMemoryGuarded (MemoryToTest - EFI_PAGES_TO_SIZE (1))) {
920 //
921 // If the head Guard is not a tail Guard of adjacent memory block,
922 // free it; otherwise, keep it.
923 //
924 Start -= EFI_PAGES_TO_SIZE (1);
925 PagesToFree += 1;
926 }
927 } else if (IsMemoryGuarded (MemoryToTest)) {
928 //
929 // Pages before memory to free are still in Guard. It's a partial free
930 // case. We need to keep one page to be a tail Guard.
931 //
932 Start += EFI_PAGES_TO_SIZE (1);
933 PagesToFree -= 1;
934 }
935
936 //
937 // Tail Guard must be the page after this memory block to free, if any.
938 //
939 MemoryToTest = Start + EFI_PAGES_TO_SIZE (PagesToFree);
940 if (IsTailGuard (MemoryToTest)) {
941 if (!IsMemoryGuarded (MemoryToTest + EFI_PAGES_TO_SIZE (1))) {
942 //
943 // If the tail Guard is not a head Guard of adjacent memory block,
944 // free it; otherwise, keep it.
945 //
946 PagesToFree += 1;
947 }
948 } else if (IsMemoryGuarded (MemoryToTest)) {
949 //
950 // Pages after memory to free are still in Guard. It's a partial free
951 // case. We need to keep one page to be a head Guard.
952 //
953 PagesToFree -= 1;
954 }
955
956 *Memory = Start;
957 *NumberOfPages = PagesToFree;
958 }
959
960 /**
961 Adjust the base and number of pages to really allocate according to Guard.
962
963 @param[in,out] Memory Base address of free memory.
964 @param[in,out] NumberOfPages Size of memory to allocate.
965
966 @return VOID.
967 **/
968 VOID
969 AdjustMemoryA (
970 IN OUT EFI_PHYSICAL_ADDRESS *Memory,
971 IN OUT UINTN *NumberOfPages
972 )
973 {
974 //
975 // FindFreePages() has already taken the Guard into account. It's safe to
976 // adjust the start address and/or number of pages here, to make sure that
977 // the Guards are also "allocated".
978 //
979 if (!IsGuardPage (*Memory + EFI_PAGES_TO_SIZE (*NumberOfPages))) {
980 // No tail Guard, add one.
981 *NumberOfPages += 1;
982 }
983
984 if (!IsGuardPage (*Memory - EFI_PAGE_SIZE)) {
985 // No head Guard, add one.
986 *Memory -= EFI_PAGE_SIZE;
987 *NumberOfPages += 1;
988 }
989 }
990
991 /**
992 Adjust the pool head position to make sure the Guard page is adjavent to
993 pool tail or pool head.
994
995 @param[in] Memory Base address of memory allocated.
996 @param[in] NoPages Number of pages actually allocated.
997 @param[in] Size Size of memory requested.
998 (plus pool head/tail overhead)
999
1000 @return Address of pool head
1001 **/
1002 VOID *
1003 AdjustPoolHeadA (
1004 IN EFI_PHYSICAL_ADDRESS Memory,
1005 IN UINTN NoPages,
1006 IN UINTN Size
1007 )
1008 {
1009 if ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) != 0) {
1010 //
1011 // Pool head is put near the head Guard
1012 //
1013 return (VOID *)(UINTN)Memory;
1014 }
1015
1016 //
1017 // Pool head is put near the tail Guard
1018 //
1019 return (VOID *)(UINTN)(Memory + EFI_PAGES_TO_SIZE (NoPages) - Size);
1020 }
1021
1022 /**
1023 Get the page base address according to pool head address.
1024
1025 @param[in] Memory Head address of pool to free.
1026
1027 @return Address of pool head.
1028 **/
1029 VOID *
1030 AdjustPoolHeadF (
1031 IN EFI_PHYSICAL_ADDRESS Memory
1032 )
1033 {
1034 if ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) != 0) {
1035 //
1036 // Pool head is put near the head Guard
1037 //
1038 return (VOID *)(UINTN)Memory;
1039 }
1040
1041 //
1042 // Pool head is put near the tail Guard
1043 //
1044 return (VOID *)(UINTN)(Memory & ~EFI_PAGE_MASK);
1045 }
1046
1047 /**
1048 Helper function of memory allocation with Guard pages.
1049
1050 @param FreePageList The free page node.
1051 @param NumberOfPages Number of pages to be allocated.
1052 @param MaxAddress Request to allocate memory below this address.
1053 @param MemoryType Type of memory requested.
1054
1055 @return Memory address of allocated pages.
1056 **/
1057 UINTN
1058 InternalAllocMaxAddressWithGuard (
1059 IN OUT LIST_ENTRY *FreePageList,
1060 IN UINTN NumberOfPages,
1061 IN UINTN MaxAddress,
1062 IN EFI_MEMORY_TYPE MemoryType
1063
1064 )
1065 {
1066 LIST_ENTRY *Node;
1067 FREE_PAGE_LIST *Pages;
1068 UINTN PagesToAlloc;
1069 UINTN HeadGuard;
1070 UINTN TailGuard;
1071 UINTN Address;
1072
1073 for (Node = FreePageList->BackLink; Node != FreePageList;
1074 Node = Node->BackLink) {
1075 Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);
1076 if (Pages->NumberOfPages >= NumberOfPages &&
1077 (UINTN)Pages + EFI_PAGES_TO_SIZE (NumberOfPages) - 1 <= MaxAddress) {
1078
1079 //
1080 // We may need 1 or 2 more pages for Guard. Check it out.
1081 //
1082 PagesToAlloc = NumberOfPages;
1083 TailGuard = (UINTN)Pages + EFI_PAGES_TO_SIZE (Pages->NumberOfPages);
1084 if (!IsGuardPage (TailGuard)) {
1085 //
1086 // Add one if no Guard at the end of current free memory block.
1087 //
1088 PagesToAlloc += 1;
1089 TailGuard = 0;
1090 }
1091
1092 HeadGuard = (UINTN)Pages +
1093 EFI_PAGES_TO_SIZE (Pages->NumberOfPages - PagesToAlloc) -
1094 EFI_PAGE_SIZE;
1095 if (!IsGuardPage (HeadGuard)) {
1096 //
1097 // Add one if no Guard at the page before the address to allocate
1098 //
1099 PagesToAlloc += 1;
1100 HeadGuard = 0;
1101 }
1102
1103 if (Pages->NumberOfPages < PagesToAlloc) {
1104 // Not enough space to allocate memory with Guards? Try next block.
1105 continue;
1106 }
1107
1108 Address = InternalAllocPagesOnOneNode (Pages, PagesToAlloc, MaxAddress);
1109 ConvertSmmMemoryMapEntry(MemoryType, Address, PagesToAlloc, FALSE);
1110 CoreFreeMemoryMapStack();
1111 if (HeadGuard == 0) {
1112 // Don't pass the Guard page to user.
1113 Address += EFI_PAGE_SIZE;
1114 }
1115 SetGuardForMemory (Address, NumberOfPages);
1116 return Address;
1117 }
1118 }
1119
1120 return (UINTN)(-1);
1121 }
1122
1123 /**
1124 Helper function of memory free with Guard pages.
1125
1126 @param[in] Memory Base address of memory being freed.
1127 @param[in] NumberOfPages The number of pages to free.
1128 @param[in] AddRegion If this memory is new added region.
1129
1130 @retval EFI_NOT_FOUND Could not find the entry that covers the range.
1131 @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or NumberOfPages is zero.
1132 @return EFI_SUCCESS Pages successfully freed.
1133 **/
1134 EFI_STATUS
1135 SmmInternalFreePagesExWithGuard (
1136 IN EFI_PHYSICAL_ADDRESS Memory,
1137 IN UINTN NumberOfPages,
1138 IN BOOLEAN AddRegion
1139 )
1140 {
1141 EFI_PHYSICAL_ADDRESS MemoryToFree;
1142 UINTN PagesToFree;
1143
1144 MemoryToFree = Memory;
1145 PagesToFree = NumberOfPages;
1146
1147 AdjustMemoryF (&MemoryToFree, &PagesToFree);
1148 UnsetGuardForMemory (Memory, NumberOfPages);
1149
1150 return SmmInternalFreePagesEx (MemoryToFree, PagesToFree, AddRegion);
1151 }
1152
1153 /**
1154 Set all Guard pages which cannot be set during the non-SMM mode time.
1155 **/
1156 VOID
1157 SetAllGuardPages (
1158 VOID
1159 )
1160 {
1161 UINTN Entries[GUARDED_HEAP_MAP_TABLE_DEPTH];
1162 UINTN Shifts[GUARDED_HEAP_MAP_TABLE_DEPTH];
1163 UINTN Indices[GUARDED_HEAP_MAP_TABLE_DEPTH];
1164 UINT64 Tables[GUARDED_HEAP_MAP_TABLE_DEPTH];
1165 UINT64 Addresses[GUARDED_HEAP_MAP_TABLE_DEPTH];
1166 UINT64 TableEntry;
1167 UINT64 Address;
1168 UINT64 GuardPage;
1169 INTN Level;
1170 UINTN Index;
1171 BOOLEAN OnGuarding;
1172
1173 if (mGuardedMemoryMap == 0) {
1174 return;
1175 }
1176
1177 CopyMem (Entries, mLevelMask, sizeof (Entries));
1178 CopyMem (Shifts, mLevelShift, sizeof (Shifts));
1179
1180 SetMem (Tables, sizeof(Tables), 0);
1181 SetMem (Addresses, sizeof(Addresses), 0);
1182 SetMem (Indices, sizeof(Indices), 0);
1183
1184 Level = GUARDED_HEAP_MAP_TABLE_DEPTH - mMapLevel;
1185 Tables[Level] = mGuardedMemoryMap;
1186 Address = 0;
1187 OnGuarding = FALSE;
1188
1189 DEBUG_CODE (
1190 DumpGuardedMemoryBitmap ();
1191 );
1192
1193 while (TRUE) {
1194 if (Indices[Level] > Entries[Level]) {
1195 Tables[Level] = 0;
1196 Level -= 1;
1197 } else {
1198
1199 TableEntry = ((UINT64 *)(UINTN)(Tables[Level]))[Indices[Level]];
1200 Address = Addresses[Level];
1201
1202 if (TableEntry == 0) {
1203
1204 OnGuarding = FALSE;
1205
1206 } else if (Level < GUARDED_HEAP_MAP_TABLE_DEPTH - 1) {
1207
1208 Level += 1;
1209 Tables[Level] = TableEntry;
1210 Addresses[Level] = Address;
1211 Indices[Level] = 0;
1212
1213 continue;
1214
1215 } else {
1216
1217 Index = 0;
1218 while (Index < GUARDED_HEAP_MAP_ENTRY_BITS) {
1219 if ((TableEntry & 1) == 1) {
1220 if (OnGuarding) {
1221 GuardPage = 0;
1222 } else {
1223 GuardPage = Address - EFI_PAGE_SIZE;
1224 }
1225 OnGuarding = TRUE;
1226 } else {
1227 if (OnGuarding) {
1228 GuardPage = Address;
1229 } else {
1230 GuardPage = 0;
1231 }
1232 OnGuarding = FALSE;
1233 }
1234
1235 if (GuardPage != 0) {
1236 SetGuardPage (GuardPage);
1237 }
1238
1239 if (TableEntry == 0) {
1240 break;
1241 }
1242
1243 TableEntry = RShiftU64 (TableEntry, 1);
1244 Address += EFI_PAGE_SIZE;
1245 Index += 1;
1246 }
1247 }
1248 }
1249
1250 if (Level < (GUARDED_HEAP_MAP_TABLE_DEPTH - (INTN)mMapLevel)) {
1251 break;
1252 }
1253
1254 Indices[Level] += 1;
1255 Address = (Level == 0) ? 0 : Addresses[Level - 1];
1256 Addresses[Level] = Address | LShiftU64(Indices[Level], Shifts[Level]);
1257
1258 }
1259 }
1260
1261 /**
1262 Hook function used to set all Guard pages after entering SMM mode.
1263 **/
1264 VOID
1265 SmmEntryPointMemoryManagementHook (
1266 VOID
1267 )
1268 {
1269 EFI_STATUS Status;
1270
1271 if (mSmmMemoryAttribute == NULL) {
1272 Status = SmmLocateProtocol (
1273 &gEdkiiSmmMemoryAttributeProtocolGuid,
1274 NULL,
1275 (VOID **)&mSmmMemoryAttribute
1276 );
1277 if (!EFI_ERROR(Status)) {
1278 SetAllGuardPages ();
1279 }
1280 }
1281 }
1282
1283 /**
1284 Helper function to convert a UINT64 value in binary to a string.
1285
1286 @param[in] Value Value of a UINT64 integer.
1287 @param[out] BinString String buffer to contain the conversion result.
1288
1289 @return VOID.
1290 **/
1291 VOID
1292 Uint64ToBinString (
1293 IN UINT64 Value,
1294 OUT CHAR8 *BinString
1295 )
1296 {
1297 UINTN Index;
1298
1299 if (BinString == NULL) {
1300 return;
1301 }
1302
1303 for (Index = 64; Index > 0; --Index) {
1304 BinString[Index - 1] = '0' + (Value & 1);
1305 Value = RShiftU64 (Value, 1);
1306 }
1307 BinString[64] = '\0';
1308 }
1309
1310 /**
1311 Dump the guarded memory bit map.
1312 **/
1313 VOID
1314 EFIAPI
1315 DumpGuardedMemoryBitmap (
1316 VOID
1317 )
1318 {
1319 UINTN Entries[GUARDED_HEAP_MAP_TABLE_DEPTH];
1320 UINTN Shifts[GUARDED_HEAP_MAP_TABLE_DEPTH];
1321 UINTN Indices[GUARDED_HEAP_MAP_TABLE_DEPTH];
1322 UINT64 Tables[GUARDED_HEAP_MAP_TABLE_DEPTH];
1323 UINT64 Addresses[GUARDED_HEAP_MAP_TABLE_DEPTH];
1324 UINT64 TableEntry;
1325 UINT64 Address;
1326 INTN Level;
1327 UINTN RepeatZero;
1328 CHAR8 String[GUARDED_HEAP_MAP_ENTRY_BITS + 1];
1329 CHAR8 *Ruler1;
1330 CHAR8 *Ruler2;
1331
1332 if (mGuardedMemoryMap == 0) {
1333 return;
1334 }
1335
1336 Ruler1 = " 3 2 1 0";
1337 Ruler2 = "FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210";
1338
1339 DEBUG ((HEAP_GUARD_DEBUG_LEVEL, "============================="
1340 " Guarded Memory Bitmap "
1341 "==============================\r\n"));
1342 DEBUG ((HEAP_GUARD_DEBUG_LEVEL, " %a\r\n", Ruler1));
1343 DEBUG ((HEAP_GUARD_DEBUG_LEVEL, " %a\r\n", Ruler2));
1344
1345 CopyMem (Entries, mLevelMask, sizeof (Entries));
1346 CopyMem (Shifts, mLevelShift, sizeof (Shifts));
1347
1348 SetMem (Indices, sizeof(Indices), 0);
1349 SetMem (Tables, sizeof(Tables), 0);
1350 SetMem (Addresses, sizeof(Addresses), 0);
1351
1352 Level = GUARDED_HEAP_MAP_TABLE_DEPTH - mMapLevel;
1353 Tables[Level] = mGuardedMemoryMap;
1354 Address = 0;
1355 RepeatZero = 0;
1356
1357 while (TRUE) {
1358 if (Indices[Level] > Entries[Level]) {
1359
1360 Tables[Level] = 0;
1361 Level -= 1;
1362 RepeatZero = 0;
1363
1364 DEBUG ((
1365 HEAP_GUARD_DEBUG_LEVEL,
1366 "========================================="
1367 "=========================================\r\n"
1368 ));
1369
1370 } else {
1371
1372 TableEntry = ((UINT64 *)(UINTN)Tables[Level])[Indices[Level]];
1373 Address = Addresses[Level];
1374
1375 if (TableEntry == 0) {
1376
1377 if (Level == GUARDED_HEAP_MAP_TABLE_DEPTH - 1) {
1378 if (RepeatZero == 0) {
1379 Uint64ToBinString(TableEntry, String);
1380 DEBUG ((HEAP_GUARD_DEBUG_LEVEL, "%016lx: %a\r\n", Address, String));
1381 } else if (RepeatZero == 1) {
1382 DEBUG ((HEAP_GUARD_DEBUG_LEVEL, "... : ...\r\n"));
1383 }
1384 RepeatZero += 1;
1385 }
1386
1387 } else if (Level < GUARDED_HEAP_MAP_TABLE_DEPTH - 1) {
1388
1389 Level += 1;
1390 Tables[Level] = TableEntry;
1391 Addresses[Level] = Address;
1392 Indices[Level] = 0;
1393 RepeatZero = 0;
1394
1395 continue;
1396
1397 } else {
1398
1399 RepeatZero = 0;
1400 Uint64ToBinString(TableEntry, String);
1401 DEBUG ((HEAP_GUARD_DEBUG_LEVEL, "%016lx: %a\r\n", Address, String));
1402
1403 }
1404 }
1405
1406 if (Level < (GUARDED_HEAP_MAP_TABLE_DEPTH - (INTN)mMapLevel)) {
1407 break;
1408 }
1409
1410 Indices[Level] += 1;
1411 Address = (Level == 0) ? 0 : Addresses[Level - 1];
1412 Addresses[Level] = Address | LShiftU64(Indices[Level], Shifts[Level]);
1413
1414 }
1415 }
1416
1417 /**
1418 Debug function used to verify if the Guard page is well set or not.
1419
1420 @param[in] BaseAddress Address of memory to check.
1421 @param[in] NumberOfPages Size of memory in pages.
1422
1423 @return TRUE The head Guard and tail Guard are both well set.
1424 @return FALSE The head Guard and/or tail Guard are not well set.
1425 **/
1426 BOOLEAN
1427 VerifyMemoryGuard (
1428 IN EFI_PHYSICAL_ADDRESS BaseAddress,
1429 IN UINTN NumberOfPages
1430 )
1431 {
1432 EFI_STATUS Status;
1433 UINT64 Attribute;
1434 EFI_PHYSICAL_ADDRESS Address;
1435
1436 if (mSmmMemoryAttribute == NULL) {
1437 return TRUE;
1438 }
1439
1440 Attribute = 0;
1441 Address = BaseAddress - EFI_PAGE_SIZE;
1442 Status = mSmmMemoryAttribute->GetMemoryAttributes (
1443 mSmmMemoryAttribute,
1444 Address,
1445 EFI_PAGE_SIZE,
1446 &Attribute
1447 );
1448 if (EFI_ERROR (Status) || (Attribute & EFI_MEMORY_RP) == 0) {
1449 DEBUG ((DEBUG_ERROR, "Head Guard is not set at: %016lx (%016lX)!!!\r\n",
1450 Address, Attribute));
1451 DumpGuardedMemoryBitmap ();
1452 return FALSE;
1453 }
1454
1455 Attribute = 0;
1456 Address = BaseAddress + EFI_PAGES_TO_SIZE (NumberOfPages);
1457 Status = mSmmMemoryAttribute->GetMemoryAttributes (
1458 mSmmMemoryAttribute,
1459 Address,
1460 EFI_PAGE_SIZE,
1461 &Attribute
1462 );
1463 if (EFI_ERROR (Status) || (Attribute & EFI_MEMORY_RP) == 0) {
1464 DEBUG ((DEBUG_ERROR, "Tail Guard is not set at: %016lx (%016lX)!!!\r\n",
1465 Address, Attribute));
1466 DumpGuardedMemoryBitmap ();
1467 return FALSE;
1468 }
1469
1470 return TRUE;
1471 }
1472