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