- Fixed the freeing of memory from boot load drivers.
[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.174 2003/10/12 17:05:45 hbirr 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 INIT_FUNCTION
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 INIT_FUNCTION
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 INIT_FUNCTION
293 MiFreeBootDriverMemory(PVOID StartAddress, ULONG Length)
294 {
295 ULONG i;
296
297 for (i = 0; i < PAGE_ROUND_UP(Length)/PAGE_SIZE; i++)
298 {
299 MmDeleteVirtualMapping(NULL, StartAddress + i * PAGE_SIZE, TRUE, NULL, NULL);
300
301 }
302 }
303
304 VOID INIT_FUNCTION
305 ExpInitializeExecutive(VOID)
306 {
307 LARGE_INTEGER Timeout;
308 HANDLE ProcessHandle;
309 HANDLE ThreadHandle;
310 ULONG BootDriverCount;
311 ULONG i;
312 ULONG start;
313 ULONG length;
314 PCHAR name;
315 CHAR str[50];
316 NTSTATUS Status;
317 BOOLEAN SetupBoot;
318 PCHAR p1, p2;
319 ULONG MaxMem;
320 BOOLEAN NoBootScreen = FALSE;
321 UNICODE_STRING Name;
322 HANDLE InitDoneEventHandle;
323 OBJECT_ATTRIBUTES ObjectAttributes;
324
325 /*
326 * Fail at runtime if someone has changed various structures without
327 * updating the offsets used for the assembler code.
328 */
329 assert(FIELD_OFFSET(KTHREAD, InitialStack) == KTHREAD_INITIAL_STACK);
330 assert(FIELD_OFFSET(KTHREAD, Teb) == KTHREAD_TEB);
331 assert(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK);
332 assert(FIELD_OFFSET(KTHREAD, ServiceTable) == KTHREAD_SERVICE_TABLE);
333 assert(FIELD_OFFSET(KTHREAD, PreviousMode) == KTHREAD_PREVIOUS_MODE);
334 assert(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME);
335 assert(FIELD_OFFSET(KTHREAD, CallbackStack) == KTHREAD_CALLBACK_STACK);
336 assert(FIELD_OFFSET(ETHREAD, ThreadsProcess) == ETHREAD_THREADS_PROCESS);
337 assert(FIELD_OFFSET(KPROCESS, DirectoryTableBase) ==
338 KPROCESS_DIRECTORY_TABLE_BASE);
339 assert(FIELD_OFFSET(KPROCESS, IopmOffset) == KPROCESS_IOPM_OFFSET);
340 assert(FIELD_OFFSET(KPROCESS, LdtDescriptor) == KPROCESS_LDT_DESCRIPTOR0);
341 assert(FIELD_OFFSET(KTRAP_FRAME, Reserved9) == KTRAP_FRAME_RESERVED9);
342 assert(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
343 assert(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
344
345 assert(FIELD_OFFSET(KPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
346 assert(FIELD_OFFSET(KPCR, Self) == KPCR_SELF);
347 assert(FIELD_OFFSET(IKPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
348 assert(FIELD_OFFSET(IKPCR, Self) == KPCR_SELF);
349 assert(FIELD_OFFSET(IKPCR, CurrentThread) == KPCR_CURRENT_THREAD);
350
351 LdrInit1();
352
353 KeLowerIrql(DISPATCH_LEVEL);
354
355 NtEarlyInitVdm();
356
357 p1 = (PCHAR)KeLoaderBlock.CommandLine;
358
359 MaxMem = 0;
360 while(*p1 && (p2 = strchr(p1, '/')))
361 {
362 p2++;
363 if (!_strnicmp(p2, "MAXMEM", 6))
364 {
365 p2 += 6;
366 while (isspace(*p2)) p2++;
367 if (*p2 == '=')
368 {
369 p2++;
370 while(isspace(*p2)) p2++;
371 if (isdigit(*p2))
372 {
373 while (isdigit(*p2))
374 {
375 MaxMem = MaxMem * 10 + *p2 - '0';
376 p2++;
377 }
378 break;
379 }
380 }
381 }
382 else if (!_strnicmp(p2, "NOBOOTSCREEN", 12))
383 {
384 p2 += 12;
385 NoBootScreen = TRUE;
386 }
387 else if (!_strnicmp(p2, "CRASHDUMP", 9))
388 {
389 p2 += 9;
390 if (*p2 == ':')
391 {
392 p2++;
393 if (!_strnicmp(p2, "FULL", 4))
394 {
395 MmCoreDumpType = MM_CORE_DUMP_TYPE_FULL;
396 }
397 else
398 {
399 MmCoreDumpType = MM_CORE_DUMP_TYPE_NONE;
400 }
401 }
402 }
403 p1 = p2;
404 }
405
406 MmInit1(FirstKrnlPhysAddr,
407 LastKrnlPhysAddr,
408 LastKernelAddress,
409 (PADDRESS_RANGE)&KeMemoryMap,
410 KeMemoryMapRangeCount,
411 MaxMem > 8 ? MaxMem : 4096);
412
413 /* Import ANSI code page table */
414 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
415 {
416 start = KeLoaderModules[i].ModStart;
417 length = KeLoaderModules[i].ModEnd - start;
418
419 name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
420 if (name == NULL)
421 {
422 name = (PCHAR)KeLoaderModules[i].String;
423 }
424 else
425 {
426 name++;
427 }
428
429 if (!_stricmp (name, "ansi.nls"))
430 {
431 RtlpImportAnsiCodePage((PUSHORT)start, length);
432 }
433 }
434
435 /* Import OEM code page table */
436 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
437 {
438 start = KeLoaderModules[i].ModStart;
439 length = KeLoaderModules[i].ModEnd - start;
440
441 name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
442 if (name == NULL)
443 {
444 name = (PCHAR)KeLoaderModules[i].String;
445 }
446 else
447 {
448 name++;
449 }
450
451 if (!_stricmp (name, "oem.nls"))
452 {
453 RtlpImportOemCodePage((PUSHORT)start, length);
454 }
455 }
456
457 /* Import Unicode casemap table */
458 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
459 {
460 start = KeLoaderModules[i].ModStart;
461 length = KeLoaderModules[i].ModEnd - start;
462
463 name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
464 if (name == NULL)
465 {
466 name = (PCHAR)KeLoaderModules[i].String;
467 }
468 else
469 {
470 name++;
471 }
472
473 if (!_stricmp (name, "casemap.nls"))
474 {
475 RtlpImportUnicodeCasemap((PUSHORT)start, length);
476 }
477 }
478
479 /* Create initial NLS tables */
480 RtlpCreateInitialNlsTables();
481
482 /*
483 * Initialize the kernel debugger
484 */
485 KdInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
486
487 MmInit2();
488 KeInit2();
489
490 KeLowerIrql(PASSIVE_LEVEL);
491
492 if (!SeInit1())
493 KEBUGCHECK(SECURITY_INITIALIZATION_FAILED);
494
495 ObInit();
496
497 if (!SeInit2())
498 KEBUGCHECK(SECURITY1_INITIALIZATION_FAILED);
499
500 PiInitProcessManager();
501
502 if (KdPollBreakIn ())
503 {
504 DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
505 }
506
507 /* Initialize all processors */
508 KeNumberProcessors = 0;
509
510 while (!HalAllProcessorsStarted())
511 {
512 PVOID ProcessorStack;
513
514 if (KeNumberProcessors != 0)
515 {
516 KePrepareForApplicationProcessorInit(KeNumberProcessors);
517 PsPrepareForApplicationProcessorInit(KeNumberProcessors);
518 }
519 /* Allocate a stack for use when booting the processor */
520 /* FIXME: The nonpaged memory for the stack is not released after use */
521 ProcessorStack =
522 ExAllocatePool(NonPagedPool, MM_STACK_SIZE) + MM_STACK_SIZE;
523 Ki386InitialStackArray[((int)KeNumberProcessors)] =
524 (PVOID)(ProcessorStack - MM_STACK_SIZE);
525 HalInitializeProcessor(KeNumberProcessors, ProcessorStack);
526 KeNumberProcessors++;
527 }
528
529 /*
530 * Initialize various critical subsystems
531 */
532 HalInitSystem(1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
533
534 ExInit();
535 KdInit1();
536 IoInit();
537 PoInit();
538 LdrInitModuleManagement();
539 CmInitializeRegistry();
540 NtInit();
541 MmInit3();
542 CcInit();
543 KdInit2();
544 FsRtlpInitFileLockingImplementation();
545
546 /* Report all resources used by hal */
547 HalReportResourceUsage();
548
549 /*
550 * Clear the screen to blue
551 */
552 HalInitSystem(2, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
553
554 /*
555 * Display version number and copyright/warranty message
556 */
557 HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR" (Build "
558 KERNEL_VERSION_BUILD_STR")\n");
559 HalDisplayString(RES_STR_LEGAL_COPYRIGHT);
560 HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
561 "Public License, and you\n");
562 HalDisplayString("are welcome to change it and/or distribute copies of it "
563 "under certain\n");
564 HalDisplayString("conditions. There is absolutely no warranty for "
565 "ReactOS.\n\n");
566
567 if (KeNumberProcessors > 1)
568 {
569 sprintf(str,
570 "Found %d system processors. [%lu MB Memory]\n",
571 KeNumberProcessors,
572 (KeLoaderBlock.MemHigher + 1088)/ 1024);
573 }
574 else
575 {
576 sprintf(str,
577 "Found 1 system processor. [%lu MB Memory]\n",
578 (KeLoaderBlock.MemHigher + 1088)/ 1024);
579 }
580 HalDisplayString(str);
581
582 KdInit3();
583
584
585 /* Create the NLS section */
586 RtlpCreateNlsSection();
587
588 /*
589 * Initalize services loaded at boot time
590 */
591 DPRINT("%d files loaded\n",KeLoaderBlock.ModsCount);
592 for (i=0; i < KeLoaderBlock.ModsCount; i++)
593 {
594 CPRINT("Module: '%s' at %08lx, length 0x%08lx\n",
595 KeLoaderModules[i].String,
596 KeLoaderModules[i].ModStart,
597 KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart);
598 }
599
600 /* Pass 1: import system hive registry chunk */
601 SetupBoot = TRUE;
602 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
603 {
604 start = KeLoaderModules[i].ModStart;
605 length = KeLoaderModules[i].ModEnd - start;
606
607 DPRINT("Module: '%s'\n", (PCHAR)KeLoaderModules[i].String);
608 name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
609 if (name == NULL)
610 {
611 name = (PCHAR)KeLoaderModules[i].String;
612 }
613 else
614 {
615 name++;
616 }
617
618 if (!_stricmp (name, "system") ||
619 !_stricmp (name, "system.hiv"))
620 {
621 CPRINT("Process system hive registry chunk at %08lx\n", start);
622 SetupBoot = FALSE;
623 CmImportSystemHive((PCHAR)start, length);
624 }
625 }
626
627 /* Pass 2: import hardware hive registry chunk */
628 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
629 {
630 start = KeLoaderModules[i].ModStart;
631 length = KeLoaderModules[i].ModEnd - start;
632 name = (PCHAR)KeLoaderModules[i].String;
633 if (!_stricmp (name, "hardware") ||
634 !_stricmp (name, "hardware.hiv"))
635 {
636 CPRINT("Process hardware hive registry chunk at %08lx\n", start);
637 CmImportHardwareHive((PCHAR)start, length);
638 }
639 }
640
641 /* Create dummy keys if no hardware hive was found */
642 CmImportHardwareHive (NULL, 0);
643
644 /* Initialize volatile registry settings */
645 if (SetupBoot == FALSE)
646 {
647 CmInit2((PCHAR)KeLoaderBlock.CommandLine);
648 }
649
650 /*
651 * Enter the kernel debugger before starting up the boot drivers
652 */
653 #ifdef KDBG
654 KdbEnter();
655 #endif /* KDBG */
656
657 IoCreateDriverList();
658
659 IoInit2();
660
661 /* Pass 3: process boot loaded drivers */
662 BootDriverCount = 0;
663 for (i=1; i < KeLoaderBlock.ModsCount; i++)
664 {
665 start = KeLoaderModules[i].ModStart;
666 length = KeLoaderModules[i].ModEnd - start;
667 name = (PCHAR)KeLoaderModules[i].String;
668 if (RtlpCheckFileNameExtension(name, ".sys") ||
669 RtlpCheckFileNameExtension(name, ".sym"))
670 {
671 CPRINT("Initializing driver '%s' at %08lx, length 0x%08lx\n",
672 name, start, length);
673 LdrInitializeBootStartDriver((PVOID)start, name, length);
674 }
675 if (RtlpCheckFileNameExtension(name, ".sys"))
676 BootDriverCount++;
677 }
678
679 /* Pass 4: free memory for all boot files, except ntoskrnl.exe and hal.dll */
680 for (i = 2; i < KeLoaderBlock.ModsCount; i++)
681 {
682 #ifdef KDBG
683 /* Do not free the memory from symbol files, if the kernel debugger is active */
684 if (!RtlpCheckFileNameExtension(name, ".sym"))
685 #endif
686 {
687 MiFreeBootDriverMemory((PVOID)KeLoaderModules[i].ModStart,
688 KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart);
689 }
690 }
691
692 if (BootDriverCount == 0)
693 {
694 DbgPrint("No boot drivers available.\n");
695 KEBUGCHECK(0);
696 }
697
698 /* Display the boot screen image if not disabled */
699 if (!NoBootScreen)
700 {
701 InbvEnableBootDriver(TRUE);
702 }
703
704 /* Create ARC names for boot devices */
705 IoCreateArcNames();
706
707 /* Create the SystemRoot symbolic link */
708 CPRINT("CommandLine: %s\n", (PUCHAR)KeLoaderBlock.CommandLine);
709 Status = IoCreateSystemRootLink((PUCHAR)KeLoaderBlock.CommandLine);
710 if (!NT_SUCCESS(Status))
711 KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE);
712
713 #ifdef DBGPRINT_FILE_LOG
714 /* On the assumption that we can now access disks start up the debug
715 logger thread */
716 DebugLogInit2();
717 #endif /* DBGPRINT_FILE_LOG */
718
719 #ifdef KDBG
720 KdbInitProfiling2();
721 #endif /* KDBG */
722
723 PiInitDefaultLocale();
724
725 /*
726 * Load boot start drivers
727 */
728 IopLoadBootStartDrivers();
729
730 /*
731 * Load Auto configured drivers
732 */
733 LdrLoadAutoConfigDrivers();
734
735 IoDestroyDriverList();
736
737 /*
738 * Assign drive letters
739 */
740 IoAssignDriveLetters ((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock,
741 NULL,
742 NULL,
743 NULL);
744
745 /*
746 * Initialize shared user page:
747 * - set dos system path, dos device map, etc.
748 */
749 InitSystemSharedUserPage ((PUCHAR)KeLoaderBlock.CommandLine);
750
751 /* Create 'ReactOSInitDone' event */
752 RtlInitUnicodeString(&Name, L"\\ReactOSInitDone");
753 InitializeObjectAttributes(&ObjectAttributes,
754 &Name,
755 0,
756 NULL,
757 NULL);
758 Status = NtCreateEvent(&InitDoneEventHandle,
759 EVENT_ALL_ACCESS,
760 &ObjectAttributes,
761 FALSE, /* Synchronization event */
762 FALSE); /* Not signalled */
763 if (!NT_SUCCESS(Status))
764 {
765 DPRINT1("Failed to create 'ReactOSInitDone' event (Status 0x%x)\n", Status);
766 InitDoneEventHandle = INVALID_HANDLE_VALUE;
767 }
768
769 /*
770 * Launch initial process
771 */
772 Status = LdrLoadInitialProcess(&ProcessHandle,
773 &ThreadHandle);
774 if (!NT_SUCCESS(Status))
775 {
776 KEBUGCHECKEX(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
777 }
778
779 if (InitDoneEventHandle != INVALID_HANDLE_VALUE)
780 {
781 HANDLE Handles[2]; /* Init event, Initial process */
782
783 Handles[0] = InitDoneEventHandle;
784 Handles[1] = ProcessHandle;
785
786 /* Wait for the system to be initialized */
787 Timeout.QuadPart = -1200000000LL; /* 120 second timeout */
788 Status = NtWaitForMultipleObjects(((LONG) sizeof(Handles) / sizeof(HANDLE)),
789 Handles,
790 WaitAny,
791 FALSE, /* Non-alertable */
792 &Timeout);
793 if (!NT_SUCCESS(Status))
794 {
795 DPRINT1("NtWaitForMultipleObjects failed with status 0x%x!\n", Status);
796 }
797 else if (Status == STATUS_TIMEOUT)
798 {
799 DPRINT1("WARNING: System not initialized after 120 seconds.\n");
800 }
801 else if (Status == STATUS_WAIT_0 + 1)
802 {
803 /*
804 * Crash the system if the initial process was terminated.
805 */
806 KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 0, 0, 0);
807 }
808
809 if (!NoBootScreen)
810 {
811 InbvEnableBootDriver(FALSE);
812 }
813
814 NtSetEvent(InitDoneEventHandle, NULL);
815
816 NtClose(InitDoneEventHandle);
817 }
818 else
819 {
820 /* On failure to create 'ReactOSInitDone' event, go to text mode ASAP */
821 if (!NoBootScreen)
822 {
823 InbvEnableBootDriver(FALSE);
824 }
825
826 /*
827 * Crash the system if the initial process terminates within 5 seconds.
828 */
829 Timeout.QuadPart = -50000000LL;
830 Status = NtWaitForSingleObject(ProcessHandle,
831 FALSE,
832 &Timeout);
833 if (Status != STATUS_TIMEOUT)
834 {
835 KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 0, 0, 0);
836 }
837 }
838
839 NtClose(ThreadHandle);
840 NtClose(ProcessHandle);
841 }
842
843
844 VOID
845 KiSystemStartup(BOOLEAN BootProcessor)
846 {
847 HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
848
849 if (BootProcessor)
850 {
851 ExpInitializeExecutive();
852 MiFreeInitMemory();
853 /* Never returns */
854 PsTerminateSystemThread(STATUS_SUCCESS);
855 KEBUGCHECK(0);
856 }
857 /* Do application processor initialization */
858 KeApplicationProcessorInit();
859 PsApplicationProcessorInit();
860 KeLowerIrql(PASSIVE_LEVEL);
861 PsIdleThreadMain(NULL);
862 KEBUGCHECK(0);
863 for(;;);
864 }
865
866
867 VOID INIT_FUNCTION
868 _main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock)
869 /*
870 * FUNCTION: Called by the boot loader to start the kernel
871 * ARGUMENTS:
872 * LoaderBlock = Pointer to boot parameters initialized by the boot
873 * loader
874 * NOTE: The boot parameters are stored in low memory which will become
875 * invalid after the memory managment is initialized so we make a local copy.
876 */
877 {
878 ULONG i;
879 ULONG size;
880 ULONG last_kernel_address;
881 extern ULONG _bss_end__;
882 ULONG HalBase;
883 ULONG DriverBase;
884 ULONG DriverSize;
885
886 /* Low level architecture specific initialization */
887 KeInit1();
888
889 /*
890 * Copy the parameters to a local buffer because lowmem will go away
891 */
892 memcpy(&KeLoaderBlock, _LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
893 memcpy(&KeLoaderModules[1], (PVOID)KeLoaderBlock.ModsAddr,
894 sizeof(LOADER_MODULE) * KeLoaderBlock.ModsCount);
895 KeLoaderBlock.ModsCount++;
896 KeLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
897
898 /*
899 * Convert a path specification in the grub format to one understood by the
900 * rest of the kernel.
901 */
902 if (((PUCHAR)_LoaderBlock->CommandLine)[0] == '(')
903 {
904 ULONG DiskNumber = 0, PartNumber = 0;
905 PCH p;
906 CHAR Temp[256];
907 PCH options;
908 PCH s1;
909
910 if (((PUCHAR)_LoaderBlock->CommandLine)[1] == 'h' &&
911 ((PUCHAR)_LoaderBlock->CommandLine)[2] == 'd')
912 {
913 DiskNumber = ((PUCHAR)_LoaderBlock->CommandLine)[3] - '0';
914 PartNumber = ((PUCHAR)_LoaderBlock->CommandLine)[5] - '0';
915 }
916 strcpy(Temp, &((PUCHAR)_LoaderBlock->CommandLine)[7]);
917 if ((options = strchr(Temp, ' ')) != NULL)
918 {
919 *options = 0;
920 options++;
921 }
922 else
923 {
924 options = "";
925 }
926 if ((s1 = strrchr(Temp, '/')) != NULL)
927 {
928 *s1 = 0;
929 if ((s1 = strrchr(Temp, '/')) != NULL)
930 {
931 *s1 = 0;
932 }
933 }
934 sprintf(KeLoaderCommandLine,
935 "multi(0)disk(0)rdisk(%lu)partition(%lu)%s %s",
936 DiskNumber, PartNumber + 1, Temp, options);
937
938 p = KeLoaderCommandLine;
939 while (*p != 0 && *p != ' ')
940 {
941 if ((*p) == '/')
942 {
943 (*p) = '\\';
944 }
945 p++;
946 }
947 DPRINT1("Command Line: %s\n", KeLoaderCommandLine);
948 }
949 else
950 {
951 strcpy(KeLoaderCommandLine, (PUCHAR)_LoaderBlock->CommandLine);
952 }
953 KeLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
954
955 strcpy(KeLoaderModuleStrings[0], "ntoskrnl.exe");
956 KeLoaderModules[0].String = (ULONG)KeLoaderModuleStrings[0];
957 KeLoaderModules[0].ModStart = 0xC0000000;
958 KeLoaderModules[0].ModEnd = PAGE_ROUND_UP((ULONG)&_bss_end__);
959 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
960 {
961 CHAR* s;
962 if ((s = strrchr((PUCHAR)KeLoaderModules[i].String, '/')) != 0)
963 {
964 strcpy(KeLoaderModuleStrings[i], s + 1);
965 }
966 else
967 {
968 strcpy(KeLoaderModuleStrings[i], (PUCHAR)KeLoaderModules[i].String);
969 }
970 KeLoaderModules[i].ModStart -= 0x200000;
971 KeLoaderModules[i].ModStart += 0xc0000000;
972 KeLoaderModules[i].ModEnd -= 0x200000;
973 KeLoaderModules[i].ModEnd += 0xc0000000;
974 KeLoaderModules[i].String = (ULONG)KeLoaderModuleStrings[i];
975 }
976
977 #ifdef HAL_DBG
978 HalnInitializeDisplay((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
979 #endif
980
981 HalBase = KeLoaderModules[1].ModStart;
982 DriverBase =
983 PAGE_ROUND_UP(KeLoaderModules[KeLoaderBlock.ModsCount - 1].ModEnd);
984
985 /*
986 * Process hal.dll
987 */
988 LdrSafePEProcessModule((PVOID)HalBase, (PVOID)DriverBase, (PVOID)0xC0000000, &DriverSize);
989
990 LdrHalBase = (ULONG_PTR)DriverBase;
991 last_kernel_address = DriverBase + DriverSize;
992
993 /*
994 * Process ntoskrnl.exe
995 */
996 LdrSafePEProcessModule((PVOID)0xC0000000, (PVOID)0xC0000000, (PVOID)DriverBase, &DriverSize);
997
998 FirstKrnlPhysAddr = KeLoaderModules[0].ModStart - 0xc0000000 + 0x200000;
999 LastKrnlPhysAddr = last_kernel_address - 0xc0000000 + 0x200000;
1000 LastKernelAddress = last_kernel_address;
1001
1002 #ifndef ACPI
1003 /* FIXME: VMware does not like it when ReactOS is using the BIOS memory map */
1004 KeLoaderBlock.Flags &= ~MB_FLAGS_MMAP_INFO;
1005 #endif
1006
1007 KeMemoryMapRangeCount = 0;
1008 if (KeLoaderBlock.Flags & MB_FLAGS_MMAP_INFO)
1009 {
1010 /* We have a memory map from the nice BIOS */
1011 size = *((PULONG)(KeLoaderBlock.MmapAddr - sizeof(ULONG)));
1012 i = 0;
1013 while (i < KeLoaderBlock.MmapLength)
1014 {
1015 memcpy (&KeMemoryMap[KeMemoryMapRangeCount],
1016 (PVOID)(KeLoaderBlock.MmapAddr + i),
1017 sizeof(ADDRESS_RANGE));
1018 KeMemoryMapRangeCount++;
1019 i += size;
1020 }
1021 }
1022
1023 KiSystemStartup(1);
1024 }
1025
1026 /* EOF */
1027