现在的位置: 首页 > 综合 > 正文

Linux/boot/setup.S

2013年10月02日 ⁄ 综合 ⁄ 共 9275字 ⁄ 字号 评论关闭

Linux/boot/setup.S 

 

 1 !
 2 !       setup.S         Copyright (C) 1991, 1992 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 ! Move PS/2 aux init code to psaux.c
 15 ! (troyer@saifr00.cfsat.Honeywell.COM) 03Oct92
 16 !
 17 ! some changes and additional features by Christoph Niemann, March 1993
 18 ! (niemann@rubdv15.ETDV.Ruhr-Uni-Bochum.De)
 19 !
 20
 21 ! NOTE! These had better be the same as in bootsect.s!
 22 #include <linux/config.h>
 23 #include <linux/segment.h>
 24
 25 #ifndef SVGA_MODE
 26 #define SVGA_MODE ASK_VGA
 27 #endif
 28
 29 INITSEG = DEF_INITSEG ! we move boot here - out of the way
 30 SYSSEG   = DEF_SYSSEG   ! system loaded at 0x10000 (65536).
 31 SETUPSEG = DEF_SETUPSEG ! this is the current segment
 32
 33 .globl begtext, begdata, begbss, endtext, enddata, endbss
 34 .text
 35 begtext:
 36 .data
 37 begdata:
 38 .bss
 39 begbss:
 40 .text
 41
 42 entry start
 43 start:
 44
 45 ! ok, the read went well so we get current cursor position and save it for
 46 ! posterity.
 47
 48         mov     ax,#INITSEG     ! this is done in bootsect already, but...
 49         mov     ds,ax
 50
 51 ! Get memory size (extended mem, kB)
 52
 53         mov     ah,#0x88
 54         int     0x15
 55         mov     [2],ax
 56
 57 ! set the keyboard repeat rate to the max
 58
 59         mov     ax,#0x0305
 60         xor     bx,bx           ! clear bx
 61         int     0x16
 62
 63 ! check for EGA/VGA and some config parameters
 64
 65         mov     ah,#0x12
 66         mov     bl,#0x10
 67         int     0x10
 68         mov     [8],ax
 69         mov     [10],bx
 70         mov     [12],cx
 71         mov     ax,#0x5019
 72         cmp     bl,#0x10
 73         je      novga
 74         mov     ax,#0x1a00      ! Added check for EGA/VGA discrimination
 75         int     0x10
 76         mov     bx,ax
 77         mov     ax,#0x5019
 78         cmp     bl,#0x1a        ! 1a means VGA, anything else EGA or lower
 79         jne     novga  
 80         call    chsvga
 81 novga: mov     [14],ax
 82         mov     ah,#0x03        ! read cursor pos
 83         xor    bh,bh           ! clear bh
 84         int     0x10            ! save it in known place, con_init fetches
 85         mov     [0],dx          ! it from 0x90000.
 86        
 87 ! Get video-card data:
 88        
 89         mov     ah,#0x0f
 90         int     0x10
 91         mov     [4],bx          ! bh = display page
 92         mov     [6],ax          ! al = video mode, ah = window width
 93
 94 ! Get hd0 data
 95
 96         xor     ax,ax           ! clear ax
 97         mov     ds,ax
 98         lds     si,[4*0x41]
 99         mov     ax,#INITSEG
