Windows NT引导过程源代码分析(10)

2019-08-30 13:20

@@:

nop ; 留一个位置给int3指令

; 设置初始化的IRQL = HIGH_LEVEL RaiseIrql HIGH_LEVEL mov KissIrql, al

or _KiBootFeatureBits, KF_CMPXCHG8B ; CMPXCHG8B是XP的一个标识

;初始化ebp,esp和其他参数寄存器,为初始化内核做准备 mov ebx, KissIdleThread mov edx, KissIdleStack mov eax, KissPbNumber

and edx, NOT 3h ; 4字节边界对齐

xor ebp, ebp ; (ebp) = 0. 没有更多的栈帧了 mov esp, edx

; 为空闲线程栈NPX_SAVE_AREA预留空间并初始化

subesp, NPX_FRAME_LENGTH+KTRAP_FRAME_LENGTH+KTRAP_FRAME_ALIGN push CR0_EM+CR0_TS+CR0_MP ; 为Cr0NpxState预留空间

; arg6 - LoaderBlock ; arg5 - processor number ; arg4 - addr of prcb ; arg3 - idle thread's stack ; arg2 - addr of current thread obj ; arg1 - addr of current process obj ; 初始化系统数据结构和HAL

stdCall _KiInitializeKernel, //执行内核初始化 ; 设置空闲线程的优先级.

mov ebx,PCR[PcPrcbData+PbCurrentThread] ; 设置空闲线程的地址 mov byte ptr [ebx]+ThPriority, 0 ; 设置优先级为0

; Control is returned to the idle thread with IRQL at HIGH_LEVEL. Lower IRQL ; to DISPATCH_LEVEL and set wait IRQL of idle thread. sti

LowerIrql DISPATCH_LEVEL

mov byte ptr [ebx]+ThWaitIrql, DISPATCH_LEVEL

// KiInitializeKernel函数返回以后,启动中断,将IRQL降低为DISPATCH_LEVEL // 从而允许线程调度器选择新的线程

mov ebx, PCR[PcSelfPcr] ; 获取PCR的地址

; 在一个多处理器系统中,引导处理器直接进入空闲循环.而其他的处理器不会直接进入空闲循环; ; 而是等到所有处理器已经开启并且引导主扇区允许进入为止;

; 屏障KiBarrierWait对于系统的第一个处理器并不起作用,而仅对后续的处理器起作用

ifndef NT_UP

@@: cmp _KiBarrierWait, 0 ; 判断是否设置了KiBarrierWait YIELD

jnz short @b endif

push 0

jmp @KiIdleLoop@0 ; 进入空闲循环

stdENDP _KiSystemStartup

1.2 内核初始化

内核的初始化主要是内核各个组件的初始化,但由于这些内核组件之间有紧密的耦合关系,所以它们的初始化并不是简单地顺序执行初始化。为了解决在初始化过程中的相互依赖性问题,内核的初始化分两个阶段进行,称为阶段0和阶段1。大多数内核组件的初始化函数相应地带有一个整数参数,以指明一次调用是阶段0 初始化还是阶段1 初始化,而有些组件的初始化函数通过检查一个全局变量InitializationPhase 的值来判断当前处于哪个阶段。

我们首先来看阶段0 初始化。阶段0 初始化的目的是,将阶段1 初始化所要用到的基本数据结构建立起来。在阶段0 初始化过程中,中断被禁止,因此处理器可以顺序地执行自己的初始化逻辑。KiSystemStartup 函数首先初始化处理器的状态,包括调整它的IDT,初始化TSS(Task State Segment),以及构造PCR(Processor Control Region)。然后,调用HalInitializeProcessor 函数,为当前处理器初始化其HAL 中的PCR 和处理器间中断向量;接着调用KiInitializeKernel 函数,执行内核初始化。最后,当前线程蜕变成一个空闲线程。

因此,KiInitializeKernel 函数是实际执行内核初始化的函数,其代码位于base\\ntos\\ke\\i386\\kernlini.c 文件中。它的职责是:初始化内核数据结构,初始化空闲线程和进程对象,初始化PCR,然后调用执行体初始化函数ExpInitializeExecutive,最后返回。

VOID

KiInitializeKernel ( INPKPROCESSProcess, INPKTHREADThread, INPVOIDIdleStack, INPKPRCBPrcb, INCCHARNumber,

PLOADER_PARAMETER_BLOCKLoaderBlock ) {

ULONGDirectoryTableBase[2]; PVOIDDpcStack; KIRQLOldIrql; PKPCRPcr;

BOOLEANNpxFlag;

#if !defined(NT_UP)

BOOLEANFxsrPresent; BOOLEANXMMIPresent; #endif

ULONGFeatureBits;

#ifdefined(KE_MULTINODE)

LONG Index; #endif

KiSetProcessorType(); KiSetCR0Bits();

NpxFlag = KiIsNpxPresent(); Pcr = KeGetPcr();

// 初始化处理器的电源状态 PoInitializePrcb(Prcb);

// 检测不支持的处理器的版本 if (Prcb->CpuType == 3) {

KeBugCheckEx(UNSUPPORTED_PROCESSOR,0x386,0,0,0); }

