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

memtest: VCPI support
author Pascal Bellard <pascal.bellard@slitaz.org>
date Wed Apr 19 22:14:58 2017 +0200 (2017-04-19)
parents 67179a0300fd
children 9e463ebef079
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 TINYSYSTEM the full file in one segment
18 #define CHECK_CPU need a 386+
19 #define VM2RM (0x3C+0x19B)
20 #define SHUTDOWNDOS shutdown DOS services
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 startz // 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 startz:
46 jmp start
47 end_header:
48 comstart:
49 cld # assume nothing
50 #ifdef CMDLINE
51 movw $stacktop, %di # cmdline offset at 0x22
52 #else
53 #undef HELP
54 #endif
55 pushw $INITSEG
56 popw %es
57 #ifdef CMDLINE
58 movw $0x80, %si
59 lodsb
60 cbw
61 xchgw %ax, %cx
62 jcxz nocmdline
63 movw $0xA33F, 0x7F(%si)
64 skipspace:
65 lodsb
66 cmpb $0x20, %al
67 je skipspace
68 decw %si
69 rep
70 movsb
71 # ifdef HELP
72 # define PUTS
73 movw $EXEADRS(helpmsg), %si
74 cmpb $'/'+1, %al
75 # ifdef CHECK_CPU
76 js jsputs
77 # else
78 js puts
79 # endif
80 # endif
81 nocmdline:
82 #endif
83 movw $SYSSEG, %ax
84 movb $(512-(end_header-_start))/2, %cl
85 movw $end_header, %di
86 #ifdef CHECK_CPU
87 #define PUTS
88 movw $EXEADRS(realmode_expected), %si
89 //movb setup_sects-realmode_expected(%si), %ch
90 .byte 0x8A, 0x6C, setup_sects-realmode_expected
91 // bits 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
92 // flags 0 NT IOPL OF DF IF TF SF ZF 0 AF 0 PF 1 CF
93 //movb $0x10, %ah // DF = IF = TF = 0
94 pushw %ax
95 popfw // < 286 : flags[12..15] are forced 1
96 pushfw // = 286 : flags[12..15] are forced 0
97 popw %dx // > 286 : only flags[15] is forced 0
98 cmpb %ah, %dh // test Fx and 0x cases: S= < 386, C= < 286
99 jsputs:
100 js puts // S= not 386+
101 smsww %dx
102 shrw $1, %dx
103 # ifdef VM2RM
104 jnc isrm
105 push %cs
106 call VM2RM
107 isrm:
108 # else
109 jc puts // protected mode: vm86
110 # endif
111 #else
112 movb EXEADRS(setup_sects), %ch
113 #endif
114 movw $0x100, %si
115 rep
116 movsw
117 movw %ds, %bx
118 pushw %es
119 popw %ss
120 #ifndef SHUTDOWNDOS
121 ljmp $INITSEG, $movesys
122 #else
123 pushaw
124 movw %cx, %ds # %ds = 0
125 movw $4, %si
126 pushl (%si)
127 movw $step19, (%si)
128 movw %es, 2(%si)
129 pushfw
130 popw %ax
131 incb %ah # set TF
132 pushw %ax
133 popfw
134 ljmp *4*0x19-4(%si)
135 #endif
136 start:
137 pushw %dx
138 #else
139 #undef HELP
140 #undef CMDLINE
141 #undef CHECK_CPU
142 #endif
143 cld # assume nothing
144 stacktop = 0x9E00 # in 0x8000 .. 0xA000
145 zeroed = 12 # zeroed registers
146 movw $stacktop-12-zeroed, %di # stacktop is an arbitrary value >=
147 # length of bootsect + length of
148 # setup + room for stack;
149 # 12 is disk parm size.
150 pushw $INITSEG
151 popw %ss # %ss contain INITSEG
152 movw %di, %sp # put stack at INITSEG:stacktop-...
154 # Many BIOS's default disk parameter tables will not recognize
155 # multi-sector reads beyond the maximum sector number specified
156 # in the default diskette parameter tables - this may mean 7
157 # sectors in some cases.
158 #
159 # Since single sector reads are slow and out of the question,
160 # we must take care of this by creating new parameter tables
161 # (for the first disk) in RAM. We can set the maximum sector
162 # count to 36 - the most we will encounter on an ED 2.88.
163 #
164 # High doesn't hurt. Low does. Let's use the max: 63
166 pushw %ss
167 popw %es # %es = %ss = INITSEG
168 xorw %ax, %ax # %ax = 0
169 #ifdef EXE_SUPPORT
170 cwd # %dx = 0
171 #endif
172 movw $zeroed/2, %cx # clear gdt + offset, %ds, limits
173 rep # don't worry about cld
174 stosw # already done above
175 popw %bx # offset = 0
176 popw %ds # %ds = 0
177 popw %fs # %fs = 0
179 movb setup_sects+0x7C00, %al # read bootsector + setup (%ds = 0)
180 incw %ax
182 ldsw 0x78(%bx), %si # %ds:%bx+0x78 is parameter table address
183 pushw %es
184 pushw %di
185 movb $6, %cl # copy 12 bytes
186 rep # don't worry about cld
187 movsw # already done above
188 pushw %ss
189 popw %ds # now %ds = %es = %ss = INITSEG
190 popl %fs:0x78(%bx) # update parameter table address
191 movb $63, 0x4-12(%di) # patch sector count, %di = stacktop
192 cli
194 xchg %ax, %di # sector count
195 popw %ax # limits = 0
196 incw %cx # cylinder 0, sector 1, clear Z
197 call read_first_sectors # read setup
199 # This routine loads the system at address LOADSEG, making sure
200 # no 64kB boundaries are crossed. We try to load it as fast as
201 # possible, loading whole tracks whenever we can.
203 popw %bx # clear %bx
204 movw syssize, %di
205 decw %di
206 shrw $9-4, %di
207 incw %di
208 movw $SYSSEG, %cx
209 call read_sectorsCX
211 # This procedure turns off the floppy drive motor, so
212 # that we enter the kernel in a known state, and
213 # don't have to worry about it later.
215 kill_motor:
216 xchgw %ax, %di # reset FDC (%di < 128)
217 int $0x13
219 # After that (everything loaded), we jump to the setup-routine
220 # loaded directly after the bootblock:
221 # Segments are as follows: %ds = %ss = INITSEG
223 jmp_setup:
224 ljmp $SETUPSEG, $0
226 #ifdef PUTS
227 #define PUTC
228 putslp:
229 call putc
230 puts:
231 lodsb
232 orb %al, %al
233 jne putslp
234 int $0x20 // dos exit
235 #endif
236 #ifdef EXE_SUPPORT
237 #ifdef SHUTDOWNDOS
238 doiret:
239 iret
240 step19:
241 pushw %si
242 pushw %ds
243 movw %sp, %si
244 ldsw %ss:4(%si), %si
245 cmpw $0x19CD, (%si)
246 popw %ds
247 popw %si
248 jne doiret
249 xorw %si, %si
250 movw %si, %ds
251 pushw %cs
252 popw %ss
253 movw $stacktop-4-16, %sp
254 popl 4(%si)
255 popaw
256 #endif
257 movesys: // %ax = SYSSEG
258 #ifdef TINYSYSTEM
259 movw %si, %cx
260 negw %cx
261 xorw %di, %di
262 movw %ax, %es
263 movw %si, %dx
264 shrw $4, %dx
265 # ifdef SHUTDOWNDOS
266 movw %bx, %ds
267 # endif
268 addw %dx, %bx
269 subw %ax, %bx
270 jnc forward
271 addw %cx, %di
272 addw %cx, %si
273 incw %cx
274 std
275 forward:
276 rep
277 movsb
278 cld
279 #else
280 movw %cs:syssize, %bp
281 shrw $4, %si
282 addw %si, %bx
283 subw %ax, %bx
284 jnc forward
285 addw %bp, %ax
286 forward:
287 movw %ax, %es
288 movw %ax, %dx
289 addw %bx, %dx
290 movw %dx, %ds
291 sbbw %dx, %dx // %dx = 0 : -1
292 cmc // C = 1 : 0
293 adcw %dx, %ax
294 xorw %si, %si
295 xorw %di, %di
296 movb $8, %cl
297 rep
298 movsw
299 decw %bp
300 jns forward
301 #endif
302 #ifndef NO_CURSOR_DEFINITION
303 movb $1, %ah
304 movb $0, %bh
305 movb $0x20, %ch // 0x2000
306 int $0x10
307 #endif
308 pushw %ss
309 popw %ds
310 jmp jmp_setup
311 #endif
312 putcdot:
313 #ifdef PUTC
314 movb $0x2E, %al
315 putc:
316 movb $0xE, %ah
317 movw $7, %bx
318 int $0x10
319 #endif
320 ret
323 # read_sectors reads %di sectors into %es:0 buffer.
324 # %es:0 is updated to the next memory location.
325 # First, sectors are read sector by sector until
326 # sector per track count is known. Then they are
327 # read track by track.
328 # Assume no error on first track.
330 #ifdef FLOPPY_1440K_ONLY
331 #define FLOPPY_HEADS 2 /* 2 heads */
332 #define FLOPPY_SECTORS 18 /* 18 sectors */
333 #else
334 #define FLOPPY_HEADS 2 /* 2 heads minimum */
335 #define FLOPPY_SECTORS 9 /* 9 sectors minimum */
336 #endif
338 check_limits:
339 #ifndef FLOPPY_1440K_ONLY
340 popw %dx
341 #ifdef FLOPPY_SECTORS
342 cmpb $FLOPPY_SECTORS+1, %cl # minimum sector count
343 jb check_head
344 #endif
345 cmpb %al, %cl # max sector known ?
346 ja next_head # no -> store it
347 check_head:
348 #ifdef FLOPPY_HEADS
349 cmpb $FLOPPY_HEADS, %dh # 2 heads minimum
350 jb check_cylinder
351 #endif
352 cmpb %ah, %dh # max head known ?
353 ja next_cylinder # no -> store it
354 check_cylinder:
355 #endif
356 pushaw
357 #ifndef FLOPPY_1440K_ONLY
358 cbw # %ah = 0
359 #endif
360 int $0x13 # reset controler
361 popaw
362 movb $1, %al # sector by sector...
363 read_sectorslp:
364 pushw %dx # some bios break dx...
365 #ifndef FLOPPY_1440K_ONLY
366 pushw %ax # limits
367 subb %cl, %al # sectors remaining in track
368 ja tolastsect
369 movb $1, %al # 1 sector mini
370 tolastsect:
371 #else
372 movb $FLOPPY_SECTORS+1, %al
373 subb %cl, %al # sectors remaining in track
374 #endif
375 cbw
376 cmpw %di, %ax
377 jb more1trk
378 movw %di, %ax # sectors to read
379 more1trk:
380 pushw %ax # save context
381 movb $2, %ah # cmd: read chs
382 int $0x13
383 #ifndef FLOPPY_1440K_ONLY
384 popw %dx # save %ax
385 popw %ax # limits
386 #else
387 popw %ax # restore context
388 popw %dx
389 #endif
390 jc check_limits
391 #ifndef FLOPPY_1440K_ONLY
392 xchgw %ax, %bp
393 addw %dx,%cx # next sector
394 movw %cx, %gs
395 movw %es, %cx
396 pushw %dx
397 shlw $5, %dx
398 addw %dx, %cx
399 popw %dx
400 subw %dx,%di # update sector counter
401 popw %dx
402 read_sectorsCX:
403 movw %cx, %es # next location
404 jz putcdot
405 #else
406 addw %ax,%cx # next sector
407 movw %cx, %gs
408 movw %es, %cx
409 pushw %ax
410 shlw $5, %ax
411 addw %ax, %cx
412 popw %ax
413 subw %ax,%di # update sector counter
414 read_sectorsCX:
415 movw %cx, %es # next location
416 jz putcdot
417 #endif
418 read_sectors:
419 movw %gs, %cx
420 #ifndef FLOPPY_1440K_ONLY
421 # al is last sector+1
422 # ah is last cylinder+1
423 xchgw %ax, %bp
424 #endif
425 #ifndef FLOPPY_1440K_ONLY
426 cmpb %al,%cl # reach sector limit ?
427 jne bdendlp
428 next_head:
429 movb %cl,%al
430 #else
431 cmpb $FLOPPY_SECTORS+1,%cl # reach sector limit ?
432 jne bdendlp
433 #endif
434 incb %dh # next head
435 movb $1,%cl # first sector
436 #ifndef FLOPPY_1440K_ONLY
437 cmpb %ah, %dh # reach head limit ?
438 jne bdendlp
439 next_cylinder:
440 movb %dh,%ah
441 #else
442 cmpb %cl,%dh # reach head limit ?
443 je bdendlp
444 #endif
445 # NOTE : support 256 cylinders max
446 incb %ch # next cylinder
447 movb $0,%dh # first head
448 read_first_sectors:
449 bdendlp:
450 jmp read_sectorslp
452 #ifdef VM2RM
453 pagebuf = 0x96000
454 saved_ss_sp = gdt_abs-44
455 saved_sp = gdt_abs-44
456 saved_ss = gdt_abs-42
457 tss = gdt_abs-40
458 gdt = gdt_abs-32
459 gdt_null = gdt_abs-32
460 gdt_vcpi = gdt_abs-24
461 gdt_vcpi2 = gdt_abs-16
462 gdt_vcpi3 = gdt_abs-8
463 gdt_abs:
464 .word 0xFFFF,0
465 .byte 0,0x92,0xCF,0
466 gdt_code:
467 .word 0xFFFF
468 gdt_code_base:
469 .long 0x9A000000
470 .byte 0x8F,0
471 gdt_tss:
472 .word 0x00FF
473 gdt_tss_base:
474 .long 0x89000000+EXEADRS(tss)
475 .byte 0,0
476 gdtr:
477 gdt_lim:
478 .word 0xFFFF
479 gdt_base:
480 .long EXEADRS(gdt)
481 sw2pm_params:
482 sw2pm_cr3:
483 .long pagebuf+0x1000
484 sw2pm_gdtr_ptr:
485 .long EXEADRS(gdtr)
486 sw2pm_idtr_ptr:
487 .long EXEADRS(idtr)
488 sw2pm_ldtr:
489 .word 0
490 sw2pm_tr:
491 SEL_TSS = gdt_tss-gdt_null
492 .word SEL_TSS
493 sw2pm_jumpaddr:
494 #define SETUPEXEADRS(x) (x+0x2E0)
495 pm_code = 0x0084
496 .long SETUPEXEADRS(pm_code)
497 SEL_CODE = gdt_code-gdt_null
498 .word SEL_CODE
499 idtr:
500 idt_lim:
501 .word 0x03FF
502 idt_base:
503 .long 0
504 #endif
505 #ifdef HELP
506 helpmsg:
507 .ascii "No help."
508 .byte 13,10
509 .byte 0
510 #endif
511 #ifdef CHECK_CPU
512 # if VM2RM
513 .org 484
514 realmode_expected:
515 helpend:
516 .ascii "386+ only."
517 # else
518 .org 475
519 realmode_expected:
520 helpend:
521 .ascii "386 real mode only."
522 # endif
523 .byte 13,10,0
524 #endif
525 .org 497
526 setup_sects:
527 .byte 0
528 .org 500
529 syssize:
530 .word 0