3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
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.
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.
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.
19 /* $Id: main.c,v 1.173 2003/10/12 16:39:52 vizzini Exp $
21 * PROJECT: ReactOS kernel
22 * FILE: ntoskrnl/ke/main.c
23 * PURPOSE: Initalizes the kernel
24 * PROGRAMMER: David Welch (welch@cwcom.net)
29 /* INCLUDES *****************************************************************/
31 #define NTOS_MODE_KERNEL
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 #include <napi/core.h>
57 #include <internal/ntosdbg.h>
63 #include <internal/debug.h>
65 /* GLOBALS *******************************************************************/
67 ULONG EXPORTED NtBuildNumber
= KERNEL_VERSION_BUILD
;
68 ULONG EXPORTED NtGlobalFlag
= 0;
69 CHAR EXPORTED KeNumberProcessors
;
70 LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock
;
71 ULONG EXPORTED KeDcacheFlushCount
= 0;
72 ULONG EXPORTED KeIcacheFlushCount
= 0;
73 static LOADER_MODULE KeLoaderModules
[64];
74 static UCHAR KeLoaderModuleStrings
[64][256];
75 static UCHAR KeLoaderCommandLine
[256];
76 static ADDRESS_RANGE KeMemoryMap
[64];
77 static ULONG KeMemoryMapRangeCount
;
78 static ULONG FirstKrnlPhysAddr
;
79 static ULONG LastKrnlPhysAddr
;
80 static ULONG LastKernelAddress
;
81 volatile BOOLEAN Initialized
= FALSE
;
82 extern ULONG MmCoreDumpType
;
84 extern PVOID Ki386InitialStackArray
[MAXIMUM_PROCESSORS
];
87 /* FUNCTIONS ****************************************************************/
90 RtlpCheckFileNameExtension(PCHAR FileName
,
95 Ext
= strrchr(FileName
, '.');
98 if ((Extension
== NULL
) || (*Extension
== 0))
104 if (*Extension
!= '.')
107 if (_stricmp(Ext
, Extension
) == 0)
115 InitSystemSharedUserPage (PCSZ ParameterLine
)
117 UNICODE_STRING ArcDeviceName
;
118 UNICODE_STRING ArcName
;
119 UNICODE_STRING BootPath
;
120 UNICODE_STRING DriveDeviceName
;
121 UNICODE_STRING DriveName
;
122 WCHAR DriveNameBuffer
[20];
124 PWCHAR ArcNameBuffer
;
128 OBJECT_ATTRIBUTES ObjectAttributes
;
131 BOOLEAN BootDriveFound
;
135 * The shared user page has been zeroed-out right after creation.
136 * There is NO need to do this again.
139 SharedUserData
->NtProductType
= NtProductWinNt
;
141 BootDriveFound
= FALSE
;
144 * Retrieve the current dos system path
145 * (e.g.: C:\reactos) from the given arc path
146 * (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos)
147 * Format: "<arc_name>\<path> [options...]"
150 /* create local parameter line copy */
151 ParamBuffer
= ExAllocatePool (PagedPool
, 256);
152 strcpy (ParamBuffer
, (char *)ParameterLine
);
153 DPRINT("%s\n", ParamBuffer
);
155 /* cut options off */
156 p
= strchr (ParamBuffer
, ' ');
161 DPRINT("%s\n", ParamBuffer
);
164 p
= strchr (ParamBuffer
, '\\');
167 DPRINT("Boot path: %s\n", p
);
168 RtlCreateUnicodeStringFromAsciiz (&BootPath
, p
);
173 DPRINT("Boot path: %s\n", "\\");
174 RtlCreateUnicodeStringFromAsciiz (&BootPath
, "\\");
176 DPRINT("Arc name: %s\n", ParamBuffer
);
178 /* Only arc name left - build full arc name */
179 ArcNameBuffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
180 swprintf (ArcNameBuffer
, L
"\\ArcName\\%S", ParamBuffer
);
181 RtlInitUnicodeString (&ArcName
, ArcNameBuffer
);
182 DPRINT("Arc name: %wZ\n", &ArcName
);
184 /* free ParamBuffer */
185 ExFreePool (ParamBuffer
);
187 /* allocate arc device name string */
188 ArcDeviceName
.Length
= 0;
189 ArcDeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
190 ArcDeviceName
.Buffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
192 InitializeObjectAttributes (&ObjectAttributes
,
198 Status
= NtOpenSymbolicLinkObject (&Handle
,
199 SYMBOLIC_LINK_ALL_ACCESS
,
201 RtlFreeUnicodeString (&ArcName
);
202 if (!NT_SUCCESS(Status
))
204 RtlFreeUnicodeString (&BootPath
);
205 RtlFreeUnicodeString (&ArcDeviceName
);
206 CPRINT("NtOpenSymbolicLinkObject() failed (Status %x)\n",
212 Status
= NtQuerySymbolicLinkObject (Handle
,
216 if (!NT_SUCCESS(Status
))
218 RtlFreeUnicodeString (&BootPath
);
219 RtlFreeUnicodeString (&ArcDeviceName
);
220 CPRINT("NtQuerySymbolicObject() failed (Status %x)\n",
225 DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length
, &ArcDeviceName
);
228 /* allocate device name string */
229 DriveDeviceName
.Length
= 0;
230 DriveDeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
231 DriveDeviceName
.Buffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
233 for (i
= 0; i
< 26; i
++)
235 swprintf (DriveNameBuffer
, L
"\\??\\%C:", 'A' + i
);
236 RtlInitUnicodeString (&DriveName
,
239 InitializeObjectAttributes (&ObjectAttributes
,
245 Status
= NtOpenSymbolicLinkObject (&Handle
,
246 SYMBOLIC_LINK_ALL_ACCESS
,
248 if (!NT_SUCCESS(Status
))
250 DPRINT("Failed to open link %wZ\n",
255 Status
= NtQuerySymbolicLinkObject (Handle
,
258 if (!NT_SUCCESS(Status
))
260 DPRINT("Failed query open link %wZ\n",
264 DPRINT("Opened link: %wZ ==> %wZ\n",
265 &DriveName
, &DriveDeviceName
);
267 if (!RtlCompareUnicodeString (&ArcDeviceName
, &DriveDeviceName
, FALSE
))
269 DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i
, &BootPath
);
270 swprintf(SharedUserData
->NtSystemRoot
,
271 L
"%C:%wZ", 'A' + i
, &BootPath
);
273 BootDriveFound
= TRUE
;
279 RtlFreeUnicodeString (&BootPath
);
280 RtlFreeUnicodeString (&DriveDeviceName
);
281 RtlFreeUnicodeString (&ArcDeviceName
);
283 DPRINT("DosDeviceMap: 0x%x\n", SharedUserData
->DosDeviceMap
);
285 if (BootDriveFound
== FALSE
)
287 DbgPrint("No system drive found!\n");
293 MiFreeBootDriverMemory(PVOID StartAddress
, ULONG Length
)
295 PHYSICAL_ADDRESS Page
;
298 for (i
= 0; i
< PAGE_ROUND_UP(Length
)/PAGE_SIZE
; i
++)
300 Page
= MmGetPhysicalAddressForProcess(NULL
, StartAddress
+ i
* PAGE_SIZE
);
301 MmDeleteVirtualMapping(NULL
, StartAddress
+ i
* PAGE_SIZE
, FALSE
, NULL
, NULL
);
302 MmDereferencePage(Page
);
307 ExpInitializeExecutive(VOID
)
309 LARGE_INTEGER Timeout
;
310 HANDLE ProcessHandle
;
312 ULONG BootDriverCount
;
322 BOOLEAN NoBootScreen
= FALSE
;
324 HANDLE InitDoneEventHandle
;
325 OBJECT_ATTRIBUTES ObjectAttributes
;
328 * Fail at runtime if someone has changed various structures without
329 * updating the offsets used for the assembler code.
331 assert(FIELD_OFFSET(KTHREAD
, InitialStack
) == KTHREAD_INITIAL_STACK
);
332 assert(FIELD_OFFSET(KTHREAD
, Teb
) == KTHREAD_TEB
);
333 assert(FIELD_OFFSET(KTHREAD
, KernelStack
) == KTHREAD_KERNEL_STACK
);
334 assert(FIELD_OFFSET(KTHREAD
, ServiceTable
) == KTHREAD_SERVICE_TABLE
);
335 assert(FIELD_OFFSET(KTHREAD
, PreviousMode
) == KTHREAD_PREVIOUS_MODE
);
336 assert(FIELD_OFFSET(KTHREAD
, TrapFrame
) == KTHREAD_TRAP_FRAME
);
337 assert(FIELD_OFFSET(KTHREAD
, CallbackStack
) == KTHREAD_CALLBACK_STACK
);
338 assert(FIELD_OFFSET(ETHREAD
, ThreadsProcess
) == ETHREAD_THREADS_PROCESS
);
339 assert(FIELD_OFFSET(KPROCESS
, DirectoryTableBase
) ==
340 KPROCESS_DIRECTORY_TABLE_BASE
);
341 assert(FIELD_OFFSET(KPROCESS
, IopmOffset
) == KPROCESS_IOPM_OFFSET
);
342 assert(FIELD_OFFSET(KPROCESS
, LdtDescriptor
) == KPROCESS_LDT_DESCRIPTOR0
);
343 assert(FIELD_OFFSET(KTRAP_FRAME
, Reserved9
) == KTRAP_FRAME_RESERVED9
);
344 assert(FIELD_OFFSET(KV86M_TRAP_FRAME
, regs
) == TF_REGS
);
345 assert(FIELD_OFFSET(KV86M_TRAP_FRAME
, orig_ebp
) == TF_ORIG_EBP
);
347 assert(FIELD_OFFSET(KPCR
, Tib
.ExceptionList
) == KPCR_EXCEPTION_LIST
);
348 assert(FIELD_OFFSET(KPCR
, Self
) == KPCR_SELF
);
349 assert(FIELD_OFFSET(IKPCR
, Tib
.ExceptionList
) == KPCR_EXCEPTION_LIST
);
350 assert(FIELD_OFFSET(IKPCR
, Self
) == KPCR_SELF
);
351 assert(FIELD_OFFSET(IKPCR
, CurrentThread
) == KPCR_CURRENT_THREAD
);
355 KeLowerIrql(DISPATCH_LEVEL
);
359 p1
= (PCHAR
)KeLoaderBlock
.CommandLine
;
362 while(*p1
&& (p2
= strchr(p1
, '/')))
365 if (!_strnicmp(p2
, "MAXMEM", 6))
368 while (isspace(*p2
)) p2
++;
372 while(isspace(*p2
)) p2
++;
377 MaxMem
= MaxMem
* 10 + *p2
- '0';
384 else if (!_strnicmp(p2
, "NOBOOTSCREEN", 12))
389 else if (!_strnicmp(p2
, "CRASHDUMP", 9))
395 if (!_strnicmp(p2
, "FULL", 4))
397 MmCoreDumpType
= MM_CORE_DUMP_TYPE_FULL
;
401 MmCoreDumpType
= MM_CORE_DUMP_TYPE_NONE
;
408 MmInit1(FirstKrnlPhysAddr
,
411 (PADDRESS_RANGE
)&KeMemoryMap
,
412 KeMemoryMapRangeCount
,
413 MaxMem
> 8 ? MaxMem
: 4096);
415 /* Import ANSI code page table */
416 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
418 start
= KeLoaderModules
[i
].ModStart
;
419 length
= KeLoaderModules
[i
].ModEnd
- start
;
421 name
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '\\');
424 name
= (PCHAR
)KeLoaderModules
[i
].String
;
431 if (!_stricmp (name
, "ansi.nls"))
433 RtlpImportAnsiCodePage((PUSHORT
)start
, length
);
437 /* Import OEM code page table */
438 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
440 start
= KeLoaderModules
[i
].ModStart
;
441 length
= KeLoaderModules
[i
].ModEnd
- start
;
443 name
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '\\');
446 name
= (PCHAR
)KeLoaderModules
[i
].String
;
453 if (!_stricmp (name
, "oem.nls"))
455 RtlpImportOemCodePage((PUSHORT
)start
, length
);
459 /* Import Unicode casemap table */
460 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
462 start
= KeLoaderModules
[i
].ModStart
;
463 length
= KeLoaderModules
[i
].ModEnd
- start
;
465 name
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '\\');
468 name
= (PCHAR
)KeLoaderModules
[i
].String
;
475 if (!_stricmp (name
, "casemap.nls"))
477 RtlpImportUnicodeCasemap((PUSHORT
)start
, length
);
481 /* Create initial NLS tables */
482 RtlpCreateInitialNlsTables();
485 * Initialize the kernel debugger
487 KdInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
492 KeLowerIrql(PASSIVE_LEVEL
);
495 KEBUGCHECK(SECURITY_INITIALIZATION_FAILED
);
500 KEBUGCHECK(SECURITY1_INITIALIZATION_FAILED
);
502 PiInitProcessManager();
504 if (KdPollBreakIn ())
506 DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C
);
509 /* Initialize all processors */
510 KeNumberProcessors
= 0;
512 while (!HalAllProcessorsStarted())
514 PVOID ProcessorStack
;
516 if (KeNumberProcessors
!= 0)
518 KePrepareForApplicationProcessorInit(KeNumberProcessors
);
519 PsPrepareForApplicationProcessorInit(KeNumberProcessors
);
521 /* Allocate a stack for use when booting the processor */
522 /* FIXME: The nonpaged memory for the stack is not released after use */
524 ExAllocatePool(NonPagedPool
, MM_STACK_SIZE
) + MM_STACK_SIZE
;
525 Ki386InitialStackArray
[((int)KeNumberProcessors
)] =
526 (PVOID
)(ProcessorStack
- MM_STACK_SIZE
);
527 HalInitializeProcessor(KeNumberProcessors
, ProcessorStack
);
528 KeNumberProcessors
++;
532 * Initialize various critical subsystems
534 HalInitSystem(1, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
540 LdrInitModuleManagement();
541 CmInitializeRegistry();
546 FsRtlpInitFileLockingImplementation();
548 /* Report all resources used by hal */
549 HalReportResourceUsage();
552 * Clear the screen to blue
554 HalInitSystem(2, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
557 * Display version number and copyright/warranty message
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 "
566 HalDisplayString("conditions. There is absolutely no warranty for "
569 if (KeNumberProcessors
> 1)
572 "Found %d system processors. [%lu MB Memory]\n",
574 (KeLoaderBlock
.MemHigher
+ 1088)/ 1024);
579 "Found 1 system processor. [%lu MB Memory]\n",
580 (KeLoaderBlock
.MemHigher
+ 1088)/ 1024);
582 HalDisplayString(str
);
587 /* Create the NLS section */
588 RtlpCreateNlsSection();
591 * Initalize services loaded at boot time
593 DPRINT("%d files loaded\n",KeLoaderBlock
.ModsCount
);
594 for (i
=0; i
< KeLoaderBlock
.ModsCount
; i
++)
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
);
602 /* Pass 1: import system hive registry chunk */
604 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
606 start
= KeLoaderModules
[i
].ModStart
;
607 length
= KeLoaderModules
[i
].ModEnd
- start
;
609 DPRINT("Module: '%s'\n", (PCHAR
)KeLoaderModules
[i
].String
);
610 name
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '\\');
613 name
= (PCHAR
)KeLoaderModules
[i
].String
;
620 if (!_stricmp (name
, "system") ||
621 !_stricmp (name
, "system.hiv"))
623 CPRINT("Process system hive registry chunk at %08lx\n", start
);
625 CmImportSystemHive((PCHAR
)start
, length
);
629 /* Pass 2: import hardware hive registry chunk */
630 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
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"))
638 CPRINT("Process hardware hive registry chunk at %08lx\n", start
);
639 CmImportHardwareHive((PCHAR
)start
, length
);
643 /* Create dummy keys if no hardware hive was found */
644 CmImportHardwareHive (NULL
, 0);
646 /* Initialize volatile registry settings */
647 if (SetupBoot
== FALSE
)
649 CmInit2((PCHAR
)KeLoaderBlock
.CommandLine
);
653 * Enter the kernel debugger before starting up the boot drivers
659 IoCreateDriverList();
663 /* Pass 3: process boot loaded drivers */
665 for (i
=1; i
< KeLoaderBlock
.ModsCount
; i
++)
667 start
= KeLoaderModules
[i
].ModStart
;
668 length
= KeLoaderModules
[i
].ModEnd
- start
;
669 name
= (PCHAR
)KeLoaderModules
[i
].String
;
670 if (RtlpCheckFileNameExtension(name
, ".sys") ||
671 RtlpCheckFileNameExtension(name
, ".sym"))
673 CPRINT("Initializing driver '%s' at %08lx, length 0x%08lx\n",
674 name
, start
, length
);
675 LdrInitializeBootStartDriver((PVOID
)start
, name
, length
);
677 if (RtlpCheckFileNameExtension(name
, ".sys"))
681 /* Pass 4: free memory for all boot files, except ntoskrnl.exe and hal.dll */
682 for (i
= 2; i
< KeLoaderBlock
.ModsCount
; i
++)
685 /* Do not free the memory from symbol files, if the kernel debugger is active */
686 if (!RtlpCheckFileNameExtension(name
, ".sym"))
689 MiFreeBootDriverMemory((PVOID
)KeLoaderModules
[i
].ModStart
,
690 KeLoaderModules
[i
].ModEnd
- KeLoaderModules
[i
].ModStart
);
694 if (BootDriverCount
== 0)
696 DbgPrint("No boot drivers available.\n");
700 /* Display the boot screen image if not disabled */
703 InbvEnableBootDriver(TRUE
);
706 /* Create ARC names for boot devices */
709 /* Create the SystemRoot symbolic link */
710 CPRINT("CommandLine: %s\n", (PUCHAR
)KeLoaderBlock
.CommandLine
);
711 Status
= IoCreateSystemRootLink((PUCHAR
)KeLoaderBlock
.CommandLine
);
712 if (!NT_SUCCESS(Status
))
713 KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE
);
715 #ifdef DBGPRINT_FILE_LOG
716 /* On the assumption that we can now access disks start up the debug
719 #endif /* DBGPRINT_FILE_LOG */
725 PiInitDefaultLocale();
728 * Load boot start drivers
730 IopLoadBootStartDrivers();
733 * Load Auto configured drivers
735 LdrLoadAutoConfigDrivers();
737 IoDestroyDriverList();
740 * Assign drive letters
742 IoAssignDriveLetters ((PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
,
748 * Initialize shared user page:
749 * - set dos system path, dos device map, etc.
751 InitSystemSharedUserPage ((PUCHAR
)KeLoaderBlock
.CommandLine
);
753 /* Create 'ReactOSInitDone' event */
754 RtlInitUnicodeString(&Name
, L
"\\ReactOSInitDone");
755 InitializeObjectAttributes(&ObjectAttributes
,
760 Status
= NtCreateEvent(&InitDoneEventHandle
,
763 FALSE
, /* Synchronization event */
764 FALSE
); /* Not signalled */
765 if (!NT_SUCCESS(Status
))
767 DPRINT1("Failed to create 'ReactOSInitDone' event (Status 0x%x)\n", Status
);
768 InitDoneEventHandle
= INVALID_HANDLE_VALUE
;
772 * Launch initial process
774 Status
= LdrLoadInitialProcess(&ProcessHandle
,
776 if (!NT_SUCCESS(Status
))
778 KEBUGCHECKEX(SESSION4_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
781 if (InitDoneEventHandle
!= INVALID_HANDLE_VALUE
)
783 HANDLE Handles
[2]; /* Init event, Initial process */
785 Handles
[0] = InitDoneEventHandle
;
786 Handles
[1] = ProcessHandle
;
788 /* Wait for the system to be initialized */
789 Timeout
.QuadPart
= -1200000000LL; /* 120 second timeout */
790 Status
= NtWaitForMultipleObjects(((LONG
) sizeof(Handles
) / sizeof(HANDLE
)),
793 FALSE
, /* Non-alertable */
795 if (!NT_SUCCESS(Status
))
797 DPRINT1("NtWaitForMultipleObjects failed with status 0x%x!\n", Status
);
799 else if (Status
== STATUS_TIMEOUT
)
801 DPRINT1("WARNING: System not initialized after 120 seconds.\n");
803 else if (Status
== STATUS_WAIT_0
+ 1)
806 * Crash the system if the initial process was terminated.
808 KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
813 InbvEnableBootDriver(FALSE
);
816 NtSetEvent(InitDoneEventHandle
, NULL
);
818 NtClose(InitDoneEventHandle
);
822 /* On failure to create 'ReactOSInitDone' event, go to text mode ASAP */
825 InbvEnableBootDriver(FALSE
);
829 * Crash the system if the initial process terminates within 5 seconds.
831 Timeout
.QuadPart
= -50000000LL;
832 Status
= NtWaitForSingleObject(ProcessHandle
,
835 if (Status
!= STATUS_TIMEOUT
)
837 KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
841 NtClose(ThreadHandle
);
842 NtClose(ProcessHandle
);
844 PsTerminateSystemThread(STATUS_SUCCESS
);
849 KiSystemStartup(BOOLEAN BootProcessor
)
851 HalInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
856 ExpInitializeExecutive();
859 /* Do application processor initialization */
860 KeApplicationProcessorInit();
861 PsApplicationProcessorInit();
862 KeLowerIrql(PASSIVE_LEVEL
);
863 PsIdleThreadMain(NULL
);
869 _main (ULONG MultiBootMagic
, PLOADER_PARAMETER_BLOCK _LoaderBlock
)
871 * FUNCTION: Called by the boot loader to start the kernel
873 * LoaderBlock = Pointer to boot parameters initialized by the boot
875 * NOTE: The boot parameters are stored in low memory which will become
876 * invalid after the memory managment is initialized so we make a local copy.
881 ULONG last_kernel_address
;
882 extern ULONG _bss_end__
;
887 /* Low level architecture specific initialization */
891 * Copy the parameters to a local buffer because lowmem will go away
893 memcpy(&KeLoaderBlock
, _LoaderBlock
, sizeof(LOADER_PARAMETER_BLOCK
));
894 memcpy(&KeLoaderModules
[1], (PVOID
)KeLoaderBlock
.ModsAddr
,
895 sizeof(LOADER_MODULE
) * KeLoaderBlock
.ModsCount
);
896 KeLoaderBlock
.ModsCount
++;
897 KeLoaderBlock
.ModsAddr
= (ULONG
)&KeLoaderModules
;
900 * Convert a path specification in the grub format to one understood by the
901 * rest of the kernel.
903 if (((PUCHAR
)_LoaderBlock
->CommandLine
)[0] == '(')
905 ULONG DiskNumber
= 0, PartNumber
= 0;
911 if (((PUCHAR
)_LoaderBlock
->CommandLine
)[1] == 'h' &&
912 ((PUCHAR
)_LoaderBlock
->CommandLine
)[2] == 'd')
914 DiskNumber
= ((PUCHAR
)_LoaderBlock
->CommandLine
)[3] - '0';
915 PartNumber
= ((PUCHAR
)_LoaderBlock
->CommandLine
)[5] - '0';
917 strcpy(Temp
, &((PUCHAR
)_LoaderBlock
->CommandLine
)[7]);
918 if ((options
= strchr(Temp
, ' ')) != NULL
)
927 if ((s1
= strrchr(Temp
, '/')) != NULL
)
930 if ((s1
= strrchr(Temp
, '/')) != NULL
)
935 sprintf(KeLoaderCommandLine
,
936 "multi(0)disk(0)rdisk(%lu)partition(%lu)%s %s",
937 DiskNumber
, PartNumber
+ 1, Temp
, options
);
939 p
= KeLoaderCommandLine
;
940 while (*p
!= 0 && *p
!= ' ')
948 DPRINT1("Command Line: %s\n", KeLoaderCommandLine
);
952 strcpy(KeLoaderCommandLine
, (PUCHAR
)_LoaderBlock
->CommandLine
);
954 KeLoaderBlock
.CommandLine
= (ULONG
)KeLoaderCommandLine
;
956 strcpy(KeLoaderModuleStrings
[0], "ntoskrnl.exe");
957 KeLoaderModules
[0].String
= (ULONG
)KeLoaderModuleStrings
[0];
958 KeLoaderModules
[0].ModStart
= 0xC0000000;
959 KeLoaderModules
[0].ModEnd
= PAGE_ROUND_UP((ULONG
)&_bss_end__
);
960 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
963 if ((s
= strrchr((PUCHAR
)KeLoaderModules
[i
].String
, '/')) != 0)
965 strcpy(KeLoaderModuleStrings
[i
], s
+ 1);
969 strcpy(KeLoaderModuleStrings
[i
], (PUCHAR
)KeLoaderModules
[i
].String
);
971 KeLoaderModules
[i
].ModStart
-= 0x200000;
972 KeLoaderModules
[i
].ModStart
+= 0xc0000000;
973 KeLoaderModules
[i
].ModEnd
-= 0x200000;
974 KeLoaderModules
[i
].ModEnd
+= 0xc0000000;
975 KeLoaderModules
[i
].String
= (ULONG
)KeLoaderModuleStrings
[i
];
979 HalnInitializeDisplay((PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
982 HalBase
= KeLoaderModules
[1].ModStart
;
984 PAGE_ROUND_UP(KeLoaderModules
[KeLoaderBlock
.ModsCount
- 1].ModEnd
);
989 LdrSafePEProcessModule((PVOID
)HalBase
, (PVOID
)DriverBase
, (PVOID
)0xC0000000, &DriverSize
);
991 LdrHalBase
= (ULONG_PTR
)DriverBase
;
992 last_kernel_address
= DriverBase
+ DriverSize
;
995 * Process ntoskrnl.exe
997 LdrSafePEProcessModule((PVOID
)0xC0000000, (PVOID
)0xC0000000, (PVOID
)DriverBase
, &DriverSize
);
999 FirstKrnlPhysAddr
= KeLoaderModules
[0].ModStart
- 0xc0000000 + 0x200000;
1000 LastKrnlPhysAddr
= last_kernel_address
- 0xc0000000 + 0x200000;
1001 LastKernelAddress
= last_kernel_address
;
1004 /* FIXME: VMware does not like it when ReactOS is using the BIOS memory map */
1005 KeLoaderBlock
.Flags
&= ~MB_FLAGS_MMAP_INFO
;
1008 KeMemoryMapRangeCount
= 0;
1009 if (KeLoaderBlock
.Flags
& MB_FLAGS_MMAP_INFO
)
1011 /* We have a memory map from the nice BIOS */
1012 size
= *((PULONG
)(KeLoaderBlock
.MmapAddr
- sizeof(ULONG
)));
1014 while (i
< KeLoaderBlock
.MmapLength
)
1016 memcpy (&KeMemoryMap
[KeMemoryMapRangeCount
],
1017 (PVOID
)(KeLoaderBlock
.MmapAddr
+ i
),
1018 sizeof(ADDRESS_RANGE
));
1019 KeMemoryMapRangeCount
++;