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

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