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