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