[winldr]
[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 LoadOptions, BootOptions;
161 #if DBG
162 LPCSTR DbgOptions;
163 #endif
164 PVOID NtosBase = NULL, HalBase = NULL, KdComBase = NULL;
165 BOOLEAN Status;
166 ULONG i, ErrorLine;
167 HINF InfHandle;
168 INFCONTEXT InfContext;
169 PLOADER_PARAMETER_BLOCK LoaderBlock, LoaderBlockVA;
170 PSETUP_LOADER_BLOCK SetupBlock;
171 KERNEL_ENTRY_POINT KiSystemStartup;
172 PLDR_DATA_TABLE_ENTRY KernelDTE, HalDTE, KdComDTE = NULL;
173 // Mm-related things
174 PVOID GdtIdt;
175 ULONG PcrBasePage=0;
176 ULONG TssBasePage=0;
177 LPCSTR SourcePath;
178 LPCSTR SourcePaths[] =
179 {
180 "", /* Only for floppy boot */
181 #if defined(_M_IX86)
182 "\\I386",
183 #elif defined(_M_MPPC)
184 "\\PPC",
185 #elif defined(_M_MRX000)
186 "\\MIPS",
187 #endif
188 "\\reactos",
189 NULL
190 };
191
192 /* Open 'txtsetup.sif' from any of source paths */
193 MachDiskGetBootPath(SystemPath, sizeof(SystemPath));
194 for (i = MachDiskBootingFromFloppy() ? 0 : 1; ; i++)
195 {
196 SourcePath = SourcePaths[i];
197 if (!SourcePath)
198 {
199 printf("Failed to open 'txtsetup.sif'\n");
200 return;
201 }
202 sprintf(FileName, "%s\\txtsetup.sif", SourcePath);
203 if (InfOpenFile (&InfHandle, FileName, &ErrorLine))
204 {
205 sprintf(BootPath, "%s%s\\", SystemPath, SourcePath);
206 break;
207 }
208 }
209
210 /* Get Load options - debug and non-debug */
211 if (!InfFindFirstLine(InfHandle,
212 "SetupData",
213 "OsLoadOptions",
214 &InfContext))
215 {
216 printf("Failed to find 'SetupData/OsLoadOptions'\n");
217 return;
218 }
219
220 if (!InfGetDataField (&InfContext, 1, &LoadOptions))
221 {
222 printf("Failed to get load options\n");
223 return;
224 }
225
226 BootOptions = LoadOptions;
227
228 #if DBG
229 /* Get debug load options and use them */
230 if (InfFindFirstLine(InfHandle,
231 "SetupData",
232 "DbgOsLoadOptions",
233 &InfContext))
234 {
235 if (!InfGetDataField(&InfContext, 1, &DbgOptions))
236 DbgOptions = "";
237 else
238 BootOptions = DbgOptions;
239 }
240 #endif
241
242 DPRINTM(DPRINT_WINDOWS,"BootOptions: '%s'\n", BootOptions);
243
244 SetupUiInitialize();
245 UiDrawStatusText("");
246 UiDrawStatusText("Detecting Hardware...");
247
248 /* Let user know we started loading */
249 UiDrawStatusText("Loading...");
250
251 /* Construct the system path */
252 sprintf(SystemPath, "%s\\", SourcePath);
253
254 DPRINTM(DPRINT_WINDOWS,"BootPath: '%s', SystemPath: '%s'\n", BootPath, SystemPath);
255
256 /* Allocate and minimalistic-initialize LPB */
257 AllocateAndInitLPB(&LoaderBlock);
258
259 /* Allocate and initialize setup loader block */
260 SetupBlock = MmHeapAlloc(sizeof(SETUP_LOADER_BLOCK));
261 RtlZeroMemory(SetupBlock, sizeof(SETUP_LOADER_BLOCK));
262 LoaderBlock->SetupLdrBlock = SetupBlock;
263
264 /* Set textmode setup flag */
265 SetupBlock->Flags = SETUPLDR_TEXT_MODE;
266
267 /* Detect hardware */
268 UseRealHeap = TRUE;
269 LoaderBlock->ConfigurationRoot = MachHwDetect();
270
271 /* Load kernel */
272 strcpy(FileName, BootPath);
273 strcat(FileName, "NTOSKRNL.EXE");
274 Status = WinLdrLoadImage(FileName, LoaderSystemCode, &NtosBase);
275 DPRINTM(DPRINT_WINDOWS, "Ntos loaded with status %d at %p\n", Status, NtosBase);
276
277 /* Load HAL */
278 strcpy(FileName, BootPath);
279 strcat(FileName, "HAL.DLL");
280 Status = WinLdrLoadImage(FileName, LoaderHalCode, &HalBase);
281 DPRINTM(DPRINT_WINDOWS, "HAL loaded with status %d at %p\n", Status, HalBase);
282
283 /* Load kernel-debugger support dll */
284 strcpy(FileName, BootPath);
285 strcat(FileName, "KDCOM.DLL");
286 Status = WinLdrLoadImage(FileName, LoaderBootDriver, &KdComBase);
287 DPRINTM(DPRINT_WINDOWS, "KdCom loaded with status %d at %p\n", Status, KdComBase);
288
289 /* Allocate data table entries for above-loaded modules */
290 WinLdrAllocateDataTableEntry(LoaderBlock, "ntoskrnl.exe",
291 "NTOSKRNL.EXE", NtosBase, &KernelDTE);
292 WinLdrAllocateDataTableEntry(LoaderBlock, "hal.dll",
293 "HAL.DLL", HalBase, &HalDTE);
294 WinLdrAllocateDataTableEntry(LoaderBlock, "kdcom.dll",
295 "KDCOM.DLL", KdComBase, &KdComDTE);
296
297 /* Load all referenced DLLs for kernel, HAL and kdcom.dll */
298 strcpy(SearchPath, BootPath);
299 WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, KernelDTE);
300 WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, HalDTE);
301 if (KdComDTE)
302 WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, KdComDTE);
303
304 /* Load NLS data */
305 SetupLdrLoadNlsData(LoaderBlock, InfHandle, BootPath);
306
307 /* Get a list of boot drivers */
308 SetupLdrScanBootDrivers(LoaderBlock, InfHandle, BootPath);
309
310 /* Load boot drivers */
311 Status = WinLdrLoadBootDrivers(LoaderBlock, BootPath);
312 DPRINTM(DPRINT_WINDOWS, "Boot drivers loaded with status %d\n", Status);
313
314 /* Alloc PCR, TSS, do magic things with the GDT/IDT */
315 WinLdrSetupForNt(LoaderBlock, &GdtIdt, &PcrBasePage, &TssBasePage);
316
317 /* Initialize Phase 1 - no drivers loading anymore */
318 WinLdrInitializePhase1(LoaderBlock, (PCHAR)BootOptions, SystemPath, BootPath, _WIN32_WINNT_WS03);
319
320 /* Save entry-point pointer and Loader block VAs */
321 KiSystemStartup = (KERNEL_ENTRY_POINT)KernelDTE->EntryPoint;
322 LoaderBlockVA = PaToVa(LoaderBlock);
323
324 /* "Stop all motors", change videomode */
325 MachPrepareForReactOS(TRUE);
326
327 /* Debugging... */
328 //DumpMemoryAllocMap();
329
330 /* Turn on paging mode of CPU*/
331 WinLdrTurnOnPaging(LoaderBlock, PcrBasePage, TssBasePage, GdtIdt);
332
333 /* Save final value of LoaderPagesSpanned */
334 LoaderBlock->Extension->LoaderPagesSpanned = LoaderPagesSpanned;
335
336 DPRINTM(DPRINT_WINDOWS, "Hello from paged mode, KiSystemStartup %p, LoaderBlockVA %p!\n",
337 KiSystemStartup, LoaderBlockVA);
338
339 //WinLdrpDumpMemoryDescriptors(LoaderBlockVA);
340 //WinLdrpDumpBootDriver(LoaderBlockVA);
341 //WinLdrpDumpArcDisks(LoaderBlockVA);
342
343 /*asm(".intel_syntax noprefix\n");
344 asm("test1:\n");
345 asm("jmp test1\n");
346 asm(".att_syntax\n");*/
347
348 /* Pass control */
349 (*KiSystemStartup)(LoaderBlockVA);
350
351 return;
352 }