- Implement boot drivers loading.
[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 <debug.h>
25
26 // TODO: Move to .h
27 VOID AllocateAndInitLPB(PLOADER_PARAMETER_BLOCK *OutLoaderBlock);
28 BOOLEAN WinLdrLoadBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock, LPSTR BootPath);
29 void WinLdrSetupForNt(PLOADER_PARAMETER_BLOCK LoaderBlock,
30 PVOID *GdtIdt,
31 ULONG *PcrBasePage,
32 ULONG *TssBasePage);
33 VOID
34 WinLdrInitializePhase1(PLOADER_PARAMETER_BLOCK LoaderBlock,
35 PCHAR Options,
36 PCHAR SystemPath,
37 PCHAR BootPath,
38 USHORT VersionToBoot);
39 BOOLEAN
40 WinLdrLoadNLSData(IN OUT PLOADER_PARAMETER_BLOCK LoaderBlock,
41 IN LPCSTR DirectoryPath,
42 IN LPCSTR AnsiFileName,
43 IN LPCSTR OemFileName,
44 IN LPCSTR LanguageFileName);
45 BOOLEAN
46 WinLdrAddDriverToList(LIST_ENTRY *BootDriverListHead,
47 LPWSTR RegistryPath,
48 LPWSTR ImagePath,
49 LPWSTR ServiceName);
50
51
52 //FIXME: Do a better way to retrieve Arc disk information
53 extern ULONG reactos_disk_count;
54 extern ARC_DISK_SIGNATURE reactos_arc_disk_info[];
55 extern char reactos_arc_strings[32][256];
56
57 extern BOOLEAN UseRealHeap;
58 extern ULONG LoaderPagesSpanned;
59
60
61 VOID
62 SetupLdrLoadNlsData(PLOADER_PARAMETER_BLOCK LoaderBlock, HINF InfHandle, LPCSTR SearchPath)
63 {
64 INFCONTEXT InfContext;
65 BOOLEAN Status;
66 LPCSTR AnsiName, OemName, LangName;
67
68 /* Get ANSI codepage file */
69 if (!InfFindFirstLine(InfHandle, "NLS", "AnsiCodepage", &InfContext))
70 {
71 printf("Failed to find 'NLS/AnsiCodepage'\n");
72 return;
73 }
74 if (!InfGetDataField(&InfContext, 1, &AnsiName))
75 {
76 printf("Failed to get load options\n");
77 return;
78 }
79
80 /* Get OEM codepage file */
81 if (!InfFindFirstLine(InfHandle, "NLS", "OemCodepage", &InfContext))
82 {
83 printf("Failed to find 'NLS/AnsiCodepage'\n");
84 return;
85 }
86 if (!InfGetDataField(&InfContext, 1, &OemName))
87 {
88 printf("Failed to get load options\n");
89 return;
90 }
91
92 if (!InfFindFirstLine(InfHandle, "NLS", "UnicodeCasetable", &InfContext))
93 {
94 printf("Failed to find 'NLS/AnsiCodepage'\n");
95 return;
96 }
97 if (!InfGetDataField(&InfContext, 1, &LangName))
98 {
99 printf("Failed to get load options\n");
100 return;
101 }
102
103 Status = WinLdrLoadNLSData(LoaderBlock, SearchPath, AnsiName, OemName, LangName);
104 DPRINTM(DPRINT_WINDOWS, "NLS data loaded with status %d\n", Status);
105 }
106
107 VOID
108 SetupLdrScanBootDrivers(PLOADER_PARAMETER_BLOCK LoaderBlock, HINF InfHandle, LPCSTR SearchPath)
109 {
110 INFCONTEXT InfContext;
111 BOOLEAN Status;
112 LPCSTR Media, DriverName;
113 WCHAR ServiceName[256];
114 WCHAR ImagePath[256];
115
116 /* Open inf section */
117 if (!InfFindFirstLine(InfHandle, "SourceDisksFiles", NULL, &InfContext))
118 return;
119
120 /* Load all listed boot drivers */
121 do
122 {
123 if (InfGetDataField(&InfContext, 7, &Media) &&
124 InfGetDataField(&InfContext, 0, &DriverName))
125 {
126 if (strcmp(Media, "x") == 0)
127 {
128 /* Convert name to widechar */
129 swprintf(ServiceName, L"%S", DriverName);
130
131 /* Remove .sys extension */
132 ServiceName[wcslen(ServiceName) - 4] = 0;
133
134 /* Prepare image path */
135 swprintf(ImagePath, L"%S", DriverName);
136
137 /* Add it to the list */
138 Status = WinLdrAddDriverToList(&LoaderBlock->BootDriverListHead,
139 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\",
140 ImagePath,
141 ServiceName);
142
143 if (!Status)
144 {
145 DPRINTM(DPRINT_WINDOWS, "could not add boot driver %s, %s\n", SearchPath, DriverName);
146 return;
147 }
148 }
149 }
150 } while (InfFindNextLine(&InfContext, &InfContext));
151 }
152
153 VOID LoadReactOSSetup2(VOID)
154 {
155 CHAR SystemPath[512], SearchPath[512];
156 CHAR FileName[512];
157 CHAR BootPath[512];
158 LPCSTR BootOptions;
159 PVOID NtosBase = NULL, HalBase = NULL, KdComBase = NULL;
160 BOOLEAN Status;
161 ULONG BootDevice;
162 ULONG i, ErrorLine;
163 HINF InfHandle;
164 INFCONTEXT InfContext;
165 PLOADER_PARAMETER_BLOCK LoaderBlock, LoaderBlockVA;
166 KERNEL_ENTRY_POINT KiSystemStartup;
167 PLDR_DATA_TABLE_ENTRY KernelDTE, HalDTE, KdComDTE = NULL;
168 // Mm-related things
169 PVOID GdtIdt;
170 ULONG PcrBasePage=0;
171 ULONG TssBasePage=0;
172 LPCSTR SourcePath;
173 LPCSTR SourcePaths[] =
174 {
175 "", /* Only for floppy boot */
176 #if defined(_M_IX86)
177 "\\I386",
178 #elif defined(_M_MPPC)
179 "\\PPC",
180 #elif defined(_M_MRX000)
181 "\\MIPS",
182 #endif
183 "\\reactos",
184 NULL
185 };
186
187 /* Get boot device number */
188 MachDiskGetBootDevice(&BootDevice);
189
190 /* Open 'txtsetup.sif' from any of source paths */
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 break;
202 }
203
204 /* If we didn't find it anywhere, then just use root */
205 if (!*SourcePath)
206 SourcePath = "\\";
207
208 /* Load options */
209 if (!InfFindFirstLine(InfHandle,
210 "SetupData",
211 "OsLoadOptions",
212 &InfContext))
213 {
214 printf("Failed to find 'SetupData/OsLoadOptions'\n");
215 return;
216 }
217
218 if (!InfGetDataField (&InfContext, 1, &BootOptions))
219 {
220 printf("Failed to get load options\n");
221 return;
222 }
223
224 /* Save source path */
225 strcpy(BootPath, SourcePath);
226
227 SetupUiInitialize();
228 UiDrawStatusText("");
229 UiDrawStatusText("Detecting Hardware...");
230
231 /* Let user know we started loading */
232 UiDrawStatusText("Loading...");
233
234 /* Try to open system drive */
235 FsOpenBootVolume();
236
237 /* Append a backslash to the bootpath if needed */
238 if ((strlen(BootPath)==0) || BootPath[strlen(BootPath)] != '\\')
239 {
240 strcat(BootPath, "\\");
241 }
242
243 /* Construct the system path */
244 MachDiskGetBootPath(SystemPath, sizeof(SystemPath));
245 strcat(SystemPath, SourcePath);
246
247 DPRINTM(DPRINT_WINDOWS,"SystemRoot: '%s', SystemPath: '%s'\n", BootPath, SystemPath);
248
249 /* Allocate and minimalistic-initialize LPB */
250 AllocateAndInitLPB(&LoaderBlock);
251
252 /* Detect hardware */
253 UseRealHeap = TRUE;
254 LoaderBlock->ConfigurationRoot = MachHwDetect();
255
256 /* Load kernel */
257 strcpy(FileName, BootPath);
258 strcat(FileName, "NTOSKRNL.EXE");
259 Status = WinLdrLoadImage(FileName, LoaderSystemCode, &NtosBase);
260 DPRINTM(DPRINT_WINDOWS, "Ntos loaded with status %d at %p\n", Status, NtosBase);
261
262 /* Load HAL */
263 strcpy(FileName, BootPath);
264 strcat(FileName, "HAL.DLL");
265 Status = WinLdrLoadImage(FileName, LoaderHalCode, &HalBase);
266 DPRINTM(DPRINT_WINDOWS, "HAL loaded with status %d at %p\n", Status, HalBase);
267
268 /* Load kernel-debugger support dll */
269 strcpy(FileName, BootPath);
270 strcat(FileName, "KDCOM.DLL");
271 Status = WinLdrLoadImage(FileName, LoaderBootDriver, &KdComBase);
272 DPRINTM(DPRINT_WINDOWS, "KdCom loaded with status %d at %p\n", Status, KdComBase);
273
274 /* Allocate data table entries for above-loaded modules */
275 WinLdrAllocateDataTableEntry(LoaderBlock, "ntoskrnl.exe",
276 "NTOSKRNL.EXE", NtosBase, &KernelDTE);
277 WinLdrAllocateDataTableEntry(LoaderBlock, "hal.dll",
278 "HAL.DLL", HalBase, &HalDTE);
279 WinLdrAllocateDataTableEntry(LoaderBlock, "kdcom.dll",
280 "KDCOM.DLL", KdComBase, &KdComDTE);
281
282 /* Load all referenced DLLs for kernel, HAL and kdcom.dll */
283 strcpy(SearchPath, BootPath);
284 WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, KernelDTE);
285 WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, HalDTE);
286 if (KdComDTE)
287 WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, KdComDTE);
288
289 /* Load NLS data */
290 SetupLdrLoadNlsData(LoaderBlock, InfHandle, BootPath);
291
292 /* Get a list of boot drivers */
293 SetupLdrScanBootDrivers(LoaderBlock, InfHandle, BootPath);
294
295 /* Load boot drivers */
296 Status = WinLdrLoadBootDrivers(LoaderBlock, BootPath);
297 DPRINTM(DPRINT_WINDOWS, "Boot drivers loaded with status %d\n", Status);
298
299 /* Alloc PCR, TSS, do magic things with the GDT/IDT */
300 WinLdrSetupForNt(LoaderBlock, &GdtIdt, &PcrBasePage, &TssBasePage);
301
302 /* Initialize Phase 1 - no drivers loading anymore */
303 WinLdrInitializePhase1(LoaderBlock, (PCHAR)BootOptions, SystemPath, BootPath, _WIN32_WINNT_WS03);
304
305 /* Save entry-point pointer and Loader block VAs */
306 KiSystemStartup = (KERNEL_ENTRY_POINT)KernelDTE->EntryPoint;
307 LoaderBlockVA = PaToVa(LoaderBlock);
308
309 /* "Stop all motors", change videomode */
310 MachPrepareForReactOS(FALSE);
311
312 /* Debugging... */
313 //DumpMemoryAllocMap();
314
315 /* Turn on paging mode of CPU*/
316 WinLdrTurnOnPaging(LoaderBlock, PcrBasePage, TssBasePage, GdtIdt);
317
318 /* Save final value of LoaderPagesSpanned */
319 LoaderBlock->Extension->LoaderPagesSpanned = LoaderPagesSpanned;
320
321 DPRINTM(DPRINT_WINDOWS, "Hello from paged mode, KiSystemStartup %p, LoaderBlockVA %p!\n",
322 KiSystemStartup, LoaderBlockVA);
323
324 //WinLdrpDumpMemoryDescriptors(LoaderBlockVA);
325 //WinLdrpDumpBootDriver(LoaderBlockVA);
326 //WinLdrpDumpArcDisks(LoaderBlockVA);
327
328 /* Pass control */
329 (*KiSystemStartup)(LoaderBlockVA);
330
331 return;
332 }