wok-current view memtest/stuff/bootloader.S @ rev 19399

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