3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
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.
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.
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.
21 * PROJECT: ReactOS kernel
22 * FILE: ntoskrnl/ke/main.c
23 * PURPOSE: Initalizes the kernel
24 * PROGRAMMER: David Welch (welch@cwcom.net)
29 /* INCLUDES *****************************************************************/
31 #define NTOS_MODE_KERNEL
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 #include <napi/core.h>
57 #include <internal/ntosdbg.h>
63 #include <internal/debug.h>
65 /* GLOBALS *******************************************************************/
67 ULONG EXPORTED NtBuildNumber = KERNEL_VERSION_BUILD;
68 ULONG EXPORTED NtGlobalFlag = 0;
69 CHAR EXPORTED KeNumberProcessors;
70 LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock;
71 ULONG EXPORTED KeDcacheFlushCount = 0;
72 ULONG EXPORTED KeIcacheFlushCount = 0;
73 static LOADER_MODULE KeLoaderModules[64];
74 static UCHAR KeLoaderModuleStrings[64][256];
75 static UCHAR KeLoaderCommandLine[256];
76 static ADDRESS_RANGE KeMemoryMap[64];
77 static ULONG KeMemoryMapRangeCount;
78 static ULONG FirstKrnlPhysAddr;
79 static ULONG LastKrnlPhysAddr;
80 static ULONG LastKernelAddress;
81 volatile BOOLEAN Initialized = FALSE;
82 extern ULONG MmCoreDumpType;
84 extern PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS];
87 /* FUNCTIONS ****************************************************************/
90 RtlpCheckFileNameExtension(PCHAR FileName,
95 Ext = strrchr(FileName, '.');
98 if ((Extension == NULL) || (*Extension == 0))
104 if (*Extension != '.')
107 if (_stricmp(Ext, Extension) == 0)
115 InitSystemSharedUserPage (PCSZ ParameterLine)
117 UNICODE_STRING ArcDeviceName;
118 UNICODE_STRING ArcName;
119 UNICODE_STRING BootPath;
120 UNICODE_STRING DriveDeviceName;
121 UNICODE_STRING DriveName;
122 WCHAR DriveNameBuffer[20];
124 PWCHAR ArcNameBuffer;
128 OBJECT_ATTRIBUTES ObjectAttributes;
131 BOOLEAN BootDriveFound;
135 * The shared user page has been zeroed-out right after creation.
136 * There is NO need to do this again.
139 SharedUserData->NtProductType = NtProductWinNt;
141 BootDriveFound = FALSE;
144 * Retrieve the current dos system path
145 * (e.g.: C:\reactos) from the given arc path
146 * (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos)
147 * Format: "<arc_name>\<path> [options...]"
150 /* create local parameter line copy */
151 ParamBuffer = ExAllocatePool (PagedPool, 256);
152 strcpy (ParamBuffer, (char *)ParameterLine);
153 DPRINT("%s\n", ParamBuffer);
155 /* cut options off */
156 p = strchr (ParamBuffer, ' ');
161 DPRINT("%s\n", ParamBuffer);
164 p = strchr (ParamBuffer, '\\');
167 DPRINT("Boot path: %s\n", p);
168 RtlCreateUnicodeStringFromAsciiz (&BootPath, p);
173 DPRINT("Boot path: %s\n", "\\");
174 RtlCreateUnicodeStringFromAsciiz (&BootPath, "\\");
176 DPRINT("Arc name: %s\n", ParamBuffer);
178 /* Only arc name left - build full arc name */
179 ArcNameBuffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
180 swprintf (ArcNameBuffer, L"\\ArcName\\%S", ParamBuffer);
181 RtlInitUnicodeString (&ArcName, ArcNameBuffer);
182 DPRINT("Arc name: %wZ\n", &ArcName);
184 /* free ParamBuffer */
185 ExFreePool (ParamBuffer);
187 /* allocate arc device name string */
188 ArcDeviceName.Length = 0;
189 ArcDeviceName.MaximumLength = 256 * sizeof(WCHAR);
190 ArcDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
192 InitializeObjectAttributes (&ObjectAttributes,
198 Status = NtOpenSymbolicLinkObject (&Handle,
199 SYMBOLIC_LINK_ALL_ACCESS,
201 RtlFreeUnicodeString (&ArcName);
202 if (!NT_SUCCESS(Status))
204 RtlFreeUnicodeString (&BootPath);
205 RtlFreeUnicodeString (&ArcDeviceName);
206 CPRINT("NtOpenSymbolicLinkObject() failed (Status %x)\n",
212 Status = NtQuerySymbolicLinkObject (Handle,
216 if (!NT_SUCCESS(Status))
218 RtlFreeUnicodeString (&BootPath);
219 RtlFreeUnicodeString (&ArcDeviceName);
220 CPRINT("NtQuerySymbolicObject() failed (Status %x)\n",
225 DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length, &ArcDeviceName);
228 /* allocate device name string */
229 DriveDeviceName.Length = 0;
230 DriveDeviceName.MaximumLength = 256 * sizeof(WCHAR);
231 DriveDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
233 for (i = 0; i < 26; i++)
235 swprintf (DriveNameBuffer, L"\\??\\%C:", 'A' + i);
236 RtlInitUnicodeString (&DriveName,
239 InitializeObjectAttributes (&ObjectAttributes,
245 Status = NtOpenSymbolicLinkObject (&Handle,
246 SYMBOLIC_LINK_ALL_ACCESS,
248 if (!NT_SUCCESS(Status))
250 DPRINT("Failed to open link %wZ\n",
255 Status = NtQuerySymbolicLinkObject (Handle,
258 if (!NT_SUCCESS(Status))
260 DPRINT("Failed query open link %wZ\n",
264 DPRINT("Opened link: %wZ ==> %wZ\n",
265 &DriveName, &DriveDeviceName);
267 if (!RtlCompareUnicodeString (&ArcDeviceName, &DriveDeviceName, FALSE))
269 DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i, &BootPath);
270 swprintf(SharedUserData->NtSystemRoot,
271 L"%C:%wZ", 'A' + i, &BootPath);
273 BootDriveFound = TRUE;
279 RtlFreeUnicodeString (&BootPath);
280 RtlFreeUnicodeString (&DriveDeviceName);
281 RtlFreeUnicodeString (&ArcDeviceName);
283 DPRINT("DosDeviceMap: 0x%x\n", SharedUserData->DosDeviceMap);
285 if (BootDriveFound == FALSE)
287 DbgPrint("No system drive found!\n");
293 MiFreeBootDriverMemory(PVOID StartAddress, ULONG Length)
295 PHYSICAL_ADDRESS Page;
298 for (i = 0; i < PAGE_ROUND_UP(Length)/PAGE_SIZE; i++)
300 Page = MmGetPhysicalAddressForProcess(NULL, StartAddress + i * PAGE_SIZE);
301 MmDeleteVirtualMapping(NULL, StartAddress + i * PAGE_SIZE, FALSE, NULL, NULL);
302 MmDereferencePage(Page);
307 ExpInitializeExecutive(VOID)
309 LARGE_INTEGER Timeout;
310 HANDLE ProcessHandle;
312 ULONG BootDriverCount;
322 BOOLEAN NoBootScreen = FALSE;
324 HANDLE InitDoneEventHandle;
325 OBJECT_ATTRIBUTES ObjectAttributes;
328 * Fail at runtime if someone has changed various structures without
329 * updating the offsets used for the assembler code.
331 assert(FIELD_OFFSET(KTHREAD, InitialStack) == KTHREAD_INITIAL_STACK);
332 assert(FIELD_OFFSET(KTHREAD, Teb) == KTHREAD_TEB);
333 assert(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK);
334 assert(FIELD_OFFSET(KTHREAD, ServiceTable) == KTHREAD_SERVICE_TABLE);
335 assert(FIELD_OFFSET(KTHREAD, PreviousMode) == KTHREAD_PREVIOUS_MODE);
336 assert(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME);
337 assert(FIELD_OFFSET(KTHREAD, CallbackStack) == KTHREAD_CALLBACK_STACK);
338 assert(FIELD_OFFSET(ETHREAD, ThreadsProcess) == ETHREAD_THREADS_PROCESS);
339 assert(FIELD_OFFSET(KPROCESS, DirectoryTableBase) ==
340 KPROCESS_DIRECTORY_TABLE_BASE);
341 assert(FIELD_OFFSET(KPROCESS, IopmOffset) == KPROCESS_IOPM_OFFSET);
342 assert(FIELD_OFFSET(KPROCESS, LdtDescriptor) == KPROCESS_LDT_DESCRIPTOR0);
343 assert(FIELD_OFFSET(KTRAP_FRAME, Reserved9) == KTRAP_FRAME_RESERVED9);
344 assert(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
345 assert(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
347 assert(FIELD_OFFSET(KPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
348 assert(FIELD_OFFSET(KPCR, Self) == KPCR_SELF);
349 assert(FIELD_OFFSET(IKPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
350 assert(FIELD_OFFSET(IKPCR, Self) == KPCR_SELF);
351 assert(FIELD_OFFSET(IKPCR, CurrentThread) == KPCR_CURRENT_THREAD);
355 KeLowerIrql(DISPATCH_LEVEL);
359 p1 = (PCHAR)KeLoaderBlock.CommandLine;
362 while(*p1 && (p2 = strchr(p1, '/')))
365 if (!_strnicmp(p2, "MAXMEM", 6))
368 while (isspace(*p2)) p2++;
372 while(isspace(*p2)) p2++;
377 MaxMem = MaxMem * 10 + *p2 - '0';
384 else if (!_strnicmp(p2, "NOBOOTSCREEN", 12))
389 else if (!_strnicmp(p2, "CRASHDUMP", 9))
395 if (!_strnicmp(p2, "FULL", 4))
397 MmCoreDumpType = MM_CORE_DUMP_TYPE_FULL;
401 MmCoreDumpType = MM_CORE_DUMP_TYPE_NONE;
408 MmInit1(FirstKrnlPhysAddr,
411 (PADDRESS_RANGE)&KeMemoryMap,
412 KeMemoryMapRangeCount,
413 MaxMem > 8 ? MaxMem : 4096);
415 /* Import ANSI code page table */
416 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
418 start = KeLoaderModules[i].ModStart;
419 length = KeLoaderModules[i].ModEnd - start;
421 name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
424 name = (PCHAR)KeLoaderModules[i].String;
431 if (!_stricmp (name, "ansi.nls"))
433 RtlpImportAnsiCodePage((PUSHORT)start, length);
437 /* Import OEM code page table */
438 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
440 start = KeLoaderModules[i].ModStart;
441 length = KeLoaderModules[i].ModEnd - start;
443 name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
446 name = (PCHAR)KeLoaderModules[i].String;
453 if (!_stricmp (name, "oem.nls"))
455 RtlpImportOemCodePage((PUSHORT)start, length);
459 /* Import Unicode casemap table */
460 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
462 start = KeLoaderModules[i].ModStart;
463 length = KeLoaderModules[i].ModEnd - start;
465 name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
468 name = (PCHAR)KeLoaderModules[i].String;
475 if (!_stricmp (name, "casemap.nls"))
477 RtlpImportUnicodeCasemap((PUSHORT)start, length);
481 /* Create initial NLS tables */
482 RtlpCreateInitialNlsTables();
485 * Initialize the kernel debugger
487 KdInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
492 KeLowerIrql(PASSIVE_LEVEL);
495 KEBUGCHECK(SECURITY_INITIALIZATION_FAILED);
500 KEBUGCHECK(SECURITY1_INITIALIZATION_FAILED);
502 PiInitProcessManager();
506 if (KdPollBreakIn ())
508 DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
511 /* Initialize all processors */
512 KeNumberProcessors = 0;
514 while (!HalAllProcessorsStarted())
516 PVOID ProcessorStack;
518 if (KeNumberProcessors != 0)
520 KePrepareForApplicationProcessorInit(KeNumberProcessors);
521 PsPrepareForApplicationProcessorInit(KeNumberProcessors);
523 /* Allocate a stack for use when booting the processor */
524 /* FIXME: The nonpaged memory for the stack is not released after use */
526 ExAllocatePool(NonPagedPool, MM_STACK_SIZE) + MM_STACK_SIZE;
527 Ki386InitialStackArray[((int)KeNumberProcessors)] =
528 (PVOID)(ProcessorStack - MM_STACK_SIZE);
529 HalInitializeProcessor(KeNumberProcessors, ProcessorStack);
530 KeNumberProcessors++;
534 * Initialize various critical subsystems
536 HalInitSystem(1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
541 LdrInitModuleManagement();
542 CmInitializeRegistry();
547 FsRtlpInitFileLockingImplementation();
549 /* Report all resources used by hal */
550 HalReportResourceUsage();
553 * Clear the screen to blue
555 HalInitSystem(2, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
558 * Display version number and copyright/warranty message
560 HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR" (Build "
561 KERNEL_VERSION_BUILD_STR")\n");
562 HalDisplayString(RES_STR_LEGAL_COPYRIGHT);
563 HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
564 "Public License, and you\n");
565 HalDisplayString("are welcome to change it and/or distribute copies of it "
567 HalDisplayString("conditions. There is absolutely no warranty for "
570 if (KeNumberProcessors > 1)
573 "Found %d system processors. [%lu MB Memory]\n",
575 (KeLoaderBlock.MemHigher + 1088)/ 1024);
580 "Found 1 system processor. [%lu MB Memory]\n",
581 (KeLoaderBlock.MemHigher + 1088)/ 1024);
583 HalDisplayString(str);
588 /* Create the NLS section */
589 RtlpCreateNlsSection();
592 * Initalize services loaded at boot time
594 DPRINT("%d files loaded\n",KeLoaderBlock.ModsCount);
595 for (i=0; i < KeLoaderBlock.ModsCount; i++)
597 CPRINT("Module: '%s' at %08lx, length 0x%08lx\n",
598 KeLoaderModules[i].String,
599 KeLoaderModules[i].ModStart,
600 KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart);
603 /* Pass 1: import system hive registry chunk */
605 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
607 start = KeLoaderModules[i].ModStart;
608 length = KeLoaderModules[i].ModEnd - start;
610 DPRINT("Module: '%s'\n", (PCHAR)KeLoaderModules[i].String);
611 name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
614 name = (PCHAR)KeLoaderModules[i].String;
621 if (!_stricmp (name, "system") ||
622 !_stricmp (name, "system.hiv"))
624 CPRINT("Process system hive registry chunk at %08lx\n", start);
626 CmImportSystemHive((PCHAR)start, length);
630 /* Pass 2: import hardware hive registry chunk */
631 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
633 start = KeLoaderModules[i].ModStart;
634 length = KeLoaderModules[i].ModEnd - start;
635 name = (PCHAR)KeLoaderModules[i].String;
636 if (!_stricmp (name, "hardware") ||
637 !_stricmp (name, "hardware.hiv"))
639 CPRINT("Process hardware hive registry chunk at %08lx\n", start);
640 CmImportHardwareHive((PCHAR)start, length);
644 /* Create dummy keys if no hardware hive was found */
645 CmImportHardwareHive (NULL, 0);
647 /* Initialize volatile registry settings */
648 if (SetupBoot == FALSE)
650 CmInit2((PCHAR)KeLoaderBlock.CommandLine);
654 * Enter the kernel debugger before starting up the boot drivers
660 IoCreateDriverList();
664 /* Pass 3: process boot loaded drivers */
666 for (i=1; i < KeLoaderBlock.ModsCount; i++)
668 start = KeLoaderModules[i].ModStart;
669 length = KeLoaderModules[i].ModEnd - start;
670 name = (PCHAR)KeLoaderModules[i].String;
671 if (RtlpCheckFileNameExtension(name, ".sys") ||
672 RtlpCheckFileNameExtension(name, ".sym"))
674 CPRINT("Initializing driver '%s' at %08lx, length 0x%08lx\n",
675 name, start, length);
676 LdrInitializeBootStartDriver((PVOID)start, name, length);
678 if (RtlpCheckFileNameExtension(name, ".sys"))
682 /* Pass 4: free memory for all boot files, except ntoskrnl.exe and hal.dll */
683 for (i = 2; i < KeLoaderBlock.ModsCount; i++)
686 /* Do not free the memory from symbol files, if the kernel debugger is activ */
687 if (!RtlpCheckFileNameExtension(name, ".sym"))
690 MiFreeBootDriverMemory((PVOID)KeLoaderModules[i].ModStart,
691 KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart);
695 if (BootDriverCount == 0)
697 DbgPrint("No boot drivers available.\n");
701 /* Display the boot screen image if not disabled */
704 InbvEnableBootDriver(TRUE);
707 /* Create ARC names for boot devices */
710 /* Create the SystemRoot symbolic link */
711 CPRINT("CommandLine: %s\n", (PUCHAR)KeLoaderBlock.CommandLine);
712 Status = IoCreateSystemRootLink((PUCHAR)KeLoaderBlock.CommandLine);
713 if (!NT_SUCCESS(Status))
714 KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE);
716 #ifdef DBGPRINT_FILE_LOG
717 /* On the assumption that we can now access disks start up the debug
720 #endif /* DBGPRINT_FILE_LOG */
726 PiInitDefaultLocale();
730 * Load boot start drivers
732 IopLoadBootStartDrivers();
735 * Load Auto configured drivers
737 LdrLoadAutoConfigDrivers();
740 IoDestroyDriverList();
743 * Assign drive letters
745 IoAssignDriveLetters ((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock,
751 * Initialize shared user page:
752 * - set dos system path, dos device map, etc.
754 InitSystemSharedUserPage ((PUCHAR)KeLoaderBlock.CommandLine);
756 /* Create 'ReactOSInitDone' event */
757 RtlInitUnicodeString(&Name, L"\\ReactOSInitDone");
758 InitializeObjectAttributes(&ObjectAttributes,
763 Status = NtCreateEvent(&InitDoneEventHandle,
766 FALSE, /* Synchronization event */
767 FALSE); /* Not signalled */
768 if (!NT_SUCCESS(Status))
770 DPRINT1("Failed to create 'ReactOSInitDone' event (Status 0x%x)\n", Status);
771 InitDoneEventHandle = INVALID_HANDLE_VALUE;
775 * Launch initial process
777 Status = LdrLoadInitialProcess(&ProcessHandle,
779 if (!NT_SUCCESS(Status))
781 KEBUGCHECKEX(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
784 if (InitDoneEventHandle != INVALID_HANDLE_VALUE)
786 HANDLE Handles[2]; /* Init event, Initial process */
788 Handles[0] = InitDoneEventHandle;
789 Handles[1] = ProcessHandle;
791 /* Wait for the system to be initialized */
792 Timeout.QuadPart = -1200000000LL; /* 120 second timeout */
793 Status = NtWaitForMultipleObjects(((LONG) sizeof(Handles) / sizeof(HANDLE)),
796 FALSE, /* Non-alertable */
798 if (!NT_SUCCESS(Status))
800 DPRINT1("NtWaitForMultipleObjects failed with status 0x%x!\n", Status);
802 else if (Status == STATUS_TIMEOUT)
804 DPRINT1("WARNING: System not initialized after 120 seconds.\n");
806 else if (Status == STATUS_WAIT_0 + 1)
809 * Crash the system if the initial process was terminated.
811 KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 0, 0, 0);
816 InbvEnableBootDriver(FALSE);
819 NtSetEvent(InitDoneEventHandle, NULL);
821 NtClose(InitDoneEventHandle);
825 /* On failure to create 'ReactOSInitDone' event, go to text mode ASAP */
828 InbvEnableBootDriver(FALSE);
832 * Crash the system if the initial process terminates within 5 seconds.
834 Timeout.QuadPart = -50000000LL;
835 Status = NtWaitForSingleObject(ProcessHandle,
838 if (Status != STATUS_TIMEOUT)
840 KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 0, 0, 0);
844 NtClose(ThreadHandle);
845 NtClose(ProcessHandle);
847 PsTerminateSystemThread(STATUS_SUCCESS);
852 KiSystemStartup(BOOLEAN BootProcessor)
854 HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
859 ExpInitializeExecutive();
862 /* Do application processor initialization */
863 KeApplicationProcessorInit();
864 PsApplicationProcessorInit();
865 KeLowerIrql(PASSIVE_LEVEL);
866 PsIdleThreadMain(NULL);
872 _main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock)
874 * FUNCTION: Called by the boot loader to start the kernel
876 * LoaderBlock = Pointer to boot parameters initialized by the boot
878 * NOTE: The boot parameters are stored in low memory which will become
879 * invalid after the memory managment is initialized so we make a local copy.
884 ULONG last_kernel_address;
885 extern ULONG _bss_end__;
890 /* Low level architecture specific initialization */
894 * Copy the parameters to a local buffer because lowmem will go away
896 memcpy(&KeLoaderBlock, _LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
897 memcpy(&KeLoaderModules[1], (PVOID)KeLoaderBlock.ModsAddr,
898 sizeof(LOADER_MODULE) * KeLoaderBlock.ModsCount);
899 KeLoaderBlock.ModsCount++;
900 KeLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
903 * Convert a path specification in the grub format to one understood by the
904 * rest of the kernel.
906 if (((PUCHAR)_LoaderBlock->CommandLine)[0] == '(')
908 ULONG DiskNumber = 0, PartNumber = 0;
914 if (((PUCHAR)_LoaderBlock->CommandLine)[1] == 'h' &&
915 ((PUCHAR)_LoaderBlock->CommandLine)[2] == 'd')
917 DiskNumber = ((PUCHAR)_LoaderBlock->CommandLine)[3] - '0';
918 PartNumber = ((PUCHAR)_LoaderBlock->CommandLine)[5] - '0';
920 strcpy(Temp, &((PUCHAR)_LoaderBlock->CommandLine)[7]);
921 if ((options = strchr(Temp, ' ')) != NULL)
930 if ((s1 = strrchr(Temp, '/')) != NULL)
933 if ((s1 = strrchr(Temp, '/')) != NULL)
938 sprintf(KeLoaderCommandLine,
939 "multi(0)disk(0)rdisk(%lu)partition(%lu)%s %s",
940 DiskNumber, PartNumber + 1, Temp, options);
942 p = KeLoaderCommandLine;
943 while (*p != 0 && *p != ' ')
951 DPRINT1("Command Line: %s\n", KeLoaderCommandLine);
955 strcpy(KeLoaderCommandLine, (PUCHAR)_LoaderBlock->CommandLine);
957 KeLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
959 strcpy(KeLoaderModuleStrings[0], "ntoskrnl.exe");
960 KeLoaderModules[0].String = (ULONG)KeLoaderModuleStrings[0];
961 KeLoaderModules[0].ModStart = 0xC0000000;
962 KeLoaderModules[0].ModEnd = PAGE_ROUND_UP((ULONG)&_bss_end__);
963 for (i = 1; i < KeLoaderBlock.ModsCount; i++)
966 if ((s = strrchr((PUCHAR)KeLoaderModules[i].String, '/')) != 0)
968 strcpy(KeLoaderModuleStrings[i], s + 1);
972 strcpy(KeLoaderModuleStrings[i], (PUCHAR)KeLoaderModules[i].String);
974 KeLoaderModules[i].ModStart -= 0x200000;
975 KeLoaderModules[i].ModStart += 0xc0000000;
976 KeLoaderModules[i].ModEnd -= 0x200000;
977 KeLoaderModules[i].ModEnd += 0xc0000000;
978 KeLoaderModules[i].String = (ULONG)KeLoaderModuleStrings[i];
982 HalnInitializeDisplay((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
985 HalBase = KeLoaderModules[1].ModStart;
987 PAGE_ROUND_UP(KeLoaderModules[KeLoaderBlock.ModsCount - 1].ModEnd);
992 LdrSafePEProcessModule((PVOID)HalBase, (PVOID)DriverBase, (PVOID)0xC0000000, &DriverSize);
994 LdrHalBase = (ULONG_PTR)DriverBase;
995 last_kernel_address = DriverBase + DriverSize;
998 * Process ntoskrnl.exe
1000 LdrSafePEProcessModule((PVOID)0xC0000000, (PVOID)0xC0000000, (PVOID)DriverBase, &DriverSize);
1002 FirstKrnlPhysAddr = KeLoaderModules[0].ModStart - 0xc0000000 + 0x200000;
1003 LastKrnlPhysAddr = last_kernel_address - 0xc0000000 + 0x200000;
1004 LastKernelAddress = last_kernel_address;
1007 /* FIXME: VMware does not like it when ReactOS is using the BIOS memory map */
1008 KeLoaderBlock.Flags &= ~MB_FLAGS_MMAP_INFO;
1011 KeMemoryMapRangeCount = 0;
1012 if (KeLoaderBlock.Flags & MB_FLAGS_MMAP_INFO)
1014 /* We have a memory map from the nice BIOS */
1015 size = *((PULONG)(KeLoaderBlock.MmapAddr - sizeof(ULONG)));
1017 while (i < KeLoaderBlock.MmapLength)
1019 memcpy (&KeMemoryMap[KeMemoryMapRangeCount],
1020 (PVOID)(KeLoaderBlock.MmapAddr + i),
1021 sizeof(ADDRESS_RANGE));
1022 KeMemoryMapRangeCount++;