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