- Implement loading of NLS data, SYSTEM hive data (just simple loading into memory...
[reactos.git] / reactos / boot / freeldr / freeldr / windows / winldr.c
index 45c86f4..89dae9c 100644 (file)
 VOID DumpMemoryAllocMap(VOID);\r
 VOID WinLdrpDumpMemoryDescriptors(PLOADER_PARAMETER_BLOCK LoaderBlock);\r
 \r
+BOOLEAN\r
+WinLdrLoadNLSData(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,\r
+                  IN LPCSTR DirectoryPath,\r
+                  IN LPCSTR AnsiFileName,\r
+                  IN LPCSTR OemFileName,\r
+                  IN LPCSTR LanguageFileName)\r
+{\r
+       CHAR FileName[255];\r
+       PFILE AnsiFileHandle;\r
+       PFILE OemFileHandle;\r
+       PFILE LanguageFileHandle;\r
+       ULONG AnsiFileSize, OemFileSize, LanguageFileSize;\r
+       ULONG TotalSize;\r
+       ULONG_PTR NlsDataBase;\r
+       PVOID NlsVirtual;\r
+       BOOLEAN Status, AnsiEqualsOem = FALSE;\r
+\r
+       /* There may be a case, when OEM and ANSI page coincide */\r
+       if (!strcmp(AnsiFileName, OemFileName))\r
+               AnsiEqualsOem = TRUE;\r
+\r
+       /* Open file with ANSI and store its size */\r
+       //Print(L"Loading %s...\n", Filename);\r
+       strcpy(FileName, DirectoryPath);\r
+       strcat(FileName, AnsiFileName);\r
+       AnsiFileHandle = FsOpenFile(FileName);\r
+\r
+       if (AnsiFileHandle == NULL)\r
+               goto Failure;\r
+\r
+       AnsiFileSize = FsGetFileSize(AnsiFileHandle);\r
+       DbgPrint((DPRINT_WINDOWS, "AnsiFileSize: %d\n", AnsiFileSize));\r
+       FsCloseFile(AnsiFileHandle);\r
+\r
+       /* Open OEM file and store its length */\r
+       if (AnsiEqualsOem)\r
+       {\r
+               OemFileSize = 0;\r
+       }\r
+       else\r
+       {\r
+               //Print(L"Loading %s...\n", Filename);\r
+               strcpy(FileName, DirectoryPath);\r
+               strcat(FileName, OemFileName);\r
+               OemFileHandle = FsOpenFile(FileName);\r
+\r
+               if (OemFileHandle == NULL)\r
+                       goto Failure;\r
+\r
+               OemFileSize = FsGetFileSize(OemFileHandle);\r
+               FsCloseFile(OemFileHandle);\r
+       }\r
+       DbgPrint((DPRINT_WINDOWS, "OemFileSize: %d\n", OemFileSize));\r
+\r
+       /* And finally open the language codepage file and store its length */\r
+       //Print(L"Loading %s...\n", Filename);\r
+       strcpy(FileName, DirectoryPath);\r
+       strcat(FileName, LanguageFileName);\r
+       LanguageFileHandle = FsOpenFile(FileName);\r
+\r
+       if (LanguageFileHandle == NULL)\r
+               goto Failure;\r
+\r
+       LanguageFileSize = FsGetFileSize(LanguageFileHandle);\r
+       FsCloseFile(LanguageFileHandle);\r
+       DbgPrint((DPRINT_WINDOWS, "LanguageFileSize: %d\n", LanguageFileSize));\r
+\r
+       /* Sum up all three length, having in mind that every one of them\r
+          must start at a page boundary => thus round up each file to a page */\r
+       TotalSize = MM_SIZE_TO_PAGES(AnsiFileSize) +\r
+               MM_SIZE_TO_PAGES(OemFileSize)  +\r
+               MM_SIZE_TO_PAGES(LanguageFileSize);\r
+\r
+       NlsDataBase = (ULONG_PTR)MmAllocateMemory(TotalSize*MM_PAGE_SIZE);\r
+\r
+       if (NlsDataBase == 0)\r
+               goto Failure;\r
+\r
+       NlsVirtual = (PVOID)(KSEG0_BASE | NlsDataBase);\r
+       LoaderBlock->NlsData->AnsiCodePageData = NlsVirtual;\r
+       LoaderBlock->NlsData->OemCodePageData = (PVOID)((PUCHAR)NlsVirtual +\r
+               (MM_SIZE_TO_PAGES(AnsiFileSize) << MM_PAGE_SHIFT));\r
+       LoaderBlock->NlsData->UnicodeCodePageData = (PVOID)((PUCHAR)NlsVirtual +\r
+               (MM_SIZE_TO_PAGES(AnsiFileSize) << MM_PAGE_SHIFT) +\r
+               (MM_SIZE_TO_PAGES(OemFileSize) << MM_PAGE_SHIFT));\r
+\r
+       /* Ansi and OEM data are the same - just set pointers to the same area */\r
+       if (AnsiEqualsOem)\r
+               LoaderBlock->NlsData->OemCodePageData = LoaderBlock->NlsData->AnsiCodePageData;\r
+\r
+\r
+       /* Now actually read the data into memory, starting with Ansi file */\r
+       strcpy(FileName, DirectoryPath);\r
+       strcat(FileName, AnsiFileName);\r
+       AnsiFileHandle = FsOpenFile(FileName);\r
+\r
+       if (AnsiFileHandle == NULL)\r
+               goto Failure;\r
+\r
+       Status = FsReadFile(AnsiFileHandle, AnsiFileSize, NULL, VaToPa(LoaderBlock->NlsData->AnsiCodePageData));\r
+\r
+       if (!Status)\r
+               goto Failure;\r
+\r
+       FsCloseFile(AnsiFileHandle);\r
+\r
+       /* OEM now, if it doesn't equal Ansi of course */\r
+       if (!AnsiEqualsOem)\r
+       {\r
+               strcpy(FileName, DirectoryPath);\r
+               strcat(FileName, OemFileName);\r
+               OemFileHandle = FsOpenFile(FileName);\r
+\r
+               if (OemFileHandle == NULL)\r
+                       goto Failure;\r
+\r
+               Status = FsReadFile(OemFileHandle, OemFileSize, NULL, VaToPa(LoaderBlock->NlsData->OemCodePageData));\r
+\r
+               if (!Status)\r
+                       goto Failure;\r
+\r
+               FsCloseFile(AnsiFileHandle);\r
+       }\r
+\r
+       /* finally the language file */\r
+       strcpy(FileName, DirectoryPath);\r
+       strcat(FileName, LanguageFileName);\r
+       LanguageFileHandle = FsOpenFile(FileName);\r
+\r
+       if (LanguageFileHandle == NULL)\r
+               goto Failure;\r
+\r
+       Status = FsReadFile(LanguageFileHandle, LanguageFileSize, NULL, VaToPa(LoaderBlock->NlsData->UnicodeCodePageData));\r
+\r
+       if (!Status)\r
+               goto Failure;\r
+\r
+       FsCloseFile(LanguageFileHandle);\r
+\r
+       //\r
+       // THIS IS HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACK\r
+       // Should go to WinLdrLoadOemHalFont(), when it will be implemented\r
+       //\r
+       LoaderBlock->OemFontFile = VaToPa(LoaderBlock->NlsData->UnicodeCodePageData);\r
+\r
+       /* Convert NlsTables address to VA */\r
+       LoaderBlock->NlsData = PaToVa(LoaderBlock->NlsData);\r
+\r
+       return TRUE;\r
+\r
+Failure:\r
+       //UiMessageBox("Error reading NLS file %s\n", Filename);\r
+       UiMessageBox("Error reading NLS file!");\r
+       return FALSE;\r
+}\r
+\r
+BOOLEAN\r
+WinLdrLoadSystemHive(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,\r
+                     IN LPCSTR DirectoryPath,\r
+                     IN LPCSTR HiveName)\r
+{\r
+       PFILE FileHandle;\r
+       CHAR FullHiveName[256];\r
+       BOOLEAN Status;\r
+       ULONG HiveFileSize;\r
+       ULONG_PTR HiveDataPhysical;\r
+       PVOID HiveDataVirtual;\r
+\r
+       /* Concatenate path and filename to get the full name */\r
+       strcpy(FullHiveName, DirectoryPath);\r
+       strcat(FullHiveName, HiveName);\r
+       //Print(L"Loading %s...\n", FullHiveName);\r
+       FileHandle = FsOpenFile(FullHiveName);\r
+\r
+       if (FileHandle == NULL)\r
+       {\r
+               UiMessageBox("Opening hive file failed!");\r
+               return FALSE;\r
+       }\r
+\r
+       /* Get the file length */\r
+       HiveFileSize = FsGetFileSize(FileHandle);\r
+\r
+       if (HiveFileSize == 0)\r
+       {\r
+               FsCloseFile(FileHandle);\r
+               UiMessageBox("Hive file has 0 size!");\r
+               return FALSE;\r
+       }\r
+\r
+       /* Round up the size to page boundary and alloc memory */\r
+       HiveDataPhysical = (ULONG_PTR)MmAllocateMemory(\r
+               MM_SIZE_TO_PAGES(HiveFileSize + MM_PAGE_SIZE - 1) << MM_PAGE_SHIFT);\r
+\r
+       if (HiveDataPhysical == 0)\r
+       {\r
+               FsCloseFile(FileHandle);\r
+               UiMessageBox("Unable to alloc memory for a hive!");\r
+               return FALSE;\r
+       }\r
+\r
+       /* Convert address to virtual */\r
+       HiveDataVirtual = (PVOID)(KSEG0_BASE | HiveDataPhysical);\r
+\r
+       /* Fill LoaderBlock's entries */\r
+       LoaderBlock->RegistryLength = HiveFileSize;\r
+       LoaderBlock->RegistryBase = HiveDataVirtual;\r
+\r
+       /* Finally read from file to the memory */\r
+       Status = FsReadFile(FileHandle, HiveFileSize, NULL, (PVOID)HiveDataPhysical);\r
+       FsCloseFile(FileHandle);\r
+       if (!Status)\r
+       {\r
+               UiMessageBox("Unable to read from hive file!");\r
+               return FALSE;\r
+       }\r
+\r
+       return TRUE;\r
+}\r
+\r
+void InitializeHWConfig(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock)\r
+{\r
+       PCONFIGURATION_COMPONENT_DATA ConfigurationRoot;\r
+       PCONFIGURATION_COMPONENT Component;\r
+       PCONFIGURATION_COMPONENT_DATA /*CurrentEntry,*/ PreviousEntry, AdapterEntry;\r
+       BOOLEAN IsNextEntryChild;\r
+\r
+       DbgPrint((DPRINT_WINDOWS, "InitializeHWConfig()\n"));\r
+\r
+       LoaderBlock->ConfigurationRoot = MmAllocateMemory(sizeof(CONFIGURATION_COMPONENT_DATA));\r
+       RtlZeroMemory(LoaderBlock->ConfigurationRoot, sizeof(CONFIGURATION_COMPONENT_DATA));\r
+\r
+       /* Fill root == SystemClass */\r
+       ConfigurationRoot = LoaderBlock->ConfigurationRoot;\r
+       Component = &LoaderBlock->ConfigurationRoot->ComponentEntry;\r
+\r
+       Component->Class = SystemClass;\r
+       Component->Type = MaximumType;\r
+       Component->Version = 0; // FIXME: ?\r
+       Component->Key = 0;\r
+       Component->AffinityMask = 0;\r
+\r
+       IsNextEntryChild = TRUE;\r
+       PreviousEntry = ConfigurationRoot;\r
+\r
+       /* Enumerate all PCI buses */\r
+       AdapterEntry = ConfigurationRoot;\r
+\r
+       /* TODO: Disk Geometry */\r
+       /* TODO: Keyboard */\r
+\r
+       /* TODO: Serial port */\r
+\r
+       //Config->ConfigurationData = alloc(sizeof(CONFIGURATION_COMPONENT_DATA), EfiLoaderData);\r
+\r
+       /* Convert everything to VA */\r
+       ConvertConfigToVA(LoaderBlock->ConfigurationRoot);\r
+       LoaderBlock->ConfigurationRoot = PaToVa(LoaderBlock->ConfigurationRoot);\r
+}\r
+\r
+\r
+// Init "phase 0"\r
+VOID\r
+AllocateAndInitLPB(PLOADER_PARAMETER_BLOCK *OutLoaderBlock)\r
+{\r
+       PLOADER_PARAMETER_BLOCK LoaderBlock;\r
+\r
+       /* Allocate and zero-init the LPB */\r
+       LoaderBlock = MmAllocateMemory(sizeof(LOADER_PARAMETER_BLOCK));\r
+       RtlZeroMemory(LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));\r
+\r
+       /* Init three critical lists, used right away */\r
+       InitializeListHead(&LoaderBlock->LoadOrderListHead);\r
+       InitializeListHead(&LoaderBlock->MemoryDescriptorListHead);\r
+       InitializeListHead(&LoaderBlock->BootDriverListHead);\r
+\r
+\r
+       *OutLoaderBlock = LoaderBlock;\r
+}\r
+\r
+// Init "phase 1"\r
+VOID\r
+WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock)\r
+{\r
+       //CHAR  Options[] = "/DEBUG /DEBUGPORT=COM1 /BAUDRATE=115200";\r
+       CHAR    Options[] = "/NODEBUG";\r
+       CHAR    SystemRoot[] = "\\WINNT";\r
+       CHAR    HalPath[] = "\\";\r
+       CHAR    ArcBoot[] = "multi(0)";\r
+       CHAR    ArcHal[] = "multi(0)";\r
+\r
+       PLOADER_PARAMETER_EXTENSION Extension;\r
+\r
+       LoaderBlock->u.I386.CommonDataArea = NULL; // Force No ABIOS support\r
+       \r
+       /* Fill Arc BootDevice */\r
+       LoaderBlock->ArcBootDeviceName = MmAllocateMemory(strlen(ArcBoot)+1);\r
+       strcpy(LoaderBlock->ArcBootDeviceName, ArcBoot);\r
+       LoaderBlock->ArcBootDeviceName = PaToVa(LoaderBlock->ArcBootDeviceName);\r
+\r
+       /* Fill Arc HalDevice */\r
+       LoaderBlock->ArcHalDeviceName = MmAllocateMemory(strlen(ArcHal)+1);\r
+       strcpy(LoaderBlock->ArcHalDeviceName, ArcHal);\r
+       LoaderBlock->ArcHalDeviceName = PaToVa(LoaderBlock->ArcHalDeviceName);\r
+\r
+       /* Fill SystemRoot */\r
+       LoaderBlock->NtBootPathName = MmAllocateMemory(strlen(SystemRoot)+1);\r
+       strcpy(LoaderBlock->NtBootPathName, SystemRoot);\r
+       LoaderBlock->NtBootPathName = PaToVa(LoaderBlock->NtBootPathName);\r
+\r
+       /* Fill NtHalPathName */\r
+       LoaderBlock->NtHalPathName = MmAllocateMemory(strlen(HalPath)+1);\r
+       strcpy(LoaderBlock->NtHalPathName, HalPath);\r
+       LoaderBlock->NtHalPathName = PaToVa(LoaderBlock->NtHalPathName);\r
+\r
+       /* Fill load options */\r
+       LoaderBlock->LoadOptions = MmAllocateMemory(strlen(Options)+1);\r
+       strcpy(LoaderBlock->LoadOptions, Options);\r
+       LoaderBlock->LoadOptions = PaToVa(LoaderBlock->LoadOptions);\r
+\r
+       /* Arc devices */\r
+       LoaderBlock->ArcDiskInformation = (PARC_DISK_INFORMATION)MmAllocateMemory(sizeof(ARC_DISK_INFORMATION));\r
+       InitializeListHead(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead);\r
+       List_PaToVa(&LoaderBlock->ArcDiskInformation->DiskSignatureListHead);\r
+       LoaderBlock->ArcDiskInformation = PaToVa(LoaderBlock->ArcDiskInformation);\r
+\r
+       /* Alloc space for NLS (it will be converted to VA in WinLdrLoadNLS) */\r
+       LoaderBlock->NlsData = MmAllocateMemory(sizeof(NLS_DATA_BLOCK));\r
+       if (LoaderBlock->NlsData == NULL)\r
+       {\r
+               UiMessageBox("Failed to allocate memory for NLS table data!");\r
+               return;\r
+       }\r
+       RtlZeroMemory(LoaderBlock->NlsData, sizeof(NLS_DATA_BLOCK));\r
+\r
+       /* Create configuration entries */\r
+       InitializeHWConfig(LoaderBlock);\r
+\r
+       /* Convert all DTE into virtual addresses */\r
+       //TODO: !!!\r
+\r
+       /* Convert all list's to Virtual address */\r
+       List_PaToVa(&LoaderBlock->LoadOrderListHead);\r
+\r
+       /* this one will be converted right before switching to\r
+          virtual paging mode */\r
+       //List_PaToVa(&LoaderBlock->MemoryDescriptorListHead);\r
+\r
+       List_PaToVa(&LoaderBlock->BootDriverListHead);\r
+\r
+       /* Initialize Extension now */\r
+       Extension = MmAllocateMemory(sizeof(LOADER_PARAMETER_EXTENSION));\r
+       if (Extension == NULL)\r
+       {\r
+               UiMessageBox("Failed to allocate LPB Extension!");\r
+               return;\r
+       }\r
+       RtlZeroMemory(Extension, sizeof(LOADER_PARAMETER_EXTENSION));\r
+\r
+       Extension->Size = sizeof(LOADER_PARAMETER_EXTENSION);\r
+       Extension->MajorVersion = 4;\r
+       Extension->MinorVersion = 0;\r
+\r
+\r
+       LoaderBlock->Extension = PaToVa(Extension);\r
+}\r
+\r
+// Last step before going virtual\r
+void WinLdrSetupForNt(PLOADER_PARAMETER_BLOCK LoaderBlock,\r
+                      PVOID *GdtIdt,\r
+                      ULONG *PcrBasePage,\r
+                      ULONG *TssBasePage)\r
+{\r
+       ULONG TssSize;\r
+       ULONG TssPages;\r
+       ULONG_PTR Pcr = 0;\r
+       ULONG_PTR Tss = 0;\r
+       ULONG BlockSize, NumPages;\r
+\r
+       LoaderBlock->u.I386.CommonDataArea = NULL;//CommonDataArea;\r
+       //LoaderBlock->u.I386.MachineType = MachineType; //FIXME: MachineType?\r
+\r
+       /* Allocate 2 pages for PCR */\r
+       Pcr = (ULONG_PTR)MmAllocateMemory(2 * MM_PAGE_SIZE);\r
+       *PcrBasePage = Pcr >> MM_PAGE_SHIFT;\r
+\r
+       if (Pcr == 0)\r
+       {\r
+               UiMessageBox("Can't allocate PCR\n");\r
+               return;\r
+       }\r
+\r
+       /* Allocate TSS */\r
+       TssSize = (sizeof(KTSS) + MM_PAGE_SIZE) & ~(MM_PAGE_SIZE - 1);\r
+       TssPages = TssSize / MM_PAGE_SIZE;\r
+\r
+       Tss = (ULONG_PTR)MmAllocateMemory(TssSize);\r
+\r
+       *TssBasePage = Tss >> MM_PAGE_SHIFT;\r
+\r
+       /* Allocate space for new GDT + IDT */\r
+       BlockSize = NUM_GDT*sizeof(KGDTENTRY) + NUM_IDT*sizeof(KIDTENTRY);//FIXME: Use GDT/IDT limits here?\r
+       NumPages = (BlockSize + MM_PAGE_SIZE - 1) >> MM_PAGE_SHIFT;\r
+       *GdtIdt = (PKGDTENTRY)MmAllocateMemory(NumPages * MM_PAGE_SIZE);\r
+\r
+       if (*GdtIdt == NULL)\r
+       {\r
+               UiMessageBox("Can't allocate pages for GDT+IDT!\n");\r
+               return;\r
+       }\r
+\r
+       /* Zero newly prepared GDT+IDT */\r
+       RtlZeroMemory(*GdtIdt, NumPages << MM_PAGE_SHIFT);\r
+}\r
+\r
+\r
 VOID\r
 LoadAndBootWindows(PCSTR OperatingSystemName, WORD OperatingSystemVersion)\r
 {\r
@@ -96,7 +512,7 @@ LoadAndBootWindows(PCSTR OperatingSystemName, WORD OperatingSystemVersion)
        DbgPrint((DPRINT_WINDOWS,"SystemRoot: '%s'\n", BootPath));\r
 \r
        /* Allocate and minimalistic-initialize LPB */\r
-       //AllocateAndInitLPB(&LoaderBlock);\r
+       AllocateAndInitLPB(&LoaderBlock);\r
 \r
        // Load kernel\r
        strcpy(FileName, BootPath);\r
@@ -122,19 +538,19 @@ LoadAndBootWindows(PCSTR OperatingSystemName, WORD OperatingSystemVersion)
        WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, HalDTE);\r
 \r
        /* Initialize Phase 1 - before NLS */\r
