summaryrefslogtreecommitdiff
path: root/src/lrmi
diff options
context:
space:
mode:
Diffstat (limited to 'src/lrmi')
-rw-r--r--src/lrmi/Makefile.am18
-rw-r--r--src/lrmi/backend-vm86.c219
-rw-r--r--src/lrmi/backend-x86emu.c292
-rw-r--r--src/lrmi/common.c247
-rw-r--r--src/lrmi/common.h30
5 files changed, 806 insertions, 0 deletions
diff --git a/src/lrmi/Makefile.am b/src/lrmi/Makefile.am
new file mode 100644
index 0000000..fd73483
--- /dev/null
+++ b/src/lrmi/Makefile.am
@@ -0,0 +1,18 @@
+lib_LTLIBRARIES = libx86.la
+
+if X86EMU
+BACKEND_SRC = backend-x86emu.c
+BACKEND_LIBRARY = $(top_srcdir)/src/x86emu/libx86emu.la
+BACKEND_INCLUDES = -I$(top_srcdir)/src/x86emu
+else # VM86
+BACKEND_SRC = backend-vm86.c
+BACKEND_LIBRARY = $(top_srcdir)/src/vm86/libvm86.la
+BACKEND_INCLUDES = -I$(top_srcdir)/src/vm86
+endif
+
+libx86_la_SOURCES = common.c $(BACKEND_SRC)
+libx86_la_LIBADD = $(BACKEND_LIBRARY)
+INCLUDES = -I$(top_srcdir)/include $(BACKEND_INCLUDES)
+
+libx86includedir = $(includedir)
+libx86include_HEADERS = $(top_srcdir)/include/libx86.h
diff --git a/src/lrmi/backend-vm86.c b/src/lrmi/backend-vm86.c
new file mode 100644
index 0000000..29342b1
--- /dev/null
+++ b/src/lrmi/backend-vm86.c
@@ -0,0 +1,219 @@
+/*
+Linux Real Mode Interface - A library of DPMI-like functions for Linux.
+
+Copyright (C) 1998 by Josh Vanderhoof
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included 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 OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL JOSH VANDERHOOF BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#if defined(__i386__) && (defined(__linux__) || defined(__NetBSD__) \
+ || defined(__FreeBSD__) || defined(__OpenBSD__))
+
+#include <string.h>
+#include "libx86.h"
+#include "common.h"
+#include "vm86.h"
+
+#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)
+#endif
+#define DEFAULT_STACK_SIZE 0x1000
+
+extern vm86context context;
+
+static inline void
+set_bit(unsigned int bit, void *array)
+{
+ unsigned char *a = array;
+
+ a[bit / 8] |= (1 << (bit % 8));
+}
+
+int
+LRMI_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__) || 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 void
+set_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 void
+get_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);
+}
+
+int
+LRMI_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;
+}
+
+int
+LRMI_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;
+}
+
+size_t
+LRMI_base_addr(void)
+{
+ return 0;
+}
+
+#else /* (__linux__ || __NetBSD__ || __FreeBSD__ || __OpenBSD__) && __i386__ */
+#warning "LRMI is not supported on your system!"
+#endif
diff --git a/src/lrmi/backend-x86emu.c b/src/lrmi/backend-x86emu.c
new file mode 100644
index 0000000..3e2a7b0
--- /dev/null
+++ b/src/lrmi/backend-x86emu.c
@@ -0,0 +1,292 @@
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include "x86emu.h"
+#include "libx86.h"
+#include "common.h"
+
+#define M _X86EMU_env
+
+#define X86_EAX _X86EMU_env.x86.R_EAX
+#define X86_EBX _X86EMU_env.x86.R_EBX
+#define X86_ECX _X86EMU_env.x86.R_ECX
+#define X86_EDX _X86EMU_env.x86.R_EDX
+#define X86_ESI _X86EMU_env.x86.R_ESI
+#define X86_EDI _X86EMU_env.x86.R_EDI
+#define X86_EBP _X86EMU_env.x86.R_EBP
+#define X86_EIP _X86EMU_env.x86.R_EIP
+#define X86_ESP _X86EMU_env.x86.R_ESP
+#define X86_EFLAGS _X86EMU_env.x86.R_EFLG
+
+#define X86_FLAGS _X86EMU_env.x86.R_FLG
+#define X86_AX _X86EMU_env.x86.R_AX
+#define X86_BX _X86EMU_env.x86.R_BX
+#define X86_CX _X86EMU_env.x86.R_CX
+#define X86_DX _X86EMU_env.x86.R_DX
+#define X86_SI _X86EMU_env.x86.R_SI
+#define X86_DI _X86EMU_env.x86.R_DI
+#define X86_BP _X86EMU_env.x86.R_BP
+#define X86_IP _X86EMU_env.x86.R_IP
+#define X86_SP _X86EMU_env.x86.R_SP
+#define X86_CS _X86EMU_env.x86.R_CS
+#define X86_DS _X86EMU_env.x86.R_DS
+#define X86_ES _X86EMU_env.x86.R_ES
+#define X86_SS _X86EMU_env.x86.R_SS
+#define X86_FS _X86EMU_env.x86.R_FS
+#define X86_GS _X86EMU_env.x86.R_GS
+
+#define X86_AL _X86EMU_env.x86.R_AL
+#define X86_BL _X86EMU_env.x86.R_BL
+#define X86_CL _X86EMU_env.x86.R_CL
+#define X86_DL _X86EMU_env.x86.R_DL
+
+#define X86_AH _X86EMU_env.x86.R_AH
+#define X86_BH _X86EMU_env.x86.R_BH
+#define X86_CH _X86EMU_env.x86.R_CH
+#define X86_DH _X86EMU_env.x86.R_DH
+
+
+#define CARD8 unsigned char
+#define CARD16 unsigned short
+#define CARD32 unsigned long
+#define pointer void *
+#define IOADDRESS void *
+#define Bool int
+
+#define X86_TF_MASK 0x00000100
+#define X86_IF_MASK 0x00000200
+#define X86_IOPL_MASK 0x00003000
+#define X86_NT_MASK 0x00004000
+#define X86_VM_MASK 0x00020000
+#define X86_AC_MASK 0x00040000
+#define X86_VIF_MASK 0x00080000 /* virtual interrupt flag */
+#define X86_VIP_MASK 0x00100000 /* virtual interrupt pending */
+#define X86_ID_MASK 0x00200000
+
+#define MEM_RB(name, addr) (*name->mem->rb)(name, addr)
+#define MEM_RW(name, addr) (*name->mem->rw)(name, addr)
+#define MEM_RL(name, addr) (*name->mem->rl)(name, addr)
+#define MEM_WB(name, addr, val) (*name->mem->wb)(name, addr, val)
+#define MEM_WW(addr, val) wrw(addr, val)
+#define MEM_WL(name, addr, val) (*name->mem->wl)(name, addr, val)
+
+
+#define SHMERRORPTR (pointer)(-1)
+
+#define __BUILDIO(bwl,bw,type) \
+static inline void out##bwl##_local(unsigned long port, unsigned type value) { __asm__ __volatile__("out" #bwl " %" #bw "0, %w1" : : "a"(value), "Nd"(port)); \
+}\
+static inline unsigned type in##bwl##_local(unsigned long port) { \
+ unsigned type value; \
+ __asm__ __volatile__("in" #bwl " %w1, %" #bw "0" : "=a"(value) : "Nd"(port)); \
+ return value; \
+}\
+
+__BUILDIO(b,b,char)
+__BUILDIO(w,w,short)
+__BUILDIO(l,,int)
+
+
+char *mmap_addr = SHMERRORPTR;
+struct LRMI_regs *regs;
+static void *stack;
+
+
+void
+printk(const char *fmt, ...)
+{
+ va_list argptr;
+ va_start(argptr, fmt);
+
+ fprintf(stderr, fmt, argptr);
+ va_end(argptr);
+}
+
+u8 read_b(int addr) {
+ return *((char *)mmap_addr + addr);
+}
+
+CARD8
+x_inb(CARD16 port)
+{
+ CARD8 val;
+ val = inb_local(port);
+ return val;
+}
+
+CARD16
+x_inw(CARD16 port)
+{
+ CARD16 val;
+ val = inw_local(port);
+ return val;
+}
+
+CARD32
+x_inl(CARD16 port)
+{
+ CARD32 val;
+ val = inl_local(port);
+ return val;
+}
+
+void
+x_outb(CARD16 port, CARD8 val)
+{
+ outb_local(port, val);
+}
+
+void
+x_outw(CARD16 port, CARD16 val)
+{
+ outw_local(port, val);
+}
+
+void x_outl(CARD16 port, CARD32 val)
+{
+ outl_local(port, val);
+}
+
+void pushw(u16 val)
+{
+ X86_ESP -= 2;
+ MEM_WW(((u32) X86_SS << 4) + X86_SP, val);
+}
+
+static void x86emu_do_int(int num)
+{
+ u32 eflags;
+
+ /* fprintf(stderr, "Calling INT 0x%X (%04X:%04X)\n", num,
+ (read_b((num << 2) + 3) << 8) + read_b((num << 2) + 2),
+ (read_b((num << 2) + 1) << 8) + read_b((num << 2)));
+
+ fprintf(stderr, " EAX is %X\n", (int) X86_EAX);
+ */
+
+ eflags = X86_EFLAGS;
+ eflags = eflags | X86_IF_MASK;
+ pushw(eflags);
+ pushw(X86_CS);
+ pushw(X86_IP);
+ X86_EFLAGS = X86_EFLAGS & ~(X86_VIF_MASK | X86_TF_MASK);
+ X86_CS = (read_b((num << 2) + 3) << 8) + read_b((num << 2) + 2);
+ X86_IP = (read_b((num << 2) + 1) << 8) + read_b((num << 2));
+
+ /* fprintf(stderr, "Leaving interrupt call.\n"); */
+}
+
+int LRMI_init() {
+ int i;
+ X86EMU_intrFuncs intFuncs[256];
+
+ if (!LRMI_common_init())
+ return 0;
+
+ mmap_addr = 0;
+
+ X86EMU_pioFuncs pioFuncs = {
+ (&x_inb),
+ (&x_inw),
+ (&x_inl),
+ (&x_outb),
+ (&x_outw),
+ (&x_outl)
+ };
+
+ X86EMU_setupPioFuncs(&pioFuncs);
+
+ for (i=0;i<256;i++)
+ intFuncs[i] = x86emu_do_int;
+ X86EMU_setupIntrFuncs(intFuncs);
+
+ X86_EFLAGS = X86_IF_MASK | X86_IOPL_MASK;
+
+ /*
+ * Allocate a 64k stack.
+ */
+ stack = LRMI_alloc_real(64 * 1024);
+ X86_SS = (unsigned int) stack >> 4;
+ X86_ESP = 0xFFF9;
+ memset (stack, 0, 64*1024);
+
+ *((char *)0) = 0x4f; /* Make sure that we end up jumping back to a
+ halt instruction */
+
+ M.mem_base = 0;
+ M.mem_size = 1024*1024;
+
+ return 1;
+}
+
+int real_call(struct LRMI_regs *registers) {
+ regs = registers;
+
+ X86_EAX = registers->eax;
+ X86_EBX = registers->ebx;
+ X86_ECX = registers->ecx;
+ X86_EDX = registers->edx;
+ X86_ESI = registers->esi;
+ X86_EDI = registers->edi;
+ X86_EBP = registers->ebp;
+ X86_EIP = registers->ip;
+ X86_ES = registers->es;
+ X86_FS = registers->fs;
+ X86_GS = registers->gs;
+ X86_CS = registers->cs;
+
+ if (registers->ss != 0) {
+ X86_SS = registers->ss;
+ } else {
+ X86_SS = (unsigned int) stack >> 4;
+ }
+
+ if (registers->ds != 0) {
+ X86_DS = registers->ds;
+ }
+
+ if (registers->sp != 0) {
+ X86_ESP = registers->sp;
+ } else {
+ X86_ESP = 0xFFF9;
+ }
+
+ M.x86.debug |= DEBUG_DECODE_F;
+
+ memset (stack, 0, 64*1024);
+
+ X86EMU_exec();
+
+ registers->eax = X86_EAX;
+ registers->ebx = X86_EBX;
+ registers->ecx = X86_ECX;
+ registers->edx = X86_EDX;
+ registers->esi = X86_ESI;
+ registers->edi = X86_EDI;
+ registers->ebp = X86_EBP;
+ registers->es = X86_ES;
+
+ return 1;
+}
+
+int LRMI_int(int num, struct LRMI_regs *registers) {
+ u32 eflags;
+ eflags = X86_EFLAGS;
+ eflags = eflags | X86_IF_MASK;
+ X86_EFLAGS = X86_EFLAGS & ~(X86_VIF_MASK | X86_TF_MASK | X86_IF_MASK | X86_NT_MASK);
+
+ registers->cs = (read_b((num << 2) + 3) << 8) + read_b((num << 2) + 2);
+ registers->ip = (read_b((num << 2) + 1) << 8) + read_b((num << 2));
+ regs = registers;
+ return real_call(registers);
+}
+
+int LRMI_call(struct LRMI_regs *registers) {
+ return real_call(registers);
+}
+
+size_t
+LRMI_base_addr(void)
+{
+ return (size_t)mmap_addr;
+}
diff --git a/src/lrmi/common.c b/src/lrmi/common.c
new file mode 100644
index 0000000..85c744c
--- /dev/null
+++ b/src/lrmi/common.c
@@ -0,0 +1,247 @@
+/*
+Linux Real Mode Interface - A library of DPMI-like functions for Linux.
+
+Copyright (C) 1998 by Josh Vanderhoof
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included 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 OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL JOSH VANDERHOOF BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "libx86.h"
+
+#define REAL_MEM_BASE ((void *)0x01000)
+#define REAL_MEM_SIZE 0xa0000
+#define REAL_MEM_BLOCKS 0x100
+
+struct 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 int
+read_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 int
+map_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 int
+real_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 void
+real_mem_deinit(void)
+{
+ if (mem_info.ready) {
+ munmap((void *)REAL_MEM_BASE, REAL_MEM_SIZE);
+ mem_info.ready = 0;
+ }
+}
+
+static void
+insert_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 void
+delete_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;
+}
+
+
+void
+LRMI_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);
+ }
+}
+
+int LRMI_common_init(void)
+{
+ void *m;
+ int fd_mem;
+
+ 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;
+ }
+
+ close(fd_mem);
+
+ return 1;
+}
diff --git a/src/lrmi/common.h b/src/lrmi/common.h
new file mode 100644
index 0000000..99bf883
--- /dev/null
+++ b/src/lrmi/common.h
@@ -0,0 +1,30 @@
+/*
+Common routines for x86emu/lrmi interfaces. Taken from lrmi.c.
+
+Copyright (C) 1998 by Josh Vanderhoof
+Copyright (C) 2005 by Jonathan McDowell <noodles@earth.li>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included 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 OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL JOSH VANDERHOOF BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+
+void *LRMI_alloc_real(int size);
+void LRMI_free_real(void *m);
+int LRMI_common_init(void);