⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lrmi.c

📁 超强的嵌入式GUI系统
💻 C
📖 第 1 页 / 共 2 页
字号:
	cx = CONTEXT_REGS.REG(ecx) & 0xffff;	while (cx--)		em_outs(size, seg);	CONTEXT_REGS.REG(ecx) &= 0xffff0000;}static voidem_inbl(unsigned char literal){	asm volatile ("inb %w1, %b0"	 : "=a" (CONTEXT_REGS.REG(eax))	 : "d" (literal), "0" (CONTEXT_REGS.REG(eax)));}static voidem_inb(void){	asm volatile ("inb %w1, %b0"	 : "=a" (CONTEXT_REGS.REG(eax))	 : "d" (CONTEXT_REGS.REG(edx)), "0" (CONTEXT_REGS.REG(eax)));}static voidem_inw(void){	asm volatile ("inw %w1, %w0"	 : "=a" (CONTEXT_REGS.REG(eax))	 : "d" (CONTEXT_REGS.REG(edx)), "0" (CONTEXT_REGS.REG(eax)));}static voidem_inl(void){	asm volatile ("inl %w1, %0"	 : "=a" (CONTEXT_REGS.REG(eax))	 : "d" (CONTEXT_REGS.REG(edx)));}static voidem_outbl(unsigned char literal){	asm volatile ("outb %b0, %w1"	 : : "a" (CONTEXT_REGS.REG(eax)),	 "d" (literal));}static voidem_outb(void){	asm volatile ("outb %b0, %w1"	 : : "a" (CONTEXT_REGS.REG(eax)),	 "d" (CONTEXT_REGS.REG(edx)));}static voidem_outw(void){	asm volatile ("outw %w0, %w1"	 : : "a" (CONTEXT_REGS.REG(eax)),	 "d" (CONTEXT_REGS.REG(edx)));}static voidem_outl(void){	asm volatile ("outl %0, %w1"	 : : "a" (CONTEXT_REGS.REG(eax)),	 "d" (CONTEXT_REGS.REG(edx)));}static intemulate(void){	unsigned char *insn;	struct {		unsigned char seg;		unsigned int size : 1;		unsigned int rep : 1;	} prefix = { DSEG, 0, 0 };	int i = 0;	insn = (unsigned char *)((unsigned int)CONTEXT_REGS.REG(cs) << 4);	insn += CONTEXT_REGS.REG(eip);	while (1) {		if (insn[i] == 0x66) {			prefix.size = 1 - prefix.size;			i++;		} else if (insn[i] == 0xf3) {			prefix.rep = 1;			i++;		} else if (insn[i] == CSEG || insn[i] == SSEG		 || insn[i] == DSEG || insn[i] == ESEG		 || insn[i] == FSEG || insn[i] == GSEG) {			prefix.seg = insn[i];			i++;		} else if (insn[i] == 0xf0 || insn[i] == 0xf2		 || insn[i] == 0x67) {			/* these prefixes are just ignored */			i++;		} else if (insn[i] == 0x6c) {			if (prefix.rep)				em_rep_ins(1);			else				em_ins(1);			i++;			break;		} else if (insn[i] == 0x6d) {			if (prefix.rep) {				if (prefix.size)					em_rep_ins(4);				else					em_rep_ins(2);			} else {				if (prefix.size)					em_ins(4);				else					em_ins(2);			}			i++;			break;		} else if (insn[i] == 0x6e) {			if (prefix.rep)				em_rep_outs(1, prefix.seg);			else				em_outs(1, prefix.seg);			i++;			break;		} else if (insn[i] == 0x6f) {			if (prefix.rep) {				if (prefix.size)					em_rep_outs(4, prefix.seg);				else					em_rep_outs(2, prefix.seg);			} else {				if (prefix.size)					em_outs(4, prefix.seg);				else					em_outs(2, prefix.seg);			}			i++;			break;		} else if (insn[i] == 0xe4) {			em_inbl(insn[i + 1]);			i += 2;			break;		} else if (insn[i] == 0xec) {			em_inb();			i++;			break;		} else if (insn[i] == 0xed) {			if (prefix.size)				em_inl();			else				em_inw();			i++;			break;		} else if (insn[i] == 0xe6) {			em_outbl(insn[i + 1]);			i += 2;			break;		} else if (insn[i] == 0xee) {			em_outb();			i++;			break;		} else if (insn[i] == 0xef) {			if (prefix.size)				em_outl();			else				em_outw();			i++;			break;		} else			return 0;	}	CONTEXT_REGS.REG(eip) += i;	return 1;}#if defined(__linux__)/* I don't know how to make sure I get the right vm86() from libc. The one I want is syscall # 113 (vm86old() in libc 5, vm86() in glibc) which should be declared as "int vm86(struct vm86_struct *);" in <sys/vm86.h>. This just does syscall 113 with inline asm, which should work for both libc's (I hope).*/#if !defined(USE_LIBC_VM86)static intlrmi_vm86(struct vm86_struct *vm){	int r;#ifdef __PIC__	asm volatile (	 "pushl %%ebx\n\t"	 "movl %2, %%ebx\n\t"	 "int $0x80\n\t"	 "popl %%ebx"	 : "=a" (r)	 : "0" (113), "r" (vm));#else	asm volatile (	 "int $0x80"	 : "=a" (r)	 : "0" (113), "b" (vm));#endif	return r;}#else#define lrmi_vm86 vm86#endif#endif /* __linux__ */static voiddebug_info(int vret){#ifdef LRMI_DEBUG	int i;	unsigned char *p;	fputs("vm86() failed\n", stderr);	fprintf(stderr, "return = 0x%x\n", vret);	fprintf(stderr, "eax = 0x%08x\n", CONTEXT_REGS.REG(eax));	fprintf(stderr, "ebx = 0x%08x\n", CONTEXT_REGS.REG(ebx));	fprintf(stderr, "ecx = 0x%08x\n", CONTEXT_REGS.REG(ecx));	fprintf(stderr, "edx = 0x%08x\n", CONTEXT_REGS.REG(edx));	fprintf(stderr, "esi = 0x%08x\n", CONTEXT_REGS.REG(esi));	fprintf(stderr, "edi = 0x%08x\n", CONTEXT_REGS.REG(edi));	fprintf(stderr, "ebp = 0x%08x\n", CONTEXT_REGS.REG(ebp));	fprintf(stderr, "eip = 0x%08x\n", CONTEXT_REGS.REG(eip));	fprintf(stderr, "cs  = 0x%04x\n", CONTEXT_REGS.REG(cs));	fprintf(stderr, "esp = 0x%08x\n", CONTEXT_REGS.REG(esp));	fprintf(stderr, "ss  = 0x%04x\n", CONTEXT_REGS.REG(ss));	fprintf(stderr, "ds  = 0x%04x\n", CONTEXT_REGS.REG(ds));	fprintf(stderr, "es  = 0x%04x\n", CONTEXT_REGS.REG(es));	fprintf(stderr, "fs  = 0x%04x\n", CONTEXT_REGS.REG(fs));	fprintf(stderr, "gs  = 0x%04x\n", CONTEXT_REGS.REG(gs));	fprintf(stderr, "eflags  = 0x%08x\n", CONTEXT_REGS.REG(eflags));	fputs("cs:ip = [ ", stderr);	p = (unsigned char *)((CONTEXT_REGS.REG(cs) << 4) + (CONTEXT_REGS.REG(eip) & 0xffff));	for (i = 0; i < 16; ++i)		fprintf(stderr, "%02x ", (unsigned int)p[i]);	fputs("]\n", stderr);#endif}#if defined(__linux__)static intrun_vm86(void){	unsigned int vret;	sigset_t all_sigs, old_sigs;	unsigned long old_gs, old_fs;	while (1) {		// FIXME: may apply this to BSD equivalents?		sigfillset(&all_sigs);		sigprocmask(SIG_SETMASK, &all_sigs, &old_sigs);		asm volatile ("mov %%gs, %0" : "=rm" (old_gs));		asm volatile ("mov %%fs, %0" : "=rm" (old_fs));		vret = lrmi_vm86(&context.vm);		asm volatile ("mov %0, %%gs" :: "rm" (old_gs));		asm volatile ("mov %0, %%fs" :: "rm" (old_fs));		sigprocmask(SIG_SETMASK, &old_sigs, NULL);		if (VM86_TYPE(vret) == VM86_INTx) {			unsigned int v = VM86_ARG(vret);			if (v == RETURN_TO_32_INT)				return 1;			pushw(CONTEXT_REGS.REG(eflags));			pushw(CONTEXT_REGS.REG(cs));			pushw(CONTEXT_REGS.REG(eip));			CONTEXT_REGS.REG(cs) = get_int_seg(v);			CONTEXT_REGS.REG(eip) = get_int_off(v);			CONTEXT_REGS.REG(eflags) &= ~(VIF_MASK | TF_MASK);			continue;		}		if (VM86_TYPE(vret) != VM86_UNKNOWN)			break;		if (!emulate())			break;	}	debug_info(vret);	return 0;}#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)#if defined(__NetBSD__) || defined(__OpenBSD__)static voidvm86_callback(int sig, int code, struct sigcontext *sc){	/* Sync our context with what the kernel develivered to us. */	memcpy(&CONTEXT_REGS, sc, sizeof(*sc));	switch (VM86_TYPE(code)) {		case VM86_INTx:		{			unsigned int v = VM86_ARG(code);			if (v == RETURN_TO_32_INT) {				context.success = 1;				longjmp(context.env, 1);			}			pushw(CONTEXT_REGS.REG(eflags));			pushw(CONTEXT_REGS.REG(cs));			pushw(CONTEXT_REGS.REG(eip));			CONTEXT_REGS.REG(cs) = get_int_seg(v);			CONTEXT_REGS.REG(eip) = get_int_off(v);			CONTEXT_REGS.REG(eflags) &= ~(VIF_MASK | TF_MASK);			break;		}		case VM86_UNKNOWN:			if (emulate() == 0) {				context.success = 0;				context.vret = code;				longjmp(context.env, 1);			}			break;		default:			context.success = 0;			context.vret = code;			longjmp(context.env, 1);			return;	}	/* ...and sync our context back to the kernel. */	memcpy(sc, &CONTEXT_REGS, sizeof(*sc));}#elif defined(__FreeBSD__)static voidvm86_callback(int sig, int code, struct sigcontext *sc){	unsigned char *addr;	/* Sync our context with what the kernel develivered to us. */	memcpy(&CONTEXT_REGS, sc, sizeof(*sc));	if (code) {		/* XXX probably need to call original signal handler here */		context.success = 0;		context.vret = code;		longjmp(context.env, 1);	}	addr = (unsigned char *)((CONTEXT_REGS.REG(cs) << 4) +		CONTEXT_REGS.REG(eip));	if (addr[0] == 0xcd) { /* int opcode */		if (addr[1] == RETURN_TO_32_INT) {			context.success = 1;			longjmp(context.env, 1);		}		pushw(CONTEXT_REGS.REG(eflags));		pushw(CONTEXT_REGS.REG(cs));		pushw(CONTEXT_REGS.REG(eip));		CONTEXT_REGS.REG(cs) = get_int_seg(addr[1]);		CONTEXT_REGS.REG(eip) = get_int_off(addr[1]);		CONTEXT_REGS.REG(eflags) &= ~(VIF_MASK | TF_MASK);	} else {		if (emulate() == 0) {			context.success = 0;			longjmp(context.env, 1);		}	}	/* ...and sync our context back to the kernel. */	memcpy(sc, &CONTEXT_REGS, sizeof(*sc));}#endif /* __FreeBSD__ */static intrun_vm86(void){	if (context.old_sighandler) {#ifdef LRMI_DEBUG		fprintf(stderr, "run_vm86: callback already installed\n");#endif		return (0);	}#if defined(__NetBSD__) || defined(__OpenBSD__)	context.old_sighandler = signal(SIGURG, (void (*)(int))vm86_callback);#elif defined(__FreeBSD__)	context.old_sighandler = signal(SIGBUS, (void (*)(int))vm86_callback);#endif	if (context.old_sighandler == (void *)-1) {		context.old_sighandler = NULL;#ifdef LRMI_DEBUG		fprintf(stderr, "run_vm86: cannot install callback\n");#endif		return (0);	}	if (setjmp(context.env)) {#if defined(__NetBSD__) || defined(__OpenBSD__)		(void) signal(SIGURG, context.old_sighandler);#elif defined(__FreeBSD__)		(void) signal(SIGBUS, context.old_sighandler);#endif		context.old_sighandler = NULL;		if (context.success)			return (1);		debug_info(context.vret);		return (0);	}#if defined(__NetBSD__) || defined(__OpenBSD__)	if (i386_vm86(&context.vm) == -1)		return (0);#elif defined(__FreeBSD__)	if (i386_vm86(VM86_INIT, &context.vm.init))		return 0;	CONTEXT_REGS.REG(eflags) |= PSL_VM | PSL_VIF;	sigreturn(&context.vm.uc);#endif /* __FreeBSD__ */	/* NOTREACHED */	return (0);}#endif	/* __NetBSD__ || __FreeBSD__ || __OpenBSD__ */intLRMI_call(struct LRMI_regs *r){	unsigned int vret;	memset(&CONTEXT_REGS, 0, sizeof(CONTEXT_REGS));	set_regs(r);	CONTEXT_REGS.REG(cs) = r->cs;	CONTEXT_REGS.REG(eip) = r->ip;	if (r->ss == 0 && r->sp == 0) {		CONTEXT_REGS.REG(ss) = context.stack_seg;		CONTEXT_REGS.REG(esp) = context.stack_off;	} else {		CONTEXT_REGS.REG(ss) = r->ss;		CONTEXT_REGS.REG(esp) = r->sp;	}	pushw(context.ret_seg);	pushw(context.ret_off);	vret = run_vm86();	get_regs(r);	return vret;}intLRMI_int(int i, struct LRMI_regs *r){	unsigned int vret;	unsigned int seg, off;	seg = get_int_seg(i);	off = get_int_off(i);	/*	 If the interrupt is in regular memory, it's probably	 still pointing at a dos TSR (which is now gone).	*/	if (seg < 0xa000 || (seg << 4) + off >= 0x100000) {#ifdef LRMI_DEBUG		fprintf(stderr, "Int 0x%x is not in rom (%04x:%04x)\n", i, seg, off);#endif		return 0;	}	memset(&CONTEXT_REGS, 0, sizeof(CONTEXT_REGS));	set_regs(r);	CONTEXT_REGS.REG(cs) = seg;	CONTEXT_REGS.REG(eip) = off;	if (r->ss == 0 && r->sp == 0) {		CONTEXT_REGS.REG(ss) = context.stack_seg;		CONTEXT_REGS.REG(esp) = context.stack_off;	} else {		CONTEXT_REGS.REG(ss) = r->ss;		CONTEXT_REGS.REG(esp) = r->sp;	}	pushw(DEFAULT_VM86_FLAGS);	pushw(context.ret_seg);	pushw(context.ret_off);	vret = run_vm86();	get_regs(r);	return vret;}#else /* (__linux__ || __NetBSD__ || __FreeBSD__ || __OpenBSD__) && __i386__ */#warning "LRMI is not supported on your system!"#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -