1 #include <sys/types.h>
2 #include <sys/stat.h>
3 #include <sys/mman.h>
4 #include <fcntl.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <stdarg.h>
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <fcntl.h>
11 #include <unistd.h>
12 #include <stdlib.h>
13 #include <sys/mman.h>
14 #if !defined(__FreeBSD__) && !defined(__DragonFly__)
15 #include <sys/io.h>
16 #endif
17 #include <string.h>
18 #include <sys/ipc.h>
19 #include <sys/shm.h>
20 
21 #define SHMERRORPTR (pointer)(-1)
22 
23 #define _INT10_PRIVATE
24 #include "x86emu/include/xf86int10.h"
25 #include "x86emu/include/x86emu.h"
26 #include "x86emu/include/xf86x86emu.h"
27 #include "lrmi.h"
28 #include "x86-common.h"
29 
30 #ifndef DEBUG
31 #define DEBUG
32 #endif
33 #define ALLOC_ENTRIES(x) (V_RAM - 1)
34 #define TRUE 1
35 #define FALSE 0
36 
37 #define __BUILDIO(bwl,bw,type) \
38 static inline void out##bwl##_local(unsigned long port, unsigned type value) {        __asm__ __volatile__("out" #bwl " %" #bw "0, %w1" : : "a"(value), "Nd"(port)); \
39 }\
40 static inline unsigned type in##bwl##_local(unsigned long port) { \
41         unsigned type value; \
42         __asm__ __volatile__("in" #bwl " %w1, %" #bw "0" : "=a"(value) : "Nd"(port)); \
43         return value; \
44 }\
45 
46 __BUILDIO(b,b,char)
47 __BUILDIO(w,w,short)
48 __BUILDIO(l,,int)
49 
50 
51 char *mmap_addr = SHMERRORPTR;
52 struct LRMI_regs *regs;
53 static void *stack;
54 
55 
56 void
printk(const char * fmt,...)57 printk(const char *fmt, ...)
58 {
59 	va_list argptr;
60 	va_start(argptr, fmt);
61 
62 	fprintf(stderr, fmt, argptr);
63 	va_end(argptr);
64 }
65 
read_b(int addr)66 u8 read_b(int addr) {
67 	return *((char *)mmap_addr + addr);
68 }
69 
70 CARD8
x_inb(CARD16 port)71 x_inb(CARD16 port)
72 {
73 	CARD8 val;
74 	val = inb_local(port);
75 	return val;
76 }
77 
78 CARD16
x_inw(CARD16 port)79 x_inw(CARD16 port)
80 {
81 	CARD16 val;
82 	val = inw_local(port);
83 	return val;
84 }
85 
86 CARD32
x_inl(CARD16 port)87 x_inl(CARD16 port)
88 {
89 	CARD32 val;
90 	val = inl_local(port);
91 	return val;
92 }
93 
94 void
x_outb(CARD16 port,CARD8 val)95 x_outb(CARD16 port, CARD8 val)
96 {
97         outb_local(port, val);
98 }
99 
100 void
x_outw(CARD16 port,CARD16 val)101 x_outw(CARD16 port, CARD16 val)
102 {
103         outw_local(port, val);
104 }
105 
x_outl(CARD16 port,CARD32 val)106 void x_outl(CARD16 port, CARD32 val)
107 {
108 	outl_local(port, val);
109 }
110 
pushw(u16 val)111 void pushw(u16 val)
112 {
113 	X86_ESP -= 2;
114 	MEM_WW(((u32) X86_SS << 4) + X86_SP, val);
115 }
116 
x86emu_do_int(int num)117 static void x86emu_do_int(int num)
118 {
119 	u32 eflags;
120 
121 	/*	fprintf(stderr, "Calling INT 0x%X (%04X:%04X)\n", num,
122 			(read_b((num << 2) + 3) << 8) + read_b((num << 2) + 2),
123 			(read_b((num << 2) + 1) << 8) + read_b((num << 2)));
124 
125 	fprintf(stderr, " EAX is %X\n", (int) X86_EAX);
126 	*/
127 
128 	eflags = X86_EFLAGS;
129 	eflags = eflags | X86_IF_MASK;
130 	pushw(eflags);
131 	pushw(X86_CS);
132 	pushw(X86_IP);
133 	X86_EFLAGS = X86_EFLAGS & ~(X86_VIF_MASK | X86_TF_MASK);
134 	X86_CS = (read_b((num << 2) + 3) << 8) + read_b((num << 2) + 2);
135 	X86_IP = (read_b((num << 2) + 1) << 8) + read_b((num << 2));
136 
137 	/*	fprintf(stderr, "Leaving interrupt call.\n"); */
138 }
139 
LRMI_init()140 int LRMI_init() {
141 	int i;
142 	X86EMU_intrFuncs intFuncs[256];
143 
144 	if (!LRMI_common_init())
145 		return 0;
146 
147 	mmap_addr = 0;
148 
149 	X86EMU_pioFuncs pioFuncs = {
150 		(&x_inb),
151 		(&x_inw),
152 		(&x_inl),
153 		(&x_outb),
154 		(&x_outw),
155 		(&x_outl)
156 	};
157 
158 	X86EMU_setupPioFuncs(&pioFuncs);
159 
160 	for (i=0;i<256;i++)
161 		intFuncs[i] = x86emu_do_int;
162 	X86EMU_setupIntrFuncs(intFuncs);
163 
164 	X86_EFLAGS = X86_IF_MASK | X86_IOPL_MASK;
165 
166 	/*
167 	 * Allocate a 64k stack.
168 	 */
169 	stack = LRMI_alloc_real(64 * 1024);
170 	X86_SS = (unsigned int) stack >> 4;
171 	X86_ESP = 0xFFF9;
172 	memset (stack, 0, 64*1024);
173 
174 	*((volatile char *)0) = 0x4f; /* Make sure that we end up jumping back to a
175 					 halt instruction */
176 
177 	M.mem_base = 0;
178 	M.mem_size = 1024*1024;
179 
180 	return 1;
181 }
182 
real_call(struct LRMI_regs * registers)183 int real_call(struct LRMI_regs *registers) {
184         regs = registers;
185 
186         X86_EAX = registers->eax;
187         X86_EBX = registers->ebx;
188         X86_ECX = registers->ecx;
189         X86_EDX = registers->edx;
190         X86_ESI = registers->esi;
191         X86_EDI = registers->edi;
192         X86_EBP = registers->ebp;
193         X86_EIP = registers->ip;
194         X86_ES = registers->es;
195         X86_FS = registers->fs;
196         X86_GS = registers->gs;
197         X86_CS = registers->cs;
198 
199         if (registers->ss != 0) {
200                 X86_SS = registers->ss;
201         } else {
202 	        X86_SS = (unsigned int) stack >> 4;
203 	}
204 
205 	if (registers->ds != 0) {
206 		X86_DS = registers->ds;
207 	}
208 
209 	if (registers->sp != 0) {
210 		X86_ESP = registers->sp;
211 	} else {
212 	  	X86_ESP = 0xFFF9;
213 	}
214 
215 	M.x86.debug |= DEBUG_DECODE_F;
216 
217 	memset (stack, 0, 64*1024);
218 
219 	X86EMU_exec();
220 
221 	registers->eax = X86_EAX;
222 	registers->ebx = X86_EBX;
223 	registers->ecx = X86_ECX;
224 	registers->edx = X86_EDX;
225 	registers->esi = X86_ESI;
226 	registers->edi = X86_EDI;
227 	registers->ebp = X86_EBP;
228 	registers->es = X86_ES;
229 
230 	return 1;
231 }
232 
LRMI_int(int num,struct LRMI_regs * registers)233 int LRMI_int(int num, struct LRMI_regs *registers) {
234 	u32 eflags;
235 	eflags = X86_EFLAGS;
236 	eflags = eflags | X86_IF_MASK;
237 	X86_EFLAGS = X86_EFLAGS  & ~(X86_VIF_MASK | X86_TF_MASK | X86_IF_MASK | X86_NT_MASK);
238 
239 	registers->cs = (read_b((num << 2) + 3) << 8) + read_b((num << 2) + 2);
240 	registers->ip = (read_b((num << 2) + 1) << 8) + read_b((num << 2));
241 	regs = registers;
242 	return real_call(registers);
243 }
244 
LRMI_call(struct LRMI_regs * registers)245 int LRMI_call(struct LRMI_regs *registers) {
246 	return real_call(registers);
247 }
248 
249 size_t
LRMI_base_addr(void)250 LRMI_base_addr(void)
251 {
252 	return (size_t)mmap_addr;
253 }
254