// 获取处理器相关特性

FeatureBits = KiGetFeatureBits();

//如果主机处理器支持特性,那么在加载选项中设置开启不可执行保护 SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_OPTIN;

if (strstr(KeLoaderBlock->LoadOptions, \) != NULL) { SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_ALWAYSON; FeatureBits |= KF_GLOBAL_32BIT_NOEXECUTE;

} elseif (strstr(KeLoaderBlock->LoadOptions, \) != NULL) { SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_OPTOUT; FeatureBits |= KF_GLOBAL_32BIT_NOEXECUTE;

} elseif (strstr(KeLoaderBlock->LoadOptions, \) != NULL) { FeatureBits |= KF_GLOBAL_32BIT_NOEXECUTE;

} elseif (strstr(KeLoaderBlock->LoadOptions, \) != NULL) { SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_ALWAYSOFF; FeatureBits |= KF_GLOBAL_32BIT_EXECUTE;

} elseif (strstr(KeLoaderBlock->LoadOptions, \) != NULL) { FeatureBits |= KF_GLOBAL_32BIT_NOEXECUTE;

} elseif (strstr(KeLoaderBlock->LoadOptions, \) != NULL) { SharedUserData->NXSupportPolicy = NX_SUPPORT_POLICY_ALWAYSOFF; FeatureBits |= KF_GLOBAL_32BIT_EXECUTE; }

#ifdefined (_X86PAE_)

if ((FeatureBits & KF_NOEXECUTE) == 0) {

FeatureBits &= ~KF_GLOBAL_32BIT_NOEXECUTE; }

if ((FeatureBits & KF_GLOBAL_32BIT_NOEXECUTE) != 0) { KiEnableNXSupport(); } #endif

Prcb->FeatureBits = FeatureBits;

// 初始化PRCB中的ProcessorControlSpace内容,使得本地内核调试器可以像GDT一样获得数据 KiSaveProcessorControlState(&Prcb->ProcessorState);

// 获得处理器缓存大小信息 KiGetCacheInformation();

// 初始化每个处理器的锁数据 KiInitSpinLocks(Prcb, Number);

// 如果初始的处理器已经被初始化,那么初始化每个系统数据结构 if (Number == 0) {

KeNodeBlock[0] = &KiNode0;

#ifdefined(KE_MULTINODE)

for (Index = 1; Index < MAXIMUM_CCNUMA_NODES; Index++) {

//

// Set temporary node. //

KeNodeBlock[Index] = &KiNodeInit[Index]; } #endif

Prcb->ParentNode = KeNodeBlock[0];

KeNodeBlock[0]->ProcessorMask = Prcb->SetMember;

// Initial setting for global Cpu & Stepping levels KeI386NpxPresent = NpxFlag; KeI386CpuType = Prcb->CpuType; KeI386CpuStep = Prcb->CpuStep;

KeProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL; KeProcessorLevel = (USHORT)Prcb->CpuType; if (Prcb->CpuID == 0) { KeProcessorRevision = 0xFF00 |

(((Prcb->CpuStep>> 4) + 0xa0 ) & 0x0F0) | (Prcb->CpuStep& 0xf); } else {

KeProcessorRevision = Prcb->CpuStep; }

KeFeatureBits = FeatureBits;

KeI386FxsrPresent = ((KeFeatureBits&KF_FXSR) ? TRUE:FALSE); KeI386XMMIPresent = ((KeFeatureBits&KF_XMMI) ? TRUE:FALSE);

// As of Windows XP, cmpxchg8b is a required instruction. if ((KeFeatureBits&KF_ ) == 0) {

ULONGVendor[3];

RtlCopyMemory(Vendor, Prcb->VendorString, sizeof(Vendor)); KeBugCheckEx(UNSUPPORTED_PROCESSOR, (1 << 24 )

| (Prcb->CpuType<< 16) | Prcb->CpuStep, Vendor[0], Vendor[1], Vendor[2]); }

// 初始化兼容锁

//此处省略部分无关代码

// Performance architecture independent initialization. KiInitSystem();

// 初始化空闲线程和进程对象 DirectoryTableBase[0] = 0; DirectoryTableBase[1] = 0;

InitializeListHead(&KiProcessListHead); KeInitializeProcess(Process,

(KPRIORITY)0, (KAFFINITY)(0xffffffff), &DirectoryTableBase[0], FALSE);

Process->QuantumReset = MAXCHAR;//此处设置为最大值

KeInitializeSpinLock(&Ki486CompatibilityLock);

// 初始化内核自旋锁

KeInitializeSpinLock(&KiFreezeExecutionLock);

// 降低IRQL到APC级别 KeLowerIrql(APC_LEVEL);


Windows NT引导过程源代码分析(10).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:重庆一中高2009级(下)09年文科数学2月月考试题 doc

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: