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.182 2004/01/05 14:28:21 weiden 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/nls.h>
51 #include <reactos/bugcodes.h>
52 #include <ntos/bootvid.h>
53 #include <napi/core.h>
56 #include <internal/ntosdbg.h>
58 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
67 #include <internal/debug.h>
69 /* GLOBALS *******************************************************************/
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;
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;
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
;
99 extern PVOID Ki386InitialStackArray
[MAXIMUM_PROCESSORS
];
102 /* FUNCTIONS ****************************************************************/
104 static VOID INIT_FUNCTION
105 InitSystemSharedUserPage (PCSZ ParameterLine
)
107 UNICODE_STRING ArcDeviceName
;
108 UNICODE_STRING ArcName
;
109 UNICODE_STRING BootPath
;
110 UNICODE_STRING DriveDeviceName
;
111 UNICODE_STRING DriveName
;
112 WCHAR DriveNameBuffer
[20];
114 PWCHAR ArcNameBuffer
;
118 OBJECT_ATTRIBUTES ObjectAttributes
;
121 BOOLEAN BootDriveFound
;
125 * The shared user page has been zeroed-out right after creation.
126 * There is NO need to do this again.
129 SharedUserData
->NtProductType
= NtProductWinNt
;
131 BootDriveFound
= FALSE
;
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...]"
140 /* create local parameter line copy */
141 ParamBuffer
= ExAllocatePool (PagedPool
, 256);
142 strcpy (ParamBuffer
, (char *)ParameterLine
);
143 DPRINT("%s\n", ParamBuffer
);
145 /* cut options off */
146 p
= strchr (ParamBuffer
, ' ');
151 DPRINT("%s\n", ParamBuffer
);
154 p
= strchr (ParamBuffer
, '\\');
157 DPRINT("Boot path: %s\n", p
);
158 RtlCreateUnicodeStringFromAsciiz (&BootPath
, p
);
163 DPRINT("Boot path: %s\n", "\\");
164 RtlCreateUnicodeStringFromAsciiz (&BootPath
, "\\");
166 DPRINT("Arc name: %s\n", ParamBuffer
);
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
);
174 /* free ParamBuffer */
175 ExFreePool (ParamBuffer
);
177 /* allocate arc device name string */
178 ArcDeviceName
.Length
= 0;
179 ArcDeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
180 ArcDeviceName
.Buffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
182 InitializeObjectAttributes (&ObjectAttributes
,
188 Status
= NtOpenSymbolicLinkObject (&Handle
,
189 SYMBOLIC_LINK_ALL_ACCESS
,
191 RtlFreeUnicodeString (&ArcName
);
192 if (!NT_SUCCESS(Status
))
194 RtlFreeUnicodeString (&BootPath
);
195 RtlFreeUnicodeString (&ArcDeviceName
);
196 CPRINT("NtOpenSymbolicLinkObject() failed (Status %x)\n",
202 Status
= NtQuerySymbolicLinkObject (Handle
,
206 if (!NT_SUCCESS(Status
))
208 RtlFreeUnicodeString (&BootPath
);
209 RtlFreeUnicodeString (&ArcDeviceName
);
210 CPRINT("NtQuerySymbolicObject() failed (Status %x)\n",
215 DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length
, &ArcDeviceName
);
218 /* allocate device name string */
219 DriveDeviceName
.Length
= 0;
220 DriveDeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
221 DriveDeviceName
.Buffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
223 for (i
= 0; i
< 26; i
++)
225 swprintf (DriveNameBuffer
, L
"\\??\\%C:", 'A' + i
);
226 RtlInitUnicodeString (&DriveName
,
229 InitializeObjectAttributes (&ObjectAttributes
,
235 Status
= NtOpenSymbolicLinkObject (&Handle
,
236 SYMBOLIC_LINK_ALL_ACCESS
,
238 if (!NT_SUCCESS(Status
))
240 DPRINT("Failed to open link %wZ\n",
245 Status
= NtQuerySymbolicLinkObject (Handle
,
248 if (!NT_SUCCESS(Status
))
250 DPRINT("Failed query open link %wZ\n",
254 DPRINT("Opened link: %wZ ==> %wZ\n",
255 &DriveName
, &DriveDeviceName
);
257 if (!RtlCompareUnicodeString (&ArcDeviceName
, &DriveDeviceName
, FALSE
))
259 DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i
, &BootPath
);
260 swprintf(SharedUserData
->NtSystemRoot
,
261 L
"%C:%wZ", 'A' + i
, &BootPath
);
263 BootDriveFound
= TRUE
;
269 RtlFreeUnicodeString (&BootPath
);
270 RtlFreeUnicodeString (&DriveDeviceName
);
271 RtlFreeUnicodeString (&ArcDeviceName
);
273 DPRINT("DosDeviceMap: 0x%x\n", SharedUserData
->DosDeviceMap
);
275 if (BootDriveFound
== FALSE
)
277 DbgPrint("No system drive found!\n");
283 ExpInitializeExecutive(VOID
)
285 LARGE_INTEGER Timeout
;
286 HANDLE ProcessHandle
;
297 BOOLEAN NoBootScreen
= FALSE
;
299 HANDLE InitDoneEventHandle
;
300 OBJECT_ATTRIBUTES ObjectAttributes
;
303 * Fail at runtime if someone has changed various structures without
304 * updating the offsets used for the assembler code.
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
);
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
);
330 KeLowerIrql(DISPATCH_LEVEL
);
334 p1
= (PCHAR
)KeLoaderBlock
.CommandLine
;
337 while(*p1
&& (p2
= strchr(p1
, '/')))
340 if (!_strnicmp(p2
, "MAXMEM", 6))
343 while (isspace(*p2
)) p2
++;
347 while(isspace(*p2
)) p2
++;
352 MaxMem
= MaxMem
* 10 + *p2
- '0';
359 else if (!_strnicmp(p2
, "NOBOOTSCREEN", 12))
364 else if (!_strnicmp(p2
, "CRASHDUMP", 9))
370 if (!_strnicmp(p2
, "FULL", 4))
372 MmCoreDumpType
= MM_CORE_DUMP_TYPE_FULL
;
376 MmCoreDumpType
= MM_CORE_DUMP_TYPE_NONE
;
383 MmInit1(FirstKrnlPhysAddr
,
386 (PADDRESS_RANGE
)&KeMemoryMap
,
387 KeMemoryMapRangeCount
,
388 MaxMem
> 8 ? MaxMem
: 4096);
390 /* Import ANSI code page table */
391 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
393 start
= KeLoaderModules
[i
].ModStart
;
394 length
= KeLoaderModules
[i
].ModEnd
- start
;
396 name
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '\\');
399 name
= (PCHAR
)KeLoaderModules
[i
].String
;
406 if (!_stricmp (name
, "ansi.nls"))
408 RtlpImportAnsiCodePage((PUSHORT
)start
, length
);
412 /* Import OEM code page table */
413 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
415 start
= KeLoaderModules
[i
].ModStart
;
416 length
= KeLoaderModules
[i
].ModEnd
- start
;
418 name
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '\\');
421 name
= (PCHAR
)KeLoaderModules
[i
].String
;
428 if (!_stricmp (name
, "oem.nls"))
430 RtlpImportOemCodePage((PUSHORT
)start
, length
);
434 /* Import Unicode casemap table */
435 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
437 start
= KeLoaderModules
[i
].ModStart
;
438 length
= KeLoaderModules
[i
].ModEnd
- start
;
440 name
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '\\');
443 name
= (PCHAR
)KeLoaderModules
[i
].String
;
450 if (!_stricmp (name
, "casemap.nls"))
452 RtlpImportUnicodeCasemap((PUSHORT
)start
, length
);
456 /* Create initial NLS tables */
457 RtlpCreateInitialNlsTables();
460 * Initialize the kernel debugger
462 KdInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
466 KeLowerIrql(PASSIVE_LEVEL
);
469 KEBUGCHECK(SECURITY_INITIALIZATION_FAILED
);
476 KEBUGCHECK(SECURITY1_INITIALIZATION_FAILED
);
478 PiInitProcessManager();
480 if (KdPollBreakIn ())
482 DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C
);
485 /* Initialize all processors */
486 KeNumberProcessors
= 0;
488 while (!HalAllProcessorsStarted())
490 PVOID ProcessorStack
;
492 if (KeNumberProcessors
!= 0)
494 KePrepareForApplicationProcessorInit(KeNumberProcessors
);
495 PsPrepareForApplicationProcessorInit(KeNumberProcessors
);
497 /* Allocate a stack for use when booting the processor */
498 /* FIXME: The nonpaged memory for the stack is not released after use */
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
++;
508 * Initialize various critical subsystems
510 HalInitSystem(1, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
516 LdrInitModuleManagement();
517 CmInitializeRegistry();
522 FsRtlpInitFileLockingImplementation();
524 /* Report all resources used by hal */
525 HalReportResourceUsage();
528 * Clear the screen to blue
530 HalInitSystem(2, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
533 * Display version number and copyright/warranty message
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 "
542 HalDisplayString("conditions. There is absolutely no warranty for "
545 if (KeNumberProcessors
> 1)
548 "Found %d system processors. [%lu MB Memory]\n",
550 (KeLoaderBlock
.MemHigher
+ 1088)/ 1024);
555 "Found 1 system processor. [%lu MB Memory]\n",
556 (KeLoaderBlock
.MemHigher
+ 1088)/ 1024);
558 HalDisplayString(str
);
563 /* Create the NLS section */
564 RtlpCreateNlsSection();
567 * Initalize services loaded at boot time
569 DPRINT("%d files loaded\n",KeLoaderBlock
.ModsCount
);
570 for (i
=0; i
< KeLoaderBlock
.ModsCount
; i
++)
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
);
578 /* Pass 1: import system hive registry chunk */
580 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
582 start
= KeLoaderModules
[i
].ModStart
;
583 length
= KeLoaderModules
[i
].ModEnd
- start
;
585 DPRINT("Module: '%s'\n", (PCHAR
)KeLoaderModules
[i
].String
);
586 name
= strrchr((PCHAR
)KeLoaderModules
[i
].String
, '\\');
589 name
= (PCHAR
)KeLoaderModules
[i
].String
;
596 if (!_stricmp (name
, "system") ||
597 !_stricmp (name
, "system.hiv"))
599 CPRINT("Process system hive registry chunk at %08lx\n", start
);
601 CmImportSystemHive((PCHAR
)start
, length
);
605 /* Pass 2: import hardware hive registry chunk */
606 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
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"))
614 CPRINT("Process hardware hive registry chunk at %08lx\n", start
);
615 CmImportHardwareHive((PCHAR
)start
, length
);
619 /* Create dummy keys if no hardware hive was found */
620 CmImportHardwareHive (NULL
, 0);
622 /* Initialize volatile registry settings */
623 if (SetupBoot
== FALSE
)
625 CmInit2((PCHAR
)KeLoaderBlock
.CommandLine
);
629 * Enter the kernel debugger before starting up the boot drivers
635 IoCreateDriverList();
640 * Load boot start drivers
642 IopInitializeBootDrivers();
644 /* Display the boot screen image if not disabled */
647 InbvEnableBootDriver(TRUE
);
650 /* Create ARC names for boot devices */
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
);
663 /* On the assumption that we can now access disks start up the debug
665 if ((KdDebuggerEnabled
== TRUE
) && (KdDebugState
& KD_DEBUG_FILELOG
))
670 PiInitDefaultLocale();
673 * Load services for devices found by PnP manager
675 IopInitializePnpServices(IopRootDeviceNode
, FALSE
);
678 * Load system start drivers
680 IopInitializeSystemDrivers();
682 IoDestroyDriverList();
685 * Assign drive letters
687 IoAssignDriveLetters ((PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
,
693 * Initialize shared user page:
694 * - set dos system path, dos device map, etc.
696 InitSystemSharedUserPage ((PUCHAR
)KeLoaderBlock
.CommandLine
);
698 /* Create 'ReactOSInitDone' event */
699 RtlInitUnicodeString(&Name
, L
"\\ReactOSInitDone");
700 InitializeObjectAttributes(&ObjectAttributes
,
705 Status
= NtCreateEvent(&InitDoneEventHandle
,
708 FALSE
, /* Synchronization event */
709 FALSE
); /* Not signalled */
710 if (!NT_SUCCESS(Status
))
712 DPRINT1("Failed to create 'ReactOSInitDone' event (Status 0x%x)\n", Status
);
713 InitDoneEventHandle
= INVALID_HANDLE_VALUE
;
717 * Launch initial process
719 Status
= LdrLoadInitialProcess(&ProcessHandle
,
721 if (!NT_SUCCESS(Status
))
723 KEBUGCHECKEX(SESSION4_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
726 if (InitDoneEventHandle
!= INVALID_HANDLE_VALUE
)
728 HANDLE Handles
[2]; /* Init event, Initial process */
730 Handles
[0] = InitDoneEventHandle
;
731 Handles
[1] = ProcessHandle
;
733 /* Wait for the system to be initialized */
735 Timeout
.QuadPart
= -1200000000LL; /* 120 second timeout */
737 Timeout
.QuadPart
= -1200000000; /* 120 second timeout */
739 Status
= NtWaitForMultipleObjects(((LONG
) sizeof(Handles
) / sizeof(HANDLE
)),
742 FALSE
, /* Non-alertable */
744 if (!NT_SUCCESS(Status
))
746 DPRINT1("NtWaitForMultipleObjects failed with status 0x%x!\n", Status
);
748 else if (Status
== STATUS_TIMEOUT
)
750 DPRINT1("WARNING: System not initialized after 120 seconds.\n");
752 else if (Status
== STATUS_WAIT_0
+ 1)
755 * Crash the system if the initial process was terminated.
757 KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
762 InbvEnableBootDriver(FALSE
);
765 NtSetEvent(InitDoneEventHandle
, NULL
);
767 NtClose(InitDoneEventHandle
);
771 /* On failure to create 'ReactOSInitDone' event, go to text mode ASAP */
774 InbvEnableBootDriver(FALSE
);
778 * Crash the system if the initial process terminates within 5 seconds.
781 Timeout
.QuadPart
= -50000000LL;
783 Timeout
.QuadPart
= -50000000;
785 Status
= NtWaitForSingleObject(ProcessHandle
,
788 if (Status
!= STATUS_TIMEOUT
)
790 KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED
, Status
, 0, 0, 0);
794 NtClose(ThreadHandle
);
795 NtClose(ProcessHandle
);
800 KiSystemStartup(BOOLEAN BootProcessor
)
802 HalInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
806 ExpInitializeExecutive();
809 PsTerminateSystemThread(STATUS_SUCCESS
);
812 /* Do application processor initialization */
813 KeApplicationProcessorInit();
814 PsApplicationProcessorInit();
815 KeLowerIrql(PASSIVE_LEVEL
);
816 PsIdleThreadMain(NULL
);
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.
828 VOID
/*INIT_FUNCTION*/
829 _main (ULONG MultiBootMagic
, PLOADER_PARAMETER_BLOCK _LoaderBlock
)
831 * FUNCTION: Called by the boot loader to start the kernel
833 * LoaderBlock = Pointer to boot parameters initialized by the boot
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.
841 ULONG last_kernel_address
;
842 extern ULONG _bss_end__
;
847 /* Low level architecture specific initialization */
851 * Copy the parameters to a local buffer because lowmem will go away
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
;
860 * Convert a path specification in the grub format to one understood by the
861 * rest of the kernel.
863 if (((PUCHAR
)_LoaderBlock
->CommandLine
)[0] == '(')
865 ULONG DiskNumber
= 0, PartNumber
= 0;
871 if (((PUCHAR
)_LoaderBlock
->CommandLine
)[1] == 'h' &&
872 ((PUCHAR
)_LoaderBlock
->CommandLine
)[2] == 'd')
874 DiskNumber
= ((PUCHAR
)_LoaderBlock
->CommandLine
)[3] - '0';
875 PartNumber
= ((PUCHAR
)_LoaderBlock
->CommandLine
)[5] - '0';
877 strcpy(Temp
, &((PUCHAR
)_LoaderBlock
->CommandLine
)[7]);
878 if ((options
= strchr(Temp
, ' ')) != NULL
)
887 if ((s1
= strrchr(Temp
, '/')) != NULL
)
890 if ((s1
= strrchr(Temp
, '/')) != NULL
)
895 sprintf(KeLoaderCommandLine
,
896 "multi(0)disk(0)rdisk(%lu)partition(%lu)%s %s",
897 DiskNumber
, PartNumber
+ 1, Temp
, options
);
899 p
= KeLoaderCommandLine
;
900 while (*p
!= 0 && *p
!= ' ')
908 DPRINT1("Command Line: %s\n", KeLoaderCommandLine
);
912 strcpy(KeLoaderCommandLine
, (PUCHAR
)_LoaderBlock
->CommandLine
);
914 KeLoaderBlock
.CommandLine
= (ULONG
)KeLoaderCommandLine
;
916 strcpy(KeLoaderModuleStrings
[0], "ntoskrnl.exe");
917 KeLoaderModules
[0].String
= (ULONG
)KeLoaderModuleStrings
[0];
918 KeLoaderModules
[0].ModStart
= KERNEL_BASE
;
920 KeLoaderModules
[0].ModEnd
= PAGE_ROUND_UP((ULONG
)&_bss_end__
);
922 /* Take this value from the PE... */
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
);
930 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
933 if ((s
= strrchr((PUCHAR
)KeLoaderModules
[i
].String
, '/')) != 0)
935 strcpy(KeLoaderModuleStrings
[i
], s
+ 1);
939 strcpy(KeLoaderModuleStrings
[i
], (PUCHAR
)KeLoaderModules
[i
].String
);
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
];
950 HalnInitializeDisplay((PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
953 HalBase
= KeLoaderModules
[1].ModStart
;
955 PAGE_ROUND_UP(KeLoaderModules
[KeLoaderBlock
.ModsCount
- 1].ModEnd
);
960 LdrSafePEProcessModule((PVOID
)HalBase
, (PVOID
)DriverBase
, (PVOID
)KERNEL_BASE
, &DriverSize
);
962 LdrHalBase
= (ULONG_PTR
)DriverBase
;
963 last_kernel_address
= DriverBase
+ DriverSize
;
966 * Process ntoskrnl.exe
968 LdrSafePEProcessModule((PVOID
)KERNEL_BASE
, (PVOID
)KERNEL_BASE
, (PVOID
)DriverBase
, &DriverSize
);
970 /* Now our imports from HAL is fixed. This is the first */
971 /* time in the boot process that we can use HAL */
973 FirstKrnlPhysAddr
= KeLoaderModules
[0].ModStart
- KERNEL_BASE
+ 0x200000;
974 LastKrnlPhysAddr
= last_kernel_address
- KERNEL_BASE
+ 0x200000;
975 LastKernelAddress
= last_kernel_address
;
978 /* FIXME: VMware does not like it when ReactOS is using the BIOS memory map */
979 KeLoaderBlock
.Flags
&= ~MB_FLAGS_MMAP_INFO
;
982 KeMemoryMapRangeCount
= 0;
983 if (KeLoaderBlock
.Flags
& MB_FLAGS_MMAP_INFO
)
985 /* We have a memory map from the nice BIOS */
986 size
= *((PULONG
)(KeLoaderBlock
.MmapAddr
- sizeof(ULONG
)));
988 while (i
< KeLoaderBlock
.MmapLength
)
990 memcpy (&KeMemoryMap
[KeMemoryMapRangeCount
],
991 (PVOID
)(KeLoaderBlock
.MmapAddr
+ i
),
992 sizeof(ADDRESS_RANGE
));
993 KeMemoryMapRangeCount
++;