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