Fixed driver loading order, cleaned up relevant functions, and moved boot driver
[reactos.git] / reactos / ntoskrnl / ke / main.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id: main.c,v 1.175 2003/10/15 17:04:39 navaraf Exp $
20 *
21 * PROJECT: ReactOS kernel
22 * FILE: ntoskrnl/ke/main.c
23 * PURPOSE: Initalizes the kernel
24 * PROGRAMMER: David Welch (welch@cwcom.net)
25 * UPDATE HISTORY:
26 * 28/05/98: Created
27 */
28
29 /* INCLUDES *****************************************************************/
30
31 #define NTOS_MODE_KERNEL
32 #include <ntos.h>
33 #include <internal/ntoskrnl.h>
34 #include <reactos/resource.h>
35 #include <internal/mm.h>
36 #include <internal/ifs.h>
37 #include <internal/module.h>
38 #include <internal/ldr.h>
39 #include <internal/ex.h>
40 #include <internal/ps.h>
41 #include <internal/ke.h>
42 #include <internal/io.h>
43 #include <internal/po.h>
44 #include <internal/cc.h>
45 #include <internal/se.h>
46 #include <internal/v86m.h>
47 #include <internal/kd.h>
48 #include <internal/trap.h>
49 #include "../dbg/kdb.h"
50 #include <internal/registry.h>
51 #include <internal/nls.h>
52 #include <reactos/bugcodes.h>
53 #include <ntos/bootvid.h>
54 #include <napi/core.h>
55
56 #ifdef HALDBG
57 #include <internal/ntosdbg.h>
58 #else
59 #define ps(args...)
60 #endif
61
62 #define NDEBUG
63 #include <internal/debug.h>
64
65 /* GLOBALS *******************************************************************/
66
67 ULONG EXPORTED NtBuildNumber = KERNEL_VERSION_BUILD;
68 ULONG EXPORTED NtGlobalFlag = 0;
69 CHAR EXPORTED KeNumberProcessors;
70 LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock;
71 ULONG EXPORTED KeDcacheFlushCount = 0;
72 ULONG EXPORTED KeIcacheFlushCount = 0;
73 static LOADER_MODULE KeLoaderModules[64];
74 static UCHAR KeLoaderModuleStrings[64][256];
75 static UCHAR KeLoaderCommandLine[256];
76 static ADDRESS_RANGE KeMemoryMap[64];
77 static ULONG KeMemoryMapRangeCount;
78 static ULONG FirstKrnlPhysAddr;
79 static ULONG LastKrnlPhysAddr;
80 static ULONG LastKernelAddress;
81 volatile BOOLEAN Initialized = FALSE;
82 extern ULONG MmCoreDumpType;
83
84 extern PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS];
85
86
87 /* FUNCTIONS ****************************************************************/
88
89 static VOID INIT_FUNCTION
90 InitSystemSharedUserPage (PCSZ ParameterLine)
91 {
92 UNICODE_STRING ArcDeviceName;
93 UNICODE_STRING ArcName;
94 UNICODE_STRING BootPath;
95 UNICODE_STRING DriveDeviceName;
96 UNICODE_STRING DriveName;
97 WCHAR DriveNameBuffer[20];
98 PCHAR ParamBuffer;
99 PWCHAR ArcNameBuffer;
100 PCHAR p;
101 NTSTATUS Status;
102 ULONG Length;
103 OBJECT_ATTRIBUTES ObjectAttributes;
104 HANDLE Handle;
105 ULONG i;
106 BOOLEAN BootDriveFound;
107
108 /*
109 * NOTE:
110 * The shared user page has been zeroed-out right after creation.
111 * There is NO need to do this again.
112 */
113
114 SharedUserData->NtProductType = NtProductWinNt;
115
116 BootDriveFound = FALSE;
117
118 /*
119 * Retrieve the current dos system path
120 * (e.g.: C:\reactos) from the given arc path
121 * (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos)
122 * Format: "<arc_name>\<path> [options...]"
123 */
124
125 /* create local parameter line copy */
126 ParamBuffer = ExAllocatePool (PagedPool, 256);
127 strcpy (ParamBuffer, (char *)ParameterLine);
128 DPRINT("%s\n", ParamBuffer);
129
130 /* cut options off */
131 p = strchr (ParamBuffer, ' ');
132 if (p)
133 {
134 *p = 0;
135 }
136 DPRINT("%s\n", ParamBuffer);
137
138 /* extract path */
139 p = strchr (ParamBuffer, '\\');
140 if (p)
141 {
142 DPRINT("Boot path: %s\n", p);
143 RtlCreateUnicodeStringFromAsciiz (&BootPath, p);
144 *p = 0;
145 }
146 else
147 {
148 DPRINT("Boot path: %s\n", "\\");
149 RtlCreateUnicodeStringFromAsciiz (&BootPath, "\\");
150 }
151 DPRINT("Arc name: %s\n", ParamBuffer);
152
153 /* Only arc name left - build full arc name */
154 ArcNameBuffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
155 swprintf (ArcNameBuffer, L"\\ArcName\\%S", ParamBuffer);
156 RtlInitUnicodeString (&ArcName, ArcNameBuffer);
157 DPRINT("Arc name: %wZ\n", &ArcName);
158
159 /* free ParamBuffer */
160 ExFreePool (ParamBuffer);
161
162 /* allocate arc device name string */
163 ArcDeviceName.Length = 0;
164 ArcDeviceName.MaximumLength = 256 * sizeof(WCHAR);
165 ArcDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
166
167 InitializeObjectAttributes (&ObjectAttributes,
168 &ArcName,
169 OBJ_OPENLINK,
170 NULL,
171 NULL);
172
173 Status = NtOpenSymbolicLinkObject (&Handle,
174 SYMBOLIC_LINK_ALL_ACCESS,
175 &ObjectAttributes);
176 RtlFreeUnicodeString (&ArcName);
177 if (!NT_SUCCESS(Status))
178 {
179 RtlFreeUnicodeString (&BootPath);
180 RtlFreeUnicodeString (&ArcDeviceName);
181 CPRINT("NtOpenSymbolicLinkObject() failed (Status %x)\n",
182 Status);
183
184 KEBUGCHECK (0x0);
185 }
186
187 Status = NtQuerySymbolicLinkObject (Handle,
188 &ArcDeviceName,
189 &Length);
190 NtClose (Handle);
191 if (!NT_SUCCESS(Status))
192 {
193 RtlFreeUnicodeString (&BootPath);
194 RtlFreeUnicodeString (&ArcDeviceName);
195 CPRINT("NtQuerySymbolicObject() failed (Status %x)\n",
196 Status);
197
198 KEBUGCHECK (0x0);
199 }
200 DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length, &ArcDeviceName);
201
202
203 /* allocate device name string */
204 DriveDeviceName.Length = 0;
205 DriveDeviceName.MaximumLength = 256 * sizeof(WCHAR);
206 DriveDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
207
208 for (i = 0; i < 26; i++)
209 {
210 swprintf (DriveNameBuffer, L"\\??\\%C:", 'A' + i);
211 RtlInitUnicodeString (&DriveName,
212 DriveNameBuffer);
213
214 InitializeObjectAttributes (&ObjectAttributes,
215 &DriveName,
216 OBJ_OPENLINK,
217 NULL,
218 NULL);
219
220 Status = NtOpenSymbolicLinkObject (&Handle,
221 SYMBOLIC_LINK_ALL_ACCESS,
222 &ObjectAttributes);
223 if (!NT_SUCCESS(Status))
224 {
225 DPRINT("Failed to open link %wZ\n",
226 &DriveName);
227 continue;
228 }
229
230 Status = NtQuerySymbolicLinkObject (Handle,
231 &DriveDeviceName,
232 &Length);
233 if (!NT_SUCCESS(Status))
234 {
235 DPRINT("Failed query open link %wZ\n",
236 &DriveName);
237 continue;
238 }
239 DPRINT("Opened link: %wZ ==> %wZ\n",
240 &DriveName, &DriveDeviceName);
241
242 if (!RtlCompareUnicodeString (&ArcDeviceName, &DriveDeviceName, FALSE))
243 {
244 DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i, &BootPath);
245 swprintf(SharedUserData->NtSystemRoot,
246 L"%C:%wZ", 'A' + i, &BootPath);
247
248 BootDriveFound = TRUE;
249 }
250
251 NtClose (Handle);
252 }
253
254 RtlFreeUnicodeString (&BootPath);
255 RtlFreeUnicodeString (&DriveDeviceName);
256 RtlFreeUnicodeString (&ArcDeviceName);
257
258 DPRINT("DosDeviceMap: 0x%x\n", SharedUserData->DosDeviceMap);
259
260 if (BootDriveFound == FALSE)
261 {
262 DbgPrint("No system drive found!\n");
263 KEBUGCHECK (0x0);
264 }
265 }
266
267 VOID INIT_FUNCTION
268 ExpInitializeExecutive(VOID)
269 {
270 LARGE_INTEGER Timeout;
271 HANDLE ProcessHandle;
272 HANDLE ThreadHandle;
273 ULONG i;
274 ULONG start;
275 ULONG length;
276 PCHAR name;
277 CHAR str[50];
278 NTSTATUS Status;
279 BOOLEAN SetupBoot;
280 PCHAR p1, p2;
281 ULONG MaxMem;
282 BOOLEAN NoBootScreen = FALSE;
283 UNICODE_STRING Name;
284 HANDLE InitDoneEventHandle;
285 OBJECT_ATTRIBUTES ObjectAttributes;
286
287 /*
288 * Fail at runtime if someone has changed various structures without
289 * updating the offsets used for the assembler code.
290 */
291 assert(FIELD_OFFSET(KTHREAD, InitialStack) == KTHREAD_INITIAL_STACK);
292 assert(FIELD_OFFSET(KTHREAD, Teb) == KTHREAD_TEB);
293 assert(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK);
294 assert(FIELD_OFFSET(KTHREAD, ServiceTable) == KTHREAD_SERVICE_TABLE);
295 assert(FIELD_OFFSET(KTHREAD, PreviousMode) == KTHREAD_PREVIOUS_MODE);
296 assert(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME);
297 assert(FIELD_OFFSET(KTHREAD, CallbackStack) == KTHREAD_CALLBACK_STACK);
298 assert(FIELD_OFFSET(ETHREAD, ThreadsProcess) == ETHREAD_THREADS_PROCESS);
299 assert(FIELD_OFFSET(KPROCESS, DirectoryTableBase) ==
300 KPROCESS_DIRECTORY_TABLE_BASE);
301 assert(FIELD_OFFSET(KPROCESS, IopmOffset) == KPROCESS_IOPM_OFFSET);
302 assert(FIELD_OFFSET(KPROCESS, LdtDescriptor) == KPROCESS_LDT_DESCRIPTOR0);
303 assert(FIELD_OFFSET(KTRAP_FRAME, Reserved9) == KTRAP_FRAME_RESERVED9);
304 assert(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
305 assert(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
306
307 assert(FIELD_OFFSET(KPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
308 assert(FIELD_OFFSET(KPCR, Self) == KPCR_SELF);
309 assert(FIELD_OFFSET(IKPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
310 assert(FIELD_OFFSET(IKPCR, Self) == KPCR_SELF);
311 assert(FIELD_OFFSET(IKPCR, CurrentThread) == KPCR_CURRENT_THREAD);
312
313 LdrInit1();
314
315 KeLowerIrql(DISPATCH_LEVEL);
316
317 NtEarlyInitVdm();
318
319 p1 = (PCHAR)KeLoaderBlock.CommandLine;
320
321 MaxMem = 0;
322 while(*p1 && (p2 = strchr(p1, '/')))
323 {
324 p2++;
325 if (!_strnicmp(p2, "MAXMEM", 6))
326 {
327 p2 += 6;
328 while (isspace(*p2)) p2++;
329 if (*p2 == '=')
330 {
331 p2++;
332 while(isspace(*p2)) p2++;
333 if (isdigit(*p2))
334 {
335 while (isdigit(*p2))
336 {
337 MaxMem = MaxMem * 10 + *p2 - '0';
338 p2++;
339 }
340 break;
341 }
342 }
343 }
344 else if (!_strnicmp(p2, "NOBOOTSCREEN", 12))
345 {
346 p2 += 12;
347 NoBootScreen = TRUE;
348 }
349 else if (!_strnicmp(p2, "CRASHDUMP", 9))
350 {
351 p2 += 9;
352 if (*p2 == ':')
353 {
354 p2++;
355 if (!_strnicmp(p2, "FULL", 4))
356 {
357 MmCoreDumpType = MM_CORE_DUMP_TYPE_FULL;
358 }
359 else
360 {
361 MmCoreDumpType = MM_CORE_DUMP_TYPE_NONE;
362 }
363 }
364 }
365 p1 = p2;
366 }
367
368 MmInit1(FirstKrnlPhysAddr,
369 LastKrnlPhysAddr,
370 LastKernelAddress,
371 (PADDRESS_RANGE)&KeMemoryMap,
372 KeMemoryMapRangeCount,
373 MaxMem > 8 ? MaxMem : 4096);
374
375 /* Import ANSI code page table */
376 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
377 {
378 start = KeLoaderModules[i].ModStart;
379 length = KeLoaderModules[i].ModEnd - start;
380
381 name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
382 if (name == NULL)
383 {
384 name = (PCHAR)KeLoaderModules[i].String;
385 }
386 else
387 {
388 name++;
389 }
390
391 if (!_stricmp (name, "ansi.nls"))
392 {
393 RtlpImportAnsiCodePage((PUSHORT)start, length);
394 }
395 }
396
397 /* Import OEM code page table */
398 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
399 {
400 start = KeLoaderModules[i].ModStart;
401 length = KeLoaderModules[i].ModEnd - start;
402
403 name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
404 if (name == NULL)
405 {
406 name = (PCHAR)KeLoaderModules[i].String;
407 }
408 else
409 {
410 name++;
411 }
412
413 if (!_stricmp (name, "oem.nls"))
414 {
415 RtlpImportOemCodePage((PUSHORT)start, length);
416 }
417 }
418
419 /* Import Unicode casemap table */
420 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
421 {
422 start = KeLoaderModules[i].ModStart;
423 length = KeLoaderModules[i].ModEnd - start;
424
425 name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
426 if (name == NULL)
427 {
428 name = (PCHAR)KeLoaderModules[i].String;
429 }
430 else
431 {
432 name++;
433 }
434
435 if (!_stricmp (name, "casemap.nls"))
436 {
437 RtlpImportUnicodeCasemap((PUSHORT)start, length);
438 }
439 }
440
441 /* Create initial NLS tables */
442 RtlpCreateInitialNlsTables();
443
444 /*
445 * Initialize the kernel debugger
446 */
447 KdInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
448
449 MmInit2();
450 KeInit2();
451
452 KeLowerIrql(PASSIVE_LEVEL);
453
454 if (!SeInit1())
455 KEBUGCHECK(SECURITY_INITIALIZATION_FAILED);
456
457 ObInit();
458
459 if (!SeInit2())
460 KEBUGCHECK(SECURITY1_INITIALIZATION_FAILED);
461
462 PiInitProcessManager();
463
464 if (KdPollBreakIn ())
465 {
466 DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
467 }
468
469 /* Initialize all processors */
470 KeNumberProcessors = 0;
471
472 while (!HalAllProcessorsStarted())
473 {
474 PVOID ProcessorStack;
475
476 if (KeNumberProcessors != 0)
477 {
478 KePrepareForApplicationProcessorInit(KeNumberProcessors);
479 PsPrepareForApplicationProcessorInit(KeNumberProcessors);
480 }
481 /* Allocate a stack for use when booting the processor */
482 /* FIXME: The nonpaged memory for the stack is not released after use */
483 ProcessorStack =
484 ExAllocatePool(NonPagedPool, MM_STACK_SIZE) + MM_STACK_SIZE;
485 Ki386InitialStackArray[((int)KeNumberProcessors)] =
486 (PVOID)(ProcessorStack - MM_STACK_SIZE);
487 HalInitializeProcessor(KeNumberProcessors, ProcessorStack);
488 KeNumberProcessors++;
489 }
490
491 /*
492 * Initialize various critical subsystems
493 */
494 HalInitSystem(1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
495
496 ExInit();
497 KdInit1();
498 IoInit();
499 PoInit();
500 LdrInitModuleManagement();
501 CmInitializeRegistry();
502 NtInit();
503 MmInit3();
504 CcInit();
505 KdInit2();
506 FsRtlpInitFileLockingImplementation();
507
508 /* Report all resources used by hal */
509 HalReportResourceUsage();
510
511 /*
512 * Clear the screen to blue
513 */
514 HalInitSystem(2, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
515
516 /*
517 * Display version number and copyright/warranty message
518 */
519 HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR" (Build "
520 KERNEL_VERSION_BUILD_STR")\n");
521 HalDisplayString(RES_STR_LEGAL_COPYRIGHT);
522 HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
523 "Public License, and you\n");
524 HalDisplayString("are welcome to change it and/or distribute copies of it "
525 "under certain\n");
526 HalDisplayString("conditions. There is absolutely no warranty for "
527 "ReactOS.\n\n");
528
529 if (KeNumberProcessors > 1)
530 {
531 sprintf(str,
532 "Found %d system processors. [%lu MB Memory]\n",
533 KeNumberProcessors,
534 (KeLoaderBlock.MemHigher + 1088)/ 1024);
535 }
536 else
537 {
538 sprintf(str,
539 "Found 1 system processor. [%lu MB Memory]\n",
540 (KeLoaderBlock.MemHigher + 1088)/ 1024);
541 }
542 HalDisplayString(str);
543
544 KdInit3();
545
546
547 /* Create the NLS section */
548 RtlpCreateNlsSection();
549
550 /*
551 * Initalize services loaded at boot time
552 */
553 DPRINT("%d files loaded\n",KeLoaderBlock.ModsCount);
554 for (i=0; i < KeLoaderBlock.ModsCount; i++)
555 {
556 CPRINT("Module: '%s' at %08lx, length 0x%08lx\n",
557 KeLoaderModules[i].String,
558 KeLoaderModules[i].ModStart,
559 KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart);
560 }
561
562 /* Pass 1: import system hive registry chunk */
563 SetupBoot = TRUE;
564 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
565 {
566 start = KeLoaderModules[i].ModStart;
567 length = KeLoaderModules[i].ModEnd - start;
568
569 DPRINT("Module: '%s'\n", (PCHAR)KeLoaderModules[i].String);
570 name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
571 if (name == NULL)
572 {
573 name = (PCHAR)KeLoaderModules[i].String;
574 }
575 else
576 {
577 name++;
578 }
579
580 if (!_stricmp (name, "system") ||
581 !_stricmp (name, "system.hiv"))
582 {
583 CPRINT("Process system hive registry chunk at %08lx\n", start);
584 SetupBoot = FALSE;
585 CmImportSystemHive((PCHAR)start, length);
586 }
587 }
588
589 /* Pass 2: import hardware hive registry chunk */
590 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
591 {
592 start = KeLoaderModules[i].ModStart;
593 length = KeLoaderModules[i].ModEnd - start;
594 name = (PCHAR)KeLoaderModules[i].String;
595 if (!_stricmp (name, "hardware") ||
596 !_stricmp (name, "hardware.hiv"))
597 {
598 CPRINT("Process hardware hive registry chunk at %08lx\n", start);
599 CmImportHardwareHive((PCHAR)start, length);
600 }
601 }
602
603 /* Create dummy keys if no hardware hive was found */
604 CmImportHardwareHive (NULL, 0);
605
606 /* Initialize volatile registry settings */
607 if (SetupBoot == FALSE)
608 {
609 CmInit2((PCHAR)KeLoaderBlock.CommandLine);
610 }
611
612 /*
613 * Enter the kernel debugger before starting up the boot drivers
614 */
615 #ifdef KDBG
616 KdbEnter();
617 #endif /* KDBG */
618
619 IoCreateDriverList();
620
621 IoInit2();
622
623 /*
624 * Load boot start drivers
625 */
626 IopInitializeBootDrivers();
627
628 /* Display the boot screen image if not disabled */
629 if (!NoBootScreen)
630 {
631 InbvEnableBootDriver(TRUE);
632 }
633
634 /* Create ARC names for boot devices */
635 IoCreateArcNames();
636
637 /* Create the SystemRoot symbolic link */
638 CPRINT("CommandLine: %s\n", (PUCHAR)KeLoaderBlock.CommandLine);
639 Status = IoCreateSystemRootLink((PUCHAR)KeLoaderBlock.CommandLine);
640 if (!NT_SUCCESS(Status))
641 KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE);
642
643 #ifdef DBGPRINT_FILE_LOG
644 /* On the assumption that we can now access disks start up the debug
645 logger thread */
646 DebugLogInit2();
647 #endif /* DBGPRINT_FILE_LOG */
648
649 #ifdef KDBG
650 KdbInitProfiling2();
651 #endif /* KDBG */
652
653 PiInitDefaultLocale();
654
655 /*
656 * Load services for devices found by PnP manager
657 */
658 IopInitializePnpServices(IopRootDeviceNode, FALSE);
659
660 /*
661 * Load system start drivers
662 */
663 IopInitializeSystemDrivers();
664
665 IoDestroyDriverList();
666
667 /*
668 * Assign drive letters
669 */
670 IoAssignDriveLetters ((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock,
671 NULL,
672 NULL,
673 NULL);
674
675 /*
676 * Initialize shared user page:
677 * - set dos system path, dos device map, etc.
678 */
679 InitSystemSharedUserPage ((PUCHAR)KeLoaderBlock.CommandLine);
680
681 /* Create 'ReactOSInitDone' event */
682 RtlInitUnicodeString(&Name, L"\\ReactOSInitDone");
683 InitializeObjectAttributes(&ObjectAttributes,
684 &Name,
685 0,
686 NULL,
687 NULL);
688 Status = NtCreateEvent(&InitDoneEventHandle,
689 EVENT_ALL_ACCESS,
690 &ObjectAttributes,
691 FALSE, /* Synchronization event */
692 FALSE); /* Not signalled */
693 if (!NT_SUCCESS(Status))
694 {
695 DPRINT1("Failed to create 'ReactOSInitDone' event (Status 0x%x)\n", Status);
696 InitDoneEventHandle = INVALID_HANDLE_VALUE;
697 }
698
699 /*
700 * Launch initial process
701 */
702 Status = LdrLoadInitialProcess(&ProcessHandle,
703 &ThreadHandle);
704 if (!NT_SUCCESS(Status))
705 {
706 KEBUGCHECKEX(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
707 }
708
709 if (InitDoneEventHandle != INVALID_HANDLE_VALUE)
710 {
711 HANDLE Handles[2]; /* Init event, Initial process */
712
713 Handles[0] = InitDoneEventHandle;
714 Handles[1] = ProcessHandle;
715
716 /* Wait for the system to be initialized */
717 Timeout.QuadPart = -1200000000LL; /* 120 second timeout */
718 Status = NtWaitForMultipleObjects(((LONG) sizeof(Handles) / sizeof(HANDLE)),
719 Handles,
720 WaitAny,
721 FALSE, /* Non-alertable */
722 &Timeout);
723 if (!NT_SUCCESS(Status))
724 {
725 DPRINT1("NtWaitForMultipleObjects failed with status 0x%x!\n", Status);
726 }
727 else if (Status == STATUS_TIMEOUT)
728 {
729 DPRINT1("WARNING: System not initialized after 120 seconds.\n");
730 }
731 else if (Status == STATUS_WAIT_0 + 1)
732 {
733 /*
734 * Crash the system if the initial process was terminated.
735 */
736 KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 0, 0, 0);
737 }
738
739 if (!NoBootScreen)
740 {
741 InbvEnableBootDriver(FALSE);
742 }
743
744 NtSetEvent(InitDoneEventHandle, NULL);
745
746 NtClose(InitDoneEventHandle);
747 }
748 else
749 {
750 /* On failure to create 'ReactOSInitDone' event, go to text mode ASAP */
751 if (!NoBootScreen)
752 {
753 InbvEnableBootDriver(FALSE);
754 }
755
756 /*
757 * Crash the system if the initial process terminates within 5 seconds.
758 */
759 Timeout.QuadPart = -50000000LL;
760 Status = NtWaitForSingleObject(ProcessHandle,
761 FALSE,
762 &Timeout);
763 if (Status != STATUS_TIMEOUT)
764 {
765 KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 0, 0, 0);
766 }
767 }
768
769 NtClose(ThreadHandle);
770 NtClose(ProcessHandle);
771 }
772
773
774 VOID
775 KiSystemStartup(BOOLEAN BootProcessor)
776 {
777 HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
778
779 if (BootProcessor)
780 {
781 ExpInitializeExecutive();
782 MiFreeInitMemory();
783 /* Never returns */
784 PsTerminateSystemThread(STATUS_SUCCESS);
785 KEBUGCHECK(0);
786 }
787 /* Do application processor initialization */
788 KeApplicationProcessorInit();
789 PsApplicationProcessorInit();
790 KeLowerIrql(PASSIVE_LEVEL);
791 PsIdleThreadMain(NULL);
792 KEBUGCHECK(0);
793 for(;;);
794 }
795
796 VOID INIT_FUNCTION
797 _main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock)
798 /*
799 * FUNCTION: Called by the boot loader to start the kernel
800 * ARGUMENTS:
801 * LoaderBlock = Pointer to boot parameters initialized by the boot
802 * loader
803 * NOTE: The boot parameters are stored in low memory which will become
804 * invalid after the memory managment is initialized so we make a local copy.
805 */
806 {
807 ULONG i;
808 ULONG size;
809 ULONG last_kernel_address;
810 extern ULONG _bss_end__;
811 ULONG HalBase;
812 ULONG DriverBase;
813 ULONG DriverSize;
814
815 /* Low level architecture specific initialization */
816 KeInit1();
817
818 /*
819 * Copy the parameters to a local buffer because lowmem will go away
820 */
821 memcpy(&KeLoaderBlock, _LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
822 memcpy(&KeLoaderModules[1], (PVOID)KeLoaderBlock.ModsAddr,
823 sizeof(LOADER_MODULE) * KeLoaderBlock.ModsCount);
824 KeLoaderBlock.ModsCount++;
825 KeLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
826
827 /*
828 * Convert a path specification in the grub format to one understood by the
829 * rest of the kernel.
830 */
831 if (((PUCHAR)_LoaderBlock->CommandLine)[0] == '(')
832 {
833 ULONG DiskNumber = 0, PartNumber = 0;
834 PCH p;
835 CHAR Temp[256];
836 PCH options;
837 PCH s1;
838
839 if (((PUCHAR)_LoaderBlock->CommandLine)[1] == 'h' &&
840 ((PUCHAR)_LoaderBlock->CommandLine)[2] == 'd')
841 {
842 DiskNumber = ((PUCHAR)_LoaderBlock->CommandLine)[3] - '0';
843 PartNumber = ((PUCHAR)_LoaderBlock->CommandLine)[5] - '0';
844 }
845 strcpy(Temp, &((PUCHAR)_LoaderBlock->CommandLine)[7]);
846 if ((options = strchr(Temp, ' ')) != NULL)
847 {
848 *options = 0;
849 options++;
850 }
851 else
852 {
853 options = "";
854 }
855 if ((s1 = strrchr(Temp, '/')) != NULL)
856 {
857 *s1 = 0;
858 if ((s1 = strrchr(Temp, '/')) != NULL)
859 {
860 *s1 = 0;
861 }
862 }
863 sprintf(KeLoaderCommandLine,
864 "multi(0)disk(0)rdisk(%lu)partition(%lu)%s %s",
865 DiskNumber, PartNumber + 1, Temp, options);
866
867 p = KeLoaderCommandLine;
868 while (*p != 0 && *p != ' ')
869 {
870 if ((*p) == '/')
871 {
872 (*p) = '\\';
873 }
874 p++;
875 }
876 DPRINT1("Command Line: %s\n", KeLoaderCommandLine);
877 }
878 else
879 {
880 strcpy(KeLoaderCommandLine, (PUCHAR)_LoaderBlock->CommandLine);
881 }
882 KeLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
883
884 strcpy(KeLoaderModuleStrings[0], "ntoskrnl.exe");
885 KeLoaderModules[0].String = (ULONG)KeLoaderModuleStrings[0];
886 KeLoaderModules[0].ModStart = 0xC0000000;
887 KeLoaderModules[0].ModEnd = PAGE_ROUND_UP((ULONG)&_bss_end__);
888 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
889 {
890 CHAR* s;
891 if ((s = strrchr((PUCHAR)KeLoaderModules[i].String, '/')) != 0)
892 {
893 strcpy(KeLoaderModuleStrings[i], s + 1);
894 }
895 else
896 {
897 strcpy(KeLoaderModuleStrings[i], (PUCHAR)KeLoaderModules[i].String);
898 }
899 KeLoaderModules[i].ModStart -= 0x200000;
900 KeLoaderModules[i].ModStart += 0xc0000000;
901 KeLoaderModules[i].ModEnd -= 0x200000;
902 KeLoaderModules[i].ModEnd += 0xc0000000;
903 KeLoaderModules[i].String = (ULONG)KeLoaderModuleStrings[i];
904 }
905
906 #ifdef HAL_DBG
907 HalnInitializeDisplay((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
908 #endif
909
910 HalBase = KeLoaderModules[1].ModStart;
911 DriverBase =
912 PAGE_ROUND_UP(KeLoaderModules[KeLoaderBlock.ModsCount - 1].ModEnd);
913
914 /*
915 * Process hal.dll
916 */
917 LdrSafePEProcessModule((PVOID)HalBase, (PVOID)DriverBase, (PVOID)0xC0000000, &DriverSize);
918
919 LdrHalBase = (ULONG_PTR)DriverBase;
920 last_kernel_address = DriverBase + DriverSize;
921
922 /*
923 * Process ntoskrnl.exe
924 */
925 LdrSafePEProcessModule((PVOID)0xC0000000, (PVOID)0xC0000000, (PVOID)DriverBase, &DriverSize);
926
927 FirstKrnlPhysAddr = KeLoaderModules[0].ModStart - 0xc0000000 + 0x200000;
928 LastKrnlPhysAddr = last_kernel_address - 0xc0000000 + 0x200000;
929 LastKernelAddress = last_kernel_address;
930
931 #ifndef ACPI
932 /* FIXME: VMware does not like it when ReactOS is using the BIOS memory map */
933 KeLoaderBlock.Flags &= ~MB_FLAGS_MMAP_INFO;
934 #endif
935
936 KeMemoryMapRangeCount = 0;
937 if (KeLoaderBlock.Flags & MB_FLAGS_MMAP_INFO)
938 {
939 /* We have a memory map from the nice BIOS */
940 size = *((PULONG)(KeLoaderBlock.MmapAddr - sizeof(ULONG)));
941 i = 0;
942 while (i < KeLoaderBlock.MmapLength)
943 {
944 memcpy (&KeMemoryMap[KeMemoryMapRangeCount],
945 (PVOID)(KeLoaderBlock.MmapAddr + i),
946 sizeof(ADDRESS_RANGE));
947 KeMemoryMapRangeCount++;
948 i += size;
949 }
950 }
951
952 KiSystemStartup(1);
953 }
954
955 /* EOF */
956