Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenmeminit.c
Go to the documentation of this file.
00001 /* 00002 * FreeLoader 00003 * Copyright (C) 2006-2008 Aleksey Bragin <aleksey@reactos.org> 00004 * Copyright (C) 2006-2009 Hervé Poussineau <hpoussin@reactos.org> 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2 of the License, or 00009 * (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License along 00017 * with this program; if not, write to the Free Software Foundation, Inc., 00018 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00019 */ 00020 00021 #include <freeldr.h> 00022 #include <debug.h> 00023 00024 DBG_DEFAULT_CHANNEL(MEMORY); 00025 00026 #if DBG 00027 typedef struct 00028 { 00029 TYPE_OF_MEMORY Type; 00030 PCSTR TypeString; 00031 } FREELDR_MEMORY_TYPE, *PFREELDR_MEMORY_TYPE; 00032 00033 FREELDR_MEMORY_TYPE MemoryTypeArray[] = 00034 { 00035 { LoaderMaximum, "Unknown memory" }, 00036 { LoaderFree, "Free memory" }, 00037 { LoaderBad, "Bad memory" }, 00038 { LoaderLoadedProgram, "LoadedProgram" }, 00039 { LoaderFirmwareTemporary, "FirmwareTemporary" }, 00040 { LoaderFirmwarePermanent, "FirmwarePermanent" }, 00041 { LoaderOsloaderHeap, "OsloaderHeap" }, 00042 { LoaderOsloaderStack, "OsloaderStack" }, 00043 { LoaderSystemCode, "SystemCode" }, 00044 { LoaderHalCode, "HalCode" }, 00045 { LoaderBootDriver, "BootDriver" }, 00046 { LoaderRegistryData, "RegistryData" }, 00047 { LoaderMemoryData, "MemoryData" }, 00048 { LoaderNlsData, "NlsData" }, 00049 { LoaderSpecialMemory, "SpecialMemory" }, 00050 { LoaderReserve, "Reserve" }, 00051 }; 00052 ULONG MemoryTypeCount = sizeof(MemoryTypeArray) / sizeof(MemoryTypeArray[0]); 00053 #endif 00054 00055 PVOID PageLookupTableAddress = NULL; 00056 PFN_NUMBER TotalPagesInLookupTable = 0; 00057 PFN_NUMBER FreePagesInLookupTable = 0; 00058 PFN_NUMBER LastFreePageHint = 0; 00059 PFN_NUMBER MmLowestPhysicalPage = 0xFFFFFFFF; 00060 PFN_NUMBER MmHighestPhysicalPage = 0; 00061 00062 PFREELDR_MEMORY_DESCRIPTOR BiosMemoryMap; 00063 ULONG BiosMemoryMapEntryCount; 00064 00065 extern ULONG_PTR MmHeapPointer; 00066 extern ULONG_PTR MmHeapStart; 00067 00068 ULONG 00069 AddMemoryDescriptor( 00070 IN OUT PFREELDR_MEMORY_DESCRIPTOR List, 00071 IN ULONG MaxCount, 00072 IN PFN_NUMBER BasePage, 00073 IN PFN_NUMBER PageCount, 00074 IN TYPE_OF_MEMORY MemoryType) 00075 { 00076 ULONG i, c; 00077 PFN_NUMBER NextBase; 00078 TRACE("AddMemoryDescriptor(0x%lx-0x%lx [0x%lx pages])\n", 00079 BasePage, BasePage + PageCount, PageCount); 00080 00081 /* Scan through all existing descriptors */ 00082 for (i = 0, c = 0; (c < MaxCount) && (List[c].PageCount != 0); c++) 00083 { 00084 /* Count entries completely below the new range */ 00085 if (List[i].BasePage + List[i].PageCount <= BasePage) i++; 00086 } 00087 00088 /* Check if the list is full */ 00089 if (c >= MaxCount) return c; 00090 00091 /* Is there an existing descriptor starting before the new range */ 00092 while ((i < c) && (List[i].BasePage <= BasePage)) 00093 { 00094 /* The end of the existing one is the minimum for the new range */ 00095 NextBase = List[i].BasePage + List[i].PageCount; 00096 00097 /* Bail out, if everything is trimmed away */ 00098 if ((BasePage + PageCount) <= NextBase) return c; 00099 00100 /* Trim the naew range at the lower end */ 00101 PageCount -= (NextBase - BasePage); 00102 BasePage = NextBase; 00103 00104 /* Go to the next entry and repeat */ 00105 i++; 00106 } 00107 00108 ASSERT(PageCount > 0); 00109 00110 /* Are there still entries above? */ 00111 if (i < c) 00112 { 00113 /* Shift the following entries one up */ 00114 RtlMoveMemory(&List[i+1], &List[i], (c - i) * sizeof(List[0])); 00115 00116 /* Insert the new range */ 00117 List[i].BasePage = BasePage; 00118 List[i].PageCount = min(PageCount, List[i+1].BasePage - BasePage); 00119 List[i].MemoryType = MemoryType; 00120 c++; 00121 00122 TRACE("Inserting at i=%ld: (0x%lx:0x%lx)\n", 00123 i, List[i].BasePage, List[i].PageCount); 00124 00125 /* Check if the range was trimmed */ 00126 if (PageCount > List[i].PageCount) 00127 { 00128 /* Recursively process the trimmed part */ 00129 c = AddMemoryDescriptor(List, 00130 MaxCount, 00131 BasePage + List[i].PageCount, 00132 PageCount - List[i].PageCount, 00133 MemoryType); 00134 } 00135 } 00136 else 00137 { 00138 /* We can simply add the range here */ 00139 TRACE("Adding i=%ld: (0x%lx:0x%lx)\n", i, BasePage, PageCount); 00140 List[i].BasePage = BasePage; 00141 List[i].PageCount = PageCount; 00142 List[i].MemoryType = MemoryType; 00143 c++; 00144 } 00145 00146 /* Return the new count */ 00147 return c; 00148 } 00149 00150 const FREELDR_MEMORY_DESCRIPTOR* 00151 ArcGetMemoryDescriptor(const FREELDR_MEMORY_DESCRIPTOR* Current) 00152 { 00153 if (Current == NULL) 00154 { 00155 return BiosMemoryMap; 00156 } 00157 else 00158 { 00159 Current++; 00160 if (Current->PageCount == 0) return NULL; 00161 return Current; 00162 } 00163 } 00164 00165 00166 BOOLEAN MmInitializeMemoryManager(VOID) 00167 { 00168 #if DBG 00169 const FREELDR_MEMORY_DESCRIPTOR* MemoryDescriptor = NULL; 00170 #endif 00171 00172 TRACE("Initializing Memory Manager.\n"); 00173 00174 BiosMemoryMap = MachVtbl.GetMemoryMap(&BiosMemoryMapEntryCount); 00175 00176 #if DBG 00177 // Dump the system memory map 00178 TRACE("System Memory Map (Base Address, Length, Type):\n"); 00179 while ((MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor)) != NULL) 00180 { 00181 TRACE("%x\t %x\t %s\n", 00182 MemoryDescriptor->BasePage * MM_PAGE_SIZE, 00183 MemoryDescriptor->PageCount * MM_PAGE_SIZE, 00184 MmGetSystemMemoryMapTypeString(MemoryDescriptor->MemoryType)); 00185 } 00186 #endif 00187 00188 // Find address for the page lookup table 00189 TotalPagesInLookupTable = MmGetAddressablePageCountIncludingHoles(); 00190 PageLookupTableAddress = MmFindLocationForPageLookupTable(TotalPagesInLookupTable); 00191 LastFreePageHint = MmHighestPhysicalPage; 00192 00193 if (PageLookupTableAddress == 0) 00194 { 00195 // If we get here then we probably couldn't 00196 // find a contiguous chunk of memory big 00197 // enough to hold the page lookup table 00198 printf("Error initializing memory manager!\n"); 00199 return FALSE; 00200 } 00201 00202 // Initialize the page lookup table 00203 MmInitPageLookupTable(PageLookupTableAddress, TotalPagesInLookupTable); 00204 00205 MmUpdateLastFreePageHint(PageLookupTableAddress, TotalPagesInLookupTable); 00206 00207 FreePagesInLookupTable = MmCountFreePagesInLookupTable(PageLookupTableAddress, 00208 TotalPagesInLookupTable); 00209 00210 MmInitializeHeap(PageLookupTableAddress); 00211 00212 TRACE("Memory Manager initialized. 0x%x pages available.\n", FreePagesInLookupTable); 00213 00214 00215 return TRUE; 00216 } 00217 00218 #if DBG 00219 PCSTR MmGetSystemMemoryMapTypeString(TYPE_OF_MEMORY Type) 00220 { 00221 ULONG Index; 00222 00223 for (Index=1; Index<MemoryTypeCount; Index++) 00224 { 00225 if (MemoryTypeArray[Index].Type == Type) 00226 { 00227 return MemoryTypeArray[Index].TypeString; 00228 } 00229 } 00230 00231 return MemoryTypeArray[0].TypeString; 00232 } 00233 #endif 00234 00235 PFN_NUMBER MmGetPageNumberFromAddress(PVOID Address) 00236 { 00237 return ((ULONG_PTR)Address) / MM_PAGE_SIZE; 00238 } 00239 00240 PFN_NUMBER MmGetAddressablePageCountIncludingHoles(VOID) 00241 { 00242 const FREELDR_MEMORY_DESCRIPTOR* MemoryDescriptor = NULL; 00243 PFN_NUMBER PageCount; 00244 00245 // 00246 // Go through the whole memory map to get max address 00247 // 00248 while ((MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor)) != NULL) 00249 { 00250 // 00251 // Check if we got a higher end page address 00252 // 00253 if (MemoryDescriptor->BasePage + MemoryDescriptor->PageCount > MmHighestPhysicalPage) 00254 { 00255 // 00256 // Yes, remember it if this is real memory 00257 // 00258 if (MemoryDescriptor->MemoryType == LoaderFree) 00259 MmHighestPhysicalPage = MemoryDescriptor->BasePage + MemoryDescriptor->PageCount; 00260 } 00261 00262 // 00263 // Check if we got a higher (usable) start page address 00264 // 00265 if (MemoryDescriptor->BasePage < MmLowestPhysicalPage) 00266 { 00267 // 00268 // Yes, remember it if this is real memory 00269 // 00270 MmLowestPhysicalPage = MemoryDescriptor->BasePage; 00271 } 00272 } 00273 00274 TRACE("lo/hi %lx %lx\n", MmLowestPhysicalPage, MmHighestPhysicalPage); 00275 PageCount = MmHighestPhysicalPage - MmLowestPhysicalPage; 00276 TRACE("MmGetAddressablePageCountIncludingHoles() returning 0x%x\n", PageCount); 00277 return PageCount; 00278 } 00279 00280 PVOID MmFindLocationForPageLookupTable(PFN_NUMBER TotalPageCount) 00281 { 00282 const FREELDR_MEMORY_DESCRIPTOR* MemoryDescriptor = NULL; 00283 SIZE_T PageLookupTableSize; 00284 PFN_NUMBER PageLookupTablePages; 00285 PFN_NUMBER PageLookupTableStartPage = 0; 00286 PVOID PageLookupTableMemAddress = NULL; 00287 00288 // Calculate how much pages we need to keep the page lookup table 00289 PageLookupTableSize = TotalPageCount * sizeof(PAGE_LOOKUP_TABLE_ITEM); 00290 PageLookupTablePages = PageLookupTableSize / MM_PAGE_SIZE; 00291 00292 // Search the highest memory block big enough to contain lookup table 00293 while ((MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor)) != NULL) 00294 { 00295 // Continue, if memory is not free 00296 if (MemoryDescriptor->MemoryType != LoaderFree) continue; 00297 00298 // Continue, if the block is not big enough? 00299 if (MemoryDescriptor->PageCount < PageLookupTablePages) continue; 00300 00301 // Continue, if it is not at a higher address than previous address 00302 if (MemoryDescriptor->BasePage < PageLookupTableStartPage) continue; 00303 00304 // Continue, if the address is too high 00305 if (MemoryDescriptor->BasePage >= MM_MAX_PAGE) continue; 00306 00307 // Memory block is more suitable than the previous one 00308 PageLookupTableStartPage = MemoryDescriptor->BasePage; 00309 PageLookupTableMemAddress = (PVOID)((ULONG_PTR) 00310 (MemoryDescriptor->BasePage + MemoryDescriptor->PageCount) * MM_PAGE_SIZE 00311 - PageLookupTableSize); 00312 } 00313 00314 TRACE("MmFindLocationForPageLookupTable() returning 0x%x\n", PageLookupTableMemAddress); 00315 00316 return PageLookupTableMemAddress; 00317 } 00318 00319 VOID MmInitPageLookupTable(PVOID PageLookupTable, PFN_NUMBER TotalPageCount) 00320 { 00321 const FREELDR_MEMORY_DESCRIPTOR* MemoryDescriptor = NULL; 00322 PFN_NUMBER PageLookupTableStartPage; 00323 PFN_NUMBER PageLookupTablePageCount; 00324 00325 TRACE("MmInitPageLookupTable()\n"); 00326 00327 // Mark every page as allocated initially 00328 // We will go through and mark pages again according to the memory map 00329 // But this will mark any holes not described in the map as allocated 00330 MmMarkPagesInLookupTable(PageLookupTable, MmLowestPhysicalPage, TotalPageCount, LoaderFirmwarePermanent); 00331 00332 // Parse the whole memory map 00333 while ((MemoryDescriptor = ArcGetMemoryDescriptor(MemoryDescriptor)) != NULL) 00334 { 00335 // Mark used pages in the lookup table 00336 00337 if (MemoryDescriptor->BasePage + MemoryDescriptor->PageCount <= TotalPageCount) 00338 { 00339 TRACE("Marking pages 0x%lx-0x%lx as type %s\n", 00340 MemoryDescriptor->BasePage, 00341 MemoryDescriptor->BasePage + MemoryDescriptor->PageCount, 00342 MmGetSystemMemoryMapTypeString(MemoryDescriptor->MemoryType)); 00343 MmMarkPagesInLookupTable(PageLookupTable, 00344 MemoryDescriptor->BasePage, 00345 MemoryDescriptor->PageCount, 00346 MemoryDescriptor->MemoryType); 00347 } 00348 else 00349 TRACE("Ignoring pages 0x%lx-0x%lx (%s)\n", 00350 MemoryDescriptor->BasePage, 00351 MemoryDescriptor->BasePage + MemoryDescriptor->PageCount, 00352 MmGetSystemMemoryMapTypeString(MemoryDescriptor->MemoryType)); 00353 } 00354 00355 // Mark the pages that the lookup table occupies as reserved 00356 PageLookupTableStartPage = MmGetPageNumberFromAddress(PageLookupTable); 00357 PageLookupTablePageCount = MmGetPageNumberFromAddress((PVOID)((ULONG_PTR)PageLookupTable + ROUND_UP(TotalPageCount * sizeof(PAGE_LOOKUP_TABLE_ITEM), MM_PAGE_SIZE))) - PageLookupTableStartPage; 00358 TRACE("Marking the page lookup table pages as reserved StartPage: 0x%x PageCount: 0x%x\n", PageLookupTableStartPage, PageLookupTablePageCount); 00359 MmMarkPagesInLookupTable(PageLookupTable, PageLookupTableStartPage, PageLookupTablePageCount, LoaderFirmwareTemporary); 00360 } 00361 00362 VOID MmMarkPagesInLookupTable(PVOID PageLookupTable, PFN_NUMBER StartPage, PFN_NUMBER PageCount, TYPE_OF_MEMORY PageAllocated) 00363 { 00364 PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable; 00365 PFN_NUMBER Index; 00366 TRACE("MmMarkPagesInLookupTable()\n"); 00367 00368 /* Validate the range */ 00369 if ((StartPage < MmLowestPhysicalPage) || 00370 ((StartPage + PageCount - 1) > MmHighestPhysicalPage)) 00371 { 00372 ERR("Memory (0x%lx:0x%lx) outside of lookup table! Valid range: 0x%lx-0x%lx.\n", 00373 StartPage, PageCount, MmLowestPhysicalPage, MmHighestPhysicalPage); 00374 return; 00375 } 00376 00377 StartPage -= MmLowestPhysicalPage; 00378 for (Index=StartPage; Index<(StartPage+PageCount); Index++) 00379 { 00380 #if 0 00381 if ((Index <= (StartPage + 16)) || (Index >= (StartPage+PageCount-16))) 00382 { 00383 TRACE("Index = 0x%x StartPage = 0x%x PageCount = 0x%x\n", Index, StartPage, PageCount); 00384 } 00385 #endif 00386 RealPageLookupTable[Index].PageAllocated = PageAllocated; 00387 RealPageLookupTable[Index].PageAllocationLength = (PageAllocated != LoaderFree) ? 1 : 0; 00388 } 00389 TRACE("MmMarkPagesInLookupTable() Done\n"); 00390 } 00391 00392 VOID MmAllocatePagesInLookupTable(PVOID PageLookupTable, PFN_NUMBER StartPage, PFN_NUMBER PageCount, TYPE_OF_MEMORY MemoryType) 00393 { 00394 PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable; 00395 PFN_NUMBER Index; 00396 00397 StartPage -= MmLowestPhysicalPage; 00398 for (Index=StartPage; Index<(StartPage+PageCount); Index++) 00399 { 00400 RealPageLookupTable[Index].PageAllocated = MemoryType; 00401 RealPageLookupTable[Index].PageAllocationLength = (Index == StartPage) ? PageCount : 0; 00402 } 00403 } 00404 00405 PFN_NUMBER MmCountFreePagesInLookupTable(PVOID PageLookupTable, PFN_NUMBER TotalPageCount) 00406 { 00407 PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable; 00408 PFN_NUMBER Index; 00409 PFN_NUMBER FreePageCount; 00410 00411 FreePageCount = 0; 00412 for (Index=0; Index<TotalPageCount; Index++) 00413 { 00414 if (RealPageLookupTable[Index].PageAllocated == LoaderFree) 00415 { 00416 FreePageCount++; 00417 } 00418 } 00419 00420 return FreePageCount; 00421 } 00422 00423 PFN_NUMBER MmFindAvailablePages(PVOID PageLookupTable, PFN_NUMBER TotalPageCount, PFN_NUMBER PagesNeeded, BOOLEAN FromEnd) 00424 { 00425 PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable; 00426 PFN_NUMBER AvailablePagesSoFar; 00427 PFN_NUMBER Index; 00428 00429 if (LastFreePageHint > TotalPageCount) 00430 { 00431 LastFreePageHint = TotalPageCount; 00432 } 00433 00434 AvailablePagesSoFar = 0; 00435 if (FromEnd) 00436 { 00437 /* Allocate "high" (from end) pages */ 00438 for (Index=LastFreePageHint-1; Index>0; Index--) 00439 { 00440 if (RealPageLookupTable[Index].PageAllocated != LoaderFree) 00441 { 00442 AvailablePagesSoFar = 0; 00443 continue; 00444 } 00445 else 00446 { 00447 AvailablePagesSoFar++; 00448 } 00449 00450 if (AvailablePagesSoFar >= PagesNeeded) 00451 { 00452 return Index + MmLowestPhysicalPage; 00453 } 00454 } 00455 } 00456 else 00457 { 00458 TRACE("Alloc low memory, LastFreePageHint 0x%x, TPC 0x%x\n", LastFreePageHint, TotalPageCount); 00459 /* Allocate "low" pages */ 00460 for (Index=1; Index < LastFreePageHint; Index++) 00461 { 00462 if (RealPageLookupTable[Index].PageAllocated != LoaderFree) 00463 { 00464 AvailablePagesSoFar = 0; 00465 continue; 00466 } 00467 else 00468 { 00469 AvailablePagesSoFar++; 00470 } 00471 00472 if (AvailablePagesSoFar >= PagesNeeded) 00473 { 00474 return Index - AvailablePagesSoFar + 1 + MmLowestPhysicalPage; 00475 } 00476 } 00477 } 00478 00479 return 0; 00480 } 00481 00482 PFN_NUMBER MmFindAvailablePagesBeforePage(PVOID PageLookupTable, PFN_NUMBER TotalPageCount, PFN_NUMBER PagesNeeded, PFN_NUMBER LastPage) 00483 { 00484 PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable; 00485 PFN_NUMBER AvailablePagesSoFar; 00486 PFN_NUMBER Index; 00487 00488 if (LastPage > TotalPageCount) 00489 { 00490 return MmFindAvailablePages(PageLookupTable, TotalPageCount, PagesNeeded, TRUE); 00491 } 00492 00493 AvailablePagesSoFar = 0; 00494 for (Index=LastPage-1; Index>0; Index--) 00495 { 00496 if (RealPageLookupTable[Index].PageAllocated != LoaderFree) 00497 { 00498 AvailablePagesSoFar = 0; 00499 continue; 00500 } 00501 else 00502 { 00503 AvailablePagesSoFar++; 00504 } 00505 00506 if (AvailablePagesSoFar >= PagesNeeded) 00507 { 00508 return Index + MmLowestPhysicalPage; 00509 } 00510 } 00511 00512 return 0; 00513 } 00514 00515 VOID MmUpdateLastFreePageHint(PVOID PageLookupTable, PFN_NUMBER TotalPageCount) 00516 { 00517 PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable; 00518 PFN_NUMBER Index; 00519 00520 for (Index=TotalPageCount-1; Index>0; Index--) 00521 { 00522 if (RealPageLookupTable[Index].PageAllocated == LoaderFree) 00523 { 00524 LastFreePageHint = Index + 1 + MmLowestPhysicalPage; 00525 break; 00526 } 00527 } 00528 } 00529 00530 BOOLEAN MmAreMemoryPagesAvailable(PVOID PageLookupTable, PFN_NUMBER TotalPageCount, PVOID PageAddress, PFN_NUMBER PageCount) 00531 { 00532 PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable; 00533 PFN_NUMBER StartPage; 00534 PFN_NUMBER Index; 00535 00536 StartPage = MmGetPageNumberFromAddress(PageAddress); 00537 00538 if (StartPage < MmLowestPhysicalPage) return FALSE; 00539 00540 StartPage -= MmLowestPhysicalPage; 00541 00542 // Make sure they aren't trying to go past the 00543 // end of availabe memory 00544 if ((StartPage + PageCount) > TotalPageCount) 00545 { 00546 return FALSE; 00547 } 00548 00549 for (Index = StartPage; Index < (StartPage + PageCount); Index++) 00550 { 00551 // If this page is allocated then there obviously isn't 00552 // memory availabe so return FALSE 00553 if (RealPageLookupTable[Index].PageAllocated != LoaderFree) 00554 { 00555 return FALSE; 00556 } 00557 } 00558 00559 return TRUE; 00560 } Generated on Sat May 26 2012 04:18:03 for ReactOS by
1.7.6.1
|