[Vesautils-devel] CVS: vesautils Makefile, NONE, 1.1 README, NONE, 1.1 dosint.c, NONE, 1.1 get-edid, NONE, 1.1 mode3.c, NONE, 1.1 vbe.h, NONE, 1.1 vbemodeinfo.c, NONE, 1.1 vbetest.c, NONE, 1.1 vbetool.1, NONE, 1.1 vbetool.c, NONE, 1.1 vbetool.h, NONE, 1.1 vga_reset.c, NONE, 1.1

Alex Beregszaszi alex at mplayerhq.hu
Fri Aug 12 19:48:18 CEST 2005


Update of /cvsroot/vesautils/vesautils
In directory mail:/var2/tmp/cvs-serv31043

Added Files:
	Makefile README dosint.c get-edid mode3.c vbe.h vbemodeinfo.c 
	vbetest.c vbetool.1 vbetool.c vbetool.h vga_reset.c 
Log Message:
initial commit

--- NEW FILE: Makefile ---
CFLAGS ?= -g -Wall
LDFLAGS = -llrmi

all = dosint mode3 vbemodeinfo vbetest vga_reset vbetool

%.o: %.c
	$(CC) -c $(CFLAGS) -o $@ $<

all: $(all)

vbetest: vbetest.c
	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^

mode3: mode3.c
	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^

dosint: dosint.c
	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^

vbemodeinfo: vbemodeinfo.c
	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^

vga_reset: vga_reset.c
	$(CC) $(CFLAGS) $(LDFLAGS) -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 $(CFLAGS) $^ >.depend

--- NEW FILE: README ---
VESA utils
==========

1, Intro

This is a collection of utilities and a library for handling
VESA BIOS Extension (VBE) with the help of LRMI under Linux and BSD
systems.

2, Prerequisities

Get LRMI from http://sourceforge.net/projects/lrmi and install it.

3, Tools

get-edid: dump edid information
mode3: set vesa mode
vbemodeinfo: dump information about a vbe mode
vbetest: list vbe modes and test them
vga_reset: call vga bios init function

4, Authors

Nick Kurshev
* original vbelib for MPlayer

Matan Zivav
* svgalib imported utils (mode3, vga_reset, get-edid)

Matthew Garrett <mjg59 at srcf.ucam.org>
* vbetool

Josh Vanderhoof
* LRMI and vbetest

Alex Beregszaszi
* new libvbe

--- NEW FILE: dosint.c ---
#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);
}

--- NEW FILE: get-edid ---
#!/bin/sh
./dosint 0x10 0x4f15 0x0001 0x80

--- NEW FILE: mode3.c ---
/*
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;
}

--- NEW FILE: vbe.h ---
/*
This file is in the public domain.
*/

#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

--- NEW FILE: vbemodeinfo.c ---
/*
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;
}

--- NEW FILE: vbetest.c ---
/*
List the available VESA graphics modes.

This program is in the public domain.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#if defined(__linux__)
#include <sys/io.h>
#include <sys/kd.h>
#include <sys/stat.h>
#elif defined(__NetBSD__)
#include <time.h>
#include <dev/wscons/wsconsio.h>
#include <machine/sysarch.h>
#elif defined(__FreeBSD__)
#include <machine/console.h>
#include <machine/sysarch.h>
#endif

#include <lrmi.h>
#include "vbe.h"

struct {
	struct vbe_info_block *info;
	struct vbe_mode_info_block *mode;
	char *win; 	/* this doesn't point directly at the window, see update_window() */
	int win_low, win_high;
} vbe;

static char *run_command = NULL;

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");
	}
}

int
update_window(int address)
{
	struct LRMI_regs r;
	int w, g;

	if (address >= vbe.win_low && address < vbe.win_high)
		return 0;

	g = vbe.mode->win_granularity * 1024;
	w = address / g;

	memset(&r, 0, sizeof(r));

	r.eax = 0x4f05;
	r.ebx = 0;
	r.edx = w;

	LRMI_int(0x10, &r);

	vbe.win_low = w * g;
	vbe.win_high = vbe.win_low + vbe.mode->win_size * 1024;

	vbe.win = (char *)(vbe.mode->win_a_segment << 4);
	vbe.win -= vbe.win_low;

	return 1;
}

