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
);
26 PVOID PageLookupTableAddress
= NULL
;
27 PFN_NUMBER TotalPagesInLookupTable
= 0;
28 PFN_NUMBER FreePagesInLookupTable
= 0;
29 PFN_NUMBER LastFreePageHint
= 0;
30 PFN_NUMBER MmLowestPhysicalPage
= 0xFFFFFFFF;
31 PFN_NUMBER MmHighestPhysicalPage
= 0;
33 PFREELDR_MEMORY_DESCRIPTOR BiosMemoryMap
;
34 ULONG BiosMemoryMapEntryCount
;
35 SIZE_T FrLdrImageSize
;
42 } FREELDR_MEMORY_TYPE
, *PFREELDR_MEMORY_TYPE
;
44 FREELDR_MEMORY_TYPE MemoryTypeArray
[] =
46 { LoaderMaximum
, "Unknown memory" },
47 { LoaderFree
, "Free memory" },
48 { LoaderBad
, "Bad memory" },
49 { LoaderLoadedProgram
, "LoadedProgram" },
50 { LoaderFirmwareTemporary
, "FirmwareTemporary" },
51 { LoaderFirmwarePermanent
, "FirmwarePermanent" },
52 { LoaderOsloaderHeap
, "OsloaderHeap" },
53 { LoaderOsloaderStack
, "OsloaderStack" },
54 { LoaderSystemCode
, "SystemCode" },
55 { LoaderHalCode
, "HalCode" },
56 { LoaderBootDriver
, "BootDriver" },
57 { LoaderRegistryData
, "RegistryData" },
58 { LoaderMemoryData
, "MemoryData" },
59 { LoaderNlsData
, "NlsData" },
60 { LoaderSpecialMemory
, "SpecialMemory" },
61 { LoaderReserve
, "Reserve" },
63 ULONG MemoryTypeCount
= sizeof(MemoryTypeArray
) / sizeof(MemoryTypeArray
[0]);
66 MmGetSystemMemoryMapTypeString(
71 for (Index
= 1; Index
< MemoryTypeCount
; Index
++)
73 if (MemoryTypeArray
[Index
].Type
== Type
)
75 return MemoryTypeArray
[Index
].TypeString
;
79 return MemoryTypeArray
[0].TypeString
;
84 PFREELDR_MEMORY_DESCRIPTOR List
)
88 DbgPrint("Dumping Memory map:\n");
89 for (i
= 0; List
[i
].PageCount
!= 0; i
++)
91 DbgPrint("%02d %08x - %08x: %s\n",
93 List
[i
].BasePage
* PAGE_SIZE
,
94 (List
[i
].BasePage
+ List
[i
].PageCount
) * PAGE_SIZE
,
95 MmGetSystemMemoryMapTypeString(List
[i
].MemoryType
));
103 IN OUT PFREELDR_MEMORY_DESCRIPTOR List
,
105 IN PFN_NUMBER BasePage
,
106 IN PFN_NUMBER PageCount
,
107 IN TYPE_OF_MEMORY MemoryType
)
109 ULONG Index
, DescriptCount
;
111 TRACE("AddMemoryDescriptor(0x%Ix, 0x%Ix, %u)\n",
112 BasePage
, PageCount
, MemoryType
);
114 EndPage
= BasePage
+ PageCount
;
116 /* Skip over all descriptor below the new range */
118 while ((List
[Index
].PageCount
!= 0) &&
119 ((List
[Index
].BasePage
+ List
[Index
].PageCount
) <= BasePage
))
124 /* Count the descriptors */
125 DescriptCount
= Index
;
126 while (List
[DescriptCount
].PageCount
!= 0)
131 /* Check if the existing range conflicts with the new range */
132 while ((List
[Index
].PageCount
!= 0) &&
133 (List
[Index
].BasePage
< EndPage
))
135 TRACE("AddMemoryDescriptor conflict @%lu: new=[%lx:%lx], existing=[%lx,%lx]\n",
136 Index
, BasePage
, PageCount
, List
[Index
].BasePage
, List
[Index
].PageCount
);
139 * We have 4 overlapping cases:
141 * Case (a) (b) (c) (d)
142 * Existing range |---| |-----| |---| |---|
143 * New range |---| |---| |-----| |---|
147 /* Check if the existing range starts before the new range (a)/(b) */
148 if (List
[Index
].BasePage
< BasePage
)
150 /* Check if the existing range extends beyond the new range (b) */
151 if (List
[Index
].BasePage
+ List
[Index
].PageCount
> EndPage
)
153 /* Split the descriptor */
154 RtlMoveMemory(&List
[Index
+ 1],
156 (DescriptCount
- Index
) * sizeof(List
[0]));
157 List
[Index
+ 1].BasePage
= EndPage
;
158 List
[Index
+ 1].PageCount
= List
[Index
].BasePage
+
159 List
[Index
].PageCount
-
160 List
[Index
+ 1].BasePage
;
161 List
[Index
].PageCount
= BasePage
- List
[Index
].BasePage
;
168 /* Crop the existing range and continue with the next range */
169 List
[Index
].PageCount
= BasePage
- List
[Index
].BasePage
;
173 /* Check if the existing range is fully covered by the new range (c) */
174 else if ((List
[Index
].BasePage
+ List
[Index
].PageCount
) <=
177 /* Delete this descriptor */
178 RtlMoveMemory(&List
[Index
],
180 (DescriptCount
- Index
) * sizeof(List
[0]));
183 /* Otherwise the existing range ends after the new range (d) */
186 /* Crop the existing range at the start and bail out */
187 List
[Index
].PageCount
-= EndPage
- List
[Index
].BasePage
;
188 List
[Index
].BasePage
= EndPage
;
193 /* Make sure we can still add a new descriptor */
194 if (DescriptCount
>= MaxCount
)
196 FrLdrBugCheckWithMessage(
200 "Ran out of static memory descriptors!");
203 /* Insert the new descriptor */
204 if (Index
< DescriptCount
)
206 RtlMoveMemory(&List
[Index
+ 1],
208 (DescriptCount
- Index
) * sizeof(List
[0]));
211 List
[Index
].BasePage
= BasePage
;
212 List
[Index
].PageCount
= PageCount
;
213 List
[Index
].MemoryType
= MemoryType
;
216 #if 0 // only enable on demand!
217 DbgDumpMemoryMap(List
);
219 return DescriptCount
;
222 const FREELDR_MEMORY_DESCRIPTOR
*
223 ArcGetMemoryDescriptor(const FREELDR_MEMORY_DESCRIPTOR
* Current
)
227 return BiosMemoryMap
;
232 if (Current
->PageCount
== 0) return NULL
;
239 MmCheckFreeldrImageFile(VOID
)
241 PIMAGE_NT_HEADERS NtHeaders
;
242 PIMAGE_FILE_HEADER FileHeader
;
243 PIMAGE_OPTIONAL_HEADER OptionalHeader
;
245 /* Get the NT headers */
246 NtHeaders
= RtlImageNtHeader(&__ImageBase
);
249 ERR("Could not get NtHeaders!\n");
250 FrLdrBugCheckWithMessage(
251 FREELDR_IMAGE_CORRUPTION
,
254 "Could not get NtHeaders!\n");
257 /* Check the file header */
258 FileHeader
= &NtHeaders
->FileHeader
;
259 if ((FileHeader
->Machine
!= IMAGE_FILE_MACHINE_NATIVE
) ||
260 (FileHeader
->NumberOfSections
!= FREELDR_SECTION_COUNT
) ||
261 (FileHeader
->PointerToSymbolTable
!= 0) || // Symbols stripped
262 (FileHeader
->NumberOfSymbols
!= 0) || // "" ""
263 (FileHeader
->SizeOfOptionalHeader
!= sizeof(IMAGE_OPTIONAL_HEADER
)))
265 ERR("FreeLdr FileHeader is invalid.\n");
266 FrLdrBugCheckWithMessage(
267 FREELDR_IMAGE_CORRUPTION
,
270 "FreeLdr FileHeader is invalid.\n"
271 "Machine == 0x%lx, expected 0x%lx\n"
272 "NumberOfSections == 0x%lx, expected 0x%lx\n"
273 "PointerToSymbolTable == 0x%lx, expected 0\n"
274 "NumberOfSymbols == 0x%lx, expected 0\n"
275 "SizeOfOptionalHeader == 0x%lx, expected 0x%lx\n",
276 FileHeader
->Machine
, IMAGE_FILE_MACHINE_NATIVE
,
277 FileHeader
->NumberOfSections
, FREELDR_SECTION_COUNT
,
278 FileHeader
->PointerToSymbolTable
,
279 FileHeader
->NumberOfSymbols
,
280 FileHeader
->SizeOfOptionalHeader
, sizeof(IMAGE_OPTIONAL_HEADER
));
283 /* Check the optional header */
284 OptionalHeader
= &NtHeaders
->OptionalHeader
;
285 if ((OptionalHeader
->Magic
!= IMAGE_NT_OPTIONAL_HDR_MAGIC
) ||
286 (OptionalHeader
->Subsystem
!= IMAGE_SUBSYSTEM_NATIVE
) ||
287 (OptionalHeader
->ImageBase
!= FREELDR_PE_BASE
) ||
288 (OptionalHeader
->SizeOfImage
> MAX_FREELDR_PE_SIZE
) ||
289 (OptionalHeader
->SectionAlignment
!= OptionalHeader
->FileAlignment
))
291 ERR("FreeLdr OptionalHeader is invalid.\n");
292 FrLdrBugCheckWithMessage(
293 FREELDR_IMAGE_CORRUPTION
,
296 "FreeLdr OptionalHeader is invalid.\n"
297 "Magic == 0x%lx, expected 0x%lx\n"
298 "Subsystem == 0x%lx, expected 1 (native)\n"
299 "ImageBase == 0x%lx, expected 0x%lx\n"
300 "SizeOfImage == 0x%lx, maximum 0x%lx\n"
301 "SectionAlignment 0x%lx doesn't match FileAlignment 0x%lx\n",
302 OptionalHeader
->Magic
, IMAGE_NT_OPTIONAL_HDR_MAGIC
,
303 OptionalHeader
->Subsystem
,
304 OptionalHeader
->ImageBase
, FREELDR_PE_BASE
,
305 OptionalHeader
->SizeOfImage
, MAX_FREELDR_PE_SIZE
,
306 OptionalHeader
->SectionAlignment
, OptionalHeader
->FileAlignment
);
309 /* Calculate the full image size */
310 FrLdrImageSize
= (ULONG_PTR
)&__ImageBase
+ OptionalHeader
->SizeOfImage
- FREELDR_BASE
;
313 BOOLEAN
MmInitializeMemoryManager(VOID
)
316 const FREELDR_MEMORY_DESCRIPTOR
* MemoryDescriptor
= NULL
;
319 TRACE("Initializing Memory Manager.\n");
321 /* Check the freeldr binary */
322 MmCheckFreeldrImageFile();
324 BiosMemoryMap
= MachVtbl
.GetMemoryMap(&BiosMemoryMapEntryCount
);
327 // Dump the system memory map
328 TRACE("System Memory Map (Base Address, Length, Type):\n");
329 while ((MemoryDescriptor
= ArcGetMemoryDescriptor(MemoryDescriptor
)) != NULL
)
331 TRACE("%x\t %x\t %s\n",
332 MemoryDescriptor
->BasePage
* MM_PAGE_SIZE
,
333 MemoryDescriptor
->PageCount
* MM_PAGE_SIZE
,
334 MmGetSystemMemoryMapTypeString(MemoryDescriptor
->MemoryType
));
338 // Find address for the page lookup table
339 TotalPagesInLookupTable
= MmGetAddressablePageCountIncludingHoles();
340 PageLookupTableAddress
= MmFindLocationForPageLookupTable(TotalPagesInLookupTable
);
341 LastFreePageHint
= MmHighestPhysicalPage
;
343 if (PageLookupTableAddress
== 0)
345 // If we get here then we probably couldn't
346 // find a contiguous chunk of memory big
347 // enough to hold the page lookup table
348 printf("Error initializing memory manager!\n");
352 // Initialize the page lookup table
353 MmInitPageLookupTable(PageLookupTableAddress
, TotalPagesInLookupTable
);
355 MmUpdateLastFreePageHint(PageLookupTableAddress
, TotalPagesInLookupTable
);
357 FreePagesInLookupTable
= MmCountFreePagesInLookupTable(PageLookupTableAddress
,
358 TotalPagesInLookupTable
);
360 MmInitializeHeap(PageLookupTableAddress
);
362 TRACE("Memory Manager initialized. 0x%x pages available.\n", FreePagesInLookupTable
);
369 PFN_NUMBER
MmGetPageNumberFromAddress(PVOID Address
)
371 return ((ULONG_PTR
)Address
) / MM_PAGE_SIZE
;
374 PFN_NUMBER
MmGetAddressablePageCountIncludingHoles(VOID
)
376 const FREELDR_MEMORY_DESCRIPTOR
* MemoryDescriptor
= NULL
;
377 PFN_NUMBER PageCount
;
380 // Go through the whole memory map to get max address
382 while ((MemoryDescriptor
= ArcGetMemoryDescriptor(MemoryDescriptor
)) != NULL
)
385 // Check if we got a higher end page address
387 if (MemoryDescriptor
->BasePage
+ MemoryDescriptor
->PageCount
> MmHighestPhysicalPage
)
390 // Yes, remember it if this is real memory
392 if (MemoryDescriptor
->MemoryType
== LoaderFree
)
393 MmHighestPhysicalPage
= MemoryDescriptor
->BasePage
+ MemoryDescriptor
->PageCount
;
397 // Check if we got a higher (usable) start page address
399 if (MemoryDescriptor
->BasePage
< MmLowestPhysicalPage
)
402 // Yes, remember it if this is real memory
404 MmLowestPhysicalPage
= MemoryDescriptor
->BasePage
;
408 TRACE("lo/hi %lx %lx\n", MmLowestPhysicalPage
, MmHighestPhysicalPage
);
409 PageCount
= MmHighestPhysicalPage
- MmLowestPhysicalPage
;
410 TRACE("MmGetAddressablePageCountIncludingHoles() returning 0x%x\n", PageCount
);
414 PVOID
MmFindLocationForPageLookupTable(PFN_NUMBER TotalPageCount
)
416 const FREELDR_MEMORY_DESCRIPTOR
* MemoryDescriptor
= NULL
;
417 SIZE_T PageLookupTableSize
;
418 PFN_NUMBER PageLookupTablePages
;
419 PFN_NUMBER PageLookupTableStartPage
= 0;
420 PVOID PageLookupTableMemAddress
= NULL
;
422 // Calculate how much pages we need to keep the page lookup table
423 PageLookupTableSize
= TotalPageCount
* sizeof(PAGE_LOOKUP_TABLE_ITEM
);
424 PageLookupTablePages
= PageLookupTableSize
/ MM_PAGE_SIZE
;
426 // Search the highest memory block big enough to contain lookup table
427 while ((MemoryDescriptor
= ArcGetMemoryDescriptor(MemoryDescriptor
)) != NULL
)
429 // Continue, if memory is not free
430 if (MemoryDescriptor
->MemoryType
!= LoaderFree
) continue;
432 // Continue, if the block is not big enough?
433 if (MemoryDescriptor
->PageCount
< PageLookupTablePages
) continue;
435 // Continue, if it is not at a higher address than previous address
436 if (MemoryDescriptor
->BasePage
< PageLookupTableStartPage
) continue;
438 // Continue, if the address is too high
439 if (MemoryDescriptor
->BasePage
>= MM_MAX_PAGE
) continue;
441 // Memory block is more suitable than the previous one
442 PageLookupTableStartPage
= MemoryDescriptor
->BasePage
;
443 PageLookupTableMemAddress
= (PVOID
)((ULONG_PTR
)
444 (MemoryDescriptor
->BasePage
+ MemoryDescriptor
->PageCount
) * MM_PAGE_SIZE
445 - PageLookupTableSize
);
448 TRACE("MmFindLocationForPageLookupTable() returning 0x%x\n", PageLookupTableMemAddress
);
450 return PageLookupTableMemAddress
;
453 VOID
MmInitPageLookupTable(PVOID PageLookupTable
, PFN_NUMBER TotalPageCount
)
455 const FREELDR_MEMORY_DESCRIPTOR
* MemoryDescriptor
= NULL
;
456 PFN_NUMBER PageLookupTableStartPage
;
457 PFN_NUMBER PageLookupTablePageCount
;
459 TRACE("MmInitPageLookupTable()\n");
461 // Mark every page as allocated initially
462 // We will go through and mark pages again according to the memory map
463 // But this will mark any holes not described in the map as allocated
464 MmMarkPagesInLookupTable(PageLookupTable
, MmLowestPhysicalPage
, TotalPageCount
, LoaderFirmwarePermanent
);
466 // Parse the whole memory map
467 while ((MemoryDescriptor
= ArcGetMemoryDescriptor(MemoryDescriptor
)) != NULL
)
469 // Mark used pages in the lookup table
471 if (MemoryDescriptor
->BasePage
+ MemoryDescriptor
->PageCount
<= TotalPageCount
)
473 TRACE("Marking pages 0x%lx-0x%lx as type %s\n",
474 MemoryDescriptor
->BasePage
,
475 MemoryDescriptor
->BasePage
+ MemoryDescriptor
->PageCount
,
476 MmGetSystemMemoryMapTypeString(MemoryDescriptor
->MemoryType
));
477 MmMarkPagesInLookupTable(PageLookupTable
,
478 MemoryDescriptor
->BasePage
,
479 MemoryDescriptor
->PageCount
,
480 MemoryDescriptor
->MemoryType
);
483 TRACE("Ignoring pages 0x%lx-0x%lx (%s)\n",
484 MemoryDescriptor
->BasePage
,
485 MemoryDescriptor
->BasePage
+ MemoryDescriptor
->PageCount
,
486 MmGetSystemMemoryMapTypeString(MemoryDescriptor
->MemoryType
));
489 // Mark the pages that the lookup table occupies as reserved
490 PageLookupTableStartPage
= MmGetPageNumberFromAddress(PageLookupTable
);
491 PageLookupTablePageCount
= MmGetPageNumberFromAddress((PVOID
)((ULONG_PTR
)PageLookupTable
+ ROUND_UP(TotalPageCount
* sizeof(PAGE_LOOKUP_TABLE_ITEM
), MM_PAGE_SIZE
))) - PageLookupTableStartPage
;
492 TRACE("Marking the page lookup table pages as reserved StartPage: 0x%x PageCount: 0x%x\n", PageLookupTableStartPage
, PageLookupTablePageCount
);
493 MmMarkPagesInLookupTable(PageLookupTable
, PageLookupTableStartPage
, PageLookupTablePageCount
, LoaderFirmwareTemporary
);
496 VOID
MmMarkPagesInLookupTable(PVOID PageLookupTable
, PFN_NUMBER StartPage
, PFN_NUMBER PageCount
, TYPE_OF_MEMORY PageAllocated
)
498 PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable
= (PPAGE_LOOKUP_TABLE_ITEM
)PageLookupTable
;
500 TRACE("MmMarkPagesInLookupTable()\n");
502 /* Validate the range */
503 if ((StartPage
< MmLowestPhysicalPage
) ||
504 ((StartPage
+ PageCount
- 1) > MmHighestPhysicalPage
))
506 ERR("Memory (0x%lx:0x%lx) outside of lookup table! Valid range: 0x%lx-0x%lx.\n",
507 StartPage
, PageCount
, MmLowestPhysicalPage
, MmHighestPhysicalPage
);
511 StartPage
-= MmLowestPhysicalPage
;
512 for (Index
=StartPage
; Index
<(StartPage
+PageCount
); Index
++)
515 if ((Index
<= (StartPage
+ 16)) || (Index
>= (StartPage
+PageCount
-16)))
517 TRACE("Index = 0x%x StartPage = 0x%x PageCount = 0x%x\n", Index
, StartPage
, PageCount
);
520 RealPageLookupTable
[Index
].PageAllocated
= PageAllocated
;
521 RealPageLookupTable
[Index
].PageAllocationLength
= (PageAllocated
!= LoaderFree
) ? 1 : 0;
523 TRACE("MmMarkPagesInLookupTable() Done\n");
526 VOID
MmAllocatePagesInLookupTable(PVOID PageLookupTable
, PFN_NUMBER StartPage
, PFN_NUMBER PageCount
, TYPE_OF_MEMORY MemoryType
)
528 PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable
= (PPAGE_LOOKUP_TABLE_ITEM
)PageLookupTable
;
531 StartPage
-= MmLowestPhysicalPage
;
532 for (Index
=StartPage
; Index
<(StartPage
+PageCount
); Index
++)
534 RealPageLookupTable
[Index
].PageAllocated
= MemoryType
;
535 RealPageLookupTable
[Index
].PageAllocationLength
= (Index
== StartPage
) ? PageCount
: 0;
539 PFN_NUMBER
MmCountFreePagesInLookupTable(PVOID PageLookupTable
, PFN_NUMBER TotalPageCount
)
541 PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable
= (PPAGE_LOOKUP_TABLE_ITEM
)PageLookupTable
;
543 PFN_NUMBER FreePageCount
;
546 for (Index
=0; Index
<TotalPageCount
; Index
++)
548 if (RealPageLookupTable
[Index
].PageAllocated
== LoaderFree
)
554 return FreePageCount
;
557 PFN_NUMBER
MmFindAvailablePages(PVOID PageLookupTable
, PFN_NUMBER TotalPageCount
, PFN_NUMBER PagesNeeded
, BOOLEAN FromEnd
)
559 PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable
= (PPAGE_LOOKUP_TABLE_ITEM
)PageLookupTable
;
560 PFN_NUMBER AvailablePagesSoFar
;
563 if (LastFreePageHint
> TotalPageCount
)
565 LastFreePageHint
= TotalPageCount
;
568 AvailablePagesSoFar
= 0;
571 /* Allocate "high" (from end) pages */
572 for (Index
=LastFreePageHint
-1; Index
>0; Index
--)
574 if (RealPageLookupTable
[Index
].PageAllocated
!= LoaderFree
)
576 AvailablePagesSoFar
= 0;
581 AvailablePagesSoFar
++;
584 if (AvailablePagesSoFar
>= PagesNeeded
)
586 return Index
+ MmLowestPhysicalPage
;
592 TRACE("Alloc low memory, LastFreePageHint 0x%x, TPC 0x%x\n", LastFreePageHint
, TotalPageCount
);
593 /* Allocate "low" pages */
594 for (Index
=1; Index
< LastFreePageHint
; Index
++)
596 if (RealPageLookupTable
[Index
].PageAllocated
!= LoaderFree
)
598 AvailablePagesSoFar
= 0;
603 AvailablePagesSoFar
++;
606 if (AvailablePagesSoFar
>= PagesNeeded
)
608 return Index
- AvailablePagesSoFar
+ 1 + MmLowestPhysicalPage
;
616 PFN_NUMBER
MmFindAvailablePagesBeforePage(PVOID PageLookupTable
, PFN_NUMBER TotalPageCount
, PFN_NUMBER PagesNeeded
, PFN_NUMBER LastPage
)
618 PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable
= (PPAGE_LOOKUP_TABLE_ITEM
)PageLookupTable
;
619 PFN_NUMBER AvailablePagesSoFar
;
622 if (LastPage
> TotalPageCount
)
624 return MmFindAvailablePages(PageLookupTable
, TotalPageCount
, PagesNeeded
, TRUE
);
627 AvailablePagesSoFar
= 0;
628 for (Index
=LastPage
-1; Index
>0; Index
--)
630 if (RealPageLookupTable
[Index
].PageAllocated
!= LoaderFree
)
632 AvailablePagesSoFar
= 0;
637 AvailablePagesSoFar
++;
640 if (AvailablePagesSoFar
>= PagesNeeded
)
642 return Index
+ MmLowestPhysicalPage
;
649 VOID
MmUpdateLastFreePageHint(PVOID PageLookupTable
, PFN_NUMBER TotalPageCount
)
651 PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable
= (PPAGE_LOOKUP_TABLE_ITEM
)PageLookupTable
;
654 for (Index
=TotalPageCount
-1; Index
>0; Index
--)
656 if (RealPageLookupTable
[Index
].PageAllocated
== LoaderFree
)
658 LastFreePageHint
= Index
+ 1 + MmLowestPhysicalPage
;
664 BOOLEAN
MmAreMemoryPagesAvailable(PVOID PageLookupTable
, PFN_NUMBER TotalPageCount
, PVOID PageAddress
, PFN_NUMBER PageCount
)
666 PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable
= (PPAGE_LOOKUP_TABLE_ITEM
)PageLookupTable
;
667 PFN_NUMBER StartPage
;
670 StartPage
= MmGetPageNumberFromAddress(PageAddress
);
672 if (StartPage
< MmLowestPhysicalPage
) return FALSE
;
674 StartPage
-= MmLowestPhysicalPage
;
676 // Make sure they aren't trying to go past the
677 // end of available memory
678 if ((StartPage
+ PageCount
) > TotalPageCount
)
683 for (Index
= StartPage
; Index
< (StartPage
+ PageCount
); Index
++)
685 // If this page is allocated then there obviously isn't
686 // memory available so return FALSE
687 if (RealPageLookupTable
[Index
].PageAllocated
!= LoaderFree
)