Ouch!
[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.145 2002/12/07 15:43:29 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 <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 BOOLEAN SetupBoot;
301
302 /*
303 * Fail at runtime if someone has changed various structures without
304 * updating the offsets used for the assembler code.
305 */
306 assert(FIELD_OFFSET(KTHREAD, InitialStack) == KTHREAD_INITIAL_STACK);
307 assert(FIELD_OFFSET(KTHREAD, Teb) == KTHREAD_TEB);
308 assert(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK);
309 assert(FIELD_OFFSET(KTHREAD, PreviousMode) == KTHREAD_PREVIOUS_MODE);
310 assert(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME);
311 assert(FIELD_OFFSET(KTHREAD, CallbackStack) == KTHREAD_CALLBACK_STACK);
312 assert(FIELD_OFFSET(ETHREAD, ThreadsProcess) == ETHREAD_THREADS_PROCESS);
313 assert(FIELD_OFFSET(KPROCESS, DirectoryTableBase) ==
314 KPROCESS_DIRECTORY_TABLE_BASE);
315 assert(FIELD_OFFSET(KTRAP_FRAME, Reserved9) == KTRAP_FRAME_RESERVED9);
316 assert(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
317 assert(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
318
319 assert(FIELD_OFFSET(KPCR, ExceptionList) == KPCR_EXCEPTION_LIST);
320 assert(FIELD_OFFSET(KPCR, Self) == KPCR_SELF);
321 assert(FIELD_OFFSET(KPCR, CurrentThread) == KPCR_CURRENT_THREAD);
322
323 LdrInit1();
324
325 KeLowerIrql(DISPATCH_LEVEL);
326
327 NtEarlyInitVdm();
328
329 MmInit1(FirstKrnlPhysAddr,
330 LastKrnlPhysAddr,
331 LastKernelAddress,
332 (PADDRESS_RANGE)&KeMemoryMap,
333 KeMemoryMapRangeCount);
334
335 /* create default nls tables */
336 RtlpInitNlsTables();
337
338 /*
339 * Initialize the kernel debugger
340 */
341 KdInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
342
343 MmInit2();
344 KeInit2();
345
346 KeLowerIrql(PASSIVE_LEVEL);
347
348 if (!SeInit1())
349 KeBugCheck(SECURITY_INITIALIZATION_FAILED);
350
351 ObInit();
352
353 if (!SeInit2())
354 KeBugCheck(SECURITY1_INITIALIZATION_FAILED);
355
356 PiInitProcessManager();
357
358 KdInit1();
359
360 if (KdPollBreakIn ())
361 {
362 DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
363 }
364
365 /*
366 * Display version number and copyright/warranty message
367 */
368 HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR" (Build "
369 KERNEL_VERSION_BUILD_STR")\n");
370 HalDisplayString(RES_STR_LEGAL_COPYRIGHT);
371 HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
372 "Public License, and you\n");
373 HalDisplayString("are welcome to change it and/or distribute copies of it "
374 "under certain\n");
375 HalDisplayString("conditions. There is absolutely no warranty for "
376 "ReactOS.\n\n");
377
378 /* Initialize all processors */
379 KeNumberProcessors = 0;
380
381 while (!HalAllProcessorsStarted())
382 {
383 PVOID ProcessorStack;
384
385 if (KeNumberProcessors != 0)
386 {
387 KePrepareForApplicationProcessorInit(KeNumberProcessors);
388 PsPrepareForApplicationProcessorInit(KeNumberProcessors);
389 }
390 /* Allocate a stack for use when booting the processor */
391 /* FIXME: The nonpaged memory for the stack is not released after use */
392 ProcessorStack =
393 ExAllocatePool(NonPagedPool, MM_STACK_SIZE) + MM_STACK_SIZE;
394 Ki386InitialStackArray[((int)KeNumberProcessors)] =
395 (PVOID)(ProcessorStack - MM_STACK_SIZE);
396 HalInitializeProcessor(KeNumberProcessors, ProcessorStack);
397 KeNumberProcessors++;
398 }
399
400 if (KeNumberProcessors > 1)
401 {
402 sprintf(str,
403 "Found %d system processors. [%u MB Memory]\n",
404 KeNumberProcessors,
405 (KeLoaderBlock.MemHigher + 1088)/ 1024);
406 }
407 else
408 {
409 sprintf(str,
410 "Found 1 system processor. [%u MB Memory]\n",
411 (KeLoaderBlock.MemHigher + 1088)/ 1024);
412 }
413 HalDisplayString(str);
414
415 /*
416 * Initialize various critical subsystems
417 */
418 HalInitSystem(1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
419
420 ExInit();
421 IoInit();
422 PoInit();
423 LdrInitModuleManagement();
424 CmInitializeRegistry();
425 NtInit();
426 MmInit3();
427 CcInit();
428 KdInit2();
429 FsRtlpInitFileLockingImplementation();
430
431 /* Report all resources used by hal */
432 HalReportResourceUsage();
433
434 /*
435 * Initalize services loaded at boot time
436 */
437 DPRINT("%d files loaded\n",KeLoaderBlock.ModsCount);
438 for (i=0; i < KeLoaderBlock.ModsCount; i++)
439 {
440 CPRINT("Module: '%s' at %08lx, length 0x%08lx\n",
441 KeLoaderModules[i].String,
442 KeLoaderModules[i].ModStart,
443 KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart);
444 }
445
446 /* Pass 1: load nls files */
447 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
448 {
449 name = (PCHAR)KeLoaderModules[i].String;
450 if (RtlpCheckFileNameExtension(name, ".nls"))
451 {
452 ULONG Mod2Start = 0;
453 ULONG Mod2End = 0;
454 ULONG Mod3Start = 0;
455 ULONG Mod3End = 0;
456
457 name = (PCHAR)KeLoaderModules[i+1].String;
458 if (RtlpCheckFileNameExtension(name, ".nls"))
459 {
460 Mod2Start = (ULONG)KeLoaderModules[i+1].ModStart;
461 Mod2End = (ULONG)KeLoaderModules[i+1].ModEnd;
462
463 name = (PCHAR)KeLoaderModules[i+2].String;
464 if (RtlpCheckFileNameExtension(name, ".nls"))
465 {
466 Mod3Start = (ULONG)KeLoaderModules[i+2].ModStart;
467 Mod3End = (ULONG)KeLoaderModules[i+2].ModEnd;
468 }
469 }
470
471 /* Initialize nls sections */
472 RtlpInitNlsSections((ULONG)KeLoaderModules[i].ModStart,
473 (ULONG)KeLoaderModules[i].ModEnd,
474 Mod2Start,
475 Mod2End,
476 Mod3Start,
477 Mod3End);
478 break;
479 }
480 }
481
482 /* Pass 2: load registry chunks passed in */
483 SetupBoot = TRUE;
484 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
485 {
486 start = KeLoaderModules[i].ModStart;
487 length = KeLoaderModules[i].ModEnd - start;
488 name = (PCHAR)KeLoaderModules[i].String;
489 if (RtlpCheckFileNameExtension(name, "") ||
490 RtlpCheckFileNameExtension(name, ".hiv"))
491 {
492 CPRINT("Process registry chunk at %08lx\n", start);
493 CmImportHive((PCHAR)start, length);
494 }
495 if (_stricmp(name, "system") == 0 ||
496 _stricmp(name, "system.hiv") == 0)
497 {
498 SetupBoot = FALSE;
499 }
500 }
501
502 /* Initialize volatile registry settings */
503 if (SetupBoot == FALSE)
504 {
505 CmInit2((PCHAR)KeLoaderBlock.CommandLine);
506 }
507
508 /*
509 * Enter the kernel debugger before starting up the boot drivers
510 */
511 #ifdef KDBG
512 KdbEnter();
513 #endif /* KDBG */
514
515 IoCreateDriverList();
516
517 /* Pass 3: process boot loaded drivers */
518 BootDriverCount = 0;
519 for (i=1; i < KeLoaderBlock.ModsCount; i++)
520 {
521 start = KeLoaderModules[i].ModStart;
522 length = KeLoaderModules[i].ModEnd - start;
523 name = (PCHAR)KeLoaderModules[i].String;
524 if (RtlpCheckFileNameExtension(name, ".sys") ||
525 RtlpCheckFileNameExtension(name, ".sym"))
526 {
527 CPRINT("Initializing driver '%s' at %08lx, length 0x%08lx\n",
528 name, start, length);
529 LdrInitializeBootStartDriver((PVOID)start, name, length);
530 }
531 if (RtlpCheckFileNameExtension(name, ".sys"))
532 BootDriverCount++;
533 }
534
535 if (BootDriverCount == 0)
536 {
537 DbgPrint("No boot drivers available.\n");
538 KeBugCheck(0);
539 }
540
541 /* Create ARC names for boot devices */
542 IoCreateArcNames();
543
544 /* Create the SystemRoot symbolic link */
545 CPRINT("CommandLine: %s\n", (PUCHAR)KeLoaderBlock.CommandLine);
546 Status = IoCreateSystemRootLink((PUCHAR)KeLoaderBlock.CommandLine);
547 if (!NT_SUCCESS(Status))
548 KeBugCheck(INACCESSIBLE_BOOT_DEVICE);
549
550 #ifdef DBGPRINT_FILE_LOG
551 /* On the assumption that we can now access disks start up the debug
552 logger thread */
553 DebugLogInit2();
554 #endif /* DBGPRINT_FILE_LOG */
555
556
557 PiInitDefaultLocale();
558
559 /*
560 * Start the motherboard enumerator (the HAL)
561 */
562 HalInitSystem(2, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
563 #if 0
564 /*
565 * Load boot start drivers
566 */
567 IopLoadBootStartDrivers();
568 #else
569 /*
570 * Load Auto configured drivers
571 */
572 LdrLoadAutoConfigDrivers();
573 #endif
574
575 IoDestroyDriverList();
576
577 /*
578 * Assign drive letters
579 */
580 IoAssignDriveLetters ((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock,
581 NULL,
582 NULL,
583 NULL);
584
585 /*
586 * Initialize shared user page:
587 * - set dos system path, dos device map, etc.
588 */
589 InitSystemSharedUserPage ((PUCHAR)KeLoaderBlock.CommandLine);
590
591 /*
592 * Launch initial process
593 */
594 Status = LdrLoadInitialProcess(&ProcessHandle,
595 &ThreadHandle);
596 if (!NT_SUCCESS(Status))
597 {
598 KeBugCheckEx(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
599 }
600
601 /*
602 * Crash the system if the initial process terminates within 5 seconds.
603 */
604 Timeout.QuadPart = -50000000LL;
605 Status = NtWaitForSingleObject(ProcessHandle,
606 FALSE,
607 &Timeout);
608 if (Status != STATUS_TIMEOUT)
609 {
610 KeBugCheckEx(SESSION5_INITIALIZATION_FAILED, Status, 0, 0, 0);
611 }
612
613 NtClose(ThreadHandle);
614 NtClose(ProcessHandle);
615
616 PsTerminateSystemThread(STATUS_SUCCESS);
617 }
618
619
620 VOID
621 KiSystemStartup(BOOLEAN BootProcessor)
622 {
623 HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
624
625 if (BootProcessor)
626 {
627 /* Never returns */
628 ExpInitializeExecutive();
629 KeBugCheck(0);
630 }
631 /* Do application processor initialization */
632 KeApplicationProcessorInit();
633 PsApplicationProcessorInit();
634 KeLowerIrql(PASSIVE_LEVEL);
635 PsIdleThreadMain(NULL);
636 KeBugCheck(0);
637 for(;;);
638 }
639
640 VOID
641 _main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock)
642 /*
643 * FUNCTION: Called by the boot loader to start the kernel
644 * ARGUMENTS:
645 * LoaderBlock = Pointer to boot parameters initialized by the boot
646 * loader
647 * NOTE: The boot parameters are stored in low memory which will become
648 * invalid after the memory managment is initialized so we make a local copy.
649 */
650 {
651 ULONG i;
652 ULONG size;
653 ULONG last_kernel_address;
654 extern ULONG _bss_end__;
655 ULONG HalBase;
656 ULONG DriverBase;
657 ULONG DriverSize;
658
659 /* Low level architecture specific initialization */
660 KeInit1();
661
662 /*
663 * Copy the parameters to a local buffer because lowmem will go away
664 */
665 memcpy(&KeLoaderBlock, _LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
666 memcpy(&KeLoaderModules[1], (PVOID)KeLoaderBlock.ModsAddr,
667 sizeof(LOADER_MODULE) * KeLoaderBlock.ModsCount);
668 KeLoaderBlock.ModsCount++;
669 KeLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
670
671 /*
672 * Convert a path specification in the grub format to one understood by the
673 * rest of the kernel.
674 */
675 if (((PUCHAR)_LoaderBlock->CommandLine)[0] == '(')
676 {
677 ULONG DiskNumber = 0, PartNumber = 0;
678 PCH p;
679 CHAR Temp[256];
680 PCH options;
681 PCH s1;
682
683 if (((PUCHAR)_LoaderBlock->CommandLine)[1] == 'h' &&
684 ((PUCHAR)_LoaderBlock->CommandLine)[2] == 'd')
685 {
686 DiskNumber = ((PUCHAR)_LoaderBlock->CommandLine)[3] - '0';
687 PartNumber = ((PUCHAR)_LoaderBlock->CommandLine)[5] - '0';
688 }
689 strcpy(Temp, &((PUCHAR)_LoaderBlock->CommandLine)[7]);
690 if ((options = strchr(Temp, ' ')) != NULL)
691 {
692 *options = 0;
693 options++;
694 }
695 else
696 {
697 options = "";
698 }
699 if ((s1 = strrchr(Temp, '/')) != NULL)
700 {
701 *s1 = 0;
702 if ((s1 = strrchr(Temp, '/')) != NULL)
703 {
704 *s1 = 0;
705 }
706 }
707 sprintf(KeLoaderCommandLine,
708 "multi(0)disk(0)rdisk(%d)partition(%d)%s %s",
709 DiskNumber, PartNumber + 1, Temp, options);
710
711 p = KeLoaderCommandLine;
712 while (*p != 0 && *p != ' ')
713 {
714 if ((*p) == '/')
715 {
716 (*p) = '\\';
717 }
718 p++;
719 }
720 DPRINT1("Command Line: %s\n", KeLoaderCommandLine);
721 }
722 else
723 {
724 strcpy(KeLoaderCommandLine, (PUCHAR)_LoaderBlock->CommandLine);
725 }
726 KeLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
727
728 strcpy(KeLoaderModuleStrings[0], "ntoskrnl.exe");
729 KeLoaderModules[0].String = (ULONG)KeLoaderModuleStrings[0];
730 KeLoaderModules[0].ModStart = 0xC0000000;
731 KeLoaderModules[0].ModEnd = PAGE_ROUND_UP((ULONG)&_bss_end__);
732 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
733 {
734 CHAR* s;
735 if ((s = strrchr((PUCHAR)KeLoaderModules[i].String, '/')) != 0)
736 {
737 strcpy(KeLoaderModuleStrings[i], s + 1);
738 }
739 else
740 {
741 strcpy(KeLoaderModuleStrings[i], (PUCHAR)KeLoaderModules[i].String);
742 }
743 KeLoaderModules[i].ModStart -= 0x200000;
744 KeLoaderModules[i].ModStart += 0xc0000000;
745 KeLoaderModules[i].ModEnd -= 0x200000;
746 KeLoaderModules[i].ModEnd += 0xc0000000;
747 KeLoaderModules[i].String = (ULONG)KeLoaderModuleStrings[i];
748 }
749
750 #ifdef HAL_DBG
751 HalnInitializeDisplay((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
752 #endif
753
754 HalBase = KeLoaderModules[1].ModStart;
755 DriverBase =
756 PAGE_ROUND_UP(KeLoaderModules[KeLoaderBlock.ModsCount - 1].ModEnd);
757
758 /*
759 * Process hal.dll
760 */
761 LdrSafePEProcessModule((PVOID)HalBase, (PVOID)DriverBase, (PVOID)0xC0000000, &DriverSize);
762
763 LdrHalBase = (ULONG_PTR)DriverBase;
764 last_kernel_address = DriverBase + DriverSize;
765
766 /*
767 * Process ntoskrnl.exe
768 */
769 LdrSafePEProcessModule((PVOID)0xC0000000, (PVOID)0xC0000000, (PVOID)DriverBase, &DriverSize);
770
771 FirstKrnlPhysAddr = KeLoaderModules[0].ModStart - 0xc0000000 + 0x200000;
772 LastKrnlPhysAddr = last_kernel_address - 0xc0000000 + 0x200000;
773 LastKernelAddress = last_kernel_address;
774
775 #ifndef ACPI
776 /* FIXME: VMware does not like it when ReactOS is using the BIOS memory map */
777 KeLoaderBlock.Flags &= ~MB_FLAGS_MMAP_INFO;
778 #endif
779
780 KeMemoryMapRangeCount = 0;
781 if (KeLoaderBlock.Flags & MB_FLAGS_MMAP_INFO)
782 {
783 /* We have a memory map from the nice BIOS */
784 size = *((PULONG)(KeLoaderBlock.MmapAddr - sizeof(ULONG)));
785 i = 0;
786 while (i < KeLoaderBlock.MmapLength)
787 {
788 memcpy (&KeMemoryMap[KeMemoryMapRangeCount],
789 (PVOID)(KeLoaderBlock.MmapAddr + i),
790 sizeof(ADDRESS_RANGE));
791 KeMemoryMapRangeCount++;
792 i += size;
793 }
794 }
795
796 KiSystemStartup(1);
797 }
798
799 /* EOF */
800