void
set_pixel(int x, int y, int r, int g, int b)
{
	int x_res = vbe.mode->x_resolution;
	int y_res = vbe.mode->y_resolution;
	int shift_r = vbe.mode->red_field_position;
	int shift_g = vbe.mode->green_field_position;
	int shift_b = vbe.mode->blue_field_position;
	int pixel_size = (vbe.mode->bits_per_pixel + 7) / 8;
	int bpl = vbe.mode->bytes_per_scanline;
	int c, addr;

	if (x < 0 || x >= x_res || y < 0 || y >= y_res)
		return;

	r >>= 8 - vbe.mode->red_mask_size;
	g >>= 8 - vbe.mode->green_mask_size;
	b >>= 8 - vbe.mode->blue_mask_size;

	c = (r << shift_r) | (g << shift_g) | (b << shift_b);

	addr = y * bpl + (x * pixel_size);

	update_window(addr);

	memcpy(vbe.win + addr, &c, pixel_size);
}

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;
	}

	vbe.win_low = vbe.win_high = -1;

	/*
	 Draw a colorful checkerboard
	*/
	if (vbe.mode->memory_model == VBE_MODEL_RGB) {
		int x_res = vbe.mode->x_resolution;
		int y_res = vbe.mode->y_resolution;
		int x, y;

		for (y = 0; y < y_res; ++y) {
			for (x = 0; x < x_res; ++x) {
				int r, g, b;
				if ((x & 16) ^ (y & 16)) {
					r = x * 255 / x_res;
					g = y * 255 / y_res;
					b = 255 - x * 255 / x_res;
				} else {
					r = 255 - x * 255 / x_res;
					g = y * 255 / y_res;
					b = 255 - y * 255 / y_res;
				}

				set_pixel(x, y, r, g, b);
			}
		}
	}
}

void
interactive_set_mode(int n)
{
	void *state;
#if defined(__linux__)
	struct stat stat;
#elif defined(__NetBSD__)
	struct wsdisplay_fbinfo wsi;
#elif defined(__FreeBSD__)
	struct vid_info vi;
#endif

	if (n == -1) {
		printf("Type a mode number, or 'q' to quit - ");

		if (scanf("%d", &n) != 1)
			return;
	}

#if defined(__linux__)
	if (fstat(0, &stat) != 0) {
		fprintf(stderr, "Can't stat() stdin\n");
		return;
	}

	if ((stat.st_rdev & 0xff00) != 0x400
	 || (stat.st_rdev & 0xff) > 63)
#elif defined(__NetBSD__)
	if (ioctl(0, WSDISPLAYIO_GINFO, &wsi) == -1)
#elif defined(__FreeBSD__) 
	memset(&vi, 0, sizeof(vi));
	vi.size = sizeof(vi);
	if (ioctl(0, CONS_GETINFO, &vi) == -1)
#endif
	{
		fprintf(stderr, "To switch video modes, "
		 "this program must be run from the console\n");
		return;
	}

	printf("setting mode %d\n", n);

#if defined(__linux__) || defined(__FreeBSD__)
	ioctl(0, KDSETMODE, KD_GRAPHICS);
#elif defined(__NetBSD__)
	ioctl(0, WSDISPLAYIO_SMODE, WSDISPLAYIO_MODE_MAPPED);
#endif

	state = save_state();

	if (state == NULL)
		return;

	set_mode(n);

	system(run_command);

	sleep(5);

	text_mode();
	restore_state(state);

#if defined(__linux__) || defined(__FreeBSD__)
	ioctl(0, KDSETMODE, KD_TEXT);
#elif defined(__NetBSD__)
	ioctl(0, WSDISPLAYIO_SMODE, WSDISPLAYIO_MODE_EMUL);
#endif
}

void
usage_and_quit(int error)
{
	fputs("Usage: vbetest [-m mode] [-c command]\n",
	 error ? stderr : stdout);
	exit(error);
}

int
main(int argc, char *argv[])
{
	struct LRMI_regs r;
	short int *mode_list;
	int i, mode = -1;
#if defined(__NetBSD__)
	unsigned long iomap[32];
#endif

	for (i = 1; i < argc; i++) {
		if (strcmp(argv[i], "-c") == 0) {
			i++;
			if (i == argc)
				usage_and_quit(1);
			run_command = argv[i];
		} else if (strcmp(argv[i], "-m") == 0) {
			char *e;
			i++;
			if (i == argc)
				usage_and_quit(1);
			mode = strtol(argv[i], &e, 10);
			if (e == argv[i])
				usage_and_quit(1);
		} else
			usage_and_quit(1);
	}

	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);