100         mov     es,ax
101         mov     di,#0x0080
102         mov     cx,#0x10
103         cld
104         rep
105         movsb
106
107 ! Get hd1 data
108
109         xor     ax,ax           ! clear ax
110         mov     ds,ax
111         lds     si,[4*0x46]
112         mov     ax,#INITSEG
113         mov     es,ax
114         mov     di,#0x0090
115         mov     cx,#0x10
116         cld
117         rep
118         movsb
119
120 ! Check that there IS a hd1 :-)
121
122         mov     ax,#0x01500
123         mov     dl,#0x81
124         int     0x13
125         jc      no_disk1
126         cmp     ah,#3
127         je      is_disk1
128 no_disk1:
129         mov     ax,#INITSEG
130         mov     es,ax
131         mov     di,#0x0090
132         mov     cx,#0x10
133         xor     ax,ax           ! clear ax
134         cld
135         rep
136         stosb
137 is_disk1:
138
139 ! check for PS/2 pointing device
140
141         mov     ax,#INITSEG
142         mov     ds,ax
143         mov     [0x1ff],#0      ! default is no pointing device
144         int     0x11            ! int 0x11: equipment determination
145         test    al,#0x04        ! check if pointing device installed
146         jz      no_psmouse
147         mov     [0x1ff],#0xaa   ! device present
148 no_psmouse:
149 ! now we want to move to protected mode ...
150
151         cli                     ! no interrupts allowed !
152         mov     al,#0x80        ! disable NMI for the bootup sequence
153         out     #0x70,al
154
155 ! first we move the system to its rightful place
156
157         mov     ax,#0x100       ! start of destination segment
158         mov     bx,#0x1000      ! start of source segment
159         cld                    ! 'direction'=0, movs moves forward
160 do_move:
161         mov     es,ax           ! destination segment
162         add     ax,#0x100
163         cmp     ax,#0x9000
164         jz      end_move
165         mov     ds,bx           ! source segment
166         add     bx,#0x100
167         sub     di,di
168         sub     si,si
169         mov     cx,#0x800
170         rep
171         movsw
172         jmp     do_move
173
174 ! then we load the segment descriptors
175
176 end_move:
177         mov     ax,#SETUPSEG    ! right, forgot this at first. didn't work :-)
178         mov     ds,ax
179         lidt    idt_48          ! load idt with 0,0
180         lgdt    gdt_48          ! load gdt with whatever appropriate
181
182 ! that was painless, now we enable A20
183
184         call    empty_8042
185         mov     al,#0xD1                ! command write
186         out     #0x64,al
187         call    empty_8042
188         mov     al,#0xDF                ! A20 on
189         out     #0x60,al
190         call    empty_8042
191
192 ! make sure any possible coprocessor is properly reset..
193
194         xor     ax,ax
195         out     #0xf0,al
196         call    delay
197         out     #0xf1,al
198         call    delay
199
200 ! well, that went ok, I hope. Now we have to reprogram the interrupts :-(
201 ! we put them right after the intel-reserved hardware interrupts, at
202 ! int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
203 ! messed this up with the original PC, and they haven't been able to
204 ! rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
205 ! which is used for the internal hardware interrupts as well. We just
206 ! have to reprogram the 8259's, and it isn't fun.
207
208         mov     al,#0x11                ! initialization sequence
209         out     #0x20,al                ! send it to 8259A-1
210         call    delay
211         out     #0xA0,al                ! and to 8259A-2
212         call    delay
213         mov     al,#0x20                ! start of hardware int's (0x20)
214         out     #0x21,al
215         call    delay
216         mov     al,#0x28                ! start of hardware int's 2 (0x28)
217         out     #0xA1,al
218         call    delay
219         mov     al,#0x04                ! 8259-1 is master
220         out     #0x21,al
221         call    delay
222         mov     al,#0x02                ! 8259-2 is slave
223         out     #0xA1,al
224         call    delay
225         mov     al,#0x01                ! 8086 mode for both
226         out     #0x21,al
227         call    delay
228         out     #0xA1,al
229         call    delay
230         mov     al,#0xFF                ! mask off all interrupts for now
231         out     #0xA1,al
232         call    delay
233         mov     al,#0xFB                ! mask all irq's but irq2 which
234         out     #0x21,al                ! is cascaded
235
236 ! well, that certainly wasn't fun :-(. Hopefully it works, and we don't
237 ! need no steenking BIOS anyway (except for the initial loading :-).
238 ! The BIOS-routine wants lots of unnecessary data, and it's less
239 ! "interesting" anyway. This is how REAL programmers do it.
240 !
241 ! Well, now's the time to actually move into protected mode. To make
242 ! things as simple as possible, we do no register set-up or anything,
243 ! we let the gnu-compiled 32-bit programs do that. We just jump to
244 ! absolute address 0x00000, in 32-bit protected mode.
245 !
246 ! Note that the short jump isn't strictly needed, althought there are
247 ! reasons why it might be a good idea. It won't hurt in any case.
248 !
249         mov     ax,#0x0001      ! protected mode (PE) bit
250         lmsw    ax              ! This is it!
251         jmp     flush_instr
252 flush_instr:
253         jmpi    0x1000,KERNEL_CS        ! jmp offset 1000 of segment 0x10 (cs)
254
255 ! This routine checks that the keyboard command queue is empty
256 ! (after emptying the output buffers)
257 !
258 ! No timeout is used - if this hangs there is something wrong with
259 ! the machine, and we probably couldn't proceed anyway.
260 empty_8042:
261         call    delay
262         in      al,#0x64        ! 8042 status port
263         test    al,#1           ! output buffer?
264         jz      no_output
265         call    delay
266         in      al,#0x60        ! read it
267         jmp     empty_8042
268 no_output:
269         test    al,#2           ! is input buffer full?
270         jnz     empty_8042      ! yes - loop
271         ret
272 !
273 ! Read a key and return the (US-)ascii code in al, scan code in ah
274 !
275 getkey:
276         xor     ah,ah
277         int     0x16
278         ret
279
280 !
281 ! Read a key with a timeout of 30 seconds. The cmos clock is used to get
282 ! the time.
283 !
284 getkt:
285         call    gettime
286         add     al,#30          ! wait 30 seconds
287         cmp     al,#60
288         jl      lminute
289         sub     al,#60
290 lminute:
291         mov     cl,al
292 again: mov     ah,#0x01
293         int     0x16
294         jnz     getkey          ! key pressed, so get it
295         call    gettime
296         cmp     al,cl
297         jne     again
298         mov     al,#0x20        ! timeout, return default char `space'
299         ret
300
301 !
302 ! Flush the keyboard buffer
303 !
304 flush: mov     ah,#0x01
305         int     0x16
306         jz      empty
307         xor     ah,ah
308         int     0x16
309         jmp     flush
310 empty: ret
311
312 !
313 ! Read the cmos clock. Return the seconds in al
314 !
315 gettime:
316         push    cx
317         mov     ah,#0x02
318         int     0x1a
319         mov     al,dh                   ! dh contains the seconds
320         and     al,#0x0f
321         mov     ah,dh
322         mov     cl,#0x04
323         shr     ah,cl
324         aad
325

抱歉!评论已关闭.