Initial. Don't... just don't ask.

This commit is contained in:
Ryan McGrath 2011-02-24 00:22:00 -08:00
commit 00bae13bba
586 changed files with 129057 additions and 0 deletions

41
lrmi-0.6m/Makefile Normal file
View file

@ -0,0 +1,41 @@
CFLAGS ?= -g -Wall
sources = lrmi.c
objects = lrmi.o
all = vbetest mode3 vga_reset vbemodeinfo dosint
%.o: %.c
$(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $<
all: $(all)
vbetest: vbetest.c lrmi.o
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $^
mode3: mode3.c lrmi.o
$(CC) $(CFLAGS) -o $@ $^
dosint: dosint.c lrmi.o
$(CC) $(CFLAGS) -o $@ $^
vbemodeinfo: vbemodeinfo.c lrmi.o
$(CC) $(CFLAGS) -o $@ $^
vga_reset: vga_reset.c lrmi.o
$(CC) $(CFLAGS) -o $@ $^
install: mode3 vga_reset
install mode3 /sbin
install vga_reset /sbin
.PHONY: clean
clean:
rm -f $(objects) $(all) core regs-out *.bak
.PHONY: distclean
distclean: clean
rm -f .depend
.PHONY: depend
depend: $(sources)
-$(CC) -M $(CPPFLAGS) $^ >.depend

13
lrmi-0.6m/README Normal file
View file

@ -0,0 +1,13 @@
This is a modified version of Josh Vanderhoof's lrmi-0.5 package
The original is available at http://www.planet.net/pjoshv/
vbetest - show available modes, and test a mode
mode3 - set mode using vesa bios. It can usually restore text mode after
svgalib leaves a non-working text-mode.
vga_reset - call real mode c000:0003, which should be the video card's
initialization routine. Should work in some cases when mode3 fails to
restore text mode.

51
lrmi-0.6m/dosint.c Normal file
View file

@ -0,0 +1,51 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "lrmi.h"
unsigned char * edid = NULL;
int read_edid()
{
int i;
struct LRMI_regs regs;
if (!LRMI_init()) {
return -1;
}
edid = LRMI_alloc_real(128);
if ( edid == NULL )
{
return -1;
}
memset(edid, 0xed, 128);
memset(&regs, 0, sizeof(regs));
regs.es = (unsigned int)edid >> 4;
regs.edi = 0;
regs.eax = 0x4f15;
regs.ebx = 0x01;
ioperm(0,0x400,1);
iopl(3);
LRMI_int( 0x10, &regs );
iopl(0);
ioperm(0,0x400,0);
if(*edid || *(edid+7)) return -2;
for(i=1;i<=6;i++) if(*(edid+i)!=0xff) return -2;
return regs.eax;
}
int main ( int argc, char *argv[])
{
read_edid();
fwrite(edid,128,1,stdout);
}

2
lrmi-0.6m/get-edid Executable file
View file

@ -0,0 +1,2 @@
#!/bin/sh
./dosint 0x10 0x4f15 0x0001 0x80

945
lrmi-0.6m/lrmi.c Normal file
View file

@ -0,0 +1,945 @@
#define DEBUG 0
/*
Linux Real Mode Interface - A library of DPMI-like functions for Linux.
Copyright (C) 1998 by Josh Vanderhoof
You are free to distribute and modify this file, as long as you
do not remove this copyright notice and clearly label modified
versions as being modified.
This software has NO WARRANTY. Use it at your own risk.
*/
#include <stdio.h>
#include <string.h>
#include <asm/vm86.h>
#ifdef USE_LIBC_VM86
#include <sys/vm86.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 0x10000
#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
real_mem_init(void)
{
void *m;
int fd_zero;
if (mem_info.ready)
return 1;
fd_zero = open("/dev/zero", O_RDONLY);
if (fd_zero == -1)
{
perror("open /dev/zero");
return 0;
}
m = mmap((void *)REAL_MEM_BASE, REAL_MEM_SIZE,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE, fd_zero, 0);
if (m == (void *)-1)
{
perror("mmap /dev/zero");
close(fd_zero);
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
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);
}
}
#define DEFAULT_VM86_FLAGS (IF_MASK | IOPL_MASK)
#define DEFAULT_STACK_SIZE 0x1000
#define RETURN_TO_32_INT 255
static struct
{
int ready;
unsigned short ret_seg, ret_off;
unsigned short stack_seg, stack_off;
struct vm86_struct vm;
} context = { 0 };
static inline void
set_bit(unsigned int bit, void *array)
{
unsigned char *a = array;
a[bit / 8] |= (1 << (bit % 8));
}
static inline unsigned int
get_int_seg(int i)
{
return *(unsigned short *)(i * 4 + 2);
}
static inline unsigned int
get_int_off(int i)
{
return *(unsigned short *)(i * 4);
}
static inline void
pushw(unsigned short i)
{
struct vm86_regs *r = &context.vm.regs;
r->esp -= 2;
*(unsigned short *)(((unsigned int)r->ss << 4) + r->esp) = i;
}
int
LRMI_init(void)
{
void *m;
int fd_mem;
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)
*/
fd_mem = open("/dev/mem", O_RDWR);
if (fd_mem == -1)
{
perror("open /dev/mem");
return 0;
}
m = mmap((void *)0, 0x502,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE, fd_mem, 0);
if (m == (void *)-1)
{
perror("mmap /dev/mem");
return 0;
}
m = mmap((void *)0xa0000, 0x100000 - 0xa0000,
PROT_READ | PROT_WRITE,
MAP_FIXED | MAP_SHARED, fd_mem, 0xa0000);
if (m == (void *)-1)
{
perror("mmap /dev/mem");
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));
context.vm.cpu_type=CPU_386;
/*
Enable kernel emulation of all ints except RETURN_TO_32_INT
*/
memset(&context.vm.int_revectored, 0, sizeof(context.vm.int_revectored));
set_bit(RETURN_TO_32_INT, &context.vm.int_revectored);
context.ready = 1;
return 1;
}
static void
set_regs(struct LRMI_regs *r)
{
context.vm.regs.edi = r->edi;
context.vm.regs.esi = r->esi;
context.vm.regs.ebp = r->ebp;
context.vm.regs.ebx = r->ebx;
context.vm.regs.edx = r->edx;
context.vm.regs.ecx = r->ecx;
context.vm.regs.eax = r->eax;
context.vm.regs.eflags = DEFAULT_VM86_FLAGS;
context.vm.regs.es = r->es;
context.vm.regs.ds = r->ds;
context.vm.regs.fs = r->fs;
context.vm.regs.gs = r->gs;
}
static void
get_regs(struct LRMI_regs *r)
{
r->edi = context.vm.regs.edi;
r->esi = context.vm.regs.esi;
r->ebp = context.vm.regs.ebp;
r->ebx = context.vm.regs.ebx;
r->edx = context.vm.regs.edx;
r->ecx = context.vm.regs.ecx;
r->eax = context.vm.regs.eax;
r->flags = context.vm.regs.eflags;
r->es = context.vm.regs.es;
r->ds = context.vm.regs.ds;
r->fs = context.vm.regs.fs;
r->gs = context.vm.regs.gs;
}
#define DIRECTION_FLAG (1 << 10)
static void
em_ins(int size)
{
unsigned int edx, edi;
edx = context.vm.regs.edx & 0xffff;
edi = context.vm.regs.edi & 0xffff;
edi += (unsigned int)context.vm.regs.ds << 4;
if (context.vm.regs.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.vm.regs.ds << 4;
context.vm.regs.edi &= 0xffff0000;
context.vm.regs.edi |= edi & 0xffff;
}
static void
em_rep_ins(int size)
{
unsigned int ecx, edx, edi;
ecx = context.vm.regs.ecx & 0xffff;
edx = context.vm.regs.edx & 0xffff;
edi = context.vm.regs.edi & 0xffff;
edi += (unsigned int)context.vm.regs.ds << 4;
if (context.vm.regs.eflags & DIRECTION_FLAG)
{
if (size == 4)
asm volatile ("std; rep; insl; cld"
: "=D" (edi), "=c" (ecx)
: "d" (edx), "0" (edi), "1" (ecx));
else if (size == 2)
asm volatile ("std; rep; insw; cld"
: "=D" (edi), "=c" (ecx)
: "d" (edx), "0" (edi), "1" (ecx));
else
asm volatile ("std; rep; insb; cld"
: "=D" (edi), "=c" (ecx)
: "d" (edx), "0" (edi), "1" (ecx));
}
else
{
if (size == 4)
asm volatile ("cld; rep; insl"
: "=D" (edi), "=c" (ecx)
: "d" (edx), "0" (edi), "1" (ecx));
else if (size == 2)
asm volatile ("cld; rep; insw"
: "=D" (edi), "=c" (ecx)
: "d" (edx), "0" (edi), "1" (ecx));
else
asm volatile ("cld; rep; insb"
: "=D" (edi), "=c" (ecx)
: "d" (edx), "0" (edi), "1" (ecx));
}
edi -= (unsigned int)context.vm.regs.ds << 4;
context.vm.regs.edi &= 0xffff0000;
context.vm.regs.edi |= edi & 0xffff;
context.vm.regs.ecx &= 0xffff0000;
context.vm.regs.ecx |= ecx & 0xffff;
}
static void
em_outs(int size)
{
unsigned int edx, esi;
edx = context.vm.regs.edx & 0xffff;
esi = context.vm.regs.esi & 0xffff;
esi += (unsigned int)context.vm.regs.ds << 4;
if (context.vm.regs.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 -= (unsigned int)context.vm.regs.ds << 4;
context.vm.regs.esi &= 0xffff0000;
context.vm.regs.esi |= esi & 0xffff;
}
static void
em_rep_outs(int size)
{
unsigned int ecx, edx, esi;
ecx = context.vm.regs.ecx & 0xffff;
edx = context.vm.regs.edx & 0xffff;
esi = context.vm.regs.esi & 0xffff;
esi += (unsigned int)context.vm.regs.ds << 4;
if (context.vm.regs.eflags & DIRECTION_FLAG)
{
if (size == 4)
asm volatile ("std; rep; outsl; cld"
: "=S" (esi), "=c" (ecx)
: "d" (edx), "0" (esi), "1" (ecx));
else if (size == 2)
asm volatile ("std; rep; outsw; cld"
: "=S" (esi), "=c" (ecx)
: "d" (edx), "0" (esi), "1" (ecx));
else
asm volatile ("std; rep; outsb; cld"
: "=S" (esi), "=c" (ecx)
: "d" (edx), "0" (esi), "1" (ecx));
}
else
{
if (size == 4)
asm volatile ("cld; rep; outsl"
: "=S" (esi), "=c" (ecx)
: "d" (edx), "0" (esi), "1" (ecx));
else if (size == 2)
asm volatile ("cld; rep; outsw"
: "=S" (esi), "=c" (ecx)
: "d" (edx), "0" (esi), "1" (ecx));
else
asm volatile ("cld; rep; outsb"
: "=S" (esi), "=c" (ecx)
: "d" (edx), "0" (esi), "1" (ecx));
}
esi -= (unsigned int)context.vm.regs.ds << 4;
context.vm.regs.esi &= 0xffff0000;
context.vm.regs.esi |= esi & 0xffff;
context.vm.regs.ecx &= 0xffff0000;
context.vm.regs.ecx |= ecx & 0xffff;
}
static void
em_inb(int port)
{
asm volatile ("inb (%w1), %b0"
: "=a" (context.vm.regs.eax)
: "d" (port));
#if DEBUG
printf("inb %04x %02x\n",context.vm.regs.edx,context.vm.regs.eax);
#endif
}
static void
em_inw(int port)
{
asm volatile ("inw (%w1), %w0"
: "=a" (context.vm.regs.eax)
: "d" (port));
#if DEBUG
printf("inw %04x %04x\n",context.vm.regs.edx,context.vm.regs.eax);
#endif
}
static void
em_inl(int port)
{
asm volatile ("inl (%w1), %0"
: "=a" (context.vm.regs.eax)
: "d" (port));
#if DEBUG
printf("inl %04x %08x\n",context.vm.regs.edx,context.vm.regs.eax);
#endif
}
static void
em_outb(int port)
{
asm volatile ("outb %b0, (%w1)"
: : "a" (context.vm.regs.eax),
"d" (port));
#if DEBUG
printf("outb %04x %02x\n",context.vm.regs.edx,context.vm.regs.eax);
#endif
}
static void
em_outw(int port)
{
asm volatile ("outw %w0, (%w1)"
: : "a" (context.vm.regs.eax),
"d" (port));
#if DEBUG
printf("outw %04x %02x\n",context.vm.regs.edx,context.vm.regs.eax);
#endif
}
static void
em_outl(int port)
{
asm volatile ("outl %0, (%w1)"
: : "a" (context.vm.regs.eax),
"d" (port));
#if DEBUG
printf("outl %04x %08x\n",context.vm.regs.edx,context.vm.regs.eax);
#endif
}
static int
emulate(void)
{
unsigned char *insn;
struct
{
unsigned int size : 1;
unsigned int rep : 1;
} prefix = { 0, 0 };
int i = 0;
insn = (unsigned char *)((unsigned int)context.vm.regs.cs << 4);
insn += context.vm.regs.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] == 0xf0 || insn[i] == 0xf2
|| insn[i] == 0x26 || insn[i] == 0x2e
|| insn[i] == 0x36 || insn[i] == 0x3e
|| insn[i] == 0x64 || insn[i] == 0x65
|| 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);
else
em_outs(1);
i++;
break;
}
else if (insn[i] == 0x6f)
{
if (prefix.rep)
{
if (prefix.size)
em_rep_outs(4);
else
em_rep_outs(2);
}
else
{
if (prefix.size)
em_outs(4);
else
em_outs(2);
}
i++;
break;
}
else if (insn[i] == 0xe4)
{
i++;
em_inb(insn[i]);
i++;
break;
}
else if (insn[i] == 0xe5)
{
i++;
if (prefix.size)
em_inl(insn[i]);
else
em_inw(insn[i]);
i++;
break;
}
else if (insn[i] == 0xe6)
{
i++;
em_outb(insn[i]);
i++;
break;
}
else if (insn[i] == 0xe7)
{
i++;
if (prefix.size)
em_outl(insn[i]);
else
em_outw(insn[i]);
i++;
break;
}
else if (insn[i] == 0xec)
{
em_inb(context.vm.regs.edx);
i++;
break;
}
else if (insn[i] == 0xed)
{
if (prefix.size)
em_inl(context.vm.regs.edx);
else
em_inw(context.vm.regs.edx);
i++;
break;
}
else if (insn[i] == 0xee)
{
em_outb(context.vm.regs.edx);
i++;
break;
}
else if (insn[i] == 0xef)
{
if (prefix.size)
em_outl(context.vm.regs.edx);
else
em_outw(context.vm.regs.edx);
i++;
break;
}
else
return 0;
}
context.vm.regs.eip += i;
return 1;
}
/*
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 int
lrmi_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
static void
debug_info(int vret)
{
int i;
unsigned char *p;
fputs("vm86() failed\n", stderr);
fprintf(stderr, "return = 0x%x\n", vret);
fprintf(stderr, "eax = 0x%08lx\n", context.vm.regs.eax);
fprintf(stderr, "ebx = 0x%08lx\n", context.vm.regs.ebx);
fprintf(stderr, "ecx = 0x%08lx\n", context.vm.regs.ecx);
fprintf(stderr, "edx = 0x%08lx\n", context.vm.regs.edx);
fprintf(stderr, "esi = 0x%08lx\n", context.vm.regs.esi);
fprintf(stderr, "edi = 0x%08lx\n", context.vm.regs.edi);
fprintf(stderr, "ebp = 0x%08lx\n", context.vm.regs.ebp);
fprintf(stderr, "eip = 0x%08lx\n", context.vm.regs.eip);
fprintf(stderr, "cs = 0x%04x\n", context.vm.regs.cs);
fprintf(stderr, "esp = 0x%08lx\n", context.vm.regs.esp);
fprintf(stderr, "ss = 0x%04x\n", context.vm.regs.ss);
fprintf(stderr, "ds = 0x%04x\n", context.vm.regs.ds);
fprintf(stderr, "es = 0x%04x\n", context.vm.regs.es);
fprintf(stderr, "fs = 0x%04x\n", context.vm.regs.fs);
fprintf(stderr, "gs = 0x%04x\n", context.vm.regs.gs);
fprintf(stderr, "eflags = 0x%08lx\n", context.vm.regs.eflags);
fputs("cs:ip = [ ", stderr);
p = (unsigned char *)((context.vm.regs.cs << 4) + (context.vm.regs.eip & 0xffff));
for (i = 0; i < 16; ++i)
fprintf(stderr, "%02x ", (unsigned int)p[i]);
fputs("]\n", stderr);
}
static int
run_vm86(void)
{
unsigned int vret;
while (1)
{
vret = lrmi_vm86(&context.vm);
if (VM86_TYPE(vret) == VM86_SIGNAL ||
VM86_TYPE(vret) == VM86_STI ||
VM86_TYPE(vret) == VM86_PICRETURN) {
context.vm.regs.eflags &= ~VIP_MASK;
continue;
}
if (VM86_TYPE(vret) == VM86_INTx)
{
unsigned int v = VM86_ARG(vret);
if (v == RETURN_TO_32_INT)
return 1;
pushw(context.vm.regs.eflags);
pushw(context.vm.regs.cs);
pushw(context.vm.regs.eip);
context.vm.regs.cs = get_int_seg(v);
context.vm.regs.eip = get_int_off(v);
context.vm.regs.eflags &= ~(VIF_MASK | TF_MASK);
continue;
}
if (VM86_TYPE(vret) != VM86_UNKNOWN)
break;
if (!emulate())
break;
}
debug_info(vret);
return 0;
}
int
LRMI_call(struct LRMI_regs *r)
{
unsigned int vret;
memset(&context.vm.regs, 0, sizeof(context.vm.regs));
set_regs(r);
context.vm.regs.cs = r->cs;
context.vm.regs.eip = r->ip;
if (r->ss == 0 && r->sp == 0)
{
context.vm.regs.ss = context.stack_seg;
context.vm.regs.esp = context.stack_off;
}
else
{
context.vm.regs.ss = r->ss;
context.vm.regs.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)
{
fprintf(stderr, "Int 0x%x is not in rom (%04x:%04x)\n", i, seg, off);
return 0;
}
memset(&context.vm.regs, 0, sizeof(context.vm.regs));
set_regs(r);
context.vm.regs.cs = seg;
context.vm.regs.eip = off;
if (r->ss == 0 && r->sp == 0)
{
context.vm.regs.ss = context.stack_seg;
context.vm.regs.esp = context.stack_off;
}
else
{
context.vm.regs.ss = r->ss;
context.vm.regs.esp = r->sp;
}
pushw(DEFAULT_VM86_FLAGS);
pushw(context.ret_seg);
pushw(context.ret_off);
vret = run_vm86();
get_regs(r);
return vret;
}

75
lrmi-0.6m/lrmi.h Normal file
View file

@ -0,0 +1,75 @@
/*
Linux Real Mode Interface - A library of DPMI-like functions for Linux.
Copyright (C) 1998 by Josh Vanderhoof
You are free to distribute and modify this file, as long as you
do not remove this copyright notice and clearly label modified
versions as being modified.
This software has NO WARRANTY. Use it at your own risk.
*/
#ifndef LRMI_H
#define LRMI_H
#if defined __GLIBC__ && __GLIBC__ >= 2
#include <sys/io.h>
#endif
struct LRMI_regs
{
unsigned int edi;
unsigned int esi;
unsigned int ebp;
unsigned int reserved;
unsigned int ebx;
unsigned int edx;
unsigned int ecx;
unsigned int eax;
unsigned short int flags;
unsigned short int es;
unsigned short int ds;
unsigned short int fs;
unsigned short int gs;
unsigned short int ip;
unsigned short int cs;
unsigned short int sp;
unsigned short int ss;
};
/*
Initialize
returns 1 if sucessful, 0 for failure
*/
int
LRMI_init(void);
/*
Simulate a 16 bit far call
returns 1 if sucessful, 0 for failure
*/
int
LRMI_call(struct LRMI_regs *r);
/*
Simulate a 16 bit interrupt
returns 1 if sucessful, 0 for failure
*/
int
LRMI_int(int interrupt, struct LRMI_regs *r);
/*
Allocate real mode memory
The returned block is paragraph (16 byte) aligned
*/
void *
LRMI_alloc_real(int size);
/*
Free real mode memory
*/
void
LRMI_free_real(void *m);
#endif