#if 0
	/*
	 Allow read/write to video IO ports
	*/
	ioperm(0x2b0, 0x2df - 0x2b0, 1);
	ioperm(0x3b0, 0x3df - 0x3b0, 1);
#else
	/*
	 Allow read/write to ALL io ports
	*/
#if defined(__linux__)
	ioperm(0, 1024, 1);
	iopl(3);
#elif defined(__NetBSD__)
	memset(&iomap[0], 0xff, sizeof(iomap));
	i386_set_ioperm(iomap);
	i386_iopl(3);
#elif defined(__FreeBSD__)
	i386_set_ioperm(0, 0x10000, 1);
#endif
#endif

	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);

		mode_list++;
	}

	LRMI_free_real(vbe.info);

	interactive_set_mode(mode);

	return 0;
}

--- NEW FILE: vbetool.1 ---
.TH VBETOOL "1" "31 December 2004" "vbetool 0.2" "User Commands"
.SH NAME 
vbetool - run real-mode video BIOS code to alter hardware state

.SH SYNOPSIS
.B "vbetool [[vbestate save|restore]|[vbemode set|get]|[vgamode]|[dpms on|off|standby|suspend|reduced]|[post]]"

.SH DESCRIPTION
.B vbetool
uses lrmi in order to run code from the video BIOS. Currently, 
it is able to alter DPMS states, save/restore video card state and 
attempt to initialize the video card from scratch.

.SH OPTIONS
.B vbetool
takes the following options:
.IP "vbestate"
.B vbetool
will use the VESA 0x4f0f extensions to save or restore hardware
state. This will be sent to or read from stdin. This information is
highly hardware specific - do not attempt to restore state saved from
a different machine. This command will not work unless you are at a
text console, as it interferes badly with X.

.IP "dpms"
.B vbetool
will use the VESA 0x4f10 extensions to alter the power management
state of your screen. "On", "off", "standby", "suspend" and "reduced"
are acceptable further options and determine which state will be
activated.

.IP "vbemode"
.B vbetool
will get or set the current VESA mode. "get" will return the current
mode number on stdout - "set" will set the mode to the next argument.

.IP "vgamode"
.B vbetool
will set the legacy VGA mode to the following numeric argument.

.IP "post"
.B vbetool
will attempt to run BIOS code located at c000:0003. This is the code
run by the system BIOS at boot in order to intialise the video
hardware. Note that on some machines (especially laptops), not all of
this code is present after system boot - as a result, executing this
command may result in undefined behaviour. This command must be run
from a text console, as it will otherwise interfere with the operation
of X.

.SH BUGS
Switching dpms modes may interact badly with X on some systems.
.PP
The vbestate command may behave in strange ways.
.PP
The post command may result in the execution of arbitrary code that
happens to be lying around in the area where chunks of your video BIOS
used to be.
.PP
The VESA specification does not require that "vbemode get" provides
the correct mode if the current mode was set via some means other than
the VESA BIOS extensions.

