Author: stepan
Date: 2009-05-29 15:09:57 +0200 (Fri, 29 May 2009)
New Revision: 1167

Added:
   coreboot-v3/util/x86emu/x86.c
   coreboot-v3/util/x86emu/x86_asm.S
   coreboot-v3/util/x86emu/x86_interrupts.c
Modified:
   coreboot-v3/util/x86emu/Config.lb
   coreboot-v3/util/x86emu/Makefile
   coreboot-v3/util/x86emu/biosemu.c
   coreboot-v3/util/x86emu/vm86.c
   coreboot-v3/util/x86emu/vm86_gdt.c
Log:
Part II - svn externals need to be committed separately

drop most of the crappy vm86 code and replace it with a rewritten
version that has all assembler in a .S file and all C code in a .c
file. Also, remove requirement to move around between GDTs.

This version includes the suggestions from Peter to clean up CR0 manipulation
and to guard critical code paths by cli/sti. Tested and working on my hardware.

Signed-off-by: Stefan Reinauer <[email protected]>
Acked-by: Peter Stuge <[email protected]>



Modified: coreboot-v3/util/x86emu/Config.lb
===================================================================
--- coreboot-v3/util/x86emu/Config.lb   2009-05-09 23:36:20 UTC (rev 1166)
+++ coreboot-v3/util/x86emu/Config.lb   2009-05-29 13:09:57 UTC (rev 1167)
@@ -6,8 +6,9 @@
   dir x86emu
 else
   if CONFIG_PCI_OPTION_ROM_RUN_VM86
-    object vm86.o
-    object vm86_gdt.o
+    object x86.o
+    object x86_interrupts.o
+    object x86_asm.S
   else
     object biosemu.o
     dir pcbios

Modified: coreboot-v3/util/x86emu/Makefile
===================================================================
--- coreboot-v3/util/x86emu/Makefile    2009-05-09 23:36:20 UTC (rev 1166)
+++ coreboot-v3/util/x86emu/Makefile    2009-05-29 13:09:57 UTC (rev 1167)
@@ -37,7 +37,7 @@
 #TODO: remove these, these are .h files from slof, to make the merge easier...
 X86EMU_INCLUDE += -I $(src)/util/x86emu/yabel/compat
 endif
-VM86_SRC    = vm86.c vm86_gdt.c 
+VM86_SRC    = x86.c x86_asm.S
 
 ifeq ($(CONFIG_PCI_OPTION_ROM_RUN_X86EMU),y)
 LIBX86EMU_SRC=$(patsubst %,x86emu/%,$(X86EMU_SRC)) $(BIOSEMU_SRC)

Modified: coreboot-v3/util/x86emu/biosemu.c
===================================================================
--- coreboot-v3/util/x86emu/biosemu.c   2009-05-09 23:36:20 UTC (rev 1166)
+++ coreboot-v3/util/x86emu/biosemu.c   2009-05-29 13:09:57 UTC (rev 1167)
@@ -213,6 +213,7 @@
                ret = run_bios_int(num);
 
 }
