# HG changeset patch # User Pascal Bellard # Date 1329552134 -3600 # Node ID e5a37b6b4d0a9715220e6be97cace918150fe1d4 # Parent 0205643e403f58c05b9c00664d30c12435e9b27d remove runcom diff -r 0205643e403f -r e5a37b6b4d0a runcom/receipt --- a/runcom/receipt Sun Feb 12 11:28:15 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -# SliTaz package receipt. - -PACKAGE="runcom" -VERSION="1.0" -CATEGORY="system-tools" -SHORT_DESC="DOS .com binary format support" -MAINTAINER="dev@slitaz.org" -WEB_SITE="http://bellard.org/jslinux" - -# Rules to configure and make the package. -compile_rules() -{ - mkdir -p $src - cd $src - #tarball=$(wget -O - $WEB_SITE/tech.html | \ - # sed '/linuxstart/!d;s/.*href="\([^"]*\)".*/\1/') - #wget $WEB_SITE/$tarball - #tar xzf $tarball - mkdir -p $DESTDIR/usr/bin - cc -o $DESTDIR/usr/bin/runcom $stuff/runcom.c - cc -o $src/debug.o -Wa,-a=$src/debug.lst -c $stuff/debug.S - objcopy -O binary $src/debug.o $DESTDIR/usr/bin/debug.bin - cp $stuff/debug.com $DESTDIR/usr/bin - chmod +x $DESTDIR/usr/bin/debug.* -} - -# Rules to gen a SliTaz package suitable for Tazpkg. -genpkg_rules() -{ - cp -a $_pkg/* $fs -} - -# Post install command for Tazpkg. -post_install() -{ - fmt="binfmt_misc" - proc="/proc/sys/fs/binfmt_misc" - bin=":BOOTBIN:E::bin::/usr/bin/runcom:" - com=":DOSCOM:E::com::/usr/bin/runcom:" - rc="$1/etc/init.d/local.sh" - grep -q "$com" $rc || cat >> $rc <$proc/register -echo "$com" >$proc/register -EOT - [ -n "$1" ] && return - [ ! -e $proc/register ] && modprobe $fmt && mount -t $fmt $fmt $proc - echo "$bin" >$proc/register - echo "$com" >$proc/register -} - -# Pre remove command for Tazpkg. -pre_remove() -{ - echo -1 > $1/proc/sys/fs/binfmt_misc/BOOTBIN - echo -1 > $1/proc/sys/fs/binfmt_misc/DOSCOM - sed -i '/binfmt_misc/{NN;/DOSCOM:E::com/d}' $1/etc/init.d/local.sh -} diff -r 0205643e403f -r e5a37b6b4d0a runcom/stuff/debug.S --- a/runcom/stuff/debug.S Sun Feb 12 11:28:15 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,493 +0,0 @@ -// Usage: -// -// f DX:CX load one CHS sector to 0000:7C00 -// t trace one step -// g
go to adrs -// d
display 16 bytes, CR for next 16 bytes... -// e
... enter memory byte/word/dword -// m self move -// + default segment offset -// -// Example: -// m 0FC0 move debugger to 0FC0:0000 0FC0:01FF -// f 1 read floppy boot sector to 0000:7C00 -// f 80 1 read hard disk master boot sector to 0000:7C00 -// g 7C0E ... - -#define REGS32 28 bytes display FS, GS and 32 bits datas for AX..DI -#define ADJESDI 16 bytes add segment overflow support for e and d -#define ASCIIDUMP 20 bytes display hexa and ascii datas -#define INPUTBUFFER 3 bytes overload init code with a 32+ bytes input buffer - -.macro pushib val - .byte 0x6A, \val-_start -.endm - -#ifdef REGS32 -#define SEGREGSZ 10 -#define REGSZ 32 -#define USER_SP REGSZ+SEGREGSZ-28(%bp) -#define FIXSP 14 -#else -#define SEGREGSZ 6 -#define REGSZ 16 -#define USER_SP REGSZ+SEGREGSZ-14(%bp) -#define FIXSP 10 -#endif -#define USER_FLAGS REGSZ+SEGREGSZ+4(%bp) -#define USER_FLAGS_HIGH REGSZ+SEGREGSZ+5(%bp) -#define USER_IP REGSZ+SEGREGSZ(%bp) -#define USER_CS REGSZ+SEGREGSZ+2(%bp) -#define USER_CSIP REGSZ+SEGREGSZ(%bp) - -#ifdef INPUTBUFFER -//#define ABS(x) (x-(setvectors-_start)) -#define ABS(x) (x-32) -#else -#define ABS(x) (x) -#endif -.macro initcode - movw $0x0FC0, %di # move (and jump) to 0FC0:0000 - subw $_startz-_start, USER_IP - movw USER_IP, %ax - shrw $4, %ax # _start MUST be aligned on paragraph - addw USER_CS, %ax # normalize %cs to have _start=0 - movw %ax, %ds -.endm - - .text - .code16 - .org 0 - - .globl _start -_start: - pushf - pushw %cs - stc - call init # the start code will be overwritten by the input buffer -_startz: - -#ifdef INPUTBUFFER -isinit: - initcode - addw $FIXSP, USER_SP # adjust SP with [FLAGS CS IP DS ES [FS GS]] size - pushib setvectors - jmp moveself -#endif - -setvectors: - xorw %si, %si # set interrupt vectors in 0 segment - movw %si, %ds - movb $0x7D, %cl # skip nmi -hooklp: # interrupts: 0=div0 1=step 2=nmi 3=brk 4=ov 5=bound 6=invalid - pushw %cs - pushib ABS(dbgstart) # set %cs:dbgstart - popl (%si) # to interrupt vector -skiphook: - lodsl # %si += 4 - shrb $1,%cl - jnc skiphook - jnz hooklp # note %cx will be cleared: SP will be untouched - decw (3-7)*4(%si) # update int3 vector - jmp dbgstartz # registers are already pushed by startup code - -regs: - .ascii "ss" - .ascii "di" - .ascii "si" - .ascii "bp" - .ascii "sp" - .ascii "bx" - .ascii "dx" - .ascii "cx" - .ascii "ax" -#ifdef REGS32 - .ascii "gs" - .ascii "fs" -#endif - .ascii "es" - .ascii "ds" - .ascii "ip" - .ascii "cs" -# Bit Label Desciption -# --------------------------- -# 0 CF Carry flag -# 2 PF Parity flag -# 4 AF Auxiliary carry flag -# 6 ZF Zero flag -# 7 SF Sign flag -# 8 TF Trap flag -# 9 IF Interrupt enable flag -# 10 DF Direction flag -# 11 OF Overflow flag -#ifdef REGS32 - .ascii "odi|sz|a|p|c" # flags bits -#else - .ascii "oditsz?a?p c=" # flags bits -#endif -# 12-13 IOPL I/O Priviledge level -# 14 NT Nested task flag -# 16 RF Resume flag -# 17 VM Virtual 8086 mode flag -# 18 AC Alignment check flag (486+) -# 19 VIF Virutal interrupt flag -# 20 VIP Virtual interrupt pending flag -# 21 ID ID flag - -#ifdef INPUTBUFFER -ismove: - pushw %ax -moveself: - popw %si -#else -isinit: - initcode -ismove: - xorw %si, %si -#endif - movw %di, %es # move code to %di:0 - pushw %di -#ifdef INPUTBUFFER - xorw %di, %di # and jmp into (%di:setvectors) with retf -#else - movw $setvectors, %di # and jmp into (%di:setvectors) with retf - movw %di, %si -#endif - movw $_end-setvectors, %cx - pushw %di - rep movsb - retf - -int3: - .byte 0x68 # push $0x086A OV UP DI NT PL ZR - NA - PO - NC -# interrupt entry point: the registers [FLAGS CS IP] are already pushed -dbgstart: - .byte 0x6A, 0x08 # push $0x08 NV UP DI NT PL NZ - NA - PO - NC - popf -init: - pushw %ds - pushw %es -#ifdef REGS32 - pushw %fs - pushw %gs - pushal # [FLAGS CS IP DS ES FS GS] EAX ECX EDX EBX ESP EBP ESI EDI [SS] -#else - pushaw # [FLAGS CS IP DS ES] AX CX DX BX SP BP SI DI [SS] -#endif - pushw %ss - movw %sp, %bp -#ifndef INPUTBUFFER - pushf - addw $FIXSP, USER_SP # adjust SP with [FLAGS CS IP DS ES [FS GS]] size - popf -#endif - jc isinit - jnz notint3 - decw USER_IP - lesw USER_CSIP, %di -#define OPCODE_BRK 0xCC - .byte 0xB0 # movb $IM, %al -break: - .byte 0xCC - stosb -notint3: -#ifdef INPUTBUFFER - addw $FIXSP, USER_SP # adjust SP with [FLAGS CS IP DS ES [FS GS]] size -#endif -dbgstartz: -dbgregslp: - pushw %cs - popw %ds - movw $ABS(regs), %si -#ifdef REGS32 - subw %si, %bp - movw $15, %cx -#else - movw $13, %cx -#endif -regslp: - call putreg # display register name and value - loop regslp -#ifdef REGS32 - movw (%bp,%si), %dx # get flags -#else - movw USER_FLAGS, %dx - pushw %si - stc # add trailing = -#endif - movb $13, %cl - rcrw %cl, %dx -nextbit: - lodsb - shlw $1, %dx -#ifdef REGS32 - jnc skipflag - cmpb $'|', %al # remove system flags - je skipflag - call dbgputc -skipflag: -#else - call dbgputcbit # display active flags bits -#endif - loop nextbit -#ifdef REGS32 - movw %sp, %bp -#else - popw %si - movb $8, %cl -stacklp: - lodsw # si += 2 - call putr16 # display flags and the beginning of the stack - loop stacklp -#endif - call getline - lodsb - xchgw %ax, %di - call getval - .byte 0x81, 0xC3 # addw $0, %bx -offset_value: - .word 0 - movw %bx, %es - xchgw %ax, %di - subb $'m', %al - je ismove - subb $'+'-'m', %al - jne not_offset - movw %di, ABS(offset_value) -not_offset: - orb $1, USER_FLAGS_HIGH # set TF - subb $'t'-'+', %al - je done - subb $'d'-'t', %al - xchgw %ax, %cx - jcxz dump # 'd' ? - loop noenter # 'e' ? -nextval: - call getval - jcxz dbgregslp - xchgb %dl, %dh -mextmsb: - stosb - xchgw %ax, %dx - xchgb %al, %dh -#ifdef ADJESDI - call adjustESDI -#endif - decw %cx - loopne mextmsb - jmp nextval -noenter: - loop not_floppy_load # f DX:CX ? - movw %es, %dx - movw %cx, %es - movw %di, %cx - movw $0x0201, %ax - movw $0x7C00, %bx - pushw %bx - int $0x13 - popw %di -godbgregslpifc: - jc dbgregslp -dump: - movw %es, %ax - call putax - movw %di, %ax - call putax - movw $16, %cx -dhex: - movb %es:(%di), %ah -#ifdef ASCIIDUMP - movb %ah, (%si) - incw %si -#endif -#ifdef ADJESDI - call incESDI -#else - incw %di -#endif -#ifdef REGS32 - movb $0x30, %dh # the data has 2 digits -#else - movb $0x01, %dh # the data has 2 digits -#endif - call putx - loop dhex -#ifdef ASCIIDUMP - movb $16, %cl - subw %cx, %si -dascii: - lodsb - cmpb $0x7F, %al - jnc skipascii - cmpb $0x20, %al - cmc -skipascii: - call dbgputcbit - loop dascii -#endif - call dbgputcr - int $0x16 - cmpb $13, %al - je dump -notdump: -not_floppy_load: - stc - loop godbgregslpifc # g ? -isgo: - andb $0xfe, USER_FLAGS_HIGH # clear TF - xchgw %ax, %cx - jcxz done -setbreak: - movb $OPCODE_BRK, %al - xchgb %al, %es:(%di) - movb %al, ABS(break) -done: - popw %ax # %ss -#ifdef REGS32 - popal - popw %gs - popw %fs -#else - popaw -#endif - popw %es - popw %ds - iret - -#ifdef ADJESDI -adjustESDI: - decw %di -incESDI: - incw %di - jnz esok - pushw %es - addb $0x10,-3(%bp) - popw %es -esok: - ret -#endif - -putreg: - call dbgput2c - movb $'=', %al - call dbgputc -putr16: -#ifdef REGS32 - movl -2(%bp,%si), %eax - movw $0x3FC0, %dx # check bits 7..14 - shrw %cl, %dx -putax: - movb $0xF0, %dh # the data has 4 digits - jnc putx # 16 bits register ? - incw %bp # a 32 bits register, not 16 bits - incw %bp - movb $0xFF, %dh # the data has 8 digits - jmp putx -putxlp: -#else -# movw _start-ABS(regs)-2(%bp,%si), %ax - .byte 0x8b, 0x42, _start-ABS(regs)-2 -putax: - movb $0x07, %dh # the data has 4 digits -putx: -putxlp: - rolw $4, %ax -#endif - pushw %ax - andb $0xf, %al - addb $0x90, %al - daa - adcb $0x40, %al - daa - call dbgputc - popw %ax -#ifdef REGS32 -putx: - roll $4, %eax -#endif - shrb $1, %dh - jc putxlp -#ifdef REGS32 - jnz putx -#endif -dbgputcbit: - jc dbgputc - mov $0x20, %al -dbgputc: - movw $7, %bx - mov $0xE, %ah - int $0x10 - xchgw %ax, %bx -# clc # for putax - ret - -# get value in DX:AX, BX is segment CX is digits count. -getval: - xorw %ax, %ax - xorw %bx, %bx - xorw %cx, %cx -getvalz: - xchgw %ax, %bx - cwd - decw %cx -isx: - shll $4, %edx - orb %al, %dl - incw %cx -gotspc: -getvallp: - lodsb - cmpb $0x20, %al # heat heading spaces - jne notspc - jcxz gotspc -notspc: - subb $'0', %al - cmpb $10, %al # in 0..9 ? - jb isx - subb $'a'-'0'-10, %al - cmpb $16, %al # in a..f ? - jb isx - cmpb $':'-'a'+10, %al - pushl %edx - popw %ax - popw %dx - je getvalz # store segment in %bx - pushw %dx - shlw $12, %dx - orw %dx, %bx - popw %dx - ret - -getline: - call dbgputcr -getlinebs: - cmpw $ABS(buffer), %si - je getc - decw %si -getlinelp: - call dbgputc -getc: - int $0x16 - cmpb $8, %al - je getlinebs - orb $0x20, %al - movb %al, (%si) - inc %si - cmpb $0x2D, %al - jne getlinelp -dbgputcr: - movw $ABS(crlf), %si -dbgput2c: - call dbgput1c -dbgput1c: - lodsb - jmp dbgputc - -crlf: - .byte 13,10 -_end: -buffer: - - .org 510 - .byte 0x55, 0xAA - diff -r 0205643e403f -r e5a37b6b4d0a runcom/stuff/debug.com Binary file runcom/stuff/debug.com has changed diff -r 0205643e403f -r e5a37b6b4d0a runcom/stuff/debug8086.S --- a/runcom/stuff/debug8086.S Sun Feb 12 11:28:15 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,477 +0,0 @@ -// Usage: -// -// f DX:CX load one CHS sector to 0000:7C00 -// t trace one step -// g
go to adrs -// d
display 16 bytes, CR for next 16 bytes... -// e
... enter memory byte/word/dword -// m self move -// + default segment offset -// -// Example: -// m 0FC0 move debugger to 0FC0:0000 0FC0:01FF -// f 1 read floppy boot sector to 0000:7C00 -// f 80 1 read hard disk master boot sector to 0000:7C00 -// g 7C0E ... - -#define ADJESDI 16 bytes add segment overflow support for e and d -#define ASCIIDUMP 20 bytes display hexa and ascii datas -#define INPUTBUFFER 2 bytes overload init code with a 32+ bytes input buffer -//#define CPU186 -26 bytes 80186+ CPU - -.macro pusham - pushw %ax - pushw %cx - pushw %dx - pushw %bx - movw %sp, %bx - leaw 14(%bx), %bx # adjust SP with [FLAGS CS IP AX CX DX BX] size - pushw %bx # %sp - pushw %bp - pushw %si - pushw %di -.endm - -.macro popam - popw %di - popw %si - popw %bp - popw %ax # %sp - popw %bx - popw %dx - popw %cx - popw %ax -.endm - -#ifdef INPUTBUFFER -//#define ABS(x) (x-(setvectors-_start)) -#define ABS(x) (x-30) -#else -#define ABS(x) (x) -#endif - -#define SEGREGSZ 6 -#define REGSZ 16 -#define USER_SP REGSZ+SEGREGSZ-10(%bp) -#define USER_FLAGS REGSZ+SEGREGSZ+4(%bp) -#define USER_FLAGS_HIGH REGSZ+SEGREGSZ+5(%bp) -#define USER_IP REGSZ+SEGREGSZ(%bp) -#define USER_CS REGSZ+SEGREGSZ+2(%bp) -#define USER_CSIP REGSZ+SEGREGSZ(%bp) - -.macro initcode - movw $0x0FC0, %di # move (and jump) to 0FC0:0000 - subw $_startz-_start, USER_IP - movw USER_IP, %ax -#ifdef CPU186 - cld # ensure movsb will work - shrw $4, %ax # _start MUST be aligned on paragraph -#else - movb $4, %cl - shrw %cl, %ax # _start MUST be aligned on paragraph -#endif - addw USER_CS, %ax # normalize %cs to have _start=0 - movw %ax, %ds -.endm - .text - .code16 -#ifdef CPU186 - .arch i186 -#else - .arch i8086 -#endif - .org 0 - - .globl _start -_start: - pushf - pushw %cs - stc - call init # the start code will be overwritten by the input buffer -_startz: - -#ifdef INPUTBUFFER -isinit: - initcode - movw $setvectors, %si - jmp moveself -#endif - -setvectors: - xorw %si, %si # set interrupt vectors in 0 segment - movw %si, %ds - movb $0xF9, %ch # skip nmi -hooklp: # interrupts: 0=div0 1=step 2=nmi 3=brk 4=ov 5=bound 6=invalid - movw $ABS(dbgstart), (%si) # set %cs:dbgstart - lodsw # %si += 2 - movw %cs, (%si) # to interrupt vector -skiphook: - lodsw # %si += 2 - shrb $1,%ch - jnc skiphook - jnz hooklp # note %cx will be cleared: SP will be untouched -#ifdef CPU186 - decw (3-7)*4(%si) # update int3 vector -#else - movb $ABS(int3), (3-7)*4(%si) # update int3 vector -#endif - jmp dbgstartz # registers are already pushed by startup code - -regs: - .ascii "ss" - .ascii "es" - .ascii "ds" - .ascii "di" - .ascii "si" - .ascii "bp" - .ascii "sp" - .ascii "bx" - .ascii "dx" - .ascii "cx" - .ascii "ax" - .ascii "ip" - .ascii "cs" -# Bit Label Desciption -# --------------------------- -# 0 CF Carry flag -# 2 PF Parity flag -# 4 AF Auxiliary carry flag -# 6 ZF Zero flag -# 7 SF Sign flag -# 8 TF Trap flag -# 9 IF Interrupt enable flag -# 10 DF Direction flag -# 11 OF Overflow flag - .ascii "oditsz?a?p c=" # flags bits - -int3: -#ifdef CPU186 - .byte 0x68 # push $0x086A OV UP DI NT PL ZR - NA - PO - NC -# interrupt entry point: the registers [FLAGS CS IP] are already pushed -dbgstart: - .byte 0x6A, 0x08 # push $0x08 NV UP DI NT PL NZ - NA - PO - NC - popf -init: - pushaw # [FLAGS CS IP] AX CX DX BX SP BP SI DI [DS ES SS] -#else - stc - .byte 0x73 # jnc -# interrupt entry point: the registers [FLAGS CS IP] are already pushed -dbgstart: - clc - pushw %ax - sbbw %ax,%ax # copy CF to SF - clc - popw %ax -init: - cld # ensure movsb will work - pusham # [FLAGS CS IP] AX CX DX BX SP BP SI DI [DS ES SS] -#endif - pushw %ds - pushw %es - pushw %ss - movw %sp, %bp -#ifdef CPU186 - pushf - addw $6, USER_SP # adjust SP with [FLAGS CS IP] size - popf -#endif - jc isinit - jns notint3 - decw USER_IP - lesw USER_CSIP, %di -#define OPCODE_BRK 0xCC - .byte 0xB0 # movb $IM, %al -break: - .byte 0xCC - stosb -notint3: -dbgstartz: -dbgregslp: - call getcmd - .byte 0x81, 0xC3 # addw $0, %bx -offset_value: - .word 0 - movw %bx, %es - xchgw %ax, %di - subb $'m', %al - jne isinotmove -#ifdef INPUTBUFFER -ismove: - xchgw %ax, %si -moveself: -#else -isinit: - jmp ismove - initcode -ismove: -#endif - movw %di, %es # move code to %di:0 - pushw %di -#ifdef INPUTBUFFER - xorw %di, %di # and jmp into (%di:setvectors) with retf -#else - movw $setvectors, %di # and jmp into (%di:setvectors) with retf - movw %di, %si -#endif - movw $_end-setvectors, %cx - pushw %di - rep movsb - retf - -isinotmove: - subb $'+'-'m', %al - jne not_offset - movw %di, ABS(offset_value) -not_offset: - orb $1, USER_FLAGS_HIGH # set TF - subb $'t'-'+', %al - je done - subb $'d'-'t', %al - xchgw %ax, %cx - jcxz dump # 'd' ? - loop noenter # 'e' ? -nextval: - call getval - jcxz dbgregslp - xchgb %dl, %dh -mextmsb: - stosb - xchgw %ax, %dx - xchgb %al, %dh -#ifdef ADJESDI - call adjustESDI -#endif - decw %cx - loopne mextmsb - jmp nextval -noenter: - loop not_floppy_load # f DX:CX ? - movw %es, %dx - movw %cx, %es - movw %di, %cx - movw $0x0201, %ax - movw $0x7C00, %bx - pushw %bx - int $0x13 - popw %di -godbgregslpifc: - jc dbgregslp -dump: - movw %es, %ax - call putax - movw %di, %ax - call putax - movw $16, %cx -dhex: - movb %es:(%di), %ah -#ifdef ASCIIDUMP - movb %ah, (%si) - incw %si -#endif -#ifdef ADJESDI - call incESDI -#else - incw %di -#endif - movb $0x01, %dh # the data has 2 digits - call putx - loop dhex -#ifdef ASCIIDUMP - movb $16, %cl - subw %cx, %si -dascii: - lodsb - cmpb $0x7F, %al - jnc skipascii - cmpb $0x20, %al - cmc -skipascii: - call dbgputcbit - loop dascii -#endif - call dbgputcr - int $0x16 - cmpb $13, %al - je dump -notdump: -not_floppy_load: - stc - loop godbgregslpifc # g ? -isgo: - andb $0xfe, USER_FLAGS_HIGH # clear TF - xchgw %ax, %cx - jcxz done -setbreak: - movb $OPCODE_BRK, %al - xchgb %al, %es:(%di) - movb %al, ABS(break) -done: - popw %ax # %ss - popw %es - popw %ds -#ifdef CPU186 - popaw -#else - popam -#endif - iret - -#ifdef ADJESDI -adjustESDI: - decw %di -incESDI: - incw %di - jnz esok - pushw %es - addb $0x10,-3(%bp) - popw %es -esok: - ret -#endif - -putreg: - call dbgput2c - movb $'=', %al - call dbgputc -putr16: -# movw _start-ABS(regs)-2(%bp,%si), %ax - .byte 0x8b, 0x42, _start-ABS(regs)-2 -putax: - movb $0x07, %dh # the data has 4 digits -putx: -putxlp: -#ifdef CPU186 - rolw $4, %ax -#else - pushw %cx - movb $4, %cl - rolw %cl, %ax - popw %cx -#endif - pushw %ax - andb $0xf, %al - addb $0x90, %al - daa - adcb $0x40, %al - daa - call dbgputc - popw %ax - shrb $1, %dh - jc putxlp -dbgputcbit: - jc dbgputc - mov $0x20, %al -dbgputc: - movw $7, %bx - mov $0xE, %ah - int $0x10 - xchgw %ax, %bx - ret - -getline: - movw $ABS(regs), %si - movw $13, %cx -regslp: - call putreg # display register name and value - loop regslp - movw USER_FLAGS, %dx - pushw %si - movb $13, %cl - stc # add trailing = - rcrw %cl, %dx -nextbit: - lodsb - shlw $1, %dx - call dbgputcbit # display active flags bits - loop nextbit - popw %si - movb $8, %cl -stacklp: - lodsw # si += 2 - call putr16 # display flags and the beginning of the stack - loop stacklp - call dbgputcr -getlinebs: - cmpw $ABS(buffer), %si - je getc - decw %si -getlinelp: - call dbgputc -getc: - int $0x16 - cmpb $8, %al - je getlinebs - orb $0x20, %al - movb %al, (%si) - inc %si - cmpb $0x2D, %al - jne getlinelp -dbgputcr: - movw $ABS(crlf), %si -dbgput2c: - call dbgput1c -dbgput1c: - lodsb - jmp dbgputc - -getcmd: - pushw %cs - popw %ds - call getline - lodsb - xchgw %ax, %di -# get value in DX:AX, BX is segment CX is digits count. -getval: - xorw %bx, %bx - xorw %cx, %cx -getvalz: - pushw %bx # save segment - xorw %bx, %bx - mul %bx # clear %dx:%ax - decw %cx -isx: - incw %cx - orb $0xE0, %dh -getvalbit: - shlw $1, %bx - rclw $1, %dx - jc getvalbit - orb %al, %bl -gotspc: - lodsb - cmpb $0x20, %al # space ? - jne notspc - jcxz gotspc -notspc: - sub $'0', %al - cmpb $10, %al # in 0..9 ? - jb isx - sub $'a'-'0'-10, %al - cmpb $16, %al # in a..f ? - jb isx - cmpb $':'-'a'+10, %al - popw %ax - je getvalz # store segment in %bx - xchgw %ax, %bx - pushw %dx -#ifdef CPU186 - shlw $12, %dx -#else - pushw %cx - movb $12, %cl - shlw %cl, %dx - popw %cx -#endif - addw %dx, %bx - popw %dx - ret - -crlf: - .byte 13,10 -_end: -buffer: - - .org 510 - .byte 0x55, 0xAA - diff -r 0205643e403f -r e5a37b6b4d0a runcom/stuff/runcom.c --- a/runcom/stuff/runcom.c Sun Feb 12 11:28:15 2012 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1364 +0,0 @@ -/* - * Simple example of use of vm86: launch a basic .com DOS executable - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -//#define DUMP_INT21 - -static inline int vm86(int func, struct vm86plus_struct *v86) -{ - return syscall(__NR_vm86, func, v86); -} - -#define CF_MASK 0x00000001 -#define ZF_MASK 0x00000040 -#define TF_MASK 0x00000100 -#define IF_MASK 0x00000200 -#define DF_MASK 0x00000400 -#define IOPL_MASK 0x00003000 -#define NT_MASK 0x00004000 -#define RF_MASK 0x00010000 -#define VM_MASK 0x00020000 -#define AC_MASK 0x00040000 -#define VIF_MASK 0x00080000 -#define VIP_MASK 0x00100000 -#define ID_MASK 0x00200000 - -void usage(void) -{ - printf("runcom version 0.2-slitaz (c) 2003-2011 Fabrice Bellard\n" - "usage: runcom file.com [args...]\n" - "Run simple .com DOS executables (linux vm86 test mode)\n"); - exit(1); -} - -static inline void set_bit(uint8_t *a, unsigned int bit) -{ - a[bit / 8] |= (1 << (bit % 8)); -} - -static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg) -{ - return (uint8_t *)((seg << 4) + (reg & 0xffff)); -} - -static inline void pushw(struct vm86_regs *r, int val) -{ - r->esp = (r->esp & ~0xffff) | ((r->esp - 2) & 0xffff); - *(uint16_t *)seg_to_linear(r->ss, r->esp) = val; -} - -void dump_regs(struct vm86_regs *r) -{ - int i; - uint8_t *p8; - uint16_t *p16; - fprintf(stderr, - "EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n" - "ESI=%08lx EDI=%08lx EBP=%08lx ESP=%08lx\n" - "EIP=%08lx EFL=%08lx " - "CS=%04x DS=%04x ES=%04x SS=%04x FS=%04x GS=%04x\n[SP]", - r->eax, r->ebx, r->ecx, r->edx, r->esi, r->edi, r->ebp, r->esp, - r->eip, r->eflags, - r->cs, r->ds, r->es, r->ss, r->fs, r->gs); - for (p16 = (uint16_t *) seg_to_linear(r->ss, r->esp), i = 0; i < 15; i++) - fprintf(stderr," %04x", *p16++); - fprintf(stderr,"\n[IP]"); - for (p8 = seg_to_linear(r->cs, r->eip), i = 0; i < 25; i++) - fprintf(stderr," %02x", *p8++); - fprintf(stderr,"\n"); -} - -#define DOS_FD_MAX 256 -typedef struct { - int fd; /* -1 means closed */ -} DOSFile; - -DOSFile dos_files[DOS_FD_MAX]; -uint16_t cur_psp; - -void dos_init(void) -{ - int i; - for(i = 0; i < DOS_FD_MAX; i++) - dos_files[i].fd = (i < 3) ? i : -1; -} - -static inline void set_error(struct vm86_regs *r, int val) -{ - r->eflags &= ~CF_MASK; - if (val) { - r->eax = (r->eax & ~0xffff) | val; - r->eflags |= CF_MASK; - } -} -static DOSFile *get_file(int h) -{ - DOSFile *fh; - - if (h < DOS_FD_MAX) { - fh = &dos_files[h]; - if (fh->fd != -1) - return fh; - } - return NULL; -} - -/* return -1 if error */ -static int get_new_handle(void) -{ - DOSFile *fh; - int i; - - for(i = 0; i < DOS_FD_MAX; i++) { - fh = &dos_files[i]; - if (fh->fd == -1) - return i; - } - return -1; -} - -static char *get_filename1(struct vm86_regs *r, char *buf, int buf_size, - uint16_t seg, uint16_t offset) -{ - char *q; - int c; - q = buf; - for(;;) { - c = *seg_to_linear(seg, offset); - if (c == 0) - break; - if (q >= buf + buf_size - 1) - break; - c = tolower(c); - if (c == '\\') - c = '/'; - *q++ = c; - offset++; - } - *q = '\0'; - return buf; -} - -static char *get_filename(struct vm86_regs *r, char *buf, int buf_size) -{ - return get_filename1(r, buf, buf_size, r->ds, r->edx & 0xffff); -} - -typedef struct __attribute__((packed)) { - uint8_t drive_num; - uint8_t file_name[8]; - uint8_t file_ext[3]; - uint16_t current_block; - uint16_t logical_record_size; - uint32_t file_size; - uint16_t date; - uint16_t time; - uint8_t reserved[8]; - uint8_t record_in_block; - uint32_t record_num; -} FCB; - -typedef struct __attribute__((packed)) { - uint16_t environ; - uint16_t cmdtail_off; - uint16_t cmdtail_seg; - uint32_t fcb1; - uint32_t fcb2; - uint16_t sp, ss; - uint16_t ip, cs; -} ExecParamBlock; - -typedef struct MemBlock { - struct MemBlock *next; - uint16_t seg; - uint16_t size; /* in paragraphs */ -} MemBlock; - -/* first allocated paragraph */ -MemBlock *first_mem_block = NULL; - -#define MEM_START 0x1000 -#define MEM_END 0xa000 - -/* return -1 if error */ -int mem_malloc(int size, int *pmax_size) -{ - MemBlock *m, **pm; - int seg_free, seg; - - /* XXX: this is totally inefficient, but we have only 1 or 2 - blocks ! */ - seg_free = MEM_START; - for(pm = &first_mem_block; *pm != NULL; pm = &(*pm)->next) { - m = *pm; - seg = m->seg + m->size; - if (seg > seg_free) - seg_free = seg; - } - if ((seg_free + size) > MEM_END) - return -1; - if (pmax_size) - *pmax_size = MEM_END - seg_free; - /* add at the end */ - m = malloc(sizeof(MemBlock)); - *pm = m; - m->next = NULL; - m->seg = seg_free; - m->size = size; -#ifdef DUMP_INT21 - printf("mem_malloc size=0x%04x: 0x%04x\n", size, seg_free); -#endif - return seg_free; -} - -/* return -1 if error */ -int mem_free(int seg) -{ - MemBlock *m, **pm; - for(pm = &first_mem_block; *pm != NULL; pm = &(*pm)->next) { - m = *pm; - if (m->seg == seg) { - *pm = m->next; - free(m); - return 0; - } - } - return -1; -} - -/* return -1 if error or the maxmium size */ -int mem_resize(int seg, int new_size) -{ - MemBlock *m, **pm, *m1; - int max_size; - - for(pm = &first_mem_block; *pm != NULL; pm = &(*pm)->next) { - m = *pm; - if (m->seg == seg) { - m1 = m->next; - if (!m1) - max_size = MEM_END - m->seg; - else - max_size = m1->seg - m->seg; - if (new_size > max_size) - return -1; - m->size = new_size; - return max_size; - } - } - return -1; -} - -int load_boot(const char *filename, struct vm86_regs *r) -{ - int fd, ret; - - /* load the boot sector */ - fd = open(filename, O_RDONLY); - if (fd >= 0) { - *seg_to_linear(0x0, 0x7dff) = 0; - r->eax = 0x200; - r->ebx = r->esp = r->eip = 0x7c00; - r->ecx = 1; - r->esi = r->edi = r->ebp = - r->edx = 0; /* floppy disk */ - r->cs = r->ss = r->ds = r->es = 0; - r->eflags = VIF_MASK; - ret = read(fd, seg_to_linear(0x0, 0x7c00), 0x200); - if (lseek(fd, 0, SEEK_END) > 4*1024*1024) - r->edx = 0x80; /* hard disk */ - close(fd); - if (ret != 0x200 || - *seg_to_linear(0x0, 0x7dfe) != 0x55 || - *seg_to_linear(0x0, 0x7dff) != 0xaa) { - fprintf(stderr,"No boot sector.\n"); - fd = -1; - } - } - return fd; -} - -/* return the PSP or -1 if error */ -int load_exe(ExecParamBlock *blk, const char *filename, - int psp, uint32_t *pfile_size) -{ - int fd, size, base; - struct { - uint16_t signature; // 0x5A4D 'MZ' - uint16_t bytes_in_last_block; - uint16_t blocks_in_file; - uint16_t num_relocs; - uint16_t header_paragraphs; // Size of header - uint16_t min_extra_paragraphs; // BSS size - uint16_t max_extra_paragraphs; - uint16_t ss; // Initial (relative) SS value - uint16_t sp; // Initial SP value - uint16_t checksum; - uint16_t ip; // Initial IP value - uint16_t cs; // Initial (relative) CS value - uint16_t reloc_table_offset; - uint16_t overlay_number; - } header; - struct { - uint16_t offset; - uint16_t segment; - } rel; - - /* load the MSDOS .exe executable */ - fd = open(filename, O_RDONLY); - if (fd < 0) { - return -1; - } - if (read(fd, &header, sizeof(header)) != sizeof(header)) { - close(fd); - return -1; - } - - memset(seg_to_linear(psp, 0x100), 0, 65536 - 0x100); - - size = (header.blocks_in_file * 512) - (header.header_paragraphs * 16) + - (header.bytes_in_last_block ? header.bytes_in_last_block - 512 : 0); - header.min_extra_paragraphs += (size-1)/16; - - /* address of last segment allocated */ - *(uint16_t *)seg_to_linear(psp, 2) = psp + header.min_extra_paragraphs; - - if (pfile_size) - *pfile_size = size; - - if (mem_resize(psp, header.min_extra_paragraphs) < 0 || - lseek(fd, header.header_paragraphs * 16, SEEK_SET) < 0 || - read(fd, seg_to_linear(psp, 0x100), size) != size || - lseek(fd, header.reloc_table_offset, SEEK_SET) < 0) { - close(fd); - return -1; - } - - base = psp + 16; - while (header.num_relocs-- && read(fd, &rel, sizeof(rel)) == sizeof(rel)) - if (rel.segment != 0 || rel.offset != 0) - * (uint16_t *) seg_to_linear(base + rel.segment, rel.offset) += base; - close(fd); - - blk->cs = base + header.cs; - blk->ip = header.ip; - blk->ss = base + header.ss; - blk->sp = header.sp - 6; - - /* push return far address */ - *(uint16_t *)seg_to_linear(blk->ss, blk->sp + 4) = psp; - - return psp; -} - -/* return the PSP or -1 if error */ -int load_com(ExecParamBlock *blk, const char *filename, uint32_t *pfile_size, - int argc, char **argv) -{ - int psp, fd, ret; - - /* load the MSDOS .com executable */ - fd = open(filename, O_RDONLY); - if (fd < 0) { - return -1; - } - psp = mem_malloc(65536 / 16, NULL); - ret = read(fd, seg_to_linear(psp, 0x100), 65536 - 0x100); - close(fd); - if (ret <= 0) { - mem_free(psp); - return -1; - } - if (pfile_size) - *pfile_size = ret; - - /* reset the PSP */ - memset(seg_to_linear(psp, 0), 0, 0x100); - - *seg_to_linear(psp, 0) = 0xcd; /* int $0x20 */ - *seg_to_linear(psp, 1) = 0x20; - /* address of last segment allocated */ - *(uint16_t *)seg_to_linear(psp, 2) = psp + 0xfff; - - if (argc) { - int i, p; - char *s; - /* set the command line */ - p = 0x81; - for(i = 2; i < argc; i++) { - if (p >= 0xff) - break; - *seg_to_linear(psp, p++) = ' '; - s = argv[i]; - while (*s) { - if (p >= 0xff) - break; - *seg_to_linear(psp, p++) = *s++; - } - } - *seg_to_linear(psp, p) = '\r'; - *seg_to_linear(psp, 0x80) = p - 0x81; - } - else { - int len; - /* copy the command line */ - len = *seg_to_linear(blk->cmdtail_seg, blk->cmdtail_off); - memcpy(seg_to_linear(psp, 0x80), - seg_to_linear(blk->cmdtail_seg, blk->cmdtail_off), len + 2); - } - - blk->sp = 0xfffc; - blk->ip = 0x100; - blk->cs = blk->ss = psp; - - if (*(uint16_t *)seg_to_linear(psp, 0x100) == 0x5A4D) - psp = load_exe(blk, filename, psp, pfile_size); - - /* push ax value */ - *(uint16_t *)seg_to_linear(blk->ss, blk->sp) = 0; - /* push return address to 0 */ - *(uint16_t *)seg_to_linear(blk->ss, blk->sp + 2) = 0; - - return psp; -} - - -void unsupported_function(struct vm86_regs *r, uint8_t num, uint8_t ah) -{ - fprintf(stderr, "int 0x%02x: unsupported function 0x%02x\n", num, ah); - dump_regs(r); - set_error(r, 0x01); /* function number invalid */ -} - -/* Open hard disk image ./hd[0-7] / floppy image ./fd[0-7] or /dev/fd[0-7] */ -int open_disk(struct vm86_regs *r) -{ - int fd = -1, drive = r->edx & 0xff; - char filename[9], n = '0' + (drive & 7); - if (drive > 127) { - strcpy(filename,"hd0"); - filename[2] = n; - } - else { - strcpy(filename,"/dev/fd0"); - filename[7] = n; - fd = open(filename+5, O_RDONLY); - } - if (fd < 0) - fd = open(filename, O_RDONLY); - return fd; -} - - -void read_sectors(int fd, struct vm86_regs *r, int first_sector, - int sector_count, void *buffer) -{ - int drive = r->edx & 0xff; - r->eax &= ~0xff00; - r->eax |= 0x0400; /* sector not found */ - r->eflags |= CF_MASK; - if (fd >= 0) { - static struct stat st; - first_sector <<= 9; - sector_count <<= 9; - if (drive < 8 && fstat(fd, &st) == 0) { - static ino_t inodes[8]; - ino_t last = inodes[drive]; - inodes[drive] = st.st_ino; - if (last && last != st.st_ino) { - set_error(r, 0x0600); /* floppy disk swap */ - goto failed; - } - } - if (lseek(fd, first_sector, SEEK_CUR) >= 0 && - read(fd, buffer, sector_count) == sector_count) { - r->eax &= ~0xff00; - r->eflags &= ~CF_MASK; - } - failed: - close(fd); - } -} - -void do_int10(struct vm86_regs *r) -{ - uint8_t ah; - - ah = (r->eax >> 8); - switch(ah) { - case 0x0E: /* write char */ - { - uint8_t c = r->eax; - write(1, &c, 1); - } - break; - default: - unsupported_function(r, 0x10, ah); - } -} - -void do_int13(struct vm86_regs *r) -{ - uint8_t ah; - - ah = (r->eax >> 8); - switch(ah) { - case 0x00: /* reset disk */ - { - r->eax &= ~0xff00; /* success */ - r->eflags &= ~CF_MASK; - } - break; - case 0x02: /* read disk CHS */ - { - int fd, c, h, s, heads, sectors, cylinders; - long size; - fd = open_disk(r); - if (fd >= 0) { - size = lseek(fd, 0, SEEK_END) / 512; - if ((r->edx & 0xff) > 127) { - sectors = 63; - if (size % sectors) - sectors = 62; - if (size % sectors) - sectors = 32; - if (size % sectors) - sectors = 17; - if (size % sectors) - fd = -1; - size /= sectors; - for (heads = 256; size % heads; heads--); - cylinders = size / heads; - } - else { - int i; - heads = 1 + (size > 256*2); - cylinders = 40 * (1 + (size > 512*2)); - size /= heads; - for (i = 0; i < 5; i++) - if (size % (cylinders + i) == 0) break; - if (i == 5) - fd = -1; - cylinders += i; - sectors = size / cylinders; - } - } - c = ((r->ecx & 0xC0) << 2) | ((r->ecx >> 8) & 0xff); - h = (r->edx >> 8) & 0xff; - s = (r->ecx & 0x3f) -1; - if (fd < 0 || c >= cylinders || h >= heads || s >= sectors) { - set_error(r, 0x0400); /* sector not found */ - break; - } - read_sectors(fd, r, (((c * heads) + h) * sectors) + s, - r->eax & 0xff, seg_to_linear(r->es, r->ebx)); - } - break; - case 0x42: /* read disk LBA */ - { - uint16_t *packet = (uint16_t *) seg_to_linear(r->ds, r-> esi); - uint8_t *to = seg_to_linear(packet[3], packet[2]); - if ((packet[3] & packet[2]) == 0xffff) - to = * (uint8_t **) &packet[8]; - if (packet[0] != 0x0010 && packet[0] != 0x0018) - goto unsupported; - read_sectors(open_disk(r), r, * (uint32_t *) &packet[4], packet[1], to); - } - break; - default: - unsupported: - unsupported_function(r, 0x13, ah); - } -} - -void do_int15(struct vm86_regs *r) -{ - uint8_t ah; - - ah = (r->eax >> 8); - switch(ah) { - case 0x87: /* move memory */ - /* XXX */ - break; - default: - unsupported_function(r, 0x15, ah); - } -} - -void do_int16(struct vm86_regs *r) -{ - static uint16_t last_ax, hold_char; - struct termios termios_def, termios_raw; - uint8_t ah; - - ah = (r->eax >> 8); - tcgetattr(0, &termios_def); - termios_raw = termios_def; - cfmakeraw(&termios_raw); - tcsetattr(0, TCSADRAIN, &termios_raw); - switch(ah) { - case 0x01: /* test keyboard */ - { - int count; - r->eflags &= ~ZF_MASK; - if (hold_char) { - r->eax &= ~0xffff; - r->eax |= last_ax; - break; - } - if (ioctl(0, FIONREAD, &count) < 0 || count == 0) { - r->eflags |= ZF_MASK; - break; - } - hold_char = 2; - } - case 0x00: /* read keyboard */ - { - uint8_t c; - if (hold_char) - hold_char--; - read(0, &c, 1); - if (c == 3) { - tcsetattr(0, TCSADRAIN, &termios_def); - exit(0); - } - if (c == 10) - c = 13; - r->eax &= ~0xffff; - r->eax |= last_ax = c; - /* XXX ah = scan code */ - } - break; - default: - unsupported_function(r, 0x16, ah); - } - tcsetattr(0, TCSADRAIN, &termios_def); -} - -void do_int1a(struct vm86_regs *r) -{ - uint8_t ah; - - ah = (r->eax >> 8); - switch(ah) { - case 0x00: /* GET SYSTEM TIME */ - { - uint16_t *timer = (uint16_t *) seg_to_linear(0, 0x46C); - r->ecx &= ~0xffff; - r->ecx |= *timer++; - r->edx &= ~0xffff; - r->edx |= *timer; - r->eax &= ~0xff; - } - break; - default: - unsupported_function(r, 0x1a, ah); - } -} - -void do_int20(struct vm86_regs *r) -{ - /* terminate program */ - exit(0); -} - -void do_int21(struct vm86_regs *r) -{ - uint8_t ah; - - ah = (r->eax >> 8); - switch(ah) { - case 0x00: /* exit */ - exit(0); - case 0x02: /* write char */ - { - uint8_t c = r->edx; - write(1, &c, 1); - } - break; - case 0x09: /* write string */ - { - uint8_t c; - int offset; - offset = r->edx; - for(;;) { - c = *seg_to_linear(r->ds, offset); - if (c == '$') - break; - write(1, &c, 1); - offset++; - } - r->eax = (r->eax & ~0xff) | '$'; - } - break; - case 0x0a: /* buffered input */ - { - int max_len, cur_len, ret; - uint8_t ch; - uint16_t off; - - /* XXX: should use raw mode to avoid sending the CRLF to - the terminal */ - off = r->edx & 0xffff; - max_len = *seg_to_linear(r->ds, off); - cur_len = 0; - while (cur_len < max_len) { - ret = read(0, &ch, 1); - if (ret < 0) { - if (errno != EINTR && errno != EAGAIN) - break; - } else if (ret == 0) { - break; - } else { - if (ch == '\n') - break; - } - *seg_to_linear(r->ds, off + 2 + cur_len++) = ch; - } - *seg_to_linear(r->ds, off + 1) = cur_len; - *seg_to_linear(r->ds, off + 2 + cur_len) = '\r'; - } - break; - case 0x25: /* set interrupt vector */ - { - uint16_t *ptr; - ptr = (uint16_t *)seg_to_linear(0, (r->eax & 0xff) * 4); - ptr[0] = r->edx; - ptr[1] = r->ds; - } - break; - case 0x29: /* parse filename into FCB */ -#if 0 - /* not really needed */ - { - const uint8_t *p, *p_start; - uint8_t file[8], ext[3]; - FCB *fcb; - int file_len, ext_len, has_wildchars, c, drive_num; - - /* XXX: not complete at all */ - fcb = (FCB *)seg_to_linear(r->es, r->edi); - printf("ds=0x%x si=0x%lx\n", r->ds, r->esi); - p_start = (const uint8_t *)seg_to_linear(r->ds, r->esi); - - p = p_start; - has_wildchars = 0; - - /* drive */ - if (isalpha(p[0]) && p[1] == ':') { - drive_num = toupper(p[0]) - 'A' + 1; - p += 2; - } else { - drive_num = 0; - } - - /* filename */ - file_len = 0; - for(;;) { - c = *p; - if (!(c >= 33 && c <= 126)) - break; - if (c == '.') - break; - if (c == '*' || c == '?') - has_wildchars = 1; - if (file_len < 8) - file[file_len++] = c; - } - memset(file + file_len, ' ', 8 - file_len); - - /* extension */ - ext_len = 0; - if (*p == '.') { - for(;;) { - c = *p; - if (!(c >= 33 && c <= 126)) - break; - if (c == '*' || c == '?') - has_wildchars = 1; - ext[ext_len++] = c; - if (ext_len >= 3) - break; - } - } - memset(ext + ext_len, ' ', 3 - ext_len); - -#if 0 - { - printf("drive=%d file=%8s ext=%3s\n", - drive_num, file, ext); - } -#endif - if (drive_num == 0 && r->eax & (1 << 1)) { - /* keep drive */ - } else { - fcb->drive_num = drive_num; /* default drive */ - } - - if (file_len == 0 && r->eax & (1 << 2)) { - /* keep */ - } else { - memcpy(fcb->file_name, file, 8); - } - - if (ext_len == 0 && r->eax & (1 << 3)) { - /* keep */ - } else { - memcpy(fcb->file_ext, ext, 3); - } - r->eax = (r->eax & ~0xff) | has_wildchars; - r->esi = (r->esi & ~0xffff) | ((r->esi + (p - p_start)) & 0xffff); - } -#endif - break; - case 0x2A: /* get system date */ - { - time_t t = time(NULL); - struct tm *now=localtime(&t); - - r->ecx = now->tm_year; - r->edx = (now->tm_mon * 256) + now->tm_mday; - r->eax = now->tm_wday;; - } - break; - case 0x2C: /* get system time */ - { - time_t t = time(NULL); - struct tm *now=localtime(&t); - struct timeval tim; - - gettimeofday(&tim, NULL); - r->edx = (now->tm_hour * 256) + now->tm_min; - r->edx = (tim.tv_sec * 256) + tim.tv_usec/10000; - } - break; - case 0x30: /* get dos version */ - { - int major, minor, serial, oem; - /* XXX: return correct value for FreeDOS */ - major = 0x03; - minor = 0x31; - serial = 0x123456; - oem = 0x66; - r->eax = (r->eax & ~0xffff) | major | (minor << 8); - r->ecx = (r->ecx & ~0xffff) | (serial & 0xffff); - r->ebx = (r->ebx & ~0xffff) | (serial & 0xff) | (0x66 << 8); - } - break; - case 0x35: /* get interrupt vector */ - { - uint16_t *ptr; - ptr = (uint16_t *)seg_to_linear(0, (r->eax & 0xff) * 4); - r->ebx = (r->ebx & ~0xffff) | ptr[0]; - r->es = ptr[1]; - } - break; - case 0x37: - { - switch(r->eax & 0xff) { - case 0x00: /* get switch char */ - r->eax = (r->eax & ~0xff) | 0x00; - r->edx = (r->edx & ~0xff) | '/'; - break; - default: - goto unsupported; - } - } - break; - case 0x3c: /* create or truncate file */ - { - char filename[1024]; - int fd, h, flags; - - h = get_new_handle(); - if (h < 0) { - set_error(r, 0x04); /* too many open files */ - } else { - get_filename(r, filename, sizeof(filename)); - if (r->ecx & 1) - flags = 0444; /* read-only */ - else - flags = 0777; - fd = open(filename, O_RDWR | O_TRUNC | O_CREAT, flags); -#ifdef DUMP_INT21 - printf("int21: create: file='%s' cx=0x%04x ret=%d\n", - filename, (int)(r->ecx & 0xffff), h); -#endif - if (fd < 0) { - set_error(r, 0x03); /* path not found */ - } else { - dos_files[h].fd = fd; - set_error(r, 0); - r->eax = (r->eax & ~0xffff) | h; - } - } - } - break; - case 0x3d: /* open file */ - { - char filename[1024]; - int fd, h; - - h = get_new_handle(); - if (h < 0) { - set_error(r, 0x04); /* too many open files */ - } else { - get_filename(r, filename, sizeof(filename)); -#ifdef DUMP_INT21 - printf("int21: open: file='%s' al=0x%02x ret=%d\n", - filename, (int)(r->eax & 0xff), h); -#endif - fd = open(filename, r->eax & 3); - if (fd < 0) { - set_error(r, 0x02); /* file not found */ - } else { - dos_files[h].fd = fd; - set_error(r, 0); - r->eax = (r->eax & ~0xffff) | h; - } - } - } - break; - case 0x3e: /* close file */ - { - DOSFile *fh = get_file(r->ebx & 0xffff); -#ifdef DUMP_INT21 - printf("int21: close fd=%d\n", (int)(r->ebx & 0xffff)); -#endif - if (!fh) { - set_error(r, 0x06); /* invalid handle */ - } else { - close(fh->fd); - fh->fd = -1; - set_error(r, 0); - } - } - break; - case 0x3f: /* read */ - { - DOSFile *fh = get_file(r->ebx & 0xffff); - int n, ret; - - if (!fh) { - set_error(r, 0x06); /* invalid handle */ - } else { - n = r->ecx & 0xffff; - for(;;) { - ret = read(fh->fd, - seg_to_linear(r->ds, r->edx), n); - if (ret < 0) { - if (errno != EINTR && errno != EAGAIN) - break; - } else { - break; - } - } -#ifdef DUMP_INT21 - printf("int21: read: fd=%d n=%d ret=%d\n", - (int)(r->ebx & 0xffff), n, ret); -#endif - if (ret < 0) { - set_error(r, 0x05); /* acces denied */ - } else { - r->eax = (r->eax & ~0xffff) | ret; - set_error(r, 0); - } - } - } - break; - case 0x40: /* write */ - { - DOSFile *fh = get_file(r->ebx & 0xffff); - int n, ret, pos; - - if (!fh) { - set_error(r, 0x06); /* invalid handle */ - } else { - n = r->ecx & 0xffff; - if (n == 0) { - /* truncate */ - pos = lseek(fh->fd, 0, SEEK_CUR); - if (pos >= 0) { - ret = ftruncate(fh->fd, pos); - } else { - ret = -1; - } - } else { - for(;;) { - ret = write(fh->fd, - seg_to_linear(r->ds, r->edx), n); - if (ret < 0) { - if (errno != EINTR && errno != EAGAIN) - break; - } else { - break; - } - } - } -#ifdef DUMP_INT21 - printf("int21: write: fd=%d n=%d ret=%d\n", - (int)(r->ebx & 0xffff), n, ret); -#endif - if (ret < 0) { - set_error(r, 0x05); /* acces denied */ - } else { - r->eax = (r->eax & ~0xffff) | ret; - set_error(r, 0); - } - } - } - break; - case 0x41: /* unlink */ - { - char filename[1024]; - get_filename(r, filename, sizeof(filename)); - if (unlink(filename) < 0) { - set_error(r, 0x02); /* file not found */ - } else { - set_error(r, 0); - } - } - break; - case 0x42: /* lseek */ - { - DOSFile *fh = get_file(r->ebx & 0xffff); - int pos, ret; - - if (!fh) { - set_error(r, 0x06); /* invalid handle */ - } else { - pos = ((r->ecx & 0xffff) << 16) | (r->edx & 0xffff); - ret = lseek(fh->fd, pos, r->eax & 0xff); -#ifdef DUMP_INT21 - printf("int21: lseek: fd=%d pos=%d whence=%d ret=%d\n", - (int)(r->ebx & 0xffff), pos, (uint8_t)r->eax, ret); -#endif - if (ret < 0) { - set_error(r, 0x01); /* function number invalid */ - } else { - r->edx = (r->edx & ~0xffff) | ((unsigned)ret >> 16); - r->eax = (r->eax & ~0xffff) | (ret & 0xffff); - set_error(r, 0); - } - } - } - break; - case 0x44: /* ioctl */ - switch(r->eax & 0xff) { - case 0x00: /* get device information */ - { - DOSFile *fh = get_file(r->ebx & 0xffff); - int ret; - - if (!fh) { - set_error(r, 0x06); /* invalid handle */ - } else { - ret = 0; - if (isatty(fh->fd)) { - ret |= 0x80; - if (fh->fd == 0) - ret |= (1 << 0); - else - ret |= (1 << 1); - } - r->edx = (r->edx & ~0xffff) | ret; - set_error(r, 0); - } - } - break; - default: - goto unsupported; - } - break; - case 0x48: /* allocate memory */ - { - int ret, max_size; -#ifdef DUMP_INT21 - printf("int21: allocate memory: size=0x%04x\n", (uint16_t)r->ebx); -#endif - ret = mem_malloc(r->ebx & 0xffff, &max_size); - if (ret < 0) { - set_error(r, 0x08); /* insufficient memory*/ - } else { - r->eax = (r->eax & ~0xffff) | ret; - r->ebx = (r->ebx & ~0xffff) | max_size; - set_error(r, 0); - } - } - break; - case 0x49: /* free memory */ - { -#ifdef DUMP_INT21 - printf("int21: free memory: block=0x%04x\n", r->es); -#endif - if (mem_free(r->es) < 0) { - set_error(r, 0x09); /* memory block address invalid */ - } else { - set_error(r, 0); - } - } - break; - case 0x4a: /* resize memory block */ - { - int ret; -#ifdef DUMP_INT21 - printf("int21: resize memory block: block=0x%04x size=0x%04x\n", - r->es, (uint16_t)r->ebx); -#endif - ret = mem_resize(r->es, r->ebx & 0xffff); - if (ret < 0) { - set_error(r, 0x08); /* insufficient memory*/ - } else { - r->ebx = (r->ebx & ~0xffff) | ret; - set_error(r, 0); - } - } - break; - case 0x4b: /* load program */ - { - char filename[1024]; - ExecParamBlock *blk; - int ret; - - if ((r->eax & 0xff) != 0x01) /* only load */ - goto unsupported; - get_filename(r, filename, sizeof(filename)); - blk = (ExecParamBlock *)seg_to_linear(r->es, r->ebx); - ret = load_com(blk, filename, NULL, 0, NULL); - if (ret < 0) { - set_error(r, 0x02); /* file not found */ - } else { - cur_psp = ret; - set_error(r, 0); - } - } - break; - case 0x4c: /* exit with return code */ - exit(r->eax & 0xff); - break; - case 0x50: /* set PSP address */ -#ifdef DUMP_INT21 - printf("int21: set PSP: 0x%04x\n", (uint16_t)r->ebx); -#endif - cur_psp = r->ebx; - break; - case 0x51: /* get PSP address */ -#ifdef DUMP_INT21 - printf("int21: get PSP: ret=0x%04x\n", cur_psp); -#endif - r->ebx = (r->ebx & ~0xffff) | cur_psp; - break; - case 0x55: /* create child PSP */ - { - uint8_t *psp_ptr; -#ifdef DUMP_INT21 - printf("int21: create child PSP: psp=0x%04x last_seg=0x%04x\n", - (uint16_t)r->edx, (uint16_t)r->esi); -#endif - psp_ptr = seg_to_linear(r->edx & 0xffff, 0); - memset(psp_ptr, 0, 0x80); - psp_ptr[0] = 0xcd; /* int $0x20 */ - psp_ptr[1] = 0x20; - *(uint16_t *)(psp_ptr + 2) = r->esi; - r->eax = (r->eax & ~0xff); - } - break; - default: - unsupported: - unsupported_function(r, 0x21, ah); - } -} - -void do_int29(struct vm86_regs *r) -{ - uint8_t c = r->eax; - write(1, &c, 1); -} - -void raise_interrupt(int number) -{ - if (* (uint32_t *) seg_to_linear(0, number * 4) == 0) - return; - // FIXME VM86_SIGNAL -} - -void biosclock() -{ - uint32_t *timer = (uint32_t *) seg_to_linear(0, 0x46C); - ++*timer; - raise_interrupt(8); - raise_interrupt(0x1C); -} - -int main(int argc, char **argv) -{ - uint8_t *vm86_mem; - const char *filename; - int ret; - uint32_t file_size; - struct sigaction sa; - struct itimerval timerval; - struct vm86plus_struct ctx; - struct vm86_regs *r; - ExecParamBlock blk1, *blk = &blk1; - - if (argc < 2) - usage(); - filename = argv[1]; - - vm86_mem = mmap((void *)0x00000000, 0x110000, - PROT_WRITE | PROT_READ | PROT_EXEC, - MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); - if (vm86_mem == MAP_FAILED) { - perror("mmap"); - exit(1); - } - - memset(&ctx, 0, sizeof(ctx)); - r = &ctx.regs; - set_bit((uint8_t *)&ctx.int_revectored, 0x10); - set_bit((uint8_t *)&ctx.int_revectored, 0x13); - set_bit((uint8_t *)&ctx.int_revectored, 0x15); - set_bit((uint8_t *)&ctx.int_revectored, 0x16); - set_bit((uint8_t *)&ctx.int_revectored, 0x1a); - set_bit((uint8_t *)&ctx.int_revectored, 0x20); - set_bit((uint8_t *)&ctx.int_revectored, 0x21); - set_bit((uint8_t *)&ctx.int_revectored, 0x29); - - dos_init(); - - if (strstr(filename,".com") || strstr(filename,".exe") || - strstr(filename,".COM") || strstr(filename,".EXE")) { - ret = load_com(blk, filename, &file_size, argc, argv); - if (ret < 0) { - perror(filename); - exit(1); - } - cur_psp = ret; - - /* init basic registers */ - r->eip = blk->ip; - r->esp = blk->sp + 2; /* pop ax value */ - r->cs = blk->cs; - r->ss = blk->ss; - r->ds = cur_psp; - r->es = cur_psp; - r->eflags = VIF_MASK; - - /* the value of these registers seem to be assumed by pi_10.com */ - r->esi = 0x100; -#if 0 - r->ebx = file_size >> 16; - r->ecx = file_size & 0xffff; -#else - r->ecx = 0xff; -#endif - r->ebp = 0x0900; - r->edi = 0xfffe; - } - else { - if (load_boot(filename, r) < 0) { - if (errno) - perror(filename); - exit(1); - } - } - - sa.sa_handler = biosclock; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESTART; - if (sigaction(SIGALRM, &sa, 0) == 0) { - timerval.it_interval.tv_sec = timerval.it_value.tv_sec = 0; - timerval.it_interval.tv_usec = timerval.it_value.tv_usec = 10000000 / 182; - setitimer (ITIMER_REAL, &timerval, NULL); - } - - for(;;) { - ret = vm86(VM86_ENTER, &ctx); - switch(VM86_TYPE(ret)) { - case VM86_INTx: - { - int int_num; - - int_num = VM86_ARG(ret); - switch(int_num) { - case 0x10: - do_int10(r); - break; - case 0x13: - do_int13(r); - break; - case 0x15: - do_int15(r); - break; - case 0x16: - do_int16(r); - break; - case 0x1a: - do_int1a(r); - break; - case 0x20: - do_int20(r); - break; - case 0x21: - do_int21(r); - break; - case 0x29: - do_int29(r); - break; - default: - fprintf(stderr, "unsupported int 0x%02x\n", int_num); - dump_regs(&ctx.regs); - break; - } - } - break; - case VM86_SIGNAL: - /* a signal came, we just ignore that */ - break; - case VM86_STI: - break; - case VM86_TRAP: - /* just executes the interruption */ - { - uint16_t *int_vector; - uint32_t eflags; - - eflags = r->eflags & ~IF_MASK; - if (r->eflags & VIF_MASK) - eflags |= IF_MASK; - pushw(r, eflags); - pushw(r, r->cs); - pushw(r, r->eip); - int_vector = (uint16_t *)seg_to_linear(0, VM86_ARG(ret) * 4); - r->eip = int_vector[0]; - r->cs = int_vector[1]; - r->eflags &= ~(VIF_MASK | TF_MASK | AC_MASK); - } - break; - default: - fprintf(stderr, "unhandled vm86 return code (0x%x)\n", ret); - dump_regs(&ctx.regs); - exit(1); - } - } -}