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