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