2012.1.22 - Linux内核 - 操作系统的引导

时间:2022-11-07 15:45:42

本文始作于2012年1月22日,刊登于人人网,于2013年2月13日迁移至此

现在是早上4:24,今天忙活了一宿,把setup.s大体轮廓作出来了,只是刚刚达到要求的合格品,明天还要继续改进,要把所有信息都进行输出才算完满。我在写输出的时候不明白什么是页号,后来百度,虽然还是不太明白,但是知道该怎么填了,像Bios这样低端的部分肯定用0。

bios中断中的页号:

   页就是将显示内存分成N份,每份叫一页.这是一种简化的说法,事实上根据硬件的不同有些小区别.
   它的产生是因为显存大于内存分配给显存的映射空间.一般在文本模式下只有一页,因此总是用第0页就可以了.
   在图形模式下需要计算出屏幕上某个位置处在显存的第几页,并进行换页操作才能写入指定位置.
   可以看看VGA编程方面的相关资料.

完成功能:setup.s在运行开始向屏幕输出一串字符串“Now we are in SETUP”;能判断出有没有第二快硬盘,并将结果输出。其实原内核已经可以判断出来了,我做的只是在适当的地方插入输出语句和必要的跳转。

2012.1.22 - Linux内核 - 操作系统的引导

源代码如下:

  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 ! Show some message
 34 
 35     mov ax,#SETUPSEG
 36     mov es,ax
 37 
 38     mov ah,#0x03    ! read cursor pos
 39     xor bh,bh 
 40     int 0x10
 41 
 42     mov cx,#19
 43     mov bx,#0x0007
 44     mov bp,#message
 45     mov ax,#0x1301
 46     int 0x10
 47 
 48     mov ax,#0xe0d
 49     int 0x10
 50     mov al,#0x0a
 51     int 0x10
 52     mov ax,#0xe0d
 53     int 0x10
 54     mov al,#0x0a
 55     int 0x10
 56 
 57 ! ok, the read went well so we get current cursor position and save it for
 58 ! posterity.
 59 
 60     mov    ax,#INITSEG    ! this is done in bootsect already, but...
 61     mov    ds,ax
 62     mov    ah,#0x03    ! read cursor pos
 63     xor    bh,bh
 64     int    0x10        ! save it in known place, con_init fetches
 65     mov    [0],dx        ! it from 0x90000.
 66 
 67 ! Get memory size (extended mem, kB)
 68 
 69     mov    ah,#0x88
 70     int    0x15
 71     mov    [2],ax
 72 
 73 ! Get video-card data:
 74 
 75     mov    ah,#0x0f
 76     int    0x10
 77     mov    [4],bx        ! bh = display page
 78     mov    [6],ax        ! al = video mode, ah = window width
 79 
 80 ! check for EGA/VGA and some config parameters
 81 
 82     mov    ah,#0x12
 83     mov    bl,#0x10
 84     int    0x10
 85     mov    [8],ax
 86     mov    [10],bx
 87     mov    [12],cx
 88 
 89 ! Get hd0 data
 90 
 91     mov    ax,#0x0000
 92     mov    ds,ax
 93     lds    si,[4*0x41]
 94     mov    ax,#INITSEG
 95     mov    es,ax
 96     mov    di,#0x0080
 97     mov    cx,#0x10
 98     rep
 99     movsb
