Changes in v1.7.11 (12/05/2002) (brianp)
[reactos.git] / freeldr / freeldr / reactos / reactos.c
1 /*
2 * FreeLoader
3 *
4 * Copyright (C) 1998-2002 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 <reactos.h>
25 #include <rtl.h>
26 #include <disk.h>
27 #include <fs.h>
28 #include <ui.h>
29 #include <multiboot.h>
30 #include <mm.h>
31 #include <inifile.h>
32
33 #include "registry.h"
34 #include "hwdetect.h"
35
36
37 #define NDEBUG
38
39
40 static BOOL
41 LoadKernel(PCHAR szFileName, int nPos)
42 {
43 PFILE FilePointer;
44 PCHAR szShortName;
45 char szBuffer[256];
46
47 szShortName = strrchr(szFileName, '\\');
48 if (szShortName == NULL)
49 szShortName = szFileName;
50 else
51 szShortName = szShortName + 1;
52
53 FilePointer = FsOpenFile(szFileName);
54 if (FilePointer == NULL)
55 {
56 strcpy(szBuffer, szShortName);
57 strcat(szBuffer, " not found.");
58 UiMessageBox(szBuffer);
59 return(FALSE);
60 }
61
62 /*
63 * Update the status bar with the current file
64 */
65 strcpy(szBuffer, "Reading ");
66 strcat(szBuffer, szShortName);
67 UiDrawStatusText(szBuffer);
68
69 /*
70 * Load the kernel
71 */
72 MultiBootLoadKernel(FilePointer);
73
74 UiDrawProgressBarCenter(nPos, 100);
75
76 return(TRUE);
77 }
78
79 static BOOL
80 LoadSymbolFile(PCHAR szSystemRoot,
81 PCHAR ModuleName,
82 int nPos)
83 {
84 CHAR SymbolFileName[1024];
85 PFILE FilePointer;
86 U32 Length;
87 PCHAR Start;
88 PCHAR Ext;
89 char value[256];
90 char *p;
91
92 /* Get the path to the symbol store */
93 strcpy(SymbolFileName, szSystemRoot);
94 strcat(SymbolFileName, "symbols\\");
95
96 /* Get the symbol filename from the module name */
97 Start = strrchr(ModuleName, '\\');
98 if (Start == NULL)
99 Start = ModuleName;
100 else
101 Start++;
102
103 Ext = strrchr(ModuleName, '.');
104 if (Ext != NULL)
105 Length = Ext - Start;
106 else
107 Length = strlen(Start);
108
109 strncat(SymbolFileName, Start, Length);
110 strcat(SymbolFileName, ".sym");
111
112 FilePointer = FsOpenFile((PCHAR)&SymbolFileName[0]);
113 if (FilePointer == NULL)
114 {
115 DbgPrint((DPRINT_REACTOS, "Symbol file %s not loaded.\n", SymbolFileName));
116 /* This is not critical */
117 return FALSE;
118 }
119
120 DbgPrint((DPRINT_REACTOS, "Symbol file %s is loaded.\n", SymbolFileName));
121
122 /*
123 * Update the status bar with the current file
124 */
125 strcpy(value, "Reading ");
126 p = strrchr(SymbolFileName, '\\');
127 if (p == NULL)
128 strcat(value, SymbolFileName);
129 else
130 strcat(value, p + 1);
131 UiDrawStatusText(value);
132
133 /*
134 * Load the symbol file
135 */
136 MultiBootLoadModule(FilePointer, SymbolFileName, NULL);
137
138 UiDrawProgressBarCenter(nPos, 100);
139
140 return (TRUE);
141 }
142
143 static BOOL
144 LoadDriver(PCHAR szFileName, int nPos)
145 {
146 PFILE FilePointer;
147 char value[256];
148 char *p;
149
150 FilePointer = FsOpenFile(szFileName);
151 if (FilePointer == NULL)
152 {
153 strcpy(value, szFileName);
154 strcat(value, " not found.");
155 UiMessageBox(value);
156 return(FALSE);
157 }
158
159 /*
160 * Update the status bar with the current file
161 */
162 strcpy(value, "Reading ");
163 p = strrchr(szFileName, '\\');
164 if (p == NULL)
165 strcat(value, szFileName);
166 else
167 strcat(value, p + 1);
168 UiDrawStatusText(value);
169
170 /*
171 * Load the driver
172 */
173 MultiBootLoadModule(FilePointer, szFileName, NULL);
174
175 UiDrawProgressBarCenter(nPos, 100);
176
177 return(TRUE);
178 }
179
180
181 #if 0
182 static BOOL
183 LoadNlsFile(PCHAR szFileName, PCHAR szModuleName)
184 {
185 PFILE FilePointer;
186 char value[256];
187 char *p;
188
189 FilePointer = FsOpenFile(szFileName);
190 if (FilePointer == NULL)
191 {
192 strcpy(value, szFileName);
193 strcat(value, " not found.");
194 UiMessageBox(value);
195 return(FALSE);
196 }
197
198 /*
199 * Update the status bar with the current file
200 */
201 strcpy(value, "Reading ");
202 p = strrchr(szFileName, '\\');
203 if (p == NULL)
204 strcat(value, szFileName);
205 else
206 strcat(value, p + 1);
207 UiDrawStatusText(value);
208
209 /*
210 * Load the driver
211 */
212 MultiBootLoadModule(FilePointer, szModuleName, NULL);
213
214 return(TRUE);
215 }
216 #endif
217
218
219 static VOID
220 LoadBootDrivers(PCHAR szSystemRoot, int nPos)
221 {
222 S32 rc = 0;
223 HKEY hGroupKey, hServiceKey, hDriverKey;
224 char ValueBuffer[512];
225 char ServiceName[256];
226 U32 BufferSize;
227 U32 Index;
228 char *GroupName;
229
230 U32 ValueSize;
231 U32 ValueType;
232 U32 StartValue;
233 UCHAR DriverGroup[256];
234 U32 DriverGroupSize;
235
236 UCHAR ImagePath[256];
237
238 /* get 'service group order' key */
239 rc = RegOpenKey(NULL,
240 "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ServiceGroupOrder",
241 &hGroupKey);
242 if (rc != ERROR_SUCCESS)
243 {
244 DbgPrint((DPRINT_REACTOS, "Failed to open the 'ServiceGroupOrder key (rc %d)\n", (int)rc));
245 return;
246 }
247
248 /* enumerate drivers */
249 rc = RegOpenKey(NULL,
250 "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services",
251 &hServiceKey);
252 if (rc != ERROR_SUCCESS)
253 {
254 DbgPrint((DPRINT_REACTOS, "Failed to open the 'Services' key (rc %d)\n", (int)rc));
255 return;
256 }
257
258 BufferSize = sizeof(ValueBuffer);
259 rc = RegQueryValue(hGroupKey, "List", NULL, (PUCHAR)ValueBuffer, &BufferSize);
260 DbgPrint((DPRINT_REACTOS, "RegQueryValue(): rc %d\n", (int)rc));
261 if (rc != ERROR_SUCCESS)
262 return;
263
264 DbgPrint((DPRINT_REACTOS, "BufferSize: %d \n", (int)BufferSize));
265
266 DbgPrint((DPRINT_REACTOS, "ValueBuffer: '%s' \n", ValueBuffer));
267
268 GroupName = ValueBuffer;
269 while (*GroupName)
270 {
271 DbgPrint((DPRINT_REACTOS, "Driver group: '%s'\n", GroupName));
272
273 /* enumerate all drivers */
274 Index = 0;
275 while (TRUE)
276 {
277 ValueSize = sizeof(ValueBuffer);
278 rc = RegEnumKey(hServiceKey, Index, ServiceName, &ValueSize);
279 DbgPrint((DPRINT_REACTOS, "RegEnumKey(): rc %d\n", (int)rc));
280 if (rc == ERROR_NO_MORE_ITEMS)
281 break;
282 if (rc != ERROR_SUCCESS)
283 return;
284 DbgPrint((DPRINT_REACTOS, "Service %d: '%s'\n", (int)Index, ServiceName));
285
286 /* open driver Key */
287 rc = RegOpenKey(hServiceKey, ServiceName, &hDriverKey);
288
289 ValueSize = sizeof(U32);
290 rc = RegQueryValue(hDriverKey, "Start", &ValueType, (PUCHAR)&StartValue, &ValueSize);
291 DbgPrint((DPRINT_REACTOS, " Start: %x \n", (int)StartValue));
292
293 DriverGroupSize = 256;
294 rc = RegQueryValue(hDriverKey, "Group", NULL, (PUCHAR)DriverGroup, &DriverGroupSize);
295 DbgPrint((DPRINT_REACTOS, " Group: '%s' \n", DriverGroup));
296
297 if ((StartValue == 0) && (stricmp(DriverGroup, GroupName) == 0))
298 {
299 ValueSize = 256;
300 rc = RegQueryValue(hDriverKey,
301 "ImagePathName",
302 NULL,
303 (PUCHAR)ImagePath,
304 &ValueSize);
305 if (rc != ERROR_SUCCESS)
306 {
307 DbgPrint((DPRINT_REACTOS, " ImagePath: not found\n"));
308 strcpy(ImagePath, szSystemRoot);
309 strcat(ImagePath, "system32\\drivers\\");
310 strcat(ImagePath, ServiceName);
311 strcat(ImagePath, ".sys");
312 }
313 else
314 {
315 DbgPrint((DPRINT_REACTOS, " ImagePath: '%s'\n", ImagePath));
316 }
317 DbgPrint((DPRINT_REACTOS, " Loading driver: '%s'\n", ImagePath));
318
319 if (nPos < 100)
320 nPos += 5;
321
322 LoadDriver(ImagePath, nPos);
323 LoadSymbolFile(szSystemRoot, ImagePath, nPos);
324 }
325 else
326 {
327 DbgPrint((DPRINT_REACTOS, " Skipping driver '%s' with Start %d and Group '%s' (Current group '%s')\n",
328 ImagePath, StartValue, DriverGroup, GroupName));
329 }
330 Index++;
331 }
332
333 GroupName = GroupName + strlen(GroupName) + 1;
334 }
335 }
336
337 #if 0
338 static BOOL
339 LoadNlsFiles(PCHAR szSystemRoot)
340 {
341 S32 rc = ERROR_SUCCESS;
342 HKEY hKey;
343 char szIdBuffer[80];
344 char szNameBuffer[80];
345 char szFileName[256];
346 U32 BufferSize;
347
348 /* open the codepage key */
349 rc = RegOpenKey(NULL,
350 "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage",
351 &hKey);
352 if (rc != ERROR_SUCCESS)
353 return(FALSE);
354
355
356 /* get ANSI codepage */
357 BufferSize = 80;
358 rc = RegQueryValue(hKey, "ACP", NULL, (PUCHAR)szIdBuffer, &BufferSize);
359 if (rc != ERROR_SUCCESS)
360 return(FALSE);
361
362 BufferSize = 80;
363 rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)szNameBuffer, &BufferSize);
364 if (rc != ERROR_SUCCESS)
365 return(FALSE);
366
367
368 /* load ANSI codepage table */
369 strcpy(szFileName, szSystemRoot);
370 strcat(szFileName, "system32\\");
371 strcat(szFileName, szNameBuffer);
372 if (!LoadNlsFile(szFileName, "ANSI.NLS"))
373 return(FALSE);
374
375
376 /* get OEM codepage */
377 BufferSize = 80;
378 rc = RegQueryValue(hKey, "OEMCP", NULL, (PUCHAR)szIdBuffer, &BufferSize);
379 if (rc != ERROR_SUCCESS)
380 return(FALSE);
381
382 BufferSize = 80;
383 rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)szNameBuffer, &BufferSize);
384 if (rc != ERROR_SUCCESS)
385 return(FALSE);
386
387 /* load OEM codepage table */
388 strcpy(szFileName, szSystemRoot);
389 strcat(szFileName, "system32\\");
390 strcat(szFileName, szNameBuffer);
391 if (!LoadNlsFile(szFileName, "OEM.NLS"))
392 return(FALSE);
393
394
395 /* open the language key */
396 rc = RegOpenKey(NULL,
397 "\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\Language",
398 &hKey);
399 if (rc != ERROR_SUCCESS)
400 return(FALSE);
401
402
403 /* get the Unicode case table */
404 BufferSize = 80;
405 rc = RegQueryValue(hKey, "Default", NULL, (PUCHAR)szIdBuffer, &BufferSize);
406 if (rc != ERROR_SUCCESS)
407 return(FALSE);
408
409 BufferSize = 80;
410 rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)szNameBuffer, &BufferSize);
411 if (rc != ERROR_SUCCESS)
412 return(FALSE);
413
414 /* load Unicode case table */
415 strcpy(szFileName, szSystemRoot);
416 strcat(szFileName, "system32\\");
417 strcat(szFileName, szNameBuffer);
418 if (!LoadNlsFile(szFileName, "UNICASE.NLS"))
419 return(FALSE);
420
421 return(TRUE);
422 }
423 #endif
424
425
426 void
427 LoadAndBootReactOS(PUCHAR OperatingSystemName)
428 {
429 PFILE FilePointer;
430 char name[1024];
431 char value[1024];
432 char szKernelName[1024];
433 char szHalName[1024];
434 char szFileName[1024];
435 char szBootPath[256];
436 int i;
437 // int nNumDriverFiles=0;
438 // int nNumFilesLoaded=0;
439 char MsgBuffer[256];
440 U32 SectionId;
441
442 char* Base;
443 U32 Size;
444
445
446 //
447 // Open the operating system section
448 // specified in the .ini file
449 //
450 if (!IniOpenSection(OperatingSystemName, &SectionId))
451 {
452 sprintf(MsgBuffer,"Operating System section '%s' not found in freeldr.ini", OperatingSystemName);
453 UiMessageBox(MsgBuffer);
454 return;
455 }
456
457 /*
458 * Setup multiboot information structure
459 */
460 mb_info.flags = MB_INFO_FLAG_MEM_SIZE | MB_INFO_FLAG_BOOT_DEVICE | MB_INFO_FLAG_COMMAND_LINE | MB_INFO_FLAG_MODULES;
461 mb_info.mem_lower = GetConventionalMemorySize();
462 mb_info.mem_upper = GetExtendedMemorySize();
463 mb_info.boot_device = 0xffffffff;
464 mb_info.cmdline = (unsigned long)multiboot_kernel_cmdline;
465 mb_info.mods_count = 0;
466 mb_info.mods_addr = (unsigned long)multiboot_modules;
467 mb_info.mmap_length = (unsigned long)GetBiosMemoryMap((PBIOS_MEMORY_MAP)&multiboot_memory_map, 32) * sizeof(memory_map_t);
468 if (mb_info.mmap_length)
469 {
470 mb_info.mmap_addr = (unsigned long)&multiboot_memory_map;
471 mb_info.flags |= MB_INFO_FLAG_MEMORY_MAP;
472 multiboot_memory_map_descriptor_size = sizeof(memory_map_t); // GetBiosMemoryMap uses a fixed value of 24
473 DbgPrint((DPRINT_REACTOS, "memory map length: %d\n", mb_info.mmap_length));
474 DbgPrint((DPRINT_REACTOS, "dumping memory map:\n"));
475 for (i=0; i<(mb_info.mmap_length/sizeof(memory_map_t)); i++)
476 {
477 DbgPrint((DPRINT_REACTOS, "start: %x\t size: %x\t type %d\n",
478 multiboot_memory_map[i].base_addr_low,
479 multiboot_memory_map[i].length_low,
480 multiboot_memory_map[i].type));
481 }
482 }
483 DbgPrint((DPRINT_REACTOS, "low_mem = %d\n", mb_info.mem_lower));
484 DbgPrint((DPRINT_REACTOS, "high_mem = %d\n", mb_info.mem_upper));
485
486 /*
487 * Make sure the system path is set in the .ini file
488 */
489 if (!IniReadSettingByName(SectionId, "SystemPath", value, 1024))
490 {
491 UiMessageBox("System path not specified for selected operating system.");
492 return;
493 }
494
495 /*
496 * Verify system path
497 */
498 if (!DissectArcPath(value, szBootPath, &BootDrive, &BootPartition))
499 {
500 sprintf(MsgBuffer,"Invalid system path: '%s'", value);
501 UiMessageBox(MsgBuffer);
502 return;
503 }
504
505 /* set boot drive and partition */
506 ((char *)(&mb_info.boot_device))[0] = (char)BootDrive;
507 ((char *)(&mb_info.boot_device))[1] = (char)BootPartition;
508
509 /* copy ARC path into kernel command line */
510 strcpy(multiboot_kernel_cmdline, value);
511
512 /*
513 * Read the optional kernel parameters (if any)
514 */
515 if (IniReadSettingByName(SectionId, "Options", value, 1024))
516 {
517 strcat(multiboot_kernel_cmdline, " ");
518 strcat(multiboot_kernel_cmdline, value);
519 }
520
521 /* append a backslash */
522 if ((strlen(szBootPath)==0) ||
523 szBootPath[strlen(szBootPath)] != '\\')
524 strcat(szBootPath, "\\");
525
526 DbgPrint((DPRINT_REACTOS,"SystemRoot: '%s'\n", szBootPath));
527
528 UiDrawBackdrop();
529 UiDrawStatusText("Loading...");
530 UiDrawProgressBarCenter(0, 100);
531
532 /*
533 * Try to open boot drive
534 */
535 if (!FsOpenVolume(BootDrive, BootPartition))
536 {
537 UiMessageBox("Failed to open boot drive.");
538 return;
539 }
540
541 /*
542 * Find the kernel image name
543 * and try to load the kernel off the disk
544 */
545 if(IniReadSettingByName(SectionId, "Kernel", value, 1024))
546 {
547 /*
548 * Set the name and
549 */
550 if (value[0] == '\\')
551 {
552 strcpy(szKernelName, value);
553 }
554 else
555 {
556 strcpy(szKernelName, szBootPath);
557 strcat(szKernelName, "SYSTEM32\\");
558 strcat(szKernelName, value);
559 }
560 }
561 else
562 {
563 strcpy(value, "NTOSKRNL.EXE");
564 strcpy(szKernelName, szBootPath);
565 strcat(szKernelName, "SYSTEM32\\");
566 strcat(szKernelName, value);
567 }
568
569 if (!LoadKernel(szKernelName, 5))
570 return;
571
572 /*
573 * Find the HAL image name
574 * and try to load the kernel off the disk
575 */
576 if(IniReadSettingByName(SectionId, "Hal", value, 1024))
577 {
578 /*
579 * Set the name and
580 */
581 if (value[0] == '\\')
582 {
583 strcpy(szHalName, value);
584 }
585 else
586 {
587 strcpy(szHalName, szBootPath);
588 strcat(szHalName, "SYSTEM32\\");
589 strcat(szHalName, value);
590 }
591 }
592 else
593 {
594 strcpy(value, "HAL.DLL");
595 strcpy(szHalName, szBootPath);
596 strcat(szHalName, "SYSTEM32\\");
597 strcat(szHalName, value);
598 }
599
600 if (!LoadDriver(szHalName, 10))
601 return;
602
603 /*
604 * Find the System hive image name
605 * and try to load it off the disk
606 */
607 if(IniReadSettingByName(SectionId, "SystemHive", value, 1024))
608 {
609 /*
610 * Set the name and
611 */
612 if (value[0] == '\\')
613 {
614 strcpy(szFileName, value);
615 }
616 else
617 {
618 strcpy(szFileName, szBootPath);
619 strcat(szFileName, "SYSTEM32\\CONFIG\\");
620 strcat(szFileName, value);
621 }
622 }
623 else
624 {
625 strcpy(value, "SYSTEM.HIV");
626 strcpy(szFileName, szBootPath);
627 strcat(szFileName, "SYSTEM32\\CONFIG\\");
628 strcat(szFileName, value);
629 }
630
631 DbgPrint((DPRINT_REACTOS, "SystemHive: '%s'", szFileName));
632
633 FilePointer = FsOpenFile(szFileName);
634 if (FilePointer == NULL)
635 {
636 strcat(value, " not found.");
637 UiMessageBox(value);
638 return;
639 }
640
641 /*
642 * Update the status bar with the current file
643 */
644 strcpy(name, "Reading ");
645 strcat(name, value);
646 while (strlen(name) < 80)
647 strcat(name, " ");
648 UiDrawStatusText(name);
649
650 /*
651 * Load the system hive
652 */
653 Base = MultiBootLoadModule(FilePointer, szFileName, &Size);
654 RegInitializeRegistry();
655 RegImportHive(Base, Size);
656
657 UiDrawProgressBarCenter(15, 100);
658 DbgPrint((DPRINT_REACTOS, "SystemHive loaded at 0x%x size %u", (unsigned)Base, (unsigned)Size));
659
660 /*
661 * Retrieve hardware information and create the hardware hive
662 */
663 DetectHardware();
664 #if 0
665 Base = MultiBootCreateModule(HARDWARE.HIV);
666 RegExportHive("\\Registry\\Machine\\HARDWARE", Base, &Size);
667 MultiBootCloseModule(Base, Size);
668 #endif
669 UiDrawProgressBarCenter(20, 100);
670
671 /*
672 * Initialize the 'currentControlSet' link
673 */
674 RegInitCurrentControlSet(FALSE);
675
676 /*
677 * Load NLS files
678 */
679 #if 0
680 if (!LoadNlsFiles(szBootPath))
681 {
682 MessageBox("Failed to load NLS files\n");
683 return;
684 }
685 #endif
686
687 LoadSymbolFile(szBootPath, szKernelName, 25);
688 LoadSymbolFile(szBootPath, szHalName, 25);
689
690 UiDrawProgressBarCenter(25, 100);
691
692 /*
693 * Load boot drivers
694 */
695 LoadBootDrivers(szBootPath, 25);
696
697
698 /*
699 * Clear the screen and redraw the backdrop and status bar
700 */
701 UiDrawBackdrop();
702 UiDrawStatusText("Press any key to boot");
703
704 /*
705 * Wait for user
706 */
707 strcpy(name, "Kernel and Drivers loaded.\nPress any key to boot ");
708 strcat(name, OperatingSystemName);
709 strcat(name, ".");
710 //MessageBox(name);
711
712
713 UiUnInitialize("Booting ReactOS...");
714
715 /*
716 * Now boot the kernel
717 */
718 DiskStopFloppyMotor();
719 boot_reactos();
720 }
721
722 /* EOF */