- Added a boot option for reducing the used memory size ('/maxmem=used_memory_in_mb').
[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.161 2003/06/14 17:46:24 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, PreviousMode) == KTHREAD_PREVIOUS_MODE);
328 assert(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME);
329 assert(FIELD_OFFSET(KTHREAD, CallbackStack) == KTHREAD_CALLBACK_STACK);
330 assert(FIELD_OFFSET(ETHREAD, ThreadsProcess) == ETHREAD_THREADS_PROCESS);
331 assert(FIELD_OFFSET(KPROCESS, DirectoryTableBase) ==
332 KPROCESS_DIRECTORY_TABLE_BASE);
333 assert(FIELD_OFFSET(KTRAP_FRAME, Reserved9) == KTRAP_FRAME_RESERVED9);
334 assert(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
335 assert(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
336
337 assert(FIELD_OFFSET(KPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
338 assert(FIELD_OFFSET(KPCR, Self) == KPCR_SELF);
339 assert(FIELD_OFFSET(IKPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
340 assert(FIELD_OFFSET(IKPCR, Self) == KPCR_SELF);
341 assert(FIELD_OFFSET(IKPCR, CurrentThread) == KPCR_CURRENT_THREAD);
342
343 LdrInit1();
344
345 KeLowerIrql(DISPATCH_LEVEL);
346
347 NtEarlyInitVdm();
348
349 p1 = (PCHAR)KeLoaderBlock.CommandLine;
350
351 MaxMem = 0;
352 while(*p1 && (p2 = strchr(p1, '/')))
353 {
354 p2++;
355 if (!_strnicmp(p2, "MAXMEM", 6))
356 {
357 p2 += 6;
358 while (isspace(*p2)) p2++;
359 if (*p2 == '=')
360 {
361 p2++;
362 while(isspace(*p2)) p2++;
363 if (isdigit(*p2))
364 {
365 while (isdigit(*p2))
366 {
367 MaxMem = MaxMem * 10 + *p2 - '0';
368 p2++;
369 }
370 break;
371 }
372 }
373 }
374 p1 = p2;
375 }
376
377 MmInit1(FirstKrnlPhysAddr,
378 LastKrnlPhysAddr,
379 LastKernelAddress,
380 (PADDRESS_RANGE)&KeMemoryMap,
381 KeMemoryMapRangeCount,
382 MaxMem > 8 ? MaxMem : 4096);
383
384 /* Import ANSI code page table */
385 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
386 {
387 start = KeLoaderModules[i].ModStart;
388 length = KeLoaderModules[i].ModEnd - start;
389
390 name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
391 if (name == NULL)
392 {
393 name = (PCHAR)KeLoaderModules[i].String;
394 }
395 else
396 {
397 name++;
398 }
399
400 if (!_stricmp (name, "ansi.nls"))
401 {
402 RtlpImportAnsiCodePage((PUSHORT)start, length);
403 }
404 }
405
406 /* Import OEM code page table */
407 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
408 {
409 start = KeLoaderModules[i].ModStart;
410 length = KeLoaderModules[i].ModEnd - start;
411
412 name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
413 if (name == NULL)
414 {
415 name = (PCHAR)KeLoaderModules[i].String;
416 }
417 else
418 {
419 name++;
420 }
421
422 if (!_stricmp (name, "oem.nls"))
423 {
424 RtlpImportOemCodePage((PUSHORT)start, length);
425 }
426 }
427
428 /* Import Unicode casemap table */
429 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
430 {
431 start = KeLoaderModules[i].ModStart;
432 length = KeLoaderModules[i].ModEnd - start;
433
434 name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
435 if (name == NULL)
436 {
437 name = (PCHAR)KeLoaderModules[i].String;
438 }
439 else
440 {
441 name++;
442 }
443
444 if (!_stricmp (name, "casemap.nls"))
445 {
446 RtlpImportUnicodeCasemap((PUSHORT)start, length);
447 }
448 }
449
450 /* Create initial NLS tables */
451 RtlpCreateInitialNlsTables();
452
453 /*
454 * Initialize the kernel debugger
455 */
456 KdInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
457
458 MmInit2();
459 KeInit2();
460
461 KeLowerIrql(PASSIVE_LEVEL);
462
463 if (!SeInit1())
464 KeBugCheck(SECURITY_INITIALIZATION_FAILED);
465
466 ObInit();
467
468 if (!SeInit2())
469 KeBugCheck(SECURITY1_INITIALIZATION_FAILED);
470
471 PiInitProcessManager();
472
473 KdInit1();
474
475 if (KdPollBreakIn ())
476 {
477 DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
478 }
479
480 /*
481 * Display version number and copyright/warranty message
482 */
483 HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR" (Build "
484 KERNEL_VERSION_BUILD_STR")\n");
485 HalDisplayString(RES_STR_LEGAL_COPYRIGHT);
486 HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
487 "Public License, and you\n");
488 HalDisplayString("are welcome to change it and/or distribute copies of it "
489 "under certain\n");
490 HalDisplayString("conditions. There is absolutely no warranty for "
491 "ReactOS.\n\n");
492
493 /* Initialize all processors */
494 KeNumberProcessors = 0;
495
496 while (!HalAllProcessorsStarted())
497 {
498 PVOID ProcessorStack;
499
500 if (KeNumberProcessors != 0)
501 {
502 KePrepareForApplicationProcessorInit(KeNumberProcessors);
503 PsPrepareForApplicationProcessorInit(KeNumberProcessors);
504 }
505 /* Allocate a stack for use when booting the processor */
506 /* FIXME: The nonpaged memory for the stack is not released after use */
507 ProcessorStack =
508 ExAllocatePool(NonPagedPool, MM_STACK_SIZE) + MM_STACK_SIZE;
509 Ki386InitialStackArray[((int)KeNumberProcessors)] =
510 (PVOID)(ProcessorStack - MM_STACK_SIZE);
511 HalInitializeProcessor(KeNumberProcessors, ProcessorStack);
512 KeNumberProcessors++;
513 }
514
515 if (KeNumberProcessors > 1)
516 {
517 sprintf(str,
518 "Found %d system processors. [%lu MB Memory]\n",
519 KeNumberProcessors,
520 (KeLoaderBlock.MemHigher + 1088)/ 1024);
521 }
522 else
523 {
524 sprintf(str,
525 "Found 1 system processor. [%lu MB Memory]\n",
526 (KeLoaderBlock.MemHigher + 1088)/ 1024);
527 }
528 HalDisplayString(str);
529
530 /*
531 * Initialize various critical subsystems
532 */
533 HalInitSystem(1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
534
535 ExInit();
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 /* Create the NLS section */
550 RtlpCreateNlsSection();
551
552 /*
553 * Initalize services loaded at boot time
554 */
555 DPRINT("%d files loaded\n",KeLoaderBlock.ModsCount);
556 for (i=0; i < KeLoaderBlock.ModsCount; i++)
557 {
558 CPRINT("Module: '%s' at %08lx, length 0x%08lx\n",
559 KeLoaderModules[i].String,
560 KeLoaderModules[i].ModStart,
561 KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart);
562 }
563
564 /* Pass 1: import system hive registry chunk */
565 SetupBoot = TRUE;
566 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
567 {
568 start = KeLoaderModules[i].ModStart;
569 length = KeLoaderModules[i].ModEnd - start;
570
571 DPRINT("Module: '%s'\n", (PCHAR)KeLoaderModules[i].String);
572 name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
573 if (name == NULL)
574 {
575 name = (PCHAR)KeLoaderModules[i].String;
576 }
577 else
578 {
579 name++;
580 }
581
582 if (!_stricmp (name, "system") ||
583 !_stricmp (name, "system.hiv"))
584 {
585 CPRINT("Process system hive registry chunk at %08lx\n", start);
586 SetupBoot = FALSE;
587 CmImportSystemHive((PCHAR)start, length);
588 }
589 }
590
591 /* Pass 2: import hardware hive registry chunk */
592 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
593 {
594 start = KeLoaderModules[i].ModStart;
595 length = KeLoaderModules[i].ModEnd - start;
596 name = (PCHAR)KeLoaderModules[i].String;
597 if (!_stricmp (name, "hardware") ||
598 !_stricmp (name, "hardware.hiv"))
599 {
600 CPRINT("Process hardware hive registry chunk at %08lx\n", start);
601 CmImportHardwareHive((PCHAR)start, length);
602 }
603 }
604
605 /* Create dummy keys if no hardware hive was found */
606 CmImportHardwareHive (NULL, 0);
607
608 /* Initialize volatile registry settings */
609 if (SetupBoot == FALSE)
610 {
611 CmInit2((PCHAR)KeLoaderBlock.CommandLine);
612 }
613
614 /*
615 * Enter the kernel debugger before starting up the boot drivers
616 */
617 #ifdef KDBG
618 KdbEnter();
619 #endif /* KDBG */
620
621 IoCreateDriverList();
622
623 IoInit2();
624
625 /* Pass 3: process boot loaded drivers */
626 BootDriverCount = 0;
627 for (i=1; i < KeLoaderBlock.ModsCount; i++)
628 {
629 start = KeLoaderModules[i].ModStart;
630 length = KeLoaderModules[i].ModEnd - start;
631 name = (PCHAR)KeLoaderModules[i].String;
632 if (RtlpCheckFileNameExtension(name, ".sys") ||
633 RtlpCheckFileNameExtension(name, ".sym"))
634 {
635 CPRINT("Initializing driver '%s' at %08lx, length 0x%08lx\n",
636 name, start, length);
637 LdrInitializeBootStartDriver((PVOID)start, name, length);
638 }
639 if (RtlpCheckFileNameExtension(name, ".sys"))
640 BootDriverCount++;
641 }
642
643 /* Pass 4: free memory for all boot files, except ntoskrnl.exe and hal.dll */
644 for (i = 2; i < KeLoaderBlock.ModsCount; i++)
645 {
646 MiFreeBootDriverMemory((PVOID)KeLoaderModules[i].ModStart,
647 KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart);
648 }
649
650 if (BootDriverCount == 0)
651 {
652 DbgPrint("No boot drivers available.\n");
653 KeBugCheck(0);
654 }
655
656 /* Create ARC names for boot devices */
657 IoCreateArcNames();
658
659 /* Create the SystemRoot symbolic link */
660 CPRINT("CommandLine: %s\n", (PUCHAR)KeLoaderBlock.CommandLine);
661 Status = IoCreateSystemRootLink((PUCHAR)KeLoaderBlock.CommandLine);
662 if (!NT_SUCCESS(Status))
663 KeBugCheck(INACCESSIBLE_BOOT_DEVICE);
664
665 #ifdef DBGPRINT_FILE_LOG
666 /* On the assumption that we can now access disks start up the debug
667 logger thread */
668 DebugLogInit2();
669 #endif /* DBGPRINT_FILE_LOG */
670
671 #ifdef KDBG
672 KdbInitProfiling2();
673 #endif /* KDBG */
674
675
676 PiInitDefaultLocale();
677
678 /*
679 * Start the motherboard enumerator (the HAL)
680 */
681 HalInitSystem(2, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
682 #if 0
683 /*
684 * Load boot start drivers
685 */
686 IopLoadBootStartDrivers();
687 #else
688 /*
689 * Load Auto configured drivers
690 */
691 LdrLoadAutoConfigDrivers();
692 #endif
693
694 IoDestroyDriverList();
695
696 /*
697 * Assign drive letters
698 */
699 IoAssignDriveLetters ((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock,
700 NULL,
701 NULL,
702 NULL);
703
704 /*
705 * Initialize shared user page:
706 * - set dos system path, dos device map, etc.
707 */
708 InitSystemSharedUserPage ((PUCHAR)KeLoaderBlock.CommandLine);
709
710 /*
711 * Launch initial process
712 */
713 Status = LdrLoadInitialProcess(&ProcessHandle,
714 &ThreadHandle);
715 if (!NT_SUCCESS(Status))
716 {
717 KeBugCheckEx(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
718 }
719
720 /*
721 * Crash the system if the initial process terminates within 5 seconds.
722 */
723 Timeout.QuadPart = -50000000LL;
724 Status = NtWaitForSingleObject(ProcessHandle,
725 FALSE,
726 &Timeout);
727 if (Status != STATUS_TIMEOUT)
728 {
729 KeBugCheckEx(SESSION5_INITIALIZATION_FAILED, Status, 0, 0, 0);
730 }
731
732 NtClose(ThreadHandle);
733 NtClose(ProcessHandle);
734
735 PsTerminateSystemThread(STATUS_SUCCESS);
736 }
737
738
739 VOID
740 KiSystemStartup(BOOLEAN BootProcessor)
741 {
742 HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
743
744 if (BootProcessor)
745 {
746 /* Never returns */
747 ExpInitializeExecutive();
748 KeBugCheck(0);
749 }
750 /* Do application processor initialization */
751 KeApplicationProcessorInit();
752 PsApplicationProcessorInit();
753 KeLowerIrql(PASSIVE_LEVEL);
754 PsIdleThreadMain(NULL);
755 KeBugCheck(0);
756 for(;;);
757 }
758
759 VOID
760 _main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock)
761 /*
762 * FUNCTION: Called by the boot loader to start the kernel
763 * ARGUMENTS:
764 * LoaderBlock = Pointer to boot parameters initialized by the boot
765 * loader
766 * NOTE: The boot parameters are stored in low memory which will become
767 * invalid after the memory managment is initialized so we make a local copy.
768 */
769 {
770 ULONG i;
771 ULONG size;
772 ULONG last_kernel_address;
773 extern ULONG _bss_end__;
774 ULONG HalBase;
775 ULONG DriverBase;
776 ULONG DriverSize;
777
778 /* Low level architecture specific initialization */
779 KeInit1();
780
781 /*
782 * Copy the parameters to a local buffer because lowmem will go away
783 */
784 memcpy(&KeLoaderBlock, _LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
785 memcpy(&KeLoaderModules[1], (PVOID)KeLoaderBlock.ModsAddr,
786 sizeof(LOADER_MODULE) * KeLoaderBlock.ModsCount);
787 KeLoaderBlock.ModsCount++;
788 KeLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
789
790 /*
791 * Convert a path specification in the grub format to one understood by the
792 * rest of the kernel.
793 */
794 if (((PUCHAR)_LoaderBlock->CommandLine)[0] == '(')
795 {
796 ULONG DiskNumber = 0, PartNumber = 0;
797 PCH p;
798 CHAR Temp[256];
799 PCH options;
800 PCH s1;
801
802 if (((PUCHAR)_LoaderBlock->CommandLine)[1] == 'h' &&
803 ((PUCHAR)_LoaderBlock->CommandLine)[2] == 'd')
804 {
805 DiskNumber = ((PUCHAR)_LoaderBlock->CommandLine)[3] - '0';
806 PartNumber = ((PUCHAR)_LoaderBlock->CommandLine)[5] - '0';
807 }
808 strcpy(Temp, &((PUCHAR)_LoaderBlock->CommandLine)[7]);
809 if ((options = strchr(Temp, ' ')) != NULL)
810 {
811 *options = 0;
812 options++;
813 }
814 else
815 {
816 options = "";
817 }
818 if ((s1 = strrchr(Temp, '/')) != NULL)
819 {
820 *s1 = 0;
821 if ((s1 = strrchr(Temp, '/')) != NULL)
822 {
823 *s1 = 0;
824 }
825 }
826 sprintf(KeLoaderCommandLine,
827 "multi(0)disk(0)rdisk(%lu)partition(%lu)%s %s",
828 DiskNumber, PartNumber + 1, Temp, options);
829
830 p = KeLoaderCommandLine;
831 while (*p != 0 && *p != ' ')
832 {
833 if ((*p) == '/')
834 {
835 (*p) = '\\';
836 }
837 p++;
838 }
839 DPRINT1("Command Line: %s\n", KeLoaderCommandLine);
840 }
841 else
842 {
843 strcpy(KeLoaderCommandLine, (PUCHAR)_LoaderBlock->CommandLine);
844 }
845 KeLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
846
847 strcpy(KeLoaderModuleStrings[0], "ntoskrnl.exe");
848 KeLoaderModules[0].String = (ULONG)KeLoaderModuleStrings[0];
849 KeLoaderModules[0].ModStart = 0xC0000000;
850 KeLoaderModules[0].ModEnd = PAGE_ROUND_UP((ULONG)&_bss_end__);
851 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
852 {
853 CHAR* s;
854 if ((s = strrchr((PUCHAR)KeLoaderModules[i].String, '/')) != 0)
855 {
856 strcpy(KeLoaderModuleStrings[i], s + 1);
857 }
858 else
859 {
860 strcpy(KeLoaderModuleStrings[i], (PUCHAR)KeLoaderModules[i].String);
861 }
862 KeLoaderModules[i].ModStart -= 0x200000;
863 KeLoaderModules[i].ModStart += 0xc0000000;
864 KeLoaderModules[i].ModEnd -= 0x200000;
865 KeLoaderModules[i].ModEnd += 0xc0000000;
866 KeLoaderModules[i].String = (ULONG)KeLoaderModuleStrings[i];
867 }
868
869 #ifdef HAL_DBG
870 HalnInitializeDisplay((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
871 #endif
872
873 HalBase = KeLoaderModules[1].ModStart;
874 DriverBase =
875 PAGE_ROUND_UP(KeLoaderModules[KeLoaderBlock.ModsCount - 1].ModEnd);
876
877 /*
878 * Process hal.dll
879 */
880 LdrSafePEProcessModule((PVOID)HalBase, (PVOID)DriverBase, (PVOID)0xC0000000, &DriverSize);
881
882 LdrHalBase = (ULONG_PTR)DriverBase;
883 last_kernel_address = DriverBase + DriverSize;
884
885 /*
886 * Process ntoskrnl.exe
887 */
888 LdrSafePEProcessModule((PVOID)0xC0000000, (PVOID)0xC0000000, (PVOID)DriverBase, &DriverSize);
889
890 FirstKrnlPhysAddr = KeLoaderModules[0].ModStart - 0xc0000000 + 0x200000;
891 LastKrnlPhysAddr = last_kernel_address - 0xc0000000 + 0x200000;
892 LastKernelAddress = last_kernel_address;
893
894 #ifndef ACPI
895 /* FIXME: VMware does not like it when ReactOS is using the BIOS memory map */
896 KeLoaderBlock.Flags &= ~MB_FLAGS_MMAP_INFO;
897 #endif
898
899 KeMemoryMapRangeCount = 0;
900 if (KeLoaderBlock.Flags & MB_FLAGS_MMAP_INFO)
901 {
902 /* We have a memory map from the nice BIOS */
903 size = *((PULONG)(KeLoaderBlock.MmapAddr - sizeof(ULONG)));
904 i = 0;
905 while (i < KeLoaderBlock.MmapLength)
906 {
907 memcpy (&KeMemoryMap[KeMemoryMapRangeCount],
908 (PVOID)(KeLoaderBlock.MmapAddr + i),
909 sizeof(ADDRESS_RANGE));
910 KeMemoryMapRangeCount++;
911 i += size;
912 }
913 }
914
915 KiSystemStartup(1);
916 }
917
918 /* EOF */
919