summaryrefslogtreecommitdiffstats
path: root/src/boot/setup.s
diff options
context:
space:
mode:
Diffstat (limited to 'src/boot/setup.s')
-rw-r--r--src/boot/setup.s242
1 files changed, 242 insertions, 0 deletions
diff --git a/src/boot/setup.s b/src/boot/setup.s
new file mode 100644
index 0000000..b8aae75
--- /dev/null
+++ b/src/boot/setup.s
@@ -0,0 +1,242 @@
1 .code16
2# rewrite with AT&T syntax by falcon <wuzhangjin@gmail.com> at 081012
3#
4# setup.s (C) 1991 Linus Torvalds
5#
6# setup.s is responsible for getting the system data from the BIOS,
7# and putting them into the appropriate places in system memory.
8# both setup.s and system has been loaded by the bootblock.
9#
10# This code asks the bios for memory/disk/other parameters, and
11# puts them in a "safe" place: 0x90000-0x901FF, ie where the
12# boot-block used to be. It is then up to the protected mode
13# system to read them from there before the area is overwritten
14# for buffer-blocks.
15#
16
17# NOTE! These had better be the same as in bootsect.s!
18
19 .equ INITSEG, 0x9000 # we move boot here - out of the way
20 .equ SYSSEG, 0x1000 # system loaded at 0x10000 (65536).
21 .equ SETUPSEG, 0x9020 # this is the current segment
22
23 .global _start, begtext, begdata, begbss, endtext, enddata, endbss
24 .text
25 begtext:
26 .data
27 begdata:
28 .bss
29 begbss:
30 .text
31
32 ljmp $SETUPSEG, $_start
33_start:
34
35# ok, the read went well so we get current cursor position and save it for
36# posterity.
37
38 mov $INITSEG, %ax # this is done in bootsect already, but...
39 mov %ax, %ds
40 mov $0x03, %ah # read cursor pos
41 xor %bh, %bh
42 int $0x10 # save it in known place, con_init fetches
43 mov %dx, %ds:0 # it from 0x90000.
44# Get memory size (extended mem, kB)
45
46 mov $0x88, %ah
47 int $0x15
48 mov %ax, %ds:2
49
50# Get video-card data:
51
52 mov $0x0f, %ah
53 int $0x10
54 mov %bx, %ds:4 # bh = display page
55 mov %ax, %ds:6 # al = video mode, ah = window width
56
57# check for EGA/VGA and some config parameters
58
59 mov $0x12, %ah
60 mov $0x10, %bl
61 int $0x10
62 mov %ax, %ds:8
63 mov %bx, %ds:10
64 mov %cx, %ds:12
65
66# Get hd0 data
67
68 mov $0x0000, %ax
69 mov %ax, %ds
70 lds %ds:4*0x41, %si
71 mov $INITSEG, %ax
72 mov %ax, %es
73 mov $0x0080, %di
74 mov $0x10, %cx
75 rep
76 movsb
77
78# Get hd1 data
79
80 mov $0x0000, %ax
81 mov %ax, %ds
82 lds %ds:4*0x46, %si
83 mov $INITSEG, %ax
84 mov %ax, %es
85 mov $0x0090, %di
86 mov $0x10, %cx
87 rep
88 movsb
89
90# Check that there IS a hd1 :-)
91
92 mov $0x01500, %ax
93 mov $0x81, %dl
94 int $0x13
95 jc no_disk1
96 cmp $3, %ah
97 je is_disk1
98no_disk1:
99 mov $INITSEG, %ax
100 mov %ax, %es
101 mov $0x0090, %di
102 mov $0x10, %cx
103 mov $0x00, %ax
104 rep
105 stosb
106is_disk1:
107
108# now we want to move to protected mode ...
109
110 cli # no interrupts allowed !
111
112# first we move the system to it's rightful place
113
114 mov $0x0000, %ax
115 cld # 'direction'=0, movs moves forward
116do_move:
117 mov %ax, %es # destination segment
118 add $0x1000, %ax
119 cmp $0x9000, %ax
120 jz end_move
121 mov %ax, %ds # source segment
122 sub %di, %di
123 sub %si, %si
124 mov $0x8000, %cx
125 rep
126 movsw
127 jmp do_move
128
129# then we load the segment descriptors
130
131end_move:
132 mov $SETUPSEG, %ax # right, forgot this at first. didn't work :-)
133 mov %ax, %ds
134 lidt idt_48 # load idt with 0,0
135 lgdt gdt_48 # load gdt with whatever appropriate
136
137# that was painless, now we enable A20
138
139 #call empty_8042 # 8042 is the keyboard controller
140 #mov $0xD1, %al # command write
141 #out %al, $0x64
142 #call empty_8042
143 #mov $0xDF, %al # A20 on
144 #out %al, $0x60
145 #call empty_8042
146 inb $0x92, %al # open A20 line(Fast Gate A20).
147 orb $0b00000010, %al
148 outb %al, $0x92
149
150# well, that went ok, I hope. Now we have to reprogram the interrupts :-(
151# we put them right after the intel-reserved hardware interrupts, at
152# int 0x20-0x2F. There they won't mess up anything. Sadly IBM really
153# messed this up with the original PC, and they haven't been able to
154# rectify it afterwards. Thus the bios puts interrupts at 0x08-0x0f,
155# which is used for the internal hardware interrupts as well. We just
156# have to reprogram the 8259's, and it isn't fun.
157
158 mov $0x11, %al # initialization sequence(ICW1)
159 # ICW4 needed(1),CASCADE mode,Level-triggered
160 out %al, $0x20 # send it to 8259A-1
161 .word 0x00eb,0x00eb # jmp $+2, jmp $+2
162 out %al, $0xA0 # and to 8259A-2
163 .word 0x00eb,0x00eb
164 mov $0x20, %al # start of hardware int's (0x20)(ICW2)
165 out %al, $0x21 # from 0x20-0x27
166 .word 0x00eb,0x00eb
167 mov $0x28, %al # start of hardware int's 2 (0x28)
168 out %al, $0xA1 # from 0x28-0x2F
169 .word 0x00eb,0x00eb # IR 7654 3210
170 mov $0x04, %al # 8259-1 is master(0000 0100) --\
171 out %al, $0x21 # |
172 .word 0x00eb,0x00eb # INT /
173 mov $0x02, %al # 8259-2 is slave( 010 --> 2)
174 out %al, $0xA1
175 .word 0x00eb,0x00eb
176 mov $0x01, %al # 8086 mode for both
177 out %al, $0x21
178 .word 0x00eb,0x00eb
179 out %al, $0xA1
180 .word 0x00eb,0x00eb
181 mov $0xFF, %al # mask off all interrupts for now
182 out %al, $0x21
183 .word 0x00eb,0x00eb
184 out %al, $0xA1
185
186# well, that certainly wasn't fun :-(. Hopefully it works, and we don't
187# need no steenking BIOS anyway (except for the initial loading :-).
188# The BIOS-routine wants lots of unnecessary data, and it's less
189# "interesting" anyway. This is how REAL programmers do it.
190#
191# Well, now's the time to actually move into protected mode. To make
192# things as simple as possible, we do no register set-up or anything,
193# we let the gnu-compiled 32-bit programs do that. We just jump to
194# absolute address 0x00000, in 32-bit protected mode.
195 #mov $0x0001, %ax # protected mode (PE) bit
196 #lmsw %ax # This is it!
197 mov %cr0, %eax # get machine status(cr0|MSW)
198 bts $0, %eax # turn on the PE-bit
199 mov %eax, %cr0 # protection enabled
200
201 # segment-descriptor (INDEX:TI:RPL)
202 .equ sel_cs0, 0x0008 # select for code segment 0 ( 001:0 :00)
203 ljmp $sel_cs0, $0 # jmp offset 0 of code segment 0 in gdt
204
205# This routine checks that the keyboard command queue is empty
206# No timeout is used - if this hangs there is something wrong with
207# the machine, and we probably couldn't proceed anyway.
208empty_8042:
209 .word 0x00eb,0x00eb
210 in $0x64, %al # 8042 status port
211 test $2, %al # is input buffer full?
212 jnz empty_8042 # yes - loop
213 ret
214
215gdt:
216 .word 0,0,0,0 # dummy
217
218 .word 0x07FF # 8Mb - limit=2047 (2048*4096=8Mb)
219 .word 0x0000 # base address=0
220 .word 0x9A00 # code read/exec
221 .word 0x00C0 # granularity=4096, 386
222
223 .word 0x07FF # 8Mb - limit=2047 (2048*4096=8Mb)
224 .word 0x0000 # base address=0
225 .word 0x9200 # data read/write
226 .word 0x00C0 # granularity=4096, 386
227
228idt_48:
229 .word 0 # idt limit=0
230 .word 0,0 # idt base=0L
231
232gdt_48:
233 .word 0x800 # gdt limit=2048, 256 GDT entries
234 .word 512+gdt, 0x9 # gdt base = 0X9xxxx,
235 # 512+gdt is the real gdt after setup is moved to 0x9020 * 0x10
236
237.text
238endtext:
239.data
240enddata:
241.bss
242endbss: