Temporary fix to prevent a crash when running in VMware (and possibly bochs too)
[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.101 2001/07/14 21:10:31 chorns 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/module.h>
36 #include <internal/ldr.h>
37 #include <internal/ex.h>
38 #include <internal/ps.h>
39 #include <internal/ke.h>
40 #include <internal/io.h>
41 #include <internal/po.h>
42 //#include <internal/se.h>
43 #include <napi/shared_data.h>
44 #include <internal/v86m.h>
45 #include <internal/kd.h>
46 #include <internal/trap.h>
47 #include "../dbg/kdb.h"
48
49 #define NDEBUG
50 #include <internal/debug.h>
51
52 /* GLOBALS *******************************************************************/
53
54 ULONG EXPORTED NtBuildNumber = KERNEL_VERSION_BUILD;
55 ULONG EXPORTED NtGlobalFlag = 0;
56 CHAR EXPORTED KeNumberProcessors;
57 LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock;
58 static LOADER_MODULE KeLoaderModules[64];
59 static UCHAR KeLoaderModuleStrings[64][256];
60 static UCHAR KeLoaderCommandLine[256];
61 static ADDRESS_RANGE KeMemoryMap[64];
62 static ULONG KeMemoryMapRangeCount;
63 static ULONG FirstKrnlPhysAddr;
64 static ULONG LastKrnlPhysAddr;
65 static ULONG LastKernelAddress;
66 volatile BOOLEAN Initialized = FALSE;
67
68 /* FUNCTIONS ****************************************************************/
69
70 static BOOLEAN
71 RtlpCheckFileNameExtension(PCHAR FileName,
72 PCHAR Extension)
73 {
74 PCHAR Ext;
75
76 Ext = strrchr(FileName, '.');
77 if ((Extension == NULL) || (*Extension == 0))
78 {
79 if (Ext == NULL)
80 return TRUE;
81 else
82 return FALSE;
83 }
84 if (*Extension != '.')
85 Ext++;
86
87 if (_stricmp(Ext, Extension) == 0)
88 return TRUE;
89 else
90 return FALSE;
91 }
92
93 static VOID
94 CreateSystemRootLink (PCSZ ParameterLine)
95 {
96 UNICODE_STRING LinkName;
97 UNICODE_STRING DeviceName;
98 UNICODE_STRING ArcName;
99 UNICODE_STRING BootPath;
100 PCHAR ParamBuffer;
101 PWCHAR ArcNameBuffer;
102 PCHAR p;
103 NTSTATUS Status;
104 ULONG Length;
105 OBJECT_ATTRIBUTES ObjectAttributes;
106 HANDLE Handle;
107
108 /* create local parameter line copy */
109 ParamBuffer = ExAllocatePool (PagedPool, 256);
110 strcpy (ParamBuffer, (char *)ParameterLine);
111
112 DPRINT("%s\n", ParamBuffer);
113 /* Format: <arc_name>\<path> [options...] */
114
115 /* cut options off */
116 p = strchr (ParamBuffer, ' ');
117 if (p)
118 *p = 0;
119 DPRINT("%s\n", ParamBuffer);
120
121 /* extract path */
122 p = strchr (ParamBuffer, '\\');
123 if (p)
124 {
125 DPRINT("Boot path: %s\n", p);
126 RtlCreateUnicodeStringFromAsciiz (&BootPath, p);
127 *p = 0;
128 }
129 else
130 {
131 DPRINT("Boot path: %s\n", "\\");
132 RtlCreateUnicodeStringFromAsciiz (&BootPath, "\\");
133 }
134 DPRINT("Arc name: %s\n", ParamBuffer);
135
136 /* Only arc name left - build full arc name */
137 ArcNameBuffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
138 swprintf (ArcNameBuffer,
139 L"\\ArcName\\%S", ParamBuffer);
140 RtlInitUnicodeString (&ArcName, ArcNameBuffer);
141 DPRINT1("Arc name: %wZ\n", &ArcName);
142
143 /* free ParamBuffer */
144 ExFreePool (ParamBuffer);
145
146 /* allocate device name string */
147 DeviceName.Length = 0;
148 DeviceName.MaximumLength = 256 * sizeof(WCHAR);
149 DeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
150
151 InitializeObjectAttributes (&ObjectAttributes,
152 &ArcName,
153 0,
154 NULL,
155 NULL);
156
157 Status = NtOpenSymbolicLinkObject (&Handle,
158 SYMBOLIC_LINK_ALL_ACCESS,
159 &ObjectAttributes);
160 if (!NT_SUCCESS(Status))
161 {
162 RtlFreeUnicodeString (&BootPath);
163 RtlFreeUnicodeString (&DeviceName);
164 DPRINT("NtOpenSymbolicLinkObject() '%wZ' failed (Status %x)\n",
165 &ArcName,
166 Status);
167 RtlFreeUnicodeString (&ArcName);
168
169 KeBugCheck (0x0);
170 }
171 RtlFreeUnicodeString (&ArcName);
172
173 Status = NtQuerySymbolicLinkObject (Handle,
174 &DeviceName,
175 &Length);
176 NtClose (Handle);
177 if (!NT_SUCCESS(Status))
178 {
179 RtlFreeUnicodeString (&BootPath);
180 RtlFreeUnicodeString (&DeviceName);
181 DbgPrint("NtQuerySymbolicObject() failed (Status %x)\n",
182 Status);
183
184 KeBugCheck (0x0);
185 }
186 DPRINT("Length: %lu DeviceName: %wZ\n", Length, &DeviceName);
187
188 RtlAppendUnicodeStringToString (&DeviceName,
189 &BootPath);
190
191 RtlFreeUnicodeString (&BootPath);
192 DPRINT("DeviceName: %wZ\n", &DeviceName);
193
194 /* create the '\SystemRoot' link */
195 RtlInitUnicodeString (&LinkName,
196 L"\\SystemRoot");
197
198 Status = IoCreateSymbolicLink (&LinkName,
199 &DeviceName);
200 RtlFreeUnicodeString (&DeviceName);
201 if (!NT_SUCCESS(Status))
202 {
203 DbgPrint("IoCreateSymbolicLink() failed (Status %x)\n",
204 Status);
205
206 KeBugCheck (0x0);
207 }
208
209 /* Check if '\SystemRoot'(LinkName) can be opened, otherwise crash it! */
210 InitializeObjectAttributes (&ObjectAttributes,
211 &LinkName,
212 0,
213 NULL,
214 NULL);
215
216 Status = NtOpenSymbolicLinkObject (&Handle,
217 SYMBOLIC_LINK_ALL_ACCESS,
218 &ObjectAttributes);
219 if (!NT_SUCCESS(Status))
220 {
221 DbgPrint("NtOpenSymbolicLinkObject() failed to open '\\SystemRoot' (Status %x)\n",
222 Status);
223 KeBugCheck (0x0);
224 }
225 NtClose(Handle);
226 }
227
228
229 static VOID
230 InitSystemSharedUserPage (PCSZ ParameterLine)
231 {
232 PKUSER_SHARED_DATA SharedPage;
233
234 UNICODE_STRING ArcDeviceName;
235 UNICODE_STRING ArcName;
236 UNICODE_STRING BootPath;
237 UNICODE_STRING DriveDeviceName;
238 UNICODE_STRING DriveName;
239 WCHAR DriveNameBuffer[20];
240 PCHAR ParamBuffer;
241 PWCHAR ArcNameBuffer;
242 PCHAR p;
243 NTSTATUS Status;
244 ULONG Length;
245 OBJECT_ATTRIBUTES ObjectAttributes;
246 HANDLE Handle;
247 ULONG i;
248 BOOLEAN BootDriveFound;
249
250 SharedPage = (PKUSER_SHARED_DATA)KERNEL_SHARED_DATA_BASE;
251 SharedPage->DosDeviceMap = 0;
252 SharedPage->NtProductType = NtProductWinNt;
253 for (i = 0; i < 32; i++)
254 {
255 SharedPage->DosDeviceDriveType[i] = 0;
256 }
257
258 BootDriveFound = FALSE;
259
260 /*
261 * Retrieve the current dos system path
262 * (e.g.: C:\reactos) from the given arc path
263 * (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos)
264 * Format: "<arc_name>\<path> [options...]"
265 */
266
267 /* create local parameter line copy */
268 ParamBuffer = ExAllocatePool (PagedPool, 256);
269 strcpy (ParamBuffer, (char *)ParameterLine);
270 DPRINT("%s\n", ParamBuffer);
271
272 /* cut options off */
273 p = strchr (ParamBuffer, ' ');
274 if (p)
275 {
276 *p = 0;
277 }
278 DPRINT("%s\n", ParamBuffer);
279
280 /* extract path */
281 p = strchr (ParamBuffer, '\\');
282 if (p)
283 {
284 DPRINT("Boot path: %s\n", p);
285 RtlCreateUnicodeStringFromAsciiz (&BootPath, p);
286 *p = 0;
287 }
288 else
289 {
290 DPRINT("Boot path: %s\n", "\\");
291 RtlCreateUnicodeStringFromAsciiz (&BootPath, "\\");
292 }
293 DPRINT("Arc name: %s\n", ParamBuffer);
294
295 /* Only arc name left - build full arc name */
296 ArcNameBuffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
297 swprintf (ArcNameBuffer, L"\\ArcName\\%S", ParamBuffer);
298 RtlInitUnicodeString (&ArcName, ArcNameBuffer);
299 DPRINT("Arc name: %wZ\n", &ArcName);
300
301 /* free ParamBuffer */
302 ExFreePool (ParamBuffer);
303
304 /* allocate arc device name string */
305 ArcDeviceName.Length = 0;
306 ArcDeviceName.MaximumLength = 256 * sizeof(WCHAR);
307 ArcDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
308
309 InitializeObjectAttributes (&ObjectAttributes,
310 &ArcName,
311 0,
312 NULL,
313 NULL);
314
315 Status = NtOpenSymbolicLinkObject (&Handle,
316 SYMBOLIC_LINK_ALL_ACCESS,
317 &ObjectAttributes);
318 RtlFreeUnicodeString (&ArcName);
319 if (!NT_SUCCESS(Status))
320 {
321 RtlFreeUnicodeString (&BootPath);
322 RtlFreeUnicodeString (&ArcDeviceName);
323 DbgPrint("NtOpenSymbolicLinkObject() failed (Status %x)\n",
324 Status);
325
326 KeBugCheck (0x0);
327 }
328
329 Status = NtQuerySymbolicLinkObject (Handle,
330 &ArcDeviceName,
331 &Length);
332 NtClose (Handle);
333 if (!NT_SUCCESS(Status))
334 {
335 RtlFreeUnicodeString (&BootPath);
336 RtlFreeUnicodeString (&ArcDeviceName);
337 DbgPrint("NtQuerySymbolicObject() failed (Status %x)\n",
338 Status);
339
340 KeBugCheck (0x0);
341 }
342 DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length, &ArcDeviceName);
343
344
345 /* allocate device name string */
346 DriveDeviceName.Length = 0;
347 DriveDeviceName.MaximumLength = 256 * sizeof(WCHAR);
348 DriveDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
349
350 for (i = 0; i < 26; i++)
351 {
352 swprintf (DriveNameBuffer, L"\\??\\%C:", 'A' + i);
353 RtlInitUnicodeString (&DriveName,
354 DriveNameBuffer);
355
356 InitializeObjectAttributes (&ObjectAttributes,
357 &DriveName,
358 0,
359 NULL,
360 NULL);
361
362 Status = NtOpenSymbolicLinkObject (&Handle,
363 SYMBOLIC_LINK_ALL_ACCESS,
364 &ObjectAttributes);
365 if (!NT_SUCCESS(Status))
366 {
367 DPRINT("Failed to open link %wZ\n",
368 &DriveName);
369 continue;
370 }
371
372 Status = NtQuerySymbolicLinkObject (Handle,
373 &DriveDeviceName,
374 &Length);
375 if (!NT_SUCCESS(Status))
376 {
377 DPRINT("Failed query open link %wZ\n",
378 &DriveName);
379 continue;
380 }
381 DPRINT("Opened link: %wZ ==> %wZ\n",
382 &DriveName, &DriveDeviceName);
383
384 if (!RtlCompareUnicodeString (&ArcDeviceName, &DriveDeviceName, FALSE))
385 {
386 DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i, &BootPath);
387 swprintf (SharedPage->NtSystemRoot,
388 L"%C:%wZ", 'A' + i, &BootPath);
389
390 BootDriveFound = TRUE;
391 }
392
393 NtClose (Handle);
394
395 /* set bit in dos drives bitmap (drive available) */
396 SharedPage->DosDeviceMap |= (1<<i);
397 }
398
399 RtlFreeUnicodeString (&BootPath);
400 RtlFreeUnicodeString (&DriveDeviceName);
401 RtlFreeUnicodeString (&ArcDeviceName);
402
403 DPRINT("DosDeviceMap: 0x%x\n", SharedPage->DosDeviceMap);
404
405 if (BootDriveFound == FALSE)
406 {
407 DbgPrint("No system drive found!\n");
408 KeBugCheck (0x0);
409 }
410 }
411
412 #ifndef NDEBUG
413
414 VOID DumpBIOSMemoryMap(VOID)
415 {
416 ULONG i;
417
418 DbgPrint("Dumping BIOS memory map:\n");
419 DbgPrint("Memory map base: %d\n", KeLoaderBlock.MmapAddr);
420 DbgPrint("Memory map size: %d\n", KeLoaderBlock.MmapLength);
421 DbgPrint("Address range count: %d\n", KeMemoryMapRangeCount);
422 for (i = 0; i < KeMemoryMapRangeCount; i++)
423 {
424 DbgPrint("Range: Base (%08X) Length (%08X) Type (%02X)\n",
425 KeMemoryMap[i].BaseAddrLow,
426 KeMemoryMap[i].LengthLow,
427 KeMemoryMap[i].Type);
428 }
429 for (;;);
430 }
431
432 #endif /* !NDEBUG */
433
434 VOID
435 ExpInitializeExecutive(VOID)
436 {
437 ULONG i;
438 ULONG start;
439 ULONG length;
440 PCHAR name;
441 CHAR str[50];
442
443 /*
444 * Fail at runtime if someone has changed various structures without
445 * updating the offsets used for the assembler code.
446 */
447 assert(FIELD_OFFSET(KTHREAD, InitialStack) == KTHREAD_INITIAL_STACK);
448 assert(FIELD_OFFSET(KTHREAD, Teb) == KTHREAD_TEB);
449 assert(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK);
450 assert(FIELD_OFFSET(KTHREAD, PreviousMode) == KTHREAD_PREVIOUS_MODE);
451 assert(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME);
452 assert(FIELD_OFFSET(ETHREAD, ThreadsProcess) == ETHREAD_THREADS_PROCESS);
453 assert(FIELD_OFFSET(KPROCESS, DirectoryTableBase) ==
454 KPROCESS_DIRECTORY_TABLE_BASE);
455 assert(FIELD_OFFSET(KTRAP_FRAME, Reserved9) == KTRAP_FRAME_RESERVED9);
456 assert(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
457 assert(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
458
459 assert(FIELD_OFFSET(KPCR, ExceptionList) == KPCR_EXCEPTION_LIST);
460 assert(FIELD_OFFSET(KPCR, Self) == KPCR_SELF);
461 assert(FIELD_OFFSET(KPCR, CurrentThread) == KPCR_CURRENT_THREAD);
462
463 LdrInit1();
464
465 KeLowerIrql(DISPATCH_LEVEL);
466
467 NtEarlyInitVdm();
468
469 MmInit1(FirstKrnlPhysAddr,
470 LastKrnlPhysAddr,
471 LastKernelAddress,
472 (PADDRESS_RANGE)&KeMemoryMap,
473 KeMemoryMapRangeCount);
474
475 /*
476 * Initialize the kernel debugger
477 */
478 KdInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
479 if (KdPollBreakIn ())
480 {
481 DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
482 }
483
484 MmInit2();
485 KeInit2();
486
487 KeLowerIrql(PASSIVE_LEVEL);
488
489 ObInit();
490 PiInitProcessManager();
491
492 /*
493 * Display version number and copyright/warranty message
494 */
495 HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR" (Build "
496 KERNEL_VERSION_BUILD_STR")\n");
497 HalDisplayString(RES_STR_LEGAL_COPYRIGHT);
498 HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
499 "Public License, and you\n");
500 HalDisplayString("are welcome to change it and/or distribute copies of it "
501 "under certain\n");
502 HalDisplayString("conditions. There is absolutely no warranty for "
503 "ReactOS.\n\n");
504
505 /* Initialize all processors */
506 KeNumberProcessors = 0;
507
508 while (!HalAllProcessorsStarted())
509 {
510 if (KeNumberProcessors != 0)
511 {
512 KePrepareForApplicationProcessorInit(KeNumberProcessors);
513 PsPrepareForApplicationProcessorInit(KeNumberProcessors);
514 }
515 HalInitializeProcessor(KeNumberProcessors);
516 KeNumberProcessors++;
517 }
518
519 if (KeNumberProcessors > 1)
520 {
521 sprintf(str,
522 "Found %d system processors. [%lu MB Memory]\n",
523 KeNumberProcessors,
524 (KeLoaderBlock.MemHigher + 1088)/ 1024);
525 }
526 else
527 {
528 sprintf(str,
529 "Found 1 system processor. [%lu MB Memory]\n",
530 (KeLoaderBlock.MemHigher + 1088)/ 1024);
531 }
532 HalDisplayString(str);
533
534 /*
535 * Initialize various critical subsystems
536 */
537 HalInitSystem(1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
538
539 ExInit();
540 IoInit();
541 PoInit();
542 LdrInitModuleManagement();
543 CmInitializeRegistry();
544 NtInit();
545 MmInit3();
546
547 /* Report all resources used by hal */
548 HalReportResourceUsage();
549
550 // DumpBIOSMemoryMap();
551
552 /*
553 * Initalize services loaded at boot time
554 */
555 DPRINT1("%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: load nls files */
565 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
566 {
567 name = (PCHAR)KeLoaderModules[i].String;
568 if (RtlpCheckFileNameExtension(name, ".nls"))
569 {
570 ULONG Mod2Start = 0;
571 ULONG Mod2End = 0;
572 ULONG Mod3Start = 0;
573 ULONG Mod3End = 0;
574
575 name = (PCHAR)KeLoaderModules[i+1].String;
576 if (RtlpCheckFileNameExtension(name, ".nls"))
577 {
578 Mod2Start = (ULONG)KeLoaderModules[i+1].ModStart;
579 Mod2End = (ULONG)KeLoaderModules[i+1].ModEnd;
580
581 name = (PCHAR)KeLoaderModules[i+2].String;
582 if (RtlpCheckFileNameExtension(name, ".nls"))
583 {
584 Mod3Start = (ULONG)KeLoaderModules[i+2].ModStart;
585 Mod3End = (ULONG)KeLoaderModules[i+2].ModEnd;
586 }
587 }
588
589 /* Initialize nls sections */
590 RtlpInitNlsSections((ULONG)KeLoaderModules[i].ModStart,
591 (ULONG)KeLoaderModules[i].ModEnd,
592 Mod2Start,
593 Mod2End,
594 Mod3Start,
595 Mod3End);
596 break;
597 }
598 }
599
600 /* Pass 2: load registry chunks passed in */
601 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
602 {
603 start = KeLoaderModules[i].ModStart;
604 name = (PCHAR)KeLoaderModules[i].String;
605 if (RtlpCheckFileNameExtension(name, "") ||
606 RtlpCheckFileNameExtension(name, ".hiv"))
607 {
608 CPRINT("Process registry chunk at %08lx\n", start);
609 CmImportHive((PCHAR) start);
610 }
611 }
612
613 /*
614 * Enter the kernel debugger before starting up the boot drivers
615 */
616 #ifdef KDBG
617 KdbEnter();
618 #endif /* KDBG */
619
620 /* Pass 3: process boot loaded drivers */
621 for (i=1; i < KeLoaderBlock.ModsCount; i++)
622 {
623 start = KeLoaderModules[i].ModStart;
624 length = KeLoaderModules[i].ModEnd - start;
625 name = (PCHAR)KeLoaderModules[i].String;
626 if (RtlpCheckFileNameExtension(name, ".sys") ||
627 RtlpCheckFileNameExtension(name, ".sym"))
628 {
629 CPRINT("Processing module '%s' at %08lx, length 0x%08lx\n",
630 name, start, length);
631 LdrProcessDriver((PVOID)start, name, length);
632 }
633 }
634
635 /* Create the SystemRoot symbolic link */
636 CPRINT("CommandLine: %s\n", (PUCHAR)KeLoaderBlock.CommandLine);
637
638 CreateSystemRootLink ((PUCHAR)KeLoaderBlock.CommandLine);
639
640 #ifdef DBGPRINT_FILE_LOG
641 /* On the assumption that we can now access disks start up the debug
642 logger thread */
643 DebugLogInit2();
644 #endif /* DBGPRINT_FILE_LOG */
645
646
647 CmInitializeRegistry2();
648
649 PiInitDefaultLocale();
650
651 /*
652 * Start the motherboard enumerator (the HAL)
653 */
654 HalInitSystem(2, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
655
656 /*
657 * Load boot start drivers
658 */
659 IopLoadBootStartDrivers();
660
661 /*
662 * Load Auto configured drivers
663 */
664 LdrLoadAutoConfigDrivers();
665
666 /*
667 * Assign drive letters
668 */
669 IoAssignDriveLetters ((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock,
670 NULL,
671 NULL,
672 NULL);
673
674 /*
675 * Initialize shared user page:
676 * - set dos system path, dos device map, etc.
677 */
678 InitSystemSharedUserPage ((PUCHAR)KeLoaderBlock.CommandLine);
679
680 /*
681 * Launch initial process
682 */
683 LdrLoadInitialProcess();
684
685 PsTerminateSystemThread(STATUS_SUCCESS);
686 }
687
688 VOID
689 KiSystemStartup(BOOLEAN BootProcessor)
690 {
691 HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
692 if (BootProcessor)
693 {
694 /* Never returns */
695 ExpInitializeExecutive();
696 KeBugCheck(0);
697 }
698 /* Do application processor initialization */
699 KeApplicationProcessorInit();
700 PsApplicationProcessorInit();
701 KeLowerIrql(PASSIVE_LEVEL);
702 PsIdleThreadMain(NULL);
703 KeBugCheck(0);
704 for(;;);
705 }
706
707 VOID
708 _main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock)
709 /*
710 * FUNCTION: Called by the boot loader to start the kernel
711 * ARGUMENTS:
712 * LoaderBlock = Pointer to boot parameters initialized by the boot
713 * loader
714 * NOTE: The boot parameters are stored in low memory which will become
715 * invalid after the memory managment is initialized so we make a local copy.
716 */
717 {
718 ULONG i;
719 ULONG size;
720 ULONG last_kernel_address;
721 extern ULONG _bss_end__;
722
723 /*
724 * Copy the parameters to a local buffer because lowmem will go away
725 */
726 memcpy (&KeLoaderBlock, _LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
727 memcpy (&KeLoaderModules[1], (PVOID)KeLoaderBlock.ModsAddr,
728 sizeof(LOADER_MODULE) * KeLoaderBlock.ModsCount);
729 KeLoaderBlock.ModsCount++;
730 KeLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
731
732 /*
733 * FIXME: Preliminary hack!!!! Add boot device to beginning of command line.
734 * This should be done by the boot loader.
735 */
736 strcpy (KeLoaderCommandLine,
737 "multi(0)disk(0)rdisk(0)partition(1)\\reactos /DEBUGPORT=SCREEN");
738 strcat (KeLoaderCommandLine, (PUCHAR)KeLoaderBlock.CommandLine);
739
740 KeLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
741 strcpy(KeLoaderModuleStrings[0], "ntoskrnl.exe");
742 KeLoaderModules[0].String = (ULONG)KeLoaderModuleStrings[0];
743 KeLoaderModules[0].ModStart = 0xC0000000;
744 KeLoaderModules[0].ModEnd = PAGE_ROUND_UP((ULONG)&_bss_end__);
745 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
746 {
747 strcpy(KeLoaderModuleStrings[i], (PUCHAR)KeLoaderModules[i].String);
748 KeLoaderModules[i].ModStart -= 0x200000;
749 KeLoaderModules[i].ModStart += 0xc0000000;
750 KeLoaderModules[i].ModEnd -= 0x200000;
751 KeLoaderModules[i].ModEnd += 0xc0000000;
752 KeLoaderModules[i].String = (ULONG)KeLoaderModuleStrings[i];
753 }
754
755 last_kernel_address = KeLoaderModules[KeLoaderBlock.ModsCount - 1].ModEnd;
756
757 FirstKrnlPhysAddr = KeLoaderModules[0].ModStart - 0xc0000000 + 0x200000;
758 LastKrnlPhysAddr = last_kernel_address - 0xc0000000 + 0x200000;
759 LastKernelAddress = last_kernel_address;
760
761 #ifndef ACPI
762 /* FIXME: VMware does not like it when ReactOS is using the BIOS memory map */
763 KeLoaderBlock.Flags &= ~MB_FLAGS_MMAP_INFO;
764 #endif
765
766 KeMemoryMapRangeCount = 0;
767 if (KeLoaderBlock.Flags & MB_FLAGS_MMAP_INFO)
768 {
769 /* We have a memory map from the nice BIOS */
770 size = *((PULONG)(KeLoaderBlock.MmapAddr - sizeof(ULONG)));
771 i = 0;
772 while (i < KeLoaderBlock.MmapLength)
773 {
774 memcpy (&KeMemoryMap[KeMemoryMapRangeCount],
775 (PVOID)(KeLoaderBlock.MmapAddr + i),
776 sizeof(ADDRESS_RANGE));
777 KeMemoryMapRangeCount++;
778 i += size;
779 }
780 }
781
782 KeInit1();
783
784 KiSystemStartup(1);
785 }
786
787 /* EOF */
788