1 |
2 | bootsect.s (C) 1991 Linus Torvalds
3 |
4 | bootsect.s is loaded at 0x7c00 by the bios-startup routines, and moves
5 | iself out of the way to address 0x90000, and jumps there.
6 |
7 | It then loads 'setup' directly after itself (0x90200), and the system
8 | at 0x10000, using BIOS interrupts.
9 |
10 | NOTE! currently system is at most 8*65536 bytes long. This should be no
11 | problem, even in the future. I want to keep it simple. This 512 kB
12 | kernel size should be enough, especially as this doesn't contain the
13 | buffer cache as in minix
14 |
15 | The loader has been made as simple as possible, and continuos
16 | read errors will result in a unbreakable loop. Reboot by hand. It
17 | loads pretty fast by getting whole sectors at a time whenever possible.
18
19 .globl begtext, begdata, begbss, endtext, enddata, endbss
20 .text
21 begtext:
22 .data
23 begdata:
24 .bss
25 begbss:
26 .text
27
28 SETUPLEN = 4 | nr of setup-sectors
29 BOOTSEG = 0x07c0 | original address of boot-sector
30 INITSEG = 0x9000 | we move boot here - out of the way
31 SETUPSEG = 0x9020 | setup starts here
32 SYSSEG = 0x1000 | system loaded at 0x10000 (65536).
33 ENDSEG = SYSSEG + SYSSIZE | where to stop loading
34
35 | ROOT_DEV: 0x000 - same type of floppy as boot.
36 | 0x301 - first partition on first drive etc
37 ROOT_DEV = 0 | 0x306
38
39 entry start
40 start:
41 mov ax,#BOOTSEG
42 mov ds,ax
43 mov ax,#INITSEG
44 mov es,ax
45 mov cx,#256
46 sub si,si
47 sub di,di
48 rep
49 movw
50 jmpi go,INITSEG
51 go: mov ax,cs
52 mov ds,ax
53 mov es,ax
54 | put stack at 0x9ff00.
55 mov ss,ax
56 mov sp,#0xFF00 | arbitrary value >>512
57
58 | load the setup-sectors directly after the bootblock.
59 | Note that 'es' is already set up.
60
61 load_setup:
62 mov dx,#0x0000 | drive 0, head 0
63 mov cx,#0x0002 | sector 2, track 0
64 mov bx,#0x0200 | address = 512, in INITSEG
65 mov ax,#0x0200+SETUPLEN | service 2, nr of sectors
66 int 0x13 | read it
67 jnc ok_load_setup | ok - continue
68 mov dx,#0x0000
69 mov ax,#0x0000 | reset the diskette
70 int 0x13
71 j load_setup
72
73 ok_load_setup:
74
75 | Get disk drive parameters, specifically nr of sectors/track
76
77 mov dl,#0x00
78 mov ax,#0x0800 | AH=8 is get drive parameters
79 int 0x13
80 mov ch,#0x00
81 seg cs
82 mov sectors,cx
83 mov ax,#INITSEG
84 mov es,ax
85
86 | Print some inane message
87
88 mov ah,#0x03 | read cursor pos
89 xor bh,bh
90 int 0x10
91
92 mov cx,#24
93 mov bx,#0x0007 | page 0, attribute 7 (normal)
94 mov bp,#msg1
95 mov ax,#0x1301 | write string, move cursor
96 int 0x10
97
98 | ok, we've written the message, now
99 | we want to load the system (at 0x10000)
100
101 mov ax,#SYSSEG
102 mov es,ax | segment of 0x010000
103 call read_it
104 call kill_motor
105
106 | After that we check which root-device to use. If the device is
107 | defined (!= 0), nothing is done and the given device is used.
108 | Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending
109 | on the number of sectors that the BIOS reports currently.
110
111 seg cs
112 mov ax,root_dev
113 cmp ax,#0
114 jne root_defined
115 seg cs
116 mov bx,sectors
117 mov ax,#0x0208 | /dev/ps0 - 1.2Mb
118 cmp bx,#15
119 je root_defined
120 mov ax,#0x021c | /dev/PS0 - 1.44Mb
121 cmp bx,#18
122 je root_defined
123 undef_root:
124 jmp undef_root
125 root_defined:
126 seg cs
127 mov root_dev,ax
128
129 | after that (everyting loaded), we jump to
130 | the setup-routine loaded directly after
131 | the bootblock:
132
133 jmpi 0,SETUPSEG
134
135 | This routine loads the system at address 0x10000, making sure
136 | no 64kB boundaries are crossed. We try to load it as fast as
137 | possible, loading whole tracks whenever we can.
138 |
139 | in: es - starting address segment (normally 0x1000)
140 |
141 sread: .word 1+SETUPLEN | sectors read of current track
142 head: .word 0 | current head
143 track: .word 0 | current track
144
145 read_it:
146 mov ax,es
147 test ax,#0x0fff
148 die: jne die | es must be at 64kB boundary
149 xor bx,bx | bx is starting address within segment
150 rp_read:
151 mov ax,es
152 cmp ax,#ENDSEG | have we loaded all yet?
153 jb ok1_read
154 ret
155 ok1_read:
156 seg cs
157 mov ax,sectors
158 sub ax,sread
159 mov cx,ax
160 shl cx,#9
161 add cx,bx
162 jnc ok2_read
163 je ok2_read
164 xor ax,ax
165 sub ax,bx
166 shr ax,#9
167 ok2_read:
168 call read_track
169 mov cx,ax
170 add ax,sread
171 seg cs
172 cmp ax,sectors
173 jne ok3_read
174 mov ax,#1
175 sub ax,head
176 jne ok4_read
177 inc track
178 ok4_read:
179 mov head,ax
180 xor ax,ax
181 ok3_read:
182 mov sread,ax
183 shl cx,#9
184 add bx,cx
185 jnc rp_read
186 mov ax,es
187 add ax,#0x1000
188 mov es,ax
189 xor bx,bx
190 jmp rp_read
191
192 read_track:
193 push ax
194 push bx
195 push cx
196 push dx
197 mov dx,track
198 mov cx,sread
199 inc cx
200 mov ch,dl
201 mov dx,head
202 mov dh,dl
203 mov dl,#0
204 and dx,#0x0100
205 mov ah,#2
206 int 0x13
207 jc bad_rt
208 pop dx
209 pop cx
210 pop bx
211 pop ax
212 ret
213 bad_rt: mov ax,#0
214 mov dx,#0
215 int 0x13
216 pop dx
217 pop cx
218 pop bx
219 pop ax
220 jmp read_track
221
222 /* 223 * This procedure turns off the floppy drive motor, so 224 * that we enter the kernel in a known state, and 225 * don't have to worry about it later. 226 */ 227 kill_motor:
228 push dx
229 mov dx,#0x3f2
230 mov al,#0
231 outb
232 pop dx
233 ret
234
235 sectors:
236 .word 0
237
238 msg1:
239 .byte 13,10
240 .ascii "Loading system ..."
241 .byte 13,10,13,10
242
243 .org 508
244 root_dev:
245 .word ROOT_DEV
246 boot_flag:
247 .word 0xAA55
248
249 .text
250 endtext:
251 .data
252 enddata:
253 .bss
254 endbss: