]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/PiSmmCore/HeapGuard.c
MdeModulePkg/PiSmmCore: Implement heap guard feature for SMM mode
[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 VOID
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 BitMap = GetGuardedMemoryBits (Address - EFI_PAGE_SIZE, 3);
517 return ((BitMap == 0b001) || (BitMap == 0b100) || (BitMap == 0b101));
518 }
519
520 /**
521 Check to see if the page at the given address is a head Guard page or not.
522
523 @param[in] Address The address to check for.
524
525 @return TRUE The page at Address is a head Guard page.
526 @return FALSE The page at Address is not a head Guard page.
527 **/
528 BOOLEAN
529 EFIAPI
530 IsHeadGuard (
531 IN EFI_PHYSICAL_ADDRESS Address
532 )
533 {
534 return (GetGuardedMemoryBits (Address, 2) == 0b10);
535 }
536
537 /**
538 Check to see if the page at the given address is a tail Guard page or not.
539
540 @param[in] Address The address to check for.
541
542 @return TRUE The page at Address is a tail Guard page.
543 @return FALSE The page at Address is not a tail Guard page.
544 **/
545 BOOLEAN
546 EFIAPI
547 IsTailGuard (
548 IN EFI_PHYSICAL_ADDRESS Address
549 )
550 {
551 return (GetGuardedMemoryBits (Address - EFI_PAGE_SIZE, 2) == 0b01);
552 }
553
554 /**
555 Check to see if the page at the given address is guarded or not.
556
557 @param[in] Address The address to check for.
558
559 @return TRUE The page at Address is guarded.
560 @return FALSE The page at Address is not guarded.
561 **/
562 BOOLEAN
563 EFIAPI
564 IsMemoryGuarded (
565 IN EFI_PHYSICAL_ADDRESS Address
566 )
567 {
568 return (GetGuardMapBit (Address) == 1);
569 }
570
571 /**
572 Set the page at the given address to be a Guard page.
573
574 This is done by changing the page table attribute to be NOT PRSENT.
575
576 @param[in] BaseAddress Page address to Guard at.
577
578 @return VOID.
579 **/
580 VOID
581 EFIAPI
582 SetGuardPage (
583 IN EFI_PHYSICAL_ADDRESS BaseAddress
584 )
585 {
586 if (mSmmMemoryAttribute != NULL) {
587 mOnGuarding = TRUE;
588 mSmmMemoryAttribute->SetMemoryAttributes (
589 mSmmMemoryAttribute,
590 BaseAddress,
591 EFI_PAGE_SIZE,
592 EFI_MEMORY_RP
593 );
594 mOnGuarding = FALSE;
595 }
596 }
597
598 /**
599 Unset the Guard page at the given address to the normal memory.
600
601 This is done by changing the page table attribute to be PRSENT.
602
603 @param[in] BaseAddress Page address to Guard at.
604
605 @return VOID.
606 **/
607 VOID
608 EFIAPI
609 UnsetGuardPage (
610 IN EFI_PHYSICAL_ADDRESS BaseAddress
611 )
612 {
613 if (mSmmMemoryAttribute != NULL) {
614 mOnGuarding = TRUE;
615 mSmmMemoryAttribute->ClearMemoryAttributes (
616 mSmmMemoryAttribute,
617 BaseAddress,
618 EFI_PAGE_SIZE,
619 EFI_MEMORY_RP
620 );
621 mOnGuarding = FALSE;
622 }
623 }
624
625 /**
626 Check to see if the memory at the given address should be guarded or not.
627
628 @param[in] MemoryType Memory type to check.
629 @param[in] AllocateType Allocation type to check.
630 @param[in] PageOrPool Indicate a page allocation or pool allocation.
631
632
633 @return TRUE The given type of memory should be guarded.
634 @return FALSE The given type of memory should not be guarded.
635 **/
636 BOOLEAN
637 IsMemoryTypeToGuard (
638 IN EFI_MEMORY_TYPE MemoryType,
639 IN EFI_ALLOCATE_TYPE AllocateType,
640 IN UINT8 PageOrPool
641 )
642 {
643 UINT64 TestBit;
644 UINT64 ConfigBit;
645
646 if ((PcdGet8 (PcdHeapGuardPropertyMask) & PageOrPool) == 0
647 || mOnGuarding
648 || AllocateType == AllocateAddress) {
649 return FALSE;
650 }
651
652 ConfigBit = 0;
653 if ((PageOrPool & GUARD_HEAP_TYPE_POOL) != 0) {
654 ConfigBit |= PcdGet64 (PcdHeapGuardPoolType);
655 }
656
657 if ((PageOrPool & GUARD_HEAP_TYPE_PAGE) != 0) {
658 ConfigBit |= PcdGet64 (PcdHeapGuardPageType);
659 }
660
661 if (MemoryType == EfiRuntimeServicesData ||
662 MemoryType == EfiRuntimeServicesCode) {
663 TestBit = LShiftU64 (1, MemoryType);
664 } else if (MemoryType == EfiMaxMemoryType) {
665 TestBit = (UINT64)-1;
666 } else {
667 TestBit = 0;
668 }
669
670 return ((ConfigBit & TestBit) != 0);
671 }
672
673 /**
674 Check to see if the pool at the given address should be guarded or not.
675
676 @param[in] MemoryType Pool type to check.
677
678
679 @return TRUE The given type of pool should be guarded.
680 @return FALSE The given type of pool should not be guarded.
681 **/
682 BOOLEAN
683 IsPoolTypeToGuard (
684 IN EFI_MEMORY_TYPE MemoryType
685 )
686 {
687 return IsMemoryTypeToGuard (MemoryType, AllocateAnyPages,
688 GUARD_HEAP_TYPE_POOL);
689 }
690
691 /**
692 Check to see if the page at the given address should be guarded or not.
693
694 @param[in] MemoryType Page type to check.
695 @param[in] AllocateType Allocation type to check.
696
697 @return TRUE The given type of page should be guarded.
698 @return FALSE The given type of page should not be guarded.
699 **/
700 BOOLEAN
701 IsPageTypeToGuard (
702 IN EFI_MEMORY_TYPE MemoryType,
703 IN EFI_ALLOCATE_TYPE AllocateType
704 )
705 {
706 return IsMemoryTypeToGuard (MemoryType, AllocateType, GUARD_HEAP_TYPE_PAGE);
707 }
708
709 /**
710 Check to see if the heap guard is enabled for page and/or pool allocation.
711
712 @return TRUE/FALSE.
713 **/
714 BOOLEAN
715 IsHeapGuardEnabled (
716 VOID
717 )
718 {
719 return IsMemoryTypeToGuard (EfiMaxMemoryType, AllocateAnyPages,
720 GUARD_HEAP_TYPE_POOL|GUARD_HEAP_TYPE_PAGE);
721 }
722
723 /**
724 Set head Guard and tail Guard for the given memory range.
725
726 @param[in] Memory Base address of memory to set guard for.
727 @param[in] NumberOfPages Memory size in pages.
728
729 @return VOID.
730 **/
731 VOID
732 SetGuardForMemory (
733 IN EFI_PHYSICAL_ADDRESS Memory,
734 IN UINTN NumberOfPages
735 )
736 {
737 EFI_PHYSICAL_ADDRESS GuardPage;
738
739 //
740 // Set tail Guard
741 //
742 GuardPage = Memory + EFI_PAGES_TO_SIZE (NumberOfPages);
743 if (!IsGuardPage (GuardPage)) {
744 SetGuardPage (GuardPage);
745 }
746
747 // Set head Guard
748 GuardPage = Memory - EFI_PAGES_TO_SIZE (1);
749 if (!IsGuardPage (GuardPage)) {
750 SetGuardPage (GuardPage);
751 }
752
753 //
754 // Mark the memory range as Guarded
755 //
756 SetGuardedMemoryBits (Memory, NumberOfPages);
757 }
758
759 /**
760 Unset head Guard and tail Guard for the given memory range.
761
762 @param[in] Memory Base address of memory to unset guard for.
763 @param[in] NumberOfPages Memory size in pages.
764
765 @return VOID.
766 **/
767 VOID
768 UnsetGuardForMemory (
769 IN EFI_PHYSICAL_ADDRESS Memory,
770 IN UINTN NumberOfPages
771 )
772 {
773 EFI_PHYSICAL_ADDRESS GuardPage;
774
775 if (NumberOfPages == 0) {
776 return;
777 }
778
779 //
780 // Head Guard must be one page before, if any.
781 //
782 GuardPage = Memory - EFI_PAGES_TO_SIZE (1);
783 if (IsHeadGuard (GuardPage)) {
784 if (!IsMemoryGuarded (GuardPage - EFI_PAGES_TO_SIZE (1))) {
785 //
786 // If the head Guard is not a tail Guard of adjacent memory block,
787 // unset it.
788 //
789 UnsetGuardPage (GuardPage);
790 }
791 } else if (IsMemoryGuarded (GuardPage)) {
792 //
793 // Pages before memory to free are still in Guard. It's a partial free
794 // case. Turn first page of memory block to free into a new Guard.
795 //
796 SetGuardPage (Memory);
797 }
798
799 //
800 // Tail Guard must be the page after this memory block to free, if any.
801 //
802 GuardPage = Memory + EFI_PAGES_TO_SIZE (NumberOfPages);
803 if (IsTailGuard (GuardPage)) {
804 if (!IsMemoryGuarded (GuardPage + EFI_PAGES_TO_SIZE (1))) {
805 //
806 // If the tail Guard is not a head Guard of adjacent memory block,
807 // free it; otherwise, keep it.
808 //
809 UnsetGuardPage (GuardPage);
810 }
811 } else if (IsMemoryGuarded (GuardPage)) {
812 //
813 // Pages after memory to free are still in Guard. It's a partial free
814 // case. We need to keep one page to be a head Guard.
815 //
816 SetGuardPage (GuardPage - EFI_PAGES_TO_SIZE (1));
817 }
818
819 //
820 // No matter what, we just clear the mark of the Guarded memory.
821 //
822 ClearGuardedMemoryBits(Memory, NumberOfPages);
823 }
824
825 /**
826 Adjust address of free memory according to existing and/or required Guard.
827
828 This function will check if there're existing Guard pages of adjacent
829 memory blocks, and try to use it as the Guard page of the memory to be
830 allocated.
831
832 @param[in] Start Start address of free memory block.
833 @param[in] Size Size of free memory block.
834 @param[in] SizeRequested Size of memory to allocate.
835
836 @return The end address of memory block found.
837 @return 0 if no enough space for the required size of memory and its Guard.
838 **/
839 UINT64
840 AdjustMemoryS (
841 IN UINT64 Start,
842 IN UINT64 Size,
843 IN UINT64 SizeRequested
844 )
845 {
846 UINT64 Target;
847
848 Target = Start + Size - SizeRequested;
849
850 //
851 // At least one more page needed for Guard page.
852 //
853 if (Size < (SizeRequested + EFI_PAGES_TO_SIZE (1))) {
854 return 0;
855 }
856
857 if (!IsGuardPage (Start + Size)) {
858 // No Guard at tail to share. One more page is needed.
859 Target -= EFI_PAGES_TO_SIZE (1);
860 }
861
862 // Out of range?
863 if (Target < Start) {
864 return 0;
865 }
866
867 // At the edge?
868 if (Target == Start) {
869 if (!IsGuardPage (Target - EFI_PAGES_TO_SIZE (1))) {
870 // No enough space for a new head Guard if no Guard at head to share.
871 return 0;
872 }
873 }
874
875 // OK, we have enough pages for memory and its Guards. Return the End of the
876 // free space.
877 return Target + SizeRequested - 1;
878 }
879
880 /**
881 Adjust the start address and number of pages to free according to Guard.
882
883 The purpose of this function is to keep the shared Guard page with adjacent
884 memory block if it's still in guard, or free it if no more sharing. Another
885 is to reserve pages as Guard pages in partial page free situation.
886
887 @param[in,out] Memory Base address of memory to free.
888 @param[in,out] NumberOfPages Size of memory to free.
889
890 @return VOID.
891 **/
892 VOID
893 AdjustMemoryF (
894 IN OUT EFI_PHYSICAL_ADDRESS *Memory,
895 IN OUT UINTN *NumberOfPages
896 )
897 {
898 EFI_PHYSICAL_ADDRESS Start;
899 EFI_PHYSICAL_ADDRESS MemoryToTest;
900 UINTN PagesToFree;
901
902 if (Memory == NULL || NumberOfPages == NULL || *NumberOfPages == 0) {
903 return;
904 }
905
906 Start = *Memory;
907 PagesToFree = *NumberOfPages;
908
909 //
910 // Head Guard must be one page before, if any.
911 //
912 MemoryToTest = Start - EFI_PAGES_TO_SIZE (1);
913 if (IsHeadGuard (MemoryToTest)) {
914 if (!IsMemoryGuarded (MemoryToTest - EFI_PAGES_TO_SIZE (1))) {
915 //
916 // If the head Guard is not a tail Guard of adjacent memory block,
917 // free it; otherwise, keep it.
918 //
919 Start -= EFI_PAGES_TO_SIZE (1);
920 PagesToFree += 1;
921 }
922 } else if (IsMemoryGuarded (MemoryToTest)) {
923 //
924 // Pages before memory to free are still in Guard. It's a partial free
925 // case. We need to keep one page to be a tail Guard.
926 //
927 Start += EFI_PAGES_TO_SIZE (1);
928 PagesToFree -= 1;
929 }
930
931 //
932 // Tail Guard must be the page after this memory block to free, if any.
933 //
934 MemoryToTest = Start + EFI_PAGES_TO_SIZE (PagesToFree);
935 if (IsTailGuard (MemoryToTest)) {
936 if (!IsMemoryGuarded (MemoryToTest + EFI_PAGES_TO_SIZE (1))) {
937 //
938 // If the tail Guard is not a head Guard of adjacent memory block,
939 // free it; otherwise, keep it.
940 //
941 PagesToFree += 1;
942 }
943 } else if (IsMemoryGuarded (MemoryToTest)) {
944 //
945 // Pages after memory to free are still in Guard. It's a partial free
946 // case. We need to keep one page to be a head Guard.
947 //
948 PagesToFree -= 1;
949 }
950
951 *Memory = Start;
952 *NumberOfPages = PagesToFree;
953 }
954
955 /**
956 Adjust the base and number of pages to really allocate according to Guard.
957
958 @param[in,out] Memory Base address of free memory.
959 @param[in,out] NumberOfPages Size of memory to allocate.
960
961 @return VOID.
962 **/
963 VOID
964 AdjustMemoryA (
965 IN OUT EFI_PHYSICAL_ADDRESS *Memory,
966 IN OUT UINTN *NumberOfPages
967 )
968 {
969 //
970 // FindFreePages() has already taken the Guard into account. It's safe to
971 // adjust the start address and/or number of pages here, to make sure that
972 // the Guards are also "allocated".
973 //
974 if (!IsGuardPage (*Memory + EFI_PAGES_TO_SIZE (*NumberOfPages))) {
975 // No tail Guard, add one.
976 *NumberOfPages += 1;
977 }
978
979 if (!IsGuardPage (*Memory - EFI_PAGE_SIZE)) {
980 // No head Guard, add one.
981 *Memory -= EFI_PAGE_SIZE;
982 *NumberOfPages += 1;
983 }
984 }
985
986 /**
987 Adjust the pool head position to make sure the Guard page is adjavent to
988 pool tail or pool head.
989
990 @param[in] Memory Base address of memory allocated.
991 @param[in] NoPages Number of pages actually allocated.
992 @param[in] Size Size of memory requested.
993 (plus pool head/tail overhead)
994
995 @return Address of pool head
996 **/
997 VOID *
998 AdjustPoolHeadA (
999 IN EFI_PHYSICAL_ADDRESS Memory,
1000 IN UINTN NoPages,
1001 IN UINTN Size
1002 )
1003 {
1004 if ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) != 0) {
1005 //
1006 // Pool head is put near the head Guard
1007 //
1008 return (VOID *)(UINTN)Memory;
1009 }
1010
1011 //
1012 // Pool head is put near the tail Guard
1013 //
1014 return (VOID *)(UINTN)(Memory + EFI_PAGES_TO_SIZE (NoPages) - Size);
1015 }
1016
1017 /**
1018 Get the page base address according to pool head address.
1019
1020 @param[in] Memory Head address of pool to free.
1021
1022 @return Address of pool head.
1023 **/
1024 VOID *
1025 AdjustPoolHeadF (
1026 IN EFI_PHYSICAL_ADDRESS Memory
1027 )
1028 {
1029 if ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) != 0) {
1030 //
1031 // Pool head is put near the head Guard
1032 //
1033 return (VOID *)(UINTN)Memory;
1034 }
1035
1036 //
1037 // Pool head is put near the tail Guard
1038 //
1039 return (VOID *)(UINTN)(Memory & ~EFI_PAGE_MASK);
1040 }
1041
1042 /**
1043 Helper function of memory allocation with Guard pages.
1044
1045 @param FreePageList The free page node.
1046 @param NumberOfPages Number of pages to be allocated.
1047 @param MaxAddress Request to allocate memory below this address.
1048 @param MemoryType Type of memory requested.
1049
1050 @return Memory address of allocated pages.
1051 **/
1052 UINTN
1053 InternalAllocMaxAddressWithGuard (
1054 IN OUT LIST_ENTRY *FreePageList,
1055 IN UINTN NumberOfPages,
1056 IN UINTN MaxAddress,
1057 IN EFI_MEMORY_TYPE MemoryType
1058
1059 )
1060 {
1061 LIST_ENTRY *Node;
1062 FREE_PAGE_LIST *Pages;
1063 UINTN PagesToAlloc;
1064 UINTN HeadGuard;
1065 UINTN TailGuard;
1066 UINTN Address;
1067
1068 for (Node = FreePageList->BackLink; Node != FreePageList;
1069 Node = Node->BackLink) {
1070 Pages = BASE_CR (Node, FREE_PAGE_LIST, Link);
1071 if (Pages->NumberOfPages >= NumberOfPages &&
1072 (UINTN)Pages + EFI_PAGES_TO_SIZE (NumberOfPages) - 1 <= MaxAddress) {
1073
1074 //
1075 // We may need 1 or 2 more pages for Guard. Check it out.
1076 //
1077 PagesToAlloc = NumberOfPages;
1078 TailGuard = (UINTN)Pages + EFI_PAGES_TO_SIZE (Pages->NumberOfPages);
1079 if (!IsGuardPage (TailGuard)) {
1080 //
1081 // Add one if no Guard at the end of current free memory block.
1082 //
1083 PagesToAlloc += 1;
1084 TailGuard = 0;
1085 }
1086
1087 HeadGuard = (UINTN)Pages +
1088 EFI_PAGES_TO_SIZE (Pages->NumberOfPages - PagesToAlloc) -
1089 EFI_PAGE_SIZE;
1090 if (!IsGuardPage (HeadGuard)) {
1091 //
1092 // Add one if no Guard at the page before the address to allocate
1093 //
1094 PagesToAlloc += 1;
1095 HeadGuard = 0;
1096 }
1097
1098 if (Pages->NumberOfPages < PagesToAlloc) {
1099 // Not enough space to allocate memory with Guards? Try next block.
1100 continue;
1101 }
1102
1103 Address = InternalAllocPagesOnOneNode (Pages, PagesToAlloc, MaxAddress);
1104 ConvertSmmMemoryMapEntry(MemoryType, Address, PagesToAlloc, FALSE);
1105 CoreFreeMemoryMapStack();
1106 if (HeadGuard == 0) {
1107 // Don't pass the Guard page to user.
1108 Address += EFI_PAGE_SIZE;
1109 }
1110 SetGuardForMemory (Address, NumberOfPages);
1111 return Address;
1112 }
1113 }
1114
1115 return (UINTN)(-1);
1116 }
1117
1118 /**
1119 Helper function of memory free with Guard pages.
1120
1121 @param[in] Memory Base address of memory being freed.
1122 @param[in] NumberOfPages The number of pages to free.
1123 @param[in] AddRegion If this memory is new added region.
1124
1125 @retval EFI_NOT_FOUND Could not find the entry that covers the range.
1126 @retval EFI_INVALID_PARAMETER Address not aligned, Address is zero or NumberOfPages is zero.
1127 @return EFI_SUCCESS Pages successfully freed.
1128 **/
1129 EFI_STATUS
1130 SmmInternalFreePagesExWithGuard (
1131 IN EFI_PHYSICAL_ADDRESS Memory,
1132 IN UINTN NumberOfPages,
1133 IN BOOLEAN AddRegion
1134 )
1135 {
1136 EFI_PHYSICAL_ADDRESS MemoryToFree;
1137 UINTN PagesToFree;
1138
1139 MemoryToFree = Memory;
1140 PagesToFree = NumberOfPages;
1141
1142 AdjustMemoryF (&MemoryToFree, &PagesToFree);
1143 UnsetGuardForMemory (Memory, NumberOfPages);
1144
1145 return SmmInternalFreePagesEx (MemoryToFree, PagesToFree, AddRegion);
1146 }
1147
1148 /**
1149 Set all Guard pages which cannot be set during the non-SMM mode time.
1150 **/
1151 VOID
1152 SetAllGuardPages (
1153 VOID
1154 )
1155 {
1156 UINTN Entries[GUARDED_HEAP_MAP_TABLE_DEPTH];
1157 UINTN Shifts[GUARDED_HEAP_MAP_TABLE_DEPTH];
1158 UINTN Indices[GUARDED_HEAP_MAP_TABLE_DEPTH];
1159 UINT64 Tables[GUARDED_HEAP_MAP_TABLE_DEPTH];
1160 UINT64 Addresses[GUARDED_HEAP_MAP_TABLE_DEPTH];
1161 UINT64 TableEntry;
1162 UINT64 Address;
1163 UINT64 GuardPage;
1164 INTN Level;
1165 UINTN Index;
1166 BOOLEAN OnGuarding;
1167
1168 if (mGuardedMemoryMap == 0) {
1169 return;
1170 }
1171
1172 CopyMem (Entries, mLevelMask, sizeof (Entries));
1173 CopyMem (Shifts, mLevelShift, sizeof (Shifts));
1174
1175 SetMem (Tables, sizeof(Tables), 0);
1176 SetMem (Addresses, sizeof(Addresses), 0);
1177 SetMem (Indices, sizeof(Indices), 0);
1178
1179 Level = GUARDED_HEAP_MAP_TABLE_DEPTH - mMapLevel;
1180 Tables[Level] = mGuardedMemoryMap;
1181 Address = 0;
1182 OnGuarding = FALSE;
1183
1184 DEBUG_CODE (
1185 DumpGuardedMemoryBitmap ();
1186 );
1187
1188 while (TRUE) {
1189 if (Indices[Level] > Entries[Level]) {
1190 Tables[Level] = 0;
1191 Level -= 1;
1192 } else {
1193
1194 TableEntry = ((UINT64 *)(UINTN)(Tables[Level]))[Indices[Level]];
1195 Address = Addresses[Level];
1196
1197 if (TableEntry == 0) {
1198
1199 OnGuarding = FALSE;
1200
1201 } else if (Level < GUARDED_HEAP_MAP_TABLE_DEPTH - 1) {
1202
1203 Level += 1;
1204 Tables[Level] = TableEntry;
1205 Addresses[Level] = Address;
1206 Indices[Level] = 0;
1207
1208 continue;
1209
1210 } else {
1211
1212 Index = 0;
1213 while (Index < GUARDED_HEAP_MAP_ENTRY_BITS) {
1214 if ((TableEntry & 1) == 1) {
1215 if (OnGuarding) {
1216 GuardPage = 0;
1217 } else {
1218 GuardPage = Address - EFI_PAGE_SIZE;
1219 }
1220 OnGuarding = TRUE;
1221 } else {
1222 if (OnGuarding) {
1223 GuardPage = Address;
1224 } else {
1225 GuardPage = 0;
1226 }
1227 OnGuarding = FALSE;
1228 }
1229
1230 if (GuardPage != 0) {
1231 SetGuardPage (GuardPage);
1232 }
1233
1234 if (TableEntry == 0) {
1235 break;
1236 }
1237
1238 TableEntry = RShiftU64 (TableEntry, 1);
1239 Address += EFI_PAGE_SIZE;
1240 Index += 1;
1241 }
1242 }
1243 }
1244
1245 if (Level < (GUARDED_HEAP_MAP_TABLE_DEPTH - (INTN)mMapLevel)) {
1246 break;
1247 }
1248
1249 Indices[Level] += 1;
1250 Address = (Level == 0) ? 0 : Addresses[Level - 1];
1251 Addresses[Level] = Address | LShiftU64(Indices[Level], Shifts[Level]);
1252
1253 }
1254 }
1255
1256 /**
1257 Hook function used to set all Guard pages after entering SMM mode.
1258 **/
1259 VOID
1260 SmmEntryPointMemoryManagementHook (
1261 VOID
1262 )
1263 {
1264 EFI_STATUS Status;
1265
1266 if (mSmmMemoryAttribute == NULL) {
1267 Status = SmmLocateProtocol (
1268 &gEdkiiSmmMemoryAttributeProtocolGuid,
1269 NULL,
1270 (VOID **)&mSmmMemoryAttribute
1271 );
1272 if (!EFI_ERROR(Status)) {
1273 SetAllGuardPages ();
1274 }
1275 }
1276 }
1277
1278 /**
1279 Helper function to convert a UINT64 value in binary to a string.
1280
1281 @param[in] Value Value of a UINT64 integer.
1282 @param[out] BinString String buffer to contain the conversion result.
1283
1284 @return VOID.
1285 **/
1286 VOID
1287 Uint64ToBinString (
1288 IN UINT64 Value,
1289 OUT CHAR8 *BinString
1290 )
1291 {
1292 UINTN Index;
1293
1294 if (BinString == NULL) {
1295 return;
1296 }
1297
1298 for (Index = 64; Index > 0; --Index) {
1299 BinString[Index - 1] = '0' + (Value & 1);
1300 Value = RShiftU64 (Value, 1);
1301 }
1302 BinString[64] = '\0';
1303 }
1304
1305 /**
1306 Dump the guarded memory bit map.
1307 **/
1308 VOID
1309 EFIAPI
1310 DumpGuardedMemoryBitmap (
1311 VOID
1312 )
1313 {
1314 UINTN Entries[GUARDED_HEAP_MAP_TABLE_DEPTH];
1315 UINTN Shifts[GUARDED_HEAP_MAP_TABLE_DEPTH];
1316 UINTN Indices[GUARDED_HEAP_MAP_TABLE_DEPTH];
1317 UINT64 Tables[GUARDED_HEAP_MAP_TABLE_DEPTH];
1318 UINT64 Addresses[GUARDED_HEAP_MAP_TABLE_DEPTH];
1319 UINT64 TableEntry;
1320 UINT64 Address;
1321 INTN Level;
1322 UINTN RepeatZero;
1323 CHAR8 String[GUARDED_HEAP_MAP_ENTRY_BITS + 1];
1324 CHAR8 *Ruler1;
1325 CHAR8 *Ruler2;
1326
1327 if (mGuardedMemoryMap == 0) {
1328 return;
1329 }
1330
1331 Ruler1 = " 3 2 1 0";
1332 Ruler2 = "FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210";
1333
1334 DEBUG ((HEAP_GUARD_DEBUG_LEVEL, "============================="
1335 " Guarded Memory Bitmap "
1336 "==============================\r\n"));
1337 DEBUG ((HEAP_GUARD_DEBUG_LEVEL, " %a\r\n", Ruler1));
1338 DEBUG ((HEAP_GUARD_DEBUG_LEVEL, " %a\r\n", Ruler2));
1339
1340 CopyMem (Entries, mLevelMask, sizeof (Entries));
1341 CopyMem (Shifts, mLevelShift, sizeof (Shifts));
1342
1343 SetMem (Indices, sizeof(Indices), 0);
1344 SetMem (Tables, sizeof(Tables), 0);
1345 SetMem (Addresses, sizeof(Addresses), 0);
1346
1347 Level = GUARDED_HEAP_MAP_TABLE_DEPTH - mMapLevel;
1348 Tables[Level] = mGuardedMemoryMap;
1349 Address = 0;
1350 RepeatZero = 0;
1351
1352 while (TRUE) {
1353 if (Indices[Level] > Entries[Level]) {
1354
1355 Tables[Level] = 0;
1356 Level -= 1;
1357 RepeatZero = 0;
1358
1359 DEBUG ((
1360 HEAP_GUARD_DEBUG_LEVEL,
1361 "========================================="
1362 "=========================================\r\n"
1363 ));
1364
1365 } else {
1366
1367 TableEntry = ((UINT64 *)(UINTN)Tables[Level])[Indices[Level]];
1368 Address = Addresses[Level];
1369
1370 if (TableEntry == 0) {
1371
1372 if (Level == GUARDED_HEAP_MAP_TABLE_DEPTH - 1) {
1373 if (RepeatZero == 0) {
1374 Uint64ToBinString(TableEntry, String);
1375 DEBUG ((HEAP_GUARD_DEBUG_LEVEL, "%016lx: %a\r\n", Address, String));
1376 } else if (RepeatZero == 1) {
1377 DEBUG ((HEAP_GUARD_DEBUG_LEVEL, "... : ...\r\n"));
1378 }
1379 RepeatZero += 1;
1380 }
1381
1382 } else if (Level < GUARDED_HEAP_MAP_TABLE_DEPTH - 1) {
1383
1384 Level += 1;
1385 Tables[Level] = TableEntry;
1386 Addresses[Level] = Address;
1387 Indices[Level] = 0;
1388 RepeatZero = 0;
1389
1390 continue;
1391
1392 } else {
1393
1394 RepeatZero = 0;
1395 Uint64ToBinString(TableEntry, String);
1396 DEBUG ((HEAP_GUARD_DEBUG_LEVEL, "%016lx: %a\r\n", Address, String));
1397
1398 }
1399 }
1400
1401 if (Level < (GUARDED_HEAP_MAP_TABLE_DEPTH - (INTN)mMapLevel)) {
1402 break;
1403 }
1404
1405 Indices[Level] += 1;
1406 Address = (Level == 0) ? 0 : Addresses[Level - 1];
1407 Addresses[Level] = Address | LShiftU64(Indices[Level], Shifts[Level]);
1408
1409 }
1410 }
1411
1412 /**
1413 Debug function used to verify if the Guard page is well set or not.
1414
1415 @param[in] BaseAddress Address of memory to check.
1416 @param[in] NumberOfPages Size of memory in pages.
1417
1418 @return TRUE The head Guard and tail Guard are both well set.
1419 @return FALSE The head Guard and/or tail Guard are not well set.
1420 **/
1421 BOOLEAN
1422 VerifyMemoryGuard (
1423 IN EFI_PHYSICAL_ADDRESS BaseAddress,
1424 IN UINTN NumberOfPages
1425 )
1426 {
1427 EFI_STATUS Status;
1428 UINT64 Attribute;
1429 EFI_PHYSICAL_ADDRESS Address;
1430
1431 if (mSmmMemoryAttribute == NULL) {
1432 return TRUE;
1433 }
1434
1435 Attribute = 0;
1436 Address = BaseAddress - EFI_PAGE_SIZE;
1437 Status = mSmmMemoryAttribute->GetMemoryAttributes (
1438 mSmmMemoryAttribute,
1439 Address,
1440 EFI_PAGE_SIZE,
1441 &Attribute
1442 );
1443 if (EFI_ERROR (Status) || (Attribute & EFI_MEMORY_RP) == 0) {
1444 DEBUG ((DEBUG_ERROR, "Head Guard is not set at: %016lx (%016lX)!!!\r\n",
1445 Address, Attribute));
1446 DumpGuardedMemoryBitmap ();
1447 return FALSE;
1448 }
1449
1450 Attribute = 0;
1451 Address = BaseAddress + EFI_PAGES_TO_SIZE (NumberOfPages);
1452 Status = mSmmMemoryAttribute->GetMemoryAttributes (
1453 mSmmMemoryAttribute,
1454 Address,
1455 EFI_PAGE_SIZE,
1456 &Attribute
1457 );
1458 if (EFI_ERROR (Status) || (Attribute & EFI_MEMORY_RP) == 0) {
1459 DEBUG ((DEBUG_ERROR, "Tail Guard is not set at: %016lx (%016lX)!!!\r\n",
1460 Address, Attribute));
1461 DumpGuardedMemoryBitmap ();
1462 return FALSE;
1463 }
1464
1465 return TRUE;
1466 }
1467