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

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