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