zoukankan      html  css  js  c++  java
  • 《Linux内核设计的艺术》学习笔记(六)执行setup.s

      参考资料

      1. 8259A可编程中断控制器

    jmpi 0, SETUPSEG // 0x90200

      到这里,bootsect.s的执行就算结束了。控制权转移到了setup.s文件的手中。

      setup程序的主要作用是利用ROM BIOS中断读取机器系统数据,并将这些数据保存到0x90000开始的位置。下表基本归纳了Line 109之前的所有代码逻辑。

      表1 setup.s前半段代码的作用

    内存地址 长度(字节) 名称 描述
    0x90000 2 光标位置 行列都是从0开始,各占一个字节。由int 0x10中断(入口参数为AH=0x03)取得到DX中,并保存到内存。
    0x90002 2 扩展内存数 系统从1MB开始的扩展内存数值(KB)。由0x15中断(入口参数为AH=0x88)取得到AX中,并保存到内存。
    0x90004 2 当前活动页 当前显示的页面。由int 0x10中断(入口参数为AH=0x0F)取得到BH中,并保存到内存。
    0x90006 1 显示模式 同上,由int 0x10中断(入口参数为AH=0x0F)取得到AL中,并保存到内存。
    0x90007 1 字符的列数 同上,int 0x10中断(入口参数为AH=0x0F)取得到AH中,并保存到内存。
    0x90008 2 未知 被破坏了。int 0x10中断(入口参数为AH=0x0F,BL=0x10)。
    0x9000A 1 内存大小标识 同上,int 0x10中断(入口参数AH=0x0F,BL=0x10)取得到BL中,并保存到内存(0x00=64K,0x01=128K,0x02=192K,0x03=256K)。
    0x9000B 1 视频状态 同上,int 0x10中断(入口参数AH=0x0F,BL=0x10)取得到BL中,并保存到内存(0x00为彩色模式,I/O端口为0x3DX;0x01为单色,I/O端口为0x3BX)。
    0x9000C 2 显卡特性参数 同上,int 0x10中断(入口参数AH=0x0F,BL=0x10)取得到CX中,并保存到内存。CH和CL各有含义。
    0x90080 16 硬盘hd0参数表 取中断向量0x41所指的内存值,放于0x9000:0x0080处。由movsb命令实现。
    0x90090 16 硬盘hd1参数表 取中断向量0x46所指的内存值,放于0x9000:0x0090处。由movsb命令实现。
    0x901FC 2 根设备号 根文件系统所在的设备号在bootsect.s中设置,这里没有代码参与。 见bootsect.s中第251行。

     

    接下来使用cli命令屏蔽中断。

    cld命令将DF设置为0,增址方向。std与之相反。

    通过movsw命令,将system模块从0x10000到0x8FFFF的内存数据块(512KB)移动到0x00000开始的位置。每次移动64KB,共移动8次。

    初始化IDT寄存器和GDT寄存器。

    选通A20地址线。

    重新对8259A中断控制器编程。

    通过lmsw命令将0x0001写入到控制寄存器CR0中,打开保护模式。

    最后,通过jmpi 0, 8命令跳转至CS段8,偏移地址为0处。即,0x00000处。 

     

    图1 setup.s程序结束后内存中程序示意图

     

    setup.s代码如下:

      1 !
      2 !    setup.s        (C) 1991 Linus Torvalds
      3 !
      4 ! setup.s is responsible for getting the system data from the BIOS,
      5 ! and putting them into the appropriate places in system memory.
      6 ! both setup.s and system has been loaded by the bootblock.
      7 !
      8 ! This code asks the bios for memory/disk/other parameters, and
      9 ! puts them in a "safe" place: 0x90000-0x901FF, ie where the
     10 ! boot-block used to be. It is then up to the protected mode
     11 ! system to read them from there before the area is overwritten
     12 ! for buffer-blocks.
     13 !
     14 
     15 ! NOTE! These had better be the same as in bootsect.s!
     16 
     17 INITSEG  = 0x9000    ! we move boot here - out of the way
     18 SYSSEG   = 0x1000    ! system loaded at 0x10000 (65536).
     19 SETUPSEG = 0x9020    ! this is the current segment
     20 
     21 .globl begtext, begdata, begbss, endtext, enddata, endbss
     22 .text
     23 begtext:
     24 .data
     25 begdata:
     26 .bss
     27 begbss:
     28 .text
     29 
     30 entry start
     31 start:
     32 
     33 ! ok, the read went well so we get current cursor position and save it for
     34 ! posterity.
     35 
     36     mov    ax,#INITSEG    ! this is done in bootsect already, but...
     37     mov    ds,ax
     38     mov    ah,#0x03    ! read cursor pos
     39     xor    bh,bh
     40     int    0x10        ! save it in known place, con_init fetches
     41     mov    [0],dx        ! it from 0x90000.
     42 
     43 ! Get memory size (extended mem, kB)
     44 
     45     mov    ah,#0x88
     46     int    0x15
     47     mov    [2],ax
     48 
     49 ! Get video-card data:
     50 
     51     mov    ah,#0x0f
     52     int    0x10
     53     mov    [4],bx        ! bh = display page
     54     mov    [6],ax        ! al = video mode, ah = window width
     55 
     56 ! check for EGA/VGA and some config parameters
     57 
     58     mov    ah,#0x12
     59     mov    bl,#0x10
     60     int    0x10
     61     mov    [8],ax
     62     mov    [10],bx
     63     mov    [12],cx
     64 
     65 ! Get hd0 data
     66 
     67     mov    ax,#0x0000
     68     mov    ds,ax
     69     lds    si,[4*0x41]
     70     mov    ax,#INITSEG
     71     mov    es,ax
     72     mov    di,#0x0080
     73     mov    cx,#0x10
     74     rep
     75     movsb
     76 
     77 ! Get hd1 data
     78 
     79     mov    ax,#0x0000
     80     mov    ds,ax
     81     lds    si,[4*0x46]
     82     mov    ax,#INITSEG
     83     mov    es,ax
     84     mov    di,#0x0090
     85     mov    cx,#0x10
     86     rep
     87     movsb
     88 
     89 ! Check that there IS a hd1 :-)
     90 
     91     mov    ax,#0x01500
     92     mov    dl,#0x81
     93     int    0x13
     94     jc    no_disk1
     95     cmp    ah,#3
     96     je    is_disk1
     97 no_disk1:
     98     mov    ax,#INITSEG
     99     mov    es,ax
    100     mov    di,#0x0090
    101     mov    cx,#0x10
    102     mov    ax,#0x00
    103     rep
    104     stosb
    105 is_disk1:
    106 
    107 ! now we want to move to protected mode ...
    108 
    109     cli            ! no interrupts allowed !
    110 
    111 ! first we move the system to it's rightful place
    112 
    113     mov    ax,#0x0000
    114     cld            ! 'direction'=0, movs moves forward
    115 do_move:
    116     mov    es,ax        ! destination segment
    117     add    ax,#0x1000
    118     cmp    ax,#0x9000
    119     jz    end_move
    120     mov    ds,ax        ! source segment
    121     sub    di,di
    122     sub    si,si
    123     mov     cx,#0x8000
    124     rep
    125     movsw
    126     jmp    do_move
    127 
    128 ! then we load the segment descriptors
    129 
    130 end_move:
    131     mov    ax,#SETUPSEG    ! right, forgot this at first. didn't work :-)
    132     mov    ds,ax
    133     lidt    idt_48        ! load idt with 0,0
    134     lgdt    gdt_48        ! load gdt with whatever appropriate
    135 
    136 ! that was painless, now we enable A20
    137 
    138     call    empty_8042
    139     mov    al,#0xD1        ! command write
    140     out    #0x64,al
    141     call    empty_8042
    142     mov    al,#0xDF        ! A20 on
    143     out    #0x60,al
    144     call    empty_8042
    145 
    146 ! well, that went ok, I hope. Now we have to reprogram the interrupts :-(
    147 ! we put them right after the intel-reserved hardware interrupts, at
    148 ! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
    149 ! messed this up with the original PC, and they haven't been able to
    150 ! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
    151 ! which is used for the internal hardware interrupts as well. We just
    152 ! have to reprogram the 8259's, and it isn't fun.
    153 
    154     mov    al,#0x11        ! initialization sequence
    155     out    #0x20,al        ! send it to 8259A-1
    156     .word    0x00eb,0x00eb        ! jmp $+2, jmp $+2
    157     out    #0xA0,al        ! and to 8259A-2
    158     .word    0x00eb,0x00eb
    159     mov    al,#0x20        ! start of hardware int's (0x20)
    160     out    #0x21,al
    161     .word    0x00eb,0x00eb
    162     mov    al,#0x28        ! start of hardware int's 2 (0x28)
    163     out    #0xA1,al
    164     .word    0x00eb,0x00eb
    165     mov    al,#0x04        ! 8259-1 is master
    166     out    #0x21,al
    167     .word    0x00eb,0x00eb
    168     mov    al,#0x02        ! 8259-2 is slave
    169     out    #0xA1,al
    170     .word    0x00eb,0x00eb
    171     mov    al,#0x01        ! 8086 mode for both
    172     out    #0x21,al
    173     .word    0x00eb,0x00eb
    174     out    #0xA1,al
    175     .word    0x00eb,0x00eb
    176     mov    al,#0xFF        ! mask off all interrupts for now
    177     out    #0x21,al
    178     .word    0x00eb,0x00eb
    179     out    #0xA1,al
    180 
    181 ! well, that certainly wasn't fun :-(. Hopefully it works, and we don't
    182 ! need no steenking BIOS anyway (except for the initial loading :-).
    183 ! The BIOS-routine wants lots of unnecessary data, and it's less
    184 ! "interesting" anyway. This is how REAL programmers do it.
    185 !
    186 ! Well, now's the time to actually move into protected mode. To make
    187 ! things as simple as possible, we do no register set-up or anything,
    188 ! we let the gnu-compiled 32-bit programs do that. We just jump to
    189 ! absolute address 0x00000, in 32-bit protected mode.
    190 
    191     mov    ax,#0x0001    ! protected mode (PE) bit
    192     lmsw    ax        ! This is it!
    193     jmpi    0,8        ! jmp offset 0 of segment 8 (cs)
    194 
    195 ! This routine checks that the keyboard command queue is empty
    196 ! No timeout is used - if this hangs there is something wrong with
    197 ! the machine, and we probably couldn't proceed anyway.
    198 empty_8042:
    199     .word    0x00eb,0x00eb
    200     in    al,#0x64    ! 8042 status port
    201     test    al,#2        ! is input buffer full?
    202     jnz    empty_8042    ! yes - loop
    203     ret
    204 
    205 gdt:
    206     .word    0,0,0,0        ! dummy
    207 
    208     .word    0x07FF        ! 8Mb - limit=2047 (2048*4096=8Mb)
    209     .word    0x0000        ! base address=0
    210     .word    0x9A00        ! code read/exec
    211     .word    0x00C0        ! granularity=4096, 386
    212 
    213     .word    0x07FF        ! 8Mb - limit=2047 (2048*4096=8Mb)
    214     .word    0x0000        ! base address=0
    215     .word    0x9200        ! data read/write
    216     .word    0x00C0        ! granularity=4096, 386
    217 
    218 idt_48:
    219     .word    0            ! idt limit=0
    220     .word    0,0            ! idt base=0L
    221 
    222 gdt_48:
    223     .word    0x800        ! gdt limit=2048, 256 GDT entries
    224     .word    512+gdt,0x9    ! gdt base = 0X9xxxx
    225     
    226 .text
    227 endtext:
    228 .data
    229 enddata:
    230 .bss
    231 endbss:
    View Code
  • 相关阅读:
    [转] css选择器中:first-child与:first-of-type的区别
    [转] Javascript中理解发布--订阅模式
    [转] 浅析JavaScript设计模式——发布-订阅/观察者模式
    [转] linux学习第四十四篇:Nginx安装,Nginx默认虚拟主机,Nginx域名重定向
    [转] meta标签的作用及整理
    [转] 安装npm全局包提示权限不够
    [转] UniCode编码表
    Unicode字符编码表
    [转] Lodash常用API笔记
    [转] JavaScript 之 ArrayBuffer
  • 原文地址:https://www.cnblogs.com/AmitX-moten/p/4853882.html
Copyright © 2011-2022 走看看