Merge from branch ReactX to Trunk,
[reactos.git] / reactos / boot / freeldr / freeldr / reactos / setupldr.c
1 /*
2 * FreeLoader
3 *
4 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
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 #define _NTSYSTEM_
22 #include <freeldr.h>
23 #include <debug.h>
24
25 extern ULONG PageDirectoryStart;
26 extern ULONG PageDirectoryEnd;
27
28 ROS_LOADER_PARAMETER_BLOCK LoaderBlock;
29 char reactos_kernel_cmdline[255]; // Command line passed to kernel
30 LOADER_MODULE reactos_modules[64]; // Array to hold boot module info loaded for the kernel
31 char reactos_module_strings[64][256]; // Array to hold module names
32 reactos_mem_data_t reactos_mem_data;
33 char szBootPath[256];
34 char szHalName[256];
35 CHAR SystemRoot[255];
36 extern ULONG_PTR KernelBase, KernelEntryPoint;
37
38 extern BOOLEAN FrLdrLoadDriver(PCHAR szFileName, INT nPos);
39
40 #define USE_UI
41
42 BOOLEAN
43 NTAPI
44 static FrLdrLoadKernel(IN PCHAR szFileName,
45 IN INT nPos)
46 {
47 PFILE FilePointer;
48 PCHAR szShortName;
49 CHAR szBuffer[256];
50 PVOID LoadBase;
51 PIMAGE_NT_HEADERS NtHeader;
52
53 /* Extract Kernel filename without path */
54 szShortName = strrchr(szFileName, '\\');
55 if (!szShortName)
56 {
57 /* No path, leave it alone */
58 szShortName = szFileName;
59 }
60 else
61 {
62 /* Skip the path */
63 szShortName = szShortName + 1;
64 }
65
66 /* Open the Kernel */
67 FilePointer = FsOpenFile(szFileName);
68 if (!FilePointer)
69 {
70 /* Return failure on the short name */
71 strcpy(szBuffer, szShortName);
72 strcat(szBuffer, " not found.");
73 UiMessageBox(szBuffer);
74 return FALSE;
75 }
76
77 /* Update the status bar with the current file */
78 strcpy(szBuffer, "Reading ");
79 strcat(szBuffer, szShortName);
80 UiDrawStatusText(szBuffer);
81
82 /* Do the actual loading */
83 LoadBase = FrLdrMapImage(FilePointer, szShortName, 1);
84
85 /* Get the NT header, kernel base and kernel entry */
86 NtHeader = RtlImageNtHeader(LoadBase);
87 KernelBase = NtHeader->OptionalHeader.ImageBase;
88 KernelEntryPoint = KernelBase + NtHeader->OptionalHeader.AddressOfEntryPoint;
89 LoaderBlock.KernelBase = KernelBase;
90
91 /* Update Processbar and return success */
92 return TRUE;
93 }
94
95 static BOOLEAN
96 LoadDriver(PCSTR szSourcePath, PCSTR szFileName)
97 {
98 return FrLdrLoadDriver((PCHAR)szFileName, 0);
99 }
100
101
102 static BOOLEAN
103 LoadNlsFile(PCSTR szSourcePath, PCSTR szFileName, PCSTR szModuleName)
104 {
105 CHAR szFullName[256];
106 CHAR szBuffer[80];
107 PFILE FilePointer;
108 PCSTR szShortName;
109
110 if (szSourcePath[0] != '\\')
111 {
112 strcpy(szFullName, "\\");
113 strcat(szFullName, szSourcePath);
114 }
115 else
116 {
117 strcpy(szFullName, szSourcePath);
118 }
119
120 if (szFullName[strlen(szFullName)] != '\\')
121 {
122 strcat(szFullName, "\\");
123 }
124
125 if (szFileName[0] != '\\')
126 {
127 strcat(szFullName, szFileName);
128 }
129 else
130 {
131 strcat(szFullName, szFileName + 1);
132 }
133
134 szShortName = strrchr(szFileName, '\\');
135 if (szShortName == NULL)
136 szShortName = szFileName;
137 else
138 szShortName = szShortName + 1;
139
140
141 FilePointer = FsOpenFile(szFullName);
142 if (FilePointer == NULL)
143 {
144 printf("Could not find %s\n", szFileName);
145 return(FALSE);
146 }
147
148 /*
149 * Update the status bar with the current file
150 */
151 sprintf(szBuffer, "Setup is loading files (%s)", szShortName);
152 UiDrawStatusText(szBuffer);
153
154 /* Load the driver */
155 FrLdrLoadModule(FilePointer, szModuleName, NULL);
156
157 return(TRUE);
158 }
159
160 VOID RunLoader(VOID)
161 {
162 ULONG_PTR Base;
163 ULONG Size, i;
164 const char *SourcePath;
165 const char *LoadOptions = "", *DbgLoadOptions = "";
166 const char *sourcePaths[] = {
167 "", /* Only for floppy boot */
168 #if defined(_M_IX86)
169 "\\I386",
170 #elif defined(_M_MPPC)
171 "\\PPC",
172 #elif defined(_M_MRX000)
173 "\\MIPS",
174 #endif
175 "\\reactos",
176 NULL };
177 char szKernelName[256];
178
179 HINF InfHandle;
180 ULONG ErrorLine;
181 INFCONTEXT InfContext;
182
183 /* Setup multiboot information structure */
184 LoaderBlock.CommandLine = reactos_kernel_cmdline;
185 LoaderBlock.PageDirectoryStart = (ULONG)&PageDirectoryStart;
186 LoaderBlock.PageDirectoryEnd = (ULONG)&PageDirectoryEnd;
187 LoaderBlock.ModsCount = 0;
188 LoaderBlock.ModsAddr = reactos_modules;
189 LoaderBlock.MmapLength = (unsigned long)MachGetMemoryMap((PBIOS_MEMORY_MAP)reactos_memory_map, 32) * sizeof(memory_map_t);
190 if (LoaderBlock.MmapLength)
191 {
192 ULONG i;
193
194 LoaderBlock.MmapAddr = (unsigned long)&reactos_memory_map;
195 reactos_memory_map_descriptor_size = sizeof(memory_map_t); // GetBiosMemoryMap uses a fixed value of 24
196 for (i=0; i<(LoaderBlock.MmapLength/sizeof(memory_map_t)); i++)
197 {
198 if (BiosMemoryUsable == reactos_memory_map[i].type &&
199 0 == reactos_memory_map[i].base_addr_low)
200 {
201 LoaderBlock.MemLower = (reactos_memory_map[i].base_addr_low + reactos_memory_map[i].length_low) / 1024;
202 if (640 < LoaderBlock.MemLower)
203 {
204 LoaderBlock.MemLower = 640;
205 }
206 }
207 if (BiosMemoryUsable == reactos_memory_map[i].type &&
208 reactos_memory_map[i].base_addr_low <= 1024 * 1024 &&
209 1024 * 1024 <= reactos_memory_map[i].base_addr_low + reactos_memory_map[i].length_low)
210 {
211 LoaderBlock.MemHigher = (reactos_memory_map[i].base_addr_low + reactos_memory_map[i].length_low) / 1024 - 1024;
212 }
213 }
214 }
215
216 #ifdef USE_UI
217 SetupUiInitialize();
218 #endif
219 UiDrawStatusText("");
220
221 extern BOOLEAN FrLdrBootType;
222 FrLdrBootType = TRUE;
223
224 /* Initialize registry */
225 RegInitializeRegistry();
226
227 /* Detect hardware */
228 UiDrawStatusText("Detecting hardware...");
229 MachHwDetect();
230 UiDrawStatusText("");
231
232 /* set boot device */
233 MachDiskGetBootDevice(&LoaderBlock.BootDevice);
234
235 /* Open boot drive */
236 if (!FsOpenBootVolume())
237 {
238 UiMessageBox("Failed to open boot drive.");
239 return;
240 }
241
242 /* Open 'txtsetup.sif' */
243 for (i = MachDiskBootingFromFloppy() ? 0 : 1; ; i++)
244 {
245 SourcePath = sourcePaths[i];
246 if (!SourcePath)
247 {
248 printf("Failed to open 'txtsetup.sif'\n");
249 return;
250 }
251 strcpy(szKernelName, SourcePath);
252 strcat(szKernelName, "\\txtsetup.sif");
253 if (InfOpenFile (&InfHandle, szKernelName, &ErrorLine))
254 break;
255 }
256 if (!*SourcePath)
257 SourcePath = "\\";
258
259 #ifdef DBG
260 /* Get load options */
261 if (InfFindFirstLine (InfHandle,
262 "SetupData",
263 "DbgOsLoadOptions",
264 &InfContext))
265 {
266 if (!InfGetDataField (&InfContext, 1, &DbgLoadOptions))
267 DbgLoadOptions = "";
268 }
269 #endif
270 if (!strlen(DbgLoadOptions) && !InfFindFirstLine (InfHandle,
271 "SetupData",
272 "OsLoadOptions",
273 &InfContext))
274 {
275 printf("Failed to find 'SetupData/OsLoadOptions'\n");
276 return;
277 }
278
279 if (!InfGetDataField (&InfContext,
280 1,
281 &LoadOptions))
282 {
283 printf("Failed to get load options\n");
284 return;
285 }
286
287 /* Set kernel command line */
288 MachDiskGetBootPath(reactos_kernel_cmdline, sizeof(reactos_kernel_cmdline));
289 strcat(strcat(strcat(strcat(reactos_kernel_cmdline, SourcePath), " "),
290 LoadOptions), DbgLoadOptions);
291
292 strcpy(SystemRoot, SourcePath);
293 strcat(SystemRoot, "\\");
294
295 /* Setup the boot path and kernel path */
296 strcpy(szBootPath, SourcePath);
297 strcpy(szKernelName, szBootPath);
298 strcat(szKernelName, "\\ntoskrnl.exe");
299
300 /* Setup the HAL path */
301 strcpy(szHalName, szBootPath);
302 strcat(szHalName, "\\hal.dll");
303
304 /* Load the kernel */
305 if (!FrLdrLoadKernel(szKernelName, 5)) return;
306
307 /* Export the hardware hive */
308 Base = FrLdrCreateModule ("HARDWARE");
309 RegExportBinaryHive (L"\\Registry\\Machine\\HARDWARE", (PVOID)Base, &Size);
310 FrLdrCloseModule (Base, Size);
311
312 /* Insert boot disk 2 */
313 if (MachDiskBootingFromFloppy())
314 {
315 UiMessageBox("Please insert \"ReactOS Boot Disk 2\" and press ENTER");
316
317 /* Open boot drive */
318 if (!FsOpenBootVolume())
319 {
320 UiMessageBox("Failed to open boot drive.");
321 return;
322 }
323
324 /* FIXME: check volume label or disk marker file */
325 }
326
327
328 /* Get ANSI codepage file */
329 if (!InfFindFirstLine (InfHandle,
330 "NLS",
331 "AnsiCodepage",
332 &InfContext))
333 {
334 printf("Failed to find 'NLS/AnsiCodepage'\n");
335 return;
336 }
337
338 if (!InfGetDataField (&InfContext,
339 1,
340 &LoadOptions))
341 {
342 printf("Failed to get load options\n");
343 return;
344 }
345
346 /* Load ANSI codepage file */
347 if (!LoadNlsFile(SourcePath, LoadOptions, "ansi.nls"))
348 {
349 UiMessageBox("Failed to load the ANSI codepage file.");
350 return;
351 }
352
353 /* Get OEM codepage file */
354 if (!InfFindFirstLine (InfHandle,
355 "NLS",
356 "OemCodepage",
357 &InfContext))
358 {
359 printf("Failed to find 'NLS/AnsiCodepage'\n");
360 return;
361 }
362
363 if (!InfGetDataField (&InfContext,
364 1,
365 &LoadOptions))
366 {
367 printf("Failed to get load options\n");
368 return;
369 }
370
371 /* Load OEM codepage file */
372 if (!LoadNlsFile(SourcePath, LoadOptions, "oem.nls"))
373 {
374 UiMessageBox("Failed to load the OEM codepage file.");
375 return;
376 }
377
378 /* Get Unicode Casemap file */
379 if (!InfFindFirstLine (InfHandle,
380 "NLS",
381 "UnicodeCasetable",
382 &InfContext))
383 {
384 printf("Failed to find 'NLS/AnsiCodepage'\n");
385 return;
386 }
387
388 if (!InfGetDataField (&InfContext,
389 1,
390 &LoadOptions))
391 {
392 printf("Failed to get load options\n");
393 return;
394 }
395
396 /* Load Unicode casemap file */
397 if (!LoadNlsFile(SourcePath, LoadOptions, "casemap.nls"))
398 {
399 UiMessageBox("Failed to load the Unicode casemap file.");
400 return;
401 }
402
403 /* Load vfatfs.sys (could be loaded by the setup prog!) */
404 if (!LoadDriver(SourcePath, "vfatfs.sys"))
405 return;
406
407 /* Load additional files specified in txtsetup.inf */
408 if (InfFindFirstLine(InfHandle,
409 "SourceDisksFiles",
410 NULL,
411 &InfContext))
412 {
413 do
414 {
415 LPCSTR Media, DriverName;
416 if (InfGetDataField(&InfContext, 7, &Media) &&
417 InfGetDataField(&InfContext, 0, &DriverName))
418 {
419 if (strcmp(Media, "x") == 0)
420 {
421 if (!LoadDriver(SourcePath, DriverName))
422 return;
423 }
424 }
425 } while (InfFindNextLine(&InfContext, &InfContext));
426 }
427
428 UiUnInitialize("Booting ReactOS...");
429
430 /* Now boot the kernel */
431 DiskStopFloppyMotor();
432 MachVideoPrepareForReactOS(TRUE);
433 FrLdrStartup(0x2badb002);
434 }
435
436 /* EOF */