《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
原文地址:https://www.cnblogs.com/AmitX-moten/p/4853882.html