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