ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

wlmemory.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.