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