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