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

memtest: default setup size = 4
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sun Nov 10 11:19:32 2013 +0000 (2013-11-10)
parents d39aa07ef47c
children d038b033c321
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 cld # assume nothing
48 #ifdef CMDLINE
49 movw $stacktop, %di
50 #else
51 #undef HELP
52 #endif
53 pushw $INITSEG
54 popw %es
55 #ifdef CMDLINE
56 movw $0x80, %si
57 lodsb
58 cbw
59 xchgw %ax, %cx
60 jcxz nocmdline
61 movw $0xA33F, 0x7F(%si)
62 skipspace:
63 lodsb
64 cmpb $0x20, %al
65 je skipspace
66 decw %si
67 rep
68 movsb
69 # ifdef HELP
70 # define PUTS
71 movw $EXEADRS(helpmsg), %si
72 cmpb $'/', %al
73 # ifdef CHECK_REALMODE
74 je jeputs
75 # else
76 je puts
77 # endif
78 # endif
79 nocmdline:
80 #endif
81 movw $SYSSEG, %ax
82 #ifdef CHECK_REALMODE
83 #define PUTS
84 movw $EXEADRS(realmode_expected), %si
85 pushfw // save flags
86 // bits 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
87 // flags 0 NT IOPL OF DF IF TF SF ZF 0 AF 0 PF 1 CF
88 //movb $0x10, %ah // DF = IF = TF = 0
89 pushw %ax
90 popfw // < 286 : flags[12..15] are forced 1
91 pushfw // = 286 : flags[12..15] are forced 0
92 popw %dx // > 286 : only flags[15] is forced 0
93 popfw // restore flags
94 addb %ah, %dh // test F0 and 00 cases
95 cmpb %ah, %dh
96 jeputs:
97 jbe puts // C=8086/80186, Z=80286
98 smsww %dx
99 shrw $1, %dx
100 jc puts
101 #endif
102 movw $0x100, %si
103 movw $end_header, %di
104 movb EXEADRS(setup_sects), %ch
105 movb $(512-(end_header-_start))/2, %cl
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 addw $(512/16)-1, %di
179 shrw $9-4, %di
180 movw $SYSSEG, %cx
181 call read_sectorsCX
183 # This procedure turns off the floppy drive motor, so
184 # that we enter the kernel in a known state, and
185 # don't have to worry about it later.
187 kill_motor:
188 xchgw %ax, %di # reset FDC (%di < 128)
189 int $0x13
191 # After that (everything loaded), we jump to the setup-routine
192 # loaded directly after the bootblock:
193 # Segments are as follows: %ds = %ss = INITSEG
195 jmp_setup:
196 ljmp $SETUPSEG, $0
198 #ifdef PUTS
199 #define PUTC
200 putslp:
201 call putc
202 puts:
203 lodsb
204 orb %al, %al
205 jne putslp
206 int $0x20 // dos exit
207 #endif
208 #ifdef EXE_SUPPORT
209 movesys:
210 pushw %es
211 popw %ss
212 movw EXEADRS(syssize), %bp // %ds untouched
213 movw %ds, %bx
214 cwd
215 incw %dx
216 cmpw %ax, %bx
217 jnc forward
218 negw %dx
219 addw %bp, %ax
220 addw %bp, %bx
221 forward:
222 movw %ax, %es
223 movw %bx, %ds
224 xorw %di, %di
225 movb $8, %cl
226 pushw %si
227 rep
228 movsw
229 popw %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 ret
255 # read_sectors reads %di sectors into %es:0 buffer.
256 # %es:0 is updated to the next memory location.
257 # First, sectors are read sector by sector until
258 # sector per track count is known. Then they are
259 # read track by track.
260 # Assume no error on first track.
262 #ifdef FLOPPY_1440K_ONLY
263 #define FLOPPY_HEADS 2 /* 2 heads */
264 #define FLOPPY_SECTORS 18 /* 18 sectors */
265 #else
266 #define FLOPPY_HEADS 2 /* 2 heads minimum */
267 #define FLOPPY_SECTORS 9 /* 9 sectors minimum */
268 #endif
270 check_limits:
271 #ifndef FLOPPY_1440K_ONLY
272 popw %dx
273 #ifdef FLOPPY_SECTORS
274 cmpb $FLOPPY_SECTORS+1, %cl # minimum sector count
275 jb check_head
276 #endif
277 cmpb %al, %cl # max sector known ?
278 ja next_head # no -> store it
279 check_head:
280 #ifdef FLOPPY_HEADS
281 cmpb $FLOPPY_HEADS, %dh # 2 heads minimum
282 jb check_cylinder
283 #endif
284 cmpb %ah, %dh # max head known ?
285 ja next_cylinder # no -> store it
286 check_cylinder:
287 #endif
288 pushaw
289 #ifndef FLOPPY_1440K_ONLY
290 cbw # %ah = 0
291 #endif
292 int $0x13 # reset controler
293 popaw
294 movb $1, %al # sector by sector...
295 read_sectorslp:
296 pushw %dx # some bios break dx...
297 #ifndef FLOPPY_1440K_ONLY
298 pushw %ax # limits
299 subb %cl, %al # sectors remaining in track
300 ja tolastsect
301 movb $1, %al # 1 sector mini
302 tolastsect:
303 #else
304 mov $FLOPPY_SECTORS+1, %al
305 subb %cl, %al # sectors remaining in track
306 #endif
307 cbw
308 cmpw %di, %ax
309 jb more1trk
310 movw %di, %ax # sectors to read
311 more1trk:
312 pushw %ax # save context
313 movb $2, %ah # cmd: read chs
314 int $0x13
315 #ifndef FLOPPY_1440K_ONLY
316 popw %dx # save %ax
317 popw %ax # limits
318 #else
319 popw %ax # restore context
320 popw %dx
321 #endif
322 jc check_limits
323 #ifndef FLOPPY_1440K_ONLY
324 xchgw %ax, %bp
325 addw %dx,%cx # next sector
326 movw %cx, %gs
327 movw %es, %cx
328 pushw %dx
329 shlw $5, %dx
330 addw %dx, %cx
331 popw %dx
332 subw %dx,%di # update sector counter
333 popw %dx
334 read_sectorsCX:
335 movw %cx, %es # next location
336 jz putcdot
337 #else
338 addw %ax,%cx # next sector
339 movw %cx, %gs
340 movw %es, %cx
341 pushw %ax
342 shlw $5, %ax
343 addw %ax, %cx
344 popw %ax
345 subw %ax,%di # update sector counter
346 read_sectorsCX:
347 movw %cx, %es # next location
348 jz putcdot
349 #endif
350 read_sectors:
351 movw %gs, %cx
352 #ifndef FLOPPY_1440K_ONLY
353 # al is last sector+1
354 # ah is last cylinder+1
355 xchgw %ax, %bp
356 #endif
357 #ifndef FLOPPY_1440K_ONLY
358 cmpb %al,%cl # reach sector limit ?
359 jne bdendlp
360 next_head:
361 movb %cl,%al
362 #else
363 cmpb $FLOPPY_SECTORS+1,%cl # reach sector limit ?
364 jne bdendlp
365 #endif
366 incb %dh # next head
367 movb $1,%cl # first sector
368 #ifndef FLOPPY_1440K_ONLY
369 cmpb %ah, %dh # reach head limit ?
370 jne bdendlp
371 next_cylinder:
372 movb %dh,%ah
373 #else
374 cmpb %cl,%dh # reach head limit ?
375 je bdendlp
376 #endif
377 # NOTE : support 256 cylinders max
378 incb %ch # next cylinder
379 read_first_sectors:
380 movb $0,%dh # first head
381 bdendlp:
382 jmp read_sectorslp
384 #ifdef CHECK_REALMODE
385 realmode_expected:
386 .ascii "386+ real mode only."
387 .byte 13,10,0
388 #endif
389 #ifdef HELP
390 helpmsg:
391 .ascii "No help available."
392 .byte 13,10
393 .byte 0
394 #endif
395 .org 497