diff --git a/reactos/boot/freeldr/freeldr/arch/i386/loader.c b/reactos/boot/freeldr/freeldr/arch/i386/loader.c index f538c028636..4bd7d07ccd7 100644 --- a/reactos/boot/freeldr/freeldr/arch/i386/loader.c +++ b/reactos/boot/freeldr/freeldr/arch/i386/loader.c @@ -513,7 +513,7 @@ FrLdrReMapImage(IN PVOID Base, /* Allocate memory for the driver */ DriverSize = NtHeader->OptionalHeader.SizeOfImage; - LoadBase = MmAllocateMemoryAtAddress(DriverSize, LoadBase); + LoadBase = MmAllocateMemoryAtAddress(DriverSize, LoadBase, LoaderSystemCode); ASSERT(LoadBase); /* Copy headers over */ diff --git a/reactos/boot/freeldr/freeldr/include/mm.h b/reactos/boot/freeldr/freeldr/include/mm.h index cf920c16c0d..a708be10b14 100644 --- a/reactos/boot/freeldr/freeldr/include/mm.h +++ b/reactos/boot/freeldr/freeldr/include/mm.h @@ -47,6 +47,14 @@ typedef struct ( ((a) >> MM_PAGE_SHIFT) + ((a) & MM_PAGE_MASK ? 1 : 0) ) #endif // defined __i386__ or _PPC_ or _MIPS_ +// +// This is the zone which is used by the OS loader +// +#define LOADER_HIGH_ZONE ((16*1024*1024) >> MM_PAGE_SHIFT) //16Mb page + +// HEAP and STACK size +#define HEAP_PAGES 0x100//0x18 +#define STACK_PAGES 0x00 typedef struct { @@ -79,7 +87,7 @@ PVOID MmFindLocationForPageLookupTable(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG Map VOID MmSortBiosMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount); // Sorts the BIOS_MEMORY_MAP array so the first element corresponds to the first address in memory VOID MmInitPageLookupTable(PVOID PageLookupTable, ULONG TotalPageCount, PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount); // Inits the page lookup table according to the memory types in the memory map VOID MmMarkPagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG PageCount, TYPE_OF_MEMORY PageAllocated); // Marks the specified pages as allocated or free in the lookup table -VOID MmAllocatePagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG PageCount); // Allocates the specified pages in the lookup table +VOID MmAllocatePagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG PageCount, TYPE_OF_MEMORY MemoryType); // Allocates the specified pages in the lookup table ULONG MmCountFreePagesInLookupTable(PVOID PageLookupTable, ULONG TotalPageCount); // Returns the number of free pages in the lookup table ULONG MmFindAvailablePages(PVOID PageLookupTable, ULONG TotalPageCount, ULONG PagesNeeded, BOOLEAN FromEnd); // Returns the page number of the first available page range from the beginning or end of memory ULONG MmFindAvailablePagesBeforePage(PVOID PageLookupTable, ULONG TotalPageCount, ULONG PagesNeeded, ULONG LastPage); // Returns the page number of the first available page range before the specified page @@ -93,12 +101,17 @@ PPAGE_LOOKUP_TABLE_ITEM MmGetMemoryMap(ULONG *NoEntries); // Returns a pointer //BOOLEAN MmInitializeMemoryManager(ULONG LowMemoryStart, ULONG LowMemoryLength); BOOLEAN MmInitializeMemoryManager(VOID); +VOID MmInitializeHeap(PVOID PageLookupTable); PVOID MmAllocateMemory(ULONG MemorySize); +PVOID MmAllocateMemoryWithType(ULONG MemorySize, TYPE_OF_MEMORY MemoryType); VOID MmFreeMemory(PVOID MemoryPointer); VOID MmChangeAllocationPolicy(BOOLEAN PolicyAllocatePagesFromEnd); //PVOID MmAllocateLowMemory(ULONG MemorySize); //VOID MmFreeLowMemory(PVOID MemoryPointer); -PVOID MmAllocateMemoryAtAddress(ULONG MemorySize, PVOID DesiredAddress); -PVOID MmAllocateHighestMemoryBelowAddress(ULONG MemorySize, PVOID DesiredAddress); +PVOID MmAllocateMemoryAtAddress(ULONG MemorySize, PVOID DesiredAddress, TYPE_OF_MEMORY MemoryType); +PVOID MmAllocateHighestMemoryBelowAddress(ULONG MemorySize, PVOID DesiredAddress, TYPE_OF_MEMORY MemoryType); + +PVOID MmHeapAlloc(ULONG MemorySize); +VOID MmHeapFree(PVOID MemoryPointer); #endif // defined __MEMORY_H diff --git a/reactos/boot/freeldr/freeldr/include/winldr.h b/reactos/boot/freeldr/freeldr/include/winldr.h index 57ef9a6f59d..bd7b9f51379 100644 --- a/reactos/boot/freeldr/freeldr/include/winldr.h +++ b/reactos/boot/freeldr/freeldr/include/winldr.h @@ -40,8 +40,8 @@ NTAPI #define SECTOR_SIZE 512 // Descriptors -#define NUM_GDT 28 //15. The kernel wants 0xD8 as a last GDT entry offset -#define NUM_IDT 0x100 // only 16 are used though +#define NUM_GDT 128 // Must be 128 +#define NUM_IDT 0x100 // only 16 are used though. Must be 0x100 // conversion.c PVOID VaToPa(PVOID Va); @@ -52,6 +52,7 @@ VOID ConvertConfigToVA(PCONFIGURATION_COMPONENT_DATA Start); // peloader.c BOOLEAN WinLdrLoadImage(IN PCHAR FileName, + TYPE_OF_MEMORY MemoryType, OUT PVOID *ImageBasePA); diff --git a/reactos/boot/freeldr/freeldr/linuxboot.c b/reactos/boot/freeldr/freeldr/linuxboot.c index b48eb7c6139..df2bb8fc7d6 100644 --- a/reactos/boot/freeldr/freeldr/linuxboot.c +++ b/reactos/boot/freeldr/freeldr/linuxboot.c @@ -374,7 +374,7 @@ BOOLEAN LinuxReadKernel(PFILE LinuxKernelFile) UiDrawStatusText(StatusText); // Allocate memory for Linux kernel - LinuxKernelLoadAddress = MmAllocateMemoryAtAddress(LinuxKernelSize, (PVOID)LINUX_KERNEL_LOAD_ADDRESS); + LinuxKernelLoadAddress = MmAllocateMemoryAtAddress(LinuxKernelSize, (PVOID)LINUX_KERNEL_LOAD_ADDRESS, LoaderSystemCode); if (LinuxKernelLoadAddress != (PVOID)LINUX_KERNEL_LOAD_ADDRESS) { return FALSE; @@ -451,11 +451,11 @@ BOOLEAN LinuxReadInitrd(PFILE LinuxInitrdFile) //LinuxInitrdLoadAddress = MmAllocateMemoryAtAddress(LinuxInitrdSize, (PVOID)ROUND_UP((LINUX_KERNEL_LOAD_ADDRESS + LinuxKernelSize), 0x100000)); if (LinuxSetupSector->Version <= 0x0202) { - LinuxInitrdLoadAddress = MmAllocateHighestMemoryBelowAddress(LinuxInitrdSize, (PVOID)LINUX_MAX_INITRD_ADDRESS); + LinuxInitrdLoadAddress = MmAllocateHighestMemoryBelowAddress(LinuxInitrdSize, (PVOID)LINUX_MAX_INITRD_ADDRESS, LoaderSystemCode); } else { - LinuxInitrdLoadAddress = MmAllocateHighestMemoryBelowAddress(LinuxInitrdSize, (PVOID)LinuxSetupSector->InitrdAddressMax); + LinuxInitrdLoadAddress = MmAllocateHighestMemoryBelowAddress(LinuxInitrdSize, (PVOID)LinuxSetupSector->InitrdAddressMax, LoaderSystemCode); } if (LinuxInitrdLoadAddress == NULL) { diff --git a/reactos/boot/freeldr/freeldr/mm/meminit.c b/reactos/boot/freeldr/freeldr/mm/meminit.c index 90c8b3a493b..ef8c828b12b 100644 --- a/reactos/boot/freeldr/freeldr/mm/meminit.c +++ b/reactos/boot/freeldr/freeldr/mm/meminit.c @@ -281,7 +281,7 @@ VOID MmMarkPagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG Page DbgPrint((DPRINT_MEMORY, "MmMarkPagesInLookupTable() Done\n")); } -VOID MmAllocatePagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG PageCount) +VOID MmAllocatePagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG PageCount, TYPE_OF_MEMORY MemoryType) { PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable; ULONG Index; diff --git a/reactos/boot/freeldr/freeldr/mm/mm.c b/reactos/boot/freeldr/freeldr/mm/mm.c index adee5f7dc56..94e23f1ec03 100644 --- a/reactos/boot/freeldr/freeldr/mm/mm.c +++ b/reactos/boot/freeldr/freeldr/mm/mm.c @@ -57,7 +57,7 @@ VOID MmChangeAllocationPolicy(BOOLEAN PolicyAllocatePagesFromEnd) AllocateFromEnd = PolicyAllocatePagesFromEnd; } -PVOID MmAllocateMemory(ULONG MemorySize) +PVOID MmAllocateMemoryWithType(ULONG MemorySize, TYPE_OF_MEMORY MemoryType) { ULONG PagesNeeded; ULONG FirstFreePageFromEnd; @@ -100,7 +100,7 @@ PVOID MmAllocateMemory(ULONG MemorySize) return NULL; } - MmAllocatePagesInLookupTable(PageLookupTableAddress, FirstFreePageFromEnd, PagesNeeded); + MmAllocatePagesInLookupTable(PageLookupTableAddress, FirstFreePageFromEnd, PagesNeeded, MemoryType); FreePagesInLookupTable -= PagesNeeded; MemPointer = (PVOID)(FirstFreePageFromEnd * MM_PAGE_SIZE); @@ -123,7 +123,13 @@ PVOID MmAllocateMemory(ULONG MemorySize) return MemPointer; } -PVOID MmAllocateMemoryAtAddress(ULONG MemorySize, PVOID DesiredAddress) +PVOID MmAllocateMemory(ULONG MemorySize) +{ + // Temporary forwarder... + return MmAllocateMemoryWithType(MemorySize, LoaderOsloaderHeap); +} + +PVOID MmAllocateMemoryAtAddress(ULONG MemorySize, PVOID DesiredAddress, TYPE_OF_MEMORY MemoryType) { ULONG PagesNeeded; ULONG StartPageNumber; @@ -166,7 +172,7 @@ PVOID MmAllocateMemoryAtAddress(ULONG MemorySize, PVOID DesiredAddress) return NULL; } - MmAllocatePagesInLookupTable(PageLookupTableAddress, StartPageNumber, PagesNeeded); + MmAllocatePagesInLookupTable(PageLookupTableAddress, StartPageNumber, PagesNeeded, MemoryType); FreePagesInLookupTable -= PagesNeeded; MemPointer = (PVOID)(StartPageNumber * MM_PAGE_SIZE); @@ -182,7 +188,7 @@ PVOID MmAllocateMemoryAtAddress(ULONG MemorySize, PVOID DesiredAddress) return MemPointer; } -PVOID MmAllocateHighestMemoryBelowAddress(ULONG MemorySize, PVOID DesiredAddress) +PVOID MmAllocateHighestMemoryBelowAddress(ULONG MemorySize, PVOID DesiredAddress, TYPE_OF_MEMORY MemoryType) { ULONG PagesNeeded; ULONG FirstFreePageFromEnd; @@ -221,7 +227,7 @@ PVOID MmAllocateHighestMemoryBelowAddress(ULONG MemorySize, PVOID DesiredAddress return NULL; } - MmAllocatePagesInLookupTable(PageLookupTableAddress, FirstFreePageFromEnd, PagesNeeded); + MmAllocatePagesInLookupTable(PageLookupTableAddress, FirstFreePageFromEnd, PagesNeeded, MemoryType); FreePagesInLookupTable -= PagesNeeded; MemPointer = (PVOID)(FirstFreePageFromEnd * MM_PAGE_SIZE); @@ -302,6 +308,18 @@ VOID MmFreeMemory(PVOID MemoryPointer) #endif // DBG } +PVOID MmHeapAlloc(ULONG MemorySize) +{ + // Stub for WinLdr + return NULL; +} + +VOID MmHeapFree(PVOID MemoryPointer) +{ + // Stub for WinLdr +} + + #ifdef DBG VOID VerifyHeap(VOID) { diff --git a/reactos/boot/freeldr/freeldr/windows/conversion.c b/reactos/boot/freeldr/freeldr/windows/conversion.c index 18395ce6d17..3cc4ef7326c 100644 --- a/reactos/boot/freeldr/freeldr/windows/conversion.c +++ b/reactos/boot/freeldr/freeldr/windows/conversion.c @@ -70,7 +70,7 @@ ConvertConfigToVA(PCONFIGURATION_COMPONENT_DATA Start) PCONFIGURATION_COMPONENT_DATA Child; PCONFIGURATION_COMPONENT_DATA Sibling; - DbgPrint((DPRINT_WINDOWS, "ConvertConfigToVA(Start 0x%X)", Start)); + DbgPrint((DPRINT_WINDOWS, "ConvertConfigToVA(Start 0x%X)\n", Start)); Child = Start; while (Child != NULL) @@ -87,11 +87,12 @@ ConvertConfigToVA(PCONFIGURATION_COMPONENT_DATA Start) if (Child->Sibling) Child->Sibling = PaToVa(Child->Sibling); - DbgPrint((DPRINT_WINDOWS, "Device 0x%X class %d", Child, Child->ComponentEntry.Class)); + DbgPrint((DPRINT_WINDOWS, "Device 0x%X class %d type %d, parent %p\n", Child, + Child->ComponentEntry.Class, Child->ComponentEntry.Type, Child->Parent)); // If the child has a sibling list, then search the sibling list // for an entry that matches the specified class, type, and key. - Sibling = Child->Sibling; + Sibling = VaToPa(Child->Sibling); while (Sibling != NULL) { if (Sibling->ConfigurationData) @@ -106,7 +107,8 @@ ConvertConfigToVA(PCONFIGURATION_COMPONENT_DATA Start) if (Sibling->Sibling) Sibling->Sibling = PaToVa(Sibling->Sibling); - DbgPrint((DPRINT_WINDOWS, "Device 0x%X class %d", Sibling, Sibling->ComponentEntry.Class)); + DbgPrint((DPRINT_WINDOWS, "Device 0x%X class %d type %d sib, parent %p\n", Sibling, + Sibling->ComponentEntry.Class, Sibling->ComponentEntry.Type, Sibling->Parent)); // If the sibling has a child tree, then search the child tree // for an entry that matches the specified class, type, and key. @@ -116,6 +118,7 @@ ConvertConfigToVA(PCONFIGURATION_COMPONENT_DATA Start) Sibling = VaToPa(Sibling->Sibling); } + // Go to the next child Child = VaToPa(Child->Child); } } diff --git a/reactos/boot/freeldr/freeldr/windows/peloader.c b/reactos/boot/freeldr/freeldr/windows/peloader.c index 0e1416f8878..fdbb21d3c91 100644 --- a/reactos/boot/freeldr/freeldr/windows/peloader.c +++ b/reactos/boot/freeldr/freeldr/windows/peloader.c @@ -1,5 +1,5 @@ /* - * PROJECT: WinLoader + * PROJECT: FreeLoader * LICENSE: GPL - See COPYING in the top level directory * FILE: freeldr/winldr/peloader.c * PURPOSE: Provides routines for loading PE files. To be merged with @@ -17,23 +17,149 @@ #include #include + +BOOLEAN +WinLdrpCompareDllName(IN PCH DllName, + IN PUNICODE_STRING UnicodeName); + +BOOLEAN +WinLdrpBindImportName(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock, + IN PVOID DllBase, + IN PVOID ImageBase, + IN PIMAGE_THUNK_DATA ThunkData, + IN PIMAGE_EXPORT_DIRECTORY ExportDirectory, + IN ULONG ExportSize, + IN BOOLEAN ProcessForwards); + +BOOLEAN +WinLdrpLoadAndScanReferencedDll(PLOADER_PARAMETER_BLOCK WinLdrBlock, + PCCH DirectoryPath, + PCH ImportName, + PLDR_DATA_TABLE_ENTRY *DataTableEntry); + +BOOLEAN +WinLdrpScanImportAddressTable(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock, + IN PVOID DllBase, + IN PVOID ImageBase, + IN PIMAGE_THUNK_DATA ThunkData); + + + /* FUNCTIONS **************************************************************/ +/* Returns TRUE if DLL has already been loaded - looks in LoadOrderList in LPB */ BOOLEAN WinLdrCheckForLoadedDll(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock, IN PCH DllName, OUT PLDR_DATA_TABLE_ENTRY *LoadedEntry) { + PLDR_DATA_TABLE_ENTRY DataTableEntry; + LIST_ENTRY *ModuleEntry; + + DbgPrint((DPRINT_WINDOWS, "WinLdrCheckForLoadedDll: DllName %X, LoadedEntry: %X\n", + DllName, LoadedEntry)); + + /* Just go through each entry in the LoadOrderList and compare loaded module's + name with a given name */ + ModuleEntry = WinLdrBlock->LoadOrderListHead.Flink; + while (ModuleEntry != &WinLdrBlock->LoadOrderListHead) + { + /* Get pointer to the current DTE */ + DataTableEntry = CONTAINING_RECORD(ModuleEntry, + LDR_DATA_TABLE_ENTRY, + InLoadOrderLinks); + + DbgPrint((DPRINT_WINDOWS, "WinLdrCheckForLoadedDll: DTE %p, EP %p\n", + DataTableEntry, DataTableEntry->EntryPoint)); + + /* Compare names */ + if (WinLdrpCompareDllName(DllName, &DataTableEntry->BaseDllName)) + { + /* Yes, found it, report pointer to the loaded module's DTE + to the caller and increase load count for it */ + *LoadedEntry = DataTableEntry; + DataTableEntry->LoadCount++; + DbgPrint((DPRINT_WINDOWS, "WinLdrCheckForLoadedDll: LoadedEntry %X\n", DataTableEntry)); + return TRUE; + } + + /* Go to the next entry */ + ModuleEntry = ModuleEntry->Flink; + } + + /* Nothing found */ return FALSE; } - BOOLEAN WinLdrScanImportDescriptorTable(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock, IN PCCH DirectoryPath, IN PLDR_DATA_TABLE_ENTRY ScanDTE) { - return FALSE; + PLDR_DATA_TABLE_ENTRY DataTableEntry; + PIMAGE_IMPORT_DESCRIPTOR ImportTable; + ULONG ImportTableSize; + PCH ImportName; + BOOLEAN Status; + + /* Get a pointer to the import table of this image */ + ImportTable = (PIMAGE_IMPORT_DESCRIPTOR)RtlImageDirectoryEntryToData(VaToPa(ScanDTE->DllBase), + TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &ImportTableSize); + + { + UNICODE_STRING BaseName; + BaseName.Buffer = VaToPa(ScanDTE->BaseDllName.Buffer); + BaseName.MaximumLength = ScanDTE->BaseDllName.MaximumLength; + BaseName.Length = ScanDTE->BaseDllName.Length; + DbgPrint((DPRINT_WINDOWS, "WinLdrScanImportDescriptorTable(): %wZ ImportTable = 0x%X\n", + &BaseName, ImportTable)); + } + + /* If image doesn't have any import directory - just return success */ + if (ImportTable == NULL) + return TRUE; + + /* Loop through all entries */ + for (;(ImportTable->Name != 0) && (ImportTable->FirstThunk != 0);ImportTable++) + { + /* Get pointer to the name */ + ImportName = (PCH)VaToPa(RVA(ScanDTE->DllBase, ImportTable->Name)); + DbgPrint((DPRINT_WINDOWS, "WinLdrScanImportDescriptorTable(): Looking at %s\n", ImportName)); + + /* In case we get a reference to ourselves - just skip it */ + if (WinLdrpCompareDllName(ImportName, &ScanDTE->BaseDllName)) + continue; + + /* Load the DLL if it is not already loaded */ + if (!WinLdrCheckForLoadedDll(WinLdrBlock, ImportName, &DataTableEntry)) + { + Status = WinLdrpLoadAndScanReferencedDll(WinLdrBlock, + DirectoryPath, + ImportName, + &DataTableEntry); + + if (!Status) + { + DbgPrint((DPRINT_WINDOWS, "WinLdrpLoadAndScanReferencedDll() failed\n")); + return Status; + } + } + + /* Scan its import address table */ + Status = WinLdrpScanImportAddressTable( + WinLdrBlock, + DataTableEntry->DllBase, + ScanDTE->DllBase, + (PIMAGE_THUNK_DATA)RVA(ScanDTE->DllBase, ImportTable->FirstThunk)); + + if (!Status) + { + DbgPrint((DPRINT_WINDOWS, "WinLdrpScanImportAddressTable() failed\n")); + return Status; + } + } + + return TRUE; } BOOLEAN @@ -50,7 +176,7 @@ WinLdrAllocateDataTableEntry(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock, USHORT Length; /* Allocate memory for a data table entry, zero-initialize it */ - DataTableEntry = (PLDR_DATA_TABLE_ENTRY)MmAllocateMemory(sizeof(LDR_DATA_TABLE_ENTRY)); + DataTableEntry = (PLDR_DATA_TABLE_ENTRY)MmHeapAlloc(sizeof(LDR_DATA_TABLE_ENTRY)); if (DataTableEntry == NULL) return FALSE; RtlZeroMemory(DataTableEntry, sizeof(LDR_DATA_TABLE_ENTRY)); @@ -61,17 +187,19 @@ WinLdrAllocateDataTableEntry(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock, /* Initialize corresponding fields of DTE based on NT headers value */ DataTableEntry->DllBase = BaseVA; DataTableEntry->SizeOfImage = NtHeaders->OptionalHeader.SizeOfImage; - DataTableEntry->EntryPoint = (PVOID)((ULONG)BaseVA + - NtHeaders->OptionalHeader.AddressOfEntryPoint); + DataTableEntry->EntryPoint = RVA(BaseVA, NtHeaders->OptionalHeader.AddressOfEntryPoint); DataTableEntry->SectionPointer = 0; DataTableEntry->CheckSum = NtHeaders->OptionalHeader.CheckSum; /* Initialize BaseDllName field (UNICODE_STRING) from the Ansi BaseDllName by simple conversion - copying each character */ Length = (USHORT)(strlen(BaseDllName) * sizeof(WCHAR)); - Buffer = (PWSTR)MmAllocateMemory(Length); + Buffer = (PWSTR)MmHeapAlloc(Length); if (Buffer == NULL) + { + MmHeapFree(DataTableEntry); return FALSE; + } RtlZeroMemory(Buffer, Length); DataTableEntry->BaseDllName.Length = Length; @@ -85,9 +213,12 @@ WinLdrAllocateDataTableEntry(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock, /* Initialize FullDllName field (UNICODE_STRING) from the Ansi FullDllName using the same method */ Length = (USHORT)(strlen(FullDllName) * sizeof(WCHAR)); - Buffer = (PWSTR)MmAllocateMemory(Length); + Buffer = (PWSTR)MmHeapAlloc(Length); if (Buffer == NULL) + { + MmHeapFree(DataTableEntry); return FALSE; + } RtlZeroMemory(Buffer, Length); DataTableEntry->FullDllName.Length = Length; @@ -121,6 +252,7 @@ WinLdrAllocateDataTableEntry(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock, */ BOOLEAN WinLdrLoadImage(IN PCHAR FileName, + TYPE_OF_MEMORY MemoryType, OUT PVOID *ImageBasePA) { PFILE FileHandle; @@ -133,7 +265,11 @@ WinLdrLoadImage(IN PCHAR FileName, BOOLEAN Status; ULONG i, BytesRead; - //Print(L"Loading %s... ", FileName); + CHAR ProgressString[256]; + + /* Inform user we are loading files */ + sprintf(ProgressString, "Loading %s...", FileName); + UiDrawProgressBarCenter(1, 100, ProgressString); /* Open the image file */ FileHandle = FsOpenFile(FileName); @@ -181,14 +317,15 @@ WinLdrLoadImage(IN PCHAR FileName, /* Try to allocate this memory, if fails - allocate somewhere else */ PhysicalBase = MmAllocateMemoryAtAddress(NtHeaders->OptionalHeader.SizeOfImage, - (PVOID)NtHeaders->OptionalHeader.ImageBase); + (PVOID)((ULONG)NtHeaders->OptionalHeader.ImageBase & (KSEG0_BASE - 1)), + MemoryType); if (PhysicalBase == NULL) { /* It's ok, we don't panic - let's allocate again at any other "low" place */ - MmChangeAllocationPolicy(FALSE); - PhysicalBase = MmAllocateMemory(NtHeaders->OptionalHeader.SizeOfImage); - MmChangeAllocationPolicy(TRUE); + //MmChangeAllocationPolicy(FALSE); + PhysicalBase = MmAllocateMemoryWithType(NtHeaders->OptionalHeader.SizeOfImage, MemoryType); + //MmChangeAllocationPolicy(TRUE); if (PhysicalBase == NULL) { @@ -261,12 +398,18 @@ WinLdrLoadImage(IN PCHAR FileName, Status = FsReadFile(FileHandle, SizeOfRawData, &BytesRead, (PUCHAR)PhysicalBase + SectionHeader->VirtualAddress); if (!Status && (BytesRead == 0)) + { + DbgPrint((DPRINT_WINDOWS, "WinLdrLoadImage(): Error reading section from file!\n")); break; + } } /* Size of data is less than the virtual size - fill up the remainder with zeroes */ if (SizeOfRawData < VirtualSize) + { + DbgPrint((DPRINT_WINDOWS, "WinLdrLoadImage(): SORD %d < VS %d", SizeOfRawData, VirtualSize)); RtlZeroMemory((PVOID)(SectionHeader->VirtualAddress + (ULONG)PhysicalBase + SizeOfRawData), VirtualSize - SizeOfRawData); + } SectionHeader++; } @@ -285,10 +428,10 @@ WinLdrLoadImage(IN PCHAR FileName, DbgPrint((DPRINT_WINDOWS, "Relocating %p -> %p\n", NtHeaders->OptionalHeader.ImageBase, VirtualBase)); Status = (BOOLEAN)LdrRelocateImageWithBias(PhysicalBase, - 0, - "FLx86", + (ULONG_PTR)VirtualBase - (ULONG_PTR)PhysicalBase, + "FreeLdr", TRUE, - 3, + TRUE, /* in case of conflict still return success */ FALSE); } @@ -296,3 +439,394 @@ WinLdrLoadImage(IN PCHAR FileName, } /* PRIVATE FUNCTIONS *******************************************************/ + +/* DllName - physical, UnicodeString->Buffer - virtual */ +BOOLEAN +WinLdrpCompareDllName(IN PCH DllName, + IN PUNICODE_STRING UnicodeName) +{ + PWSTR Buffer; + UNICODE_STRING UnicodeNamePA; + ULONG i, Length; + + /* First obvious check: for length of two names */ + Length = strlen(DllName); + + UnicodeNamePA.Length = UnicodeName->Length; + UnicodeNamePA.MaximumLength = UnicodeName->MaximumLength; + UnicodeNamePA.Buffer = VaToPa(UnicodeName->Buffer); + DbgPrint((DPRINT_WINDOWS, "WinLdrpCompareDllName: %s and %wZ, Length = %d " + "UN->Length %d\n", DllName, &UnicodeNamePA, Length, UnicodeName->Length)); + + if ((Length * sizeof(WCHAR)) > UnicodeName->Length) + return FALSE; + + /* Store pointer to unicode string's buffer */ + Buffer = VaToPa(UnicodeName->Buffer); + + /* Loop character by character */ + for (i = 0; i < Length; i++) + { + /* Compare two characters, uppercasing them */ + if (toupper(*DllName) != toupper((CHAR)*Buffer)) + return FALSE; + + /* Move to the next character */ + DllName++; + Buffer++; + } + + /* Check, if strings either fully match, or match till the "." (w/o extension) */ + if ((UnicodeName->Length == Length * sizeof(WCHAR)) || (*Buffer == L'.')) + { + /* Yes they do */ + return TRUE; + } + + /* Strings don't match, return FALSE */ + return FALSE; +} + +BOOLEAN +WinLdrpBindImportName(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock, + IN PVOID DllBase, + IN PVOID ImageBase, + IN PIMAGE_THUNK_DATA ThunkData, + IN PIMAGE_EXPORT_DIRECTORY ExportDirectory, + IN ULONG ExportSize, + IN BOOLEAN ProcessForwards) +{ + ULONG Ordinal; + PULONG NameTable, FunctionTable; + PUSHORT OrdinalTable; + LONG High, Low, Middle, Result; + ULONG Hint; + + //DbgPrint((DPRINT_WINDOWS, "WinLdrpBindImportName(): DllBase 0x%X, ImageBase 0x%X, ThunkData 0x%X, ExportDirectory 0x%X, ExportSize %d, ProcessForwards 0x%X\n", + // DllBase, ImageBase, ThunkData, ExportDirectory, ExportSize, ProcessForwards)); + + /* Check passed DllBase param */ + if(DllBase == NULL) + { + DbgPrint((DPRINT_WINDOWS, "WARNING: DllBase == NULL!\n")); + return FALSE; + } + + /* Convert all non-critical pointers to PA from VA */ + ThunkData = VaToPa(ThunkData); + + /* Is the reference by ordinal? */ + if (IMAGE_SNAP_BY_ORDINAL(ThunkData->u1.Ordinal) && !ProcessForwards) + { + /* Yes, calculate the ordinal */ + Ordinal = (ULONG)(IMAGE_ORDINAL(ThunkData->u1.Ordinal) - (UINT32)ExportDirectory->Base); + //DbgPrint((DPRINT_WINDOWS, "WinLdrpBindImportName(): Ordinal %d\n", Ordinal)); + } + else + { + /* It's reference by name, we have to look it up in the export directory */ + if (!ProcessForwards) + { + /* AddressOfData in thunk entry will become a virtual address (from relative) */ + //DbgPrint((DPRINT_WINDOWS, "WinLdrpBindImportName(): ThunkData->u1.AOD was %p\n", ThunkData->u1.AddressOfData)); + ThunkData->u1.AddressOfData = + (ULONG)RVA(ImageBase, ThunkData->u1.AddressOfData); + //DbgPrint((DPRINT_WINDOWS, "WinLdrpBindImportName(): ThunkData->u1.AOD became %p\n", ThunkData->u1.AddressOfData)); + } + + /* Get pointers to Name and Ordinal tables (RVA -> VA) */ + NameTable = (PULONG)VaToPa(RVA(DllBase, ExportDirectory->AddressOfNames)); + OrdinalTable = (PUSHORT)VaToPa(RVA(DllBase, ExportDirectory->AddressOfNameOrdinals)); + + //DbgPrint((DPRINT_WINDOWS, "NameTable 0x%X, OrdinalTable 0x%X, ED->AddressOfNames 0x%X, ED->AOFO 0x%X\n", + // NameTable, OrdinalTable, ExportDirectory->AddressOfNames, ExportDirectory->AddressOfNameOrdinals)); + + /* Get the hint, convert it to a physical pointer */ + Hint = ((PIMAGE_IMPORT_BY_NAME)VaToPa((PVOID)ThunkData->u1.AddressOfData))->Hint; + //DbgPrint((DPRINT_WINDOWS, "HintIndex %d\n", Hint)); + + /* If Hint is less than total number of entries in the export directory, + and import name == export name, then we can just get it from the OrdinalTable */ + if ( + (Hint < ExportDirectory->NumberOfNames) && + ( + strcmp(VaToPa(&((PIMAGE_IMPORT_BY_NAME)VaToPa((PVOID)ThunkData->u1.AddressOfData))->Name[0]), + (PCHAR)VaToPa( RVA(DllBase, NameTable[Hint])) ) == 0 + ) + ) + { + Ordinal = OrdinalTable[Hint]; + //DbgPrint((DPRINT_WINDOWS, "WinLdrpBindImportName(): Ordinal %d\n", Ordinal)); + } + else + { + /* It's not the easy way, we have to lookup import name in the name table. + Let's use a binary search for this task. */ + + //DbgPrint((DPRINT_WINDOWS, "WinLdrpBindImportName() looking up the import name using binary search...\n")); + + /* Low boundary is set to 0, and high boundary to the maximum index */ + Low = 0; + High = ExportDirectory->NumberOfNames - 1; + + /* Perform a binary-search loop */ + while (High >= Low) + { + /* Divide by 2 by shifting to the right once */ + Middle = (Low + High) >> 1; + + /* Compare the names */ + Result = strcmp(VaToPa(&((PIMAGE_IMPORT_BY_NAME)VaToPa((PVOID)ThunkData->u1.AddressOfData))->Name[0]), + (PCHAR)VaToPa(RVA(DllBase, NameTable[Middle]))); + + /*DbgPrint((DPRINT_WINDOWS, "Binary search: comparing Import '__', Export '%s'\n",*/ + /*VaToPa(&((PIMAGE_IMPORT_BY_NAME)VaToPa(ThunkData->u1.AddressOfData))->Name[0]),*/ + /*(PCHAR)VaToPa(RVA(DllBase, NameTable[Middle]))));*/ + + /*DbgPrint((DPRINT_WINDOWS, "TE->u1.AOD %p, fulladdr %p\n", + ThunkData->u1.AddressOfData, + ((PIMAGE_IMPORT_BY_NAME)VaToPa(ThunkData->u1.AddressOfData))->Name ));*/ + + + /* Depending on result of strcmp, perform different actions */ + if (Result < 0) + { + /* Adjust top boundary */ + High = Middle - 1; + } + else if (Result > 0) + { + /* Adjust bottom boundary */ + Low = Middle + 1; + } + else + { + /* Yay, found it! */ + break; + } + } + + /* If high boundary is less than low boundary, then no result found */ + if (High < Low) + { + //Print(L"Error in binary search\n"); + DbgPrint((DPRINT_WINDOWS, "Error in binary search!\n")); + return FALSE; + } + + /* Everything allright, get the ordinal */ + Ordinal = OrdinalTable[Middle]; + + //DbgPrint((DPRINT_WINDOWS, "WinLdrpBindImportName() found Ordinal %d\n", Ordinal)); + } + } + + /* Check ordinal number for validity! */ + if (Ordinal >= ExportDirectory->NumberOfFunctions) + { + DbgPrint((DPRINT_WINDOWS, "Ordinal number is invalid!\n")); + return FALSE; + } + + /* Get a pointer to the function table */ + FunctionTable = (PULONG)VaToPa(RVA(DllBase, ExportDirectory->AddressOfFunctions)); + + /* Save a pointer to the function */ + ThunkData->u1.Function = (ULONG)RVA(DllBase, FunctionTable[Ordinal]); + + /* Is it a forwarder? (function pointer isn't within the export directory) */ + if (((ULONG)VaToPa((PVOID)ThunkData->u1.Function) > (ULONG)ExportDirectory) && + ((ULONG)VaToPa((PVOID)ThunkData->u1.Function) < ((ULONG)ExportDirectory + ExportSize))) + { + PLDR_DATA_TABLE_ENTRY DataTableEntry; + CHAR ForwardDllName[255]; + PIMAGE_EXPORT_DIRECTORY RefExportDirectory; + ULONG RefExportSize; + + /* Save the name of the forward dll */ + RtlCopyMemory(ForwardDllName, (PCHAR)VaToPa((PVOID)ThunkData->u1.Function), sizeof(ForwardDllName)); + + /* Strip out its extension */ + *strchr(ForwardDllName,'.') = '\0'; + + DbgPrint((DPRINT_WINDOWS, "WinLdrpBindImportName(): ForwardDllName %s\n", ForwardDllName)); + if (!WinLdrCheckForLoadedDll(WinLdrBlock, ForwardDllName, &DataTableEntry)) + { + /* We can't continue if DLL couldn't be loaded, so bomb out with an error */ + //Print(L"Error loading DLL!\n"); + DbgPrint((DPRINT_WINDOWS, "Error loading DLL!\n")); + return FALSE; + } + + /* Get pointer to the export directory of loaded DLL */ + RefExportDirectory = (PIMAGE_EXPORT_DIRECTORY) + RtlImageDirectoryEntryToData(VaToPa(DataTableEntry->DllBase), + TRUE, + IMAGE_DIRECTORY_ENTRY_EXPORT, + &RefExportSize); + + /* Fail if it's NULL */ + if (RefExportDirectory) + { + UCHAR Buffer[128]; + IMAGE_THUNK_DATA RefThunkData; + PIMAGE_IMPORT_BY_NAME ImportByName; + PCHAR ImportName; + BOOLEAN Status; + + /* Get pointer to the import name */ + ImportName = strchr((PCHAR)VaToPa((PVOID)ThunkData->u1.Function), '.') + 1; + + /* Create a IMAGE_IMPORT_BY_NAME structure, pointing to the local Buffer */ + ImportByName = (PIMAGE_IMPORT_BY_NAME)Buffer; + + /* Fill the name with the import name */ + RtlCopyMemory(ImportByName->Name, ImportName, strlen(ImportName)+1); + + /* Set Hint to 0 */ + ImportByName->Hint = 0; + + /* And finally point ThunkData's AddressOfData to that structure */ + RefThunkData.u1.AddressOfData = (ULONG)ImportByName; + + /* And recursively call ourselves */ + Status = WinLdrpBindImportName( + WinLdrBlock, + DataTableEntry->DllBase, + ImageBase, + &RefThunkData, + RefExportDirectory, + RefExportSize, + TRUE); + + /* Fill out the ThunkData with data from RefThunkData */ + ThunkData->u1 = RefThunkData.u1; + + /* Return what we got from the recursive call */ + return Status; + } + else + { + /* Fail if ExportDirectory is NULL */ + return FALSE; + } + } + + /* Success! */ + return TRUE; +} + +BOOLEAN +WinLdrpLoadAndScanReferencedDll(PLOADER_PARAMETER_BLOCK WinLdrBlock, + PCCH DirectoryPath, + PCH ImportName, + PLDR_DATA_TABLE_ENTRY *DataTableEntry) +{ + CHAR FullDllName[256]; + BOOLEAN Status; + PVOID BasePA; + + /* Prepare the full path to the file to be loaded */ + strcpy(FullDllName, DirectoryPath); + strcat(FullDllName, ImportName); + + DbgPrint((DPRINT_WINDOWS, "Loading referenced DLL: %s\n", FullDllName)); + //Print(L"Loading referenced DLL: %s\n", FullDllName); + + /* Load the image */ + Status = WinLdrLoadImage(FullDllName, LoaderHalCode, &BasePA); + + if (!Status) + { + DbgPrint((DPRINT_WINDOWS, "WinLdrLoadImage() failed\n")); + return Status; + } + + /* Allocate DTE for newly loaded DLL */ + Status = WinLdrAllocateDataTableEntry(WinLdrBlock, + ImportName, + FullDllName, + BasePA, + DataTableEntry); + + if (!Status) + { + DbgPrint((DPRINT_WINDOWS, + "WinLdrAllocateDataTableEntry() failed with Status=0x%X\n", Status)); + return Status; + } + + /* Scan its dependencies too */ + DbgPrint((DPRINT_WINDOWS, + "WinLdrScanImportDescriptorTable() calling ourselves for %S\n", + VaToPa((*DataTableEntry)->BaseDllName.Buffer))); + Status = WinLdrScanImportDescriptorTable(WinLdrBlock, DirectoryPath, *DataTableEntry); + + if (!Status) + { + DbgPrint((DPRINT_WINDOWS, + "WinLdrScanImportDescriptorTable() failed with Status=0x%X\n", Status)); + return Status; + } + + return TRUE; +} + +BOOLEAN +WinLdrpScanImportAddressTable(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock, + IN PVOID DllBase, + IN PVOID ImageBase, + IN PIMAGE_THUNK_DATA ThunkData) +{ + PIMAGE_EXPORT_DIRECTORY ExportDirectory = NULL; + BOOLEAN Status; + ULONG ExportSize; + + DbgPrint((DPRINT_WINDOWS, "WinLdrpScanImportAddressTable(): DllBase 0x%X, " + "ImageBase 0x%X, ThunkData 0x%X\n", DllBase, ImageBase, ThunkData)); + + /* Obtain the export table from the DLL's base */ + if (DllBase == NULL) + { + //Print(L"Error, DllBase == NULL!\n"); + return FALSE; + } + else + { + ExportDirectory = + (PIMAGE_EXPORT_DIRECTORY)RtlImageDirectoryEntryToData(VaToPa(DllBase), + TRUE, + IMAGE_DIRECTORY_ENTRY_EXPORT, + &ExportSize); + } + + DbgPrint((DPRINT_WINDOWS, "WinLdrpScanImportAddressTable(): ExportDirectory 0x%X\n", ExportDirectory)); + + /* If pointer to Export Directory is */ + if (ExportDirectory == NULL) + return FALSE; + + /* Go through each entry in the thunk table and bind it */ + while (((PIMAGE_THUNK_DATA)VaToPa(ThunkData))->u1.AddressOfData != 0) + { + /* Bind it */ + Status = WinLdrpBindImportName( + WinLdrBlock, + DllBase, + ImageBase, + ThunkData, + ExportDirectory, + ExportSize, + FALSE); + + /* Move to the next entry */ + ThunkData++; + + /* Return error if binding was unsuccessful */ + if (!Status) + return Status; + } + + /* Return success */ + return TRUE; +} diff --git a/reactos/boot/freeldr/freeldr/windows/winldr.c b/reactos/boot/freeldr/freeldr/windows/winldr.c index d111a45fdd2..2cfb680c72b 100644 --- a/reactos/boot/freeldr/freeldr/windows/winldr.c +++ b/reactos/boot/freeldr/freeldr/windows/winldr.c @@ -29,9 +29,6 @@ extern ULONG reactos_disk_count; extern ARC_DISK_SIGNATURE reactos_arc_disk_info[]; extern char reactos_arc_strings[32][256]; -ARC_DISK_SIGNATURE BldrDiskInfo[32]; -CHAR BldrArcNames[32][256]; - BOOLEAN WinLdrCheckForLoadedDll(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock, IN PCH DllName, @@ -44,47 +41,6 @@ VOID WinLdrpDumpBootDriver(PLOADER_PARAMETER_BLOCK LoaderBlock); VOID WinLdrpDumpArcDisks(PLOADER_PARAMETER_BLOCK LoaderBlock); -void InitializeHWConfig(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock) -{ - PCONFIGURATION_COMPONENT_DATA ConfigurationRoot; - PCONFIGURATION_COMPONENT Component; - PCONFIGURATION_COMPONENT_DATA /*CurrentEntry,*/ PreviousEntry, AdapterEntry; - BOOLEAN IsNextEntryChild; - - DbgPrint((DPRINT_WINDOWS, "InitializeHWConfig()\n")); - - LoaderBlock->ConfigurationRoot = MmAllocateMemory(sizeof(CONFIGURATION_COMPONENT_DATA)); - RtlZeroMemory(LoaderBlock->ConfigurationRoot, sizeof(CONFIGURATION_COMPONENT_DATA)); - - /* Fill root == SystemClass */ - ConfigurationRoot = LoaderBlock->ConfigurationRoot; - Component = &LoaderBlock->ConfigurationRoot->ComponentEntry; - - Component->Class = SystemClass; - Component->Type = MaximumType; - Component->Version = 0; // FIXME: ? - Component->Key = 0; - Component->AffinityMask = 0; - - IsNextEntryChild = TRUE; - PreviousEntry = ConfigurationRoot; - - /* Enumerate all PCI buses */ - AdapterEntry = ConfigurationRoot; - - /* TODO: Disk Geometry */ - /* TODO: Keyboard */ - - /* TODO: Serial port */ - - //Config->ConfigurationData = alloc(sizeof(CONFIGURATION_COMPONENT_DATA), EfiLoaderData); - - /* Convert everything to VA */ - ConvertConfigToVA(LoaderBlock->ConfigurationRoot); - LoaderBlock->ConfigurationRoot = PaToVa(LoaderBlock->ConfigurationRoot); -} - - // Init "phase 0" VOID AllocateAndInitLPB(PLOADER_PARAMETER_BLOCK *OutLoaderBlock) @@ -92,7 +48,7 @@ AllocateAndInitLPB(PLOADER_PARAMETER_BLOCK *OutLoaderBlock) PLOADER_PARAMETER_BLOCK LoaderBlock; /* Allocate and zero-init the LPB */ - LoaderBlock = MmAllocateMemory(sizeof(LOADER_PARAMETER_BLOCK)); + LoaderBlock = MmHeapAlloc(sizeof(LOADER_PARAMETER_BLOCK)); RtlZeroMemory(LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK)); /* Init three critical lists, used right away */ @@ -101,7 +57,7 @@ AllocateAndInitLPB(PLOADER_PARAMETER_BLOCK *OutLoaderBlock) InitializeListHead(&LoaderBlock->BootDriverListHead); /* Alloc space for NLS (it will be converted to VA in WinLdrLoadNLS) */ - LoaderBlock->NlsData = MmAllocateMemory(sizeof(NLS_DATA_BLOCK)); + LoaderBlock->NlsData = MmHeapAlloc(sizeof(NLS_DATA_BLOCK)); if (LoaderBlock->NlsData == NULL) { UiMessageBox("Failed to allocate memory for NLS table data!"); @@ -114,47 +70,63 @@ AllocateAndInitLPB(PLOADER_PARAMETER_BLOCK *OutLoaderBlock) // Init "phase 1" VOID -WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock) +WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock, + PCHAR Options, + PCHAR SystemPath, + WORD VersionToBoot) { - //CHAR Options[] = "/CRASHDEBUG /DEBUGPORT=COM1 /BAUDRATE=115200"; - CHAR Options[] = "/NODEBUG"; - CHAR SystemRoot[] = "\\WINNT\\"; - CHAR HalPath[] = "\\"; - CHAR ArcBoot[] = "multi(0)disk(0)rdisk(1)partition(1)"; - CHAR ArcHal[] = "multi(0)disk(0)rdisk(1)partition(1)"; + /* Examples of correct options and paths */ + //CHAR Options[] = "/DEBUGPORT=COM1 /BAUDRATE=115200"; + //CHAR Options[] = "/NODEBUG"; + //CHAR SystemRoot[] = "\\WINNT\\"; + //CHAR ArcBoot[] = "multi(0)disk(0)rdisk(0)partition(1)"; - ULONG i; + CHAR HalPath[] = "\\"; + CHAR SystemRoot[256]; + CHAR ArcBoot[256]; + ULONG i, PathSeparator; PLOADER_PARAMETER_EXTENSION Extension; LoaderBlock->u.I386.CommonDataArea = NULL; // Force No ABIOS support + /* Construct SystemRoot and ArcBoot from SystemPath */ + PathSeparator = strstr(SystemPath, "\\") - SystemPath; + strncpy(ArcBoot, SystemPath, PathSeparator); + ArcBoot[PathSeparator] = 0; + strcpy(SystemRoot, &SystemPath[PathSeparator]); + strcat(SystemRoot, "\\"); + + DbgPrint((DPRINT_WINDOWS, "ArcBoot: %s\n", ArcBoot)); + DbgPrint((DPRINT_WINDOWS, "SystemRoot: %s\n", SystemRoot)); + DbgPrint((DPRINT_WINDOWS, "Options: %s\n", Options)); + /* Fill Arc BootDevice */ - LoaderBlock->ArcBootDeviceName = MmAllocateMemory(strlen(ArcBoot)+1); + LoaderBlock->ArcBootDeviceName = MmHeapAlloc(strlen(ArcBoot)+1); strcpy(LoaderBlock->ArcBootDeviceName, ArcBoot); LoaderBlock->ArcBootDeviceName = PaToVa(LoaderBlock->ArcBootDeviceName); - /* Fill Arc HalDevice */ - LoaderBlock->ArcHalDeviceName = MmAllocateMemory(strlen(ArcHal)+1); - strcpy(LoaderBlock->ArcHalDeviceName, ArcHal); + /* Fill Arc HalDevice, it matches ArcBoot path */ + LoaderBlock->ArcHalDeviceName = MmHeapAlloc(strlen(ArcBoot)+1); + strcpy(LoaderBlock->ArcHalDeviceName, ArcBoot); LoaderBlock->ArcHalDeviceName = PaToVa(LoaderBlock->ArcHalDeviceName); /* Fill SystemRoot */ - LoaderBlock->NtBootPathName = MmAllocateMemory(strlen(SystemRoot)+1); + LoaderBlock->NtBootPathName = MmHeapAlloc(strlen(SystemRoot)+1); strcpy(LoaderBlock->NtBootPathName, SystemRoot); LoaderBlock->NtBootPathName = PaToVa(LoaderBlock->NtBootPathName); /* Fill NtHalPathName */ - LoaderBlock->NtHalPathName = MmAllocateMemory(strlen(HalPath)+1); + LoaderBlock->NtHalPathName = MmHeapAlloc(strlen(HalPath)+1); strcpy(LoaderBlock->NtHalPathName, HalPath); LoaderBlock->NtHalPathName = PaToVa(LoaderBlock->NtHalPathName); /* Fill load options */ - LoaderBlock->LoadOptions = MmAllocateMemory(strlen(Options)+1); + LoaderBlock->LoadOptions = MmHeapAlloc(strlen(Options)+1); strcpy(LoaderBlock->LoadOptions, Options); LoaderBlock->LoadOptions = PaToVa(LoaderBlock->LoadOptions); /* Arc devices */ - LoaderBlock->ArcDiskInformation = (PARC_DISK_INFORMATION)MmAllocateMemory(sizeof(ARC_DISK_INFORMATION)); + LoaderBlock->ArcDiskInformation = (PARC_DISK_INFORMATION)MmHeapAlloc(sizeof(ARC_DISK_INFORMATION)); InitializeListHead(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead); /* Convert ARC disk information from freeldr to a correct format */ @@ -163,42 +135,48 @@ WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock) PARC_DISK_SIGNATURE ArcDiskInfo; /* Get the ARC structure */ - ArcDiskInfo = &BldrDiskInfo[i]; + ArcDiskInfo = (PARC_DISK_SIGNATURE)MmHeapAlloc(sizeof(ARC_DISK_SIGNATURE)); + RtlZeroMemory(ArcDiskInfo, sizeof(ARC_DISK_SIGNATURE)); /* Copy the data over */ ArcDiskInfo->Signature = reactos_arc_disk_info[i].Signature; ArcDiskInfo->CheckSum = reactos_arc_disk_info[i].CheckSum; /* Copy the ARC Name */ - strcpy(BldrArcNames[i], reactos_arc_disk_info[i].ArcName); - ArcDiskInfo->ArcName = BldrArcNames[i]; + ArcDiskInfo->ArcName = (PCHAR)MmHeapAlloc(sizeof(CHAR)*256); + strcpy(ArcDiskInfo->ArcName, reactos_arc_disk_info[i].ArcName); + ArcDiskInfo->ArcName = (PCHAR)PaToVa(ArcDiskInfo->ArcName); + + /* Mark partition table as valid */ + ArcDiskInfo->ValidPartitionTable = TRUE; /* Insert into the list */ InsertTailList(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead, &ArcDiskInfo->ListEntry); } - /* Convert the list to virtual address */ + /* Convert all list's to Virtual address */ + + /* Convert the ArcDisks list to virtual address */ List_PaToVa(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead); LoaderBlock->ArcDiskInformation = PaToVa(LoaderBlock->ArcDiskInformation); - /* Create configuration entries */ - InitializeHWConfig(LoaderBlock); + /* Convert configuration entries to VA */ + ConvertConfigToVA(LoaderBlock->ConfigurationRoot); + LoaderBlock->ConfigurationRoot = PaToVa(LoaderBlock->ConfigurationRoot); /* Convert all DTE into virtual addresses */ - //TODO: !!! - - /* Convert all list's to Virtual address */ List_PaToVa(&LoaderBlock->LoadOrderListHead); /* this one will be converted right before switching to virtual paging mode */ //List_PaToVa(&LoaderBlock->MemoryDescriptorListHead); + /* Convert list of boot drivers */ List_PaToVa(&LoaderBlock->BootDriverListHead); /* Initialize Extension now */ - Extension = MmAllocateMemory(sizeof(LOADER_PARAMETER_EXTENSION)); + Extension = MmHeapAlloc(sizeof(LOADER_PARAMETER_EXTENSION)); if (Extension == NULL) { UiMessageBox("Failed to allocate LPB Extension!"); @@ -206,9 +184,10 @@ WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock) } RtlZeroMemory(Extension, sizeof(LOADER_PARAMETER_EXTENSION)); + /* Save size and version information */ Extension->Size = sizeof(LOADER_PARAMETER_EXTENSION); - Extension->MajorVersion = 4; - Extension->MinorVersion = 0; + Extension->MajorVersion = (VersionToBoot & 0xFF00) >> 8; + Extension->MinorVersion = VersionToBoot & 0xFF; LoaderBlock->Extension = PaToVa(Extension); @@ -230,7 +209,7 @@ void WinLdrSetupForNt(PLOADER_PARAMETER_BLOCK LoaderBlock, //LoaderBlock->u.I386.MachineType = MachineType; //FIXME: MachineType? /* Allocate 2 pages for PCR */ - Pcr = (ULONG_PTR)MmAllocateMemory(2 * MM_PAGE_SIZE); + Pcr = (ULONG_PTR)MmAllocateMemoryWithType(2 * MM_PAGE_SIZE, LoaderStartupPcrPage); *PcrBasePage = Pcr >> MM_PAGE_SHIFT; if (Pcr == 0) @@ -243,14 +222,14 @@ void WinLdrSetupForNt(PLOADER_PARAMETER_BLOCK LoaderBlock, TssSize = (sizeof(KTSS) + MM_PAGE_SIZE) & ~(MM_PAGE_SIZE - 1); TssPages = TssSize / MM_PAGE_SIZE; - Tss = (ULONG_PTR)MmAllocateMemory(TssSize); + Tss = (ULONG_PTR)MmAllocateMemoryWithType(TssSize, LoaderMemoryData); *TssBasePage = Tss >> MM_PAGE_SHIFT; /* Allocate space for new GDT + IDT */ BlockSize = NUM_GDT*sizeof(KGDTENTRY) + NUM_IDT*sizeof(KIDTENTRY);//FIXME: Use GDT/IDT limits here? NumPages = (BlockSize + MM_PAGE_SIZE - 1) >> MM_PAGE_SHIFT; - *GdtIdt = (PKGDTENTRY)MmAllocateMemory(NumPages * MM_PAGE_SIZE); + *GdtIdt = (PKGDTENTRY)MmAllocateMemoryWithType(NumPages * MM_PAGE_SIZE, LoaderMemoryData); if (*GdtIdt == NULL) { @@ -301,7 +280,7 @@ WinLdrLoadDeviceDriver(PLOADER_PARAMETER_BLOCK LoaderBlock, // It's not loaded, we have to load it sprintf(FullPath,"%s%wZ", BootPath, FilePath); - Status = WinLdrLoadImage(FullPath, &DriverBase); + Status = WinLdrLoadImage(FullPath, LoaderBootDriver, &DriverBase); if (!Status) return FALSE; @@ -344,8 +323,8 @@ WinLdrLoadBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock, { BootDriver = CONTAINING_RECORD(NextBd, BOOT_DRIVER_LIST_ENTRY, ListEntry); - //DbgPrint((DPRINT_WINDOWS, "BootDriver %wZ DTE %08X RegPath: %wZ\n", &BootDriver->FilePath, - // BootDriver->DataTableEntry, &BootDriver->RegistryPath)); + DbgPrint((DPRINT_WINDOWS, "BootDriver %wZ DTE %08X RegPath: %wZ\n", &BootDriver->FilePath, + BootDriver->DataTableEntry, &BootDriver->RegistryPath)); // Paths are relative (FIXME: Are they always relative?) @@ -361,6 +340,10 @@ WinLdrLoadBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock, return FALSE; } + // Convert the RegistryPath and DTE addresses to VA since we are not going to use it anymore + BootDriver->RegistryPath.Buffer = PaToVa(BootDriver->RegistryPath.Buffer); + BootDriver->DataTableEntry = PaToVa(BootDriver->DataTableEntry); + NextBd = BootDriver->ListEntry.Flink; } @@ -371,9 +354,10 @@ VOID LoadAndBootWindows(PCSTR OperatingSystemName, WORD OperatingSystemVersion) { CHAR MsgBuffer[256]; - CHAR SystemPath[1024], SearchPath[1024]; - CHAR FileName[1024]; - CHAR BootPath[256]; + CHAR SystemPath[512], SearchPath[512]; + CHAR FileName[512]; + CHAR BootPath[512]; + CHAR BootOptions[256]; PVOID NtosBase = NULL, HalBase = NULL, KdComBase = NULL; BOOLEAN Status; ULONG SectionId; @@ -402,9 +386,6 @@ LoadAndBootWindows(PCSTR OperatingSystemName, WORD OperatingSystemVersion) UiDrawStatusText("Detecting Hardware..."); UiDrawProgressBarCenter(1, 100, "Loading Windows..."); - //FIXME: This is needed only for MachHwDetect() which performs registry operations! - RegInitializeRegistry(); - /* Make sure the system path is set in the .ini file */ if (!IniReadSettingByName(SectionId, "SystemPath", SystemPath, sizeof(SystemPath))) { @@ -412,16 +393,21 @@ LoadAndBootWindows(PCSTR OperatingSystemName, WORD OperatingSystemVersion) return; } - if (!MachDiskNormalizeSystemPath(SystemPath, - sizeof(SystemPath))) + /* Read booting options */ + if (!IniReadSettingByName(SectionId, "Options", BootOptions, sizeof(BootOptions))) + { + /* Nothing read, make the string empty */ + strcpy(BootOptions, ""); + } + + /* Normalize system path */ + if (!MachDiskNormalizeSystemPath(SystemPath, sizeof(SystemPath))) { UiMessageBox("Invalid system path"); return; } - /* Detect hardware */ - MachHwDetect(); - + /* Let user know we started loading */ UiDrawStatusText("Loading..."); /* Try to open system drive */ @@ -439,36 +425,43 @@ LoadAndBootWindows(PCSTR OperatingSystemName, WORD OperatingSystemVersion) DbgPrint((DPRINT_WINDOWS,"SystemRoot: '%s'\n", BootPath)); - // Allocate and minimalistic-initialize LPB + /* Allocate and minimalistic-initialize LPB */ AllocateAndInitLPB(&LoaderBlock); - // Load kernel + /* Detect hardware */ +#if WHEN_MERGE_COMPLETE + MachHwDetect(&LoaderBlock->ConfigurationRoot); +#else + MachHwDetect(); +#endif + + /* Load kernel */ strcpy(FileName, BootPath); strcat(FileName, "SYSTEM32\\NTOSKRNL.EXE"); - Status = WinLdrLoadImage(FileName, &NtosBase); + Status = WinLdrLoadImage(FileName, LoaderSystemCode, &NtosBase); DbgPrint((DPRINT_WINDOWS, "Ntos loaded with status %d at %p\n", Status, NtosBase)); - // Load HAL + /* Load HAL */ strcpy(FileName, BootPath); strcat(FileName, "SYSTEM32\\HAL.DLL"); - Status = WinLdrLoadImage(FileName, &HalBase); + Status = WinLdrLoadImage(FileName, LoaderHalCode, &HalBase); DbgPrint((DPRINT_WINDOWS, "HAL loaded with status %d at %p\n", Status, HalBase)); - // Load kernel-debugger support dll - if (OperatingSystemVersion > _WIN32_WINNT_NT4) + /* Load kernel-debugger support dll */ + if (OperatingSystemVersion > _WIN32_WINNT_WIN2K) { strcpy(FileName, BootPath); strcat(FileName, "SYSTEM32\\KDCOM.DLL"); - Status = WinLdrLoadImage(FileName, &KdComBase); + Status = WinLdrLoadImage(FileName, LoaderBootDriver, &KdComBase); DbgPrint((DPRINT_WINDOWS, "KdCom loaded with status %d at %p\n", Status, KdComBase)); } - // Allocate data table entries for above-loaded modules + /* Allocate data table entries for above-loaded modules */ WinLdrAllocateDataTableEntry(LoaderBlock, "ntoskrnl.exe", "WINNT\\SYSTEM32\\NTOSKRNL.EXE", NtosBase, &KernelDTE); WinLdrAllocateDataTableEntry(LoaderBlock, "hal.dll", "WINNT\\SYSTEM32\\HAL.DLL", HalBase, &HalDTE); - if (OperatingSystemVersion > _WIN32_WINNT_NT4) + if (OperatingSystemVersion > _WIN32_WINNT_WIN2K) { WinLdrAllocateDataTableEntry(LoaderBlock, "kdcom.dll", "WINNT\\SYSTEM32\\KDCOM.DLL", KdComBase, &KdComDTE); @@ -491,16 +484,19 @@ LoadAndBootWindows(PCSTR OperatingSystemName, WORD OperatingSystemVersion) DbgPrint((DPRINT_WINDOWS, "Boot drivers loaded with status %d\n", Status)); /* Initialize Phase 1 - no drivers loading anymore */ - WinLdrInitializePhase1(LoaderBlock); + WinLdrInitializePhase1(LoaderBlock, BootOptions, SystemPath, OperatingSystemVersion); /* Alloc PCR, TSS, do magic things with the GDT/IDT */ WinLdrSetupForNt(LoaderBlock, &GdtIdt, &PcrBasePage, &TssBasePage); - /* Save entry-point pointer (VA) */ + /* Save entry-point pointer and Loader block VAs */ KiSystemStartup = (KERNEL_ENTRY_POINT)KernelDTE->EntryPoint; - LoaderBlockVA = PaToVa(LoaderBlock); + /* "Stop all motors", change videomode */ + DiskStopFloppyMotor(); + MachVideoPrepareForReactOS(FALSE); + /* Debugging... */ //DumpMemoryAllocMap(); @@ -521,7 +517,7 @@ LoadAndBootWindows(PCSTR OperatingSystemName, WORD OperatingSystemVersion) asm("jmp test1\n"); asm(".att_syntax\n");*/ - + /* Pass control */ (*KiSystemStartup)(LoaderBlockVA); return; @@ -539,7 +535,6 @@ WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock) { MemoryDescriptor = CONTAINING_RECORD(NextMd, MEMORY_ALLOCATION_DESCRIPTOR, ListEntry); - DbgPrint((DPRINT_WINDOWS, "BP %08X PC %04X MT %d\n", MemoryDescriptor->BasePage, MemoryDescriptor->PageCount, MemoryDescriptor->MemoryType)); diff --git a/reactos/boot/freeldr/freeldr/windows/wlmemory.c b/reactos/boot/freeldr/freeldr/windows/wlmemory.c index ae447b372b1..8835702a0f5 100644 --- a/reactos/boot/freeldr/freeldr/windows/wlmemory.c +++ b/reactos/boot/freeldr/freeldr/windows/wlmemory.c @@ -19,40 +19,33 @@ extern ULONG TotalNLSSize; #undef KIP0PCRADDRESS #define KIP0PCRADDRESS 0xffdff000 -// -// This is the zone which is used by the OS loader -// -#define LOADER_HIGH_ZONE ((16*1024*1024) >> MM_PAGE_SHIFT) //16Mb page - #define HYPER_SPACE_ENTRY 0x300 -//TODO: Check if this is correct PCHAR MemTypeDesc[] = { - "ExceptionBlock ", - "SystemBlock ", + "ExceptionBlock ", // ? + "SystemBlock ", // ? "Free ", - "Bad ", - "LoadedProgram ", - "FirmwareTemporary ", - "FirmwarePermanent ", - "OsloaderHeap ", - "OsloaderStack ", + "Bad ", // used + "LoadedProgram ", // == Free + "FirmwareTemporary ", // == Free + "FirmwarePermanent ", // == Bad + "OsloaderHeap ", // used + "OsloaderStack ", // == Free "SystemCode ", "HalCode ", - "BootDriver ", - "ConsoleInDriver ", - "ConsoleOutDriver ", - "StartupDpcStack ", - "StartupKernelStack", - "StartupPanicStack ", - "StartupPcrPage ", - "StartupPdrPage ", - "RegistryData ", - "MemoryData ", - "NlsData ", - "SpecialMemory ", - "BBTMemory ", - "Maximum " + "BootDriver ", // not used + "ConsoleInDriver ", // ? + "ConsoleOutDriver ", // ? + "StartupDpcStack ", // ? + "StartupKernelStack", // ? + "StartupPanicStack ", // ? + "StartupPcrPage ", // ? + "StartupPdrPage ", // ? + "RegistryData ", // used + "MemoryData ", // not used + "NlsData ", // used + "SpecialMemory ", // == Bad + "BBTMemory " // == Bad }; VOID @@ -61,8 +54,8 @@ WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock); VOID MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, - UINT64 BasePage, - UINT64 PageCount, + ULONG BasePage, + ULONG PageCount, ULONG Type); VOID WinLdrInsertDescriptor(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, @@ -136,8 +129,9 @@ MempAllocatePageTables() // Allocate memory block for all these things: // PDE, HAL mapping page table, physical mapping, kernel mapping + // FIXME: PDE+HAL+KernelPTEs == FirmwarePermanent, Physical PTEs = FirmwareTemporary TotalSize = (1+1+NumPageTables*2)*MM_PAGE_SIZE; - Buffer = MmAllocateMemory(TotalSize); + Buffer = MmAllocateMemoryWithType(TotalSize, LoaderFirmwarePermanent); if (Buffer == NULL) { @@ -168,6 +162,9 @@ MempAllocatePageTables() PhysicalPageTablesBuffer = &Buffer[MM_PAGE_SIZE*2]; KernelPageTablesBuffer = PhysicalPageTablesBuffer + NumPageTables*MM_PAGE_SIZE; + // Mark physical PTE's buffer as FirmwareTemporary + //MmSetMemoryType(KernelPageTablesBuffer, NumPageTables*MM_PAGE_SIZE, LoaderFirmwareTemporary); + // Zero counters of page tables used PhysicalPageTables = 0; KernelPageTables = 0; @@ -211,7 +208,7 @@ MempSetupPaging(IN ULONG StartPage, ULONG Entry, Page; //Print(L"MempSetupPaging: SP 0x%X, Number: 0x%X\n", StartPage, NumberOfPages); - + // HACK if (StartPage+NumberOfPages >= 0x80000) { @@ -265,10 +262,71 @@ MempSetupPaging(IN ULONG StartPage, return TRUE; } +VOID +MempDisablePages() +{ + int i; + + // + // We need to delete kernel mapping from memory areas which are + // marked as Special or Permanent memory (thus non-accessible) + // + + for (i=0; i LOADER_HIGH_ZONE) + EndPage = LOADER_HIGH_ZONE; + } + + for (Page = StartPage; Page < EndPage; Page++) + { + PHARDWARE_PTE KernelPT; + ULONG Entry = (Page >> 10) + (KSEG0_BASE >> 22); + + if (PDE[Entry].Valid) + { + KernelPT = (PHARDWARE_PTE)(PDE[Entry].PageFrameNumber << MM_PAGE_SHIFT); + + if (KernelPT) + { + KernelPT[Page & 0x3ff].PageFrameNumber = 0; + KernelPT[Page & 0x3ff].Valid = 0; + KernelPT[Page & 0x3ff].Write = 0; + } + } + } + } + } +} + + VOID MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, - UINT64 BasePage, - UINT64 PageCount, + ULONG BasePage, + ULONG PageCount, ULONG Type) { BOOLEAN Status; @@ -285,81 +343,42 @@ MempAddMemoryBlock(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, } // - // Base page and page count are always set + // Set Base page, page count and type // Mad[MadCount].BasePage = BasePage; Mad[MadCount].PageCount = PageCount; + Mad[MadCount].MemoryType = Type; // // Check if it's more than the allowed for OS loader // if yes - don't map the pages, just add as FirmwareTemporary // - if (BasePage + PageCount > LOADER_HIGH_ZONE && (Type != LoaderNlsData)) + if (BasePage + PageCount > LOADER_HIGH_ZONE) { - Mad[MadCount].MemoryType = LoaderFirmwareTemporary; + if (Mad[MadCount].MemoryType != LoaderSpecialMemory || + Mad[MadCount].MemoryType != LoaderFirmwarePermanent) + { + Mad[MadCount].MemoryType = LoaderFirmwareTemporary; + } WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]); MadCount++; - Status = MempSetupPaging(BasePage, PageCount); - if (!Status) - { - DbgPrint((DPRINT_WINDOWS, "Error during WinLdrpSetupPaging\n")); - return; - } return; } + + // + // Add descriptor + // + WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]); + MadCount++; - if (BasePage == 0xFFF && PageCount == 1) + // + // Map it (don't map low 1Mb because it was already contigiously + // mapped in WinLdrTurnOnPaging) + // + if (BasePage >= 0x100) { - Mad[MadCount].MemoryType = LoaderSpecialMemory; - - WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]); - MadCount++; - - // - // Map it - // - Status = MempSetupPaging(BasePage, PageCount); - if (!Status) - { - DbgPrint((DPRINT_WINDOWS, "Error during MempSetupPaging\n")); - return; - } - } - else if (BasePage == 0 && PageCount == 1) - { - Mad[MadCount].MemoryType = LoaderFirmwarePermanent; - - WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]); - MadCount++; - - // - // Map it - // - Status = MempSetupPaging(BasePage, PageCount); - if (!Status) - { - DbgPrint((DPRINT_WINDOWS, "Error during MempSetupPaging\n")); - return; - } - } - else - { - // - // Set memory type - // - Mad[MadCount].MemoryType = Type; - - // - // Add descriptor - // - WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]); - MadCount++; - - // - // Map it - // Status = MempSetupPaging(BasePage, PageCount); if (!Status) { @@ -375,13 +394,12 @@ WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, ULONG TssBasePage, PVOID GdtIdt) { - ULONG i, PagesCount; - ULONG LastPageIndex, LastPageType, NtType; + ULONG i, PagesCount, MemoryMapSizeInPages; + ULONG LastPageIndex, LastPageType, MemoryMapStartPage; PPAGE_LOOKUP_TABLE_ITEM MemoryMap; ULONG NoEntries; PKTSS Tss; - PVOID NlsBase = VaToPa(((PNLS_DATA_BLOCK)VaToPa(LoaderBlock->NlsData))->AnsiCodePageData); - ULONG NlsBasePage = (ULONG_PTR)NlsBase >> PAGE_SHIFT; + BOOLEAN Status; // // Creating a suitable memory map for the Windows can be tricky, so let's @@ -418,76 +436,47 @@ WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, return FALSE; } - DbgPrint((DPRINT_WINDOWS, "Got memory map with %d entries, NlsBasePage 0x%X\n", - NoEntries, NlsBasePage)); + // Calculate parameters of the memory map + MemoryMapStartPage = (ULONG_PTR)MemoryMap >> MM_PAGE_SHIFT; + MemoryMapSizeInPages = NoEntries * sizeof(PAGE_LOOKUP_TABLE_ITEM); - // Construct a good memory map from what we've got + DbgPrint((DPRINT_WINDOWS, "Got memory map with %d entries\n", NoEntries)); + + // Always contigiously map low 1Mb of memory + Status = MempSetupPaging(0, 0x100); + if (!Status) + { + DbgPrint((DPRINT_WINDOWS, "Error during MempSetupPaging of low 1Mb\n")); + return FALSE; + } + + // Construct a good memory map from what we've got, + // but mark entries which the memory allocation bitmap takes + // as free entries (this is done in order to have the ability + // to place mem alloc bitmap outside lower 16Mb zone) PagesCount = 1; LastPageIndex = 0; LastPageType = MemoryMap[0].PageAllocated; for(i=1;i= MemoryMapStartPage && + i < (MemoryMapStartPage+MemoryMapSizeInPages)) + { + // Exclude it if current page belongs to the memory map + MemoryMap[i].PageAllocated = LoaderFree; + } + + // Process entry if (MemoryMap[i].PageAllocated == LastPageType && - (i < NlsBasePage || i > NlsBasePage+TotalNLSSize) && (i != NoEntries-1) ) + (i != NoEntries-1) ) { PagesCount++; } - else if (i == NlsBasePage) - { - // This is NLS data, map it accordingly - // It's VERY important for NT kernel - it calculates size of NLS - // tables based on NlsData memory type descriptors! - - // Firstly map what we already have (if we have any) - // Convert mem types - if (LastPageType == 0) - NtType = LoaderFree; - else if (LastPageType != 0 && LastPageType != 1) - NtType = LoaderFirmwarePermanent; - else if (LastPageType == 1) - NtType = LoaderSystemCode; - else - NtType = LoaderFirmwarePermanent; - - if (PagesCount > 0) - MempAddMemoryBlock(LoaderBlock, LastPageIndex, PagesCount, NtType); - - // Then map nls data - MempAddMemoryBlock(LoaderBlock, NlsBasePage, TotalNLSSize, LoaderNlsData); - - // skip them - i += TotalNLSSize; - - // Reset our counter vars - LastPageIndex = i; - LastPageType = MemoryMap[i].PageAllocated; - PagesCount = 1; - - continue; - } else { // Add the resulting region - - // Convert mem types - if (LastPageType == 0) - { - NtType = LoaderFree; - } - else if (LastPageType != 0 && LastPageType != 1) - { - NtType = LoaderFirmwarePermanent; - } - else if (LastPageType == 1) - { - NtType = LoaderSystemCode; - } - else - { - NtType = LoaderFirmwarePermanent; - } - - MempAddMemoryBlock(LoaderBlock, LastPageIndex, PagesCount, NtType); + MempAddMemoryBlock(LoaderBlock, LastPageIndex, PagesCount, LastPageType); // Reset our counter vars LastPageIndex = i; @@ -496,6 +485,30 @@ WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, } } + // TEMP, DEBUG! + // adding special reserved memory zones for vmware workstation +#if 0 + { + Mad[MadCount].BasePage = 0xfec00; + Mad[MadCount].PageCount = 0x10; + Mad[MadCount].MemoryType = LoaderSpecialMemory; + WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]); + MadCount++; + + Mad[MadCount].BasePage = 0xfee00; + Mad[MadCount].PageCount = 0x1; + Mad[MadCount].MemoryType = LoaderSpecialMemory; + WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]); + MadCount++; + + Mad[MadCount].BasePage = 0xfffe0; + Mad[MadCount].PageCount = 0x20; + Mad[MadCount].MemoryType = LoaderSpecialMemory; + WinLdrInsertDescriptor(LoaderBlock, &Mad[MadCount]); + MadCount++; + } +#endif + DbgPrint((DPRINT_WINDOWS, "MadCount: %d\n", MadCount)); WinLdrpDumpMemoryDescriptors(LoaderBlock); //FIXME: Delete! @@ -527,7 +540,10 @@ WinLdrTurnOnPaging(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, Tss = (PKTSS)(KSEG0_BASE | (TssBasePage << MM_PAGE_SHIFT)); - // Fill the memory descriptor list and + // Unmap what is not needed from kernel page table + MempDisablePages(); + + // Fill the memory descriptor list and //PrepareMemoryDescriptorList(); DbgPrint((DPRINT_WINDOWS, "Memory Descriptor List prepared, printing PDE\n")); List_PaToVa(&LoaderBlock->MemoryDescriptorListHead); @@ -728,7 +744,7 @@ WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss) // // TSS Selector (0x28) // - pGdt[5].LimitLow = 0x78-1; // 60 dwords + pGdt[5].LimitLow = 0x78-1; //FIXME: Check this pGdt[5].BaseLow = (USHORT)(Tss & 0xffff); pGdt[5].HighWord.Bytes.BaseMid = (UCHAR)((Tss >> 16) & 0xff); pGdt[5].HighWord.Bytes.Flags1 = 0x89; @@ -829,118 +845,9 @@ WinLdrSetProcessorContext(PVOID GdtIdt, IN ULONG Pcr, IN ULONG Tss) // Some unused descriptors should go here // ... - // - // Fill IDT with Traps - // -#if 0 - pIdt[0].Offset = (i386DivideByZero | KSEG0_BASE) & 0xFFFF; - pIdt[0].ExtendedOffset = 0x8; // Selector - pIdt[0].Access = 0x8F00; - pIdt[0].Selector = (i386DivideByZero | KSEG0_BASE) >> 16; // Extended Offset - - pIdt[1].Offset = (i386DebugException | KSEG0_BASE) & 0xFFFF; - pIdt[1].ExtendedOffset = 0x8; // Selector - pIdt[1].Access = 0x8F00; - pIdt[1].Selector = (i386DebugException | KSEG0_BASE) >> 16; // Extended Offset - - pIdt[2].Offset = (i386NMIException | KSEG0_BASE) & 0xFFFF; - pIdt[2].ExtendedOffset = 0x8; // Selector - pIdt[2].Access = 0x8F00; - pIdt[2].Selector = (i386NMIException | KSEG0_BASE) >> 16; // Extended Offset - - pIdt[3].Offset = (i386Breakpoint | KSEG0_BASE) & 0xFFFF; - pIdt[3].ExtendedOffset = 0x8; // Selector - pIdt[3].Access = 0x8F00; - pIdt[3].Selector = (i386Breakpoint | KSEG0_BASE) >> 16; // Extended Offset - - pIdt[4].Offset = (i386Overflow | KSEG0_BASE) & 0xFFFF; - pIdt[4].ExtendedOffset = 0x8; // Selector - pIdt[4].Access = 0x8F00; - pIdt[4].Selector = (i386Overflow | KSEG0_BASE) >> 16; // Extended Offset - - pIdt[5].Selector = (i386BoundException | KSEG0_BASE) >> 16; // Extended Offset - pIdt[5].Offset = (i386BoundException | KSEG0_BASE) & 0xFFFF; - pIdt[5].ExtendedOffset = 0x8; // Selector - pIdt[5].Access = 0x8F00; - - pIdt[6].Selector = (i386InvalidOpcode | KSEG0_BASE) >> 16; // Extended Offset - pIdt[6].Offset = (i386InvalidOpcode | KSEG0_BASE) & 0xFFFF; - pIdt[6].ExtendedOffset = 0x8; // Selector - pIdt[6].Access = 0x8F00; - - pIdt[7].Selector = (i386FPUNotAvailable | KSEG0_BASE) >> 16; // Extended Offset - pIdt[7].Offset = (i386FPUNotAvailable | KSEG0_BASE) & 0xFFFF; - pIdt[7].ExtendedOffset = 0x8; // Selector - pIdt[7].Access = 0x8F00; - - pIdt[8].Selector = (i386DoubleFault | KSEG0_BASE) >> 16; // Extended Offset - pIdt[8].Offset = (i386DoubleFault | KSEG0_BASE) & 0xFFFF; - pIdt[8].ExtendedOffset = 0x8; // Selector - pIdt[8].Access = 0x8F00; - - pIdt[9].Selector = (i386CoprocessorSegment | KSEG0_BASE) >> 16; // Extended Offset - pIdt[9].Offset = (i386CoprocessorSegment | KSEG0_BASE) & 0xFFFF; - pIdt[9].ExtendedOffset = 0x8; // Selector - pIdt[9].Access = 0x8F00; - - pIdt[10].Selector = (i386InvalidTSS | KSEG0_BASE) >> 16; // Extended Offset - pIdt[10].Offset = (i386InvalidTSS | KSEG0_BASE) & 0xFFFF; - pIdt[10].ExtendedOffset = 0x8; // Selector - pIdt[10].Access = 0x8F00; - - pIdt[11].Selector = (i386SegmentNotPresent | KSEG0_BASE) >> 16; // Extended Offset - pIdt[11].Offset = (i386SegmentNotPresent | KSEG0_BASE) & 0xFFFF; - pIdt[11].ExtendedOffset = 0x8; // Selector - pIdt[11].Access = 0x8F00; - - pIdt[12].Selector = (i386StackException | KSEG0_BASE) >> 16; // Extended Offset - pIdt[12].Offset = (i386StackException | KSEG0_BASE) & 0xFFFF; - pIdt[12].ExtendedOffset = 0x8; // Selector - pIdt[12].Access = 0x8F00; - - pIdt[13].Selector = (i386GeneralProtectionFault | KSEG0_BASE) >> 16; // Extended Offset - pIdt[13].Offset = (i386GeneralProtectionFault | KSEG0_BASE) & 0xFFFF; - pIdt[13].ExtendedOffset = 0x8; // Selector - pIdt[13].Access = 0x8F00; - - pIdt[14].Selector = (i386PageFault | KSEG0_BASE) >> 16; // Extended Offset - pIdt[14].Offset = (i386PageFault | KSEG0_BASE) & 0xFFFF; - pIdt[14].ExtendedOffset = 0x8; // Selector - pIdt[14].Access = 0x8F00; - - pIdt[15].Selector = 0; // Extended Offset - pIdt[15].Offset = 0; - pIdt[15].ExtendedOffset = 0; // Selector - pIdt[15].Access = 0; - - pIdt[16].Selector = (i386CoprocessorError | KSEG0_BASE) >> 16; // Extended Offset - pIdt[16].Offset = (i386CoprocessorError | KSEG0_BASE) & 0xFFFF; - pIdt[16].ExtendedOffset = 0x8; // Selector - pIdt[16].Access = 0x8F00; - - pIdt[17].Selector = (i386AlignmentCheck | KSEG0_BASE) >> 16; // Extended Offset - pIdt[17].Offset = (i386AlignmentCheck | KSEG0_BASE) & 0xFFFF; - pIdt[17].ExtendedOffset = 0x8; // Selector - pIdt[17].Access = 0x8F00; -#endif - - /*for (i=0; i<16; i++) - { - //pIdt[i].Offset = ((ULONG_PTR)i386GeneralProtectionFault | KSEG0_BASE) & 0xFFFF; - //pIdt[i].ExtendedOffset = 0x8; // Selector - //pIdt[i].Access = 0x8F00; - //pIdt[i].Selector = ((ULONG_PTR)i386GeneralProtectionFault | KSEG0_BASE) >> 16; // Extended Offset - - pIdt[i].Offset = ((ULONG_PTR)i386GeneralProtectionFault | KSEG0_BASE) & 0xFFFF; - pIdt[i].ExtendedOffset = ((ULONG_PTR)i386GeneralProtectionFault | KSEG0_BASE) >> 16; // Extended Offset - pIdt[i].Access = 0x8F00; - pIdt[i].Selector = 0x8; - }*/ - // Copy the old IDT RtlCopyMemory(pIdt, (PVOID)OldIdt.Base, OldIdt.Limit); - // Mask interrupts //asm("cli\n"); // they are already masked before enabling paged mode diff --git a/reactos/boot/freeldr/freeldr/windows/wlregistry.c b/reactos/boot/freeldr/freeldr/windows/wlregistry.c index 81e67ccfcb7..278a1afd870 100644 --- a/reactos/boot/freeldr/freeldr/windows/wlregistry.c +++ b/reactos/boot/freeldr/freeldr/windows/wlregistry.c @@ -72,8 +72,9 @@ WinLdrLoadSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, } /* Round up the size to page boundary and alloc memory */ - HiveDataPhysical = (ULONG_PTR)MmAllocateMemory( - MM_SIZE_TO_PAGES(HiveFileSize + MM_PAGE_SIZE - 1) << MM_PAGE_SHIFT); + HiveDataPhysical = (ULONG_PTR)MmAllocateMemoryWithType( + MM_SIZE_TO_PAGES(HiveFileSize + MM_PAGE_SIZE - 1) << MM_PAGE_SHIFT, + LoaderRegistryData); if (HiveDataPhysical == 0) { @@ -141,6 +142,14 @@ BOOLEAN WinLdrLoadAndScanSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, // Scan registry and prepare boot drivers list WinLdrScanRegistry(LoaderBlock, DirectoryPath); + // Add boot filesystem driver to the list + //FIXME: Use corresponding driver instead of hardcoding + Status = WinLdrAddDriverToList(&LoaderBlock->BootDriverListHead, + L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\", + NULL, + L"fastfat"); + + // Get names of NLS files Status = WinLdrGetNLSNames(AnsiName, OemName, LangName); if (!Status) @@ -331,7 +340,7 @@ WinLdrLoadNLSData(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, /* Store it for later marking the pages as NlsData type */ TotalNLSSize = TotalSize; - NlsDataBase = (ULONG_PTR)MmAllocateMemory(TotalSize*MM_PAGE_SIZE); + NlsDataBase = (ULONG_PTR)MmAllocateMemoryWithType(TotalSize*MM_PAGE_SIZE, LoaderNlsData); if (NlsDataBase == 0) goto Failure; @@ -562,7 +571,7 @@ WinLdrScanRegistry(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, DbgPrint((DPRINT_WINDOWS, " Failed to add boot driver\n")); } else { - //DbgPrint((DPRINT_REACTOS, " Skipping driver '%S' with Start %d, Tag %d and Group '%S' (Current Tag %d, current group '%S')\n", + //DbgPrint((DPRINT_WINDOWS, " Skipping driver '%S' with Start %d, Tag %d and Group '%S' (Current Tag %d, current group '%S')\n", // ServiceName, StartValue, TagValue, DriverGroup, OrderList[TagIndex], GroupName)); } } @@ -637,7 +646,7 @@ WinLdrScanRegistry(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock, DbgPrint((DPRINT_WINDOWS, " Failed to add boot driver\n")); } else { - //DbgPrint((DPRINT_REACTOS, " Skipping driver '%S' with Start %d, Tag %d and Group '%S' (Current group '%S')\n", + //DbgPrint((DPRINT_WINDOWS, " Skipping driver '%S' with Start %d, Tag %d and Group '%S' (Current group '%S')\n", // ServiceName, StartValue, TagValue, DriverGroup, GroupName)); } } @@ -660,7 +669,7 @@ WinLdrAddDriverToList(LIST_ENTRY *BootDriverListHead, NTSTATUS Status; ULONG PathLength; - BootDriverEntry = MmAllocateMemory(sizeof(BOOT_DRIVER_LIST_ENTRY)); + BootDriverEntry = MmHeapAlloc(sizeof(BOOT_DRIVER_LIST_ENTRY)); if (!BootDriverEntry) return FALSE; @@ -677,14 +686,21 @@ WinLdrAddDriverToList(LIST_ENTRY *BootDriverListHead, BootDriverEntry->FilePath.Length = 0; BootDriverEntry->FilePath.MaximumLength = PathLength + sizeof(WCHAR); - BootDriverEntry->FilePath.Buffer = MmAllocateMemory(PathLength); + BootDriverEntry->FilePath.Buffer = MmHeapAlloc(PathLength); if (!BootDriverEntry->FilePath.Buffer) + { + MmHeapFree(BootDriverEntry); return FALSE; + } Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, ImagePath); if (!NT_SUCCESS(Status)) + { + MmHeapFree(BootDriverEntry->FilePath.Buffer); + MmHeapFree(BootDriverEntry); return FALSE; + } } else { @@ -692,29 +708,44 @@ WinLdrAddDriverToList(LIST_ENTRY *BootDriverListHead, PathLength = wcslen(ServiceName)*sizeof(WCHAR) + sizeof(L"system32\\drivers\\.sys");; BootDriverEntry->FilePath.Length = 0; BootDriverEntry->FilePath.MaximumLength = PathLength+sizeof(WCHAR); - BootDriverEntry->FilePath.Buffer = MmAllocateMemory(PathLength); + BootDriverEntry->FilePath.Buffer = MmHeapAlloc(PathLength); if (!BootDriverEntry->FilePath.Buffer) + { + MmHeapFree(BootDriverEntry); return FALSE; + } Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, L"system32\\drivers\\"); if (!NT_SUCCESS(Status)) + { + MmHeapFree(BootDriverEntry->FilePath.Buffer); + MmHeapFree(BootDriverEntry); return FALSE; + } Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, ServiceName); if (!NT_SUCCESS(Status)) + { + MmHeapFree(BootDriverEntry->FilePath.Buffer); + MmHeapFree(BootDriverEntry); return FALSE; + } Status = RtlAppendUnicodeToString(&BootDriverEntry->FilePath, L".sys"); if (!NT_SUCCESS(Status)) + { + MmHeapFree(BootDriverEntry->FilePath.Buffer); + MmHeapFree(BootDriverEntry); return FALSE; + } } // Add registry path - PathLength = wcslen(RegistryPath)*sizeof(WCHAR); + PathLength = (wcslen(RegistryPath)+wcslen(ServiceName))*sizeof(WCHAR); BootDriverEntry->RegistryPath.Length = 0; - BootDriverEntry->RegistryPath.MaximumLength = PathLength+sizeof(WCHAR); - BootDriverEntry->RegistryPath.Buffer = MmAllocateMemory(PathLength); + BootDriverEntry->RegistryPath.MaximumLength = PathLength;//+sizeof(WCHAR); + BootDriverEntry->RegistryPath.Buffer = MmHeapAlloc(PathLength); if (!BootDriverEntry->RegistryPath.Buffer) return FALSE; @@ -722,8 +753,12 @@ WinLdrAddDriverToList(LIST_ENTRY *BootDriverListHead, if (!NT_SUCCESS(Status)) return FALSE; + Status = RtlAppendUnicodeToString(&BootDriverEntry->RegistryPath, ServiceName); + if (!NT_SUCCESS(Status)) + return FALSE; + // Insert entry at top of the list - InsertHeadList(BootDriverListHead, &BootDriverEntry->ListEntry); + InsertTailList(BootDriverListHead, &BootDriverEntry->ListEntry); return TRUE; }