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