- Use WinXP style /SOS output when enabled. (TODO: Display banner/memory/cpu).
[reactos.git] / reactos / boot / freeldr / freeldr / reactos / reactos.c
1 /*
2 * FreeLoader
3 *
4 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
5 * Copyright (C) 2005 Alex Ionescu <alex@relsoft.net>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include <freeldr.h>
23
24 #define NDEBUG
25 #include <debug.h>
26
27 ROS_LOADER_PARAMETER_BLOCK LoaderBlock;
28 char reactos_kernel_cmdline[255]; // Command line passed to kernel
29 LOADER_MODULE reactos_modules[64]; // Array to hold boot module info loaded for the kernel
30 char reactos_module_strings[64][256]; // Array to hold module names
31 unsigned long reactos_memory_map_descriptor_size;
32 memory_map_t reactos_memory_map[32]; // Memory map
33 ARC_DISK_SIGNATURE reactos_arc_disk_info[32]; // ARC Disk Information
34 char reactos_arc_strings[32][256];
35 unsigned long reactos_disk_count = 0;
36 CHAR szHalName[255];
37 CHAR szBootPath[255];
38 static CHAR szLoadingMsg[] = "Loading ReactOS...";
39 BOOLEAN FrLdrBootType;
40
41 static BOOLEAN
42 NTAPI
43 FrLdrLoadKernel(PCHAR szFileName,
44 INT nPos)
45 {
46 PFILE FilePointer;
47 PCHAR szShortName;
48 CHAR szBuffer[256];
49
50 /* Extract Kernel filename without path */
51 szShortName = strrchr(szFileName, '\\');
52 if (szShortName == NULL) {
53
54 /* No path, leave it alone */
55 szShortName = szFileName;
56
57 } else {
58
59 /* Skip the path */
60 szShortName = szShortName + 1;
61 }
62
63 /* Open the Kernel */
64 FilePointer = FsOpenFile(szFileName);
65
66 /* Make sure it worked */
67 if (FilePointer == NULL) {
68
69 /* Return failure on the short name */
70 strcpy(szBuffer, szShortName);
71 strcat(szBuffer, " not found.");
72 UiMessageBox(szBuffer);
73 return(FALSE);
74 }
75
76 /* Update the status bar with the current file */
77 strcpy(szBuffer, "Reading ");
78 strcat(szBuffer, szShortName);
79 UiDrawStatusText(szBuffer);
80
81 /* Do the actual loading */
82 FrLdrMapKernel(FilePointer);
83
84 /* Update Processbar and return success */
85 UiDrawProgressBarCenter(nPos, 100, szLoadingMsg);
86 return(TRUE);
87 }
88
89 BOOLEAN
90 NTAPI
91 FrLdrMapImage(
92 IN FILE *Image,
93 IN PCHAR ShortName
94 );
95
96 BOOLEAN
97 NTAPI
98 FrLdrLoadImage(IN PCHAR szFileName,
99 IN INT nPos)
100 {
101 PFILE FilePointer;
102 PCHAR szShortName;
103 CHAR szBuffer[256], szFullPath[256];
104
105 /* Check if this the HAL being loaded */
106 if (!_stricmp(szFileName, "hal.dll"))
107 {
108 /* Use the boot.ini name instead */
109 szFileName = szHalName;
110 }
111
112 /* Extract filename without path */
113 szShortName = strrchr(szFileName, '\\');
114 if (!szShortName)
115 {
116 /* No path, leave it alone */
117 szShortName = szFileName;
118
119 /* Which means we need to build a path now */
120 strcpy(szBuffer, szFileName);
121 strcpy(szFullPath, szBootPath);
122 if (!FrLdrBootType)
123 {
124 strcat(szFullPath, "SYSTEM32\\DRIVERS\\");
125 }
126 else
127 {
128 strcat(szFullPath, "\\");
129 }
130 strcat(szFullPath, szBuffer);
131 szFileName = szFullPath;
132 }
133 else
134 {
135 /* Skip the path */
136 szShortName = szShortName + 1;
137 }
138
139 /* Open the image */
140 FilePointer = FsOpenFile(szFileName);
141 if (!FilePointer)
142 {
143 /* Return failure on the short name */
144 strcpy(szBuffer, szShortName);
145 strcat(szBuffer, " not found.");
146 UiMessageBox(szBuffer);
147 return FALSE;
148 }
149
150 /* Update the status bar with the current file */
151 strcpy(szBuffer, "Reading ");
152 strcat(szBuffer, szShortName);
153 UiDrawStatusText(szBuffer);
154
155 /* Do the actual loading */
156 FrLdrMapImage(FilePointer, szShortName);
157
158 /* Update Processbar and return success */
159 if (!FrLdrBootType) UiDrawProgressBarCenter(nPos, 100, szLoadingMsg);
160 return TRUE;
161 }
162
163 static VOID
164 FreeldrFreeMem(PVOID Area)
165 {
166 MmFreeMemory(Area);
167 }
168
169 static PVOID
170 FreeldrAllocMem(ULONG_PTR Size)
171 {
172 return MmAllocateMemory((ULONG) Size);
173 }
174
175 static BOOLEAN
176 FreeldrReadFile(PVOID FileContext, PVOID Buffer, ULONG Size)
177 {
178 ULONG BytesRead;
179
180 return FsReadFile((PFILE) FileContext, (ULONG) Size, &BytesRead, Buffer)
181 && Size == BytesRead;
182 }
183
184 static BOOLEAN
185 FreeldrSeekFile(PVOID FileContext, ULONG_PTR Position)
186 {
187 FsSetFilePointer((PFILE) FileContext, (ULONG) Position);
188 return TRUE;
189 }
190
191 static BOOLEAN
192 LoadKernelSymbols(PCHAR szKernelName, int nPos)
193 {
194 static ROSSYM_CALLBACKS FreeldrCallbacks =
195 {
196 FreeldrAllocMem,
197 FreeldrFreeMem,
198 FreeldrReadFile,
199 FreeldrSeekFile
200 };
201 PFILE FilePointer;
202 PROSSYM_INFO RosSymInfo;
203 ULONG Size;
204 ULONG_PTR Base;
205 //return TRUE;
206
207 RosSymInit(&FreeldrCallbacks);
208
209 FilePointer = FsOpenFile(szKernelName);
210 if (FilePointer == NULL)
211 {
212 return FALSE;
213 }
214 if (! RosSymCreateFromFile(FilePointer, &RosSymInfo))
215 {
216 return FALSE;
217 }
218 Base = FrLdrCreateModule("NTOSKRNL.SYM");
219 Size = RosSymGetRawDataLength(RosSymInfo);
220 RosSymGetRawData(RosSymInfo, (PVOID)Base);
221 FrLdrCloseModule(Base, Size);
222 RosSymDelete(RosSymInfo);
223 return TRUE;
224 }
225
226 static BOOLEAN
227 FrLdrLoadNlsFile(PCSTR szFileName,
228 PCSTR szModuleName)
229 {
230 PFILE FilePointer;
231 CHAR value[256];
232 LPSTR p;
233
234 /* Open the Driver */
235 FilePointer = FsOpenFile(szFileName);
236
237 /* Make sure we did */
238 if (FilePointer == NULL) {
239
240 /* Fail if file wasn't opened */
241 strcpy(value, szFileName);
242 strcat(value, " not found.");
243 UiMessageBox(value);
244 return(FALSE);
245 }
246
247 /* Update the status bar with the current file */
248 strcpy(value, "Reading ");
249 p = strrchr(szFileName, '\\');
250 if (p == NULL) {
251
252 strcat(value, szFileName);
253
254 } else {
255
256 strcat(value, p + 1);
257 }
258 UiDrawStatusText(value);
259
260 /* Load the driver */
261 FrLdrLoadModule(FilePointer, szModuleName, NULL);
262 return(TRUE);
263 }
264
265 static BOOLEAN
266 FrLdrLoadNlsFiles(PCHAR szSystemRoot,
267 PCHAR szErrorOut)
268 {
269 LONG rc = ERROR_SUCCESS;
270 FRLDRHKEY hKey;
271 WCHAR szIdBuffer[80];
272 WCHAR szNameBuffer[80];
273 CHAR szFileName[256];
274 ULONG BufferSize;
275
276 /* open the codepage key */
277 rc = RegOpenKey(NULL,
278 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\CodePage",
279 &hKey);
280 if (rc != ERROR_SUCCESS) {
281
282 strcpy(szErrorOut, "Couldn't open CodePage registry key");
283 return(FALSE);
284 }
285
286 /* get ANSI codepage */
287 BufferSize = sizeof(szIdBuffer);
288 rc = RegQueryValue(hKey, L"ACP", NULL, (PUCHAR)szIdBuffer, &BufferSize);
289 if (rc != ERROR_SUCCESS) {
290
291 strcpy(szErrorOut, "Couldn't get ACP NLS setting");
292 return(FALSE);
293 }
294
295 BufferSize = sizeof(szNameBuffer);
296 rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)szNameBuffer, &BufferSize);
297 if (rc != ERROR_SUCCESS) {
298
299 strcpy(szErrorOut, "ACP NLS Setting exists, but isn't readable");
300 return(FALSE);
301 }
302
303 /* load ANSI codepage table */
304 sprintf(szFileName,"%ssystem32\\%S", szSystemRoot, szNameBuffer);
305 DbgPrint((DPRINT_REACTOS, "ANSI file: %s\n", szFileName));
306 if (!FrLdrLoadNlsFile(szFileName, "ansi.nls")) {
307
308 strcpy(szErrorOut, "Couldn't load ansi.nls");
309 return(FALSE);
310 }
311
312 /* get OEM codepage */
313 BufferSize = sizeof(szIdBuffer);
314 rc = RegQueryValue(hKey, L"OEMCP", NULL, (PUCHAR)szIdBuffer, &BufferSize);
315 if (rc != ERROR_SUCCESS) {
316
317 strcpy(szErrorOut, "Couldn't get OEMCP NLS setting");
318 return(FALSE);
319 }
320
321 BufferSize = sizeof(szNameBuffer);
322 rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)szNameBuffer, &BufferSize);
323 if (rc != ERROR_SUCCESS) {
324
325 strcpy(szErrorOut, "OEMCP NLS setting exists, but isn't readable");
326 return(FALSE);
327 }
328
329 /* load OEM codepage table */
330 sprintf(szFileName, "%ssystem32\\%S", szSystemRoot, szNameBuffer);
331 DbgPrint((DPRINT_REACTOS, "Oem file: %s\n", szFileName));
332 if (!FrLdrLoadNlsFile(szFileName, "oem.nls")) {
333
334 strcpy(szErrorOut, "Couldn't load oem.nls");
335 return(FALSE);
336 }
337
338 /* open the language key */
339 rc = RegOpenKey(NULL,
340 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\NLS\\Language",
341 &hKey);
342 if (rc != ERROR_SUCCESS) {
343
344 strcpy(szErrorOut, "Couldn't open Language registry key");
345 return(FALSE);
346 }
347
348 /* get the Unicode case table */
349 BufferSize = sizeof(szIdBuffer);
350 rc = RegQueryValue(hKey, L"Default", NULL, (PUCHAR)szIdBuffer, &BufferSize);
351 if (rc != ERROR_SUCCESS) {
352
353 strcpy(szErrorOut, "Couldn't get Language Default setting");
354 return(FALSE);
355 }
356
357 BufferSize = sizeof(szNameBuffer);
358 rc = RegQueryValue(hKey, szIdBuffer, NULL, (PUCHAR)szNameBuffer, &BufferSize);
359 if (rc != ERROR_SUCCESS) {
360
361 strcpy(szErrorOut, "Language Default setting exists, but isn't readable");
362 return(FALSE);
363 }
364
365 /* load Unicode case table */
366 sprintf(szFileName, "%ssystem32\\%S", szSystemRoot, szNameBuffer);
367 DbgPrint((DPRINT_REACTOS, "Casemap file: %s\n", szFileName));
368 if (!FrLdrLoadNlsFile(szFileName, "casemap.nls")) {
369
370 strcpy(szErrorOut, "casemap.nls");
371 return(FALSE);
372 }
373
374 return(TRUE);
375 }
376
377 static BOOLEAN
378 FrLdrLoadDriver(PCHAR szFileName,
379 INT nPos)
380 {
381 PFILE FilePointer;
382 CHAR value[256];
383 LPSTR p;
384
385 /* Open the Driver */
386 FilePointer = FsOpenFile(szFileName);
387
388 /* Make sure we did */
389 if (FilePointer == NULL) {
390
391 /* Fail if file wasn't opened */
392 strcpy(value, szFileName);
393 strcat(value, " not found.");
394 UiMessageBox(value);
395 return(FALSE);
396 }
397
398 /* Update the status bar with the current file */
399 strcpy(value, "Reading ");
400 p = strrchr(szFileName, '\\');
401 if (p == NULL) {
402
403 strcat(value, szFileName);
404
405 } else {
406
407 strcat(value, p + 1);
408
409 }
410 UiDrawStatusText(value);
411
412 /* Load the driver */
413 FrLdrLoadModule(FilePointer, szFileName, NULL);
414
415 /* Update status and return */
416 UiDrawProgressBarCenter(nPos, 100, szLoadingMsg);
417 return(TRUE);
418 }
419
420 static VOID
421 FrLdrLoadBootDrivers(PCHAR szSystemRoot,
422 INT nPos)
423 {
424 LONG rc = 0;
425 FRLDRHKEY hGroupKey, hOrderKey, hServiceKey, hDriverKey;
426 WCHAR GroupNameBuffer[512];
427 WCHAR ServiceName[256];
428 ULONG OrderList[128];
429 ULONG BufferSize;
430 ULONG Index;
431 ULONG TagIndex;
432 LPWSTR GroupName;
433
434 ULONG ValueSize;
435 ULONG ValueType;
436 ULONG StartValue;
437 ULONG TagValue;
438 WCHAR DriverGroup[256];
439 ULONG DriverGroupSize;
440
441 CHAR ImagePath[256];
442 WCHAR TempImagePath[256];
443
444 /* get 'service group order' key */
445 rc = RegOpenKey(NULL,
446 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\ServiceGroupOrder",
447 &hGroupKey);
448 if (rc != ERROR_SUCCESS) {
449
450 DbgPrint((DPRINT_REACTOS, "Failed to open the 'ServiceGroupOrder' key (rc %d)\n", (int)rc));
451 return;
452 }
453
454 /* get 'group order list' key */
455 rc = RegOpenKey(NULL,
456 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\GroupOrderList",
457 &hOrderKey);
458 if (rc != ERROR_SUCCESS) {
459
460 DbgPrint((DPRINT_REACTOS, "Failed to open the 'GroupOrderList' key (rc %d)\n", (int)rc));
461 return;
462 }
463
464 /* enumerate drivers */
465 rc = RegOpenKey(NULL,
466 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services",
467 &hServiceKey);
468 if (rc != ERROR_SUCCESS) {
469
470 DbgPrint((DPRINT_REACTOS, "Failed to open the 'Services' key (rc %d)\n", (int)rc));
471 return;
472 }
473
474 /* Get the Name Group */
475 BufferSize = sizeof(GroupNameBuffer);
476 rc = RegQueryValue(hGroupKey, L"List", NULL, (PUCHAR)GroupNameBuffer, &BufferSize);
477 DbgPrint((DPRINT_REACTOS, "RegQueryValue(): rc %d\n", (int)rc));
478 if (rc != ERROR_SUCCESS) return;
479 DbgPrint((DPRINT_REACTOS, "BufferSize: %d \n", (int)BufferSize));
480 DbgPrint((DPRINT_REACTOS, "GroupNameBuffer: '%S' \n", GroupNameBuffer));
481
482 /* Loop through each group */
483 GroupName = GroupNameBuffer;
484 while (*GroupName) {
485 DbgPrint((DPRINT_REACTOS, "Driver group: '%S'\n", GroupName));
486
487 /* Query the Order */
488 BufferSize = sizeof(OrderList);
489 rc = RegQueryValue(hOrderKey, GroupName, NULL, (PUCHAR)OrderList, &BufferSize);
490 if (rc != ERROR_SUCCESS) OrderList[0] = 0;
491
492 /* enumerate all drivers */
493 for (TagIndex = 1; TagIndex <= OrderList[0]; TagIndex++) {
494
495 Index = 0;
496
497 while (TRUE) {
498
499 /* Get the Driver's Name */
500 ValueSize = sizeof(ServiceName);
501 rc = RegEnumKey(hServiceKey, Index, ServiceName, &ValueSize);
502 DbgPrint((DPRINT_REACTOS, "RegEnumKey(): rc %d\n", (int)rc));
503
504 /* Makre sure it's valid, and check if we're done */
505 if (rc == ERROR_NO_MORE_ITEMS) break;
506 if (rc != ERROR_SUCCESS) return;
507 DbgPrint((DPRINT_REACTOS, "Service %d: '%S'\n", (int)Index, ServiceName));
508
509 /* open driver Key */
510 rc = RegOpenKey(hServiceKey, ServiceName, &hDriverKey);
511 if (rc == ERROR_SUCCESS)
512 {
513 /* Read the Start Value */
514 ValueSize = sizeof(ULONG);
515 rc = RegQueryValue(hDriverKey, L"Start", &ValueType, (PUCHAR)&StartValue, &ValueSize);
516 if (rc != ERROR_SUCCESS) StartValue = (ULONG)-1;
517 DbgPrint((DPRINT_REACTOS, " Start: %x \n", (int)StartValue));
518
519 /* Read the Tag */
520 ValueSize = sizeof(ULONG);
521 rc = RegQueryValue(hDriverKey, L"Tag", &ValueType, (PUCHAR)&TagValue, &ValueSize);
522 if (rc != ERROR_SUCCESS) TagValue = (ULONG)-1;
523 DbgPrint((DPRINT_REACTOS, " Tag: %x \n", (int)TagValue));
524
525 /* Read the driver's group */
526 DriverGroupSize = sizeof(DriverGroup);
527 rc = RegQueryValue(hDriverKey, L"Group", NULL, (PUCHAR)DriverGroup, &DriverGroupSize);
528 DbgPrint((DPRINT_REACTOS, " Group: '%S' \n", DriverGroup));
529
530 /* Make sure it should be started */
531 if ((StartValue == 0) &&
532 (TagValue == OrderList[TagIndex]) &&
533 (_wcsicmp(DriverGroup, GroupName) == 0)) {
534
535 /* Get the Driver's Location */
536 ValueSize = sizeof(TempImagePath);
537 rc = RegQueryValue(hDriverKey, L"ImagePath", NULL, (PUCHAR)TempImagePath, &ValueSize);
538
539 /* Write the whole path if it suceeded, else prepare to fail */
540 if (rc != ERROR_SUCCESS) {
541 DbgPrint((DPRINT_REACTOS, " ImagePath: not found\n"));
542 sprintf(ImagePath, "%s\\system32\\drivers\\%S.sys", szSystemRoot, ServiceName);
543 } else if (TempImagePath[0] != L'\\') {
544 sprintf(ImagePath, "%s%S", szSystemRoot, TempImagePath);
545 } else {
546 sprintf(ImagePath, "%S", TempImagePath);
547 DbgPrint((DPRINT_REACTOS, " ImagePath: '%s'\n", ImagePath));
548 }
549
550 DbgPrint((DPRINT_REACTOS, " Loading driver: '%s'\n", ImagePath));
551
552 /* Update the position if needed */
553 if (nPos < 100) nPos += 5;
554
555 FrLdrLoadDriver(ImagePath, nPos);
556
557 } else {
558
559 DbgPrint((DPRINT_REACTOS, " Skipping driver '%S' with Start %d, Tag %d and Group '%S' (Current Tag %d, current group '%S')\n",
560 ServiceName, StartValue, TagValue, DriverGroup, OrderList[TagIndex], GroupName));
561 }
562 }
563
564 Index++;
565 }
566 }
567
568 Index = 0;
569 while (TRUE) {
570
571 /* Get the Driver's Name */
572 ValueSize = sizeof(ServiceName);
573 rc = RegEnumKey(hServiceKey, Index, ServiceName, &ValueSize);
574
575 DbgPrint((DPRINT_REACTOS, "RegEnumKey(): rc %d\n", (int)rc));
576 if (rc == ERROR_NO_MORE_ITEMS) break;
577 if (rc != ERROR_SUCCESS) return;
578 DbgPrint((DPRINT_REACTOS, "Service %d: '%S'\n", (int)Index, ServiceName));
579
580 /* open driver Key */
581 rc = RegOpenKey(hServiceKey, ServiceName, &hDriverKey);
582 if (rc == ERROR_SUCCESS)
583 {
584 /* Read the Start Value */
585 ValueSize = sizeof(ULONG);
586 rc = RegQueryValue(hDriverKey, L"Start", &ValueType, (PUCHAR)&StartValue, &ValueSize);
587 if (rc != ERROR_SUCCESS) StartValue = (ULONG)-1;
588 DbgPrint((DPRINT_REACTOS, " Start: %x \n", (int)StartValue));
589
590 /* Read the Tag */
591 ValueSize = sizeof(ULONG);
592 rc = RegQueryValue(hDriverKey, L"Tag", &ValueType, (PUCHAR)&TagValue, &ValueSize);
593 if (rc != ERROR_SUCCESS) TagValue = (ULONG)-1;
594 DbgPrint((DPRINT_REACTOS, " Tag: %x \n", (int)TagValue));
595
596 /* Read the driver's group */
597 DriverGroupSize = sizeof(DriverGroup);
598 rc = RegQueryValue(hDriverKey, L"Group", NULL, (PUCHAR)DriverGroup, &DriverGroupSize);
599 DbgPrint((DPRINT_REACTOS, " Group: '%S' \n", DriverGroup));
600
601 for (TagIndex = 1; TagIndex <= OrderList[0]; TagIndex++) {
602 if (TagValue == OrderList[TagIndex]) break;
603 }
604
605 if ((StartValue == 0) &&
606 (TagIndex > OrderList[0]) &&
607 (_wcsicmp(DriverGroup, GroupName) == 0)) {
608
609 ValueSize = sizeof(TempImagePath);
610 rc = RegQueryValue(hDriverKey, L"ImagePath", NULL, (PUCHAR)TempImagePath, &ValueSize);
611 if (rc != ERROR_SUCCESS) {
612 DbgPrint((DPRINT_REACTOS, " ImagePath: not found\n"));
613 sprintf(ImagePath, "%ssystem32\\drivers\\%S.sys", szSystemRoot, ServiceName);
614 } else if (TempImagePath[0] != L'\\') {
615 sprintf(ImagePath, "%s%S", szSystemRoot, TempImagePath);
616 } else {
617 sprintf(ImagePath, "%S", TempImagePath);
618 DbgPrint((DPRINT_REACTOS, " ImagePath: '%s'\n", ImagePath));
619 }
620 DbgPrint((DPRINT_REACTOS, " Loading driver: '%s'\n", ImagePath));
621
622 if (nPos < 100) nPos += 5;
623
624 FrLdrLoadDriver(ImagePath, nPos);
625
626 } else {
627
628 DbgPrint((DPRINT_REACTOS, " Skipping driver '%S' with Start %d, Tag %d and Group '%S' (Current group '%S')\n",
629 ServiceName, StartValue, TagValue, DriverGroup, GroupName));
630 }
631 }
632
633 Index++;
634 }
635
636 /* Move to the next group name */
637 GroupName = GroupName + wcslen(GroupName) + 1;
638 }
639 }
640
641 VOID
642 LoadAndBootReactOS(PCSTR OperatingSystemName)
643 {
644 PFILE FilePointer;
645 CHAR name[255];
646 CHAR value[255];
647 CHAR SystemPath[255];
648 CHAR szKernelName[255];
649 CHAR szFileName[255];
650 UINT i;
651 CHAR MsgBuffer[256];
652 ULONG SectionId;
653
654 ULONG_PTR Base;
655 ULONG Size;
656
657 extern ULONG PageDirectoryStart;
658 extern ULONG PageDirectoryEnd;
659 extern BOOLEAN AcpiPresent;
660
661 //
662 // Open the operating system section
663 // specified in the .ini file
664 //
665 if (!IniOpenSection(OperatingSystemName, &SectionId))
666 {
667 sprintf(MsgBuffer,"Operating System section '%s' not found in freeldr.ini", OperatingSystemName);
668 UiMessageBox(MsgBuffer);
669 return;
670 }
671
672 UiDrawBackdrop();
673 UiDrawStatusText("Detecting Hardware...");
674 UiDrawProgressBarCenter(1, 100, szLoadingMsg);
675
676 /*
677 * Setup multiboot information structure
678 */
679 LoaderBlock.Flags = MB_FLAGS_BOOT_DEVICE | MB_FLAGS_COMMAND_LINE | MB_FLAGS_MODULE_INFO;
680 LoaderBlock.PageDirectoryStart = (ULONG)&PageDirectoryStart;
681 LoaderBlock.PageDirectoryEnd = (ULONG)&PageDirectoryEnd;
682 LoaderBlock.BootDevice = 0xffffffff;
683 LoaderBlock.CommandLine = reactos_kernel_cmdline;
684 LoaderBlock.ModsCount = 0;
685 LoaderBlock.ModsAddr = reactos_modules;
686 LoaderBlock.DrivesAddr = reactos_arc_disk_info;
687 LoaderBlock.MmapLength = (unsigned long)MachGetMemoryMap((PBIOS_MEMORY_MAP)(PVOID)&reactos_memory_map, 32) * sizeof(memory_map_t);
688 if (LoaderBlock.MmapLength)
689 {
690 LoaderBlock.MmapAddr = (unsigned long)&reactos_memory_map;
691 LoaderBlock.Flags |= MB_FLAGS_MEM_INFO | MB_FLAGS_MMAP_INFO;
692 reactos_memory_map_descriptor_size = sizeof(memory_map_t); // GetBiosMemoryMap uses a fixed value of 24
693 DbgPrint((DPRINT_REACTOS, "memory map length: %d\n", LoaderBlock.MmapLength));
694 DbgPrint((DPRINT_REACTOS, "dumping memory map:\n"));
695 for (i=0; i<(LoaderBlock.MmapLength/sizeof(memory_map_t)); i++)
696 {
697 if (BiosMemoryUsable == reactos_memory_map[i].type &&
698 0 == reactos_memory_map[i].base_addr_low)
699 {
700 LoaderBlock.MemLower = (reactos_memory_map[i].base_addr_low + reactos_memory_map[i].length_low) / 1024;
701 if (640 < LoaderBlock.MemLower)
702 {
703 LoaderBlock.MemLower = 640;
704 }
705 }
706 if (BiosMemoryUsable == reactos_memory_map[i].type &&
707 reactos_memory_map[i].base_addr_low <= 1024 * 1024 &&
708 1024 * 1024 <= reactos_memory_map[i].base_addr_low + reactos_memory_map[i].length_low)
709 {
710 LoaderBlock.MemHigher = (reactos_memory_map[i].base_addr_low + reactos_memory_map[i].length_low) / 1024 - 1024;
711 }
712 DbgPrint((DPRINT_REACTOS, "start: %x\t size: %x\t type %d\n",
713 reactos_memory_map[i].base_addr_low,
714 reactos_memory_map[i].length_low,
715 reactos_memory_map[i].type));
716 }
717 }
718 DbgPrint((DPRINT_REACTOS, "low_mem = %d\n", LoaderBlock.MemLower));
719 DbgPrint((DPRINT_REACTOS, "high_mem = %d\n", LoaderBlock.MemHigher));
720
721 /*
722 * Initialize the registry
723 */
724 RegInitializeRegistry();
725
726 /*
727 * Make sure the system path is set in the .ini file
728 */
729 if (!IniReadSettingByName(SectionId, "SystemPath", SystemPath, sizeof(SystemPath)))
730 {
731 UiMessageBox("System path not specified for selected operating system.");
732 return;
733 }
734
735 /*
736 * Special case for Live CD.
737 */
738 if (!_stricmp(SystemPath, "LiveCD"))
739 {
740 /* Normalize */
741 MachDiskGetBootPath(SystemPath, sizeof(SystemPath));
742 strcat(SystemPath, "\\reactos");
743 strcat(strcpy(reactos_kernel_cmdline, SystemPath),
744 " /MININT");
745 }
746 else
747 {
748 if (! MachDiskNormalizeSystemPath(SystemPath,
749 sizeof(SystemPath)))
750 {
751 UiMessageBox("Invalid system path");
752 return;
753 }
754 /* copy system path into kernel command line */
755 strcpy(reactos_kernel_cmdline, SystemPath);
756 }
757
758 /*
759 * Read the optional kernel parameters (if any)
760 */
761 if (IniReadSettingByName(SectionId, "Options", value, sizeof(value)))
762 {
763 strcat(reactos_kernel_cmdline, " ");
764 strcat(reactos_kernel_cmdline, value);
765 }
766
767 /*
768 * Detect hardware
769 */
770 MachHwDetect();
771 UiDrawProgressBarCenter(5, 100, szLoadingMsg);
772
773 if (AcpiPresent) LoaderBlock.Flags |= MB_FLAGS_ACPI_TABLE;
774 LoaderBlock.DrivesCount = reactos_disk_count;
775
776 UiDrawStatusText("Loading...");
777
778 /*
779 * Try to open system drive
780 */
781 if (!FsOpenSystemVolume(SystemPath, szBootPath, &LoaderBlock.BootDevice))
782 {
783 UiMessageBox("Failed to open boot drive.");
784 return;
785 }
786
787 /* append a backslash */
788 if ((strlen(szBootPath)==0) ||
789 szBootPath[strlen(szBootPath)] != '\\')
790 strcat(szBootPath, "\\");
791
792 DbgPrint((DPRINT_REACTOS,"SystemRoot: '%s'\n", szBootPath));
793
794 /*
795 * Find the kernel image name
796 * and try to load the kernel off the disk
797 */
798 if(IniReadSettingByName(SectionId, "Kernel", value, sizeof(value)))
799 {
800 /*
801 * Set the name and
802 */
803 if (value[0] == '\\')
804 {
805 strcpy(szKernelName, value);
806 }
807 else
808 {
809 strcpy(szKernelName, szBootPath);
810 strcat(szKernelName, "SYSTEM32\\");
811 strcat(szKernelName, value);
812 }
813 }
814 else
815 {
816 strcpy(value, "NTOSKRNL.EXE");
817 strcpy(szKernelName, szBootPath);
818 strcat(szKernelName, "SYSTEM32\\");
819 strcat(szKernelName, value);
820 }
821
822 /*
823 * Find the HAL image name
824 * and try to load the kernel off the disk
825 */
826 if(IniReadSettingByName(SectionId, "Hal", value, sizeof(value)))
827 {
828 /*
829 * Set the name and
830 */
831 if (value[0] == '\\')
832 {
833 strcpy(szHalName, value);
834 }
835 else
836 {
837 strcpy(szHalName, szBootPath);
838 strcat(szHalName, "SYSTEM32\\");
839 strcat(szHalName, value);
840 }
841 }
842 else
843 {
844 strcpy(value, "HAL.DLL");
845 strcpy(szHalName, szBootPath);
846 strcat(szHalName, "SYSTEM32\\");
847 strcat(szHalName, value);
848 }
849
850 /* Load the kernel */
851 if (!FrLdrLoadKernel(szKernelName, 5)) return;
852
853 /*
854 * Load the System hive from disk
855 */
856 strcpy(szFileName, szBootPath);
857 strcat(szFileName, "SYSTEM32\\CONFIG\\SYSTEM");
858
859 DbgPrint((DPRINT_REACTOS, "SystemHive: '%s'", szFileName));
860
861 FilePointer = FsOpenFile(szFileName);
862 if (FilePointer == NULL)
863 {
864 UiMessageBox("Could not find the System hive!");
865 return;
866 }
867
868 /*
869 * Update the status bar with the current file
870 */
871 strcpy(name, "Reading ");
872 strcat(name, value);
873 while (strlen(name) < 80)
874 strcat(name, " ");
875 UiDrawStatusText(name);
876
877 /*
878 * Load the System hive
879 */
880 Base = FrLdrLoadModule(FilePointer, szFileName, &Size);
881 if (Base == 0 || Size == 0)
882 {
883 UiMessageBox("Could not load the System hive!\n");
884 return;
885 }
886 DbgPrint((DPRINT_REACTOS, "SystemHive loaded at 0x%x size %u", (unsigned)Base, (unsigned)Size));
887
888 /*
889 * Import the loaded system hive
890 */
891 RegImportBinaryHive((PCHAR)Base, Size);
892
893 /*
894 * Initialize the 'CurrentControlSet' link
895 */
896 RegInitCurrentControlSet(FALSE);
897
898 UiDrawProgressBarCenter(15, 100, szLoadingMsg);
899
900 /*
901 * Export the hardware hive
902 */
903 Base = FrLdrCreateModule ("HARDWARE");
904 RegExportBinaryHive (L"\\Registry\\Machine\\HARDWARE", (PCHAR)Base, &Size);
905 FrLdrCloseModule (Base, Size);
906
907 UiDrawProgressBarCenter(20, 100, szLoadingMsg);
908
909 /*
910 * Load NLS files
911 */
912 if (!FrLdrLoadNlsFiles(szBootPath, MsgBuffer))
913 {
914 UiMessageBox(MsgBuffer);
915 return;
916 }
917 UiDrawProgressBarCenter(30, 100, szLoadingMsg);
918
919 /*
920 * Load kernel symbols
921 */
922 LoadKernelSymbols(szKernelName, 30);
923 UiDrawProgressBarCenter(40, 100, szLoadingMsg);
924
925 /*
926 * Load boot drivers
927 */
928 FrLdrLoadBootDrivers(szBootPath, 40);
929 //UiUnInitialize("Booting ReactOS...");
930
931 /*
932 * Now boot the kernel
933 */
934 DiskStopFloppyMotor();
935 //MachVideoPrepareForReactOS();
936 FrLdrStartup(0x2badb002);
937 }
938
939 #undef DbgPrint
940 ULONG
941 DbgPrint(const char *Format, ...)
942 {
943 va_list ap;
944 CHAR Buffer[512];
945 ULONG Length;
946
947 va_start(ap, Format);
948
949 /* Construct a string */
950 Length = _vsnprintf(Buffer, 512, Format, ap);
951
952 /* Check if we went past the buffer */
953 if (Length == -1)
954 {
955 /* Terminate it if we went over-board */
956 Buffer[sizeof(Buffer) - 1] = '\n';
957
958 /* Put maximum */
959 Length = sizeof(Buffer);
960 }
961
962 /* Show it as a message box */
963 UiMessageBox(Buffer);
964
965 /* Cleanup and exit */
966 va_end(ap);
967 return 0;
968 }
969
970 /* EOF */