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