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