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.86 2001/04/10 17:48:17 dwelch 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 #include <ddk/ntddk.h>
32 #include <internal/ntoskrnl.h>
33 #include <reactos/resource.h>
34 #include <internal/mm.h>
35 #include <internal/module.h>
36 #include <internal/ldr.h>
37 #include <internal/ex.h>
38 #include <internal/ps.h>
39 #include <internal/ke.h>
40 #include <internal/io.h>
41 #include <napi/shared_data.h>
42 #include <internal/v86m.h>
43 #include <internal/kd.h>
44 #include <internal/trap.h>
45 #include <internal/config.h>
46 #include "../dbg/kdb.h"
49 #include <internal/debug.h>
51 /* GLOBALS *******************************************************************/
53 ULONG EXPORTED NtBuildNumber
= KERNEL_VERSION_BUILD
;
54 ULONG EXPORTED NtGlobalFlag
= 0;
55 CHAR EXPORTED KeNumberProcessors
= 1;
56 LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock
;
57 static LOADER_MODULE KeLoaderModules
[64];
58 static UCHAR KeLoaderModuleStrings
[64][256];
59 static UCHAR KeLoaderCommandLine
[256];
61 /* FUNCTIONS ****************************************************************/
64 CreateSystemRootLink (PCSZ ParameterLine
)
66 UNICODE_STRING LinkName
;
67 UNICODE_STRING DeviceName
;
68 UNICODE_STRING ArcName
;
69 UNICODE_STRING BootPath
;
75 OBJECT_ATTRIBUTES ObjectAttributes
;
78 /* create local parameter line copy */
79 ParamBuffer
= ExAllocatePool (PagedPool
, 256);
80 strcpy (ParamBuffer
, (char *)ParameterLine
);
82 DPRINT("%s\n", ParamBuffer
);
83 /* Format: <arc_name>\<path> [options...] */
86 p
= strchr (ParamBuffer
, ' ');
89 DPRINT("%s\n", ParamBuffer
);
92 p
= strchr (ParamBuffer
, '\\');
95 DPRINT("Boot path: %s\n", p
);
96 RtlCreateUnicodeStringFromAsciiz (&BootPath
, p
);
101 DPRINT("Boot path: %s\n", "\\");
102 RtlCreateUnicodeStringFromAsciiz (&BootPath
, "\\");
104 DPRINT("Arc name: %s\n", ParamBuffer
);
106 /* Only arc name left - build full arc name */
107 ArcNameBuffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
108 swprintf (ArcNameBuffer
,
109 L
"\\ArcName\\%S", ParamBuffer
);
110 RtlInitUnicodeString (&ArcName
, ArcNameBuffer
);
111 DPRINT1("Arc name: %wZ\n", &ArcName
);
113 /* free ParamBuffer */
114 ExFreePool (ParamBuffer
);
116 /* allocate device name string */
117 DeviceName
.Length
= 0;
118 DeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
119 DeviceName
.Buffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
121 InitializeObjectAttributes (&ObjectAttributes
,
127 Status
= NtOpenSymbolicLinkObject (&Handle
,
128 SYMBOLIC_LINK_ALL_ACCESS
,
130 if (!NT_SUCCESS(Status
))
132 RtlFreeUnicodeString (&BootPath
);
133 RtlFreeUnicodeString (&DeviceName
);
134 DbgPrint("NtOpenSymbolicLinkObject() '%wZ' failed (Status %x)\n",
137 RtlFreeUnicodeString (&ArcName
);
141 RtlFreeUnicodeString (&ArcName
);
143 Status
= NtQuerySymbolicLinkObject (Handle
,
147 if (!NT_SUCCESS(Status
))
149 RtlFreeUnicodeString (&BootPath
);
150 RtlFreeUnicodeString (&DeviceName
);
151 DbgPrint("NtQuerySymbolicObject() failed (Status %x)\n",
156 DPRINT("Length: %lu DeviceName: %wZ\n", Length
, &DeviceName
);
158 RtlAppendUnicodeStringToString (&DeviceName
,
161 RtlFreeUnicodeString (&BootPath
);
162 DPRINT("DeviceName: %wZ\n", &DeviceName
);
164 /* create the '\SystemRoot' link */
165 RtlInitUnicodeString (&LinkName
,
168 Status
= IoCreateSymbolicLink (&LinkName
,
170 RtlFreeUnicodeString (&DeviceName
);
171 if (!NT_SUCCESS(Status
))
173 DbgPrint("IoCreateSymbolicLink() failed (Status %x)\n",
179 /* Check if '\SystemRoot'(LinkName) can be opened, otherwise crash it! */
180 InitializeObjectAttributes (&ObjectAttributes
,
186 Status
= NtOpenSymbolicLinkObject (&Handle
,
187 SYMBOLIC_LINK_ALL_ACCESS
,
189 if (!NT_SUCCESS(Status
))
191 DbgPrint("NtOpenSymbolicLinkObject() failed to open '\\SystemRoot' (Status %x)\n",
200 InitSystemSharedUserPage (PCSZ ParameterLine
)
202 PKUSER_SHARED_DATA SharedPage
;
204 UNICODE_STRING ArcDeviceName
;
205 UNICODE_STRING ArcName
;
206 UNICODE_STRING BootPath
;
207 UNICODE_STRING DriveDeviceName
;
208 UNICODE_STRING DriveName
;
209 WCHAR DriveNameBuffer
[20];
211 PWCHAR ArcNameBuffer
;
215 OBJECT_ATTRIBUTES ObjectAttributes
;
218 BOOLEAN BootDriveFound
;
220 SharedPage
= (PKUSER_SHARED_DATA
)KERNEL_SHARED_DATA_BASE
;
221 SharedPage
->DosDeviceMap
= 0;
222 SharedPage
->NtProductType
= NtProductWinNt
;
223 for (i
= 0; i
< 32; i
++)
225 SharedPage
->DosDeviceDriveType
[i
] = 0;
228 BootDriveFound
= FALSE
;
231 * Retrieve the current dos system path
232 * (e.g.: C:\reactos) from the given arc path
233 * (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos)
234 * Format: "<arc_name>\<path> [options...]"
237 /* create local parameter line copy */
238 ParamBuffer
= ExAllocatePool (PagedPool
, 256);
239 strcpy (ParamBuffer
, (char *)ParameterLine
);
240 DPRINT("%s\n", ParamBuffer
);
242 /* cut options off */
243 p
= strchr (ParamBuffer
, ' ');
248 DPRINT("%s\n", ParamBuffer
);
251 p
= strchr (ParamBuffer
, '\\');
254 DPRINT("Boot path: %s\n", p
);
255 RtlCreateUnicodeStringFromAsciiz (&BootPath
, p
);
260 DPRINT("Boot path: %s\n", "\\");
261 RtlCreateUnicodeStringFromAsciiz (&BootPath
, "\\");
263 DPRINT("Arc name: %s\n", ParamBuffer
);
265 /* Only arc name left - build full arc name */
266 ArcNameBuffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
267 swprintf (ArcNameBuffer
, L
"\\ArcName\\%S", ParamBuffer
);
268 RtlInitUnicodeString (&ArcName
, ArcNameBuffer
);
269 DPRINT("Arc name: %wZ\n", &ArcName
);
271 /* free ParamBuffer */
272 ExFreePool (ParamBuffer
);
274 /* allocate arc device name string */
275 ArcDeviceName
.Length
= 0;
276 ArcDeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
277 ArcDeviceName
.Buffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
279 InitializeObjectAttributes (&ObjectAttributes
,
285 Status
= NtOpenSymbolicLinkObject (&Handle
,
286 SYMBOLIC_LINK_ALL_ACCESS
,
288 RtlFreeUnicodeString (&ArcName
);
289 if (!NT_SUCCESS(Status
))
291 RtlFreeUnicodeString (&BootPath
);
292 RtlFreeUnicodeString (&ArcDeviceName
);
293 DbgPrint("NtOpenSymbolicLinkObject() failed (Status %x)\n",
299 Status
= NtQuerySymbolicLinkObject (Handle
,
303 if (!NT_SUCCESS(Status
))
305 RtlFreeUnicodeString (&BootPath
);
306 RtlFreeUnicodeString (&ArcDeviceName
);
307 DbgPrint("NtQuerySymbolicObject() failed (Status %x)\n",
312 DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length
, &ArcDeviceName
);
315 /* allocate device name string */
316 DriveDeviceName
.Length
= 0;
317 DriveDeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
318 DriveDeviceName
.Buffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
320 for (i
= 0; i
< 26; i
++)
322 swprintf (DriveNameBuffer
, L
"\\??\\%C:", 'A' + i
);
323 RtlInitUnicodeString (&DriveName
,
326 InitializeObjectAttributes (&ObjectAttributes
,
332 Status
= NtOpenSymbolicLinkObject (&Handle
,
333 SYMBOLIC_LINK_ALL_ACCESS
,
335 if (!NT_SUCCESS(Status
))
337 DPRINT("Failed to open link %wZ\n",
342 Status
= NtQuerySymbolicLinkObject (Handle
,
345 if (!NT_SUCCESS(Status
))
347 DPRINT("Failed query open link %wZ\n",
351 DPRINT("Opened link: %wZ ==> %wZ\n",
352 &DriveName
, &DriveDeviceName
);
354 if (!RtlCompareUnicodeString (&ArcDeviceName
, &DriveDeviceName
, FALSE
))
356 DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i
, &BootPath
);
357 swprintf (SharedPage
->NtSystemRoot
,
358 L
"%C:%wZ", 'A' + i
, &BootPath
);
360 BootDriveFound
= TRUE
;
365 /* set bit in dos drives bitmap (drive available) */
366 SharedPage
->DosDeviceMap
|= (1<<i
);
369 RtlFreeUnicodeString (&BootPath
);
370 RtlFreeUnicodeString (&DriveDeviceName
);
371 RtlFreeUnicodeString (&ArcDeviceName
);
373 DPRINT("DosDeviceMap: 0x%x\n", SharedPage
->DosDeviceMap
);
375 if (BootDriveFound
== FALSE
)
377 DbgPrint("No system drive found!\n");
383 _main (ULONG MultiBootMagic
, PLOADER_PARAMETER_BLOCK _LoaderBlock
)
385 * FUNCTION: Called by the boot loader to start the kernel
387 * LoaderBlock = Pointer to boot parameters initialized by the boot
389 * NOTE: The boot parameters are stored in low memory which will become
390 * invalid after the memory managment is initialized so we make a local copy.
394 ULONG last_kernel_address
;
397 extern ULONG _bss_end__
;
400 * Copy the parameters to a local buffer because lowmem will go away
402 memcpy (&KeLoaderBlock
, _LoaderBlock
, sizeof(LOADER_PARAMETER_BLOCK
));
403 memcpy (&KeLoaderModules
[1], (PVOID
)KeLoaderBlock
.ModsAddr
,
404 sizeof(LOADER_MODULE
) * KeLoaderBlock
.ModsCount
);
405 KeLoaderBlock
.ModsCount
++;
406 KeLoaderBlock
.ModsAddr
= (ULONG
)&KeLoaderModules
;
409 * FIXME: Preliminary hack!!!! Add boot device to beginning of command line.
410 * This should be done by the boot loader.
412 strcpy (KeLoaderCommandLine
,
413 "multi(0)disk(0)rdisk(0)partition(1)\\reactos ");
414 strcat (KeLoaderCommandLine
, (PUCHAR
)KeLoaderBlock
.CommandLine
);
416 KeLoaderBlock
.CommandLine
= (ULONG
)KeLoaderCommandLine
;
417 strcpy(KeLoaderModuleStrings
[0], "ntoskrnl.exe");
418 KeLoaderModules
[0].String
= (ULONG
)KeLoaderModuleStrings
[0];
419 KeLoaderModules
[0].ModStart
= 0xC0000000;
420 KeLoaderModules
[0].ModEnd
= PAGE_ROUND_UP((ULONG
)&_bss_end__
);
421 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
423 strcpy(KeLoaderModuleStrings
[i
], (PUCHAR
)KeLoaderModules
[i
].String
);
424 KeLoaderModules
[i
].ModStart
-= 0x200000;
425 KeLoaderModules
[i
].ModStart
+= 0xc0000000;
426 KeLoaderModules
[i
].ModEnd
-= 0x200000;
427 KeLoaderModules
[i
].ModEnd
+= 0xc0000000;
428 KeLoaderModules
[i
].String
= (ULONG
)KeLoaderModuleStrings
[i
];
432 * Initialization phase 0
434 HalInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
437 KeLowerIrql(DISPATCH_LEVEL
);
440 * Display version number and copyright/warranty message
442 HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR
" (Build "
443 KERNEL_VERSION_BUILD_STR
")\n");
444 HalDisplayString(RES_STR_LEGAL_COPYRIGHT
);
445 HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
446 "Public License, and you\n");
447 HalDisplayString("are welcome to change it and/or distribute copies of it "
449 HalDisplayString("conditions. There is absolutely no warranty for ReactOS.\n");
452 * Fail at runtime if someone has changed various structures without
453 * updating the offsets used for the assembler code
455 assert(FIELD_OFFSET(KTHREAD
, InitialStack
) == KTHREAD_INITIAL_STACK
);
456 assert(FIELD_OFFSET(KTHREAD
, Teb
) == KTHREAD_TEB
);
457 assert(FIELD_OFFSET(KTHREAD
, KernelStack
) == KTHREAD_KERNEL_STACK
);
458 assert(FIELD_OFFSET(KTHREAD
, PreviousMode
) == KTHREAD_PREVIOUS_MODE
);
459 assert(FIELD_OFFSET(KTHREAD
, TrapFrame
) == KTHREAD_TRAP_FRAME
);
460 assert(FIELD_OFFSET(ETHREAD
, ThreadsProcess
) == ETHREAD_THREADS_PROCESS
);
461 assert(FIELD_OFFSET(KPROCESS
, PageTableDirectory
) ==
462 KPROCESS_PAGE_TABLE_DIRECTORY
);
463 assert(FIELD_OFFSET(KTRAP_FRAME
, Reserved9
) == KTRAP_FRAME_RESERVED9
);
464 assert(FIELD_OFFSET(KV86M_TRAP_FRAME
, regs
) == TF_REGS
);
465 assert(FIELD_OFFSET(KV86M_TRAP_FRAME
, orig_ebp
) == TF_ORIG_EBP
);
467 last_kernel_address
= KeLoaderModules
[KeLoaderBlock
.ModsCount
- 1].ModEnd
;
470 MmInit1(KeLoaderModules
[0].ModStart
- 0xc0000000 + 0x200000,
471 last_kernel_address
- 0xc0000000 + 0x200000,
472 last_kernel_address
);
475 * Initialize the kernel debugger
477 KdInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
478 if (KdPollBreakIn ())
480 DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C
);
484 * Initialization phase 1
485 * Initalize various critical subsystems
487 HalInitSystem (1, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
494 KeLowerIrql(PASSIVE_LEVEL
);
497 PiInitProcessManager();
500 LdrInitModuleManagement();
501 CmInitializeRegistry();
505 /* Report all resources used by hal */
506 HalReportResourceUsage ();
509 * Enter the kernel debugger before starting up the boot drivers
516 * Initalize services loaded at boot time
518 DPRINT1("%d files loaded\n",KeLoaderBlock
.ModsCount
);
519 for (i
=0; i
< KeLoaderBlock
.ModsCount
; i
++)
521 DPRINT1("module: %s\n", KeLoaderModules
[i
].String
);
524 /* Pass 1: load registry chunks passed in */
525 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
527 start
= KeLoaderModules
[i
].ModStart
;
528 if (strcmp ((PCHAR
) start
, "REGEDIT4") == 0)
530 DPRINT1("process registry chunk at %08lx\n", start
);
531 CmImportHive((PCHAR
) start
);
535 /* Pass 2: process boot loaded drivers */
536 for (i
=1; i
< KeLoaderBlock
.ModsCount
; i
++)
538 start
= KeLoaderModules
[i
].ModStart
;
539 name
= (PCHAR
)KeLoaderModules
[i
].String
;
540 if (strcmp ((PCHAR
) start
, "REGEDIT4") != 0)
542 DPRINT1("process module '%s' at %08lx\n", name
, start
);
543 LdrProcessDriver((PVOID
)start
, name
);
547 /* Create the SystemRoot symbolic link */
548 DbgPrint("CommandLine: %s\n", (PUCHAR
)KeLoaderBlock
.CommandLine
);
549 CreateSystemRootLink ((PUCHAR
)KeLoaderBlock
.CommandLine
);
551 #ifdef DBGPRINT_FILE_LOG
552 /* On the assumption that we can now access disks start up the debug
555 #endif /* DBGPRINT_FILE_LOG */
557 CmInitializeRegistry2();
560 * Load Auto configured drivers
562 LdrLoadAutoConfigDrivers();
565 * Assign drive letters
567 IoAssignDriveLetters ((PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
,
573 * Initialize shared user page:
574 * - set dos system path, dos device map, etc.
576 InitSystemSharedUserPage ((PUCHAR
)KeLoaderBlock
.CommandLine
);
579 * Launch initial process
581 LdrLoadInitialProcess();
583 DbgPrint("Finished main()\n");
584 PsTerminateSystemThread(STATUS_SUCCESS
);