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