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

2019-08-30 13:20

#ifdefi386

//此处硬编码osloader的地址

FileName = (PCHAR)BlAllocateHeap(2); FileName[0] = '\\\\'; FileName[1] = '\\0'; #else

FileSize = strlen(&HalDirectoryPath[0]) + 1; FileName = (PCHAR)BlAllocateHeap(FileSize); strcpy(FileName, &HalDirectoryPath[0]); #endif//i386

BlLoaderBlock->NtHalPathName = FileName;

// 获取NTFS设备的签名信息以允许内核创建正确的ARC名称 BlGetArcDiskInformation();

// 此处执行特定的安装代码.

Status = BlSetupForNt(BlLoaderBlock); if (Status != ESUCCESS) {

BlFatalError(LOAD_SW_INT_ERR_CLASS,DIAG_BL_SETUP_FOR_NT,LOAD_SW_INT_ERR_ACT); gotoLoadFailed; }

// 关闭调试系统 BlLogTerminate();

// 将控制权转换给已加载的映像 (SystemEntry)(BlLoaderBlock); Status = EBADF;

BlFatalError(LOAD_SW_BAD_FILE_CLASS,DIAG_BL_KERNEL_INIT_XFER,LOAD_SW_FILE_REINST_ACT); LoadFailed:

returnStatus; }

至此,引导系统所需的模块(包括内核映像、HAL,以及必要的设备驱动程序)都已经被加载到内存中。而且,在此过程中os loader 也已经构造了一个参数块,记录下了这次引导过程中加载器所获得的各种参数信息。参数块的类型为LOADER_PARAMETER_BLOCK,Windows 内核在初始化过程中将会用到这些参数信息。WRK 中包含有它的定义,如下(见public\\internal\\base\\inc\\arc.h 文件):

typedefstruct_LOADER_PARAMETER_BLOCK {

LIST_ENTRYLoadOrderListHead; //加载的模块链表,每个元素都为KLDR_DATA_TABLE_ENTRY

LIST_ENTRYMemoryDescriptorListHead;

//内存描述符链表,每个元素都为MEMORY_ALLOCATION_DESCRIPTOR

LIST_ENTRYBootDriverListHead;//引导驱动程序链表,每个元素都为BOOT_DRIVER_LIST_ENTRY ULONG_PTRKernelStack; ULONG_PTRPrcb; ULONG_PTRProcess; ULONG_PTRThread; PVOIDRegistryBase;

//内核栈顶

//进程环境,指向一个进程控制块 //初始进程,EPROCESS //初始线程,ETHREAD //系统储巢的长度 //系统储巢的基地址

ULONGRegistryLength;

PCONFIGURATION_COMPONENT_DATAConfigurationRoot; //配置树,包含ISA,磁盘和ACPI的配置数据 PCHARArcBootDeviceName;

//引导分区的ARC名称

PCHARArcHalDeviceName; //系统分区的ARC名称

PCHARNtBootPathName; //OS目录的路径名称,比如\PCHARNtHalPathName; PCHARLoadOptions;

//OD加载器的路径名称,比如\//引导选项,来自boot.ini

//包含ANSI代码页,OEM代码页和Unicode码表 //OEM字体文件

PNLS_DATA_BLOCKNlsData; PVOIDOemFontFile;

PARC_DISK_INFORMATIONArcDiskInformation; //所有磁盘的签名结构

struct_SETUP_LOADER_BLOCK *SetupLoaderBlock; //网络引导或文字模式安装引导 PLOADER_PARAMETER_EXTENSIONExtension; //扩展部分

union {

I386_LOADER_BLOCKI386; // ALPHA_LOADER_BLOCK Alpha; // IA64_LOADER_BLOCK Ia64;

} u;

} LOADER_PARAMETER_BLOCK, *PLOADER_PARAMETER_BLOCK;

由上述代码的注解可以看出,LOADER_PARAMETER_BLOCK 参数块中包含了有关这次引导的各种参数信息和系统配置,这里ARC 名称是指符合ARC(Advanced RISCComputing)命名规范的字符串,例如“multi(0)disk(0)rdisk(0)partition(1)”是指0 号磁盘控制器第一块硬盘上的第一个分区。注意,参数块中的绝大多数信息由os loader 来填充,而在接下来的内核初始化过程中使用,但也有例外,比如有关线程和进程的信息需要在内核初始化过程中填充。

最后,os loader 将控制权交给内核模块的入口函数,该函数将不再返回,所以,接下来的引导过程由内核模块继续进行,引导扇区和系统加载器(ntldr 或os loader)的使命已经完成。下图显示了以上介绍的引导步骤。

我们已经看到,ntldr 构造了一个类型为LOADER_PARAMETER_BLOCK 的参数块,把与系统初始化相关的参数信息包装到此结构中,然后将控制权传递给内核模块ntoskrnl.exe 的入口函数。因此,内核的初始化从内核模块的入口函数开始,WRK 包含了内核初始化过程的绝大多数代码。此入口函数为KiSystemStartup,它是一个汇编函数,位于base\\ntos\\ke\\i386\\newsysbg.asm 文件中。

cPublicProc _KiSystemStartup ,1

push ebp mov ebp, esp

sub esp, 32 ;分配空间给全局变量 mov ebx, dword ptr KissLoaderBlock

mov _KeLoaderBlock, ebx ; 获取加载器的参数 movzx ecx, _KeNumberProcessors ;获取处理器的个数 mov KissPbNumber, ecx

or ecx, ecx ;判断是否为引导处理器 jnz @f ;不是引导处理器

; 初始化0阶段使用静态的内存

mov dword ptr [ebx].LpbThread, offset _KiInitialThread ;初始化线程 mov dword ptr [ebx].LpbKernelStack, offset P0BootStack ;内核堆栈 push KGDT_R0_PCR ; P0 needs FS set pop fs

; 在Prcb中存储处理器序号

mov byte ptr PCR[PcPrcbData+PbNumber], cl

;此处开始构造PCR (Processor Control Region)

@@:

mov eax, dword ptr [ebx].LpbThread mov dword ptr KissIdleThread, eax

lea ecx, [eax].ThApcState.AsApcListHead ;初始化内核APC链表头 mov [eax].ThApcState.AsApcListHead, ecx ; mov [eax].ThApcState.AsApcListHead+4, ecx ; mov eax, dword ptr [ebx].LpbKernelStack mov dword ptr KissIdleStack, eax

stdCall _KiInitializeMachineType cmp byte ptr KissPbNumber, 0 jne kiss_notp0

; 初始化GDT,PCR,TSS,IDT

stdCall GetMachineBootPointers ; (edi) -> gdt ; (esi) -> pcr ; (edx) ->tss ; (eax) -> idt

; 保存相关参数到相应的寄存器 mov KissGdt, edi mov KissPcr, esi mov KissTss, edx mov KissIdt, eax

;将TSS转换为32位,因为ntloader传递的tss为16位 lea ecx,[edi]+KGDT_TSS ; (ecx) -> TSS descriptor

mov byte ptr [ecx+5],089h ; 32bit, dpl=0, present, TSS32, not busy

; KiInitializeTSS2( ; TSS的线性地址 ; TSS描述符的线性地址 ; );

stdCall _KiInitializeTSS2, stdCall _KiInitializeTSS, mov cx,KGDT_TSS

ltr cx ;从GDT中取出相应的TSS段描述符

; 设置32位双重故障任务门去获取双重故障异常 mov eax,KissIdt

lea ecx,[eax]+40h ; 异常向量号8

mov byte ptr [ecx+5],085h ; 描述符特权级别dpl=0, present, taskgate mov word ptr [ecx+2],KGDT_DF_TSS

lea ecx,[edi]+KGDT_DF_TSS

mov byte ptr [ecx+5],089h ; 32位, 描述符特权级别dpl=0, present, TSS32, not busy

mov edx,offset FLAT:_KiDoubleFaultTSS mov eax,edx

mov [ecx+KgdtBaseLow],ax shr eax,16

mov [ecx+KgdtBaseHi],ah mov [ecx+KgdtBaseMid],al mov eax, MINIMUM_TSS_SIZE mov [ecx+KgdtLimitLow],ax

; KiInitializeTSS(

; 双重故障任务状态段 ; ); push edx

stdCall _KiInitializeTSS, pop edx

mov eax,cr3

mov [edx+TssCr3],eax

mov eax, offset FLAT:_KiDoubleFaultStack mov dword ptr [edx+TssEsp],eax mov dword ptr [edx+TssEsp0],eax

mov dword ptr [edx+020h],offset FLAT:_KiTrap08 mov dword ptr [edx+024h],0 ; eflags

mov word ptr [edx+04ch],KGDT_R0_CODE ; 设置CS的值 mov word ptr [edx+058h],KGDT_R0_PCR ; 设置FS的值 mov [edx+050h],ss

mov word ptr [edx+048h],KGDT_R3_DATA OR RPL_MASK ; Es mov word ptr [edx+054h],KGDT_R3_DATA OR RPL_MASK ; Ds


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

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

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

马上注册会员

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