100 
101 ! Get hd1 data
102 
103     mov    ax,#0x0000
104     mov    ds,ax
105     lds    si,[4*0x46]
106     mov    ax,#INITSEG
107     mov    es,ax
108     mov    di,#0x0090
109     mov    cx,#0x10
110     rep
111     movsb
112 
113 ! Check that there IS a hd1 :-)
114 
115     mov    ax,#0x01500
116     mov    dl,#0x81
117     int    0x13
118     jc    no_disk1
119     cmp    ah,#3
120     je    is_disk1
121 
122 no_disk1:
123 
124 ! Show some message
125 
126     mov ax,#SETUPSEG
127     mov es,ax
128 
129     mov ah,#0x03    ! read cursor pos
130     xor bh,bh 
131     int 0x10
132 
133     mov cx,#15
134     mov bx,#0x0007
135     mov bp,#no
136     mov ax,#0x1301
137     int 0x10
138 
139     mov ax,#0xe0d
140     int 0x10
141     mov al,#0x0a
142     int 0x10
143     int 0x10
144     int 0x10
145     int 0x10
146     int 0x10
147 
148     mov    ax,#INITSEG
149     mov    es,ax
150     mov    di,#0x0090
151     mov    cx,#0x10
152     mov    ax,#0x00
153     rep
154     stosb
155 
156     jmp exit
157 
158 is_disk1:
159 
160 ! Show some message
161 
162     mov ax,#SETUPSEG
163     mov es,ax
164 
165     mov ah,#0x03    ! read cursor pos
166     xor bh,bh 
167     int 0x10
168 
169     mov cx,#12
170     mov bx,#0x0007
171     mov bp,#exist
172     mov ax,#0x1301
173     int 0x10
174 
175     mov ax,#0xe0d
176     int 0x10
177     mov al,#0x0a
178     int 0x10
179     int 0x10
180     int 0x10
181     int 0x10
182     int 0x10
183 
184 exit:
185 
186 ! now we want to move to protected mode ...
187 
188     cli            ! no interrupts allowed !
189 
190 ! first we move the system to it's rightful place
191 
192     mov    ax,#0x0000
193     cld            ! 'direction'=0, movs moves forward
194 do_move:
195     mov    es,ax        ! destination segment
196     add    ax,#0x1000
197     cmp    ax,#0x9000
198     jz    end_move
199     mov    ds,ax        ! source segment
200     sub    di,di
201     sub    si,si
202     mov     cx,#0x8000
203     rep
204     movsw
205     jmp    do_move
206 
207 ! then we load the segment descriptors
208 
209 end_move:
210     mov    ax,#SETUPSEG    ! right, forgot this at first. didn't work :-)
211     mov    ds,ax
212     lidt    idt_48        ! load idt with 0,0
213     lgdt    gdt_48        ! load gdt with whatever appropriate
214 
215 ! that was painless, now we enable A20
216 
217     call    empty_8042
218     mov    al,#0xD1        ! command write
219     out    #0x64,al
220     call    empty_8042
221     mov    al,#0xDF        ! A20 on
222     out    #0x60,al
223     call    empty_8042
224 
225 ! well, that went ok, I hope. Now we have to reprogram the interrupts :-(
226 ! we put them right after the intel-reserved hardware interrupts, at
227 ! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
228 ! messed this up with the original PC, and they haven't been able to
229 ! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
230 ! which is used for the internal hardware interrupts as well. We just
231 ! have to reprogram the 8259's, and it isn't fun.
232 
233     mov    al,#0x11        ! initialization sequence
234     out    #0x20,al        ! send it to 8259A-1
235     .word    0x00eb,0x00eb        ! jmp $+2, jmp $+2
236     out    #0xA0,al        ! and to 8259A-2
237     .word    0x00eb,0x00eb
238     mov    al,#0x20        ! start of hardware int's (0x20)
239     out    #0x21,al
240     .word    0x00eb,0x00eb
241     mov    al,#0x28        ! start of hardware int's 2 (0x28)
242     out    #0xA1,al
243     .word    0x00eb,0x00eb
244     mov    al,#0x04        ! 8259-1 is master
245     out    #0x21,al
246     .word    0x00eb,0x00eb
247     mov    al,#0x02        ! 8259-2 is slave
248     out    #0xA1,al
249     .word    0x00eb,0x00eb
250     mov    al,#0x01        ! 8086 mode for both
251     out    #0x21,al
252     .word    0x00eb,0x00eb
253     out    #0xA1,al
254     .word    0x00eb,0x00eb
255     mov    al,#0xFF        ! mask off all interrupts for now
256     out    #0x21,al
257     .word    0x00eb,0x00eb
258     out    #0xA1,al
259 
260 ! well, that certainly wasn't fun :-(. Hopefully it works, and we don't
261 ! need no steenking BIOS anyway (except for the initial loading :-).
262 ! The BIOS-routine wants lots of unnecessary data, and it's less
263 ! "interesting" anyway. This is how REAL programmers do it.
264 !
265 ! Well, now's the time to actually move into protected mode. To make
266 ! things as simple as possible, we do no register set-up or anything,
267 ! we let the gnu-compiled 32-bit programs do that. We just jump to
268 ! absolute address 0x00000, in 32-bit protected mode.
269     mov    ax,#0x0001    ! protected mode (PE) bit
270     lmsw    ax        ! This is it!
271     jmpi    0,8        ! jmp offset 0 of segment 8 (cs)
272 
273 ! This routine checks that the keyboard command queue is empty
274 ! No timeout is used - if this hangs there is something wrong with
275 ! the machine, and we probably couldn't proceed anyway.
276 empty_8042:
277     .word    0x00eb,0x00eb
278     in    al,#0x64    ! 8042 status port
279     test    al,#2        ! is input buffer full?
280     jnz    empty_8042    ! yes - loop
281     ret
282 
283 gdt:
284     .word    0,0,0,0        ! dummy
285 
286     .word    0x07FF        ! 8Mb - limit=2047 (2048*4096=8Mb)
287     .word    0x0000        ! base address=0
288     .word    0x9A00        ! code read/exec
289     .word    0x00C0        ! granularity=4096, 386
290 
291     .word    0x07FF        ! 8Mb - limit=2047 (2048*4096=8Mb)
292     .word    0x0000        ! base address=0
293     .word    0x9200        ! data read/write
294     .word    0x00C0        ! granularity=4096, 386
295 
296 message:                ! 19byte
297     .ascii  "Now we are in SETUP"
298 
299 exist:                  ! 12byte
300     .ascii  "There is hd1"
301 
302 no:                     ! 15byte
303     .ascii  "There isn't hd1"
304 !    .byte   13,10,13,10
305 
306 idt_48:
307     .word    0            ! idt limit=0
308     .word    0,0            ! idt base=0L
309 
310 gdt_48:
311     .word    0x800        ! gdt limit=2048, 256 GDT entries
312     .word    512+gdt,0x9    ! gdt base = 0X9xxxx
313     
314 .text
315 endtext:
316 .data
317 enddata:
318 .bss
319 endbss: