wok view memtest/stuff/bootloader.S @ rev 17711
Up inkscape (0.91) update wget_url
author | Yuri Pourre <yuripourre@gmail.com> |
---|---|
date | Tue Mar 03 23:37:12 2015 -0300 (2015-03-03) |
parents | d038b033c321 |
children | 5797509d0229 |
line source
1 SYSSEG = 0x1000
2 INITSEG = 0x9000
3 SETUPSEG = 0x9020
5 .text
6 .code16
7 .org 0
8 .globl _start
9 _start:
11 #define CODESZ 512
13 /* some extra features */
14 #define EXE_SUPPORT real mode dos .exe file support
15 #define CMDLINE 0x9E00
16 #define HELP store help message for /? argument
17 #define CHECK_REALMODE does not support vm86
19 /* some contraints to reduce the size */
20 //#define FLOPPY_1440K_ONLY 1.44M floppies support only
21 #define NO_CURSOR_DEFINITION
23 #ifdef EXE_SUPPORT
24 #define EXEADRS(x) x+0xE0
25 stacktop = 0x9E00 # in 0x8000 .. 0xA000
26 decw %bp // Magic number: MZ
27 popw %dx
28 jmp start // Bytes on last page of file
29 .word (CODESZ+511)/512 // Pages in file
30 .word 0 // Relocations
31 .word (end_header-_start)/16 // Size of header in paragraphs
32 .word 4096 // Minimum extra paragraphs needed
33 .word -1 // Maximum extra paragraphs needed
34 .word (CODESZ+15)/16 // Initial (relative) SS value
35 .word stacktop // Initial SP value
36 .word 0 // Checksum
37 .word EXEADRS(comstart) // Initial IP value
38 .word 0xFFF0 // Initial (relative) CS value
39 // .word 0x001C // File address of relocation table
40 // .word 0,0,0 // Overlay number
41 .ascii "(SliTaz)"
42 end_header:
43 comstart:
44 cld # assume nothing
45 #ifdef CMDLINE
46 movw $stacktop, %di
47 #else
48 #undef HELP
49 #endif
50 pushw $INITSEG
51 popw %es
52 #ifdef CMDLINE
53 movw $0x80, %si
54 lodsb
55 cbw
56 xchgw %ax, %cx
57 jcxz nocmdline
58 movw $0xA33F, 0x7F(%si)
59 skipspace:
60 lodsb
61 cmpb $0x20, %al
62 je skipspace
63 decw %si
64 rep
65 movsb
66 # ifdef HELP
67 # define PUTS
68 movw $EXEADRS(helpmsg), %si
69 cmpb $'/'+1, %al
70 # ifdef CHECK_REALMODE
71 js jsputs
72 # else
73 js puts
74 # endif
75 # endif
76 nocmdline:
77 #endif
78 movw $SYSSEG, %ax
79 #ifdef CHECK_REALMODE
80 #define PUTS
81 movw $EXEADRS(realmode_expected), %si
82 // bits 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
83 // flags 0 NT IOPL OF DF IF TF SF ZF 0 AF 0 PF 1 CF
84 //movb $0x10, %ah // DF = IF = TF = 0
85 pushw %ax
86 popfw // < 286 : flags[12..15] are forced 1
87 pushfw // = 286 : flags[12..15] are forced 0
88 popw %dx // > 286 : only flags[15] is forced 0
89 cmpb %ah, %dh // test Fx and 0x cases
90 jsputs:
91 js puts // S= not 386+
92 smsww %dx
93 shrw $1, %dx
94 jc puts
95 //movw syssize-realmode_expected(%si), %bp
96 .byte 0x8B, 0x6C, syssize-realmode_expected
97 //movb setup_sects-realmode_expected(%si), %ch
98 .byte 0x8A, 0x6C, setup_sects-realmode_expected
99 #else
100 movw EXEADRS(syssize), %bp
101 movb EXEADRS(setup_sects), %ch
102 #endif
103 movb $(512-(end_header-_start))/2, %cl
104 movw $0x100, %si
105 movw $end_header, %di
106 rep
107 movsw
108 ljmp $INITSEG, $movesys
109 start:
110 pushw %dx
111 #else
112 #undef HELP
113 #undef CMDLINE
114 #undef CHECK_REALMODE
115 #endif
116 cld # assume nothing
117 stacktop = 0x9E00 # in 0x8000 .. 0xA000
118 zeroed = 12 # zeroed registers
119 movw $stacktop-12-zeroed, %di # stacktop is an arbitrary value >=
120 # length of bootsect + length of
121 # setup + room for stack;
122 # 12 is disk parm size.
123 pushw $INITSEG
124 popw %ss # %ss contain INITSEG
125 movw %di, %sp # put stack at INITSEG:stacktop-...
127 # Many BIOS's default disk parameter tables will not recognize
128 # multi-sector reads beyond the maximum sector number specified
129 # in the default diskette parameter tables - this may mean 7
130 # sectors in some cases.
131 #
132 # Since single sector reads are slow and out of the question,
133 # we must take care of this by creating new parameter tables
134 # (for the first disk) in RAM. We can set the maximum sector
135 # count to 36 - the most we will encounter on an ED 2.88.
136 #
137 # High doesn't hurt. Low does. Let's use the max: 63
139 pushw %ss
140 popw %es # %es = %ss = INITSEG
141 xorw %ax, %ax # %ax = 0
142 #ifdef EXE_SUPPORT
143 cwd # %dx = 0
144 #endif
145 movw $zeroed/2, %cx # clear gdt + offset, %ds, limits
146 rep # don't worry about cld
147 stosw # already done above
148 popw %bx # offset = 0
149 popw %ds # %ds = 0
150 popw %fs # %fs = 0
152 movb setup_sects+0x7C00, %al # read bootsector + setup (%ds = 0)
153 incw %ax
155 ldsw 0x78(%bx), %si # %ds:%bx+0x78 is parameter table address
156 pushw %es
157 pushw %di
158 movb $6, %cl # copy 12 bytes
159 rep # don't worry about cld
160 movsw # already done above
161 pushw %ss
162 popw %ds # now %ds = %es = %ss = INITSEG
163 popl %fs:0x78(%bx) # update parameter table address
164 movb $63, 0x4-12(%di) # patch sector count, %di = stacktop
165 cli
167 xchg %ax, %di # sector count
168 popw %ax # limits = 0
169 incw %cx # cylinder 0, sector 1, clear Z
170 call read_first_sectors # read setup
172 # This routine loads the system at address LOADSEG, making sure
173 # no 64kB boundaries are crossed. We try to load it as fast as
174 # possible, loading whole tracks whenever we can.
176 popw %bx # clear %bx
177 movw syssize, %di
178 decw %di
179 shrw $9-4, %di
180 incw %di
181 movw $SYSSEG, %cx
182 call read_sectorsCX
184 # This procedure turns off the floppy drive motor, so
185 # that we enter the kernel in a known state, and
186 # don't have to worry about it later.
188 kill_motor:
189 xchgw %ax, %di # reset FDC (%di < 128)
190 int $0x13
192 # After that (everything loaded), we jump to the setup-routine
193 # loaded directly after the bootblock:
194 # Segments are as follows: %ds = %ss = INITSEG
196 jmp_setup:
197 ljmp $SETUPSEG, $0
199 #ifdef PUTS
200 #define PUTC
201 putslp:
202 call putc
203 puts:
204 lodsb
205 orb %al, %al
206 jne putslp
207 int $0x20 // dos exit
208 #endif
209 #ifdef EXE_SUPPORT
210 movesys: // %ax = SYSSEG
211 pushw %es
212 popw %ss
213 movw %ds, %bx
214 subw %ax, %bx
215 jnc forward
216 addw %bp, %ax
217 forward:
218 movw %ax, %es
219 movw %ax, %dx
220 addw %bx, %dx
221 movw %dx, %ds
222 sbbw %dx, %dx // %dx = 0 : -1
223 cmc // C = 1 : 0
224 adcw %dx, %ax
225 xorw %di, %di
226 movb $8, %cl
227 pushw %si
228 rep
229 movsw
230 popw %si
231 decw %bp
232 jns forward
233 #ifndef NO_CURSOR_DEFINITION
234 movb $1, %ah
235 movb $0, %bh
236 movb $0x20, %ch // 0x2000
237 int $0x10
238 #endif
239 pushw %ss
240 popw %ds
241 jmp jmp_setup
242 #endif
243 putcdot:
244 #ifdef PUTC
245 movb $0x2E, %al
246 putc:
247 movb $0xE, %ah
248 movw $7, %bx
249 int $0x10
250 #endif
251 ret
254 # read_sectors reads %di sectors into %es:0 buffer.
255 # %es:0 is updated to the next memory location.
256 # First, sectors are read sector by sector until
257 # sector per track count is known. Then they are
258 # read track by track.
259 # Assume no error on first track.
261 #ifdef FLOPPY_1440K_ONLY
262 #define FLOPPY_HEADS 2 /* 2 heads */
263 #define FLOPPY_SECTORS 18 /* 18 sectors */
264 #else
265 #define FLOPPY_HEADS 2 /* 2 heads minimum */
266 #define FLOPPY_SECTORS 9 /* 9 sectors minimum */
267 #endif
269 check_limits:
270 #ifndef FLOPPY_1440K_ONLY
271 popw %dx
272 #ifdef FLOPPY_SECTORS
273 cmpb $FLOPPY_SECTORS+1, %cl # minimum sector count
274 jb check_head
275 #endif
276 cmpb %al, %cl # max sector known ?
277 ja next_head # no -> store it
278 check_head:
279 #ifdef FLOPPY_HEADS
280 cmpb $FLOPPY_HEADS, %dh # 2 heads minimum
281 jb check_cylinder
282 #endif
283 cmpb %ah, %dh # max head known ?
284 ja next_cylinder # no -> store it
285 check_cylinder:
286 #endif
287 pushaw
288 #ifndef FLOPPY_1440K_ONLY
289 cbw # %ah = 0
290 #endif
291 int $0x13 # reset controler
292 popaw
293 movb $1, %al # sector by sector...
294 read_sectorslp:
295 pushw %dx # some bios break dx...
296 #ifndef FLOPPY_1440K_ONLY
297 pushw %ax # limits
298 subb %cl, %al # sectors remaining in track
299 ja tolastsect
300 movb $1, %al # 1 sector mini
301 tolastsect:
302 #else
303 mov $FLOPPY_SECTORS+1, %al
304 subb %cl, %al # sectors remaining in track
305 #endif
306 cbw
307 cmpw %di, %ax
308 jb more1trk
309 movw %di, %ax # sectors to read
310 more1trk:
311 pushw %ax # save context
312 movb $2, %ah # cmd: read chs
313 int $0x13
314 #ifndef FLOPPY_1440K_ONLY
315 popw %dx # save %ax
316 popw %ax # limits
317 #else
318 popw %ax # restore context
319 popw %dx
320 #endif
321 jc check_limits
322 #ifndef FLOPPY_1440K_ONLY
323 xchgw %ax, %bp
324 addw %dx,%cx # next sector
325 movw %cx, %gs
326 movw %es, %cx
327 pushw %dx
328 shlw $5, %dx
329 addw %dx, %cx
330 popw %dx
331 subw %dx,%di # update sector counter
332 popw %dx
333 read_sectorsCX:
334 movw %cx, %es # next location
335 jz putcdot
336 #else
337 addw %ax,%cx # next sector
338 movw %cx, %gs
339 movw %es, %cx
340 pushw %ax
341 shlw $5, %ax
342 addw %ax, %cx
343 popw %ax
344 subw %ax,%di # update sector counter
345 read_sectorsCX:
346 movw %cx, %es # next location
347 jz putcdot
348 #endif
349 read_sectors:
350 movw %gs, %cx
351 #ifndef FLOPPY_1440K_ONLY
352 # al is last sector+1
353 # ah is last cylinder+1
354 xchgw %ax, %bp
355 #endif
356 #ifndef FLOPPY_1440K_ONLY
357 cmpb %al,%cl # reach sector limit ?
358 jne bdendlp
359 next_head:
360 movb %cl,%al
361 #else
362 cmpb $FLOPPY_SECTORS+1,%cl # reach sector limit ?
363 jne bdendlp
364 #endif
365 incb %dh # next head
366 movb $1,%cl # first sector
367 #ifndef FLOPPY_1440K_ONLY
368 cmpb %ah, %dh # reach head limit ?
369 jne bdendlp
370 next_cylinder:
371 movb %dh,%ah
372 #else
373 cmpb %cl,%dh # reach head limit ?
374 je bdendlp
375 #endif
376 # NOTE : support 256 cylinders max
377 incb %ch # next cylinder
378 read_first_sectors:
379 movb $0,%dh # first head
380 bdendlp:
381 jmp read_sectorslp
383 #ifdef HELP
384 helpmsg:
385 .ascii "No help available."
386 .byte 13,10
387 .byte 0
388 #endif
389 #ifdef CHECK_REALMODE
390 .org 475
391 realmode_expected:
392 helpend:
393 .ascii "386 real mode only."
394 .byte 13,10,0
395 #endif
396 .org 497
397 setup_sects:
398 .byte 0
399 .org 500
400 syssize:
401 .word 0