wok-next diff memtest/stuff/bootloader.S @ rev 15188
Add memtest-serial
author | Pascal Bellard <pascal.bellard@slitaz.org> |
---|---|
date | Sun Aug 25 18:09:21 2013 +0000 (2013-08-25) |
parents | |
children | d9dd83ccc85f |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/memtest/stuff/bootloader.S Sun Aug 25 18:09:21 2013 +0000 1.3 @@ -0,0 +1,389 @@ 1.4 +SYSSEG = 0x1000 1.5 +INITSEG = 0x9000 1.6 +SETUPSEG = 0x9020 1.7 + 1.8 +setup_sects = 497 1.9 +syssize = 500 1.10 + 1.11 + .text 1.12 + .code16 1.13 + .org 0 1.14 + .globl _start 1.15 +_start: 1.16 + 1.17 +#define CODESZ 512 1.18 + 1.19 +/* some extra features */ 1.20 +#define EXE_SUPPORT real mode dos .exe file support 1.21 +#define CMDLINE 0x9E00 1.22 +#define HELP store help message for /? argument 1.23 +#define CHECK_REALMODE does not support vm86 1.24 + 1.25 +/* some contraints to reduce the size */ 1.26 +//#define FLOPPY_1440K_ONLY 1.44M floppies support only 1.27 +#define NO_CURSOR_DEFINITION 1.28 + 1.29 +#ifdef EXE_SUPPORT 1.30 +#define EXEADRS(x) x+0xE0 1.31 +stacktop = 0x9E00 # in 0x8000 .. 0xA000 1.32 + decw %bp // Magic number: MZ 1.33 + popw %dx 1.34 + jmp start // Bytes on last page of file 1.35 + .word (CODESZ+511)/512 // Pages in file 1.36 + .word 0 // Relocations 1.37 + .word (end_header-_start)/16 // Size of header in paragraphs 1.38 + .word 4096 // Minimum extra paragraphs needed 1.39 + .word -1 // Maximum extra paragraphs needed 1.40 + .word (CODESZ+15)/16 // Initial (relative) SS value 1.41 + .word stacktop // Initial SP value 1.42 + .word 0 // Checksum 1.43 + .word EXEADRS(comstart) // Initial IP value 1.44 + .word 0xFFF0 // Initial (relative) CS value 1.45 +// .word 0x001C // File address of relocation table 1.46 +// .word 0,0,0 // Overlay number 1.47 + .ascii "(SliTaz)" 1.48 +end_header: 1.49 +comstart: 1.50 +#ifdef CMDLINE 1.51 + .word 0xA33A // CMP AH,[BP+DI+stacktop] 1.52 + .word stacktop 1.53 +#else 1.54 +#undef HELP 1.55 +#endif 1.56 + cld # assume nothing 1.57 + pushw $INITSEG 1.58 + popw %es 1.59 +#ifdef CMDLINE 1.60 + movw %sp, %di 1.61 + movw $0x80, %si 1.62 + lodsb 1.63 + cbw 1.64 + xchgw %ax, %cx 1.65 + jcxz nocmdline 1.66 + movb $0x3F, 0x7F(%si) 1.67 +skipspace: 1.68 + lodsb 1.69 + cmpb $0x20, %al 1.70 + je skipspace 1.71 + decw %si 1.72 + rep 1.73 + movsb 1.74 +# ifdef HELP 1.75 +# define PUTS 1.76 + movw $EXEADRS(helpmsg), %si 1.77 + cmpb $'/', %al 1.78 + je puts 1.79 +# endif 1.80 +nocmdline: 1.81 +#endif 1.82 +#ifdef CHECK_REALMODE 1.83 +#define PUTS 1.84 + movw $EXEADRS(realmode_expected), %si 1.85 + pushfw // save flags 1.86 + // bits 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 1.87 + // flags 0 NT IOPL OF DF IF TF SF ZF 0 AF 0 PF 1 CF 1.88 + movb $0x10, %ah // DF = IF = TF = 0 1.89 + pushw %ax 1.90 + popfw // < 286 : flags[12..15] are forced 1 1.91 + pushfw // = 286 : flags[12..15] are forced 0 1.92 + popw %cx // > 286 : only flags[15] is forced 0 1.93 + popfw // restore flags 1.94 + addb %ah, %ch // test F0 and 00 cases 1.95 + cmpb %ah, %ch 1.96 + jbe puts // C=8086/80186, Z=80286 1.97 + smsww %ax 1.98 + andb $1, %al 1.99 + jne puts 1.100 +#endif 1.101 + movw $0x100, %si 1.102 + movw $end_header, %di 1.103 + movb EXEADRS(setup_sects), %ch 1.104 + movb $(512-(end_header-_start))/2, %cl 1.105 + rep 1.106 + movsw 1.107 + ljmp $INITSEG, $movesys 1.108 +start: 1.109 + pushw %dx 1.110 + xorw %dx, %dx 1.111 +#else 1.112 +#undef HELP 1.113 +#undef CMDLINE 1.114 +#undef CHECK_REALMODE 1.115 +#endif 1.116 + cld # assume nothing 1.117 +stacktop = 0x9E00 # in 0x8000 .. 0xA000 1.118 +zeroed = 12 # zeroed registers 1.119 + movw $stacktop-12-zeroed, %di # stacktop is an arbitrary value >= 1.120 + # length of bootsect + length of 1.121 + # setup + room for stack; 1.122 + # 12 is disk parm size. 1.123 + pushw $INITSEG 1.124 + popw %ss # %ss contain INITSEG 1.125 + movw %di, %sp # put stack at INITSEG:stacktop-... 1.126 + 1.127 +# Many BIOS's default disk parameter tables will not recognize 1.128 +# multi-sector reads beyond the maximum sector number specified 1.129 +# in the default diskette parameter tables - this may mean 7 1.130 +# sectors in some cases. 1.131 +# 1.132 +# Since single sector reads are slow and out of the question, 1.133 +# we must take care of this by creating new parameter tables 1.134 +# (for the first disk) in RAM. We can set the maximum sector 1.135 +# count to 36 - the most we will encounter on an ED 2.88. 1.136 +# 1.137 +# High doesn't hurt. Low does. Let's use the max: 63 1.138 + 1.139 + pushw %ss 1.140 + popw %es # %es = %ss = INITSEG 1.141 + xorw %ax, %ax # %ax = 0 1.142 + movw $zeroed/2, %cx # clear gdt + offset, %ds, limits 1.143 + rep # don't worry about cld 1.144 + stosw # already done above 1.145 + popw %bx # offset = 0 1.146 + popw %ds # %ds = 0 1.147 + popw %fs # %fs = 0 1.148 + 1.149 + movb setup_sects+0x7C00, %al # read bootsector + setup (%ds = 0) 1.150 + incw %ax 1.151 + 1.152 + ldsw 0x78(%bx), %si # %ds:%bx+0x78 is parameter table address 1.153 + pushw %es 1.154 + pushw %di 1.155 + movb $6, %cl # copy 12 bytes 1.156 + rep # don't worry about cld 1.157 + movsw # already done above 1.158 + pushw %ss 1.159 + popw %ds # now %ds = %es = %ss = INITSEG 1.160 + popl %fs:0x78(%bx) # update parameter table address 1.161 + movb $63, 0x4-12(%di) # patch sector count, %di = stacktop 1.162 + cli 1.163 + 1.164 + xchg %ax, %di # sector count 1.165 + popw %ax # limits = 0 1.166 + incw %cx # cylinder 0, sector 1, clear Z 1.167 + call read_first_sectors # read setup 1.168 + 1.169 +# This routine loads the system at address LOADSEG, making sure 1.170 +# no 64kB boundaries are crossed. We try to load it as fast as 1.171 +# possible, loading whole tracks whenever we can. 1.172 + 1.173 + popw %bx # clear %bx 1.174 + movw syssize, %di 1.175 + addw $(512/16)-1, %di 1.176 + shrw $9-4, %di 1.177 + movw $SYSSEG, %cx 1.178 + call read_sectorsCX 1.179 + 1.180 +# This procedure turns off the floppy drive motor, so 1.181 +# that we enter the kernel in a known state, and 1.182 +# don't have to worry about it later. 1.183 + 1.184 +kill_motor: 1.185 + xchgw %ax, %di # reset FDC (%di < 128) 1.186 + int $0x13 1.187 + 1.188 +# After that (everything loaded), we jump to the setup-routine 1.189 +# loaded directly after the bootblock: 1.190 +# Segments are as follows: %ds = %ss = INITSEG 1.191 + 1.192 +jmp_setup: 1.193 + ljmp $SETUPSEG, $0 1.194 + 1.195 +#ifdef PUTS 1.196 +#define PUTC 1.197 +puts: 1.198 + lodsb 1.199 + orb %al, %al 1.200 + je exit 1.201 + call putc 1.202 + jmp puts 1.203 +#endif 1.204 +#ifdef EXE_SUPPORT 1.205 +movesys: 1.206 + pushw %es 1.207 + popw %ss 1.208 + movw EXEADRS(syssize), %bp // %ds untouched 1.209 + movw $SYSSEG, %ax 1.210 + movw %ds, %bx 1.211 + cwd 1.212 + incw %dx 1.213 + cmpw %ax, %bx 1.214 + jnc forward 1.215 + negw %dx 1.216 + addw %bp, %ax 1.217 + addw %bp, %bx 1.218 +forward: 1.219 + movw %ax, %es 1.220 + movw %bx, %ds 1.221 + xorw %di, %di 1.222 + movb $8, %cl 1.223 + rep 1.224 + movsw 1.225 + subw $16, %si 1.226 + addw %dx, %ax 1.227 + addw %dx, %bx 1.228 + decw %bp 1.229 + jns forward 1.230 +#ifndef NO_CURSOR_DEFINITION 1.231 + movb $1, %ah 1.232 + movb $0, %bh 1.233 + movb $0x20, %ch // 0x2000 1.234 + int $0x10 1.235 +#endif 1.236 + pushw %ss 1.237 + popw %ds 1.238 + jmp jmp_setup 1.239 +#endif 1.240 +putcdot: 1.241 +#ifdef PUTC 1.242 + movb $0x2E, %al 1.243 +putc: 1.244 + movb $0xE, %ah 1.245 + movw $7, %bx 1.246 + int $0x10 1.247 +#endif 1.248 +exit: 1.249 + ret 1.250 + 1.251 + 1.252 +# read_sectors reads %di sectors into %es:0 buffer. 1.253 +# %es:0 is updated to the next memory location. 1.254 +# First, sectors are read sector by sector until 1.255 +# sector per track count is known. Then they are 1.256 +# read track by track. 1.257 +# Assume no error on first track. 1.258 + 1.259 +#ifdef FLOPPY_1440K_ONLY 1.260 +#define FLOPPY_HEADS 2 /* 2 heads */ 1.261 +#define FLOPPY_SECTORS 18 /* 18 sectors */ 1.262 +#else 1.263 +#define FLOPPY_HEADS 2 /* 2 heads minimum */ 1.264 +#define FLOPPY_SECTORS 9 /* 9 sectors minimum */ 1.265 +#endif 1.266 + 1.267 +check_limits: 1.268 +#ifndef FLOPPY_1440K_ONLY 1.269 + popw %dx 1.270 +#ifdef FLOPPY_SECTORS 1.271 + cmpb $FLOPPY_SECTORS+1, %cl # minimum sector count 1.272 + jb check_head 1.273 +#endif 1.274 + cmpb %al, %cl # max sector known ? 1.275 + ja next_head # no -> store it 1.276 +check_head: 1.277 +#ifdef FLOPPY_HEADS 1.278 + cmpb $FLOPPY_HEADS, %dh # 2 heads minimum 1.279 + jb check_cylinder 1.280 +#endif 1.281 + cmpb %ah, %dh # max head known ? 1.282 + ja next_cylinder # no -> store it 1.283 +check_cylinder: 1.284 +#endif 1.285 + pushaw 1.286 +#ifndef FLOPPY_1440K_ONLY 1.287 + cbw # %ah = 0 1.288 +#endif 1.289 + int $0x13 # reset controler 1.290 + popaw 1.291 + movb $1, %al # sector by sector... 1.292 +read_sectorslp: 1.293 + pushw %dx # some bios break dx... 1.294 +#ifndef FLOPPY_1440K_ONLY 1.295 + pushw %ax # limits 1.296 + subb %cl, %al # sectors remaining in track 1.297 + ja tolastsect 1.298 + movb $1, %al # 1 sector mini 1.299 +tolastsect: 1.300 +#else 1.301 + mov $FLOPPY_SECTORS+1, %al 1.302 + subb %cl, %al # sectors remaining in track 1.303 +#endif 1.304 + cbw 1.305 + cmpw %di, %ax 1.306 + jb more1trk 1.307 + movw %di, %ax # sectors to read 1.308 +more1trk: 1.309 + pushw %ax # save context 1.310 + movb $2, %ah # cmd: read chs 1.311 + int $0x13 1.312 +#ifndef FLOPPY_1440K_ONLY 1.313 + popw %dx # save %ax 1.314 + popw %ax # limits 1.315 +#else 1.316 + popw %ax # restore context 1.317 + popw %dx 1.318 +#endif 1.319 + jc check_limits 1.320 +#ifndef FLOPPY_1440K_ONLY 1.321 + xchgw %ax, %bp 1.322 + addw %dx,%cx # next sector 1.323 + movw %cx, %gs 1.324 + movw %es, %cx 1.325 + pushw %dx 1.326 + shlw $5, %dx 1.327 + addw %dx, %cx 1.328 + popw %dx 1.329 + subw %dx,%di # update sector counter 1.330 + popw %dx 1.331 +read_sectorsCX: 1.332 + movw %cx, %es # next location 1.333 + jz putcdot 1.334 +#else 1.335 + addw %ax,%cx # next sector 1.336 + movw %cx, %gs 1.337 + movw %es, %cx 1.338 + pushw %ax 1.339 + shlw $5, %ax 1.340 + addw %ax, %cx 1.341 + popw %ax 1.342 + subw %ax,%di # update sector counter 1.343 +read_sectorsCX: 1.344 + movw %cx, %es # next location 1.345 + jz putcdot 1.346 +#endif 1.347 +read_sectors: 1.348 + movw %gs, %cx 1.349 +#ifndef FLOPPY_1440K_ONLY 1.350 +# al is last sector+1 1.351 +# ah is last cylinder+1 1.352 + xchgw %ax, %bp 1.353 +#endif 1.354 +#ifndef FLOPPY_1440K_ONLY 1.355 + cmpb %al,%cl # reach sector limit ? 1.356 + jne bdendlp 1.357 +next_head: 1.358 + movb %cl,%al 1.359 +#else 1.360 + cmpb $FLOPPY_SECTORS+1,%cl # reach sector limit ? 1.361 + jne bdendlp 1.362 +#endif 1.363 + incb %dh # next head 1.364 + movb $1,%cl # first sector 1.365 +#ifndef FLOPPY_1440K_ONLY 1.366 + cmpb %ah, %dh # reach head limit ? 1.367 + jne bdendlp 1.368 +next_cylinder: 1.369 + movb %dh,%ah 1.370 +#else 1.371 + cmpb %cl,%dh # reach head limit ? 1.372 + je bdendlp 1.373 +#endif 1.374 +# NOTE : support 256 cylinders max 1.375 + incb %ch # next cylinder 1.376 +read_first_sectors: 1.377 + movb $0,%dh # first head 1.378 +bdendlp: 1.379 + jmp read_sectorslp 1.380 + 1.381 +#ifdef CHECK_REALMODE 1.382 +realmode_expected: 1.383 + .ascii "386 real mode only." 1.384 + .byte 13,10,0 1.385 +#endif 1.386 +#ifdef HELP 1.387 +helpmsg: 1.388 + .ascii "No help available." 1.389 + .byte 13,10 1.390 + .byte 0 1.391 +#endif 1.392 + .org 497