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 -}