[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, DbgOptions, 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 /* Get Load options - debug and non-debug */
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, &LoadOptions))
218 {
219 printf("Failed to get load options\n");
220 return;
221 }
222
223 BootOptions = LoadOptions;
224
225 #if DBG
226 /* Get debug load options and use them */
227 if (InfFindFirstLine(InfHandle,
228 "SetupData",
229 "DbgOsLoadOptions",
230 &InfContext))
231 {
232 if (!InfGetDataField(&InfContext, 1, &DbgOptions))
233 DbgOptions = "";
234 else
235 BootOptions = DbgOptions;
236 }
237 #endif
238
239 DPRINTM(DPRINT_WINDOWS,"BootOptions: '%s'\n", BootOptions);
240
241 SetupUiInitialize();
242 UiDrawStatusText("");
243 UiDrawStatusText("Detecting Hardware...");
244
245 /* Let user know we started loading */
246 UiDrawStatusText("Loading...");
247
248 /* Construct the system path */
249 sprintf(SystemPath, "%s\\", SourcePath);
250
251 DPRINTM(DPRINT_WINDOWS,"BootPath: '%s', SystemPath: '%s'\n", BootPath, SystemPath);
252
253 /* Allocate and minimalistic-initialize LPB */
254 AllocateAndInitLPB(&LoaderBlock);
255
256 /* Allocate and initialize setup loader block */
257 SetupBlock = MmHeapAlloc(sizeof(SETUP_LOADER_BLOCK));
258 RtlZeroMemory(SetupBlock, sizeof(SETUP_LOADER_BLOCK));
259 LoaderBlock->SetupLdrBlock = SetupBlock;
260
261 /* Set textmode setup flag */
262 SetupBlock->Flags = SETUPLDR_TEXT_MODE;
263
264 /* Detect hardware */
265 UseRealHeap = TRUE;
266 LoaderBlock->ConfigurationRoot = MachHwDetect();
267
268 /* Load kernel */
269 strcpy(FileName, BootPath);
270 strcat(FileName, "NTOSKRNL.EXE");
271 Status = WinLdrLoadImage(FileName, LoaderSystemCode, &NtosBase);
272 DPRINTM(DPRINT_WINDOWS, "Ntos loaded with status %d at %p\n", Status, NtosBase);
273
274 /* Load HAL */
275 strcpy(FileName, BootPath);
276 strcat(FileName, "HAL.DLL");
277 Status = WinLdrLoadImage(FileName, LoaderHalCode, &HalBase);
278 DPRINTM(DPRINT_WINDOWS, "HAL loaded with status %d at %p\n", Status, HalBase);
279
280 /* Load kernel-debugger support dll */
281 strcpy(FileName, BootPath);
282 strcat(FileName, "KDCOM.DLL");
283 Status = WinLdrLoadImage(FileName, LoaderBootDriver, &KdComBase);
284 DPRINTM(DPRINT_WINDOWS, "KdCom loaded with status %d at %p\n", Status, KdComBase);
285
286 /* Allocate data table entries for above-loaded modules */
287 WinLdrAllocateDataTableEntry(LoaderBlock, "ntoskrnl.exe",
288 "NTOSKRNL.EXE", NtosBase, &KernelDTE);
289 WinLdrAllocateDataTableEntry(LoaderBlock, "hal.dll",
290 "HAL.DLL", HalBase, &HalDTE);
291 WinLdrAllocateDataTableEntry(LoaderBlock, "kdcom.dll",
292 "KDCOM.DLL", KdComBase, &KdComDTE);
293
294 /* Load all referenced DLLs for kernel, HAL and kdcom.dll */
295 strcpy(SearchPath, BootPath);
296 WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, KernelDTE);
297 WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, HalDTE);
298 if (KdComDTE)
299 WinLdrScanImportDescriptorTable(LoaderBlock, SearchPath, KdComDTE);
300
301 /* Load NLS data */
302 SetupLdrLoadNlsData(LoaderBlock, InfHandle, BootPath);
303
304 /* Get a list of boot drivers */
305 SetupLdrScanBootDrivers(LoaderBlock, InfHandle, BootPath);
306
307 /* Load boot drivers */
308 Status = WinLdrLoadBootDrivers(LoaderBlock, BootPath);
309 DPRINTM(DPRINT_WINDOWS, "Boot drivers loaded with status %d\n", Status);
310
311 /* Alloc PCR, TSS, do magic things with the GDT/IDT */
312 WinLdrSetupForNt(LoaderBlock, &GdtIdt, &PcrBasePage, &TssBasePage);
313
314 /* Initialize Phase 1 - no drivers loading anymore */
315 WinLdrInitializePhase1(LoaderBlock, (PCHAR)BootOptions, SystemPath, BootPath, _WIN32_WINNT_WS03);
316
317 /* Save entry-point pointer and Loader block VAs */
318 KiSystemStartup = (KERNEL_ENTRY_POINT)KernelDTE->EntryPoint;
319 LoaderBlockVA = PaToVa(LoaderBlock);
320
321 /* "Stop all motors", change videomode */
322 MachPrepareForReactOS(TRUE);
323
324 /* Debugging... */
325 //DumpMemoryAllocMap();
326
327 /* Turn on paging mode of CPU*/
328 WinLdrTurnOnPaging(LoaderBlock, PcrBasePage, TssBasePage, GdtIdt);
329
330 /* Save final value of LoaderPagesSpanned */
331 LoaderBlock->Extension->LoaderPagesSpanned = LoaderPagesSpanned;
332
333 DPRINTM(DPRINT_WINDOWS, "Hello from paged mode, KiSystemStartup %p, LoaderBlockVA %p!\n",
334 KiSystemStartup, LoaderBlockVA);
335
336 //WinLdrpDumpMemoryDescriptors(LoaderBlockVA);
337 //WinLdrpDumpBootDriver(LoaderBlockVA);
338 //WinLdrpDumpArcDisks(LoaderBlockVA);
339
340 /*asm(".intel_syntax noprefix\n");
341 asm("test1:\n");
342 asm("jmp test1\n");
343 asm(".att_syntax\n");*/
344
345 /* Pass control */
346 (*KiSystemStartup)(LoaderBlockVA);
347
348 return;
349 }