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