bitkeeper revision 1.1691.1.5 (42a6b4baIjkVZx9lVWvoA9RqgAGLMQ)

The following allows you to run unmodified guest operating systems
under Xen on VMX (VT) enabled processors. The tree lives under
<ROOT>/tools/dfw. Instead of booting a guest kernel, boot vmxloader and
specify the disk image in qemurc.

        Leendert

Signed-Off-By: Leendert van Doorn <leendert@watson.ibm.com>
This commit is contained in:
kaf24@firebug.cl.cam.ac.uk committed 2005-06-08 09:04:58 +00:00
1 parent 40eafaacb1
commit 13e63314c4
41 files changed
+26037

No files matched your search

+40
View File
@@ -567,6 +567,46 @@
41090ec8Pj_bkgCBpg2W7WfmNkumEA tools/examples/xmexample1
40cf2937oKlROYOJTN8GWwWM5AmjBg tools/examples/xmexample2
41fc0c18_k4iL81hu4pMIWQu9dKpKA tools/examples/xmexample3
42a6b4b7KssGzTDVN-XG2FM1gCEnnw tools/firmware/Makefile
42a6b4b7qP95OSsEL8XWKKZ1p1myjQ tools/firmware/README
42a6b4b78PWdYzKYvLt_EHhvQCl9ig tools/firmware/rombios/Makefile
42a6b4b75sz5KF9Lry2EGnPMhOdnUA tools/firmware/rombios/apmbios.S
42a6b4b7YwP9rl3AJRTmZbBoal_c6Q tools/firmware/rombios/biossums.c
42a6b4b83gANosDYd43YaK7ATQvBEg tools/firmware/rombios/makesym.perl
42a6b4b8qcIQIBXDeOY3JRwsLM6lhw tools/firmware/rombios/rombios.c
42a6b4b8K7yqnU3-QxndYNZUgHpniw tools/firmware/rombios/rombios.diffs
42a6b4b86GMM969Y82nK3HuUi6eP9g tools/firmware/vgabios/BUGS
42a6b4b8J_MHMVmmF_igI7zeDxSiwA tools/firmware/vgabios/COPYING
42a6b4b8SYW5q21pPPuQt88Bkpqc2Q tools/firmware/vgabios/ChangeLog
42a6b4b8INe7qe20YYlwATaAADEMQA tools/firmware/vgabios/Makefile
42a6b4b8AYFCsoAeqqQ8dibmgxkfLA tools/firmware/vgabios/Notes
42a6b4b8NUXHh1hudvvNCuqgo9cB-Q tools/firmware/vgabios/README
42a6b4b8MM0Pj6uDwdJ4Eyg6hB-oEA tools/firmware/vgabios/TODO
42a6b4b8AL0YrgudjmQr7QvJ3we1Cg tools/firmware/vgabios/biossums.c
42a6b4b8Zce-r8OtpctwvqHBS8cHEw tools/firmware/vgabios/clext.c
42a6b4b8fIyMd0d8tIPV4JDAvB5l1A tools/firmware/vgabios/dataseghack
42a6b4b8M4BsNDRAJMHpY8H2iRu0qA tools/firmware/vgabios/vbe.c
42a6b4b8Z2pSU4e5qrUR5r1vEKNbKQ tools/firmware/vgabios/vbe.h
42a6b4b8EyiklW2C9eD9_t0OmRfmFQ tools/firmware/vgabios/vbe_display_api.txt
42a6b4b8oXcw5CgLj-mBVT4dUc-Umw tools/firmware/vgabios/vbetables.h
42a6b4b85jkZnCar41YreYVUAY7IDQ tools/firmware/vgabios/vgabios.c
42a6b4b8xxpRYh1BesaSgW3gpgMsaQ tools/firmware/vgabios/vgabios.h
42a6b4b8WSA5xHF-R5F8iBcB6BC5wA tools/firmware/vgabios/vgafonts.h
42a6b4b9C66bPuUTaLjCnJ0I-kGz9w tools/firmware/vgabios/vgatables.h
42a6b4b969QLJRt3TU_v3yYhZI45Gg tools/firmware/vmxassist/Makefile
42a6b4b95iuk7M2s-edoSFrWcdoYcw tools/firmware/vmxassist/TODO
42a6b4b9Q6VB27GxRNCARsDN2ZuKNw tools/firmware/vmxassist/gen.c
42a6b4b9NmLjb36-sXiiWzcGHjTOJA tools/firmware/vmxassist/head.S
42a6b4b9jmF9m22iiwu8XwEm1j5fnQ tools/firmware/vmxassist/machine.h
42a6b4b9ABmGHA1LzYjpq63FBs4hcw tools/firmware/vmxassist/mkhex
42a6b4b9xmj4TLHJtV-DhnwT9mMpfw tools/firmware/vmxassist/setup.c
42a6b4b9PjgANTP8Y8JFTToBrV9ssg tools/firmware/vmxassist/trap.S
42a6b4b9GlymU0VmQyan23pagDaRTQ tools/firmware/vmxassist/util.c
42a6b4b9mmqUyFn487gP4spU_R6xtg tools/firmware/vmxassist/util.h
42a6b4b9JssxvlpcV_-QcGRMDGgL_w tools/firmware/vmxassist/vm86.c
42a6b4b92oUAJMzCE-YcVlA2Z-2zyg tools/firmware/vmxassist/vm86.h
42a6b4b9TlkVUYTkLd_Bvq9vlrEx6g tools/firmware/vmxassist/vmxassist.ld
42a6b4b92L-2zFg-Qal6YweeE-pMiA tools/firmware/vmxassist/vmxloader.c
428d0d82yOaUzYQuYQxH7VzQytKo-g tools/ioemu/COPYING
428d0d82EdPp1TqJBembLgyB1y413w tools/ioemu/COPYING.LIB
428d0d82fd6-QydvFfHmeQBGrKnrrA tools/ioemu/Changelog
+25
View File
@@ -0,0 +1,25 @@
XEN_ROOT = ../..
include $(XEN_ROOT)/tools/Rules.mk
SUBDIRS :=
SUBDIRS += rombios
SUBDIRS += vgabios
SUBDIRS += vmxassist
.PHONY: all install clean
all:
@set -e; for subdir in $(SUBDIRS); do \
$(MAKE) -C $$subdir $@; \
done
install:
@set -e; for subdir in $(SUBDIRS); do \
$(MAKE) -C $$subdir $@; \
done
clean:
@set -e; for subdir in $(SUBDIRS); do \
$(MAKE) -C $$subdir $@; \
done
+88
View File
@@ -0,0 +1,88 @@
Domain FirmWare support
-----------------------
One of the key advantages of full virtualization hardware support (such
as Intel's VT or AMD's Pacifica) is the ability to run unmodified guest
operating systems. However, since most OSes rely on BIOS support during
their early bringup, we need to provide a surrogate ROMBIOS and VGABIOS
firmware layer.
What's more, we need to support real-mode which is required by
the firmware and bootstrap loaders. Real-mode support is especially
challenging for Intel's VMX (VT) enabled CPUs where there is no real-mode
support for VMX guest partitions. In this case you either have to do full
emulation (full real-mode emulator; more complete but potentially slower)
or partial emulation (use the VM8086 extensions, emulate only those
instructions that are missing; faster, but potentially incomplete). The
vmxassist code in this subdirectory uses the later approach because it
is smaller and faster.
The approach is relatively straight forward. Vmxloader contains three
payloads (rombios, vgabios and vmxassist) and it is bootstrapped as any
other 32-bit OS. Vmxloader copies its payloads to the addresses below
and transfers control to vmxassist.
vgabios VGABIOS (standard and Cirrus).
Resides at C000:0000.
vmxassist VMXAssist VM86 realmode emulator for VMX.
Resides at D000:0000.
rombios ROMBIOS code. Derived from Bochs.
Resides at F000:0000
Vmxassist first sets up it own world (GDT, IDT, TR, etc), enables
VM8086 and then transfers control to F000:FFF0 and executes 16-bit
code. Unsupported instructions cause a general protection failure at
which point vmxassist kicks in and emulates the offending instruction.
Whever the emulated code transitions to 32-bit protected mode, vmxassist
will go away. Whenever 32-bit protected code transitions to real-mode,
Xen/VMX will detect this and transfer control to vmxassist.
Most of the vmxassist complexity comes from properly handling the
real to protected mode and protected to real mode transitions and
the proper emulation of the segment registers. Even though the Intel
manual clearly states that you should immediately perform a jmp far
after a mode transition, many operating systems execute additional
instructions and some even refer to segment selectors and pop data
from the stack. Vmxassist contains a number of work arounds for these
OSes.
Acknowledgements
----------------
The rombios was taken (largely unmodified) from Bochs, which was written
by Kevin Lawton. The VGABIOS was written by Christophe Bothamy. Arun Sharma,
Asit Mallick and Nitin Kamble (Intel) provided the E820 patches and lots
of useful feedback.
Contact
-------
Leendert van Doorn
IBM T.J. Watson Research Center
19 Skyline Drive
Hawthorne, NY 10532
leendert@watson.ibm.com
Tested Operating Systems
------------------------
Since vmxassist uses partial emulation, it may always miss opcodes
that are required by a particular OS. The table below lists the OSes
I have tried. The Install column indicates a full CD/DVD install into
a VMX partition. The Disk column indicates booting from prefabricated
disk image.
Operating System Install Disk
------------------------------------------------------------
RedHat Enterprise Linux (RHEL3_U5) Yes Yes
Fedora Code (FC3) (-) Yes
FreeBSD 5.3 (-) Yes
MS-DOS 5.0 (-) Yes
(-) not tried yet
+58
View File
@@ -0,0 +1,58 @@
BIOS_BUILDS = BIOS-bochs-latest
#BIOS_BUILDS += BIOS-bochs-2-processors
#BIOS_BUILDS += BIOS-bochs-4-processors
#BIOS_BUILDS += BIOS-bochs-8-processors
all: bios
bios: biossums ${BIOS_BUILDS}
clean:
rm -f *.o *.a *.s rombios.bin _rombios*_.c
rm -f as86-sym.txt ld86-sym.txt
rm -f rombios*.txt rombios*.sym usage biossums
rm -f BIOS-bochs-*
BIOS-bochs-latest: rombios.c biossums
gcc -DBX_SMP_PROCESSORS=1 -E -P $< > _rombios_.c
bcc -o rombios.s -C-c -D__i86__ -0 -S _rombios_.c
sed -e 's/^\.text//' -e 's/^\.data//' rombios.s > _rombios_.s
as86 _rombios_.s -b tmp.bin -u- -w- -g -0 -j -O -l rombios.txt
-perl makesym.perl < rombios.txt > rombios.sym
mv tmp.bin BIOS-bochs-latest
./biossums BIOS-bochs-latest
rm -f _rombios_.s
BIOS-bochs-2-processors: rombios.c biossums
gcc -DBX_SMP_PROCESSORS=2 -E -P $< > _rombios2_.c
bcc -o rombios2.s -C-c -D__i86__ -0 -S _rombios2_.c
sed -e 's/^\.text//' -e 's/^\.data//' rombios2.s > _rombios2_.s
as86 _rombios2_.s -b tmp2.bin -u- -w- -g -0 -j -O -l rombios2.txt
-perl makesym.perl < rombios2.txt > rombios2.sym
mv tmp2.bin BIOS-bochs-2-processors
./biossums BIOS-bochs-2-processors
rm -f _rombios2_.s
BIOS-bochs-4-processors: rombios.c biossums
gcc -DBX_SMP_PROCESSORS=4 -E -P $< > _rombios4_.c
bcc -o rombios4.s -C-c -D__i86__ -0 -S _rombios4_.c
sed -e 's/^\.text//' -e 's/^\.data//' rombios4.s > _rombios4_.s
as86 _rombios4_.s -b tmp4.bin -u- -w- -g -0 -j -O -l rombios4.txt
-perl makesym.perl < rombios4.txt > rombios4.sym
mv tmp4.bin BIOS-bochs-4-processors
./biossums BIOS-bochs-4-processors
rm -f _rombios4_.s
BIOS-bochs-8-processors: rombios.c biossums
gcc -DBX_SMP_PROCESSORS=8 -E -P $< > _rombios8_.c
bcc -o rombios8.s -C-c -D__i86__ -0 -S _rombios8_.c
sed -e 's/^\.text//' -e 's/^\.data//' rombios8.s > _rombios8_.s
as86 _rombios8_.s -b tmp8.bin -u- -w- -g -0 -j -O -l rombios8.txt
-perl makesym.perl < rombios8.txt > rombios8.sym
mv tmp8.bin BIOS-bochs-8-processors
./biossums BIOS-bochs-8-processors
rm -f _rombios8_.s
biossums: biossums.c
gcc -o biossums biossums.c
+329
View File
@@ -0,0 +1,329 @@
// APM BIOS support for the Bochs BIOS
// Copyright (C) 2004 Fabrice Bellard
//
// Debugging extensions, 16-bit interface and extended power options
// Copyright (C) 2005 Struan Bartlett
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#if defined(APM_REAL)
#define APMSYM(s) apmreal_ ## s
#elif defined(APM_PROT16)
#define APMSYM(s) apm16_ ## s
#elif defined(APM_PROT32)
#define APMSYM(s) apm32_ ## s
#else
#error unsupported APM mode
#endif
APMSYM(out_str):
push eax
push ebx
mov ebx, eax
APMSYM(out_str1):
SEG CS
mov al, byte ptr [bx]
cmp al, #0
je APMSYM(out_str2)
outb dx, al
inc ebx
jmp APMSYM(out_str1)
APMSYM(out_str2):
pop ebx
pop eax
ret
APMSYM(07_poweroff_str):
.ascii "Shutdown"
db 0
APMSYM(07_suspend_str):
.ascii "Suspend"
db 0
APMSYM(07_standby_str):
.ascii "Standby"
db 0
#if DEBUG_APM
APMSYM(put_str):
push edx
mov dx, #INFO_PORT
call APMSYM(out_str)
pop edx
ret
; print the hex number in eax
APMSYM(put_num):
push eax
push ebx
push ecx
push edx
mov ecx, eax
mov bx, #8
mov dx, #INFO_PORT
APMSYM(put_num1):
mov eax, ecx
shr eax, #28
add al, #0x30
cmp al, #0x39
jbe APMSYM(put_num2)
add al, #0x27
APMSYM(put_num2):
outb dx, al
shl ecx, #4
dec bx
jne APMSYM(put_num1)
pop edx
pop ecx
pop ebx
pop eax
ret
APMSYM(put_reg):
outb dx, al
shr eax, #8
outb dx, al
shr eax, #8
outb dx, al
shr eax, #8
outb dx, al
mov eax,ebx
call APMSYM(put_num)
mov al, #0x3b
outb dx,al
mov al, #0x20
outb dx,al
ret
APMSYM(put_regs):
push eax
push edx
push ebx
mov dx, #INFO_PORT
mov ebx, eax
mov eax, #0x3d584145 // 'EAX='
call APMSYM(put_reg)
pop ebx
push ebx
mov eax, #0x3d584245 // 'EBX='
call APMSYM(put_reg)
mov ebx, ecx
mov eax, #0x3d584345 // 'ECX='
call APMSYM(put_reg)
mov ebx, edx
mov eax, #0x3d584445 // 'EDX='
call APMSYM(put_reg)
mov ebx, esi
mov eax, #0x3d495345 // 'ESI='
call APMSYM(put_reg)
mov ebx, edi
mov eax, #0x3d494445 // 'EDI='
call APMSYM(put_reg)
mov al, #0x0a
outb dx, al
pop ebx
pop edx
pop eax
ret
#endif
#if defined(APM_PROT32)
_apm32_entry:
#endif
#if defined(APM_PROT16)
_apm16_entry:
#endif
pushf
#if defined(APM_REAL)
_apmreal_entry:
#endif
#if DEBUG_APM
call APMSYM(put_regs)
#endif
#if defined(APM_REAL)
;-----------------
; APM installation check
APMSYM(00):
cmp al, #0x00
jne APMSYM(01)
mov ah, #1 // APM major version
mov al, #2 // APM minor version
mov bh, #0x50 // 'P'
mov bl, #0x4d // 'M'
// bit 0 : 16 bit interface supported
// bit 1 : 32 bit interface supported
mov cx, #0x3
jmp APMSYM(ok)
;-----------------
; APM real mode interface connect
APMSYM(01):
cmp al, #0x01
jne APMSYM(02)
jmp APMSYM(ok)
;-----------------
; APM 16 bit protected mode interface connect
APMSYM(02):
cmp al, #0x02
jne APMSYM(03)
mov bx, #_apm16_entry
mov ax, #0xf000 // 16 bit code segment base
mov si, #0xfff0 // 16 bit code segment size
mov cx, #0xf000 // data segment address
mov di, #0xfff0 // data segment length
jmp APMSYM(ok)
;-----------------
; APM 32 bit protected mode interface connect
APMSYM(03):
cmp al, #0x03
jne APMSYM(04)
mov ax, #0xf000 // 32 bit code segment base
mov ebx, #_apm32_entry
mov cx, #0xf000 // 16 bit code segment base
// 32 bit code segment size (low 16 bits)
// 16 bit code segment size (high 16 bits)
mov esi, #0xfff0fff0
mov dx, #0xf000 // data segment address
mov di, #0xfff0 // data segment length
jmp APMSYM(ok)
#endif
;-----------------
; APM interface disconnect
APMSYM(04):
cmp al, #0x04
jne APMSYM(07)
jmp APMSYM(ok)
;-----------------
; APM Set Power State
APMSYM(07):
cmp al, #0x07
jne APMSYM(0a)
cmp bx, #1
jne APMSYM(ok)
cmp cx, #3
je APMSYM(07_poweroff)
cmp cx, #2
je APMSYM(07_suspend)
cmp cx, #1
je APMSYM(07_standby)
jne APMSYM(ok)
APMSYM(07_poweroff):
// send power off event to emulator
cli
mov dx, #0x8900
mov ax, #APMSYM(07_poweroff_str)
call APMSYM(out_str)
APMSYM(07_1):
hlt
jmp APMSYM(07_1)
APMSYM(07_suspend):
push edx
mov dx, #0x8900
mov ax, #APMSYM(07_suspend_str)
call APMSYM(out_str)
pop edx
jmp APMSYM(ok)
APMSYM(07_standby):
push edx
mov dx, #0x8900
mov ax, #APMSYM(07_standby_str)
call APMSYM(out_str)
pop edx
jmp APMSYM(ok)
;-----------------
; Get Power Status
APMSYM(0a):
cmp al, #0x0a
jne APMSYM(0b)
mov bh, #0x01 // on line
// mov bh, #0x02 // battery
mov bl, #0xff // unknown battery status
// mov bl, #0x03 // charging
mov ch, #0x80 // no system battery
// mov ch, #0x8 // charging
mov cl, #0xff // unknown remaining time
// mov cl, #50
mov dx, #0xffff // unknown remaining time
mov si, #0 // zero battery
// mov si, #1 // one battery
jmp APMSYM(ok)
;-----------------
; Get PM Event
APMSYM(0b):
cmp al, #0x0b
jne APMSYM(0e)
mov ah, #0x80 // no event pending
jmp APMSYM(error)
;-----------------
; APM Driver Version
APMSYM(0e):
cmp al, #0x0e
jne APMSYM(unimplemented)
mov ah, #1
mov al, #2
jmp APMSYM(ok)
;-----------------
APMSYM(ok):
popf
clc
#if defined(APM_REAL)
jmp iret_modify_cf
#else
retf
#endif
APMSYM(unimplemented):
APMSYM(error):
popf
stc
#if defined(APM_REAL)
jmp iret_modify_cf
#else
retf
#endif
#undef APM_PROT32
#undef APM_PROT16
#undef APM_REAL
#undef APMSYM
+478
View File
@@ -0,0 +1,478 @@
/* biossums.c --- written by Eike W. */
#include <stdlib.h>
#include <stdio.h>
typedef unsigned char byte;
void check( int value, char* message );
#define LEN_BIOS_DATA 0x10000
#define MAX_OFFSET (LEN_BIOS_DATA - 1)
#define BIOS_OFFSET 0xFFFF
long chksum_bios_get_offset( byte* data, long offset );
byte chksum_bios_calc_value( byte* data, long offset );
byte chksum_bios_get_value( byte* data, long offset );
void chksum_bios_set_value( byte* data, long offset, byte value );
#define _32__LEN 9
#define _32__CHKSUM 10
#define _32__MINHDR 16
long chksum__32__get_offset( byte* data, long offset );
byte chksum__32__calc_value( byte* data, long offset );
byte chksum__32__get_value( byte* data, long offset );
void chksum__32__set_value( byte* data, long offset, byte value );
#define _MP__LEN 8
#define _MP__CHKSUM 10
#define _MP__MINHDR 16
long chksum__mp__get_offset( byte* data, long offset );
byte chksum__mp__calc_value( byte* data, long offset );
byte chksum__mp__get_value( byte* data, long offset );
void chksum__mp__set_value( byte* data, long offset, byte value );
#define PCMP_BASELEN 4
#define PCMP_CHKSUM 7
#define PCMP_EXT_LEN 40
#define PCMP_EXT_CHKSUM 42
#define PCMP_MINHDR 42
long chksum_pcmp_get_offset( byte* data, long offset );
byte chksum_pcmp_calc_value( byte* data, long offset );
byte chksum_pcmp_get_value( byte* data, long offset );
void chksum_pcmp_set_value( byte* data, long offset, byte value );
#define _PIR_LEN 6
#define _PIR_CHKSUM 31
#define _PIR_MINHDR 32
long chksum__pir_get_offset( byte *data, long offset );
byte chksum__pir_calc_value( byte* data, long offset );
byte chksum__pir_get_value( byte* data, long offset );
void chksum__pir_set_value( byte* data, long offset, byte value );
byte bios_data[LEN_BIOS_DATA];
int main( int argc, char* argv[] ) {
FILE* stream;
long offset, tmp_offset;
byte cur_val = 0, new_val = 0;
int hits;
if( argc != 2 ) {
printf( "Error. Need a file-name as an argument.\n" );
exit( EXIT_FAILURE );
}
if(( stream = fopen( argv[1], "rb" )) == NULL ) {
printf( "Error opening %s for reading.\n", argv[1] );
exit( EXIT_FAILURE );
}
if( fread( bios_data, 1, LEN_BIOS_DATA, stream ) < LEN_BIOS_DATA ) {
printf( "Error reading 64KBytes from %s.\n", argv[1] );
fclose( stream );
exit( EXIT_FAILURE );
}
fclose( stream );
hits = 0;
offset = 0L;
while( (tmp_offset = chksum__32__get_offset( bios_data, offset )) != -1L ) {
offset = tmp_offset;
cur_val = chksum__32__get_value( bios_data, offset );
new_val = chksum__32__calc_value( bios_data, offset );
printf( "\n\nPCI-Bios header at: 0x%4lX\n", offset );
printf( "Current checksum: 0x%02X\n", cur_val );
printf( "Calculated checksum: 0x%02X ", new_val );
hits++;
}
if( hits == 1 && cur_val != new_val ) {
printf( "Setting checksum." );
chksum__32__set_value( bios_data, offset, new_val );
}
if( hits >= 2 ) {
printf( "Multiple PCI headers! No checksum set." );
}
if( hits ) {
printf( "\n" );
}
hits = 0;
offset = 0L;
while( (tmp_offset = chksum__mp__get_offset( bios_data, offset )) != -1L ) {
offset = tmp_offset;
cur_val = chksum__mp__get_value( bios_data, offset );
new_val = chksum__mp__calc_value( bios_data, offset );
printf( "\n\nMP header at: 0x%4lX\n", offset );
printf( "Current checksum: 0x%02X\n", cur_val );
printf( "Calculated checksum: 0x%02X ", new_val );
hits++;
}
if( hits == 1 && cur_val != new_val ) {
printf( "Setting checksum." );
chksum__mp__set_value( bios_data, offset, new_val );
}
if( hits >= 2 ) {
printf( "Warning! Multiple MP headers. No checksum set." );
}
if( hits ) {
printf( "\n" );
}
hits = 0;
offset = 0L;
while( (tmp_offset = chksum_pcmp_get_offset( bios_data, offset )) != -1L ) {
offset = tmp_offset;
cur_val = chksum_pcmp_get_value( bios_data, offset );
new_val = chksum_pcmp_calc_value( bios_data, offset );
printf( "\n\nPCMP header at: 0x%4lX\n", offset );
printf( "Current checksum: 0x%02X\n", cur_val );
printf( "Calculated checksum: 0x%02X ", new_val );
hits++;
}
if( hits == 1 && cur_val != new_val ) {
printf( "Setting checksum." );
chksum_pcmp_set_value( bios_data, offset, new_val );
}
if( hits >= 2 ) {
printf( "Warning! Multiple PCMP headers. No checksum set." );
}
if( hits ) {
printf( "\n" );
}
hits = 0;
offset = 0L;
while( (tmp_offset = chksum__pir_get_offset( bios_data, offset )) != -1L ) {
offset = tmp_offset;
cur_val = chksum__pir_get_value( bios_data, offset );
new_val = chksum__pir_calc_value( bios_data, offset );
printf( "\n\n$PIR header at: 0x%4lX\n", offset );
printf( "Current checksum: 0x%02X\n", cur_val );
printf( "Calculated checksum: 0x%02X\n ", new_val );
hits++;
}
if( hits == 1 && cur_val != new_val ) {
printf( "Setting checksum." );
chksum__pir_set_value( bios_data, offset, new_val );
}
if( hits >= 2 ) {
printf( "Warning! Multiple $PIR headers. No checksum set." );
}
if( hits ) {
printf( "\n" );
}
offset = 0L;
offset = chksum_bios_get_offset( bios_data, offset );
cur_val = chksum_bios_get_value( bios_data, offset );
new_val = chksum_bios_calc_value( bios_data, offset );
printf( "\n\nBios checksum at: 0x%4lX\n", offset );
printf( "Current checksum: 0x%02X\n", cur_val );
printf( "Calculated checksum: 0x%02X ", new_val );
if( cur_val != new_val ) {
printf( "Setting checksum." );
chksum_bios_set_value( bios_data, offset, new_val );
}
printf( "\n" );
if(( stream = fopen( argv[1], "wb" )) == NULL ) {
printf( "Error opening %s for writing.\n", argv[1] );
exit( EXIT_FAILURE );
}
if( fwrite( bios_data, 1, LEN_BIOS_DATA, stream ) < LEN_BIOS_DATA ) {
printf( "Error writing 64KBytes to %s.\n", argv[1] );
fclose( stream );
exit( EXIT_FAILURE );
}
fclose( stream );
return( EXIT_SUCCESS );
}
void check( int okay, char* message ) {
if( !okay ) {
printf( "\n\nError. %s.\n", message );
exit( EXIT_FAILURE );
}
}
long chksum_bios_get_offset( byte* data, long offset ) {
return( BIOS_OFFSET );
}
byte chksum_bios_calc_value( byte* data, long offset ) {
int i;
byte sum;
sum = 0;
for( i = 0; i < MAX_OFFSET; i++ ) {
sum = sum + *( data + i );
}
sum = -sum; /* iso ensures -s + s == 0 on unsigned types */
return( sum );
}
byte chksum_bios_get_value( byte* data, long offset ) {
return( *( data + BIOS_OFFSET ) );
}
void chksum_bios_set_value( byte* data, long offset, byte value ) {
*( data + BIOS_OFFSET ) = value;
}
byte chksum__32__calc_value( byte* data, long offset ) {
int i;
int len;
byte sum;
check( offset + _32__MINHDR <= MAX_OFFSET, "_32_ header out of bounds" );
len = *( data + offset + _32__LEN ) << 4;
check( offset + len <= MAX_OFFSET, "_32_ header-length out of bounds" );
sum = 0;
for( i = 0; i < len; i++ ) {
if( i != _32__CHKSUM ) {
sum = sum + *( data + offset + i );
}
}
sum = -sum;
return( sum );
}
long chksum__32__get_offset( byte* data, long offset ) {
long result = -1L;
offset = offset + 0x0F;
offset = offset & ~( 0x0F );
while( offset + 16 < MAX_OFFSET ) {
offset = offset + 16;
if( *( data + offset + 0 ) == '_' && \
*( data + offset + 1 ) == '3' && \
*( data + offset + 2 ) == '2' && \
*( data + offset + 3 ) == '_' ) {
result = offset;
break;
}
}
return( result );
}
byte chksum__32__get_value( byte* data, long offset ) {
check( offset + _32__CHKSUM <= MAX_OFFSET, "PCI-Bios checksum out of bounds" );
return( *( data + offset + _32__CHKSUM ) );
}
void chksum__32__set_value( byte* data, long offset, byte value ) {
check( offset + _32__CHKSUM <= MAX_OFFSET, "PCI-Bios checksum out of bounds" );
*( data + offset + _32__CHKSUM ) = value;
}
byte chksum__mp__calc_value( byte* data, long offset ) {
int i;
int len;
byte sum;
check( offset + _MP__MINHDR <= MAX_OFFSET, "_MP_ header out of bounds" );
len = *( data + offset + _MP__LEN ) << 4;
check( offset + len <= MAX_OFFSET, "_MP_ header-length out of bounds" );
sum = 0;
for( i = 0; i < len; i++ ) {
if( i != _MP__CHKSUM ) {
sum = sum + *( data + offset + i );
}
}
sum = -sum;
return( sum );
}
long chksum__mp__get_offset( byte* data, long offset ) {
long result = -1L;
offset = offset + 0x0F;
offset = offset & ~( 0x0F );
while( offset + 16 < MAX_OFFSET ) {
offset = offset + 16;
if( *( data + offset + 0 ) == '_' && \
*( data + offset + 1 ) == 'M' && \
*( data + offset + 2 ) == 'P' && \
*( data + offset + 3 ) == '_' ) {
result = offset;
break;
}
}
return( result );
}
byte chksum__mp__get_value( byte* data, long offset ) {
check( offset + _MP__CHKSUM <= MAX_OFFSET, "MP checksum out of bounds" );
return( *( data + offset + _MP__CHKSUM ) );
}
void chksum__mp__set_value( byte* data, long offset, byte value ) {
check( offset + _MP__CHKSUM <= MAX_OFFSET, "MP checksum out of bounds" );
*( data + offset + _MP__CHKSUM ) = value;
}
byte chksum_pcmp_calc_value( byte* data, long offset ) {
int i;
int len;
byte sum;
check( offset + PCMP_MINHDR <= MAX_OFFSET, "PCMP header out of bounds" );
len = *( data + offset + PCMP_BASELEN ) + \
( *( data + offset + PCMP_BASELEN + 1 ) << 8 );
check( offset + len <= MAX_OFFSET, "PCMP header-length out of bounds" );
if( *( data + offset + PCMP_EXT_LEN ) | \
*( data + offset + PCMP_EXT_LEN + 1 ) | \
*( data + offset + PCMP_EXT_CHKSUM ) ) {
check( 0, "PCMP header indicates extended tables (unsupported)" );
}
sum = 0;
for( i = 0; i < len; i++ ) {
if( i != PCMP_CHKSUM ) {
sum = sum + *( data + offset + i );
}
}
sum = -sum;
return( sum );
}
long chksum_pcmp_get_offset( byte* data, long offset ) {
long result = -1L;
offset = offset + 0x0F;
offset = offset & ~( 0x0F );
while( offset + 16 < MAX_OFFSET ) {
offset = offset + 16;
if( *( data + offset + 0 ) == 'P' && \
*( data + offset + 1 ) == 'C' && \
*( data + offset + 2 ) == 'M' && \
*( data + offset + 3 ) == 'P' ) {
result = offset;
break;
}
}
return( result );
}
byte chksum_pcmp_get_value( byte* data, long offset ) {
check( offset + PCMP_CHKSUM <= MAX_OFFSET, "PCMP checksum out of bounds" );
return( *( data + offset + PCMP_CHKSUM ) );
}
void chksum_pcmp_set_value( byte* data, long offset, byte value ) {
check( offset + PCMP_CHKSUM <= MAX_OFFSET, "PCMP checksum out of bounds" );
*( data + offset + PCMP_CHKSUM ) = value;
}
byte chksum__pir_calc_value( byte* data, long offset ) {
int i;
int len;
byte sum;
check( offset + _PIR_MINHDR <= MAX_OFFSET, "$PIR header out of bounds" );
len = *( data + offset + _PIR_LEN ) + \
( *( data + offset + _PIR_LEN + 1 ) << 8 );
check( offset + len <= MAX_OFFSET, "$PIR header-length out of bounds" );
sum = 0;
for( i = 0; i < len; i++ ) {
if( i != _PIR_CHKSUM ) {
sum = sum + *( data + offset + i );
}
}
sum = -sum;
return( sum );
}
long chksum__pir_get_offset( byte* data, long offset ) {
long result = -1L;
offset = offset + 0x0F;
offset = offset & ~( 0x0F );
while( offset + 16 < MAX_OFFSET ) {
offset = offset + 16;
if( *( data + offset + 0 ) == '$' && \
*( data + offset + 1 ) == 'P' && \
*( data + offset + 2 ) == 'I' && \
*( data + offset + 3 ) == 'R' ) {
result = offset;
break;
}
}
return( result );
}
byte chksum__pir_get_value( byte* data, long offset ) {
check( offset + _PIR_CHKSUM <= MAX_OFFSET, "$PIR checksum out of bounds" );
return( *( data + offset + _PIR_CHKSUM ) );
}
void chksum__pir_set_value( byte* data, long offset, byte value ) {
check( offset + _PIR_CHKSUM <= MAX_OFFSET, "$PIR checksum out of bounds" );
*( data + offset + _PIR_CHKSUM ) = value;
}
+31
View File
@@ -0,0 +1,31 @@
#!/usr/bin/perl
#
# $Id: makesym.perl,v 1.1 2002/11/24 22:45:40 bdenney Exp $
#
# Read output file from as86 (e.g. rombios.txt) and write out a symbol
# table suitable for the Bochs debugger.
#
$WHERE_BEFORE_SYM_TABLE = 0;
$WHERE_IN_SYM_TABLE = 1;
$WHERE_AFTER_SYM_TABLE = 2;
$where = $WHERE_BEFORE_SYM_TABLE;
while (<STDIN>) {
chop;
if ($where == WHERE_BEFORE_SYM_TABLE && /^Symbols:/) {
$where = $WHERE_IN_SYM_TABLE;
} elsif ($where == $WHERE_IN_SYM_TABLE && /^$/) {
$where = $WHERE_AFTER_SYM_TABLE;
}
if ($where == $WHERE_IN_SYM_TABLE) {
@F = split (/\s+/);
($name[0], $junk, $addr[0], $junk, $name[1], $junk, $addr[1]) = @F;
foreach $col (0,1) {
next if length $addr[$col] < 1;
$addr[$col] =~ tr/A-Z/a-z/;
$addr[$col] = "000f" . $addr[$col];
print "$addr[$col] $name[$col]\n";
}
}
}
File diff suppressed because it is too large. Load diff
+206
View File
@@ -0,0 +1,206 @@
--- /home/leendert/cvs/bochs/bios/rombios.c 2005-05-23 12:18:11.000000000 -0400
+++ rombios.c 2005-06-01 23:46:45.000000000 -0400
@@ -26,6 +26,7 @@
// ROM BIOS for use with Bochs/Plex x86 emulation environment
+#define VMXASSIST
// ROM BIOS compatability entry points:
// ===================================
@@ -170,7 +171,9 @@
#define BASE_MEM_IN_K (640 - EBDA_SIZE)
// Define the application NAME
-#ifdef PLEX86
+#ifdef VMXASSIST
+# define BX_APPNAME "VMXAssist"
+#elif PLEX86
# define BX_APPNAME "Plex86"
#else
# define BX_APPNAME "Bochs"
@@ -314,7 +317,6 @@
ASM_END
}
-#if 0
// memcpy of count bytes
void
memcpyb(dseg,doffset,sseg,soffset,count)
@@ -362,6 +364,7 @@
ASM_END
}
+#if 0
// memcpy of count dword
void
memcpyd(dseg,doffset,sseg,soffset,count)
@@ -858,6 +861,7 @@
static void write_byte();
static void write_word();
static void bios_printf();
+static void copy_e820_table();
static Bit8u inhibit_mouse_int_and_events();
static void enable_mouse_int_and_events();
@@ -1420,6 +1424,16 @@
ASM_END
}
+#ifdef VMXASSIST
+void
+copy_e820_table()
+{
+ Bit8u nr_entries = read_byte(0x9000, 0x1e8);
+ write_word(0xe000, 0x8, nr_entries);
+ memcpyb(0xe000, 0x10, 0x9000, 0x2d0, nr_entries * 0x14);
+}
+#endif /* VMXASSIST */
+
#if BX_DEBUG_SERIAL
/* serial debug port*/
#define BX_DEBUG_PORT 0x03f8
@@ -1498,6 +1512,9 @@
if (c == '\n') uart_tx_byte(BX_DEBUG_PORT, '\r');
uart_tx_byte(BX_DEBUG_PORT, c);
#endif
+#ifdef VMXASSIST
+ outb(0xE9, c);
+#endif
#if BX_VIRTUAL_PORTS
if (action & BIOS_PRINTF_DEBUG) outb(DEBUG_PORT, c);
if (action & BIOS_PRINTF_INFO) outb(INFO_PORT, c);
@@ -4053,6 +4070,66 @@
case 0x20: // coded by osmaker aka K.J.
if(regs.u.r32.edx == 0x534D4150)
{
+#ifdef VMXASSIST
+ if ((regs.u.r16.bx / 0x14)* 0x14 == regs.u.r16.bx) {
+ Bit16u e820_table_size = read_word(0xe000, 0x8) * 0x14;
+
+ if (regs.u.r16.bx + 0x14 <= e820_table_size) {
+ memcpyb(ES, regs.u.r16.di,
+ 0xe000, 0x10 + regs.u.r16.bx, 0x14);
+ }
+ regs.u.r32.ebx += 0x14;
+ if ((regs.u.r32.ebx + 0x14 - 1) > e820_table_size)
+ regs.u.r32.ebx = 0;
+ regs.u.r32.eax = 0x534D4150;
+ regs.u.r32.ecx = 0x14;
+ CLEAR_CF();
+ return;
+ } else if (regs.u.r16.bx == 1) {
+ extended_memory_size = inb_cmos(0x35);
+ extended_memory_size <<= 8;
+ extended_memory_size |= inb_cmos(0x34);
+ extended_memory_size *= 64;
+ if (extended_memory_size > 0x3bc000) // greater than EFF00000???
+ {
+ extended_memory_size = 0x3bc000; // everything after this is reserved memory until we get to 0x100000000
+ }
+ extended_memory_size *= 1024;
+ extended_memory_size += 15728640; // make up for the 16mb of memory that is chopped off
+
+ if (extended_memory_size <= 15728640)
+ {
+ extended_memory_size = inb_cmos(0x31);
+ extended_memory_size <<= 8;
+ extended_memory_size |= inb_cmos(0x30);
+ extended_memory_size *= 1024;
+ }
+
+ write_word(ES, regs.u.r16.di, 0x0000);
+ write_word(ES, regs.u.r16.di+2, 0x0010);
+ write_word(ES, regs.u.r16.di+4, 0x0000);
+ write_word(ES, regs.u.r16.di+6, 0x0000);
+
+ write_word(ES, regs.u.r16.di+8, extended_memory_size);
+ extended_memory_size >>= 16;
+ write_word(ES, regs.u.r16.di+10, extended_memory_size);
+ extended_memory_size >>= 16;
+ write_word(ES, regs.u.r16.di+12, extended_memory_size);
+ extended_memory_size >>= 16;
+ write_word(ES, regs.u.r16.di+14, extended_memory_size);
+
+ write_word(ES, regs.u.r16.di+16, 0x1);
+ write_word(ES, regs.u.r16.di+18, 0x0);
+
+ regs.u.r32.ebx = 0;
+ regs.u.r32.eax = 0x534D4150;
+ regs.u.r32.ecx = 0x14;
+ CLEAR_CF();
+ return;
+ } else { /* AX=E820, DX=534D4150, BX unrecognized */
+ goto int15_unimplemented;
+ }
+#else
switch(regs.u.r16.bx)
{
case 0:
@@ -4070,6 +4147,7 @@
write_word(ES, regs.u.r16.di+18, 0x0);
regs.u.r32.ebx = 1;
+
regs.u.r32.eax = 0x534D4150;
regs.u.r32.ecx = 0x14;
CLEAR_CF();
@@ -4121,6 +4199,7 @@
goto int15_unimplemented;
break;
}
+#endif
} else {
// if DX != 0x534D4150)
goto int15_unimplemented;
@@ -9497,9 +9576,16 @@
;; int 1C already points at dummy_iret_handler (above)
mov al, #0x34 ; timer0: binary count, 16bit count, mode 2
out 0x43, al
+#ifdef VMXASSIST
+ mov al, #0x0b ; #0xe90b = 20 Hz (temporary, until we fix xen/vmx support)
+ out 0x40, al ; lsb
+ mov al, #0xe9
+ out 0x40, al ; msb
+#else
mov al, #0x00 ; maximum count of 0000H = 18.2Hz
out 0x40, al
out 0x40, al
+#endif
;; Keyboard
SET_INT_VECTOR(0x09, #0xF000, #int09_handler)
@@ -9597,10 +9683,22 @@
mov al, #0x11 ; send initialisation commands
out 0x20, al
out 0xa0, al
+#ifdef VMXASSIST
+ ;; The vm86 emulator expects interrupts to be mapped beyond the reserved
+ ;; vectors (0 through 31). Since rombios fully controls the hardware, we
+ ;; map it the way the emulator needs it and expect that it will do the
+ ;; proper 8086 interrupt translation (that is, master pic base is at 0x8
+ ;; and slave pic base is at 0x70).
+ mov al, #0x20
+ out 0x21, al
+ mov al, #0x28
+ out 0xa1, al
+#else
mov al, #0x08
out 0x21, al
mov al, #0x70
out 0xa1, al
+#endif
mov al, #0x04
out 0x21, al
mov al, #0x02
@@ -9617,6 +9715,10 @@
#endif
out 0xa1, AL ;slave pic: unmask IRQ 12, 13, 14
+#ifdef VMXASSIST
+ call _copy_e820_table
+#endif
+
call pcibios_init
call rom_scan
+3
View File
@@ -0,0 +1,3 @@
Not all the functions have been implemented yet.
Please report any bugs to <info@vruppert.de>
+504
View File
@@ -0,0 +1,504 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!
File diff suppressed because it is too large. Load diff
+80
View File
@@ -0,0 +1,80 @@
SHELL = /bin/sh
CC = gcc
CFLAGS = -g -O2 -Wall -Wstrict-prototypes
LDFLAGS =
GCC = gcc
BCC = bcc
AS86 = as86
RELEASE = `pwd | sed "s-.*/--"`
RELDATE = `date '+%d %b %Y'`
RELVERS = `pwd | sed "s-.*/--" | sed "s/vgabios//" | sed "s/-//"`
VGABIOS_DATE = "-DVGABIOS_DATE=\"$(RELDATE)\""
all: bios cirrus-bios
bios: biossums vgabios.bin vgabios.debug.bin
cirrus-bios: vgabios-cirrus.bin vgabios-cirrus.debug.bin
clean:
/bin/rm -f biossums *.o *.s *.ld86 \
temp.awk.* vgabios*.orig _vgabios_* _vgabios-debug_* core vgabios*.bin vgabios*.txt $(RELEASE).bin *.bak
rm -f VGABIOS-lgpl-latest*.bin
release:
VGABIOS_VERS=\"-DVGABIOS_VERS=\\\"$(RELVERS)\\\"\" make bios cirrus-bios
/bin/rm -f *.o *.s *.ld86 \
temp.awk.* vgabios.*.orig _vgabios_.*.c core *.bak .#*
cp VGABIOS-lgpl-latest.bin ../$(RELEASE).bin
cp VGABIOS-lgpl-latest.debug.bin ../$(RELEASE).debug.bin
cp VGABIOS-lgpl-latest.cirrus.bin ../$(RELEASE).cirrus.bin
cp VGABIOS-lgpl-latest.cirrus.debug.bin ../$(RELEASE).cirrus.debug.bin
tar czvf ../$(RELEASE).tgz --exclude CVS -C .. $(RELEASE)/
vgabios.bin: vgabios.c vgabios.h vgafonts.h vgatables.h vbe.h vbe.c vbetables.h
$(GCC) -E -P vgabios.c $(VGABIOS_VERS) $(VGABIOS_DATE) > _vgabios_.c
$(BCC) -o vgabios.s -C-c -D__i86__ -S -0 _vgabios_.c
sed -e 's/^\.text//' -e 's/^\.data//' vgabios.s > _vgabios_.s
$(AS86) _vgabios_.s -b vgabios.bin -u -w- -g -0 -j -O -l vgabios.txt
rm -f _vgabios_.s _vgabios_.c vgabios.s
mv vgabios.bin VGABIOS-lgpl-latest.bin
./biossums VGABIOS-lgpl-latest.bin
ls -l VGABIOS-lgpl-latest.bin
vgabios.debug.bin: vgabios.c vgabios.h vgafonts.h vgatables.h vbe.h vbe.c vbetables.h
$(GCC) -E -P vgabios.c $(VGABIOS_VERS) -DDEBUG $(VGABIOS_DATE) > _vgabios-debug_.c
$(BCC) -o vgabios-debug.s -C-c -D__i86__ -S -0 _vgabios-debug_.c
sed -e 's/^\.text//' -e 's/^\.data//' vgabios-debug.s > _vgabios-debug_.s
$(AS86) _vgabios-debug_.s -b vgabios.debug.bin -u -w- -g -0 -j -O -l vgabios.debug.txt
rm -f _vgabios-debug_.s _vgabios-debug_.c vgabios-debug.s
mv vgabios.debug.bin VGABIOS-lgpl-latest.debug.bin
./biossums VGABIOS-lgpl-latest.debug.bin
ls -l VGABIOS-lgpl-latest.debug.bin
vgabios-cirrus.bin: vgabios.c vgabios.h vgafonts.h vgatables.h clext.c
$(GCC) -E -P vgabios.c $(VGABIOS_VERS) -DCIRRUS $(VGABIOS_DATE) > _vgabios-cirrus_.c
$(BCC) -o vgabios-cirrus.s -C-c -D__i86__ -S -0 _vgabios-cirrus_.c
sed -e 's/^\.text//' -e 's/^\.data//' vgabios-cirrus.s > _vgabios-cirrus_.s
$(AS86) _vgabios-cirrus_.s -b vgabios-cirrus.bin -u -w- -g -0 -j -O -l vgabios.cirrus.txt
rm -f _vgabios-cirrus_.s _vgabios-cirrus_.c vgabios-cirrus.s
mv vgabios-cirrus.bin VGABIOS-lgpl-latest.cirrus.bin
./biossums VGABIOS-lgpl-latest.cirrus.bin
ls -l VGABIOS-lgpl-latest.cirrus.bin
vgabios-cirrus.debug.bin: vgabios.c vgabios.h vgafonts.h vgatables.h clext.c
$(GCC) -E -P vgabios.c $(VGABIOS_VERS) -DCIRRUS -DCIRRUS_DEBUG $(VGABIOS_DATE) > _vgabios-cirrus-debug_.c
$(BCC) -o vgabios-cirrus-debug.s -C-c -D__i86__ -S -0 _vgabios-cirrus-debug_.c
sed -e 's/^\.text//' -e 's/^\.data//' vgabios-cirrus-debug.s > _vgabios-cirrus-debug_.s
$(AS86) _vgabios-cirrus-debug_.s -b vgabios.cirrus.debug.bin -u -w- -g -0 -j -O -l vgabios.cirrus.debug.txt
rm -f _vgabios-cirrus-debug_.s _vgabios-cirrus-debug_.c vgabios-cirrus-debug.s
mv vgabios.cirrus.debug.bin VGABIOS-lgpl-latest.cirrus.debug.bin
./biossums VGABIOS-lgpl-latest.cirrus.debug.bin
ls -l VGABIOS-lgpl-latest.cirrus.debug.bin
biossums: biossums.c
$(CC) -o biossums biossums.c
+11
View File
@@ -0,0 +1,11 @@
Development notes
-----------------
- need to split video init function
1. set bios variables
2. do the real init with io based on bios variables
- characters format switching will set the bios
variables and call function #2 above
- need to rework the tables as explained in Interrupt list
+191
View File
@@ -0,0 +1,191 @@
Plex86/Bochs VGABios
--------------------
The goal of this project is to have a LGPL'd Video Bios in plex86,
Bochs and qemu.
This VGA Bios is very specific to the emulated VGA card.
It is NOT meant to drive a physical vga card.
Cirrus SVGA extension
---------------------
The Cirrus SVGA extension is designed for the Cirrus emulation in Bochs and
qemu. The initial patch for the Cirrus extension has been written by Makoto
Suzuki (suzu).
Install
-------
To compile the VGA Bios you will need :
- gcc
- bcc
- as86
- ld86
Untar the archive, and type make. You should get a "VGABIOS-lgpl-latest.bin"
file. Alternatively, you can use the binary file "VGABIOS-lgpl-latest.bin",
i have compiled for you.
Edit your plex86/bochs conf file, and modify the load-rom command in the
VGA BIOS section, to point to the new vgabios image file.
Debugging
---------
You can get a very basic debugging system: messages printed by the vgabios.
You have to register the "unmapped" device driver in plex86 or bochs, and make
sure it grabs port 0xfff0.
Comment the #undef DEBUG at the beginning of vgabios.c.
You can then use the "printf" function in the bios.
Testing
-------
Look at the "testvga.c" file in the archive. This is a minimal Turbo C 2.0
source file that calls a few int10 functions. Feel free to modify it to suit
your needs.
Copyright and License
---------------------
This program has been written by Christophe Bothamy
It is protected by the GNU Lesser Public License, which you should
have received a copy of along with this package.
Reverse Engineering
-------------------
The VGA Bios has been written without reverse-engineering any existing Bios.
Acknowledgment
--------------
The source code contains code ripped from rombios.c of plex86, written
by Kevin Lawton <kevin2001@yahoo.com>
The source code contains fonts from fntcol16.zip (c) by Joseph Gil avalable at :
ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip
These fonts are public domain
The source code is based on information taken from :
- Kevin Lawton's vga card emulation for bochs/plex86
- Ralf Brown's interrupts list avalaible at
http://www.cs.cmu.edu/afs/cs/user/ralf/pub/WWW/files.html
- Finn Thogersons' VGADOC4b available at http://home.worldonline.dk/~finth/
- Michael Abrash's Graphics Programming Black Book
- Francois Gervais' book "programmation des cartes graphiques cga-ega-vga"
edited by sybex
- DOSEMU 1.0.1 source code for several tables values and formulas
Feedback
--------
Please report any bugs, comments, patches for this VGA Bios to info@vruppert.de
You can find the latest release at : http://www.nongnu.org/vgabios/
For any information on bochs, visit the website http://bochs.sourceforge.net/
For any information on qemu, visit the website http://fabrice.bellard.free.fr/qemu/
History
-------
vgabios-0.5b : May 24 2005
- Volker
. fixed return value for the default case in the VBE section (non-debug mode)
. removed unused stuff
vgabios-0.5a : Mar 07 2005
- Volker
. Cirrus SVGA extension (initial patches from Makoto Suzuki, improvements
from Fabrice Bellard)
. vgabios image size is now exactly 32k with a checksum
. a lot of vgabios and vbe functions rewritten in assembler
. dynamicly generated VBE mode info list
. write character function for CGA and LINEAR8 modes
. read/write graphics pixel for some graphics modes
. text scroll feature for some graphics modes
. VBE 8-bit DAC support
vgabios-0.4c : Nov 06 2003
- Christophe
. fix font problem on initial screen of NT4 Loader
vgabios-0.4b : Nov 04 2003
- Volker
. fix offset of character tables
. optimizations of CRT controller accesses
. VBE i/o registers changed to 0x01CE/CF
(suggestion from Daniel Gimpelevich)
. "noclear" flag stored in BIOS area
. fix character height returned by get_font_info function
vgabios-0.4a : Aug 17 2003
- Volker
. VBE mode search rewritten (VBE modes with LFB bit removed)
. many bugfixes and optimizations
. write character function implemented for graphics modes
. support for 15bpp, 16bpp, 24bpp and 32bpp VBE modes added
. SVGA mode 0x6A added
. VBE modes 0x102, 0x117, 0x118 and 0x142 (Bochs specific)
vgabios-0.3b : Nov 23 2002
- Christophe
. added lfb-mode numbers (patch from mathis)
. updated the Makefile
. removed display of copyrights.
. changed the Copyright string to "LGPL VGABios developers"
- Volker
. set the cursor shape depending on the current font height
. clear BL before calling int 0x10 function 0x1103 in vgabios_init_func
. added some text font functions
- Jeroen
. Forced to new DISPI (0xb0c1) interface (requires latest bochs vbe code)
. Added multibuffering support
. Added new DISPI interface for: virt width, height, x offset, y offset
. Added LFB modes (to be used with the vbe-lfb patch in bochs)
see VBE_HAVE_LFB in vbe.c (currently default enabled)
. updated TODO & docs for changes after bochs 1.4
vgabios-0.3a : Mar 10 2002
- Christophe
. Fixed bug in function ah=13
- Jeroen
. updated vbebios implementation to new api
. added vbe_display_api documentation
. added 640x400x8, 640x480x8, 800x600x8, 1024x768
(>640x480 needs a special bochs patch atm)
. added 320x200x8 vbe support (uses the standard 320x200x8 vga mode to
display, this allows for testing & having something on screen as well,
at least until bochs host side display is up & running)
. adding lfbprof (vbe) testprogram (+some small fixes to it)
. merging with vbebios 0.2
vgabios-0.2b : Nov 19 2001
- Christophe
. Fixed bug in function ah=13
vgabios-0.2a : Nov 09 2001
- Christophe
. Included bugfix from techt@pikeonline.net about grayscale summing
. Added the "IBM" string at org 0x1e as Bart Oldeman suggested
. Fixed DS and ES that where inverted in the int10 parameters list!
. The following have been implemented :
- function ax=1a00, ax=1a01, ah=1b
- function ax=1130
. Added debug messages for unimplemented/unknown functions
Must be compiled with DEBUG defined. The output is trapped
by the unknown-ioport driver of plex/bochs (port 0xfff0 is used)
vgabios-0.1a : May 8 2001
- Christophe
. First release. The work has been focused only on text mode.
. The following have been implemented :
- inits
- int 10 handler
- functions ah=00, ah=01, ah=02, ah=03, ah=05, ah=06, ah=07, ah=08
ah=09, ah=0a, ah=0e, ah=0f, ax=1000, ax=1001, ax=1002, ax=1003
ax=1007, ax=1008, ax=1009, ax=1010, ax=1012, ax=1013, ax=1015
ax=1017, ax=1018, ax=1019, ax=101a, ax=101b, ah=12 bl=10,
ah=12 bl=30, ah=12 bl=31, ah=12 bl=32, ah=12 bl=33, ah=12 bl=34
ah=13
+28
View File
@@ -0,0 +1,28 @@
Short term :
------------
General
- Fix init mode (ah=00). Should use more BIOS variables
- Add new functionalities and modify static functionality table
- Performance : 16 bits IO
v0.6
- Reimplement the tables so it is compatible with the video save pointer table
- Implement the remaining functions (don't know if all are needed):
- chargen ax=1120, ax=1121, ax=1122, ax=1123, ax=1124
- display switch interface ah=12 bl=35
- video refresh control ah=12 bl=36
- save/restore state ah=1c
- Graphic modes
v1.0
- Bugfixes
=================================================================================================
VBE:
----
Long term:
- have plex86 host side display interface
- have text io functions in vbe mode
+200
View File
@@ -0,0 +1,200 @@
/* biossums.c --- written by Eike W. for the Bochs BIOS */
/* adapted for the LGPL'd VGABIOS by vruppert */
#include <stdlib.h>
#include <stdio.h>
typedef unsigned char byte;
void check( int value, char* message );
#define LEN_BIOS_DATA 0x8000
#define MAX_OFFSET (LEN_BIOS_DATA - 1)
#define BIOS_OFFSET 0x7FFF
long chksum_bios_get_offset( byte* data, long offset );
byte chksum_bios_calc_value( byte* data, long offset );
byte chksum_bios_get_value( byte* data, long offset );
void chksum_bios_set_value( byte* data, long offset, byte value );
#define PMID_LEN 20
#define PMID_CHKSUM 19
long chksum_pmid_get_offset( byte* data, long offset );
byte chksum_pmid_calc_value( byte* data, long offset );
byte chksum_pmid_get_value( byte* data, long offset );
void chksum_pmid_set_value( byte* data, long offset, byte value );
byte bios_data[LEN_BIOS_DATA];
int main( int argc, char* argv[] ) {
FILE* stream;
long offset, tmp_offset;
byte cur_val = 0, new_val = 0;
int hits;
if( argc != 2 ) {
printf( "Error. Need a file-name as an argument.\n" );
exit( EXIT_FAILURE );
}
if(( stream = fopen( argv[1], "rb" )) == NULL ) {
printf( "Error opening %s for reading.\n", argv[1] );
exit( EXIT_FAILURE );
}
if( fread( bios_data, 1, LEN_BIOS_DATA, stream ) >= LEN_BIOS_DATA ) {
printf( "Error reading max. 32767 Bytes from %s.\n", argv[1] );
fclose( stream );
exit( EXIT_FAILURE );
}
fclose( stream );
hits = 0;
offset = 0L;
while( (tmp_offset = chksum_pmid_get_offset( bios_data, offset )) != -1L ) {
offset = tmp_offset;
cur_val = chksum_pmid_get_value( bios_data, offset );
new_val = chksum_pmid_calc_value( bios_data, offset );
printf( "\nPMID entry at: 0x%4lX\n", offset );
printf( "Current checksum: 0x%02X\n", cur_val );
printf( "Calculated checksum: 0x%02X ", new_val );
hits++;
}
if( hits == 1 && cur_val != new_val ) {
printf( "Setting checksum." );
chksum_pmid_set_value( bios_data, offset, new_val );
}
if( hits >= 2 ) {
printf( "Multiple PMID entries! No checksum set." );
}
if( hits ) {
printf( "\n" );
}
offset = 0L;
offset = chksum_bios_get_offset( bios_data, offset );
cur_val = chksum_bios_get_value( bios_data, offset );
new_val = chksum_bios_calc_value( bios_data, offset );
printf( "\nBios checksum at: 0x%4lX\n", offset );
printf( "Current checksum: 0x%02X\n", cur_val );
printf( "Calculated checksum: 0x%02X ", new_val );
if( cur_val != new_val ) {
printf( "Setting checksum." );
chksum_bios_set_value( bios_data, offset, new_val );
}
printf( "\n" );
if(( stream = fopen( argv[1], "wb" )) == NULL ) {
printf( "Error opening %s for writing.\n", argv[1] );
exit( EXIT_FAILURE );
}
if( fwrite( bios_data, 1, LEN_BIOS_DATA, stream ) < LEN_BIOS_DATA ) {
printf( "Error writing 32KBytes to %s.\n", argv[1] );
fclose( stream );
exit( EXIT_FAILURE );
}
fclose( stream );
return( EXIT_SUCCESS );
}
void check( int okay, char* message ) {
if( !okay ) {
printf( "\n\nError. %s.\n", message );
exit( EXIT_FAILURE );
}
}
long chksum_bios_get_offset( byte* data, long offset ) {
return( BIOS_OFFSET );
}
byte chksum_bios_calc_value( byte* data, long offset ) {
int i;
byte sum;
sum = 0;
for( i = 0; i < MAX_OFFSET; i++ ) {
sum = sum + *( data + i );
}
sum = -sum; /* iso ensures -s + s == 0 on unsigned types */
return( sum );
}
byte chksum_bios_get_value( byte* data, long offset ) {
return( *( data + BIOS_OFFSET ) );
}
void chksum_bios_set_value( byte* data, long offset, byte value ) {
*( data + BIOS_OFFSET ) = value;
}
byte chksum_pmid_calc_value( byte* data, long offset ) {
int i;
int len;
byte sum;
len = PMID_LEN;
check( offset + len <= MAX_OFFSET, "PMID entry length out of bounds" );
sum = 0;
for( i = 0; i < len; i++ ) {
if( i != PMID_CHKSUM ) {
sum = sum + *( data + offset + i );
}
}
sum = -sum;
return( sum );
}
long chksum_pmid_get_offset( byte* data, long offset ) {
long result = -1L;
while( offset + PMID_LEN < MAX_OFFSET ) {
offset = offset + 1;
if( *( data + offset + 0 ) == 'P' && \
*( data + offset + 1 ) == 'M' && \
*( data + offset + 2 ) == 'I' && \
*( data + offset + 3 ) == 'D' ) {
result = offset;
break;
}
}
return( result );
}
byte chksum_pmid_get_value( byte* data, long offset ) {
check( offset + PMID_CHKSUM <= MAX_OFFSET, "PMID checksum out of bounds" );
return( *( data + offset + PMID_CHKSUM ) );
}
void chksum_pmid_set_value( byte* data, long offset, byte value ) {
check( offset + PMID_CHKSUM <= MAX_OFFSET, "PMID checksum out of bounds" );
*( data + offset + PMID_CHKSUM ) = value;
}
File diff suppressed because it is too large. Load diff
+23
View File
@@ -0,0 +1,23 @@
#!/bin/bash
awk \
'BEGIN { }\
/^\.text/,/DATA_SEG_DEFS_HERE/ { print }\
END { }'\
$1 > temp.awk.1
awk \
'BEGIN { i = 0; last = "hello" }\
/BLOCK_STRINGS_BEGIN/,/^\.bss/ { if ( i > 1 ) { print last } last = $0; i = i + 1 }\
END { }'\
$1 > temp.awk.2
awk \
'BEGIN { }\
/DATA_SEG_DEFS_HERE/,/BLOCK_STRINGS_BEGIN/ { print }\
END { }'\
$1 > temp.awk.3
cp $1 $1.orig
cat temp.awk.1 temp.awk.2 temp.awk.3 | sed -e 's/^\.data//' -e 's/^\.bss//' -e 's/^\.text//' > $1
/bin/rm -f temp.awk.1 temp.awk.2 temp.awk.3 $1.orig
File diff suppressed because it is too large. Load diff
+302
View File
@@ -0,0 +1,302 @@
#ifndef vbe_h_included
#define vbe_h_included
#include "vgabios.h"
// DISPI helper function
void dispi_set_enable(enable);
/** VBE int10 API
*
* See the function descriptions in vbe.c for more information
*/
Boolean vbe_has_vbe_display();
void vbe_biosfn_return_controller_information(AX, ES, DI);
void vbe_biosfn_return_mode_information(AX, CX, ES, DI);
void vbe_biosfn_set_mode(AX, BX, ES, DI);
void vbe_biosfn_save_restore_state(AX, DL, CX, ES, BX);
void vbe_biosfn_set_get_palette_data(AX);
void vbe_biosfn_return_protected_mode_interface(AX);
// The official VBE Information Block
typedef struct VbeInfoBlock
{
Bit8u VbeSignature[4];
Bit16u VbeVersion;
Bit16u OemStringPtr_Off;
Bit16u OemStringPtr_Seg;
Bit8u Capabilities[4];
Bit16u VideoModePtr_Off;
Bit16u VideoModePtr_Seg;
Bit16u TotalMemory;
Bit16u OemSoftwareRev;
Bit16u OemVendorNamePtr_Off;
Bit16u OemVendorNamePtr_Seg;
Bit16u OemProductNamePtr_Off;
Bit16u OemProductNamePtr_Seg;
Bit16u OemProductRevPtr_Off;
Bit16u OemProductRevPtr_Seg;
Bit16u Reserved[111]; // used for dynamicly generated mode list
Bit8u OemData[256];
} VbeInfoBlock;
// This one is for compactly storing a static list of mode info blocks
// this saves us 189 bytes per block
typedef struct ModeInfoBlockCompact
{
// Mandatory information for all VBE revisions
Bit16u ModeAttributes;
Bit8u WinAAttributes;
Bit8u WinBAttributes;
Bit16u WinGranularity;
Bit16u WinSize;
Bit16u WinASegment;
Bit16u WinBSegment;
Bit32u WinFuncPtr;
Bit16u BytesPerScanLine;
// Mandatory information for VBE 1.2 and above
Bit16u XResolution;
Bit16u YResolution;
Bit8u XCharSize;
Bit8u YCharSize;
Bit8u NumberOfPlanes;
Bit8u BitsPerPixel;
Bit8u NumberOfBanks;
Bit8u MemoryModel;
Bit8u BankSize;
Bit8u NumberOfImagePages;
Bit8u Reserved_page;
// Direct Color fields (required for direct/6 and YUV/7 memory models)
Bit8u RedMaskSize;
Bit8u RedFieldPosition;
Bit8u GreenMaskSize;
Bit8u GreenFieldPosition;
Bit8u BlueMaskSize;
Bit8u BlueFieldPosition;
Bit8u RsvdMaskSize;
Bit8u RsvdFieldPosition;
Bit8u DirectColorModeInfo;
// Mandatory information for VBE 2.0 and above
Bit32u PhysBasePtr;
Bit32u OffScreenMemOffset;
Bit16u OffScreenMemSize;
// Mandatory information for VBE 3.0 and above
Bit16u LinBytesPerScanLine;
Bit8u BnkNumberOfPages;
Bit8u LinNumberOfPages;
Bit8u LinRedMaskSize;
Bit8u LinRedFieldPosition;
Bit8u LinGreenMaskSize;
Bit8u LinGreenFieldPosition;
Bit8u LinBlueMaskSize;
Bit8u LinBlueFieldPosition;
Bit8u LinRsvdMaskSize;
Bit8u LinRsvdFieldPosition;
Bit32u MaxPixelClock;
// Bit8u Reserved[189]; // DO NOT PUT THIS IN HERE because of Compact Mode Info storage in bios
} ModeInfoBlockCompact;
typedef struct ModeInfoBlock
{
// Mandatory information for all VBE revisions
Bit16u ModeAttributes;
Bit8u WinAAttributes;
Bit8u WinBAttributes;
Bit16u WinGranularity;
Bit16u WinSize;
Bit16u WinASegment;
Bit16u WinBSegment;
Bit32u WinFuncPtr;
Bit16u BytesPerScanLine;
// Mandatory information for VBE 1.2 and above
Bit16u XResolution;
Bit16u YResolution;
Bit8u XCharSize;
Bit8u YCharSize;
Bit8u NumberOfPlanes;
Bit8u BitsPerPixel;
Bit8u NumberOfBanks;
Bit8u MemoryModel;
Bit8u BankSize;
Bit8u NumberOfImagePages;
Bit8u Reserved_page;
// Direct Color fields (required for direct/6 and YUV/7 memory models)
Bit8u RedMaskSize;
Bit8u RedFieldPosition;
Bit8u GreenMaskSize;
Bit8u GreenFieldPosition;
Bit8u BlueMaskSize;
Bit8u BlueFieldPosition;
Bit8u RsvdMaskSize;
Bit8u RsvdFieldPosition;
Bit8u DirectColorModeInfo;
// Mandatory information for VBE 2.0 and above
Bit32u PhysBasePtr;
Bit32u OffScreenMemOffset;
Bit16u OffScreenMemSize;
// Mandatory information for VBE 3.0 and above
Bit16u LinBytesPerScanLine;
Bit8u BnkNumberOfPages;
Bit8u LinNumberOfPages;
Bit8u LinRedMaskSize;
Bit8u LinRedFieldPosition;
Bit8u LinGreenMaskSize;
Bit8u LinGreenFieldPosition;
Bit8u LinBlueMaskSize;
Bit8u LinBlueFieldPosition;
Bit8u LinRsvdMaskSize;
Bit8u LinRsvdFieldPosition;
Bit32u MaxPixelClock;
Bit8u Reserved[189];
} ModeInfoBlock;
// VBE Return Status Info
// AL
#define VBE_RETURN_STATUS_SUPPORTED 0x4F
#define VBE_RETURN_STATUS_UNSUPPORTED 0x00
// AH
#define VBE_RETURN_STATUS_SUCCESSFULL 0x00
#define VBE_RETURN_STATUS_FAILED 0x01
#define VBE_RETURN_STATUS_NOT_SUPPORTED 0x02
#define VBE_RETURN_STATUS_INVALID 0x03
// VBE Mode Numbers
#define VBE_MODE_VESA_DEFINED 0x0100
#define VBE_MODE_REFRESH_RATE_USE_CRTC 0x0800
#define VBE_MODE_LINEAR_FRAME_BUFFER 0x4000
#define VBE_MODE_PRESERVE_DISPLAY_MEMORY 0x8000
// VBE GFX Mode Number
#define VBE_VESA_MODE_640X400X8 0x100
#define VBE_VESA_MODE_640X480X8 0x101
#define VBE_VESA_MODE_800X600X4 0x102
#define VBE_VESA_MODE_800X600X8 0x103
#define VBE_VESA_MODE_1024X768X4 0x104
#define VBE_VESA_MODE_1024X768X8 0x105
#define VBE_VESA_MODE_1280X1024X4 0x106
#define VBE_VESA_MODE_1280X1024X8 0x107
#define VBE_VESA_MODE_320X200X1555 0x10D
#define VBE_VESA_MODE_320X200X565 0x10E
#define VBE_VESA_MODE_320X200X888 0x10F
#define VBE_VESA_MODE_640X480X1555 0x110
#define VBE_VESA_MODE_640X480X565 0x111
#define VBE_VESA_MODE_640X480X888 0x112
#define VBE_VESA_MODE_800X600X1555 0x113
#define VBE_VESA_MODE_800X600X565 0x114
#define VBE_VESA_MODE_800X600X888 0x115
#define VBE_VESA_MODE_1024X768X1555 0x116
#define VBE_VESA_MODE_1024X768X565 0x117
#define VBE_VESA_MODE_1024X768X888 0x118
#define VBE_VESA_MODE_1280X1024X1555 0x119
#define VBE_VESA_MODE_1280X1024X565 0x11A
#define VBE_VESA_MODE_1280X1024X888 0x11B
// BOCHS/PLEX86 'own' mode numbers
#define VBE_OWN_MODE_320X200X8888 0x140
#define VBE_OWN_MODE_640X400X8888 0x141
#define VBE_OWN_MODE_640X480X8888 0x142
#define VBE_OWN_MODE_800X600X8888 0x143
#define VBE_OWN_MODE_1024X768X8888 0x144
#define VBE_OWN_MODE_1280X1024X8888 0x145
#define VBE_OWN_MODE_320X200X8 0x146
#define VBE_VESA_MODE_END_OF_LIST 0xFFFF
// Capabilities
#define VBE_CAPABILITY_8BIT_DAC 0x0001
#define VBE_CAPABILITY_NOT_VGA_COMPATIBLE 0x0002
#define VBE_CAPABILITY_RAMDAC_USE_BLANK_BIT 0x0004
#define VBE_CAPABILITY_STEREOSCOPIC_SUPPORT 0x0008
#define VBE_CAPABILITY_STEREO_VIA_VESA_EVC 0x0010
// Mode Attributes
#define VBE_MODE_ATTRIBUTE_SUPPORTED 0x0001
#define VBE_MODE_ATTRIBUTE_EXTENDED_INFORMATION_AVAILABLE 0x0002
#define VBE_MODE_ATTRIBUTE_TTY_BIOS_SUPPORT 0x0004
#define VBE_MODE_ATTRIBUTE_COLOR_MODE 0x0008
#define VBE_MODE_ATTRIBUTE_GRAPHICS_MODE 0x0010
#define VBE_MODE_ATTRIBUTE_NOT_VGA_COMPATIBLE 0x0020
#define VBE_MODE_ATTRIBUTE_NO_VGA_COMPATIBLE_WINDOW 0x0040
#define VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE 0x0080
#define VBE_MODE_ATTRIBUTE_DOUBLE_SCAN_MODE 0x0100
#define VBE_MODE_ATTRIBUTE_INTERLACE_MODE 0x0200
#define VBE_MODE_ATTRIBUTE_HARDWARE_TRIPLE_BUFFER 0x0400
#define VBE_MODE_ATTRIBUTE_HARDWARE_STEREOSCOPIC_DISPLAY 0x0800
#define VBE_MODE_ATTRIBUTE_DUAL_DISPLAY_START_ADDRESS 0x1000
#define VBE_MODE_ATTTRIBUTE_LFB_ONLY ( VBE_MODE_ATTRIBUTE_NO_VGA_COMPATIBLE_WINDOW | VBE_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER_MODE )
// Window attributes
#define VBE_WINDOW_ATTRIBUTE_RELOCATABLE 0x01
#define VBE_WINDOW_ATTRIBUTE_READABLE 0x02
#define VBE_WINDOW_ATTRIBUTE_WRITEABLE 0x04
// Memory model
#define VBE_MEMORYMODEL_TEXT_MODE 0x00
#define VBE_MEMORYMODEL_CGA_GRAPHICS 0x01
#define VBE_MEMORYMODEL_HERCULES_GRAPHICS 0x02
#define VBE_MEMORYMODEL_PLANAR 0x03
#define VBE_MEMORYMODEL_PACKED_PIXEL 0x04
#define VBE_MEMORYMODEL_NON_CHAIN_4_256 0x05
#define VBE_MEMORYMODEL_DIRECT_COLOR 0x06
#define VBE_MEMORYMODEL_YUV 0x07
// DirectColorModeInfo
#define VBE_DIRECTCOLOR_COLOR_RAMP_PROGRAMMABLE 0x01
#define VBE_DIRECTCOLOR_RESERVED_BITS_AVAILABLE 0x02
// GUEST <-> HOST Communication API
// FIXME: either dynamicly ask host for this or put somewhere high in physical memory
// like 0xE0000000
#define VBE_DISPI_TOTAL_VIDEO_MEMORY_MB 4
#define VBE_DISPI_BANK_ADDRESS 0xA0000
#define VBE_DISPI_BANK_SIZE_KB 64
#define VBE_DISPI_MAX_XRES 1024
#define VBE_DISPI_MAX_YRES 768
#define VBE_DISPI_IOPORT_INDEX 0x01CE
#define VBE_DISPI_IOPORT_DATA 0x01CF
#define VBE_DISPI_INDEX_ID 0x0
#define VBE_DISPI_INDEX_XRES 0x1
#define VBE_DISPI_INDEX_YRES 0x2
#define VBE_DISPI_INDEX_BPP 0x3
#define VBE_DISPI_INDEX_ENABLE 0x4
#define VBE_DISPI_INDEX_BANK 0x5
#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6
#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
#define VBE_DISPI_INDEX_X_OFFSET 0x8
#define VBE_DISPI_INDEX_Y_OFFSET 0x9
#define VBE_DISPI_ID0 0xB0C0
#define VBE_DISPI_ID1 0xB0C1
#define VBE_DISPI_ID2 0xB0C2
#define VBE_DISPI_ID3 0xB0C3
#define VBE_DISPI_DISABLED 0x00
#define VBE_DISPI_ENABLED 0x01
#define VBE_DISPI_GETCAPS 0x02
#define VBE_DISPI_8BIT_DAC 0x20
#define VBE_DISPI_LFB_ENABLED 0x40
#define VBE_DISPI_NOCLEARMEM 0x80
#define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000
#define VBE_TOTAL_VIDEO_MEMORY_DIV_64K (VBE_DISPI_TOTAL_VIDEO_MEMORY_MB*1024/64)
#endif
+227
View File
@@ -0,0 +1,227 @@
VBE Display API
-------------------------------------------------------------------------------------------------------------
This document is part of the Bochs/VBEBios documentation,
it specifies the bochs host <-> vbebios client communication.
That means, the display code implementation and the vbebios code depend
very heavily on each other. As such, this documents needs be synchronised
between bochs CVS and the vgabios CVS.
This document does not describe how the VBEBios implements the VBE2/3 spec.
This document does not describe how the Bochs display code will display gfx based upon this spec.
API History
-----------
0xb0c0 supports the following VBE_DISPI_ interfaces (present in Bochs 1.4):
VBE_DISPI_INDEX_ID
VBE_DISPI_INDEX_XRES
VBE_DISPI_INDEX_YRES
VBE_DISPI_INDEX_BPP
VBE_DISPI_INDEX_ENABLE
VBE_DISPI_INDEX_BANK
Bpp format supported is:
VBE_DISPI_BPP_8
0xb0c1 supports 0xb0c0 VBE_DISPI_ interfaces, additional interfaces (present in Bochs 2.0):
VBE_DISPI_INDEX_VIRT_WIDTH
VBE_DISPI_INDEX_VIRT_HEIGHT
VBE_DISPI_INDEX_X_OFFSET
VBE_DISPI_INDEX_Y_OFFSET
0xb0c2 supports 0xb0c1 VBE_DISPI_ interfaces, interfaces updated for
additional features (present in Bochs 2.1):
VBE_DISPI_INDEX_BPP supports >8bpp color depth (value = bits)
VBE_DISPI_INDEX_ENABLE supports new flags VBE_DISPI_NOCLEARMEM and VBE_DISPI_LFB_ENABLED
VBE i/o registers changed from 0xFF80/81 to 0x01CE/CF
0xb0c3 supports 0xb0c2 VBE_DISPI_ interfaces, interfaces updated for
additional features:
VBE_DISPI_INDEX_ENABLE supports new flags VBE_DISPI_GETCAPS and VBE_DISPI_8BIT_DAC
History
-------
Version 0.6 2002 Nov 23 Jeroen Janssen
- Added LFB support
- Added Virt width, height and x,y offset
Version 0.5 2002 March 08 Jeroen Janssen
- Added documentation about panic behaviour / current limits of the data values.
- Changed BPP API (in order to include future (A)RGB formats)
- Initial version (based upon extended display text of the vbe bochs display patch)
Todo
----
Version 0.6+ [random order]
- Add lots of different (A)RGB formats
References
----------
[VBE3] VBE 3 Specification at
http://www.vesa.org/vbe3.pdf
[BOCHS] Bochs Open Source IA-32 Emulator at
http://bochs.sourceforge.net
[VBEBIOS] VBE Bios for Bochs at
http://savannah.gnu.org/projects/vgabios/
[Screenshots] Screenshots of programs using the VBE Bios at
http://japj.org/projects/bochs_plex86/screenshots.html
Abbreviations
-------------
VBE Vesa Bios Extension
DISPI (Bochs) Display Interface
BPP Bits Per Pixel
LFB Linear Frame Buffer
#defines
--------
#define VBE_DISPI_TOTAL_VIDEO_MEMORY_MB 4
#define VBE_DISPI_BANK_ADDRESS 0xA0000
#define VBE_DISPI_BANK_SIZE_KB 64
#define VBE_DISPI_MAX_XRES 1024
#define VBE_DISPI_MAX_YRES 768
#define VBE_DISPI_IOPORT_INDEX 0x01CE
#define VBE_DISPI_IOPORT_DATA 0x01CF
#define VBE_DISPI_INDEX_ID 0x0
#define VBE_DISPI_INDEX_XRES 0x1
#define VBE_DISPI_INDEX_YRES 0x2
#define VBE_DISPI_INDEX_BPP 0x3
#define VBE_DISPI_INDEX_ENABLE 0x4
#define VBE_DISPI_INDEX_BANK 0x5
#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6
#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
#define VBE_DISPI_INDEX_X_OFFSET 0x8
#define VBE_DISPI_INDEX_Y_OFFSET 0x9
#define VBE_DISPI_ID0 0xB0C0
#define VBE_DISPI_ID1 0xB0C1
#define VBE_DISPI_ID2 0xB0C2
#define VBE_DISPI_DISABLED 0x00
#define VBE_DISPI_ENABLED 0x01
#define VBE_DISPI_VBE_ENABLED 0x40
#define VBE_DISPI_NOCLEARMEM 0x80
#define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000
API
---
The display api works by using a index (VBE_DISPI_IOPORT_INDEX) and
data (VBE_DISPI_IOPORT_DATA) ioport. One writes the index of the parameter to the index port.
Next, the parameter value can be read or written.
[0xb0c0]
* VBE_DISPI_INDEX_ID : WORD {R,W}
This parameter can be used to detect the current display API (both bochs & vbebios).
The bios writes VBE_DISPI_ID0 to the dataport and reads it back again.
This way, the display code knows the vbebios 'ID' and the vbebios can check if the correct
display code is present.
As a result, a PANIC can be generated if an incompatible vbebios/display code combination is detected.
This panic can be generated from the bochs display code (NOT the bios, see Notes).
Example values: VBE_DISPI_ID0
* VBE_DISPI_INDEX_XRES : WORD {R,W}
This parameter can be used to read/write the vbe display X resolution (in pixels).
It's illegal to set the XRES when the VBE is enabled (display code should generate PANIC).
If the value written exceeds VBE_DISPI_MAX_XRES, the display code needs to generate a PANIC.
Example values: 320,640,800,1024
* VBE_DISPI_INDEX_YRES : WORD {R,W}
This parameter can be used to read/write the vbe display Y resolution (in pixels).
It's illegal to set the YRES when the VBE is enabled (display code should generate PANIC).
If the value written exceeds VBE_DISPI_MAX_YRES, the display code needs to generate a PANIC.
Example values: 200,400,480,600,768
* VBE_DISPI_INDEX_BPP : WORD {R,W}
This parameter can be used to read/write the vbe display BPP.
It's illegal to set the BPP when the VBE is enabled (display code should generate PANIC).
If the value written is an incompatible BPP, the display code needs to generate a PANIC.
Example values: VBE_DISPI_BPP_8
* VBE_DISPI_INDEX_ENABLE : WORD {R,W}
This parameter can be used to read/write the vbe ENABLED state.
If the bios writes VBE_DISPI_ENABLED then the display code will setup a hostside display mode
with the current XRES, YRES and BPP settings.
If the bios write VBE_DISPI_DISABLED then the display code will switch back to normal vga mode behaviour.
Example values: VBE_DISPI_ENABLED, VBE_DISPI_DISABLED
* VBE_DISPI_INDEX_BANK : WORD {R,W}
This parameter can be used to read/write the current selected BANK (at 0xA0000).
This can be used for switching banks in banked mode.
[0xb0c1]
* VBE_DISPI_INDEX_VIRT_WIDTH : WORD {R,W}
This parameter can be used to read/write the current virtual width.
Upon enabling a mode, this will be set to the current xres
Setting this field during enabled mode will result in the virtual width to be changed.
Value will be adjusted if current setting is not possible.
* VBE_DISPI_INDEX_VIRT_HEIGHT : WORD {R}
This parameter can be read in order to obtain the current virtual height.
This setting will be adjusted after setting a virtual width in order to stay within limit of video memory.
* VBE_DISPI_INDEX_X_OFFSET : WORD {R,W}
The current X offset (in pixels!) of the visible screen part.
Writing a new offset will also result in a complete screen refresh.
* VBE_DISPI_INDEX_Y_OFFSET : WORD {R,W}
The current Y offset (in pixels!) of the visible screen part.
Writing a new offset will also result in a complete screen refresh.
[0xb0c2]
* VBE_DISPI_INDEX_BPP : WORD {R,W}
The value written is now the number of bits per pixel. A value of 0 is treated
the same as 8 for backward compatibilty. These values are supported: 8, 15,
16, 24 and 32. The value of 4 is not yet handled in the VBE code.
* VBE_DISPI_INDEX_ENABLE : WORD {R,W}
The new flag VBE_DISPI_NOCLEARMEM allows to preserve the VBE video memory.
The new flag VBE_DISPI_LFB_ENABLED indicates the usage of the LFB.
[0xb0c3]
* VBE_DISPI_INDEX_ENABLE : WORD {R,W}
If the new flag VBE_DISPI_GETCAPS is enabled, the xres, yres and bpp registers
return the gui capabilities.
The new flag VBE_DISPI_8BIT_DAC switches the DAC to 8 bit mode.
Displaying GFX (banked mode)
--------------
What happens is that the total screen is devided in banks of 'VBE_DISPI_BANK_SIZE_KB' KiloByte in size.
If you want to set a pixel you can calculate its bank by doing:
offset = pixel_x + pixel_y * resolution_x;
bank = offset / 64 Kb (rounded 1.9999 -> 1)
bank_pixel_pos = offset - bank * 64Kb
Now you can set the current bank and put the pixel at VBE_DISPI_BANK_ADDRESS + bank_pixel_pos
Displaying GFX (linear frame buffer mode)
--------------
NOT WRITTEN YET
Notes
-----
* Since the XRES/YRES/BPP may not be written when VBE is enabled, if you want to switch from one VBE mode
to another, you will need to disable VBE first.
* Note when the bios doesn't find a valid DISPI_ID, it can disable the VBE functions. This allows people to
use the same bios for both vbe enabled and disabled bochs executables.
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+47
View File
@@ -0,0 +1,47 @@
#ifndef vgabios_h_included
#define vgabios_h_included
/* Types */
typedef unsigned char Bit8u;
typedef unsigned short Bit16u;
typedef unsigned long Bit32u;
typedef unsigned short Boolean;
/* Defines */
#define SET_AL(val8) AX = ((AX & 0xff00) | (val8))
#define SET_BL(val8) BX = ((BX & 0xff00) | (val8))
#define SET_CL(val8) CX = ((CX & 0xff00) | (val8))
#define SET_DL(val8) DX = ((DX & 0xff00) | (val8))
#define SET_AH(val8) AX = ((AX & 0x00ff) | ((val8) << 8))
#define SET_BH(val8) BX = ((BX & 0x00ff) | ((val8) << 8))
#define SET_CH(val8) CX = ((CX & 0x00ff) | ((val8) << 8))
#define SET_DH(val8) DX = ((DX & 0x00ff) | ((val8) << 8))
#define GET_AL() ( AX & 0x00ff )
#define GET_BL() ( BX & 0x00ff )
#define GET_CL() ( CX & 0x00ff )
#define GET_DL() ( DX & 0x00ff )
#define GET_AH() ( AX >> 8 )
#define GET_BH() ( BX >> 8 )
#define GET_CH() ( CX >> 8 )
#define GET_DH() ( DX >> 8 )
#define SET_CF() FLAGS |= 0x0001
#define CLEAR_CF() FLAGS &= 0xfffe
#define GET_CF() (FLAGS & 0x0001)
#define SET_ZF() FLAGS |= 0x0040
#define CLEAR_ZF() FLAGS &= 0xffbf
#define GET_ZF() (FLAGS & 0x0040)
#define SCROLL_DOWN 0
#define SCROLL_UP 1
#define NO_ATTR 2
#define WITH_ATTR 3
#define SCREEN_SIZE(x,y) (((x*y*2)|0x00ff)+1)
#define SCREEN_MEM_START(x,y,p) ((((x*y*2)|0x00ff)+1)*p)
#define SCREEN_IO_START(x,y,p) ((((x*y)|0x00ff)+1)*p)
#endif
+784
View File
@@ -0,0 +1,784 @@
/*
* These fonts come from ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip
* The package is (c) by Joseph Gil
* The individual fonts are public domain
*/
static Bit8u vgafont8[256*8]=
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e,
0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e,
0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00,
0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00,
0x38, 0x7c, 0x38, 0xfe, 0xfe, 0x7c, 0x38, 0x7c,
0x10, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x7c,
0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00,
0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff,
0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00,
0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff,
0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78,
0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18,
0x3f, 0x33, 0x3f, 0x30, 0x30, 0x70, 0xf0, 0xe0,
0x7f, 0x63, 0x7f, 0x63, 0x63, 0x67, 0xe6, 0xc0,
0x99, 0x5a, 0x3c, 0xe7, 0xe7, 0x3c, 0x5a, 0x99,
0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00,
0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00,
0x18, 0x3c, 0x7e, 0x18, 0x18, 0x7e, 0x3c, 0x18,
0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00,
0x7f, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x00,
0x3e, 0x63, 0x38, 0x6c, 0x6c, 0x38, 0xcc, 0x78,
0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00,
0x18, 0x3c, 0x7e, 0x18, 0x7e, 0x3c, 0x18, 0xff,
0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00,
0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00,
0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00,
0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00,
0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00,
0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00,
0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00,
0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x30, 0x78, 0x78, 0x30, 0x30, 0x00, 0x30, 0x00,
0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00,
0x30, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x30, 0x00,
0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00,
0x38, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0x76, 0x00,
0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00,
0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00,
0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00,
0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60,
0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00,
0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00,
0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0x7c, 0x00,
0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00,
0x78, 0xcc, 0x0c, 0x38, 0x60, 0xcc, 0xfc, 0x00,
0x78, 0xcc, 0x0c, 0x38, 0x0c, 0xcc, 0x78, 0x00,
0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00,
0xfc, 0xc0, 0xf8, 0x0c, 0x0c, 0xcc, 0x78, 0x00,
0x38, 0x60, 0xc0, 0xf8, 0xcc, 0xcc, 0x78, 0x00,
0xfc, 0xcc, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00,
0x78, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0x78, 0x00,
0x78, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0x70, 0x00,
0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00,
0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60,
0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00,
0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00,
0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00,
0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00,
0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x78, 0x00,
0x30, 0x78, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0x00,
0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00,
0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00,
0xf8, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00,
0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00,
0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00,
0x3c, 0x66, 0xc0, 0xc0, 0xce, 0x66, 0x3e, 0x00,
0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0xcc, 0x00,
0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00,
0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00,
0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00,
0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00,
0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00,
0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00,
0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00,
0x78, 0xcc, 0xcc, 0xcc, 0xdc, 0x78, 0x1c, 0x00,
0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00,
0x78, 0xcc, 0xe0, 0x70, 0x1c, 0xcc, 0x78, 0x00,
0xfc, 0xb4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0x00,
0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00,
0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00,
0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00,
0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x78, 0x00,
0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00,
0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00,
0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00,
0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00,
0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00,
0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xdc, 0x00,
0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x00,
0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00,
0x00, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00,
0x38, 0x6c, 0x60, 0xf0, 0x60, 0x60, 0xf0, 0x00,
0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00,
0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
0x0c, 0x00, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78,
0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00,
0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
0x00, 0x00, 0xcc, 0xfe, 0xfe, 0xd6, 0xc6, 0x00,
0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x00,
0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00,
0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0,
0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e,
0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0xf0, 0x00,
0x00, 0x00, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x00,
0x10, 0x30, 0x7c, 0x30, 0x30, 0x34, 0x18, 0x00,
0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00,
0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00,
0x00, 0x00, 0xc6, 0xd6, 0xfe, 0xfe, 0x6c, 0x00,
0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00,
0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00,
0x1c, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x1c, 0x00,
0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00,
0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00,
0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00,
0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x18, 0x0c, 0x78,
0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00,
0x1c, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00,
0x7e, 0xc3, 0x3c, 0x06, 0x3e, 0x66, 0x3f, 0x00,
0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00,
0xe0, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00,
0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00,
0x00, 0x00, 0x78, 0xc0, 0xc0, 0x78, 0x0c, 0x38,
0x7e, 0xc3, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00,
0xcc, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00,
0xe0, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00,
0xcc, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
0x7c, 0xc6, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00,
0xe0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
0xc6, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00,
0x30, 0x30, 0x00, 0x78, 0xcc, 0xfc, 0xcc, 0x00,
0x1c, 0x00, 0xfc, 0x60, 0x78, 0x60, 0xfc, 0x00,
0x00, 0x00, 0x7f, 0x0c, 0x7f, 0xcc, 0x7f, 0x00,
0x3e, 0x6c, 0xcc, 0xfe, 0xcc, 0xcc, 0xce, 0x00,
0x78, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00,
0x00, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00,
0x00, 0xe0, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00,
0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00,
0x00, 0xe0, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00,
0x00, 0xcc, 0x00, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
0xc3, 0x18, 0x3c, 0x66, 0x66, 0x3c, 0x18, 0x00,
0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00,
0x18, 0x18, 0x7e, 0xc0, 0xc0, 0x7e, 0x18, 0x18,
0x38, 0x6c, 0x64, 0xf0, 0x60, 0xe6, 0xfc, 0x00,
0xcc, 0xcc, 0x78, 0xfc, 0x30, 0xfc, 0x30, 0x30,
0xf8, 0xcc, 0xcc, 0xfa, 0xc6, 0xcf, 0xc6, 0xc7,
0x0e, 0x1b, 0x18, 0x3c, 0x18, 0x18, 0xd8, 0x70,
0x1c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00,
0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
0x00, 0x1c, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00,
0x00, 0x1c, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00,
0x00, 0xf8, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0x00,
0xfc, 0x00, 0xcc, 0xec, 0xfc, 0xdc, 0xcc, 0x00,
0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00,
0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00,
0x30, 0x00, 0x30, 0x60, 0xc0, 0xcc, 0x78, 0x00,
0x00, 0x00, 0x00, 0xfc, 0xc0, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00,
0xc3, 0xc6, 0xcc, 0xde, 0x33, 0x66, 0xcc, 0x0f,
0xc3, 0xc6, 0xcc, 0xdb, 0x37, 0x6f, 0xcf, 0x03,
0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00,
0x00, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x00, 0x00,
0x00, 0xcc, 0x66, 0x33, 0x66, 0xcc, 0x00, 0x00,
0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88,
0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
0xdb, 0x77, 0xdb, 0xee, 0xdb, 0x77, 0xdb, 0xee,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18,
0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18,
0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36,
0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18,
0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36,
0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00,
0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18,
0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18,
0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36,
0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36,
0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36,
0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36,
0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36,
0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00,
0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36,
0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x76, 0xdc, 0xc8, 0xdc, 0x76, 0x00,
0x00, 0x78, 0xcc, 0xf8, 0xcc, 0xf8, 0xc0, 0xc0,
0x00, 0xfc, 0xcc, 0xc0, 0xc0, 0xc0, 0xc0, 0x00,
0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00,
0xfc, 0xcc, 0x60, 0x30, 0x60, 0xcc, 0xfc, 0x00,
0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0x70, 0x00,
0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xc0,
0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x00,
0xfc, 0x30, 0x78, 0xcc, 0xcc, 0x78, 0x30, 0xfc,
0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0x6c, 0x38, 0x00,
0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x6c, 0xee, 0x00,
0x1c, 0x30, 0x18, 0x7c, 0xcc, 0xcc, 0x78, 0x00,
0x00, 0x00, 0x7e, 0xdb, 0xdb, 0x7e, 0x00, 0x00,
0x06, 0x0c, 0x7e, 0xdb, 0xdb, 0x7e, 0x60, 0xc0,
0x38, 0x60, 0xc0, 0xf8, 0xc0, 0x60, 0x38, 0x00,
0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00,
0x00, 0xfc, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00,
0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0xfc, 0x00,
0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xfc, 0x00,
0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xfc, 0x00,
0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70,
0x30, 0x30, 0x00, 0xfc, 0x00, 0x30, 0x30, 0x00,
0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00,
0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x0f, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x1c,
0x78, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00,
0x70, 0x18, 0x30, 0x60, 0x78, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static Bit8u vgafont14[256*14]=
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x06, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00,
0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x28, 0x6c, 0xfe, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00,
0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00,
0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x66, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00,
0x00, 0x00, 0xe6, 0x66, 0x6c, 0x6c, 0x78, 0x6c, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00,
0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00,
0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xfe, 0x7c, 0x6c, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xc6, 0x8c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00,
0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00,
0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00,
0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x70, 0x1c, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x66, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00,
0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00,
0x00, 0x00, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x00, 0xcc, 0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0xcc, 0xcc, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0xc6, 0xc6, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00,
0x00, 0xc6, 0xc6, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00,
0x00, 0xc6, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x18, 0x18, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00,
0x00, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0xf8, 0xcc, 0xcc, 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0xcc, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00,
0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00,
0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0xc0, 0xc0, 0xc6, 0xcc, 0xd8, 0x30, 0x60, 0xdc, 0x86, 0x0c, 0x18, 0x3e, 0x00,
0x00, 0xc0, 0xc0, 0xc6, 0xcc, 0xd8, 0x30, 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00,
0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00,
0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfc, 0xc6, 0xc6, 0xfc, 0xc0, 0xc0, 0x40, 0x00,
0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00,
0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static Bit8u vgafont16[256*16]=
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xdb, 0xdb, 0xc3, 0xc3, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00,
0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00,
0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00,
0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00,
0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, 0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00,
0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc6, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00,
0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x18, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0xfc, 0x66, 0x66, 0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, 0x00,
0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, 0x0c, 0x1f, 0x00, 0x00,
0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00,
0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00,
0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static Bit8u vgafont14alt[1]={0x00};
static Bit8u vgafont16alt[1]={0x00};
+318
View File
@@ -0,0 +1,318 @@
/*
*
* BIOS Memory
*
*/
#define BIOSMEM_SEG 0x40
#define BIOSMEM_INITIAL_MODE 0x10
#define BIOSMEM_CURRENT_MODE 0x49
#define BIOSMEM_NB_COLS 0x4A
#define BIOSMEM_PAGE_SIZE 0x4C
#define BIOSMEM_CURRENT_START 0x4E
#define BIOSMEM_CURSOR_POS 0x50
#define BIOSMEM_CURSOR_TYPE 0x60
#define BIOSMEM_CURRENT_PAGE 0x62
#define BIOSMEM_CRTC_ADDRESS 0x63
#define BIOSMEM_CURRENT_MSR 0x65
#define BIOSMEM_CURRENT_PAL 0x66
#define BIOSMEM_NB_ROWS 0x84
#define BIOSMEM_CHAR_HEIGHT 0x85
#define BIOSMEM_VIDEO_CTL 0x87
#define BIOSMEM_SWITCHES 0x88
#define BIOSMEM_MODESET_CTL 0x89
#define BIOSMEM_DCC_INDEX 0x8A
#define BIOSMEM_VS_POINTER 0xA8
#define BIOSMEM_VBE_FLAG 0xB9
#define BIOSMEM_VBE_MODE 0xBA
/*
*
* VGA registers
*
*/
#define VGAREG_ACTL_ADDRESS 0x3c0
#define VGAREG_ACTL_WRITE_DATA 0x3c0
#define VGAREG_ACTL_READ_DATA 0x3c1
#define VGAREG_INPUT_STATUS 0x3c2
#define VGAREG_WRITE_MISC_OUTPUT 0x3c2
#define VGAREG_VIDEO_ENABLE 0x3c3
#define VGAREG_SEQU_ADDRESS 0x3c4
#define VGAREG_SEQU_DATA 0x3c5
#define VGAREG_PEL_MASK 0x3c6
#define VGAREG_DAC_STATE 0x3c7
#define VGAREG_DAC_READ_ADDRESS 0x3c7
#define VGAREG_DAC_WRITE_ADDRESS 0x3c8
#define VGAREG_DAC_DATA 0x3c9
#define VGAREG_READ_FEATURE_CTL 0x3ca
#define VGAREG_READ_MISC_OUTPUT 0x3cc
#define VGAREG_GRDC_ADDRESS 0x3ce
#define VGAREG_GRDC_DATA 0x3cf
#define VGAREG_MDA_CRTC_ADDRESS 0x3b4
#define VGAREG_MDA_CRTC_DATA 0x3b5
#define VGAREG_VGA_CRTC_ADDRESS 0x3d4
#define VGAREG_VGA_CRTC_DATA 0x3d5
#define VGAREG_MDA_WRITE_FEATURE_CTL 0x3ba
#define VGAREG_VGA_WRITE_FEATURE_CTL 0x3da
#define VGAREG_ACTL_RESET 0x3da
#define VGAREG_MDA_MODECTL 0x3b8
#define VGAREG_CGA_MODECTL 0x3d8
#define VGAREG_CGA_PALETTE 0x3d9
/* Video memory */
#define VGAMEM_GRAPH 0xA000
#define VGAMEM_CTEXT 0xB800
#define VGAMEM_MTEXT 0xB000
/*
*
* Tables of default values for each mode
*
*/
#define MODE_MAX 0x14
#define TEXT 0x00
#define GRAPH 0x01
#define CTEXT 0x00
#define MTEXT 0x01
#define CGA 0x02
#define PLANAR1 0x03
#define PLANAR4 0x04
#define LINEAR8 0x05
// for SVGA
#define LINEAR15 0x10
#define LINEAR16 0x11
#define LINEAR24 0x12
#define LINEAR32 0x13
typedef struct
{Bit8u svgamode;
Bit16u vesamode;
Bit8u class; /* TEXT, GRAPH */
Bit8u memmodel; /* CTEXT,MTEXT,CGA,PL1,PL2,PL4,P8,P15,P16,P24,P32 */
Bit8u nbpages;
Bit8u pixbits;
Bit16u swidth, sheight;
Bit16u twidth, theight;
Bit16u cwidth, cheight;
Bit16u sstart;
Bit16u slength;
Bit8u miscreg;
Bit8u pelmask;
Bit8u crtcmodel;
Bit8u actlmodel;
Bit8u grdcmodel;
Bit8u sequmodel;
Bit8u dacmodel; /* 0 1 2 3 */
} VGAMODES;
static VGAMODES vga_modes[MODE_MAX+1]=
{//mode vesa class model pg bits sw sh tw th cw ch sstart slength misc pelm crtc actl gdc sequ dac
{0x00, 0xFFFF, TEXT, CTEXT, 8, 4, 360, 400, 40, 25, 9, 16, 0xB800, 0x0800, 0x67, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x02},
{0x01, 0xFFFF, TEXT, CTEXT, 8, 4, 360, 400, 40, 25, 9, 16, 0xB800, 0x0800, 0x67, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x02},
{0x02, 0xFFFF, TEXT, CTEXT, 4, 4, 720, 400, 80, 25, 9, 16, 0xB800, 0x1000, 0x67, 0xFF, 0x01, 0x00, 0x00, 0x01, 0x02},
{0x03, 0xFFFF, TEXT, CTEXT, 4, 4, 720, 400, 80, 25, 9, 16, 0xB800, 0x1000, 0x67, 0xFF, 0x01, 0x00, 0x00, 0x01, 0x02},
{0x04, 0xFFFF, GRAPH, CGA, 4, 2, 320, 200, 40, 25, 8, 8, 0xB800, 0x0800, 0x63, 0xFF, 0x02, 0x01, 0x01, 0x02, 0x01},
{0x05, 0xFFFF, GRAPH, CGA, 1, 2, 320, 200, 40, 25, 8, 8, 0xB800, 0x0800, 0x63, 0xFF, 0x02, 0x01, 0x01, 0x02, 0x01},
{0x06, 0xFFFF, GRAPH, CGA, 1, 1, 640, 200, 80, 25, 8, 8, 0xB800, 0x1000, 0x63, 0xFF, 0x03, 0x02, 0x02, 0x03, 0x01},
{0x07, 0xFFFF, TEXT, MTEXT, 4, 4, 720, 400, 80, 25, 9, 16, 0xB000, 0x1000, 0x66, 0xFF, 0x04, 0x03, 0x03, 0x01, 0x00},
{0x0D, 0xFFFF, GRAPH, PLANAR4, 8, 4, 320, 200, 40, 25, 8, 8, 0xA000, 0x2000, 0x63, 0xFF, 0x05, 0x04, 0x04, 0x04, 0x01},
{0x0E, 0xFFFF, GRAPH, PLANAR4, 4, 4, 640, 200, 80, 25, 8, 8, 0xA000, 0x4000, 0x63, 0xFF, 0x06, 0x04, 0x04, 0x05, 0x01},
{0x0F, 0xFFFF, GRAPH, PLANAR1, 2, 1, 640, 350, 80, 25, 8, 14, 0xA000, 0x8000, 0xa3, 0xFF, 0x07, 0x05, 0x04, 0x05, 0x00},
{0x10, 0xFFFF, GRAPH, PLANAR4, 2, 4, 640, 350, 80, 25, 8, 14, 0xA000, 0x8000, 0xa3, 0xFF, 0x07, 0x06, 0x04, 0x05, 0x02},
{0x11, 0xFFFF, GRAPH, PLANAR1, 1, 1, 640, 480, 80, 30, 8, 16, 0xA000, 0x0000, 0xe3, 0xFF, 0x08, 0x07, 0x04, 0x05, 0x02},
{0x12, 0xFFFF, GRAPH, PLANAR4, 1, 4, 640, 480, 80, 30, 8, 16, 0xA000, 0x0000, 0xe3, 0xFF, 0x08, 0x06, 0x04, 0x05, 0x02},
{0x13, 0xFFFF, GRAPH, LINEAR8, 1, 8, 320, 200, 40, 25, 8, 8, 0xA000, 0x0000, 0x63, 0xFF, 0x09, 0x08, 0x05, 0x06, 0x03},
{0x6A, 0xFFFF, GRAPH, PLANAR4, 1, 4, 800, 600,100, 37, 8, 16, 0xA000, 0x0000, 0xe3, 0xFF, 0x0A, 0x06, 0x04, 0x05, 0x02}
};
/* CRTC */
#define CRTC_MAX_REG 0x18
#define CRTC_MAX_MODEL 0x0A
static Bit8u crtc_access[CRTC_MAX_REG+1]=
{ /* 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
static Bit8u crtc_regs[CRTC_MAX_MODEL+1][CRTC_MAX_REG+1]=
{/* Model 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 */
/* 00 */ 0x2d,0x27,0x28,0x90,0x2b,0xa0,0xbf,0x1f,0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x14,0x1f,0x96,0xb9,0xa3,0xff,
/* 01 */ 0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x28,0x1f,0x96,0xb9,0xa3,0xff,
/* 02 */ 0x2d,0x27,0x28,0x90,0x2b,0x80,0xbf,0x1f,0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xa2,0xff,
/* 03 */ 0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f,0x00,0xc1,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xc2,0xff,
/* 04 */ 0x5f,0x4f,0x50,0x82,0x55,0x81,0xbf,0x1f,0x00,0x4f,0x0d,0x0e,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x28,0x0f,0x96,0xb9,0xa3,0xff,
/* 05 */ 0x2d,0x27,0x28,0x90,0x2b,0x80,0xbf,0x1f,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x14,0x00,0x96,0xb9,0xe3,0xff,
/* 06 */ 0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f,0x00,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x28,0x00,0x96,0xb9,0xe3,0xff,
/* 07 */ 0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x83,0x85,0x5d,0x28,0x0f,0x63,0xba,0xe3,0xff,
/* 08 */ 0x5f,0x4f,0x50,0x82,0x54,0x80,0x0b,0x3e,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0xea,0x8c,0xdf,0x28,0x00,0xe7,0x04,0xe3,0xff,
/* 09 */ 0x5f,0x4f,0x50,0x82,0x54,0x80,0xbf,0x1f,0x00,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x9c,0x8e,0x8f,0x28,0x40,0x96,0xb9,0xa3,0xff,
/* 0A */ 0x7f,0x63,0x63,0x83,0x6b,0x1b,0x72,0xf0,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x59,0x8d,0x57,0x32,0x00,0x57,0x73,0xe3,0xff
};
/* Attribute Controler 0x3c0 */
#define ACTL_MAX_REG 0x14
#define ACTL_MAX_MODEL 0x08
static Bit8u actl_access[ACTL_MAX_REG+1]=
{/* 00 01 02 03 04 05 06 07 08 09 0A 0B OC OD OE OF 10 11 12 13 14 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
static Bit8u actl_regs[ACTL_MAX_MODEL+1][ACTL_MAX_REG+1]=
{/* Model 00 01 02 03 04 05 06 07 08 09 0A 0B OC OD OE OF 10 11 12 13 14 */
/* 00 */ 0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x0c,0x00,0x0f,0x08,0x00,
/* 01 */ 0x00,0x13,0x15,0x17,0x02,0x04,0x06,0x07,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x01,0x00,0x03,0x00,0x00,
/* 02 */ 0x00,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x17,0x01,0x00,0x01,0x00,0x00,
/* 03 */ 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x0e,0x00,0x0f,0x08,0x00,
/* 04 */ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x01,0x00,0x0f,0x00,0x00,
/* 05 */ 0x00,0x08,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x18,0x00,0x00,0x01,0x00,0x01,0x00,0x00,
/* 06 */ 0x00,0x01,0x02,0x03,0x04,0x05,0x14,0x07,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f,0x01,0x00,0x0f,0x00,0x00,
/* 07 */ 0x00,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x01,0x00,0x01,0x00,0x00,
/* 08 */ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x41,0x00,0x0f,0x00,0x00
};
/* Sequencer 0x3c4 */
#define SEQU_MAX_REG 0x04
#define SEQU_MAX_MODEL 0x06
static Bit8u sequ_access[SEQU_MAX_REG+1]=
{ /* 00 01 02 03 04 */
0x00,0x00,0x00,0x00,0x00
};
static Bit8u sequ_regs[SEQU_MAX_MODEL+1][SEQU_MAX_REG+1]=
{/* Model 00 01 02 03 04 */
/* 00 */ 0x03,0x08,0x03,0x00,0x02,
/* 01 */ 0x03,0x00,0x03,0x00,0x02,
/* 02 */ 0x03,0x09,0x03,0x00,0x02,
/* 03 */ 0x03,0x01,0x01,0x00,0x06,
/* 04 */ 0x03,0x09,0x0f,0x00,0x06,
/* 05 */ 0x03,0x01,0x0f,0x00,0x06,
/* 06 */ 0x03,0x01,0x0f,0x00,0x0e
};
/* Graphic ctl 0x3ce */
#define GRDC_MAX_REG 0x08
#define GRDC_MAX_MODEL 0x05
static Bit8u grdc_access[GRDC_MAX_REG+1]=
{ /* 00 01 02 03 04 05 06 07 08 */
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
static Bit8u grdc_regs[GRDC_MAX_MODEL+1][GRDC_MAX_REG+1]=
{/* Model 00 01 02 03 04 05 06 07 08 */
/* 00 */ 0x00,0x00,0x00,0x00,0x00,0x10,0x0e,0x0f,0xff,
/* 01 */ 0x00,0x00,0x00,0x00,0x00,0x30,0x0f,0x0f,0xff,
/* 02 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x0f,0xff,
/* 03 */ 0x00,0x00,0x00,0x00,0x00,0x10,0x0a,0x0f,0xff,
/* 04 */ 0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x0f,0xff,
/* 05 */ 0x00,0x00,0x00,0x00,0x00,0x40,0x05,0x0f,0xff
};
/* Default Palette */
#define DAC_MAX_MODEL 3
static Bit8u dac_regs[DAC_MAX_MODEL+1]=
{0x3f,0x3f,0x3f,0xff};
/* Mono */
static Bit8u palette0[63+1][3]=
{
0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00,
0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f,
0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00,
0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f
};
static Bit8u palette1[63+1][3]=
{
0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a,
0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a,
0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f,
0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f,
0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a,
0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a,
0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f,
0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f
};
static Bit8u palette2[63+1][3]=
{
0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x2a,0x00, 0x2a,0x2a,0x2a,
0x00,0x00,0x15, 0x00,0x00,0x3f, 0x00,0x2a,0x15, 0x00,0x2a,0x3f, 0x2a,0x00,0x15, 0x2a,0x00,0x3f, 0x2a,0x2a,0x15, 0x2a,0x2a,0x3f,
0x00,0x15,0x00, 0x00,0x15,0x2a, 0x00,0x3f,0x00, 0x00,0x3f,0x2a, 0x2a,0x15,0x00, 0x2a,0x15,0x2a, 0x2a,0x3f,0x00, 0x2a,0x3f,0x2a,
0x00,0x15,0x15, 0x00,0x15,0x3f, 0x00,0x3f,0x15, 0x00,0x3f,0x3f, 0x2a,0x15,0x15, 0x2a,0x15,0x3f, 0x2a,0x3f,0x15, 0x2a,0x3f,0x3f,
0x15,0x00,0x00, 0x15,0x00,0x2a, 0x15,0x2a,0x00, 0x15,0x2a,0x2a, 0x3f,0x00,0x00, 0x3f,0x00,0x2a, 0x3f,0x2a,0x00, 0x3f,0x2a,0x2a,
0x15,0x00,0x15, 0x15,0x00,0x3f, 0x15,0x2a,0x15, 0x15,0x2a,0x3f, 0x3f,0x00,0x15, 0x3f,0x00,0x3f, 0x3f,0x2a,0x15, 0x3f,0x2a,0x3f,
0x15,0x15,0x00, 0x15,0x15,0x2a, 0x15,0x3f,0x00, 0x15,0x3f,0x2a, 0x3f,0x15,0x00, 0x3f,0x15,0x2a, 0x3f,0x3f,0x00, 0x3f,0x3f,0x2a,
0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f
};
static Bit8u palette3[256][3]=
{
0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a, 0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a,
0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f, 0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f,
0x00,0x00,0x00, 0x05,0x05,0x05, 0x08,0x08,0x08, 0x0b,0x0b,0x0b, 0x0e,0x0e,0x0e, 0x11,0x11,0x11, 0x14,0x14,0x14, 0x18,0x18,0x18,
0x1c,0x1c,0x1c, 0x20,0x20,0x20, 0x24,0x24,0x24, 0x28,0x28,0x28, 0x2d,0x2d,0x2d, 0x32,0x32,0x32, 0x38,0x38,0x38, 0x3f,0x3f,0x3f,
0x00,0x00,0x3f, 0x10,0x00,0x3f, 0x1f,0x00,0x3f, 0x2f,0x00,0x3f, 0x3f,0x00,0x3f, 0x3f,0x00,0x2f, 0x3f,0x00,0x1f, 0x3f,0x00,0x10,
0x3f,0x00,0x00, 0x3f,0x10,0x00, 0x3f,0x1f,0x00, 0x3f,0x2f,0x00, 0x3f,0x3f,0x00, 0x2f,0x3f,0x00, 0x1f,0x3f,0x00, 0x10,0x3f,0x00,
0x00,0x3f,0x00, 0x00,0x3f,0x10, 0x00,0x3f,0x1f, 0x00,0x3f,0x2f, 0x00,0x3f,0x3f, 0x00,0x2f,0x3f, 0x00,0x1f,0x3f, 0x00,0x10,0x3f,
0x1f,0x1f,0x3f, 0x27,0x1f,0x3f, 0x2f,0x1f,0x3f, 0x37,0x1f,0x3f, 0x3f,0x1f,0x3f, 0x3f,0x1f,0x37, 0x3f,0x1f,0x2f, 0x3f,0x1f,0x27,
0x3f,0x1f,0x1f, 0x3f,0x27,0x1f, 0x3f,0x2f,0x1f, 0x3f,0x37,0x1f, 0x3f,0x3f,0x1f, 0x37,0x3f,0x1f, 0x2f,0x3f,0x1f, 0x27,0x3f,0x1f,
0x1f,0x3f,0x1f, 0x1f,0x3f,0x27, 0x1f,0x3f,0x2f, 0x1f,0x3f,0x37, 0x1f,0x3f,0x3f, 0x1f,0x37,0x3f, 0x1f,0x2f,0x3f, 0x1f,0x27,0x3f,
0x2d,0x2d,0x3f, 0x31,0x2d,0x3f, 0x36,0x2d,0x3f, 0x3a,0x2d,0x3f, 0x3f,0x2d,0x3f, 0x3f,0x2d,0x3a, 0x3f,0x2d,0x36, 0x3f,0x2d,0x31,
0x3f,0x2d,0x2d, 0x3f,0x31,0x2d, 0x3f,0x36,0x2d, 0x3f,0x3a,0x2d, 0x3f,0x3f,0x2d, 0x3a,0x3f,0x2d, 0x36,0x3f,0x2d, 0x31,0x3f,0x2d,
0x2d,0x3f,0x2d, 0x2d,0x3f,0x31, 0x2d,0x3f,0x36, 0x2d,0x3f,0x3a, 0x2d,0x3f,0x3f, 0x2d,0x3a,0x3f, 0x2d,0x36,0x3f, 0x2d,0x31,0x3f,
0x00,0x00,0x1c, 0x07,0x00,0x1c, 0x0e,0x00,0x1c, 0x15,0x00,0x1c, 0x1c,0x00,0x1c, 0x1c,0x00,0x15, 0x1c,0x00,0x0e, 0x1c,0x00,0x07,
0x1c,0x00,0x00, 0x1c,0x07,0x00, 0x1c,0x0e,0x00, 0x1c,0x15,0x00, 0x1c,0x1c,0x00, 0x15,0x1c,0x00, 0x0e,0x1c,0x00, 0x07,0x1c,0x00,
0x00,0x1c,0x00, 0x00,0x1c,0x07, 0x00,0x1c,0x0e, 0x00,0x1c,0x15, 0x00,0x1c,0x1c, 0x00,0x15,0x1c, 0x00,0x0e,0x1c, 0x00,0x07,0x1c,
0x0e,0x0e,0x1c, 0x11,0x0e,0x1c, 0x15,0x0e,0x1c, 0x18,0x0e,0x1c, 0x1c,0x0e,0x1c, 0x1c,0x0e,0x18, 0x1c,0x0e,0x15, 0x1c,0x0e,0x11,
0x1c,0x0e,0x0e, 0x1c,0x11,0x0e, 0x1c,0x15,0x0e, 0x1c,0x18,0x0e, 0x1c,0x1c,0x0e, 0x18,0x1c,0x0e, 0x15,0x1c,0x0e, 0x11,0x1c,0x0e,
0x0e,0x1c,0x0e, 0x0e,0x1c,0x11, 0x0e,0x1c,0x15, 0x0e,0x1c,0x18, 0x0e,0x1c,0x1c, 0x0e,0x18,0x1c, 0x0e,0x15,0x1c, 0x0e,0x11,0x1c,
0x14,0x14,0x1c, 0x16,0x14,0x1c, 0x18,0x14,0x1c, 0x1a,0x14,0x1c, 0x1c,0x14,0x1c, 0x1c,0x14,0x1a, 0x1c,0x14,0x18, 0x1c,0x14,0x16,
0x1c,0x14,0x14, 0x1c,0x16,0x14, 0x1c,0x18,0x14, 0x1c,0x1a,0x14, 0x1c,0x1c,0x14, 0x1a,0x1c,0x14, 0x18,0x1c,0x14, 0x16,0x1c,0x14,
0x14,0x1c,0x14, 0x14,0x1c,0x16, 0x14,0x1c,0x18, 0x14,0x1c,0x1a, 0x14,0x1c,0x1c, 0x14,0x1a,0x1c, 0x14,0x18,0x1c, 0x14,0x16,0x1c,
0x00,0x00,0x10, 0x04,0x00,0x10, 0x08,0x00,0x10, 0x0c,0x00,0x10, 0x10,0x00,0x10, 0x10,0x00,0x0c, 0x10,0x00,0x08, 0x10,0x00,0x04,
0x10,0x00,0x00, 0x10,0x04,0x00, 0x10,0x08,0x00, 0x10,0x0c,0x00, 0x10,0x10,0x00, 0x0c,0x10,0x00, 0x08,0x10,0x00, 0x04,0x10,0x00,
0x00,0x10,0x00, 0x00,0x10,0x04, 0x00,0x10,0x08, 0x00,0x10,0x0c, 0x00,0x10,0x10, 0x00,0x0c,0x10, 0x00,0x08,0x10, 0x00,0x04,0x10,
0x08,0x08,0x10, 0x0a,0x08,0x10, 0x0c,0x08,0x10, 0x0e,0x08,0x10, 0x10,0x08,0x10, 0x10,0x08,0x0e, 0x10,0x08,0x0c, 0x10,0x08,0x0a,
0x10,0x08,0x08, 0x10,0x0a,0x08, 0x10,0x0c,0x08, 0x10,0x0e,0x08, 0x10,0x10,0x08, 0x0e,0x10,0x08, 0x0c,0x10,0x08, 0x0a,0x10,0x08,
0x08,0x10,0x08, 0x08,0x10,0x0a, 0x08,0x10,0x0c, 0x08,0x10,0x0e, 0x08,0x10,0x10, 0x08,0x0e,0x10, 0x08,0x0c,0x10, 0x08,0x0a,0x10,
0x0b,0x0b,0x10, 0x0c,0x0b,0x10, 0x0d,0x0b,0x10, 0x0f,0x0b,0x10, 0x10,0x0b,0x10, 0x10,0x0b,0x0f, 0x10,0x0b,0x0d, 0x10,0x0b,0x0c,
0x10,0x0b,0x0b, 0x10,0x0c,0x0b, 0x10,0x0d,0x0b, 0x10,0x0f,0x0b, 0x10,0x10,0x0b, 0x0f,0x10,0x0b, 0x0d,0x10,0x0b, 0x0c,0x10,0x0b,
0x0b,0x10,0x0b, 0x0b,0x10,0x0c, 0x0b,0x10,0x0d, 0x0b,0x10,0x0f, 0x0b,0x10,0x10, 0x0b,0x0f,0x10, 0x0b,0x0d,0x10, 0x0b,0x0c,0x10,
0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00
};
static Bit8u static_functionality[0x10]=
{
/* 0 */ 0xff, // All modes supported #1
/* 1 */ 0xe0, // All modes supported #2
/* 2 */ 0x0f, // All modes supported #3
/* 3 */ 0x00, 0x00, 0x00, 0x00, // reserved
/* 7 */ 0x07, // 200, 350, 400 scan lines
/* 8 */ 0x02, // mamimum number of visible charsets in text mode
/* 9 */ 0x08, // total number of charset blocks in text mode
/* a */ 0xe7, // Change to add new functions
/* b */ 0x0c, // Change to add new functions
/* c */ 0x00, // reserved
/* d */ 0x00, // reserved
/* e */ 0x00, // Change to add new functions
/* f */ 0x00 // reserved
};
+84
View File
@@ -0,0 +1,84 @@
#
# Makefile
#
# Leendert van Doorn, leendert@watson.ibm.com
# Copyright (c) 2005, International Business Machines Corporation.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
# version 2, as published by the Free Software Foundation.
#
# This program is distributed in the hope it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307 USA.
#
# The emulator code lives in ROM space
TEXTADDR=0x000D0000
DEFINES=-DDEBUG -DTEXTADDR=${TEXTADDR}
XENINC=-I../../../xen/include
#TEXTADDR=0x000E0000
#DEFINES=-DDEBUG -DTEST -DTEXTADDR=${TEXTADDR}
#XENINC=-I/home/leendert/xen/xeno-unstable.bk/xen/include
LD=ld
CC=gcc
CPP=cpp -P
OBJCOPY=objcopy -p -O binary -R .note -R .comment -R .bss -S --gap-fill=0
CFLAGS=${DEFINES} -I. $(XENINC) -Wall -fno-builtin -O2 -msoft-float
OBJECTS = head.o trap.o vm86.o setup.o util.o
all: vmxloader
vmxloader: roms.h vmxloader.c
${CC} ${DEFINES} -c vmxloader.c
$(CC) -o vmxloader.tmp -nostdlib -Wl,-N -Wl,-Ttext -Wl,0x100000 vmxloader.o
objcopy --change-addresses=0xC0000000 vmxloader.tmp vmxloader
rm -f vmxloader.tmp
vmxassist.bin: vmxassist.ld ${OBJECTS}
${CPP} ${DEFINES} vmxassist.ld > vmxassist.tmp
${LD} -o vmxassist -nostdlib --fatal-warnings -N -T vmxassist.tmp ${OBJECTS}
nm -n vmxassist > vmxassist.sym
${OBJCOPY} vmxassist vmxassist.tmp
dd if=vmxassist.tmp of=vmxassist.bin ibs=512 conv=sync
rm -f vmxassist.tmp
head.o: machine.h head.S
${CC} ${CFLAGS} -D__ASSEMBLY__ ${DEFINES} -c head.S
trap.o: machine.h offsets.h trap.S
${CC} ${CFLAGS} -D__ASSEMBLY__ ${DEFINES} -c trap.S
vm86.o: machine.h vm86.c
${CC} ${CFLAGS} -c vm86.c
setup.o: machine.h setup.c
${CC} ${CFLAGS} -c setup.c
util.o: machine.h util.c
${CC} ${CFLAGS} -c util.c
roms.h: ../rombios/BIOS-bochs-latest ../vgabios/VGABIOS-lgpl-latest.bin ../vgabios/VGABIOS-lgpl-latest.cirrus.bin vmxassist.bin
./mkhex rombios ../rombios/BIOS-bochs-latest > roms.h
./mkhex vgabios_stdvga ../vgabios/VGABIOS-lgpl-latest.bin >> roms.h
./mkhex vgabios_cirrusvga ../vgabios/VGABIOS-lgpl-latest.cirrus.bin >> roms.h
./mkhex vmxassist vmxassist.bin >> roms.h
offsets.h: gen
./gen > offsets.h
gen: gen.c
${CC} ${CFLAGS} -o gen gen.c
clean:
rm -f vmxassist vmxassist.tmp vmxassist.bin vmxassist.run vmxassist.sym head.s roms.h
rm -f vmxloader vmxloader.tmp vmxloader.o ${OBJECTS}
rm -f gen gen.o offsets.h
+8
View File
@@ -0,0 +1,8 @@
- Use the VME extensions (interrupt handling)
- Use E820 map in vmxassist instead of cmos hack
- Add ACPI support (Nitin's patch)
+52
View File
@@ -0,0 +1,52 @@
/*
* gen.c: Generate assembler symbols.
*
* Leendert van Doorn, leendert@watson.ibm.com
* Copyright (c) 2005, International Business Machines Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
*/
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <public/vmx_assist.h>
int
main()
{
printf("/* MACHINE GENERATED; DO NOT EDIT */\n");
printf("#define VMX_ASSIST_CTX_GS_SEL 0x%x\n",
offsetof(struct vmx_assist_context, gs_sel));
printf("#define VMX_ASSIST_CTX_FS_SEL 0x%x\n",
offsetof(struct vmx_assist_context, fs_sel));
printf("#define VMX_ASSIST_CTX_DS_SEL 0x%x\n",
offsetof(struct vmx_assist_context, ds_sel));
printf("#define VMX_ASSIST_CTX_ES_SEL 0x%x\n",
offsetof(struct vmx_assist_context, es_sel));
printf("#define VMX_ASSIST_CTX_SS_SEL 0x%x\n",
offsetof(struct vmx_assist_context, ss_sel));
printf("#define VMX_ASSIST_CTX_ESP 0x%x\n",
offsetof(struct vmx_assist_context, esp));
printf("#define VMX_ASSIST_CTX_EFLAGS 0x%x\n",
offsetof(struct vmx_assist_context, eflags));
printf("#define VMX_ASSIST_CTX_CS_SEL 0x%x\n",
offsetof(struct vmx_assist_context, cs_sel));
printf("#define VMX_ASSIST_CTX_EIP 0x%x\n",
offsetof(struct vmx_assist_context, eip));
printf("#define VMX_ASSIST_CTX_CR0 0x%x\n",
offsetof(struct vmx_assist_context, cr0));
return 0;
}
+162
View File
@@ -0,0 +1,162 @@
/*
* head.S: VMXAssist runtime start off.
*
* Leendert van Doorn, leendert@watson.ibm.com
* Copyright (c) 2005, International Business Machines Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
*/
#include "vm86.h"
#include "machine.h"
/*
* When a partition tries to mask off the CR0_PE bit a world
* switch happens to the environment below. The magic indicates
* that this is a valid context.
*/
#ifdef TEST
.byte 0x55, 0xaa
.byte 0x80
.code16
jmp _start16
#else
jmp _start
#endif
.align 8
.long VMXASSIST_MAGIC
.long newctx /* new context */
.long oldctx /* old context */
#ifdef TEST
/*
* We are running in 16-bit. Get into the protected mode as soon as
* possible. We use our own (minimal) GDT to get started.
*
* ROM is a misnomer as this code isn't really rommable (although it
* only requires a few changes) but it does live in a BIOS ROM segment.
* This code allows me to debug vmxassists under (a modified version of)
* Bochs and load it as a "optromimage1".
*/
.code16
.globl _start16
_start16:
cli
/* load our own global descriptor table */
data32 addr32 lgdt %cs:(rom_gdtr - TEXTADDR)
/* go to protected mode */
movl %cr0, %eax
orl $CR0_PE, %eax
movl %eax, %cr0
data32 ljmp $0x08, $1f
.align 32
.globl rom_gdt
rom_gdt:
.word 0, 0 /* 0x00: reserved */
.byte 0, 0, 0, 0
.word 0xFFFF, 0 /* 0x08: CS 32-bit */
.byte 0, 0x9A, 0xCF, 0
.word 0xFFFF, 0 /* 0x10: CS 32-bit */
.byte 0, 0x92, 0xCF, 0
rom_gdt_end:
.align 4
.globl rom_gdtr
rom_gdtr:
.word rom_gdt_end - rom_gdt - 1
.long rom_gdt
.code32
1:
/* welcome to the 32-bit world */
movw $0x10, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
movw %ax, %fs
movw %ax, %gs
/* enable Bochs debug facilities */
movw $0x8A00, %dx
movw $0x8A00, %ax
outw %ax, (%dx)
jmp _start
#endif /* TEST */
/*
* This is the real start. Control was transfered to this point
* with CR0_PE set and executing in some 32-bit segment. We call
* main and setup our own environment.
*/
.globl _start
_start:
cli
/* clear bss */
cld
xorb %al, %al
movl $_bbss, %edi
movl $_ebss, %ecx
subl %edi, %ecx
rep stosb
/* make sure we are in a sane world */
clts
/* setup my own stack */
movl $stack_top - 4*4, %esp
movl %esp, %ebp
/* go ... */
call main
jmp halt
/*
* Something bad happened, print invoking %eip and loop forever
*/
.align 4
.globl halt
halt:
pushl $halt_msg
call printf
#ifdef TEST
movw $0x8A00, %dx
movw $0x8AE0, %ax
outw %ax, (%dx)
#endif
cli
jmp .
.data
halt_msg:
.asciz "Halt called from %%eip 0x%x\n"
/*
* Our stack
*/
.bss
.align 8
.globl stack, stack_top
stack:
.skip STACK_SIZE
stack_top:
+203
View File
@@ -0,0 +1,203 @@
/*
* machine.h: Intel CPU specific definitions
*
* Leendert van Doorn, leendert@watson.ibm.com
* Copyright (c) 2005, International Business Machines Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
*/
#ifndef __MACHINE_H__
#define __MACHINE_H__
/* the size of our stack (4KB) */
#define STACK_SIZE 8192
#define TSS_SELECTOR 0x08
#define CODE_SELECTOR 0x10
#define DATA_SELECTOR 0x18
#define CR0_PE (1 << 0)
#define CR0_EM (1 << 2)
#define CR0_TS (1 << 3)
#define CR0_NE (1 << 5)
#define CR0_PG (1 << 31)
#define CR4_VME (1 << 0)
#define CR4_PVI (1 << 1)
#define CR4_PSE (1 << 4)
#define EFLAGS_TF (1 << 8)
#define EFLAGS_IF (1 << 9)
#define EFLAGS_DF (1 << 10)
#define EFLAGS_VM (1 << 17)
#define EFLAGS_VIF (1 << 19)
#define EFLAGS_VIP (1 << 20)
#define LOG_PGSIZE 12 /* log2(page size) */
#define LOG_PDSIZE 22 /* log2(page directory size) */
/* Derived constants */
#define PGSIZE (1 << LOG_PGSIZE) /* page size */
#define PGMASK (~(PGSIZE - 1)) /* page mask */
#define LPGSIZE (1 << LOG_PDSIZE) /* large page size */
#define LPGMASK (~(LPGSIZE - 1)) /* large page mask */
#ifdef TEST
#define PTE_P (1 << 0) /* Present */
#define PTE_RW (1 << 1) /* Read/Write */
#define PTE_US (1 << 2) /* User/Supervisor */
#define PTE_PS (1 << 7) /* Page Size */
#endif
/* Programmable Interrupt Contoller (PIC) defines */
#define PIC_MASTER 0x20
#define PIC_SLAVE 0xA0
#define PIC_CMD 0 /* command */
#define PIC_ISR 0 /* interrupt status */
#define PIC_IMR 1 /* interrupt mask */
#ifndef __ASSEMBLY__
struct dtr {
unsigned short size;
unsigned long base __attribute__ ((packed));
};
struct tss {
unsigned short prev_link;
unsigned short _1;
unsigned long esp0;
unsigned short ss0;
unsigned short _2;
unsigned long esp1;
unsigned short ss1;
unsigned short _3;
unsigned long esp2;
unsigned short ss2;
unsigned short _4;
unsigned long cr3;
unsigned long eip;
unsigned long eflags;
unsigned long eax;
unsigned long ecx;
unsigned long edx;
unsigned long ebx;
unsigned long esi;
unsigned long edi;
unsigned long esp;
unsigned long ebp;
unsigned long es;
unsigned long cs;
unsigned long ss;
unsigned long ds;
unsigned long fs;
unsigned long gs;
unsigned short ldt_segment;
unsigned short _5;
unsigned short _6;
unsigned short iomap_base;
unsigned char iomap[8192];
};
static inline void
outw(unsigned short addr, unsigned short val)
{
__asm__ __volatile__ ("outw %%ax, %%dx" :: "d"(addr), "a"(val));
}
static inline void
outb(unsigned short addr, unsigned char val)
{
__asm__ __volatile__ ("outb %%al, %%dx" :: "d"(addr), "a"(val));
}
static inline unsigned char
inb(unsigned short addr)
{
unsigned char val;
__asm__ __volatile__ ("inb %w1,%0" : "=a" (val) : "Nd" (addr));
return val;
}
static inline unsigned
get_cmos(int reg)
{
outb(0x70, reg);
return inb(0x71);
}
static inline unsigned
get_cr0(void)
{
unsigned rv;
__asm__ __volatile__("movl %%cr0, %0" : "=r"(rv));
return rv;
}
static inline void
set_cr0(unsigned value)
{
__asm__ __volatile__(
"movl %0, %%cr0\n"
"jmp 1f\n"
"1: nop\n"
: /* no outputs */
: "r"(value)
);
}
static inline unsigned
get_cr2(void)
{
unsigned rv;
__asm__ __volatile__("movl %%cr2, %0" : "=r"(rv));
return rv;
}
static inline unsigned
get_cr4(void)
{
unsigned rv;
__asm__ __volatile__("movl %%cr4, %0" : "=r"(rv));
return rv;
}
#ifdef TEST
static inline void
set_cr3(unsigned addr)
{
__asm__ __volatile__("movl %0, %%cr3" : /* no outputs */ : "r"(addr));
}
static inline void
set_cr4(unsigned value)
{
__asm__ __volatile__("movl %0, %%cr4" : /* no outputs */ : "r"(value));
}
static inline void
breakpoint(void)
{
outw(0x8A00, 0x8AE0);
}
#endif /* TEST */
#endif /* __ASSEMBLY__ */
#endif /* __MACHINE_H__ */
+26
View File
@@ -0,0 +1,26 @@
#!/bin/sh
#
# mkhex: Generate C embeddable hexdumps
#
# Leendert van Doorn, leendert@watson.ibm.com
# Copyright (c) 2005, International Business Machines Corporation.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
# version 2, as published by the Free Software Foundation.
#
# This program is distributed in the hope it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
# Place - Suite 330, Boston, MA 02111-1307 USA.
#
echo "unsigned $1[] = {"
od -v -t x $2 | sed 's/^[0-9]* /0x/' | sed 's/ /, 0x/g' | sed 's/$/,/'
echo "};"
+338
View File
@@ -0,0 +1,338 @@
/*
* setup.c: Setup the world for vmxassist.
*
* Leendert van Doorn, leendert@watson.ibm.com
* Copyright (c) 2005, International Business Machines Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
*/
#include "vm86.h"
#include "util.h"
#include "machine.h"
#ifndef TEST
#if (VMXASSIST_BASE != TEXTADDR)
#error VMXAssist base mismatch
#endif
#endif
#define NR_PGD (PGSIZE / sizeof(unsigned))
#define min(a, b) ((a) > (b) ? (b) : (a))
unsigned long long gdt[] __attribute__ ((aligned(32))) = {
0x0000000000000000ULL, /* 0x00: reserved */
0x0000890000000000ULL, /* 0x08: 32-bit TSS */
0x00CF9A000000FFFFULL, /* 0x10: CS 32-bit */
0x00CF92000000FFFFULL, /* 0x18: DS 32-bit */
};
struct dtr gdtr = { sizeof(gdt)-1, (unsigned long) &gdt };
struct tss tss __attribute__ ((aligned(4)));
unsigned long long idt[NR_TRAPS] __attribute__ ((aligned(32)));
struct dtr idtr = { sizeof(idt)-1, (unsigned long) &idt };
#ifdef TEST
unsigned pgd[NR_PGD] __attribute__ ((aligned(PGSIZE))) = { 0 };
#endif
struct vmx_assist_context oldctx;
struct vmx_assist_context newctx;
unsigned long memory_size;
int initialize_real_mode;
extern char stack[], stack_top[];
extern unsigned trap_handlers[];
void
banner(void)
{
printf("VMXAssist (%s)\n", __DATE__);
/* Bochs its way to convey memory size */
memory_size = ((get_cmos(0x35) << 8) | get_cmos(0x34)) << 6;
if (memory_size > 0x3bc000)
memory_size = 0x3bc000;
memory_size = (memory_size << 10) + 0xF00000;
if (memory_size <= 0xF00000)
memory_size =
(((get_cmos(0x31) << 8) | get_cmos(0x30)) + 0x400) << 10;
memory_size += 0x400 << 10; /* + 1MB */
printf("Memory size %ld MB\n", memory_size >> 20);
printf("\n");
}
#ifdef TEST
void
setup_paging(void)
{
unsigned long i;
if (((unsigned)pgd & ~PGMASK) != 0)
panic("PGD not page aligned");
set_cr4(get_cr4() | CR4_PSE);
for (i = 0; i < NR_PGD; i++)
pgd[i] = (i * LPGSIZE)| PTE_PS | PTE_US | PTE_RW | PTE_P;
set_cr3((unsigned) pgd);
set_cr0(get_cr0() | (CR0_PE|CR0_PG));
}
#endif /* TEST */
void
setup_gdt(void)
{
/* setup task state segment */
memset(&tss, 0, sizeof(0));
tss.ss0 = DATA_SELECTOR;
tss.esp0 = (unsigned) stack_top - 4*4;
tss.iomap_base = offsetof(struct tss, iomap);
/* initialize gdt's tss selector */
unsigned long long addr = (unsigned long long) &tss;
gdt[TSS_SELECTOR / sizeof(gdt[0])] |=
((addr & 0xFF000000) << (56-24)) |
((addr & 0x00FF0000) << (32-16)) |
((addr & 0x0000FFFF) << (16)) |
(sizeof(tss) - 1);
/* switch to our own gdt and set current tss */
__asm__ __volatile__ ("lgdt %0" : : "m" (gdtr));
__asm__ __volatile__ ("movl %%eax,%%ds;"
"movl %%eax,%%es;"
"movl %%eax,%%fs;"
"movl %%eax,%%gs;"
"movl %%eax,%%ss" : : "a" (DATA_SELECTOR));
/* XXX 0x10 == CODE_SELECTOR (figure out gnuas) */
__asm__ __volatile__ ("ljmp $0x10,$1f; 1:");
__asm__ __volatile__ ("ltr %%ax" : : "a" (TSS_SELECTOR));
}
void
set_intr_gate(int i, unsigned handler)
{
unsigned long long addr = handler;
idt[i] = ((addr & 0xFFFF0000ULL) << 32) | (0x8E00ULL << 32) |
(addr & 0xFFFFULL) | (CODE_SELECTOR << 16);
}
void
setup_idt(void)
{
int i;
for (i = 0; i < NR_TRAPS; i++)
set_intr_gate(i, trap_handlers[i]);
__asm__ __volatile__ ("lidt %0" : : "m" (idtr));
}
void
setup_pic(void)
{
/* mask all interrupts */
outb(PIC_MASTER + PIC_IMR, 0xFF);
outb(PIC_SLAVE + PIC_IMR, 0xFF);
/* setup master PIC */
outb(PIC_MASTER + PIC_CMD, 0x11); /* edge triggered, cascade, ICW4 */
outb(PIC_MASTER + PIC_IMR, NR_EXCEPTION_HANDLER);
outb(PIC_MASTER + PIC_IMR, 1 << 2); /* slave on channel 2 */
outb(PIC_MASTER + PIC_IMR, 0x01);
/* setup slave PIC */
outb(PIC_SLAVE + PIC_CMD, 0x11); /* edge triggered, cascade, ICW4 */
outb(PIC_SLAVE + PIC_IMR, NR_EXCEPTION_HANDLER + 8);
outb(PIC_SLAVE + PIC_IMR, 0x02); /* slave identity is 2 */
outb(PIC_SLAVE + PIC_IMR, 0x01);
/* enable all interrupts */
outb(PIC_MASTER + PIC_IMR, 0);
outb(PIC_SLAVE + PIC_IMR, 0);
}
void
enter_real_mode(struct regs *regs)
{
/* mask off TSS busy bit */
gdt[TSS_SELECTOR / sizeof(gdt[0])] &= ~0x0000020000000000ULL;
/* start 8086 emulation of BIOS */
if (initialize_real_mode) {
initialize_real_mode = 0;
regs->eflags |= EFLAGS_VM | 0x02;
regs->ves = regs->vds = regs->vfs = regs->vgs = 0xF000;
regs->cs = 0xF000; /* ROM BIOS POST entry point */
#ifdef TEST
regs->eip = 0xFFE0;
#else
regs->eip = 0xFFF0;
#endif
regs->uesp = 0;
regs->uss = 0;
printf("Starting emulated 16-bit real-mode: ip=%04x:%04x\n",
regs->cs, regs->eip);
mode = VM86_REAL; /* becomes previous mode */
set_mode(regs, VM86_REAL);
/* this should get us into 16-bit mode */
return;
} else {
/* go from protected to real mode */
regs->eflags |= EFLAGS_VM;
set_mode(regs, VM86_PROTECTED_TO_REAL);
emulate(regs);
}
}
/*
* Setup the environment for VMX assist.
* This environment consists of flat segments (code and data),
* its own gdt, idt, and tr.
*/
void
setup_ctx(void)
{
struct vmx_assist_context *c = &newctx;
memset(c, 0, sizeof(*c));
c->eip = (unsigned long) switch_to_real_mode;
c->esp = (unsigned) stack_top - 4*4;
c->eflags = 0x2; /* no interrupts, please */
/*
* Obviously, vmx assist is not running with CR0_PE disabled.
* The reason why the vmx assist cr0 has CR0.PE disabled is
* that a transtion to CR0.PE causes a world switch. It seems
* more natural to enable CR0.PE to cause a world switch to
* protected mode rather than disabling it.
*/
#ifdef TEST
c->cr0 = (get_cr0() | CR0_NE | CR0_PG) & ~CR0_PE;
c->cr3 = (unsigned long) pgd;
#else
c->cr0 = (get_cr0() | CR0_NE) & ~CR0_PE;
c->cr3 = 0;
#endif
c->cr4 = get_cr4();
c->idtr_limit = sizeof(idt)-1;
c->idtr_base = (unsigned long) &idt;
c->gdtr_limit = sizeof(gdt)-1;
c->gdtr_base = (unsigned long) &gdt;
c->cs_sel = CODE_SELECTOR;
c->cs_limit = 0xFFFFFFFF;
c->cs_base = 0;
c->cs_arbytes.fields.seg_type = 0xb;
c->cs_arbytes.fields.s = 1;
c->cs_arbytes.fields.dpl = 0;
c->cs_arbytes.fields.p = 1;
c->cs_arbytes.fields.avl = 0;
c->cs_arbytes.fields.default_ops_size = 1;
c->cs_arbytes.fields.g = 1;
c->ds_sel = DATA_SELECTOR;
c->ds_limit = 0xFFFFFFFF;
c->ds_base = 0;
c->ds_arbytes = c->cs_arbytes;
c->ds_arbytes.fields.seg_type = 0x3;
c->es_sel = DATA_SELECTOR;
c->es_limit = 0xFFFFFFFF;
c->es_base = 0;
c->es_arbytes = c->ds_arbytes;
c->ss_sel = DATA_SELECTOR;
c->ss_limit = 0xFFFFFFFF;
c->ss_base = 0;
c->ss_arbytes = c->ds_arbytes;
c->fs_sel = DATA_SELECTOR;
c->fs_limit = 0xFFFFFFFF;
c->fs_base = 0;
c->fs_arbytes = c->ds_arbytes;
c->gs_sel = DATA_SELECTOR;
c->gs_limit = 0xFFFFFFFF;
c->gs_base = 0;
c->gs_arbytes = c->ds_arbytes;
c->tr_sel = TSS_SELECTOR;
c->tr_limit = sizeof(tss) - 1;
c->tr_base = (unsigned long) &tss;
c->tr_arbytes.fields.seg_type = 0xb; /* 0x9 | 0x2 (busy) */
c->tr_arbytes.fields.s = 0;
c->tr_arbytes.fields.dpl = 0;
c->tr_arbytes.fields.p = 1;
c->tr_arbytes.fields.avl = 0;
c->tr_arbytes.fields.default_ops_size = 0;
c->tr_arbytes.fields.g = 0;
c->ldtr_sel = 0;
c->ldtr_limit = 0;
c->ldtr_base = 0;
c->ldtr_arbytes = c->ds_arbytes;
c->ldtr_arbytes.fields.seg_type = 0x2;
c->ldtr_arbytes.fields.s = 0;
c->ldtr_arbytes.fields.dpl = 0;
c->ldtr_arbytes.fields.p = 1;
c->ldtr_arbytes.fields.avl = 0;
c->ldtr_arbytes.fields.default_ops_size = 0;
c->ldtr_arbytes.fields.g = 0;
}
/*
* Start BIOS by causing a world switch to vmxassist, which causes
* VM8086 to be enabled and control is transfered to F000:FFF0.
*/
void
start_bios(void)
{
unsigned long cr0;
printf("Start BIOS ...\n");
initialize_real_mode = 1;
cr0 = get_cr0();
#ifndef TEST
set_cr0(cr0 | CR0_PE);
#endif
set_cr0(cr0 & ~CR0_PE);
panic("vmxassist returned"); /* "cannot happen" */
}
int
main()
{
banner();
#ifdef TEST
setup_paging();
#endif
setup_gdt();
setup_idt();
setup_ctx();
setup_pic();
start_bios();
return 0;
}
+189
View File
@@ -0,0 +1,189 @@
/*
* trap.S: Trap and world switch handlers
*
* Leendert van Doorn, leendert@watson.ibm.com
* Copyright (c) 2005, International Business Machines Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
*/
#include "machine.h"
#include "offsets.h"
/*
* All processor exception/faults/interrupts end up here.
*
* On an exception/fault, the processor pushes CS:EIP, SS, ESP and an
* optional error code onto the stack. The common_trap routine
* below saves the processor context and transfers control to trap()
* whose job it is to virtualize and pass on the trap.
*/
.macro TRAP_HANDLER trapno error
.text
.align 16
1: .if \error == 0
pushl $0 /* dummy error code */
.endif
pushl $\trapno
jmp common_trap
.section .rodata
.long 1b
.text
.endm
.section .rodata
.align 4
.global trap_handlers
trap_handlers:
TRAP_HANDLER 0, 0 /* divide error */
TRAP_HANDLER 1, 0 /* debug */
TRAP_HANDLER 2, 0 /* NMI interrupt */
TRAP_HANDLER 3, 0 /* breakpoint */
TRAP_HANDLER 4, 0 /* overflow */
TRAP_HANDLER 5, 0 /* BOUND range exceeded */
TRAP_HANDLER 6, 0 /* invalid opcode */
TRAP_HANDLER 7, 0 /* device not available */
TRAP_HANDLER 8, 1 /* double fault */
TRAP_HANDLER 9, 0 /* coprocessor segment overrun */
TRAP_HANDLER 10, 1 /* invalid TSS */
TRAP_HANDLER 11, 1 /* segment not present */
TRAP_HANDLER 12, 1 /* stack-segment fault */
TRAP_HANDLER 13, 1 /* general protection */
TRAP_HANDLER 14, 1 /* page fault */
TRAP_HANDLER 15, 0 /* reserved */
TRAP_HANDLER 16, 0 /* FPU floating-point error */
TRAP_HANDLER 17, 1 /* alignment check */
TRAP_HANDLER 18, 0 /* machine check */
TRAP_HANDLER 19, 0 /* SIMD floating-point error */
TRAP_HANDLER 20, 0 /* reserved */
TRAP_HANDLER 21, 0 /* reserved */
TRAP_HANDLER 22, 0 /* reserved */
TRAP_HANDLER 23, 0 /* reserved */
TRAP_HANDLER 24, 0 /* reserved */
TRAP_HANDLER 25, 0 /* reserved */
TRAP_HANDLER 26, 0 /* reserved */
TRAP_HANDLER 27, 0 /* reserved */
TRAP_HANDLER 28, 0 /* reserved */
TRAP_HANDLER 29, 0 /* reserved */
TRAP_HANDLER 30, 0 /* reserved */
TRAP_HANDLER 31, 0 /* reserved */
TRAP_HANDLER 32, 0 /* irq 0 */
TRAP_HANDLER 33, 0 /* irq 1 */
TRAP_HANDLER 34, 0 /* irq 2 */
TRAP_HANDLER 35, 0 /* irq 3 */
TRAP_HANDLER 36, 0 /* irq 4 */
TRAP_HANDLER 37, 0 /* irq 5 */
TRAP_HANDLER 38, 0 /* irq 6 */
TRAP_HANDLER 39, 0 /* irq 7 */
TRAP_HANDLER 40, 0 /* irq 8 */
TRAP_HANDLER 41, 0 /* irq 9 */
TRAP_HANDLER 42, 0 /* irq 10 */
TRAP_HANDLER 43, 0 /* irq 11 */
TRAP_HANDLER 44, 0 /* irq 12 */
TRAP_HANDLER 45, 0 /* irq 13 */
TRAP_HANDLER 46, 0 /* irq 14 */
TRAP_HANDLER 47, 0 /* irq 15 */
.text
.align 16
common_trap: /* common trap handler */
pushl %gs
pushl %fs
pushl %ds
pushl %es
pushal
movl $DATA_SELECTOR, %eax /* make sure these are sane */
movl %eax, %ds
movl %eax, %es
movl %eax, %fs
movl %eax, %gs
movl %esp, %ebp
pushl %ebp
pushl 52(%ebp)
pushl 48(%ebp)
call trap /* trap(trapno, errno, regs) */
addl $12, %esp
trap_return:
popal
popl %es
popl %ds
popl %fs
popl %gs
addl $8, %esp /* skip trapno, errno */
iret
/* NOT REACHED */
/*
* A world switch to real mode occured. The hypervisor saved the
* executing context into "oldctx" and instantiated "newctx", which
* gets us here. Here we push a stack frame that is compatible with
* a trap frame (see above) so that we can handle this event as a
* regular trap.
*/
.text
.align 16
.globl switch_to_real_mode
switch_to_real_mode:
pushl oldctx+VMX_ASSIST_CTX_GS_SEL /* 16 to 32-bit transition */
pushl oldctx+VMX_ASSIST_CTX_FS_SEL
pushl oldctx+VMX_ASSIST_CTX_DS_SEL
pushl oldctx+VMX_ASSIST_CTX_ES_SEL
pushl oldctx+VMX_ASSIST_CTX_SS_SEL
pushl oldctx+VMX_ASSIST_CTX_ESP
pushl oldctx+VMX_ASSIST_CTX_EFLAGS
pushl oldctx+VMX_ASSIST_CTX_CS_SEL
pushl oldctx+VMX_ASSIST_CTX_EIP
pushl $-1 /* trapno, errno */
pushl $-1
pushl %gs
pushl %fs
pushl %ds
pushl %es
pushal
movl %esp, %ebp
pushl %ebp
call enter_real_mode
addl $4, %esp
jmp trap_return
/* NOT REACHED */
/*
* Switch to protected mode. At this point all the registers have
* been reloaded by trap_return and all we have to do is cause a
* world switch by turning on CR0.PE.
*/
.text
.align 16
.globl switch_to_protected_mode
switch_to_protected_mode:
movl oldctx+VMX_ASSIST_CTX_CR0, %esp
movl %esp, %cr0 /* actual world switch ! */
/* NOT REACHED */
pushl $switch_failed
call panic
jmp .
.data
.align 4
switch_failed:
.asciz "World switch to protected mode failed\n"
+364
View File
@@ -0,0 +1,364 @@
/*
* util.c: Commonly used utility functions.
*
* Leendert van Doorn, leendert@watson.ibm.com
* Copyright (c) 2005, International Business Machines Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
*/
#include <stdarg.h>
#include <public/vmx_assist.h>
#include "util.h"
#include "machine.h"
#define isdigit(c) ((c) >= '0' && (c) <= '9')
#define min(a, b) ((a) < (b) ? (a) : (b))
static void putchar(int);
static char *printnum(char *, unsigned long, int);
static void _doprint(void (*)(int), char const *, va_list);
void
dump_regs(struct regs *regs)
{
printf("eax %8x ecx %8x edx %8x ebx %8x\n",
regs->eax, regs->ecx, regs->edx, regs->ebx);
printf("esp %8x ebp %8x esi %8x edi %8x\n",
regs->esp, regs->ebp, regs->esi, regs->edi);
printf("eip %8x eflags %8x cs %8x ds %8x\n",
regs->eip, regs->eflags, regs->cs, regs->ds);
printf("es %8x fs %8x uss %8x uesp %8x\n",
regs->es, regs->fs, regs->uss, regs->uesp);
printf("ves %8x vds %8x vfs %8x vgs %8x\n",
regs->ves, regs->vds, regs->vfs, regs->vgs);
if (regs->trapno != -1 || regs->errno != -1)
printf("trapno %8x errno %8x\n", regs->trapno, regs->errno);
printf("cr0 %8lx cr2 %8x cr3 %8lx cr4 %8lx\n",
oldctx.cr0, get_cr2(), oldctx.cr3, oldctx.cr4);
}
#ifdef DEBUG
void
hexdump(unsigned char *data, int sz)
{
unsigned char *d;
int i;
for (d = data; sz > 0; d += 16, sz -= 16) {
int n = sz > 16 ? 16 : sz;
printf("%08x: ", (unsigned)d);
for (i = 0; i < n; i++)
printf("%02x%c", d[i], i == 7 ? '-' : ' ');
for (; i < 16; i++)
printf(" %c", i == 7 ? '-' : ' ');
printf(" ");
for (i = 0; i < n; i++)
printf("%c", d[i] >= ' ' && d[i] <= '~' ? d[i] : '.');
printf("\n");
}
}
void
dump_dtr(unsigned long base, unsigned long limit)
{
unsigned long long entry;
int i;
for (i = 0; i < limit; i += 8) {
entry = ((unsigned long long *) base)[i >> 3];
printf("[0x%x] = 0x%08x%08x\n", i,
(unsigned)(entry >> 32), (unsigned)(entry));
}
}
void
dump_vmx_context(struct vmx_assist_context *c)
{
printf("eip 0x%lx, esp 0x%lx, eflags 0x%lx\n",
c->eip, c->esp, c->eflags);
printf("cr0 0x%lx, cr3 0x%lx, cr4 0x%lx\n", c->cr0, c->cr3, c->cr4);
printf("idtr: limit 0x%lx, base 0x%lx\n",
c->idtr_limit, c->idtr_base);
printf("gdtr: limit 0x%lx, base 0x%lx\n",
c->gdtr_limit, c->gdtr_base);
printf("cs: sel 0x%lx, limit 0x%lx, base 0x%lx\n",
c->cs_sel, c->cs_limit, c->cs_base);
printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n",
c->cs_arbytes.fields.seg_type,
c->cs_arbytes.fields.s,
c->cs_arbytes.fields.dpl,
c->cs_arbytes.fields.p,
c->cs_arbytes.fields.avl,
c->cs_arbytes.fields.default_ops_size,
c->cs_arbytes.fields.g,
c->cs_arbytes.fields.null_bit);
printf("ds: sel 0x%lx, limit 0x%lx, base 0x%lx\n",
c->ds_sel, c->ds_limit, c->ds_base);
printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n",
c->ds_arbytes.fields.seg_type,
c->ds_arbytes.fields.s,
c->ds_arbytes.fields.dpl,
c->ds_arbytes.fields.p,
c->ds_arbytes.fields.avl,
c->ds_arbytes.fields.default_ops_size,
c->ds_arbytes.fields.g,
c->ds_arbytes.fields.null_bit);
printf("es: sel 0x%lx, limit 0x%lx, base 0x%lx\n",
c->es_sel, c->es_limit, c->es_base);
printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n",
c->es_arbytes.fields.seg_type,
c->es_arbytes.fields.s,
c->es_arbytes.fields.dpl,
c->es_arbytes.fields.p,
c->es_arbytes.fields.avl,
c->es_arbytes.fields.default_ops_size,
c->es_arbytes.fields.g,
c->es_arbytes.fields.null_bit);
printf("ss: sel 0x%lx, limit 0x%lx, base 0x%lx\n",
c->ss_sel, c->ss_limit, c->ss_base);
printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n",
c->ss_arbytes.fields.seg_type,
c->ss_arbytes.fields.s,
c->ss_arbytes.fields.dpl,
c->ss_arbytes.fields.p,
c->ss_arbytes.fields.avl,
c->ss_arbytes.fields.default_ops_size,
c->ss_arbytes.fields.g,
c->ss_arbytes.fields.null_bit);
printf("fs: sel 0x%lx, limit 0x%lx, base 0x%lx\n",
c->fs_sel, c->fs_limit, c->fs_base);
printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n",
c->fs_arbytes.fields.seg_type,
c->fs_arbytes.fields.s,
c->fs_arbytes.fields.dpl,
c->fs_arbytes.fields.p,
c->fs_arbytes.fields.avl,
c->fs_arbytes.fields.default_ops_size,
c->fs_arbytes.fields.g,
c->fs_arbytes.fields.null_bit);
printf("gs: sel 0x%lx, limit 0x%lx, base 0x%lx\n",
c->gs_sel, c->gs_limit, c->gs_base);
printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n",
c->gs_arbytes.fields.seg_type,
c->gs_arbytes.fields.s,
c->gs_arbytes.fields.dpl,
c->gs_arbytes.fields.p,
c->gs_arbytes.fields.avl,
c->gs_arbytes.fields.default_ops_size,
c->gs_arbytes.fields.g,
c->gs_arbytes.fields.null_bit);
printf("tr: sel 0x%lx, limit 0x%lx, base 0x%lx\n",
c->tr_sel, c->tr_limit, c->tr_base);
printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n",
c->tr_arbytes.fields.seg_type,
c->tr_arbytes.fields.s,
c->tr_arbytes.fields.dpl,
c->tr_arbytes.fields.p,
c->tr_arbytes.fields.avl,
c->tr_arbytes.fields.default_ops_size,
c->tr_arbytes.fields.g,
c->tr_arbytes.fields.null_bit);
printf("ldtr: sel 0x%lx, limit 0x%lx, base 0x%lx\n",
c->ldtr_sel, c->ldtr_limit, c->ldtr_base);
printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n",
c->ldtr_arbytes.fields.seg_type,
c->ldtr_arbytes.fields.s,
c->ldtr_arbytes.fields.dpl,
c->ldtr_arbytes.fields.p,
c->ldtr_arbytes.fields.avl,
c->ldtr_arbytes.fields.default_ops_size,
c->ldtr_arbytes.fields.g,
c->ldtr_arbytes.fields.null_bit);
printf("GDTR <0x%lx,0x%lx>:\n", c->gdtr_base, c->gdtr_limit);
dump_dtr(c->gdtr_base, c->gdtr_limit);
}
#endif /* DEBUG */
/*
* Lightweight printf that doesn't drag in everything under the sun.
*/
int
printf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
_doprint(putchar, fmt, ap);
va_end(ap);
return 0; /* for gcc compat */
}
int
vprintf(const char *fmt, va_list ap)
{
_doprint(putchar, fmt, ap);
return 0; /* for gcc compat */
}
void
panic(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
_doprint(putchar, fmt, ap);
putchar('\n');
va_end(ap);
halt();
}
unsigned
strlen(const char *s)
{
const char *q = s;
while (*s++)
/* void */;
return s - q - 1;
}
static void
putchar(int ch)
{
outb(0xE9, ch);
}
/*
* A stripped down version of doprint,
* but still powerful enough for most tasks.
*/
static void
_doprint(void (*put)(int), char const *fmt, va_list ap)
{
register char *str, c;
int lflag, zflag, nflag;
char buffer[17];
unsigned value;
int i, slen, pad;
for ( ; *fmt != '\0'; fmt++) {
pad = zflag = nflag = lflag = 0;
if (*fmt == '%') {
c = *++fmt;
if (c == '-' || isdigit(c)) {
if (c == '-') {
nflag = 1;
c = *++fmt;
}
zflag = c == '0';
for (pad = 0; isdigit(c); c = *++fmt)
pad = (pad * 10) + c - '0';
}
if (c == 'l') { /* long extension */
lflag = 1;
c = *++fmt;
}
if (c == 'd' || c == 'u' || c == 'o' || c == 'x') {
if (lflag)
value = va_arg(ap, unsigned);
else
value = (unsigned) va_arg(ap, unsigned int);
str = buffer;
printnum(str, value,
c == 'o' ? 8 : (c == 'x' ? 16 : 10));
goto printn;
} else if (c == 'O' || c == 'D' || c == 'X') {
value = va_arg(ap, unsigned);
str = buffer;
printnum(str, value,
c == 'O' ? 8 : (c == 'X' ? 16 : 10));
printn:
slen = strlen(str);
for (i = pad - slen; i > 0; i--)
put(zflag ? '0' : ' ');
while (*str) put(*str++);
} else if (c == 's') {
str = va_arg(ap, char *);
slen = strlen(str);
if (nflag == 0)
for (i = pad - slen; i > 0; i--) put(' ');
while (*str) put(*str++);
if (nflag)
for (i = pad - slen; i > 0; i--) put(' ');
} else if (c == 'c')
put(va_arg(ap, int));
else
put(*fmt);
} else
put(*fmt);
}
}
static char *
printnum(char *p, unsigned long num, int base)
{
unsigned long n;
if ((n = num/base) > 0)
p = printnum(p, n, base);
*p++ = "0123456789ABCDEF"[(int)(num % base)];
*p = '\0';
return p;
}
void *
memset(void *s, int c, unsigned n)
{
int t0, t1;
__asm__ __volatile__ ("cld; rep; stosb"
: "=&c" (t0), "=&D" (t1)
: "a" (c), "1" (s), "0" (n)
: "memory");
return s;
}
void *
memcpy(void *dest, const void *src, unsigned n)
{
int t0, t1, t2;
__asm__ __volatile__(
"cld\n"
"rep; movsl\n"
"testb $2,%b4\n"
"je 1f\n"
"movsw\n"
"1: testb $1,%b4\n"
"je 2f\n"
"movsb\n"
"2:"
: "=&c" (t0), "=&D" (t1), "=&S" (t2)
: "0" (n/4), "q" (n), "1" ((long) dest), "2" ((long) src)
: "memory"
);
return dest;
}
+41
View File
@@ -0,0 +1,41 @@
/*
* util.h: Useful utility functions.
*
* Leendert van Doorn, leendert@watson.ibm.com
* Copyright (c) 2005, International Business Machines Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
*/
#ifndef __UTIL_H__
#define __UTIL_H__
#include <stdarg.h>
#include <vm86.h>
#define offsetof(type, member) ((unsigned) &((type *)0)->member)
struct vmx_assist_context;
extern void hexdump(unsigned char *, int);
extern void dump_regs(struct regs *);
extern void dump_vmx_context(struct vmx_assist_context *);
extern void dump_dtr(unsigned long, unsigned long);
extern void *memcpy(void *, const void *, unsigned);
extern void *memset(void *, int, unsigned);
extern int printf(const char *fmt, ...);
extern int vprintf(const char *fmt, va_list ap);
extern void panic(const char *format, ...);
extern void halt(void);
#endif /* __UTIL_H__ */
+956
View File
@@ -0,0 +1,956 @@
/*
* vm86.c: A vm86 emulator. The main purpose of this emulator is to do as
* little work as possible.
*
* Leendert van Doorn, leendert@watson.ibm.com
* Copyright (c) 2005, International Business Machines Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
*/
#include "vm86.h"
#include "util.h"
#include "machine.h"
#define HIGHMEM (1 << 20) /* 1MB */
#define MASK16(v) ((v) & 0xFFFF)
#define DATA32 0x0001
#define ADDR32 0x0002
#define SEG_CS 0x0004
#define SEG_DS 0x0008
#define SEG_ES 0x0010
#define SEG_SS 0x0020
#define SEG_FS 0x0040
#define SEG_GS 0x0080
unsigned prev_eip = 0;
enum vm86_mode mode;
#ifdef DEBUG
int traceset = 0;
#endif /* DEBUG */
unsigned
address(struct regs *regs, unsigned seg, unsigned off)
{
unsigned long long entry;
unsigned addr;
/* real mode: segment is part of the address */
if (mode == VM86_REAL || mode == VM86_REAL_TO_PROTECTED)
return ((seg & 0xFFFF) << 4) + off;
/* protected mode: use seg as index into gdt */
if (seg > oldctx.gdtr_limit) {
printf("address: Invalid segment descriptor (0x%x)\n", seg);
return 0;
}
entry = ((unsigned long long *) oldctx.gdtr_base)[seg >> 3];
addr = (((entry >> (56-24)) & 0xFF000000) |
((entry >> (32-16)) & 0x00FF0000) |
((entry >> ( 16)) & 0x0000FFFF)) + off;
return addr;
}
#ifdef DEBUG
void
trace(struct regs *regs, int adjust, char *fmt, ...)
{
unsigned off = regs->eip - adjust;
va_list ap;
if ((traceset & (1 << mode)) &&
(mode == VM86_REAL_TO_PROTECTED || mode == VM86_REAL)) {
/* 16-bit, seg:off addressing */
unsigned addr = address(regs, regs->cs, off);
printf("0x%08x: 0x%x:0x%04x ", addr, regs->cs, off);
printf("(%d) ", mode);
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
printf("\n");
}
if ((traceset & (1 << mode)) &&
(mode == VM86_PROTECTED_TO_REAL || mode == VM86_PROTECTED)) {
/* 16-bit, gdt addressing */
unsigned addr = address(regs, regs->cs, off);
printf("0x%08x: 0x%x:0x%08x ", addr, regs->cs, off);
printf("(%d) ", mode);
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
printf("\n");
}
}
#endif /* DEBUG */
static inline unsigned
read32(unsigned addr)
{
return *(unsigned long *) addr;
}
static inline unsigned
read16(unsigned addr)
{
return *(unsigned short *) addr;
}
static inline unsigned
read8(unsigned addr)
{
return *(unsigned char *) addr;
}
static inline void
write32(unsigned addr, unsigned value)
{
*(unsigned long *) addr = value;
}
static inline void
write16(unsigned addr, unsigned value)
{
*(unsigned short *) addr = value;
}
static inline void
write8(unsigned addr, unsigned value)
{
*(unsigned char *) addr = value;
}
static inline void
push32(struct regs *regs, unsigned value)
{
regs->uesp -= 4;
write32(address(regs, regs->uss, MASK16(regs->uesp)), value);
}
static inline void
push16(struct regs *regs, unsigned value)
{
regs->uesp -= 2;
write16(address(regs, regs->uss, MASK16(regs->uesp)), value);
}
static inline unsigned
pop32(struct regs *regs)
{
unsigned value = read32(address(regs, regs->uss, MASK16(regs->uesp)));
regs->uesp += 4;
return value;
}
static inline unsigned
pop16(struct regs *regs)
{
unsigned value = read16(address(regs, regs->uss, MASK16(regs->uesp)));
regs->uesp += 2;
return value;
}
static inline unsigned
fetch32(struct regs *regs)
{
unsigned addr = address(regs, regs->cs, MASK16(regs->eip));
regs->eip += 4;
return read32(addr);
}
static inline unsigned
fetch16(struct regs *regs)
{
unsigned addr = address(regs, regs->cs, MASK16(regs->eip));
regs->eip += 2;
return read16(addr);
}
static inline unsigned
fetch8(struct regs *regs)
{
unsigned addr = address(regs, regs->cs, MASK16(regs->eip));
regs->eip++;
return read8(addr);
}
unsigned
getreg(struct regs *regs, int r)
{
switch (r & 7) {
case 0: return regs->eax;
case 1: return regs->ecx;
case 2: return regs->edx;
case 3: return regs->ebx;
case 4: return regs->esp;
case 5: return regs->ebp;
case 6: return regs->esi;
case 7: return regs->edi;
}
return ~0;
}
void
setreg(struct regs *regs, int r, unsigned v)
{
switch (r & 7) {
case 0: regs->eax = v; break;
case 1: regs->ecx = v; break;
case 2: regs->edx = v; break;
case 3: regs->ebx = v; break;
case 4: regs->esp = v; break;
case 5: regs->ebp = v; break;
case 6: regs->esi = v; break;
case 7: regs->edi = v; break;
}
}
/*
* Operand (modrm) decode
*/
unsigned
operand(unsigned prefix, struct regs *regs, unsigned modrm)
{
int mod, disp = 0, seg;
seg = regs->vds;
if (prefix & SEG_ES)
seg = regs->ves;
if (prefix & SEG_DS)
seg = regs->vds;
if (prefix & SEG_CS)
seg = regs->cs;
if (prefix & SEG_SS)
seg = regs->uss;
if (prefix & SEG_FS)
seg = regs->fs;
if (prefix & SEG_GS)
seg = regs->gs;
if (prefix & ADDR32) { /* 32-bit addressing */
switch ((mod = (modrm >> 6) & 3)) {
case 0:
switch (modrm & 7) {
case 0: return address(regs, seg, regs->eax);
case 1: return address(regs, seg, regs->ecx);
case 2: return address(regs, seg, regs->edx);
case 3: return address(regs, seg, regs->ebx);
case 4: panic("No SIB decode (yet)");
case 5: return address(regs, seg, fetch32(regs));
case 6: return address(regs, seg, regs->esi);
case 7: return address(regs, seg, regs->edi);
}
break;
case 1:
case 2:
if ((modrm & 7) != 4) {
if (mod == 1)
disp = (char) fetch8(regs);
else
disp = (int) fetch32(regs);
}
switch (modrm & 7) {
case 0: return address(regs, seg, regs->eax + disp);
case 1: return address(regs, seg, regs->ecx + disp);
case 2: return address(regs, seg, regs->edx + disp);
case 3: return address(regs, seg, regs->ebx + disp);
case 4: panic("No SIB decode (yet)");
case 5: return address(regs, seg, regs->ebp + disp);
case 6: return address(regs, seg, regs->esi + disp);
case 7: return address(regs, seg, regs->edi + disp);
}
break;
case 3:
return getreg(regs, modrm);
}
} else { /* 16-bit addressing */
switch ((mod = (modrm >> 6) & 3)) {
case 0:
switch (modrm & 7) {
case 0: return address(regs, seg, MASK16(regs->ebx) +
MASK16(regs->esi));
case 1: return address(regs, seg, MASK16(regs->ebx) +
MASK16(regs->edi));
case 2: return address(regs, seg, MASK16(regs->ebp) +
MASK16(regs->esi));
case 3: return address(regs, seg, MASK16(regs->ebp) +
MASK16(regs->edi));
case 4: return address(regs, seg, MASK16(regs->esi));
case 5: return address(regs, seg, MASK16(regs->edi));
case 6: return address(regs, seg, fetch16(regs));
case 7: return address(regs, seg, MASK16(regs->ebx));
}
break;
case 1:
case 2:
if (mod == 1)
disp = (char) fetch8(regs);
else
disp = (int) fetch16(regs);
switch (modrm & 7) {
case 0: return address(regs, seg, MASK16(regs->ebx) +
MASK16(regs->esi) + disp);
case 1: return address(regs, seg, MASK16(regs->ebx) +
MASK16(regs->edi) + disp);
case 2: return address(regs, seg, MASK16(regs->ebp) +
MASK16(regs->esi) + disp);
case 3: return address(regs, seg, MASK16(regs->ebp) +
MASK16(regs->edi) + disp);
case 4: return address(regs, seg,
MASK16(regs->esi) + disp);
case 5: return address(regs, seg,
MASK16(regs->edi) + disp);
case 6: return address(regs, seg,
MASK16(regs->ebp) + disp);
case 7: return address(regs, seg,
MASK16(regs->ebx) + disp);
}
break;
case 3:
return MASK16(getreg(regs, modrm));
}
}
return 0;
}
/*
* Load new IDT
*/
int
lidt(struct regs *regs, unsigned prefix, unsigned modrm)
{
unsigned eip = regs->eip - 3;
unsigned addr = operand(prefix, regs, modrm);
oldctx.idtr_limit = ((struct dtr *) addr)->size;
if ((prefix & DATA32) == 0)
oldctx.idtr_base = ((struct dtr *) addr)->base & 0xFFFFFF;
else
oldctx.idtr_base = ((struct dtr *) addr)->base;
TRACE((regs, regs->eip - eip, "lidt 0x%x <%d, 0x%x>",
addr, oldctx.idtr_limit, oldctx.idtr_base));
return 1;
}
/*
* Load new GDT
*/
int
lgdt(struct regs *regs, unsigned prefix, unsigned modrm)
{
unsigned eip = regs->eip - 3;
unsigned addr = operand(prefix, regs, modrm);
oldctx.gdtr_limit = ((struct dtr *) addr)->size;
if ((prefix & DATA32) == 0)
oldctx.gdtr_base = ((struct dtr *) addr)->base & 0xFFFFFF;
else
oldctx.gdtr_base = ((struct dtr *) addr)->base;
TRACE((regs, regs->eip - eip, "lgdt 0x%x <%d, 0x%x>",
addr, oldctx.gdtr_limit, oldctx.gdtr_base));
return 1;
}
/*
* Modify CR0 either through an lmsw instruction.
*/
int
lmsw(struct regs *regs, unsigned prefix, unsigned modrm)
{
unsigned eip = regs->eip - 3;
unsigned ax = operand(prefix, regs, modrm) & 0xF;
unsigned cr0 = (oldctx.cr0 & 0xFFFFFFF0) | ax;
TRACE((regs, regs->eip - eip, "lmsw 0x%x", ax));
#ifndef TEST
oldctx.cr0 = cr0 | CR0_PE | CR0_NE;
#else
oldctx.cr0 = cr0 | CR0_PE | CR0_NE | CR0_PG;
#endif
if (cr0 & CR0_PE)
set_mode(regs, VM86_REAL_TO_PROTECTED);
return 1;
}
/*
* Move to and from a control register.
*/
int
movcr(struct regs *regs, unsigned prefix, unsigned opc)
{
unsigned eip = regs->eip - 2;
unsigned modrm = fetch8(regs);
unsigned cr = (modrm >> 3) & 7;
if ((modrm & 0xC0) != 0xC0) /* only registers */
return 0;
switch (opc) {
case 0x20: /* mov Rd, Cd */
TRACE((regs, regs->eip - eip, "movl %%cr%d, %%eax", cr));
switch (cr) {
case 0:
#ifndef TEST
setreg(regs, modrm,
oldctx.cr0 & ~(CR0_PE | CR0_NE));
#else
setreg(regs, modrm,
oldctx.cr0 & ~(CR0_PE | CR0_NE | CR0_PG));
#endif
break;
case 2:
setreg(regs, modrm, get_cr2());
break;
case 3:
setreg(regs, modrm, oldctx.cr3);
break;
case 4:
setreg(regs, modrm, oldctx.cr4);
break;
}
break;
case 0x22: /* mov Cd, Rd */
TRACE((regs, regs->eip - eip, "movl %%eax, %%cr%d", cr));
switch (cr) {
case 0:
oldctx.cr0 = getreg(regs, modrm) | (CR0_PE | CR0_NE);
#ifdef TEST
oldctx.cr0 |= CR0_PG;
#endif
if (getreg(regs, modrm) & CR0_PE)
set_mode(regs, VM86_REAL_TO_PROTECTED);
break;
case 3:
oldctx.cr3 = getreg(regs, modrm);
break;
case 4:
oldctx.cr4 = getreg(regs, modrm);
break;
}
break;
}
return 1;
}
/*
* Emulate a segment load in protected mode
*/
int
load_seg(unsigned long sel, unsigned long *base, unsigned long *limit,
union vmcs_arbytes *arbytes)
{
unsigned long long entry;
/* protected mode: use seg as index into gdt */
if (sel == 0 || sel > oldctx.gdtr_limit)
return 0;
entry = ((unsigned long long *) oldctx.gdtr_base)[sel >> 3];
*base = (((entry >> (56-24)) & 0xFF000000) |
((entry >> (32-16)) & 0x00FF0000) |
((entry >> ( 16)) & 0x0000FFFF));
*limit = (((entry >> (48-16)) & 0x000F0000) |
((entry ) & 0x0000FFFF));
arbytes->bytes = 0;
arbytes->fields.seg_type = (entry >> (8+32)) & 0xF; /* TYPE */
arbytes->fields.s = (entry >> (12+32)) & 0x1; /* S */
if (arbytes->fields.s)
arbytes->fields.seg_type |= 1; /* accessed */
arbytes->fields.dpl = (entry >> (13+32)) & 0x3; /* DPL */
arbytes->fields.p = (entry >> (15+32)) & 0x1; /* P */
arbytes->fields.avl = (entry >> (20+32)) & 0x1; /* AVL */
arbytes->fields.default_ops_size = (entry >> (22+32)) & 0x1; /* D */
if (entry & (1ULL << (23+32))) { /* G */
arbytes->fields.g = 1;
*limit = (*limit << 12) | 0xFFF;
}
return 1;
}
/*
* Transition to protected mode
*/
void
protected_mode(struct regs *regs)
{
regs->eflags &= ~(EFLAGS_TF|EFLAGS_VM);
oldctx.eip = regs->eip;
oldctx.esp = regs->uesp;
oldctx.eflags = regs->eflags;
/* reload all segment registers */
if (!load_seg(regs->cs, &oldctx.cs_base,
&oldctx.cs_limit, &oldctx.cs_arbytes))
panic("Invalid %%cs=0x%x for protected mode\n", regs->cs);
oldctx.cs_sel = regs->cs;
if (load_seg(regs->ves, &oldctx.es_base,
&oldctx.es_limit, &oldctx.es_arbytes))
oldctx.es_sel = regs->ves;
if (load_seg(regs->uss, &oldctx.ss_base,
&oldctx.ss_limit, &oldctx.ss_arbytes))
oldctx.ss_sel = regs->uss;
if (load_seg(regs->vds, &oldctx.ds_base,
&oldctx.ds_limit, &oldctx.ds_arbytes))
oldctx.ds_sel = regs->vds;
if (load_seg(regs->vfs, &oldctx.fs_base,
&oldctx.fs_limit, &oldctx.fs_arbytes))
oldctx.fs_sel = regs->vfs;
if (load_seg(regs->vgs, &oldctx.gs_base,
&oldctx.gs_limit, &oldctx.gs_arbytes))
oldctx.gs_sel = regs->vgs;
/* initialize jump environment to warp back to protected mode */
regs->cs = CODE_SELECTOR;
regs->ds = DATA_SELECTOR;
regs->es = DATA_SELECTOR;
regs->fs = DATA_SELECTOR;
regs->gs = DATA_SELECTOR;
regs->eip = (unsigned) &switch_to_protected_mode;
/* this should get us into 32-bit mode */
}
/*
* Start real-mode emulation
*/
void
real_mode(struct regs *regs)
{
regs->eflags |= EFLAGS_VM | 0x02;
regs->ds = DATA_SELECTOR;
regs->es = DATA_SELECTOR;
regs->fs = DATA_SELECTOR;
regs->gs = DATA_SELECTOR;
/*
* When we transition from protected to real-mode and we
* have not reloaded the segment descriptors yet, they are
* interpreted as if they were in protect mode.
* We emulate this behavior by assuming that these memory
* reference are below 1MB and set %ss, %ds, %es accordingly.
*/
if (regs->uss != 0) {
if (regs->uss >= HIGHMEM)
panic("%%ss 0x%lx higher than 1MB", regs->uss);
regs->uss = address(regs, regs->uss, 0) >> 4;
}
if (regs->vds != 0) {
if (regs->vds >= HIGHMEM)
panic("%%ds 0x%lx higher than 1MB", regs->vds);
regs->vds = address(regs, regs->vds, 0) >> 4;
}
if (regs->ves != 0) {
if (regs->ves >= HIGHMEM)
panic("%%es 0x%lx higher than 1MB", regs->ves);
regs->ves = address(regs, regs->ves, 0) >> 4;
}
/* this should get us into 16-bit mode */
}
/*
* This is the smarts of the emulator and handles the mode transitions. The
* emulator handles 4 different modes. 1) VM86_REAL: emulated real-mode, Just
* handle those instructions that are not supported under VM8086.
* 2) VM86_REAL_TO_PROTECTED: going from real-mode to protected mode. In this
* we single step through the instructions until we reload the new %cs (some
* OSes do a lot of computations before reloading %cs). 2) VM86_PROTECTED_TO_REAL
* when we are going from protected to real mode. In this case we emulate the
* instructions by hand. Finally, 4) VM86_PROTECTED when we transitioned to
* protected mode and we should abandon the emulator. No instructions are
* emulated when in VM86_PROTECTED mode.
*/
void
set_mode(struct regs *regs, enum vm86_mode newmode)
{
switch (newmode) {
case VM86_REAL:
TRACE((regs, 0, "<VM86_REAL>"));
if (mode == VM86_PROTECTED_TO_REAL) {
real_mode(regs);
break;
} else if (mode == VM86_REAL) {
break;
} else
panic("unexpected real mode transition");
break;
case VM86_REAL_TO_PROTECTED:
TRACE((regs, 0, "<VM86_REAL_TO_PROTECTED>"));
if (mode == VM86_REAL) {
regs->eflags |= EFLAGS_TF;
break;
} else if (mode == VM86_REAL_TO_PROTECTED) {
break;
} else
panic("unexpected real-to-protected mode transition");
break;
case VM86_PROTECTED_TO_REAL:
if (mode == VM86_PROTECTED)
break;
else
panic("unexpected protected-to-real mode transition");
case VM86_PROTECTED:
TRACE((regs, 0, "<VM86_PROTECTED>"));
if (mode == VM86_REAL_TO_PROTECTED) {
protected_mode(regs);
break;
} else
panic("unexpected protected mode transition");
break;
}
mode = newmode;
}
void
jmpl(struct regs *regs, int prefix)
{
unsigned n = regs->eip;
unsigned cs, eip;
if (mode == VM86_REAL_TO_PROTECTED) { /* jump to protected mode */
eip = (prefix & DATA32) ? fetch32(regs) : fetch16(regs);
cs = fetch16(regs);
TRACE((regs, (regs->eip - n) + 1, "jmpl 0x%x:0x%x", cs, eip));
regs->cs = cs;
regs->eip = eip;
set_mode(regs, VM86_PROTECTED);
} else if (mode == VM86_PROTECTED_TO_REAL) { /* jump to real mode */
eip = (prefix & DATA32) ? fetch32(regs) : fetch16(regs);
cs = fetch16(regs);
TRACE((regs, (regs->eip - n) + 1, "jmpl 0x%x:0x%x", cs, eip));
regs->cs = cs;
regs->eip = eip;
set_mode(regs, VM86_REAL);
} else
panic("jmpl");
}
void
retl(struct regs *regs, int prefix)
{
unsigned cs, eip;
if (prefix & DATA32) {
eip = pop32(regs);
cs = MASK16(pop32(regs));
} else {
eip = pop16(regs);
cs = pop16(regs);
}
TRACE((regs, 1, "retl (to 0x%x:0x%x)", cs, eip));
if (mode == VM86_REAL_TO_PROTECTED) { /* jump to protected mode */
regs->cs = cs;
regs->eip = eip;
set_mode(regs, VM86_PROTECTED);
} else if (mode == VM86_PROTECTED_TO_REAL) { /* jump to real mode */
regs->cs = cs;
regs->eip = eip;
set_mode(regs, VM86_REAL);
} else
panic("retl");
}
void
interrupt(struct regs *regs, int n)
{
TRACE((regs, 0, "external interrupt %d", n));
push16(regs, regs->eflags);
push16(regs, regs->cs);
push16(regs, regs->eip);
regs->eflags &= ~EFLAGS_IF;
regs->eip = read16(address(regs, 0, n * 4));
regs->cs = read16(address(regs, 0, n * 4 + 2));
}
enum { OPC_INVALID, OPC_EMULATED };
/*
* Emulate a single instruction, including all its prefixes. We only implement
* a small subset of the opcodes, and not all opcodes are implemented for each
* of the four modes we can operate in.
*/
int
opcode(struct regs *regs)
{
unsigned eip = regs->eip;
unsigned opc, modrm, disp;
unsigned prefix = 0;
for (;;) {
switch ((opc = fetch8(regs))) {
case 0x0F: /* two byte opcode */
if (mode == VM86_PROTECTED)
goto invalid;
switch ((opc = fetch8(regs))) {
case 0x01:
switch (((modrm = fetch8(regs)) >> 3) & 7) {
case 0: /* sgdt */
case 1: /* sidt */
goto invalid;
case 2: /* lgdt */
if (!lgdt(regs, prefix, modrm))
goto invalid;
return OPC_EMULATED;
case 3: /* lidt */
if (!lidt(regs, prefix, modrm))
goto invalid;
return OPC_EMULATED;
case 4: /* smsw */
goto invalid;
case 5:
goto invalid;
case 6: /* lmsw */
if (!lmsw(regs, prefix, modrm))
goto invalid;
return OPC_EMULATED;
case 7: /* invlpg */
goto invalid;
}
break;
case 0x20: /* mov Rd, Cd (1h) */
case 0x22:
if (!movcr(regs, prefix, opc))
goto invalid;
return OPC_EMULATED;
default:
goto invalid;
}
goto invalid;
case 0x26:
TRACE((regs, regs->eip - eip, "%%es:"));
prefix |= SEG_ES;
continue;
case 0x2E:
TRACE((regs, regs->eip - eip, "%%cs:"));
prefix |= SEG_CS;
continue;
case 0x36:
TRACE((regs, regs->eip - eip, "%%ss:"));
prefix |= SEG_SS;
continue;
case 0x3E:
TRACE((regs, regs->eip - eip, "%%ds:"));
prefix |= SEG_DS;
continue;
case 0x64:
TRACE((regs, regs->eip - eip, "%%fs:"));
prefix |= SEG_FS;
continue;
case 0x65:
TRACE((regs, regs->eip - eip, "%%gs:"));
prefix |= SEG_GS;
continue;
case 0x66:
TRACE((regs, regs->eip - eip, "data32"));
prefix |= DATA32;
continue;
case 0x67:
TRACE((regs, regs->eip - eip, "addr32"));
prefix |= ADDR32;
continue;
case 0x90: /* nop */
TRACE((regs, regs->eip - eip, "nop"));
return OPC_EMULATED;
case 0x9C: /* pushf */
TRACE((regs, regs->eip - eip, "pushf"));
if (prefix & DATA32)
push32(regs, regs->eflags & ~EFLAGS_VM);
else
push16(regs, regs->eflags & ~EFLAGS_VM);
return OPC_EMULATED;
case 0x9D: /* popf */
TRACE((regs, regs->eip - eip, "popf"));
if (prefix & DATA32)
regs->eflags = pop32(regs);
else
regs->eflags = (regs->eflags & 0xFFFF0000L) |
pop16(regs);
regs->eflags |= EFLAGS_VM;
return OPC_EMULATED;
case 0xCB: /* retl */
if ((mode == VM86_REAL_TO_PROTECTED) ||
(mode == VM86_PROTECTED_TO_REAL)) {
retl(regs, prefix);
return OPC_EMULATED;
}
goto invalid;
case 0xCD: /* int $n */
TRACE((regs, regs->eip - eip, "int"));
interrupt(regs, fetch8(regs));
return OPC_EMULATED;
case 0xCF: /* iret */
if (prefix & DATA32) {
TRACE((regs, regs->eip - eip, "data32 iretd"));
regs->eip = pop32(regs);
regs->cs = pop32(regs);
regs->eflags = pop32(regs);
} else {
TRACE((regs, regs->eip - eip, "iret"));
regs->eip = pop16(regs);
regs->cs = pop16(regs);
regs->eflags = (regs->eflags & 0xFFFF0000L) |
pop16(regs);
}
return OPC_EMULATED;
case 0xEA: /* jmpl */
if ((mode == VM86_REAL_TO_PROTECTED) ||
(mode == VM86_PROTECTED_TO_REAL)) {
jmpl(regs, prefix);
return OPC_EMULATED;
}
goto invalid;
case 0xEB: /* short jump */
if ((mode == VM86_REAL_TO_PROTECTED) ||
(mode == VM86_PROTECTED_TO_REAL)) {
disp = (char) fetch8(regs);
TRACE((regs, 2, "jmp 0x%x", regs->eip + disp));
regs->eip += disp;
return OPC_EMULATED;
}
goto invalid;
case 0xF0: /* lock */
TRACE((regs, regs->eip - eip, "lock"));
continue;
case 0xFA: /* cli */
TRACE((regs, regs->eip - eip, "cli"));
regs->eflags &= ~EFLAGS_IF;
return OPC_EMULATED;
case 0xFB: /* sti */
TRACE((regs, regs->eip - eip, "sti"));
regs->eflags |= EFLAGS_IF;
return OPC_EMULATED;
default:
goto invalid;
}
}
invalid:
regs->eip = eip;
return OPC_INVALID;
}
void
emulate(struct regs *regs)
{
unsigned flteip;
int nemul = 0;
/* emulate as many instructions as possible */
while (opcode(regs) != OPC_INVALID)
nemul++;
/* detect the case where we are not making progress */
if (nemul == 0 && prev_eip == regs->eip) {
flteip = address(regs, MASK16(regs->cs), regs->eip);
panic("Unknown opcode at %04x:%04x=0x%x",
MASK16(regs->cs), regs->eip, flteip);
} else
prev_eip = regs->eip;
}
void
trap(int trapno, int errno, struct regs *regs)
{
/* emulate device interrupts */
if (trapno >= NR_EXCEPTION_HANDLER) {
int irq = trapno - NR_EXCEPTION_HANDLER;
if (irq < 8)
interrupt(regs, irq + 8);
else
interrupt(regs, 0x70 + (irq - 8));
return;
}
switch (trapno) {
case 1: /* Debug */
if (regs->eflags & EFLAGS_VM) {
/* emulate any 8086 instructions */
if (mode != VM86_REAL_TO_PROTECTED)
panic("not in real-to-protected mode");
emulate(regs);
return;
}
goto invalid;
case 13: /* GPF */
if (regs->eflags & EFLAGS_VM) {
/* emulate any 8086 instructions */
if (mode == VM86_PROTECTED)
panic("unexpected protected mode");
emulate(regs);
return;
}
goto invalid;
default:
invalid:
printf("Trap (%d) while in %s mode\n",
trapno, regs->eflags & EFLAGS_VM ? "real" : "protected");
if (trapno == 14)
printf("Page fault address 0x%x\n", get_cr2());
dump_regs(regs);
halt();
}
}
+67
View File
@@ -0,0 +1,67 @@
/*
* vm86.h: vm86 emulator definitions.
*
* Leendert van Doorn, leendert@watson.ibm.com
* Copyright (c) 2005, International Business Machines Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
*/
#ifndef __VM86_H__
#define __VM86_H__
#include <public/vmx_assist.h>
#define NR_EXCEPTION_HANDLER 32
#define NR_INTERRUPT_HANDLERS 16
#define NR_TRAPS (NR_EXCEPTION_HANDLER+NR_INTERRUPT_HANDLERS)
#ifndef __ASSEMBLY__
struct regs {
unsigned edi, esi, ebp, esp, ebx, edx, ecx, eax;
unsigned ds, es, fs, gs;
unsigned trapno, errno;
unsigned eip, cs, eflags, uesp, uss;
unsigned ves, vds, vfs, vgs;
};
enum vm86_mode {
VM86_REAL = 0,
VM86_REAL_TO_PROTECTED,
VM86_PROTECTED_TO_REAL,
VM86_PROTECTED
};
#ifdef DEBUG
#define TRACE(a) trace a
#else
#define TRACE(a)
#endif
extern enum vm86_mode prevmode, mode;
extern struct vmx_assist_context oldctx;
extern struct vmx_assist_context newctx;
extern void emulate(struct regs *);
extern void interrupt(struct regs *, int);
extern void dump_regs(struct regs *);
extern void trace(struct regs *, int, char *, ...);
extern void set_mode(struct regs *, enum vm86_mode);
extern void switch_to_real_mode(void);
extern void switch_to_protected_mode(void);
#endif /* __ASSEMBLY__ */
#endif /* __VM86_H__ */
+34
View File
@@ -0,0 +1,34 @@
/*
* vmxassist.ld
*/
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
/*OUTPUT_ARCH(i386)*/
ENTRY(_start)
SECTIONS
{
.text TEXTADDR :
{
_btext = .;
*(.text)
*(.rodata)
*(.rodata.str1.1)
*(.rodata.str1.4)
_etext = .;
}
.data :
{
_bdata = .;
*(.data)
_edata = .;
}
.bss :
{
_bbss = .;
*(.bss)
_ebss = .;
}
}
+110
View File
@@ -0,0 +1,110 @@
/*
* vmxloader.c: ROM/VMXAssist image loader.
*
* A quicky so that we can boot rom images as if they were a Linux kernel.
* This code will copy the rom images (ROMBIOS/VGABIOS/VM86) into their
* respective spaces and transfer control to VM86 to execute the BIOSes.
*
* Leendert van Doorn, leendert@watson.ibm.com
* Copyright (c) 2005, International Business Machines Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place - Suite 330, Boston, MA 02111-1307 USA.
*/
#include "machine.h"
#include "roms.h"
/*
* C runtime start off
*/
asm(" \n\
.text \n\
.globl _start \n\
_start: \n\
cli \n\
movl $stack_top, %esp \n\
movl %esp, %ebp \n\
call main \n\
jmp halt \n\
\n\
.globl halt \n\
halt: \n\
sti \n\
jmp . \n\
\n\
.bss \n\
.align 8 \n\
.globl stack, stack_top \n\
stack: \n\
.skip 0x4000 \n\
stack_top: \n\
");
void *
memcpy(void *dest, const void *src, unsigned n)
{
int t0, t1, t2;
__asm__ __volatile__(
"cld\n"
"rep; movsl\n"
"testb $2,%b4\n"
"je 1f\n"
"movsw\n"
"1: testb $1,%b4\n"
"je 2f\n"
"movsb\n"
"2:"
: "=&c" (t0), "=&D" (t1), "=&S" (t2)
: "0" (n/4), "q" (n), "1" ((long) dest), "2" ((long) src)
: "memory"
);
return dest;
}
int
puts(const char *s)
{
while (*s)
outb(0xE9, *s++);
return 0;
}
int
cirrus_check(void)
{
outw(0x3C4, 0x9206);
return inb(0x3C5) == 0x12;
}
int
main()
{
puts("VMXAssist Loader\n");
puts("Loading ROMBIOS ...\n");
memcpy((void *)0xF0000, rombios, sizeof(rombios));
if (cirrus_check()) {
puts("Loading Cirrus VGABIOS ...\n");
memcpy((void *)0xC0000,
vgabios_cirrusvga, sizeof(vgabios_cirrusvga));
} else {
puts("Loading Standard VGABIOS ...\n");
memcpy((void *)0xC0000,
vgabios_stdvga, sizeof(vgabios_stdvga));
}
puts("Loading VMXAssist ...\n");
memcpy((void *)TEXTADDR, vmxassist, sizeof(vmxassist));
puts("Go ...\n");
((void (*)())TEXTADDR)();
}
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.