52
lrmi-0.6m/mode3.c Normal file
View file

@ -0,0 +1,52 @@
/*
Set mode to VESA mode 3 (80x25 text mode)
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/kd.h>
#include <sys/stat.h>
#include "lrmi.h"
void set_vesa_mode(int mode){
struct LRMI_regs r;
memset(&r, 0, sizeof(r));
r.eax = 0x4f02;
r.ebx = mode;
if (!LRMI_int(0x10, &r))
{
fprintf(stderr, "Can't set video mode (vm86 failure)\n");
}
}
int main(int argc, char *argv[]){
int i;
if((argc>1)&&(!strcmp(argv[1],"-h"))){
printf("Usage: mode3 [ modenum [ font ] ]\n"
"\n"
"uses VESA bios to set video mode to modenum (3 by default)\n"
"if font is given, uses setfont to change the screen font\n\n");
return 0;
};
if (!LRMI_init())
return 1;
ioperm(0, 0x400, 1);
iopl(3);
i=3;
if(argc>1){
sscanf(argv[1],"%i",&i);
if((i<=0))i=3;
};
set_vesa_mode(i);
if(argc>2){
execlp("setfont",argv[2],NULL);
return 1;
};
return 0;
}

104
lrmi-0.6m/vbe.h Normal file
View file

@ -0,0 +1,104 @@
/*
Copyright (C) 1996 by Josh Vanderhoof
You are free to distribute and modify this file, as long as you
do not remove this copyright notice and clearly label modified
versions as being modified.
This software has NO WARRANTY. Use it at your own risk.
*/
#ifndef _VBE_H
#define _VBE_H
/* structures for vbe 2.0 */
struct vbe_info_block
{
char vbe_signature[4];
short vbe_version;
unsigned short oem_string_off;
unsigned short oem_string_seg;
int capabilities;
unsigned short video_mode_list_off;
unsigned short video_mode_list_seg;
short total_memory;
short oem_software_rev;
unsigned short oem_vendor_name_off;
unsigned short oem_vendor_name_seg;
unsigned short oem_product_name_off;
unsigned short oem_product_name_seg;
unsigned short oem_product_rev_off;
unsigned short oem_product_rev_seg;
char reserved[222];
char oem_data[256];
} __attribute__ ((packed));
#define VBE_ATTR_MODE_SUPPORTED (1 << 0)
#define VBE_ATTR_TTY (1 << 2)
#define VBE_ATTR_COLOR (1 << 3)
#define VBE_ATTR_GRAPHICS (1 << 4)
#define VBE_ATTR_NOT_VGA (1 << 5)
#define VBE_ATTR_NOT_WINDOWED (1 << 6)
#define VBE_ATTR_LINEAR (1 << 7)
#define VBE_WIN_RELOCATABLE (1 << 0)
#define VBE_WIN_READABLE (1 << 1)
#define VBE_WIN_WRITEABLE (1 << 2)
#define VBE_MODEL_TEXT 0
#define VBE_MODEL_CGA 1
#define VBE_MODEL_HERCULES 2
#define VBE_MODEL_PLANAR 3
#define VBE_MODEL_PACKED 4
#define VBE_MODEL_256 5
#define VBE_MODEL_RGB 6
#define VBE_MODEL_YUV 7
struct vbe_mode_info_block
{
unsigned short mode_attributes;
unsigned char win_a_attributes;
unsigned char win_b_attributes;
unsigned short win_granularity;
unsigned short win_size;
unsigned short win_a_segment;
unsigned short win_b_segment;
unsigned short win_func_ptr_off;
unsigned short win_func_ptr_seg;
unsigned short bytes_per_scanline;
unsigned short x_resolution;
unsigned short y_resolution;
unsigned char x_char_size;
unsigned char y_char_size;
unsigned char number_of_planes;
unsigned char bits_per_pixel;
unsigned char number_of_banks;
unsigned char memory_model;
unsigned char bank_size;
unsigned char number_of_image_pages;
unsigned char res1;
unsigned char red_mask_size;
unsigned char red_field_position;
unsigned char green_mask_size;
unsigned char green_field_position;
unsigned char blue_mask_size;
unsigned char blue_field_position;
unsigned char rsvd_mask_size;
unsigned char rsvd_field_position;
unsigned char direct_color_mode_info;
unsigned int phys_base_ptr;
unsigned int offscreen_mem_offset;
unsigned short offscreen_mem_size;
unsigned char res2[206];
} __attribute__ ((packed));
struct vbe_palette_entry
{
unsigned char blue;
unsigned char green;
unsigned char red;
unsigned char align;
} __attribute__ ((packed));
#endif

