kernel.c

来自「一个类似windows」· C语言 代码 · 共 599 行 · 第 1/2 页

C
599
字号
    * with MmAllocPage() here because MmInit1() has not yet been
    * called, so we use a predefined page in low memory
    */

   KPCR = (PKIPCR)KPCR_BASE;
   memset(KPCR, 0, PAGE_SIZE);
   KPCR->Self = (PKPCR)KPCR;
   KPCR->Prcb = &KPCR->PrcbData;
   KPCR->Irql = SYNCH_LEVEL;
   KPCR->NtTib.Self = &KPCR->NtTib;
   KPCR->GDT = KiBootGdt;
   KPCR->IDT = KiIdt;
   KPCR->TSS = &KiBootTss;
   KPCR->Number = 0;
   KPCR->SetMember = 1 << 0;
   KeActiveProcessors = 1 << 0;
   KPCR->PrcbData.SetMember = 1 << 0;
   KiPcrInitDone = 1;
   PcrsAllocated++;

   KiInitializeGdt (NULL);
   Ki386BootInitializeTSS();
   Ki386InitializeLdt();

   /* Get processor information. */
   Ki386GetCpuId();

   /* Check FPU/MMX/SSE support. */
   KiCheckFPU();

   /* Mark the end of the exception handler list */
   KPCR->NtTib.ExceptionList = (PVOID)-1;

   KeInitDpc(KPCR->Prcb);

   KeInitExceptions ();
   KeInitInterrupts ();

   KeActiveProcessors |= 1 << 0;


   if (KPCR->PrcbData.FeatureBits & X86_FEATURE_PGE)
   {
      ULONG Flags;
      /* Enable global pages */
      Ke386GlobalPagesEnabled = TRUE;
      Ke386SaveFlags(Flags);
      Ke386DisableInterrupts();
      Ke386SetCr4(Ke386GetCr4() | X86_CR4_PGE);
      Ke386RestoreFlags(Flags);
   }

   /* Search for pae and noexecute */
   p1 = (PCHAR)KeLoaderBlock.CommandLine;
   while(*p1 && (p2 = strchr(p1, '/')))
   {
      p2++;
      if (!_strnicmp(p2, "PAE", 3))
      {
	 if (p2[3] == ' ' || p2[3] == 0)
	 {
	    p2 += 3;
	    Pae = TRUE;
	 }
      }
      else if (!_strnicmp(p2, "NOEXECUTE", 9))
      {
         if (p2[9] == ' ' || p2[9] == '=' || p2[9] == 0)
	 {
	    p2 += 9;
	    NoExecute = TRUE;
	 }
      }
      p1 = p2;
   }
#if 0
   /*
    * FIXME:
    *   Make the detection of the noexecute feature more portable.
    */
   if(KPCR->PrcbData.CpuType == 0xf &&
      RtlCompareMemory("AuthenticAMD", KPCR->PrcbData.VendorString, 12) == 12)
   {
      if (NoExecute)
      {
         ULONG Flags, l, h;
         Ke386SaveFlags(Flags);
         Ke386DisableInterrupts();

	 Ke386Rdmsr(0xc0000080, l, h);
	 l |= (1 << 11);
	 Ke386Wrmsr(0xc0000080, l, h);
	 Ke386NoExecute = TRUE;
         Ke386RestoreFlags(Flags);
      }
   }
   else
   {
      NoExecute=FALSE;
   }
#endif

   Ke386Pae = Ke386GetCr4() & X86_CR4_PAE ? TRUE : FALSE;
#if 0
   /* Enable PAE mode */
   if ((Pae && (KPCR->PrcbData.FeatureBits & X86_FEATURE_PAE)) || NoExecute)
   {
      MiEnablePAE((PVOID*)LastKernelAddress);
      Ke386PaeEnabled = TRUE;
   }
