Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenwlmemory.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: EFI Windows Loader 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: freeldr/winldr/wlmemory.c 00005 * PURPOSE: Memory related routines 00006 * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org) 00007 */ 00008 00009 /* INCLUDES ***************************************************************/ 00010 00011 #include <freeldr.h> 00012 00013 #include <debug.h> 00014 00015 DBG_DEFAULT_CHANNEL(WINDOWS); 00016 00017 extern ULONG LoaderPagesSpanned; 00018 00019 PCHAR MemTypeDesc[] = { 00020 "ExceptionBlock ", // ? 00021 "SystemBlock ", // ? 00022 "Free ", 00023 "Bad ", // used 00024 "LoadedProgram ", // == Free 00025 "FirmwareTemporary ", // == Free 00026 "FirmwarePermanent ", // == Bad 00027 "OsloaderHeap ", // used 00028 "OsloaderStack ", // == Free 00029 "SystemCode ", 00030 "HalCode ", 00031 "BootDriver ", // not used 00032 "ConsoleInDriver ", // ? 00033 "ConsoleOutDriver ", // ? 00034 "StartupDpcStack ", // ? 00035 "StartupKernelStack", // ? 00036 "StartupPanicStack ", // ? 00037 "StartupPcrPage ", // ? 00038 "StartupPdrPage ", // ? 00039 "RegistryData ", // used 00040 "MemoryData ", // not used 00041 "NlsData ", // used 00042 "SpecialMemory ", // == Bad 00043 "BBTMemory " // == Bad 00044 }; 00045 00046 static VOID 00047 WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, 00048 IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor); 00049 00050 extern PFREELDR_MEMORY_DESCRIPTOR BiosMemoryMap; 00051 extern ULONG BiosMemoryMapEntryCount; 00052 extern PFN_NUMBER MmLowestPhysicalPage; 00053 extern PFN_NUMBER MmHighestPhysicalPage; 00054 00055 /* GLOBALS ***************************************************************/ 00056 00057 MEMORY_ALLOCATION_DESCRIPTOR *Mad; 00058 ULONG MadCount = 0; 00059 /* 200 MADs fit into 1 page, that should really be enough! */ 00060 #define MAX_MAD_COUNT 200 00061 00062 /* FUNCTIONS **************************************************************/ 00063 00064 VOID 00065 MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, 00066 PFN_NUMBER BasePage, 00067 PFN_NUMBER PageCount, 00068 ULONG Type) 00069 { 00070 BOOLEAN Status = TRUE; 00071 00072 TRACE("MempAddMemoryBlock(BasePage=0x%lx, PageCount=0x%lx, Type=%ld)\n", 00073 BasePage, PageCount, Type); 00074 // 00075 // Check for memory block after 4GB - we don't support it yet 00076 // Note: Even last page before 4GB limit is not supported 00077 // 00078 if (BasePage >= MM_MAX_PAGE) 00079 { 00080 // 00081 // Just skip this, without even adding to MAD list 00082 // 00083 return; 00084 } 00085 00086 // 00087 // Check if last page is after 4GB limit and shorten this block if needed 00088 // 00089 if (BasePage + PageCount > MM_MAX_PAGE) 00090 { 00091 // 00092 // shorten this block 00093 // 00094 PageCount = MM_MAX_PAGE - BasePage; 00095 } 00096 00097 /* Check if we have slots left */ 00098 if (MadCount >= MAX_MAD_COUNT) 00099 { 00100 ERR("Error: no MAD slots left!\n"); 00101 return; 00102 } 00103 00104 /* Get rid of the loader heap */ 00105 //if (Type == LoaderOsloaderHeap) Type = LoaderFirmwareTemporary; 00106 00107 // 00108 // Set Base page, page count and type 00109 // 00110 Mad[MadCount].BasePage = BasePage; 00111 Mad[MadCount].PageCount = PageCount; 00112 Mad[MadCount].MemoryType = Type; 00113 00114 // 00115 // Add descriptor 00116 // 00117 WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]); 00118 MadCount++; 00119 00120 /* Make sure we don't map too high */ 00121 if (BasePage + PageCount > LoaderPagesSpanned) return; 00122 00123 /* Special handling for page 0 */ 00124 if (BasePage == 0) 00125 { 00126 /* If its only one page, ignore it! */ 00127 if (PageCount == 1) return; 00128 00129 /* Otherwise, skip first page */ 00130 BasePage++; 00131 PageCount--; 00132 } 00133 00134 switch (Type) 00135 { 00136 /* Pages used by the loader */ 00137 case LoaderLoadedProgram: 00138 case LoaderOsloaderStack: 00139 case LoaderFirmwareTemporary: 00140 /* Map these pages into user mode */ 00141 Status = MempSetupPaging(BasePage, PageCount, FALSE); 00142 break; 00143 00144 /* Pages used by the kernel */ 00145 case LoaderExceptionBlock: 00146 case LoaderSystemBlock: 00147 case LoaderFirmwarePermanent: 00148 case LoaderSystemCode: 00149 case LoaderHalCode: 00150 case LoaderBootDriver: 00151 case LoaderConsoleInDriver: 00152 case LoaderConsoleOutDriver: 00153 case LoaderStartupDpcStack: 00154 case LoaderStartupKernelStack: 00155 case LoaderStartupPanicStack: 00156 case LoaderStartupPcrPage: 00157 case LoaderStartupPdrPage: 00158 case LoaderRegistryData: 00159 case LoaderMemoryData: 00160 case LoaderNlsData: 00161 case LoaderXIPRom: 00162 case LoaderOsloaderHeap: // FIXME 00163 /* Map these pages into kernel mode */ 00164 Status = MempSetupPaging(BasePage, PageCount, TRUE); 00165 break; 00166 00167 /* Pages not in use */ 00168 case LoaderFree: 00169 case LoaderBad: 00170 break; 00171 00172 /* Invisible to kernel */ 00173 case LoaderSpecialMemory: 00174 case LoaderHALCachedMemory: 00175 case LoaderBBTMemory: 00176 break; 00177 00178 // FIXME: not known (not used anyway) 00179 case LoaderReserve: 00180 case LoaderLargePageFiller: 00181 case LoaderErrorLogMemory: 00182 break; 00183 } 00184 00185 if (!Status) 00186 { 00187 ERR("Error during MempSetupPaging\n"); 00188 } 00189 } 00190 00191 #ifdef _M_ARM 00192 #define PKTSS PVOID 00193 #endif 00194 00195 BOOLEAN 00196 WinLdrSetupMemoryLayout(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock) 00197 { 00198 PFN_NUMBER i, PagesCount, MemoryMapSizeInPages, NoEntries; 00199 PFN_NUMBER LastPageIndex, MemoryMapStartPage; 00200 PPAGE_LOOKUP_TABLE_ITEM MemoryMap; 00201 ULONG LastPageType; 00202 //PKTSS Tss; 00203 //BOOLEAN Status; 00204 00205 /* Cleanup heap */ 00206 HeapCleanupAll(); 00207 00208 // 00209 // Creating a suitable memory map for Windows can be tricky, so let's 00210 // give a few advices: 00211 // 1) One must not map the whole available memory pages to PDE! 00212 // Map only what's needed - 16Mb, 24Mb, 32Mb max I think, 00213 // thus occupying 4, 6 or 8 PDE entries for identical mapping, 00214 // the same quantity for KSEG0_BASE mapping, one more entry for 00215 // hyperspace and one more entry for HAL physical pages mapping. 00216 // 2) Memory descriptors must map *the whole* physical memory 00217 // showing any memory above 16/24/32 as FirmwareTemporary 00218 // 00219 // 3) Overall memory blocks count must not exceed 30 (?? why?) 00220 // 00221 00222 // 00223 // During MmInitMachineDependent, the kernel zeroes PDE at the following address 00224 // 0xC0300000 - 0xC03007FC 00225 // 00226 // Then it finds the best place for non-paged pool: 00227 // StartPde C0300F70, EndPde C0300FF8, NumberOfPages C13, NextPhysPage 3AD 00228 // 00229 00230 // Allocate memory for memory allocation descriptors 00231 Mad = MmAllocateMemoryWithType(sizeof(MEMORY_ALLOCATION_DESCRIPTOR) * MAX_MAD_COUNT, 00232 LoaderMemoryData); 00233 00234 // Setup an entry for each descriptor 00235 MemoryMap = MmGetMemoryMap(&NoEntries); 00236 if (MemoryMap == NULL) 00237 { 00238 UiMessageBox("Can not retrieve the current memory map"); 00239 return FALSE; 00240 } 00241 00242 // Calculate parameters of the memory map 00243 MemoryMapStartPage = (ULONG_PTR)MemoryMap >> MM_PAGE_SHIFT; 00244 MemoryMapSizeInPages = (NoEntries * sizeof(PAGE_LOOKUP_TABLE_ITEM) + MM_PAGE_SIZE - 1) / MM_PAGE_SIZE; 00245 00246 TRACE("Got memory map with %d entries\n", NoEntries); 00247 #if 0 00248 // Always contiguously map low 1Mb of memory 00249 Status = MempSetupPaging(0, 0x100, FALSE); 00250 if (!Status) 00251 { 00252 ERR("Error during MempSetupPaging of low 1Mb\n"); 00253 return FALSE; 00254 } 00255 #endif 00256 // Construct a good memory map from what we've got, 00257 // but mark entries which the memory allocation bitmap takes 00258 // as free entries (this is done in order to have the ability 00259 // to place mem alloc bitmap outside lower 16Mb zone) 00260 PagesCount = 1; 00261 LastPageIndex = 0; 00262 LastPageType = MemoryMap[0].PageAllocated; 00263 for (i = 1; i < NoEntries; i++) 00264 { 00265 // Check if its memory map itself 00266 if (i >= MemoryMapStartPage && 00267 i < (MemoryMapStartPage+MemoryMapSizeInPages)) 00268 { 00269 // Exclude it if current page belongs to the memory map 00270 MemoryMap[i].PageAllocated = LoaderFree; 00271 } 00272 00273 // Process entry 00274 if (MemoryMap[i].PageAllocated == LastPageType && 00275 (i != NoEntries-1) ) 00276 { 00277 PagesCount++; 00278 } 00279 else 00280 { 00281 // Add the resulting region 00282 MempAddMemoryBlock(LoaderBlock, LastPageIndex, PagesCount, LastPageType); 00283 00284 // Reset our counter vars 00285 LastPageIndex = i; 00286 LastPageType = MemoryMap[i].PageAllocated; 00287 PagesCount = 1; 00288 } 00289 } 00290 00291 // TEMP, DEBUG! 00292 // adding special reserved memory zones for vmware workstation 00293 #if 0 00294 { 00295 Mad[MadCount].BasePage = 0xfec00; 00296 Mad[MadCount].PageCount = 0x10; 00297 Mad[MadCount].MemoryType = LoaderSpecialMemory; 00298 WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]); 00299 MadCount++; 00300 00301 Mad[MadCount].BasePage = 0xfee00; 00302 Mad[MadCount].PageCount = 0x1; 00303 Mad[MadCount].MemoryType = LoaderSpecialMemory; 00304 WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]); 00305 MadCount++; 00306 00307 Mad[MadCount].BasePage = 0xfffe0; 00308 Mad[MadCount].PageCount = 0x20; 00309 Mad[MadCount].MemoryType = LoaderSpecialMemory; 00310 WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]); 00311 MadCount++; 00312 } 00313 #endif 00314 00315 /* Now we need to add high descriptors from the bios memory map */ 00316 for (i = 0; i < BiosMemoryMapEntryCount; i++) 00317 { 00318 /* Check if its higher than the lookup table */ 00319 if (BiosMemoryMap->BasePage > MmHighestPhysicalPage) 00320 { 00321 /* Copy this descriptor */ 00322 MempAddMemoryBlock(LoaderBlock, 00323 BiosMemoryMap->BasePage, 00324 BiosMemoryMap->PageCount, 00325 BiosMemoryMap->MemoryType); 00326 } 00327 } 00328 00329 TRACE("MadCount: %d\n", MadCount); 00330 00331 WinLdrpDumpMemoryDescriptors(LoaderBlock); //FIXME: Delete! 00332 00333 // Map our loader image, so we can continue running 00334 /*Status = MempSetupPaging(OsLoaderBase >> MM_PAGE_SHIFT, OsLoaderSize >> MM_PAGE_SHIFT); 00335 if (!Status) 00336 { 00337 UiMessageBox("Error during MempSetupPaging"); 00338 return; 00339 }*/ 00340 00341 // Fill the memory descriptor list and 00342 //PrepareMemoryDescriptorList(); 00343 TRACE("Memory Descriptor List prepared, printing PDE\n"); 00344 List_PaToVa(&LoaderBlock->MemoryDescriptorListHead); 00345 00346 #if DBG 00347 MempDump(); 00348 #endif 00349 00350 return TRUE; 00351 } 00352 00353 // Two special things this func does: it sorts descriptors, 00354 // and it merges free ones 00355 static VOID 00356 WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, 00357 IN PMEMORY_ALLOCATION_DESCRIPTOR NewDescriptor) 00358 { 00359 PLIST_ENTRY ListHead = &LoaderBlock->MemoryDescriptorListHead; 00360 PLIST_ENTRY PreviousEntry, NextEntry; 00361 PMEMORY_ALLOCATION_DESCRIPTOR PreviousDescriptor = NULL, NextDescriptor = NULL; 00362 00363 TRACE("BP=0x%X PC=0x%X %s\n", NewDescriptor->BasePage, 00364 NewDescriptor->PageCount, MemTypeDesc[NewDescriptor->MemoryType]); 00365 00366 /* Find a place where to insert the new descriptor to */ 00367 PreviousEntry = ListHead; 00368 NextEntry = ListHead->Flink; 00369 while (NextEntry != ListHead) 00370 { 00371 NextDescriptor = CONTAINING_RECORD(NextEntry, 00372 MEMORY_ALLOCATION_DESCRIPTOR, 00373 ListEntry); 00374 if (NewDescriptor->BasePage < NextDescriptor->BasePage) 00375 break; 00376 00377 PreviousEntry = NextEntry; 00378 PreviousDescriptor = NextDescriptor; 00379 NextEntry = NextEntry->Flink; 00380 } 00381 00382 /* Don't forget about merging free areas */ 00383 if (NewDescriptor->MemoryType != LoaderFree) 00384 { 00385 /* Just insert, nothing to merge */ 00386 InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry); 00387 } 00388 else 00389 { 00390 /* Previous block also free? */ 00391 if ((PreviousEntry != ListHead) && (PreviousDescriptor->MemoryType == LoaderFree) && 00392 ((PreviousDescriptor->BasePage + PreviousDescriptor->PageCount) == 00393 NewDescriptor->BasePage)) 00394 { 00395 /* Just enlarge previous descriptor's PageCount */ 00396 PreviousDescriptor->PageCount += NewDescriptor->PageCount; 00397 NewDescriptor = PreviousDescriptor; 00398 } 00399 else 00400 { 00401 /* Nope, just insert */ 00402 InsertHeadList(PreviousEntry, &NewDescriptor->ListEntry); 00403 } 00404 00405 /* Next block is free ?*/ 00406 if ((NextEntry != ListHead) && 00407 (NextDescriptor->MemoryType == LoaderFree) && 00408 ((NewDescriptor->BasePage + NewDescriptor->PageCount) == NextDescriptor->BasePage)) 00409 { 00410 /* Enlarge next descriptor's PageCount */ 00411 NewDescriptor->PageCount += NextDescriptor->PageCount; 00412 RemoveEntryList(&NextDescriptor->ListEntry); 00413 } 00414 } 00415 00416 return; 00417 } Generated on Sun May 27 2012 04:19:18 for ReactOS by
1.7.6.1
|