diff options
author | Dave Airlie <airlied@redhat.com> | 2009-08-04 09:07:53 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2009-08-04 09:08:48 +1000 |
commit | 2dd13517503c806dbf950c51072153cad2798a01 (patch) | |
tree | f77e54d0300005ad07fdc659a240f43af85a348c |
vbetool: import 1.1 from Fedora
-rw-r--r-- | COPYING | 348 | ||||
-rw-r--r-- | Makefile.am | 17 | ||||
-rw-r--r-- | configure.in | 17 | ||||
-rw-r--r-- | include/fpu_regs.h | 112 | ||||
-rw-r--r-- | include/lrmi.h | 103 | ||||
-rw-r--r-- | include/regs.h | 330 | ||||
-rw-r--r-- | include/types.h | 107 | ||||
-rw-r--r-- | include/x86emu.h | 194 | ||||
-rw-r--r-- | include/xf86int10.h | 213 | ||||
-rw-r--r-- | include/xf86x86emu.h | 51 | ||||
-rw-r--r-- | vbetool.1 | 95 | ||||
-rw-r--r-- | vbetool.c | 572 | ||||
-rw-r--r-- | vbetool.h | 19 | ||||
-rw-r--r-- | x86-common.c | 249 | ||||
-rw-r--r-- | x86-common.h | 43 |
15 files changed, 2470 insertions, 0 deletions
@@ -0,0 +1,348 @@ +vbetool-0.1 + +The lrmi.* files were written by Josh Vanderhoof. See the LRMI file +and their source code for license. + +This package is distributed under the license below: + + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 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. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, 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 or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) 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; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, 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 executable. However, as a +special exception, the source code 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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + + 5. 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 Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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 to +this License. + + 7. 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 Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), 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 Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. 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 program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 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 + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..07605b6 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,17 @@ +AUTOMAKE_OPTIONS = foreign + +sbin_PROGRAMS = vbetool + +vbetool_LDADD = $(libdir)/libpci.a + +man_MANS = vbetool.1 +vbetool_SOURCES = vbetool.c $(x86) +noinst_HEADERS = vbetool.h + +EXTRA_DIST = vbetool.1 LRMI + +maintainer-clean-local: + $(RM) Makefile.in aclocal.m4 config.h.in stamp-h.in configure + +AM_CFLAGS = -g -Wall -pedantic -std=gnu99 +AM_LDFLAGS = -lz -lx86 diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..d57946c --- /dev/null +++ b/configure.in @@ -0,0 +1,17 @@ + +dnl Process this file with autoconf to produce a configure script. + +AC_INIT(vbetool.c) +AM_INIT_AUTOMAKE(vbetool, 0.3) + +dnl Checks for programs + +AC_PROG_CC + +dnl Simple, huh? + +AC_ARG_WITH([x86emu], AC_HELP_STRING([--with-x86emu],[build with x86emu support]), [USEX86EMU=true]) + +AM_CONDITIONAL(WITH_X86EMU, test x$USEX86EMU = xtrue) + +AC_OUTPUT([Makefile]) diff --git a/include/fpu_regs.h b/include/fpu_regs.h new file mode 100644 index 0000000..a125075 --- /dev/null +++ b/include/fpu_regs.h @@ -0,0 +1,112 @@ +/**************************************************************************** +* +* Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* Copyright (C) David Mosberger-Tang +* Copyright (C) 1999 Egbert Eich +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* Developer: Kendall Bennett +* +* Description: Header file for FPU register definitions. +* +****************************************************************************/ +/* $XFree86: xc/extras/x86emu/include/x86emu/fpu_regs.h,v 1.2 2003/10/22 20:03:05 tsi Exp $ */ + +#ifndef __X86EMU_FPU_REGS_H +#define __X86EMU_FPU_REGS_H + +#ifdef X86_FPU_SUPPORT + +/* Basic 8087 register can hold any of the following values: */ + +union x86_fpu_reg_u { + s8 tenbytes[10]; + double dval; + float fval; + s16 sval; + s32 lval; + }; + +struct x86_fpu_reg { + union x86_fpu_reg_u reg; + char tag; + }; + +/* + * Since we are not going to worry about the problems of aliasing + * registers, every time a register is modified, its result type is + * set in the tag fields for that register. If some operation + * attempts to access the type in a way inconsistent with its current + * storage format, then we flag the operation. If common, we'll + * attempt the conversion. + */ + +#define X86_FPU_VALID 0x80 +#define X86_FPU_REGTYP(r) ((r) & 0x7F) + +#define X86_FPU_WORD 0x0 +#define X86_FPU_SHORT 0x1 +#define X86_FPU_LONG 0x2 +#define X86_FPU_FLOAT 0x3 +#define X86_FPU_DOUBLE 0x4 +#define X86_FPU_LDBL 0x5 +#define X86_FPU_BSD 0x6 + +#define X86_FPU_STKTOP 0 + +struct x86_fpu_registers { + struct x86_fpu_reg x86_fpu_stack[8]; + int x86_fpu_flags; + int x86_fpu_config; /* rounding modes, etc. */ + short x86_fpu_tos, x86_fpu_bos; + }; + +/* + * There are two versions of the following macro. + * + * One version is for opcode D9, for which there are more than 32 + * instructions encoded in the second byte of the opcode. + * + * The other version, deals with all the other 7 i87 opcodes, for + * which there are only 32 strings needed to describe the + * instructions. + */ + +#endif /* X86_FPU_SUPPORT */ + +#ifdef DEBUG +# define DECODE_PRINTINSTR32(t,mod,rh,rl) \ + DECODE_PRINTF(t[(mod<<3)+(rh)]); +# define DECODE_PRINTINSTR256(t,mod,rh,rl) \ + DECODE_PRINTF(t[(mod<<6)+(rh<<3)+(rl)]); +#else +# define DECODE_PRINTINSTR32(t,mod,rh,rl) +# define DECODE_PRINTINSTR256(t,mod,rh,rl) +#endif + +#endif /* __X86EMU_FPU_REGS_H */ diff --git a/include/lrmi.h b/include/lrmi.h new file mode 100644 index 0000000..0306fa7 --- /dev/null +++ b/include/lrmi.h @@ -0,0 +1,103 @@ +/* +Linux Real Mode Interface - A library of DPMI-like functions for Linux. + +Copyright (C) 1998 by Josh Vanderhoof + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL JOSH VANDERHOOF BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef LRMI_H +#define LRMI_H + +struct LRMI_regs { + unsigned int edi; + unsigned int esi; + unsigned int ebp; + unsigned int reserved; + unsigned int ebx; + unsigned int edx; + unsigned int ecx; + unsigned int eax; + unsigned short int flags; + unsigned short int es; + unsigned short int ds; + unsigned short int fs; + unsigned short int gs; + unsigned short int ip; + unsigned short int cs; + unsigned short int sp; + unsigned short int ss; +}; + + +#ifndef LRMI_PREFIX +#define LRMI_PREFIX LRMI_ +#endif + +#define LRMI_CONCAT2(a, b) a ## b +#define LRMI_CONCAT(a, b) LRMI_CONCAT2(a, b) +#define LRMI_MAKENAME(a) LRMI_CONCAT(LRMI_PREFIX, a) + +/* + Initialize + returns 1 if sucessful, 0 for failure +*/ +#define LRMI_init LRMI_MAKENAME(init) +int +LRMI_init(void); + +/* + Simulate a 16 bit far call + returns 1 if sucessful, 0 for failure +*/ +#define LRMI_call LRMI_MAKENAME(call) +int +LRMI_call(struct LRMI_regs *r); + +/* + Simulate a 16 bit interrupt + returns 1 if sucessful, 0 for failure +*/ +#define LRMI_int LRMI_MAKENAME(int) +int +LRMI_int(int interrupt, struct LRMI_regs *r); + +/* + Allocate real mode memory + The returned block is paragraph (16 byte) aligned +*/ +#define LRMI_alloc_real LRMI_MAKENAME(alloc_real) +void * +LRMI_alloc_real(int size); + +/* + Free real mode memory +*/ +#define LRMI_free_real LRMI_MAKENAME(free_real) +void +LRMI_free_real(void *m); + +/* + * Get the base address of the real memory address space block. + */ +size_t +LRMI_base_addr(void); + +#endif diff --git a/include/regs.h b/include/regs.h new file mode 100644 index 0000000..fba2991 --- /dev/null +++ b/include/regs.h @@ -0,0 +1,330 @@ +/**************************************************************************** +* +* Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* Copyright (C) David Mosberger-Tang +* Copyright (C) 1999 Egbert Eich +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* Developer: Kendall Bennett +* +* Description: Header file for x86 register definitions. +* +****************************************************************************/ +/* $XFree86: xc/extras/x86emu/include/x86emu/regs.h,v 1.5 2003/10/22 20:03:05 tsi Exp $ */ + +#ifndef __X86EMU_REGS_H +#define __X86EMU_REGS_H + +/*---------------------- Macros and type definitions ----------------------*/ + +/* + * General EAX, EBX, ECX, EDX type registers. Note that for + * portability, and speed, the issue of byte swapping is not addressed + * in the registers. All registers are stored in the default format + * available on the host machine. The only critical issue is that the + * registers should line up EXACTLY in the same manner as they do in + * the 386. That is: + * + * EAX & 0xff === AL + * EAX & 0xffff == AX + * + * etc. The result is that alot of the calculations can then be + * done using the native instruction set fully. + */ + +#ifdef __BIG_ENDIAN__ + +typedef struct { + u32 e_reg; + } I32_reg_t; + +typedef struct { + u16 filler0, x_reg; + } I16_reg_t; + +typedef struct { + u8 filler0, filler1, h_reg, l_reg; + } I8_reg_t; + +#else /* !__BIG_ENDIAN__ */ + +typedef struct { + u32 e_reg; + } I32_reg_t; + +typedef struct { + u16 x_reg; + } I16_reg_t; + +typedef struct { + u8 l_reg, h_reg; + } I8_reg_t; + +#endif /* BIG_ENDIAN */ + +typedef union { + I32_reg_t I32_reg; + I16_reg_t I16_reg; + I8_reg_t I8_reg; + } i386_general_register; + +struct i386_general_regs { + i386_general_register A, B, C, D; + }; + +typedef struct i386_general_regs Gen_reg_t; + +struct i386_special_regs { + i386_general_register SP, BP, SI, DI, IP; + u32 FLAGS; + }; + +/* + * Segment registers here represent the 16 bit quantities + * CS, DS, ES, SS. + */ + +struct i386_segment_regs { + u16 CS, DS, SS, ES, FS, GS; + }; + +/* 8 bit registers */ +#define R_AH gen.A.I8_reg.h_reg +#define R_AL gen.A.I8_reg.l_reg +#define R_BH gen.B.I8_reg.h_reg +#define R_BL gen.B.I8_reg.l_reg +#define R_CH gen.C.I8_reg.h_reg +#define R_CL gen.C.I8_reg.l_reg +#define R_DH gen.D.I8_reg.h_reg +#define R_DL gen.D.I8_reg.l_reg + +/* 16 bit registers */ +#define R_AX gen.A.I16_reg.x_reg +#define R_BX gen.B.I16_reg.x_reg +#define R_CX gen.C.I16_reg.x_reg +#define R_DX gen.D.I16_reg.x_reg + +/* 32 bit extended registers */ +#define R_EAX gen.A.I32_reg.e_reg +#define R_EBX gen.B.I32_reg.e_reg +#define R_ECX gen.C.I32_reg.e_reg +#define R_EDX gen.D.I32_reg.e_reg + +/* special registers */ +#define R_SP spc.SP.I16_reg.x_reg +#define R_BP spc.BP.I16_reg.x_reg +#define R_SI spc.SI.I16_reg.x_reg +#define R_DI spc.DI.I16_reg.x_reg +#define R_IP spc.IP.I16_reg.x_reg +#define R_FLG spc.FLAGS + +/* special registers */ +#define R_SP spc.SP.I16_reg.x_reg +#define R_BP spc.BP.I16_reg.x_reg +#define R_SI spc.SI.I16_reg.x_reg +#define R_DI spc.DI.I16_reg.x_reg +#define R_IP spc.IP.I16_reg.x_reg +#define R_FLG spc.FLAGS + +/* special registers */ +#define R_ESP spc.SP.I32_reg.e_reg +#define R_EBP spc.BP.I32_reg.e_reg +#define R_ESI spc.SI.I32_reg.e_reg +#define R_EDI spc.DI.I32_reg.e_reg +#define R_EIP spc.IP.I32_reg.e_reg +#define R_EFLG spc.FLAGS + +/* segment registers */ +#define R_CS seg.CS +#define R_DS seg.DS +#define R_SS seg.SS +#define R_ES seg.ES +#define R_FS seg.FS +#define R_GS seg.GS + +/* flag conditions */ +#define FB_CF 0x0001 /* CARRY flag */ +#define FB_PF 0x0004 /* PARITY flag */ +#define FB_AF 0x0010 /* AUX flag */ +#define FB_ZF 0x0040 /* ZERO flag */ +#define FB_SF 0x0080 /* SIGN flag */ +#define FB_TF 0x0100 /* TRAP flag */ +#define FB_IF 0x0200 /* INTERRUPT ENABLE flag */ +#define FB_DF 0x0400 /* DIR flag */ +#define FB_OF 0x0800 /* OVERFLOW flag */ + +/* 80286 and above always have bit#1 set */ +#define F_ALWAYS_ON (0x0002) /* flag bits always on */ + +/* + * Define a mask for only those flag bits we will ever pass back + * (via PUSHF) + */ +#define F_MSK (FB_CF|FB_PF|FB_AF|FB_ZF|FB_SF|FB_TF|FB_IF|FB_DF|FB_OF) + +/* following bits masked in to a 16bit quantity */ + +#define F_CF 0x0001 /* CARRY flag */ +#define F_PF 0x0004 /* PARITY flag */ +#define F_AF 0x0010 /* AUX flag */ +#define F_ZF 0x0040 /* ZERO flag */ +#define F_SF 0x0080 /* SIGN flag */ +#define F_TF 0x0100 /* TRAP flag */ +#define F_IF 0x0200 /* INTERRUPT ENABLE flag */ +#define F_DF 0x0400 /* DIR flag */ +#define F_OF 0x0800 /* OVERFLOW flag */ + +#define TOGGLE_FLAG(flag) (M.x86.R_FLG ^= (flag)) +#define SET_FLAG(flag) (M.x86.R_FLG |= (flag)) +#define CLEAR_FLAG(flag) (M.x86.R_FLG &= ~(flag)) +#define ACCESS_FLAG(flag) (M.x86.R_FLG & (flag)) +#define CLEARALL_FLAG(m) (M.x86.R_FLG = 0) + +#define CONDITIONAL_SET_FLAG(COND,FLAG) \ + if (COND) SET_FLAG(FLAG); else CLEAR_FLAG(FLAG) + +#define F_PF_CALC 0x010000 /* PARITY flag has been calced */ +#define F_ZF_CALC 0x020000 /* ZERO flag has been calced */ +#define F_SF_CALC 0x040000 /* SIGN flag has been calced */ + +#define F_ALL_CALC 0xff0000 /* All have been calced */ + +/* + * Emulator machine state. + * Segment usage control. + */ +#define SYSMODE_SEG_DS_SS 0x00000001 +#define SYSMODE_SEGOVR_CS 0x00000002 +#define SYSMODE_SEGOVR_DS 0x00000004 +#define SYSMODE_SEGOVR_ES 0x00000008 +#define SYSMODE_SEGOVR_FS 0x00000010 +#define SYSMODE_SEGOVR_GS 0x00000020 +#define SYSMODE_SEGOVR_SS 0x00000040 +#define SYSMODE_PREFIX_REPE 0x00000080 +#define SYSMODE_PREFIX_REPNE 0x00000100 +#define SYSMODE_PREFIX_DATA 0x00000200 +#define SYSMODE_PREFIX_ADDR 0x00000400 +#define SYSMODE_INTR_PENDING 0x10000000 +#define SYSMODE_EXTRN_INTR 0x20000000 +#define SYSMODE_HALTED 0x40000000 + +#define SYSMODE_SEGMASK (SYSMODE_SEG_DS_SS | \ + SYSMODE_SEGOVR_CS | \ + SYSMODE_SEGOVR_DS | \ + SYSMODE_SEGOVR_ES | \ + SYSMODE_SEGOVR_FS | \ + SYSMODE_SEGOVR_GS | \ + SYSMODE_SEGOVR_SS) +#define SYSMODE_CLRMASK (SYSMODE_SEG_DS_SS | \ + SYSMODE_SEGOVR_CS | \ + SYSMODE_SEGOVR_DS | \ + SYSMODE_SEGOVR_ES | \ + SYSMODE_SEGOVR_FS | \ + SYSMODE_SEGOVR_GS | \ + SYSMODE_SEGOVR_SS | \ + SYSMODE_PREFIX_DATA | \ + SYSMODE_PREFIX_ADDR) + +#define INTR_SYNCH 0x1 +#define INTR_ASYNCH 0x2 +#define INTR_HALTED 0x4 + +typedef struct { + struct i386_general_regs gen; + struct i386_special_regs spc; + struct i386_segment_regs seg; + /* + * MODE contains information on: + * REPE prefix 2 bits repe,repne + * SEGMENT overrides 5 bits normal,DS,SS,CS,ES + * Delayed flag set 3 bits (zero, signed, parity) + * reserved 6 bits + * interrupt # 8 bits instruction raised interrupt + * BIOS video segregs 4 bits + * Interrupt Pending 1 bits + * Extern interrupt 1 bits + * Halted 1 bits + */ + u32 mode; + volatile int intr; /* mask of pending interrupts */ + int debug; +#ifdef DEBUG + int check; + u16 saved_ip; + u16 saved_cs; + int enc_pos; + int enc_str_pos; + char decode_buf[32]; /* encoded byte stream */ + char decoded_buf[256]; /* disassembled strings */ +#endif + u8 intno; + u8 __pad[3]; + } X86EMU_regs; + +/**************************************************************************** +REMARKS: +Structure maintaining the emulator machine state. + +MEMBERS: +mem_base - Base real mode memory for the emulator +mem_size - Size of the real mode memory block for the emulator +private - private data pointer +x86 - X86 registers +****************************************************************************/ +typedef struct { + unsigned long mem_base; + unsigned long mem_size; + void* private; + X86EMU_regs x86; + } X86EMU_sysEnv; + +/*----------------------------- Global Variables --------------------------*/ + +#ifdef __cplusplus +extern "C" { /* Use "C" linkage when in C++ mode */ +#endif + +/* Global emulator machine state. + * + * We keep it global to avoid pointer dereferences in the code for speed. + */ + +extern X86EMU_sysEnv _X86EMU_env; +#define M _X86EMU_env + +/*-------------------------- Function Prototypes --------------------------*/ + +/* Function to log information at runtime */ + +void printk(const char *fmt, ...); + +#ifdef __cplusplus +} /* End of "C" linkage for C++ */ +#endif + +#endif /* __X86EMU_REGS_H */ diff --git a/include/types.h b/include/types.h new file mode 100644 index 0000000..5232d10 --- /dev/null +++ b/include/types.h @@ -0,0 +1,107 @@ +/**************************************************************************** +* +* Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* Copyright (C) David Mosberger-Tang +* Copyright (C) 1999 Egbert Eich +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* Developer: Kendall Bennett +* +* Description: Header file for x86 emulator type definitions. +* +****************************************************************************/ + +/* $XFree86: xc/extras/x86emu/include/x86emu/types.h,v 1.6 2003/06/12 14:12:26 eich Exp $ */ + +#ifndef __X86EMU_TYPES_H +#define __X86EMU_TYPES_H + +#ifndef IN_MODULE +#include <sys/types.h> +#endif + +/* + * The following kludge is an attempt to work around typedef conflicts with + * <sys/types.h>. + */ +#define u8 x86emuu8 +#define u16 x86emuu16 +#define u32 x86emuu32 +#define u64 x86emuu64 +#define s8 x86emus8 +#define s16 x86emus16 +#define s32 x86emus32 +#define s64 x86emus64 +#define uint x86emuuint +#define sint x86emusint + +/*---------------------- Macros and type definitions ----------------------*/ + +/* Currently only for Linux/32bit */ +#undef __HAS_LONG_LONG__ +#if defined(__GNUC__) && !defined(NO_LONG_LONG) +#define __HAS_LONG_LONG__ +#endif + +/* Taken from Xmd.h */ +#undef NUM32 +#if defined (_LP64) || \ + defined(__alpha) || defined(__alpha__) || \ + defined(__ia64__) || defined(ia64) || \ + defined(__sparc64__) || \ + defined(__s390x__) || \ + (defined(__hppa__) && defined(__LP64)) || \ + defined(__amd64__) || defined(amd64) || \ + (defined(__sgi) && (_MIPS_SZLONG == 64)) +#define NUM32 int +#else +#define NUM32 long +#endif + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned NUM32 u32; +#ifdef __HAS_LONG_LONG__ +typedef unsigned long long u64; +#endif + +typedef char s8; +typedef short s16; +typedef NUM32 s32; +#ifdef __HAS_LONG_LONG__ +typedef long long s64; +#endif + +typedef unsigned int uint; +typedef int sint; + +typedef u16 X86EMU_pioAddr; + +#undef NUM32 + +#endif /* __X86EMU_TYPES_H */ diff --git a/include/x86emu.h b/include/x86emu.h new file mode 100644 index 0000000..d484eec --- /dev/null +++ b/include/x86emu.h @@ -0,0 +1,194 @@ +/**************************************************************************** +* +* Realmode X86 Emulator Library +* +* Copyright (C) 1996-1999 SciTech Software, Inc. +* Copyright (C) David Mosberger-Tang +* Copyright (C) 1999 Egbert Eich +* +* ======================================================================== +* +* Permission to use, copy, modify, distribute, and sell this software and +* its documentation for any purpose is hereby granted without fee, +* provided that the above copyright notice appear in all copies and that +* both that copyright notice and this permission notice appear in +* supporting documentation, and that the name of the authors not be used +* in advertising or publicity pertaining to distribution of the software +* without specific, written prior permission. The authors makes no +* representations about the suitability of this software for any purpose. +* It is provided "as is" without express or implied warranty. +* +* THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO +* EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR +* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF +* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR +* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +* PERFORMANCE OF THIS SOFTWARE. +* +* ======================================================================== +* +* Language: ANSI C +* Environment: Any +* Developer: Kendall Bennett +* +* Description: Header file for public specific functions. +* Any application linking against us should only +* include this header +* +****************************************************************************/ +/* $XFree86$ */ + +#ifndef __X86EMU_X86EMU_H +#define __X86EMU_X86EMU_H + +#ifdef SCITECH +#include "scitech.h" +#define X86API _ASMAPI +#define X86APIP _ASMAPIP +typedef int X86EMU_pioAddr; +#else +#include "types.h" +#define X86API +#define X86APIP * +#endif +#include "regs.h" + +/*---------------------- Macros and type definitions ----------------------*/ + +/* #pragma pack(1) */ /* Don't pack structs with function pointers! */ + +/**************************************************************************** +REMARKS: +Data structure containing ponters to programmed I/O functions used by the +emulator. This is used so that the user program can hook all programmed +I/O for the emulator to handled as necessary by the user program. By +default the emulator contains simple functions that do not do access the +hardware in any way. To allow the emualtor access the hardware, you will +need to override the programmed I/O functions using the X86EMU_setupPioFuncs +function. + +HEADER: +x86emu.h + +MEMBERS: +inb - Function to read a byte from an I/O port +inw - Function to read a word from an I/O port +inl - Function to read a dword from an I/O port +outb - Function to write a byte to an I/O port +outw - Function to write a word to an I/O port +outl - Function to write a dword to an I/O port +****************************************************************************/ +typedef struct { + u8 (X86APIP inb)(X86EMU_pioAddr addr); + u16 (X86APIP inw)(X86EMU_pioAddr addr); + u32 (X86APIP inl)(X86EMU_pioAddr addr); + void (X86APIP outb)(X86EMU_pioAddr addr, u8 val); + void (X86APIP outw)(X86EMU_pioAddr addr, u16 val); + void (X86APIP outl)(X86EMU_pioAddr addr, u32 val); + } X86EMU_pioFuncs; + +/**************************************************************************** +REMARKS: +Data structure containing ponters to memory access functions used by the +emulator. This is used so that the user program can hook all memory +access functions as necessary for the emulator. By default the emulator +contains simple functions that only access the internal memory of the +emulator. If you need specialised functions to handle access to different +types of memory (ie: hardware framebuffer accesses and BIOS memory access +etc), you will need to override this using the X86EMU_setupMemFuncs +function. + +HEADER: +x86emu.h + +MEMBERS: +rdb - Function to read a byte from an address +rdw - Function to read a word from an address +rdl - Function to read a dword from an address +wrb - Function to write a byte to an address +wrw - Function to write a word to an address +wrl - Function to write a dword to an address +****************************************************************************/ +typedef struct { + u8 (X86APIP rdb)(u32 addr); + u16 (X86APIP rdw)(u32 addr); + u32 (X86APIP rdl)(u32 addr); + void (X86APIP wrb)(u32 addr, u8 val); + void (X86APIP wrw)(u32 addr, u16 val); + void (X86APIP wrl)(u32 addr, u32 val); + } X86EMU_memFuncs; + +/**************************************************************************** + Here are the default memory read and write + function in case they are needed as fallbacks. +***************************************************************************/ +extern u8 X86API rdb(u32 addr); +extern u16 X86API rdw(u32 addr); +extern u32 X86API rdl(u32 addr); +extern void X86API wrb(u32 addr, u8 val); +extern void X86API wrw(u32 addr, u16 val); +extern void X86API wrl(u32 addr, u32 val); + +/* #pragma pack() */ + +/*--------------------- type definitions -----------------------------------*/ + +typedef void (X86APIP X86EMU_intrFuncs)(int num); +extern X86EMU_intrFuncs _X86EMU_intrTab[256]; + +/*-------------------------- Function Prototypes --------------------------*/ + +#ifdef __cplusplus +extern "C" { /* Use "C" linkage when in C++ mode */ +#endif + +void X86EMU_setupMemFuncs(X86EMU_memFuncs *funcs); +void X86EMU_setupPioFuncs(X86EMU_pioFuncs *funcs); +void X86EMU_setupIntrFuncs(X86EMU_intrFuncs funcs[]); +void X86EMU_prepareForInt(int num); + +/* decode.c */ + +void X86EMU_exec(void); +void X86EMU_halt_sys(void); + +#ifdef DEBUG +#define HALT_SYS() \ + printk("halt_sys: file %s, line %d\n", __FILE__, __LINE__), \ + X86EMU_halt_sys() +#else +#define HALT_SYS() X86EMU_halt_sys() +#endif + +/* Debug options */ + +#define DEBUG_DECODE_F 0x000001 /* print decoded instruction */ +#define DEBUG_TRACE_F 0x000002 /* dump regs before/after execution */ +#define DEBUG_STEP_F 0x000004 +#define DEBUG_DISASSEMBLE_F 0x000008 +#define DEBUG_BREAK_F 0x000010 +#define DEBUG_SVC_F 0x000020 +#define DEBUG_FS_F 0x000080 +#define DEBUG_PROC_F 0x000100 +#define DEBUG_SYSINT_F 0x000200 /* bios system interrupts. */ +#define DEBUG_TRACECALL_F 0x000400 +#define DEBUG_INSTRUMENT_F 0x000800 +#define DEBUG_MEM_TRACE_F 0x001000 +#define DEBUG_IO_TRACE_F 0x002000 +#define DEBUG_TRACECALL_REGS_F 0x004000 +#define DEBUG_DECODE_NOPRINT_F 0x008000 +#define DEBUG_SAVE_IP_CS_F 0x010000 +#define DEBUG_SYS_F (DEBUG_SVC_F|DEBUG_FS_F|DEBUG_PROC_F) + +void X86EMU_trace_regs(void); +void X86EMU_trace_xregs(void); +void X86EMU_dump_memory(u16 seg, u16 off, u32 amt); +int X86EMU_trace_on(void); +int X86EMU_trace_off(void); + +#ifdef __cplusplus +} /* End of "C" linkage for C++ */ +#endif + +#endif /* __X86EMU_X86EMU_H */ diff --git a/include/xf86int10.h b/include/xf86int10.h new file mode 100644 index 0000000..9c131dd --- /dev/null +++ b/include/xf86int10.h @@ -0,0 +1,213 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/int10/xf86int10.h,v 1.23 2002/04/04 14:05:51 eich Exp $ */ + +/* + * XFree86 int10 module + * execute BIOS int 10h calls in x86 real mode environment + * Copyright 1999 Egbert Eich + */ + +#ifndef _XF86INT10_H +#define _XF86INT10_H + + +#define SEG_ADDR(x) (((x) >> 4) & 0x00F000) +#define SEG_OFF(x) ((x) & 0x0FFFF) + +#define SET_BIOS_SCRATCH 0x1 +#define RESTORE_BIOS_SCRATCH 0x2 + +#define CARD8 unsigned char +#define CARD16 unsigned short +#define CARD32 unsigned long +#define pointer void * +#define IOADDRESS void * +#define Bool int + +#define X86_TF_MASK 0x00000100 +#define X86_IF_MASK 0x00000200 +#define X86_IOPL_MASK 0x00003000 +#define X86_NT_MASK 0x00004000 +#define X86_VM_MASK 0x00020000 +#define X86_AC_MASK 0x00040000 +#define X86_VIF_MASK 0x00080000 /* virtual interrupt flag */ +#define X86_VIP_MASK 0x00100000 /* virtual interrupt pending */ +#define X86_ID_MASK 0x00200000 + + +/* int10 info structure */ +typedef struct { + int entityIndex; + int scrnIndex; + pointer cpuRegs; + CARD16 BIOSseg; + CARD16 inb40time; + char * BIOSScratch; + int Flags; + pointer private; + struct _int10Mem* mem; + int num; + int ax; + int bx; + int cx; + int dx; + int si; + int di; + int es; + int bp; + int flags; + int stackseg; + //PCITAG Tag; + IOADDRESS ioBase; +} xf86Int10InfoRec, *xf86Int10InfoPtr; + +typedef struct _int10Mem { + CARD8(*rb)(xf86Int10InfoPtr, int); + CARD16(*rw)(xf86Int10InfoPtr, int); + CARD32(*rl)(xf86Int10InfoPtr, int); + void(*wb)(xf86Int10InfoPtr, int, CARD8); + void(*ww)(xf86Int10InfoPtr, int, CARD16); + void(*wl)(xf86Int10InfoPtr, int, CARD32); +} int10MemRec, *int10MemPtr; + +typedef struct { + CARD8 save_msr; + CARD8 save_pos102; + CARD8 save_vse; + CARD8 save_46e8; +} legacyVGARec, *legacyVGAPtr; + +//typedef struct { + //BusType bus; + //union { + //struct { + //int bus; + //int dev; + //int func; + ////} pci; + //int legacy; + //} location; +////} xf86int10BiosLocation, *xf86int10BiosLocationPtr; + +/* OS dependent functions */ +xf86Int10InfoPtr xf86InitInt10(int entityIndex); +xf86Int10InfoPtr xf86ExtendedInitInt10(int entityIndex, int Flags); +void xf86FreeInt10(xf86Int10InfoPtr pInt); +void *xf86Int10AllocPages(xf86Int10InfoPtr pInt, int num, int *off); +void xf86Int10FreePages(xf86Int10InfoPtr pInt, void *pbase, int num); +pointer xf86int10Addr(xf86Int10InfoPtr pInt, CARD32 addr); + +/* x86 executor related functions */ +void xf86ExecX86int10(xf86Int10InfoPtr pInt); + +#ifdef _INT10_PRIVATE + +#define I_S_DEFAULT_INT_VECT 0xFF065 +#define SYS_SIZE 0x100000 +#define SYS_BIOS 0xF0000 +#if 1 +#define BIOS_SIZE 0x10000 +#else /* a bug in DGUX requires this - let's try it */ +#define BIOS_SIZE (0x10000 - 1) +#endif +#define LOW_PAGE_SIZE 0x600 +#define V_RAM 0xA0000 +#define VRAM_SIZE 0x20000 +#define V_BIOS_SIZE 0x10000 +#define V_BIOS 0xC0000 +#define BIOS_SCRATCH_OFF 0x449 +#define BIOS_SCRATCH_END 0x466 +#define BIOS_SCRATCH_LEN (BIOS_SCRATCH_END - BIOS_SCRATCH_OFF + 1) +#define HIGH_MEM V_BIOS +#define HIGH_MEM_SIZE (SYS_BIOS - HIGH_MEM) +#define SEG_ADR(type, seg, reg) type((seg << 4) + (X86_##reg)) +#define SEG_EADR(type, seg, reg) type((seg << 4) + (X86_E##reg)) + +#define X86_TF_MASK 0x00000100 +#define X86_IF_MASK 0x00000200 +#define X86_IOPL_MASK 0x00003000 +#define X86_NT_MASK 0x00004000 +#define X86_VM_MASK 0x00020000 +#define X86_AC_MASK 0x00040000 +#define X86_VIF_MASK 0x00080000 /* virtual interrupt flag */ +#define X86_VIP_MASK 0x00100000 /* virtual interrupt pending */ +#define X86_ID_MASK 0x00200000 + +#define MEM_RB(name, addr) (*name->mem->rb)(name, addr) +#define MEM_RW(name, addr) (*name->mem->rw)(name, addr) +#define MEM_RL(name, addr) (*name->mem->rl)(name, addr) +#define MEM_WB(name, addr, val) (*name->mem->wb)(name, addr, val) +#define MEM_WW(addr, val) wrw(addr, val) +#define MEM_WL(name, addr, val) (*name->mem->wl)(name, addr, val) + +/* OS dependent functions */ +Bool MapCurrentInt10(xf86Int10InfoPtr pInt); +/* x86 executor related functions */ +Bool xf86Int10ExecSetup(xf86Int10InfoPtr pInt); + +/* int.c */ +extern xf86Int10InfoPtr Int10Current; +int int_handler(xf86Int10InfoPtr pInt); + +/* helper_exec.c */ +int setup_int(xf86Int10InfoPtr pInt); +void finish_int(xf86Int10InfoPtr, int sig); +CARD32 getIntVect(xf86Int10InfoPtr pInt, int num); +void pushw(CARD16 val); +int run_bios_int(int num, xf86Int10InfoPtr pInt); +void dump_code(xf86Int10InfoPtr pInt); +void dump_registers(xf86Int10InfoPtr pInt); +void stack_trace(xf86Int10InfoPtr pInt); +xf86Int10InfoPtr getInt10Rec(int entityIndex); +CARD8 bios_checksum(CARD8 *start, int size); +void LockLegacyVGA(xf86Int10InfoPtr pInt, legacyVGAPtr vga); +void UnlockLegacyVGA(xf86Int10InfoPtr pInt, legacyVGAPtr vga); +#if defined (_PC) +void xf86Int10SaveRestoreBIOSVars(xf86Int10InfoPtr pInt, Bool save); +#endif +int port_rep_inb(xf86Int10InfoPtr pInt, + CARD16 port, CARD32 base, int d_f, CARD32 count); +int port_rep_inw(xf86Int10InfoPtr pInt, + CARD16 port, CARD32 base, int d_f, CARD32 count); +int port_rep_inl(xf86Int10InfoPtr pInt, + CARD16 port, CARD32 base, int d_f, CARD32 count); +int port_rep_outb(xf86Int10InfoPtr pInt, + CARD16 port, CARD32 base, int d_f, CARD32 count); +int port_rep_outw(xf86Int10InfoPtr pInt, + CARD16 port, CARD32 base, int d_f, CARD32 count); +int port_rep_outl(xf86Int10InfoPtr pInt, + CARD16 port, CARD32 base, int d_f, CARD32 count); + +CARD8 x_inb(CARD16 port); +CARD16 x_inw(CARD16 port); +void x_outb(CARD16 port, CARD8 val); +void x_outw(CARD16 port, CARD16 val); +CARD32 x_inl(CARD16 port); +void x_outl(CARD16 port, CARD32 val); + +CARD8 Mem_rb(CARD32 addr); +CARD16 Mem_rw(CARD32 addr); +CARD32 Mem_rl(CARD32 addr); +void Mem_wb(CARD32 addr, CARD8 val); +void Mem_ww(CARD32 addr, CARD16 val); +void Mem_wl(CARD32 addr, CARD32 val); + +/* helper_mem.c */ +void setup_int_vect(xf86Int10InfoPtr pInt); +int setup_system_bios(void *base_addr); +void reset_int_vect(xf86Int10InfoPtr pInt); +void set_return_trap(xf86Int10InfoPtr pInt); +//void * xf86HandleInt10Options(ScrnInfoPtr pScrn, int entityIndex); +Bool int10skip(void* options); +Bool int10_check_bios(int scrnIndex, int codeSeg, unsigned char* vbiosMem); +Bool initPrimary(void* options); +//void xf86int10ParseBiosLocation(void* options, + //xf86int10BiosLocationPtr bios); +#ifdef DEBUG +void dprint(unsigned long start, unsigned long size); +#endif + +/* pci.c */ +int mapPciRom(char *filename, unsigned char *address); + +#endif /* _INT10_PRIVATE */ +#endif /* _XF86INT10_H */ diff --git a/include/xf86x86emu.h b/include/xf86x86emu.h new file mode 100644 index 0000000..c4d86b8 --- /dev/null +++ b/include/xf86x86emu.h @@ -0,0 +1,51 @@ +/* $XFree86: xc/programs/Xserver/hw/xfree86/int10/xf86x86emu.h,v 1.1 2000/01/23 04:44:35 dawes Exp $ */ +/* + * XFree86 int10 module + * execute BIOS int 10h calls in x86 real mode environment + * Copyright 1999 Egbert Eich + */ +#ifndef XF86X86EMU_H_ +#define XF86X86EMU_H_ +#include "x86emu.h" + +#define M _X86EMU_env + +#define X86_EAX M.x86.R_EAX +#define X86_EBX M.x86.R_EBX +#define X86_ECX M.x86.R_ECX +#define X86_EDX M.x86.R_EDX +#define X86_ESI M.x86.R_ESI +#define X86_EDI M.x86.R_EDI +#define X86_EBP M.x86.R_EBP +#define X86_EIP M.x86.R_EIP +#define X86_ESP M.x86.R_ESP +#define X86_EFLAGS M.x86.R_EFLG + +#define X86_FLAGS M.x86.R_FLG +#define X86_AX M.x86.R_AX +#define X86_BX M.x86.R_BX +#define X86_CX M.x86.R_CX +#define X86_DX M.x86.R_DX +#define X86_SI M.x86.R_SI +#define X86_DI M.x86.R_DI +#define X86_BP M.x86.R_BP +#define X86_IP M.x86.R_IP +#define X86_SP M.x86.R_SP +#define X86_CS M.x86.R_CS +#define X86_DS M.x86.R_DS +#define X86_ES M.x86.R_ES +#define X86_SS M.x86.R_SS +#define X86_FS M.x86.R_FS +#define X86_GS M.x86.R_GS + +#define X86_AL M.x86.R_AL +#define X86_BL M.x86.R_BL +#define X86_CL M.x86.R_CL +#define X86_DL M.x86.R_DL + +#define X86_AH M.x86.R_AH +#define X86_BH M.x86.R_BH +#define X86_CH M.x86.R_CH +#define X86_DH M.x86.R_DH + +#endif diff --git a/vbetool.1 b/vbetool.1 new file mode 100644 index 0000000..cf15d88 --- /dev/null +++ b/vbetool.1 @@ -0,0 +1,95 @@ +.TH VBETOOL "1" "31 December 2004" "vbetool 0.2" "User Commands" +.SH NAME +vbetool - run real-mode video BIOS code to alter hardware state + +.SH SYNOPSIS +.B "vbetool [[vbestate save|restore]|[vbemode set|get]|[vgamode]|[dpms on|off|standby|suspend|reduced]|[post [romfile]]|[vgastate on|off]|[vbefp panelid|panelsize|getbrightness|setbrightness|invert]]" + +.SH DESCRIPTION +.B vbetool +uses lrmi in order to run code from the video BIOS. Currently, +it is able to alter DPMS states, save/restore video card state and +attempt to initialize the video card from scratch. + +.SH OPTIONS +.B vbetool +takes the following options: +.IP "vbestate" +.B vbetool +will use the VESA 0x4f0f extensions to save or restore hardware +state. This will be sent to or read from stdin. This information is +highly hardware specific - do not attempt to restore state saved from +a different machine. This command will not work unless you are at a +text console, as it interferes badly with X. + +.IP "dpms" +.B vbetool +will use the VESA 0x4f10 extensions to alter the power management +state of your screen. "On", "off", "standby", "suspend" and "reduced" +are acceptable further options and determine which state will be +activated. + +.IP "vbemode" +.B vbetool +will get or set the current VESA mode. "get" will return the current +mode number on stdout - "set" will set the mode to the next argument. + +.IP "vgamode" +.B vbetool +will set the legacy VGA mode to the following numeric argument. + +.IP "post" +.B vbetool +will attempt to run BIOS code located at c000:0003. This is the code +run by the system BIOS at boot in order to intialise the video +hardware. Note that on some machines (especially laptops), not all of +this code is present after system boot - as a result, executing this +command may result in undefined behaviour. This command must be run +from a text console, as it will otherwise interfere with the operation +of X. This command takes an optional argument which is the location of +a file containing a ROM image. If provided, this image will be mapped +to the c000 segment and used instead of the system's video BIOS. + +.IP "vgastate" +.B vbetool +will enable or disable the current video card. On most hardware, disabling +will cause the hardware to stop responding until it is reenabled. You +probably don't want to do this if you're using a framebuffer. + +.IP "vbefp" +.B vbetool +will execute a VESA flat panel interface call. +.IP +panelid will provide information about the panel +.IP +panelsize will provide the size of the panel +.IP +getbrightness will provide the current screen brightness as an integer +.IP +setbrightness accepts an integer as an argument and will set the screen brightness to that +.IP +invert will invert the colours of the screen + +.SH BUGS +Switching dpms modes may interact badly with X on some systems. +.PP +The vbestate command may behave in strange ways. +.PP +The post command may result in the execution of arbitrary code that +happens to be lying around in the area where chunks of your video BIOS +used to be. +.PP +The VESA specification does not require that "vbemode get" provides +the correct mode if the current mode was set via some means other than +the VESA BIOS extensions. +.PP +The VESA flat panel interface ceased development at the proposal stage. +panelid and panelsize will work on many machines, but the other arguments are +unlikely to be implemented on available hardware. + +.SH AUTHOR +vbetool was written by Matthew Garrett <mjg59@srcf.ucam.org>, based on +code from read-edid by John Fremlin <john@fremlin.de>, LRMI +(http://sourceforge.net/projects/lrmi/) and XFree +(http://www.xfree86.org). It is released under the terms of the GNU +General Public License. diff --git a/vbetool.c b/vbetool.c new file mode 100644 index 0000000..f6eee59 --- /dev/null +++ b/vbetool.c @@ -0,0 +1,572 @@ +/* +Run video BIOS code for various purposes + +Copyright Matthew Garrett <mjg59@srcf.ucam.org>, heavily based on +vbetest.c from the lrmi package and read-edid.c by John Fremlin + +This program is released under the terms of the GNU General Public License, +version 2 +*/ + +#include <pci/pci.h> +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/io.h> +#include <sys/kd.h> +#include <sys/stat.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/mman.h> + +#include <libx86.h> +#include "vbetool.h" + +#define access_ptr_register(reg_frame,reg) (reg_frame -> reg) +#define access_seg_register(reg_frame,es) reg_frame.es +#define real_mode_int(interrupt,reg_frame_ptr) !LRMI_int(interrupt,reg_frame_ptr) + +#define DPMS_STATE_ON 0x0000 +#define DPMS_STATE_STANDBY 0x0100 +#define DPMS_STATE_SUSPEND 0x0200 +#define DPMS_STATE_OFF 0x0400 +#define DPMS_STATE_LOW 0x0800 + +static struct pci_access *pacc; + +int vbetool_init (void) { + if (!LRMI_init()) { + fprintf(stderr, "Failed to initialise LRMI (Linux Real-Mode Interface).\n"); + exit(1); + } + + iopl(3); + + pacc = pci_alloc(); + pacc->numeric_ids = 1; + pci_init(pacc); + return 0; +} + +#ifndef S2RAM +int main(int argc, char *argv[]) +{ + /* Don't bother checking for privilege if they only want usage() */ + if (argc < 2) + goto usage; + + vbetool_init(); + + if (!strcmp(argv[1], "vbestate")) { + /* VBE save/restore tends to break when done underneath X */ + int err = check_console(); + + if (err) { + return err; + } + + if (!strcmp(argv[2], "save")) { + save_state(); + } else if (!strcmp(argv[2], "restore")) { + restore_state(); + } else { + goto usage; + } + } else if (!strcmp(argv[1], "dpms")) { + if (!strcmp(argv[2], "on")) { + return do_blank(DPMS_STATE_ON); + } else if (!strcmp(argv[2], "suspend")) { + return do_blank(DPMS_STATE_SUSPEND); + } else if (!strcmp(argv[2], "standby")) { + return do_blank(DPMS_STATE_STANDBY); + } else if (!strcmp(argv[2], "off")) { + return do_blank(DPMS_STATE_OFF); + } else if (!strcmp(argv[2], "reduced")) { + return do_blank(DPMS_STATE_LOW); + } else { + goto usage; + } + } else if (!strcmp(argv[1], "vbemode")) { + if (!strcmp(argv[2], "set")) { + return do_set_mode(atoi(argv[3]),0); + } else if (!strcmp(argv[2], "get")) { + return do_get_mode(); + } else { + goto usage; + } + } else if (!strcmp(argv[1], "vgamode")) { + if (!strcmp(argv[2], "set")) { + return do_set_mode(atoi(argv[3]),1); + } else { + return do_set_mode(atoi(argv[2]),1); + } + } else if (!strcmp(argv[1], "post")) { + /* Again, we don't really want to do this while X is in + control */ + int err = check_console(); + + if (err) { + return err; + } + + if (argc >= 3) { + void *rc; + int romfd = open (argv[2], O_RDWR); + + munmap(0xc0000, 64*1024); + rc = mmap(0xc0000, 64*1024, + PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_FIXED|MAP_PRIVATE, romfd, 0); + } + + return do_post(); + } else if (!strcmp(argv[1], "vgastate")) { + if (!strcmp(argv[2], "on")) { + return enable_vga(); + } else { + return disable_vga(); + } + } else if (!strcmp(argv[1], "vbefp")) { + if (!strcmp(argv[2], "id") || !strcmp(argv[2], "panelid")) { + return do_get_panel_id(0); + } else if (!strcmp(argv[2], "panelsize")) { + return do_get_panel_id(1); + } else if (!strcmp(argv[2], "getbrightness")) { + return do_get_panel_brightness(); + } else if (!strcmp(argv[2], "setbrightness")) { + return do_set_panel_brightness(atoi(argv[3])); + } else if (!strcmp(argv[2], "invert")) { + return do_invert_panel(); + } else { + return 1; + } + } else { + usage: + fprintf(stderr, + "%s: Usage %s [[vbestate save|restore]|[vbemode set|get]|[vgamode]|[dpms on|off|standby|suspend|reduced]|[post [romfile]]|[vgastate on|off]|[vbefp panelid|panelsize|getbrightness|setbrightness|invert]]\n", + argv[0], argv[0]); + return 1; + } + + return 0; +} +#endif + +int do_vbe_service(unsigned int AX, unsigned int BX, reg_frame * regs) +{ + const unsigned interrupt = 0x10; + unsigned function_sup; + unsigned success; + regs->ds = 0x0040; + + access_ptr_register(regs, eax) = AX; + access_ptr_register(regs, ebx) = BX; + + if (real_mode_int(interrupt, regs)) { + fprintf(stderr, + "Error: something went wrong performing real mode interrupt\n"); + return -1; + } + + AX = access_ptr_register(regs, eax); + + function_sup = ((AX & 0xff) == 0x4f); + success = ((AX & 0xff00) == 0); + + if (!success) { + fprintf(stderr, "Real mode call failed\n"); + return -2; + } + + if (!function_sup) { + fprintf(stderr, "Function not supported\n"); + return -3; + } + + return access_ptr_register(regs, ebx); +} + +int do_real_post(unsigned pci_device) +{ + int error = 0; + struct LRMI_regs r; + memset(&r, 0, sizeof(r)); + + /* Several machines seem to want the device that they're POSTing in + here */ + r.eax = pci_device; + + /* 0xc000 is the video option ROM. The init code for each + option ROM is at 0x0003 - so jump to c000:0003 and start running */ + r.cs = 0xc000; + r.ip = 0x0003; + + /* This is all heavily cargo culted but seems to work */ + r.edx = 0x80; + r.ds = 0x0040; + + if (!LRMI_call(&r)) { + fprintf(stderr, + "Error: something went wrong performing real mode call\n"); + error = 1; + } + + return error; +} + +int do_post(void) +{ + struct pci_dev *p; + unsigned int c; + unsigned int pci_id; + int error; + + pci_scan_bus(pacc); + + for (p = pacc->devices; p; p = p->next) { + c = pci_read_word(p, PCI_CLASS_DEVICE); + if (c == 0x300) { + pci_id = + (p->bus << 8) + (p->dev << 3) + + (p->func & 0x7); + error = do_real_post(pci_id); + if (error != 0) { + return error; + } + } + } + return 0; +} + +void restore_state_from(char *data) +{ + struct LRMI_regs r; + + /* VGA BIOS mode 3 is text mode */ + do_set_mode(3,1); + + memset(&r, 0, sizeof(r)); + + r.eax = 0x4f04; + r.ecx = 0xf; /* all states */ + r.edx = 2; /* restore state */ + r.es = (unsigned int) (data - LRMI_base_addr()) >> 4; + r.ebx = (unsigned int) (data - LRMI_base_addr()) & 0xf; + r.ds = 0x0040; + + if (!LRMI_int(0x10, &r)) { + fprintf(stderr, + "Can't restore video state (vm86 failure)\n"); + } else if ((r.eax & 0xffff) != 0x4f) { + fprintf(stderr, "Restore video state failed\n"); + } + + LRMI_free_real(data); + + ioctl(0, KDSETMODE, KD_TEXT); + +} + +void restore_state(void) +{ + + char *data = NULL; + char tmpbuffer[524288]; + int i, length = 0; + + /* We really, really don't want to fail to read the entire set */ + while ((i = read(0, tmpbuffer + length, sizeof(tmpbuffer)-length))) { + if (i == -1) { + if (errno != EAGAIN && errno != EINTR) { + perror("Failed to read state - "); + return; + } + } else { + length += i; + } + } + + data = LRMI_alloc_real(length); + memcpy(data, tmpbuffer, length); + + restore_state_from(data); +} + +char *__save_state(int *psize) +{ + struct LRMI_regs r; + char *buffer; + unsigned int size; + + memset(&r, 0, sizeof(r)); + + r.eax = 0x4f04; + r.ecx = 0xf; /* all states */ + r.edx = 0; /* get buffer size */ + r.ds = 0x0040; + + if (!LRMI_int(0x10, &r)) { + fprintf(stderr, + "Can't get video state buffer size (vm86 failure)\n"); + } + + if ((r.eax & 0xffff) != 0x4f) { + fprintf(stderr, "Get video state buffer size failed\n"); + } + + *psize = size = (r.ebx & 0xffff) * 64; + + buffer = LRMI_alloc_real(size); + + if (buffer == NULL) { + fprintf(stderr, "Can't allocate video state buffer\n"); + return NULL; + } + + memset(&r, 0, sizeof(r)); + + fprintf(stderr, "Allocated buffer at %p (base is 0x%x)\n", buffer, + LRMI_base_addr()); + + r.eax = 0x4f04; + r.ecx = 0xf; /* all states */ + r.edx = 1; /* save state */ + + r.es = (unsigned int) (buffer - LRMI_base_addr()) >> 4; + r.ebx = (unsigned int) (buffer - LRMI_base_addr()) & 0xf; + r.ds = 0x0040; + + fprintf(stderr, "ES: 0x%04X EBX: 0x%04X\n", r.es, r.ebx); + + if (!LRMI_int(0x10, &r)) { + fprintf(stderr, "Can't save video state (vm86 failure)\n"); + } + + if ((r.eax & 0xffff) != 0x4f) { + fprintf(stderr, "Save video state failed\n"); + } + return buffer; +} + +void save_state(void) +{ + int size; + char *buffer = __save_state(&size); + ssize_t num_written; + + if (buffer) + /* FIXME: should retry on short write); */ + num_written = write(1, buffer, size); +} + +int do_blank(int state) +{ + reg_frame regs; + int error; + + memset(®s, 0, sizeof(regs)); + error = do_vbe_service(0x4f10, state |= 0x01, ®s); + if (error<0) { + return error; + } + return 0; +} + +int do_set_mode (int mode, int vga) { + reg_frame regs; + int error; + + memset(®s, 0, sizeof(regs)); + + if (vga) { + error = do_vbe_service(mode, 0, ®s); + } else { + error = do_vbe_service(0x4f02, mode, ®s); + } + + if (error<0) { + return error; + } + + return 0; +} + +int do_get_panel_brightness() { + reg_frame regs; + int error; + + memset(®s, 0, sizeof(regs)); + + error = do_vbe_service(0x4f11, 0x05, ®s); + + if (error<0) { + return error; + } + + printf("%d\n",regs.ecx); + + return 0; +} + +int do_invert_panel() { + reg_frame regs; + int error; + + memset(®s, 0, sizeof(regs)); + + error = do_vbe_service(0x4f11, 0x02, ®s); + + if (error<0) { + return error; + } + + if ((regs.ebx & 0xff) == 0) + regs.ecx = 3; + else + regs.ecx = 0; + + error = do_vbe_service(0x4f11, 0x0102, ®s); + + if (error<0) { + return error; + } + + return 0; +} + +int do_set_panel_brightness(int brightness) { + reg_frame regs; + int error; + + memset(®s, 0, sizeof(regs)); + + regs.ecx = brightness; + + error = do_vbe_service(0x4f11, 0x0105, ®s); + + if (error<0) { + return error; + } + + printf("%d\n",regs.ecx); + + return 0; +} + +int do_get_mode() { + reg_frame regs; + int error; + + memset(®s, 0, sizeof(regs)); + error = do_vbe_service(0x4f03, 0, ®s); + + if (error<0) { + return error; + } + + printf("%d\n",error); + return 0; +} + +int check_console() +{ + struct stat stat; + + return 0; + + if (fstat(0, &stat) != 0) { + fprintf(stderr, "Can't stat() stdin\n"); + return 10; + } + + if ((stat.st_rdev & 0xff00) != 0x400 || (stat.st_rdev & 0xff) > 63) { + fprintf(stderr, "To perform this operation, " + "this program must be run from the console\n"); + return 11; + } + + ioctl(0, KDSETMODE, KD_GRAPHICS); + return 0; +} + +int enable_vga() { + outb(0x03 | inb(0x3CC), 0x3C2); + outb(0x01 | inb(0x3C3), 0x3C3); + outb(0x08 | inb(0x46e8), 0x46e8); + outb(0x01 | inb(0x102), 0x102); + return 0; +} + +int disable_vga() { + outb(~0x03 & inb(0x3CC), 0x3C2); + outb(~0x01 & inb(0x3C3), 0x3C3); + outb(~0x08 & inb(0x46e8), 0x46e8); + outb(~0x01 & inb(0x102), 0x102); + return 0; +} + +/* Based on xserver-xorg-driver-i810/src/i830_driver.c */ +struct panel_id { + int hsize:16, vsize:16; + int fptype:16; + int redbpp:8, greenbpp:8, bluebpp:8, reservedbpp:8; + int rsvdoffscrnmemsize:32, rsvdoffscrnmemptr:32; + char reserved[14]; +} __attribute__((packed)); + +int do_get_panel_id(int just_dimensions) +{ + reg_frame r = { + .eax = 0x4f11, + .ebx = 0x0001 + }; + struct panel_id *id = LRMI_alloc_real(sizeof(struct panel_id)); + r.es = (unsigned short)(((int)(id-LRMI_base_addr()) >> 4) & 0xffff); + r.edi = (unsigned long)(id-LRMI_base_addr()) & 0xf; + + if(sizeof(struct panel_id) != 32) + return fprintf(stderr, "oops: panel_id, sizeof struct panel_id != 32, it's %ld...\n", sizeof(struct panel_id)), 7; + + if(real_mode_int(0x10, &r)) + return fprintf(stderr, "Can't get panel id (vm86 failure)\n"), 8; + + if((r.eax & 0xff) != 0x4f) + return fprintf(stderr, "Panel id function not supported\n"), 9; + + if(r.eax & 0xff00) + { + if((r.eax & 0xff00) == 0x100) + fprintf(stderr, "Panel id read failed\n"); + else + fprintf(stderr, "Panel id function not successful\n"); + return 10; + } + + if(!just_dimensions) + printf("size:\t%d %d\n" + "type:\t%d\n" + "bpp:\t%d %d %d %d\n", + id->hsize, id->vsize, + id->fptype, + id->redbpp, id->greenbpp, id->bluebpp, id->reservedbpp); + else + printf("%dx%d\n", id->hsize, id->vsize); + +#if 0 + + /* Don't have a use for these and they don't seem to be documented. + * 320 appears to be 320kB of mapped memory and the following + * pointer is 0x1ffb8000 which is kernel mapping + 0xb8000 offset. + */ + printf("ram:\t%dkB\n" + "offset:\t%p\n", + id->rsvdoffscrnmemsize, + (void *)id->rsvdoffscrnmemptr); +#endif + + return 0; +} diff --git a/vbetool.h b/vbetool.h new file mode 100644 index 0000000..cc19a5a --- /dev/null +++ b/vbetool.h @@ -0,0 +1,19 @@ +typedef struct LRMI_regs reg_frame; + +int do_vbe_service(unsigned int AX, unsigned int BX, reg_frame *regs); +int do_real_post(unsigned pci_device); +int do_blank(int state); +int do_set_mode (int mode, int vga); +int do_get_mode(void); +int do_get_panel_brightness(void); +int do_set_panel_brightness(int brightness); +int do_invert_panel(void); +int do_post(void); +void restore_state(void); +void save_state(void); +void text_mode(void); +int check_console(void); +int enable_vga(void); +int disable_vga(void); +int do_get_panel_id(); + diff --git a/x86-common.c b/x86-common.c new file mode 100644 index 0000000..496179a --- /dev/null +++ b/x86-common.c @@ -0,0 +1,249 @@ +/* +Linux Real Mode Interface - A library of DPMI-like functions for Linux. + +Copyright (C) 1998 by Josh Vanderhoof + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL JOSH VANDERHOOF BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <unistd.h> +#include <fcntl.h> + +#include "include/lrmi.h" + +#define REAL_MEM_BASE ((void *)0x10000) +#define REAL_MEM_SIZE 0x90000 +#define REAL_MEM_BLOCKS 0x100 + +struct mem_block { + unsigned int size : 20; + unsigned int free : 1; +}; + +static struct { + int ready; + int count; + struct mem_block blocks[REAL_MEM_BLOCKS]; +} mem_info = { 0 }; + +static int +real_mem_init(void) +{ + void *m; + int fd_zero; + + if (mem_info.ready) + return 1; + + fd_zero = open("/dev/zero", O_RDWR); + if (fd_zero == -1) { + perror("open /dev/zero"); + return 0; + } + + m = mmap((void *)REAL_MEM_BASE, REAL_MEM_SIZE, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_FIXED | MAP_SHARED, fd_zero, 0); + + if (m == (void *)-1) { + perror("mmap /dev/zero"); + close(fd_zero); + return 0; + } + + close(fd_zero); + + mem_info.ready = 1; + mem_info.count = 1; + mem_info.blocks[0].size = REAL_MEM_SIZE; + mem_info.blocks[0].free = 1; + + return 1; +} + +static void +real_mem_deinit(void) +{ + if (mem_info.ready) { + munmap((void *)REAL_MEM_BASE, REAL_MEM_SIZE); + mem_info.ready = 0; + } +} + + +static void +insert_block(int i) +{ + memmove( + mem_info.blocks + i + 1, + mem_info.blocks + i, + (mem_info.count - i) * sizeof(struct mem_block)); + + mem_info.count++; +} + +static void +delete_block(int i) +{ + mem_info.count--; + + memmove( + mem_info.blocks + i, + mem_info.blocks + i + 1, + (mem_info.count - i) * sizeof(struct mem_block)); +} + +void * +LRMI_alloc_real(int size) +{ + int i; + char *r = (char *)REAL_MEM_BASE; + + if (!mem_info.ready) + return NULL; + + if (mem_info.count == REAL_MEM_BLOCKS) + return NULL; + + size = (size + 15) & ~15; + + for (i = 0; i < mem_info.count; i++) { + if (mem_info.blocks[i].free && size < mem_info.blocks[i].size) { + insert_block(i); + + mem_info.blocks[i].size = size; + mem_info.blocks[i].free = 0; + mem_info.blocks[i + 1].size -= size; + + return (void *)r; + } + + r += mem_info.blocks[i].size; + } + + return NULL; +} + + +void +LRMI_free_real(void *m) +{ + int i; + char *r = (char *)REAL_MEM_BASE; + + if (!mem_info.ready) + return; + + i = 0; + while (m != (void *)r) { + r += mem_info.blocks[i].size; + i++; + if (i == mem_info.count) + return; + } + + mem_info.blocks[i].free = 1; + + if (i + 1 < mem_info.count && mem_info.blocks[i + 1].free) { + mem_info.blocks[i].size += mem_info.blocks[i + 1].size; + delete_block(i + 1); + } + + if (i - 1 >= 0 && mem_info.blocks[i - 1].free) { + mem_info.blocks[i - 1].size += mem_info.blocks[i].size; + delete_block(i); + } +} + +#define DEFAULT_STACK_SIZE 0x1000 + +static inline void +set_bit(unsigned int bit, void *array) +{ + unsigned char *a = array; + + a[bit / 8] |= (1 << (bit % 8)); +} + +static inline unsigned int +get_int_seg(int i) +{ + return *(unsigned short *)(i * 4 + 2); +} + + +static inline unsigned int +get_int_off(int i) +{ + return *(unsigned short *)(i * 4); +} + +int LRMI_common_init(void) +{ + void *m; + int fd_mem; + + if (!real_mem_init()) + return 0; + + /* + Map the Interrupt Vectors (0x0 - 0x400) + BIOS data (0x400 - 0x502) + and the ROM (0xa0000 - 0x100000) + */ + fd_mem = open("/dev/mem", O_RDWR); + + if (fd_mem == -1) { + real_mem_deinit(); + perror("open /dev/mem"); + return 0; + } + + m = mmap((void *)0, 0x502, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_FIXED | MAP_SHARED, fd_mem, 0); + + if (m == (void *)-1) { + close(fd_mem); + real_mem_deinit(); + perror("mmap /dev/mem"); + return 0; + } + + m = mmap((void *)0xa0000, 0x100000 - 0xa0000, + PROT_READ | PROT_WRITE, + MAP_FIXED | MAP_SHARED, fd_mem, 0xa0000); + + if (m == (void *)-1) { + munmap((void *)0, 0x502); + close(fd_mem); + real_mem_deinit(); + perror("mmap /dev/mem"); + return 0; + } + + close(fd_mem); + + return 1; +} diff --git a/x86-common.h b/x86-common.h new file mode 100644 index 0000000..851210e --- /dev/null +++ b/x86-common.h @@ -0,0 +1,43 @@ +/* +Common routines for x86emu/lrmi interfaces. Taken from lrmi.c. + +Copyright (C) 1998 by Josh Vanderhoof +Copyright (C) 2005 by Jonathan McDowell <noodles@earth.li> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL JOSH VANDERHOOF BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <unistd.h> +#include <fcntl.h> + +#include "include/lrmi.h" + +#define REAL_MEM_BASE ((void *)0x10000) +#define REAL_MEM_SIZE 0x40000 +#define REAL_MEM_BLOCKS 0x100 + +void *LRMI_alloc_real(int size); +void LRMI_free_real(void *m); +int LRMI_common_init(void); |