1 /* $Id: main.c,v 1.69 2000/12/26 05:32:44 dwelch Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ke/main.c
6 * PURPOSE: Initalizes the kernel
7 * PROGRAMMER: David Welch (welch@cwcom.net)
12 /* INCLUDES *****************************************************************/
14 #include <ddk/ntddk.h>
15 #include <internal/ntoskrnl.h>
16 #include <reactos/buildno.h>
17 #include <internal/mm.h>
18 #include <internal/module.h>
19 #include <internal/ldr.h>
20 #include <internal/ex.h>
21 #include <internal/ps.h>
22 #include <internal/hal.h>
23 #include <internal/ke.h>
24 #include <internal/io.h>
25 #include <internal/mmhal.h>
26 #include <internal/i386/segment.h>
27 #include <napi/shared_data.h>
28 #include <internal/v86m.h>
31 #include <internal/debug.h>
33 /* GLOBALS *******************************************************************/
35 ULONG EXPORTED NtBuildNumber
= KERNEL_VERSION_BUILD
;
36 ULONG EXPORTED NtGlobalFlag
= 0;
37 CHAR EXPORTED KeNumberProcessors
= 1;
38 LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock
;
39 static LOADER_MODULE KeLoaderModules
[64];
40 static UCHAR KeLoaderModuleStrings
[64][256];
41 static UCHAR KeLoaderCommandLine
[256];
43 /* FUNCTIONS ****************************************************************/
46 CreateSystemRootLink (PCSZ ParameterLine
)
48 UNICODE_STRING LinkName
;
49 UNICODE_STRING DeviceName
;
50 UNICODE_STRING ArcName
;
51 UNICODE_STRING BootPath
;
57 OBJECT_ATTRIBUTES ObjectAttributes
;
60 /* create local parameter line copy */
61 ParamBuffer
= ExAllocatePool (PagedPool
, 256);
62 strcpy (ParamBuffer
, (char *)ParameterLine
);
64 DPRINT("%s\n", ParamBuffer
);
65 /* Format: <arc_name>\<path> [options...] */
68 p
= strchr (ParamBuffer
, ' ');
71 DPRINT("%s\n", ParamBuffer
);
74 p
= strchr (ParamBuffer
, '\\');
77 DPRINT("Boot path: %s\n", p
);
78 RtlCreateUnicodeStringFromAsciiz (&BootPath
, p
);
83 DPRINT("Boot path: %s\n", "\\");
84 RtlCreateUnicodeStringFromAsciiz (&BootPath
, "\\");
86 DPRINT("Arc name: %s\n", ParamBuffer
);
88 /* Only arc name left - build full arc name */
89 ArcNameBuffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
90 swprintf (ArcNameBuffer
,
91 L
"\\ArcName\\%S", ParamBuffer
);
92 RtlInitUnicodeString (&ArcName
, ArcNameBuffer
);
93 DPRINT("Arc name: %wZ\n", &ArcName
);
95 /* free ParamBuffer */
96 ExFreePool (ParamBuffer
);
98 /* allocate device name string */
99 DeviceName
.Length
= 0;
100 DeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
101 DeviceName
.Buffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
103 InitializeObjectAttributes (&ObjectAttributes
,
109 Status
= NtOpenSymbolicLinkObject (&Handle
,
110 SYMBOLIC_LINK_ALL_ACCESS
,
112 if (!NT_SUCCESS(Status
))
114 RtlFreeUnicodeString (&BootPath
);
115 RtlFreeUnicodeString (&DeviceName
);
116 DbgPrint("NtOpenSymbolicLinkObject() '%wZ' failed (Status %x)\n",
119 RtlFreeUnicodeString (&ArcName
);
123 RtlFreeUnicodeString (&ArcName
);
125 Status
= NtQuerySymbolicLinkObject (Handle
,
129 if (!NT_SUCCESS(Status
))
131 RtlFreeUnicodeString (&BootPath
);
132 RtlFreeUnicodeString (&DeviceName
);
133 DbgPrint("NtQuerySymbolicObject() failed (Status %x)\n",
138 DPRINT("Length: %lu DeviceName: %wZ\n", Length
, &DeviceName
);
140 RtlAppendUnicodeStringToString (&DeviceName
,
143 RtlFreeUnicodeString (&BootPath
);
144 DPRINT("DeviceName: %wZ\n", &DeviceName
);
146 /* create the '\SystemRoot' link */
147 RtlInitUnicodeString (&LinkName
,
150 Status
= IoCreateSymbolicLink (&LinkName
,
152 RtlFreeUnicodeString (&DeviceName
);
153 if (!NT_SUCCESS(Status
))
155 DbgPrint("IoCreateSymbolicLink() failed (Status %x)\n",
161 /* Check if '\SystemRoot'(LinkName) can be opened, otherwise crash it! */
162 InitializeObjectAttributes (&ObjectAttributes
,
168 Status
= NtOpenSymbolicLinkObject (&Handle
,
169 SYMBOLIC_LINK_ALL_ACCESS
,
171 if (!NT_SUCCESS(Status
))
173 DbgPrint("NtOpenSymbolicLinkObject() failed to open '\\SystemRoot' (Status %x)\n",
182 InitSystemSharedUserPage (PCSZ ParameterLine
)
184 PKUSER_SHARED_DATA SharedPage
;
186 UNICODE_STRING ArcDeviceName
;
187 UNICODE_STRING ArcName
;
188 UNICODE_STRING BootPath
;
189 UNICODE_STRING DriveDeviceName
;
190 UNICODE_STRING DriveName
;
191 WCHAR DriveNameBuffer
[20];
193 PWCHAR ArcNameBuffer
;
197 OBJECT_ATTRIBUTES ObjectAttributes
;
200 BOOLEAN BootDriveFound
;
202 SharedPage
= (PKUSER_SHARED_DATA
)KERNEL_SHARED_DATA_BASE
;
203 SharedPage
->DosDeviceMap
= 0;
204 SharedPage
->NtProductType
= NtProductWinNt
;
205 for (i
= 0; i
< 32; i
++)
207 SharedPage
->DosDeviceDriveType
[i
] = 0;
210 BootDriveFound
= FALSE
;
213 * Retrieve the current dos system path
214 * (e.g.: C:\reactos) from the given arc path
215 * (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos)
216 * Format: "<arc_name>\<path> [options...]"
219 /* create local parameter line copy */
220 ParamBuffer
= ExAllocatePool (PagedPool
, 256);
221 strcpy (ParamBuffer
, (char *)ParameterLine
);
222 DPRINT("%s\n", ParamBuffer
);
224 /* cut options off */
225 p
= strchr (ParamBuffer
, ' ');
230 DPRINT("%s\n", ParamBuffer
);
233 p
= strchr (ParamBuffer
, '\\');
236 DPRINT("Boot path: %s\n", p
);
237 RtlCreateUnicodeStringFromAsciiz (&BootPath
, p
);
242 DPRINT("Boot path: %s\n", "\\");
243 RtlCreateUnicodeStringFromAsciiz (&BootPath
, "\\");
245 DPRINT("Arc name: %s\n", ParamBuffer
);
247 /* Only arc name left - build full arc name */
248 ArcNameBuffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
249 swprintf (ArcNameBuffer
, L
"\\ArcName\\%S", ParamBuffer
);
250 RtlInitUnicodeString (&ArcName
, ArcNameBuffer
);
251 DPRINT("Arc name: %wZ\n", &ArcName
);
253 /* free ParamBuffer */
254 ExFreePool (ParamBuffer
);
256 /* allocate arc device name string */
257 ArcDeviceName
.Length
= 0;
258 ArcDeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
259 ArcDeviceName
.Buffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
261 InitializeObjectAttributes (&ObjectAttributes
,
267 Status
= NtOpenSymbolicLinkObject (&Handle
,
268 SYMBOLIC_LINK_ALL_ACCESS
,
270 RtlFreeUnicodeString (&ArcName
);
271 if (!NT_SUCCESS(Status
))
273 RtlFreeUnicodeString (&BootPath
);
274 RtlFreeUnicodeString (&ArcDeviceName
);
275 DbgPrint("NtOpenSymbolicLinkObject() failed (Status %x)\n",
281 Status
= NtQuerySymbolicLinkObject (Handle
,
285 if (!NT_SUCCESS(Status
))
287 RtlFreeUnicodeString (&BootPath
);
288 RtlFreeUnicodeString (&ArcDeviceName
);
289 DbgPrint("NtQuerySymbolicObject() failed (Status %x)\n",
294 DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length
, &ArcDeviceName
);
297 /* allocate device name string */
298 DriveDeviceName
.Length
= 0;
299 DriveDeviceName
.MaximumLength
= 256 * sizeof(WCHAR
);
300 DriveDeviceName
.Buffer
= ExAllocatePool (PagedPool
, 256 * sizeof(WCHAR
));
302 for (i
= 0; i
< 26; i
++)
304 swprintf (DriveNameBuffer
, L
"\\??\\%C:", 'A' + i
);
305 RtlInitUnicodeString (&DriveName
,
308 InitializeObjectAttributes (&ObjectAttributes
,
314 Status
= NtOpenSymbolicLinkObject (&Handle
,
315 SYMBOLIC_LINK_ALL_ACCESS
,
317 if (!NT_SUCCESS(Status
))
319 DPRINT("Failed to open link %wZ\n",
324 Status
= NtQuerySymbolicLinkObject (Handle
,
327 if (!NT_SUCCESS(Status
))
329 DPRINT("Failed query open link %wZ\n",
333 DPRINT("Opened link: %wZ ==> %wZ\n",
334 &DriveName
, &DriveDeviceName
);
336 if (!RtlCompareUnicodeString (&ArcDeviceName
, &DriveDeviceName
, FALSE
))
338 DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i
, &BootPath
);
339 swprintf (SharedPage
->NtSystemRoot
,
340 L
"%C:%wZ", 'A' + i
, &BootPath
);
342 BootDriveFound
= TRUE
;
347 /* set bit in dos drives bitmap (drive available) */
348 SharedPage
->DosDeviceMap
|= (1<<i
);
351 RtlFreeUnicodeString (&BootPath
);
352 RtlFreeUnicodeString (&DriveDeviceName
);
353 RtlFreeUnicodeString (&ArcDeviceName
);
355 DPRINT("DosDeviceMap: 0x%x\n", SharedPage
->DosDeviceMap
);
357 if (BootDriveFound
== FALSE
)
359 DbgPrint("No system drive found!\n");
364 extern NTSTATUS STDCALL
365 Ke386CallBios(UCHAR Int
, KV86M_REGISTERS
* Regs
);
367 struct __attribute__((packed
)) vesa_info
373 ULONG SupportedModes
;
374 USHORT TotalVideoMemory
;
378 ULONG ProductRevisionString
;
386 extern UCHAR OrigIVT
[1024];
387 KV86M_REGISTERS regs
;
389 struct vesa_info
* vi
;
391 for (i
= 0; i
< (640 / 4); i
++)
393 MmCreateVirtualMapping(NULL
,
395 PAGE_EXECUTE_READWRITE
,
396 (ULONG
)MmAllocPage(0));
398 for (; i
< (1024 / 4); i
++)
400 MmCreateVirtualMapping(NULL
,
405 vi
= (struct vesa_info
*)0x20000;
406 vi
->Signature
[0] = 'V';
407 vi
->Signature
[1] = 'B';
408 vi
->Signature
[2] = 'E';
409 vi
->Signature
[3] = '2';
410 memset(®s
, 0, sizeof(regs
));
414 memcpy((PVOID
)0x0, OrigIVT
, 1024);
415 Status
= Ke386CallBios(0x10, ®s
);
416 DbgPrint("Finished (Status %x, CS:EIP %x:%x)\n", Status
, regs
.Cs
,
418 DbgPrint("Eax %x\n", regs
.Eax
);
419 DbgPrint("Signature %.4s\n", vi
->Signature
);
420 DbgPrint("TotalVideoMemory %dKB\n", vi
->TotalVideoMemory
* 64);
424 _main (ULONG MultiBootMagic
, PLOADER_PARAMETER_BLOCK _LoaderBlock
)
426 * FUNCTION: Called by the boot loader to start the kernel
428 * LoaderBlock = Pointer to boot parameters initialized by the boot
430 * NOTE: The boot parameters are stored in low memory which will become
431 * invalid after the memory managment is initialized so we make a local copy.
435 ULONG last_kernel_address
;
439 * Copy the parameters to a local buffer because lowmem will go away
441 memcpy (&KeLoaderBlock
, _LoaderBlock
, sizeof(LOADER_PARAMETER_BLOCK
));
442 memcpy (&KeLoaderModules
, (PVOID
)KeLoaderBlock
.ModsAddr
,
443 sizeof(LOADER_MODULE
) * KeLoaderBlock
.ModsCount
);
444 KeLoaderBlock
.ModsAddr
= (ULONG
)&KeLoaderModules
;
445 strcpy (KeLoaderCommandLine
, (PUCHAR
)KeLoaderBlock
.CommandLine
);
446 KeLoaderBlock
.CommandLine
= (ULONG
)KeLoaderCommandLine
;
447 for (i
= 0; i
< KeLoaderBlock
.ModsCount
; i
++)
449 strcpy(KeLoaderModuleStrings
[i
], (PUCHAR
)KeLoaderModules
[i
].String
);
450 KeLoaderModules
[i
].ModStart
-= 0x200000;
451 KeLoaderModules
[i
].ModStart
+= 0xc0000000;
452 KeLoaderModules
[i
].ModEnd
-= 0x200000;
453 KeLoaderModules
[i
].ModEnd
+= 0xc0000000;
454 KeLoaderModules
[i
].String
= (ULONG
)KeLoaderModuleStrings
[i
];
459 * FIXME: Preliminary hack!!!!
460 * Initializes the kernel parameter line.
461 * This should be done by the boot loader.
463 strcpy ((PUCHAR
)KeLoaderBlock
.CommandLine
,
464 "multi(0)disk(0)rdisk(0)partition(1)\\reactos /DEBUGPORT=SCREEN");
467 * Initialization phase 0
469 HalInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
471 KeLowerIrql(DISPATCH_LEVEL
);
475 sprintf(tmpbuf
,"system with %d MB extended memory\n",
476 (unsigned int)(KeLoaderBlock
.MemLower
)/1024);
477 HalDisplayString(tmpbuf
);
481 * Display version number and copyright/warranty message
483 HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR
" (Build "
484 KERNEL_VERSION_BUILD_STR
")\n");
485 HalDisplayString("Copyright 2000 (So who owns the copyright?).\n");
486 HalDisplayString("ReactOS is free software, covered by the GNU General "
487 "Public License, and you\n");
488 HalDisplayString("are welcome to change it and/or distribute copies of it "
490 HalDisplayString("conditions.\n");
491 HalDisplayString("There is absolutely no warranty for ReactOS.\n");
493 last_kernel_address
= KeLoaderModules
[KeLoaderBlock
.ModsCount
- 1].ModEnd
;
496 MmInit1(KeLoaderModules
[0].ModStart
- 0xc0000000 + 0x200000,
497 last_kernel_address
- 0xc0000000 + 0x200000,
498 last_kernel_address
);
501 * Initialize the kernel debugger
503 KdInitSystem (0, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
504 if (KdPollBreakIn ())
506 DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C
);
510 * Initialization phase 1
511 * Initalize various critical subsystems
513 HalInitSystem (1, (PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
);
520 KeLowerIrql(PASSIVE_LEVEL
);
523 PiInitProcessManager();
526 LdrInitModuleManagement();
527 CmInitializeRegistry();
531 /* Report all resources used by hal */
532 HalReportResourceUsage ();
535 * Initalize services loaded at boot time
537 DPRINT1("%d files loaded\n",KeLoaderBlock
.ModsCount
);
539 /* Pass 1: load registry chunks passed in */
540 for (i
= 1; i
< KeLoaderBlock
.ModsCount
; i
++)
542 start
= KeLoaderModules
[i
].ModStart
;
543 if (strcmp ((PCHAR
) start
, "REGEDIT4") == 0)
545 DPRINT1("process registry chunk at %08lx\n", start
);
546 CmImportHive((PCHAR
) start
);
550 /* Pass 2: process boot loaded drivers */
551 for (i
=1; i
< KeLoaderBlock
.ModsCount
; i
++)
553 start
= KeLoaderModules
[i
].ModStart
;
554 if (strcmp ((PCHAR
) start
, "REGEDIT4") != 0)
556 DPRINT1("process module at %08lx\n", start
);
557 LdrProcessDriver((PVOID
)start
);
561 /* Create the SystemRoot symbolic link */
562 CreateSystemRootLink ((PUCHAR
)KeLoaderBlock
.CommandLine
);
564 CmInitializeRegistry2();
567 * Load Auto configured drivers
569 LdrLoadAutoConfigDrivers();
572 * Assign drive letters
574 IoAssignDriveLetters ((PLOADER_PARAMETER_BLOCK
)&KeLoaderBlock
,
580 * Initialize shared user page:
581 * - set dos system path, dos device map, etc.
583 InitSystemSharedUserPage ((PUCHAR
)KeLoaderBlock
.CommandLine
);
586 * Launch initial process
589 LdrLoadInitialProcess();
594 DbgPrint("Finished main()\n");
595 PsTerminateSystemThread(STATUS_SUCCESS
);