.SH AUTHOR
vbetool was written by Matthew Garrett <mjg59 at srcf.ucam.org>, based on
code from read-edid by John Fremlin <john at fremlin.de>, LRMI
(http://sourceforge.net/projects/lrmi/) and XFree
(http://www.xfree86.org). It is released under the terms of the GNU
General Public License.

--- NEW FILE: vbetool.c ---
/*
Run video BIOS code for various purposes

Copyright Matthew Garrett <mjg59 at srcf.ucam.org>, heavily based on
vbetest.c from the lrmi package and read-edid.c by John Fremlin

This program is released under the terms of the GNU General Public License,
version 2
*/

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/io.h>
#include <sys/kd.h>
#include <sys/stat.h>
#include <errno.h>
#ifdef HAVE_PCI
#include <pci/pci.h>
#endif

#include <lrmi.h>
#include "vbetool.h"

#define access_ptr_register(reg_frame,reg) (reg_frame -> reg)
#define access_seg_register(reg_frame,es) reg_frame.es
#define real_mode_int(interrupt,reg_frame_ptr) !LRMI_int(interrupt,reg_frame_ptr)

#define DPMS_STATE_ON 0x0000
#define DPMS_STATE_STANDBY 0x0100
#define DPMS_STATE_SUSPEND 0x0200
#define DPMS_STATE_OFF 0x0400
#define DPMS_STATE_LOW 0x0800

#ifdef HAVE_PCI
static struct pci_access *pacc;
#endif

int main(int argc, char *argv[])
{
	if (!LRMI_init())
		return 1;

	ioperm(0, 1024, 1);
	iopl(3);

#ifdef HAVE_PCI
	pacc = pci_alloc();
	pacc->numeric_ids = 1;
	pci_init(pacc);
#endif

	if (!strcmp(argv[1], "vbestate")) {
		/* VBE save/restore tends to break when done underneath X */
		int err = check_console();

		if (err) {
			return err;
		}

		if (!strcmp(argv[2], "save")) {
			save_state();
		} else if (!strcmp(argv[2], "restore")) {
			restore_state();
		} else {
			goto usage;
		}
	} else if (!strcmp(argv[1], "dpms")) {
		if (!strcmp(argv[2], "on")) {
			return do_blank(DPMS_STATE_ON);
		} else if (!strcmp(argv[2], "suspend")) {
			return do_blank(DPMS_STATE_SUSPEND);
		} else if (!strcmp(argv[2], "standby")) {
			return do_blank(DPMS_STATE_STANDBY);
		} else if (!strcmp(argv[2], "off")) {
			return do_blank(DPMS_STATE_OFF);
		} else if (!strcmp(argv[2], "reduced")) {
			return do_blank(DPMS_STATE_LOW);
		} else {
			goto usage;
		}
	} else if (!strcmp(argv[1], "vbemode")) {
		if (!strcmp(argv[2], "set")) {
			return do_set_mode(atoi(argv[3]),0);
		} else if (!strcmp(argv[2], "get")) {
			return do_get_mode();
		} else {
			goto usage;
		}
	} else if (!strcmp(argv[1], "vgamode")) {
		if (!strcmp(argv[2], "set")) {
			return do_set_mode(atoi(argv[3]),1);
		} else {
			return do_set_mode(atoi(argv[2]),1);
		}
	} else if (!strcmp(argv[1], "post")) {
		/* Again, we don't really want to do this while X is in 
		   control */
		int err = check_console();

		if (err) {
			return err;
		}
#ifdef HAVE_PCI
		return do_post();
#else
		fprintf(stderr, "%s: not compiled with PCI support\n", argv[0]);
		return -1;
#endif
	} else {
	      usage:
		fprintf(stderr,
			"%s: Usage %s [[vbestate save|restore]|[vbemode set|get]|[vgamode]|[dpms on|off|standby|suspend|reduced]|[post]]\n",
			argv[0], argv[0]);
		return 1;
	}

	return 0;
}

int do_vbe_service(unsigned int AX, unsigned int BX, reg_frame * regs)
{
	const unsigned interrupt = 0x10;
	unsigned function_sup;
	unsigned success;

	access_ptr_register(regs, eax) = AX;
	access_ptr_register(regs, ebx) = BX;

	if (real_mode_int(interrupt, regs)) {
		fprintf(stderr,
			"Error: something went wrong performing real mode interrupt\n");
		return -1;
	}

	AX = access_ptr_register(regs, eax);

	function_sup = ((AX & 0xff) == 0x4f);
	success = ((AX & 0xff00) == 0);

	if (!success)
		return -2;
	if (!function_sup)
		return -3;

	return access_ptr_register(regs, ebx);
}

#ifdef HAVE_PCI
int do_real_post(unsigned pci_device)
{
	int error = 0;
	struct LRMI_regs r;
	memset(&r, 0, sizeof(r));

	/* Several machines seem to want the device that they're POSTing in
	   here */
	r.eax = pci_device;

	/* 0xc000 is the video option ROM.  The init code for each
	   option ROM is at 0x0003 - so jump to c000:0003 and start running */
	r.cs = 0xc000;
	r.ip = 0x0003;

	/* This is all heavily cargo culted but seems to work */
	r.edx = 0x80;
	r.ss = 0x0030;
	r.ds = 0x0040;
	r.sp = 0xfffe;

	if (!LRMI_call(&r)) {
		fprintf(stderr,
			"Error: something went wrong performing real mode call\n");
		error = 1;
	}

	return error;
}

int do_post()
{
	struct pci_dev *p;
	unsigned int c;
	unsigned int pci_id;
	int error;

	pci_scan_bus(pacc);

	for (p = pacc->devices; p; p = p->next) {
		c = pci_read_word(p, PCI_CLASS_DEVICE);
		if (c == 0x300) {
			pci_id =
			    (p->bus << 8) + (p->dev << 3) +
			    (p->func & 0x7);
			error = do_real_post(pci_id);
			if (error != 0) {
				return error;
			}
		}
	}
	return 0;
}
#endif

void restore_state()
{
	struct LRMI_regs r;

	void *data = NULL;
	char tmpbuffer[524288];
	int i, length = 0;

	/* We really, really don't want to fail to read the entire set */
	while ((i = read(0, tmpbuffer + length, sizeof(tmpbuffer)-length))) {
		if (i == -1) {
			if (errno != EAGAIN && errno != EINTR) {
				perror("Failed to read state - ");
				return;
			}
		} else {
			length += i;
		}
	}

	data = LRMI_alloc_real(length);
	memcpy(data, tmpbuffer, length);

	/* VGA BIOS mode 3 is text mode */
	do_set_mode(3,1);

	memset(&r, 0, sizeof(r));

	r.eax = 0x4f04;
	r.ecx = 0xf;		/* all states */
	r.edx = 2;		/* restore state */
	r.es = (unsigned int) data >> 4;
	r.ebx = (unsigned int) data & 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(data);

	ioctl(0, KDSETMODE, KD_TEXT);
}

void save_state()
{
	struct LRMI_regs r;
	void *buffer;
	unsigned int size;

	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");
	}

	if ((r.eax & 0xffff) != 0x4f) {
		fprintf(stderr, "Get video state buffer size failed\n");
	}

	size = (r.ebx & 0xffff) * 64;

	buffer = LRMI_alloc_real(size);

	if (buffer == NULL) {
		fprintf(stderr, "Can't allocate video state buffer\n");
	}

	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");
	}

	if ((r.eax & 0xffff) != 0x4f) {
		fprintf(stderr, "Save video state failed\n");
	}

	write(1, buffer, size);
}

