Support for VMWare NIC, and some general clean-up and other minor changes:
[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.173 2003/10/12 16:39:52 vizzini 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 #define NTOS_MODE_KERNEL
32 #include <ntos.h>
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/registry.h>
51 #include <internal/nls.h>
52 #include <reactos/bugcodes.h>
53 #include <ntos/bootvid.h>
54 #include <napi/core.h>
55
56 #ifdef HALDBG
57 #include <internal/ntosdbg.h>
58 #else
59 #define ps(args...)
60 #endif
61
62 #define NDEBUG
63 #include <internal/debug.h>
64
65 /* GLOBALS *******************************************************************/
66
67 ULONG EXPORTED NtBuildNumber = KERNEL_VERSION_BUILD;
68 ULONG EXPORTED NtGlobalFlag = 0;
69 CHAR EXPORTED KeNumberProcessors;
70 LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock;
71 ULONG EXPORTED KeDcacheFlushCount = 0;
72 ULONG EXPORTED KeIcacheFlushCount = 0;
73 static LOADER_MODULE KeLoaderModules[64];
74 static UCHAR KeLoaderModuleStrings[64][256];
75 static UCHAR KeLoaderCommandLine[256];
76 static ADDRESS_RANGE KeMemoryMap[64];
77 static ULONG KeMemoryMapRangeCount;
78 static ULONG FirstKrnlPhysAddr;
79 static ULONG LastKrnlPhysAddr;
80 static ULONG LastKernelAddress;
81 volatile BOOLEAN Initialized = FALSE;
82 extern ULONG MmCoreDumpType;
83
84 extern PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS];
85
86
87 /* FUNCTIONS ****************************************************************/
88
89 static BOOLEAN
90 RtlpCheckFileNameExtension(PCHAR FileName,
91 PCHAR Extension)
92 {
93 PCHAR Ext;
94
95 Ext = strrchr(FileName, '.');
96 if (Ext == NULL)
97 {
98 if ((Extension == NULL) || (*Extension == 0))
99 return TRUE;
100 else
101 return FALSE;
102 }
103
104 if (*Extension != '.')
105 Ext++;
106
107 if (_stricmp(Ext, Extension) == 0)
108 return TRUE;
109 else
110 return FALSE;
111 }
112
113
114 static VOID
115 InitSystemSharedUserPage (PCSZ ParameterLine)
116 {
117 UNICODE_STRING ArcDeviceName;
118 UNICODE_STRING ArcName;
119 UNICODE_STRING BootPath;
120 UNICODE_STRING DriveDeviceName;
121 UNICODE_STRING DriveName;
122 WCHAR DriveNameBuffer[20];
123 PCHAR ParamBuffer;
124 PWCHAR ArcNameBuffer;
125 PCHAR p;
126 NTSTATUS Status;
127 ULONG Length;
128 OBJECT_ATTRIBUTES ObjectAttributes;
129 HANDLE Handle;
130 ULONG i;
131 BOOLEAN BootDriveFound;
132
133 /*
134 * NOTE:
135 * The shared user page has been zeroed-out right after creation.
136 * There is NO need to do this again.
137 */
138
139 SharedUserData->NtProductType = NtProductWinNt;
140
141 BootDriveFound = FALSE;
142
143 /*
144 * Retrieve the current dos system path
145 * (e.g.: C:\reactos) from the given arc path
146 * (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos)
147 * Format: "<arc_name>\<path> [options...]"
148 */
149
150 /* create local parameter line copy */
151 ParamBuffer = ExAllocatePool (PagedPool, 256);
152 strcpy (ParamBuffer, (char *)ParameterLine);
153 DPRINT("%s\n", ParamBuffer);
154
155 /* cut options off */
156 p = strchr (ParamBuffer, ' ');
157 if (p)
158 {
159 *p = 0;
160 }
161 DPRINT("%s\n", ParamBuffer);
162
163 /* extract path */
164 p = strchr (ParamBuffer, '\\');
165 if (p)
166 {
167 DPRINT("Boot path: %s\n", p);
168 RtlCreateUnicodeStringFromAsciiz (&BootPath, p);
169 *p = 0;
170 }
171 else
172 {
173 DPRINT("Boot path: %s\n", "\\");
174 RtlCreateUnicodeStringFromAsciiz (&BootPath, "\\");
175 }
176 DPRINT("Arc name: %s\n", ParamBuffer);
177
178 /* Only arc name left - build full arc name */
179 ArcNameBuffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
180 swprintf (ArcNameBuffer, L"\\ArcName\\%S", ParamBuffer);
181 RtlInitUnicodeString (&ArcName, ArcNameBuffer);
182 DPRINT("Arc name: %wZ\n", &ArcName);
183
184 /* free ParamBuffer */
185 ExFreePool (ParamBuffer);
186
187 /* allocate arc device name string */
188 ArcDeviceName.Length = 0;
189 ArcDeviceName.MaximumLength = 256 * sizeof(WCHAR);
190 ArcDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
191
192 InitializeObjectAttributes (&ObjectAttributes,
193 &ArcName,
194 OBJ_OPENLINK,
195 NULL,
196 NULL);
197
198 Status = NtOpenSymbolicLinkObject (&Handle,
199 SYMBOLIC_LINK_ALL_ACCESS,
200 &ObjectAttributes);
201 RtlFreeUnicodeString (&ArcName);
202 if (!NT_SUCCESS(Status))
203 {
204 RtlFreeUnicodeString (&BootPath);
205 RtlFreeUnicodeString (&ArcDeviceName);
206 CPRINT("NtOpenSymbolicLinkObject() failed (Status %x)\n",
207 Status);
208
209 KEBUGCHECK (0x0);
210 }
211
212 Status = NtQuerySymbolicLinkObject (Handle,
213 &ArcDeviceName,
214 &Length);
215 NtClose (Handle);
216 if (!NT_SUCCESS(Status))
217 {
218 RtlFreeUnicodeString (&BootPath);
219 RtlFreeUnicodeString (&ArcDeviceName);
220 CPRINT("NtQuerySymbolicObject() failed (Status %x)\n",
221 Status);
222
223 KEBUGCHECK (0x0);
224 }
225 DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length, &ArcDeviceName);
226
227
228 /* allocate device name string */
229 DriveDeviceName.Length = 0;
230 DriveDeviceName.MaximumLength = 256 * sizeof(WCHAR);
231 DriveDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
232
233 for (i = 0; i < 26; i++)
234 {
235 swprintf (DriveNameBuffer, L"\\??\\%C:", 'A' + i);
236 RtlInitUnicodeString (&DriveName,
237 DriveNameBuffer);
238
239 InitializeObjectAttributes (&ObjectAttributes,
240 &DriveName,
241 OBJ_OPENLINK,
242 NULL,
243 NULL);
244
245 Status = NtOpenSymbolicLinkObject (&Handle,
246 SYMBOLIC_LINK_ALL_ACCESS,
247 &ObjectAttributes);
248 if (!NT_SUCCESS(Status))
249 {
250 DPRINT("Failed to open link %wZ\n",
251 &DriveName);
252 continue;
253 }
254
255 Status = NtQuerySymbolicLinkObject (Handle,
256 &DriveDeviceName,
257 &Length);
258 if (!NT_SUCCESS(Status))
259 {
260 DPRINT("Failed query open link %wZ\n",
261 &DriveName);
262 continue;
263 }
264 DPRINT("Opened link: %wZ ==> %wZ\n",
265 &DriveName, &DriveDeviceName);
266
267 if (!RtlCompareUnicodeString (&ArcDeviceName, &DriveDeviceName, FALSE))
268 {
269 DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i, &BootPath);
270 swprintf(SharedUserData->NtSystemRoot,
271 L"%C:%wZ", 'A' + i, &BootPath);
272
273 BootDriveFound = TRUE;
274 }
275
276 NtClose (Handle);
277 }
278
279 RtlFreeUnicodeString (&BootPath);
280 RtlFreeUnicodeString (&DriveDeviceName);
281 RtlFreeUnicodeString (&ArcDeviceName);
282
283 DPRINT("DosDeviceMap: 0x%x\n", SharedUserData->DosDeviceMap);
284
285 if (BootDriveFound == FALSE)
286 {
287 DbgPrint("No system drive found!\n");
288 KEBUGCHECK (0x0);
289 }
290 }
291
292 VOID STATIC
293 MiFreeBootDriverMemory(PVOID StartAddress, ULONG Length)
294 {
295 PHYSICAL_ADDRESS Page;
296 ULONG i;
297
298 for (i = 0; i < PAGE_ROUND_UP(Length)/PAGE_SIZE; i++)
299 {
300 Page = MmGetPhysicalAddressForProcess(NULL, StartAddress + i * PAGE_SIZE);
301 MmDeleteVirtualMapping(NULL, StartAddress + i * PAGE_SIZE, FALSE, NULL, NULL);
302 MmDereferencePage(Page);
303 }
304 }
305
306 VOID
307 ExpInitializeExecutive(VOID)
308 {
309 LARGE_INTEGER Timeout;
310 HANDLE ProcessHandle;
311 HANDLE ThreadHandle;
312 ULONG BootDriverCount;
313 ULONG i;
314 ULONG start;
315 ULONG length;
316 PCHAR name;
317 CHAR str[50];
318 NTSTATUS Status;
319 BOOLEAN SetupBoot;
320 PCHAR p1, p2;
321 ULONG MaxMem;
322 BOOLEAN NoBootScreen = FALSE;
323 UNICODE_STRING Name;
324 HANDLE InitDoneEventHandle;
325 OBJECT_ATTRIBUTES ObjectAttributes;
326
327 /*
328 * Fail at runtime if someone has changed various structures without
329 * updating the offsets used for the assembler code.
330 */
331 assert(FIELD_OFFSET(KTHREAD, InitialStack) == KTHREAD_INITIAL_STACK);
332 assert(FIELD_OFFSET(KTHREAD, Teb) == KTHREAD_TEB);
333 assert(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK);
334 assert(FIELD_OFFSET(KTHREAD, ServiceTable) == KTHREAD_SERVICE_TABLE);
335 assert(FIELD_OFFSET(KTHREAD, PreviousMode) == KTHREAD_PREVIOUS_MODE);
336 assert(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME);
337 assert(FIELD_OFFSET(KTHREAD, CallbackStack) == KTHREAD_CALLBACK_STACK);
338 assert(FIELD_OFFSET(ETHREAD, ThreadsProcess) == ETHREAD_THREADS_PROCESS);
339 assert(FIELD_OFFSET(KPROCESS, DirectoryTableBase) ==
340 KPROCESS_DIRECTORY_TABLE_BASE);
341 assert(FIELD_OFFSET(KPROCESS, IopmOffset) == KPROCESS_IOPM_OFFSET);
342 assert(FIELD_OFFSET(KPROCESS, LdtDescriptor) == KPROCESS_LDT_DESCRIPTOR0);
343 assert(FIELD_OFFSET(KTRAP_FRAME, Reserved9) == KTRAP_FRAME_RESERVED9);
344 assert(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
345 assert(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
346
347 assert(FIELD_OFFSET(KPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
348 assert(FIELD_OFFSET(KPCR, Self) == KPCR_SELF);
349 assert(FIELD_OFFSET(IKPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
350 assert(FIELD_OFFSET(IKPCR, Self) == KPCR_SELF);
351 assert(FIELD_OFFSET(IKPCR, CurrentThread) == KPCR_CURRENT_THREAD);
352
353 LdrInit1();
354
355 KeLowerIrql(DISPATCH_LEVEL);
356
357 NtEarlyInitVdm();
358
359 p1 = (PCHAR)KeLoaderBlock.CommandLine;
360
361 MaxMem = 0;
362 while(*p1 && (p2 = strchr(p1, '/')))
363 {
364 p2++;
365 if (!_strnicmp(p2, "MAXMEM", 6))
366 {
367 p2 += 6;
368 while (isspace(*p2)) p2++;
369 if (*p2 == '=')
370 {
371 p2++;
372 while(isspace(*p2)) p2++;
373 if (isdigit(*p2))
374 {
375 while (isdigit(*p2))
376 {
377 MaxMem = MaxMem * 10 + *p2 - '0';
378 p2++;
379 }
380 break;
381 }
382 }
383 }
384 else if (!_strnicmp(p2, "NOBOOTSCREEN", 12))
385 {
386 p2 += 12;
387 NoBootScreen = TRUE;
388 }
389 else if (!_strnicmp(p2, "CRASHDUMP", 9))
390 {
391 p2 += 9;
392 if (*p2 == ':')
393 {
394 p2++;
395 if (!_strnicmp(p2, "FULL", 4))
396 {
397 MmCoreDumpType = MM_CORE_DUMP_TYPE_FULL;
398 }
399 else
400 {
401 MmCoreDumpType = MM_CORE_DUMP_TYPE_NONE;
402 }
403 }
404 }
405 p1 = p2;
406 }
407
408 MmInit1(FirstKrnlPhysAddr,
409 LastKrnlPhysAddr,
410 LastKernelAddress,
411 (PADDRESS_RANGE)&KeMemoryMap,
412 KeMemoryMapRangeCount,
413 MaxMem > 8 ? MaxMem : 4096);
414
415 /* Import ANSI code page table */
416 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
417 {
418 start = KeLoaderModules[i].ModStart;
419 length = KeLoaderModules[i].ModEnd - start;
420
421 name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
422 if (name == NULL)
423 {
424 name = (PCHAR)KeLoaderModules[i].String;
425 }
426 else
427 {
428 name++;
429 }
430
431 if (!_stricmp (name, "ansi.nls"))
432 {
433 RtlpImportAnsiCodePage((PUSHORT)start, length);
434 }
435 }
436
437 /* Import OEM code page table */
438 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
439 {
440 start = KeLoaderModules[i].ModStart;
441 length = KeLoaderModules[i].ModEnd - start;
442
443 name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
444 if (name == NULL)
445 {
446 name = (PCHAR)KeLoaderModules[i].String;
447 }
448 else
449 {
450 name++;
451 }
452
453 if (!_stricmp (name, "oem.nls"))
454 {
455 RtlpImportOemCodePage((PUSHORT)start, length);
456 }
457 }
458
459 /* Import Unicode casemap table */
460 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
461 {
462 start = KeLoaderModules[i].ModStart;
463 length = KeLoaderModules[i].ModEnd - start;
464
465 name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
466 if (name == NULL)
467 {
468 name = (PCHAR)KeLoaderModules[i].String;
469 }
470 else
471 {
472 name++;
473 }
474
475 if (!_stricmp (name, "casemap.nls"))
476 {
477 RtlpImportUnicodeCasemap((PUSHORT)start, length);
478 }
479 }
480
481 /* Create initial NLS tables */
482 RtlpCreateInitialNlsTables();
483
484 /*
485 * Initialize the kernel debugger
486 */
487 KdInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
488
489 MmInit2();
490 KeInit2();
491
492 KeLowerIrql(PASSIVE_LEVEL);
493
494 if (!SeInit1())
495 KEBUGCHECK(SECURITY_INITIALIZATION_FAILED);
496
497 ObInit();
498
499 if (!SeInit2())
500 KEBUGCHECK(SECURITY1_INITIALIZATION_FAILED);
501
502 PiInitProcessManager();
503
504 if (KdPollBreakIn ())
505 {
506 DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
507 }
508
509 /* Initialize all processors */
510 KeNumberProcessors = 0;
511
512 while (!HalAllProcessorsStarted())
513 {
514 PVOID ProcessorStack;
515
516 if (KeNumberProcessors != 0)
517 {
518 KePrepareForApplicationProcessorInit(KeNumberProcessors);
519 PsPrepareForApplicationProcessorInit(KeNumberProcessors);
520 }
521 /* Allocate a stack for use when booting the processor */
522 /* FIXME: The nonpaged memory for the stack is not released after use */
523 ProcessorStack =
524 ExAllocatePool(NonPagedPool, MM_STACK_SIZE) + MM_STACK_SIZE;
525 Ki386InitialStackArray[((int)KeNumberProcessors)] =
526 (PVOID)(ProcessorStack - MM_STACK_SIZE);
527 HalInitializeProcessor(KeNumberProcessors, ProcessorStack);
528 KeNumberProcessors++;
529 }
530
531 /*
532 * Initialize various critical subsystems
533 */
534 HalInitSystem(1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
535
536 ExInit();
537 KdInit1();
538 IoInit();
539 PoInit();
540 LdrInitModuleManagement();
541 CmInitializeRegistry();
542 NtInit();
543 MmInit3();
544 CcInit();
545 KdInit2();
546 FsRtlpInitFileLockingImplementation();
547
548 /* Report all resources used by hal */
549 HalReportResourceUsage();
550
551 /*
552 * Clear the screen to blue
553 */
554 HalInitSystem(2, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
555
556 /*
557 * Display version number and copyright/warranty message
558 */
559 HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR" (Build "
560 KERNEL_VERSION_BUILD_STR")\n");
561 HalDisplayString(RES_STR_LEGAL_COPYRIGHT);
562 HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
563 "Public License, and you\n");
564 HalDisplayString("are welcome to change it and/or distribute copies of it "
565 "under certain\n");
566 HalDisplayString("conditions. There is absolutely no warranty for "
567 "ReactOS.\n\n");
568
569 if (KeNumberProcessors > 1)
570 {
571 sprintf(str,
572 "Found %d system processors. [%lu MB Memory]\n",
573 KeNumberProcessors,
574 (KeLoaderBlock.MemHigher + 1088)/ 1024);
575 }
576 else
577 {
578 sprintf(str,
579 "Found 1 system processor. [%lu MB Memory]\n",
580 (KeLoaderBlock.MemHigher + 1088)/ 1024);
581 }
582 HalDisplayString(str);
583
584 KdInit3();
585
586
587 /* Create the NLS section */
588 RtlpCreateNlsSection();
589
590 /*
591 * Initalize services loaded at boot time
592 */
593 DPRINT("%d files loaded\n",KeLoaderBlock.ModsCount);
594 for (i=0; i < KeLoaderBlock.ModsCount; i++)
595 {
596 CPRINT("Module: '%s' at %08lx, length 0x%08lx\n",
597 KeLoaderModules[i].String,
598 KeLoaderModules[i].ModStart,
599 KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart);
600 }
601
602 /* Pass 1: import system hive registry chunk */
603 SetupBoot = TRUE;
604 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
605 {
606 start = KeLoaderModules[i].ModStart;
607 length = KeLoaderModules[i].ModEnd - start;
608
609 DPRINT("Module: '%s'\n", (PCHAR)KeLoaderModules[i].String);
610 name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
611 if (name == NULL)
612 {
613 name = (PCHAR)KeLoaderModules[i].String;
614 }
615 else
616 {
617 name++;
618 }
619
620 if (!_stricmp (name, "system") ||
621 !_stricmp (name, "system.hiv"))
622 {
623 CPRINT("Process system hive registry chunk at %08lx\n", start);
624 SetupBoot = FALSE;
625 CmImportSystemHive((PCHAR)start, length);
626 }
627 }
628
629 /* Pass 2: import hardware hive registry chunk */
630 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
631 {
632 start = KeLoaderModules[i].ModStart;
633 length = KeLoaderModules[i].ModEnd - start;
634 name = (PCHAR)KeLoaderModules[i].String;
635 if (!_stricmp (name, "hardware") ||
636 !_stricmp (name, "hardware.hiv"))
637 {
638 CPRINT("Process hardware hive registry chunk at %08lx\n", start);
639 CmImportHardwareHive((PCHAR)start, length);
640 }
641 }
642
643 /* Create dummy keys if no hardware hive was found */
644 CmImportHardwareHive (NULL, 0);
645
646 /* Initialize volatile registry settings */
647 if (SetupBoot == FALSE)
648 {
649 CmInit2((PCHAR)KeLoaderBlock.CommandLine);
650 }
651
652 /*
653 * Enter the kernel debugger before starting up the boot drivers
654 */
655 #ifdef KDBG
656 KdbEnter();
657 #endif /* KDBG */
658
659 IoCreateDriverList();
660
661 IoInit2();
662
663 /* Pass 3: process boot loaded drivers */
664 BootDriverCount = 0;
665 for (i=1; i < KeLoaderBlock.ModsCount; i++)
666 {
667 start = KeLoaderModules[i].ModStart;
668 length = KeLoaderModules[i].ModEnd - start;
669 name = (PCHAR)KeLoaderModules[i].String;
670 if (RtlpCheckFileNameExtension(name, ".sys") ||
671 RtlpCheckFileNameExtension(name, ".sym"))
672 {
673 CPRINT("Initializing driver '%s' at %08lx, length 0x%08lx\n",
674 name, start, length);
675 LdrInitializeBootStartDriver((PVOID)start, name, length);
676 }
677 if (RtlpCheckFileNameExtension(name, ".sys"))
678 BootDriverCount++;
679 }
680
681 /* Pass 4: free memory for all boot files, except ntoskrnl.exe and hal.dll */
682 for (i = 2; i < KeLoaderBlock.ModsCount; i++)
683 {
684 #ifdef KDBG
685 /* Do not free the memory from symbol files, if the kernel debugger is active */
686 if (!RtlpCheckFileNameExtension(name, ".sym"))
687 #endif
688 {
689 MiFreeBootDriverMemory((PVOID)KeLoaderModules[i].ModStart,
690 KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart);
691 }
692 }
693
694 if (BootDriverCount == 0)
695 {
696 DbgPrint("No boot drivers available.\n");
697 KEBUGCHECK(0);
698 }
699
700 /* Display the boot screen image if not disabled */
701 if (!NoBootScreen)
702 {
703 InbvEnableBootDriver(TRUE);
704 }
705
706 /* Create ARC names for boot devices */
707 IoCreateArcNames();
708
709 /* Create the SystemRoot symbolic link */
710 CPRINT("CommandLine: %s\n", (PUCHAR)KeLoaderBlock.CommandLine);
711 Status = IoCreateSystemRootLink((PUCHAR)KeLoaderBlock.CommandLine);
712 if (!NT_SUCCESS(Status))
713 KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE);
714
715 #ifdef DBGPRINT_FILE_LOG
716 /* On the assumption that we can now access disks start up the debug
717 logger thread */
718 DebugLogInit2();
719 #endif /* DBGPRINT_FILE_LOG */
720
721 #ifdef KDBG
722 KdbInitProfiling2();
723 #endif /* KDBG */
724
725 PiInitDefaultLocale();
726
727 /*
728 * Load boot start drivers
729 */
730 IopLoadBootStartDrivers();
731
732 /*
733 * Load Auto configured drivers
734 */
735 LdrLoadAutoConfigDrivers();
736
737 IoDestroyDriverList();
738
739 /*
740 * Assign drive letters
741 */
742 IoAssignDriveLetters ((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock,
743 NULL,
744 NULL,
745 NULL);
746
747 /*
748 * Initialize shared user page:
749 * - set dos system path, dos device map, etc.
750 */
751 InitSystemSharedUserPage ((PUCHAR)KeLoaderBlock.CommandLine);
752
753 /* Create 'ReactOSInitDone' event */
754 RtlInitUnicodeString(&Name, L"\\ReactOSInitDone");
755 InitializeObjectAttributes(&ObjectAttributes,
756 &Name,
757 0,
758 NULL,
759 NULL);
760 Status = NtCreateEvent(&InitDoneEventHandle,
761 EVENT_ALL_ACCESS,
762 &ObjectAttributes,
763 FALSE, /* Synchronization event */
764 FALSE); /* Not signalled */
765 if (!NT_SUCCESS(Status))
766 {
767 DPRINT1("Failed to create 'ReactOSInitDone' event (Status 0x%x)\n", Status);
768 InitDoneEventHandle = INVALID_HANDLE_VALUE;
769 }
770
771 /*
772 * Launch initial process
773 */
774 Status = LdrLoadInitialProcess(&ProcessHandle,
775 &ThreadHandle);
776 if (!NT_SUCCESS(Status))
777 {
778 KEBUGCHECKEX(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
779 }
780
781 if (InitDoneEventHandle != INVALID_HANDLE_VALUE)
782 {
783 HANDLE Handles[2]; /* Init event, Initial process */
784
785 Handles[0] = InitDoneEventHandle;
786 Handles[1] = ProcessHandle;
787
788 /* Wait for the system to be initialized */
789 Timeout.QuadPart = -1200000000LL; /* 120 second timeout */
790 Status = NtWaitForMultipleObjects(((LONG) sizeof(Handles) / sizeof(HANDLE)),
791 Handles,
792 WaitAny,
793 FALSE, /* Non-alertable */
794 &Timeout);
795 if (!NT_SUCCESS(Status))
796 {
797 DPRINT1("NtWaitForMultipleObjects failed with status 0x%x!\n", Status);
798 }
799 else if (Status == STATUS_TIMEOUT)
800 {
801 DPRINT1("WARNING: System not initialized after 120 seconds.\n");
802 }
803 else if (Status == STATUS_WAIT_0 + 1)
804 {
805 /*
806 * Crash the system if the initial process was terminated.
807 */
808 KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 0, 0, 0);
809 }
810
811 if (!NoBootScreen)
812 {
813 InbvEnableBootDriver(FALSE);
814 }
815
816 NtSetEvent(InitDoneEventHandle, NULL);
817
818 NtClose(InitDoneEventHandle);
819 }
820 else
821 {
822 /* On failure to create 'ReactOSInitDone' event, go to text mode ASAP */
823 if (!NoBootScreen)
824 {
825 InbvEnableBootDriver(FALSE);
826 }
827
828 /*
829 * Crash the system if the initial process terminates within 5 seconds.
830 */
831 Timeout.QuadPart = -50000000LL;
832 Status = NtWaitForSingleObject(ProcessHandle,
833 FALSE,
834 &Timeout);
835 if (Status != STATUS_TIMEOUT)
836 {
837 KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 0, 0, 0);
838 }
839 }
840
841 NtClose(ThreadHandle);
842 NtClose(ProcessHandle);
843
844 PsTerminateSystemThread(STATUS_SUCCESS);
845 }
846
847
848 VOID
849 KiSystemStartup(BOOLEAN BootProcessor)
850 {
851 HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
852
853 if (BootProcessor)
854 {
855 /* Never returns */
856 ExpInitializeExecutive();
857 KEBUGCHECK(0);
858 }
859 /* Do application processor initialization */
860 KeApplicationProcessorInit();
861 PsApplicationProcessorInit();
862 KeLowerIrql(PASSIVE_LEVEL);
863 PsIdleThreadMain(NULL);
864 KEBUGCHECK(0);
865 for(;;);
866 }
867
868 VOID
869 _main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock)
870 /*
871 * FUNCTION: Called by the boot loader to start the kernel
872 * ARGUMENTS:
873 * LoaderBlock = Pointer to boot parameters initialized by the boot
874 * loader
875 * NOTE: The boot parameters are stored in low memory which will become
876 * invalid after the memory managment is initialized so we make a local copy.
877 */
878 {
879 ULONG i;
880 ULONG size;
881 ULONG last_kernel_address;
882 extern ULONG _bss_end__;
883 ULONG HalBase;
884 ULONG DriverBase;
885 ULONG DriverSize;
886
887 /* Low level architecture specific initialization */
888 KeInit1();
889
890 /*
891 * Copy the parameters to a local buffer because lowmem will go away
892 */
893 memcpy(&KeLoaderBlock, _LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
894 memcpy(&KeLoaderModules[1], (PVOID)KeLoaderBlock.ModsAddr,
895 sizeof(LOADER_MODULE) * KeLoaderBlock.ModsCount);
896 KeLoaderBlock.ModsCount++;
897 KeLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
898
899 /*
900 * Convert a path specification in the grub format to one understood by the
901 * rest of the kernel.
902 */
903 if (((PUCHAR)_LoaderBlock->CommandLine)[0] == '(')
904 {
905 ULONG DiskNumber = 0, PartNumber = 0;
906 PCH p;
907 CHAR Temp[256];
908 PCH options;
909 PCH s1;
910
911 if (((PUCHAR)_LoaderBlock->CommandLine)[1] == 'h' &&
912 ((PUCHAR)_LoaderBlock->CommandLine)[2] == 'd')
913 {
914 DiskNumber = ((PUCHAR)_LoaderBlock->CommandLine)[3] - '0';
915 PartNumber = ((PUCHAR)_LoaderBlock->CommandLine)[5] - '0';
916 }
917 strcpy(Temp, &((PUCHAR)_LoaderBlock->CommandLine)[7]);
918 if ((options = strchr(Temp, ' ')) != NULL)
919 {
920 *options = 0;
921 options++;
922 }
923 else
924 {
925 options = "";
926 }
927 if ((s1 = strrchr(Temp, '/')) != NULL)
928 {
929 *s1 = 0;
930 if ((s1 = strrchr(Temp, '/')) != NULL)
931 {
932 *s1 = 0;
933 }
934 }
935 sprintf(KeLoaderCommandLine,
936 "multi(0)disk(0)rdisk(%lu)partition(%lu)%s %s",
937 DiskNumber, PartNumber + 1, Temp, options);
938
939 p = KeLoaderCommandLine;
940 while (*p != 0 && *p != ' ')
941 {
942 if ((*p) == '/')
943 {
944 (*p) = '\\';
945 }
946 p++;
947 }
948 DPRINT1("Command Line: %s\n", KeLoaderCommandLine);
949 }
950 else
951 {
952 strcpy(KeLoaderCommandLine, (PUCHAR)_LoaderBlock->CommandLine);
953 }
954 KeLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
955
956 strcpy(KeLoaderModuleStrings[0], "ntoskrnl.exe");
957 KeLoaderModules[0].String = (ULONG)KeLoaderModuleStrings[0];
958 KeLoaderModules[0].ModStart = 0xC0000000;
959 KeLoaderModules[0].ModEnd = PAGE_ROUND_UP((ULONG)&_bss_end__);
960 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
961 {
962 CHAR* s;
963 if ((s = strrchr((PUCHAR)KeLoaderModules[i].String, '/')) != 0)
964 {
965 strcpy(KeLoaderModuleStrings[i], s + 1);
966 }
967 else
968 {
969 strcpy(KeLoaderModuleStrings[i], (PUCHAR)KeLoaderModules[i].String);
970 }
971 KeLoaderModules[i].ModStart -= 0x200000;
972 KeLoaderModules[i].ModStart += 0xc0000000;
973 KeLoaderModules[i].ModEnd -= 0x200000;
974 KeLoaderModules[i].ModEnd += 0xc0000000;
975 KeLoaderModules[i].String = (ULONG)KeLoaderModuleStrings[i];
976 }
977
978 #ifdef HAL_DBG
979 HalnInitializeDisplay((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
980 #endif
981
982 HalBase = KeLoaderModules[1].ModStart;
983 DriverBase =
984 PAGE_ROUND_UP(KeLoaderModules[KeLoaderBlock.ModsCount - 1].ModEnd);
985
986 /*
987 * Process hal.dll
988 */
989 LdrSafePEProcessModule((PVOID)HalBase, (PVOID)DriverBase, (PVOID)0xC0000000, &DriverSize);
990
991 LdrHalBase = (ULONG_PTR)DriverBase;
992 last_kernel_address = DriverBase + DriverSize;
993
994 /*
995 * Process ntoskrnl.exe
996 */
997 LdrSafePEProcessModule((PVOID)0xC0000000, (PVOID)0xC0000000, (PVOID)DriverBase, &DriverSize);
998
999 FirstKrnlPhysAddr = KeLoaderModules[0].ModStart - 0xc0000000 + 0x200000;
1000 LastKrnlPhysAddr = last_kernel_address - 0xc0000000 + 0x200000;
1001 LastKernelAddress = last_kernel_address;
1002
1003 #ifndef ACPI
1004 /* FIXME: VMware does not like it when ReactOS is using the BIOS memory map */
1005 KeLoaderBlock.Flags &= ~MB_FLAGS_MMAP_INFO;
1006 #endif
1007
1008 KeMemoryMapRangeCount = 0;
1009 if (KeLoaderBlock.Flags & MB_FLAGS_MMAP_INFO)
1010 {
1011 /* We have a memory map from the nice BIOS */
1012 size = *((PULONG)(KeLoaderBlock.MmapAddr - sizeof(ULONG)));
1013 i = 0;
1014 while (i < KeLoaderBlock.MmapLength)
1015 {
1016 memcpy (&KeMemoryMap[KeMemoryMapRangeCount],
1017 (PVOID)(KeLoaderBlock.MmapAddr + i),
1018 sizeof(ADDRESS_RANGE));
1019 KeMemoryMapRangeCount++;
1020 i += size;
1021 }
1022 }
1023
1024 KiSystemStartup(1);
1025 }
1026
1027 /* EOF */
1028