Reverting to 13775. Sorry for the mess. This is dedicated to Jane! 19934415.
[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();
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) || defined(DBG)
700 KdbInitProfiling2();
701 #endif /* KDBG */
702
703 /* On the assumption that we can now access disks start up the debug
704 * logger thread */
705 if ((KdDebuggerEnabled == TRUE) && (KdDebugState & KD_DEBUG_BOOTLOG))
706 {
707 DebugLogInit2();
708 }
709
710 PiInitDefaultLocale();
711
712 /*
713 * Load services for devices found by PnP manager
714 */
715 IopInitializePnpServices(IopRootDeviceNode, FALSE);
716
717 /*
718 * Load system start drivers
719 */
720 IopInitializeSystemDrivers();
721
722 IoDestroyDriverList();
723
724 /* Stop boot logging */
725 IopStopBootLog();
726
727 /*
728 * Assign drive letters
729 */
730 IoAssignDriveLetters ((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock,
731 NULL,
732 NULL,
733 NULL);
734
735 /*
736 * Initialize shared user page:
737 * - set dos system path, dos device map, etc.
738 */
739 InitSystemSharedUserPage ((PCHAR)KeLoaderBlock.CommandLine);
740
741 /* Create 'ReactOSInitDone' event */
742 RtlInitUnicodeString(&Name, L"\\ReactOSInitDone");
743 InitializeObjectAttributes(&ObjectAttributes,
744 &Name,
745 0,
746 NULL,
747 NULL);
748 Status = ZwCreateEvent(&InitDoneEventHandle,
749 EVENT_ALL_ACCESS,
750 &ObjectAttributes,
751 SynchronizationEvent,
752 FALSE); /* Not signalled */
753 if (!NT_SUCCESS(Status))
754 {
755 DPRINT1("Failed to create 'ReactOSInitDone' event (Status 0x%x)\n", Status);
756 InitDoneEventHandle = INVALID_HANDLE_VALUE;
757 }
758
759 /*
760 * Launch initial process
761 */
762 Status = LdrLoadInitialProcess(&ProcessHandle,
763 &ThreadHandle);
764 if (!NT_SUCCESS(Status))
765 {
766 KEBUGCHECKEX(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
767 }
768
769 if (InitDoneEventHandle != INVALID_HANDLE_VALUE)
770 {
771 HANDLE Handles[2]; /* Init event, Initial process */
772
773 Handles[0] = InitDoneEventHandle;
774 Handles[1] = ProcessHandle;
775
776 /* Wait for the system to be initialized */
777 Timeout.QuadPart = (LONGLONG)-1200000000; /* 120 second timeout */
778 Status = ZwWaitForMultipleObjects(((LONG) sizeof(Handles) / sizeof(HANDLE)),
779 Handles,
780 WaitAny,
781 FALSE, /* Non-alertable */
782 &Timeout);
783 if (!NT_SUCCESS(Status))
784 {
785 DPRINT1("NtWaitForMultipleObjects failed with status 0x%x!\n", Status);
786 }
787 else if (Status == STATUS_TIMEOUT)
788 {
789 DPRINT1("WARNING: System not initialized after 120 seconds.\n");
790 }
791 else if (Status == STATUS_WAIT_0 + 1)
792 {
793 /*
794 * Crash the system if the initial process was terminated.
795 */
796 KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 0, 0, 0);
797 }
798
799 if (!NoGuiBoot)
800 {
801 InbvEnableBootDriver(FALSE);
802 }
803
804 ZwSetEvent(InitDoneEventHandle, NULL);
805
806 ZwClose(InitDoneEventHandle);
807 }
808 else
809 {
810 /* On failure to create 'ReactOSInitDone' event, go to text mode ASAP */
811 if (!NoGuiBoot)
812 {
813 InbvEnableBootDriver(FALSE);
814 }
815
816 /*
817 * Crash the system if the initial process terminates within 5 seconds.
818 */
819 Timeout.QuadPart = (LONGLONG)-50000000; /* 5 second timeout */
820 Status = ZwWaitForSingleObject(ProcessHandle,
821 FALSE,
822 &Timeout);
823 if (Status != STATUS_TIMEOUT)
824 {
825 KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 1, 0, 0);
826 }
827 }
828 /*
829 * Tell ke/timer.c it's okay to run.
830 */
831
832 KiTimerSystemAuditing = 1;
833
834 ZwClose(ThreadHandle);
835 ZwClose(ProcessHandle);
836 }
837
838 VOID __attribute((noinline))
839 KiSystemStartup(BOOLEAN BootProcessor)
840 {
841 DPRINT1("KiSystemStartup(%d)\n", BootProcessor);
842 if (BootProcessor)
843 {
844 }
845 else
846 {
847 KeApplicationProcessorInit();
848 }
849
850 HalInitializeProcessor(KeNumberProcessors, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
851
852 if (BootProcessor)
853 {
854 ExpInitializeExecutive();
855 MiFreeInitMemory();
856 /* Never returns */
857 PsTerminateSystemThread(STATUS_SUCCESS);
858 }
859 else
860 {
861 /* Do application processor initialization */
862 PsApplicationProcessorInit();
863 KeLowerIrql(PASSIVE_LEVEL);
864 PsIdleThreadMain(NULL);
865 }
866 KEBUGCHECK(0);
867 for(;;);
868 }
869
870 VOID INIT_FUNCTION
871 _main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock)
872 /*
873 * FUNCTION: Called by the boot loader to start the kernel
874 * ARGUMENTS:
875 * LoaderBlock = Pointer to boot parameters initialized by the boot
876 * loader
877 * NOTE: The boot parameters are stored in low memory which will become
878 * invalid after the memory managment is initialized so we make a local copy.
879 */
880 {
881 ULONG i;
882 ULONG size;
883 ULONG HalBase;
884 ULONG DriverBase;
885 ULONG DriverSize;
886
887 /* Set up the Stacks */
888 trap_stack = PAGE_ROUND_UP(&double_trap_stack);
889 trap_stack_top = trap_stack + 3 * PAGE_SIZE;
890 init_stack = PAGE_ROUND_UP(&kernel_stack);
891 init_stack_top = init_stack + 3 * PAGE_SIZE;
892
893 /*
894 * Copy the parameters to a local buffer because lowmem will go away
895 */
896 memcpy(&KeLoaderBlock, _LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
897 memcpy(&KeLoaderModules[1], (PVOID)KeLoaderBlock.ModsAddr,
898 sizeof(LOADER_MODULE) * KeLoaderBlock.ModsCount);
899 KeLoaderBlock.ModsCount++;
900 KeLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
901
902 /* Save the Base Address */
903 MmSystemRangeStart = (PVOID)KeLoaderBlock.KernelBase;
904
905 /*
906 * Convert a path specification in the grub format to one understood by the
907 * rest of the kernel.
908 */
909 if (((PUCHAR)_LoaderBlock->CommandLine)[0] == '(')
910 {
911 ULONG DiskNumber = 0, PartNumber = 0;
912 PCH p;
913 CHAR Temp[256];
914 PCH options;
915 PCH s1;
916
917 if (((PUCHAR)_LoaderBlock->CommandLine)[1] == 'h' &&
918 ((PUCHAR)_LoaderBlock->CommandLine)[2] == 'd')
919 {
920 DiskNumber = ((PCHAR)_LoaderBlock->CommandLine)[3] - '0';
921 PartNumber = ((PCHAR)_LoaderBlock->CommandLine)[5] - '0';
922 }
923 strcpy(Temp, &((PCHAR)_LoaderBlock->CommandLine)[7]);
924 if ((options = strchr(Temp, ' ')) != NULL)
925 {
926 *options = 0;
927 options++;
928 }
929 else
930 {
931 options = "";
932 }
933 if ((s1 = strrchr(Temp, '/')) != NULL)
934 {
935 *s1 = 0;
936 if ((s1 = strrchr(Temp, '/')) != NULL)
937 {
938 *s1 = 0;
939 }
940 }
941 sprintf(KeLoaderCommandLine,
942 "multi(0)disk(0)rdisk(%lu)partition(%lu)%s %s",
943 DiskNumber, PartNumber + 1, Temp, options);
944
945 p = KeLoaderCommandLine;
946 while (*p != 0 && *p != ' ')
947 {
948 if ((*p) == '/')
949 {
950 (*p) = '\\';
951 }
952 p++;
953 }
954 DPRINT1("Command Line: %s\n", KeLoaderCommandLine);
955 }
956 else
957 {
958 strcpy(KeLoaderCommandLine, (PCHAR)_LoaderBlock->CommandLine);
959 }
960 KeLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
961
962 strcpy(KeLoaderModuleStrings[0], "ntoskrnl.exe");
963 KeLoaderModules[0].String = (ULONG)KeLoaderModuleStrings[0];
964 KeLoaderModules[0].ModStart = KERNEL_BASE;
965 /* Take this value from the PE... */
966 PIMAGE_NT_HEADERS NtHeader = RtlImageNtHeader((PVOID)KeLoaderModules[0].ModStart);
967 PIMAGE_OPTIONAL_HEADER OptHead = &NtHeader->OptionalHeader;
968 KeLoaderModules[0].ModEnd = KeLoaderModules[0].ModStart + PAGE_ROUND_UP((ULONG)OptHead->SizeOfImage);
969 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
970 {
971 CHAR* s;
972 if ((s = strrchr((PCHAR)KeLoaderModules[i].String, '/')) != 0)
973 {
974 strcpy(KeLoaderModuleStrings[i], s + 1);
975 }
976 else
977 {
978 strcpy(KeLoaderModuleStrings[i], (PCHAR)KeLoaderModules[i].String);
979 }
980 KeLoaderModules[i].ModStart -= 0x200000;
981 KeLoaderModules[i].ModStart += KERNEL_BASE;
982 KeLoaderModules[i].ModEnd -= 0x200000;
983 KeLoaderModules[i].ModEnd += KERNEL_BASE;
984 KeLoaderModules[i].String = (ULONG)KeLoaderModuleStrings[i];
985 }
986
987 LastKernelAddress = PAGE_ROUND_UP(KeLoaderModules[KeLoaderBlock.ModsCount - 1].ModEnd);
988
989 /* Low level architecture specific initialization */
990 KeInit1((PCHAR)KeLoaderBlock.CommandLine, &LastKernelAddress);
991
992 HalBase = KeLoaderModules[1].ModStart;
993 DriverBase = LastKernelAddress;
994 LdrHalBase = (ULONG_PTR)DriverBase;
995
996 LdrInitModuleManagement();
997
998 /*
999 * Process hal.dll
1000 */
1001 LdrSafePEProcessModule((PVOID)HalBase, (PVOID)DriverBase, (PVOID)KERNEL_BASE, &DriverSize);
1002
1003 LastKernelAddress += PAGE_ROUND_UP(DriverSize);
1004
1005 /*
1006 * Process ntoskrnl.exe
1007 */
1008 LdrSafePEProcessModule((PVOID)KERNEL_BASE, (PVOID)KERNEL_BASE, (PVOID)DriverBase, &DriverSize);
1009
1010 /* Now our imports from HAL are fixed. This is the first */
1011 /* time in the boot process that we can use HAL */
1012
1013 FirstKrnlPhysAddr = KeLoaderModules[0].ModStart - KERNEL_BASE + 0x200000;
1014 LastKrnlPhysAddr = LastKernelAddress - KERNEL_BASE + 0x200000;
1015
1016 KeMemoryMapRangeCount = 0;
1017 if (KeLoaderBlock.Flags & MB_FLAGS_MMAP_INFO)
1018 {
1019 /* We have a memory map from the nice BIOS */
1020 size = *((PULONG)(KeLoaderBlock.MmapAddr - sizeof(ULONG)));
1021 i = 0;
1022 while (i < KeLoaderBlock.MmapLength)
1023 {
1024 memcpy (&KeMemoryMap[KeMemoryMapRangeCount],
1025 (PVOID)(KeLoaderBlock.MmapAddr + i),
1026 sizeof(ADDRESS_RANGE));
1027 KeMemoryMapRangeCount++;
1028 i += size;
1029 }
1030 KeLoaderBlock.MmapLength = KeMemoryMapRangeCount * sizeof(ADDRESS_RANGE);
1031 KeLoaderBlock.MmapAddr = (ULONG)KeMemoryMap;
1032 }
1033 else
1034 {
1035 KeLoaderBlock.MmapLength = 0;
1036 KeLoaderBlock.MmapAddr = (ULONG)KeMemoryMap;
1037 }
1038
1039 KdInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
1040 HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
1041
1042 DPRINT1("_main (%x, %x)\n", MultiBootMagic, _LoaderBlock);
1043
1044
1045 KiSystemStartup(1);
1046 }
1047
1048 /* EOF */
1049