- Move ReactOS specific code to ReactOS specific files/directories.
[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 #include <freeldr.h>
22 #include <debug.h>
23 #include <arch.h>
24 #include <disk.h>
25 #include <reactos.h>
26 #include <rtl.h>
27 #include <fs.h>
28 #include <multiboot.h>
29 #include <mm.h>
30 #include <machine.h>
31 #include <ui.h>
32 #include <inffile.h>
33
34 #include "registry.h"
35
36 LOADER_PARAMETER_BLOCK LoaderBlock;
37 char reactos_kernel_cmdline[255]; // Command line passed to kernel
38 LOADER_MODULE reactos_modules[64]; // Array to hold boot module info loaded for the kernel
39 char reactos_module_strings[64][256]; // Array to hold module names
40 unsigned long reactos_memory_map_descriptor_size;
41 memory_map_t reactos_memory_map[32]; // Memory map
42
43 #define USE_UI
44
45
46 static BOOL
47 LoadKernel(PCHAR szSourcePath, PCHAR szFileName)
48 {
49 CHAR szFullName[256];
50 #ifdef USE_UI
51 CHAR szBuffer[80];
52 #endif
53 PFILE FilePointer;
54 PCHAR szShortName;
55
56 if (szSourcePath[0] != '\\')
57 {
58 strcpy(szFullName, "\\");
59 strcat(szFullName, szSourcePath);
60 }
61 else
62 {
63 strcpy(szFullName, szSourcePath);
64 }
65
66 if (szFullName[strlen(szFullName)] != '\\')
67 {
68 strcat(szFullName, "\\");
69 }
70
71 if (szFileName[0] != '\\')
72 {
73 strcat(szFullName, szFileName);
74 }
75 else
76 {
77 strcat(szFullName, szFileName + 1);
78 }
79
80 szShortName = strrchr(szFileName, '\\');
81 if (szShortName == NULL)
82 szShortName = szFileName;
83 else
84 szShortName = szShortName + 1;
85
86 FilePointer = FsOpenFile(szFullName);
87 if (FilePointer == NULL)
88 {
89 printf("Could not find %s\n", szShortName);
90 return(FALSE);
91 }
92
93 /*
94 * Update the status bar with the current file
95 */
96 #ifdef USE_UI
97 sprintf(szBuffer, "Setup is loading files (%s)", szShortName);
98 UiDrawStatusText(szBuffer);
99 #else
100 printf("Reading %s\n", szShortName);
101 #endif
102
103 /*
104 * Load the kernel
105 */
106 FrLdrMapKernel(FilePointer);
107
108 return(TRUE);
109 }
110
111
112 static BOOL
113 LoadDriver(PCHAR szSourcePath, PCHAR szFileName)
114 {
115 CHAR szFullName[256];
116 #ifdef USE_UI
117 CHAR szBuffer[80];
118 #endif
119 PFILE FilePointer;
120 PCHAR szShortName;
121
122 if (szSourcePath[0] != '\\')
123 {
124 strcpy(szFullName, "\\");
125 strcat(szFullName, szSourcePath);
126 }
127 else
128 {
129 strcpy(szFullName, szSourcePath);
130 }
131
132 if (szFullName[strlen(szFullName)] != '\\')
133 {
134 strcat(szFullName, "\\");
135 }
136
137 if (szFileName[0] != '\\')
138 {
139 strcat(szFullName, szFileName);
140 }
141 else
142 {
143 strcat(szFullName, szFileName + 1);
144 }
145
146 szShortName = strrchr(szFileName, '\\');
147 if (szShortName == NULL)
148 szShortName = szFileName;
149 else
150 szShortName = szShortName + 1;
151
152
153 FilePointer = FsOpenFile(szFullName);
154 if (FilePointer == NULL)
155 {
156 printf("Could not find %s\n", szFileName);
157 return(FALSE);
158 }
159
160 /*
161 * Update the status bar with the current file
162 */
163 #ifdef USE_UI
164 sprintf(szBuffer, "Setup is loading files (%s)", szShortName);
165 UiDrawStatusText(szBuffer);
166 #else
167 printf("Reading %s\n", szShortName);
168 #endif
169
170 /* Load the driver */
171 FrLdrLoadModule(FilePointer, szFileName, NULL);
172
173 return(TRUE);
174 }
175
176
177 static BOOL
178 LoadNlsFile(PCHAR szSourcePath, PCHAR szFileName, PCHAR szModuleName)
179 {
180 CHAR szFullName[256];
181 #ifdef USE_UI
182 CHAR szBuffer[80];
183 #endif
184 PFILE FilePointer;
185 PCHAR szShortName;
186
187 if (szSourcePath[0] != '\\')
188 {
189 strcpy(szFullName, "\\");
190 strcat(szFullName, szSourcePath);
191 }
192 else
193 {
194 strcpy(szFullName, szSourcePath);
195 }
196
197 if (szFullName[strlen(szFullName)] != '\\')
198 {
199 strcat(szFullName, "\\");
200 }
201
202 if (szFileName[0] != '\\')
203 {
204 strcat(szFullName, szFileName);
205 }
206 else
207 {
208 strcat(szFullName, szFileName + 1);
209 }
210
211 szShortName = strrchr(szFileName, '\\');
212 if (szShortName == NULL)
213 szShortName = szFileName;
214 else
215 szShortName = szShortName + 1;
216
217
218 FilePointer = FsOpenFile(szFullName);
219 if (FilePointer == NULL)
220 {
221 printf("Could not find %s\n", szFileName);
222 return(FALSE);
223 }
224
225 /*
226 * Update the status bar with the current file
227 */
228 #ifdef USE_UI
229 sprintf(szBuffer, "Setup is loading files (%s)", szShortName);
230 UiDrawStatusText(szBuffer);
231 #else
232 printf("Reading %s\n", szShortName);
233 #endif
234
235 /* Load the driver */
236 FrLdrLoadModule(FilePointer, szModuleName, NULL);
237
238 return(TRUE);
239 }
240
241 BOOL SetupUiInitialize(VOID);
242
243 VOID RunLoader(VOID)
244 {
245 ULONG_PTR Base;
246 ULONG Size;
247 char *SourcePath;
248 char *LoadOptions;
249 UINT i;
250
251 HINF InfHandle;
252 ULONG ErrorLine;
253 INFCONTEXT InfContext;
254
255 extern ULONG PageDirectoryStart;
256 extern ULONG PageDirectoryEnd;
257
258 /* Setup multiboot information structure */
259 LoaderBlock.Flags = MB_FLAGS_BOOT_DEVICE | MB_FLAGS_COMMAND_LINE | MB_FLAGS_MODULE_INFO;
260 LoaderBlock.PageDirectoryStart = (ULONG)&PageDirectoryStart;
261 LoaderBlock.PageDirectoryEnd = (ULONG)&PageDirectoryEnd;
262 LoaderBlock.BootDevice = 0xffffffff;
263 LoaderBlock.CommandLine = (unsigned long)reactos_kernel_cmdline;
264 LoaderBlock.ModsCount = 0;
265 LoaderBlock.ModsAddr = (unsigned long)reactos_modules;
266 LoaderBlock.MmapLength = (unsigned long)MachGetMemoryMap((PBIOS_MEMORY_MAP)(PVOID)&reactos_memory_map, 32) * sizeof(memory_map_t);
267 if (LoaderBlock.MmapLength)
268 {
269 LoaderBlock.MmapAddr = (unsigned long)&reactos_memory_map;
270 LoaderBlock.Flags |= MB_FLAGS_MEM_INFO | MB_FLAGS_MMAP_INFO;
271 reactos_memory_map_descriptor_size = sizeof(memory_map_t); // GetBiosMemoryMap uses a fixed value of 24
272 for (i = 0; i < (LoaderBlock.MmapLength / sizeof(memory_map_t)); i++)
273 {
274 if (MEMTYPE_USABLE == reactos_memory_map[i].type &&
275 0 == reactos_memory_map[i].base_addr_low)
276 {
277 LoaderBlock.MemLower = (reactos_memory_map[i].base_addr_low + reactos_memory_map[i].length_low) / 1024;
278 if (640 < LoaderBlock.MemLower)
279 {
280 LoaderBlock.MemLower = 640;
281 }
282 }
283 if (MEMTYPE_USABLE == reactos_memory_map[i].type &&
284 reactos_memory_map[i].base_addr_low <= 1024 * 1024 &&
285 1024 * 1024 <= reactos_memory_map[i].base_addr_low + reactos_memory_map[i].length_low)
286 {
287 LoaderBlock.MemHigher = (reactos_memory_map[i].base_addr_low + reactos_memory_map[i].length_low) / 1024 - 1024;
288 }
289 #if 0
290 printf("start: %x\t size: %x\t type %d\n",
291 reactos_memory_map[i].base_addr_low,
292 reactos_memory_map[i].length_low,
293 reactos_memory_map[i].type);
294 #endif
295 }
296 }
297 #if 0
298 printf("low_mem = %d\n", LoaderBlock.MemLower);
299 printf("high_mem = %d\n", LoaderBlock.MemHigher);
300 MachConsGetCh();
301 #endif
302
303 #ifdef USE_UI
304 SetupUiInitialize();
305 UiDrawStatusText("");
306 #endif
307
308 /* Initialize registry */
309 RegInitializeRegistry();
310
311 /* Detect hardware */
312 #ifdef USE_UI
313 UiDrawStatusText("Detecting hardware...");
314 #else
315 printf("Detecting hardware...\n\n");
316 #endif
317 MachHwDetect();
318 #ifdef USE_UI
319 UiDrawStatusText("");
320 #endif
321
322 /* set boot device */
323 MachDiskGetBootDevice(&LoaderBlock.BootDevice);
324
325 /* Open boot drive */
326 if (!FsOpenBootVolume())
327 {
328 #ifdef USE_UI
329 UiMessageBox("Failed to open boot drive.");
330 #else
331 printf("Failed to open boot drive.");
332 #endif
333 return;
334 }
335
336 /* Open 'txtsetup.sif' */
337 if (!InfOpenFile (&InfHandle,
338 MachDiskBootingFromFloppy() ? "\\txtsetup.sif" : "\\reactos\\txtsetup.sif",
339 &ErrorLine))
340 {
341 printf("Failed to open 'txtsetup.sif'\n");
342 return;
343 }
344
345 /* Get load options */
346 if (!InfFindFirstLine (InfHandle,
347 "SetupData",
348 "OsLoadOptions",
349 &InfContext))
350 {
351 printf("Failed to find 'SetupData/OsLoadOptions'\n");
352 return;
353 }
354
355 if (!InfGetDataField (&InfContext,
356 1,
357 &LoadOptions))
358 {
359 printf("Failed to get load options\n");
360 return;
361 }
362 #if 0
363 printf("LoadOptions: '%s'\n", LoadOptions);
364 #endif
365
366 if (MachDiskBootingFromFloppy())
367 {
368 /* Boot from floppy disk */
369 SourcePath = "\\";
370 }
371 else
372 {
373 /* Boot from cdrom */
374 SourcePath = "\\reactos";
375 }
376
377 /* Set kernel command line */
378 MachDiskGetBootPath(reactos_kernel_cmdline, sizeof(reactos_kernel_cmdline));
379 strcat(strcat(strcat(reactos_kernel_cmdline, SourcePath), " "),
380 LoadOptions);
381
382 /* Load ntoskrnl.exe */
383 if (!LoadKernel(SourcePath, "ntoskrnl.exe"))
384 return;
385
386
387 /* Load hal.dll */
388 if (!LoadDriver(SourcePath, "hal.dll"))
389 return;
390
391
392 /* Export the hardware hive */
393 Base = FrLdrCreateModule ("HARDWARE");
394 RegExportBinaryHive ("\\Registry\\Machine\\HARDWARE", (PVOID)Base, &Size);
395 FrLdrCloseModule (Base, Size);
396
397 #if 0
398 printf("Base: %x\n", Base);
399 printf("Size: %u\n", Size);
400 printf("*** System stopped ***\n");
401 for(;;);
402 #endif
403
404 /* Insert boot disk 2 */
405 if (MachDiskBootingFromFloppy())
406 {
407 #ifdef USE_UI
408 UiMessageBox("Please insert \"ReactOS Boot Disk 2\" and press ENTER");
409 #else
410 printf("\n\n Please insert \"ReactOS Boot Disk 2\" and press ENTER\n");
411 MachConsGetCh();
412 #endif
413
414 /* Open boot drive */
415 if (!FsOpenBootVolume())
416 {
417 #ifdef USE_UI
418 UiMessageBox("Failed to open boot drive.");
419 #else
420 printf("Failed to open boot drive.");
421 #endif
422 return;
423 }
424
425 /* FIXME: check volume label or disk marker file */
426 }
427
428
429 /* Get ANSI codepage file */
430 if (!InfFindFirstLine (InfHandle,
431 "NLS",
432 "AnsiCodepage",
433 &InfContext))
434 {
435 printf("Failed to find 'NLS/AnsiCodepage'\n");
436 return;
437 }
438
439 if (!InfGetDataField (&InfContext,
440 1,
441 &LoadOptions))
442 {
443 printf("Failed to get load options\n");
444 return;
445 }
446
447 /* Load ANSI codepage file */
448 if (!LoadNlsFile(SourcePath, LoadOptions, "ansi.nls"))
449 {
450 #ifdef USE_UI
451 UiMessageBox("Failed to load the ANSI codepage file.");
452 #else
453 printf("Failed to load the ANSI codepage file.");
454 #endif
455 return;
456 }
457
458 /* Get OEM codepage file */
459 if (!InfFindFirstLine (InfHandle,
460 "NLS",
461 "OemCodepage",
462 &InfContext))
463 {
464 printf("Failed to find 'NLS/AnsiCodepage'\n");
465 return;
466 }
467
468 if (!InfGetDataField (&InfContext,
469 1,
470 &LoadOptions))
471 {
472 printf("Failed to get load options\n");
473 return;
474 }
475
476 /* Load OEM codepage file */
477 if (!LoadNlsFile(SourcePath, LoadOptions, "oem.nls"))
478 {
479 #ifdef USE_UI
480 UiMessageBox("Failed to load the OEM codepage file.");
481 #else
482 printf("Failed to load the OEM codepage file.");
483 #endif
484 return;
485 }
486
487 /* Get Unicode Casemap file */
488 if (!InfFindFirstLine (InfHandle,
489 "NLS",
490 "UnicodeCasetable",
491 &InfContext))
492 {
493 printf("Failed to find 'NLS/AnsiCodepage'\n");
494 return;
495 }
496
497 if (!InfGetDataField (&InfContext,
498 1,
499 &LoadOptions))
500 {
501 printf("Failed to get load options\n");
502 return;
503 }
504
505 /* Load Unicode casemap file */
506 if (!LoadNlsFile(SourcePath, LoadOptions, "casemap.nls"))
507 {
508 #ifdef USE_UI
509 UiMessageBox("Failed to load the Unicode casemap file.");
510 #else
511 printf("Failed to load the Unicode casemap file.");
512 #endif
513 return;
514 }
515
516 #if 0
517 /* Load acpi.sys */
518 if (!LoadDriver(SourcePath, "acpi.sys"))
519 return;
520 #endif
521
522 #if 0
523 /* Load isapnp.sys */
524 if (!LoadDriver(SourcePath, "isapnp.sys"))
525 return;
526 #endif
527
528 #if 0
529 /* Load pci.sys */
530 if (!LoadDriver(SourcePath, "pci.sys"))
531 return;
532 #endif
533
534 /* Load scsiport.sys */
535 if (!LoadDriver(SourcePath, "scsiport.sys"))
536 return;
537
538 /* Load atapi.sys (depends on hardware detection) */
539 if (!LoadDriver(SourcePath, "atapi.sys"))
540 return;
541
542 /* Load class2.sys */
543 if (!LoadDriver(SourcePath, "class2.sys"))
544 return;
545
546 /* Load cdrom.sys */
547 if (!LoadDriver(SourcePath, "cdrom.sys"))
548 return;
549
550 /* Load cdfs.sys */
551 if (!LoadDriver(SourcePath, "cdfs.sys"))
552 return;
553
554 /* Load disk.sys */
555 if (!LoadDriver(SourcePath, "disk.sys"))
556 return;
557
558 /* Load floppy.sys */
559 if (!LoadDriver(SourcePath, "floppy.sys"))
560 return;
561
562 /* Load vfatfs.sys (could be loaded by the setup prog!) */
563 if (!LoadDriver(SourcePath, "vfatfs.sys"))
564 return;
565
566
567 /* Load keyboard driver */
568 #if 0
569 if (!LoadDriver(SourcePath, "keyboard.sys"))
570 return;
571 #endif
572 if (!LoadDriver(SourcePath, "i8042prt.sys"))
573 return;
574 if (!LoadDriver(SourcePath, "kbdclass.sys"))
575 return;
576
577 /* Load screen driver */
578 if (!LoadDriver(SourcePath, "blue.sys"))
579 return;
580
581 #ifdef USE_UI
582 UiUnInitialize("Booting ReactOS...");
583 #endif
584
585 /* Now boot the kernel */
586 DiskStopFloppyMotor();
587 MachVideoPrepareForReactOS();
588 FrLdrStartup(0x2badb002);
589 }
590
591 /* EOF */