- Make freeldr do identity memory mapping. This simplifies a lot of things throughout...
[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 ROS_LOADER_PARAMETER_BLOCK LoaderBlock;
26 char reactos_kernel_cmdline[255]; // Command line passed to kernel
27 LOADER_MODULE reactos_modules[64]; // Array to hold boot module info loaded for the kernel
28 char reactos_module_strings[64][256]; // Array to hold module names
29 unsigned long reactos_memory_map_descriptor_size;
30 memory_map_t reactos_memory_map[32]; // Memory map
31 char szBootPath[256];
32 char szHalName[256];
33 CHAR SystemRoot[255];
34 extern ULONG_PTR KernelBase, KernelEntryPoint;
35
36 extern BOOLEAN FrLdrLoadDriver(PCHAR szFileName, INT nPos);
37
38 #define USE_UI
39
40 BOOLEAN
41 NTAPI
42 static FrLdrLoadKernel(IN PCHAR szFileName,
43 IN INT nPos)
44 {
45 PFILE FilePointer;
46 PCHAR szShortName;
47 CHAR szBuffer[256];
48 PVOID LoadBase;
49 PIMAGE_NT_HEADERS NtHeader;
50
51 /* Extract Kernel filename without path */
52 szShortName = strrchr(szFileName, '\\');
53 if (!szShortName)
54 {
55 /* No path, leave it alone */
56 szShortName = szFileName;
57 }
58 else
59 {
60 /* Skip the path */
61 szShortName = szShortName + 1;
62 }
63
64 /* Open the Kernel */
65 FilePointer = FsOpenFile(szFileName);
66 if (!FilePointer)
67 {
68 /* Return failure on the short name */
69 strcpy(szBuffer, szShortName);
70 strcat(szBuffer, " not found.");
71 UiMessageBox(szBuffer);
72 return FALSE;
73 }
74
75 /* Update the status bar with the current file */
76 strcpy(szBuffer, "Reading ");
77 strcat(szBuffer, szShortName);
78 UiDrawStatusText(szBuffer);
79
80 /* Do the actual loading */
81 LoadBase = FrLdrMapImage(FilePointer, szShortName, 1);
82
83 /* Get the NT header, kernel base and kernel entry */
84 NtHeader = RtlImageNtHeader(LoadBase);
85 KernelBase = NtHeader->OptionalHeader.ImageBase;
86 KernelEntryPoint = KernelBase + NtHeader->OptionalHeader.AddressOfEntryPoint;
87 LoaderBlock.KernelBase = KernelBase;
88
89 /* Update Processbar and return success */
90 return TRUE;
91 }
92
93 static BOOLEAN
94 LoadDriver(PCSTR szSourcePath, PCSTR szFileName)
95 {
96 return FrLdrLoadDriver((PCHAR)szFileName, 0);
97 }
98
99
100 static BOOLEAN
101 LoadNlsFile(PCSTR szSourcePath, PCSTR szFileName, PCSTR szModuleName)
102 {
103 CHAR szFullName[256];
104 #ifdef USE_UI
105 CHAR szBuffer[80];
106 #endif
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 #ifdef USE_UI
152 sprintf(szBuffer, "Setup is loading files (%s)", szShortName);
153 UiDrawStatusText(szBuffer);
154 #else
155 printf("Reading %s\n", szShortName);
156 #endif
157
158 /* Load the driver */
159 FrLdrLoadModule(FilePointer, szModuleName, NULL);
160
161 return(TRUE);
162 }
163
164 VOID RunLoader(VOID)
165 {
166 ULONG_PTR Base;
167 ULONG Size;
168 const char *SourcePath;
169 const char *LoadOptions = "", *DbgLoadOptions = "";
170 char szKernelName[256];
171
172 HINF InfHandle;
173 ULONG ErrorLine;
174 INFCONTEXT InfContext;
175
176 /* Setup multiboot information structure */
177 LoaderBlock.CommandLine = reactos_kernel_cmdline;
178 LoaderBlock.ModsCount = 0;
179 LoaderBlock.ModsAddr = reactos_modules;
180 LoaderBlock.MmapLength = (unsigned long)MachGetMemoryMap((PBIOS_MEMORY_MAP)reactos_memory_map, 32) * sizeof(memory_map_t);
181 if (LoaderBlock.MmapLength)
182 {
183 ULONG i;
184
185 LoaderBlock.MmapAddr = (unsigned long)&reactos_memory_map;
186 reactos_memory_map_descriptor_size = sizeof(memory_map_t); // GetBiosMemoryMap uses a fixed value of 24
187 for (i=0; i<(LoaderBlock.MmapLength/sizeof(memory_map_t)); i++)
188 {
189 if (BiosMemoryUsable == reactos_memory_map[i].type &&
190 0 == reactos_memory_map[i].base_addr_low)
191 {
192 LoaderBlock.MemLower = (reactos_memory_map[i].base_addr_low + reactos_memory_map[i].length_low) / 1024;
193 if (640 < LoaderBlock.MemLower)
194 {
195 LoaderBlock.MemLower = 640;
196 }
197 }
198 if (BiosMemoryUsable == reactos_memory_map[i].type &&
199 reactos_memory_map[i].base_addr_low <= 1024 * 1024 &&
200 1024 * 1024 <= reactos_memory_map[i].base_addr_low + reactos_memory_map[i].length_low)
201 {
202 LoaderBlock.MemHigher = (reactos_memory_map[i].base_addr_low + reactos_memory_map[i].length_low) / 1024 - 1024;
203 }
204 }
205 }
206
207 #ifdef USE_UI
208 SetupUiInitialize();
209 UiDrawStatusText("");
210 #endif
211
212 extern BOOLEAN FrLdrBootType;
213 FrLdrBootType = TRUE;
214
215 /* Initialize registry */
216 RegInitializeRegistry();
217
218 /* Detect hardware */
219 #ifdef USE_UI
220 UiDrawStatusText("Detecting hardware...");
221 #else
222 printf("Detecting hardware...\n\n");
223 #endif
224 MachHwDetect();
225 #ifdef USE_UI
226 UiDrawStatusText("");
227 #endif
228
229 /* set boot device */
230 MachDiskGetBootDevice(&LoaderBlock.BootDevice);
231
232 /* Open boot drive */
233 if (!FsOpenBootVolume())
234 {
235 #ifdef USE_UI
236 UiMessageBox("Failed to open boot drive.");
237 #else
238 printf("Failed to open boot drive.");
239 #endif
240 return;
241 }
242
243 /* Open 'txtsetup.sif' */
244 if (!InfOpenFile (&InfHandle,
245 MachDiskBootingFromFloppy() ? "\\txtsetup.sif" : "\\reactos\\txtsetup.sif",
246 &ErrorLine))
247 {
248 printf("Failed to open 'txtsetup.sif'\n");
249 return;
250 }
251
252 #ifdef DBG
253 /* Get load options */
254 if (InfFindFirstLine (InfHandle,
255 "SetupData",
256 "DbgOsLoadOptions",
257 &InfContext))
258 {
259 if (!InfGetDataField (&InfContext, 1, &DbgLoadOptions))
260 DbgLoadOptions = "";
261 }
262 #endif
263 if (!strlen(DbgLoadOptions) && !InfFindFirstLine (InfHandle,
264 "SetupData",
265 "OsLoadOptions",
266 &InfContext))
267 {
268 printf("Failed to find 'SetupData/OsLoadOptions'\n");
269 return;
270 }
271
272 if (!InfGetDataField (&InfContext,
273 1,
274 &LoadOptions))
275 {
276 printf("Failed to get load options\n");
277 return;
278 }
279 #if 0
280 printf("LoadOptions: '%s'\n", LoadOptions);
281 #endif
282
283 if (MachDiskBootingFromFloppy())
284 {
285 /* Boot from floppy disk */
286 SourcePath = "\\";
287 }
288 else
289 {
290 /* Boot from cdrom */
291 SourcePath = "\\reactos";
292 }
293
294 /* Set kernel command line */
295 MachDiskGetBootPath(reactos_kernel_cmdline, sizeof(reactos_kernel_cmdline));
296 strcat(strcat(strcat(strcat(reactos_kernel_cmdline, SourcePath), " "),
297 LoadOptions), DbgLoadOptions);
298
299 strcpy(SystemRoot, SourcePath);
300 strcat(SystemRoot, "\\");
301
302 /* Setup the boot path and kernel path */
303 strcpy(szBootPath, SourcePath);
304 strcpy(szKernelName, szBootPath);
305 strcat(szKernelName, "\\ntoskrnl.exe");
306
307 /* Setup the HAL path */
308 strcpy(szHalName, szBootPath);
309 strcat(szHalName, "\\hal.dll");
310
311 /* Load the kernel */
312 if (!FrLdrLoadKernel(szKernelName, 5)) return;
313
314 /* Export the hardware hive */
315 Base = FrLdrCreateModule ("HARDWARE");
316 RegExportBinaryHive (L"\\Registry\\Machine\\HARDWARE", (PVOID)Base, &Size);
317 FrLdrCloseModule (Base, Size);
318
319 #if 0
320 printf("Base: %x\n", Base);
321 printf("Size: %u\n", Size);
322 printf("*** System stopped ***\n");
323 for(;;);
324 #endif
325
326 /* Insert boot disk 2 */
327 if (MachDiskBootingFromFloppy())
328 {
329 #ifdef USE_UI
330 UiMessageBox("Please insert \"ReactOS Boot Disk 2\" and press ENTER");
331 #else
332 printf("\n\n Please insert \"ReactOS Boot Disk 2\" and press ENTER\n");
333 MachConsGetCh();
334 #endif
335
336 /* Open boot drive */
337 if (!FsOpenBootVolume())
338 {
339 #ifdef USE_UI
340 UiMessageBox("Failed to open boot drive.");
341 #else
342 printf("Failed to open boot drive.");
343 #endif
344 return;
345 }
346
347 /* FIXME: check volume label or disk marker file */
348 }
349
350
351 /* Get ANSI codepage file */
352 if (!InfFindFirstLine (InfHandle,
353 "NLS",
354 "AnsiCodepage",
355 &InfContext))
356 {
357 printf("Failed to find 'NLS/AnsiCodepage'\n");
358 return;
359 }
360
361 if (!InfGetDataField (&InfContext,
362 1,
363 &LoadOptions))
364 {
365 printf("Failed to get load options\n");
366 return;
367 }
368
369 /* Load ANSI codepage file */
370 if (!LoadNlsFile(SourcePath, LoadOptions, "ansi.nls"))
371 {
372 #ifdef USE_UI
373 UiMessageBox("Failed to load the ANSI codepage file.");
374 #else
375 printf("Failed to load the ANSI codepage file.");
376 #endif
377 return;
378 }
379
380 /* Get OEM codepage file */
381 if (!InfFindFirstLine (InfHandle,
382 "NLS",
383 "OemCodepage",
384 &InfContext))
385 {
386 printf("Failed to find 'NLS/AnsiCodepage'\n");
387 return;
388 }
389
390 if (!InfGetDataField (&InfContext,
391 1,
392 &LoadOptions))
393 {
394 printf("Failed to get load options\n");
395 return;
396 }
397
398 /* Load OEM codepage file */
399 if (!LoadNlsFile(SourcePath, LoadOptions, "oem.nls"))
400 {
401 #ifdef USE_UI
402 UiMessageBox("Failed to load the OEM codepage file.");
403 #else
404 printf("Failed to load the OEM codepage file.");
405 #endif
406 return;
407 }
408
409 /* Get Unicode Casemap file */
410 if (!InfFindFirstLine (InfHandle,
411 "NLS",
412 "UnicodeCasetable",
413 &InfContext))
414 {
415 printf("Failed to find 'NLS/AnsiCodepage'\n");
416 return;
417 }
418
419 if (!InfGetDataField (&InfContext,
420 1,
421 &LoadOptions))
422 {
423 printf("Failed to get load options\n");
424 return;
425 }
426
427 /* Load Unicode casemap file */
428 if (!LoadNlsFile(SourcePath, LoadOptions, "casemap.nls"))
429 {
430 #ifdef USE_UI
431 UiMessageBox("Failed to load the Unicode casemap file.");
432 #else
433 printf("Failed to load the Unicode casemap file.");
434 #endif
435 return;
436 }
437
438 #if 0
439 /* Load acpi.sys */
440 if (!LoadDriver(SourcePath, "acpi.sys"))
441 return;
442 #endif
443
444 #if 0
445 /* Load isapnp.sys */
446 if (!LoadDriver(SourcePath, "isapnp.sys"))
447 return;
448 #endif
449
450 #if 0
451 /* Load pci.sys */
452 if (!LoadDriver(SourcePath, "pci.sys"))
453 return;
454 #endif
455
456 /* Load scsiport.sys */
457 if (!LoadDriver(SourcePath, "scsiport.sys"))
458 return;
459
460 /* Load atapi.sys (depends on hardware detection) */
461 if (!LoadDriver(SourcePath, "atapi.sys"))
462 return;
463
464 /* Load buslogic.sys (depends on hardware detection) */
465 if (!LoadDriver(SourcePath, "buslogic.sys"))
466 return;
467
468 /* Load class2.sys */
469 if (!LoadDriver(SourcePath, "class2.sys"))
470 return;
471
472 /* Load cdrom.sys */
473 if (!LoadDriver(SourcePath, "cdrom.sys"))
474 return;
475
476 /* Load cdfs.sys */
477 if (!LoadDriver(SourcePath, "cdfs.sys"))
478 return;
479
480 /* Load disk.sys */
481 if (!LoadDriver(SourcePath, "disk.sys"))
482 return;
483
484 /* Load floppy.sys */
485 if (!LoadDriver(SourcePath, "floppy.sys"))
486 return;
487
488 /* Load vfatfs.sys (could be loaded by the setup prog!) */
489 if (!LoadDriver(SourcePath, "vfatfs.sys"))
490 return;
491
492
493 /* Load keyboard driver */
494 if (!LoadDriver(SourcePath, "i8042prt.sys"))
495 return;
496 if (!LoadDriver(SourcePath, "kbdclass.sys"))
497 return;
498
499 /* Load screen driver */
500 if (!LoadDriver(SourcePath, "blue.sys"))
501 return;
502
503 #ifdef USE_UI
504 UiUnInitialize("Booting ReactOS...");
505 #endif
506
507 /* Now boot the kernel */
508 DiskStopFloppyMotor();
509 MachVideoPrepareForReactOS(TRUE);
510 FrLdrStartup(0x2badb002);
511 }
512
513 /* EOF */