wok-undigest rev 635
remove runcom
author | Pascal Bellard <pascal.bellard@slitaz.org> |
---|---|
date | Sat Feb 18 09:02:14 2012 +0100 (2012-02-18) |
parents | 0205643e403f |
children | 4e7f011b44f9 |
files | runcom/receipt runcom/stuff/debug.S runcom/stuff/debug.com runcom/stuff/debug8086.S runcom/stuff/runcom.c |
line diff
1.1 --- a/runcom/receipt Sun Feb 12 11:28:15 2012 +0000 1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 1.3 @@ -1,58 +0,0 @@ 1.4 -# SliTaz package receipt. 1.5 - 1.6 -PACKAGE="runcom" 1.7 -VERSION="1.0" 1.8 -CATEGORY="system-tools" 1.9 -SHORT_DESC="DOS .com binary format support" 1.10 -MAINTAINER="dev@slitaz.org" 1.11 -WEB_SITE="http://bellard.org/jslinux" 1.12 - 1.13 -# Rules to configure and make the package. 1.14 -compile_rules() 1.15 -{ 1.16 - mkdir -p $src 1.17 - cd $src 1.18 - #tarball=$(wget -O - $WEB_SITE/tech.html | \ 1.19 - # sed '/linuxstart/!d;s/.*href="\([^"]*\)".*/\1/') 1.20 - #wget $WEB_SITE/$tarball 1.21 - #tar xzf $tarball 1.22 - mkdir -p $DESTDIR/usr/bin 1.23 - cc -o $DESTDIR/usr/bin/runcom $stuff/runcom.c 1.24 - cc -o $src/debug.o -Wa,-a=$src/debug.lst -c $stuff/debug.S 1.25 - objcopy -O binary $src/debug.o $DESTDIR/usr/bin/debug.bin 1.26 - cp $stuff/debug.com $DESTDIR/usr/bin 1.27 - chmod +x $DESTDIR/usr/bin/debug.* 1.28 -} 1.29 - 1.30 -# Rules to gen a SliTaz package suitable for Tazpkg. 1.31 -genpkg_rules() 1.32 -{ 1.33 - cp -a $_pkg/* $fs 1.34 -} 1.35 - 1.36 -# Post install command for Tazpkg. 1.37 -post_install() 1.38 -{ 1.39 - fmt="binfmt_misc" 1.40 - proc="/proc/sys/fs/binfmt_misc" 1.41 - bin=":BOOTBIN:E::bin::/usr/bin/runcom:" 1.42 - com=":DOSCOM:E::com::/usr/bin/runcom:" 1.43 - rc="$1/etc/init.d/local.sh" 1.44 - grep -q "$com" $rc || cat >> $rc <<EOT 1.45 -[ ! -e $proc/register ] && modprobe $fmt && mount -t $fmt $fmt $proc 1.46 -echo "$bin" >$proc/register 1.47 -echo "$com" >$proc/register 1.48 -EOT 1.49 - [ -n "$1" ] && return 1.50 - [ ! -e $proc/register ] && modprobe $fmt && mount -t $fmt $fmt $proc 1.51 - echo "$bin" >$proc/register 1.52 - echo "$com" >$proc/register 1.53 -} 1.54 - 1.55 -# Pre remove command for Tazpkg. 1.56 -pre_remove() 1.57 -{ 1.58 - echo -1 > $1/proc/sys/fs/binfmt_misc/BOOTBIN 1.59 - echo -1 > $1/proc/sys/fs/binfmt_misc/DOSCOM 1.60 - sed -i '/binfmt_misc/{NN;/DOSCOM:E::com/d}' $1/etc/init.d/local.sh 1.61 -}
2.1 --- a/runcom/stuff/debug.S Sun Feb 12 11:28:15 2012 +0000 2.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 2.3 @@ -1,493 +0,0 @@ 2.4 -// Usage: 2.5 -// 2.6 -// f DX:CX load one CHS sector to 0000:7C00 2.7 -// t trace one step 2.8 -// g <address> go to adrs 2.9 -// d <address> display 16 bytes, CR for next 16 bytes... 2.10 -// e <address> <words>... enter memory byte/word/dword 2.11 -// m <segment> self move 2.12 -// + <segment> default segment offset 2.13 -// 2.14 -// Example: 2.15 -// m 0FC0 move debugger to 0FC0:0000 0FC0:01FF 2.16 -// f 1 read floppy boot sector to 0000:7C00 2.17 -// f 80 1 read hard disk master boot sector to 0000:7C00 2.18 -// g 7C0E ... 2.19 - 2.20 -#define REGS32 28 bytes display FS, GS and 32 bits datas for AX..DI 2.21 -#define ADJESDI 16 bytes add segment overflow support for e and d 2.22 -#define ASCIIDUMP 20 bytes display hexa and ascii datas 2.23 -#define INPUTBUFFER 3 bytes overload init code with a 32+ bytes input buffer 2.24 - 2.25 -.macro pushib val 2.26 - .byte 0x6A, \val-_start 2.27 -.endm 2.28 - 2.29 -#ifdef REGS32 2.30 -#define SEGREGSZ 10 2.31 -#define REGSZ 32 2.32 -#define USER_SP REGSZ+SEGREGSZ-28(%bp) 2.33 -#define FIXSP 14 2.34 -#else 2.35 -#define SEGREGSZ 6 2.36 -#define REGSZ 16 2.37 -#define USER_SP REGSZ+SEGREGSZ-14(%bp) 2.38 -#define FIXSP 10 2.39 -#endif 2.40 -#define USER_FLAGS REGSZ+SEGREGSZ+4(%bp) 2.41 -#define USER_FLAGS_HIGH REGSZ+SEGREGSZ+5(%bp) 2.42 -#define USER_IP REGSZ+SEGREGSZ(%bp) 2.43 -#define USER_CS REGSZ+SEGREGSZ+2(%bp) 2.44 -#define USER_CSIP REGSZ+SEGREGSZ(%bp) 2.45 - 2.46 -#ifdef INPUTBUFFER 2.47 -//#define ABS(x) (x-(setvectors-_start)) 2.48 -#define ABS(x) (x-32) 2.49 -#else 2.50 -#define ABS(x) (x) 2.51 -#endif 2.52 -.macro initcode 2.53 - movw $0x0FC0, %di # move (and jump) to 0FC0:0000 2.54 - subw $_startz-_start, USER_IP 2.55 - movw USER_IP, %ax 2.56 - shrw $4, %ax # _start MUST be aligned on paragraph 2.57 - addw USER_CS, %ax # normalize %cs to have _start=0 2.58 - movw %ax, %ds 2.59 -.endm 2.60 - 2.61 - .text 2.62 - .code16 2.63 - .org 0 2.64 - 2.65 - .globl _start 2.66 -_start: 2.67 - pushf 2.68 - pushw %cs 2.69 - stc 2.70 - call init # the start code will be overwritten by the input buffer 2.71 -_startz: 2.72 - 2.73 -#ifdef INPUTBUFFER 2.74 -isinit: 2.75 - initcode 2.76 - addw $FIXSP, USER_SP # adjust SP with [FLAGS CS IP DS ES [FS GS]] size 2.77 - pushib setvectors 2.78 - jmp moveself 2.79 -#endif 2.80 - 2.81 -setvectors: 2.82 - xorw %si, %si # set interrupt vectors in 0 segment 2.83 - movw %si, %ds 2.84 - movb $0x7D, %cl # skip nmi 2.85 -hooklp: # interrupts: 0=div0 1=step 2=nmi 3=brk 4=ov 5=bound 6=invalid 2.86 - pushw %cs 2.87 - pushib ABS(dbgstart) # set %cs:dbgstart 2.88 - popl (%si) # to interrupt vector 2.89 -skiphook: 2.90 - lodsl # %si += 4 2.91 - shrb $1,%cl 2.92 - jnc skiphook 2.93 - jnz hooklp # note %cx will be cleared: SP will be untouched 2.94 - decw (3-7)*4(%si) # update int3 vector 2.95 - jmp dbgstartz # registers are already pushed by startup code 2.96 - 2.97 -regs: 2.98 - .ascii "ss" 2.99 - .ascii "di" 2.100 - .ascii "si" 2.101 - .ascii "bp" 2.102 - .ascii "sp" 2.103 - .ascii "bx" 2.104 - .ascii "dx" 2.105 - .ascii "cx" 2.106 - .ascii "ax" 2.107 -#ifdef REGS32 2.108 - .ascii "gs" 2.109 - .ascii "fs" 2.110 -#endif 2.111 - .ascii "es" 2.112 - .ascii "ds" 2.113 - .ascii "ip" 2.114 - .ascii "cs" 2.115 -# Bit Label Desciption 2.116 -# --------------------------- 2.117 -# 0 CF Carry flag 2.118 -# 2 PF Parity flag 2.119 -# 4 AF Auxiliary carry flag 2.120 -# 6 ZF Zero flag 2.121 -# 7 SF Sign flag 2.122 -# 8 TF Trap flag 2.123 -# 9 IF Interrupt enable flag 2.124 -# 10 DF Direction flag 2.125 -# 11 OF Overflow flag 2.126 -#ifdef REGS32 2.127 - .ascii "odi|sz|a|p|c" # flags bits 2.128 -#else 2.129 - .ascii "oditsz?a?p c=" # flags bits 2.130 -#endif 2.131 -# 12-13 IOPL I/O Priviledge level 2.132 -# 14 NT Nested task flag 2.133 -# 16 RF Resume flag 2.134 -# 17 VM Virtual 8086 mode flag 2.135 -# 18 AC Alignment check flag (486+) 2.136 -# 19 VIF Virutal interrupt flag 2.137 -# 20 VIP Virtual interrupt pending flag 2.138 -# 21 ID ID flag 2.139 - 2.140 -#ifdef INPUTBUFFER 2.141 -ismove: 2.142 - pushw %ax 2.143 -moveself: 2.144 - popw %si 2.145 -#else 2.146 -isinit: 2.147 - initcode 2.148 -ismove: 2.149 - xorw %si, %si 2.150 -#endif 2.151 - movw %di, %es # move code to %di:0 2.152 - pushw %di 2.153 -#ifdef INPUTBUFFER 2.154 - xorw %di, %di # and jmp into (%di:setvectors) with retf 2.155 -#else 2.156 - movw $setvectors, %di # and jmp into (%di:setvectors) with retf 2.157 - movw %di, %si 2.158 -#endif 2.159 - movw $_end-setvectors, %cx 2.160 - pushw %di 2.161 - rep movsb 2.162 - retf 2.163 - 2.164 -int3: 2.165 - .byte 0x68 # push $0x086A OV UP DI NT PL ZR - NA - PO - NC 2.166 -# interrupt entry point: the registers [FLAGS CS IP] are already pushed 2.167 -dbgstart: 2.168 - .byte 0x6A, 0x08 # push $0x08 NV UP DI NT PL NZ - NA - PO - NC 2.169 - popf 2.170 -init: 2.171 - pushw %ds 2.172 - pushw %es 2.173 -#ifdef REGS32 2.174 - pushw %fs 2.175 - pushw %gs 2.176 - pushal # [FLAGS CS IP DS ES FS GS] EAX ECX EDX EBX ESP EBP ESI EDI [SS] 2.177 -#else 2.178 - pushaw # [FLAGS CS IP DS ES] AX CX DX BX SP BP SI DI [SS] 2.179 -#endif 2.180 - pushw %ss 2.181 - movw %sp, %bp 2.182 -#ifndef INPUTBUFFER 2.183 - pushf 2.184 - addw $FIXSP, USER_SP # adjust SP with [FLAGS CS IP DS ES [FS GS]] size 2.185 - popf 2.186 -#endif 2.187 - jc isinit 2.188 - jnz notint3 2.189 - decw USER_IP 2.190 - lesw USER_CSIP, %di 2.191 -#define OPCODE_BRK 0xCC 2.192 - .byte 0xB0 # movb $IM, %al 2.193 -break: 2.194 - .byte 0xCC 2.195 - stosb 2.196 -notint3: 2.197 -#ifdef INPUTBUFFER 2.198 - addw $FIXSP, USER_SP # adjust SP with [FLAGS CS IP DS ES [FS GS]] size 2.199 -#endif 2.200 -dbgstartz: 2.201 -dbgregslp: 2.202 - pushw %cs 2.203 - popw %ds 2.204 - movw $ABS(regs), %si 2.205 -#ifdef REGS32 2.206 - subw %si, %bp 2.207 - movw $15, %cx 2.208 -#else 2.209 - movw $13, %cx 2.210 -#endif 2.211 -regslp: 2.212 - call putreg # display register name and value 2.213 - loop regslp 2.214 -#ifdef REGS32 2.215 - movw (%bp,%si), %dx # get flags 2.216 -#else 2.217 - movw USER_FLAGS, %dx 2.218 - pushw %si 2.219 - stc # add trailing = 2.220 -#endif 2.221 - movb $13, %cl 2.222 - rcrw %cl, %dx 2.223 -nextbit: 2.224 - lodsb 2.225 - shlw $1, %dx 2.226 -#ifdef REGS32 2.227 - jnc skipflag 2.228 - cmpb $'|', %al # remove system flags 2.229 - je skipflag 2.230 - call dbgputc 2.231 -skipflag: 2.232 -#else 2.233 - call dbgputcbit # display active flags bits 2.234 -#endif 2.235 - loop nextbit 2.236 -#ifdef REGS32 2.237 - movw %sp, %bp 2.238 -#else 2.239 - popw %si 2.240 - movb $8, %cl 2.241 -stacklp: 2.242 - lodsw # si += 2 2.243 - call putr16 # display flags and the beginning of the stack 2.244 - loop stacklp 2.245 -#endif 2.246 - call getline 2.247 - lodsb 2.248 - xchgw %ax, %di 2.249 - call getval 2.250 - .byte 0x81, 0xC3 # addw $0, %bx 2.251 -offset_value: 2.252 - .word 0 2.253 - movw %bx, %es 2.254 - xchgw %ax, %di 2.255 - subb $'m', %al 2.256 - je ismove 2.257 - subb $'+'-'m', %al 2.258 - jne not_offset 2.259 - movw %di, ABS(offset_value) 2.260 -not_offset: 2.261 - orb $1, USER_FLAGS_HIGH # set TF 2.262 - subb $'t'-'+', %al 2.263 - je done 2.264 - subb $'d'-'t', %al 2.265 - xchgw %ax, %cx 2.266 - jcxz dump # 'd' ? 2.267 - loop noenter # 'e' ? 2.268 -nextval: 2.269 - call getval 2.270 - jcxz dbgregslp 2.271 - xchgb %dl, %dh 2.272 -mextmsb: 2.273 - stosb 2.274 - xchgw %ax, %dx 2.275 - xchgb %al, %dh 2.276 -#ifdef ADJESDI 2.277 - call adjustESDI 2.278 -#endif 2.279 - decw %cx 2.280 - loopne mextmsb 2.281 - jmp nextval 2.282 -noenter: 2.283 - loop not_floppy_load # f DX:CX ? 2.284 - movw %es, %dx 2.285 - movw %cx, %es 2.286 - movw %di, %cx 2.287 - movw $0x0201, %ax 2.288 - movw $0x7C00, %bx 2.289 - pushw %bx 2.290 - int $0x13 2.291 - popw %di 2.292 -godbgregslpifc: 2.293 - jc dbgregslp 2.294 -dump: 2.295 - movw %es, %ax 2.296 - call putax 2.297 - movw %di, %ax 2.298 - call putax 2.299 - movw $16, %cx 2.300 -dhex: 2.301 - movb %es:(%di), %ah 2.302 -#ifdef ASCIIDUMP 2.303 - movb %ah, (%si) 2.304 - incw %si 2.305 -#endif 2.306 -#ifdef ADJESDI 2.307 - call incESDI 2.308 -#else 2.309 - incw %di 2.310 -#endif 2.311 -#ifdef REGS32 2.312 - movb $0x30, %dh # the data has 2 digits 2.313 -#else 2.314 - movb $0x01, %dh # the data has 2 digits 2.315 -#endif 2.316 - call putx 2.317 - loop dhex 2.318 -#ifdef ASCIIDUMP 2.319 - movb $16, %cl 2.320 - subw %cx, %si 2.321 -dascii: 2.322 - lodsb 2.323 - cmpb $0x7F, %al 2.324 - jnc skipascii 2.325 - cmpb $0x20, %al 2.326 - cmc 2.327 -skipascii: 2.328 - call dbgputcbit 2.329 - loop dascii 2.330 -#endif 2.331 - call dbgputcr 2.332 - int $0x16 2.333 - cmpb $13, %al 2.334 - je dump 2.335 -notdump: 2.336 -not_floppy_load: 2.337 - stc 2.338 - loop godbgregslpifc # g ? 2.339 -isgo: 2.340 - andb $0xfe, USER_FLAGS_HIGH # clear TF 2.341 - xchgw %ax, %cx 2.342 - jcxz done 2.343 -setbreak: 2.344 - movb $OPCODE_BRK, %al 2.345 - xchgb %al, %es:(%di) 2.346 - movb %al, ABS(break) 2.347 -done: 2.348 - popw %ax # %ss 2.349 -#ifdef REGS32 2.350 - popal 2.351 - popw %gs 2.352 - popw %fs 2.353 -#else 2.354 - popaw 2.355 -#endif 2.356 - popw %es 2.357 - popw %ds 2.358 - iret 2.359 - 2.360 -#ifdef ADJESDI 2.361 -adjustESDI: 2.362 - decw %di 2.363 -incESDI: 2.364 - incw %di 2.365 - jnz esok 2.366 - pushw %es 2.367 - addb $0x10,-3(%bp) 2.368 - popw %es 2.369 -esok: 2.370 - ret 2.371 -#endif 2.372 - 2.373 -putreg: 2.374 - call dbgput2c 2.375 - movb $'=', %al 2.376 - call dbgputc 2.377 -putr16: 2.378 -#ifdef REGS32 2.379 - movl -2(%bp,%si), %eax 2.380 - movw $0x3FC0, %dx # check bits 7..14 2.381 - shrw %cl, %dx 2.382 -putax: 2.383 - movb $0xF0, %dh # the data has 4 digits 2.384 - jnc putx # 16 bits register ? 2.385 - incw %bp # a 32 bits register, not 16 bits 2.386 - incw %bp 2.387 - movb $0xFF, %dh # the data has 8 digits 2.388 - jmp putx 2.389 -putxlp: 2.390 -#else 2.391 -# movw _start-ABS(regs)-2(%bp,%si), %ax 2.392 - .byte 0x8b, 0x42, _start-ABS(regs)-2 2.393 -putax: 2.394 - movb $0x07, %dh # the data has 4 digits 2.395 -putx: 2.396 -putxlp: 2.397 - rolw $4, %ax 2.398 -#endif 2.399 - pushw %ax 2.400 - andb $0xf, %al 2.401 - addb $0x90, %al 2.402 - daa 2.403 - adcb $0x40, %al 2.404 - daa 2.405 - call dbgputc 2.406 - popw %ax 2.407 -#ifdef REGS32 2.408 -putx: 2.409 - roll $4, %eax 2.410 -#endif 2.411 - shrb $1, %dh 2.412 - jc putxlp 2.413 -#ifdef REGS32 2.414 - jnz putx 2.415 -#endif 2.416 -dbgputcbit: 2.417 - jc dbgputc 2.418 - mov $0x20, %al 2.419 -dbgputc: 2.420 - movw $7, %bx 2.421 - mov $0xE, %ah 2.422 - int $0x10 2.423 - xchgw %ax, %bx 2.424 -# clc # for putax 2.425 - ret 2.426 - 2.427 -# get value in DX:AX, BX is segment CX is digits count. 2.428 -getval: 2.429 - xorw %ax, %ax 2.430 - xorw %bx, %bx 2.431 - xorw %cx, %cx 2.432 -getvalz: 2.433 - xchgw %ax, %bx 2.434 - cwd 2.435 - decw %cx 2.436 -isx: 2.437 - shll $4, %edx 2.438 - orb %al, %dl 2.439 - incw %cx 2.440 -gotspc: 2.441 -getvallp: 2.442 - lodsb 2.443 - cmpb $0x20, %al # heat heading spaces 2.444 - jne notspc 2.445 - jcxz gotspc 2.446 -notspc: 2.447 - subb $'0', %al 2.448 - cmpb $10, %al # in 0..9 ? 2.449 - jb isx 2.450 - subb $'a'-'0'-10, %al 2.451 - cmpb $16, %al # in a..f ? 2.452 - jb isx 2.453 - cmpb $':'-'a'+10, %al 2.454 - pushl %edx 2.455 - popw %ax 2.456 - popw %dx 2.457 - je getvalz # store segment in %bx 2.458 - pushw %dx 2.459 - shlw $12, %dx 2.460 - orw %dx, %bx 2.461 - popw %dx 2.462 - ret 2.463 - 2.464 -getline: 2.465 - call dbgputcr 2.466 -getlinebs: 2.467 - cmpw $ABS(buffer), %si 2.468 - je getc 2.469 - decw %si 2.470 -getlinelp: 2.471 - call dbgputc 2.472 -getc: 2.473 - int $0x16 2.474 - cmpb $8, %al 2.475 - je getlinebs 2.476 - orb $0x20, %al 2.477 - movb %al, (%si) 2.478 - inc %si 2.479 - cmpb $0x2D, %al 2.480 - jne getlinelp 2.481 -dbgputcr: 2.482 - movw $ABS(crlf), %si 2.483 -dbgput2c: 2.484 - call dbgput1c 2.485 -dbgput1c: 2.486 - lodsb 2.487 - jmp dbgputc 2.488 - 2.489 -crlf: 2.490 - .byte 13,10 2.491 -_end: 2.492 -buffer: 2.493 - 2.494 - .org 510 2.495 - .byte 0x55, 0xAA 2.496 -
3.1 Binary file runcom/stuff/debug.com has changed
4.1 --- a/runcom/stuff/debug8086.S Sun Feb 12 11:28:15 2012 +0000 4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 4.3 @@ -1,477 +0,0 @@ 4.4 -// Usage: 4.5 -// 4.6 -// f DX:CX load one CHS sector to 0000:7C00 4.7 -// t trace one step 4.8 -// g <address> go to adrs 4.9 -// d <address> display 16 bytes, CR for next 16 bytes... 4.10 -// e <address> <words>... enter memory byte/word/dword 4.11 -// m <segment> self move 4.12 -// + <segment> default segment offset 4.13 -// 4.14 -// Example: 4.15 -// m 0FC0 move debugger to 0FC0:0000 0FC0:01FF 4.16 -// f 1 read floppy boot sector to 0000:7C00 4.17 -// f 80 1 read hard disk master boot sector to 0000:7C00 4.18 -// g 7C0E ... 4.19 - 4.20 -#define ADJESDI 16 bytes add segment overflow support for e and d 4.21 -#define ASCIIDUMP 20 bytes display hexa and ascii datas 4.22 -#define INPUTBUFFER 2 bytes overload init code with a 32+ bytes input buffer 4.23 -//#define CPU186 -26 bytes 80186+ CPU 4.24 - 4.25 -.macro pusham 4.26 - pushw %ax 4.27 - pushw %cx 4.28 - pushw %dx 4.29 - pushw %bx 4.30 - movw %sp, %bx 4.31 - leaw 14(%bx), %bx # adjust SP with [FLAGS CS IP AX CX DX BX] size 4.32 - pushw %bx # %sp 4.33 - pushw %bp 4.34 - pushw %si 4.35 - pushw %di 4.36 -.endm 4.37 - 4.38 -.macro popam 4.39 - popw %di 4.40 - popw %si 4.41 - popw %bp 4.42 - popw %ax # %sp 4.43 - popw %bx 4.44 - popw %dx 4.45 - popw %cx 4.46 - popw %ax 4.47 -.endm 4.48 - 4.49 -#ifdef INPUTBUFFER 4.50 -//#define ABS(x) (x-(setvectors-_start)) 4.51 -#define ABS(x) (x-30) 4.52 -#else 4.53 -#define ABS(x) (x) 4.54 -#endif 4.55 - 4.56 -#define SEGREGSZ 6 4.57 -#define REGSZ 16 4.58 -#define USER_SP REGSZ+SEGREGSZ-10(%bp) 4.59 -#define USER_FLAGS REGSZ+SEGREGSZ+4(%bp) 4.60 -#define USER_FLAGS_HIGH REGSZ+SEGREGSZ+5(%bp) 4.61 -#define USER_IP REGSZ+SEGREGSZ(%bp) 4.62 -#define USER_CS REGSZ+SEGREGSZ+2(%bp) 4.63 -#define USER_CSIP REGSZ+SEGREGSZ(%bp) 4.64 - 4.65 -.macro initcode 4.66 - movw $0x0FC0, %di # move (and jump) to 0FC0:0000 4.67 - subw $_startz-_start, USER_IP 4.68 - movw USER_IP, %ax 4.69 -#ifdef CPU186 4.70 - cld # ensure movsb will work 4.71 - shrw $4, %ax # _start MUST be aligned on paragraph 4.72 -#else 4.73 - movb $4, %cl 4.74 - shrw %cl, %ax # _start MUST be aligned on paragraph 4.75 -#endif 4.76 - addw USER_CS, %ax # normalize %cs to have _start=0 4.77 - movw %ax, %ds 4.78 -.endm 4.79 - .text 4.80 - .code16 4.81 -#ifdef CPU186 4.82 - .arch i186 4.83 -#else 4.84 - .arch i8086 4.85 -#endif 4.86 - .org 0 4.87 - 4.88 - .globl _start 4.89 -_start: 4.90 - pushf 4.91 - pushw %cs 4.92 - stc 4.93 - call init # the start code will be overwritten by the input buffer 4.94 -_startz: 4.95 - 4.96 -#ifdef INPUTBUFFER 4.97 -isinit: 4.98 - initcode 4.99 - movw $setvectors, %si 4.100 - jmp moveself 4.101 -#endif 4.102 - 4.103 -setvectors: 4.104 - xorw %si, %si # set interrupt vectors in 0 segment 4.105 - movw %si, %ds 4.106 - movb $0xF9, %ch # skip nmi 4.107 -hooklp: # interrupts: 0=div0 1=step 2=nmi 3=brk 4=ov 5=bound 6=invalid 4.108 - movw $ABS(dbgstart), (%si) # set %cs:dbgstart 4.109 - lodsw # %si += 2 4.110 - movw %cs, (%si) # to interrupt vector 4.111 -skiphook: 4.112 - lodsw # %si += 2 4.113 - shrb $1,%ch 4.114 - jnc skiphook 4.115 - jnz hooklp # note %cx will be cleared: SP will be untouched 4.116 -#ifdef CPU186 4.117 - decw (3-7)*4(%si) # update int3 vector 4.118 -#else 4.119 - movb $ABS(int3), (3-7)*4(%si) # update int3 vector 4.120 -#endif 4.121 - jmp dbgstartz # registers are already pushed by startup code 4.122 - 4.123 -regs: 4.124 - .ascii "ss" 4.125 - .ascii "es" 4.126 - .ascii "ds" 4.127 - .ascii "di" 4.128 - .ascii "si" 4.129 - .ascii "bp" 4.130 - .ascii "sp" 4.131 - .ascii "bx" 4.132 - .ascii "dx" 4.133 - .ascii "cx" 4.134 - .ascii "ax" 4.135 - .ascii "ip" 4.136 - .ascii "cs" 4.137 -# Bit Label Desciption 4.138 -# --------------------------- 4.139 -# 0 CF Carry flag 4.140 -# 2 PF Parity flag 4.141 -# 4 AF Auxiliary carry flag 4.142 -# 6 ZF Zero flag 4.143 -# 7 SF Sign flag 4.144 -# 8 TF Trap flag 4.145 -# 9 IF Interrupt enable flag 4.146 -# 10 DF Direction flag 4.147 -# 11 OF Overflow flag 4.148 - .ascii "oditsz?a?p c=" # flags bits 4.149 - 4.150 -int3: 4.151 -#ifdef CPU186 4.152 - .byte 0x68 # push $0x086A OV UP DI NT PL ZR - NA - PO - NC 4.153 -# interrupt entry point: the registers [FLAGS CS IP] are already pushed 4.154 -dbgstart: 4.155 - .byte 0x6A, 0x08 # push $0x08 NV UP DI NT PL NZ - NA - PO - NC 4.156 - popf 4.157 -init: 4.158 - pushaw # [FLAGS CS IP] AX CX DX BX SP BP SI DI [DS ES SS] 4.159 -#else 4.160 - stc 4.161 - .byte 0x73 # jnc 4.162 -# interrupt entry point: the registers [FLAGS CS IP] are already pushed 4.163 -dbgstart: 4.164 - clc 4.165 - pushw %ax 4.166 - sbbw %ax,%ax # copy CF to SF 4.167 - clc 4.168 - popw %ax 4.169 -init: 4.170 - cld # ensure movsb will work 4.171 - pusham # [FLAGS CS IP] AX CX DX BX SP BP SI DI [DS ES SS] 4.172 -#endif 4.173 - pushw %ds 4.174 - pushw %es 4.175 - pushw %ss 4.176 - movw %sp, %bp 4.177 -#ifdef CPU186 4.178 - pushf 4.179 - addw $6, USER_SP # adjust SP with [FLAGS CS IP] size 4.180 - popf 4.181 -#endif 4.182 - jc isinit 4.183 - jns notint3 4.184 - decw USER_IP 4.185 - lesw USER_CSIP, %di 4.186 -#define OPCODE_BRK 0xCC 4.187 - .byte 0xB0 # movb $IM, %al 4.188 -break: 4.189 - .byte 0xCC 4.190 - stosb 4.191 -notint3: 4.192 -dbgstartz: 4.193 -dbgregslp: 4.194 - call getcmd 4.195 - .byte 0x81, 0xC3 # addw $0, %bx 4.196 -offset_value: 4.197 - .word 0 4.198 - movw %bx, %es 4.199 - xchgw %ax, %di 4.200 - subb $'m', %al 4.201 - jne isinotmove 4.202 -#ifdef INPUTBUFFER 4.203 -ismove: 4.204 - xchgw %ax, %si 4.205 -moveself: 4.206 -#else 4.207 -isinit: 4.208 - jmp ismove 4.209 - initcode 4.210 -ismove: 4.211 -#endif 4.212 - movw %di, %es # move code to %di:0 4.213 - pushw %di 4.214 -#ifdef INPUTBUFFER 4.215 - xorw %di, %di # and jmp into (%di:setvectors) with retf 4.216 -#else 4.217 - movw $setvectors, %di # and jmp into (%di:setvectors) with retf 4.218 - movw %di, %si 4.219 -#endif 4.220 - movw $_end-setvectors, %cx 4.221 - pushw %di 4.222 - rep movsb 4.223 - retf 4.224 - 4.225 -isinotmove: 4.226 - subb $'+'-'m', %al 4.227 - jne not_offset 4.228 - movw %di, ABS(offset_value) 4.229 -not_offset: 4.230 - orb $1, USER_FLAGS_HIGH # set TF 4.231 - subb $'t'-'+', %al 4.232 - je done 4.233 - subb $'d'-'t', %al 4.234 - xchgw %ax, %cx 4.235 - jcxz dump # 'd' ? 4.236 - loop noenter # 'e' ? 4.237 -nextval: 4.238 - call getval 4.239 - jcxz dbgregslp 4.240 - xchgb %dl, %dh 4.241 -mextmsb: 4.242 - stosb 4.243 - xchgw %ax, %dx 4.244 - xchgb %al, %dh 4.245 -#ifdef ADJESDI 4.246 - call adjustESDI 4.247 -#endif 4.248 - decw %cx 4.249 - loopne mextmsb 4.250 - jmp nextval 4.251 -noenter: 4.252 - loop not_floppy_load # f DX:CX ? 4.253 - movw %es, %dx 4.254 - movw %cx, %es 4.255 - movw %di, %cx 4.256 - movw $0x0201, %ax 4.257 - movw $0x7C00, %bx 4.258 - pushw %bx 4.259 - int $0x13 4.260 - popw %di 4.261 -godbgregslpifc: 4.262 - jc dbgregslp 4.263 -dump: 4.264 - movw %es, %ax 4.265 - call putax 4.266 - movw %di, %ax 4.267 - call putax 4.268 - movw $16, %cx 4.269 -dhex: 4.270 - movb %es:(%di), %ah 4.271 -#ifdef ASCIIDUMP 4.272 - movb %ah, (%si) 4.273 - incw %si 4.274 -#endif 4.275 -#ifdef ADJESDI 4.276 - call incESDI 4.277 -#else 4.278 - incw %di 4.279 -#endif 4.280 - movb $0x01, %dh # the data has 2 digits 4.281 - call putx 4.282 - loop dhex 4.283 -#ifdef ASCIIDUMP 4.284 - movb $16, %cl 4.285 - subw %cx, %si 4.286 -dascii: 4.287 - lodsb 4.288 - cmpb $0x7F, %al 4.289 - jnc skipascii 4.290 - cmpb $0x20, %al 4.291 - cmc 4.292 -skipascii: 4.293 - call dbgputcbit 4.294 - loop dascii 4.295 -#endif 4.296 - call dbgputcr 4.297 - int $0x16 4.298 - cmpb $13, %al 4.299 - je dump 4.300 -notdump: 4.301 -not_floppy_load: 4.302 - stc 4.303 - loop godbgregslpifc # g ? 4.304 -isgo: 4.305 - andb $0xfe, USER_FLAGS_HIGH # clear TF 4.306 - xchgw %ax, %cx 4.307 - jcxz done 4.308 -setbreak: 4.309 - movb $OPCODE_BRK, %al 4.310 - xchgb %al, %es:(%di) 4.311 - movb %al, ABS(break) 4.312 -done: 4.313 - popw %ax # %ss 4.314 - popw %es 4.315 - popw %ds 4.316 -#ifdef CPU186 4.317 - popaw 4.318 -#else 4.319 - popam 4.320 -#endif 4.321 - iret 4.322 - 4.323 -#ifdef ADJESDI 4.324 -adjustESDI: 4.325 - decw %di 4.326 -incESDI: 4.327 - incw %di 4.328 - jnz esok 4.329 - pushw %es 4.330 - addb $0x10,-3(%bp) 4.331 - popw %es 4.332 -esok: 4.333 - ret 4.334 -#endif 4.335 - 4.336 -putreg: 4.337 - call dbgput2c 4.338 - movb $'=', %al 4.339 - call dbgputc 4.340 -putr16: 4.341 -# movw _start-ABS(regs)-2(%bp,%si), %ax 4.342 - .byte 0x8b, 0x42, _start-ABS(regs)-2 4.343 -putax: 4.344 - movb $0x07, %dh # the data has 4 digits 4.345 -putx: 4.346 -putxlp: 4.347 -#ifdef CPU186 4.348 - rolw $4, %ax 4.349 -#else 4.350 - pushw %cx 4.351 - movb $4, %cl 4.352 - rolw %cl, %ax 4.353 - popw %cx 4.354 -#endif 4.355 - pushw %ax 4.356 - andb $0xf, %al 4.357 - addb $0x90, %al 4.358 - daa 4.359 - adcb $0x40, %al 4.360 - daa 4.361 - call dbgputc 4.362 - popw %ax 4.363 - shrb $1, %dh 4.364 - jc putxlp 4.365 -dbgputcbit: 4.366 - jc dbgputc 4.367 - mov $0x20, %al 4.368 -dbgputc: 4.369 - movw $7, %bx 4.370 - mov $0xE, %ah 4.371 - int $0x10 4.372 - xchgw %ax, %bx 4.373 - ret 4.374 - 4.375 -getline: 4.376 - movw $ABS(regs), %si 4.377 - movw $13, %cx 4.378 -regslp: 4.379 - call putreg # display register name and value 4.380 - loop regslp 4.381 - movw USER_FLAGS, %dx 4.382 - pushw %si 4.383 - movb $13, %cl 4.384 - stc # add trailing = 4.385 - rcrw %cl, %dx 4.386 -nextbit: 4.387 - lodsb 4.388 - shlw $1, %dx 4.389 - call dbgputcbit # display active flags bits 4.390 - loop nextbit 4.391 - popw %si 4.392 - movb $8, %cl 4.393 -stacklp: 4.394 - lodsw # si += 2 4.395 - call putr16 # display flags and the beginning of the stack 4.396 - loop stacklp 4.397 - call dbgputcr 4.398 -getlinebs: 4.399 - cmpw $ABS(buffer), %si 4.400 - je getc 4.401 - decw %si 4.402 -getlinelp: 4.403 - call dbgputc 4.404 -getc: 4.405 - int $0x16 4.406 - cmpb $8, %al 4.407 - je getlinebs 4.408 - orb $0x20, %al 4.409 - movb %al, (%si) 4.410 - inc %si 4.411 - cmpb $0x2D, %al 4.412 - jne getlinelp 4.413 -dbgputcr: 4.414 - movw $ABS(crlf), %si 4.415 -dbgput2c: 4.416 - call dbgput1c 4.417 -dbgput1c: 4.418 - lodsb 4.419 - jmp dbgputc 4.420 - 4.421 -getcmd: 4.422 - pushw %cs 4.423 - popw %ds 4.424 - call getline 4.425 - lodsb 4.426 - xchgw %ax, %di 4.427 -# get value in DX:AX, BX is segment CX is digits count. 4.428 -getval: 4.429 - xorw %bx, %bx 4.430 - xorw %cx, %cx 4.431 -getvalz: 4.432 - pushw %bx # save segment 4.433 - xorw %bx, %bx 4.434 - mul %bx # clear %dx:%ax 4.435 - decw %cx 4.436 -isx: 4.437 - incw %cx 4.438 - orb $0xE0, %dh 4.439 -getvalbit: 4.440 - shlw $1, %bx 4.441 - rclw $1, %dx 4.442 - jc getvalbit 4.443 - orb %al, %bl 4.444 -gotspc: 4.445 - lodsb 4.446 - cmpb $0x20, %al # space ? 4.447 - jne notspc 4.448 - jcxz gotspc 4.449 -notspc: 4.450 - sub $'0', %al 4.451 - cmpb $10, %al # in 0..9 ? 4.452 - jb isx 4.453 - sub $'a'-'0'-10, %al 4.454 - cmpb $16, %al # in a..f ? 4.455 - jb isx 4.456 - cmpb $':'-'a'+10, %al 4.457 - popw %ax 4.458 - je getvalz # store segment in %bx 4.459 - xchgw %ax, %bx 4.460 - pushw %dx 4.461 -#ifdef CPU186 4.462 - shlw $12, %dx 4.463 -#else 4.464 - pushw %cx 4.465 - movb $12, %cl 4.466 - shlw %cl, %dx 4.467 - popw %cx 4.468 -#endif 4.469 - addw %dx, %bx 4.470 - popw %dx 4.471 - ret 4.472 - 4.473 -crlf: 4.474 - .byte 13,10 4.475 -_end: 4.476 -buffer: 4.477 - 4.478 - .org 510 4.479 - .byte 0x55, 0xAA 4.480 -
5.1 --- a/runcom/stuff/runcom.c Sun Feb 12 11:28:15 2012 +0000 5.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 5.3 @@ -1,1364 +0,0 @@ 5.4 -/* 5.5 - * Simple example of use of vm86: launch a basic .com DOS executable 5.6 - */ 5.7 -#include <stdlib.h> 5.8 -#include <stdio.h> 5.9 -#include <string.h> 5.10 -#include <inttypes.h> 5.11 -#include <unistd.h> 5.12 -#include <fcntl.h> 5.13 -#include <time.h> 5.14 -#include <sys/mman.h> 5.15 -#include <sys/ioctl.h> 5.16 -#include <sys/time.h> 5.17 -#include <sys/types.h> 5.18 -#include <sys/stat.h> 5.19 -#include <signal.h> 5.20 -#include <errno.h> 5.21 -#include <ctype.h> 5.22 -#include <termios.h> 5.23 - 5.24 -#include <sys/syscall.h> 5.25 -#include <asm/vm86.h> 5.26 - 5.27 -//#define DUMP_INT21 5.28 - 5.29 -static inline int vm86(int func, struct vm86plus_struct *v86) 5.30 -{ 5.31 - return syscall(__NR_vm86, func, v86); 5.32 -} 5.33 - 5.34 -#define CF_MASK 0x00000001 5.35 -#define ZF_MASK 0x00000040 5.36 -#define TF_MASK 0x00000100 5.37 -#define IF_MASK 0x00000200 5.38 -#define DF_MASK 0x00000400 5.39 -#define IOPL_MASK 0x00003000 5.40 -#define NT_MASK 0x00004000 5.41 -#define RF_MASK 0x00010000 5.42 -#define VM_MASK 0x00020000 5.43 -#define AC_MASK 0x00040000 5.44 -#define VIF_MASK 0x00080000 5.45 -#define VIP_MASK 0x00100000 5.46 -#define ID_MASK 0x00200000 5.47 - 5.48 -void usage(void) 5.49 -{ 5.50 - printf("runcom version 0.2-slitaz (c) 2003-2011 Fabrice Bellard\n" 5.51 - "usage: runcom file.com [args...]\n" 5.52 - "Run simple .com DOS executables (linux vm86 test mode)\n"); 5.53 - exit(1); 5.54 -} 5.55 - 5.56 -static inline void set_bit(uint8_t *a, unsigned int bit) 5.57 -{ 5.58 - a[bit / 8] |= (1 << (bit % 8)); 5.59 -} 5.60 - 5.61 -static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg) 5.62 -{ 5.63 - return (uint8_t *)((seg << 4) + (reg & 0xffff)); 5.64 -} 5.65 - 5.66 -static inline void pushw(struct vm86_regs *r, int val) 5.67 -{ 5.68 - r->esp = (r->esp & ~0xffff) | ((r->esp - 2) & 0xffff); 5.69 - *(uint16_t *)seg_to_linear(r->ss, r->esp) = val; 5.70 -} 5.71 - 5.72 -void dump_regs(struct vm86_regs *r) 5.73 -{ 5.74 - int i; 5.75 - uint8_t *p8; 5.76 - uint16_t *p16; 5.77 - fprintf(stderr, 5.78 - "EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n" 5.79 - "ESI=%08lx EDI=%08lx EBP=%08lx ESP=%08lx\n" 5.80 - "EIP=%08lx EFL=%08lx " 5.81 - "CS=%04x DS=%04x ES=%04x SS=%04x FS=%04x GS=%04x\n[SP]", 5.82 - r->eax, r->ebx, r->ecx, r->edx, r->esi, r->edi, r->ebp, r->esp, 5.83 - r->eip, r->eflags, 5.84 - r->cs, r->ds, r->es, r->ss, r->fs, r->gs); 5.85 - for (p16 = (uint16_t *) seg_to_linear(r->ss, r->esp), i = 0; i < 15; i++) 5.86 - fprintf(stderr," %04x", *p16++); 5.87 - fprintf(stderr,"\n[IP]"); 5.88 - for (p8 = seg_to_linear(r->cs, r->eip), i = 0; i < 25; i++) 5.89 - fprintf(stderr," %02x", *p8++); 5.90 - fprintf(stderr,"\n"); 5.91 -} 5.92 - 5.93 -#define DOS_FD_MAX 256 5.94 -typedef struct { 5.95 - int fd; /* -1 means closed */ 5.96 -} DOSFile; 5.97 - 5.98 -DOSFile dos_files[DOS_FD_MAX]; 5.99 -uint16_t cur_psp; 5.100 - 5.101 -void dos_init(void) 5.102 -{ 5.103 - int i; 5.104 - for(i = 0; i < DOS_FD_MAX; i++) 5.105 - dos_files[i].fd = (i < 3) ? i : -1; 5.106 -} 5.107 - 5.108 -static inline void set_error(struct vm86_regs *r, int val) 5.109 -{ 5.110 - r->eflags &= ~CF_MASK; 5.111 - if (val) { 5.112 - r->eax = (r->eax & ~0xffff) | val; 5.113 - r->eflags |= CF_MASK; 5.114 - } 5.115 -} 5.116 -static DOSFile *get_file(int h) 5.117 -{ 5.118 - DOSFile *fh; 5.119 - 5.120 - if (h < DOS_FD_MAX) { 5.121 - fh = &dos_files[h]; 5.122 - if (fh->fd != -1) 5.123 - return fh; 5.124 - } 5.125 - return NULL; 5.126 -} 5.127 - 5.128 -/* return -1 if error */ 5.129 -static int get_new_handle(void) 5.130 -{ 5.131 - DOSFile *fh; 5.132 - int i; 5.133 - 5.134 - for(i = 0; i < DOS_FD_MAX; i++) { 5.135 - fh = &dos_files[i]; 5.136 - if (fh->fd == -1) 5.137 - return i; 5.138 - } 5.139 - return -1; 5.140 -} 5.141 - 5.142 -static char *get_filename1(struct vm86_regs *r, char *buf, int buf_size, 5.143 - uint16_t seg, uint16_t offset) 5.144 -{ 5.145 - char *q; 5.146 - int c; 5.147 - q = buf; 5.148 - for(;;) { 5.149 - c = *seg_to_linear(seg, offset); 5.150 - if (c == 0) 5.151 - break; 5.152 - if (q >= buf + buf_size - 1) 5.153 - break; 5.154 - c = tolower(c); 5.155 - if (c == '\\') 5.156 - c = '/'; 5.157 - *q++ = c; 5.158 - offset++; 5.159 - } 5.160 - *q = '\0'; 5.161 - return buf; 5.162 -} 5.163 - 5.164 -static char *get_filename(struct vm86_regs *r, char *buf, int buf_size) 5.165 -{ 5.166 - return get_filename1(r, buf, buf_size, r->ds, r->edx & 0xffff); 5.167 -} 5.168 - 5.169 -typedef struct __attribute__((packed)) { 5.170 - uint8_t drive_num; 5.171 - uint8_t file_name[8]; 5.172 - uint8_t file_ext[3]; 5.173 - uint16_t current_block; 5.174 - uint16_t logical_record_size; 5.175 - uint32_t file_size; 5.176 - uint16_t date; 5.177 - uint16_t time; 5.178 - uint8_t reserved[8]; 5.179 - uint8_t record_in_block; 5.180 - uint32_t record_num; 5.181 -} FCB; 5.182 - 5.183 -typedef struct __attribute__((packed)) { 5.184 - uint16_t environ; 5.185 - uint16_t cmdtail_off; 5.186 - uint16_t cmdtail_seg; 5.187 - uint32_t fcb1; 5.188 - uint32_t fcb2; 5.189 - uint16_t sp, ss; 5.190 - uint16_t ip, cs; 5.191 -} ExecParamBlock; 5.192 - 5.193 -typedef struct MemBlock { 5.194 - struct MemBlock *next; 5.195 - uint16_t seg; 5.196 - uint16_t size; /* in paragraphs */ 5.197 -} MemBlock; 5.198 - 5.199 -/* first allocated paragraph */ 5.200 -MemBlock *first_mem_block = NULL; 5.201 - 5.202 -#define MEM_START 0x1000 5.203 -#define MEM_END 0xa000 5.204 - 5.205 -/* return -1 if error */ 5.206 -int mem_malloc(int size, int *pmax_size) 5.207 -{ 5.208 - MemBlock *m, **pm; 5.209 - int seg_free, seg; 5.210 - 5.211 - /* XXX: this is totally inefficient, but we have only 1 or 2 5.212 - blocks ! */ 5.213 - seg_free = MEM_START; 5.214 - for(pm = &first_mem_block; *pm != NULL; pm = &(*pm)->next) { 5.215 - m = *pm; 5.216 - seg = m->seg + m->size; 5.217 - if (seg > seg_free) 5.218 - seg_free = seg; 5.219 - } 5.220 - if ((seg_free + size) > MEM_END) 5.221 - return -1; 5.222 - if (pmax_size) 5.223 - *pmax_size = MEM_END - seg_free; 5.224 - /* add at the end */ 5.225 - m = malloc(sizeof(MemBlock)); 5.226 - *pm = m; 5.227 - m->next = NULL; 5.228 - m->seg = seg_free; 5.229 - m->size = size; 5.230 -#ifdef DUMP_INT21 5.231 - printf("mem_malloc size=0x%04x: 0x%04x\n", size, seg_free); 5.232 -#endif 5.233 - return seg_free; 5.234 -} 5.235 - 5.236 -/* return -1 if error */ 5.237 -int mem_free(int seg) 5.238 -{ 5.239 - MemBlock *m, **pm; 5.240 - for(pm = &first_mem_block; *pm != NULL; pm = &(*pm)->next) { 5.241 - m = *pm; 5.242 - if (m->seg == seg) { 5.243 - *pm = m->next; 5.244 - free(m); 5.245 - return 0; 5.246 - } 5.247 - } 5.248 - return -1; 5.249 -} 5.250 - 5.251 -/* return -1 if error or the maxmium size */ 5.252 -int mem_resize(int seg, int new_size) 5.253 -{ 5.254 - MemBlock *m, **pm, *m1; 5.255 - int max_size; 5.256 - 5.257 - for(pm = &first_mem_block; *pm != NULL; pm = &(*pm)->next) { 5.258 - m = *pm; 5.259 - if (m->seg == seg) { 5.260 - m1 = m->next; 5.261 - if (!m1) 5.262 - max_size = MEM_END - m->seg; 5.263 - else 5.264 - max_size = m1->seg - m->seg; 5.265 - if (new_size > max_size) 5.266 - return -1; 5.267 - m->size = new_size; 5.268 - return max_size; 5.269 - } 5.270 - } 5.271 - return -1; 5.272 -} 5.273 - 5.274 -int load_boot(const char *filename, struct vm86_regs *r) 5.275 -{ 5.276 - int fd, ret; 5.277 - 5.278 - /* load the boot sector */ 5.279 - fd = open(filename, O_RDONLY); 5.280 - if (fd >= 0) { 5.281 - *seg_to_linear(0x0, 0x7dff) = 0; 5.282 - r->eax = 0x200; 5.283 - r->ebx = r->esp = r->eip = 0x7c00; 5.284 - r->ecx = 1; 5.285 - r->esi = r->edi = r->ebp = 5.286 - r->edx = 0; /* floppy disk */ 5.287 - r->cs = r->ss = r->ds = r->es = 0; 5.288 - r->eflags = VIF_MASK; 5.289 - ret = read(fd, seg_to_linear(0x0, 0x7c00), 0x200); 5.290 - if (lseek(fd, 0, SEEK_END) > 4*1024*1024) 5.291 - r->edx = 0x80; /* hard disk */ 5.292 - close(fd); 5.293 - if (ret != 0x200 || 5.294 - *seg_to_linear(0x0, 0x7dfe) != 0x55 || 5.295 - *seg_to_linear(0x0, 0x7dff) != 0xaa) { 5.296 - fprintf(stderr,"No boot sector.\n"); 5.297 - fd = -1; 5.298 - } 5.299 - } 5.300 - return fd; 5.301 -} 5.302 - 5.303 -/* return the PSP or -1 if error */ 5.304 -int load_exe(ExecParamBlock *blk, const char *filename, 5.305 - int psp, uint32_t *pfile_size) 5.306 -{ 5.307 - int fd, size, base; 5.308 - struct { 5.309 - uint16_t signature; // 0x5A4D 'MZ' 5.310 - uint16_t bytes_in_last_block; 5.311 - uint16_t blocks_in_file; 5.312 - uint16_t num_relocs; 5.313 - uint16_t header_paragraphs; // Size of header 5.314 - uint16_t min_extra_paragraphs; // BSS size 5.315 - uint16_t max_extra_paragraphs; 5.316 - uint16_t ss; // Initial (relative) SS value 5.317 - uint16_t sp; // Initial SP value 5.318 - uint16_t checksum; 5.319 - uint16_t ip; // Initial IP value 5.320 - uint16_t cs; // Initial (relative) CS value 5.321 - uint16_t reloc_table_offset; 5.322 - uint16_t overlay_number; 5.323 - } header; 5.324 - struct { 5.325 - uint16_t offset; 5.326 - uint16_t segment; 5.327 - } rel; 5.328 - 5.329 - /* load the MSDOS .exe executable */ 5.330 - fd = open(filename, O_RDONLY); 5.331 - if (fd < 0) { 5.332 - return -1; 5.333 - } 5.334 - if (read(fd, &header, sizeof(header)) != sizeof(header)) { 5.335 - close(fd); 5.336 - return -1; 5.337 - } 5.338 - 5.339 - memset(seg_to_linear(psp, 0x100), 0, 65536 - 0x100); 5.340 - 5.341 - size = (header.blocks_in_file * 512) - (header.header_paragraphs * 16) + 5.342 - (header.bytes_in_last_block ? header.bytes_in_last_block - 512 : 0); 5.343 - header.min_extra_paragraphs += (size-1)/16; 5.344 - 5.345 - /* address of last segment allocated */ 5.346 - *(uint16_t *)seg_to_linear(psp, 2) = psp + header.min_extra_paragraphs; 5.347 - 5.348 - if (pfile_size) 5.349 - *pfile_size = size; 5.350 - 5.351 - if (mem_resize(psp, header.min_extra_paragraphs) < 0 || 5.352 - lseek(fd, header.header_paragraphs * 16, SEEK_SET) < 0 || 5.353 - read(fd, seg_to_linear(psp, 0x100), size) != size || 5.354 - lseek(fd, header.reloc_table_offset, SEEK_SET) < 0) { 5.355 - close(fd); 5.356 - return -1; 5.357 - } 5.358 - 5.359 - base = psp + 16; 5.360 - while (header.num_relocs-- && read(fd, &rel, sizeof(rel)) == sizeof(rel)) 5.361 - if (rel.segment != 0 || rel.offset != 0) 5.362 - * (uint16_t *) seg_to_linear(base + rel.segment, rel.offset) += base; 5.363 - close(fd); 5.364 - 5.365 - blk->cs = base + header.cs; 5.366 - blk->ip = header.ip; 5.367 - blk->ss = base + header.ss; 5.368 - blk->sp = header.sp - 6; 5.369 - 5.370 - /* push return far address */ 5.371 - *(uint16_t *)seg_to_linear(blk->ss, blk->sp + 4) = psp; 5.372 - 5.373 - return psp; 5.374 -} 5.375 - 5.376 -/* return the PSP or -1 if error */ 5.377 -int load_com(ExecParamBlock *blk, const char *filename, uint32_t *pfile_size, 5.378 - int argc, char **argv) 5.379 -{ 5.380 - int psp, fd, ret; 5.381 - 5.382 - /* load the MSDOS .com executable */ 5.383 - fd = open(filename, O_RDONLY); 5.384 - if (fd < 0) { 5.385 - return -1; 5.386 - } 5.387 - psp = mem_malloc(65536 / 16, NULL); 5.388 - ret = read(fd, seg_to_linear(psp, 0x100), 65536 - 0x100); 5.389 - close(fd); 5.390 - if (ret <= 0) { 5.391 - mem_free(psp); 5.392 - return -1; 5.393 - } 5.394 - if (pfile_size) 5.395 - *pfile_size = ret; 5.396 - 5.397 - /* reset the PSP */ 5.398 - memset(seg_to_linear(psp, 0), 0, 0x100); 5.399 - 5.400 - *seg_to_linear(psp, 0) = 0xcd; /* int $0x20 */ 5.401 - *seg_to_linear(psp, 1) = 0x20; 5.402 - /* address of last segment allocated */ 5.403 - *(uint16_t *)seg_to_linear(psp, 2) = psp + 0xfff; 5.404 - 5.405 - if (argc) { 5.406 - int i, p; 5.407 - char *s; 5.408 - /* set the command line */ 5.409 - p = 0x81; 5.410 - for(i = 2; i < argc; i++) { 5.411 - if (p >= 0xff) 5.412 - break; 5.413 - *seg_to_linear(psp, p++) = ' '; 5.414 - s = argv[i]; 5.415 - while (*s) { 5.416 - if (p >= 0xff) 5.417 - break; 5.418 - *seg_to_linear(psp, p++) = *s++; 5.419 - } 5.420 - } 5.421 - *seg_to_linear(psp, p) = '\r'; 5.422 - *seg_to_linear(psp, 0x80) = p - 0x81; 5.423 - } 5.424 - else { 5.425 - int len; 5.426 - /* copy the command line */ 5.427 - len = *seg_to_linear(blk->cmdtail_seg, blk->cmdtail_off); 5.428 - memcpy(seg_to_linear(psp, 0x80), 5.429 - seg_to_linear(blk->cmdtail_seg, blk->cmdtail_off), len + 2); 5.430 - } 5.431 - 5.432 - blk->sp = 0xfffc; 5.433 - blk->ip = 0x100; 5.434 - blk->cs = blk->ss = psp; 5.435 - 5.436 - if (*(uint16_t *)seg_to_linear(psp, 0x100) == 0x5A4D) 5.437 - psp = load_exe(blk, filename, psp, pfile_size); 5.438 - 5.439 - /* push ax value */ 5.440 - *(uint16_t *)seg_to_linear(blk->ss, blk->sp) = 0; 5.441 - /* push return address to 0 */ 5.442 - *(uint16_t *)seg_to_linear(blk->ss, blk->sp + 2) = 0; 5.443 - 5.444 - return psp; 5.445 -} 5.446 - 5.447 - 5.448 -void unsupported_function(struct vm86_regs *r, uint8_t num, uint8_t ah) 5.449 -{ 5.450 - fprintf(stderr, "int 0x%02x: unsupported function 0x%02x\n", num, ah); 5.451 - dump_regs(r); 5.452 - set_error(r, 0x01); /* function number invalid */ 5.453 -} 5.454 - 5.455 -/* Open hard disk image ./hd[0-7] / floppy image ./fd[0-7] or /dev/fd[0-7] */ 5.456 -int open_disk(struct vm86_regs *r) 5.457 -{ 5.458 - int fd = -1, drive = r->edx & 0xff; 5.459 - char filename[9], n = '0' + (drive & 7); 5.460 - if (drive > 127) { 5.461 - strcpy(filename,"hd0"); 5.462 - filename[2] = n; 5.463 - } 5.464 - else { 5.465 - strcpy(filename,"/dev/fd0"); 5.466 - filename[7] = n; 5.467 - fd = open(filename+5, O_RDONLY); 5.468 - } 5.469 - if (fd < 0) 5.470 - fd = open(filename, O_RDONLY); 5.471 - return fd; 5.472 -} 5.473 - 5.474 - 5.475 -void read_sectors(int fd, struct vm86_regs *r, int first_sector, 5.476 - int sector_count, void *buffer) 5.477 -{ 5.478 - int drive = r->edx & 0xff; 5.479 - r->eax &= ~0xff00; 5.480 - r->eax |= 0x0400; /* sector not found */ 5.481 - r->eflags |= CF_MASK; 5.482 - if (fd >= 0) { 5.483 - static struct stat st; 5.484 - first_sector <<= 9; 5.485 - sector_count <<= 9; 5.486 - if (drive < 8 && fstat(fd, &st) == 0) { 5.487 - static ino_t inodes[8]; 5.488 - ino_t last = inodes[drive]; 5.489 - inodes[drive] = st.st_ino; 5.490 - if (last && last != st.st_ino) { 5.491 - set_error(r, 0x0600); /* floppy disk swap */ 5.492 - goto failed; 5.493 - } 5.494 - } 5.495 - if (lseek(fd, first_sector, SEEK_CUR) >= 0 && 5.496 - read(fd, buffer, sector_count) == sector_count) { 5.497 - r->eax &= ~0xff00; 5.498 - r->eflags &= ~CF_MASK; 5.499 - } 5.500 - failed: 5.501 - close(fd); 5.502 - } 5.503 -} 5.504 - 5.505 -void do_int10(struct vm86_regs *r) 5.506 -{ 5.507 - uint8_t ah; 5.508 - 5.509 - ah = (r->eax >> 8); 5.510 - switch(ah) { 5.511 - case 0x0E: /* write char */ 5.512 - { 5.513 - uint8_t c = r->eax; 5.514 - write(1, &c, 1); 5.515 - } 5.516 - break; 5.517 - default: 5.518 - unsupported_function(r, 0x10, ah); 5.519 - } 5.520 -} 5.521 - 5.522 -void do_int13(struct vm86_regs *r) 5.523 -{ 5.524 - uint8_t ah; 5.525 - 5.526 - ah = (r->eax >> 8); 5.527 - switch(ah) { 5.528 - case 0x00: /* reset disk */ 5.529 - { 5.530 - r->eax &= ~0xff00; /* success */ 5.531 - r->eflags &= ~CF_MASK; 5.532 - } 5.533 - break; 5.534 - case 0x02: /* read disk CHS */ 5.535 - { 5.536 - int fd, c, h, s, heads, sectors, cylinders; 5.537 - long size; 5.538 - fd = open_disk(r); 5.539 - if (fd >= 0) { 5.540 - size = lseek(fd, 0, SEEK_END) / 512; 5.541 - if ((r->edx & 0xff) > 127) { 5.542 - sectors = 63; 5.543 - if (size % sectors) 5.544 - sectors = 62; 5.545 - if (size % sectors) 5.546 - sectors = 32; 5.547 - if (size % sectors) 5.548 - sectors = 17; 5.549 - if (size % sectors) 5.550 - fd = -1; 5.551 - size /= sectors; 5.552 - for (heads = 256; size % heads; heads--); 5.553 - cylinders = size / heads; 5.554 - } 5.555 - else { 5.556 - int i; 5.557 - heads = 1 + (size > 256*2); 5.558 - cylinders = 40 * (1 + (size > 512*2)); 5.559 - size /= heads; 5.560 - for (i = 0; i < 5; i++) 5.561 - if (size % (cylinders + i) == 0) break; 5.562 - if (i == 5) 5.563 - fd = -1; 5.564 - cylinders += i; 5.565 - sectors = size / cylinders; 5.566 - } 5.567 - } 5.568 - c = ((r->ecx & 0xC0) << 2) | ((r->ecx >> 8) & 0xff); 5.569 - h = (r->edx >> 8) & 0xff; 5.570 - s = (r->ecx & 0x3f) -1; 5.571 - if (fd < 0 || c >= cylinders || h >= heads || s >= sectors) { 5.572 - set_error(r, 0x0400); /* sector not found */ 5.573 - break; 5.574 - } 5.575 - read_sectors(fd, r, (((c * heads) + h) * sectors) + s, 5.576 - r->eax & 0xff, seg_to_linear(r->es, r->ebx)); 5.577 - } 5.578 - break; 5.579 - case 0x42: /* read disk LBA */ 5.580 - { 5.581 - uint16_t *packet = (uint16_t *) seg_to_linear(r->ds, r-> esi); 5.582 - uint8_t *to = seg_to_linear(packet[3], packet[2]); 5.583 - if ((packet[3] & packet[2]) == 0xffff) 5.584 - to = * (uint8_t **) &packet[8]; 5.585 - if (packet[0] != 0x0010 && packet[0] != 0x0018) 5.586 - goto unsupported; 5.587 - read_sectors(open_disk(r), r, * (uint32_t *) &packet[4], packet[1], to); 5.588 - } 5.589 - break; 5.590 - default: 5.591 - unsupported: 5.592 - unsupported_function(r, 0x13, ah); 5.593 - } 5.594 -} 5.595 - 5.596 -void do_int15(struct vm86_regs *r) 5.597 -{ 5.598 - uint8_t ah; 5.599 - 5.600 - ah = (r->eax >> 8); 5.601 - switch(ah) { 5.602 - case 0x87: /* move memory */ 5.603 - /* XXX */ 5.604 - break; 5.605 - default: 5.606 - unsupported_function(r, 0x15, ah); 5.607 - } 5.608 -} 5.609 - 5.610 -void do_int16(struct vm86_regs *r) 5.611 -{ 5.612 - static uint16_t last_ax, hold_char; 5.613 - struct termios termios_def, termios_raw; 5.614 - uint8_t ah; 5.615 - 5.616 - ah = (r->eax >> 8); 5.617 - tcgetattr(0, &termios_def); 5.618 - termios_raw = termios_def; 5.619 - cfmakeraw(&termios_raw); 5.620 - tcsetattr(0, TCSADRAIN, &termios_raw); 5.621 - switch(ah) { 5.622 - case 0x01: /* test keyboard */ 5.623 - { 5.624 - int count; 5.625 - r->eflags &= ~ZF_MASK; 5.626 - if (hold_char) { 5.627 - r->eax &= ~0xffff; 5.628 - r->eax |= last_ax; 5.629 - break; 5.630 - } 5.631 - if (ioctl(0, FIONREAD, &count) < 0 || count == 0) { 5.632 - r->eflags |= ZF_MASK; 5.633 - break; 5.634 - } 5.635 - hold_char = 2; 5.636 - } 5.637 - case 0x00: /* read keyboard */ 5.638 - { 5.639 - uint8_t c; 5.640 - if (hold_char) 5.641 - hold_char--; 5.642 - read(0, &c, 1); 5.643 - if (c == 3) { 5.644 - tcsetattr(0, TCSADRAIN, &termios_def); 5.645 - exit(0); 5.646 - } 5.647 - if (c == 10) 5.648 - c = 13; 5.649 - r->eax &= ~0xffff; 5.650 - r->eax |= last_ax = c; 5.651 - /* XXX ah = scan code */ 5.652 - } 5.653 - break; 5.654 - default: 5.655 - unsupported_function(r, 0x16, ah); 5.656 - } 5.657 - tcsetattr(0, TCSADRAIN, &termios_def); 5.658 -} 5.659 - 5.660 -void do_int1a(struct vm86_regs *r) 5.661 -{ 5.662 - uint8_t ah; 5.663 - 5.664 - ah = (r->eax >> 8); 5.665 - switch(ah) { 5.666 - case 0x00: /* GET SYSTEM TIME */ 5.667 - { 5.668 - uint16_t *timer = (uint16_t *) seg_to_linear(0, 0x46C); 5.669 - r->ecx &= ~0xffff; 5.670 - r->ecx |= *timer++; 5.671 - r->edx &= ~0xffff; 5.672 - r->edx |= *timer; 5.673 - r->eax &= ~0xff; 5.674 - } 5.675 - break; 5.676 - default: 5.677 - unsupported_function(r, 0x1a, ah); 5.678 - } 5.679 -} 5.680 - 5.681 -void do_int20(struct vm86_regs *r) 5.682 -{ 5.683 - /* terminate program */ 5.684 - exit(0); 5.685 -} 5.686 - 5.687 -void do_int21(struct vm86_regs *r) 5.688 -{ 5.689 - uint8_t ah; 5.690 - 5.691 - ah = (r->eax >> 8); 5.692 - switch(ah) { 5.693 - case 0x00: /* exit */ 5.694 - exit(0); 5.695 - case 0x02: /* write char */ 5.696 - { 5.697 - uint8_t c = r->edx; 5.698 - write(1, &c, 1); 5.699 - } 5.700 - break; 5.701 - case 0x09: /* write string */ 5.702 - { 5.703 - uint8_t c; 5.704 - int offset; 5.705 - offset = r->edx; 5.706 - for(;;) { 5.707 - c = *seg_to_linear(r->ds, offset); 5.708 - if (c == '$') 5.709 - break; 5.710 - write(1, &c, 1); 5.711 - offset++; 5.712 - } 5.713 - r->eax = (r->eax & ~0xff) | '$'; 5.714 - } 5.715 - break; 5.716 - case 0x0a: /* buffered input */ 5.717 - { 5.718 - int max_len, cur_len, ret; 5.719 - uint8_t ch; 5.720 - uint16_t off; 5.721 - 5.722 - /* XXX: should use raw mode to avoid sending the CRLF to 5.723 - the terminal */ 5.724 - off = r->edx & 0xffff; 5.725 - max_len = *seg_to_linear(r->ds, off); 5.726 - cur_len = 0; 5.727 - while (cur_len < max_len) { 5.728 - ret = read(0, &ch, 1); 5.729 - if (ret < 0) { 5.730 - if (errno != EINTR && errno != EAGAIN) 5.731 - break; 5.732 - } else if (ret == 0) { 5.733 - break; 5.734 - } else { 5.735 - if (ch == '\n') 5.736 - break; 5.737 - } 5.738 - *seg_to_linear(r->ds, off + 2 + cur_len++) = ch; 5.739 - } 5.740 - *seg_to_linear(r->ds, off + 1) = cur_len; 5.741 - *seg_to_linear(r->ds, off + 2 + cur_len) = '\r'; 5.742 - } 5.743 - break; 5.744 - case 0x25: /* set interrupt vector */ 5.745 - { 5.746 - uint16_t *ptr; 5.747 - ptr = (uint16_t *)seg_to_linear(0, (r->eax & 0xff) * 4); 5.748 - ptr[0] = r->edx; 5.749 - ptr[1] = r->ds; 5.750 - } 5.751 - break; 5.752 - case 0x29: /* parse filename into FCB */ 5.753 -#if 0 5.754 - /* not really needed */ 5.755 - { 5.756 - const uint8_t *p, *p_start; 5.757 - uint8_t file[8], ext[3]; 5.758 - FCB *fcb; 5.759 - int file_len, ext_len, has_wildchars, c, drive_num; 5.760 - 5.761 - /* XXX: not complete at all */ 5.762 - fcb = (FCB *)seg_to_linear(r->es, r->edi); 5.763 - printf("ds=0x%x si=0x%lx\n", r->ds, r->esi); 5.764 - p_start = (const uint8_t *)seg_to_linear(r->ds, r->esi); 5.765 - 5.766 - p = p_start; 5.767 - has_wildchars = 0; 5.768 - 5.769 - /* drive */ 5.770 - if (isalpha(p[0]) && p[1] == ':') { 5.771 - drive_num = toupper(p[0]) - 'A' + 1; 5.772 - p += 2; 5.773 - } else { 5.774 - drive_num = 0; 5.775 - } 5.776 - 5.777 - /* filename */ 5.778 - file_len = 0; 5.779 - for(;;) { 5.780 - c = *p; 5.781 - if (!(c >= 33 && c <= 126)) 5.782 - break; 5.783 - if (c == '.') 5.784 - break; 5.785 - if (c == '*' || c == '?') 5.786 - has_wildchars = 1; 5.787 - if (file_len < 8) 5.788 - file[file_len++] = c; 5.789 - } 5.790 - memset(file + file_len, ' ', 8 - file_len); 5.791 - 5.792 - /* extension */ 5.793 - ext_len = 0; 5.794 - if (*p == '.') { 5.795 - for(;;) { 5.796 - c = *p; 5.797 - if (!(c >= 33 && c <= 126)) 5.798 - break; 5.799 - if (c == '*' || c == '?') 5.800 - has_wildchars = 1; 5.801 - ext[ext_len++] = c; 5.802 - if (ext_len >= 3) 5.803 - break; 5.804 - } 5.805 - } 5.806 - memset(ext + ext_len, ' ', 3 - ext_len); 5.807 - 5.808 -#if 0 5.809 - { 5.810 - printf("drive=%d file=%8s ext=%3s\n", 5.811 - drive_num, file, ext); 5.812 - } 5.813 -#endif 5.814 - if (drive_num == 0 && r->eax & (1 << 1)) { 5.815 - /* keep drive */ 5.816 - } else { 5.817 - fcb->drive_num = drive_num; /* default drive */ 5.818 - } 5.819 - 5.820 - if (file_len == 0 && r->eax & (1 << 2)) { 5.821 - /* keep */ 5.822 - } else { 5.823 - memcpy(fcb->file_name, file, 8); 5.824 - } 5.825 - 5.826 - if (ext_len == 0 && r->eax & (1 << 3)) { 5.827 - /* keep */ 5.828 - } else { 5.829 - memcpy(fcb->file_ext, ext, 3); 5.830 - } 5.831 - r->eax = (r->eax & ~0xff) | has_wildchars; 5.832 - r->esi = (r->esi & ~0xffff) | ((r->esi + (p - p_start)) & 0xffff); 5.833 - } 5.834 -#endif 5.835 - break; 5.836 - case 0x2A: /* get system date */ 5.837 - { 5.838 - time_t t = time(NULL); 5.839 - struct tm *now=localtime(&t); 5.840 - 5.841 - r->ecx = now->tm_year; 5.842 - r->edx = (now->tm_mon * 256) + now->tm_mday; 5.843 - r->eax = now->tm_wday;; 5.844 - } 5.845 - break; 5.846 - case 0x2C: /* get system time */ 5.847 - { 5.848 - time_t t = time(NULL); 5.849 - struct tm *now=localtime(&t); 5.850 - struct timeval tim; 5.851 - 5.852 - gettimeofday(&tim, NULL); 5.853 - r->edx = (now->tm_hour * 256) + now->tm_min; 5.854 - r->edx = (tim.tv_sec * 256) + tim.tv_usec/10000; 5.855 - } 5.856 - break; 5.857 - case 0x30: /* get dos version */ 5.858 - { 5.859 - int major, minor, serial, oem; 5.860 - /* XXX: return correct value for FreeDOS */ 5.861 - major = 0x03; 5.862 - minor = 0x31; 5.863 - serial = 0x123456; 5.864 - oem = 0x66; 5.865 - r->eax = (r->eax & ~0xffff) | major | (minor << 8); 5.866 - r->ecx = (r->ecx & ~0xffff) | (serial & 0xffff); 5.867 - r->ebx = (r->ebx & ~0xffff) | (serial & 0xff) | (0x66 << 8); 5.868 - } 5.869 - break; 5.870 - case 0x35: /* get interrupt vector */ 5.871 - { 5.872 - uint16_t *ptr; 5.873 - ptr = (uint16_t *)seg_to_linear(0, (r->eax & 0xff) * 4); 5.874 - r->ebx = (r->ebx & ~0xffff) | ptr[0]; 5.875 - r->es = ptr[1]; 5.876 - } 5.877 - break; 5.878 - case 0x37: 5.879 - { 5.880 - switch(r->eax & 0xff) { 5.881 - case 0x00: /* get switch char */ 5.882 - r->eax = (r->eax & ~0xff) | 0x00; 5.883 - r->edx = (r->edx & ~0xff) | '/'; 5.884 - break; 5.885 - default: 5.886 - goto unsupported; 5.887 - } 5.888 - } 5.889 - break; 5.890 - case 0x3c: /* create or truncate file */ 5.891 - { 5.892 - char filename[1024]; 5.893 - int fd, h, flags; 5.894 - 5.895 - h = get_new_handle(); 5.896 - if (h < 0) { 5.897 - set_error(r, 0x04); /* too many open files */ 5.898 - } else { 5.899 - get_filename(r, filename, sizeof(filename)); 5.900 - if (r->ecx & 1) 5.901 - flags = 0444; /* read-only */ 5.902 - else 5.903 - flags = 0777; 5.904 - fd = open(filename, O_RDWR | O_TRUNC | O_CREAT, flags); 5.905 -#ifdef DUMP_INT21 5.906 - printf("int21: create: file='%s' cx=0x%04x ret=%d\n", 5.907 - filename, (int)(r->ecx & 0xffff), h); 5.908 -#endif 5.909 - if (fd < 0) { 5.910 - set_error(r, 0x03); /* path not found */ 5.911 - } else { 5.912 - dos_files[h].fd = fd; 5.913 - set_error(r, 0); 5.914 - r->eax = (r->eax & ~0xffff) | h; 5.915 - } 5.916 - } 5.917 - } 5.918 - break; 5.919 - case 0x3d: /* open file */ 5.920 - { 5.921 - char filename[1024]; 5.922 - int fd, h; 5.923 - 5.924 - h = get_new_handle(); 5.925 - if (h < 0) { 5.926 - set_error(r, 0x04); /* too many open files */ 5.927 - } else { 5.928 - get_filename(r, filename, sizeof(filename)); 5.929 -#ifdef DUMP_INT21 5.930 - printf("int21: open: file='%s' al=0x%02x ret=%d\n", 5.931 - filename, (int)(r->eax & 0xff), h); 5.932 -#endif 5.933 - fd = open(filename, r->eax & 3); 5.934 - if (fd < 0) { 5.935 - set_error(r, 0x02); /* file not found */ 5.936 - } else { 5.937 - dos_files[h].fd = fd; 5.938 - set_error(r, 0); 5.939 - r->eax = (r->eax & ~0xffff) | h; 5.940 - } 5.941 - } 5.942 - } 5.943 - break; 5.944 - case 0x3e: /* close file */ 5.945 - { 5.946 - DOSFile *fh = get_file(r->ebx & 0xffff); 5.947 -#ifdef DUMP_INT21 5.948 - printf("int21: close fd=%d\n", (int)(r->ebx & 0xffff)); 5.949 -#endif 5.950 - if (!fh) { 5.951 - set_error(r, 0x06); /* invalid handle */ 5.952 - } else { 5.953 - close(fh->fd); 5.954 - fh->fd = -1; 5.955 - set_error(r, 0); 5.956 - } 5.957 - } 5.958 - break; 5.959 - case 0x3f: /* read */ 5.960 - { 5.961 - DOSFile *fh = get_file(r->ebx & 0xffff); 5.962 - int n, ret; 5.963 - 5.964 - if (!fh) { 5.965 - set_error(r, 0x06); /* invalid handle */ 5.966 - } else { 5.967 - n = r->ecx & 0xffff; 5.968 - for(;;) { 5.969 - ret = read(fh->fd, 5.970 - seg_to_linear(r->ds, r->edx), n); 5.971 - if (ret < 0) { 5.972 - if (errno != EINTR && errno != EAGAIN) 5.973 - break; 5.974 - } else { 5.975 - break; 5.976 - } 5.977 - } 5.978 -#ifdef DUMP_INT21 5.979 - printf("int21: read: fd=%d n=%d ret=%d\n", 5.980 - (int)(r->ebx & 0xffff), n, ret); 5.981 -#endif 5.982 - if (ret < 0) { 5.983 - set_error(r, 0x05); /* acces denied */ 5.984 - } else { 5.985 - r->eax = (r->eax & ~0xffff) | ret; 5.986 - set_error(r, 0); 5.987 - } 5.988 - } 5.989 - } 5.990 - break; 5.991 - case 0x40: /* write */ 5.992 - { 5.993 - DOSFile *fh = get_file(r->ebx & 0xffff); 5.994 - int n, ret, pos; 5.995 - 5.996 - if (!fh) { 5.997 - set_error(r, 0x06); /* invalid handle */ 5.998 - } else { 5.999 - n = r->ecx & 0xffff; 5.1000 - if (n == 0) { 5.1001 - /* truncate */ 5.1002 - pos = lseek(fh->fd, 0, SEEK_CUR); 5.1003 - if (pos >= 0) { 5.1004 - ret = ftruncate(fh->fd, pos); 5.1005 - } else { 5.1006 - ret = -1; 5.1007 - } 5.1008 - } else { 5.1009 - for(;;) { 5.1010 - ret = write(fh->fd, 5.1011 - seg_to_linear(r->ds, r->edx), n); 5.1012 - if (ret < 0) { 5.1013 - if (errno != EINTR && errno != EAGAIN) 5.1014 - break; 5.1015 - } else { 5.1016 - break; 5.1017 - } 5.1018 - } 5.1019 - } 5.1020 -#ifdef DUMP_INT21 5.1021 - printf("int21: write: fd=%d n=%d ret=%d\n", 5.1022 - (int)(r->ebx & 0xffff), n, ret); 5.1023 -#endif 5.1024 - if (ret < 0) { 5.1025 - set_error(r, 0x05); /* acces denied */ 5.1026 - } else { 5.1027 - r->eax = (r->eax & ~0xffff) | ret; 5.1028 - set_error(r, 0); 5.1029 - } 5.1030 - } 5.1031 - } 5.1032 - break; 5.1033 - case 0x41: /* unlink */ 5.1034 - { 5.1035 - char filename[1024]; 5.1036 - get_filename(r, filename, sizeof(filename)); 5.1037 - if (unlink(filename) < 0) { 5.1038 - set_error(r, 0x02); /* file not found */ 5.1039 - } else { 5.1040 - set_error(r, 0); 5.1041 - } 5.1042 - } 5.1043 - break; 5.1044 - case 0x42: /* lseek */ 5.1045 - { 5.1046 - DOSFile *fh = get_file(r->ebx & 0xffff); 5.1047 - int pos, ret; 5.1048 - 5.1049 - if (!fh) { 5.1050 - set_error(r, 0x06); /* invalid handle */ 5.1051 - } else { 5.1052 - pos = ((r->ecx & 0xffff) << 16) | (r->edx & 0xffff); 5.1053 - ret = lseek(fh->fd, pos, r->eax & 0xff); 5.1054 -#ifdef DUMP_INT21 5.1055 - printf("int21: lseek: fd=%d pos=%d whence=%d ret=%d\n", 5.1056 - (int)(r->ebx & 0xffff), pos, (uint8_t)r->eax, ret); 5.1057 -#endif 5.1058 - if (ret < 0) { 5.1059 - set_error(r, 0x01); /* function number invalid */ 5.1060 - } else { 5.1061 - r->edx = (r->edx & ~0xffff) | ((unsigned)ret >> 16); 5.1062 - r->eax = (r->eax & ~0xffff) | (ret & 0xffff); 5.1063 - set_error(r, 0); 5.1064 - } 5.1065 - } 5.1066 - } 5.1067 - break; 5.1068 - case 0x44: /* ioctl */ 5.1069 - switch(r->eax & 0xff) { 5.1070 - case 0x00: /* get device information */ 5.1071 - { 5.1072 - DOSFile *fh = get_file(r->ebx & 0xffff); 5.1073 - int ret; 5.1074 - 5.1075 - if (!fh) { 5.1076 - set_error(r, 0x06); /* invalid handle */ 5.1077 - } else { 5.1078 - ret = 0; 5.1079 - if (isatty(fh->fd)) { 5.1080 - ret |= 0x80; 5.1081 - if (fh->fd == 0) 5.1082 - ret |= (1 << 0); 5.1083 - else 5.1084 - ret |= (1 << 1); 5.1085 - } 5.1086 - r->edx = (r->edx & ~0xffff) | ret; 5.1087 - set_error(r, 0); 5.1088 - } 5.1089 - } 5.1090 - break; 5.1091 - default: 5.1092 - goto unsupported; 5.1093 - } 5.1094 - break; 5.1095 - case 0x48: /* allocate memory */ 5.1096 - { 5.1097 - int ret, max_size; 5.1098 -#ifdef DUMP_INT21 5.1099 - printf("int21: allocate memory: size=0x%04x\n", (uint16_t)r->ebx); 5.1100 -#endif 5.1101 - ret = mem_malloc(r->ebx & 0xffff, &max_size); 5.1102 - if (ret < 0) { 5.1103 - set_error(r, 0x08); /* insufficient memory*/ 5.1104 - } else { 5.1105 - r->eax = (r->eax & ~0xffff) | ret; 5.1106 - r->ebx = (r->ebx & ~0xffff) | max_size; 5.1107 - set_error(r, 0); 5.1108 - } 5.1109 - } 5.1110 - break; 5.1111 - case 0x49: /* free memory */ 5.1112 - { 5.1113 -#ifdef DUMP_INT21 5.1114 - printf("int21: free memory: block=0x%04x\n", r->es); 5.1115 -#endif 5.1116 - if (mem_free(r->es) < 0) { 5.1117 - set_error(r, 0x09); /* memory block address invalid */ 5.1118 - } else { 5.1119 - set_error(r, 0); 5.1120 - } 5.1121 - } 5.1122 - break; 5.1123 - case 0x4a: /* resize memory block */ 5.1124 - { 5.1125 - int ret; 5.1126 -#ifdef DUMP_INT21 5.1127 - printf("int21: resize memory block: block=0x%04x size=0x%04x\n", 5.1128 - r->es, (uint16_t)r->ebx); 5.1129 -#endif 5.1130 - ret = mem_resize(r->es, r->ebx & 0xffff); 5.1131 - if (ret < 0) { 5.1132 - set_error(r, 0x08); /* insufficient memory*/ 5.1133 - } else { 5.1134 - r->ebx = (r->ebx & ~0xffff) | ret; 5.1135 - set_error(r, 0); 5.1136 - } 5.1137 - } 5.1138 - break; 5.1139 - case 0x4b: /* load program */ 5.1140 - { 5.1141 - char filename[1024]; 5.1142 - ExecParamBlock *blk; 5.1143 - int ret; 5.1144 - 5.1145 - if ((r->eax & 0xff) != 0x01) /* only load */ 5.1146 - goto unsupported; 5.1147 - get_filename(r, filename, sizeof(filename)); 5.1148 - blk = (ExecParamBlock *)seg_to_linear(r->es, r->ebx); 5.1149 - ret = load_com(blk, filename, NULL, 0, NULL); 5.1150 - if (ret < 0) { 5.1151 - set_error(r, 0x02); /* file not found */ 5.1152 - } else { 5.1153 - cur_psp = ret; 5.1154 - set_error(r, 0); 5.1155 - } 5.1156 - } 5.1157 - break; 5.1158 - case 0x4c: /* exit with return code */ 5.1159 - exit(r->eax & 0xff); 5.1160 - break; 5.1161 - case 0x50: /* set PSP address */ 5.1162 -#ifdef DUMP_INT21 5.1163 - printf("int21: set PSP: 0x%04x\n", (uint16_t)r->ebx); 5.1164 -#endif 5.1165 - cur_psp = r->ebx; 5.1166 - break; 5.1167 - case 0x51: /* get PSP address */ 5.1168 -#ifdef DUMP_INT21 5.1169 - printf("int21: get PSP: ret=0x%04x\n", cur_psp); 5.1170 -#endif 5.1171 - r->ebx = (r->ebx & ~0xffff) | cur_psp; 5.1172 - break; 5.1173 - case 0x55: /* create child PSP */ 5.1174 - { 5.1175 - uint8_t *psp_ptr; 5.1176 -#ifdef DUMP_INT21 5.1177 - printf("int21: create child PSP: psp=0x%04x last_seg=0x%04x\n", 5.1178 - (uint16_t)r->edx, (uint16_t)r->esi); 5.1179 -#endif 5.1180 - psp_ptr = seg_to_linear(r->edx & 0xffff, 0); 5.1181 - memset(psp_ptr, 0, 0x80); 5.1182 - psp_ptr[0] = 0xcd; /* int $0x20 */ 5.1183 - psp_ptr[1] = 0x20; 5.1184 - *(uint16_t *)(psp_ptr + 2) = r->esi; 5.1185 - r->eax = (r->eax & ~0xff); 5.1186 - } 5.1187 - break; 5.1188 - default: 5.1189 - unsupported: 5.1190 - unsupported_function(r, 0x21, ah); 5.1191 - } 5.1192 -} 5.1193 - 5.1194 -void do_int29(struct vm86_regs *r) 5.1195 -{ 5.1196 - uint8_t c = r->eax; 5.1197 - write(1, &c, 1); 5.1198 -} 5.1199 - 5.1200 -void raise_interrupt(int number) 5.1201 -{ 5.1202 - if (* (uint32_t *) seg_to_linear(0, number * 4) == 0) 5.1203 - return; 5.1204 - // FIXME VM86_SIGNAL 5.1205 -} 5.1206 - 5.1207 -void biosclock() 5.1208 -{ 5.1209 - uint32_t *timer = (uint32_t *) seg_to_linear(0, 0x46C); 5.1210 - ++*timer; 5.1211 - raise_interrupt(8); 5.1212 - raise_interrupt(0x1C); 5.1213 -} 5.1214 - 5.1215 -int main(int argc, char **argv) 5.1216 -{ 5.1217 - uint8_t *vm86_mem; 5.1218 - const char *filename; 5.1219 - int ret; 5.1220 - uint32_t file_size; 5.1221 - struct sigaction sa; 5.1222 - struct itimerval timerval; 5.1223 - struct vm86plus_struct ctx; 5.1224 - struct vm86_regs *r; 5.1225 - ExecParamBlock blk1, *blk = &blk1; 5.1226 - 5.1227 - if (argc < 2) 5.1228 - usage(); 5.1229 - filename = argv[1]; 5.1230 - 5.1231 - vm86_mem = mmap((void *)0x00000000, 0x110000, 5.1232 - PROT_WRITE | PROT_READ | PROT_EXEC, 5.1233 - MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); 5.1234 - if (vm86_mem == MAP_FAILED) { 5.1235 - perror("mmap"); 5.1236 - exit(1); 5.1237 - } 5.1238 - 5.1239 - memset(&ctx, 0, sizeof(ctx)); 5.1240 - r = &ctx.regs; 5.1241 - set_bit((uint8_t *)&ctx.int_revectored, 0x10); 5.1242 - set_bit((uint8_t *)&ctx.int_revectored, 0x13); 5.1243 - set_bit((uint8_t *)&ctx.int_revectored, 0x15); 5.1244 - set_bit((uint8_t *)&ctx.int_revectored, 0x16); 5.1245 - set_bit((uint8_t *)&ctx.int_revectored, 0x1a); 5.1246 - set_bit((uint8_t *)&ctx.int_revectored, 0x20); 5.1247 - set_bit((uint8_t *)&ctx.int_revectored, 0x21); 5.1248 - set_bit((uint8_t *)&ctx.int_revectored, 0x29); 5.1249 - 5.1250 - dos_init(); 5.1251 - 5.1252 - if (strstr(filename,".com") || strstr(filename,".exe") || 5.1253 - strstr(filename,".COM") || strstr(filename,".EXE")) { 5.1254 - ret = load_com(blk, filename, &file_size, argc, argv); 5.1255 - if (ret < 0) { 5.1256 - perror(filename); 5.1257 - exit(1); 5.1258 - } 5.1259 - cur_psp = ret; 5.1260 - 5.1261 - /* init basic registers */ 5.1262 - r->eip = blk->ip; 5.1263 - r->esp = blk->sp + 2; /* pop ax value */ 5.1264 - r->cs = blk->cs; 5.1265 - r->ss = blk->ss; 5.1266 - r->ds = cur_psp; 5.1267 - r->es = cur_psp; 5.1268 - r->eflags = VIF_MASK; 5.1269 - 5.1270 - /* the value of these registers seem to be assumed by pi_10.com */ 5.1271 - r->esi = 0x100; 5.1272 -#if 0 5.1273 - r->ebx = file_size >> 16; 5.1274 - r->ecx = file_size & 0xffff; 5.1275 -#else 5.1276 - r->ecx = 0xff; 5.1277 -#endif 5.1278 - r->ebp = 0x0900; 5.1279 - r->edi = 0xfffe; 5.1280 - } 5.1281 - else { 5.1282 - if (load_boot(filename, r) < 0) { 5.1283 - if (errno) 5.1284 - perror(filename); 5.1285 - exit(1); 5.1286 - } 5.1287 - } 5.1288 - 5.1289 - sa.sa_handler = biosclock; 5.1290 - sigemptyset(&sa.sa_mask); 5.1291 - sa.sa_flags = SA_RESTART; 5.1292 - if (sigaction(SIGALRM, &sa, 0) == 0) { 5.1293 - timerval.it_interval.tv_sec = timerval.it_value.tv_sec = 0; 5.1294 - timerval.it_interval.tv_usec = timerval.it_value.tv_usec = 10000000 / 182; 5.1295 - setitimer (ITIMER_REAL, &timerval, NULL); 5.1296 - } 5.1297 - 5.1298 - for(;;) { 5.1299 - ret = vm86(VM86_ENTER, &ctx); 5.1300 - switch(VM86_TYPE(ret)) { 5.1301 - case VM86_INTx: 5.1302 - { 5.1303 - int int_num; 5.1304 - 5.1305 - int_num = VM86_ARG(ret); 5.1306 - switch(int_num) { 5.1307 - case 0x10: 5.1308 - do_int10(r); 5.1309 - break; 5.1310 - case 0x13: 5.1311 - do_int13(r); 5.1312 - break; 5.1313 - case 0x15: 5.1314 - do_int15(r); 5.1315 - break; 5.1316 - case 0x16: 5.1317 - do_int16(r); 5.1318 - break; 5.1319 - case 0x1a: 5.1320 - do_int1a(r); 5.1321 - break; 5.1322 - case 0x20: 5.1323 - do_int20(r); 5.1324 - break; 5.1325 - case 0x21: 5.1326 - do_int21(r); 5.1327 - break; 5.1328 - case 0x29: 5.1329 - do_int29(r); 5.1330 - break; 5.1331 - default: 5.1332 - fprintf(stderr, "unsupported int 0x%02x\n", int_num); 5.1333 - dump_regs(&ctx.regs); 5.1334 - break; 5.1335 - } 5.1336 - } 5.1337 - break; 5.1338 - case VM86_SIGNAL: 5.1339 - /* a signal came, we just ignore that */ 5.1340 - break; 5.1341 - case VM86_STI: 5.1342 - break; 5.1343 - case VM86_TRAP: 5.1344 - /* just executes the interruption */ 5.1345 - { 5.1346 - uint16_t *int_vector; 5.1347 - uint32_t eflags; 5.1348 - 5.1349 - eflags = r->eflags & ~IF_MASK; 5.1350 - if (r->eflags & VIF_MASK) 5.1351 - eflags |= IF_MASK; 5.1352 - pushw(r, eflags); 5.1353 - pushw(r, r->cs); 5.1354 - pushw(r, r->eip); 5.1355 - int_vector = (uint16_t *)seg_to_linear(0, VM86_ARG(ret) * 4); 5.1356 - r->eip = int_vector[0]; 5.1357 - r->cs = int_vector[1]; 5.1358 - r->eflags &= ~(VIF_MASK | TF_MASK | AC_MASK); 5.1359 - } 5.1360 - break; 5.1361 - default: 5.1362 - fprintf(stderr, "unhandled vm86 return code (0x%x)\n", ret); 5.1363 - dump_regs(&ctx.regs); 5.1364 - exit(1); 5.1365 - } 5.1366 - } 5.1367 -}