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

📄 lrmi.c

📁 超强的嵌入式GUI系统
💻 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.*/#if defined(__i386__) && (defined(__linux__) || defined(__NetBSD__) \	|| defined(__FreeBSD__) || defined(__OpenBSD__))#include <stdio.h>#include <string.h>#if defined(__linux__)#include <asm/vm86.h>#include <signal.h>#ifdef USE_LIBC_VM86#include <sys/vm86.h>#endif#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)#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__ || __OpenBSD__ */#if defined(__FreeBSD__)#include <sys/ucontext.h>#endif#include <sys/types.h>#include <sys/stat.h>#include <sys/mman.h>#include <unistd.h>#include <fcntl.h>#include "lrmi.h"#define REAL_MEM_BASE 	((void *)0x10000)#define REAL_MEM_SIZE 	0x40000#define REAL_MEM_BLOCKS 	0x100struct mem_block {	unsigned int size : 20;	unsigned int free : 1;};static struct {	int ready;	int count;	struct mem_block blocks[REAL_MEM_BLOCKS];} mem_info = { 0 };static intread_file(char *name, void *p, size_t n){	int fd;	fd = open(name, O_RDONLY);	if (fd == -1) {		perror("open");		return 0;	}	if (read(fd, p, n) != n) {		perror("read");		close(fd);		return 0;	}	close(fd);	return 1;}static intmap_file(void *start, size_t length, int prot, int flags, char *name, long offset){	void *m;	int fd;	fd = open(name, (flags & MAP_SHARED) ? O_RDWR : O_RDONLY);	if (fd == -1) {		perror("open");		return 0;	}	m = mmap(start, length, prot, flags, fd, offset);	if (m == (void *)-1) {		perror("mmap");		close(fd);		return 0;	}	close(fd);	return 1;}static intreal_mem_init(void){	if (mem_info.ready)		return 1;	if (!map_file((void *)REAL_MEM_BASE, REAL_MEM_SIZE,	 PROT_READ | PROT_WRITE | PROT_EXEC,	 MAP_FIXED | MAP_PRIVATE, "/dev/zero", 0))		return 0;	mem_info.ready = 1;	mem_info.count = 1;	mem_info.blocks[0].size = REAL_MEM_SIZE;	mem_info.blocks[0].free = 1;	return 1;}static voidreal_mem_deinit(void){	if (mem_info.ready) {		munmap((void *)REAL_MEM_BASE, REAL_MEM_SIZE);		mem_info.ready = 0;	}}static voidinsert_block(int i){	memmove(	 mem_info.blocks + i + 1,	 mem_info.blocks + i,	 (mem_info.count - i) * sizeof(struct mem_block));	mem_info.count++;}static voiddelete_block(int i){	mem_info.count--;	memmove(	 mem_info.blocks + i,	 mem_info.blocks + i + 1,	 (mem_info.count - i) * sizeof(struct mem_block));}void *LRMI_alloc_real(int size){	int i;	char *r = (char *)REAL_MEM_BASE;	if (!mem_info.ready)		return NULL;	if (mem_info.count == REAL_MEM_BLOCKS)		return NULL;	size = (size + 15) & ~15;	for (i = 0; i < mem_info.count; i++) {		if (mem_info.blocks[i].free && size < mem_info.blocks[i].size) {			insert_block(i);			mem_info.blocks[i].size = size;			mem_info.blocks[i].free = 0;			mem_info.blocks[i + 1].size -= size;			return (void *)r;		}		r += mem_info.blocks[i].size;	}	return NULL;}voidLRMI_free_real(void *m){	int i;	char *r = (char *)REAL_MEM_BASE;	if (!mem_info.ready)		return;	i = 0;	while (m != (void *)r) {		r += mem_info.blocks[i].size;		i++;		if (i == mem_info.count)			return;	}	mem_info.blocks[i].free = 1;	if (i + 1 < mem_info.count && mem_info.blocks[i + 1].free) {		mem_info.blocks[i].size += mem_info.blocks[i + 1].size;		delete_block(i + 1);	}	if (i - 1 >= 0 && mem_info.blocks[i - 1].free) {		mem_info.blocks[i - 1].size += mem_info.blocks[i].size;		delete_block(i);	}}#if defined(__linux__)#define DEFAULT_VM86_FLAGS 	(IF_MASK | IOPL_MASK)#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)#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__) || defined(__OpenBSD__)#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__) || defined(__OpenBSD__)	struct vm86_struct vm;#elif defined(__FreeBSD__)	struct {		struct vm86_init_args init;		ucontext_t uc;	} vm;#endif#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)	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 (!real_mem_init())		return 0;	/*	 Map the Interrupt Vectors (0x0 - 0x400) + BIOS data (0x400 - 0x502)	 and the ROM (0xa0000 - 0x100000)	*/	if (!map_file((void *)0, 0x502,	 PROT_READ | PROT_WRITE | PROT_EXEC,	 MAP_FIXED | MAP_PRIVATE, "/dev/zero", 0)) {		real_mem_deinit();		return 0;	}	if (!read_file("/dev/mem", (void *)0, 0x502)) {		munmap((void *)0, 0x502);		real_mem_deinit();		return 0;	}	if (!map_file((void *)0xa0000, 0x100000 - 0xa0000,	 PROT_READ | PROT_WRITE,	 MAP_FIXED | MAP_SHARED, "/dev/mem", 0xa0000)) {		munmap((void *)0, 0x502);		real_mem_deinit();		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__) || defined(__OpenBSD__)	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;

⌨️ 快捷键说明

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