wok view memtest/stuff/bootloader.S @ rev 15469

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