II、实模式下的初始化

  实模式下的初始化,主要是指从内核引导成功后,到进入保护模式之前系统所做的一些处理。在内核源码中对应的程序是 /Arch/i386/boot/setup.S;以下部分主要是针对此文件进行的分析。这部分的分析主要是要弄懂它的处理流程和INITSEG(9000:0000)段参数表的建立,此参数表包含了很多硬件参数,这些都是以后进行保护模式下初始化,以及核心建立的基础。

1. 几个其它相关文件:

<1> /Arch/i386/boot/bootsect.S 

<2> /include/linux/config.h 

<3> /include/asm/boot.h 

<4> /include/ asm/segment.h 

<5> /include/linux/version.h 

<6> /include/linux/compile.h



2. 实模式下的初始化过程分析:

 


INITSEG(9000:0000)
段参数表:(参见Include/linux/tty.h


参数名

偏移量(段址均为0x9000)

长度Byte

参考文件

PARAM_CURSOR_POS

0x0000

2

Arch/i386/boot/video.S

extended mem Size

0x0002

2

Arch/i386/boot/setup.S

PARAM_VIDEO_PAGE

0x0004

2

Arch/i386/boot/video.S

PARAM_VIDEO_MODE

0x0006

1

Arch/i386/boot/video.S

PARAM_VIDEO_COLS

0x0007

1

Arch/i386/boot/video.S

没用

0x0008

2

Include/linux/tty.h

PARAM_VIDEO_EGA_BX

0x000a

2

Arch/i386/boot/video.S

没用

0x000c

2

Include/linux/tty.h

PARAM_VIDEO_LINES

0x000e

1

Arch/i386/boot/video.S

PARAM_HAVE_VGA

0x000f

1

Arch/i386/boot/video.S

PARAM_FONT_POINTS

0x0010

2

Arch/i386/boot/video.S

PARAM_LFB_WIDTH

0x0012

2

Arch/i386/boot/video.S

PARAM_LFB_HEIGHT

0x0014

2

Arch/i386/boot/video.S

PARAM_LFB_DEPTH

0x0016

2

Arch/i386/boot/video.S

PARAM_LFB_BASE

0x0018

4

Arch/i386/boot/video.S

PARAM_LFB_SIZE

0x001c

4

Arch/i386/boot/video.S

暂未用①

0x0020

4

Include/linux/tty.h

PARAM_LFB_LINELENGTH

0x0024

2

Arch/i386/boot/video.S

PARAM_LFB_COLORS

0x0026

6

Arch/i386/boot/video.S

暂未用②

0x002c

2

Arch/i386/boot/video.S

PARAM_VESAPM_SEG

0x002e

2

Arch/i386/boot/video.S

PARAM_VESAPM_OFF

0x0030

2

Arch/i386/boot/video.S

PARAM_LFB_PAGES

0x0032

2

Arch/i386/boot/video.S

保留

0x0034--0x003f


Include/linux/tty.h

APM BIOS Version③

0x0040

2

Arch/i386/boot/setup.S

BIOS code segment

0x0042

2

Arch/i386/boot/setup.S

BIOS entry offset

0x0044

4

Arch/i386/boot/setup.S

BIOS 16 bit code seg

0x0048

2

Arch/i386/boot/setup.S

BIOS data segment

0x004a

2

Arch/i386/boot/setup.S

支持32位标志④

0x004c

2

Arch/i386/boot/setup.S

BIOS code seg length

0x004e

4

Arch/i386/boot/setup.S

BIOS data seg length

0x0052

2

Arch/i386/boot/setup.S

hd0 参数

0x0080

16

Arch/i386/boot/setup.S

hd0 参数

0x0090

16

Arch/i386/boot/setup.S

PS/2 device 标志⑤

0x01ff

1

Arch/i386/boot/setup.S


* : ① Include/linux/tty.h : CL_MAGIC and CL_OFFSET here

 

    1. Include/linux/tty.h : 
        
    unsigned char rsvd_size; /* 0x2c */ 
      
    unsigned char rsvd_pos; /* 0x2d */



    ③ 0表示没有APM BIOS

    ④ 0x0002置位表示支持32位模式

    ⑤ 0表示没有,0x0aa表示有鼠标器

    III、保护模式下的初始化

      保护模式下的初始化,是指处理机进入保护模式后到运行系统第一个内核程序过程中系统所做的一些处理。保护模式下的初始化在内核源码中对应的程序是 /Arch/i386/boot/compressed/head.S 和 /Arch/i386/KERNEL/head.S ;以下部分主要是针对这两个文件进行的分析。

    1. 几个相关文件:
    <1.> /Arch/i386/boot/compressed/head.S 
    
    <2.> /Arch/i386/KERNEL/head.S 
    
    <3.> //Arch/i386/boot/compressed/MISC.c 
    
    <4.> /Arch/i386/boot/setup.S 
    
    <5.> /include/ asm/segment.h 
    
    <6.> /arch/i386/kernel/traps.c 
    
    <7.> /include/i386/desc.h 
    
    <8.> /include/asm-i386/processor.h
    1. 保护模式下的初始化过程分析:
      一、/Arch/i386/KERNEL/head.S流程:

     

     

    二、/Arch/i386/boot/compressed/head.S流程:

    1. 从流程图中可以看到,保护模式下的初始化主要干了这样几件事:
    1. 解压内核到0x100000处、
    2. 建立页目录和pg0页表并启动分页功能(即虚存管理功能)、
    3. 保存实模式下测到的硬件信息到empty_zero_page、初始化命令缓存区、
    4. 检测cpu类型、检查协处理器、
    5. 重新建立gdt全局描述符表、和中断描述附表idt;
    1. 从页目录和pg0页表可以看出,0&#0;4M物理内存被用作系统区,它被映射到系统段线性空间的0&#0;4M和3G&#0;3G+4M;即系统可以通过访问这两个段来访问实际的0&#0;4M物理内存,也就是系统所在的区域;
    2. 本来在实模式下初始化时已经建立了全局描述符表gdt,而此处重新建立全局描述符表gdt则主要是出于两个原因:一个就是若内核是大内核bzimag,则以前建立的gdt,可能已经在解压时被覆盖掉了所以,在这个源码文件中均只采用相对转移指令jxx nf或jxx nb;二是以前建立的gdt是建立在实地址方式下的,而现在则是在启用保护虚拟地址方式之后建立的,也即现在的gdt是建立在逻辑地址(即线性地址)上的;
    3. 每次建立新的gdt后和启用保护虚拟地址方式后都必须重新装载系统栈和重新初始化各段寄存器:cs,ds,es,fs,gs;
    4. 从实模式下的初始化和保护模式下的初始化过程可以看出,linux系统由实模式进入到保护模式的过程大致如下:

     

    6.由于分页机制只能在保护模式下启动,不能在实模式下启动,所以第一步是必要的;又因为在386保护模式下gdt和idt是建立在逻辑地址(线性地址)上的,所以第三步也是必要的;
    7.经过实模式和保护模式下的初始后,主要系统数据分布如下:

    初始后主要系统数据分布表


    位置

    系统数据

    大小

    0x101000

    页目录swapper_pg_dir

    4K

    0x102000

    页表pg0

    4K

    0x103000

    empty_bad_page

    4K

    0x104000

    empty_bad_page_table

    4K

    0x105000

    empty_zero_page

    4K

    0x105000

    系统硬件参数

    2K

    0x105800

    命令缓冲区

    2K

    0x106000

    全局描述附表gdt_table

    4192B



     

      那几张图不知道怎么传了,这篇文章在别的地方也有。可以查查。个人觉得很不错。


      从上面对 Linux 系统的初始化过程的分析可以看出,以程序执行流程为线索、一线串珠,就是按照程序的执行先后顺序,弄懂程序执行的各个阶段所进行的处理,及其各阶段之间的相互联系。而流程图应该是这种分析方法最合适的表达工具。




      事实上,以程序执行流程为线索,是分析任何源代码都首选的方法。由于操作系统的特殊性,光用这种方法是远远不够的。当然用这种方法来分析系统的初始化过程或用户进程的执行流程应该说是很有效的。