466415b0c14648e27c57987be59adf8150187812
[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.179 2003/12/14 18:16:18 hbirr 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/nls.h>
51 #include <reactos/bugcodes.h>
52 #include <ntos/bootvid.h>
53 #include <napi/core.h>
54
55 #ifdef HALDBG
56 #include <internal/ntosdbg.h>
57 #else
58 #define ps(args...)
59 #endif
60
61 #define NDEBUG
62 #include <internal/debug.h>
63
64 /* GLOBALS *******************************************************************/
65
66 ULONG EXPORTED NtBuildNumber = KERNEL_VERSION_BUILD;
67 ULONG EXPORTED NtGlobalFlag = 0;
68 CHAR EXPORTED KeNumberProcessors;
69 LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock;
70 ULONG EXPORTED KeDcacheFlushCount = 0;
71 ULONG EXPORTED KeIcacheFlushCount = 0;
72 static LOADER_MODULE KeLoaderModules[64];
73 static UCHAR KeLoaderModuleStrings[64][256];
74 static UCHAR KeLoaderCommandLine[256];
75 static ADDRESS_RANGE KeMemoryMap[64];
76 static ULONG KeMemoryMapRangeCount;
77 static ULONG FirstKrnlPhysAddr;
78 static ULONG LastKrnlPhysAddr;
79 static ULONG LastKernelAddress;
80 volatile BOOLEAN Initialized = FALSE;
81 extern ULONG MmCoreDumpType;
82
83 extern PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS];
84
85
86 /* FUNCTIONS ****************************************************************/
87
88 static VOID INIT_FUNCTION
89 InitSystemSharedUserPage (PCSZ ParameterLine)
90 {
91 UNICODE_STRING ArcDeviceName;
92 UNICODE_STRING ArcName;
93 UNICODE_STRING BootPath;
94 UNICODE_STRING DriveDeviceName;
95 UNICODE_STRING DriveName;
96 WCHAR DriveNameBuffer[20];
97 PCHAR ParamBuffer;
98 PWCHAR ArcNameBuffer;
99 PCHAR p;
100 NTSTATUS Status;
101 ULONG Length;
102 OBJECT_ATTRIBUTES ObjectAttributes;
103 HANDLE Handle;
104 ULONG i;
105 BOOLEAN BootDriveFound;
106
107 /*
108 * NOTE:
109 * The shared user page has been zeroed-out right after creation.
110 * There is NO need to do this again.
111 */
112
113 SharedUserData->NtProductType = NtProductWinNt;
114
115 BootDriveFound = FALSE;
116
117 /*
118 * Retrieve the current dos system path
119 * (e.g.: C:\reactos) from the given arc path
120 * (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos)
121 * Format: "<arc_name>\<path> [options...]"
122 */
123
124 /* create local parameter line copy */
125 ParamBuffer = ExAllocatePool (PagedPool, 256);
126 strcpy (ParamBuffer, (char *)ParameterLine);
127 DPRINT("%s\n", ParamBuffer);
128
129 /* cut options off */
130 p = strchr (ParamBuffer, ' ');
131 if (p)
132 {
133 *p = 0;
134 }
135 DPRINT("%s\n", ParamBuffer);
136
137 /* extract path */
138 p = strchr (ParamBuffer, '\\');
139 if (p)
140 {
141 DPRINT("Boot path: %s\n", p);
142 RtlCreateUnicodeStringFromAsciiz (&BootPath, p);
143 *p = 0;
144 }
145 else
146 {
147 DPRINT("Boot path: %s\n", "\\");
148 RtlCreateUnicodeStringFromAsciiz (&BootPath, "\\");
149 }
150 DPRINT("Arc name: %s\n", ParamBuffer);
151
152 /* Only arc name left - build full arc name */
153 ArcNameBuffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
154 swprintf (ArcNameBuffer, L"\\ArcName\\%S", ParamBuffer);
155 RtlInitUnicodeString (&ArcName, ArcNameBuffer);
156 DPRINT("Arc name: %wZ\n", &ArcName);
157
158 /* free ParamBuffer */
159 ExFreePool (ParamBuffer);
160
161 /* allocate arc device name string */
162 ArcDeviceName.Length = 0;
163 ArcDeviceName.MaximumLength = 256 * sizeof(WCHAR);
164 ArcDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
165
166 InitializeObjectAttributes (&ObjectAttributes,
167 &ArcName,
168 OBJ_OPENLINK,
169 NULL,
170 NULL);
171
172 Status = NtOpenSymbolicLinkObject (&Handle,
173 SYMBOLIC_LINK_ALL_ACCESS,
174 &ObjectAttributes);
175 RtlFreeUnicodeString (&ArcName);
176 if (!NT_SUCCESS(Status))
177 {
178 RtlFreeUnicodeString (&BootPath);
179 RtlFreeUnicodeString (&ArcDeviceName);
180 CPRINT("NtOpenSymbolicLinkObject() failed (Status %x)\n",
181 Status);
182
183 KEBUGCHECK (0x0);
184 }
185
186 Status = NtQuerySymbolicLinkObject (Handle,
187 &ArcDeviceName,
188 &Length);
189 NtClose (Handle);
190 if (!NT_SUCCESS(Status))
191 {
192 RtlFreeUnicodeString (&BootPath);
193 RtlFreeUnicodeString (&ArcDeviceName);
194 CPRINT("NtQuerySymbolicObject() failed (Status %x)\n",
195 Status);
196
197 KEBUGCHECK (0x0);
198 }
199 DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length, &ArcDeviceName);
200
201
202 /* allocate device name string */
203 DriveDeviceName.Length = 0;
204 DriveDeviceName.MaximumLength = 256 * sizeof(WCHAR);
205 DriveDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
206
207 for (i = 0; i < 26; i++)
208 {
209 swprintf (DriveNameBuffer, L"\\??\\%C:", 'A' + i);
210 RtlInitUnicodeString (&DriveName,
211 DriveNameBuffer);
212
213 InitializeObjectAttributes (&ObjectAttributes,
214 &DriveName,
215 OBJ_OPENLINK,
216 NULL,
217 NULL);
218
219 Status = NtOpenSymbolicLinkObject (&Handle,
220 SYMBOLIC_LINK_ALL_ACCESS,
221 &ObjectAttributes);
222 if (!NT_SUCCESS(Status))
223 {
224 DPRINT("Failed to open link %wZ\n",
225 &DriveName);
226 continue;
227 }
228
229 Status = NtQuerySymbolicLinkObject (Handle,
230 &DriveDeviceName,
231 &Length);
232 if (!NT_SUCCESS(Status))
233 {
234 DPRINT("Failed query open link %wZ\n",
235 &DriveName);
236 continue;
237 }
238 DPRINT("Opened link: %wZ ==> %wZ\n",
239 &DriveName, &DriveDeviceName);
240
241 if (!RtlCompareUnicodeString (&ArcDeviceName, &DriveDeviceName, FALSE))
242 {
243 DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i, &BootPath);
244 swprintf(SharedUserData->NtSystemRoot,
245 L"%C:%wZ", 'A' + i, &BootPath);
246
247 BootDriveFound = TRUE;
248 }
249
250 NtClose (Handle);
251 }
252
253 RtlFreeUnicodeString (&BootPath);
254 RtlFreeUnicodeString (&DriveDeviceName);
255 RtlFreeUnicodeString (&ArcDeviceName);
256
257 DPRINT("DosDeviceMap: 0x%x\n", SharedUserData->DosDeviceMap);
258
259 if (BootDriveFound == FALSE)
260 {
261 DbgPrint("No system drive found!\n");
262 KEBUGCHECK (0x0);
263 }
264 }
265
266 VOID INIT_FUNCTION
267 ExpInitializeExecutive(VOID)
268 {
269 LARGE_INTEGER Timeout;
270 HANDLE ProcessHandle;
271 HANDLE ThreadHandle;
272 ULONG i;
273 ULONG start;
274 ULONG length;
275 PCHAR name;
276 CHAR str[50];
277 NTSTATUS Status;
278 BOOLEAN SetupBoot;
279 PCHAR p1, p2;
280 ULONG MaxMem;
281 BOOLEAN NoBootScreen = FALSE;
282 UNICODE_STRING Name;
283 HANDLE InitDoneEventHandle;
284 OBJECT_ATTRIBUTES ObjectAttributes;
285
286 /*
287 * Fail at runtime if someone has changed various structures without
288 * updating the offsets used for the assembler code.
289 */
290 assert(FIELD_OFFSET(KTHREAD, InitialStack) == KTHREAD_INITIAL_STACK);
291 assert(FIELD_OFFSET(KTHREAD, Teb) == KTHREAD_TEB);
292 assert(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK);
293 assert(FIELD_OFFSET(KTHREAD, ServiceTable) == KTHREAD_SERVICE_TABLE);
294 assert(FIELD_OFFSET(KTHREAD, PreviousMode) == KTHREAD_PREVIOUS_MODE);
295 assert(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME);
296 assert(FIELD_OFFSET(KTHREAD, CallbackStack) == KTHREAD_CALLBACK_STACK);
297 assert(FIELD_OFFSET(ETHREAD, ThreadsProcess) == ETHREAD_THREADS_PROCESS);
298 assert(FIELD_OFFSET(KPROCESS, DirectoryTableBase) ==
299 KPROCESS_DIRECTORY_TABLE_BASE);
300 assert(FIELD_OFFSET(KPROCESS, IopmOffset) == KPROCESS_IOPM_OFFSET);
301 assert(FIELD_OFFSET(KPROCESS, LdtDescriptor) == KPROCESS_LDT_DESCRIPTOR0);
302 assert(FIELD_OFFSET(KTRAP_FRAME, Reserved9) == KTRAP_FRAME_RESERVED9);
303 assert(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
304 assert(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
305
306 assert(FIELD_OFFSET(KPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
307 assert(FIELD_OFFSET(KPCR, Self) == KPCR_SELF);
308 assert(FIELD_OFFSET(IKPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
309 assert(FIELD_OFFSET(IKPCR, Self) == KPCR_SELF);
310 assert(FIELD_OFFSET(IKPCR, CurrentThread) == KPCR_CURRENT_THREAD);
311
312 LdrInit1();
313
314 KeLowerIrql(DISPATCH_LEVEL);
315
316 NtEarlyInitVdm();
317
318 p1 = (PCHAR)KeLoaderBlock.CommandLine;
319
320 MaxMem = 0;
321 while(*p1 && (p2 = strchr(p1, '/')))
322 {
323 p2++;
324 if (!_strnicmp(p2, "MAXMEM", 6))
325 {
326 p2 += 6;
327 while (isspace(*p2)) p2++;
328 if (*p2 == '=')
329 {
330 p2++;
331 while(isspace(*p2)) p2++;
332 if (isdigit(*p2))
333 {
334 while (isdigit(*p2))
335 {
336 MaxMem = MaxMem * 10 + *p2 - '0';
337 p2++;
338 }
339 break;
340 }
341 }
342 }
343 else if (!_strnicmp(p2, "NOBOOTSCREEN", 12))
344 {
345 p2 += 12;
346 NoBootScreen = TRUE;
347 }
348 else if (!_strnicmp(p2, "CRASHDUMP", 9))
349 {
350 p2 += 9;
351 if (*p2 == ':')
352 {
353 p2++;
354 if (!_strnicmp(p2, "FULL", 4))
355 {
356 MmCoreDumpType = MM_CORE_DUMP_TYPE_FULL;
357 }
358 else
359 {
360 MmCoreDumpType = MM_CORE_DUMP_TYPE_NONE;
361 }
362 }
363 }
364 p1 = p2;
365 }
366
367 MmInit1(FirstKrnlPhysAddr,
368 LastKrnlPhysAddr,
369 LastKernelAddress,
370 (PADDRESS_RANGE)&KeMemoryMap,
371 KeMemoryMapRangeCount,
372 MaxMem > 8 ? MaxMem : 4096);
373
374 /* Import ANSI code page table */
375 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
376 {
377 start = KeLoaderModules[i].ModStart;
378 length = KeLoaderModules[i].ModEnd - start;
379
380 name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
381 if (name == NULL)
382 {
383 name = (PCHAR)KeLoaderModules[i].String;
384 }
385 else
386 {
387 name++;
388 }
389
390 if (!_stricmp (name, "ansi.nls"))
391 {
392 RtlpImportAnsiCodePage((PUSHORT)start, length);
393 }
394 }
395
396 /* Import OEM code page table */
397 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
398 {
399 start = KeLoaderModules[i].ModStart;
400 length = KeLoaderModules[i].ModEnd - start;
401
402 name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
403 if (name == NULL)
404 {
405 name = (PCHAR)KeLoaderModules[i].String;
406 }
407 else
408 {
409 name++;
410 }
411
412 if (!_stricmp (name, "oem.nls"))
413 {
414 RtlpImportOemCodePage((PUSHORT)start, length);
415 }
416 }
417
418 /* Import Unicode casemap table */
419 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
420 {
421 start = KeLoaderModules[i].ModStart;
422 length = KeLoaderModules[i].ModEnd - start;
423
424 name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
425 if (name == NULL)
426 {
427 name = (PCHAR)KeLoaderModules[i].String;
428 }
429 else
430 {
431 name++;
432 }
433
434 if (!_stricmp (name, "casemap.nls"))
435 {
436 RtlpImportUnicodeCasemap((PUSHORT)start, length);
437 }
438 }
439
440 /* Create initial NLS tables */
441 RtlpCreateInitialNlsTables();
442
443 /*
444 * Initialize the kernel debugger
445 */
446 KdInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
447
448 KeInit2();
449
450 KeLowerIrql(PASSIVE_LEVEL);
451
452 if (!SeInit1())
453 KEBUGCHECK(SECURITY_INITIALIZATION_FAILED);
454
455 ObInit();
456 ExInit2();
457 MmInit2();
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 ExInit3();
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 /*
797 * FIXME:
798 * INIT_FUNCTION is temporary disabled, because if ntoskrnl is compiled with
799 * higher optimisation levels, gcc puts directly some code from KiSystemStartup
800 * into _main. This code frees the memory from the init section (_main) and
801 * that does crash reactos.
802 */
803 VOID /*INIT_FUNCTION*/
804 _main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock)
805 /*
806 * FUNCTION: Called by the boot loader to start the kernel
807 * ARGUMENTS:
808 * LoaderBlock = Pointer to boot parameters initialized by the boot
809 * loader
810 * NOTE: The boot parameters are stored in low memory which will become
811 * invalid after the memory managment is initialized so we make a local copy.
812 */
813 {
814 ULONG i;
815 ULONG size;
816 ULONG last_kernel_address;
817 extern ULONG _bss_end__;
818 ULONG HalBase;
819 ULONG DriverBase;
820 ULONG DriverSize;
821
822 /* Low level architecture specific initialization */
823 KeInit1();
824
825 /*
826 * Copy the parameters to a local buffer because lowmem will go away
827 */
828 memcpy(&KeLoaderBlock, _LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
829 memcpy(&KeLoaderModules[1], (PVOID)KeLoaderBlock.ModsAddr,
830 sizeof(LOADER_MODULE) * KeLoaderBlock.ModsCount);
831 KeLoaderBlock.ModsCount++;
832 KeLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
833
834 /*
835 * Convert a path specification in the grub format to one understood by the
836 * rest of the kernel.
837 */
838 if (((PUCHAR)_LoaderBlock->CommandLine)[0] == '(')
839 {
840 ULONG DiskNumber = 0, PartNumber = 0;
841 PCH p;
842 CHAR Temp[256];
843 PCH options;
844 PCH s1;
845
846 if (((PUCHAR)_LoaderBlock->CommandLine)[1] == 'h' &&
847 ((PUCHAR)_LoaderBlock->CommandLine)[2] == 'd')
848 {
849 DiskNumber = ((PUCHAR)_LoaderBlock->CommandLine)[3] - '0';
850 PartNumber = ((PUCHAR)_LoaderBlock->CommandLine)[5] - '0';
851 }
852 strcpy(Temp, &((PUCHAR)_LoaderBlock->CommandLine)[7]);
853 if ((options = strchr(Temp, ' ')) != NULL)
854 {
855 *options = 0;
856 options++;
857 }
858 else
859 {
860 options = "";
861 }
862 if ((s1 = strrchr(Temp, '/')) != NULL)
863 {
864 *s1 = 0;
865 if ((s1 = strrchr(Temp, '/')) != NULL)
866 {
867 *s1 = 0;
868 }
869 }
870 sprintf(KeLoaderCommandLine,
871 "multi(0)disk(0)rdisk(%lu)partition(%lu)%s %s",
872 DiskNumber, PartNumber + 1, Temp, options);
873
874 p = KeLoaderCommandLine;
875 while (*p != 0 && *p != ' ')
876 {
877 if ((*p) == '/')
878 {
879 (*p) = '\\';
880 }
881 p++;
882 }
883 DPRINT1("Command Line: %s\n", KeLoaderCommandLine);
884 }
885 else
886 {
887 strcpy(KeLoaderCommandLine, (PUCHAR)_LoaderBlock->CommandLine);
888 }
889 KeLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
890
891 strcpy(KeLoaderModuleStrings[0], "ntoskrnl.exe");
892 KeLoaderModules[0].String = (ULONG)KeLoaderModuleStrings[0];
893 KeLoaderModules[0].ModStart = 0xC0000000;
894 KeLoaderModules[0].ModEnd = PAGE_ROUND_UP((ULONG)&_bss_end__);
895 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
896 {
897 CHAR* s;
898 if ((s = strrchr((PUCHAR)KeLoaderModules[i].String, '/')) != 0)
899 {
900 strcpy(KeLoaderModuleStrings[i], s + 1);
901 }
902 else
903 {
904 strcpy(KeLoaderModuleStrings[i], (PUCHAR)KeLoaderModules[i].String);
905 }
906 KeLoaderModules[i].ModStart -= 0x200000;
907 KeLoaderModules[i].ModStart += 0xc0000000;
908 KeLoaderModules[i].ModEnd -= 0x200000;
909 KeLoaderModules[i].ModEnd += 0xc0000000;
910 KeLoaderModules[i].String = (ULONG)KeLoaderModuleStrings[i];
911 }
912
913 #ifdef HAL_DBG
914 HalnInitializeDisplay((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
915 #endif
916
917 HalBase = KeLoaderModules[1].ModStart;
918 DriverBase =
919 PAGE_ROUND_UP(KeLoaderModules[KeLoaderBlock.ModsCount - 1].ModEnd);
920
921 /*
922 * Process hal.dll
923 */
924 LdrSafePEProcessModule((PVOID)HalBase, (PVOID)DriverBase, (PVOID)0xC0000000, &DriverSize);
925
926 LdrHalBase = (ULONG_PTR)DriverBase;
927 last_kernel_address = DriverBase + DriverSize;
928
929 /*
930 * Process ntoskrnl.exe
931 */
932 LdrSafePEProcessModule((PVOID)0xC0000000, (PVOID)0xC0000000, (PVOID)DriverBase, &DriverSize);
933
934 FirstKrnlPhysAddr = KeLoaderModules[0].ModStart - 0xc0000000 + 0x200000;
935 LastKrnlPhysAddr = last_kernel_address - 0xc0000000 + 0x200000;
936 LastKernelAddress = last_kernel_address;
937
938 #ifndef ACPI
939 /* FIXME: VMware does not like it when ReactOS is using the BIOS memory map */
940 KeLoaderBlock.Flags &= ~MB_FLAGS_MMAP_INFO;
941 #endif
942
943 KeMemoryMapRangeCount = 0;
944 if (KeLoaderBlock.Flags & MB_FLAGS_MMAP_INFO)
945 {
946 /* We have a memory map from the nice BIOS */
947 size = *((PULONG)(KeLoaderBlock.MmapAddr - sizeof(ULONG)));
948 i = 0;
949 while (i < KeLoaderBlock.MmapLength)
950 {
951 memcpy (&KeMemoryMap[KeMemoryMapRangeCount],
952 (PVOID)(KeLoaderBlock.MmapAddr + i),
953 sizeof(ADDRESS_RANGE));
954 KeMemoryMapRangeCount++;
955 i += size;
956 }
957 }
958
959 KiSystemStartup(1);
960 }
961
962 /* EOF */
963