- Added DiskGetExtendedDriveParameters()
[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 * Make sure the system path is set in the .ini file
498 */
499 if (!IniReadSettingByName(SectionId, "SystemPath", value, 1024))
500 {
501 UiMessageBox("System path not specified for selected operating system.");
502 return;
503 }
504
505 /*
506 * Verify system path
507 */
508 if (!DissectArcPath(value, szBootPath, &BootDrive, &BootPartition))
509 {
510 sprintf(MsgBuffer,"Invalid system path: '%s'", value);
511 UiMessageBox(MsgBuffer);
512 return;
513 }
514
515 /* set boot drive and partition */
516 ((char *)(&mb_info.boot_device))[0] = (char)BootDrive;
517 ((char *)(&mb_info.boot_device))[1] = (char)BootPartition;
518
519 /* recalculate the boot partition for freeldr */
520 i = 0;
521 rosPartition = 0;
522 while (1)
523 {
524 if (!DiskGetPartitionEntry(BootDrive, ++i, &PartitionTableEntry))
525 {
526 BootPartition = 0;
527 break;
528 }
529 if (IsRecognizedPartition(PartitionTableEntry.SystemIndicator))
530 {
531 if (++rosPartition == BootPartition)
532 {
533 BootPartition = i;
534 break;
535 }
536 }
537 }
538 if (BootPartition == 0)
539 {
540 sprintf(MsgBuffer,"Invalid system path: '%s'", value);
541 UiMessageBox(MsgBuffer);
542 return;
543 }
544
545 /* copy ARC path into kernel command line */
546 strcpy(multiboot_kernel_cmdline, value);
547
548 /*
549 * Read the optional kernel parameters (if any)
550 */
551 if (IniReadSettingByName(SectionId, "Options", value, 1024))
552 {
553 strcat(multiboot_kernel_cmdline, " ");
554 strcat(multiboot_kernel_cmdline, value);
555 }
556
557 /* append a backslash */
558 if ((strlen(szBootPath)==0) ||
559 szBootPath[strlen(szBootPath)] != '\\')
560 strcat(szBootPath, "\\");
561
562 DbgPrint((DPRINT_REACTOS,"SystemRoot: '%s'\n", szBootPath));
563
564 UiDrawBackdrop();
565 UiDrawStatusText("Loading...");
566 UiDrawProgressBarCenter(0, 100, "Loading ReactOS...");
567
568 /*
569 * Try to open boot drive
570 */
571 if (!FsOpenVolume(BootDrive, BootPartition))
572 {
573 UiMessageBox("Failed to open boot drive.");
574 return;
575 }
576
577 /*
578 * Find the kernel image name
579 * and try to load the kernel off the disk
580 */
581 if(IniReadSettingByName(SectionId, "Kernel", value, 1024))
582 {
583 /*
584 * Set the name and
585 */
586 if (value[0] == '\\')
587 {
588 strcpy(szKernelName, value);
589 }
590 else
591 {
592 strcpy(szKernelName, szBootPath);
593 strcat(szKernelName, "SYSTEM32\\");
594 strcat(szKernelName, value);
595 }
596 }
597 else
598 {
599 strcpy(value, "NTOSKRNL.EXE");
600 strcpy(szKernelName, szBootPath);
601 strcat(szKernelName, "SYSTEM32\\");
602 strcat(szKernelName, value);
603 }
604
605 if (!LoadKernel(szKernelName, 5))
606 return;
607
608 /*
609 * Find the HAL image name
610 * and try to load the kernel off the disk
611 */
612 if(IniReadSettingByName(SectionId, "Hal", value, 1024))
613 {
614 /*
615 * Set the name and
616 */
617 if (value[0] == '\\')
618 {
619 strcpy(szHalName, value);
620 }
621 else
622 {
623 strcpy(szHalName, szBootPath);
624 strcat(szHalName, "SYSTEM32\\");
625 strcat(szHalName, value);
626 }
627 }
628 else
629 {
630 strcpy(value, "HAL.DLL");
631 strcpy(szHalName, szBootPath);
632 strcat(szHalName, "SYSTEM32\\");
633 strcat(szHalName, value);
634 }
635
636 if (!LoadDriver(szHalName, 10))
637 return;
638
639 /*
640 * Load the System hive from disk
641 */
642 strcpy(szFileName, szBootPath);
643 strcat(szFileName, "SYSTEM32\\CONFIG\\SYSTEM");
644
645 DbgPrint((DPRINT_REACTOS, "SystemHive: '%s'", szFileName));
646
647 FilePointer = FsOpenFile(szFileName);
648 if (FilePointer == NULL)
649 {
650 strcpy(szFileName, szBootPath);
651 strcat(szFileName, "SYSTEM32\\CONFIG\\SYSTEM.HIV");
652
653 DbgPrint((DPRINT_REACTOS, "SystemHive: '%s'", szFileName));
654
655 FilePointer = FsOpenFile(szFileName);
656 if (FilePointer == NULL)
657 {
658 UiMessageBox("Could not find the system hive!");
659 return;
660 }
661 else
662 {
663 TextHive = TRUE;
664 }
665 }
666
667 /*
668 * Update the status bar with the current file
669 */
670 strcpy(name, "Reading ");
671 strcat(name, value);
672 while (strlen(name) < 80)
673 strcat(name, " ");
674 UiDrawStatusText(name);
675
676 /*
677 * Load the system hive
678 */
679 Base = MultiBootLoadModule(FilePointer, szFileName, &Size);
680 RegInitializeRegistry();
681
682 if (TextHive)
683 {
684 RegImportTextHive(Base, Size);
685 }
686 else
687 {
688 RegImportBinaryHive(Base, Size);
689 }
690
691 UiDrawProgressBarCenter(15, 100, "Loading ReactOS...");
692 DbgPrint((DPRINT_REACTOS, "SystemHive loaded at 0x%x size %u", (unsigned)Base, (unsigned)Size));
693
694 /*
695 * Detect hardware
696 */
697 DetectHardware();
698
699 /*
700 * Export the hardware hive
701 */
702 Base = MultiBootCreateModule ("HARDWARE");
703 RegExportBinaryHive ("\\Registry\\Machine\\HARDWARE", Base, &Size);
704 MultiBootCloseModule (Base, Size);
705
706 UiDrawProgressBarCenter(20, 100, "Loading ReactOS...");
707
708 /*
709 * Initialize the 'currentControlSet' link
710 */
711 RegInitCurrentControlSet(FALSE);
712
713 /*
714 * Load NLS files
715 */
716 #if 0
717 if (!LoadNlsFiles(szBootPath))
718 {
719 MessageBox("Failed to load NLS files\n");
720 return;
721 }
722 #endif
723
724 LoadSymbolFile(szBootPath, szKernelName, 25);
725 LoadSymbolFile(szBootPath, szHalName, 25);
726
727 UiDrawProgressBarCenter(25, 100, "Loading ReactOS...");
728
729 /*
730 * Load boot drivers
731 */
732 LoadBootDrivers(szBootPath, 25);
733
734
735 /*
736 * Clear the screen and redraw the backdrop and status bar
737 */
738 UiDrawBackdrop();
739 UiDrawStatusText("Press any key to boot");
740
741 #if 0
742 /*
743 * Wait for user
744 */
745 strcpy(name, "Kernel and Drivers loaded.\nPress any key to boot ");
746 strcat(name, OperatingSystemName);
747 strcat(name, ".");
748 MessageBox(name);
749 #endif
750
751 UiUnInitialize("Booting ReactOS...");
752
753 /*
754 * Now boot the kernel
755 */
756 DiskStopFloppyMotor();
757 boot_reactos();
758 }
759
760 /* EOF */