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.87 2001/04/13 16:12:25 chorns 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/config.h>
33 #include <internal/ntoskrnl.h>
34 #include <reactos/resource.h>
35 #include <internal/mm.h>
36 #include <internal/module.h>
37 #include <internal/ldr.h>
38 #include <internal/ex.h>
39 #include <internal/ps.h>
40 #include <internal/ke.h>
41 #include <internal/io.h>
42 #include <napi/shared_data.h>
43 #include <internal/v86m.h>
44 #include <internal/kd.h>
45 #include <internal/trap.h>
46 #include <internal/config.h>
47 #include "../dbg/kdb.h"
50 #include <internal/debug.h>
52 /* GLOBALS *******************************************************************/
54 ULONG EXPORTED NtBuildNumber
= KERNEL_VERSION_BUILD
;
55 ULONG EXPORTED NtGlobalFlag
= 0;
56 CHAR EXPORTED KeNumberProcessors
;
57 LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock
;
58 static LOADER_MODULE KeLoaderModules
[64];
59 static UCHAR KeLoaderModuleStrings
[64][256];
60 static UCHAR KeLoaderCommandLine
[256];
61 static ULONG FirstKrnlPhysAddr
;
62 static ULONG LastKrnlPhysAddr
;
63 static ULONG LastKernelAddress
;
64 volatile BOOLEAN Initialized
= FALSE
;
66 /* FUNCTIONS ****************************************************************/
69 CreateSystemRootLink (PCSZ ParameterLine
)
71 UNICODE_STRING LinkName
;
72 UNICODE_STRING DeviceName
;
73 UNICODE_STRING ArcName
;
74 UNICODE_STRING BootPath
;
80 OBJECT_ATTRIBUTES ObjectAttributes
;
83 /* create local parameter line copy */
84 ParamBuffer
= ExAllocatePool (PagedPool
, 256);
85 strcpy (ParamBuffer
, (char *)ParameterLine
);
87 DPRINT("%s\n", ParamBuffer
);
88 /* Format: <arc_name>\<path> [options...] */
91 p
= strchr (ParamBuffer
, ' ');
94 DPRINT("%s\n", ParamBuffer
);
97 p
= strchr (ParamBuffer
, '\\');
100 DPRINT("Boot path: %s\n", p
);
101 RtlCreateUnicodeStringFromAsciiz (&BootPath
, p
);
106 DPRINT("Boot path: %s\n", "\\");
107 RtlCreateUnicodeStringFromAsciiz (&BootPath
, "\\");
109 DPRINT("Arc name: %s\n", ParamBuffer
);
111 /* Only arc name left - build full arc name */
112 ArcNameBuffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
113 swprintf (ArcNameBuffer
,
114 L
"\\ArcName\\%S", ParamBuffer
);
115 RtlInitUnicodeString (&ArcName
, ArcNameBuffer
);
116 DPRINT1("Arc name: %wZ\n", &ArcName
);
118 /* free ParamBuffer */
119 ExFreePool (ParamBuffer
);
121 /* allocate device name string */
122 DeviceName
.Length
= 0;
123 DeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
124 DeviceName
.Buffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
126 InitializeObjectAttributes (&ObjectAttributes
,
132 Status
= NtOpenSymbolicLinkObject (&Handle
,
133 SYMBOLIC_LINK_ALL_ACCESS
,
135 if (!NT_SUCCESS(Status
))
137 RtlFreeUnicodeString (&BootPath
);
138 RtlFreeUnicodeString (&DeviceName
);
139 DbgPrint("NtOpenSymbolicLinkObject() '%wZ' failed (Status %x)\n",
142 RtlFreeUnicodeString (&ArcName
);
146 RtlFreeUnicodeString (&ArcName
);
148 Status
= NtQuerySymbolicLinkObject (Handle
,
152 if (!NT_SUCCESS(Status
))
154 RtlFreeUnicodeString (&BootPath
);
155 RtlFreeUnicodeString (&DeviceName
);
156 DbgPrint("NtQuerySymbolicObject() failed (Status %x)\n",
161 DPRINT("Length: %lu DeviceName: %wZ\n", Length
, &DeviceName
);
163 RtlAppendUnicodeStringToString (&DeviceName
,
166 RtlFreeUnicodeString (&BootPath
);
167 DPRINT("DeviceName: %wZ\n", &DeviceName
);
169 /* create the '\SystemRoot' link */
170 RtlInitUnicodeString (&LinkName
,
173 Status
= IoCreateSymbolicLink (&LinkName
,
175 RtlFreeUnicodeString (&DeviceName
);
176 if (!NT_SUCCESS(Status
))
178 DbgPrint("IoCreateSymbolicLink() failed (Status %x)\n",
184 /* Check if '\SystemRoot'(LinkName) can be opened, otherwise crash it! */
185 InitializeObjectAttributes (&ObjectAttributes
,
191 Status
= NtOpenSymbolicLinkObject (&Handle
,
192 SYMBOLIC_LINK_ALL_ACCESS
,
194 if (!NT_SUCCESS(Status
))
196 DbgPrint("NtOpenSymbolicLinkObject() failed to open '\\SystemRoot' (Status %x)\n",
205 InitSystemSharedUserPage (PCSZ ParameterLine
)
207 PKUSER_SHARED_DATA SharedPage
;
209 UNICODE_STRING ArcDeviceName
;
210 UNICODE_STRING ArcName
;
211 UNICODE_STRING BootPath
;
212 UNICODE_STRING DriveDeviceName
;
213 UNICODE_STRING DriveName
;
214 WCHAR DriveNameBuffer
[20];
216 PWCHAR ArcNameBuffer
;
220 OBJECT_ATTRIBUTES ObjectAttributes
;
223 BOOLEAN BootDriveFound
;
225 SharedPage
= (PKUSER_SHARED_DATA
)KERNEL_SHARED_DATA_BASE
;
226 SharedPage
->DosDeviceMap
= 0;
227 SharedPage
->NtProductType
= NtProductWinNt
;
228 for (i
= 0; i
< 32; i
++)
230 SharedPage
->DosDeviceDriveType
[i
] = 0;
233 BootDriveFound
= FALSE
;
236 * Retrieve the current dos system path
237 * (e.g.: C:\reactos) from the given arc path
238 * (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos)
239 * Format: "<arc_name>\<path> [options...]"
242 /* create local parameter line copy */
243 ParamBuffer
= ExAllocatePool (PagedPool
, 256);
244 strcpy (ParamBuffer
, (char *)ParameterLine
);
245 DPRINT("%s\n", ParamBuffer
);
247 /* cut options off */
248 p
= strchr (ParamBuffer
, ' ');
253 DPRINT("%s\n", ParamBuffer
);
256 p
= strchr (ParamBuffer
, '\\');
259 DPRINT("Boot path: %s\n", p
);
260 RtlCreateUnicodeStringFromAsciiz (&BootPath
, p
);
265 DPRINT("Boot path: %s\n", "\\");
266 RtlCreateUnicodeStringFromAsciiz (&BootPath
, "\\");
268 DPRINT("Arc name: %s\n", ParamBuffer
);
270 /* Only arc name left - build full arc name */
271 ArcNameBuffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
272 swprintf (ArcNameBuffer
, L
"\\ArcName\\%S", ParamBuffer
);
273 RtlInitUnicodeString (&ArcName
, ArcNameBuffer
);
274 DPRINT("Arc name: %wZ\n", &ArcName
);
276 /* free ParamBuffer */
277 ExFreePool (ParamBuffer
);
279 /* allocate arc device name string */
280 ArcDeviceName
.Length
= 0;
281 ArcDeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
282 ArcDeviceName
.Buffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
284 InitializeObjectAttributes (&ObjectAttributes
,
290 Status
= NtOpenSymbolicLinkObject (&Handle
,
291 SYMBOLIC_LINK_ALL_ACCESS
,
293 RtlFreeUnicodeString (&ArcName
);
294 if (!NT_SUCCESS(Status
))
296 RtlFreeUnicodeString (&BootPath
);
297 RtlFreeUnicodeString (&ArcDeviceName
);
298 DbgPrint("NtOpenSymbolicLinkObject() failed (Status %x)\n",
304 Status
= NtQuerySymbolicLinkObject (Handle
,
308 if (!NT_SUCCESS(Status
))
310 RtlFreeUnicodeString (&BootPath
);
311 RtlFreeUnicodeString (&ArcDeviceName
);
312 DbgPrint("NtQuerySymbolicObject() failed (Status %x)\n",
317 DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length
, &ArcDeviceName
);
320 /* allocate device name string */
321 DriveDeviceName
.Length
= 0;
322 DriveDeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
323 DriveDeviceName
.Buffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
325 for (i
= 0; i
< 26; i
++)
327 swprintf (DriveNameBuffer
, L
"\\??\\%C:", 'A' + i
);
328 RtlInitUnicodeString (&DriveName
,
331 InitializeObjectAttributes (&ObjectAttributes
,
337 Status
= NtOpenSymbolicLinkObject (&Handle
,
338 SYMBOLIC_LINK_ALL_ACCESS
,
340 if (!NT_SUCCESS(Status
))
342 DPRINT("Failed to open link %wZ\n",
347 Status
= NtQuerySymbolicLinkObject (Handle
,
350 if (!NT_SUCCESS(Status
))
352 DPRINT("Failed query open link %wZ\n",
356 DPRINT("Opened link: %wZ ==> %wZ\n",
357 &DriveName
, &DriveDeviceName
);
359 if (!RtlCompareUnicodeString (&ArcDeviceName
, &DriveDeviceName
, FALSE
))
361 DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i
, &BootPath
);
362 swprintf (SharedPage
->NtSystemRoot
,
363 L
"%C:%wZ", 'A' + i
, &BootPath
);
365 BootDriveFound
= TRUE
;
370 /* set bit in dos drives bitmap (drive available) */
371 SharedPage
->DosDeviceMap
|= (1<<i
);
374 RtlFreeUnicodeString (&BootPath
);
375 RtlFreeUnicodeString (&DriveDeviceName
);
376 RtlFreeUnicodeString (&ArcDeviceName
);
378 DPRINT("DosDeviceMap: 0x%x\n", SharedPage
->DosDeviceMap
);
380 if (BootDriveFound
== FALSE
)
382 DbgPrint("No system drive found!\n");
391 extern UCHAR OrigIVT
[1024];
392 KV86M_REGISTERS regs
;
394 struct vesa_info
* vi
;
396 for (i
= 0; i
< (640 / 4); i
++)
398 MmCreateVirtualMapping(NULL
,
400 PAGE_EXECUTE_READWRITE
,
401 (ULONG
)MmAllocPage(0));
403 for (; i
< (1024 / 4); i
++)
405 MmCreateVirtualMapping(NULL
,
410 vi
= (struct vesa_info
*)0x20000;
411 vi
->Signature
[0] = 'V';
412 vi
->Signature
[1] = 'B';
413 vi
->Signature
[2] = 'E';
414 vi
->Signature
[3] = '2';
415 memset(®s
, 0, sizeof(regs
));
419 memcpy((PVOID
)0x0, OrigIVT
, 1024);
420 Status
= Ke386CallBios(0x10, ®s
);
421 DbgPrint("Finished (Status %x, CS:EIP %x:%x)\n", Status
, regs
.Cs
,
423 DbgPrint("Eax %x\n", regs
.Eax
);
424 DbgPrint("Signature %.4s\n", vi
->Signature
);
425 DbgPrint("TotalVideoMemory %dKB\n", vi
->TotalVideoMemory
* 64);
430 ExpInitializeExecutive(VOID
)
433 * Initialization phase 0
435 HalInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
437 /* Execute executive initialization code on bootstrap processor only */
441 DPRINT("Phase 0 initialization started...\n");
444 * Fail at runtime if someone has changed various structures without
445 * updating the offsets used for the assembler code.
447 assert(FIELD_OFFSET(KTHREAD
, InitialStack
) == KTHREAD_INITIAL_STACK
);
448 assert(FIELD_OFFSET(KTHREAD
, Teb
) == KTHREAD_TEB
);
449 assert(FIELD_OFFSET(KTHREAD
, KernelStack
) == KTHREAD_KERNEL_STACK
);
450 assert(FIELD_OFFSET(KTHREAD
, PreviousMode
) == KTHREAD_PREVIOUS_MODE
);
451 assert(FIELD_OFFSET(KTHREAD
, TrapFrame
) == KTHREAD_TRAP_FRAME
);
452 assert(FIELD_OFFSET(ETHREAD
, ThreadsProcess
) == ETHREAD_THREADS_PROCESS
);
453 assert(FIELD_OFFSET(KPROCESS
, PageTableDirectory
) ==
454 KPROCESS_PAGE_TABLE_DIRECTORY
);
455 assert(FIELD_OFFSET(KTRAP_FRAME
, Reserved9
) == KTRAP_FRAME_RESERVED9
);
456 assert(FIELD_OFFSET(KV86M_TRAP_FRAME
, regs
) == TF_REGS
);
457 assert(FIELD_OFFSET(KV86M_TRAP_FRAME
, orig_ebp
) == TF_ORIG_EBP
);
459 assert(FIELD_OFFSET(KPCR
, ExceptionList
) == KPCR_EXCEPTION_LIST
);
460 assert(FIELD_OFFSET(KPCR
, Self
) == KPCR_SELF
);
461 assert(FIELD_OFFSET(KPCR
, CurrentThread
) == KPCR_CURRENT_THREAD
);
465 KeLowerIrql(DISPATCH_LEVEL
);
469 MmInit1(FirstKrnlPhysAddr
, LastKrnlPhysAddr
, LastKernelAddress
);
472 * Initialize the kernel debugger
474 KdInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
475 if (KdPollBreakIn ())
477 DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C
);
485 sprintf(tmpbuf
,"System with %d/%d MB memory\n",
486 (unsigned int)(KeLoaderBlock
.MemLower
)/1024,
487 (unsigned int)(KeLoaderBlock
.MemHigher
)/1024);
488 HalDisplayString(tmpbuf
);
491 KeLowerIrql(PASSIVE_LEVEL
);
494 PiInitProcessManager();
502 Phase1Initialization(NULL
);
508 KiSystemStartup(VOID
)
510 ExpInitializeExecutive();
518 /* Initialization phase 1 */
519 VOID
Phase1Initialization(PVOID Context
)
526 DPRINT("Initialization phase 1 started...\n");
529 * Display version number and copyright/warranty message
531 HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR
" (Build "
532 KERNEL_VERSION_BUILD_STR
")\n");
533 HalDisplayString(RES_STR_LEGAL_COPYRIGHT
);
534 HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
535 "Public License, and you\n");
536 HalDisplayString("are welcome to change it and/or distribute copies of it "
538 HalDisplayString("conditions. There is absolutely no warranty for ReactOS.\n");
540 /* Initialize all processors */
541 KeNumberProcessors
= 0;
543 while (!HalAllProcessorsStarted())
545 HalInitializeProcessor(
547 KeNumberProcessors
++;
550 if (KeNumberProcessors
> 1)
552 sprintf(str
, "Found %d system processors.\n",
557 strcpy(str
, "Found 1 system processor.\n");
559 HalDisplayString(str
);
563 DbgPrint("BSP halted\n");
569 * Initialize various critical subsystems
571 HalInitSystem (1, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
575 LdrInitModuleManagement();
576 CmInitializeRegistry();
580 /* Report all resources used by hal */
581 HalReportResourceUsage ();
584 * Enter the kernel debugger before starting up the boot drivers
591 * Initalize services loaded at boot time
593 DPRINT1("%d files loaded\n",KeLoaderBlock
.ModsCount
);
594 for (i
=0; i
< KeLoaderBlock
.ModsCount
; i
++)
596 DPRINT1("module: %s\n", KeLoaderModules
[i
].String
);
599 /* Pass 1: load registry chunks passed in */
600 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
602 start
= KeLoaderModules
[i
].ModStart
;
603 if (strcmp ((PCHAR
) start
, "REGEDIT4") == 0)
605 DPRINT1("process registry chunk at %08lx\n", start
);
606 CmImportHive((PCHAR
) start
);
610 /* Pass 2: process boot loaded drivers */
611 for (i
=1; i
< KeLoaderBlock
.ModsCount
; i
++)
613 start
= KeLoaderModules
[i
].ModStart
;
614 name
= (PCHAR
)KeLoaderModules
[i
].String
;
615 if (strcmp ((PCHAR
) start
, "REGEDIT4") != 0)
617 DPRINT1("process module '%s' at %08lx\n", name
, start
);
618 LdrProcessDriver((PVOID
)start
, name
);
622 DPRINT("About to try MmAllocateContiguousAlignedMemory\n");
626 MmAllocateContiguousAlignedMemory(IN ULONG NumberOfBytes
,
627 IN PHYSICAL_ADDRESS HighestAcceptableAddress
,
631 p
.QuadPart
= 16*1024*1024;
632 v
= MmAllocateContiguousAlignedMemory(12*1024, p
,
645 /* Create the SystemRoot symbolic link */
646 DbgPrint("CommandLine: %s\n", (PUCHAR
)KeLoaderBlock
.CommandLine
);
648 CreateSystemRootLink ((PUCHAR
)KeLoaderBlock
.CommandLine
);
650 #ifdef DBGPRINT_FILE_LOG
651 /* On the assumption that we can now access disks start up the debug
654 #endif /* DBGPRINT_FILE_LOG */
657 CmInitializeRegistry2();
660 * Load Auto configured drivers
662 LdrLoadAutoConfigDrivers();
665 * Assign drive letters
667 IoAssignDriveLetters ((PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
,
673 * Initialize shared user page:
674 * - set dos system path, dos device map, etc.
676 InitSystemSharedUserPage ((PUCHAR
)KeLoaderBlock
.CommandLine
);
679 * Launch initial process
681 LdrLoadInitialProcess();
683 DbgPrint("Finished kernel initialization.\n");
685 /* FIXME: Call zero page thread function */
686 PsTerminateSystemThread(STATUS_SUCCESS
);
690 _main (ULONG MultiBootMagic
, PLOADER_PARAMETER_BLOCK _LoaderBlock
)
692 * FUNCTION: Called by the boot loader to start the kernel
694 * LoaderBlock = Pointer to boot parameters initialized by the boot
696 * NOTE: The boot parameters are stored in low memory which will become
697 * invalid after the memory managment is initialized so we make a local copy.
701 ULONG last_kernel_address
;
702 extern ULONG _bss_end__
;
705 * Copy the parameters to a local buffer because lowmem will go away
707 memcpy (&KeLoaderBlock
, _LoaderBlock
, sizeof(LOADER_PARAMETER_BLOCK
));
708 memcpy (&KeLoaderModules
[1], (PVOID
)KeLoaderBlock
.ModsAddr
,
709 sizeof(LOADER_MODULE
) * KeLoaderBlock
.ModsCount
);
710 KeLoaderBlock
.ModsCount
++;
711 KeLoaderBlock
.ModsAddr
= (ULONG
)&KeLoaderModules
;
714 * FIXME: Preliminary hack!!!! Add boot device to beginning of command line.
715 * This should be done by the boot loader.
717 strcpy (KeLoaderCommandLine
,
718 "multi(0)disk(0)rdisk(0)partition(1)\\reactos /DEBUGPORT=SCREEN");
719 strcat (KeLoaderCommandLine
, (PUCHAR
)KeLoaderBlock
.CommandLine
);
721 KeLoaderBlock
.CommandLine
= (ULONG
)KeLoaderCommandLine
;
722 strcpy(KeLoaderModuleStrings
[0], "ntoskrnl.exe");
723 KeLoaderModules
[0].String
= (ULONG
)KeLoaderModuleStrings
[0];
724 KeLoaderModules
[0].ModStart
= 0xC0000000;
725 KeLoaderModules
[0].ModEnd
= PAGE_ROUND_UP((ULONG
)&_bss_end__
);
726 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
728 strcpy(KeLoaderModuleStrings
[i
], (PUCHAR
)KeLoaderModules
[i
].String
);
729 KeLoaderModules
[i
].ModStart
-= 0x200000;
730 KeLoaderModules
[i
].ModStart
+= 0xc0000000;
731 KeLoaderModules
[i
].ModEnd
-= 0x200000;
732 KeLoaderModules
[i
].ModEnd
+= 0xc0000000;
733 KeLoaderModules
[i
].String
= (ULONG
)KeLoaderModuleStrings
[i
];
736 last_kernel_address
= KeLoaderModules
[KeLoaderBlock
.ModsCount
- 1].ModEnd
;
738 FirstKrnlPhysAddr
= KeLoaderModules
[0].ModStart
- 0xc0000000 + 0x200000;
739 LastKrnlPhysAddr
= last_kernel_address
- 0xc0000000 + 0x200000;
740 LastKernelAddress
= last_kernel_address
;