132
lrmi-0.6m/vbemodeinfo.c Normal file
View file

@ -0,0 +1,132 @@
/*
List the available VESA graphics and text modes.
This program is in the public domain.
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/kd.h>
#include <sys/stat.h>
#include "lrmi.h"
#include "vbe.h"
struct
{
struct vbe_info_block *info;
struct vbe_mode_info_block *mode;
} vbe;
int
main(int argc, char *argv[]) {
struct LRMI_regs r;
int mode;
if((argc!=2)||((mode=atoi(argv[1]))==0)){
printf("usage: vbemodeinfo <mode>\n"
"where <mode> is a vesa mode numder.\n"
"use vbetest to list available modes\n\n");
return 0;
};
if (!LRMI_init())
return 1;
vbe.info = LRMI_alloc_real(sizeof(struct vbe_info_block)
+ sizeof(struct vbe_mode_info_block));
if (vbe.info == NULL) {
fprintf(stderr, "Can't alloc real mode memory\n");
return 1;
}
vbe.mode = (struct vbe_mode_info_block *)(vbe.info + 1);
/*
Allow read/write to all IO ports
*/
ioperm(0, 0x400 , 1);
iopl(3);
memset(&r, 0, sizeof(r));
r.eax = 0x4f00;
r.es = (unsigned int)vbe.info >> 4;
r.edi = 0;
memcpy(vbe.info->vbe_signature, "VBE2", 4);
if (!LRMI_int(0x10, &r)) {
fprintf(stderr, "Can't get VESA info (vm86 failure)\n");
return 1;
}
if ((r.eax & 0xffff) != 0x4f || strncmp(vbe.info->vbe_signature, "VESA", 4) != 0) {
fprintf(stderr, "No VESA bios\n");
return 1;
}
printf("VBE Version %x.%x\n",
(int)(vbe.info->vbe_version >> 8) & 0xff,
(int)vbe.info->vbe_version & 0xff);
printf("%s\n",
(char *)(vbe.info->oem_string_seg * 16 + vbe.info->oem_string_off));
memset(&r, 0, sizeof(r));
r.eax = 0x4f01;
r.ecx = mode;
r.es = (unsigned int)vbe.mode >> 4;
r.edi = (unsigned int)vbe.mode & 0xf;
if (!LRMI_int(0x10, &r)) {
fprintf(stderr, "Can't get mode info (vm86 failure)\n");
return 1;
}
printf("mode %i\n",mode);
printf ("mode_attributes = %i\n", vbe.mode->mode_attributes);
printf ("win_a_attributes = %i\n", vbe.mode->win_a_attributes);
printf ("win_b_attributes = %i\n", vbe.mode->win_b_attributes);
printf ("win_granularity = %i\n", vbe.mode->win_granularity);
printf ("win_size = %i\n", vbe.mode->win_size);
printf ("win_a_segment = %i\n", vbe.mode->win_a_segment);
printf ("win_b_segment = %i\n", vbe.mode->win_b_segment);
printf ("win_func_ptr_off = %i\n", vbe.mode->win_func_ptr_off);
printf ("win_func_ptr_seg = %i\n", vbe.mode->win_func_ptr_seg);
printf ("bytes_per_scanline = %i\n", vbe.mode->bytes_per_scanline);
printf ("x_resolution = %i\n", vbe.mode->x_resolution);
printf ("y_resolution = %i\n", vbe.mode->y_resolution);
printf ("x_char_size = %i\n", vbe.mode->x_char_size);
printf ("y_char_size = %i\n", vbe.mode->y_char_size);
printf ("number_of_planes = %i\n", vbe.mode->number_of_planes);
printf ("bits_per_pixel = %i\n", vbe.mode->bits_per_pixel);
printf ("number_of_banks = %i\n", vbe.mode->number_of_banks);
printf ("memory_model = %i\n", vbe.mode->memory_model);
printf ("bank_size = %i\n", vbe.mode->bank_size);
printf ("number_of_image_pages = %i\n", vbe.mode->number_of_image_pages);
printf ("res1 = %i\n", vbe.mode->res1);
printf ("red_mask_size = %i\n", vbe.mode->red_mask_size);
printf ("red_field_position = %i\n", vbe.mode->red_field_position);
printf ("green_mask_size = %i\n", vbe.mode->green_mask_size);
printf ("green_field_position = %i\n", vbe.mode->green_field_position);
printf ("blue_mask_size = %i\n", vbe.mode->blue_mask_size);
printf ("blue_field_position = %i\n", vbe.mode->blue_field_position);
printf ("rsvd_mask_size = %i\n", vbe.mode->rsvd_mask_size);
printf ("rsvd_field_position = %i\n", vbe.mode->rsvd_field_position);
printf ("direct_color_mode_info = %i\n", vbe.mode->direct_color_mode_info);
printf ("phys_base_ptr = %i\n", vbe.mode->phys_base_ptr);
printf ("offscreen_mem_offset = %i\n", vbe.mode->offscreen_mem_offset);
printf ("offscreen_mem_size = %i\n", vbe.mode->offscreen_mem_size);
LRMI_free_real(vbe.info);
return 0;
}