+
 #if 0
 #define SYS_BIOS 0xf0000
 /*
@@ -386,7 +387,7 @@
        pushw(X86_SS);
        pushw(X86_SP + 2);
 
-#ifndef NO_TRACE
+#ifdef DEBUG
        //X86EMU_trace_on();
 #endif
 

Modified: coreboot-v3/util/x86emu/vm86.c
===================================================================
--- coreboot-v3/util/x86emu/vm86.c      2009-05-09 23:36:20 UTC (rev 1166)
+++ coreboot-v3/util/x86emu/vm86.c      2009-05-29 13:09:57 UTC (rev 1167)
@@ -1,719 +0,0 @@
-/*
- *  Erik Arjan Hendriks <[email protected]>
- *  Copyright (C) 2000 Scyld.
- *  Copyright (C) 2000 Scyld Computing Corporation
- *  Copyright (C) 2001 University of California.  LA-CC Number 01-67.
- *  Copyright (C) 2005 [email protected]
- *  Copyright (C) 2007-2009 coresystems GmbH
- *
- *  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.
- *
- */
-
-#include <device/pci.h>
-#include <device/pci_ids.h>
-#include <device/pci_ops.h>
-#include <string.h>
-#ifdef COREBOOT_V2
-#include <console/console.h>
-#include <arch/io.h>
-#define printk(lvl, x...) printk_debug(x)
-#else
-#include <console.h>
-#include <io.h>
-#endif
-
-/* The address arguments to this function are PHYSICAL ADDRESSES */
-static void real_mode_switch_call_vga(unsigned long devfn)
-{
-       __asm__ __volatile__ (
-               /* paranoia -- does ecx get saved? not sure.
-                * This is the easiest safe thing to do.
-                */
-               "       pushal                  \n"
-               /* save the stack */
-               "       mov     %esp, __stack   \n"
-               "       jmp     1f              \n"
-               "__stack: .long 0               \n"
-               "1:\n"
-               /* get devfn into %ecx */
-               "       movl    %esp, %ebp      \n"
-               // FIXME: why is this 8?
-               "       movl    8(%ebp), %ecx   \n"
-               /* load 'our' gdt */
-               "       lgdt    %cs:__mygdtaddr \n"
-
-               /*  This configures CS properly for real mode. */
-               "       ljmp    $0x28, $__rms_16bit\n"
-               "__rms_16bit:                   \n"
-               "       .code16                 \n"
-               /* 16 bit code from here on... */
-
-               /* Load the segment registers w/ properly configured
-                * segment descriptors. They will retain these
-                * configurations (limits, writability, etc.) once
-                * protected mode is turned off.
-                */
-               "       mov     $0x30, %ax      \n"
-               "       mov     %ax, %ds        \n"
-               "       mov     %ax, %es        \n"
-               "       mov     %ax, %fs        \n"
-               "       mov     %ax, %gs        \n"
-               "       mov     %ax, %ss        \n"
-
-               /* Turn off protection (bit 0 in CR0) */
-               "       movl    %cr0, %eax      \n"
-               "       andl    $0xFFFFFFFE, %eax \n"
-               "       movl    %eax, %cr0      \n"
-
-               /* Now really going into real mode */
-               "       ljmp    $0,  $__rms_real\n"
-               "__rms_real:                    \n"
-
-               /* Setup a stack: Put the stack at the end of page zero.
-                * That way we can easily share it between real and
-                * protected, since the 16-bit ESP at segment 0 will
-                * work for any case. */
-               "       mov     $0x0, %ax       \n"
-               "       mov     %ax, %ss        \n"
-               "       movl    $0x1000, %eax   \n"
-               "       movl    %eax, %esp      \n"
-
-               /* Load our 16 it idt */
-               "       xor     %ax, %ax        \n"
-               "       mov     %ax, %ds        \n"
-               "       lidt    __myidt         \n"
-
-               /* Dump zeros in the other segment registers */
-               "       mov     %ax, %es        \n"
-               "       mov     %ax, %fs        \n"
-               "       mov     %ax, %gs        \n"
-               "       mov     $0x40, %ax      \n"
-               "       mov     %ax, %ds        \n"
-               "       mov     %cx, %ax        \n"
-
-               /* run VGA BIOS at 0xc000:0003 */
-               "       lcall   $0xc000, $0x0003\n"
-
-               /* If we got here, just about done.
-                * Need to get back to protected mode
-                */
-               "       movl    %cr0, %eax      \n"
-               "       orl     $0x0000001, %eax\n" /* PE = 1 */
-               "       movl    %eax, %cr0      \n"
-
-               /* Now that we are in protected mode
-                * jump to a 32 bit code segment.
-                */
-               "       data32  ljmp    $0x10, $vgarestart\n"
-               "vgarestart:\n"
-               "       .code32\n"
-               "       movw    $0x18, %ax      \n"
-               "       mov     %ax, %ds        \n"
-               "       mov     %ax, %es        \n"
-               "       mov     %ax, %fs        \n"
-               "       mov     %ax, %gs        \n"
-               "       mov     %ax, %ss        \n"
-
-               /* restore proper gdt and idt */
-               "       lgdt    %cs:gdtarg      \n"
-               "       lidt    idtarg          \n"
-
-               ".globl vga_exit                \n"
-               "vga_exit:                      \n"
-               "       mov     __stack, %esp   \n"
-               "       popal                   \n"
-               );
-}
-
-// FIXME: drop this
-// __asm__ (".text\n""real_mode_switch_end:\n");
-// extern char real_mode_switch_end[];
-
-/* call vga bios int 10 function 0x4f14 to enable main console
-   epia-m does not always autosence the main console so forcing it on is good 
!! */
-void vga_enable_console(void)
-{
-       __asm__ __volatile__ (
-               /* paranoia -- does ecx get saved? not sure. This is
-                * the easiest safe thing to do. */
-               "       pushal                  \n"
-               /* save the stack */
-               "       mov     %esp, __stack   \n"
-
-               /* load 'our' gdt */
-               "       lgdt    %cs:__mygdtaddr \n"
-
-               /*  This configures CS properly for real mode. */
-               "       ljmp    $0x28, $__vga_ec_16bit\n"
-               "__vga_ec_16bit:                \n"
-               "       .code16                 \n"
-               /* 16 bit code from here on... */
-
-               /* Load the segment registers w/ properly configured segment
-                * descriptors.  They will retain these configurations (limits,
-                * writability, etc.) once protected mode is turned off. */
-               "       mov     $0x30, %ax      \n"
-               "       mov     %ax, %ds        \n"
-               "       mov     %ax, %es        \n"
-               "       mov     %ax, %fs        \n"
-               "       mov     %ax, %gs        \n"
-               "       mov     %ax, %ss        \n"
-
-               /* Turn off protection (bit 0 in CR0) */
-               "       movl    %cr0, %eax      \n"
-               "       andl    $0xFFFFFFFE, %eax\n"
-               "       movl    %eax, %cr0      \n"
-
-               /* Now really going into real mode */
-               "       ljmp    $0, $__vga_ec_real \n"
-               "__vga_ec_real:                  \n"
-
-               /* put the stack at the end of page zero.
-                * that way we can easily share it between real and protected,
-                * since the 16-bit ESP at segment 0 will work for any case. */
-               /* Setup a stack */
-               "       mov     $0x0, %ax       \n"
-               "       mov     %ax, %ss        \n"
-               "       movl    $0x1000, %eax   \n"
-               "       movl    %eax, %esp      \n"
-
-               /* debugging for RGM */
-               "       mov     $0x11, %al      \n"
-               "       outb    %al, $0x80      \n"
-
-               /* Load our 16 it idt */
-               "       xor     %ax, %ax        \n"
-               "       mov     %ax, %ds        \n"
-               "       lidt    __myidt         \n"
-
-               /* Dump zeros in the other segregs */
-               "       mov     %ax, %ds        \n"
-               "       mov     %ax, %es        \n"
-               "       mov     %ax, %fs        \n"
-               "       mov     %ax, %gs        \n"
-
-               /* ask bios to enable main console */
-               /* set up for int 10 call - values found from X server
-                * bios call routines */
-               "       movw    $0x4f14,%ax     \n"
-               "       movw    $0x8003,%bx     \n"
-               "       movw    $1, %cx         \n"
-               "       movw    $0, %dx         \n"
-               "       movw    $0, %di         \n"
-               "       int     $0x10           \n"
-
-               "       movb    $0x55, %al      \n"
-               "       outb    %al, $0x80      \n"
-
-               /* if we got here, just about done.
-                * Need to get back to protected mode */
-               "       movl    %cr0, %eax      \n"
-               "       orl     $0x0000001, %eax\n" /* PE = 1 */
-               "       movl    %eax, %cr0      \n"
-
-               /* Now that we are in protected mode jump to a 32 bit code 
segment. */
-               "       data32  ljmp    $0x10, $vga_ec_restart\n"
-               "vga_ec_restart:\n"
-               "       .code32\n"
-               "       movw    $0x18, %ax      \n"
-               "       mov     %ax, %ds        \n"
-               "       mov     %ax, %es        \n"
-               "       mov     %ax, %fs        \n"
-               "       mov     %ax, %gs        \n"
-               "       mov     %ax, %ss        \n"
-
-               /* restore proper gdt and idt */
-               "       lgdt    %cs:gdtarg      \n"
-               "       lidt    idtarg          \n"
-               "       .globl  vga__ec_exit    \n"
-               "vga_ec_exit:\n"
-               "       mov     __stack, %esp   \n"
-               "       popal\n"
-               );
-}
-
-// we had hoped to avoid this.
-// this is a stub IDT only. It's main purpose is to ignore calls
-// to the BIOS.
-// no longer. Dammit. We have to respond to these.
-struct realidt {
-       unsigned short offset, cs;
-};
-
-// from a handy writeup that andrey found.
-
-// handler.
-// There are some assumptions we can make here.
-// First, the Top Of Stack (TOS) is located on the top of page zero.
-// we can share this stack between real and protected mode.
-// that simplifies a lot of things ...
-// we'll just push all the registers on the stack as longwords,
-// and pop to protected mode.
-// second, since this only ever runs as part of coreboot,
-// we know all the segment register values -- so we don't save any.
-// keep the handler that calls things small. It can do a call to
-// more complex code in coreboot itself. This helps a lot as we don't
-// have to do address fixup in this little stub, and calls are absolute
-// so the handler is relocatable.
-void handler(void)
-{
-       __asm__ __volatile__ (
-               "       .code16         \n"
-               "idthandle:             \n"
-               "       pushal          \n"
-               "       movb    $0, %al \n"
-               "       ljmp    $0, $callbiosint16\n"
-               "end_idthandle:         \n"
-               "       .code32         \n"
-               );
-}
-
-void debughandler(void)
-{
-       __asm__ __volatile__ (
-               "       .code16         \n"
-               "debughandle:           \n"
-               "       pushw   %cx     \n"
-               "       movw    $250, %cx \n"
-               "dbh1:                  \n"
-               "       loop    dbh1    \n"
-               "       popw    %cx     \n"
-               "       iret            \n"
-               "end_debughandle:       \n"
-               ".code32                \n"
-               );
-}
-
-// Calling conventions. The first C function is called with this stuff
-// on the stack. They look like value parameters, but note that if you
-// modify them they will go back to the INTx function modified.
-// the C function will call the biosint function with these as
-// REFERENCE parameters. In this way, we can easily get
-// returns back to the INTx caller (i.e. vgabios)
-void callbiosint(void)
-{
-       __asm__ __volatile__ (
-               "       .code16         \n"
-               "callbiosint16:         \n"
-               "       push    %ds     \n"
-               "       push    %es     \n"
-               "       push    %fs     \n"
-               "       push    %gs     \n"
-               // clean up the int #. To save space we put it in the lower
-               // byte. But the top 24 bits are junk.
-               "       andl    $0xff, %eax\n"
-               // this push does two things:
-               // - put the INT # on the stack as a parameter
-               // - provides us with a temp for the %cr0 mods.
-               "       pushl   %eax    \n"
-               "       movl    %cr0, %eax\n"
-               "       orl     $0x00000001, %eax\n" /* PE = 1 */
-               "       movl    %eax, %cr0\n"
-               /* Now that we are in protected mode jump to a 32 bit code 
segment. */
-               "       data32  ljmp    $0x10, $biosprotect\n"
-               "biosprotect:           \n"
-               "       .code32         \n"
-               "       movw    $0x18, %ax          \n"
-               "       mov     %ax, %ds          \n"
-               "       mov     %ax, %es          \n"
-               "       mov     %ax, %fs          \n"
-               "       mov     %ax, %gs          \n"
-               "       mov     %ax, %ss          \n"
-               "       lidt    idtarg         \n"
-               "       call    biosint \n"
-               // back to real mode ...
-               "       ljmp    $0x28, $__rms_16bit2\n"
-               "__rms_16bit2:                  \n"
-               "       .code16                 \n"
-               /* 16 bit code from here on... */
-               /* Load the segment registers w/ properly configured segment
-                * descriptors.  They will retain these configurations (limits,
-                * writability, etc.) once protected mode is turned off. */
-               "       mov     $0x30, %ax      \n"
-               "       mov     %ax, %ds        \n"
-               "       mov     %ax, %es        \n"
-               "       mov     %ax, %fs        \n"
-               "       mov     %ax, %gs        \n"
-               "       mov     %ax, %ss        \n"
-
-               /* Turn off protection (bit 0 in CR0) */
-               "       movl    %cr0, %eax              \n"
-               "       andl    $0xFFFFFFFE, %eax       \n"
-               "       movl    %eax, %cr0              \n"
-
-               /* Now really going into real mode */
-               "       ljmp $0,  $__rms_real2  \n"
-               "__rms_real2:                   \n"
-
-               /* Setup a stack
-                * FixME: where is esp? */
-               "       mov     $0x0, %ax       \n"
-               "       mov     %ax, %ss        \n"
-
-               /* ebugging for RGM */
-               "       mov     $0x11, %al      \n"
-               "       outb    %al, $0x80      \n"
-
-               /* Load our 16 it idt */
-               "       xor     %ax, %ax        \n"
-               "       mov     %ax, %ds        \n"
-               "       lidt    __myidt         \n"
-
-               /* Dump zeros in the other segregs */
-               "       mov     %ax, %es        \n"
-               "       mov     %ax, %fs        \n"
-               "       mov     %ax, %gs        \n"
-               "       mov     $0x40, %ax      \n"
-               "       mov     %ax, %ds        \n"
-
-               /* pop the INT # that you pushed earlier */
-               "       popl    %eax            \n"
-               "       pop     %gs             \n"
-               "       pop     %fs             \n"
-               "       pop     %es             \n"
-               "       pop     %ds             \n"
-               "       popal                   \n"
-               "       iret                    \n"
-               "       .code32                 \n"
-               );
-}
-
-enum {
-       PCIBIOS = 0x1a,
-       MEMSIZE = 0x12
-};
-
-int pcibios(unsigned long *pedi, unsigned long *pesi, unsigned long *pebp,
-           unsigned long *pesp, unsigned long *pebx, unsigned long *pedx,
-           unsigned long *pecx, unsigned long *peax, unsigned long *pflags);
-
-int handleint21(unsigned long *pedi, unsigned long *pesi, unsigned long *pebp,
-               unsigned long *pesp, unsigned long *pebx, unsigned long *pedx,
-               unsigned long *pecx, unsigned long *peax, unsigned long *pflags
-       );
-
-extern void vga_exit(void);
-
-int __attribute__((regparm(0)))  biosint(unsigned long intnumber,
-           unsigned long gsfs, unsigned long dses,
-           unsigned long edi, unsigned long esi,
-           unsigned long ebp, unsigned long esp,
-           unsigned long ebx, unsigned long edx,
-           unsigned long ecx, unsigned long eax,
-           unsigned long cs_ip, unsigned short stackflags)
-{
-       unsigned long ip;
-       unsigned long cs;
-       unsigned long flags;
-       int ret = -1;
-
-       ip = cs_ip & 0xffff;
-       cs = cs_ip >> 16;
-       flags = stackflags;
-
-       printk(BIOS_DEBUG, "biosint: INT# 0x%lx\n", intnumber);
-       printk(BIOS_DEBUG, "biosint: eax 0x%lx ebx 0x%lx ecx 0x%lx edx 0x%lx\n",
-                     eax, ebx, ecx, edx);
-       printk(BIOS_DEBUG, "biosint: ebp 0x%lx esp 0x%lx edi 0x%lx esi 0x%lx\n",
-                    ebp, esp, edi, esi);
-       printk(BIOS_DEBUG, "biosint:  ip 0x%lx   cs 0x%lx  flags 0x%lx\n",
-                    ip, cs, flags);
-
-       // cases in a good compiler are just as good as your own tables.
-       switch (intnumber) {
-       case 0 ... 15:
-               // These are not BIOS service, but the CPU-generated exceptions
-               printk(BIOS_INFO, "biosint: Oops, exception %lu\n", intnumber);
-               if (esp < 0x1000) {
-                       printk(BIOS_DEBUG, "Stack contents: ");
-                       while (esp < 0x1000) {
-                               printk(BIOS_DEBUG, "0x%04x ", *(unsigned short 
*) esp);
-                               esp += 2;
-                       }
-                       printk(BIOS_DEBUG, "\n");
-               }
-               printk(BIOS_DEBUG, "biosint: Bailing out\n");
-               // "longjmp"
-               vga_exit();
-               break;
-
-       case PCIBIOS:
-               ret = pcibios( &edi, &esi, &ebp, &esp,
-                              &ebx, &edx, &ecx, &eax, &flags);
-               break;
-       case MEMSIZE:
-               // who cares.
-               eax = 64 * 1024;
-               ret = 0;
-               break;
-       case 0x15:
-               ret=handleint21( &edi, &esi, &ebp, &esp,
-                               &ebx, &edx, &ecx, &eax, &flags);
-               break;
-       default:
-               printk(BIOS_INFO, "BIOSINT: Unsupport int #0x%lx\n",
-                           intnumber);
-               break;
-       }
-       if (ret)
-               flags |= 1; // carry flags
-       else
-               flags &= ~1;
-       stackflags = flags;
-       return ret;
-}
-
-void setup_realmode_idt(void)
-{
-       extern unsigned char idthandle, end_idthandle;
-#if 0
-       extern unsigned char debughandle, end_debughandle;
-#endif
-
-       int i;
-       struct realidt *idts = (struct realidt *) 0;
-       int codesize = &end_idthandle - &idthandle;
-       unsigned char *intbyte, *codeptr;
-
-       // for each int, we create a customized little handler
-       // that just pushes %ax, puts the int # in %al,
-       // then calls the common interrupt handler.
-       // this necessitated because intel didn't know much about
-       // architecture when they did the 8086 (it shows)
-       // (hmm do they know anymore even now :-)
-       // obviously you can see I don't really care about memory
-       // efficiency. If I did I would probe back through the stack
-       // and get it that way. But that's really disgusting.
-       for (i = 0; i < 256; i++) {
-               idts[i].cs = 0;
-               codeptr = (unsigned char *) 4096 + i * codesize;
-               idts[i].offset = (unsigned) codeptr;
-               memcpy(codeptr, &idthandle, codesize);
-               intbyte = codeptr + 3;
-               *intbyte = i;
-       }
-
-       // fixed entry points
-
-       // VGA BIOSes tend to hardcode f000:f065 as the previous handler of
-       // int10.
-       // calling convention here is the same as INTs, we can reuse
-       // the int entry code.
-       codeptr = (unsigned char *) 0xff065;
-       memcpy(codeptr, &idthandle, codesize);
-       intbyte = codeptr + 3;
-       *intbyte = 0x42; /* int42 is the relocated int10 */
-
-       /* The source of the following code is not yet known.
-        * We feel it may be useful someday, but right now it
-        * scribbles over code space. We are leaving it here as a
-        * "Living comment" since it may at some point be needed
-        * again. It is a very intriguing idea -- one could run
-        * vm86 code with TF set and set programmable times
-        * between instructions to slow them down. For those who
-        * recall the "turbo" switch on old PCs, this is the
-        * software equivalent.
-        */
-#if 0
-       /* debug handler - useful to set a programmable delay between 
instructions if the
-          TF bit is set upon call to real mode */
-       idts[1].cs = 0;
-       idts[1].offset = 16384;
-       memcpy((void *)16384, &debughandle, &end_debughandle - &debughandle);
-#endif
-}
-
-void run_bios(struct device *dev, unsigned long addr)
-{
-       int i;
-
-       /* clear vga bios data area */
-       for (i = 0x400; i < 0x500; i++) {
-               *(unsigned char *) i = 0;
-       }
-       setup_realmode_idt();
-       real_mode_switch_call_vga((dev->bus->secondary << 8) | 
dev->path.pci.devfn);
-}
-
-enum {
-       CHECK = 0xb001,
-       FINDDEV = 0xb102,
-       READCONFBYTE = 0xb108,
-       READCONFWORD = 0xb109,
-       READCONFDWORD = 0xb10a,
-       WRITECONFBYTE = 0xb10b,
-       WRITECONFWORD = 0xb10c,
-       WRITECONFDWORD = 0xb10d
-};
-
-// errors go in AH. Just set these up so that word assigns
-// will work. KISS.
-enum {
-       PCIBIOS_NODEV = 0x8600,
-       PCIBIOS_BADREG = 0x8700
-};
-
-int
-pcibios(unsigned long *pedi, unsigned long *pesi, unsigned long *pebp,
-       unsigned long *pesp, unsigned long *pebx, unsigned long *pedx,
-       unsigned long *pecx, unsigned long *peax, unsigned long *pflags)
-{
-       unsigned short func = (unsigned short) *peax;
-       int retval = 0;
-       unsigned short devid, vendorid, devfn;
-       /* Use short to get rid of gabage in upper half of 32-bit register */
-       short devindex;
-       unsigned char bus;
-       struct device *dev;
-
-       switch(func) {
-       case  CHECK:
-               *pedx = 0x4350;
-               *pecx = 0x2049;
-               retval = 0;
-               break;
-       case FINDDEV:
-       {
-               devid = *pecx;
-               vendorid = *pedx;
-               devindex = *pesi;
-               dev = 0;
-#ifdef COREBOOT_V2
-               while ((dev = dev_find_device(vendorid, devid, dev))) {
-#else
-               while ((dev = dev_find_pci_device(vendorid, devid, dev))) {
-#endif
-                       if (devindex <= 0)
-                               break;
-                       devindex--;
-               }
-               if (dev) {
-                       unsigned short busdevfn;
-                       *peax = 0;
-                       // busnum is an unsigned char;
-                       // devfn is an int, so we mask it off.
-                       busdevfn = (dev->bus->secondary << 8)
-                               | (dev->path.pci.devfn & 0xff);
-                       printk(BIOS_DEBUG, "0x%x: return 0x%x\n", func, 
busdevfn);
-                       *pebx = busdevfn;
-                       retval = 0;
-               } else {
-                       *peax = PCIBIOS_NODEV;
-                       retval = -1;
-               }
-       }
-       break;
-       case READCONFDWORD:
-       case READCONFWORD:
-       case READCONFBYTE:
-       case WRITECONFDWORD:
-       case WRITECONFWORD:
-       case WRITECONFBYTE:
-       {
-               unsigned long dword;
-               unsigned short word;
-               unsigned char byte;
-               unsigned char reg;
-
-               devfn = *pebx & 0xff;
-               bus = *pebx >> 8;
-               reg = *pedi;
-               dev = dev_find_slot(bus, devfn);
-               if (! dev) {
-                       printk(BIOS_DEBUG, "0x%x: BAD DEVICE bus %d devfn 
0x%x\n", func, bus, devfn);
-                       // idiots. the pcibios guys assumed you'd never pass a 
bad bus/devfn!
-                       *peax = PCIBIOS_BADREG;
-                       retval = -1;
-               }
-               switch(func) {
-               case READCONFBYTE:
-                       byte = pci_read_config8(dev, reg);
-                       *pecx = byte;
-                       break;
-               case READCONFWORD:
-                       word = pci_read_config16(dev, reg);
-                       *pecx = word;
-                       break;
-               case READCONFDWORD:
-                       dword = pci_read_config32(dev, reg);
-                       *pecx = dword;
-                       break;
-               case WRITECONFBYTE:
-                       byte = *pecx;
-                       pci_write_config8(dev, reg, byte);
-                       break;
-               case WRITECONFWORD:
-                       word = *pecx;
-                       pci_write_config16(dev, reg, word);
-                       break;
-               case WRITECONFDWORD:
-                       dword = *pecx;
-                       pci_write_config32(dev, reg, dword);
-                       break;
-               }
-
-               if (retval)
-                       retval = PCIBIOS_BADREG;
-               printk(BIOS_DEBUG, "0x%x: bus %d devfn 0x%x reg 0x%x val 
0x%lx\n",
-                            func, bus, devfn, reg, *pecx);
-               *peax = 0;
-               retval = 0;
-       }
-       break;
-       default:
-               printk(BIOS_ERR, "UNSUPPORTED PCIBIOS FUNCTION 0x%x\n",  func);
-               break;
-       }
-
-       return retval;
-}
-
-int handleint21(unsigned long *edi, unsigned long *esi, unsigned long *ebp,
-               unsigned long *esp, unsigned long *ebx, unsigned long *edx,
-               unsigned long *ecx, unsigned long *eax, unsigned long *flags)
-{
-       int res=-1;
-       switch(*eax&0xffff)
-       {
-       case 0x5f19:
-               break;
-       case 0x5f18:
-               *eax=0x5f;
-               *ebx=0x545; // MCLK = 133, 32M frame buffer, 256 M main memory
-               *ecx=0x060;
-               res=0;
-               break;
-       case 0x5f00:
-               *eax = 0x8600;
-               break;
-       case 0x5f01:
-               *eax = 0x5f;
-               *ecx = (*ecx & 0xffffff00 ) | 2; // panel type =  2 = 1024 * 768
-               res = 0;
-               break;
-       case 0x5f02:
-               *eax=0x5f;
-               *ebx= (*ebx & 0xffff0000) | 2;
-               *ecx= (*ecx & 0xffff0000) | 0x401;  // PAL + crt only
-               *edx= (*edx & 0xffff0000) | 0;  // TV Layout - default
-               res=0;
-               break;
-       case 0x5f0f:
-               *eax=0x860f;
-               break;
-       }
-       return res;
-}

Modified: coreboot-v3/util/x86emu/vm86_gdt.c
===================================================================
--- coreboot-v3/util/x86emu/vm86_gdt.c  2009-05-09 23:36:20 UTC (rev 1166)
+++ coreboot-v3/util/x86emu/vm86_gdt.c  2009-05-29 13:09:57 UTC (rev 1167)
@@ -1,101 +0,0 @@
-/*
- *  Erik Arjan Hendriks <[email protected]>
- *  Copyright (C) 2000 Scyld.
- *  Copyright (C) 2000 Scyld Computing Corporation
- *  Copyright (C) 2001 University of California.  LA-CC Number 01-67.
- *  Copyright (C) 2005 [email protected]
- *  Copyright (C) 2007 coresystems GmbH
- *
- *  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.
- *
- */
-
-
-/* Declare a temporary global descriptor table - 
- * necessary because the core part of the bios 
- * no longer sets up any 16 bit segments 
- */
-
-__asm__ (
-       /* pointer to original gdt */
-       "       .globl gdtarg\n"
-       "gdtarg:                        \n"
-       "       .word   gdt_limit       \n"
-#ifdef COREBOOT_V2
-       "       .long   gdt             \n"             
-#else
-       "       .long   gdtptr          \n"             
-#endif
-
-       /* compute the table limit */
-       "__mygdt_limit = __mygdt_end - __mygdt - 1      \n"
-       "       .globl __mygdtaddr\n"
-       "__mygdtaddr:                   \n"
-       "       .word   __mygdt_limit   \n"
-       "       .long   __mygdt         \n"
-
-       "       .globl __mygdt\n"
-       "__mygdt:                       \n"
-       /* selgdt 0, unused */
-       "       .word   0x0000, 0x0000  \n"
-       "       .byte   0x00, 0x00, 0x00, 0x00  \n"
-
-       /* selgdt 8, unused */
-       "       .word   0x0000, 0x0000          \n"
-       "       .byte   0x00, 0x00, 0x00, 0x00  \n"
-
-       /* selgdt 0x10, flat code segment */
-       "       .word   0xffff, 0x0000          \n"
-       "       .byte   0x00, 0x9b, 0xcf, 0x00  \n"     
-
-       /* selgdt 0x18, flat data segment */
-       "       .word   0xffff, 0x0000          \n"
-       "       .byte   0x00, 0x93, 0xcf, 0x00  \n"
-
-       /* selgdt 0x20, unused */
-       "       .word   0x0000, 0x0000          \n"
-       "       .byte   0x00, 0x00, 0x00, 0x00  \n"
-
-        /* selgdt 0x28 16-bit 64k code at 0x00000000 */
-       "       .word   0xffff, 0x0000          \n"
-       "       .byte   0, 0x9a, 0, 0           \n"
-
-       /* selgdt 0x30 16-bit 64k data at 0x00000000 */
-       "       .word   0xffff, 0x0000          \n"
-       "       .byte   0, 0x92, 0, 0           \n"
-
-       "__mygdt_end:                           \n"
-
-#ifndef COREBOOT_V2
-       /* FIXME: This does probably not belong here */
-       "       .globl idtarg\n"
-       "idtarg:\n"
-       "       .word   _idt_end - _idt - 1\n"     /* limit */
-       "       .long   _idt\n"
-       "       .word   0\n"
-       "_idt:\n"
-       "       .fill   20, 8, 0\n" //       # idt is unitiailzed
-       "_idt_end:\n"
-#endif
-
-       /* Declare a pointer to where our idt is going to be i.e. at mem zero */
-       "       .globl __myidt\n"
-        "__myidt:              \n"
-        /* 16-bit limit */
-        "      .word 1023      \n"
-        /* 24-bit base */
-        "      .long 0         \n"
-        "      .word 0         \n"
-);

Added: coreboot-v3/util/x86emu/x86.c
===================================================================
--- coreboot-v3/util/x86emu/x86.c                               (rev 0)
+++ coreboot-v3/util/x86emu/x86.c       2009-05-29 13:09:57 UTC (rev 1167)
@@ -0,0 +1,228 @@
+/*
+ *  Copyright (C) 2009 coresystems GmbH
+ *
+ *  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; version 2 of the License.
+ *
+ *  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.
+ *
+ */
+
+#include <device/pci.h>
+#include <string.h>
+
+#ifdef COREBOOT_V2
+#include <arch/io.h>
+#include <console/console.h>
+#define printk(x...) do_printk(x)
+#else
+#include <console.h>
+#endif
+
+#define REALMODE_BASE ((void *)0x500)
+
+struct realmode_idt {
+       u16 offset, cs;
+};
+
+struct eregs {
+       uint32_t eax, ecx, edx, ebx, esp, ebp, esi, edi;
+       uint32_t vector;
+       uint32_t error_code;
+       uint32_t eip;
+       uint32_t cs;
+       uint32_t eflags;
+};
+
+void x86_exception(struct eregs *info);
+
+extern unsigned char __idt_handler, __idt_handler_size;
+extern unsigned char __realmode_code, __realmode_code_size;
+extern unsigned char __run_optionrom, __run_interrupt;
+
+void (*run_optionrom)(u32 devfn) = (void *)&__run_optionrom;
+void (*vga_enable_console)(void) = (void *)&__run_interrupt;
+
+int (*intXX_handler[256])(struct eregs *regs) = { NULL };
+
+static int intXX_exception_handler(struct eregs *regs)
+{
+       printk(BIOS_INFO, "Oops, exception %d while executing option rom\n", 
+                       regs->vector);
+       x86_exception(regs);    // Call coreboot exception handler 
+
+       return 0;               // Never returns?
+}
+
+static int intXX_unknown_handler(struct eregs *regs)
+{
+       printk(BIOS_INFO, "Unsupported software interrupt #0x%x\n", 
+                       regs->vector);
+
+       return -1;
+}
+
+int int12_handler(struct eregs *regs);
+int int15_handler(struct eregs *regs);
+int int1a_handler(struct eregs *regs);
+
+static void setup_interrupt_handlers(void)
+{
+       int i;
+
+       /* The first 16 intXX functions are not BIOS services, 
+        * but the CPU-generated exceptions ("hardware interrupts")
+        */
+       for (i = 0; i < 0x10; i++)
+               intXX_handler[i] = &intXX_exception_handler;
+       
+       /* Mark all other intXX calls as unknown first */
+       for (i = 0x10; i < 0x100; i++)
+               intXX_handler[i] = &intXX_unknown_handler;
+
+       /* Now set the default functions that are actually
+        * needed to initialize the option roms. This is very
+        * slick, as it allows us to implement mainboard specific
+        * interrupt handlers, such as the int15
+        */
+       intXX_handler[0x12] = &int12_handler;
+       intXX_handler[0x15] = &int15_handler;
+       intXX_handler[0x1a] = &int1a_handler;
+}
+
+static void write_idt_stub(void *target, u8 intnum)
+{
+       unsigned char *codeptr;
+       codeptr = (unsigned char *) target;
+       memcpy(codeptr, &__idt_handler, (size_t)&__idt_handler_size);
+       codeptr[3] = intnum; /* modify int# in the code stub. */
+}
+
+static void setup_realmode_idt(void)
+{
+       struct realmode_idt *idts = (struct realmode_idt *) 0;
+       int i;
+
+       /* Copy IDT stub code for each interrupt. This might seem wasteful
+        * but it is really simple
+        */
+        for (i = 0; i < 256; i++) {
+               idts[i].cs = 0;
+               idts[i].offset = 0x1000 + (i * (u32)&__idt_handler_size);
+               write_idt_stub((void *)((u32 )idts[i].offset), i);
+       }
+
+       /* Many option ROMs use the hard coded interrupt entry points in the
+        * system bios. So install them at the known locations. 
+        * Only need int10 so far.
+        */
+       
+       /* int42 is the relocated int10 */
+       write_idt_stub((void *)0xff065, 0x42); 
+}
+
+void run_bios(struct device *dev, unsigned long addr)
+{
+       int i;
+
+       /* clear vga bios data area */
+       for (i = 0x400; i < 0x500; i++) {
+               *(unsigned char *) i = 0;
+       }
+       
+       /* Set up C interrupt handlers */
+       setup_interrupt_handlers();
+
+       /* Setting up realmode IDT */
+       setup_realmode_idt();
+
+       memcpy(REALMODE_BASE, &__realmode_code, (size_t)&__realmode_code_size);
+       printk(BIOS_SPEW, "Real mode stub @%p: %d bytes\n", REALMODE_BASE,
+                       (u32)&__realmode_code_size);
+
+       printk(BIOS_DEBUG, "Calling Option Rom...\n");
+       run_optionrom((dev->bus->secondary << 8) | dev->path.pci.devfn);
+}
+
+int __attribute__((regparm(0))) interrupt_handler(u32 intnumber,
+           u32 gsfs, u32 dses,
+           u32 edi, u32 esi,
+           u32 ebp, u32 esp,
+           u32 ebx, u32 edx,
+           u32 ecx, u32 eax,
+           u32 cs_ip, u16 stackflags)
+{
+       u32 ip;
+       u32 cs;
+       u32 flags;
+       int ret = -1;
+       struct eregs reg_info;
+
+       ip = cs_ip & 0xffff;
+       cs = cs_ip >> 16;
+       flags = stackflags;
+
+       printk(BIOS_DEBUG, "oprom: INT# 0x%x\n", intnumber);
+       printk(BIOS_DEBUG, "oprom: eax: %08x ebx: %08x ecx: %08x edx: %08x\n",
+                     eax, ebx, ecx, edx);
+       printk(BIOS_DEBUG, "oprom: ebp: %08x esp: %08x edi: %08x esi: %08x\n",
+                    ebp, esp, edi, esi);
+       printk(BIOS_DEBUG, "oprom:  ip: %04x      cs: %04x   flags: %08x\n",
+                    ip, cs, flags);
+
+       // Fetch arguments from the stack and put them into
+       // a structure that we want to pass on to our sub interrupt
+       // handlers.
+       reg_info = (struct eregs) {
+               .eax=eax,
+               .ecx=ecx,
+               .edx=edx,
+               .ebx=ebx,
+               .esp=esp,
+               .ebp=ebp,
+               .esi=esi,
+               .edi=edi,
+               .vector=intnumber,
+               .error_code=0, // ??
+               .eip=ip,
+               .cs=cs,
+               .eflags=flags // ??
+       };
+
+       // Call the interrupt handler for this int#
+       ret = intXX_handler[intnumber](&reg_info);
+
+       // Put registers back on the stack. The assembler code
+       // will later pop them.
+       // What happens here is that we force (volatile!) changing
+       // the values of the parameters of this function. We do this
+       // because we know that they stay alive on the stack after 
+       // we leave this function. Don't say this is bollocks.
+       *(volatile u32 *)&eax = reg_info.eax;
+       *(volatile u32 *)&ecx = reg_info.ecx;
+       *(volatile u32 *)&edx = reg_info.edx;
+       *(volatile u32 *)&ebx = reg_info.ebx;
+       *(volatile u32 *)&esi = reg_info.esi;
+       *(volatile u32 *)&edi = reg_info.edi;
+       flags = reg_info.eflags;
+
+       /* Pass errors back to our caller via the CARRY flag */
+       if (ret) {
+               printk(BIOS_DEBUG,"error!\n");
+               flags |= 1;  // error: set carry
+       }else{
+               flags &= ~1; // no error: clear carry
+       }
+       *(volatile u16 *)&stackflags = flags;
+
+       return ret;
+}
+

Added: coreboot-v3/util/x86emu/x86_asm.S
===================================================================
--- coreboot-v3/util/x86emu/x86_asm.S                           (rev 0)
+++ coreboot-v3/util/x86emu/x86_asm.S   2009-05-29 13:09:57 UTC (rev 1167)
@@ -0,0 +1,392 @@
+/*
+ *  Copyright (C) 2009 coresystems GmbH
+ *
+ *  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; version 2 of the License.
+ *
+ *  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.
+ *
+ */
+
+#define REALMODE_BASE          0x500
+#define RELOCATED(x)   (x - __realmode_code + REALMODE_BASE)
+
+/* CR0 bits */
+#define PE             (1 << 0)
+
+/* This is the intXX interrupt handler stub code. It gets copied
+ * to the IDT and to some fixed addresses in the F segment. Before
+ * the code can used, it gets patched up by the C function copying 
+ * it: byte 3 (the $0 in movb $0, %al) is overwritten with the int#.
+ */
+
+       .code16
+       .globl __idt_handler
+__idt_handler:
+       pushal
+       movb    $0, %al /* This instruction gets modified */
+       ljmp    $0, $__interrupt_handler_16bit
+       .globl __idt_handler_size
+__idt_handler_size = ( . - __idt_handler)
+
+
+/* In order to be independent of coreboot's position in RAM
+ * we relocate a part of the code to the low megabyte, so the
+ * CPU can use it in real-mode. This code lives at __realmode_code.
+ */
+       .globl __realmode_code
+__realmode_code:
+
+/* Realmode IDT pointer structure. */
+       .globl __realmode_idt
+__realmode_idt = RELOCATED(.)
+       .word 1023      /* 16-bit limit */
+       .long 0         /* 24-bit base */
+       .word 0
+
+/* Preserve old stack */
+__stack = RELOCATED(.)
+       .long 0
+
+       .code32
+       .globl __run_optionrom
+__run_optionrom = RELOCATED(.)
+       /* save all registers to the stack */
+       pushal
+
+       /* Move the protected mode stack to a safe place */
+       mov     %esp, __stack
+
+       /* Get devfn into %ecx */
+       movl    %esp, %ebp
+       // FIXME: Should this function be called with regparm=0?
+       movl    8(%ebp), %ecx
+
+       /* Clear interrupts before making a
+        * transition to Real Mode
+        */
+       cli
+
+       /* Activate the right segment descriptor real mode. */
+       ljmp    $0x28, $RELOCATED(1f)
+1:
+.code16
+       /* 16 bit code from here on... */
+
+       /* Load the segment registers w/ properly configured
+        * segment descriptors. They will retain these
+        * configurations (limits, writability, etc.) once
+        * protected mode is turned off.
+        */
+       mov     $0x30, %ax
+       mov     %ax, %ds       
+       mov     %ax, %es       
+       mov     %ax, %fs       
+       mov     %ax, %gs       
+       mov     %ax, %ss       
+
+       /* Turn off protection */
+       movl    %cr0, %eax
+       andl    $~PE, %eax
+       movl    %eax, %cr0
+
+       /* Now really going into real mode */
+       ljmp    $0, $RELOCATED(1f)
+1:
+       /* Setup a stack: Put the stack at the end of page zero.
+        * That way we can easily share it between real and
+        * protected, since the 16-bit ESP at segment 0 will
+        * work for any case. */
+       mov     $0x0, %ax
+       mov     %ax, %ss
+       movl    $0x1000, %eax
+       movl    %eax, %esp
+
+       /* Load our 16 it idt */
+       xor     %ax, %ax
+       mov     %ax, %ds
+       lidt    __realmode_idt
+
+       /* All critical work is done, allow interrupts again */
+       sti
+
+       /* Set all segments to 0x0000, ds to 0x0040 */
+       mov     %ax, %es       
+       mov     %ax, %fs       
+       mov     %ax, %gs       
+       mov     $0x40, %ax
+       mov     %ax, %ds
+       mov     %cx, %ax        // restore ax
+
+       /* ************************************ */
+       // TODO this will not work for non-VGA option ROMs
+       /* run VGA BIOS at 0xc000:0003 */
+       lcall   $0xc000, $0x0003
+       /* ************************************ */
+
+       /* Clear interrupts before making a 
+        * transition to Protected Mode
+        */
+       cli
+
+       /* If we got here, just about done.
+        * Need to get back to protected mode
+        */
+       movl    %cr0, %eax
+       orl     $PE, %eax
+       movl    %eax, %cr0
+
+       /* Now that we are in protected mode
+        * jump to a 32 bit code segment.
+        */
+       data32  ljmp    $0x10, $RELOCATED(1f)
+1:
+       .code32
+       movw    $0x18, %ax     
+       mov     %ax, %ds       
+       mov     %ax, %es
+       mov     %ax, %fs
+       mov     %ax, %gs
+       mov     %ax, %ss
+
+       /* restore proper idt */
+       lidt    idtarg
+
+       /* All critical work is done, allow interrupts again */
+       sti
+
+       /* and exit */
+       mov     __stack, %esp
+       popal
+       ret
+
+       .globl __run_interrupt
+__run_interrupt = RELOCATED(.)
+
+       /* paranoia -- does ecx get saved? not sure. This is
+        * the easiest safe thing to do. */
+       pushal
+       /* save the stack */
+       mov     %esp, __stack
+
+
+       /* Clear interrupts before making a 
+        * transition to Real Mode
+        */
+       cli
+
+       /*  This configures CS properly for real mode. */
+       ljmp    $0x28, $RELOCATED(1f)
+1:
+       .code16 /* 16 bit code from here on... */
+
+       // DEBUG
+       movb    $0xec, %al
+       outb    %al, $0x80
+
+       /* Load the segment registers w/ properly configured segment
+        * descriptors.  They will retain these configurations (limits,
+        * writability, etc.) once protected mode is turned off.
+        */
+       mov     $0x30, %ax     
+       mov     %ax, %ds       
+       mov     %ax, %es       
+       mov     %ax, %fs       
+       mov     %ax, %gs       
+       mov     %ax, %ss       
+
+       /* Turn off protected mode */
+       movl    %cr0, %eax     
+       andl    $~PE, %eax
+       movl    %eax, %cr0     
+
+       /* Now really going into real mode */
+       data32 ljmp     $0, $RELOCATED(1f)
+1:
+
+       /* put the stack at the end of page zero.
+        * that way we can easily share it between real and protected,
+        * since the 16-bit ESP at segment 0 will work for any case.
+        */
+       /* setup a stack */
+       mov     $0x0, %ax
+       mov     %ax, %ss
+       movl    $0x1000, %eax
+       movl    %eax, %esp
+
+       /* Load 16-bit intXX IDT */
+       xor     %ax, %ax       
+       mov     %ax, %ds
+       lidt    __realmode_idt
+
+       /* All critical work is done, allow interrupts again */
+       sti
+
+       /* Set all segments to 0x0000 */
+       mov     %ax, %ds
+       mov     %ax, %es
+       mov     %ax, %fs
+       mov     %ax, %gs
+
+       /* Call VGA BIOS int10 function 0x4f14 to enable main console
+        * Epia-M does not always autosence the main console so forcing
+        * it on is good.
+        */
+
+       /* Ask VGA option rom to enable main console */
+       movw    $0x4f14,%ax
+       movw    $0x8003,%bx
+       movw    $1, %cx
+       movw    $0, %dx
+       movw    $0, %di
+       int     $0x10
+
+       /* Clear interrupts before making a 
+        * transition to Protected Mode
+        */
+       cli
+
+       /* Ok, the job is done, now go back to protected mode coreboot */
+       movl    %cr0, %eax
+       orl     $PE, %eax
+       movl    %eax, %cr0
+
+       /* Now that we are in protected mode jump to a 32-bit code segment. */
+       data32  ljmp    $0x10, $RELOCATED(1f)
+1:
+       .code32
+       movw    $0x18, %ax
+       mov     %ax, %ds
+       mov     %ax, %es
+       mov     %ax, %fs
+       mov     %ax, %gs
+       mov     %ax, %ss
+
+       /* restore coreboot's 32-bit IDT */
+       lidt    idtarg
+
+       /* All critical work is done, allow interrupts again */
+       sti
+
+       /* Exit */
+       mov     __stack, %esp
+       popal
+       ret
+
+/* This is the 16-bit interrupt entry point called by the IDT stub code.
+ * Before this code code is called, %eax is pushed to the stack, and the
+ * interrupt number is loaded into %al
+ */
+       .code16
+__interrupt_handler_16bit = RELOCATED(.)
+       push    %ds
+       push    %es
+       push    %fs
+       push    %gs
+
+       /* Clean up the interrupt number. We could have done this in the stub,
+        * but it would have cost 2 more bytes per stub entry.
+        */
+       andl    $0xff, %eax
+       pushl   %eax            /* ... and make it the first parameter */
+
+       /* Clear interrupts before making a 
+        * transition to Protected Mode
+        */
+       cli
+
+       /* Switch to protected mode */
+       movl    %cr0, %eax
+       orl     $PE, %eax
+       movl    %eax, %cr0
+
+       /* ... and jump to a 32 bit code segment. */
+       data32 ljmp    $0x10, $RELOCATED(1f)
+1:
+       .code32
+       movw    $0x18, %ax
+       mov     %ax, %ds
+       mov     %ax, %es
+       mov     %ax, %fs
+       mov     %ax, %gs
+       mov     %ax, %ss
+
+       lidt    idtarg
+
+       /* All critical work is done, allow interrupts again */
+       sti
+
+       /* Call the C interrupt handler */
+       movl    $interrupt_handler, %eax
+       call    *%eax
+
+       /* Now return to real mode ... */
+       ljmp    $0x28, $RELOCATED(1f)
+1:
+       .code16
+       /* Load the segment registers with properly configured segment
+        * descriptors.  They will retain these configurations (limits,
+        * writability, etc.) once protected mode is turned off.
+        */
+       mov     $0x30, %ax
+       mov     %ax, %ds
+       mov     %ax, %es
+       mov     %ax, %fs
+       mov     %ax, %gs
+       mov     %ax, %ss
+
+       /* Clear interrupts before making a 
+        * transition to Real Mode
+        */
+       cli
+
+       /* Disable Protected Mode */
+       movl    %cr0, %eax
+       andl    $~PE, %eax
+       movl    %eax, %cr0
+
+       /* Now really going into real mode */
+       ljmp $0,  $RELOCATED(1f)
+1:
+       /* Restore real-mode stack segment */
+       mov     $0x0, %ax
+       mov     %ax, %ss
+
+       /* Restore 16-bit IDT */
+       xor     %ax, %ax
+       mov     %ax, %ds
+       lidt    __realmode_idt
+
+       /* All critical work is done, allow interrupts again */
+       sti
+
+       /* Set up our segment registers to segment 0x0000 */
+       mov     %ax, %es
+       mov     %ax, %fs
+       mov     %ax, %gs
+       mov     $0x40, %ax
+       mov     %ax, %ds
+
+       /* Restore all registers, including those
+        * manipulated by the C handler
+        */
+       popl    %eax
+       pop     %gs
+       pop     %fs
+       pop     %es
+       pop     %ds
+       popal
+       iret
+
+       .globl __realmode_code_size
+__realmode_code_size = (. - __realmode_code)
+
+       .code32

Added: coreboot-v3/util/x86emu/x86_interrupts.c
===================================================================
--- coreboot-v3/util/x86emu/x86_interrupts.c                            (rev 0)
+++ coreboot-v3/util/x86emu/x86_interrupts.c    2009-05-29 13:09:57 UTC (rev 
1167)
@@ -0,0 +1,243 @@
+/*
+ *  Copyright (C) 2001 Ronald G. Minnich
+ *  Copyright (C) 2005 [email protected]
+ *  Copyright (C) 2007-2009 coresystems GmbH
+ *
+ *  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; version 2 of the License.
+ *
+ *  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.
+ *
+ */
+
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <string.h>
+#ifdef COREBOOT_V2
+#include <console/console.h>
+#include <arch/io.h>
+#define printk(x...) do_printk(x)
+#else
+#include <console.h>
+#include <io.h>
+#endif
+
+struct eregs {
+       uint32_t eax, ecx, edx, ebx, esp, ebp, esi, edi;
+       uint32_t vector;
+       uint32_t error_code;
+       uint32_t eip;
+       uint32_t cs;
+       uint32_t eflags;
+};
+
+enum {
+       CHECK = 0xb001,
+       FINDDEV = 0xb102,
+       READCONFBYTE = 0xb108,
+       READCONFWORD = 0xb109,
+       READCONFDWORD = 0xb10a,
+       WRITECONFBYTE = 0xb10b,
+       WRITECONFWORD = 0xb10c,
+       WRITECONFDWORD = 0xb10d
+};
+
+// errors go in AH. Just set these up so that word assigns
+// will work. KISS.
+enum {
+       PCIBIOS_NODEV = 0x8600,
+       PCIBIOS_BADREG = 0x8700
+};
+
+int int12_handler(struct eregs *regs)
+{
+       regs->eax = 64 * 1024;
+       return 0;
+}
+
+int int1a_handler(struct eregs *regs)
+{
+       unsigned short func = (unsigned short) regs->eax;
+       int retval = 0;
+       unsigned short devid, vendorid, devfn;
+       /* Use short to get rid of gabage in upper half of 32-bit register */
+       short devindex;
+       unsigned char bus;
+       struct device *dev;
+
+       switch(func) {
+       case  CHECK:
+               regs->edx = 0x4350;
+               regs->ecx = 0x2049;
+               retval = 0;
+               break;
+       case FINDDEV:
+       {
+               devid = regs->ecx;
+               vendorid = regs->edx;
+               devindex = regs->esi;
+               dev = 0;
+#ifdef COREBOOT_V2
+               while ((dev = dev_find_device(vendorid, devid, dev))) {
+#else
+               while ((dev = dev_find_pci_device(vendorid, devid, dev))) {
+#endif
+                       if (devindex <= 0)
+                               break;
+                       devindex--;
+               }
+               if (dev) {
+                       unsigned short busdevfn;
+                       regs->eax = 0;
+                       // busnum is an unsigned char;
+                       // devfn is an int, so we mask it off.
+                       busdevfn = (dev->bus->secondary << 8)
+                               | (dev->path.pci.devfn & 0xff);
+                       printk(BIOS_DEBUG, "0x%x: return 0x%x\n", func, 
busdevfn);
+                       regs->ebx = busdevfn;
+                       retval = 0;
+               } else {
+                       regs->eax = PCIBIOS_NODEV;
+                       retval = -1;
+               }
+       }
+       break;
+       case READCONFDWORD:
+       case READCONFWORD:
+       case READCONFBYTE:
+       case WRITECONFDWORD:
+       case WRITECONFWORD:
+       case WRITECONFBYTE:
+       {
+               unsigned long dword;
+               unsigned short word;
+               unsigned char byte;
+               unsigned char reg;
+
+               devfn = regs->ebx & 0xff;
+               bus = regs->ebx >> 8;
+               reg = regs->edi;
+               dev = dev_find_slot(bus, devfn);
+               if (! dev) {
+                       printk(BIOS_DEBUG, "0x%x: BAD DEVICE bus %d devfn 
0x%x\n", func, bus, devfn);
+                       // idiots. the pcibios guys assumed you'd never pass a 
bad bus/devfn!
+                       regs->eax = PCIBIOS_BADREG;
+                       retval = -1;
+               }
+               switch(func) {
+               case READCONFBYTE:
+                       byte = pci_read_config8(dev, reg);
+                       regs->ecx = byte;
+                       break;
+               case READCONFWORD:
+                       word = pci_read_config16(dev, reg);
+                       regs->ecx = word;
+                       break;
+               case READCONFDWORD:
+                       dword = pci_read_config32(dev, reg);
+                       regs->ecx = dword;
+                       break;
+               case WRITECONFBYTE:
+                       byte = regs->ecx;
+                       pci_write_config8(dev, reg, byte);
+                       break;
+               case WRITECONFWORD:
+                       word = regs->ecx;
+                       pci_write_config16(dev, reg, word);
+                       break;
+               case WRITECONFDWORD:
+                       dword = regs->ecx;
+                       pci_write_config32(dev, reg, dword);
+                       break;
+               }
+
+               if (retval)
+                       retval = PCIBIOS_BADREG;
+               printk(BIOS_DEBUG, "0x%x: bus %d devfn 0x%x reg 0x%x val 
0x%x\n",
+                            func, bus, devfn, reg, regs->ecx);
+               regs->eax = 0;
+               retval = 0;
+       }
+       break;
+       default:
+               printk(BIOS_ERR, "UNSUPPORTED PCIBIOS FUNCTION 0x%x\n",  func);
+               break;
+       }
+
+       return retval;
+}
+
+int int15_handler(struct eregs *regs)
+{
+       int res = -1;
+
+       /* This int15 handler is VIA Tech. specific. Other chipsets need other
+        * handlers. The right way to do this is to move this handler code into
+        * the mainboard or northbridge code.
+        */
+       switch (regs->eax & 0xffff) {
+       case 0x5f19:
+               break;
+       case 0x5f18:
+               regs->eax = 0x5f;
+               // MCLK = 133, 32M frame buffer, 256 M main memory
+               regs->ebx = 0x545;
+               regs->ecx = 0x060;
+               res = 0;
+               break;
+       case 0x5f00:
+               regs->eax = 0x8600;
+               break;
+       case 0x5f01:
+               regs->eax = 0x5f;
+               regs->ecx = (regs->ecx & 0xffffff00 ) | 2; // panel type =  2 = 
1024 * 768
+               res = 0;
+               break;
+       case 0x5f02:
+               regs->eax = 0x5f;
+               regs->ebx = (regs->ebx & 0xffff0000) | 2;
+               regs->ecx = (regs->ecx & 0xffff0000) | 0x401;  // PAL + crt only
+               regs->edx = (regs->edx & 0xffff0000) | 0;  // TV Layout - 
default
+               res = 0;
+               break;
+       case 0x5f0f:
+               regs->eax = 0x860f;
+               break;
+       /* And now Intel IGD code */
+#define BOOT_DISPLAY_CRT        (1 << 0)
+#define BOOT_DISPLAY_TV         (1 << 1)
+#define BOOT_DISPLAY_EFP        (1 << 2)
+#define BOOT_DISPLAY_LCD        (1 << 3)
+#define BOOT_DISPLAY_CRT2       (1 << 4)
+#define BOOT_DISPLAY_TV2        (1 << 5)
+#define BOOT_DISPLAY_EFP2       (1 << 6)
+#define BOOT_DISPLAY_LCD2       (1 << 7)
+
+       case 0x5f35:
+               regs->eax = 0x5f;
+               regs->ecx = BOOT_DISPLAY_LCD|BOOT_DISPLAY_CRT;
+               res = 0;
+               break;
+       case 0x5f40:
+               regs->eax = 0x5f;
+               regs->ecx = 3; // This is mainboard specific
+               printk(BIOS_DEBUG, "DISPLAY=%x\n", regs->ecx);
+               res = 0;
+               break;
+       default:
+               printk(BIOS_DEBUG, "Unknown INT15 function %04x!\n", 
+                               regs->eax & 0xffff);
+       }
+
+       return res;
+}
+


-- 
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to