Author: sir_richard
Date: Thu Apr 22 10:13:56 2010
New Revision: 46989
URL:
http://svn.reactos.org/svn/reactos?rev=46989&view=rev
Log:
[NTOS]: Implement and call MiBuildImportsForBootDrivers. We now have full dependency
tracking for correct unloading.
[NTOS]: Implement and call MiLocateKernelSections. Pool code and paging paths will require
this information later. Loader work done for now.
Modified:
trunk/reactos/ntoskrnl/mm/sysldr.c
Modified: trunk/reactos/ntoskrnl/mm/sysldr.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/sysldr.c?rev=4…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/sysldr.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/sysldr.c [iso-8859-1] Thu Apr 22 10:13:56 2010
@@ -46,6 +46,10 @@
BOOLEAN MmMakeLowMemory;
BOOLEAN MmEnforceWriteProtection = TRUE;
+
+PMMPTE MiKernelResourceStartPte, MiKernelResourceEndPte;
+ULONG_PTR ExPoolCodeStart, ExPoolCodeEnd, MmPoolCodeStart, MmPoolCodeEnd;
+ULONG_PTR MmPteCodeStart, MmPteCodeEnd;
/* FUNCTIONS ******************************************************************/
@@ -1508,6 +1512,331 @@
}
}
+NTSTATUS
+NTAPI
+MiBuildImportsForBootDrivers(VOID)
+{
+ PLIST_ENTRY NextEntry, NextEntry2;
+ PLDR_DATA_TABLE_ENTRY LdrEntry, KernelEntry, HalEntry, LdrEntry2, LastEntry;
+ PLDR_DATA_TABLE_ENTRY* EntryArray;
+ UNICODE_STRING KernelName = RTL_CONSTANT_STRING(L"ntoskrnl.exe");
+ UNICODE_STRING HalName = RTL_CONSTANT_STRING(L"hal.dll");
+ PLOAD_IMPORTS LoadedImports;
+ ULONG LoadedImportsSize, ImportSize;
+ PULONG_PTR ImageThunk;
+ ULONG_PTR DllBase, DllEnd;
+ ULONG Modules = 0, i, j = 0;
+ PIMAGE_IMPORT_DESCRIPTOR ImportDescriptor;
+
+ /* Initialize variables */
+ KernelEntry = HalEntry = LastEntry = NULL;
+
+ /* Loop the loaded module list... we are early enough that no lock is needed */
+ NextEntry = PsLoadedModuleList.Flink;
+ while (NextEntry != &PsLoadedModuleList)
+ {
+ /* Get the entry */
+ LdrEntry = CONTAINING_RECORD(NextEntry,
+ LDR_DATA_TABLE_ENTRY,
+ InLoadOrderLinks);
+
+ /* Check if it's the kernel or HAL */
+ if (RtlEqualUnicodeString(&KernelName, &LdrEntry->BaseDllName, TRUE))
+ {
+ /* Found it */
+ KernelEntry = LdrEntry;
+ }
+ else if (RtlEqualUnicodeString(&HalName, &LdrEntry->BaseDllName,
TRUE))
+ {
+ /* Found it */
+ HalEntry = LdrEntry;
+ }
+
+ /* Check if this is a driver DLL */
+ if (LdrEntry->Flags & LDRP_DRIVER_DEPENDENT_DLL)
+ {
+ /* Check if this is the HAL or kernel */
+ if ((LdrEntry == HalEntry) || (LdrEntry == KernelEntry))
+ {
+ /* Add a reference */
+ LdrEntry->LoadCount = 1;
+ }
+ else
+ {
+ /* No referencing needed */
+ LdrEntry->LoadCount = 0;
+ }
+ }
+ else
+ {
+ /* No referencing needed */
+ LdrEntry->LoadCount = 0;
+ }
+
+ /* Remember this came from the loader */
+ LdrEntry->LoadedImports = MM_SYSLDR_BOOT_LOADED;
+
+ /* Keep looping */
+ NextEntry = NextEntry->Flink;
+ Modules++;
+ }
+
+ /* We must have at least found the kernel and HAL */
+ if (!(HalEntry) || (!KernelEntry)) return STATUS_NOT_FOUND;
+
+ /* Allocate the list */
+ EntryArray = ExAllocatePoolWithTag(PagedPool, Modules * sizeof(PVOID),
'TDmM');
+ if (!EntryArray) return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Loop the loaded module list again */
+ NextEntry = PsLoadedModuleList.Flink;
+ while (NextEntry != &PsLoadedModuleList)
+ {
+ /* Get the entry */
+ LdrEntry = CONTAINING_RECORD(NextEntry,
+ LDR_DATA_TABLE_ENTRY,
+ InLoadOrderLinks);
+#ifdef _WORKING_LOADER_
+ /* Get its imports */
+ ImageThunk = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
+ TRUE,
+ IMAGE_DIRECTORY_ENTRY_IAT,
+ &ImportSize);
+ if (!ImageThunk)
+#else
+ /* Get its imports */
+ ImportDescriptor = RtlImageDirectoryEntryToData(LdrEntry->DllBase,
+ TRUE,
+ IMAGE_DIRECTORY_ENTRY_IMPORT,
+ &ImportSize);
+ if (!ImportDescriptor)
+#endif
+ {
+ /* None present */
+ LdrEntry->LoadedImports = MM_SYSLDR_NO_IMPORTS;
+ NextEntry = NextEntry->Flink;
+ continue;
+ }
+
+ /* Clear the list and count the number of IAT thunks */
+ RtlZeroMemory(EntryArray, Modules * sizeof(PVOID));
+#ifdef _WORKING_LOADER_
+ ImportSize /= sizeof(ULONG_PTR);
+
+ /* Scan the thunks */
+ for (i = 0, DllBase = 0, DllEnd = 0; i < ImportSize; i++, ImageThunk++)
+#else
+ i = DllBase = DllEnd = 0;
+ while ((ImportDescriptor->Name) &&
+ (ImportDescriptor->OriginalFirstThunk))
+ {
+ /* Get the image thunk */
+ ImageThunk = (PVOID)((ULONG_PTR)LdrEntry->DllBase +
+ ImportDescriptor->FirstThunk);
+ while (*ImageThunk)
+#endif
+ {
+ /* Do we already have an address? */
+ if (DllBase)
+ {
+ /* Is the thunk in the same address? */
+ if ((*ImageThunk >= DllBase) && (*ImageThunk < DllEnd))
+ {
+ /* Skip it, we already have a reference for it */
+ ASSERT(EntryArray[j]);
+ ImageThunk++;
+ continue;
+ }
+ }
+
+ /* Loop the loaded module list to locate this address owner */
+ j = 0;
+ NextEntry2 = PsLoadedModuleList.Flink;
+ while (NextEntry2 != &PsLoadedModuleList)
+ {
+ /* Get the entry */
+ LdrEntry2 = CONTAINING_RECORD(NextEntry2,
+ LDR_DATA_TABLE_ENTRY,
+ InLoadOrderLinks);
+
+ /* Get the address range for this module */
+ DllBase = (ULONG_PTR)LdrEntry2->DllBase;
+ DllEnd = DllBase + LdrEntry2->SizeOfImage;
+
+ /* Check if this IAT entry matches it */
+ if ((*ImageThunk >= DllBase) && (*ImageThunk < DllEnd))
+ {
+ /* Save it */
+ //DPRINT1("Found imported dll: %wZ\n",
&LdrEntry2->BaseDllName);
+ EntryArray[j] = LdrEntry2;
+ break;
+ }
+
+ /* Keep searching */
+ NextEntry2 = NextEntry2->Flink;
+ j++;
+ }
+
+ /* Do we have a thunk outside the range? */
+ if ((*ImageThunk < DllBase) || (*ImageThunk >= DllEnd))
+ {
+ /* Could be 0... */
+ if (*ImageThunk)
+ {
+ /* Should not be happening */
+ DPRINT1("Broken IAT entry for %p at %p (%lx)\n",
+ LdrEntry, ImageThunk, *ImageThunk);
+ ASSERT(FALSE);
+ }
+
+ /* Reset if we hit this */
+ DllBase = 0;
+ }
+#ifndef _WORKING_LOADER_
+ ImageThunk++;
+ }
+
+ i++;
+ ImportDescriptor++;
+#endif
+ }
+
+ /* Now scan how many imports we really have */
+ for (i = 0, ImportSize = 0; i < Modules; i++)
+ {
+ /* Skip HAL and kernel */
+ if ((EntryArray[i]) &&
+ (EntryArray[i] != HalEntry) &&
+ (EntryArray[i] != KernelEntry))
+ {
+ /* A valid reference */
+ LastEntry = EntryArray[i];
+ ImportSize++;
+ }
+ }
+
+ /* Do we have any imports after all? */
+ if (!ImportSize)
+ {
+ /* No */
+ LdrEntry->LoadedImports = MM_SYSLDR_NO_IMPORTS;
+ }
+ else if (ImportSize == 1)
+ {
+ /* A single entry import */
+ LdrEntry->LoadedImports = (PVOID)((ULONG_PTR)LastEntry |
MM_SYSLDR_SINGLE_ENTRY);
+ LastEntry->LoadCount++;
+ }
+ else
+ {
+ /* We need an import table */
+ LoadedImportsSize = ImportSize * sizeof(PVOID) + sizeof(SIZE_T);
+ LoadedImports = ExAllocatePoolWithTag(PagedPool,
+ LoadedImportsSize,
+ 'TDmM');
+ ASSERT(LoadedImports);
+
+ /* Save the count */
+ LoadedImports->Count = ImportSize;
+
+ /* Now copy all imports */
+ for (i = 0, j = 0; i < Modules; i++)
+ {
+ /* Skip HAL and kernel */
+ if ((EntryArray[i]) &&
+ (EntryArray[i] != HalEntry) &&
+ (EntryArray[i] != KernelEntry))
+ {
+ /* A valid reference */
+ //DPRINT1("Found valid entry: %p\n", EntryArray[i]);
+ LoadedImports->Entry[j] = EntryArray[i];
+ EntryArray[i]->LoadCount++;
+ j++;
+ }
+ }
+
+ /* Should had as many entries as we expected */
+ ASSERT(j == ImportSize);
+ LdrEntry->LoadedImports = LoadedImports;
+ }
+
+ /* Next */
+ NextEntry = NextEntry->Flink;
+ }
+
+ /* Free the initial array */
+ ExFreePool(EntryArray);
+
+ /* FIXME: Might not need to keep the HAL/Kernel imports around */
+
+ /* Kernel and HAL are loaded at boot */
+ KernelEntry->LoadedImports = MM_SYSLDR_BOOT_LOADED;
+ HalEntry->LoadedImports = MM_SYSLDR_BOOT_LOADED;
+
+ /* All worked well */
+ return STATUS_SUCCESS;
+}
+
+VOID
+NTAPI
+MiLocateKernelSections(IN PLDR_DATA_TABLE_ENTRY LdrEntry)
+{
+ ULONG_PTR DllBase;
+ PIMAGE_NT_HEADERS NtHeaders;
+ PIMAGE_SECTION_HEADER SectionHeader;
+ ULONG Sections, Size;
+
+ /* Get the kernel section header */
+ DllBase = (ULONG_PTR)LdrEntry->DllBase;
+ NtHeaders = RtlImageNtHeader((PVOID)DllBase);
+ SectionHeader = IMAGE_FIRST_SECTION(NtHeaders);
+
+ /* Loop all the sections */
+ Sections = NtHeaders->FileHeader.NumberOfSections;
+ while (Sections)
+ {
+ /* Grab the size of the section */
+ Size = max(SectionHeader->SizeOfRawData, SectionHeader->Misc.VirtualSize);
+
+ /* Check for .RSRC section */
+ if (*(PULONG)SectionHeader->Name == 'rsr.')
+ {
+ /* Remember the PTEs so we can modify them later */
+ MiKernelResourceStartPte = MiAddressToPte(DllBase +
+ SectionHeader->VirtualAddress);
+ MiKernelResourceEndPte = MiKernelResourceStartPte +
+ BYTES_TO_PAGES(SectionHeader->VirtualAddress +
Size);
+ }
+ else if (*(PULONG)SectionHeader->Name == 'LOOP')
+ {
+ /* POOLCODE vs. POOLMI */
+ if (*(PULONG)&SectionHeader->Name[4] == 'EDOC')
+ {
+ /* Found Ex* Pool code */
+ ExPoolCodeStart = DllBase + SectionHeader->VirtualAddress;
+ ExPoolCodeEnd = ExPoolCodeStart + Size;
+ }
+ else if (*(PUSHORT)&SectionHeader->Name[4] == 'MI')
+ {
+ /* Found Mm* Pool code */
+ MmPoolCodeStart = DllBase + SectionHeader->VirtualAddress;
+ MmPoolCodeEnd = ExPoolCodeStart + Size;
+ }
+ }
+ else if ((*(PULONG)SectionHeader->Name == 'YSIM') &&
+ (*(PULONG)&SectionHeader->Name[4] == 'ETPS'))
+ {
+ /* Found MISYSPTE (Mm System PTE code)*/
+ MmPteCodeStart = DllBase + SectionHeader->VirtualAddress;
+ MmPteCodeEnd = ExPoolCodeStart + Size;
+ }
+
+ /* Keep going */
+ Sections--;
+ SectionHeader++;
+ }
+}
+
BOOLEAN
NTAPI
MiInitializeLoadedModuleList(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
@@ -1528,6 +1857,9 @@
LDR_DATA_TABLE_ENTRY,
InLoadOrderLinks);
PsNtosImageBase = (ULONG_PTR)LdrEntry->DllBase;
+
+ /* Locate resource section, pool code, and system pte code */
+ MiLocateKernelSections(LdrEntry);
/* Loop the loader block */
while (NextEntry != ListHead)
@@ -1541,7 +1873,7 @@
if (!RtlImageNtHeader(LdrEntry->DllBase))
{
/* Skip this entry */
- NextEntry= NextEntry->Flink;
+ NextEntry = NextEntry->Flink;
continue;
}
@@ -1584,7 +1916,7 @@
}
/* Build the import lists for the boot drivers */
- //MiBuildImportsForBootDrivers();
+ MiBuildImportsForBootDrivers();
/* We're done */
return TRUE;