333
lrmi-0.6m/vbetest.c Normal file
View file

@ -0,0 +1,333 @@
/*
List the available VESA graphics and text modes.
This program is in the public domain.
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/kd.h>
#include <sys/stat.h>
#include "lrmi.h"
#include "vbe.h"
struct
{
struct vbe_info_block *info;
struct vbe_mode_info_block *mode;
} vbe;
void *
save_state(void)
{
struct LRMI_regs r;
void *buffer;
memset(&r, 0, sizeof(r));
r.eax = 0x4f04;
r.ecx = 0xf; /* all states */
r.edx = 0; /* get buffer size */
if (!LRMI_int(0x10, &r))
{
fprintf(stderr, "Can't get video state buffer size (vm86 failure)\n");
return NULL;
}
if ((r.eax & 0xffff) != 0x4f)
{
fprintf(stderr, "Get video state buffer size failed\n");
return NULL;
}
buffer = LRMI_alloc_real((r.ebx & 0xffff) * 64);
if (buffer == NULL)
{
fprintf(stderr, "Can't allocate video state buffer\n");
return NULL;
}
memset(&r, 0, sizeof(r));
r.eax = 0x4f04;
r.ecx = 0xf; /* all states */
r.edx = 1; /* save state */
r.es = (unsigned int)buffer >> 4;
r.ebx = (unsigned int)buffer & 0xf;
if (!LRMI_int(0x10, &r))
{
fprintf(stderr, "Can't save video state (vm86 failure)\n");
return NULL;
}
if ((r.eax & 0xffff) != 0x4f)
{
fprintf(stderr, "Save video state failed\n");
return NULL;
}
return buffer;
}
void
restore_state(void *buffer)
{
struct LRMI_regs r;
memset(&r, 0, sizeof(r));
r.eax = 0x4f04;
r.ecx = 0xf; /* all states */
r.edx = 2; /* restore state */
r.es = (unsigned int)buffer >> 4;
r.ebx = (unsigned int)buffer & 0xf;
if (!LRMI_int(0x10, &r))
{
fprintf(stderr, "Can't restore video state (vm86 failure)\n");
}
else if ((r.eax & 0xffff) != 0x4f)
{
fprintf(stderr, "Restore video state failed\n");
}
LRMI_free_real(buffer);
}
void
text_mode(void)
{
struct LRMI_regs r;
memset(&r, 0, sizeof(r));
r.eax = 3;
if (!LRMI_int(0x10, &r))
{
fprintf(stderr, "Can't set text mode (vm86 failure)\n");
}
}
void
set_mode(int n)
{
struct LRMI_regs r;
memset(&r, 0, sizeof(r));
r.eax = 0x4f02;
r.ebx = n;
if (!LRMI_int(0x10, &r))
{
fprintf(stderr, "Can't set video mode (vm86 failure)\n");
}
else if ((r.eax & 0xffff) != 0x4f)
{
fprintf(stderr, "Set video mode failed\n");
}
memset(&r, 0, sizeof(r));
r.eax = 0x4f01;
r.ecx = n;
r.es = (unsigned int)vbe.mode >> 4;
r.edi = (unsigned int)vbe.mode & 0xf;
if (!LRMI_int(0x10, &r))
{
fprintf(stderr, "Can't get mode info (vm86 failure)\n");
return;
}
if ((r.eax & 0xffff) != 0x4f)
{
fprintf(stderr, "Get mode info failed\n");
return;
}
/*
Draw a blue/red fade on top line
*/
if (vbe.mode->memory_model == VBE_MODEL_RGB)
{
char *p = (char *)(vbe.mode->win_a_segment << 4);
int pixel_size = (vbe.mode->bits_per_pixel + 7) / 8;
int x_res = vbe.mode->x_resolution;
int max_r = (1 << vbe.mode->red_mask_size) - 1;
int max_b = (1 << vbe.mode->blue_mask_size) - 1;
int shift_r = vbe.mode->red_field_position;
int shift_b = vbe.mode->blue_field_position;
int i;
for (i = 0; i < x_res; i++)
{
int c;
c = (i * max_r / x_res) << shift_r;
c |= ((x_res - i) * max_b / x_res) << shift_b;
memcpy(p + i * pixel_size, &c, pixel_size);
}
for (i=2048;i<0x7fff;i++)*(p+i)=(i&0xff);
for(i=0x8000;i<0xffff;i++)*(p+i)=85;
}
}
void
interactive_set_mode(void)
{
int n;
void *state;
struct stat stat;
if (fstat(0, &stat) != 0)
{
fprintf(stderr, "Can't stat() stdin\n");
return;
}
if ((stat.st_rdev & 0xff00) != 0x400
|| (stat.st_rdev & 0xff) > 63)
{
fprintf(stderr, "To switch video modes, "
"this program must be run from the console\n");
return;
}
printf("mode? ");
scanf("%d", &n);
printf("setting mode %d\n", n);
ioctl(0, KDSETMODE, KD_GRAPHICS);
state = save_state();
if (state == NULL)
return;
set_mode(n);
sleep(5);
text_mode();
restore_state(state);
ioctl(0, KDSETMODE, KD_TEXT);
}
int
main(void)
{
struct LRMI_regs r;
short int *mode_list;
if (!LRMI_init())
return 1;
vbe.info = LRMI_alloc_real(sizeof(struct vbe_info_block)
+ sizeof(struct vbe_mode_info_block));
if (vbe.info == NULL)
{
fprintf(stderr, "Can't alloc real mode memory\n");
return 1;
}
vbe.mode = (struct vbe_mode_info_block *)(vbe.info + 1);
/*
Allow read/write to all IO ports
*/
ioperm(0, 0x400 , 1);
iopl(3);
memset(&r, 0, sizeof(r));
r.eax = 0x4f00;
r.es = (unsigned int)vbe.info >> 4;
r.edi = 0;
memcpy(vbe.info->vbe_signature, "VBE2", 4);
if (!LRMI_int(0x10, &r))
{
fprintf(stderr, "Can't get VESA info (vm86 failure)\n");
return 1;
}
if ((r.eax & 0xffff) != 0x4f || strncmp(vbe.info->vbe_signature, "VESA", 4) != 0)
{
fprintf(stderr, "No VESA bios\n");
return 1;
}
printf("VBE Version %x.%x\n",
(int)(vbe.info->vbe_version >> 8) & 0xff,
(int)vbe.info->vbe_version & 0xff);
printf("%s\n",
(char *)(vbe.info->oem_string_seg * 16 + vbe.info->oem_string_off));
mode_list = (short int *)(vbe.info->video_mode_list_seg * 16 + vbe.info->video_mode_list_off);
while (*mode_list != -1)
{
memset(&r, 0, sizeof(r));
r.eax = 0x4f01;
r.ecx = *mode_list;
r.es = (unsigned int)vbe.mode >> 4;
r.edi = (unsigned int)vbe.mode & 0xf;
if (!LRMI_int(0x10, &r))
{
fprintf(stderr, "Can't get mode info (vm86 failure)\n");
return 1;
}
if (vbe.mode->memory_model == VBE_MODEL_RGB)
printf("[%3d] %dx%d (%d:%d:%d)\n",
*mode_list,
vbe.mode->x_resolution,
vbe.mode->y_resolution,
vbe.mode->red_mask_size,
vbe.mode->green_mask_size,
vbe.mode->blue_mask_size);
else if (vbe.mode->memory_model == VBE_MODEL_256)
printf("[%3d] %dx%d (256 color palette)\n",
*mode_list,
vbe.mode->x_resolution,
vbe.mode->y_resolution);
else if (vbe.mode->memory_model == VBE_MODEL_PACKED)
printf("[%3d] %dx%d (%d color palette)\n",
*mode_list,
vbe.mode->x_resolution,
vbe.mode->y_resolution,
1 << vbe.mode->bits_per_pixel);
else if (vbe.mode->memory_model == VBE_MODEL_TEXT)
printf("[%3d] %dx%d (TEXT)\n",
*mode_list,
vbe.mode->x_resolution,
vbe.mode->y_resolution);
else printf("[%3d] %dx%d (model=%d)\n",
*mode_list,
vbe.mode->x_resolution,
vbe.mode->y_resolution,
vbe.mode->memory_model);
mode_list++;
}
LRMI_free_real(vbe.info);
interactive_set_mode();
return 0;
}

24
lrmi-0.6m/vga_reset.c Normal file
View file

@ -0,0 +1,24 @@
/*
Call real mode c0003
*/
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include "lrmi.h"
int main(int argc, char *argv[]){
struct LRMI_regs r;
if (!LRMI_init())
return 1;
ioperm(0, 0x400, 1);
iopl(3);
memset(&r,0,sizeof(r));
r.ip=3;
r.cs=0xc000;
LRMI_call(&r);
return 0;
}