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

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