2003-08-11 Casper S. Hornstrup <chorns@users.sourceforge.net>
[reactos.git] / reactos / ntoskrnl / ke / main.c
index ec5c5cc..e23817a 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: main.c,v 1.81 2001/03/18 19:35:12 dwelch Exp $
+/* $Id: main.c,v 1.167 2003/08/11 18:50:12 chorns Exp $
  *
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ke/main.c
 
 /* INCLUDES *****************************************************************/
 
-#include <ddk/ntddk.h>
+#define NTOS_MODE_KERNEL
+#include <ntos.h>
 #include <internal/ntoskrnl.h>
 #include <reactos/resource.h>
 #include <internal/mm.h>
+#include <internal/ifs.h>
 #include <internal/module.h>
 #include <internal/ldr.h>
 #include <internal/ex.h>
 #include <internal/ps.h>
 #include <internal/ke.h>
 #include <internal/io.h>
-#include <napi/shared_data.h>
+#include <internal/po.h>
+#include <internal/cc.h>
+#include <internal/se.h>
 #include <internal/v86m.h>
 #include <internal/kd.h>
+#include <internal/trap.h>
+#include "../dbg/kdb.h"
+#include <internal/registry.h>
+#include <internal/nls.h>
+#include <reactos/bugcodes.h>
+#include <ntos/bootvid.h>
+
+#ifdef HALDBG
+#include <internal/ntosdbg.h>
+#else
+#define ps(args...)
+#endif
 
 #define NDEBUG
 #include <internal/debug.h>
 
 ULONG EXPORTED NtBuildNumber = KERNEL_VERSION_BUILD;
 ULONG EXPORTED NtGlobalFlag = 0;
-CHAR  EXPORTED KeNumberProcessors = 1;
+CHAR  EXPORTED KeNumberProcessors;
 LOADER_PARAMETER_BLOCK EXPORTED KeLoaderBlock;
+ULONG EXPORTED KeDcacheFlushCount = 0;
+ULONG EXPORTED KeIcacheFlushCount = 0;
 static LOADER_MODULE KeLoaderModules[64];
 static UCHAR KeLoaderModuleStrings[64][256];
 static UCHAR KeLoaderCommandLine[256];
+static ADDRESS_RANGE KeMemoryMap[64];
+static ULONG KeMemoryMapRangeCount;
+static ULONG FirstKrnlPhysAddr;
+static ULONG LastKrnlPhysAddr;
+static ULONG LastKernelAddress;
+volatile BOOLEAN Initialized = FALSE;
 
-/* FUNCTIONS ****************************************************************/
+extern PVOID Ki386InitialStackArray[MAXIMUM_PROCESSORS];
 
