3 * Copyright (C) 2006-2008 Aleksey Bragin <aleksey@reactos.org>
4 * Copyright (C) 2006-2009 Hervé Poussineau <hpoussin@reactos.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 DBG_DEFAULT_CHANNEL(MEMORY
);
31 } FREELDR_MEMORY_TYPE
, *PFREELDR_MEMORY_TYPE
;
33 FREELDR_MEMORY_TYPE MemoryTypeArray
[] =
35 { LoaderMaximum
, "Unknown memory" },
36 { LoaderFree
, "Free memory" },
37 { LoaderBad
, "Bad memory" },
38 { LoaderLoadedProgram
, "LoadedProgram" },
39 { LoaderFirmwareTemporary
, "FirmwareTemporary" },
40 { LoaderFirmwarePermanent
, "FirmwarePermanent" },
41 { LoaderOsloaderHeap
, "OsloaderHeap" },
42 { LoaderOsloaderStack
, "OsloaderStack" },
43 { LoaderSystemCode
, "SystemCode" },
44 { LoaderHalCode
, "HalCode" },
45 { LoaderBootDriver
, "BootDriver" },
46 { LoaderRegistryData
, "RegistryData" },
47 { LoaderMemoryData
, "MemoryData" },
48 { LoaderNlsData
, "NlsData" },
49 { LoaderSpecialMemory
, "SpecialMemory" },
50 { LoaderReserve
, "Reserve" },
52 ULONG MemoryTypeCount
= sizeof(MemoryTypeArray
) / sizeof(MemoryTypeArray
[0]);
55 PVOID PageLookupTableAddress
= NULL
;
56 PFN_NUMBER TotalPagesInLookupTable
= 0;
57 PFN_NUMBER FreePagesInLookupTable
= 0;
58 PFN_NUMBER LastFreePageHint
= 0;
59 PFN_NUMBER MmLowestPhysicalPage
= 0xFFFFFFFF;
60 PFN_NUMBER MmHighestPhysicalPage
= 0;
62 PFREELDR_MEMORY_DESCRIPTOR BiosMemoryMap
;
63 ULONG BiosMemoryMapEntryCount
;
67 IN OUT PFREELDR_MEMORY_DESCRIPTOR List
,
69 IN PFN_NUMBER BasePage
,
70 IN PFN_NUMBER PageCount
,
71 IN TYPE_OF_MEMORY MemoryType
)
75 TRACE("AddMemoryDescriptor(0x%lx-0x%lx [0x%lx pages])\n",
76 BasePage
, BasePage
+ PageCount
, PageCount
);
78 /* Scan through all existing descriptors */
79 for (i
= 0, c
= 0; (c
< MaxCount
) && (List
[c
].PageCount
!= 0); c
++)
81 /* Count entries completely below the new range */
82 if (List
[i
].BasePage
+ List
[i
].PageCount
<= BasePage
) i
++;
85 /* Check if the list is full */
86 if (c
>= MaxCount
) return c
;
88 /* Is there an existing descriptor starting before the new range */
89 while ((i
< c
) && (List
[i
].BasePage
<= BasePage
))
91 /* The end of the existing one is the minimum for the new range */
92 NextBase
= List
[i
].BasePage
+ List
[i
].PageCount
;
94 /* Bail out, if everything is trimmed away */
95 if ((BasePage
+ PageCount
) <= NextBase
) return c
;
97 /* Trim the naew range at the lower end */
98 PageCount
-= (NextBase
- BasePage
);
101 /* Go to the next entry and repeat */
105 ASSERT(PageCount
> 0);
107 /* Are there still entries above? */
110 /* Shift the following entries one up */
111 RtlMoveMemory(&List
[i
+1], &List
[i
], (c
- i
) * sizeof(List
[0]));
113 /* Insert the new range */
114 List
[i
].BasePage
= BasePage
;
115 List
[i
].PageCount
= min(PageCount
, List
[i
+1].BasePage
- BasePage
);
116 List
[i
].MemoryType
= MemoryType
;
119 TRACE("Inserting at i=%ld: (0x%lx:0x%lx)\n",
120 i
, List
[i
].BasePage
, List
[i
].PageCount
);
122 /* Check if the range was trimmed */
123 if (PageCount
> List
[i
].PageCount
)
125 /* Recursively process the trimmed part */
126 c
= AddMemoryDescriptor(List
,
128 BasePage
+ List
[i
].PageCount
,
129 PageCount
- List
[i
].PageCount
,
135 /* We can simply add the range here */
136 TRACE("Adding i=%ld: (0x%lx:0x%lx)\n", i
, BasePage
, PageCount
);
137 List
[i
].BasePage
= BasePage
;
138 List
[i
].PageCount
= PageCount
;
139 List
[i
].MemoryType
= MemoryType
;
143 /* Return the new count */
147 const FREELDR_MEMORY_DESCRIPTOR
*
148 ArcGetMemoryDescriptor(const FREELDR_MEMORY_DESCRIPTOR
* Current
)
152 return BiosMemoryMap
;
157 if (Current
->PageCount
== 0) return NULL
;
164 MmCheckFreeldrImageFile()
166 PIMAGE_NT_HEADERS NtHeaders
;
167 PIMAGE_FILE_HEADER FileHeader
;
168 PIMAGE_OPTIONAL_HEADER OptionalHeader
;
170 /* Get the NT headers */
171 NtHeaders
= RtlImageNtHeader(&__ImageBase
);
174 ERR("Could not get NtHeaders!\n");
175 FrLdrBugCheckWithMessage(
176 FREELDR_IMAGE_CORRUPTION
,
179 "Could not get NtHeaders!\n");
182 /* Check the file header */
183 FileHeader
= &NtHeaders
->FileHeader
;
184 if ((FileHeader
->Machine
!= IMAGE_FILE_MACHINE_NATIVE
) ||
185 (FileHeader
->NumberOfSections
!= FREELDR_SECTION_COUNT
) ||
186 (FileHeader
->PointerToSymbolTable
!= 0) ||
187 (FileHeader
->NumberOfSymbols
!= 0) ||
188 (FileHeader
->SizeOfOptionalHeader
!= sizeof(IMAGE_OPTIONAL_HEADER
)))
190 ERR("FreeLdr FileHeader is invalid.\n");
191 FrLdrBugCheckWithMessage(
192 FREELDR_IMAGE_CORRUPTION
,
195 "FreeLdr FileHeader is invalid.\n"
196 "Machine == 0x%lx, expected 0x%lx\n"
197 "NumberOfSections == 0x%lx, expected 0x%lx\n"
198 "PointerToSymbolTable == 0x%lx, expected 0\n"
199 "NumberOfSymbols == 0x%lx, expected 0\n"
200 "SizeOfOptionalHeader == 0x%lx, expected 0x%lx\n",
201 FileHeader
->Machine
, IMAGE_FILE_MACHINE_NATIVE
,
202 FileHeader
->NumberOfSections
, FREELDR_SECTION_COUNT
,
203 FileHeader
->PointerToSymbolTable
,
204 FileHeader
->NumberOfSymbols
,
205 FileHeader
->SizeOfOptionalHeader
, sizeof(IMAGE_OPTIONAL_HEADER
));
208 /* Check the optional header */
209 OptionalHeader
= &NtHeaders
->OptionalHeader
;
210 if ((OptionalHeader
->Magic
!= IMAGE_NT_OPTIONAL_HDR_MAGIC
) ||
211 (OptionalHeader
->Subsystem
!= 1) || // native
212 (OptionalHeader
->ImageBase
!= FREELDR_PE_BASE
) ||
213 (OptionalHeader
->SizeOfImage
> MAX_FREELDR_PE_SIZE
) ||
214 (OptionalHeader
->SectionAlignment
!= OptionalHeader
->FileAlignment
))
216 ERR("FreeLdr OptionalHeader is invalid.\n");
217 FrLdrBugCheckWithMessage(
218 FREELDR_IMAGE_CORRUPTION
,
221 "FreeLdr OptionalHeader is invalid.\n"
222 "Magic == 0x%lx, expected 0x%lx\n"
223 "Subsystem == 0x%lx, expected 1 (native)\n"
224 "ImageBase == 0x%lx, expected 0x%lx\n"
225 "SizeOfImage == 0x%lx, maximum 0x%lx\n"
226 "SectionAlignment 0x%lx doesn't match FileAlignment 0x%lx\n",
227 OptionalHeader
->Magic
, IMAGE_NT_OPTIONAL_HDR_MAGIC
,
228 OptionalHeader
->Subsystem
,
229 OptionalHeader
->ImageBase
, FREELDR_PE_BASE
,
230 OptionalHeader
->SizeOfImage
, MAX_FREELDR_PE_SIZE
,
231 OptionalHeader
->SectionAlignment
, OptionalHeader
->FileAlignment
);
235 BOOLEAN
MmInitializeMemoryManager(VOID
)
238 const FREELDR_MEMORY_DESCRIPTOR
* MemoryDescriptor
= NULL
;
241 TRACE("Initializing Memory Manager.\n");
243 /* Check the freeldr binary */
244 MmCheckFreeldrImageFile();
246 BiosMemoryMap
= MachVtbl
.GetMemoryMap(&BiosMemoryMapEntryCount
);
249 // Dump the system memory map
250 TRACE("System Memory Map (Base Address, Length, Type):\n");
251 while ((MemoryDescriptor
= ArcGetMemoryDescriptor(MemoryDescriptor
)) != NULL
)
253 TRACE("%x\t %x\t %s\n",
254 MemoryDescriptor
->BasePage
* MM_PAGE_SIZE
,
255 MemoryDescriptor
->PageCount
* MM_PAGE_SIZE
,
256 MmGetSystemMemoryMapTypeString(MemoryDescriptor
->MemoryType
));
260 // Find address for the page lookup table
261 TotalPagesInLookupTable
= MmGetAddressablePageCountIncludingHoles();
262 PageLookupTableAddress
= MmFindLocationForPageLookupTable(TotalPagesInLookupTable
);
263 LastFreePageHint
= MmHighestPhysicalPage
;
265 if (PageLookupTableAddress
== 0)
267 // If we get here then we probably couldn't
268 // find a contiguous chunk of memory big
269 // enough to hold the page lookup table
270 printf("Error initializing memory manager!\n");
274 // Initialize the page lookup table
275 MmInitPageLookupTable(PageLookupTableAddress
, TotalPagesInLookupTable
);
277 MmUpdateLastFreePageHint(PageLookupTableAddress
, TotalPagesInLookupTable
);
279 FreePagesInLookupTable
= MmCountFreePagesInLookupTable(PageLookupTableAddress
,
280 TotalPagesInLookupTable
);
282 MmInitializeHeap(PageLookupTableAddress
);
284 TRACE("Memory Manager initialized. 0x%x pages available.\n", FreePagesInLookupTable
);
291 PCSTR
MmGetSystemMemoryMapTypeString(TYPE_OF_MEMORY Type
)
295 for (Index
=1; Index
<MemoryTypeCount
; Index
++)
297 if (MemoryTypeArray
[Index
].Type
== Type
)
299 return MemoryTypeArray
[Index
].TypeString
;
303 return MemoryTypeArray
[0].TypeString
;
307 PFN_NUMBER
MmGetPageNumberFromAddress(PVOID Address
)
309 return ((ULONG_PTR
)Address
) / MM_PAGE_SIZE
;
312 PFN_NUMBER
MmGetAddressablePageCountIncludingHoles(VOID
)
314 const FREELDR_MEMORY_DESCRIPTOR
* MemoryDescriptor
= NULL
;
315 PFN_NUMBER PageCount
;
318 // Go through the whole memory map to get max address
320 while ((MemoryDescriptor
= ArcGetMemoryDescriptor(MemoryDescriptor
)) != NULL
)
323 // Check if we got a higher end page address
325 if (MemoryDescriptor
->BasePage
+ MemoryDescriptor
->PageCount
> MmHighestPhysicalPage
)
328 // Yes, remember it if this is real memory
330 if (MemoryDescriptor
->MemoryType
== LoaderFree
)
331 MmHighestPhysicalPage
= MemoryDescriptor
->BasePage
+ MemoryDescriptor
->PageCount
;
335 // Check if we got a higher (usable) start page address
337 if (MemoryDescriptor
->BasePage
< MmLowestPhysicalPage
)
340 // Yes, remember it if this is real memory
342 MmLowestPhysicalPage
= MemoryDescriptor
->BasePage
;
346 TRACE("lo/hi %lx %lx\n", MmLowestPhysicalPage
, MmHighestPhysicalPage
);
347 PageCount
= MmHighestPhysicalPage
- MmLowestPhysicalPage
;
348 TRACE("MmGetAddressablePageCountIncludingHoles() returning 0x%x\n", PageCount
);
352 PVOID
MmFindLocationForPageLookupTable(PFN_NUMBER TotalPageCount
)
354 const FREELDR_MEMORY_DESCRIPTOR
* MemoryDescriptor
= NULL
;
355 SIZE_T PageLookupTableSize
;
356 PFN_NUMBER PageLookupTablePages
;
357 PFN_NUMBER PageLookupTableStartPage
= 0;
358 PVOID PageLookupTableMemAddress
= NULL
;
360 // Calculate how much pages we need to keep the page lookup table
361 PageLookupTableSize
= TotalPageCount
* sizeof(PAGE_LOOKUP_TABLE_ITEM
);
362 PageLookupTablePages
= PageLookupTableSize
/ MM_PAGE_SIZE
;
364 // Search the highest memory block big enough to contain lookup table
365 while ((MemoryDescriptor
= ArcGetMemoryDescriptor(MemoryDescriptor
)) != NULL
)
367 // Continue, if memory is not free
368 if (MemoryDescriptor
->MemoryType
!= LoaderFree
) continue;
370 // Continue, if the block is not big enough?
371 if (MemoryDescriptor
->PageCount
< PageLookupTablePages
) continue;
373 // Continue, if it is not at a higher address than previous address
374 if (MemoryDescriptor
->BasePage
< PageLookupTableStartPage
) continue;
376 // Continue, if the address is too high
377 if (MemoryDescriptor
->BasePage
>= MM_MAX_PAGE
) continue;
379 // Memory block is more suitable than the previous one
380 PageLookupTableStartPage
= MemoryDescriptor
->BasePage
;
381 PageLookupTableMemAddress
= (PVOID
)((ULONG_PTR
)
382 (MemoryDescriptor
->BasePage
+ MemoryDescriptor
->PageCount
) * MM_PAGE_SIZE
383 - PageLookupTableSize
);
386 TRACE("MmFindLocationForPageLookupTable() returning 0x%x\n", PageLookupTableMemAddress
);
388 return PageLookupTableMemAddress
;
391 VOID
MmInitPageLookupTable(PVOID PageLookupTable
, PFN_NUMBER TotalPageCount
)
393 const FREELDR_MEMORY_DESCRIPTOR
* MemoryDescriptor
= NULL
;
394 PFN_NUMBER PageLookupTableStartPage
;
395 PFN_NUMBER PageLookupTablePageCount
;
397 TRACE("MmInitPageLookupTable()\n");
399 // Mark every page as allocated initially
400 // We will go through and mark pages again according to the memory map
401 // But this will mark any holes not described in the map as allocated
402 MmMarkPagesInLookupTable(PageLookupTable
, MmLowestPhysicalPage
, TotalPageCount
, LoaderFirmwarePermanent
);
404 // Parse the whole memory map
405 while ((MemoryDescriptor
= ArcGetMemoryDescriptor(MemoryDescriptor
)) != NULL
)
407 // Mark used pages in the lookup table
409 if (MemoryDescriptor
->BasePage
+ MemoryDescriptor
->PageCount
<= TotalPageCount
)
411 TRACE("Marking pages 0x%lx-0x%lx as type %s\n",
412 MemoryDescriptor
->BasePage
,
413 MemoryDescriptor
->BasePage
+ MemoryDescriptor
->PageCount
,
414 MmGetSystemMemoryMapTypeString(MemoryDescriptor
->MemoryType
));
415 MmMarkPagesInLookupTable(PageLookupTable
,
416 MemoryDescriptor
->BasePage
,
417 MemoryDescriptor
->PageCount
,
418 MemoryDescriptor
->MemoryType
);
421 TRACE("Ignoring pages 0x%lx-0x%lx (%s)\n",
422 MemoryDescriptor
->BasePage
,
423 MemoryDescriptor
->BasePage
+ MemoryDescriptor
->PageCount
,
424 MmGetSystemMemoryMapTypeString(MemoryDescriptor
->MemoryType
));
427 // Mark the pages that the lookup table occupies as reserved
428 PageLookupTableStartPage
= MmGetPageNumberFromAddress(PageLookupTable
);
429 PageLookupTablePageCount
= MmGetPageNumberFromAddress((PVOID
)((ULONG_PTR
)PageLookupTable
+ ROUND_UP(TotalPageCount
* sizeof(PAGE_LOOKUP_TABLE_ITEM
), MM_PAGE_SIZE
))) - PageLookupTableStartPage
;
430 TRACE("Marking the page lookup table pages as reserved StartPage: 0x%x PageCount: 0x%x\n", PageLookupTableStartPage
, PageLookupTablePageCount
);
431 MmMarkPagesInLookupTable(PageLookupTable
, PageLookupTableStartPage
, PageLookupTablePageCount
, LoaderFirmwareTemporary
);
434 VOID
MmMarkPagesInLookupTable(PVOID PageLookupTable
, PFN_NUMBER StartPage
, PFN_NUMBER PageCount
, TYPE_OF_MEMORY PageAllocated
)
436 PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable
= (PPAGE_LOOKUP_TABLE_ITEM
)PageLookupTable
;
438 TRACE("MmMarkPagesInLookupTable()\n");
440 /* Validate the range */
441 if ((StartPage
< MmLowestPhysicalPage
) ||
442 ((StartPage
+ PageCount
- 1) > MmHighestPhysicalPage
))
444 ERR("Memory (0x%lx:0x%lx) outside of lookup table! Valid range: 0x%lx-0x%lx.\n",
445 StartPage
, PageCount
, MmLowestPhysicalPage
, MmHighestPhysicalPage
);
449 StartPage
-= MmLowestPhysicalPage
;
450 for (Index
=StartPage
; Index
<(StartPage
+PageCount
); Index
++)
453 if ((Index
<= (StartPage
+ 16)) || (Index
>= (StartPage
+PageCount
-16)))
455 TRACE("Index = 0x%x StartPage = 0x%x PageCount = 0x%x\n", Index
, StartPage
, PageCount
);
458 RealPageLookupTable
[Index
].PageAllocated
= PageAllocated
;
459 RealPageLookupTable
[Index
].PageAllocationLength
= (PageAllocated
!= LoaderFree
) ? 1 : 0;
461 TRACE("MmMarkPagesInLookupTable() Done\n");
464 VOID
MmAllocatePagesInLookupTable(PVOID PageLookupTable
, PFN_NUMBER StartPage
, PFN_NUMBER PageCount
, TYPE_OF_MEMORY MemoryType
)
466 PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable
= (PPAGE_LOOKUP_TABLE_ITEM
)PageLookupTable
;
469 StartPage
-= MmLowestPhysicalPage
;
470 for (Index
=StartPage
; Index
<(StartPage
+PageCount
); Index
++)
472 RealPageLookupTable
[Index
].PageAllocated
= MemoryType
;
473 RealPageLookupTable
[Index
].PageAllocationLength
= (Index
== StartPage
) ? PageCount
: 0;
477 PFN_NUMBER
MmCountFreePagesInLookupTable(PVOID PageLookupTable
, PFN_NUMBER TotalPageCount
)
479 PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable
= (PPAGE_LOOKUP_TABLE_ITEM
)PageLookupTable
;
481 PFN_NUMBER FreePageCount
;
484 for (Index
=0; Index
<TotalPageCount
; Index
++)
486 if (RealPageLookupTable
[Index
].PageAllocated
== LoaderFree
)
492 return FreePageCount
;
495 PFN_NUMBER
MmFindAvailablePages(PVOID PageLookupTable
, PFN_NUMBER TotalPageCount
, PFN_NUMBER PagesNeeded
, BOOLEAN FromEnd
)
497 PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable
= (PPAGE_LOOKUP_TABLE_ITEM
)PageLookupTable
;
498 PFN_NUMBER AvailablePagesSoFar
;
501 if (LastFreePageHint
> TotalPageCount
)
503 LastFreePageHint
= TotalPageCount
;
506 AvailablePagesSoFar
= 0;
509 /* Allocate "high" (from end) pages */
510 for (Index
=LastFreePageHint
-1; Index
>0; Index
--)
512 if (RealPageLookupTable
[Index
].PageAllocated
!= LoaderFree
)
514 AvailablePagesSoFar
= 0;
519 AvailablePagesSoFar
++;
522 if (AvailablePagesSoFar
>= PagesNeeded
)
524 return Index
+ MmLowestPhysicalPage
;
530 TRACE("Alloc low memory, LastFreePageHint 0x%x, TPC 0x%x\n", LastFreePageHint
, TotalPageCount
);
531 /* Allocate "low" pages */
532 for (Index
=1; Index
< LastFreePageHint
; Index
++)
534 if (RealPageLookupTable
[Index
].PageAllocated
!= LoaderFree
)
536 AvailablePagesSoFar
= 0;
541 AvailablePagesSoFar
++;
544 if (AvailablePagesSoFar
>= PagesNeeded
)
546 return Index
- AvailablePagesSoFar
+ 1 + MmLowestPhysicalPage
;
554 PFN_NUMBER
MmFindAvailablePagesBeforePage(PVOID PageLookupTable
, PFN_NUMBER TotalPageCount
, PFN_NUMBER PagesNeeded
, PFN_NUMBER LastPage
)
556 PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable
= (PPAGE_LOOKUP_TABLE_ITEM
)PageLookupTable
;
557 PFN_NUMBER AvailablePagesSoFar
;
560 if (LastPage
> TotalPageCount
)
562 return MmFindAvailablePages(PageLookupTable
, TotalPageCount
, PagesNeeded
, TRUE
);
565 AvailablePagesSoFar
= 0;
566 for (Index
=LastPage
-1; Index
>0; Index
--)
568 if (RealPageLookupTable
[Index
].PageAllocated
!= LoaderFree
)
570 AvailablePagesSoFar
= 0;
575 AvailablePagesSoFar
++;
578 if (AvailablePagesSoFar
>= PagesNeeded
)
580 return Index
+ MmLowestPhysicalPage
;
587 VOID
MmUpdateLastFreePageHint(PVOID PageLookupTable
, PFN_NUMBER TotalPageCount
)
589 PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable
= (PPAGE_LOOKUP_TABLE_ITEM
)PageLookupTable
;
592 for (Index
=TotalPageCount
-1; Index
>0; Index
--)
594 if (RealPageLookupTable
[Index
].PageAllocated
== LoaderFree
)
596 LastFreePageHint
= Index
+ 1 + MmLowestPhysicalPage
;
602 BOOLEAN
MmAreMemoryPagesAvailable(PVOID PageLookupTable
, PFN_NUMBER TotalPageCount
, PVOID PageAddress
, PFN_NUMBER PageCount
)
604 PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable
= (PPAGE_LOOKUP_TABLE_ITEM
)PageLookupTable
;
605 PFN_NUMBER StartPage
;
608 StartPage
= MmGetPageNumberFromAddress(PageAddress
);
610 if (StartPage
< MmLowestPhysicalPage
) return FALSE
;
612 StartPage
-= MmLowestPhysicalPage
;
614 // Make sure they aren't trying to go past the
615 // end of availabe memory
616 if ((StartPage
+ PageCount
) > TotalPageCount
)
621 for (Index
= StartPage
; Index
< (StartPage
+ PageCount
); Index
++)
623 // If this page is allocated then there obviously isn't
624 // memory availabe so return FALSE
625 if (RealPageLookupTable
[Index
].PageAllocated
!= LoaderFree
)