int do_blank(int state)
{
	reg_frame regs;
	int error;

	memset(&regs, 0, sizeof(regs));
	error = do_vbe_service(0x4f10, state |= 0x01, &regs);
	if (error<0) {
		return error;
	}
	return 0;
}

int do_set_mode (int mode, int vga) {
	reg_frame regs;
	int error;

	memset(&regs, 0, sizeof(regs));

	if (vga) {
		error = do_vbe_service(mode, 0, &regs);
	} else {
		error = do_vbe_service(0x4f02, mode, &regs);
	}

	if (error<0) {
		return error;
	}
	
	return 0;
}

int do_get_mode() {
	reg_frame regs;
	int error;

	memset(&regs, 0, sizeof(regs));
	error = do_vbe_service(0x4f03, 0, &regs);

	if (error<0) {
		return error;
	}
	
	printf("%d\n",error);
	return 0;
}

int check_console()
{
	struct stat stat;

	return 0;

	if (fstat(0, &stat) != 0) {
		fprintf(stderr, "Can't stat() stdin\n");
		return 10;
	}

	if ((stat.st_rdev & 0xff00) != 0x400 || (stat.st_rdev & 0xff) > 63) {
		fprintf(stderr, "To perform this operation, "
			"this program must be run from the console\n");
		return 11;
	}

	ioctl(0, KDSETMODE, KD_GRAPHICS);
	return 0;
}

--- NEW FILE: vbetool.h ---
typedef struct LRMI_regs reg_frame;

int do_vbe_service(unsigned int AX, unsigned int BX, reg_frame *regs);
int do_real_post(unsigned pci_device);
int do_blank(int state);
int do_set_mode (int mode, int vga);
int do_get_mode(void);
int do_post(void);
void restore_state(void);
void save_state(void);
void text_mode(void);
int check_console(void);



--- NEW FILE: vga_reset.c ---
/*
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;
}




More information about the Vesautils-devel mailing list