-static VOID
-CreateSystemRootLink (PCSZ ParameterLine)
-{
-       UNICODE_STRING LinkName;
-       UNICODE_STRING DeviceName;
-       UNICODE_STRING ArcName;
-       UNICODE_STRING BootPath;
-       PCHAR ParamBuffer;
-       PWCHAR ArcNameBuffer;
-       PCHAR p;
-       NTSTATUS Status;
-       ULONG Length;
-       OBJECT_ATTRIBUTES ObjectAttributes;
-       HANDLE Handle;
-
-       /* create local parameter line copy */
-       ParamBuffer = ExAllocatePool (PagedPool, 256);
-       strcpy (ParamBuffer, (char *)ParameterLine);
-
-       DPRINT("%s\n", ParamBuffer);
-       /* Format: <arc_name>\<path> [options...] */
-
-       /* cut options off */
-       p = strchr (ParamBuffer, ' ');
-       if (p)
-               *p = 0;
-       DPRINT("%s\n", ParamBuffer);
-
-       /* extract path */
-       p = strchr (ParamBuffer, '\\');
-       if (p)
-       {
-               DPRINT("Boot path: %s\n", p);
-               RtlCreateUnicodeStringFromAsciiz (&BootPath, p);
-               *p = 0;
-       }
-       else
-       {
-               DPRINT("Boot path: %s\n", "\\");
-               RtlCreateUnicodeStringFromAsciiz (&BootPath, "\\");
-       }
-       DPRINT("Arc name: %s\n", ParamBuffer);
-       
-       /* Only arc name left - build full arc name */
-       ArcNameBuffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
-       swprintf (ArcNameBuffer,
-                 L"\\ArcName\\%S", ParamBuffer);
-       RtlInitUnicodeString (&ArcName, ArcNameBuffer);
-       DPRINT1("Arc name: %wZ\n", &ArcName);
-
-       /* free ParamBuffer */
-       ExFreePool (ParamBuffer);
-
-       /* allocate device name string */
-       DeviceName.Length = 0;
-       DeviceName.MaximumLength = 256 * sizeof(WCHAR);
-       DeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
-
-       InitializeObjectAttributes (&ObjectAttributes,
-                                   &ArcName,
-                                   0,
-                                   NULL,
-                                   NULL);
 
-       Status = NtOpenSymbolicLinkObject (&Handle,
-                                          SYMBOLIC_LINK_ALL_ACCESS,
-                                          &ObjectAttributes);
-       if (!NT_SUCCESS(Status))
-       {
-               RtlFreeUnicodeString (&BootPath);
-               RtlFreeUnicodeString (&DeviceName);
-               DbgPrint("NtOpenSymbolicLinkObject() '%wZ' failed (Status %x)\n",
-                        &ArcName,
-                        Status);
-               RtlFreeUnicodeString (&ArcName);
-
-               KeBugCheck (0x0);
-       }
-       RtlFreeUnicodeString (&ArcName);
-
-       Status = NtQuerySymbolicLinkObject (Handle,
-                                           &DeviceName,
-                                           &Length);
-       NtClose (Handle);
-       if (!NT_SUCCESS(Status))
-       {
-               RtlFreeUnicodeString (&BootPath);
-               RtlFreeUnicodeString (&DeviceName);
-               DbgPrint("NtQuerySymbolicObject() failed (Status %x)\n",
-                        Status);
-
-               KeBugCheck (0x0);
-       }
-       DPRINT("Length: %lu DeviceName: %wZ\n", Length, &DeviceName);
-
-       RtlAppendUnicodeStringToString (&DeviceName,
-                                       &BootPath);
-
-       RtlFreeUnicodeString (&BootPath);
-       DPRINT("DeviceName: %wZ\n", &DeviceName);
-
-       /* create the '\SystemRoot' link */
-       RtlInitUnicodeString (&LinkName,
-                             L"\\SystemRoot");
+/* FUNCTIONS ****************************************************************/
 
-       Status = IoCreateSymbolicLink (&LinkName,
-                                      &DeviceName);
-       RtlFreeUnicodeString (&DeviceName);
-       if (!NT_SUCCESS(Status))
-       {
-               DbgPrint("IoCreateSymbolicLink() failed (Status %x)\n",
-                        Status);
+static BOOLEAN
+RtlpCheckFileNameExtension(PCHAR FileName,
+                          PCHAR Extension)
+{
+  PCHAR Ext;
 
-               KeBugCheck (0x0);
-       }
+  Ext = strrchr(FileName, '.');
+  if (Ext == NULL)
+    {
+      if ((Extension == NULL) || (*Extension == 0))
+       return TRUE;
+      else
+       return FALSE;
+    }
 
-       /* Check if '\SystemRoot'(LinkName) can be opened, otherwise crash it! */
-       InitializeObjectAttributes (&ObjectAttributes,
-                                   &LinkName,
-                                   0,
-                                   NULL,
-                                   NULL);
+  if (*Extension != '.')
+    Ext++;
 
-       Status = NtOpenSymbolicLinkObject (&Handle,
-                                          SYMBOLIC_LINK_ALL_ACCESS,
-                                          &ObjectAttributes);
-       if (!NT_SUCCESS(Status))
-       {
-               DbgPrint("NtOpenSymbolicLinkObject() failed to open '\\SystemRoot' (Status %x)\n",
-                        Status);
-               KeBugCheck (0x0);
-       }
-       NtClose(Handle);
+  if (_stricmp(Ext, Extension) == 0)
+    return TRUE;
+  else
+    return FALSE;
 }
 
 
 static VOID
 InitSystemSharedUserPage (PCSZ ParameterLine)
 {
-   PKUSER_SHARED_DATA SharedPage;
-
    UNICODE_STRING ArcDeviceName;
    UNICODE_STRING ArcName;
    UNICODE_STRING BootPath;
@@ -214,13 +128,13 @@ InitSystemSharedUserPage (PCSZ ParameterLine)
    ULONG i;
    BOOLEAN BootDriveFound;
 
-   SharedPage = (PKUSER_SHARED_DATA)KERNEL_SHARED_DATA_BASE;
-   SharedPage->DosDeviceMap = 0;
-   SharedPage->NtProductType = NtProductWinNt;
-   for (i = 0; i < 32; i++)
-     {
-       SharedPage->DosDeviceDriveType[i] = 0;
-     }
+   /*
+    * NOTE:
+    *   The shared user page has been zeroed-out right after creation.
+    *   There is NO need to do this again.
+    */
+
+   SharedUserData->NtProductType = NtProductWinNt;
 
    BootDriveFound = FALSE;
 
@@ -248,17 +162,17 @@ InitSystemSharedUserPage (PCSZ ParameterLine)
    p = strchr (ParamBuffer, '\\');
    if (p)
      {
-       DPRINT("Boot path: %s\n", p);
-       RtlCreateUnicodeStringFromAsciiz (&BootPath, p);
-       *p = 0;
+       DPRINT("Boot path: %s\n", p);
+       RtlCreateUnicodeStringFromAsciiz (&BootPath, p);
+       *p = 0;
      }
    else
      {
-       DPRINT("Boot path: %s\n", "\\");
-       RtlCreateUnicodeStringFromAsciiz (&BootPath, "\\");
+       DPRINT("Boot path: %s\n", "\\");
+       RtlCreateUnicodeStringFromAsciiz (&BootPath, "\\");
      }
    DPRINT("Arc name: %s\n", ParamBuffer);
-
+   
    /* Only arc name left - build full arc name */
    ArcNameBuffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
    swprintf (ArcNameBuffer, L"\\ArcName\\%S", ParamBuffer);
@@ -275,7 +189,7 @@ InitSystemSharedUserPage (PCSZ ParameterLine)
 
    InitializeObjectAttributes (&ObjectAttributes,
                               &ArcName,
-                              0,
+                              OBJ_OPENLINK,
                               NULL,
                               NULL);
 
@@ -287,10 +201,10 @@ InitSystemSharedUserPage (PCSZ ParameterLine)
      {
        RtlFreeUnicodeString (&BootPath);
        RtlFreeUnicodeString (&ArcDeviceName);
-       DbgPrint("NtOpenSymbolicLinkObject() failed (Status %x)\n",
+       CPRINT("NtOpenSymbolicLinkObject() failed (Status %x)\n",
                 Status);
 
-       KeBugCheck (0x0);
+       KEBUGCHECK (0x0);
      }
 
    Status = NtQuerySymbolicLinkObject (Handle,
@@ -301,10 +215,10 @@ InitSystemSharedUserPage (PCSZ ParameterLine)
      {
        RtlFreeUnicodeString (&BootPath);
        RtlFreeUnicodeString (&ArcDeviceName);
-       DbgPrint("NtQuerySymbolicObject() failed (Status %x)\n",
+       CPRINT("NtQuerySymbolicObject() failed (Status %x)\n",
                 Status);
 
-       KeBugCheck (0x0);
+       KEBUGCHECK (0x0);
      }
    DPRINT("Length: %lu ArcDeviceName: %wZ\n", Length, &ArcDeviceName);
 
@@ -322,7 +236,7 @@ InitSystemSharedUserPage (PCSZ ParameterLine)
 
        InitializeObjectAttributes (&ObjectAttributes,
                                    &DriveName,
-                                   0,
+                                   OBJ_OPENLINK,
                                    NULL,
                                    NULL);
 
@@ -351,88 +265,588 @@ InitSystemSharedUserPage (PCSZ ParameterLine)
        if (!RtlCompareUnicodeString (&ArcDeviceName, &DriveDeviceName, FALSE))
          {
             DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i, &BootPath);
-            swprintf (SharedPage->NtSystemRoot,
-                      L"%C:%wZ", 'A' + i, &BootPath);
-
-               BootDriveFound = TRUE;
+            swprintf(SharedUserData->NtSystemRoot,
+                     L"%C:%wZ", 'A' + i, &BootPath);
+            
+            BootDriveFound = TRUE;
          }
 
        NtClose (Handle);
-
-       /* set bit in dos drives bitmap (drive available) */
-       SharedPage->DosDeviceMap |= (1<<i);
      }
 
    RtlFreeUnicodeString (&BootPath);
    RtlFreeUnicodeString (&DriveDeviceName);
    RtlFreeUnicodeString (&ArcDeviceName);
 
-   DPRINT("DosDeviceMap: 0x%x\n", SharedPage->DosDeviceMap);
+   DPRINT("DosDeviceMap: 0x%x\n", SharedUserData->DosDeviceMap);
 
    if (BootDriveFound == FALSE)
      {
        DbgPrint("No system drive found!\n");
-       KeBugCheck (0x0);
+       KEBUGCHECK (0x0);
      }
 }
 
-extern NTSTATUS STDCALL
-Ke386CallBios(UCHAR Int, KV86M_REGISTERS* Regs);
-
-struct __attribute__((packed)) vesa_info
+VOID STATIC
+MiFreeBootDriverMemory(PVOID StartAddress, ULONG Length)
 {
-  UCHAR Signature[4];
-  USHORT Version;
-  ULONG OEMName;
-  ULONG Capabilities;
-  ULONG SupportedModes;
-  USHORT TotalVideoMemory;
-  USHORT OEMVersion;
-  ULONG VendorName;
-  ULONG ProductName;
-  ULONG ProductRevisionString;
-  UCHAR Reserved[478];
-};
+  PHYSICAL_ADDRESS Page;
+  ULONG i;
+
+  for (i = 0; i < PAGE_ROUND_UP(Length)/PAGE_SIZE; i++)
+  {
+     Page = MmGetPhysicalAddressForProcess(NULL, StartAddress + i * PAGE_SIZE);
+     MmDeleteVirtualMapping(NULL, StartAddress + i * PAGE_SIZE, FALSE, NULL, NULL);
+     MmDereferencePage(Page);
+  }
+}
 
 VOID
-TestV86Mode(VOID)
+ExpInitializeExecutive(VOID)
 {
+  LARGE_INTEGER Timeout;
+  HANDLE ProcessHandle;
+  HANDLE ThreadHandle;
+  ULONG BootDriverCount;
   ULONG i;
-  extern UCHAR OrigIVT[1024];
-  KV86M_REGISTERS regs;
+  ULONG start;
+  ULONG length;
+  PCHAR name;
+  CHAR str[50];
   NTSTATUS Status;
-  struct vesa_info* vi;
+  BOOLEAN SetupBoot;
+  PCHAR p1, p2;
+  ULONG MaxMem;
+  BOOLEAN NoBootScreen = FALSE;
+  UNICODE_STRING Name;
+  HANDLE InitDoneEventHandle;
+  OBJECT_ATTRIBUTES ObjectAttributes;
+
+  /*
+   * Fail at runtime if someone has changed various structures without
+   * updating the offsets used for the assembler code.
+   */
+  assert(FIELD_OFFSET(KTHREAD, InitialStack) == KTHREAD_INITIAL_STACK);
+  assert(FIELD_OFFSET(KTHREAD, Teb) == KTHREAD_TEB);
+  assert(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK);
+  assert(FIELD_OFFSET(KTHREAD, ServiceTable) == KTHREAD_SERVICE_TABLE);
+  assert(FIELD_OFFSET(KTHREAD, PreviousMode) == KTHREAD_PREVIOUS_MODE);
+  assert(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME);
+  assert(FIELD_OFFSET(KTHREAD, CallbackStack) == KTHREAD_CALLBACK_STACK);
+  assert(FIELD_OFFSET(ETHREAD, ThreadsProcess) == ETHREAD_THREADS_PROCESS);
+  assert(FIELD_OFFSET(KPROCESS, DirectoryTableBase) == 
+        KPROCESS_DIRECTORY_TABLE_BASE);
+  assert(FIELD_OFFSET(KTRAP_FRAME, Reserved9) == KTRAP_FRAME_RESERVED9);
+  assert(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
+  assert(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
+
+  assert(FIELD_OFFSET(KPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
+  assert(FIELD_OFFSET(KPCR, Self) == KPCR_SELF);
+  assert(FIELD_OFFSET(IKPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
+  assert(FIELD_OFFSET(IKPCR, Self) == KPCR_SELF);
+  assert(FIELD_OFFSET(IKPCR, CurrentThread) == KPCR_CURRENT_THREAD);
+
+  LdrInit1();
+
+  KeLowerIrql(DISPATCH_LEVEL);
+  
+  NtEarlyInitVdm();
+
+  p1 = (PCHAR)KeLoaderBlock.CommandLine;
+
+  MaxMem = 0;
+  while(*p1 && (p2 = strchr(p1, '/')))
+  {
+     p2++;
+     if (!_strnicmp(p2, "MAXMEM", 6))
+     {
+        p2 += 6;
+        while (isspace(*p2)) p2++;
+       if (*p2 == '=')
+       {
+          p2++;
+          while(isspace(*p2)) p2++;
+          if (isdigit(*p2))
+          {
+             while (isdigit(*p2))
+             {
+                MaxMem = MaxMem * 10 + *p2 - '0';
+                p2++;
+             }
+             break;
+          }
+       }
+     }
+    else if (!_strnicmp(p2, "NOBOOTSCREEN", 12))
+      {
+        p2 += 12;
+        NoBootScreen = TRUE;
+      }
+     p1 = p2;
+  }
+
+  MmInit1(FirstKrnlPhysAddr,
+         LastKrnlPhysAddr,
+         LastKernelAddress,
+         (PADDRESS_RANGE)&KeMemoryMap,
+         KeMemoryMapRangeCount,
+         MaxMem > 8 ? MaxMem : 4096);
+
+  /* Import ANSI code page table */
+  for (i = 1; i < KeLoaderBlock.ModsCount; i++)
+    {
+      start = KeLoaderModules[i].ModStart;
+      length = KeLoaderModules[i].ModEnd - start;
+
+      name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
+      if (name == NULL)
+       {
+         name = (PCHAR)KeLoaderModules[i].String;
+       }
+      else
+       {
+         name++;
+       }
+
+      if (!_stricmp (name, "ansi.nls"))
+       {
+         RtlpImportAnsiCodePage((PUSHORT)start, length);
+       }
+    }
+
+  /* Import OEM code page table */
+  for (i = 1; i < KeLoaderBlock.ModsCount; i++)
+    {
+      start = KeLoaderModules[i].ModStart;
+      length = KeLoaderModules[i].ModEnd - start;
+
+      name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
+      if (name == NULL)
+       {
+         name = (PCHAR)KeLoaderModules[i].String;
+       }
+      else
+       {
+         name++;
+       }
+
+      if (!_stricmp (name, "oem.nls"))
+       {
+         RtlpImportOemCodePage((PUSHORT)start, length);
+       }
+    }
+
+  /* Import Unicode casemap table */
+  for (i = 1; i < KeLoaderBlock.ModsCount; i++)
+    {
+      start = KeLoaderModules[i].ModStart;
+      length = KeLoaderModules[i].ModEnd - start;
+
+      name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
+      if (name == NULL)
+       {
+         name = (PCHAR)KeLoaderModules[i].String;
+       }
+      else
+       {
+         name++;
+       }
+
+      if (!_stricmp (name, "casemap.nls"))
+       {
+         RtlpImportUnicodeCasemap((PUSHORT)start, length);
+       }
+    }
+
+  /* Create initial NLS tables */
+  RtlpCreateInitialNlsTables();
+
+  /*
+   * Initialize the kernel debugger
+   */
+  KdInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
+
+  MmInit2();
+  KeInit2();
+  
+  KeLowerIrql(PASSIVE_LEVEL);
+
+  if (!SeInit1())
+    KEBUGCHECK(SECURITY_INITIALIZATION_FAILED);
+
+  ObInit();
+
+  if (!SeInit2())
+    KEBUGCHECK(SECURITY1_INITIALIZATION_FAILED);
+
+  PiInitProcessManager();
+
+  KdInit1();
+
+  if (KdPollBreakIn ())
+    {
+      DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
+    }
+
+  /* Initialize all processors */
+  KeNumberProcessors = 0;
+
+  while (!HalAllProcessorsStarted())
+    {
+      PVOID ProcessorStack;
+
+      if (KeNumberProcessors != 0)
+       {
+         KePrepareForApplicationProcessorInit(KeNumberProcessors);
+         PsPrepareForApplicationProcessorInit(KeNumberProcessors);
+       }
+      /* Allocate a stack for use when booting the processor */
+      /* FIXME: The nonpaged memory for the stack is not released after use */
+      ProcessorStack = 
+       ExAllocatePool(NonPagedPool, MM_STACK_SIZE) + MM_STACK_SIZE;
+      Ki386InitialStackArray[((int)KeNumberProcessors)] = 
+       (PVOID)(ProcessorStack - MM_STACK_SIZE);
+      HalInitializeProcessor(KeNumberProcessors, ProcessorStack);
+      KeNumberProcessors++;
+    }
+
+  /*
+   * Initialize various critical subsystems
+   */
+  HalInitSystem(1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
+
+  ExInit();
+  IoInit();
+  PoInit();
+  LdrInitModuleManagement();
+  CmInitializeRegistry();
+  NtInit();
+  MmInit3();
+  CcInit();
+  KdInit2();
+  FsRtlpInitFileLockingImplementation();
+
+  /* Report all resources used by hal */
+  HalReportResourceUsage();
+
+  /* Display the boot screen image if not disabled */
+  if (!NoBootScreen)
+    {
+      InbvEnableBootDriver(TRUE);
+    }
+
+  /*
+   * Clear the screen to blue
+   */
+  HalInitSystem(2, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
+
+  /*
+   * Display version number and copyright/warranty message
+   */
+  HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR" (Build "
+                  KERNEL_VERSION_BUILD_STR")\n");
+  HalDisplayString(RES_STR_LEGAL_COPYRIGHT);
+  HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
+                  "Public License, and you\n");
+  HalDisplayString("are welcome to change it and/or distribute copies of it "
+                  "under certain\n"); 
+  HalDisplayString("conditions. There is absolutely no warranty for "
+                  "ReactOS.\n\n");
+
+  if (KeNumberProcessors > 1)
+    {
+      sprintf(str,
+             "Found %d system processors. [%lu MB Memory]\n",
+             KeNumberProcessors,
+             (KeLoaderBlock.MemHigher + 1088)/ 1024);
+    }
+  else
+    {
+      sprintf(str,
+             "Found 1 system processor. [%lu MB Memory]\n",
+             (KeLoaderBlock.MemHigher + 1088)/ 1024);
+    }
+  HalDisplayString(str);
+
+  KdInit3();
+
+
+  /* Create the NLS section */
+  RtlpCreateNlsSection();
+
+  /*
+   * Initalize services loaded at boot time
+   */
+  DPRINT("%d files loaded\n",KeLoaderBlock.ModsCount);
+  for (i=0; i < KeLoaderBlock.ModsCount; i++)
+    {
+      CPRINT("Module: '%s' at %08lx, length 0x%08lx\n",
+       KeLoaderModules[i].String,
+       KeLoaderModules[i].ModStart,
+       KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart);
+    }
+
+  /* Pass 1: import system hive registry chunk */
+  SetupBoot = TRUE;
+  for (i = 1; i < KeLoaderBlock.ModsCount; i++)
+    {
+      start = KeLoaderModules[i].ModStart;
+      length = KeLoaderModules[i].ModEnd - start;
+
+      DPRINT("Module: '%s'\n", (PCHAR)KeLoaderModules[i].String);
+      name = strrchr((PCHAR)KeLoaderModules[i].String, '\\');
+      if (name == NULL)
+       {
+         name = (PCHAR)KeLoaderModules[i].String;
+       }
+      else
+       {
+         name++;
+       }
 
-  for (i = 0; i < (640 / 4); i++)
+      if (!_stricmp (name, "system") ||
+         !_stricmp (name, "system.hiv"))
+       {
+         CPRINT("Process system hive registry chunk at %08lx\n", start);
+         SetupBoot = FALSE;
+         CmImportSystemHive((PCHAR)start, length);
+       }
+    }
+
+  /* Pass 2: import hardware hive registry chunk */
+  for (i = 1; i < KeLoaderBlock.ModsCount; i++)
     {
-      MmCreateVirtualMapping(NULL,
-                            (PVOID)(i * 4096),
-                            PAGE_EXECUTE_READWRITE,
-                            (ULONG)MmAllocPage(0));
+      start = KeLoaderModules[i].ModStart;
+      length = KeLoaderModules[i].ModEnd - start;
+      name = (PCHAR)KeLoaderModules[i].String;
+      if (!_stricmp (name, "hardware") ||
+         !_stricmp (name, "hardware.hiv"))
+       {
+         CPRINT("Process hardware hive registry chunk at %08lx\n", start);
+         CmImportHardwareHive((PCHAR)start, length);
+       }
     }
-  for (; i < (1024 / 4); i++)
+
+  /* Create dummy keys if no hardware hive was found */
+  CmImportHardwareHive (NULL, 0);
+
+  /* Initialize volatile registry settings */
+  if (SetupBoot == FALSE)
     {
-      MmCreateVirtualMapping(NULL,
-                            (PVOID)(i * 4096),
-                            PAGE_EXECUTE_READ,
-                            i * 4096);
+      CmInit2((PCHAR)KeLoaderBlock.CommandLine);
     }
-  vi = (struct vesa_info*)0x20000;
-  vi->Signature[0] = 'V';
-  vi->Signature[1] = 'B';
-  vi->Signature[2] = 'E';
-  vi->Signature[3] = '2';
-  memset(&regs, 0, sizeof(regs));
-  regs.Eax = 0x4F00;  
-  regs.Es = 0x2000;
-  regs.Edi = 0x0;
-  memcpy((PVOID)0x0, OrigIVT, 1024);
-  Status = Ke386CallBios(0x10, &regs);
-  DbgPrint("Finished (Status %x, CS:EIP %x:%x)\n", Status, regs.Cs,
-          regs.Eip);
-  DbgPrint("Eax %x\n", regs.Eax);
-  DbgPrint("Signature %.4s\n", vi->Signature);
-  DbgPrint("TotalVideoMemory %dKB\n", vi->TotalVideoMemory * 64);
+
+  /*
+   * Enter the kernel debugger before starting up the boot drivers
+   */
+#ifdef KDBG
+  KdbEnter();
+#endif /* KDBG */
+
+  IoCreateDriverList();
+
+  IoInit2();
+
+  /* Pass 3: process boot loaded drivers */
+  BootDriverCount = 0;
+  for (i=1; i < KeLoaderBlock.ModsCount; i++)
+    {
+      start = KeLoaderModules[i].ModStart;
+      length = KeLoaderModules[i].ModEnd - start;
+      name = (PCHAR)KeLoaderModules[i].String;
+      if (RtlpCheckFileNameExtension(name, ".sys") ||
+         RtlpCheckFileNameExtension(name, ".sym"))
+       {
+         CPRINT("Initializing driver '%s' at %08lx, length 0x%08lx\n",
+                name, start, length);
+         LdrInitializeBootStartDriver((PVOID)start, name, length);
+       }
+      if (RtlpCheckFileNameExtension(name, ".sys"))
+       BootDriverCount++;
+    }
+
+  /* Pass 4: free memory for all boot files, except ntoskrnl.exe and hal.dll */
+  for (i = 2; i < KeLoaderBlock.ModsCount; i++)
+    {
+#ifdef KDBG
+       /* Do not free the memory from symbol files, if the kernel debugger is activ */
+       if (!RtlpCheckFileNameExtension(name, ".sym"))
+#endif
+         {
+           MiFreeBootDriverMemory((PVOID)KeLoaderModules[i].ModStart,
+                                 KeLoaderModules[i].ModEnd - KeLoaderModules[i].ModStart);
+        }
+    }
+
+  if (BootDriverCount == 0)
+    {
+      DbgPrint("No boot drivers available.\n");
+      KEBUGCHECK(0);
+    }
+
+  /* Create ARC names for boot devices */
+  IoCreateArcNames();
+
+  /* Create the SystemRoot symbolic link */
+  CPRINT("CommandLine: %s\n", (PUCHAR)KeLoaderBlock.CommandLine);
+  Status = IoCreateSystemRootLink((PUCHAR)KeLoaderBlock.CommandLine);
+  if (!NT_SUCCESS(Status))
+    KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE);
+
+#ifdef DBGPRINT_FILE_LOG
+  /* On the assumption that we can now access disks start up the debug
+     logger thread */
+  DebugLogInit2();
+#endif /* DBGPRINT_FILE_LOG */
+
+#ifdef KDBG
+  KdbInitProfiling2();
+#endif /* KDBG */
+
+
+  PiInitDefaultLocale();
+
+#if 0
+  /*
+   * Load boot start drivers
+   */
+  IopLoadBootStartDrivers();
+#else
+  /*
+   * Load Auto configured drivers
+   */
+  LdrLoadAutoConfigDrivers();
+#endif
+
+  IoDestroyDriverList();
+
+  /*
+   * Assign drive letters
+   */
+  IoAssignDriveLetters ((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock,
+                       NULL,
+                       NULL,
+                       NULL);
+
+  /*
+   * Initialize shared user page:
+   *  - set dos system path, dos device map, etc.
+   */
+  InitSystemSharedUserPage ((PUCHAR)KeLoaderBlock.CommandLine);
+
+  /* Create 'ReactOSInitDone' event */
+  RtlInitUnicodeString(&Name, L"\\ReactOSInitDone");
+  InitializeObjectAttributes(&ObjectAttributes,
+    &Name,
+    0,
+    NULL,
+    NULL);
+  Status = NtCreateEvent(&InitDoneEventHandle,
+    EVENT_ALL_ACCESS,
+    &ObjectAttributes,
+    FALSE,              /* Synchronization event */
+    FALSE);             /* Not signalled */
+  if (!NT_SUCCESS(Status))
+    {
+      DPRINT1("Failed to create 'ReactOSInitDone' event (Status 0x%x)\n", Status);
+      InitDoneEventHandle = INVALID_HANDLE_VALUE;
+    }
+
+  /*
+   *  Launch initial process
+   */
+  Status = LdrLoadInitialProcess(&ProcessHandle,
+                                &ThreadHandle);
+  if (!NT_SUCCESS(Status))
+    {
+      KEBUGCHECKEX(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
+    }
+
+  if (InitDoneEventHandle != INVALID_HANDLE_VALUE)
+    {
+      HANDLE Handles[2]; /* Init event, Initial process */
+
+      Handles[0] = InitDoneEventHandle;
+      Handles[1] = ProcessHandle;
+
+      /* Wait for the system to be initialized */
+      Timeout.QuadPart = -1200000000LL;  /* 120 second timeout */
+      Status = NtWaitForMultipleObjects(((LONG) sizeof(Handles) / sizeof(HANDLE)),
+        Handles,
+        WaitAny,
+        FALSE,    /* Non-alertable */
+        &Timeout);
+      if (!NT_SUCCESS(Status))
+        {
+          DPRINT1("NtWaitForMultipleObjects failed with status 0x%x!\n", Status);
+        }
+      else if (Status == STATUS_TIMEOUT)
+        {
+          DPRINT1("WARNING: System not initialized after 120 seconds.\n");
+        }
+      else if (Status == STATUS_WAIT_0 + 1)
+        {
+          /*
+           * Crash the system if the initial process was terminated.
+           */
+          KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 0, 0, 0);
+        }
+
+      if (!NoBootScreen)
+        {
+          InbvEnableBootDriver(FALSE);
+        }
+
+      NtSetEvent(InitDoneEventHandle, NULL);
+
+      NtClose(InitDoneEventHandle);
+    }
+  else
+    {
+      /* On failure to create 'ReactOSInitDone' event, go to text mode ASAP */
+      if (!NoBootScreen)
+        {
+          InbvEnableBootDriver(FALSE);
+        }
+
+      /*
+       * Crash the system if the initial process terminates within 5 seconds.
+       */
+      Timeout.QuadPart = -50000000LL;
+      Status = NtWaitForSingleObject(ProcessHandle,
+                                FALSE,
+                                &Timeout);
+      if (Status != STATUS_TIMEOUT)
+        {
+          KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 0, 0, 0);
+        }
+    }
+
+  NtClose(ThreadHandle);
+  NtClose(ProcessHandle);
+
+  PsTerminateSystemThread(STATUS_SUCCESS);
+}
+
+
+VOID
+KiSystemStartup(BOOLEAN BootProcessor)
+{
+  HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
+
+  if (BootProcessor)
+    {
+      /* Never returns */
+      ExpInitializeExecutive();
+      KEBUGCHECK(0);
+    }
+  /* Do application processor initialization */
+  KeApplicationProcessorInit();
+  PsApplicationProcessorInit();
+  KeLowerIrql(PASSIVE_LEVEL);
+  PsIdleThreadMain(NULL);
+  KEBUGCHECK(0);
+  for(;;);
 }
 
 VOID
@@ -446,210 +860,152 @@ _main (ULONG MultiBootMagic, PLOADER_PARAMETER_BLOCK _LoaderBlock)
  * invalid after the memory managment is initialized so we make a local copy.
  */
 {
-   ULONG i;
-   ULONG last_kernel_address;
-   ULONG start;
-   PCHAR name;
-   extern ULONG _bss_end__;
-
-   /*
-    * Copy the parameters to a local buffer because lowmem will go away
-    */
-   memcpy (&KeLoaderBlock, _LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
-   memcpy (&KeLoaderModules[1], (PVOID)KeLoaderBlock.ModsAddr,
-          sizeof(LOADER_MODULE) * KeLoaderBlock.ModsCount);
-   KeLoaderBlock.ModsCount++;
-   KeLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
-   
-   /*
-    * FIXME: Preliminary hack!!!! Add boot device to beginning of command line.
-    * This should be done by the boot loader.
-    */
-   strcpy (KeLoaderCommandLine,
-          "multi(0)disk(0)rdisk(0)partition(1)\\reactos ");
-   strcat (KeLoaderCommandLine, (PUCHAR)KeLoaderBlock.CommandLine);
-   
-   KeLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
-   strcpy(KeLoaderModuleStrings[0], "ntoskrnl.exe");
-   KeLoaderModules[0].String = (ULONG)KeLoaderModuleStrings[0];
-   KeLoaderModules[0].ModStart = 0xC0000000;
-   KeLoaderModules[0].ModEnd = PAGE_ROUND_UP((ULONG)&_bss_end__);
-   for (i = 1; i < KeLoaderBlock.ModsCount; i++)
-     {
-       strcpy(KeLoaderModuleStrings[i], (PUCHAR)KeLoaderModules[i].String);
-       KeLoaderModules[i].ModStart -= 0x200000;
-       KeLoaderModules[i].ModStart += 0xc0000000;
-       KeLoaderModules[i].ModEnd -= 0x200000;
-       KeLoaderModules[i].ModEnd += 0xc0000000;
-       KeLoaderModules[i].String = (ULONG)KeLoaderModuleStrings[i];
-     }
-   
-   /*
-    * Initialization phase 0
-    */
-   HalInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
-   KeInit1();
-   KeLowerIrql(DISPATCH_LEVEL);
+  ULONG i;
+  ULONG size;
+  ULONG last_kernel_address;
+  extern ULONG _bss_end__;
+  ULONG HalBase;
+  ULONG DriverBase;
+  ULONG DriverSize;
+
+  /* Low level architecture specific initialization */
+  KeInit1();
+
+  /*
+   * Copy the parameters to a local buffer because lowmem will go away
+   */
+  memcpy(&KeLoaderBlock, _LoaderBlock, sizeof(LOADER_PARAMETER_BLOCK));
+  memcpy(&KeLoaderModules[1], (PVOID)KeLoaderBlock.ModsAddr,
+        sizeof(LOADER_MODULE) * KeLoaderBlock.ModsCount);
+  KeLoaderBlock.ModsCount++;
+  KeLoaderBlock.ModsAddr = (ULONG)&KeLoaderModules;
+
+  /*
+   * Convert a path specification in the grub format to one understood by the
+   * rest of the kernel.
+   */
+  if (((PUCHAR)_LoaderBlock->CommandLine)[0] == '(')
+    {
+      ULONG DiskNumber = 0, PartNumber = 0;
+      PCH p;
+      CHAR Temp[256];
+      PCH options;
+      PCH s1;
+
+      if (((PUCHAR)_LoaderBlock->CommandLine)[1] == 'h' &&
+         ((PUCHAR)_LoaderBlock->CommandLine)[2] == 'd')
+       {
+         DiskNumber = ((PUCHAR)_LoaderBlock->CommandLine)[3] - '0';
+         PartNumber = ((PUCHAR)_LoaderBlock->CommandLine)[5] - '0';
+       }
+      strcpy(Temp, &((PUCHAR)_LoaderBlock->CommandLine)[7]);
+      if ((options = strchr(Temp, ' ')) != NULL)
+       {
+         *options = 0;
+         options++;
+       }
+      else
+       {
+         options = "";
+       }
+      if ((s1 = strrchr(Temp, '/')) != NULL)
+       {
+         *s1 = 0;
+         if ((s1 = strrchr(Temp, '/')) != NULL)
+           {
+             *s1 = 0;
+           }
+       }
+      sprintf(KeLoaderCommandLine, 
+             "multi(0)disk(0)rdisk(%lu)partition(%lu)%s %s",
+             DiskNumber, PartNumber + 1, Temp, options);
 
-   /*
-    * Display version number and copyright/warranty message
-    */
-   HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR" (Build "
-                   KERNEL_VERSION_BUILD_STR")\n");
-   HalDisplayString(RES_STR_LEGAL_COPYRIGHT);
-   HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
-                   "Public License, and you\n");
-   HalDisplayString("are welcome to change it and/or distribute copies of it "
-                   "under certain\n"); 
-   HalDisplayString("conditions. There is absolutely no warranty for ReactOS.\n");
+      p = KeLoaderCommandLine;
+      while (*p != 0 && *p != ' ')
+       {
+         if ((*p) == '/')
+           {
+             (*p) = '\\';
+           }
+         p++;
+       }
+      DPRINT1("Command Line: %s\n", KeLoaderCommandLine);
+    }
+  else
+    {
+      strcpy(KeLoaderCommandLine, (PUCHAR)_LoaderBlock->CommandLine);
+    }
+  KeLoaderBlock.CommandLine = (ULONG)KeLoaderCommandLine;
+  
+  strcpy(KeLoaderModuleStrings[0], "ntoskrnl.exe");
+  KeLoaderModules[0].String = (ULONG)KeLoaderModuleStrings[0];
+  KeLoaderModules[0].ModStart = 0xC0000000;
+  KeLoaderModules[0].ModEnd = PAGE_ROUND_UP((ULONG)&_bss_end__);
+  for (i = 1; i < KeLoaderBlock.ModsCount; i++)
+    {      
+      CHAR* s;
+      if ((s = strrchr((PUCHAR)KeLoaderModules[i].String, '/')) != 0)
+       {
+         strcpy(KeLoaderModuleStrings[i], s + 1);
+       }
+      else
+       {
+         strcpy(KeLoaderModuleStrings[i], (PUCHAR)KeLoaderModules[i].String);
+       }
+      KeLoaderModules[i].ModStart -= 0x200000;
+      KeLoaderModules[i].ModStart += 0xc0000000;
+      KeLoaderModules[i].ModEnd -= 0x200000;
+      KeLoaderModules[i].ModEnd += 0xc0000000;
+      KeLoaderModules[i].String = (ULONG)KeLoaderModuleStrings[i];
+    }
 
-   /*
-    * Fail at runtime if someone has changed various structures without
-    * updating the offsets used for the assembler code
-    */
-   assert(FIELD_OFFSET(KTHREAD, InitialStack) == KTHREAD_INITIAL_STACK);
-   assert(FIELD_OFFSET(KTHREAD, Teb) == KTHREAD_TEB);
-   assert(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK);
-   assert(FIELD_OFFSET(KTHREAD, PreviousMode) == KTHREAD_PREVIOUS_MODE);
-   assert(FIELD_OFFSET(KTHREAD, TrapFrame) == KTHREAD_TRAP_FRAME);
-   assert(FIELD_OFFSET(ETHREAD, ThreadsProcess) == ETHREAD_THREADS_PROCESS);
-   assert(FIELD_OFFSET(KPROCESS, PageTableDirectory) == 
-         KPROCESS_PAGE_TABLE_DIRECTORY);
-   
-   last_kernel_address = KeLoaderModules[KeLoaderBlock.ModsCount - 1].ModEnd;
-   
-   NtEarlyInitVdm();
-   MmInit1(KeLoaderModules[0].ModStart - 0xc0000000 + 0x200000,
-          last_kernel_address - 0xc0000000 + 0x200000,
-          last_kernel_address);
+#ifdef HAL_DBG
+  HalnInitializeDisplay((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
+#endif
 
-   /*
-    * Initialize the kernel debugger
-    */
-   KdInitSystem (0, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
-   if (KdPollBreakIn ())
-     {
-       DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
-     }
+  HalBase = KeLoaderModules[1].ModStart;
+  DriverBase = 
+    PAGE_ROUND_UP(KeLoaderModules[KeLoaderBlock.ModsCount - 1].ModEnd);
 
-   /*
-    * Initialization phase 1
-    * Initalize various critical subsystems
-    */
-   HalInitSystem (1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
-   MmInit2();
-   KeInit2();
+  /*
+   * Process hal.dll
+   */
+  LdrSafePEProcessModule((PVOID)HalBase, (PVOID)DriverBase, (PVOID)0xC0000000, &DriverSize);
 
-   /*
-    * Allow interrupts
-    */
-   KeLowerIrql(PASSIVE_LEVEL);
-
-   ObInit();
-   PiInitProcessManager();
-   ExInit();
-   IoInit();
-   LdrInitModuleManagement();
-   CmInitializeRegistry();
-   NtInit();
-   MmInit3();
-   
-   /* Report all resources used by hal */
-   HalReportResourceUsage ();
-   
-   /*
-    * Initalize services loaded at boot time
-    */
-   DPRINT1("%d files loaded\n",KeLoaderBlock.ModsCount);
-   for (i=0; i < KeLoaderBlock.ModsCount; i++)
-     {
-       DPRINT1("module: %s\n", KeLoaderModules[i].String);
-     }
+  LdrHalBase = (ULONG_PTR)DriverBase;
+  last_kernel_address = DriverBase + DriverSize;
 
-   /*  Pass 1: load registry chunks passed in  */
-   for (i = 1; i < KeLoaderBlock.ModsCount; i++)
-     {
-       start = KeLoaderModules[i].ModStart;
-       if (strcmp ((PCHAR) start, "REGEDIT4") == 0)
-        {
-           DPRINT1("process registry chunk at %08lx\n", start);
-           CmImportHive((PCHAR) start);
-        }
-     }
+  /*
+   * Process ntoskrnl.exe
+   */
+  LdrSafePEProcessModule((PVOID)0xC0000000, (PVOID)0xC0000000, (PVOID)DriverBase, &DriverSize);
 
-   /*  Pass 2: process boot loaded drivers  */
-   for (i=1; i < KeLoaderBlock.ModsCount; i++)
-     {
-       start = KeLoaderModules[i].ModStart;
-       name = (PCHAR)KeLoaderModules[i].String;
-       if (strcmp ((PCHAR) start, "REGEDIT4") != 0)
-        {
-           DPRINT1("process module '%s' at %08lx\n", name, start);
-           LdrProcessDriver((PVOID)start, name);
-        }
-     }
+  FirstKrnlPhysAddr = KeLoaderModules[0].ModStart - 0xc0000000 + 0x200000;
+  LastKrnlPhysAddr = last_kernel_address - 0xc0000000 + 0x200000;
+  LastKernelAddress = last_kernel_address;
 
-   DbgPrint("About to try MmAllocateContiguousAlignedMemory\n");
-   do
-     {
-extern PVOID STDCALL
-MmAllocateContiguousAlignedMemory(IN ULONG NumberOfBytes,
-                                 IN PHYSICAL_ADDRESS HighestAcceptableAddress,
-                                 IN ULONG Alignment);
-       PVOID v;
-       PHYSICAL_ADDRESS p;
-       p.QuadPart = 16*1024*1024;
-       v = MmAllocateContiguousAlignedMemory(12*1024, p,
-                                            64*1024);
-       if (v != NULL)
-        {
-          DbgPrint("Worked\n");
-        }
-       else
-        {
-          DbgPrint("Failed\n");
-        }
-     }
-   while (0);
+#ifndef ACPI
+  /* FIXME: VMware does not like it when ReactOS is using the BIOS memory map */
+  KeLoaderBlock.Flags &= ~MB_FLAGS_MMAP_INFO;
+#endif
 
-   /* Create the SystemRoot symbolic link */
-   DbgPrint("CommandLine: %s\n", (PUCHAR)KeLoaderBlock.CommandLine);
-   CreateSystemRootLink ((PUCHAR)KeLoaderBlock.CommandLine);
+  KeMemoryMapRangeCount = 0;
+  if (KeLoaderBlock.Flags & MB_FLAGS_MMAP_INFO)
+    {
+      /* We have a memory map from the nice BIOS */
+      size = *((PULONG)(KeLoaderBlock.MmapAddr - sizeof(ULONG)));
+      i = 0;
+      while (i < KeLoaderBlock.MmapLength)
+        {
+          memcpy (&KeMemoryMap[KeMemoryMapRangeCount],
+            (PVOID)(KeLoaderBlock.MmapAddr + i),
+                 sizeof(ADDRESS_RANGE));
+          KeMemoryMapRangeCount++;
+          i += size;
+        }
+    }
   
-#ifdef DBGPRINT_FILE_LOG
-   /* On the assumption that we can now access disks start up the debug 
-      logger thread */
-   DebugLogInit2();
-#endif /* DBGPRINT_FILE_LOG */
-   CmInitializeRegistry2();
-   
-   /*
-    * Load Auto configured drivers
-    */
-   LdrLoadAutoConfigDrivers();
-   
-   /*
-    * Assign drive letters
-    */
-   IoAssignDriveLetters ((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock,
-                         NULL,
-                         NULL,
-                         NULL);
-
-   /*
-    * Initialize shared user page:
-    *  - set dos system path, dos device map, etc.
-    */
-   InitSystemSharedUserPage ((PUCHAR)KeLoaderBlock.CommandLine);
-
-   /*
-    *  Launch initial process
-    */
-   LdrLoadInitialProcess();
-
-   DbgPrint("Finished main()\n");
-   PsTerminateSystemThread(STATUS_SUCCESS);
+  KiSystemStartup(1);
 }
 
 /* EOF */