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

📄 lrmi.c

📁 针对linux休眠suspend显卡状态保存恢复的一个办法
💻 C
📖 第 1 页 / 共 2 页
字号:
/*Linux Real Mode Interface - A library of DPMI-like functions for Linux.Copyright (C) 1998 by Josh VanderhoofPermission is hereby granted, free of charge, to any person obtaininga copy of this software and associated documentation files (the"Software"), to deal in the Software without restriction, includingwithout limitation the rights to use, copy, modify, merge, publish,distribute, sublicense, and/or sell copies of the Software, and topermit persons to whom the Software is furnished to do so, subject tothe following conditions:The above copyright notice and this permission notice shall beincluded in all copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OFMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL JOSH VANDERHOOF BE LIABLE FOR ANY CLAIM, DAMAGES OROTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OROTHER DEALINGS IN THE SOFTWARE.*/#include <stdio.h>#include <string.h>#if defined(__linux__) && defined(__i386__)#include <asm/vm86.h>#ifdef USE_LIBC_VM86#include <sys/vm86.h>#endif#elif defined(__NetBSD__) || defined(__FreeBSD__)#include <sys/param.h>#include <signal.h>#include <setjmp.h>#include <machine/psl.h>#include <machine/vm86.h>#include <machine/sysarch.h>#endif /* __NetBSD__ || __FreeBSD__ */#include <sys/types.h>#include <sys/stat.h>#include <sys/mman.h>#include <unistd.h>#include <fcntl.h>#include "include/lrmi.h"#include "x86-common.h"#if defined(__linux__)#define DEFAULT_VM86_FLAGS 	(IF_MASK | IOPL_MASK)#elif defined(__NetBSD__) || defined(__FreeBSD__)#define DEFAULT_VM86_FLAGS  (PSL_I | PSL_IOPL)#define TF_MASK         PSL_T#define VIF_MASK        PSL_VIF#endif#define DEFAULT_STACK_SIZE 	0x1000#define RETURN_TO_32_INT 	255#if defined(__linux__)#define CONTEXT_REGS	context.vm.regs#define REG(x)			x#elif defined(__NetBSD__)#define CONTEXT_REGS	context.vm.substr.regs#define REG(x)			vmsc.sc_ ## x#elif defined(__FreeBSD__)#define CONTEXT_REGS	context.vm.uc#define REG(x)			uc_mcontext.mc_ ## x#endifstatic struct {	int ready;	unsigned short ret_seg, ret_off;	unsigned short stack_seg, stack_off;#if defined(__linux__) || defined(__NetBSD__)	struct vm86_struct vm;#elif defined(__FreeBSD__)	struct {		struct vm86_init_args init;		ucontext_t uc;	} vm;#endif#if defined(__NetBSD__) || defined(__FreeBSD__)	int success;	jmp_buf env;	void *old_sighandler;	int vret;#endif} context = { 0 };static inline voidset_bit(unsigned int bit, void *array){	unsigned char *a = array;	a[bit / 8] |= (1 << (bit % 8));}static inline unsigned intget_int_seg(int i){	return *(unsigned short *)(i * 4 + 2);}static inline unsigned intget_int_off(int i){	return *(unsigned short *)(i * 4);}static inline voidpushw(unsigned short i){	CONTEXT_REGS.REG(esp) -= 2;	*(unsigned short *)(((unsigned int)CONTEXT_REGS.REG(ss) << 4) +		CONTEXT_REGS.REG(esp)) = i;}intLRMI_init(void){	void *m;	if (context.ready)		return 1;	if (!LRMI_common_init())		return 0;	/*	 Allocate a stack	*/	m = LRMI_alloc_real(DEFAULT_STACK_SIZE);	context.stack_seg = (unsigned int)m >> 4;	context.stack_off = DEFAULT_STACK_SIZE;	/*	 Allocate the return to 32 bit routine	*/	m = LRMI_alloc_real(2);	context.ret_seg = (unsigned int)m >> 4;	context.ret_off = (unsigned int)m & 0xf;	((unsigned char *)m)[0] = 0xcd; 	/* int opcode */	((unsigned char *)m)[1] = RETURN_TO_32_INT;	memset(&context.vm, 0, sizeof(context.vm));	/*	 Enable kernel emulation of all ints except RETURN_TO_32_INT	*/#if defined(__linux__)	memset(&context.vm.int_revectored, 0, sizeof(context.vm.int_revectored));	set_bit(RETURN_TO_32_INT, &context.vm.int_revectored);#elif defined(__NetBSD__)	set_bit(RETURN_TO_32_INT, &context.vm.int_byuser);#elif defined(__FreeBSD__)	set_bit(RETURN_TO_32_INT, &context.vm.init.int_map);#endif	context.ready = 1;	return 1;}static voidset_regs(struct LRMI_regs *r){	CONTEXT_REGS.REG(edi) = r->edi;	CONTEXT_REGS.REG(esi) = r->esi;	CONTEXT_REGS.REG(ebp) = r->ebp;	CONTEXT_REGS.REG(ebx) = r->ebx;	CONTEXT_REGS.REG(edx) = r->edx;	CONTEXT_REGS.REG(ecx) = r->ecx;	CONTEXT_REGS.REG(eax) = r->eax;	CONTEXT_REGS.REG(eflags) = DEFAULT_VM86_FLAGS;	CONTEXT_REGS.REG(es) = r->es;	CONTEXT_REGS.REG(ds) = r->ds;	CONTEXT_REGS.REG(fs) = r->fs;	CONTEXT_REGS.REG(gs) = r->gs;}static voidget_regs(struct LRMI_regs *r){	r->edi = CONTEXT_REGS.REG(edi);	r->esi = CONTEXT_REGS.REG(esi);	r->ebp = CONTEXT_REGS.REG(ebp);	r->ebx = CONTEXT_REGS.REG(ebx);	r->edx = CONTEXT_REGS.REG(edx);	r->ecx = CONTEXT_REGS.REG(ecx);	r->eax = CONTEXT_REGS.REG(eax);	r->flags = CONTEXT_REGS.REG(eflags);	r->es = CONTEXT_REGS.REG(es);	r->ds = CONTEXT_REGS.REG(ds);	r->fs = CONTEXT_REGS.REG(fs);	r->gs = CONTEXT_REGS.REG(gs);}#define DIRECTION_FLAG 	(1 << 10)enum {	CSEG = 0x2e, SSEG = 0x36, DSEG = 0x3e,	ESEG = 0x26, FSEG = 0x64, GSEG = 0x65};static voidem_ins(int size){	unsigned int edx, edi;	edx = CONTEXT_REGS.REG(edx) & 0xffff;	edi = CONTEXT_REGS.REG(edi) & 0xffff;	edi += (unsigned int)CONTEXT_REGS.REG(es) << 4;	if (CONTEXT_REGS.REG(eflags) & DIRECTION_FLAG) {		if (size == 4)			asm volatile ("std; insl; cld"			 : "=D" (edi) : "d" (edx), "0" (edi));		else if (size == 2)			asm volatile ("std; insw; cld"			 : "=D" (edi) : "d" (edx), "0" (edi));		else			asm volatile ("std; insb; cld"			 : "=D" (edi) : "d" (edx), "0" (edi));	} else {		if (size == 4)			asm volatile ("cld; insl"			 : "=D" (edi) : "d" (edx), "0" (edi));		else if (size == 2)			asm volatile ("cld; insw"			 : "=D" (edi) : "d" (edx), "0" (edi));		else			asm volatile ("cld; insb"			 : "=D" (edi) : "d" (edx), "0" (edi));	}	edi -= (unsigned int)CONTEXT_REGS.REG(es) << 4;	CONTEXT_REGS.REG(edi) &= 0xffff0000;	CONTEXT_REGS.REG(edi) |= edi & 0xffff;}static voidem_rep_ins(int size){	unsigned int cx;	cx = CONTEXT_REGS.REG(ecx) & 0xffff;	while (cx--)		em_ins(size);	CONTEXT_REGS.REG(ecx) &= 0xffff0000;}static voidem_outs(int size, int seg){	unsigned int edx, esi, base;	edx = CONTEXT_REGS.REG(edx) & 0xffff;	esi = CONTEXT_REGS.REG(esi) & 0xffff;	switch (seg) {	case CSEG: base = CONTEXT_REGS.REG(cs); break;	case SSEG: base = CONTEXT_REGS.REG(ss); break;	case ESEG: base = CONTEXT_REGS.REG(es); break;	case FSEG: base = CONTEXT_REGS.REG(fs); break;	case GSEG: base = CONTEXT_REGS.REG(gs); break;	default:	case DSEG: base = CONTEXT_REGS.REG(ds); break;	}	esi += base << 4;	if (CONTEXT_REGS.REG(eflags) & DIRECTION_FLAG) {		if (size == 4)			asm volatile ("std; outsl; cld"			 : "=S" (esi) : "d" (edx), "0" (esi));		else if (size == 2)			asm volatile ("std; outsw; cld"			 : "=S" (esi) : "d" (edx), "0" (esi));		else			asm volatile ("std; outsb; cld"			 : "=S" (esi) : "d" (edx), "0" (esi));	} else {		if (size == 4)			asm volatile ("cld; outsl"			 : "=S" (esi) : "d" (edx), "0" (esi));		else if (size == 2)			asm volatile ("cld; outsw"			 : "=S" (esi) : "d" (edx), "0" (esi));		else			asm volatile ("cld; outsb"			 : "=S" (esi) : "d" (edx), "0" (esi));	}	esi -= base << 4;	CONTEXT_REGS.REG(esi) &= 0xffff0000;	CONTEXT_REGS.REG(esi) |= esi & 0xffff;}static voidem_rep_outs(int size, int seg){	unsigned int cx;	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) {

⌨️ 快捷键说明

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