#endif
   if (KPCR->PrcbData.FeatureBits & X86_FEATURE_SYSCALL)
   {
      extern void KiFastCallEntry(void);

      /* CS Selector of the target segment. */
      Ke386Wrmsr(0x174, KGDT_R0_CODE, 0);
      /* Target ESP. */
      Ke386Wrmsr(0x175, 0, 0);
      /* Target EIP. */
      Ke386Wrmsr(0x176, (ULONG_PTR)KiFastCallEntry, 0);
   }

   /* Does the CPU Support 'prefetchnta' (SSE)  */
   if(KPCR->PrcbData.FeatureBits & X86_FEATURE_SSE)
   {
       ULONG Protect;

       Protect = MmGetPageProtect(NULL, (PVOID)RtlPrefetchMemoryNonTemporal);
       MmSetPageProtect(NULL, (PVOID)RtlPrefetchMemoryNonTemporal, Protect | PAGE_IS_WRITABLE);
       /* Replace the ret by a nop */
       *(PCHAR)RtlPrefetchMemoryNonTemporal = 0x90;
       MmSetPageProtect(NULL, (PVOID)RtlPrefetchMemoryNonTemporal, Protect);
   }
}

VOID
INIT_FUNCTION
NTAPI
KeInit2(VOID)
{
   PKIPCR Pcr = (PKIPCR)KeGetCurrentKPCR();

   KiInitializeBugCheck();
   KeInitializeDispatcher();
   KiInitializeSystemClock();

   if (Pcr->PrcbData.FeatureBits & X86_FEATURE_PAE)
   {
      DPRINT("CPU supports PAE mode\n");
      if (Ke386Pae)
      {
         DPRINT("CPU runs in PAE mode\n");
         if (Ke386NoExecute)
         {
            DPRINT("NoExecute is enabled\n");
         }
      }
      else
      {
         DPRINT("CPU doesn't run in PAE mode\n");
      }
   }
   if ((Pcr->PrcbData.FeatureBits & (X86_FEATURE_FXSR | X86_FEATURE_MMX | X86_FEATURE_SSE | X86_FEATURE_SSE2)) ||
       (Ke386CpuidFlags2 & X86_EXT_FEATURE_SSE3))
      {
         DPRINT("CPU supports" "%s%s%s%s%s" ".\n",
                ((Pcr->PrcbData.FeatureBits & X86_FEATURE_FXSR) ? " FXSR" : ""),
                ((Pcr->PrcbData.FeatureBits & X86_FEATURE_MMX) ? " MMX" : ""),
                ((Pcr->PrcbData.FeatureBits & X86_FEATURE_SSE) ? " SSE" : ""),
                ((Pcr->PrcbData.FeatureBits & X86_FEATURE_SSE2) ? " SSE2" : ""),
                ((Ke386CpuidFlags2 & X86_EXT_FEATURE_SSE3) ? " SSE3" : ""));
      }
   if (Ke386GetCr4() & X86_CR4_OSFXSR)
      {
         DPRINT("SSE enabled.\n");
      }
   if (Ke386GetCr4() & X86_CR4_OSXMMEXCPT)
      {
         DPRINT("Unmasked SIMD exceptions enabled.\n");
      }
   if (Pcr->PrcbData.VendorString[0])
   {
      DPRINT("CPU Vendor: %s\n", Pcr->PrcbData.VendorString);
   }
   if (Ke386CpuidModel[0])
   {
      DPRINT("CPU Model:  %s\n", Ke386CpuidModel);
   }

   DPRINT("Ke386CacheAlignment: %d\n", Ke386CacheAlignment);
   if (Ke386L1CacheSize)
   {

      DPRINT("Ke386L1CacheSize: %dkB\n", Ke386L1CacheSize);
   }
   if (Pcr->L2CacheSize)
   {
      DPRINT("Ke386L2CacheSize: %dkB\n", Pcr->L2CacheSize);
   }
}

VOID INIT_FUNCTION
Ki386SetProcessorFeatures(VOID)
{
   PKIPCR Pcr = (PKIPCR)KeGetCurrentKPCR();
   OBJECT_ATTRIBUTES ObjectAttributes;
   UNICODE_STRING KeyName =
   RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Session Manager\\Kernel");
   UNICODE_STRING ValueName = RTL_CONSTANT_STRING(L"FastSystemCallDisable");
   HANDLE KeyHandle;
   ULONG ResultLength;
   struct
   {
       KEY_VALUE_PARTIAL_INFORMATION Info;
       UCHAR Buffer[FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION,
                                 Data[0]) + sizeof(ULONG)];
   } ValueData;
   NTSTATUS Status;
   ULONG FastSystemCallDisable = 0;
   
   SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_PRECISION_ERRATA] = FALSE;
   SharedUserData->ProcessorFeatures[PF_FLOATING_POINT_EMULATED] = FALSE;
   SharedUserData->ProcessorFeatures[PF_COMPARE_EXCHANGE_DOUBLE] =
       (Pcr->PrcbData.FeatureBits & X86_FEATURE_CX8) ? TRUE : FALSE;
   SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] =
       (Pcr->PrcbData.FeatureBits & X86_FEATURE_MMX) ? TRUE : FALSE;
   SharedUserData->ProcessorFeatures[PF_PPC_MOVEMEM_64BIT_OK] = FALSE;
   SharedUserData->ProcessorFeatures[PF_ALPHA_BYTE_INSTRUCTIONS] = FALSE;
   SharedUserData->ProcessorFeatures[PF_XMMI_INSTRUCTIONS_AVAILABLE] =
       (Pcr->PrcbData.FeatureBits & X86_FEATURE_SSE) ? TRUE : FALSE;
   SharedUserData->ProcessorFeatures[PF_3DNOW_INSTRUCTIONS_AVAILABLE] =
       (Ke386CpuidExFlags & X86_EXT_FEATURE_3DNOW) ? TRUE : FALSE;
   SharedUserData->ProcessorFeatures[PF_RDTSC_INSTRUCTION_AVAILABLE] =
       (Pcr->PrcbData.FeatureBits & X86_FEATURE_TSC) ? TRUE : FALSE;
   SharedUserData->ProcessorFeatures[PF_PAE_ENABLED] = Ke386Pae;
   SharedUserData->ProcessorFeatures[PF_XMMI64_INSTRUCTIONS_AVAILABLE] =
       (Pcr->PrcbData.FeatureBits & X86_FEATURE_SSE2) ? TRUE : FALSE;

   /* Does the CPU Support Fast System Call? */   
   if (Pcr->PrcbData.FeatureBits & X86_FEATURE_SYSCALL) {

        /* FIXME: Check for Family == 6, Model < 3 and Stepping < 3 and disable */

        /* Make sure it's not disabled in registry */
        InitializeObjectAttributes(&ObjectAttributes,
                                   &KeyName,
                                   OBJ_CASE_INSENSITIVE,
                                   NULL,
                                   NULL);
        Status = ZwOpenKey(&KeyHandle,
                           KEY_QUERY_VALUE,
                           &ObjectAttributes);

        if (NT_SUCCESS(Status)) {

            /* Read the Value then Close the Key */
            Status = ZwQueryValueKey(KeyHandle,
                                     &ValueName,
                                     KeyValuePartialInformation,
                                     &ValueData,
                                     sizeof(ValueData),
                                     &ResultLength);
            if (NT_SUCCESS(Status))
            {
                if (ResultLength == sizeof(ValueData) &&
                    ValueData.Info.Type == REG_DWORD)
                {
                    FastSystemCallDisable = *(PULONG)ValueData.Info.Data != 0;
                }

                ZwClose(KeyHandle);
            }
        }

    } else {

        /* Disable SYSENTER/SYSEXIT, because the CPU doesn't support it */
        FastSystemCallDisable = 1;

    }

    if (FastSystemCallDisable) {
        /* Use INT2E */
        const unsigned char Entry[7] = {0x8D, 0x54, 0x24, 0x08,     /* lea    0x8(%esp),%edx    */
                                        0xCD, 0x2E,                 /* int    0x2e              */
                                        0xC3};                      /* ret                      */
        memcpy(&SharedUserData->SystemCall, Entry, sizeof(Entry));
    } else {
        /* Use SYSENTER */
        const unsigned char Entry[5] = {0x8B, 0xD4,                 /* movl    %esp,%edx        */ 
                                        0x0F, 0x34,                 /* sysenter                 */
                                        0xC3};                      /* ret                      */    
        memcpy(&SharedUserData->SystemCall, Entry, sizeof(Entry));
        /* Enable SYSENTER/SYSEXIT */
        KiFastSystemCallDisable = 0;
    }
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?