e4e27319a98073c52bbf5021146665badf744310
[reactos.git] / reactos / boot / freeldr / freeldr / windows / setupldr2.c
1 /*
2 * FreeLoader
3 *
4 * Copyright (C) 2009 Aleksey Bragin <aleksey@reactos.org>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include <freeldr.h>
22
23 #include <ndk/ldrtypes.h>
24 #include <arc/setupblk.h>
25
26 #include <debug.h>
27
28 // TODO: Move to .h
29 VOID AllocateAndInitLPB(PLOADER_PARAMETER_BLOCK *OutLoaderBlock);
30 BOOLEAN WinLdrLoadBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock, LPSTR BootPath);
31 void WinLdrSetupForNt(PLOADER_PARAMETER_BLOCK LoaderBlock,
32 PVOID *GdtIdt,
33 ULONG *PcrBasePage,
34 ULONG *TssBasePage);
35 VOID
36 WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
37 PCHAR Options,
38 PCHAR SystemPath,
39 PCHAR BootPath,
40 USHORT VersionToBoot);
41 BOOLEAN
42 WinLdrLoadNLSData(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
43 IN LPCSTR DirectoryPath,
44 IN LPCSTR AnsiFileName,
45 IN LPCSTR OemFileName,
46 IN LPCSTR LanguageFileName);
47 BOOLEAN
48 WinLdrAddDriverToList(LIST_ENTRY *BootDriverListHead,
49 LPWSTR RegistryPath,
50 LPWSTR ImagePath,
51 LPWSTR ServiceName);
52
53
54 //FIXME: Do a better way to retrieve Arc disk information
55 extern ULONG reactos_disk_count;
56 extern ARC_DISK_SIGNATURE reactos_arc_disk_info[];
57 extern char reactos_arc_strings[32][256];
58
59 extern BOOLEAN UseRealHeap;
60 extern ULONG LoaderPagesSpanned;
61
62
63 VOID
64 SetupLdrLoadNlsData(PLOADER_PARAMETER_BLOCK LoaderBlock, HINF InfHandle, LPCSTR SearchPath)
65 {
66 INFCONTEXT InfContext;
67 BOOLEAN Status;
68 LPCSTR AnsiName, OemName, LangName;
69
70 /* Get ANSI codepage file */
71 if (!InfFindFirstLine(InfHandle, "NLS", "AnsiCodepage", &InfContext))
72 {
73 printf("Failed to find 'NLS/AnsiCodepage'\n");
74 return;
75 }
76 if (!InfGetDataField(&InfContext, 1, &AnsiName))
77 {
78 printf("Failed to get load options\n");
79 return;
80 }
81
82 /* Get OEM codepage file */
83 if (!InfFindFirstLine(InfHandle, "NLS", "OemCodepage", &InfContext))
84 {
85 printf("Failed to find 'NLS/AnsiCodepage'\n");
86 return;
87 }
88 if (!InfGetDataField(&InfContext, 1, &OemName))
89 {
90 printf("Failed to get load options\n");
91 return;
92 }
93
94 if (!InfFindFirstLine(InfHandle, "NLS", "UnicodeCasetable", &InfContext))
95 {
96 printf("Failed to find 'NLS/AnsiCodepage'\n");
97 return;
98 }
99 if (!InfGetDataField(&InfContext, 1, &LangName))
100 {
101 printf("Failed to get load options\n");
102 return;
103 }
104
105 Status = WinLdrLoadNLSData(LoaderBlock, SearchPath, AnsiName, OemName, LangName);
106 DPRINTM(DPRINT_WINDOWS, "NLS data loaded with status %d\n", Status);
107 }
108
109 VOID
110 SetupLdrScanBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock, HINF InfHandle, LPCSTR SearchPath)
111 {
112 INFCONTEXT InfContext;
113 BOOLEAN Status;
114 LPCSTR Media, DriverName;
115 WCHAR ServiceName[256];
116 WCHAR ImagePath[256];
117
118 /* Open inf section */
119 if (!InfFindFirstLine(InfHandle, "SourceDisksFiles", NULL, &InfContext))
120 return;
121
122 /* Load all listed boot drivers */
123 do
124 {
125 if (InfGetDataField(&InfContext, 7, &Media) &&
126 InfGetDataField(&InfContext, 0, &DriverName))
127 {
128 if (strcmp(Media, "x") == 0)
129 {
130 /* Convert name to widechar */
131 swprintf(ServiceName, L"%S", DriverName);
132
133 /* Remove .sys extension */
134 ServiceName[wcslen(ServiceName) - 4] = 0;
135
136 /* Prepare image path */
137 swprintf(ImagePath, L"%S", DriverName);
138
139 /* Add it to the list */
140 Status = WinLdrAddDriverToList(&LoaderBlock->BootDriverListHead,
141 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\",
142 ImagePath,
143 ServiceName);
144
145 if (!Status)
146 {
147 DPRINTM(DPRINT_WINDOWS, "could not add boot driver %s, %s\n", SearchPath, DriverName);
148 return;
149 }
150 }
151 }
152 } while (InfFindNextLine(&InfContext, &InfContext));
153 }
154
155 VOID LoadReactOSSetup2(VOID)
156 {
157 CHAR SystemPath[512], SearchPath[512];
158 CHAR FileName[512];
159 CHAR BootPath[512];
160 LPCSTR BootOptions;
161 PVOID NtosBase = NULL, HalBase = NULL, KdComBase = NULL;
162 BOOLEAN Status;
163 ULONG i, ErrorLine;
164 HINF InfHandle;
165 INFCONTEXT InfContext;
166 PLOADER_PARAMETER_BLOCK LoaderBlock, LoaderBlockVA;
167 PSETUP_LOADER_BLOCK SetupBlock;
168 KERNEL_ENTRY_POINT KiSystemStartup;
169 PLDR_DATA_TABLE_ENTRY KernelDTE, HalDTE, KdComDTE = NULL;
170 // Mm-related things
171 PVOID GdtIdt;
172 ULONG PcrBasePage=0;
173 ULONG TssBasePage=0;
174 LPCSTR SourcePath;
175 LPCSTR SourcePaths[] =
176 {
177 "", /* Only for floppy boot */
178 #if defined(_M_IX86)
179 "\\I386",
180 #elif defined(_M_MPPC)
181 "\\PPC",
182 #elif defined(_M_MRX000)
183 "\\MIPS",
184 #endif
185 "\\reactos",
186 NULL
187 };
188
189 /* Open 'txtsetup.sif' from any of source paths */
190 MachDiskGetBootPath(SystemPath, sizeof(SystemPath));
191 for (i = MachDiskBootingFromFloppy() ? 0 : 1; ; i++)
192 {
193 SourcePath = SourcePaths[i];
194 if (!SourcePath)
195 {
196 printf("Failed to open 'txtsetup.sif'\n");
197 return;
198 }
199 sprintf(FileName, "%s\\txtsetup.sif", SourcePath);
200 if (InfOpenFile (&InfHandle, FileName, &ErrorLine))
201 {
202 sprintf(BootPath, "%s%s\\", SystemPath, SourcePath);
203 break;
204 }
205 }
206
207 /* Load options */
208 if (!InfFindFirstLine(InfHandle,
209 "SetupData",
210 "OsLoadOptions",
211 &InfContext))
212 {
213 printf("Failed to find 'SetupData/OsLoadOptions'\n");
214 return;
215 }
216
217 if (!InfGetDataField (&InfContext, 1, &BootOptions))
218 {
219 printf("Failed to get load options\n");
220 return;
221 }
222
223 SetupUiInitialize();
224 UiDrawStatusText("");
225 UiDrawStatusText("Detecting Hardware...");
226
227 /* Let user know we started loading */
228 UiDrawStatusText("Loading...");
229
230 /* Construct the system path */
231 sprintf(SystemPath, "%s\\", SourcePath);
232
233 DPRINTM(DPRINT_WINDOWS,"BootPath: '%s', SystemPath: '%s'\n", BootPath, SystemPath);
234
235 /* Allocate and minimalistic-initialize LPB */
236 AllocateAndInitLPB(&LoaderBlock);
237
238 /* Allocate and initialize setup loader block */
239 SetupBlock = MmHeapAlloc(sizeof(SETUP_LOADER_BLOCK));
240 RtlZeroMemory(SetupBlock, sizeof(SETUP_LOADER_BLOCK));
241 LoaderBlock->SetupLdrBlock = SetupBlock;
242
243 /* Set textmode setup flag */
244 SetupBlock->Flags = SETUPLDR_TEXT_MODE;
245
246 /* Detect hardware */
247 UseRealHeap = TRUE;
248 LoaderBlock->ConfigurationRoot = MachHwDetect();
249
250 /* Load kernel */
251 strcpy(FileName, BootPath);
252 strcat(FileName, "NTOSKRNL.EXE");
253 Status = WinLdrLoadImage(FileName, LoaderSystemCode, &NtosBase);
254 DPRINTM(DPRINT_WINDOWS, "Ntos loaded with status %d at %p\n", Status, NtosBase);
255
256 /* Load HAL */
257 strcpy(FileName, BootPath);
258 strcat(FileName, "HAL.DLL");
259 Status = WinLdrLoadImage(FileName, LoaderHalCode, &HalBase);
260 DPRINTM(DPRINT_WINDOWS, "HAL loaded with status %d at %p\n", Status, HalBase);
261
262 /* Load kernel-debugger support dll */
263 strcpy(FileName, BootPath);
264 strcat(FileName, "KDCOM.DLL");
265 Status = WinLdrLoadImage(FileName, LoaderBootDriver, &KdComBase);
266 DPRINTM(DPRINT_WINDOWS, "KdCom loaded with status %d at %p\n", Status, KdComBase);
267
268 /* Allocate data table entries for above-loaded modules */
269 WinLdrAllocateDataTableEntry(LoaderBlock, "ntoskrnl.exe",
270 "NTOSKRNL.EXE", NtosBase, &KernelDTE);
271 WinLdrAllocateDataTableEntry(LoaderBlock, "hal.dll",
272 "HAL.DLL", HalBase, &HalDTE);
273 WinLdrAllocateDataTableEntry(LoaderBlock, "kdcom.dll",
274 "KDCOM.DLL", KdComBase, &KdComDTE);
275
276 /* Load all referenced DLLs for kernel, HAL and kdcom.dll */
277 strcpy(SearchPath, BootPath);
278 WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, KernelDTE);
279 WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, HalDTE);
280 if (KdComDTE)
281 WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, KdComDTE);
282
283 /* Load NLS data */
284 SetupLdrLoadNlsData(LoaderBlock, InfHandle, BootPath);
285
286 /* Get a list of boot drivers */
287 SetupLdrScanBootDrivers(LoaderBlock, InfHandle, BootPath);
288
289 /* Load boot drivers */
290 Status = WinLdrLoadBootDrivers(LoaderBlock, BootPath);
291 DPRINTM(DPRINT_WINDOWS, "Boot drivers loaded with status %d\n", Status);
292
293 /* Alloc PCR, TSS, do magic things with the GDT/IDT */
294 WinLdrSetupForNt(LoaderBlock, &GdtIdt, &PcrBasePage, &TssBasePage);
295
296 /* Initialize Phase 1 - no drivers loading anymore */
297 WinLdrInitializePhase1(LoaderBlock, (PCHAR)BootOptions, SystemPath, BootPath, _WIN32_WINNT_WS03);
298
299 /* Save entry-point pointer and Loader block VAs */
300 KiSystemStartup = (KERNEL_ENTRY_POINT)KernelDTE->EntryPoint;
301 LoaderBlockVA = PaToVa(LoaderBlock);
302
303 /* "Stop all motors", change videomode */
304 MachPrepareForReactOS(TRUE);
305
306 /* Debugging... */
307 //DumpMemoryAllocMap();
308
309 /* Turn on paging mode of CPU*/
310 WinLdrTurnOnPaging(LoaderBlock, PcrBasePage, TssBasePage, GdtIdt);
311
312 /* Save final value of LoaderPagesSpanned */
313 LoaderBlock->Extension->LoaderPagesSpanned = LoaderPagesSpanned;
314
315 DPRINTM(DPRINT_WINDOWS, "Hello from paged mode, KiSystemStartup %p, LoaderBlockVA %p!\n",
316 KiSystemStartup, LoaderBlockVA);
317
318 //WinLdrpDumpMemoryDescriptors(LoaderBlockVA);
319 //WinLdrpDumpBootDriver(LoaderBlockVA);
320 //WinLdrpDumpArcDisks(LoaderBlockVA);
321
322 /*asm(".intel_syntax noprefix\n");
323 asm("test1:\n");
324 asm("jmp test1\n");
325 asm(".att_syntax\n");*/
326
327 /* Pass control */
328 (*KiSystemStartup)(LoaderBlockVA);
329
330 return;
331 }