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