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.195 2004/09/23 11:27:08 ekohl 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 *****************************************************************/
32 #include "../dbg/kdb.h"
33 #include <ntos/bootvid.h>
34 #include <napi/core.h>
37 #include <internal/ntosdbg.h>
39 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
48 #include <internal/debug.h>
50 /* GLOBALS *******************************************************************/
53 ULONG EXPORTED NtBuildNumber
= KERNEL_VERSION_BUILD
;
54 ULONG EXPORTED NtGlobalFlag
= 0;
55 CHAR EXPORTED KeNumberProcessors
;
56 LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock
;
57 ULONG EXPORTED KeDcacheFlushCount
= 0;
58 ULONG EXPORTED KeIcacheFlushCount
= 0;
60 /* Microsoft-style declarations */
61 EXPORTED ULONG NtBuildNumber
= KERNEL_VERSION_BUILD
;
62 EXPORTED ULONG NtGlobalFlag
= 0;
63 EXPORTED CHAR KeNumberProcessors
;
64 EXPORTED LOADER_PARAMETER_BLOCK KeLoaderBlock
;
65 EXPORTED ULONG KeDcacheFlushCount
= 0;
66 EXPORTED ULONG KeIcacheFlushCount
= 0;
69 static LOADER_MODULE KeLoaderModules
[64];
70 static UCHAR KeLoaderModuleStrings
[64][256];
71 static UCHAR KeLoaderCommandLine
[256];
72 static ADDRESS_RANGE KeMemoryMap
[64];
73 static ULONG KeMemoryMapRangeCount
;
74 static ULONG FirstKrnlPhysAddr
;
75 static ULONG LastKrnlPhysAddr
;
76 static ULONG LastKernelAddress
;
77 volatile BOOLEAN Initialized
= FALSE
;
78 extern ULONG MmCoreDumpType
;
79 extern CHAR KiTimerSystemAuditing
;
81 extern PVOID Ki386InitialStackArray
[MAXIMUM_PROCESSORS
];
84 /* FUNCTIONS ****************************************************************/
86 static VOID INIT_FUNCTION
87 InitSystemSharedUserPage (PCSZ ParameterLine
)
89 UNICODE_STRING ArcDeviceName
;
90 UNICODE_STRING ArcName
;
91 UNICODE_STRING BootPath
;
92 UNICODE_STRING DriveDeviceName
;
93 UNICODE_STRING DriveName
;
94 WCHAR DriveNameBuffer
[20];
100 OBJECT_ATTRIBUTES ObjectAttributes
;
103 BOOLEAN BootDriveFound
;
107 * The shared user page has been zeroed-out right after creation.
108 * There is NO need to do this again.
111 SharedUserData
->NtProductType
= NtProductWinNt
;
113 BootDriveFound
= FALSE
;
116 * Retrieve the current dos system path
117 * (e.g.: C:\reactos) from the given arc path
118 * (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos)
119 * Format: "<arc_name>\<path> [options...]"
122 /* create local parameter line copy */
123 ParamBuffer
= ExAllocatePool (PagedPool
, 256);
124 strcpy (ParamBuffer
, (char *)ParameterLine
);
125 DPRINT("%s\n", ParamBuffer
);
127 /* cut options off */
128 p
= strchr (ParamBuffer
, ' ');
133 DPRINT("%s\n", ParamBuffer
);
136 p
= strchr (ParamBuffer
, '\\');
139 DPRINT("Boot path: %s\n", p
);
140 RtlCreateUnicodeStringFromAsciiz (&BootPath
, p
);
145 DPRINT("Boot path: %s\n", "\\");
146 RtlCreateUnicodeStringFromAsciiz (&BootPath
, "\\");
148 DPRINT("Arc name: %s\n", ParamBuffer
);
150 /* Only arc name left - build full arc name */
151 ArcNameBuffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
152 swprintf (ArcNameBuffer
, L
"\\ArcName\\%S", ParamBuffer
);
153 RtlInitUnicodeString (&ArcName
, ArcNameBuffer
);
154 DPRINT("Arc name: %wZ\n", &ArcName
);
156 /* free ParamBuffer */
157 ExFreePool (ParamBuffer
);
159 /* allocate arc device name string */
160 ArcDeviceName
.Length
= 0;
161 ArcDeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
162 ArcDeviceName
.Buffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
164 InitializeObjectAttributes (&ObjectAttributes
,
170 Status
= NtOpenSymbolicLinkObject (&Handle
,
171 SYMBOLIC_LINK_ALL_ACCESS
,
173 RtlFreeUnicodeString (&ArcName
);
174 if (!NT_SUCCESS(Status
))
176 RtlFreeUnicodeString (&BootPath
);
177 RtlFreeUnicodeString (&ArcDeviceName
);
178 CPRINT("NtOpenSymbolicLinkObject() failed (Status %x)\n",
184 Status
= NtQuerySymbolicLinkObject (Handle
,
188 if (!NT_SUCCESS(Status
))
190 RtlFreeUnicodeString (&BootPath
);
191 RtlFreeUnicodeString (&ArcDeviceName
);
192 CPRINT("NtQuerySymbolicObject() failed (Status %x)\n",
197 DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length
, &ArcDeviceName
);
200 /* allocate device name string */
201 DriveDeviceName
.Length
= 0;
202 DriveDeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
203 DriveDeviceName
.Buffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
205 for (i
= 0; i
< 26; i
++)
207 swprintf (DriveNameBuffer
, L
"\\??\\%C:", 'A' + i
);
208 RtlInitUnicodeString (&DriveName
,
211 InitializeObjectAttributes (&ObjectAttributes
,
217 Status
= NtOpenSymbolicLinkObject (&Handle
,
218 SYMBOLIC_LINK_ALL_ACCESS
,
220 if (!NT_SUCCESS(Status
))
222 DPRINT("Failed to open link %wZ\n",
227 Status
= NtQuerySymbolicLinkObject (Handle
,
230 if (!NT_SUCCESS(Status
))
232 DPRINT("Failed query open link %wZ\n",
236 DPRINT("Opened link: %wZ ==> %wZ\n",
237 &DriveName
, &DriveDeviceName
);
239 if (!RtlCompareUnicodeString (&ArcDeviceName
, &DriveDeviceName
, FALSE
))
241 DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i
, &BootPath
);
242 swprintf(SharedUserData
->NtSystemRoot
,
243 L
"%C:%wZ", 'A' + i
, &BootPath
);
245 BootDriveFound
= TRUE
;
251 RtlFreeUnicodeString (&BootPath
);
252 RtlFreeUnicodeString (&DriveDeviceName
);
253 RtlFreeUnicodeString (&ArcDeviceName
);
255 DPRINT("DosDeviceMap: 0x%x\n", SharedUserData
->DosDeviceMap
);
257 if (BootDriveFound
== FALSE
)
259 DbgPrint("No system drive found!\n");
260 KEBUGCHECK (NO_BOOT_DEVICE
);
265 ExpInitializeExecutive(VOID
)
267 LARGE_INTEGER Timeout
;
268 HANDLE ProcessHandle
;
279 BOOLEAN NoGuiBoot
= FALSE
;
281 HANDLE InitDoneEventHandle
;
282 OBJECT_ATTRIBUTES ObjectAttributes
;
285 * Fail at runtime if someone has changed various structures without
286 * updating the offsets used for the assembler code.
288 assert(FIELD_OFFSET(KTHREAD
, InitialStack
) == KTHREAD_INITIAL_STACK
);
289 assert(FIELD_OFFSET(KTHREAD
, Teb
) == KTHREAD_TEB
);
290 assert(FIELD_OFFSET(KTHREAD
, KernelStack
) == KTHREAD_KERNEL_STACK
);
291 assert(FIELD_OFFSET(KTHREAD
, ServiceTable
) == KTHREAD_SERVICE_TABLE
);
292 assert(FIELD_OFFSET(KTHREAD
, PreviousMode
) == KTHREAD_PREVIOUS_MODE
);
293 assert(FIELD_OFFSET(KTHREAD
, TrapFrame
) == KTHREAD_TRAP_FRAME
);
294 assert(FIELD_OFFSET(KTHREAD
, CallbackStack
) == KTHREAD_CALLBACK_STACK
);
295 assert(FIELD_OFFSET(KTHREAD
, ApcState
.Process
) == KTHREAD_APCSTATE_PROCESS
);
296 assert(FIELD_OFFSET(KPROCESS
, DirectoryTableBase
) ==
297 KPROCESS_DIRECTORY_TABLE_BASE
);
298 assert(FIELD_OFFSET(KPROCESS
, IopmOffset
) == KPROCESS_IOPM_OFFSET
);
299 assert(FIELD_OFFSET(KPROCESS
, LdtDescriptor
) == KPROCESS_LDT_DESCRIPTOR0
);
300 assert(FIELD_OFFSET(KTRAP_FRAME
, Reserved9
) == KTRAP_FRAME_RESERVED9
);
301 assert(FIELD_OFFSET(KV86M_TRAP_FRAME
, regs
) == TF_REGS
);
302 assert(FIELD_OFFSET(KV86M_TRAP_FRAME
, orig_ebp
) == TF_ORIG_EBP
);
304 assert(FIELD_OFFSET(KPCR
, Tib
.ExceptionList
) == KPCR_EXCEPTION_LIST
);
305 assert(FIELD_OFFSET(KPCR
, Self
) == KPCR_SELF
);
306 assert(FIELD_OFFSET(IKPCR
, Tib
.ExceptionList
) == KPCR_EXCEPTION_LIST
);
307 assert(FIELD_OFFSET(IKPCR
, Self
) == KPCR_SELF
);
308 assert(FIELD_OFFSET(IKPCR
, CurrentThread
) == KPCR_CURRENT_THREAD
);
312 KeLowerIrql(DISPATCH_LEVEL
);
316 p1
= (PCHAR
)KeLoaderBlock
.CommandLine
;
319 while(*p1
&& (p2
= strchr(p1
, '/')))
322 if (!_strnicmp(p2
, "MAXMEM", 6))
325 while (isspace(*p2
)) p2
++;
329 while(isspace(*p2
)) p2
++;
334 MaxMem
= MaxMem
* 10 + *p2
- '0';
341 else if (!_strnicmp(p2
, "NOGUIBOOT", 12))
346 else if (!_strnicmp(p2
, "CRASHDUMP", 9))
352 if (!_strnicmp(p2
, "FULL", 4))
354 MmCoreDumpType
= MM_CORE_DUMP_TYPE_FULL
;
358 MmCoreDumpType
= MM_CORE_DUMP_TYPE_NONE
;
365 MmInit1(FirstKrnlPhysAddr
,
368 (PADDRESS_RANGE
)&KeMemoryMap
,
369 KeMemoryMapRangeCount
,
370 MaxMem
> 8 ? MaxMem
: 4096);
372 /* Import ANSI code page table */
373 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
375 start
= KeLoaderModules
[i
].ModStart
;
376 length
= KeLoaderModules
[i
].ModEnd
- start
;
378 name
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '\\');
381 name
= (PCHAR
)KeLoaderModules
[i
].String
;
388 if (!_stricmp (name
, "ansi.nls"))
390 RtlpImportAnsiCodePage((PUSHORT
)start
, length
);
394 /* Import OEM code page table */
395 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
397 start
= KeLoaderModules
[i
].ModStart
;
398 length
= KeLoaderModules
[i
].ModEnd
- start
;
400 name
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '\\');
403 name
= (PCHAR
)KeLoaderModules
[i
].String
;
410 if (!_stricmp (name
, "oem.nls"))
412 RtlpImportOemCodePage((PUSHORT
)start
, length
);
416 /* Import Unicode casemap table */
417 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
419 start
= KeLoaderModules
[i
].ModStart
;
420 length
= KeLoaderModules
[i
].ModEnd
- start
;
422 name
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '\\');
425 name
= (PCHAR
)KeLoaderModules
[i
].String
;
432 if (!_stricmp (name
, "casemap.nls"))
434 RtlpImportUnicodeCasemap((PUSHORT
)start
, length
);
438 /* Create initial NLS tables */
439 RtlpCreateInitialNlsTables();
442 * Initialize the kernel debugger
444 KdInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
449 if (KeMemoryMapRangeCount
> 0)
451 DPRINT1("MemoryMap:\n");
452 for (i
= 0; i
< KeMemoryMapRangeCount
; i
++)
454 switch(KeMemoryMap
[i
].Type
)
457 strcpy(str
, "(usable)");
460 strcpy(str
, "(reserved)");
463 strcpy(str
, "(ACPI data)");
466 strcpy(str
, "(ACPI NVS)");
469 sprintf(str
, "type %lu", KeMemoryMap
[i
].Type
);
471 DPRINT1("%08x - %08x %s\n", KeMemoryMap
[i
].BaseAddrLow
, KeMemoryMap
[i
].BaseAddrLow
+ KeMemoryMap
[i
].LengthLow
, str
);
476 KeLowerIrql(PASSIVE_LEVEL
);
479 KEBUGCHECK(SECURITY_INITIALIZATION_FAILED
);
486 KEBUGCHECK(SECURITY1_INITIALIZATION_FAILED
);
488 PiInitProcessManager();
490 if (KdPollBreakIn ())
492 DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C
);
495 /* Initialize all processors */
496 KeNumberProcessors
= 0;
498 while (!HalAllProcessorsStarted())
500 PVOID ProcessorStack
;
502 if (KeNumberProcessors
!= 0)
504 KePrepareForApplicationProcessorInit(KeNumberProcessors
);
505 PsPrepareForApplicationProcessorInit(KeNumberProcessors
);
507 /* Allocate a stack for use when booting the processor */
508 /* FIXME: The nonpaged memory for the stack is not released after use */
510 (char*)ExAllocatePool(NonPagedPool
, MM_STACK_SIZE
) + MM_STACK_SIZE
;
511 Ki386InitialStackArray
[((int)KeNumberProcessors
)] =
512 (PVOID
)((char*)ProcessorStack
- MM_STACK_SIZE
);
513 HalInitializeProcessor(KeNumberProcessors
, ProcessorStack
);
514 KeNumberProcessors
++;
518 * Initialize various critical subsystems
520 HalInitSystem(1, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
526 LdrInitModuleManagement();
527 CmInitializeRegistry();
532 FsRtlpInitFileLockingImplementation();
534 /* Report all resources used by hal */
535 HalReportResourceUsage();
538 * Clear the screen to blue
540 HalInitSystem(2, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
543 * Display version number and copyright/warranty message
545 HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR
" (Build "
546 KERNEL_VERSION_BUILD_STR
")\n");
547 HalDisplayString(RES_STR_LEGAL_COPYRIGHT
);
548 HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
549 "Public License, and you\n");
550 HalDisplayString("are welcome to change it and/or distribute copies of it "
552 HalDisplayString("conditions. There is absolutely no warranty for "
555 if (KeNumberProcessors
> 1)
558 "Found %d system processors. [%lu MB Memory]\n",
560 (KeLoaderBlock
.MemHigher
+ 1088)/ 1024);
565 "Found 1 system processor. [%lu MB Memory]\n",
566 (KeLoaderBlock
.MemHigher
+ 1088)/ 1024);
568 HalDisplayString(str
);
573 /* Create the NLS section */
574 RtlpCreateNlsSection();
577 * Initalize services loaded at boot time
579 DPRINT("%d files loaded\n",KeLoaderBlock
.ModsCount
);
580 for (i
=0; i
< KeLoaderBlock
.ModsCount
; i
++)
582 CPRINT("Module: '%s' at %08lx, length 0x%08lx\n",
583 KeLoaderModules
[i
].String
,
584 KeLoaderModules
[i
].ModStart
,
585 KeLoaderModules
[i
].ModEnd
- KeLoaderModules
[i
].ModStart
);
588 /* Pass 1: import system hive registry chunk */
590 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
592 start
= KeLoaderModules
[i
].ModStart
;
593 length
= KeLoaderModules
[i
].ModEnd
- start
;
595 DPRINT("Module: '%s'\n", (PCHAR
)KeLoaderModules
[i
].String
);
596 name
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '\\');
599 name
= (PCHAR
)KeLoaderModules
[i
].String
;
606 if (!_stricmp (name
, "system") ||
607 !_stricmp (name
, "system.hiv"))
609 CPRINT("Process system hive registry chunk at %08lx\n", start
);
611 CmImportSystemHive((PCHAR
)start
, length
);
615 /* Pass 2: import hardware hive registry chunk */
616 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
618 start
= KeLoaderModules
[i
].ModStart
;
619 length
= KeLoaderModules
[i
].ModEnd
- start
;
620 name
= (PCHAR
)KeLoaderModules
[i
].String
;
621 if (!_stricmp (name
, "hardware") ||
622 !_stricmp (name
, "hardware.hiv"))
624 CPRINT("Process hardware hive registry chunk at %08lx\n", start
);
625 CmImportHardwareHive((PCHAR
)start
, length
);
629 /* Create dummy keys if no hardware hive was found */
630 CmImportHardwareHive (NULL
, 0);
632 /* Initialize volatile registry settings */
633 if (SetupBoot
== FALSE
)
635 CmInit2((PCHAR
)KeLoaderBlock
.CommandLine
);
639 * Enter the kernel debugger before starting up the boot drivers
645 IoCreateDriverList();
649 /* Initialize Callbacks before drivers */
650 ExpInitializeCallbacks();
652 /* Start boot logging */
654 p1
= (PCHAR
)KeLoaderBlock
.CommandLine
;
655 while (*p1
&& (p2
= strchr(p1
, '/')))
658 if (!_strnicmp(p2
, "BOOTLOG", 7))
668 * Load boot start drivers
670 IopInitializeBootDrivers();
672 /* Display the boot screen image if not disabled */
675 InbvEnableBootDriver(TRUE
);
678 /* Create ARC names for boot devices */
681 /* Create the SystemRoot symbolic link */
682 CPRINT("CommandLine: %s\n", (PUCHAR
)KeLoaderBlock
.CommandLine
);
683 Status
= IoCreateSystemRootLink((PUCHAR
)KeLoaderBlock
.CommandLine
);
684 if (!NT_SUCCESS(Status
))
685 KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE
);
691 /* On the assumption that we can now access disks start up the debug
693 if ((KdDebuggerEnabled
== TRUE
) && (KdDebugState
& KD_DEBUG_BOOTLOG
))
698 PiInitDefaultLocale();
701 * Load services for devices found by PnP manager
703 IopInitializePnpServices(IopRootDeviceNode
, FALSE
);
706 * Load system start drivers
708 IopInitializeSystemDrivers();
710 IoDestroyDriverList();
712 /* Stop boot logging */
716 * Assign drive letters
718 IoAssignDriveLetters ((PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
,
724 * Initialize shared user page:
725 * - set dos system path, dos device map, etc.
727 InitSystemSharedUserPage ((PUCHAR
)KeLoaderBlock
.CommandLine
);
729 /* Create 'ReactOSInitDone' event */
730 RtlInitUnicodeString(&Name
, L
"\\ReactOSInitDone");
731 InitializeObjectAttributes(&ObjectAttributes
,
736 Status
= NtCreateEvent(&InitDoneEventHandle
,
739 FALSE
, /* Synchronization event */
740 FALSE
); /* Not signalled */
741 if (!NT_SUCCESS(Status
))
743 DPRINT1("Failed to create 'ReactOSInitDone' event (Status 0x%x)\n", Status
);
744 InitDoneEventHandle
= INVALID_HANDLE_VALUE
;
748 * Launch initial process
750 Status
= LdrLoadInitialProcess(&ProcessHandle
,
752 if (!NT_SUCCESS(Status
))
754 KEBUGCHECKEX(SESSION4_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
757 if (InitDoneEventHandle
!= INVALID_HANDLE_VALUE
)
759 HANDLE Handles
[2]; /* Init event, Initial process */
761 Handles
[0] = InitDoneEventHandle
;
762 Handles
[1] = ProcessHandle
;
764 /* Wait for the system to be initialized */
765 Timeout
.QuadPart
= (LONGLONG
)-1200000000; /* 120 second timeout */
766 Status
= NtWaitForMultipleObjects(((LONG
) sizeof(Handles
) / sizeof(HANDLE
)),
769 FALSE
, /* Non-alertable */
771 if (!NT_SUCCESS(Status
))
773 DPRINT1("NtWaitForMultipleObjects failed with status 0x%x!\n", Status
);
775 else if (Status
== STATUS_TIMEOUT
)
777 DPRINT1("WARNING: System not initialized after 120 seconds.\n");
779 else if (Status
== STATUS_WAIT_0
+ 1)
782 * Crash the system if the initial process was terminated.
784 KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
789 InbvEnableBootDriver(FALSE
);
792 NtSetEvent(InitDoneEventHandle
, NULL
);
794 NtClose(InitDoneEventHandle
);
798 /* On failure to create 'ReactOSInitDone' event, go to text mode ASAP */
801 InbvEnableBootDriver(FALSE
);
805 * Crash the system if the initial process terminates within 5 seconds.
807 Timeout
.QuadPart
= (LONGLONG
)-50000000; /* 5 second timeout */
808 Status
= NtWaitForSingleObject(ProcessHandle
,
811 if (Status
!= STATUS_TIMEOUT
)
813 KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED
, Status
, 1, 0, 0);
817 * Tell ke/timer.c it's okay to run.
820 KiTimerSystemAuditing
= 1;
822 NtClose(ThreadHandle
);
823 NtClose(ProcessHandle
);
826 VOID
__attribute((noinline
))
827 KiSystemStartup(BOOLEAN BootProcessor
)
829 HalInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
833 ExpInitializeExecutive();
836 PsTerminateSystemThread(STATUS_SUCCESS
);
839 /* Do application processor initialization */
840 KeApplicationProcessorInit();
841 PsApplicationProcessorInit();
842 KeLowerIrql(PASSIVE_LEVEL
);
843 PsIdleThreadMain(NULL
);
849 _main (ULONG MultiBootMagic
, PLOADER_PARAMETER_BLOCK _LoaderBlock
)
851 * FUNCTION: Called by the boot loader to start the kernel
853 * LoaderBlock = Pointer to boot parameters initialized by the boot
855 * NOTE: The boot parameters are stored in low memory which will become
856 * invalid after the memory managment is initialized so we make a local copy.
861 extern ULONG _bss_end__
;
867 * Copy the parameters to a local buffer because lowmem will go away
869 memcpy(&KeLoaderBlock
, _LoaderBlock
, sizeof(LOADER_PARAMETER_BLOCK
));
870 memcpy(&KeLoaderModules
[1], (PVOID
)KeLoaderBlock
.ModsAddr
,
871 sizeof(LOADER_MODULE
) * KeLoaderBlock
.ModsCount
);
872 KeLoaderBlock
.ModsCount
++;
873 KeLoaderBlock
.ModsAddr
= (ULONG
)&KeLoaderModules
;
876 * Convert a path specification in the grub format to one understood by the
877 * rest of the kernel.
879 if (((PUCHAR
)_LoaderBlock
->CommandLine
)[0] == '(')
881 ULONG DiskNumber
= 0, PartNumber
= 0;
887 if (((PUCHAR
)_LoaderBlock
->CommandLine
)[1] == 'h' &&
888 ((PUCHAR
)_LoaderBlock
->CommandLine
)[2] == 'd')
890 DiskNumber
= ((PUCHAR
)_LoaderBlock
->CommandLine
)[3] - '0';
891 PartNumber
= ((PUCHAR
)_LoaderBlock
->CommandLine
)[5] - '0';
893 strcpy(Temp
, &((PUCHAR
)_LoaderBlock
->CommandLine
)[7]);
894 if ((options
= strchr(Temp
, ' ')) != NULL
)
903 if ((s1
= strrchr(Temp
, '/')) != NULL
)
906 if ((s1
= strrchr(Temp
, '/')) != NULL
)
911 sprintf(KeLoaderCommandLine
,
912 "multi(0)disk(0)rdisk(%lu)partition(%lu)%s %s",
913 DiskNumber
, PartNumber
+ 1, Temp
, options
);
915 p
= KeLoaderCommandLine
;
916 while (*p
!= 0 && *p
!= ' ')
924 DPRINT1("Command Line: %s\n", KeLoaderCommandLine
);
928 strcpy(KeLoaderCommandLine
, (PUCHAR
)_LoaderBlock
->CommandLine
);
930 KeLoaderBlock
.CommandLine
= (ULONG
)KeLoaderCommandLine
;
932 strcpy(KeLoaderModuleStrings
[0], "ntoskrnl.exe");
933 KeLoaderModules
[0].String
= (ULONG
)KeLoaderModuleStrings
[0];
934 KeLoaderModules
[0].ModStart
= KERNEL_BASE
;
936 KeLoaderModules
[0].ModEnd
= PAGE_ROUND_UP((ULONG
)&_bss_end__
);
938 /* Take this value from the PE... */
940 PIMAGE_NT_HEADERS NtHeader
= RtlImageNtHeader((PVOID
)KeLoaderModules
[0].ModStart
);
941 PIMAGE_OPTIONAL_HEADER OptHead
= &NtHeader
->OptionalHeader
;
942 KeLoaderModules
[0].ModEnd
=
943 KeLoaderModules
[0].ModStart
+ PAGE_ROUND_UP((ULONG
)OptHead
->SizeOfImage
);
946 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
949 if ((s
= strrchr((PUCHAR
)KeLoaderModules
[i
].String
, '/')) != 0)
951 strcpy(KeLoaderModuleStrings
[i
], s
+ 1);
955 strcpy(KeLoaderModuleStrings
[i
], (PUCHAR
)KeLoaderModules
[i
].String
);
957 /* TODO: Fix this hardcoded load address stuff... */
958 KeLoaderModules
[i
].ModStart
-= 0x200000;
959 KeLoaderModules
[i
].ModStart
+= KERNEL_BASE
;
960 KeLoaderModules
[i
].ModEnd
-= 0x200000;
961 KeLoaderModules
[i
].ModEnd
+= KERNEL_BASE
;
962 KeLoaderModules
[i
].String
= (ULONG
)KeLoaderModuleStrings
[i
];
965 LastKernelAddress
= PAGE_ROUND_UP(KeLoaderModules
[KeLoaderBlock
.ModsCount
- 1].ModEnd
);
967 /* Low level architecture specific initialization */
968 KeInit1((PCHAR
)KeLoaderBlock
.CommandLine
, &LastKernelAddress
);
971 HalnInitializeDisplay((PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
974 HalBase
= KeLoaderModules
[1].ModStart
;
975 DriverBase
= LastKernelAddress
;
980 LdrSafePEProcessModule((PVOID
)HalBase
, (PVOID
)DriverBase
, (PVOID
)KERNEL_BASE
, &DriverSize
);
982 LdrHalBase
= (ULONG_PTR
)DriverBase
;
983 LastKernelAddress
+= PAGE_ROUND_UP(DriverSize
);
986 * Process ntoskrnl.exe
988 LdrSafePEProcessModule((PVOID
)KERNEL_BASE
, (PVOID
)KERNEL_BASE
, (PVOID
)DriverBase
, &DriverSize
);
990 /* Now our imports from HAL is fixed. This is the first */
991 /* time in the boot process that we can use HAL */
993 FirstKrnlPhysAddr
= KeLoaderModules
[0].ModStart
- KERNEL_BASE
+ 0x200000;
994 LastKrnlPhysAddr
= LastKernelAddress
- KERNEL_BASE
+ 0x200000;
997 /* FIXME: VMware does not like it when ReactOS is using the BIOS memory map */
998 KeLoaderBlock
.Flags
&= ~MB_FLAGS_MMAP_INFO
;
1001 KeMemoryMapRangeCount
= 0;
1002 if (KeLoaderBlock
.Flags
& MB_FLAGS_MMAP_INFO
)
1004 /* We have a memory map from the nice BIOS */
1005 size
= *((PULONG
)(KeLoaderBlock
.MmapAddr
- sizeof(ULONG
)));
1007 while (i
< KeLoaderBlock
.MmapLength
)
1009 memcpy (&KeMemoryMap
[KeMemoryMapRangeCount
],
1010 (PVOID
)(KeLoaderBlock
.MmapAddr
+ i
),
1011 sizeof(ADDRESS_RANGE
));
1012 KeMemoryMapRangeCount
++;