Correct problem with keyboard input not being accepted
[reactos.git] / reactos / ntoskrnl / ke / main.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
19 /* $Id: main.c,v 1.86 2001/04/10 17:48:17 dwelch Exp $
20 *
21 * PROJECT: ReactOS kernel
22 * FILE: ntoskrnl/ke/main.c
23 * PURPOSE: Initalizes the kernel
24 * PROGRAMMER: David Welch (welch@cwcom.net)
25 * UPDATE HISTORY:
26 * 28/05/98: Created
27 */
28
29 /* INCLUDES *****************************************************************/
30
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"
47
48 #define NDEBUG
49 #include <internal/debug.h>
50
51 /* GLOBALS *******************************************************************/
52
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];
60
61 /* FUNCTIONS ****************************************************************/
62
63 static VOID
64 CreateSystemRootLink (PCSZ ParameterLine)
65 {
66 UNICODE_STRING LinkName;
67 UNICODE_STRING DeviceName;
68 UNICODE_STRING ArcName;
69 UNICODE_STRING BootPath;
70 PCHAR ParamBuffer;
71 PWCHAR ArcNameBuffer;
72 PCHAR p;
73 NTSTATUS Status;
74 ULONG Length;
75 OBJECT_ATTRIBUTES ObjectAttributes;
76 HANDLE Handle;
77
78 /* create local parameter line copy */
79 ParamBuffer = ExAllocatePool (PagedPool, 256);
80 strcpy (ParamBuffer, (char *)ParameterLine);
81
82 DPRINT("%s\n", ParamBuffer);
83 /* Format: <arc_name>\<path> [options...] */
84
85 /* cut options off */
86 p = strchr (ParamBuffer, ' ');
87 if (p)
88 *p = 0;
89 DPRINT("%s\n", ParamBuffer);
90
91 /* extract path */
92 p = strchr (ParamBuffer, '\\');
93 if (p)
94 {
95 DPRINT("Boot path: %s\n", p);
96 RtlCreateUnicodeStringFromAsciiz (&BootPath, p);
97 *p = 0;
98 }
99 else
100 {
101 DPRINT("Boot path: %s\n", "\\");
102 RtlCreateUnicodeStringFromAsciiz (&BootPath, "\\");
103 }
104 DPRINT("Arc name: %s\n", ParamBuffer);
105
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);
112
113 /* free ParamBuffer */
114 ExFreePool (ParamBuffer);
115
116 /* allocate device name string */
117 DeviceName.Length = 0;
118 DeviceName.MaximumLength = 256 * sizeof(WCHAR);
119 DeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
120
121 InitializeObjectAttributes (&ObjectAttributes,
122 &ArcName,
123 0,
124 NULL,
125 NULL);
126
127 Status = NtOpenSymbolicLinkObject (&Handle,
128 SYMBOLIC_LINK_ALL_ACCESS,
129 &ObjectAttributes);
130 if (!NT_SUCCESS(Status))
131 {
132 RtlFreeUnicodeString (&BootPath);
133 RtlFreeUnicodeString (&DeviceName);
134 DbgPrint("NtOpenSymbolicLinkObject() '%wZ' failed (Status %x)\n",
135 &ArcName,
136 Status);
137 RtlFreeUnicodeString (&ArcName);
138
139 KeBugCheck (0x0);
140 }
141 RtlFreeUnicodeString (&ArcName);
142
143 Status = NtQuerySymbolicLinkObject (Handle,
144 &DeviceName,
145 &Length);
146 NtClose (Handle);
147 if (!NT_SUCCESS(Status))
148 {
149 RtlFreeUnicodeString (&BootPath);
150 RtlFreeUnicodeString (&DeviceName);
151 DbgPrint("NtQuerySymbolicObject() failed (Status %x)\n",
152 Status);
153
154 KeBugCheck (0x0);
155 }
156 DPRINT("Length: %lu DeviceName: %wZ\n", Length, &DeviceName);
157
158 RtlAppendUnicodeStringToString (&DeviceName,
159 &BootPath);
160
161 RtlFreeUnicodeString (&BootPath);
162 DPRINT("DeviceName: %wZ\n", &DeviceName);
163
164 /* create the '\SystemRoot' link */
165 RtlInitUnicodeString (&LinkName,
166 L"\\SystemRoot");
167
168 Status = IoCreateSymbolicLink (&LinkName,
169 &DeviceName);
170 RtlFreeUnicodeString (&DeviceName);
171 if (!NT_SUCCESS(Status))
172 {
173 DbgPrint("IoCreateSymbolicLink() failed (Status %x)\n",
174 Status);
175
176 KeBugCheck (0x0);
177 }
178
179 /* Check if '\SystemRoot'(LinkName) can be opened, otherwise crash it! */
180 InitializeObjectAttributes (&ObjectAttributes,
181 &LinkName,
182 0,
183 NULL,
184 NULL);
185
186 Status = NtOpenSymbolicLinkObject (&Handle,
187 SYMBOLIC_LINK_ALL_ACCESS,
188 &ObjectAttributes);
189 if (!NT_SUCCESS(Status))
190 {
191 DbgPrint("NtOpenSymbolicLinkObject() failed to open '\\SystemRoot' (Status %x)\n",
192 Status);
193 KeBugCheck (0x0);
194 }
195 NtClose(Handle);
196 }
197
198
199 static VOID
200 InitSystemSharedUserPage (PCSZ ParameterLine)
201 {
202 PKUSER_SHARED_DATA SharedPage;
203
204 UNICODE_STRING ArcDeviceName;
205 UNICODE_STRING ArcName;
206 UNICODE_STRING BootPath;
207 UNICODE_STRING DriveDeviceName;
208 UNICODE_STRING DriveName;
209 WCHAR DriveNameBuffer[20];
210 PCHAR ParamBuffer;
211 PWCHAR ArcNameBuffer;
212 PCHAR p;
213 NTSTATUS Status;
214 ULONG Length;
215 OBJECT_ATTRIBUTES ObjectAttributes;
216 HANDLE Handle;
217 ULONG i;
218 BOOLEAN BootDriveFound;
219
220 SharedPage = (PKUSER_SHARED_DATA)KERNEL_SHARED_DATA_BASE;
221 SharedPage->DosDeviceMap = 0;
222 SharedPage->NtProductType = NtProductWinNt;
223 for (i = 0; i < 32; i++)
224 {
225 SharedPage->DosDeviceDriveType[i] = 0;
226 }
227
228 BootDriveFound = FALSE;
229
230 /*
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...]"
235 */
236
237 /* create local parameter line copy */
238 ParamBuffer = ExAllocatePool (PagedPool, 256);
239 strcpy (ParamBuffer, (char *)ParameterLine);
240 DPRINT("%s\n", ParamBuffer);
241
242 /* cut options off */
243 p = strchr (ParamBuffer, ' ');
244 if (p)
245 {
246 *p = 0;
247 }
248 DPRINT("%s\n", ParamBuffer);
249
250 /* extract path */
251 p = strchr (ParamBuffer, '\\');
252 if (p)
253 {
254 DPRINT("Boot path: %s\n", p);
255 RtlCreateUnicodeStringFromAsciiz (&BootPath, p);
256 *p = 0;
257 }
258 else
259 {
260 DPRINT("Boot path: %s\n", "\\");
261 RtlCreateUnicodeStringFromAsciiz (&BootPath, "\\");
262 }
263 DPRINT("Arc name: %s\n", ParamBuffer);
264
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);
270
271 /* free ParamBuffer */
272 ExFreePool (ParamBuffer);
273
274 /* allocate arc device name string */
275 ArcDeviceName.Length = 0;
276 ArcDeviceName.MaximumLength = 256 * sizeof(WCHAR);
277 ArcDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
278
279 InitializeObjectAttributes (&ObjectAttributes,
280 &ArcName,
281 0,
282 NULL,
283 NULL);
284
285 Status = NtOpenSymbolicLinkObject (&Handle,
286 SYMBOLIC_LINK_ALL_ACCESS,
287 &ObjectAttributes);
288 RtlFreeUnicodeString (&ArcName);
289 if (!NT_SUCCESS(Status))
290 {
291 RtlFreeUnicodeString (&BootPath);
292 RtlFreeUnicodeString (&ArcDeviceName);
293 DbgPrint("NtOpenSymbolicLinkObject() failed (Status %x)\n",
294 Status);
295
296 KeBugCheck (0x0);
297 }
298
299 Status = NtQuerySymbolicLinkObject (Handle,
300 &ArcDeviceName,
301 &Length);
302 NtClose (Handle);
303 if (!NT_SUCCESS(Status))
304 {
305 RtlFreeUnicodeString (&BootPath);
306 RtlFreeUnicodeString (&ArcDeviceName);
307 DbgPrint("NtQuerySymbolicObject() failed (Status %x)\n",
308 Status);
309
310 KeBugCheck (0x0);
311 }
312 DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length, &ArcDeviceName);
313
314
315 /* allocate device name string */
316 DriveDeviceName.Length = 0;
317 DriveDeviceName.MaximumLength = 256 * sizeof(WCHAR);
318 DriveDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
319
320 for (i = 0; i < 26; i++)
321 {
322 swprintf (DriveNameBuffer, L"\\??\\%C:", 'A' + i);
323 RtlInitUnicodeString (&DriveName,
324 DriveNameBuffer);
325
326 InitializeObjectAttributes (&ObjectAttributes,
327 &DriveName,
328 0,
329 NULL,
330 NULL);
331
332 Status = NtOpenSymbolicLinkObject (&Handle,
333 SYMBOLIC_LINK_ALL_ACCESS,
334 &ObjectAttributes);
335 if (!NT_SUCCESS(Status))
336 {
337 DPRINT("Failed to open link %wZ\n",
338 &DriveName);
339 continue;
340 }
341
342 Status = NtQuerySymbolicLinkObject (Handle,
343 &DriveDeviceName,
344 &Length);
345 if (!NT_SUCCESS(Status))
346 {
347 DPRINT("Failed query open link %wZ\n",
348 &DriveName);
349 continue;
350 }
351 DPRINT("Opened link: %wZ ==> %wZ\n",
352 &DriveName, &DriveDeviceName);
353
354 if (!RtlCompareUnicodeString (&ArcDeviceName, &DriveDeviceName, FALSE))
355 {
356 DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i, &BootPath);
357 swprintf (SharedPage->NtSystemRoot,
358 L"%C:%wZ", 'A' + i, &BootPath);
359
360 BootDriveFound = TRUE;
361 }
362
363 NtClose (Handle);
364
365 /* set bit in dos drives bitmap (drive available) */
366 SharedPage->DosDeviceMap |= (1<<i);
367 }
368
369 RtlFreeUnicodeString (&BootPath);
370 RtlFreeUnicodeString (&DriveDeviceName);
371 RtlFreeUnicodeString (&ArcDeviceName);
372
373 DPRINT("DosDeviceMap: 0x%x\n", SharedPage->DosDeviceMap);
374
375 if (BootDriveFound == FALSE)
376 {
377 DbgPrint("No system drive found!\n");
378 KeBugCheck (0x0);
379 }
380 }
381
382 VOID
383 _main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock)
384 /*
385 * FUNCTION: Called by the boot loader to start the kernel
386 * ARGUMENTS:
387 * LoaderBlock = Pointer to boot parameters initialized by the boot
388 * loader
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.
391 */
392 {
393 ULONG i;
394 ULONG last_kernel_address;
395 ULONG start;
396 PCHAR name;
397 extern ULONG _bss_end__;
398
399 /*
400 * Copy the parameters to a local buffer because lowmem will go away
401 */
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;
407
408 /*
409 * FIXME: Preliminary hack!!!! Add boot device to beginning of command line.
410 * This should be done by the boot loader.
411 */
412 strcpy (KeLoaderCommandLine,
413 "multi(0)disk(0)rdisk(0)partition(1)\\reactos ");
414 strcat (KeLoaderCommandLine, (PUCHAR)KeLoaderBlock.CommandLine);
415
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++)
422 {
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];
429 }
430
431 /*
432 * Initialization phase 0
433 */
434 HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
435 KeInit1();
436 LdrInit1();
437 KeLowerIrql(DISPATCH_LEVEL);
438
439 /*
440 * Display version number and copyright/warranty message
441 */
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 "
448 "under certain\n");
449 HalDisplayString("conditions. There is absolutely no warranty for ReactOS.\n");
450
451 /*
452 * Fail at runtime if someone has changed various structures without
453 * updating the offsets used for the assembler code
454 */
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);
466
467 last_kernel_address = KeLoaderModules[KeLoaderBlock.ModsCount - 1].ModEnd;
468
469 NtEarlyInitVdm();
470 MmInit1(KeLoaderModules[0].ModStart - 0xc0000000 + 0x200000,
471 last_kernel_address - 0xc0000000 + 0x200000,
472 last_kernel_address);
473
474 /*
475 * Initialize the kernel debugger
476 */
477 KdInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
478 if (KdPollBreakIn ())
479 {
480 DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
481 }
482
483 /*
484 * Initialization phase 1
485 * Initalize various critical subsystems
486 */
487 HalInitSystem (1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
488 MmInit2();
489 KeInit2();
490
491 /*
492 * Allow interrupts
493 */
494 KeLowerIrql(PASSIVE_LEVEL);
495
496 ObInit();
497 PiInitProcessManager();
498 ExInit();
499 IoInit();
500 LdrInitModuleManagement();
501 CmInitializeRegistry();
502 NtInit();
503 MmInit3();
504
505 /* Report all resources used by hal */
506 HalReportResourceUsage ();
507
508 /*
509 * Enter the kernel debugger before starting up the boot drivers
510 */
511 #ifdef KDBG
512 KdbEnter();
513 #endif /* KDBG */
514
515 /*
516 * Initalize services loaded at boot time
517 */
518 DPRINT1("%d files loaded\n",KeLoaderBlock.ModsCount);
519 for (i=0; i < KeLoaderBlock.ModsCount; i++)
520 {
521 DPRINT1("module: %s\n", KeLoaderModules[i].String);
522 }
523
524 /* Pass 1: load registry chunks passed in */
525 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
526 {
527 start = KeLoaderModules[i].ModStart;
528 if (strcmp ((PCHAR) start, "REGEDIT4") == 0)
529 {
530 DPRINT1("process registry chunk at %08lx\n", start);
531 CmImportHive((PCHAR) start);
532 }
533 }
534
535 /* Pass 2: process boot loaded drivers */
536 for (i=1; i < KeLoaderBlock.ModsCount; i++)
537 {
538 start = KeLoaderModules[i].ModStart;
539 name = (PCHAR)KeLoaderModules[i].String;
540 if (strcmp ((PCHAR) start, "REGEDIT4") != 0)
541 {
542 DPRINT1("process module '%s' at %08lx\n", name, start);
543 LdrProcessDriver((PVOID)start, name);
544 }
545 }
546
547 /* Create the SystemRoot symbolic link */
548 DbgPrint("CommandLine: %s\n", (PUCHAR)KeLoaderBlock.CommandLine);
549 CreateSystemRootLink ((PUCHAR)KeLoaderBlock.CommandLine);
550
551 #ifdef DBGPRINT_FILE_LOG
552 /* On the assumption that we can now access disks start up the debug
553 logger thread */
554 DebugLogInit2();
555 #endif /* DBGPRINT_FILE_LOG */
556
557 CmInitializeRegistry2();
558
559 /*
560 * Load Auto configured drivers
561 */
562 LdrLoadAutoConfigDrivers();
563
564 /*
565 * Assign drive letters
566 */
567 IoAssignDriveLetters ((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock,
568 NULL,
569 NULL,
570 NULL);
571
572 /*
573 * Initialize shared user page:
574 * - set dos system path, dos device map, etc.
575 */
576 InitSystemSharedUserPage ((PUCHAR)KeLoaderBlock.CommandLine);
577
578 /*
579 * Launch initial process
580 */
581 LdrLoadInitialProcess();
582
583 DbgPrint("Finished main()\n");
584 PsTerminateSystemThread(STATUS_SUCCESS);
585 }
586
587 /* EOF */
588