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

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