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