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