- Copy winldr's files from the branch, with the only #ifdef WHEN_MERGE_COMPLETE hack.
svn path=/trunk/; revision=31755
--- /dev/null
- LoadBase = MmAllocateMemoryAtAddress(DriverSize, LoadBase);
+/*
+ * FreeLoader
+ * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
+ * Copyright (C) 2005 Alex Ionescu <alex@relsoft.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#define _NTSYSTEM_
+#include <freeldr.h>
+
+#define NDEBUG
+#include <debug.h>
+#undef DbgPrint
+
+/* Load Address of Next Module */
+ULONG_PTR NextModuleBase = KERNEL_BASE_PHYS;
+
+/* Currently Opened Module */
+PLOADER_MODULE CurrentModule = NULL;
+
+/* Unrelocated Kernel Base in Virtual Memory */
+ULONG_PTR KernelBase;
+
+/* Kernel Entrypoint in Virtual Memory */
+ROS_KERNEL_ENTRY_POINT KernelEntryPoint;
+
+/* Page Directory and Tables for non-PAE Systems */
+extern PAGE_DIRECTORY_X86 startup_pagedirectory;
+extern PAGE_DIRECTORY_X86 lowmem_pagetable;
+extern PAGE_DIRECTORY_X86 kernel_pagetable;
+extern PAGE_DIRECTORY_X86 hyperspace_pagetable;
+extern PAGE_DIRECTORY_X86 apic_pagetable;
+extern PAGE_DIRECTORY_X86 kpcr_pagetable;
+extern PAGE_DIRECTORY_X86 kuser_pagetable;
+
+PVOID
+NTAPI
+LdrPEGetExportByName(PVOID BaseAddress,
+ PUCHAR SymbolName,
+ USHORT Hint);
+
+/* FUNCTIONS *****************************************************************/
+
+/*++
+ * FrLdrStartup
+ * INTERNAL
+ *
+ * Prepares the system for loading the Kernel.
+ *
+ * Params:
+ * Magic - Multiboot Magic
+ *
+ * Returns:
+ * None.
+ *
+ * Remarks:
+ * None.
+ *
+ *--*/
+VOID
+NTAPI
+FrLdrStartup(ULONG Magic)
+{
+ /* Disable Interrupts */
+ _disable();
+
+ /* Re-initalize EFLAGS */
+ Ke386EraseFlags();
+
+ /* Initialize the page directory */
+ FrLdrSetupPageDirectory();
+
+ /* Initialize Paging, Write-Protection and Load NTOSKRNL */
+ FrLdrSetupPae(Magic);
+}
+
+/*++
+ * FrLdrSetupPae
+ * INTERNAL
+ *
+ * Configures PAE on a MP System, and sets the PDBR if it's supported, or if
+ * the system is UP.
+ *
+ * Params:
+ * Magic - Multiboot Magic
+ *
+ * Returns:
+ * None.
+ *
+ * Remarks:
+ * None.
+ *
+ *--*/
+VOID
+FASTCALL
+FrLdrSetupPae(ULONG Magic)
+{
+ ULONG_PTR PageDirectoryBaseAddress = (ULONG_PTR)&startup_pagedirectory;
+
+ /* Set the PDBR */
+ __writecr3(PageDirectoryBaseAddress);
+
+ /* Enable Paging and Write Protect*/
+ __writecr0(__readcr0() | X86_CR0_PG | X86_CR0_WP);
+
+ /* Jump to Kernel */
+ (*KernelEntryPoint)(Magic, &LoaderBlock);
+}
+
+/*++
+ * FrLdrSetupPageDirectory
+ * INTERNAL
+ *
+ * Sets up the ReactOS Startup Page Directory.
+ *
+ * Params:
+ * None.
+ *
+ * Returns:
+ * None.
+ *
+ * Remarks:
+ * We are setting PDEs, but using the equvivalent (for our purpose) PTE structure.
+ * As such, please note that PageFrameNumber == PageEntryNumber.
+ *
+ *--*/
+VOID
+FASTCALL
+FrLdrSetupPageDirectory(VOID)
+{
+ PPAGE_DIRECTORY_X86 PageDir;
+ ULONG KernelPageTableIndex;
+ ULONG i;
+
+ /* Get the Kernel Table Index */
+ KernelPageTableIndex = KernelBase >> PDE_SHIFT;
+
+ /* Get the Startup Page Directory */
+ PageDir = (PPAGE_DIRECTORY_X86)&startup_pagedirectory;
+
+ /* Set up the Low Memory PDE */
+ PageDir->Pde[LowMemPageTableIndex].Valid = 1;
+ PageDir->Pde[LowMemPageTableIndex].Write = 1;
+ PageDir->Pde[LowMemPageTableIndex].PageFrameNumber = PaPtrToPfn(lowmem_pagetable);
+
+ /* Set up the Kernel PDEs */
+ PageDir->Pde[KernelPageTableIndex].Valid = 1;
+ PageDir->Pde[KernelPageTableIndex].Write = 1;
+ PageDir->Pde[KernelPageTableIndex].PageFrameNumber = PaPtrToPfn(kernel_pagetable);
+ PageDir->Pde[KernelPageTableIndex + 1].Valid = 1;
+ PageDir->Pde[KernelPageTableIndex + 1].Write = 1;
+ PageDir->Pde[KernelPageTableIndex + 1].PageFrameNumber = PaPtrToPfn(kernel_pagetable + 4096);
+
+ /* Set up the Startup PDE */
+ PageDir->Pde[StartupPageTableIndex].Valid = 1;
+ PageDir->Pde[StartupPageTableIndex].Write = 1;
+ PageDir->Pde[StartupPageTableIndex].PageFrameNumber = PaPtrToPfn(startup_pagedirectory);
+
+ /* Set up the Hyperspace PDE */
+ PageDir->Pde[HyperspacePageTableIndex].Valid = 1;
+ PageDir->Pde[HyperspacePageTableIndex].Write = 1;
+ PageDir->Pde[HyperspacePageTableIndex].PageFrameNumber = PaPtrToPfn(hyperspace_pagetable);
+
+ /* Set up the HAL PDE */
+ PageDir->Pde[HalPageTableIndex].Valid = 1;
+ PageDir->Pde[HalPageTableIndex].Write = 1;
+ PageDir->Pde[HalPageTableIndex].PageFrameNumber = PaPtrToPfn(apic_pagetable);
+
+ /* Set up Low Memory PTEs */
+ PageDir = (PPAGE_DIRECTORY_X86)&lowmem_pagetable;
+ for (i=0; i<1024; i++)
+ {
+ PageDir->Pde[i].Valid = 1;
+ PageDir->Pde[i].Write = 1;
+ PageDir->Pde[i].Owner = 1;
+ PageDir->Pde[i].PageFrameNumber = PaToPfn(i * PAGE_SIZE);
+ }
+
+ /* Set up Kernel PTEs */
+ PageDir = (PPAGE_DIRECTORY_X86)&kernel_pagetable;
+ for (i=0; i<1536; i++)
+ {
+ PageDir->Pde[i].Valid = 1;
+ PageDir->Pde[i].Write = 1;
+ PageDir->Pde[i].PageFrameNumber = PaToPfn(KERNEL_BASE_PHYS + i * PAGE_SIZE);
+ }
+
+ /* Setup APIC Base */
+ PageDir = (PPAGE_DIRECTORY_X86)&apic_pagetable;
+ PageDir->Pde[0].Valid = 1;
+ PageDir->Pde[0].Write = 1;
+ PageDir->Pde[0].CacheDisable = 1;
+ PageDir->Pde[0].WriteThrough = 1;
+ PageDir->Pde[0].PageFrameNumber = PaToPfn(HAL_BASE);
+ PageDir->Pde[0x200].Valid = 1;
+ PageDir->Pde[0x200].Write = 1;
+ PageDir->Pde[0x200].CacheDisable = 1;
+ PageDir->Pde[0x200].WriteThrough = 1;
+ PageDir->Pde[0x200].PageFrameNumber = PaToPfn(HAL_BASE + KERNEL_BASE_PHYS);
+
+ /* Setup KUSER_SHARED_DATA Base */
+ PageDir->Pde[0x1F0].Valid = 1;
+ PageDir->Pde[0x1F0].Write = 1;
+ PageDir->Pde[0x1F0].PageFrameNumber = 2;
+
+ /* Setup KPCR Base*/
+ PageDir->Pde[0x1FF].Valid = 1;
+ PageDir->Pde[0x1FF].Write = 1;
+ PageDir->Pde[0x1FF].PageFrameNumber = 1;
+}
+
+PLOADER_MODULE
+NTAPI
+LdrGetModuleObject(PCHAR ModuleName)
+{
+ ULONG i;
+
+ for (i = 0; i < LoaderBlock.ModsCount; i++)
+ {
+ if (strstr(_strupr((PCHAR)reactos_modules[i].String), _strupr(ModuleName)))
+ {
+ return &reactos_modules[i];
+ }
+ }
+
+ return NULL;
+}
+
+PVOID
+NTAPI
+LdrPEFixupForward(IN PCHAR ForwardName)
+{
+ CHAR NameBuffer[128];
+ PCHAR p;
+ PLOADER_MODULE ModuleObject;
+
+ strcpy(NameBuffer, ForwardName);
+ p = strchr(NameBuffer, '.');
+ if (p == NULL) return NULL;
+ *p = 0;
+
+ ModuleObject = LdrGetModuleObject(NameBuffer);
+ if (!ModuleObject)
+ {
+ DbgPrint("LdrPEFixupForward: failed to find module %s\n", NameBuffer);
+ return NULL;
+ }
+
+ return LdrPEGetExportByName((PVOID)ModuleObject->ModStart, (PUCHAR)(p + 1), 0xffff);
+}
+
+PVOID
+NTAPI
+LdrPEGetExportByName(PVOID BaseAddress,
+ PUCHAR SymbolName,
+ USHORT Hint)
+{
+ PIMAGE_EXPORT_DIRECTORY ExportDir;
+ PULONG * ExFunctions;
+ PULONG * ExNames;
+ USHORT * ExOrdinals;
+ PVOID ExName;
+ ULONG Ordinal;
+ PVOID Function;
+ LONG minn, maxn, mid, res;
+ ULONG ExportDirSize;
+
+ /* HAL and NTOS use a virtual address, switch it to physical mode */
+ if ((ULONG_PTR)BaseAddress & KSEG0_BASE)
+ {
+ BaseAddress = RVA(BaseAddress, -KSEG0_BASE);
+ }
+
+ ExportDir = (PIMAGE_EXPORT_DIRECTORY)
+ RtlImageDirectoryEntryToData(BaseAddress,
+ TRUE,
+ IMAGE_DIRECTORY_ENTRY_EXPORT,
+ &ExportDirSize);
+ if (!ExportDir)
+ {
+ DbgPrint("LdrPEGetExportByName(): no export directory!\n");
+ return NULL;
+ }
+
+ /* The symbol names may be missing entirely */
+ if (!ExportDir->AddressOfNames)
+ {
+ DbgPrint("LdrPEGetExportByName(): symbol names missing entirely\n");
+ return NULL;
+ }
+
+ /*
+ * Get header pointers
+ */
+ ExNames = (PULONG *)RVA(BaseAddress, ExportDir->AddressOfNames);
+ ExOrdinals = (USHORT *)RVA(BaseAddress, ExportDir->AddressOfNameOrdinals);
+ ExFunctions = (PULONG *)RVA(BaseAddress, ExportDir->AddressOfFunctions);
+
+ /*
+ * Check the hint first
+ */
+ if (Hint < ExportDir->NumberOfNames)
+ {
+ ExName = RVA(BaseAddress, ExNames[Hint]);
+ if (strcmp(ExName, (PCHAR)SymbolName) == 0)
+ {
+ Ordinal = ExOrdinals[Hint];
+ Function = RVA(BaseAddress, ExFunctions[Ordinal]);
+ if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir &&
+ (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize)
+ {
+ Function = LdrPEFixupForward((PCHAR)Function);
+ if (Function == NULL)
+ {
+ DbgPrint("LdrPEGetExportByName(): failed to find %s\n", Function);
+ }
+ return Function;
+ }
+
+ if (Function != NULL) return Function;
+ }
+ }
+
+ /*
+ * Binary search
+ */
+ minn = 0;
+ maxn = ExportDir->NumberOfNames - 1;
+ while (minn <= maxn)
+ {
+ mid = (minn + maxn) / 2;
+
+ ExName = RVA(BaseAddress, ExNames[mid]);
+ res = strcmp(ExName, (PCHAR)SymbolName);
+ if (res == 0)
+ {
+ Ordinal = ExOrdinals[mid];
+ Function = RVA(BaseAddress, ExFunctions[Ordinal]);
+ if ((ULONG_PTR)Function >= (ULONG_PTR)ExportDir &&
+ (ULONG_PTR)Function < (ULONG_PTR)ExportDir + ExportDirSize)
+ {
+ Function = LdrPEFixupForward((PCHAR)Function);
+ if (Function == NULL)
+ {
+ DbgPrint("1: failed to find %s\n", Function);
+ }
+ return Function;
+ }
+ if (Function != NULL)
+ {
+ return Function;
+ }
+ }
+ else if (res > 0)
+ {
+ maxn = mid - 1;
+ }
+ else
+ {
+ minn = mid + 1;
+ }
+ }
+
+ ExName = RVA(BaseAddress, ExNames[mid]);
+ DbgPrint("2: failed to find %s\n",SymbolName);
+ return (PVOID)NULL;
+}
+
+NTSTATUS
+NTAPI
+LdrPEProcessImportDirectoryEntry(PVOID DriverBase,
+ PLOADER_MODULE LoaderModule,
+ PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory)
+{
+ PVOID* ImportAddressList;
+ PULONG FunctionNameList;
+
+ if (ImportModuleDirectory == NULL || ImportModuleDirectory->Name == 0)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ /* Get the import address list. */
+ ImportAddressList = (PVOID*)RVA(DriverBase, ImportModuleDirectory->FirstThunk);
+
+ /* Get the list of functions to import. */
+ if (ImportModuleDirectory->OriginalFirstThunk != 0)
+ {
+ FunctionNameList = (PULONG)RVA(DriverBase, ImportModuleDirectory->OriginalFirstThunk);
+ }
+ else
+ {
+ FunctionNameList = (PULONG)RVA(DriverBase, ImportModuleDirectory->FirstThunk);
+ }
+
+ /* Walk through function list and fixup addresses. */
+ while (*FunctionNameList != 0L)
+ {
+ if ((*FunctionNameList) & 0x80000000)
+ {
+ DbgPrint("Failed to import ordinal from %s\n", LoaderModule->String);
+ return STATUS_UNSUCCESSFUL;
+ }
+ else
+ {
+ IMAGE_IMPORT_BY_NAME *pe_name;
+ pe_name = RVA(DriverBase, *FunctionNameList);
+ *ImportAddressList = LdrPEGetExportByName((PVOID)LoaderModule->ModStart, pe_name->Name, pe_name->Hint);
+
+ /* Fixup the address to be virtual */
+ *ImportAddressList = RVA(*ImportAddressList, KSEG0_BASE);
+
+ //DbgPrint("Looked for: %s and found: %p\n", pe_name->Name, *ImportAddressList);
+ if ((*ImportAddressList) == NULL)
+ {
+ DbgPrint("Failed to import %s from %s\n", pe_name->Name, LoaderModule->String);
+ return STATUS_UNSUCCESSFUL;
+ }
+ }
+ ImportAddressList++;
+ FunctionNameList++;
+ }
+ return STATUS_SUCCESS;
+}
+
+extern BOOLEAN FrLdrLoadDriver(PCHAR szFileName, INT nPos);
+
+NTSTATUS
+NTAPI
+LdrPEGetOrLoadModule(IN PCHAR ModuleName,
+ IN PCHAR ImportedName,
+ IN PLOADER_MODULE* ImportedModule)
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ *ImportedModule = LdrGetModuleObject(ImportedName);
+ if (*ImportedModule == NULL)
+ {
+ if (!FrLdrLoadDriver(ImportedName, 0))
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+ else
+ {
+ return LdrPEGetOrLoadModule
+ (ModuleName, ImportedName, ImportedModule);
+ }
+ }
+
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+LdrPEFixupImports(IN PVOID DllBase,
+ IN PCHAR DllName)
+{
+ PIMAGE_IMPORT_DESCRIPTOR ImportModuleDirectory;
+ PCHAR ImportedName;
+ NTSTATUS Status;
+ PLOADER_MODULE ImportedModule;
+ ULONG Size;
+
+ /* Process each import module */
+ ImportModuleDirectory = (PIMAGE_IMPORT_DESCRIPTOR)
+ RtlImageDirectoryEntryToData(DllBase,
+ TRUE,
+ IMAGE_DIRECTORY_ENTRY_IMPORT,
+ &Size);
+ while (ImportModuleDirectory && ImportModuleDirectory->Name)
+ {
+ /* Check to make sure that import lib is kernel */
+ ImportedName = (PCHAR) DllBase + ImportModuleDirectory->Name;
+ //DbgPrint("Processing imports for file: %s into file: %s\n", DllName, ImportedName);
+
+ Status = LdrPEGetOrLoadModule(DllName, ImportedName, &ImportedModule);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ Status = LdrPEProcessImportDirectoryEntry(DllBase, ImportedModule, ImportModuleDirectory);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ //DbgPrint("Imports for file: %s into file: %s complete\n", DllName, ImportedName);
+ ImportModuleDirectory++;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+ULONG
+NTAPI
+FrLdrReMapImage(IN PVOID Base,
+ IN PVOID LoadBase)
+{
+ PIMAGE_NT_HEADERS NtHeader;
+ PIMAGE_SECTION_HEADER Section;
+ ULONG i, Size, DriverSize = 0;
+
+ /* Get the first section */
+ NtHeader = RtlImageNtHeader(Base);
+ Section = IMAGE_FIRST_SECTION(NtHeader);
+
+ /* Allocate memory for the driver */
+ DriverSize = NtHeader->OptionalHeader.SizeOfImage;
++ LoadBase = MmAllocateMemoryAtAddress(DriverSize, LoadBase, LoaderSystemCode);
+ ASSERT(LoadBase);
+
+ /* Copy headers over */
+ RtlMoveMemory(LoadBase, Base, NtHeader->OptionalHeader.SizeOfHeaders);
+
+ /* Copy image sections into virtual section */
+ for (i = 0; i < NtHeader->FileHeader.NumberOfSections; i++)
+ {
+ /* Get the size of this section and check if it's valid */
+ Size = Section[i].VirtualAddress + Section[i].Misc.VirtualSize;
+ if (Size <= DriverSize)
+ {
+ if (Section[i].SizeOfRawData)
+ {
+ /* Copy the data from the disk to the image */
+ RtlCopyMemory((PVOID)((ULONG_PTR)LoadBase +
+ Section[i].VirtualAddress),
+ (PVOID)((ULONG_PTR)Base +
+ Section[i].PointerToRawData),
+ Section[i].Misc.VirtualSize >
+ Section[i].SizeOfRawData ?
+ Section[i].SizeOfRawData :
+ Section[i].Misc.VirtualSize);
+ }
+ else
+ {
+ /* Clear the BSS area */
+ RtlZeroMemory((PVOID)((ULONG_PTR)LoadBase +
+ Section[i].VirtualAddress),
+ Section[i].Misc.VirtualSize);
+ }
+ }
+ }
+
+ /* Return the size of the mapped driver */
+ return DriverSize;
+}
+
+PVOID
+NTAPI
+FrLdrMapImage(IN FILE *Image,
+ IN PCHAR Name,
+ IN ULONG ImageType)
+{
+ PVOID ImageBase, LoadBase, ReadBuffer;
+ ULONG ImageId = LoaderBlock.ModsCount;
+ ULONG ImageSize;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ /* Try to see, maybe it's loaded already */
+ if (LdrGetModuleObject(Name) != NULL)
+ {
+ /* It's loaded, return NULL. It would be wise to return
+ correct LoadBase, but it seems to be ignored almost everywhere */
+ return NULL;
+ }
+
+ /* Set the virtual (image) and physical (load) addresses */
+ LoadBase = (PVOID)NextModuleBase;
+ ImageBase = RVA(LoadBase, KSEG0_BASE);
+
+ /* Save the Image Size */
+ ImageSize = FsGetFileSize(Image);
+
+ /* Set the file pointer to zero */
+ FsSetFilePointer(Image, 0);
+
+ /* Allocate a temporary buffer for the read */
+ ReadBuffer = MmAllocateMemory(ImageSize);
+
+ /* Load the file image */
+ FsReadFile(Image, ImageSize, NULL, ReadBuffer);
+
+ /* Map it into virtual memory */
+ ImageSize = FrLdrReMapImage(ReadBuffer, LoadBase);
+
+ /* Free the temporary buffer */
+ MmFreeMemory(ReadBuffer);
+
+ /* Calculate Difference between Real Base and Compiled Base*/
+ Status = LdrRelocateImageWithBias(LoadBase,
+ (ULONG_PTR)ImageBase -
+ (ULONG_PTR)LoadBase,
+ "FreeLdr",
+ STATUS_SUCCESS,
+ STATUS_UNSUCCESSFUL,
+ STATUS_UNSUCCESSFUL);
+ if (!NT_SUCCESS(Status))
+ {
+ /* Fail */
+ DbgPrint("Failed to relocate image: %s\n", Name);
+ return NULL;
+ }
+
+ /* Fill out Module Data Structure */
+ reactos_modules[ImageId].ModStart = (ULONG_PTR)ImageBase;
+ reactos_modules[ImageId].ModEnd = (ULONG_PTR)ImageBase + ImageSize;
+ strcpy(reactos_module_strings[ImageId], Name);
+ reactos_modules[ImageId].String = (ULONG_PTR)reactos_module_strings[ImageId];
+ LoaderBlock.ModsCount++;
+
+ /* Increase the next Load Base */
+ NextModuleBase = ROUND_UP(NextModuleBase + ImageSize, PAGE_SIZE);
+
+ /* Perform import fixups */
+ if (!NT_SUCCESS(LdrPEFixupImports(LoadBase, Name)))
+ {
+ /* Fixup failed, just don't include it in the list */
+ // NextModuleBase = OldNextModuleBase;
+ LoaderBlock.ModsCount = ImageId;
+ return NULL;
+ }
+
+ /* Return the final mapped address */
+ return LoadBase;
+}
+
+ULONG_PTR
+NTAPI
+FrLdrLoadModule(FILE *ModuleImage,
+ LPCSTR ModuleName,
+ PULONG ModuleSize)
+{
+ ULONG LocalModuleSize;
+ PLOADER_MODULE ModuleData;
+ LPSTR NameBuffer;
+ LPSTR TempName;
+
+ /* Get current module data structure and module name string array */
+ ModuleData = &reactos_modules[LoaderBlock.ModsCount];
+
+ /* Get only the Module Name */
+ do {
+
+ TempName = strchr(ModuleName, '\\');
+
+ if(TempName) {
+ ModuleName = TempName + 1;
+ }
+
+ } while(TempName);
+ NameBuffer = reactos_module_strings[LoaderBlock.ModsCount];
+
+ /* Get Module Size */
+ LocalModuleSize = FsGetFileSize(ModuleImage);
+
+ /* Fill out Module Data Structure */
+ ModuleData->ModStart = NextModuleBase;
+ ModuleData->ModEnd = NextModuleBase + LocalModuleSize;
+
+ /* Save name */
+ strcpy(NameBuffer, ModuleName);
+ ModuleData->String = (ULONG_PTR)NameBuffer;
+
+ /* Load the file image */
+ FsReadFile(ModuleImage, LocalModuleSize, NULL, (PVOID)NextModuleBase);
+
+ /* Move to next memory block and increase Module Count */
+ NextModuleBase = ROUND_UP(ModuleData->ModEnd, PAGE_SIZE);
+ LoaderBlock.ModsCount++;
+// DbgPrint("NextBase, ImageSize, ModStart, ModEnd %p %p %p %p\n",
+ // NextModuleBase, LocalModuleSize, ModuleData->ModStart, ModuleData->ModEnd);
+
+ /* Return Module Size if required */
+ if (ModuleSize != NULL) {
+ *ModuleSize = LocalModuleSize;
+ }
+
+ return(ModuleData->ModStart);
+}
+
+ULONG_PTR
+NTAPI
+FrLdrCreateModule(LPCSTR ModuleName)
+{
+ PLOADER_MODULE ModuleData;
+ LPSTR NameBuffer;
+
+ /* Get current module data structure and module name string array */
+ ModuleData = &reactos_modules[LoaderBlock.ModsCount];
+ NameBuffer = reactos_module_strings[LoaderBlock.ModsCount];
+
+ /* Set up the structure */
+ ModuleData->ModStart = NextModuleBase;
+ ModuleData->ModEnd = -1;
+
+ /* Copy the name */
+ strcpy(NameBuffer, ModuleName);
+ ModuleData->String = (ULONG_PTR)NameBuffer;
+
+ /* Set the current Module */
+ CurrentModule = ModuleData;
+
+ /* Return Module Base Address */
+ return(ModuleData->ModStart);
+}
+
+BOOLEAN
+NTAPI
+FrLdrCloseModule(ULONG_PTR ModuleBase,
+ ULONG ModuleSize)
+{
+ PLOADER_MODULE ModuleData = CurrentModule;
+
+ /* Make sure a module is opened */
+ if (ModuleData) {
+
+ /* Make sure this is the right module and that it hasn't been closed */
+ if ((ModuleBase == ModuleData->ModStart) && (ModuleData->ModEnd == (ULONG_PTR)-1)) {
+
+ /* Close the Module */
+ ModuleData->ModEnd = ModuleData->ModStart + ModuleSize;
+
+ /* Set the next Module Base and increase the number of modules */
+ NextModuleBase = ROUND_UP(ModuleData->ModEnd, PAGE_SIZE);
+ LoaderBlock.ModsCount++;
+
+ /* Close the currently opened module */
+ CurrentModule = NULL;
+
+ /* Success */
+ return(TRUE);
+ }
+ }
+
+ /* Failure path */
+ return(FALSE);
+}
--- /dev/null
- VOID MmAllocatePagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG PageCount)
+/*
+ * FreeLoader
+ * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <freeldr.h>
+#include <debug.h>
+
+#ifdef DBG
+typedef struct
+{
+ ULONG Type;
+ UCHAR TypeString[20];
+} FREELDR_MEMORY_TYPE, *PFREELDR_MEMORY_TYPE;
+
+ULONG MemoryTypeCount = 5;
+FREELDR_MEMORY_TYPE MemoryTypeArray[] =
+{
+ { 0, "Unknown Memory" },
+ { BiosMemoryUsable, "Usable Memory" },
+ { BiosMemoryReserved, "Reserved Memory" },
+ { BiosMemoryAcpiReclaim, "ACPI Reclaim Memory" },
+ { BiosMemoryAcpiNvs, "ACPI NVS Memory" },
+};
+#endif
+
+PVOID PageLookupTableAddress = NULL;
+ULONG TotalPagesInLookupTable = 0;
+ULONG FreePagesInLookupTable = 0;
+ULONG LastFreePageHint = 0;
+
+BOOLEAN MmInitializeMemoryManager(VOID)
+{
+ BIOS_MEMORY_MAP BiosMemoryMap[32];
+ ULONG BiosMemoryMapEntryCount;
+#ifdef DBG
+ ULONG Index;
+#endif
+
+ DbgPrint((DPRINT_MEMORY, "Initializing Memory Manager.\n"));
+
+ RtlZeroMemory(BiosMemoryMap, sizeof(BIOS_MEMORY_MAP) * 32);
+
+ BiosMemoryMapEntryCount = MachGetMemoryMap(BiosMemoryMap, sizeof(BiosMemoryMap) / sizeof(BIOS_MEMORY_MAP));
+
+#ifdef DBG
+ // Dump the system memory map
+ if (BiosMemoryMapEntryCount != 0)
+ {
+ DbgPrint((DPRINT_MEMORY, "System Memory Map (Base Address, Length, Type):\n"));
+ for (Index=0; Index<BiosMemoryMapEntryCount; Index++)
+ {
+ DbgPrint((DPRINT_MEMORY, "%x%x\t %x%x\t %s\n", BiosMemoryMap[Index].BaseAddress, BiosMemoryMap[Index].Length, MmGetSystemMemoryMapTypeString(BiosMemoryMap[Index].Type)));
+ }
+ }
+#endif
+
+ // If we got the system memory map then fixup invalid entries
+ if (BiosMemoryMapEntryCount != 0)
+ {
+ MmFixupSystemMemoryMap(BiosMemoryMap, &BiosMemoryMapEntryCount);
+ }
+
+ // Find address for the page lookup table
+ TotalPagesInLookupTable = MmGetAddressablePageCountIncludingHoles(BiosMemoryMap, BiosMemoryMapEntryCount);
+ PageLookupTableAddress = MmFindLocationForPageLookupTable(BiosMemoryMap, BiosMemoryMapEntryCount);
+ LastFreePageHint = TotalPagesInLookupTable;
+
+ if (PageLookupTableAddress == 0)
+ {
+ // If we get here then we probably couldn't
+ // find a contiguous chunk of memory big
+ // enough to hold the page lookup table
+ printf("Error initializing memory manager!\n");
+ return FALSE;
+ }
+
+ // Initialize the page lookup table
+ MmInitPageLookupTable(PageLookupTableAddress, TotalPagesInLookupTable, BiosMemoryMap, BiosMemoryMapEntryCount);
+ MmUpdateLastFreePageHint(PageLookupTableAddress, TotalPagesInLookupTable);
+
+ FreePagesInLookupTable = MmCountFreePagesInLookupTable(PageLookupTableAddress, TotalPagesInLookupTable);
+
+ DbgPrint((DPRINT_MEMORY, "Memory Manager initialized. %d pages available.\n", FreePagesInLookupTable));
+ return TRUE;
+}
+
+#ifdef DBG
+PUCHAR MmGetSystemMemoryMapTypeString(ULONG Type)
+{
+ ULONG Index;
+
+ for (Index=1; Index<MemoryTypeCount; Index++)
+ {
+ if (MemoryTypeArray[Index].Type == Type)
+ {
+ return MemoryTypeArray[Index].TypeString;
+ }
+ }
+
+ return MemoryTypeArray[0].TypeString;
+}
+#endif
+
+ULONG MmGetPageNumberFromAddress(PVOID Address)
+{
+ return ((ULONG)Address) / MM_PAGE_SIZE;
+}
+
+PVOID MmGetEndAddressOfAnyMemory(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount)
+{
+ ULONGLONG MaxStartAddressSoFar;
+ ULONGLONG EndAddressOfMemory;
+ ULONG Index;
+
+ MaxStartAddressSoFar = 0;
+ EndAddressOfMemory = 0;
+ for (Index=0; Index<MapCount; Index++)
+ {
+ if (MaxStartAddressSoFar <= BiosMemoryMap[Index].BaseAddress)
+ {
+ MaxStartAddressSoFar = BiosMemoryMap[Index].BaseAddress;
+ EndAddressOfMemory = (MaxStartAddressSoFar + BiosMemoryMap[Index].Length);
+ if (EndAddressOfMemory > 0xFFFFFFFF)
+ {
+ EndAddressOfMemory = 0xFFFFFFFF;
+ }
+ }
+ }
+
+ DbgPrint((DPRINT_MEMORY, "MmGetEndAddressOfAnyMemory() returning 0x%x\n", (ULONG)EndAddressOfMemory));
+
+ return (PVOID)(ULONG)EndAddressOfMemory;
+}
+
+ULONG MmGetAddressablePageCountIncludingHoles(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount)
+{
+ ULONG PageCount;
+ ULONGLONG EndAddress;
+
+ EndAddress = (ULONGLONG)(ULONG)MmGetEndAddressOfAnyMemory(BiosMemoryMap, MapCount);
+
+ // Since MmGetEndAddressOfAnyMemory() won't
+ // return addresses higher than 0xFFFFFFFF
+ // then we need to adjust the end address
+ // to 0x100000000 so we don't get an
+ // off-by-one error
+ if (EndAddress >= 0xFFFFFFFF)
+ {
+ EndAddress = 0x100000000LL;
+
+ DbgPrint((DPRINT_MEMORY, "MmGetEndAddressOfAnyMemory() returned 0xFFFFFFFF, correcting to be 0x100000000.\n"));
+ }
+
+ PageCount = (EndAddress / MM_PAGE_SIZE);
+
+ DbgPrint((DPRINT_MEMORY, "MmGetAddressablePageCountIncludingHoles() returning %d\n", PageCount));
+
+ return PageCount;
+}
+
+PVOID MmFindLocationForPageLookupTable(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount)
+{
+ ULONG TotalPageCount;
+ ULONG PageLookupTableSize;
+ PVOID PageLookupTableMemAddress;
+ int Index;
+ BIOS_MEMORY_MAP TempBiosMemoryMap[32];
+
+ TotalPageCount = MmGetAddressablePageCountIncludingHoles(BiosMemoryMap, MapCount);
+ PageLookupTableSize = TotalPageCount * sizeof(PAGE_LOOKUP_TABLE_ITEM);
+ PageLookupTableMemAddress = 0;
+
+ RtlCopyMemory(TempBiosMemoryMap, BiosMemoryMap, sizeof(BIOS_MEMORY_MAP) * 32);
+ MmSortBiosMemoryMap(TempBiosMemoryMap, MapCount);
+
+ for (Index=(MapCount-1); Index>=0; Index--)
+ {
+ // If this is usable memory with a big enough length
+ // then we'll put our page lookup table here
+ if (TempBiosMemoryMap[Index].Type == BiosMemoryUsable && TempBiosMemoryMap[Index].Length >= PageLookupTableSize)
+ {
+ PageLookupTableMemAddress = (PVOID)(ULONG)(TempBiosMemoryMap[Index].BaseAddress + (TempBiosMemoryMap[Index].Length - PageLookupTableSize));
+ break;
+ }
+ }
+
+ DbgPrint((DPRINT_MEMORY, "MmFindLocationForPageLookupTable() returning 0x%x\n", PageLookupTableMemAddress));
+
+ return PageLookupTableMemAddress;
+}
+
+VOID MmSortBiosMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount)
+{
+ ULONG Index;
+ ULONG LoopCount;
+ BIOS_MEMORY_MAP TempMapItem;
+
+ // Loop once for each entry in the memory map minus one
+ // On each loop iteration go through and sort the memory map
+ for (LoopCount=0; LoopCount<(MapCount-1); LoopCount++)
+ {
+ for (Index=0; Index<(MapCount-1); Index++)
+ {
+ if (BiosMemoryMap[Index].BaseAddress > BiosMemoryMap[Index+1].BaseAddress)
+ {
+ TempMapItem = BiosMemoryMap[Index];
+ BiosMemoryMap[Index] = BiosMemoryMap[Index+1];
+ BiosMemoryMap[Index+1] = TempMapItem;
+ }
+ }
+ }
+}
+
+VOID MmInitPageLookupTable(PVOID PageLookupTable, ULONG TotalPageCount, PBIOS_MEMORY_MAP BiosMemoryMap, ULONG MapCount)
+{
+ ULONG MemoryMapStartPage;
+ ULONG MemoryMapEndPage;
+ ULONG MemoryMapPageCount;
+ ULONG MemoryMapPageAllocated;
+ ULONG PageLookupTableStartPage;
+ ULONG PageLookupTablePageCount;
+ ULONG Index;
+
+ DbgPrint((DPRINT_MEMORY, "MmInitPageLookupTable()\n"));
+
+ // Mark every page as allocated initially
+ // We will go through and mark pages again according to the memory map
+ // But this will mark any holes not described in the map as allocated
+ MmMarkPagesInLookupTable(PageLookupTable, 0, TotalPageCount, 1);
+
+ for (Index=0; Index<MapCount; Index++)
+ {
+ MemoryMapStartPage = MmGetPageNumberFromAddress((PVOID)(ULONG)BiosMemoryMap[Index].BaseAddress);
+ MemoryMapEndPage = MmGetPageNumberFromAddress((PVOID)(ULONG)(BiosMemoryMap[Index].BaseAddress + BiosMemoryMap[Index].Length - 1));
+ MemoryMapPageCount = (MemoryMapEndPage - MemoryMapStartPage) + 1;
+ MemoryMapPageAllocated = (BiosMemoryMap[Index].Type == BiosMemoryUsable) ? LoaderFree : LoaderFirmwarePermanent;/*BiosMemoryMap[Index].Type*/;
+ DbgPrint((DPRINT_MEMORY, "Marking pages as type %d: StartPage: %d PageCount: %d\n", MemoryMapPageAllocated, MemoryMapStartPage, MemoryMapPageCount));
+ MmMarkPagesInLookupTable(PageLookupTable, MemoryMapStartPage, MemoryMapPageCount, MemoryMapPageAllocated);
+ }
+
+ // Mark the low memory region below 1MB as reserved (256 pages in region)
+ DbgPrint((DPRINT_MEMORY, "Marking the low 1MB region as reserved.\n"));
+ MmMarkPagesInLookupTable(PageLookupTable, 0, 256, LoaderFirmwarePermanent);
+
+ // Mark the pages that the lookup table occupies as reserved
+ PageLookupTableStartPage = MmGetPageNumberFromAddress(PageLookupTable);
+ PageLookupTablePageCount = MmGetPageNumberFromAddress((PVOID)((ULONG_PTR)PageLookupTable + ROUND_UP(TotalPageCount * sizeof(PAGE_LOOKUP_TABLE_ITEM), MM_PAGE_SIZE))) - PageLookupTableStartPage;
+ DbgPrint((DPRINT_MEMORY, "Marking the page lookup table pages as reserved StartPage: %d PageCount: %d\n", PageLookupTableStartPage, PageLookupTablePageCount));
+ MmMarkPagesInLookupTable(PageLookupTable, PageLookupTableStartPage, PageLookupTablePageCount, LoaderFirmwareTemporary);
+}
+
+VOID MmMarkPagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG PageCount, TYPE_OF_MEMORY PageAllocated)
+{
+ PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable;
+ ULONG Index;
+
+ for (Index=StartPage; Index<(StartPage+PageCount); Index++)
+ {
+ if ((Index <= (StartPage + 16)) || (Index >= (StartPage+PageCount-16)))
+ {
+ DbgPrint((DPRINT_MEMORY, "Index = %d StartPage = %d PageCount = %d\n", Index, StartPage, PageCount));
+ }
+ RealPageLookupTable[Index].PageAllocated = PageAllocated;
+ RealPageLookupTable[Index].PageAllocationLength = (PageAllocated != LoaderFree) ? 1 : 0;
+ }
+ DbgPrint((DPRINT_MEMORY, "MmMarkPagesInLookupTable() Done\n"));
+}
+
++VOID MmAllocatePagesInLookupTable(PVOID PageLookupTable, ULONG StartPage, ULONG PageCount, TYPE_OF_MEMORY MemoryType)
+{
+ PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable;
+ ULONG Index;
+
+ for (Index=StartPage; Index<(StartPage+PageCount); Index++)
+ {
+ RealPageLookupTable[Index].PageAllocated = LoaderSystemCode;
+ RealPageLookupTable[Index].PageAllocationLength = (Index == StartPage) ? PageCount : 0;
+ }
+}
+
+ULONG MmCountFreePagesInLookupTable(PVOID PageLookupTable, ULONG TotalPageCount)
+{
+ PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable;
+ ULONG Index;
+ ULONG FreePageCount;
+
+ FreePageCount = 0;
+ for (Index=0; Index<TotalPageCount; Index++)
+ {
+ if (RealPageLookupTable[Index].PageAllocated == LoaderFree)
+ {
+ FreePageCount++;
+ }
+ }
+
+ return FreePageCount;
+}
+
+ULONG MmFindAvailablePages(PVOID PageLookupTable, ULONG TotalPageCount, ULONG PagesNeeded, BOOLEAN FromEnd)
+{
+ PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable;
+ ULONG AvailablePagesSoFar;
+ ULONG Index;
+
+ if (LastFreePageHint > TotalPageCount)
+ {
+ LastFreePageHint = TotalPageCount;
+ }
+
+ AvailablePagesSoFar = 0;
+ if (FromEnd)
+ {
+ /* Allocate "high" (from end) pages */
+ for (Index=LastFreePageHint-1; Index>0; Index--)
+ {
+ if (RealPageLookupTable[Index].PageAllocated != LoaderFree)
+ {
+ AvailablePagesSoFar = 0;
+ continue;
+ }
+ else
+ {
+ AvailablePagesSoFar++;
+ }
+
+ if (AvailablePagesSoFar >= PagesNeeded)
+ {
+ return Index;
+ }
+ }
+ }
+ else
+ {
+ DbgPrint((DPRINT_MEMORY, "Alloc low memory, LastFreePageHint %d, TPC %d\n", LastFreePageHint, TotalPageCount));
+ /* Allocate "low" pages */
+ for (Index=1; Index < LastFreePageHint; Index++)
+ {
+ if (RealPageLookupTable[Index].PageAllocated != LoaderFree)
+ {
+ AvailablePagesSoFar = 0;
+ continue;
+ }
+ else
+ {
+ AvailablePagesSoFar++;
+ }
+
+ if (AvailablePagesSoFar >= PagesNeeded)
+ {
+ return Index - AvailablePagesSoFar + 1;
+ }
+ }
+ }
+
+ return 0;
+}
+
+ULONG MmFindAvailablePagesBeforePage(PVOID PageLookupTable, ULONG TotalPageCount, ULONG PagesNeeded, ULONG LastPage)
+{
+ PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable;
+ ULONG AvailablePagesSoFar;
+ ULONG Index;
+
+ if (LastPage > TotalPageCount)
+ {
+ return MmFindAvailablePages(PageLookupTable, TotalPageCount, PagesNeeded, TRUE);
+ }
+
+ AvailablePagesSoFar = 0;
+ for (Index=LastPage-1; Index>0; Index--)
+ {
+ if (RealPageLookupTable[Index].PageAllocated != LoaderFree)
+ {
+ AvailablePagesSoFar = 0;
+ continue;
+ }
+ else
+ {
+ AvailablePagesSoFar++;
+ }
+
+ if (AvailablePagesSoFar >= PagesNeeded)
+ {
+ return Index;
+ }
+ }
+
+ return 0;
+}
+
+VOID MmFixupSystemMemoryMap(PBIOS_MEMORY_MAP BiosMemoryMap, ULONG* MapCount)
+{
+ UINT Index;
+ UINT Index2;
+
+ // Loop through each entry in the array
+ for (Index=0; Index<*MapCount; Index++)
+ {
+ // If the entry type isn't usable then remove
+ // it from the memory map (this will help reduce
+ // the size of our lookup table)
+ if (BiosMemoryMap[Index].Type != BiosMemoryUsable)
+ {
+ // Slide every entry after this down one
+ for (Index2=Index; Index2<(*MapCount - 1); Index2++)
+ {
+ BiosMemoryMap[Index2] = BiosMemoryMap[Index2 + 1];
+ }
+ (*MapCount)--;
+ Index--;
+ }
+ }
+}
+
+VOID MmUpdateLastFreePageHint(PVOID PageLookupTable, ULONG TotalPageCount)
+{
+ PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable;
+ ULONG Index;
+
+ for (Index=TotalPageCount-1; Index>0; Index--)
+ {
+ if (RealPageLookupTable[Index].PageAllocated == LoaderFree)
+ {
+ LastFreePageHint = Index + 1;
+ break;
+ }
+ }
+}
+
+BOOLEAN MmAreMemoryPagesAvailable(PVOID PageLookupTable, ULONG TotalPageCount, PVOID PageAddress, ULONG PageCount)
+{
+ PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTable;
+ ULONG StartPage;
+ ULONG Index;
+
+ StartPage = MmGetPageNumberFromAddress(PageAddress);
+
+ // Make sure they aren't trying to go past the
+ // end of availabe memory
+ if ((StartPage + PageCount) > TotalPageCount)
+ {
+ return FALSE;
+ }
+
+ for (Index=StartPage; Index<(StartPage + PageCount); Index++)
+ {
+ // If this page is allocated then there obviously isn't
+ // memory availabe so return FALSE
+ if (RealPageLookupTable[Index].PageAllocated != LoaderFree)
+ {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
--- /dev/null
- PVOID MmAllocateMemory(ULONG MemorySize)
+/*
+ * FreeLoader
+ * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <freeldr.h>
+#include <debug.h>
+
+ULONG AllocationCount = 0;
+
+#ifdef DBG
+VOID VerifyHeap(VOID);
+VOID DumpMemoryAllocMap(VOID);
+VOID IncrementAllocationCount(VOID);
+VOID DecrementAllocationCount(VOID);
+VOID MemAllocTest(VOID);
+#endif // DBG
+
+/*
+ * Hack alert
+ * Normally, we allocate whole pages. This is ofcourse wastefull for small
+ * allocations (a few bytes). So, for small allocations (smaller than a page)
+ * we sub-allocate. When the first small allocation is done, a page is
+ * requested. We keep a pointer to that page in SubAllocationPage. The alloc
+ * is satisfied by returning a pointer to the beginning of the page. We also
+ * keep track of how many bytes are still available in the page in SubAllocationRest.
+ * When the next small request comes in, we try to allocate it just after the
+ * memory previously allocated. If it won't fit, we allocate a new page and
+ * the whole process starts again.
+ * Note that suballocations are done back-to-back, there's no bookkeeping at all.
+ * That also means that we cannot really free suballocations. So, when a free is
+ * done and it is determined that this might be a free of a sub-allocation, we
+ * just no-op the free.
+ * Perhaps we should use the heap routines from ntdll here.
+ */
+static PVOID SubAllocationPage = NULL;
+static unsigned SubAllocationRest = 0;
+
+BOOLEAN AllocateFromEnd = TRUE;
+
+VOID MmChangeAllocationPolicy(BOOLEAN PolicyAllocatePagesFromEnd)
+{
+ AllocateFromEnd = PolicyAllocatePagesFromEnd;
+}
+
- MmAllocatePagesInLookupTable(PageLookupTableAddress, FirstFreePageFromEnd, PagesNeeded);
++PVOID MmAllocateMemoryWithType(ULONG MemorySize, TYPE_OF_MEMORY MemoryType)
+{
+ ULONG PagesNeeded;
+ ULONG FirstFreePageFromEnd;
+ PVOID MemPointer;
+
+ if (MemorySize == 0)
+ {
+ DbgPrint((DPRINT_MEMORY, "MmAllocateMemory() called for 0 bytes. Returning NULL.\n"));
+ UiMessageBoxCritical("Memory allocation failed: MmAllocateMemory() called for 0 bytes.");
+ return NULL;
+ }
+
+ MemorySize = ROUND_UP(MemorySize, 4);
+ if (MemorySize <= SubAllocationRest)
+ {
+ MemPointer = (PVOID)((ULONG_PTR)SubAllocationPage + MM_PAGE_SIZE - SubAllocationRest);
+ SubAllocationRest -= MemorySize;
+ return MemPointer;
+ }
+
+ // Find out how many blocks it will take to
+ // satisfy this allocation
+ PagesNeeded = ROUND_UP(MemorySize, MM_PAGE_SIZE) / MM_PAGE_SIZE;
+
+ // If we don't have enough available mem
+ // then return NULL
+ if (FreePagesInLookupTable < PagesNeeded)
+ {
+ DbgPrint((DPRINT_MEMORY, "Memory allocation failed in MmAllocateMemory(). Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize, AllocationCount));
+ UiMessageBoxCritical("Memory allocation failed: out of memory.");
+ return NULL;
+ }
+
+ FirstFreePageFromEnd = MmFindAvailablePages(PageLookupTableAddress, TotalPagesInLookupTable, PagesNeeded, AllocateFromEnd);
+
+ if (FirstFreePageFromEnd == (ULONG)-1)
+ {
+ DbgPrint((DPRINT_MEMORY, "Memory allocation failed in MmAllocateMemory(). Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize, AllocationCount));
+ UiMessageBoxCritical("Memory allocation failed: out of memory.");
+ return NULL;
+ }
+
- PVOID MmAllocateMemoryAtAddress(ULONG MemorySize, PVOID DesiredAddress)
++ MmAllocatePagesInLookupTable(PageLookupTableAddress, FirstFreePageFromEnd, PagesNeeded, MemoryType);
+
+ FreePagesInLookupTable -= PagesNeeded;
+ MemPointer = (PVOID)(FirstFreePageFromEnd * MM_PAGE_SIZE);
+
+ if (MemorySize < MM_PAGE_SIZE)
+ {
+ SubAllocationPage = MemPointer;
+ SubAllocationRest = MM_PAGE_SIZE - MemorySize;
+ }
+
+
+#ifdef DBG
+ IncrementAllocationCount();
+ DbgPrint((DPRINT_MEMORY, "Allocated %d bytes (%d pages) of memory starting at page %d. AllocCount: %d\n", MemorySize, PagesNeeded, FirstFreePageFromEnd, AllocationCount));
+ DbgPrint((DPRINT_MEMORY, "Memory allocation pointer: 0x%x\n", MemPointer));
+ //VerifyHeap();
+#endif // DBG
+
+ // Now return the pointer
+ return MemPointer;
+}
+
- MmAllocatePagesInLookupTable(PageLookupTableAddress, StartPageNumber, PagesNeeded);
++PVOID MmAllocateMemory(ULONG MemorySize)
++{
++ // Temporary forwarder...
++ return MmAllocateMemoryWithType(MemorySize, LoaderOsloaderHeap);
++}
++
++PVOID MmAllocateMemoryAtAddress(ULONG MemorySize, PVOID DesiredAddress, TYPE_OF_MEMORY MemoryType)
+{
+ ULONG PagesNeeded;
+ ULONG StartPageNumber;
+ PVOID MemPointer;
+
+ if (MemorySize == 0)
+ {
+ DbgPrint((DPRINT_MEMORY, "MmAllocateMemoryAtAddress() called for 0 bytes. Returning NULL.\n"));
+ UiMessageBoxCritical("Memory allocation failed: MmAllocateMemoryAtAddress() called for 0 bytes.");
+ return NULL;
+ }
+
+ // Find out how many blocks it will take to
+ // satisfy this allocation
+ PagesNeeded = ROUND_UP(MemorySize, MM_PAGE_SIZE) / MM_PAGE_SIZE;
+
+ // Get the starting page number
+ StartPageNumber = MmGetPageNumberFromAddress(DesiredAddress);
+
+ // If we don't have enough available mem
+ // then return NULL
+ if (FreePagesInLookupTable < PagesNeeded)
+ {
+ DbgPrint((DPRINT_MEMORY, "Memory allocation failed in MmAllocateMemoryAtAddress(). "
+ "Not enough free memory to allocate %d bytes (requesting %d pages but have only %d). "
+ "AllocationCount: %d\n", MemorySize, PagesNeeded, FreePagesInLookupTable, AllocationCount));
+ UiMessageBoxCritical("Memory allocation failed: out of memory.");
+ return NULL;
+ }
+
+ if (MmAreMemoryPagesAvailable(PageLookupTableAddress, TotalPagesInLookupTable, DesiredAddress, PagesNeeded) == FALSE)
+ {
+ DbgPrint((DPRINT_MEMORY, "Memory allocation failed in MmAllocateMemoryAtAddress(). "
+ "Not enough free memory to allocate %d bytes at address %p. AllocationCount: %d\n",
+ MemorySize, DesiredAddress, AllocationCount));
+
+ // Don't tell this to user since caller should try to alloc this memory
+ // at a different address
+ //UiMessageBoxCritical("Memory allocation failed: out of memory.");
+ return NULL;
+ }
+
- PVOID MmAllocateHighestMemoryBelowAddress(ULONG MemorySize, PVOID DesiredAddress)
++ MmAllocatePagesInLookupTable(PageLookupTableAddress, StartPageNumber, PagesNeeded, MemoryType);
+
+ FreePagesInLookupTable -= PagesNeeded;
+ MemPointer = (PVOID)(StartPageNumber * MM_PAGE_SIZE);
+
+#ifdef DBG
+ IncrementAllocationCount();
+ DbgPrint((DPRINT_MEMORY, "Allocated %d bytes (%d pages) of memory starting at page %d. AllocCount: %d\n", MemorySize, PagesNeeded, StartPageNumber, AllocationCount));
+ DbgPrint((DPRINT_MEMORY, "Memory allocation pointer: 0x%x\n", MemPointer));
+ //VerifyHeap();
+#endif // DBG
+
+ // Now return the pointer
+ return MemPointer;
+}
+
- MmAllocatePagesInLookupTable(PageLookupTableAddress, FirstFreePageFromEnd, PagesNeeded);
++PVOID MmAllocateHighestMemoryBelowAddress(ULONG MemorySize, PVOID DesiredAddress, TYPE_OF_MEMORY MemoryType)
+{
+ ULONG PagesNeeded;
+ ULONG FirstFreePageFromEnd;
+ ULONG DesiredAddressPageNumber;
+ PVOID MemPointer;
+
+ if (MemorySize == 0)
+ {
+ DbgPrint((DPRINT_MEMORY, "MmAllocateHighestMemoryBelowAddress() called for 0 bytes. Returning NULL.\n"));
+ UiMessageBoxCritical("Memory allocation failed: MmAllocateHighestMemoryBelowAddress() called for 0 bytes.");
+ return NULL;
+ }
+
+ // Find out how many blocks it will take to
+ // satisfy this allocation
+ PagesNeeded = ROUND_UP(MemorySize, MM_PAGE_SIZE) / MM_PAGE_SIZE;
+
+ // Get the page number for their desired address
+ DesiredAddressPageNumber = (ULONG)DesiredAddress / MM_PAGE_SIZE;
+
+ // If we don't have enough available mem
+ // then return NULL
+ if (FreePagesInLookupTable < PagesNeeded)
+ {
+ DbgPrint((DPRINT_MEMORY, "Memory allocation failed in MmAllocateHighestMemoryBelowAddress(). Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize, AllocationCount));
+ UiMessageBoxCritical("Memory allocation failed: out of memory.");
+ return NULL;
+ }
+
+ FirstFreePageFromEnd = MmFindAvailablePagesBeforePage(PageLookupTableAddress, TotalPagesInLookupTable, PagesNeeded, DesiredAddressPageNumber);
+
+ if (FirstFreePageFromEnd == 0)
+ {
+ DbgPrint((DPRINT_MEMORY, "Memory allocation failed in MmAllocateHighestMemoryBelowAddress(). Not enough free memory to allocate %d bytes. AllocationCount: %d\n", MemorySize, AllocationCount));
+ UiMessageBoxCritical("Memory allocation failed: out of memory.");
+ return NULL;
+ }
+
++ MmAllocatePagesInLookupTable(PageLookupTableAddress, FirstFreePageFromEnd, PagesNeeded, MemoryType);
+
+ FreePagesInLookupTable -= PagesNeeded;
+ MemPointer = (PVOID)(FirstFreePageFromEnd * MM_PAGE_SIZE);
+
+#ifdef DBG
+ IncrementAllocationCount();
+ DbgPrint((DPRINT_MEMORY, "Allocated %d bytes (%d pages) of memory starting at page %d. AllocCount: %d\n", MemorySize, PagesNeeded, FirstFreePageFromEnd, AllocationCount));
+ DbgPrint((DPRINT_MEMORY, "Memory allocation pointer: 0x%x\n", MemPointer));
+ //VerifyHeap();
+#endif // DBG
+
+ // Now return the pointer
+ return MemPointer;
+}
+
+VOID MmFreeMemory(PVOID MemoryPointer)
+{
+ ULONG PageNumber;
+ ULONG PageCount;
+ ULONG Idx;
+ PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTableAddress;
+
+#ifdef DBG
+
+ // Make sure we didn't get a bogus pointer
+ if (MemoryPointer >= (PVOID)(TotalPagesInLookupTable * MM_PAGE_SIZE))
+ {
+ BugCheck((DPRINT_MEMORY, "Bogus memory pointer (0x%x) passed to MmFreeMemory()\n", MemoryPointer));
+ }
+#endif // DBG
+
+ // Find out the page number of the first
+ // page of memory they allocated
+ PageNumber = MmGetPageNumberFromAddress(MemoryPointer);
+ PageCount = RealPageLookupTable[PageNumber].PageAllocationLength;
+
+#ifdef DBG
+ // Make sure we didn't get a bogus pointer
+ if ((PageCount < 1) || (PageCount > (TotalPagesInLookupTable - PageNumber)))
+ {
+ BugCheck((DPRINT_MEMORY, "Invalid page count in lookup table. PageLookupTable[%d].PageAllocationLength = %d\n", PageNumber, RealPageLookupTable[PageNumber].PageAllocationLength));
+ }
+
+ // Loop through our array check all the pages
+ // to make sure they are allocated with a length of 0
+ for (Idx=PageNumber+1; Idx<(PageNumber + PageCount); Idx++)
+ {
+ if ((RealPageLookupTable[Idx].PageAllocated == LoaderFree) ||
+ (RealPageLookupTable[Idx].PageAllocationLength != 0))
+ {
+ BugCheck((DPRINT_MEMORY, "Invalid page entry in lookup table, PageAllocated should = 1 and PageAllocationLength should = 0 because this is not the first block in the run. PageLookupTable[%d].PageAllocated = %d PageLookupTable[%d].PageAllocationLength = %d\n", PageNumber, RealPageLookupTable[PageNumber].PageAllocated, PageNumber, RealPageLookupTable[PageNumber].PageAllocationLength));
+ }
+ }
+
+#endif
+
+ /* If this allocation is only a single page, it could be a sub-allocated page.
+ * Just don't free it */
+ if (1 == PageCount)
+ {
+ return;
+ }
+
+ // Loop through our array and mark all the
+ // blocks as free
+ for (Idx=PageNumber; Idx<(PageNumber + PageCount); Idx++)
+ {
+ RealPageLookupTable[Idx].PageAllocated = LoaderFree;
+ RealPageLookupTable[Idx].PageAllocationLength = 0;
+ }
+
+ FreePagesInLookupTable += PageCount;
+
+#ifdef DBG
+ DecrementAllocationCount();
+ DbgPrint((DPRINT_MEMORY, "Freed %d pages of memory starting at page %d. AllocationCount: %d\n", PageCount, PageNumber, AllocationCount));
+ //VerifyHeap();
+#endif // DBG
+}
+
++PVOID MmHeapAlloc(ULONG MemorySize)
++{
++ // Stub for WinLdr
++ return NULL;
++}
++
++VOID MmHeapFree(PVOID MemoryPointer)
++{
++ // Stub for WinLdr
++}
++
++
+#ifdef DBG
+VOID VerifyHeap(VOID)
+{
+ ULONG Idx;
+ ULONG Idx2;
+ ULONG Count;
+ PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTableAddress;
+
+ if (DUMP_MEM_MAP_ON_VERIFY)
+ {
+ DumpMemoryAllocMap();
+ }
+
+ // Loop through the array and verify that
+ // everything is kosher
+ for (Idx=0; Idx<TotalPagesInLookupTable; Idx++)
+ {
+ // Check if this block is allocated
+ if (RealPageLookupTable[Idx].PageAllocated != LoaderFree)
+ {
+ // This is the first block in the run so it
+ // had better have a length that is within range
+ if ((RealPageLookupTable[Idx].PageAllocationLength < 1) || (RealPageLookupTable[Idx].PageAllocationLength > (TotalPagesInLookupTable - Idx)))
+ {
+ BugCheck((DPRINT_MEMORY, "Allocation length out of range in heap table. PageLookupTable[Idx].PageAllocationLength = %d\n", RealPageLookupTable[Idx].PageAllocationLength));
+ }
+
+ // Now go through and verify that the rest of
+ // this run has the blocks marked allocated
+ // with a length of zero but don't check the
+ // first one because we already did
+ Count = RealPageLookupTable[Idx].PageAllocationLength;
+ for (Idx2=1; Idx2<Count; Idx2++)
+ {
+ // Make sure it's allocated
+ if (RealPageLookupTable[Idx + Idx2].PageAllocated == LoaderFree)
+ {
+ BugCheck((DPRINT_MEMORY, "Lookup table indicates hole in memory allocation. RealPageLookupTable[Idx + Idx2].PageAllocated == 0\n"));
+ }
+
+ // Make sure the length is zero
+ if (RealPageLookupTable[Idx + Idx2].PageAllocationLength != 0)
+ {
+ BugCheck((DPRINT_MEMORY, "Allocation chain has non-zero value in non-first block in lookup table. RealPageLookupTable[Idx + Idx2].PageAllocationLength != 0\n"));
+ }
+ }
+
+ // Move on to the next run
+ Idx += (Count - 1);
+ }
+ else
+ {
+ // Nope, not allocated so make sure the length is zero
+ if (RealPageLookupTable[Idx].PageAllocationLength != 0)
+ {
+ BugCheck((DPRINT_MEMORY, "Free block is start of memory allocation. RealPageLookupTable[Idx].PageAllocationLength != 0\n"));
+ }
+ }
+ }
+}
+
+VOID DumpMemoryAllocMap(VOID)
+{
+ ULONG Idx;
+ PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTableAddress;
+
+ DbgPrint((DPRINT_MEMORY, "----------- Memory Allocation Bitmap -----------\n"));
+
+ for (Idx=0; Idx<TotalPagesInLookupTable; Idx++)
+ {
+ if ((Idx % 32) == 0)
+ {
+ DbgPrint((DPRINT_MEMORY, "\n"));
+ DbgPrint((DPRINT_MEMORY, "%x:\t", (Idx * MM_PAGE_SIZE)));
+ }
+ else if ((Idx % 4) == 0)
+ {
+ DbgPrint((DPRINT_MEMORY, " "));
+ }
+
+ switch (RealPageLookupTable[Idx].PageAllocated)
+ {
+ case LoaderFree:
+ DbgPrint((DPRINT_MEMORY, "*"));
+ break;
+ case LoaderBad:
+ DbgPrint((DPRINT_MEMORY, "-"));
+ break;
+ case LoaderLoadedProgram:
+ DbgPrint((DPRINT_MEMORY, "O"));
+ break;
+ case LoaderFirmwareTemporary:
+ DbgPrint((DPRINT_MEMORY, "T"));
+ break;
+ case LoaderFirmwarePermanent:
+ DbgPrint((DPRINT_MEMORY, "P"));
+ break;
+ case LoaderOsloaderHeap:
+ DbgPrint((DPRINT_MEMORY, "H"));
+ break;
+ case LoaderOsloaderStack:
+ DbgPrint((DPRINT_MEMORY, "S"));
+ break;
+ case LoaderSystemCode:
+ DbgPrint((DPRINT_MEMORY, "K"));
+ break;
+ case LoaderHalCode:
+ DbgPrint((DPRINT_MEMORY, "L"));
+ break;
+ case LoaderBootDriver:
+ DbgPrint((DPRINT_MEMORY, "B"));
+ break;
+ case LoaderStartupPcrPage:
+ DbgPrint((DPRINT_MEMORY, "G"));
+ break;
+ case LoaderRegistryData:
+ DbgPrint((DPRINT_MEMORY, "R"));
+ break;
+ case LoaderMemoryData:
+ DbgPrint((DPRINT_MEMORY, "M"));
+ break;
+ case LoaderNlsData:
+ DbgPrint((DPRINT_MEMORY, "N"));
+ break;
+ case LoaderSpecialMemory:
+ DbgPrint((DPRINT_MEMORY, "C"));
+ break;
+ default:
+ DbgPrint((DPRINT_MEMORY, "?"));
+ break;
+ }
+ }
+
+ DbgPrint((DPRINT_MEMORY, "\n"));
+}
+
+VOID IncrementAllocationCount(VOID)
+{
+ AllocationCount++;
+}
+
+VOID DecrementAllocationCount(VOID)
+{
+ AllocationCount--;
+}
+
+VOID MemAllocTest(VOID)
+{
+ PVOID MemPtr1;
+ PVOID MemPtr2;
+ PVOID MemPtr3;
+ PVOID MemPtr4;
+ PVOID MemPtr5;
+
+ MemPtr1 = MmAllocateMemory(4096);
+ printf("MemPtr1: 0x%x\n", (int)MemPtr1);
+ MachConsGetCh();
+ MemPtr2 = MmAllocateMemory(4096);
+ printf("MemPtr2: 0x%x\n", (int)MemPtr2);
+ MachConsGetCh();
+ MemPtr3 = MmAllocateMemory(4096);
+ printf("MemPtr3: 0x%x\n", (int)MemPtr3);
+ DumpMemoryAllocMap();
+ VerifyHeap();
+ MachConsGetCh();
+
+ MmFreeMemory(MemPtr2);
+ MachConsGetCh();
+
+ MemPtr4 = MmAllocateMemory(2048);
+ printf("MemPtr4: 0x%x\n", (int)MemPtr4);
+ MachConsGetCh();
+ MemPtr5 = MmAllocateMemory(4096);
+ printf("MemPtr5: 0x%x\n", (int)MemPtr5);
+ MachConsGetCh();
+}
+#endif // DBG
+
+ULONG GetSystemMemorySize(VOID)
+{
+ return (TotalPagesInLookupTable * MM_PAGE_SIZE);
+}
+
+PPAGE_LOOKUP_TABLE_ITEM MmGetMemoryMap(ULONG *NoEntries)
+{
+ PPAGE_LOOKUP_TABLE_ITEM RealPageLookupTable = (PPAGE_LOOKUP_TABLE_ITEM)PageLookupTableAddress;
+
+ *NoEntries = TotalPagesInLookupTable;
+
+ return RealPageLookupTable;
+}
--- /dev/null
- ARC_DISK_SIGNATURE BldrDiskInfo[32];
- CHAR BldrArcNames[32][256];
-
+/*
+ * FreeLoader
+ *
+ * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
+ * Copyright (C) 2006 Aleksey Bragin <aleksey@reactos.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <freeldr.h>
+
+#include <ndk/ldrtypes.h>
+#include <debug.h>
+
+//FIXME: Do a better way to retrieve Arc disk information
+extern ULONG reactos_disk_count;
+extern ARC_DISK_SIGNATURE reactos_arc_disk_info[];
+extern char reactos_arc_strings[32][256];
+
- 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);
- }
-
-
+BOOLEAN
+WinLdrCheckForLoadedDll(IN OUT PLOADER_PARAMETER_BLOCK WinLdrBlock,
+ IN PCH DllName,
+ OUT PLDR_DATA_TABLE_ENTRY *LoadedEntry);
+
+// debug stuff
+VOID DumpMemoryAllocMap(VOID);
+VOID WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock);
+VOID WinLdrpDumpBootDriver(PLOADER_PARAMETER_BLOCK LoaderBlock);
+VOID WinLdrpDumpArcDisks(PLOADER_PARAMETER_BLOCK LoaderBlock);
+
+
- LoaderBlock = MmAllocateMemory(sizeof(LOADER_PARAMETER_BLOCK));
+// Init "phase 0"
+VOID
+AllocateAndInitLPB(PLOADER_PARAMETER_BLOCK *OutLoaderBlock)
+{
+ PLOADER_PARAMETER_BLOCK LoaderBlock;
+
+ /* Allocate and zero-init the LPB */
- LoaderBlock->NlsData = MmAllocateMemory(sizeof(NLS_DATA_BLOCK));
++ LoaderBlock = MmHeapAlloc(sizeof(LOADER_PARAMETER_BLOCK));
+ RtlZeroMemory(LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
+
+ /* Init three critical lists, used right away */
+ InitializeListHead(&LoaderBlock->LoadOrderListHead);
+ InitializeListHead(&LoaderBlock->MemoryDescriptorListHead);
+ InitializeListHead(&LoaderBlock->BootDriverListHead);
+
+ /* Alloc space for NLS (it will be converted to VA in WinLdrLoadNLS) */
- WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock)
++ LoaderBlock->NlsData = MmHeapAlloc(sizeof(NLS_DATA_BLOCK));
+ if (LoaderBlock->NlsData == NULL)
+ {
+ UiMessageBox("Failed to allocate memory for NLS table data!");
+ return;
+ }
+ RtlZeroMemory(LoaderBlock->NlsData, sizeof(NLS_DATA_BLOCK));
+
+ *OutLoaderBlock = LoaderBlock;
+}
+
+// Init "phase 1"
+VOID
- //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)";
++WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
++ PCHAR Options,
++ PCHAR SystemPath,
++ WORD VersionToBoot)
+{
- ULONG i;
++ /* 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)";
+
- LoaderBlock->ArcBootDeviceName = MmAllocateMemory(strlen(ArcBoot)+1);
++ 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 */
- /* Fill Arc HalDevice */
- LoaderBlock->ArcHalDeviceName = MmAllocateMemory(strlen(ArcHal)+1);
- strcpy(LoaderBlock->ArcHalDeviceName, ArcHal);
++ LoaderBlock->ArcBootDeviceName = MmHeapAlloc(strlen(ArcBoot)+1);
+ strcpy(LoaderBlock->ArcBootDeviceName, ArcBoot);
+ LoaderBlock->ArcBootDeviceName = PaToVa(LoaderBlock->ArcBootDeviceName);
+
- LoaderBlock->NtBootPathName = MmAllocateMemory(strlen(SystemRoot)+1);
++ /* 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->NtHalPathName = MmAllocateMemory(strlen(HalPath)+1);
++ LoaderBlock->NtBootPathName = MmHeapAlloc(strlen(SystemRoot)+1);
+ strcpy(LoaderBlock->NtBootPathName, SystemRoot);
+ LoaderBlock->NtBootPathName = PaToVa(LoaderBlock->NtBootPathName);
+
+ /* Fill NtHalPathName */
- LoaderBlock->LoadOptions = MmAllocateMemory(strlen(Options)+1);
++ LoaderBlock->NtHalPathName = MmHeapAlloc(strlen(HalPath)+1);
+ strcpy(LoaderBlock->NtHalPathName, HalPath);
+ LoaderBlock->NtHalPathName = PaToVa(LoaderBlock->NtHalPathName);
+
+ /* Fill load options */
- LoaderBlock->ArcDiskInformation = (PARC_DISK_INFORMATION)MmAllocateMemory(sizeof(ARC_DISK_INFORMATION));
++ LoaderBlock->LoadOptions = MmHeapAlloc(strlen(Options)+1);
+ strcpy(LoaderBlock->LoadOptions, Options);
+ LoaderBlock->LoadOptions = PaToVa(LoaderBlock->LoadOptions);
+
+ /* Arc devices */
- ArcDiskInfo = &BldrDiskInfo[i];
++ LoaderBlock->ArcDiskInformation = (PARC_DISK_INFORMATION)MmHeapAlloc(sizeof(ARC_DISK_INFORMATION));
+ InitializeListHead(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead);
+
+ /* Convert ARC disk information from freeldr to a correct format */
+ for (i = 0; i < reactos_disk_count; i++)
+ {
+ PARC_DISK_SIGNATURE ArcDiskInfo;
+
+ /* Get the ARC structure */
- strcpy(BldrArcNames[i], reactos_arc_disk_info[i].ArcName);
- ArcDiskInfo->ArcName = BldrArcNames[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 */
- /* Convert the list to virtual address */
++ 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);
+ }
+
- /* Create configuration entries */
- InitializeHWConfig(LoaderBlock);
++ /* Convert all list's to Virtual address */
++
++ /* Convert the ArcDisks list to virtual address */
+ List_PaToVa(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead);
+ LoaderBlock->ArcDiskInformation = PaToVa(LoaderBlock->ArcDiskInformation);
+
- //TODO: !!!
-
- /* Convert all list's to Virtual address */
++ /* Convert configuration entries to VA */
++ ConvertConfigToVA(LoaderBlock->ConfigurationRoot);
++ LoaderBlock->ConfigurationRoot = PaToVa(LoaderBlock->ConfigurationRoot);
+
+ /* Convert all DTE into virtual addresses */
- Extension = MmAllocateMemory(sizeof(LOADER_PARAMETER_EXTENSION));
+ 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->MajorVersion = 4;
- Extension->MinorVersion = 0;
++ Extension = MmHeapAlloc(sizeof(LOADER_PARAMETER_EXTENSION));
+ if (Extension == NULL)
+ {
+ UiMessageBox("Failed to allocate LPB Extension!");
+ return;
+ }
+ RtlZeroMemory(Extension, sizeof(LOADER_PARAMETER_EXTENSION));
+
++ /* Save size and version information */
+ Extension->Size = sizeof(LOADER_PARAMETER_EXTENSION);
- Pcr = (ULONG_PTR)MmAllocateMemory(2 * MM_PAGE_SIZE);
++ Extension->MajorVersion = (VersionToBoot & 0xFF00) >> 8;
++ Extension->MinorVersion = VersionToBoot & 0xFF;
+
+
+ LoaderBlock->Extension = PaToVa(Extension);
+}
+
+// Last step before going virtual
+void WinLdrSetupForNt(PLOADER_PARAMETER_BLOCK LoaderBlock,
+ PVOID *GdtIdt,
+ ULONG *PcrBasePage,
+ ULONG *TssBasePage)
+{
+ ULONG TssSize;
+ ULONG TssPages;
+ ULONG_PTR Pcr = 0;
+ ULONG_PTR Tss = 0;
+ ULONG BlockSize, NumPages;
+
+ LoaderBlock->u.I386.CommonDataArea = NULL;//CommonDataArea;
+ //LoaderBlock->u.I386.MachineType = MachineType; //FIXME: MachineType?
+
+ /* Allocate 2 pages for PCR */
- Tss = (ULONG_PTR)MmAllocateMemory(TssSize);
++ Pcr = (ULONG_PTR)MmAllocateMemoryWithType(2 * MM_PAGE_SIZE, LoaderStartupPcrPage);
+ *PcrBasePage = Pcr >> MM_PAGE_SHIFT;
+
+ if (Pcr == 0)
+ {
+ UiMessageBox("Can't allocate PCR\n");
+ return;
+ }
+
+ /* Allocate TSS */
+ TssSize = (sizeof(KTSS) + MM_PAGE_SIZE) & ~(MM_PAGE_SIZE - 1);
+ TssPages = TssSize / MM_PAGE_SIZE;
+
- *GdtIdt = (PKGDTENTRY)MmAllocateMemory(NumPages * MM_PAGE_SIZE);
++ 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;
- Status = WinLdrLoadImage(FullPath, &DriverBase);
++ *GdtIdt = (PKGDTENTRY)MmAllocateMemoryWithType(NumPages * MM_PAGE_SIZE, LoaderMemoryData);
+
+ if (*GdtIdt == NULL)
+ {
+ UiMessageBox("Can't allocate pages for GDT+IDT!\n");
+ return;
+ }
+
+ /* Zero newly prepared GDT+IDT */
+ RtlZeroMemory(*GdtIdt, NumPages << MM_PAGE_SHIFT);
+}
+
+BOOLEAN
+WinLdrLoadDeviceDriver(PLOADER_PARAMETER_BLOCK LoaderBlock,
+ LPSTR BootPath,
+ PUNICODE_STRING FilePath,
+ ULONG Flags,
+ PLDR_DATA_TABLE_ENTRY *DriverDTE)
+{
+ CHAR FullPath[1024];
+ CHAR DriverPath[1024];
+ CHAR DllName[1024];
+ PCHAR DriverNamePos;
+ BOOLEAN Status;
+ PVOID DriverBase;
+
+ // Separate the path to file name and directory path
+ sprintf(DriverPath, "%wZ", FilePath);
+ DriverNamePos = strrchr(DriverPath, '\\');
+ if (DriverNamePos != NULL)
+ {
+ // Copy the name
+ strcpy(DllName, DriverNamePos+1);
+
+ // Cut out the name from the path
+ *(DriverNamePos+1) = 0;
+ }
+
+ DbgPrint((DPRINT_WINDOWS, "DriverPath: %s, DllName: %s, LPB %p\n", DriverPath, DllName, LoaderBlock));
+
+
+ // Check if driver is already loaded
+ Status = WinLdrCheckForLoadedDll(LoaderBlock, DllName, DriverDTE);
+ if (Status)
+ {
+ // We've got the pointer to its DTE, just return success
+ return TRUE;
+ }
+
+ // It's not loaded, we have to load it
+ sprintf(FullPath,"%s%wZ", BootPath, FilePath);
- //DbgPrint((DPRINT_WINDOWS, "BootDriver %wZ DTE %08X RegPath: %wZ\n", &BootDriver->FilePath,
- // BootDriver->DataTableEntry, &BootDriver->RegistryPath));
++ Status = WinLdrLoadImage(FullPath, LoaderBootDriver, &DriverBase);
+ if (!Status)
+ return FALSE;
+
+ // Allocate a DTE for it
+ Status = WinLdrAllocateDataTableEntry(LoaderBlock, DllName, DllName, DriverBase, DriverDTE);
+ if (!Status)
+ {
+ DbgPrint((DPRINT_WINDOWS, "WinLdrAllocateDataTableEntry() failed\n"));
+ return FALSE;
+ }
+
+ // Modify any flags, if needed
+ (*DriverDTE)->Flags |= Flags;
+
+ // Look for any dependencies it may have, and load them too
+ sprintf(FullPath,"%s%s", BootPath, DriverPath);
+ Status = WinLdrScanImportDescriptorTable(LoaderBlock, FullPath, *DriverDTE);
+ if (!Status)
+ {
+ DbgPrint((DPRINT_WINDOWS, "WinLdrScanImportDescriptorTable() failed for %s\n",
+ FullPath));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+BOOLEAN
+WinLdrLoadBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock,
+ LPSTR BootPath)
+{
+ PLIST_ENTRY NextBd;
+ PBOOT_DRIVER_LIST_ENTRY BootDriver;
+ BOOLEAN Status;
+
+ // Walk through the boot drivers list
+ NextBd = LoaderBlock->BootDriverListHead.Flink;
+
+ while (NextBd != &LoaderBlock->BootDriverListHead)
+ {
+ BootDriver = CONTAINING_RECORD(NextBd, BOOT_DRIVER_LIST_ENTRY, ListEntry);
+
- CHAR SystemPath[1024], SearchPath[1024];
- CHAR FileName[1024];
- CHAR BootPath[256];
++ DbgPrint((DPRINT_WINDOWS, "BootDriver %wZ DTE %08X RegPath: %wZ\n", &BootDriver->FilePath,
++ BootDriver->DataTableEntry, &BootDriver->RegistryPath));
+
+ // Paths are relative (FIXME: Are they always relative?)
+
+ // Load it
+ Status = WinLdrLoadDeviceDriver(LoaderBlock, BootPath, &BootDriver->FilePath,
+ 0, &BootDriver->DataTableEntry);
+
+ // If loading failed - cry loudly
+ //FIXME: Maybe remove it from the list and try to continue?
+ if (!Status)
+ {
+ UiMessageBox("Can't load boot driver!");
+ 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;
+ }
+
+ return TRUE;
+}
+
+VOID
+LoadAndBootWindows(PCSTR OperatingSystemName, WORD OperatingSystemVersion)
+{
+ CHAR MsgBuffer[256];
- //FIXME: This is needed only for MachHwDetect() which performs registry operations!
- RegInitializeRegistry();
-
++ 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;
+ ULONG BootDevice;
+ PLOADER_PARAMETER_BLOCK LoaderBlock, LoaderBlockVA;
+ KERNEL_ENTRY_POINT KiSystemStartup;
+ PLDR_DATA_TABLE_ENTRY KernelDTE, HalDTE, KdComDTE = NULL;
+ // Mm-related things
+ PVOID GdtIdt;
+ ULONG PcrBasePage=0;
+ ULONG TssBasePage=0;
+
+ //sprintf(MsgBuffer,"Booting Microsoft(R) Windows(R) OS version '%04x' is not implemented yet", OperatingSystemVersion);
+ //UiMessageBox(MsgBuffer);
+
+ // Open the operating system section
+ // specified in the .ini file
+ if (!IniOpenSection(OperatingSystemName, &SectionId))
+ {
+ sprintf(MsgBuffer,"Operating System section '%s' not found in freeldr.ini", OperatingSystemName);
+ UiMessageBox(MsgBuffer);
+ return;
+ }
+
+ UiDrawBackdrop();
+ UiDrawStatusText("Detecting Hardware...");
+ UiDrawProgressBarCenter(1, 100, "Loading Windows...");
+
- if (!MachDiskNormalizeSystemPath(SystemPath,
- sizeof(SystemPath)))
+ /* Make sure the system path is set in the .ini file */
+ if (!IniReadSettingByName(SectionId, "SystemPath", SystemPath, sizeof(SystemPath)))
+ {
+ UiMessageBox("System path not specified for selected operating system.");
+ return;
+ }
+
- /* Detect hardware */
- MachHwDetect();
-
++ /* 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;
+ }
+
- // Allocate and minimalistic-initialize LPB
++ /* Let user know we started loading */
+ UiDrawStatusText("Loading...");
+
+ /* Try to open system drive */
+ BootDevice = 0xffffffff;
+ if (!FsOpenSystemVolume(SystemPath, BootPath, &BootDevice))
+ {
+ UiMessageBox("Failed to open boot drive.");
+ return;
+ }
+
+ /* append a backslash */
+ if ((strlen(BootPath)==0) ||
+ BootPath[strlen(BootPath)] != '\\')
+ strcat(BootPath, "\\");
+
+ DbgPrint((DPRINT_WINDOWS,"SystemRoot: '%s'\n", BootPath));
+
- // Load kernel
++ /* Allocate and minimalistic-initialize LPB */
+ AllocateAndInitLPB(&LoaderBlock);
+
- Status = WinLdrLoadImage(FileName, &NtosBase);
++ /* Detect hardware */
++#if WHEN_MERGE_COMPLETE
++ MachHwDetect(&LoaderBlock->ConfigurationRoot);
++#else
++ MachHwDetect();
++#endif
++
++ /* Load kernel */
+ strcpy(FileName, BootPath);
+ strcat(FileName, "SYSTEM32\\NTOSKRNL.EXE");
- // Load HAL
++ Status = WinLdrLoadImage(FileName, LoaderSystemCode, &NtosBase);
+ DbgPrint((DPRINT_WINDOWS, "Ntos loaded with status %d at %p\n", Status, NtosBase));
+
- Status = WinLdrLoadImage(FileName, &HalBase);
++ /* Load HAL */
+ strcpy(FileName, BootPath);
+ strcat(FileName, "SYSTEM32\\HAL.DLL");
- // Load kernel-debugger support dll
- if (OperatingSystemVersion > _WIN32_WINNT_NT4)
++ Status = WinLdrLoadImage(FileName, LoaderHalCode, &HalBase);
+ DbgPrint((DPRINT_WINDOWS, "HAL loaded with status %d at %p\n", Status, HalBase));
+
- Status = WinLdrLoadImage(FileName, &KdComBase);
++ /* Load kernel-debugger support dll */
++ if (OperatingSystemVersion > _WIN32_WINNT_WIN2K)
+ {
+ strcpy(FileName, BootPath);
+ strcat(FileName, "SYSTEM32\\KDCOM.DLL");
- // Allocate data table entries for above-loaded modules
++ Status = WinLdrLoadImage(FileName, LoaderBootDriver, &KdComBase);
+ DbgPrint((DPRINT_WINDOWS, "KdCom loaded with status %d at %p\n", Status, KdComBase));
+ }
+
- if (OperatingSystemVersion > _WIN32_WINNT_NT4)
++ /* 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);
- WinLdrInitializePhase1(LoaderBlock);
++ if (OperatingSystemVersion > _WIN32_WINNT_WIN2K)
+ {
+ WinLdrAllocateDataTableEntry(LoaderBlock, "kdcom.dll",
+ "WINNT\\SYSTEM32\\KDCOM.DLL", KdComBase, &KdComDTE);
+ }
+
+ /* Load all referenced DLLs for kernel, HAL and kdcom.dll */
+ strcpy(SearchPath, BootPath);
+ strcat(SearchPath, "SYSTEM32\\");
+ WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, KernelDTE);
+ WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, HalDTE);
+ if (KdComDTE)
+ WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, KdComDTE);
+
+ /* Load Hive, and then NLS data, OEM font, and prepare boot drivers list */
+ Status = WinLdrLoadAndScanSystemHive(LoaderBlock, BootPath);
+ DbgPrint((DPRINT_WINDOWS, "SYSTEM hive loaded and scanned with status %d\n", Status));
+
+ /* Load boot drivers */
+ Status = WinLdrLoadBootDrivers(LoaderBlock, BootPath);
+ DbgPrint((DPRINT_WINDOWS, "Boot drivers loaded with status %d\n", Status));
+
+ /* Initialize Phase 1 - no drivers loading anymore */
- /* Save entry-point pointer (VA) */
++ WinLdrInitializePhase1(LoaderBlock, BootOptions, SystemPath, OperatingSystemVersion);
+
+ /* Alloc PCR, TSS, do magic things with the GDT/IDT */
+ WinLdrSetupForNt(LoaderBlock, &GdtIdt, &PcrBasePage, &TssBasePage);
+
-
++ /* 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();
+
+ /* Turn on paging mode of CPU*/
+ WinLdrTurnOnPaging(LoaderBlock, PcrBasePage, TssBasePage, GdtIdt);
+
+ DbgPrint((DPRINT_WINDOWS, "Hello from paged mode, KiSystemStartup %p, LoaderBlockVA %p!\n",
+ KiSystemStartup, LoaderBlockVA));
+
+ WinLdrpDumpMemoryDescriptors(LoaderBlockVA);
+ WinLdrpDumpBootDriver(LoaderBlockVA);
+ WinLdrpDumpArcDisks(LoaderBlockVA);
+
+ //FIXME: If I substitute this debugging checkpoint, GCC will "optimize away" the code below
+ //while (1) {};
+ /*asm(".intel_syntax noprefix\n");
+ asm("test1:\n");
+ asm("jmp test1\n");
+ asm(".att_syntax\n");*/
+
-
++ /* Pass control */
+ (*KiSystemStartup)(LoaderBlockVA);
+
+ return;
+}
+
+VOID
+WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ PLIST_ENTRY NextMd;
+ PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor;
+
+ NextMd = LoaderBlock->MemoryDescriptorListHead.Flink;
+
+ while (NextMd != &LoaderBlock->MemoryDescriptorListHead)
+ {
+ MemoryDescriptor = CONTAINING_RECORD(NextMd, MEMORY_ALLOCATION_DESCRIPTOR, ListEntry);
+
+ DbgPrint((DPRINT_WINDOWS, "BP %08X PC %04X MT %d\n", MemoryDescriptor->BasePage,
+ MemoryDescriptor->PageCount, MemoryDescriptor->MemoryType));
+
+ NextMd = MemoryDescriptor->ListEntry.Flink;
+ }
+}
+
+VOID
+WinLdrpDumpBootDriver(PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ PLIST_ENTRY NextBd;
+ PBOOT_DRIVER_LIST_ENTRY BootDriver;
+
+ NextBd = LoaderBlock->BootDriverListHead.Flink;
+
+ while (NextBd != &LoaderBlock->BootDriverListHead)
+ {
+ 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));
+
+ NextBd = BootDriver->ListEntry.Flink;
+ }
+}
+
+VOID
+WinLdrpDumpArcDisks(PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+ PLIST_ENTRY NextBd;
+ PARC_DISK_SIGNATURE ArcDisk;
+
+ NextBd = LoaderBlock->ArcDiskInformation->DiskSignatureListHead.Flink;
+
+ while (NextBd != &LoaderBlock->ArcDiskInformation->DiskSignatureListHead)
+ {
+ ArcDisk = CONTAINING_RECORD(NextBd, ARC_DISK_SIGNATURE, ListEntry);
+
+ DbgPrint((DPRINT_WINDOWS, "ArcDisk %s checksum: 0x%X, signature: 0x%X\n",
+ ArcDisk->ArcName, ArcDisk->CheckSum, ArcDisk->Signature));
+
+ NextBd = ArcDisk->ListEntry.Flink;
+ }
+}
+