-       //WinLdrInitializePhase1(LoaderBlock);\r
+       WinLdrInitializePhase1(LoaderBlock);\r
 \r
        /* Load SYSTEM hive and its LOG file */\r
        strcpy(SearchPath, BootPath);\r
        strcat(SearchPath, "SYSTEM32\\CONFIG\\");\r
-       //Status = WinLdrLoadSystemHive(LoaderBlock, SearchPath, "SYSTEM");\r
+       Status = WinLdrLoadSystemHive(LoaderBlock, SearchPath, "SYSTEM");\r
        DbgPrint((DPRINT_WINDOWS, "SYSTEM hive loaded with status %d\n", Status));\r
 \r
        /* Load NLS data */\r
        strcpy(SearchPath, BootPath);\r
        strcat(SearchPath, "SYSTEM32\\");\r
-       //Status = WinLdrLoadNLSData(LoaderBlock, SearchPath,\r
-       //      "c_1252.nls", "c_437.nls", "l_intl.nls");\r
+       Status = WinLdrLoadNLSData(LoaderBlock, SearchPath,\r
+               "c_1252.nls", "c_437.nls", "l_intl.nls");\r
        DbgPrint((DPRINT_WINDOWS, "NLS data loaded with status %d\n", Status));\r
 \r
        /* Load OEM HAL font */\r
@@ -142,7 +558,7 @@ LoadAndBootWindows(PCSTR OperatingSystemName, WORD OperatingSystemVersion)
        /* Load boot drivers */\r
 \r
        /* Alloc PCR, TSS, do magic things with the GDT/IDT */\r
-       //WinLdrSetupForNt(LoaderBlock, &GdtIdt, &PcrBasePage, &TssBasePage);\r
+       WinLdrSetupForNt(LoaderBlock, &GdtIdt, &PcrBasePage, &TssBasePage);\r
 \r
        /* Save entry-point pointer (VA) */\r
        KiSystemStartup = (KERNEL_ENTRY_POINT)KernelDTE->EntryPoint;\r