--- qemu-kvm-0.12.5+dfsg.orig/.gitignore
+++ qemu-kvm-0.12.5+dfsg/.gitignore
@@ -1,52 +1,63 @@
-config-devices.*
-config-all-devices.*
-config-host.*
-config-target.*
-i386
-*-softmmu
-*-darwin-user
-*-linux-user
-*-bsd-user
-libhw32
-libhw64
-libuser
-qemu-doc.html
-qemu-tech.html
-qemu-doc.info
-qemu-tech.info
-qemu.1
-qemu.pod
-qemu-img.1
-qemu-img.pod
-qemu-img
-qemu-nbd
-qemu-nbd.8
-qemu-nbd.pod
-qemu-options.texi
-qemu-img-cmds.texi
-qemu-img-cmds.h
-qemu-io
-qemu-monitor.texi
-.gdbinit
-*.a
-*.aux
-*.cp
-*.dvi
-*.exe
-*.fn
-*.ky
-*.log
-*.pg
-*.toc
-*.tp
-*.vr
-*.d
 *.o
-.pc
-patches
-pc-bios/bios-pq/status
-pc-bios/vgabios-pq/status
-pc-bios/optionrom/multiboot.bin
-pc-bios/optionrom/multiboot.raw
-pc-bios/optionrom/extboot.bin
-.stgit-*
+*.d
+*~
+*.flat
+*.a
+config.mak
+.*.cmd
+qemu/config-host.h
+qemu/config-host.mak
+user/test/bootstrap
+user/kvmctl
+qemu/dyngen
+qemu/x86_64-softmmu
+qemu/qemu-img
+qemu/qemu-nbd
+*.ko
+*.mod.c
+kernel/kvm_main.c
+kernel/kvm.h
+kernel/kvm_svm.h
+kernel/vmx.[ch]
+kernel/svm.[ch]
+kernel/mmu.c
+kernel/paging_tmpl.h
+kernel/segment_descriptor.h
+kernel/x86_emulate.[ch]
+kernel/include/linux/kvm*.h
+kernel/Module.symvers
+kernel/Modules.symvers
+kernel/.tmp_versions
+bios/*.bin
+bios/*.sym
+bios/*.txt
+bios/acpi-dsdt.aml
+vgabios/*.bin
+vgabios/*.txt
+extboot/extboot.bin
+extboot/extboot.img
+extboot/signrom
+kernel/Module.markers
+kernel/i825[49].[ch]
+kernel/include-compat/asm
+kernel/include-compat/asm-x86/asm-x86
+kernel/include
+kernel/ioapic.[ch]
+kernel/iodev.h
+kernel/irq.[ch]
+kernel/kvm_trace.c
+kernel/lapic.[ch]
+kernel/mmu.h
+kernel/modules.order
+kernel/tss.h
+kernel/x86.[ch]
+kernel/coalesced_mmio.c
+kernel/coalesced_mmio.h
+kernel/kvm_cache_regs.h
+qemu/pc-bios/extboot.bin
+qemu/qemu-doc.html
+qemu/*.[18]
+qemu/*.pod
+qemu/qemu-tech.html
+user/kvmtrace
+user/test/x86/bootstrap
--- qemu-kvm-0.12.5+dfsg.orig/debian/qemu-kvm.init
+++ qemu-kvm-0.12.5+dfsg/debian/qemu-kvm.init
@@ -0,0 +1,74 @@
+#! /bin/sh
+### BEGIN INIT INFO
+# Provides:          qemu-kvm kvm
+# Required-Start:    
+# Required-Stop:     
+# Default-Start:     2 3 4 5
+# Default-Stop:      0 1 6
+# Short-Description: KVM init script
+# Description:       This script loads the kernel modules needed by kvm
+### END INIT INFO
+
+. /lib/lsb/init-functions
+
+# Figure out which module we need.
+if grep -q ^flags.*\\\<vmx\\\> /proc/cpuinfo
+then
+	module=kvm_intel
+elif grep -q ^flags.*\\\<svm\\\> /proc/cpuinfo
+then
+	module=kvm_amd
+else
+	module=
+fi
+
+case "$1" in
+  start)
+	if [ -z "$module" ]
+	then
+		log_failure_msg "Your system does not have the CPU extensions required to use KVM. Not doing anything."
+		exit 0
+	fi
+	if [ -c /dev/kvm -a /dev/.udev ]
+	then
+		log_success_msg "/dev/kvm already exists. Not doing anything."
+		exit 0
+	fi
+	if modprobe "$module" 
+	then
+		log_success_msg "Loading kvm module $module"
+	else
+		log_failure_msg "Module $module failed to load"
+		exit 1
+	fi
+	;;
+  stop)
+	if [ -z "$module" ]
+	then
+		exit 0
+	fi
+	if lsmod | grep -q "$module"
+	then
+		if rmmod "$module" 
+		then
+			log_success_msg "Succesfully unloaded kvm module $module"
+			rmmod kvm
+		else
+			log_failure_msg "Failed to remove $module"
+			exit 1
+		fi
+	else
+		log_failure_msg "Module $module not loaded"
+	fi
+	;;
+  force-reload|restart)
+	$0 stop
+	$0 start
+	;;
+  *)
+	echo "Usage: $0 {start|stop|restart|force-reload}" >&2
+	exit 3
+	;;
+esac
+
+:
--- qemu-kvm-0.12.5+dfsg.orig/debian/qemu-kvm.preinst
+++ qemu-kvm-0.12.5+dfsg/debian/qemu-kvm.preinst
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+set -e
+
+# Remove a no-longer used conffile
+# (from http://wiki.debian.org/DpkgConffileHandling)
+rm_conffile() {
+    PKGNAME="$1"
+    CONFFILE="$2"
+
+    [ -e "$CONFFILE" ] || return 0
+
+    md5sum="$(md5sum $CONFFILE | sed -e 's/ .*//')"
+    old_md5sum="$(dpkg-query -W -f='${Conffiles}' $PKGNAME | \
+            sed -n -e "\' $CONFFILE ' { s/ obsolete$//; s/.* //; p }")"
+    if [ "$md5sum" != "$old_md5sum" ]; then
+        echo "Obsolete conffile $CONFFILE has been modified by you."
+        echo "Saving as $CONFFILE.dpkg-bak ..."
+        mv -f "$CONFFILE" "$CONFFILE".dpkg-bak
+    else
+        echo "Removing obsolete conffile $CONFFILE ..."
+        rm -f "$CONFFILE"
+    fi
+}
+
+case "$1" in
+install|upgrade)
+    # deal with old conffiles owned by kvm package
+    kvmver="$(dpkg-query -W -f='${Version}' kvm 2>/dev/null || :)"
+    if [ -n "$kvmver" ]; then
+        rm_conffile kvm /etc/kvm/utils/kvm
+	rm_conffile kvm /etc/init.d/kvm
+    fi
+esac
+
+#DEBHELPER#
+
--- qemu-kvm-0.12.5+dfsg.orig/debian/qemu-kvm.install
+++ qemu-kvm-0.12.5+dfsg/debian/qemu-kvm.install
@@ -0,0 +1,8 @@
+etc/kvm/kvm-ifup
+etc/kvm/kvm-ifdown
+usr/bin/*
+usr/share/doc/qemu-kvm/*
+usr/share/kvm/*
+usr/share/kvm/keymaps/*
+usr/share/man/man1/*
+usr/share/man/man8/*
--- qemu-kvm-0.12.5+dfsg.orig/debian/changelog
+++ qemu-kvm-0.12.5+dfsg/debian/changelog
@@ -0,0 +1,307 @@
+qemu-kvm (0.12.5+dfsg-5+squeeze7) stable; urgency=low
+
+  * stash-away-SCM_RIGHTS-fd-until-a-getfd-command-arrives-e53f27b9d9.diff
+    patch from upstream (included in 0.13 and up, and also in ubuntu)
+    to fix NIC hotplug from libvirt (Closes: #637990)
+
+ -- Michael Tokarev <mjt@tls.msk.ru>  Wed, 17 Aug 2011 13:35:03 +0400
+
+qemu-kvm (0.12.5+dfsg-5+squeeze6) stable-security; urgency=low
+
+  * virtio-fix-indirect-descriptor-buffer-overflow-CVE-2011-2212
+    fixes a guest-triggerable buffer overflow in virtio handling
+    (closes: #632987)
+  * os-posix-set-groups-properly-for--runas-CVE-2011-2527
+    clears supplementary groups for -runas (closes: #633669)
+
+ -- Michael Tokarev <mjt@tls.msk.ru>  Wed, 13 Jul 2011 01:45:15 +0400
+
+qemu-kvm (0.12.5+dfsg-5+squeeze4) stable-security; urgency=high
+
+  * virtio: guard against negative vq notifies -- fixes a guest-triggerable
+    bug in virtio implementation (CVE-2011-2512) (Closes: #631975)
+
+ -- Michael Tokarev <mjt@tls.msk.ru>  Wed, 29 Jun 2011 00:44:36 +0400
+
+qemu-kvm (0.12.5+dfsg-5+squeeze3) stable; urgency=low
+
+  * cirrus_vga:fix-division-by-0-for-color-expansion-rop-92d675d1c1.diff
+   (fix from upstream) - fixes division by zero with some guests
+   like WinNT 4.0 and WinME.
+  * fix-vnc-zlib-overflow.diff (backport from 0.14) (closes: #616159)
+  * qdev-dont-hw_error-in-qdev_init_nofail-bd6c9a61.diff -
+    don't abort but exit on user errors (closes: #619452)
+  * fix transitional kvm package description (closes: #625206)
+  * fix long-standing migration bug on 32bits (closes: #625571)
+
+ -- Michael Tokarev <mjt@tls.msk.ru>  Sat, 28 May 2011 13:39:58 +0400
+
+qemu-kvm (0.12.5+dfsg-5+squeeze2) stable-security; urgency=high
+
+  * fix CVE-2011-1751 for 0.12.  The actual fix is in
+    hotplug-4-ignore-pci-hotplug-requests-for-unpluggable-devices-CVE-2011-1751
+    but that change, while trivial, required 6 more changes to be backported
+    to 0.12:
+   o pci-cleanly-backout-of-pci_qdev_init-925fe64ae7
+      (moving common code to a separate function and using it from another
+      place to fix a memory leak)
+   o hotplug-0-acpi_piix4-qdevfy-e8ec0571e1
+      this qdevifies acpi_piix4 device
+   o hotplug-1-pci-allow-devices-being-tagged-as-not-hotpluggable-180c22e18b
+      introduce a "no_hotplug" attribute and check it in common places
+      to ensure such devices wont be hot-(un)plugged.  This needs
+      the pci-cleanly-backout-of-pci_qdev_init patch mentioned above
+   o hotplug-2-piix-tag-as-not-hotpluggable-0965f12da6
+   o hotplug-3-vga-tag-as-not-hotplugable-be92bbf73d
+      mark certain devices as non-hotpluggable
+    And finally the actual fix for CVE-2011-1751, which verifies the
+    no_hotplug attribute when handling hot-unplug request from guest.
+    (closes: #627448)
+
+ -- Michael Tokarev <mjt@tls.msk.ru>  Sat, 21 May 2011 10:45:52 +0400
+
+qemu-kvm (0.12.5+dfsg-5+squeeze1) stable-security; urgency=high
+
+  * fix CVE-2011-0011: Setting VNC password to empty string
+    silently disables all authentication (Closes: #611134)
+  * fix CVE-2011-1750: virtio-blk: heap buffer overflow caused
+     by unaligned requests (Closes: #624177)
+  * urgency is high due to #624177
+
+ -- Michael Tokarev <mjt@tls.msk.ru>  Sat, 21 May 2011 10:45:03 +0400
+
+qemu-kvm (0.12.5+dfsg-5) unstable; urgency=low
+
+  [ Michael Tokarev ]
+  * scsi:-Dequeue-requests-before-invoking-completion-callback.diff
+    fix SIGSEGV when using lsil scsi emulation, from upstream
+    (closes: #603223)
+  * seabios-mark-irq9-active-high-in-DSDT.diff - fix non-working
+    acpi buttons (system_powerdown) for FreeBSD and other guests.
+  * don't ship roms/seabios/src/acpi-dsdt.hex which is a generated file
+    (this ensures it gets rebuilt properly after previous patch too),
+    and fix their makefile to properly state deps from it (closes: #603219)
+  * two patches from upstream git to fix alsa audio issues:
+    - fix-100%-CPU-load-when-idle-with-ALSA.diff
+    - issue-snd_pcm_start-when-capturing-audio.diff
+    (closes: #588899)
+
+ -- Jan Lübbe <jluebbe@debian.org>  Fri, 12 Nov 2010 11:18:12 +0100
+
+qemu-kvm (0.12.5+dfsg-4) unstable; urgency=low
+
+  [ Michael Tokarev ]
+  * QEMUFileBuffered:-indicate-that-were-ready-when-the-underlying-file-is-ready.diff
+   (patch from upstream to speed up migration dramatically)
+   (closes: #597517)
+  * use versioned build-depends for etherboot now when it's available in bpo
+    (closes: #588940, #581356, #598802)
+
+ -- Guido Günther <agx@sigxcpu.org>  Mon, 04 Oct 2010 09:36:58 +0200
+
+qemu-kvm (0.12.5+dfsg-3) unstable; urgency=medium
+
+  [ Michael Tokarev ]
+  * CVE-2010-2784-fix-segfault-in-mmio-subpage-handling-code.diff
+    (closes: #594478)
+
+ -- Jan Lübbe <jluebbe@debian.org>  Sat, 04 Sep 2010 19:29:59 +0200
+
+qemu-kvm (0.12.5+dfsg-2) unstable; urgency=low
+
+  [ Michael Tokarev ]
+  * patch from upstream: add-support-for-GET-EVENT-STATUS-NOTIFICATION.diff
+    (closes: #593144)
+  * two patches from upstream qemu/stable-0.12:
+    upstream-stable01-make-PIIX-and-ISA-IDE-init-functions-return-the-qdev.diff
+    upstream-stable02-fix-CMOS-info-for-drives-defined-with--device.diff
+    (closes: #588739)
+  * revert-all-bdrv_write_sync-changes.diff - this patch reverts the changes
+    which went into 0.12.5 upstream and make all metadata writes (for qcow&Co)
+    syncronous.  Yes it's more correct, but the resulting write speed is
+    insanely slow and makes all image formats except raw unusable.
+    (closes: #594069)
+
+ -- Jan Lübbe <jluebbe@debian.org>  Wed, 25 Aug 2010 13:15:11 +0200
+
+qemu-kvm (0.12.5+dfsg-1) unstable; urgency=low
+
+  [ Michael Tokarev ]
+  * new upstream bugfix/minor release, with many bugfixes
+    incorporated:
+     block:-fix-sector-comparism-in-multiwrite_req_compare.diff
+     pci:-irq_state-vmstate-breakage.diff
+    (closes: #589009, #582493, #580649)
+  * add /etc/kvm/kvm-ifdown (dummy) script (closes: #583590)
+  * add seabios-ps2-fixes.diff (two patches from seabios git)
+    (closes: #591266)
+  * sdl-do-not-disable-screensaver.diff (closes: #578672)
+  * fix-curses-return-key-when-using--k.diff (closes: #583478)
+  * vmstate:-fix-breakage-by-7e72abc382b700a72549e8147bdea413534eeedc.diff
+    (fixes cirrus vga breakage on migration)
+  * added qdev-device-use.txt documentation file from upstream
+  * actually ship debian/changelog.upstream-qemu-kvm
+
+  [ Jan Lübbe ]
+  * Add Michael Tokarev as Uploader
+  * Update Standards-Version to 3.9.1 (don't reference BSD license from
+    common-licenses)
+
+ -- Jan Lübbe <jluebbe@debian.org>  Mon, 09 Aug 2010 14:23:37 +0200
+
+qemu-kvm (0.12.4+dfsg-1) unstable; urgency=low
+
+  [ Michael Tokarev ]
+  * New upstream minor/stable release 0.12.4, incorporating
+    the following patches:
+     avoid_creating_too_large_iovecs_in_multiwrite_merge.patch
+     net:-remove-broken-net_set_boot_mask-boot-device-validation.diff
+     block:-free-iovec-arrays-allocated-by-multiwrite_merge.diff
+     bail-out-when-VCPU_CREATE-fails.diff
+  * add madv_mergeable-for-old-kernheaders-hack.diff, mostly
+    to help bpo builds (it is to enable KMS even when compiled
+    against old kernel headers, when running on recent-enough
+    kernel)
+  * fix kvm transitional package to have Priority: extra
+  * also fix kvm transitional package to properly run with reportbug,
+    and simplify the bug-script and use dh_bugfiles to install them.
+  * adedd isa-refine-irq-reservations.patch from Gerd Hoffmann
+    (closes: #574051)
+  * added be_more_specific_in_-mem-path_error_messages.diff trivial 
+    patch to be more specific when throwing errors. (closes: #574073)
+  * bump debhelper build-depend version to 7.2.3 due to dh_bugfiles.
+  * net:-remove-broken-net_set_boot_mask-boot-device-validation.diff
+    (to let it to boot from network using new -netdev syntax, cherry-
+    picked from stable) (closes: #575628)
+  * block:-free-iovec-arrays-allocated-by-multiwrite_merge.diff
+    to fix a memory leak in virtio-blk implementation
+  * rehash 04_use_etc_kvm_kvm-ifup.patch - apparently the #defines
+    are now in two places, remove one of them and patch another
+  * bail-out-when-VCPU_CREATE-fails.diff - new patch to make kvm to behave
+    a bit nicely if vcpu_create fails: before it were just segfaulting.
+    (closes: #558029)
+  * give-useful-error-messages-when-tap-open-fails.diff: when manipulation
+    of /dev/net/tun fails, give some more useful error messages.
+    (closes: #578154)
+  * document -incoming option (document--incoming-option.diff).
+    (closes: #565573)
+  * (preliminary) fix for usb keyboard keymap, usbkbd-menu-logo-keys.diff.
+    (closes: #578846)
+
+ -- Jan Lübbe <jluebbe@debian.org>  Tue, 18 May 2010 22:43:54 +0200
+
+qemu-kvm (0.12.3+dfsg-4) unstable; urgency=low
+
+  [ Michael Tokarev ]
+  * added patch from upstream, ff5414990645653bf43bf64adfc1ca77ffb9edcb,
+    revert-sdlaudio:-make-it-suck-less.diff (closes: #572943)
+    Note that this is only relevant to sdl audio (QEMU_AUDIO_DRV=sdl)
+  * don't report system dmi information in the bugreports anymore, it
+    serves almost no useful purpose these days, much less than previously.
+    VMX/SVM is either enabled or not, and if it is not enabled, kvm module
+    will warn user about this fact in dmesg during load.
+    (closes: #572930, #572924)
+  * switch back to vgabios as shipped in upstream tarball in kvm/vgabios.
+    I overlooked it, thinking it went away together with seabios as
+    both roms/seabios and roms/vgabios are empty in upstream, but vgabios
+    has never been removed.  So we're back at using it.
+    Big thanks to Bjørn Mork for the hard work he did finding bugs in the
+    version we shipped in 0.12.3+dfsg-2, which is wrong and the work
+    should have not been required.  But it helped finding all the pieces
+    finally. (closes: #572991)
+  * build-depend on linux-libc-dev >= 2.6.32, to enable KSM (Kernel 
+    Samepage Merge) and to ensure we'll not have spurious preadv()
+    problems
+  * build-depend on libaio-dev to compile in aio support
+    (which does not do any harm if not explicitly enabled)
+  * fix cleanups of old conffiles in preinst. (closes: #573280)
+  * include 573439-fail-to-set-hdd-serial-number.diff - a fix by
+    Kouichi ONO broken hdd serial number support (closes: #573439)
+
+ -- Jan Lübbe <jluebbe@debian.org>  Thu, 11 Mar 2010 17:15:31 +0100
+
+qemu-kvm (0.12.3+dfsg-3) unstable; urgency=low
+
+  [ Michael Tokarev ]
+  * fix number of jobs for seabios build to 1 (-j1)
+    or else it breaks parallel builds
+  * Ctrl-Alt-f for fullscreen is fixed in 0.12.3 (closes: #559086).
+  * added avoid_creating_too_large_iovecs_in_multiwrite_merge.patch
+    that fixes spontaneous I/O errors in guests under load.
+
+ -- Jan Lübbe <jluebbe@debian.org>  Sun, 07 Mar 2010 12:45:30 +0100
+
+qemu-kvm (0.12.3+dfsg-2) unstable; urgency=low
+
+  [ Jan Lübbe ]
+  * Build qemu-kvm-dbg and kvm packages only on i386 and amd64.
+
+  [ Michael Tokarev ]
+  * build seabios and vgabios with verbose logging
+
+ -- Jan Lübbe <jluebbe@debian.org>  Sat, 06 Mar 2010 16:25:45 +0100
+
+qemu-kvm (0.12.3+dfsg-1) unstable; urgency=low
+
+  [ Michael Tokarev ]
+  * New Upstream Version 0.12. (closes: #568804)
+    (Apparently closes: #570245)
+  * update list of files to remove for DFSG,
+    and reorganize the procedure a bit
+  * add sources for vgabios and seabios as patches from qemu-0.12.3.tar.gz
+    (since qemu-kvm-0.12.x.tar.gz does not have them).  For now we can't use
+    an external package (#489442) because qemu(-kvm) is too closely tied to
+    bios versions and the risk to get a non-working system with external
+    packages is still too high.
+  * ship kvm transitional package; set version number for it so it will
+    be higher than real kvm, and conflict/replace that old kvm in qemu-kvm.
+    (closes: #565547)
+  * remove some irrelevant patches (10-ksm-support, 07_set_sdl_title,
+    09_qemu-fix-qcow2-backing-file-with-virtio,
+    from-debian-qemu/22_net_tuntap_stall)
+  * remove/backup /etc/init.d/kvm in preinst, so that only one startup
+    script will provide kvm service, and also remove other kvm conffile
+    leftovers. (closes: #557766)
+  * split get-orig-source rule into two (tarball + dfsg)
+  * update Standards-Version to 3.8.4 (no changes needed)
+
+  [ Jan Lübbe ]
+  * Build-Depend on python for seabios
+
+ -- Jan Lübbe <jluebbe@debian.org>  Sat, 06 Mar 2010 13:42:46 +0100
+
+qemu-kvm (0.11.1+dfsg-1) unstable; urgency=low
+
+  [ Jan Lübbe ]
+  * New upstream release
+  * Provide kvm from qemu-kvm (closes: #558026)
+
+  [ Michael Tokarev ]
+  * clean up kvm/userspace in `clean' target or else the package
+    does not build twice in a row (closes: #527371).
+    Also add more workarounds to the clean target, namely,
+    clean up kvm/user/test/lib from .*.d files and remove
+    generated qemu-monitor.texi
+  * fix /etc/kvm/kvm-ifup script (missing {} in awk), thanks to
+    Andrea Zagli for the fix (closes: #560436)
+  * check in /etc/kvm/kvm-ifup that we actually found default route
+    interface and that it's actually a bridge
+  * handle etherboot-5.4.4 which moved roms from /usr/share/etherboot
+    to /usr/lib/etherboot and actually provided virtio boot rom.  Thanks
+    to John Morrissey for the fix and patch. (closes: #522179).
+
+  [ Jan Lübbe ]
+  * Remove NAME="%k" from udev rule (closes: #559300)
+
+  [ Guido Günther ]
+  * add ksm support
+
+ -- Jan Lübbe <jluebbe@debian.org>  Mon, 11 Jan 2010 14:48:32 +0100
+
+qemu-kvm (0.11.0+dfsg-1) unstable; urgency=low
+
+  * Package qemu-kvm (stable series) instead of kvm (snapshots)
+  * Simplify the packaging, remove support for external module source
+  * Move old debian/changelog to debian/changlog.kvm
+
+ -- Jan Lübbe <jluebbe@debian.org>  Mon, 02 Nov 2009 11:49:28 +0100
--- qemu-kvm-0.12.5+dfsg.orig/debian/kvm-ifdown
+++ qemu-kvm-0.12.5+dfsg/debian/kvm-ifdown
@@ -0,0 +1,6 @@
+#! /bin/sh
+# Script to shut down a network (tap) device for qemu-kvm
+# Initially this script is empty, but you can configure,
+# for example, accounting info here.
+
+:
--- qemu-kvm-0.12.5+dfsg.orig/debian/changelog.upstream-qemu-kvm
+++ qemu-kvm-0.12.5+dfsg/debian/changelog.upstream-qemu-kvm
@@ -0,0 +1,394 @@
+Changes from qemu-kvm-0.12.4 to qemu-kvm-0.12.5
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Alex Williamson (1):
+      Fix segfault after device assignment hot remove
+
+Alexander Graf (1):
+      Fix multiboot compilation
+
+Aurelien Jarno (3):
+      target-mips: fix DINSU instruction
+      qemu-options: add documentation for stdio signal=on|off
+      Update for 0.12.5 release
+
+Avi Kivity (1):
+      block: fix aio_flush segfaults for read-only protocols (e.g. curl)
+
+Chih-Min Chao (3):
+      target-arm: fix addsub/subadd implementation
+      target-arm : fix thumb2 parallel add/sub opcode decoding
+      target-arm : fix parallel saturated subtraction implementation
+
+Christoph Hellwig (2):
+      block: fix sector comparism in multiwrite_req_compare
+      virtio-blk: fix barrier support
+
+Jan Kiszka (1):
+      Avoid crash on '-usbdevice <device>' without parameters
+
+Jens Osterkamp (1):
+      qemu-sockets: avoid strlen of NULL pointer
+
+Jes Sorensen (1):
+      Correct definitions for FD_CMD_SAVE and FD_CMD_RESTORE
+
+Kevin Wolf (19):
+      ide: Fix ide_dma_cancel
+      qcow2: Clear L2 table cache after write error
+      qcow2: Fix error handling in l2_allocate
+      block: Fix multiwrite with overlapping requests
+      qcow2: Fix corruption after refblock allocation
+      qcow2: Fix corruption after error in update_refcount
+      vmdk: fix double free
+      qcow2: Fix creation of large images
+      vmdk: Fix COW
+      qcow2: Remove abort on free_clusters failure
+      block/vdi: Fix image opening and creation for odd disk sizes
+      qcow2: Restore L1 entry on l2_allocate failure
+      block: Add bdrv_(p)write_sync
+      qcow: Use bdrv_(p)write_sync for metadata writes
+      qcow2: Use bdrv_(p)write_sync for metadata writes
+      vmdk: Use bdrv_(p)write_sync for metadata writes
+      vpc: Use bdrv_(p)write_sync for metadata writes
+      block: Fix early failure in multiwrite
+      block: Handle multiwrite errors only when all requests have completed
+
+Kirill A. Shutemov (1):
+      block/vvfat.c: fix warnings with _FORTIFY_SOURCE
+
+Loïc Minier (1):
+      Fix missing symbols in .rel/.rela.plt sections
+
+Luiz Capitulino (1):
+      usb-bus: fix no params
+
+Michael S. Tsirkin (1):
+      pci: irq_state vmstate breakage
+
+Paul Brook (1):
+      Fix -usbdevice crash
+
+Rabin Vincent (2):
+      arm_timer: reload timer when enabled
+      arm_timer: fix oneshot mode
+
+Riccardo Magliocchetti (1):
+      Fix typo in balloon help
+
+Richard Henderson (1):
+      target-i386: fix xchg rax,r8
+
+Stefan Weil (1):
+      block/vpc: Fix conversion from size to disk geometry
+
+TeLeMan (1):
+      qemu-img: use the heap instead of the huge stack array for win32
+
+Thomas Monjalon (1):
+      target-ppc: fix RFI by clearing some bits of MSR
+
+Vagrant Cascadian (1):
+      audio/alsa: Spelling typo (paramters)
+
+malc (1):
+      audio/alsa: Handle SND_PCM_STATE_SETUP in alsa_poll_handler
+
+
+Changes from qemu-kvm-0.12.3 to qemu-kvm-0.12.4
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Alexander Graf (1):
+      Bail out when VCPU_CREATE fails
+
+Anthony Liguori (1):
+      Update for 0.12.4 release
+
+Aurelien Jarno (11):
+      Fix qemu -net user,hostfwd= example
+      target-i386: fix lddqu SSE instruction
+      target-i386: fix SIB decoding with index = 4
+      tcg/arm: correctly save/restore registers in prologue/epilogue
+      tcg/mips: fix branch offset during retranslation
+      sh7750: handle MMUCR TI bit
+      target-sh4: MMU: fix mem_idx computation
+      target-sh4: MMU: fix ITLB priviledge check
+      target-sh4: MMU: fix store queue addresses
+      linux-user: switch default ppc64 CPU to 970fx from 970
+      sh_pci: fix memory and I/O access
+
+Avi Kivity (1):
+      Merge commit 'v0.12.4' into stable-0.12
+
+Chris Webb (1):
+      Fix SIGFPE for vnc display of width/height = 1
+
+Christoph Hellwig (1):
+      block: avoid creating too large iovecs in multiwrite_merge
+
+Eduardo Habkost (1):
+      net: remove broken net_set_boot_mask() boot device validation
+
+Gerd Hoffmann (9):
+      fdc: fix drive property handling.
+      pci passthrough: zap option rom scanning.
+      scsi-disk: fix buffer overflow
+      lsi: use QTAILQ for lsi_queue
+      lsi: have lsi_request for the whole life time of the request.
+      lsi: move current_dev into lsi_request
+      lsi: move dma_len+dma_buf into lsi_request
+      lsi: pass lsi_request to lsi_reselect
+      lsi: fix segfault in lsi_command_complete
+
+Igor V. Kovalenko (1):
+      workaround for cmd646 bmdma register access while no dma is active
+
+Jan Kiszka (3):
+      qemu-char.c: drop debug printfs from qemu_chr_parse_compat
+      Don't set default monitor when there is a mux'ed one
+      Fix corner case in chardev udp: parameter
+
+Juergen Lock (1):
+      Workaround for broken OSS_GETVERSION on FreeBSD, part two
+
+Kevin Wolf (8):
+      json-parser: Fix segfault on malformed input
+      qcow2: Factor next_refcount_table_size out
+      qcow2: Rewrite alloc_refcount_block/grow_refcount_table
+      block: Fix multiwrite error handling
+      block: Fix error code in multiwrite for immediate failures
+      block: Fix multiwrite memory leak in error case
+      qcow2: Don't ignore immediate read/write failures
+      qcow2: Remove request from in-flight list after error
+
+Marcelo Tosatti (1):
+      Fix incoming migration with iothread
+
+Paolo Bonzini (1):
+      fix undefined shifts by >32
+
+Paul Brook (1):
+      UHCI spurious interrut fix
+
+Ryan Harper (1):
+      Fix segfault with ram_size > 4095M without kvm
+
+Stefan Hajnoczi (1):
+      block: Free iovec arrays allocated by multiwrite_merge()
+
+Stefan Weil (1):
+      tcp/mips: Change TCG_AREG0 (fp -> s0)
+
+TeLeMan (1):
+      target-i386: fix commit c22549204a6edc431e8e4358e61bd56386ff6957
+
+Vagrant Cascadian (1):
+      spelling typo (compatibilty) in hw/fw_cfg.c
+
+malc (5):
+      target-i386: Fix long jumps/calls in long mode with REX.W set
+      oss: workaround for cases when OSS_GETVERSION is not defined
+      oss: refactor code around policy setting
+      oss: issue OSS_GETVERSION ioctl only when needed
+      oss: fix fragment setting
+
+
+Changes from qemu-kvm-0.12.2 to qemu-kvm-0.12.3
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Adam Litke (1):
+      QMP: Emit asynchronous events on all QMP monitors
+
+Anthony Liguori (2):
+      pc-bios: update to newer version of (stable) seabios
+      Update version and change for 0.12.3 release
+
+Aurelien Jarno (3):
+      target-mips: don't call cpu_loop_exit() from helper.c
+      tcg/mips: fix crash in tcg_out_qemu_ld()
+      target-mips: fix ROTR and DROTR by zero
+
+Brian Jackson (1):
+      Increase VNC_MAX_WIDTH
+
+David S. Ahern (1):
+      segfault due to buffer overrun in usb-serial
+
+Evgeniy Dushistov (1):
+      Do not ignore error, if open file failed (-serial /dev/tty)
+
+Gerd Hoffmann (3):
+      ide: device version property
+      scsi: device version property
+      pc: add driver version compat properties
+
+Gleb Natapov (1):
+      reduce number of reinjects on ACK
+
+Herve Poussineau (2):
+      win32: pair qemu_memalign() with qemu_vfree()
+      win32/sdl: Fix toggle full screen
+
+Jan Kiszka (6):
+      Musicpal: Fix wm8750 I2C address
+      Musicpal: Fix descriptor walk in eth_send
+      cirrus: Properly re-register cirrus_linear_io_addr on vram unmap
+      KVM: Request setting of nmi_pending and sipi_vector
+      kvm: Fix eflags corruption in kvm mode
+      kvm: Fix eflags corruption in kvm mode
+
+Jim Meyering (1):
+      don't dereference NULL after failed strdup
+
+Kevin Wolf (16):
+      Fix QEMU_WARN_UNUSED_RESULT
+      qcow2: Fix error handling in qcow2_grow_l1_table
+      qcow2: Fix error handling in qcow_save_vmstate
+      qcow2: Return 0/-errno in get_cluster_table
+      qcow2: Return 0/-errno in qcow2_alloc_cluster_offset
+      block: Return original error codes in bdrv_pread/write
+      qcow2: Fix error handling in grow_refcount_table
+      qcow2: Improve error handling in update_refcount
+      qcow2: Allow updating no refcounts
+      qcow2: Don't ignore update_refcount return value
+      qcow2: Don't ignore qcow2_alloc_clusters return value
+      virtio_blk: Factor virtio_blk_handle_request out
+      virtio-blk: Fix restart after read error
+      virtio-blk: Fix error cases which ignored rerror/werror
+      qcow2: Fix signedness bugs
+      qcow2: Fix access after end of array
+
+Liu, Jinsong (1):
+      Fix kvm_load_mpstate for vcpu hot add
+
+Luiz Capitulino (1):
+      QMP: Fix asynchronous events delivery
+
+Marcelo Tosatti (7):
+      fix savevm command without id or tag
+      qemu-kvm: enable get/set vcpu events on reset and migration
+      Synchronize kvm headers
+      Do not allow vcpu stop with in progress PIO
+      iothread: fix vcpu stop with smp tcg
+      fix inet_parse typo
+      ide save/restore pio/atapi cmd transfer fields and io buffer
+
+Markus Armbruster (6):
+      net: Remove unused net_client_uninit()
+      net: net_check_clients() runs too early to see -device, fix
+      net: Fix bogus "Warning: vlan 0 with no nics" with -device
+      net: net_check_clients() checks only VLAN clients, fix
+      net: info network shows only VLAN clients, fix
+      net: Monitor command set_link finds only VLAN clients, fix
+
+Nathan Froyd (1):
+      target-mips: fix CpU exception for coprocessor 0
+
+Roy Tam (1):
+      json: fix PRId64 on Win32
+
+Stefan Weil (1):
+      Documentation: Add missing documentation for qdev related command line options
+
+Stefano Stabellini (1):
+      vnc_refresh: calling vnc_update_client might free vs
+
+Tom Lendacky (1):
+      virtio-net: fix network stall under load
+
+
+Changes from qemu-kvm-0.12.1 to qemu-kvm-0.12.2
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Anthony Liguori (4):
+      Merge remote branch 'mst/stable-0.12' into stable-0.12
+      vnc: Fix artifacts in hextile decoding
+      Update SeaBIOS to 0.5.1
+      Update version and changelog for release
+
+Artyom Tarasenko (2):
+      scsi-disk: Inquiry with allocation length of CDB < 36 (v4)
+      fdc/sparc32: don't hang on detection under OBP
+
+Aurelien Jarno (3):
+      cpu-all.h: fix cpu_get_real_ticks() #ifdef
+      target-i386: Fix "call im" on x86_64 when executing 32-bit code
+      loader: more ignores for rom intended to be loaded by the bios
+
+Avi Kivity (7):
+      Don't leak kvm_save_mpstate() to main qemu code
+      Don't load options roms intended to be loaded by the bios in qemu
+      linuxboot: fix gdt address calculation
+      Don't load options roms intended to be loaded by the bios in qemu
+      Reinstate cpuid vendor override when kvm is enabled
+      linuxboot: fix gdt address calculation
+      Merge remote branch 'upstream/stable-0.12' into stable-0.12
+
+Blue Swirl (1):
+      alpha: fix compile
+
+Chris Wright (1):
+      device assignment: default requires IOMMU
+
+Christoph Hellwig (1):
+      dmg: fix ->open failure
+
+Gerd Hoffmann (6):
+      pc: add machine type for 0.12
+      roms: minor fixes and cleanups.
+      fw_cfg: rom loader tweaks.
+      roms: rework rom loading via fw
+      pci: allow loading roms via fw_cfg.
+      pc: add rombar to compat properties for pc-0.10 and pc-0.11
+
+Gleb Natapov (1):
+      remove pending exception on vcpu reset.
+
+Huang Ying (1):
+      MCE: Fix bug of IA32_MCG_STATUS after system reset
+
+Jiri Denemark (1):
+      Fix CPU topology initialization
+
+Kevin Wolf (1):
+      osdep.c: Fix accept4 fallback
+
+Kirill A. Shutemov (1):
+      user_only: compile everything with -fpie
+
+Luiz Capitulino (2):
+      QMP: Drop wrong assert()
+      QMP: Don't free async event's 'data'
+
+Marcelo Tosatti (2):
+      dummy kvm_save_mpstate for CONFIG_KVM=n
+      Merge branch 'stable-0.12-upstream' into stable-0.12
+
+Michael S. Tsirkin (2):
+      e1000: fix init values for command register
+      virtio-pci: thinko fix
+
+Michael Tokarev (1):
+      Add missing newline at the end of options list
+
+Mikolaj Kucharski (1):
+      fix multiple definition of mulu64 and muls64 with user targets
+
+Milan Plzik (1):
+      Qemu's internal TFTP server breaks lock-step-iness of TFTP
+
+Roland Dreier (1):
+      vmware_vga: Check cursor dimensions passed from guest to avoid buffer overflow
+
+Scott Tsai (1):
+      USB: Improve usbdevice error messages
+
+Stefan Weil (1):
+      pc-bios: Update README (SeaBIOS)
+
+Stefano Stabellini (1):
+      vnc_refresh: return if vd->timer is NULL
+
+Thomas Horsten (1):
+      Handle TFTP ERROR from client
+
--- qemu-kvm-0.12.5+dfsg.orig/debian/changelog.kvm
+++ qemu-kvm-0.12.5+dfsg/debian/changelog.kvm
@@ -0,0 +1,686 @@
+kvm (88+dfsg-1) UNRELEASED; urgency=low
+
+  * update upstream changelog
+  * add upstream's fix for a module problem with 2.6.30
+
+ -- Jan Lübbe <jluebbe@debian.org>  Sat, 01 Aug 2009 15:12:29 +0200
+
+kvm (87+dfsg-1) experimental; urgency=low
+
+  * upload to experimental
+  * [c738942] install udev rule (Closes: 493053)
+  * [03d5918] Imported Upstream version 87+dfsg
+  * [357fb22] drop obsolete files
+  * [1cd73bd] move gbp.cont to debian/
+  * [652e2e2] adjust patches to new directory layout
+  * [2897fe3] drop readd_drive_boot_parameter_help.patch - fixed upstream
+  * [6f09ec7] add support for parallel builds
+  * [54322ee] adjust debian/rules to new source layout
+  * [07357c9] inhibit modules build we don't ship prebuilt modules
+  * [825a993] qemu's bios files in /usr/share are o.k.
+
+ -- Guido Günther <agx@sigxcpu.org>  Fri, 24 Jul 2009 14:20:07 +0200
+
+kvm (85+dfsg-4) unstable; urgency=low
+
+  * upload to unstanble
+  * Remove security/CVE-2008-0928-fedora.patch - fixed upstream.
+
+ -- Guido Günther <agx@sigxcpu.org>  Fri, 12 Jun 2009 15:16:20 +0200
+
+kvm (85+dfsg-3) experimental; urgency=low
+
+  * Pick patch from qemu-kvm to readd -drive boot= parameter help text,
+    thanks to Paul Collins (closes: #529410)
+
+ -- Jan Lübbe <jluebbe@debian.org>  Tue, 19 May 2009 12:59:11 +0200
+
+kvm (85+dfsg-2) experimental; urgency=low
+
+  * Depend on libpci-dev for PCI device assignment
+  * Setup kernel include links before configuring (closes: #528765)
+
+ -- Jan Lübbe <jluebbe@debian.org>  Mon, 18 May 2009 16:08:23 +0200
+
+kvm (85+dfsg-1) experimental; urgency=low
+
+  * New upstream release (closes: #525466)
+    - Update upstream changelog
+  * Strip mpc8544ds.dtb from upstream tarball
+  * Drop 02_fix_kernel_Makefile.patch (does not apply)
+  * Drop security/CVE-2007-5730.patch (applied upstream)
+  * Drop fr-be-duplicate-chars.patch (applied upstream)
+  * Drop altgr-dead-keys-vnc.diff (applied upstream)
+  * Drop kvm wrapper script, thanks to Roland Dreier (closes: #452395)
+    - Clean up preinst, 28-2 was before lenny
+  * Update sections for kvm-source and kvm-dbg
+  * Update homepage
+  * Update to policy 3.8.1.0 (no changes)
+
+ -- Jan Lübbe <jluebbe@debian.org>  Fri, 15 May 2009 10:42:43 +0200
+
+kvm (84+dfsg-2) experimental; urgency=low
+
+  * Enable es1370 and sb16 sound devices (closes: #516066)
+  * Enable pulseaudio audio driver
+  * Add libpulse-dev and libbluetooth-dev to Build-Depends
+
+ -- Jan Lübbe <jluebbe@debian.org>  Thu, 19 Feb 2009 11:06:18 +0100
+
+kvm (84+dfsg-1) experimental; urgency=low
+
+  [ Jan Lübbe ]
+  * New upstream release (closes: #515674)
+
+  [ Guido Günther ]
+  * Remove duplicate characters from fr-be keymap (Closes: #513845)
+
+ -- Jan Lübbe <jluebbe@debian.org>  Wed, 18 Feb 2009 17:42:31 +0100
+
+kvm (83+dfsg-1) experimental; urgency=low
+
+  * New upstream release (closes: #512420)
+  * Disable security/CVE-2008-0928-fedora.patch, it causes corruption in
+    qcow2 images (closes: #511914, #512654)
+
+ -- Jan Lübbe <jluebbe@debian.org>  Fri, 23 Jan 2009 12:17:13 +0100
+
+kvm (82+dfsg-1) experimental; urgency=low
+
+  [ Jan Lübbe ]
+  * New upstream release
+
+  [ Guido Günther ]
+  * CVE-2008-0928-fedora.patch: update patch from fedora for kvm 82
+  * 01_use_bios_files_in_usr_share_kvm.patch, 03_bios_no_ssp.patch,
+    07_change_qemu_docdir.patch, from-debian-qemu/22_net_tuntap_stall.patch:
+    refresh for kvm 82
+  * 04_use_etc_kvm_kvm-ifup.patch: adjust for kvm 82
+  * CVE-2007-1322.patch: drop - applied upstream
+  * CVE-2007-5729.patch: drop - applied upstream
+  * core-2008-1210.patch: drop - applied upstream
+  * enable audio drivers in debian/rules instead of patching
+    ./configure. Prefer alsa over oss. (Closes: #508018)
+
+ -- Guido Günther <agx@sigxcpu.org>  Sun, 11 Jan 2009 17:14:08 +0100
+
+kvm (79+dfsg-3) experimental; urgency=low
+
+  [ Roland Dreier ]
+  * add a kvm-dbg package with debugging symbols (Closes: #507421)
+
+  [ Guido Günther ]
+  * fixup dbg package build
+  * pick current fix for CVE-2008-0928 from fedora:
+            security/CVE-2008-0928.patch
+  * split up SECURITY_CVE-2007-1321+1322+1366+2893.patch:
+      * drop hw/sb16.c hunk, fixed upstream:
+            http://lists.gnu.org/archive/html/qemu-devel/2008-01/msg00709.html
+      * NE2000 "mtu" heap overflow is
+            security/CVE-2007-5729.patch
+      * QEMU "net socket" heap overflow is
+            security/CVE-2007-5730.patch
+      * Unprivileged "icebp" instruction will halt emulation is
+            security/CVE-2007-1322.patch
+      * drop qemu/block.c hunk, handled in CVE-2008-0928-fedrora.patch
+      * merge the rest in security/leftover.patch
+  * make patches apply without -p0 (Closes: #485254)
+  * move doc parts from the description to README.Debian (Closes: #470037)
+
+ -- Guido Günther <agx@sigxcpu.org>  Sat, 29 Nov 2008 16:40:42 +0100
+
+kvm (79+dfsg-2) experimental; urgency=low
+
+  * New upstream version also fixes:
+      * booting from virtio (Closes: #497214)
+      * hang on reboot with virtio (Closes: #506972)
+      * booting from cdrom via -drive (Closes: #494592)
+      * e1000 PXE booting (Closes: #487224)
+  * 22_net_tuntap_stall.patch: adjust for new qemu
+  * 04_use_etc_kvm_kvm-ifup.patch: adjust default networks scripts in
+    net.c too, otherwise we end up pickung up the qemu ones
+  * drop qemu_vnc_ext_key_event.diff, applied upstream
+  * CVE-2008-0928.patch and SECURITY_CVE-2007-1321+1322+1366+2893.patch still
+    disabled!
+  * refresh the other patches for kvm 79 to apply cleanly
+  * enable brlapi support (Closes: #504066)
+  * KVM ships no README so don't mention it in README.Debian
+    (Closes: #467266)
+  * don't try to load modules if /dev/kvm exists (Closes: #490884)
+  * fix Alt-Gr and deadkeys with vnc (Closes: #504821) -
+    thanks to Arne Bernin
+  * qemu-ifup: always pick the first interface with a default route
+    set (Closes: #506913)
+  * add myself to uploaders
+
+ -- Guido Günther <agx@sigxcpu.org>  Fri, 28 Nov 2008 10:36:07 +0100
+
+kvm (79+dfsg-1) experimental; urgency=low
+
+  * New upstream release (closes: #502612, #505298)
+  * Disabled some patches, they will be rebased and activated before uploading
+    to unstable
+  * Depend on libvdeplug2-dev to support VDE (Virtual Distributed Ethernet)
+    (closes: #494871)
+  * Apply patch to fix broken QEMU documentation link, thanks to Matt Kraii
+    (closes: #498155)
+  * The -name option can be used to set the window caption (closes: #502528)
+
+ -- Jan Lübbe <jluebbe@debian.org>  Thu, 20 Nov 2008 17:17:58 +0100
+
+kvm (72+dfsg-4) unstable; urgency=high
+
+  * debian/patches/core-2008-1210.patch: fix remote DoS via VNC
+    (CORE-2008-1210/CVE-2008-2382).
+
+ -- Jan Lübbe <jluebbe@debian.org>  Wed, 24 Dec 2008 12:23:06 +0100
+
+kvm (72+dfsg-3) unstable; urgency=medium
+
+  * Apply patch from qemu (62_fix-ptyblocking.patch) which fixes a lockup
+    when using a pty as serial console, which caused problems for libvirt
+    users. Thanks to Peter Palfrader and Riku Voipio (closes: #494831)
+
+ -- Jan Lübbe <jluebbe@debian.org>  Thu, 20 Nov 2008 16:41:26 +0100
+
+kvm (72+dfsg-2) unstable; urgency=medium
+
+  * Merge changes from NMU, thanks to Thomas Viehmann
+  * Use a sane method for creating the kvm group, thanks to Josh Tripplet
+    (closes: #502299)
+
+ -- Jan Lübbe <jluebbe@debian.org>  Thu, 16 Oct 2008 18:22:41 +0200
+
+kvm (72+dfsg-1.1) unstable; urgency=low
+
+  * Non-maintainer upload
+  * Change path of diverted kvm modules when kernel >= 2.6.26
+    (closes: #494873)
+
+ -- Thomas Viehmann <tv@beamnet.de>  Fri, 12 Sep 2008 11:48:31 +0200
+
+kvm (72+dfsg-1) unstable; urgency=low
+
+  * New upstream release (closes: #493536)
+  * Cherry-pick a commit from qemu which fixes migration
+  * Cherry-pick a commit from kvm which fixes the external module with 2.6.26
+  * Reenable audio drivers and cards (closes: #491676)
+
+ -- Jan Lübbe <jluebbe@debian.org>  Mon, 11 Aug 2008 19:51:51 +0200
+
+kvm (71+dfsg-1) unstable; urgency=low
+
+  * New upstream release
+
+ -- Jan Lübbe <jluebbe@debian.org>  Sat, 19 Jul 2008 15:52:45 +0200
+
+kvm (70+dfsg-1) unstable; urgency=low
+
+  * New upstream release
+  * Merge changes from Ubuntu in debian/control
+    - Only Build-Depend on device-tree-compiler on PowerPC
+    - Change linux-{image,headers,source}-2.6 to just
+      linux-{image,headers,source}
+    - Don't suggest sudo
+  * Reenable CPU emulation
+  * Update to policy 3.8.0.0
+    - Add debian/README.source
+
+ -- Jan Lübbe <jluebbe@debian.org>  Tue, 17 Jun 2008 18:55:51 +0200
+
+kvm (69+dfsg-1) unstable; urgency=low
+
+  [ Jan Lübbe ]
+  * New upstream releases (closes: #481989)
+    - Fixes CVE-2007-1320 (Cirrus LGD-54XX "bitblt" heap overflow)
+    - Fixes CVE-2008-2004 (format guessing vulnerability, drop the patch)
+    - Update debian patches
+  * Update upstream changelog
+  * Update Vcs-* headers to git.debian.org
+  * Drop kvm-data again, build and ship only those files relevant to the
+    target arch
+
+  [ Soren Hansen ]
+  * 03_bios_no_ssp.patch:
+    - Pass -fno-stack-protector to gcc when building the bios image.
+  * qemu_vnc_ext_key_event.diff:
+    - Implement the Extended KeyEvent extension in kvm's embedded VNC server.
+  * Add kvm init script that loads the appropriate kernel modules.
+  * Update package description
+    - We no longer support cpu emulation, so hardware support is required.
+    - The standard kernel images provide the kernel modules, so compiling
+      them yourself from kvm-source is now optional.
+    - qemu is no longer needed for creating disk images, since we have kvm-img
+      now.
+  * Move kvm-source from "Recommends:" of kvm to "Suggests:", since the
+    modules are in the standard kernel images.
+  * Update CVE-2008-0928.patch to allow any bdrv request if vm is not
+    running. This fixes the savevm monitor command.
+    - This also fixes booting with qcow2 images (closes: #470664)
+
+ -- Jan Lübbe <jluebbe@debian.org>  Mon, 26 May 2008 16:55:21 +0200
+
+kvm (66+dfsg-1.1) unstable; urgency=high
+
+  * Non-maintainer upload by the security team
+  * Merge the fixes for the security issues in the embedded qemu
+    version (Closes: #480011) Thanks to Jamie Strandboge
+   - Add CVE-2007-1320+1321+1322+1366+2893.patch from from qemu 0.9.1-1
+     to address the following issues:
+    - Note: CVE-2007-2893 is the same as CVE-2007-1323 referenced in DSA-1284-1.
+    - Note: CVE-2007-5729 and CVE-2007-5730 are the same as CVE-2007-1321
+      referenced in DSA-1284-1.
+    - Cirrus LGD-54XX "bitblt" heap overflow.
+    - NE2000 "mtu" heap overflow.
+    - QEMU "net socket" heap overflow.
+    - QEMU NE2000 "receive" integer signedness error.
+    - Infinite loop in the emulated SB16 device.
+    - Unprivileged "aam" instruction does not correctly handle the
+      undocumented divisor operand.
+    - Unprivileged "icebp" instruction will halt emulation.
+  * Include patch which defaults to existing behaviour (probing based on file
+    contents), so it still requires the mgmt app (e.g. libvirt xml) to
+    pass a new "format=raw" parameter for raw disk images
+    - Fixes possible privilege escalation, which could allow guest users
+      to read arbitrary files on the host by modifying the header to identify
+      a different format (Closes: #481204) Fixes: CVE-2008-2004
+
+ -- Steffen Joeris <white@debian.org>  Tue, 20 May 2008 13:28:14 +0000
+
+kvm (66+dfsg-1) unstable; urgency=low
+
+  * New upstream release
+  * Update upstream changelog
+  * Ship the userspace utilities
+    - Depend on python for the scripts
+
+ -- Jan Lübbe <jluebbe@debian.org>  Thu, 17 Apr 2008 22:23:14 +0200
+
+kvm (65+dfsg-2) unstable; urgency=low
+
+  * Install PXE boot ROMs only if they exists and Build-Depend on
+    etherboot only on i386
+    - This allows building on amd64 (closes: #469125)
+  * Disable qemu CPU emulation and drop Build-Depend on gcc-3.4
+    (closes: #440430)
+  * Don't Recommend qemu (we ship qemu-img as kvm-img)
+  * Move vde2 from Recommends to Suggests
+  * Suggest samba for the -smb option (closes: #474209)
+
+ -- Jan Lübbe <jluebbe@debian.org>  Thu, 10 Apr 2008 22:52:26 +0200
+
+kvm (65+dfsg-1) unstable; urgency=low
+
+  * New upstream release
+  * Update upstream changelog
+  * Put the link to ../packages/default.sh into /usr/share/modass/overrides/
+    as suggested by m-a's HOWTO-DEVEL
+    - This also avoides a Conflicts/Replaces against older kvm packages
+      (closes: #473910)
+
+ -- Jan Lübbe <jluebbe@debian.org>  Tue, 08 Apr 2008 18:49:34 +0200
+
+kvm (64+dfsg-1) unstable; urgency=low
+
+  * New upstream release
+  * Update upstream changelog
+  * Build-Depend on device-tree-compiler and build bamboo.dtb from source
+  * Clean up debian/rules
+  * Drop patch included upstream (02_snapshot_use_tmpdir.patch)
+
+ -- Jan Lübbe <jluebbe@debian.org>  Tue, 01 Apr 2008 17:21:14 +0200
+
+kvm (63+dfsg-2) unstable; urgency=low
+
+  * Depend on libncurses5-dev to allow the curses interface in addition
+    to SDL (closes: #471292)
+  * Use 02_snapshot_use_tmpdir from debian qemu svn r298 (closes: #470757)
+  * Correct my name in debian/control
+
+ -- Jan Lübbe <jluebbe@debian.org>  Wed, 26 Mar 2008 22:18:43 +0100
+
+kvm (63+dfsg-1) unstable; urgency=low
+
+  * New upstream release
+  * Update upstream changelog (from mailing list)
+  * Fix CVE-2008-0928 using the patch in the bugreport (closes: #469666)
+
+ -- Jan Lübbe <jluebbe@debian.org>  Tue, 11 Mar 2008 10:48:29 +0100
+
+kvm (62+dfsg-3) unstable; urgency=low
+
+  * Build a kvm-data package for the files loaded into the VM
+    (closes: #469125)
+
+ -- Jan Luebbe <jluebbe@debian.org>  Fri, 07 Mar 2008 00:15:56 +0100
+
+kvm (62+dfsg-2) unstable; urgency=low
+
+  * Use PXE boot ROMs from the Etherboot package
+
+ -- Jan Luebbe <jluebbe@debian.org>  Sat, 01 Mar 2008 17:33:00 +0100
+
+kvm (62+dfsg-1) unstable; urgency=low
+
+  * New upstream release
+    - even more resolutions for -std-vga (closes: #463629)
+  * Update upstream changelog
+
+ -- Jan Luebbe <jluebbe@debian.org>  Fri, 29 Feb 2008 21:51:02 +0100
+
+kvm (61+dfsg-1) unstable; urgency=low
+
+  * The "Live from FOSDEM" release
+  * New upstream release
+  * Update upstream changelog
+  * Drop dependency on vgabios
+  * Switch to git for packaging, update Vcs-* in debian/control
+
+ -- Jan Luebbe <jluebbe@debian.org>  Sat, 23 Feb 2008 17:22:29 +0100
+
+kvm (60+dfsg-1) unstable; urgency=low
+
+  * New upstream release
+  * Update upstream changelog
+  * Drop restore-IO_MEM_ROM-mark.patch (included upstream)
+  * Build and use the vgabios shipped with kvm (closes: #462434)
+  * Use install_linux_boot.patch from Ubuntu to fix the -kernel option
+    (closes: #412022)
+
+ -- Jan Luebbe <jluebbe@debian.org>  Fri, 25 Jan 2008 16:12:41 +0100
+
+kvm (58+dfsg-2) unstable; urgency=low
+
+  * Use patch from kvm-devel list to fix booting with some linux kernels
+    (closes: #458481)
+
+ -- Jan Luebbe <jluebbe@debian.org>  Mon, 21 Jan 2008 11:20:17 +0100
+
+kvm (58+dfsg-1) unstable; urgency=low
+
+  * The "Live from 24c3 in Berlin" release
+  * New upstream release (closes: #452392)
+  * Update upstream changelog
+  * Update to policy version 3.7.3 (no changes needed)
+
+ -- Jan Luebbe <jluebbe@debian.org>  Sat, 29 Dec 2007 00:00:44 +0100
+
+kvm (57+dfsg-2) unstable; urgency=low
+
+  * Build with alsa support (closes: #457536)
+
+ -- Jan Luebbe <jluebbe@debian.org>  Sun, 23 Dec 2007 20:15:30 +0100
+
+kvm (57+dfsg-1) unstable; urgency=low
+
+  * New upstream release (closes: #457061)
+    - qemu has been updated to the current cvs version
+  * Update upstream changelog
+
+ -- Jan Luebbe <jluebbe@debian.org>  Thu, 20 Dec 2007 17:14:05 +0100
+
+kvm (56+dfsg-1) unstable; urgency=low
+
+  * New upstream release
+  * Update upstream changelog
+
+ -- Jan Luebbe <jluebbe@debian.org>  Wed, 19 Dec 2007 20:27:19 +0100
+
+kvm (55+dfsg-2) unstable; urgency=low
+
+  * Depend on libgnutls for VNC TLS support
+  * Build BIOS from kvm sources (kvm and qemu patchs are different, thanks to
+    Carlo Marcelo Arenas Belon for spotting this)
+  * Fix debian/rules clean
+
+ -- Jan Luebbe <jluebbe@debian.org>  Sat, 08 Dec 2007 19:45:45 +0100
+
+kvm (55+dfsg-1) unstable; urgency=low
+
+  * New upstream release
+  * Include cpu information also for bugs against kvm-source
+  * Update upstream changelog
+  * Remove bios.bin from upstream tarball (closes: #452963) and depend on the
+    current version of bochsbios
+
+ -- Jan Luebbe <jluebbe@debian.org>  Fri, 07 Dec 2007 19:22:57 +0100
+
+kvm (54+dfsg-1) unstable; urgency=low
+
+  * New upstream release
+  * Revive get-orig-source to remove other BIOS files (see #452963).
+    Thanks Soren Hansen.
+  * Include upstream changelog from the wiki.
+  * Update README.Debian and mention the kvm modules distributed with
+    the Linux kernel (closes: #440790)
+
+ -- Jan Luebbe <jluebbe@debian.org>  Thu, 29 Nov 2007 14:40:23 +0000
+
+kvm (53-1) unstable; urgency=low
+
+  * New upstream release
+  * Upstream has removed the elpin BIOS files, stop repacking the tarball.
+
+ -- Jan Luebbe <jluebbe@debian.org>  Wed, 21 Nov 2007 16:53:51 +0100
+
+kvm (52+dfsg-1) unstable; urgency=low
+
+  * New upstream release
+  * Switch to Vcs-Svn and Vcs-Browser in debian/control
+
+ -- Jan Luebbe <jluebbe@debian.org>  Thu, 15 Nov 2007 18:47:41 +0100
+
+kvm (48+dfsg-1) unstable; urgency=low
+
+  * Adopt package with Baruch Even's permission
+  * New upstream release
+
+ -- Jan Luebbe <jluebbe@debian.org>  Thu, 25 Oct 2007 11:15:54 +0200
+
+kvm (46+dfsg-0.1) unstable; urgency=low
+
+  * Non-maintainer upload (low threshold nmu)
+  * New upstream release
+  * Adapt sf-get-orig-source from gnome-pkg-tools
+  * Repackage tarball to remove elpin VGA bios (closes: #440472)
+  * Add debian/watch file
+
+ -- Jan Luebbe <jluebbe@debian.org>  Sun, 14 Oct 2007 12:02:54 +0200
+
+kvm (36-0.1) unstable; urgency=low
+
+  * Non-maintainer upload (with permission)
+  * New upstream release (closes: #438412)
+  * Update patches
+  * Install documentation from qemu to /usr/share/doc/kvm to avoid conflicts
+    and refer to it from kvm(1) (closes: #434729)
+  * Rename conflicting manpages
+  * Add texi2html as a Build-Dependency
+  * Make module-assistant a Dependency of kvm-source because it is needed by
+    it's debian/rules
+  * debian/conffiles is not necessary for /etc
+
+ -- Jan Luebbe <jluebbe@debian.org>  Mon, 27 Aug 2007 18:45:36 +0200
+
+kvm (28-4) unstable; urgency=low
+
+  * Divert kernel modules when installing the kvm-source modules
+    (Closes: #429851)
+  * kvm-ifup, even if bridge command failed continue to work, this will allow
+    users who have no bridge setup and intend to setup some other method to
+    get it to work without messing with the package files. (Closes: #407459)
+
+ -- Baruch Even <baruch@debian.org>  Thu, 21 Jun 2007 12:37:54 +0100
+
+kvm (28-3) unstable; urgency=low
+
+  * Fix infinite loop in kvm-ifup script
+
+ -- Baruch Even <baruch@debian.org>  Mon, 18 Jun 2007 20:51:50 +0100
+
+kvm (28-2) unstable; urgency=low
+
+  * We moved a file from kvm-source to kvm, to be able to properly upgrade we
+    specify a conflict against older versions (Closes: #417652)
+  * Fix kvm-ifup script to work in more conditions (Closes: #417151)
+  * Remove old /etc/udev/kvm.rules since it's not needed (Closes: #414331)
+
+ -- Baruch Even <baruch@debian.org>  Sun, 17 Jun 2007 21:13:07 +0100
+
+kvm (28-1) unstable; urgency=low
+
+  * New upstream release (Closes: #422197)
+    - Should fix oops (Closes: #418928)
+  * kqemu is no longer in non-free (Closes: #419152)
+
+ -- Baruch Even <baruch@debian.org>  Sun, 17 Jun 2007 10:32:40 +0100
+
+kvm (18-1) unstable; urgency=low
+
+  * New upstream release (Closes: #416926)
+  * Move the module-assistant script to the kvm package from kvm-source so all
+    users will benefit from the integration (Closes: #416122)
+  * Remove patch to add qemu-ifup and kvm initscript, they are now part of kvm directly.
+
+ -- Baruch Even <baruch@debian.org>  Sat, 31 Mar 2007 21:00:34 +0300
+
+kvm (14-1) unstable; urgency=medium
+
+  [ Leonard Norrgård ]
+  * New upstream version.  KVM is now based on qemu-0.9.0.
+  * Suggest etherboot and actually suggest hal (was only mentioning it).
+  * Update copyright info.
+  * Add a couple of patches from Debian qemu: 22_net_tuntap_stall.patch,
+    04_do_not_print_rtc_freq_if_ok.patch, 62_linux_boot_nasm.patch (62_*
+    currently only to avoid a buildd FTBS problem).
+  * Reorder the first two paragraphs in the description for kvm so the
+    general description is first, the more technical second.
+  * Moved adduser to Pre-Depends, as we rely on it for installation.
+  * For a detailed changelog, please see:
+    svn log -v -r 2227:2383 svn://svn.debian.org/svn/collab-maint/ext-maint/kvm/trunk
+
+  [ Baruch Even ]
+  * Update the uploader name of Leonard so that lintian won't think it's an
+    NMU.
+  * Add XS-Vcs-Browser field
+
+ -- Baruch Even <baruch@debian.org>  Sat, 24 Feb 2007 17:43:42 +0200
+
+kvm (13-1) UNRELEASED; urgency=low
+
+  * New upstream version.
+
+ -- Leonard Norrgård <vinsci@refactor.fi>  Sat, 10 Feb 2007 07:40:59 +0200
+
+kvm (12-1) unstable; urgency=high
+
+  * New upstream version. Most important upstream changes:
+    - Attempting to reboot Linux guest no longer reboots host on AMD,
+      actual guest reboot still not possible.
+    - The option -no-acpi is no longer required to install Windows
+      (the option is still recommended as the Windows ACPI HAL will
+      eat a lot of cpu time).
+
+ -- Leonard Norrgard <vinsci@refactor.fi>  Sun, 23 Jan 2007 18:54:17 +0200
+
+kvm (11-2) unstable; urgency=low
+
+  [ Baruch Even ]
+  * Make the quilt include part conditional so we don't have to have it when
+    building the kernel module. (Closes: #407447, #407482)
+  * Do not recommend linux-image-2.6 in kvm-source, and move linux-headers-2.6
+    from depends to suggests where it belongs. The package can build from
+    vanilla kernels as well as Debian kernels. (Closes: #407729)
+
+  [ Leonard Norrgard ]
+  * Enhance manual page a bit.
+
+ -- Baruch Even <baruch@debian.org>  Sun, 21 Jan 2007 09:05:38 +0200
+
+kvm (11-1) unstable; urgency=high
+
+  * New upstream version. Closes #406800, #406275, #404075.
+  * This version fixes many stability issues in earlier versions of KVM.
+  * Automatically create group kvm on installation of package kvm
+  * Added udev support to automatically set group kvm on /dev/kvm
+  * Added reportbug script (/usr/share/bug/kvm) so some info that
+    might be relevant gets included automatically.
+  * Tell module-assistant about the kvm-source package, so it shows up
+    in the module selection menu.
+  * Add information on building the modules using module-assistant.
+  * Add /etc/kvm/kvm-ifup script (conffile) to bring up the network for
+    the VM in a simpler way, see the manual page for kvm for description.
+    This used to be /etc/qemu-ifup, as installed by the qemu package.
+  * Depend on iproute, bridge-utils, used by kvm-ifup and the upcoming
+    /etc/init.d script.
+  * Remove non-x86 bios images - KVM is only meaningful for x86 guests.
+  * Keep KVM bios files in /usr/share/kvm, rather than sharing them with
+    other packages as the KVM bios is different (also avoids unexpected
+    bios updates).
+  * Don't depend on qemu, as we now keep our own bios.
+  * Recommend kvm-source, qemu (mostly for qemu-img), vde2 and linux-image-2.6.
+  * Suggest sudo and debootstrap.
+  * For kvm-source, depend on linux-headers-2.6 | linux-source-2.6,
+    recommend linux-image-2.6 and suggest module-assistant and
+    kernel-package.
+  * Use quilt to handle patches.
+  * More detailed package description for kvm, added Homepage:.
+
+ -- Leonard Norrgard <vinsci@refactor.fi>  Sun, 14 Jan 2007 07:11:03 +0200
+
+kvm (7-1) unstable; urgency=low
+
+  * New upstream version
+  * Install the Intel and AMD modules (Closes: 402820)
+
+ -- Baruch Even <baruch@debian.org>  Wed, 13 Dec 2006 09:19:44 +0200
+
+kvm (5-2) unstable; urgency=low
+
+  * Yet another attempt to fix building on amd64.
+
+ -- Baruch Even <baruch@debian.org>  Wed,  6 Dec 2006 08:35:04 +0200
+
+kvm (5-1) unstable; urgency=low
+
+  * New upstream version
+  * Really fix building on amd64 (Closes: #400549)
+
+ -- Baruch Even <baruch@debian.org>  Wed,  6 Dec 2006 07:12:30 +0200
+
+kvm (4-2) unstable; urgency=low
+
+  * Allow build on amd64 arch, it really should mean Intel x86 64bit arches,
+    kvm still doesn't support AMD SVM instructions and requires the Intel
+    CPUs. (Closes: #400549)
+
+ -- Baruch Even <baruch@debian.org>  Tue, 28 Nov 2006 22:16:08 +0200
+
+kvm (4-1) unstable; urgency=low
+
+  * New upstream version.
+
+ -- Baruch Even <baruch@debian.org>  Tue, 21 Nov 2006 22:23:26 +0200
+
+kvm (3-2) unstable; urgency=low
+
+  * Use KERNEL_DIR variable when building the module to enable building a
+    module for a kernel that is not being run right now. (Closes: #399603)
+  * Add manpage that refers the user to qemu(1) where he can find all the
+    information he needs. 
+
+ -- Baruch Even <baruch@debian.org>  Tue, 21 Nov 2006 09:22:57 +0200
+
+kvm (3-1) unstable; urgency=low
+
+  * New upstream version. 
+  * Use upstream versioning of natural numbers.
+  * First upload to Debian (Closes: #398458)
+
+ -- Baruch Even <baruch@debian.org>  Wed, 15 Nov 2006 23:58:12 +0200
+
+kvm (0.0.2-1) unstable; urgency=low
+
+  * Initial release
+
+ -- Baruch Even <baruch@debian.org>  Tue, 14 Nov 2006 20:49:57 +0200
--- qemu-kvm-0.12.5+dfsg.orig/debian/README.source
+++ qemu-kvm-0.12.5+dfsg/debian/README.source
@@ -0,0 +1,8 @@
+This package uses the quilt patch system as documented in the Debian quilt
+package (/usr/share/doc/quilt/README.source).
+
+To update this package to a new upstream version, some binary files must be
+removed from the upstream tarball.
+The get-orig-source target in debian/rules will download and clean the tarball
+for the current version (according to debian/changelog). To get a newer
+version, first update the changelog and then run get-orig-source.
--- qemu-kvm-0.12.5+dfsg.orig/debian/qdev-device-use.txt
+++ qemu-kvm-0.12.5+dfsg/debian/qdev-device-use.txt
@@ -0,0 +1,353 @@
+= How to convert to -device & friends =
+
+=== Specifying Bus and Address on Bus ===
+
+In qdev, each device has a parent bus.  Some devices provide one or
+more buses for children.  You can specify a device's parent bus with
+-device parameter bus.
+
+A device typically has a device address on its parent bus.  For buses
+where this address can be configured, devices provide a bus-specific
+property.  These are
+
+    bus     property name       value format
+    PCI     addr                %x.%x (dev.fn, .fn optional)
+    I2C     address             %u
+    SCSI    scsi-id             %u
+
+Example: device i440FX-pcihost is on the root bus, and provides a PCI
+bus named pci.0.  To put a FOO device into its slot 4, use -device
+FOO,bus=/i440FX-pcihost/pci.0,addr=4.  The abbreviated form bus=pci.0
+also works as long as the bus name is unique.
+
+Note: the USB device address can't be controlled at this time.
+
+=== Block Devices ===
+
+A QEMU block device (drive) has a host and a guest part.
+
+In the general case, the guest device is connected to a controller
+device.  For instance, the IDE controller provides two IDE buses, each
+of which can have up to two ide-drive devices, and each ide-drive
+device is a guest part, and is connected to a host part.
+
+Except we sometimes lump controller, bus(es) and drive device(s) all
+together into a single device.  For instance, the ISA floppy
+controller is connected to up to two host drives.
+
+The old ways to define block devices define host and guest part
+together.  Sometimes, they can even define a controller device in
+addition to the block device.
+
+The new way keeps the parts separate: you create the host part with
+-drive, and guest device(s) with -device.
+
+The various old ways to define drives all boil down to the common form
+
+    -drive if=TYPE,index=IDX,bus=BUS,unit=UNIT,HOST-OPTS...
+
+TYPE, BUS and UNIT identify the controller device, which of its buses
+to use, and the drive's address on that bus.  Details depend on TYPE.
+IDX is an alternative way to specify BUS and UNIT.
+
+In the new way, this becomes something like
+
+   -drive if=none,id=DRIVE-ID,HOST-OPTS...
+   -device DEVNAME,drive=DRIVE-ID,DEV-OPTS...
+
+The -device argument differs in detail for each kind of drive:
+
+* if=ide
+
+  -device ide-drive,drive=DRIVE-ID,bus=IDE-BUS,unit=UNIT
+
+  where IDE-BUS identifies an IDE bus, normally either ide.0 or ide.1,
+  and UNIT is either 0 or 1.
+
+  Bug: new way does not work for ide.1 unit 0 (in old terms: index=2)
+  unless you disable the default CD-ROM with -nodefaults.
+
+* if=scsi
+
+  The old way implicitly creates SCSI controllers as needed.  The new
+  way makes that explicit:
+
+  -device lsi53c895a,id=ID
+
+  As for all PCI devices, you can add bus=PCI-BUS,addr=DEVFN to
+  control the PCI device address.
+
+  This SCSI controller a single SCSI bus, named ID.0.  Put a disk on
+  it:
+
+  -device scsi-disk,drive=DRIVE-ID,bus=ID.0,scsi-id=SCSI-ID
+
+* if=floppy
+
+  -global isa-fdc,driveA=DRIVE-ID,driveB=DRIVE-ID
+
+  This is -global instead of -device, because the floppy controller is
+  created automatically, and we want to configure that one, not create
+  a second one (which isn't possible anyway).
+
+  Omitting a drive parameter makes that drive empty.
+
+  Bug: driveA works only if you disable the default floppy drive with
+  -nodefaults.
+
+* if=virtio
+
+  -device virtio-blk-pci,drive=DRIVE-ID,class=C,vectors=V
+
+  This lets you control PCI device class and MSI-X vectors.
+
+  As for all PCI devices, you can add bus=PCI-BUS,addr=DEVFN to
+  control the PCI device address.
+
+* if=pflash, if=mtd, if=sd, if=xen are not yet available with -device
+
+For USB devices, the old way is actually different:
+
+    -usbdevice disk:format=FMT:FILENAME
+
+Provides much less control than -drive's HOST-OPTS...  The new way
+fixes that:
+
+    -device usb-storage,drive=DRIVE-ID
+
+=== Character Devices ===
+
+A QEMU character device has a host and a guest part.
+
+The old ways to define character devices define host and guest part
+together.
+
+The new way keeps the parts separate: you create the host part with
+-chardev, and the guest device with -device.
+
+The various old ways to define a character device are all of the
+general form
+
+    -FOO FOO-OPTS...,LEGACY-CHARDEV
+
+where FOO-OPTS... is specific to -FOO, and the host part
+LEGACY-CHARDEV is the same everywhere.
+
+In the new way, this becomes
+
+    -chardev HOST-OPTS...,id=CHR-ID
+    -device DEVNAME,chardev=CHR-ID,DEV-OPTS...
+
+The appropriate DEVNAME depends on the machine type.  For type "pc":
+
+* -serial becomes -device isa-serial,iobase=IOADDR,irq=IRQ,index=IDX
+
+  This lets you control I/O ports and IRQs.
+
+* -parallel becomes -device isa-parallel,iobase=IOADDR,irq=IRQ,index=IDX
+
+  This lets you control I/O ports and IRQs.
+
+* -usbdevice serial:vendorid=VID,productid=PRID becomes
+  -device usb-serial,vendorid=VID,productid=PRID
+
+* -usbdevice braille doesn't support LEGACY-CHARDEV syntax.  It always
+  uses "braille".  With -device, this useful default is gone, so you
+  have to use something like
+
+  -device usb-braille,chardev=braille,vendorid=VID,productid=PRID
+  -chardev braille,id=braille
+
+* -virtioconsole is still being worked on
+
+LEGACY-CHARDEV translates to -chardev HOST-OPTS... as follows:
+
+* null becomes -chardev null
+
+* pty, msmouse, braille, stdio likewise
+
+* vc:WIDTHxHEIGHT becomes -chardev vc,width=WIDTH,height=HEIGHT
+
+* vc:<COLS>Cx<ROWS>C becomes -chardev vc,cols=<COLS>,rows=<ROWS>
+
+* con: becomes -chardev console
+
+* COM<NUM> becomes -chardev serial,path=<NUM>
+
+* file:FNAME becomes -chardev file,path=FNAME
+
+* pipe:FNAME becomes -chardev pipe,path=FNAME
+
+* tcp:HOST:PORT,OPTS... becomes -chardev socket,host=HOST,port=PORT,OPTS...
+
+* telnet:HOST:PORT,OPTS... becomes
+  -chardev socket,host=HOST,port=PORT,OPTS...,telnet=on
+
+* udp:HOST:PORT@LOCALADDR:LOCALPORT becomes
+  -chardev udp,host=HOST,port=PORT,localaddr=LOCALADDR,localport=LOCALPORT
+
+* unix:FNAME becomes -chardev socket,path=FNAME
+
+* /dev/parportN becomes -chardev parport,file=/dev/parportN
+
+* /dev/ppiN likewise
+
+* Any other /dev/FNAME becomes -chardev tty,path=/dev/FNAME
+
+* mon:LEGACY-CHARDEV is special: it multiplexes the monitor onto the
+  character device defined by LEGACY-CHARDEV.  -chardev provides more
+  general multiplexing instead: you can connect up to four users to a
+  single host part.  You need to pass mux=on to -chardev to enable
+  switching the input focus.
+
+QEMU uses LEGACY-CHARDEV syntax not just to set up guest devices, but
+also in various other places such as -monitor or -net
+user,guestfwd=...  You can use chardev:CHR-ID in place of
+LEGACY-CHARDEV to refer to a host part defined with -chardev.
+
+=== Network Devices ===
+
+A QEMU network device (NIC) has a host and a guest part.
+
+The old ways to define NICs define host and guest part together.  It
+looks like this:
+
+    -net nic,vlan=VLAN,macaddr=MACADDR,model=MODEL,name=ID,addr=STR,vectors=V
+
+Except for USB it looks like this:
+
+    -usbdevice net:vlan=VLAN,macaddr=MACADDR,name=ID,addr=STR,vectors=V
+
+The new way keeps the parts separate: you create the host part with
+-netdev, and the guest device with -device, like this:
+
+    -netdev type=TYPE,id=NET-ID
+    -device DEVNAME,netdev=NET-ID,mac=MACADDR,DEV-OPTS...
+
+Unlike the old way, this creates just a network device, not a VLAN.
+If you really want a VLAN, create it the usual way, then create the
+guest device like this:
+
+    -device DEVNAME,vlan=VLAN,mac=MACADDR,DEV-OPTS...
+
+DEVNAME equals MODEL, except for virtio you have to name the virtio
+device appropriate for the bus (virtio-net-pci for PCI), and for USB
+NIC you have to use usb-net.
+
+The old name=ID parameter becomes the usual id=ID with -device.
+
+For PCI devices, you can add bus=PCI-BUS,addr=DEVFN to control the PCI
+device address, as usual.  The old -net nic provides parameter addr
+for that, it is silently ignored when the NIC is not a PCI device.
+
+-net nic accepts vectors=V for all models, but it's silently ignored
+except for virtio-net-pci (model=virtio).  With -device, only devices
+that support it accept it.
+
+Not all devices are available with -device at this time.  All PCI
+devices and ne2k_isa are.
+
+Some PCI devices aren't available with -net nic, e.g. i82558a.
+
+Bug: usb-net does not work, yet.  Patch posted.
+
+=== Graphics Devices ===
+
+Host and guest part of graphics devices have always been separate.
+
+The old way to define the guest graphics device is -vga VGA.
+
+The new way is -device.  Map from -vga argument to -device:
+
+    std         -device VGA
+    cirrus      -device cirrus-vga
+    vmware      -device vmware-svga
+    xenfb       not yet available with -device
+
+As for all PCI devices, you can add bus=PCI-BUS,addr=DEVFN to control
+the PCI device address.
+
+-device VGA supports properties bios-offset and bios-size, but they
+aren't used with machine type "pc".
+
+Bug: -device cirrus-vga and -device vmware-svga require -nodefaults.
+
+Bug: the new way requires PCI; ISA VGA is not yet available with
+-device.
+
+Bug: the new way doesn't work for machine type "pc", because it
+violates obscure device initialization ordering constraints.
+
+=== Audio Devices ===
+
+Host and guest part of audio devices have always been separate.
+
+The old way to define guest audio devices is -soundhw C1,...
+
+The new way is to define each guest audio device separately with
+-device.
+
+Map from -soundhw sound card name to -device:
+
+    ac97        -device AC97
+    cs4231a     -device cs4231a,iobase=IOADDR,irq=IRQ,dma=DMA
+    es1370      -device ES1370
+    gus         -device gus,iobase=IOADDR,irq=IRQ,dma=DMA,freq=F
+    sb16        -device sb16,iobase=IOADDR,irq=IRQ,dma=DMA,dma16=DMA16,version=V
+    adlib       not yet available with -device
+    pcspk       not yet available with -device
+
+For PCI devices, you can add bus=PCI-BUS,addr=DEVFN to control the PCI
+device address, as usual.
+
+=== USB Devices ===
+
+The old way to define a virtual USB device is -usbdevice DRIVER:OPTS...
+
+The new way is -device DEVNAME,DEV-OPTS...  Details depend on DRIVER:
+
+* mouse           -device usb-mouse
+* tablet          -device usb-tablet
+* keyboard        -device usb-kdb
+* wacom-tablet    -device usb-wacom-tablet
+* host:...        See "Host Device Assignment"
+* disk:...        See "Block Devices"
+* serial:...      See "Character Devices"
+* braille         See "Character Devices"
+* net:...         See "Network Devices"
+* bt:...          not yet available with -device
+
+=== Watchdog Devices ===
+
+Host and guest part of watchdog devices have always been separate.
+
+The old way to define a guest watchdog device is -watchdog DEVNAME.
+The new way is -device DEVNAME.  For PCI devices, you can add
+bus=PCI-BUS,addr=DEVFN to control the PCI device address, as usual.
+
+=== Host Device Assignment ===
+
+QEMU supports assigning host PCI devices (qemu-kvm only at this time)
+and host USB devices.
+
+The old way to assign a host PCI device is
+
+    -pcidevice host=ADDR,dma=none,id=ID
+
+The new way is
+
+    -device pci-assign,host=ADDR,iommu=IOMMU,id=ID
+
+The old dma=none becomes iommu=0 with -device.
+
+The old way to assign a host USB device is
+
+    -usbdevice host:auto:BUS.ADDR:VID:PRID
+
+where any of BUS, ADDR, VID, PRID can be the wildcard *.
+
+The new way is
+
+    -device usb-host,hostbus=BUS,hostaddr=ADDR,vendorid=VID,productid=PRID
+
+where left out or zero BUS, ADDR, VID, PRID serve as wildcard.
--- qemu-kvm-0.12.5+dfsg.orig/debian/control
+++ qemu-kvm-0.12.5+dfsg/debian/control
@@ -0,0 +1,60 @@
+Source: qemu-kvm
+Section: misc
+Priority: optional
+Maintainer: Jan Lübbe <jluebbe@debian.org>
+Uploaders: Guido Günther <agx@sigxcpu.org>, Michael Tokarev <mjt@tls.msk.ru>
+Build-Depends: debhelper (>= 7.2.3~), pkg-config, quilt (>= 0.40), autotools-dev,
+ bzip2, uuid-dev, zlib1g-dev, libsdl1.2-dev, libasound2-dev, libcurl4-gnutls-dev,
+ libgnutls-dev, libncurses5-dev, libvdeplug2-dev, libpulse-dev, libbluetooth-dev,
+ nasm, texi2html, bcc, iasl, device-tree-compiler [powerpc], python,
+ etherboot (>= 5.4.4) [i386 amd64], libbrlapi-dev, libpci-dev, libsasl2-dev,
+ libaio-dev, linux-libc-dev (>= 2.6.32)
+Standards-Version: 3.9.1.0
+Homepage: http://www.linux-kvm.org/
+Vcs-Browser: http://git.debian.org/?p=collab-maint/qemu-kvm.git
+Vcs-Git: git://git.debian.org/git/collab-maint/qemu-kvm.git
+
+Package: qemu-kvm
+Architecture: i386 amd64
+Pre-Depends: adduser
+Depends: ${shlibs:Depends}, ${misc:Depends}, iproute, bridge-utils, python
+Recommends: linux-image
+Suggests: debootstrap, vde2, samba
+Provides: kvm
+Conflicts: kvm-source (<= 18-1), kvm-data (<= 66+dfsg-1.1), kvm (<< 1:0)
+Replaces: kvm-data (<= 66+dfsg-1.1), kvm (<< 1:0)
+Description: Full virtualization on x86 hardware
+ Using KVM, one can run multiple virtual PCs, each running unmodified Linux or
+ Windows images. Each virtual machine has private virtualized hardware: a
+ network card, disk, graphics adapter, etc. 
+ .
+ KVM (for Kernel-based Virtual Machine) is a full virtualization solution for
+ Linux hosts on x86 hardware with x86 guests. KVM is intended for systems where
+ the processor has hardware support for virtualization, see below for details.
+ All combinations of 32-bit and 64-bit host and guest systems are supported,
+ except 64-bit guests on 32-bit hosts.
+ .
+ KVM requires your system to support hardware virtualization, provided by AMD's
+ SVM capability or Intel's VT. See /usr/share/doc/qemu-kvm/README.Debian for
+ more information.
+
+Package: qemu-kvm-dbg
+Architecture: i386 amd64
+Section: debug
+Depends: ${misc:Depends}, qemu-kvm (= ${binary:Version})
+Conflicts: kvm-dbg
+Replaces: kvm-dbg
+Priority: extra
+Description: Debugging info for qemu-kvm
+ This package contains the debugging symbols for qemu-kvm.
+
+Package: kvm
+Architecture: i386 amd64
+Depends: ${misc:Depends}, qemu-kvm
+Section: oldlibs
+Priority: extra
+Description: dummy transitional package from kvm to qemu-kvm
+ This transitional package helps users transition from the kvm package to the
+ qemu-kvm package.  Once this package and its dependencies are installed you
+ can safely remove it.
+
--- qemu-kvm-0.12.5+dfsg.orig/debian/changelog.upstream-kvm
+++ qemu-kvm-0.12.5+dfsg/debian/changelog.upstream-kvm
@@ -0,0 +1,1923 @@
+= kvm-88 [12 july 2009] =
+
+ * merge upstream qemu.git
+  * virtio indirect ring entries
+   * improves block performance for newer Linux guests
+  * -net tap,sndbuf=... option for improving udp performance
+  * msi-x support
+  * sdl window resize
+  * more flexible -net user configuration
+  * -cpu host to pass through all host cpu features
+  * multiboot support for -kernel
+ * fix KVM_GET_SUPPORTED_CPUID feature usage (Andre Przywara)
+ * fix register contents after SIPI (Gleb Natapov)
+ * re-enable device assignment (Markus Armbruster)
+ * fix ia64 build (Markus Armbruster)
+ * fix migration for virtio-net version > 7 (Michael S. Tsirkin)
+ * merge more code with upstream (Glauber Costa)
+ * fix vnet_hdr checks (Mark McLoughlin)
+  * fixes broken tap networking with rtl8139 and e1000
+ * move extboot to standard optionrom location (Jan Kiszka)
+ * emulate 32-bit syscall/sysenter instructions on 64-bit guests (Andre Przywara)
+  * allows cross-vendor live migration with 32-bit userspace on 64-bit kernel
+ * fix s390 memslot initialization for userspace_addr != 0 (Christian Borntraeger)
+ * allow s390 stfle instruction to be executed by guest (Christian Borntraeger)
+ * prepare memory slot data structures for multiple large page sizes (Joerg Roedel)
+ * correct missing locking in PIT/IRQCHIP/SET_BSP_CPU ioctl paths (Marcelo Tosatti)
+ * do not allow invalid mtrr/pat settings (Marcelo Tosatti)
+ * ignore some more AMD system configuration msrs (Andre Przywara)
+ * introduce module parameter for ignoring unknown msrs (Andre Przywara)
+ * fix ftrace build when kvm is built into the kernel
+ * convert powerpc marker probes to tracepoints (Marcelo Tosatti)
+ * drop old kvmtrace code (Marcelo Tosatti)
+ * document kvm_io_device locking (Michael S. Tsirkin)
+ * switch coalesced mmio, PIT creation, io bus to slots_lock (Michael S. Tsirkin)
+ * fix locking imbalance (Jiri Slaby)
+ * irq tracing
+ * mmio tracing
+ * irqfd deassign (Gregory Haskins)
+ * x2apic support (Gleb Natapov)
+ * avoid redelivery of edge triggered interrupt before next edge (Gleb Natapov)
+  * fixes keyboard issues running Windows XP x64 smp installer
+ * avoid pit division by zero (Marcelo Tosatti)
+ * fix KVM_GET_MSR_INDEX_LIST user memory corruption (Jan Kiszka)
+ * drop old cr3 checks in favor of new checks (Jan Kiszka)
+ * mmu tracing
+ * basic API documentation
+ * ignore msi requests if level = 0 (Michael S. Tsirkin)
+ * ioapic/pic/msi tracing (Gleb Natapov)
+ * don't kick vcpu if not in guest mode (Gleb Natapov)
+
+= kvm-87 [25 june 2009] =
+
+ * merge qemu upstream (Mark McLoughlin, Avi Kivity)
+  * tune and view live migration progress
+  * allow setting qcow2 cluster size
+  * http protocol for images
+  * qcow2 speedups
+  * networking improvements
+ * fix -no-shatdown command line option (Daniel Gollub)
+ * fix warnings on 32-bit hosts (Michael S. Tsirkin)
+ * use a bitmap for tracking used interrupts (Alex Williamson)
+ * support running without vga option rom (Jan Kiszka)
+ * make kvmtrace_format mode distro friendly (Eduardo Habkost)
+ * fix mac annoucement after live migation with virtio net (Gleb Natapov)
+ * merge cpu state more compatible with upstream qemu (Jan Kiszka)
+ * improve large page memory layout
+ * only initialize lapic after the vcpu (Glauber Costa)
+ * clean up cpuid feature trimming (Glauber Costa)
+ * avoid harmless msr warnings (Marcelo Tosatti)
+ * have bios read read MADT to implement acpi _MAT (Gleb Natapov)
+ * fix tpr patching to get cpu index from Windows PCR (Gleb Natapov)
+ * separate kvm from pic implementation (Glauber Costa)
+ * remove cpu index in libkvm/qemu interface (Gleb Natapov)
+ * halt guest instead of aborting on error
+ * fix dma on ia64 (Jes Sorensen)
+ * fix MADT, RSDT creation (Beth Kon)
+ * start libkvm removal (Glauber Costa)
+ * make qemu-kvm implementation closer to upstream (Gleb Natapov)
+ * move acpi processor descriptions to ssdt (Jes Sorensen)
+ * machine check exception support (Huang Ying)
+ * not userspace visible yet
+ * msr cleanups (Jaswinder Singh Rajput)
+ * fix cpuid error handling (Mark McLoughlin)
+ * fix jmp far decoding
+ * makefile cleanup (Christoph Hellwig)
+ * drop "interrupt shadow" flag when single stepping (Gleb Natapov)
+ * allow 4K ptes with PAT bit set
+ * irqfd (Gregory Haskins)
+ * allow speaker emulation in usespace (Jan Kiszka)
+ * fix ia64 timestamp counter (Jes Sorensen)
+ * fix PAE PDPTR handling
+  * fixes Fedora 11 i686 guests
+ * s390 inter-vcpu communication fixes (Christian Ehrhardt)
+ * s390 memory slot management improvements (Christian Ehrhardt)
+ * reduce MSI-X support to 256 vectors (Sheng Yang)
+ * avoid truncation of sysenter msrs on AMD (Andre Przywara)
+ * fix performance problem due to irq disabling on device assignment (Sheng Yang)
+ * fix init/exit text annotations (Stephen Rothwell)
+ * clean up coalesced_mmio destruction (Gregory Haskins)
+ * cleanup kernel iodevice code (Gregory Haskins)
+ * register PIT device after initialization (Gregory Haskins)
+ * avoid redundant tlb flush when using ept
+ * simplify ptptr and cr3 management on Intel
+ * cache pdptrs for i686 pae guests
+ * improve handling of unhandled ept violations
+ * fix host reboot failures with CONFIG_MAXSMP
+ * powerpc e500 adjustments (Liu Yu)
+ * vmx unrestricted guest (Nitin A Kamble)
+ * clean up lapic interface (Jan Kiszka)
+ * fix PIC locking (Marcelo Tosatti)
+ * improve PIC and IOAPIC scaling (Marcelo Tosatti)
+ * handle machine checks while running in guest mode (Andi Kleen)
+ * disable large pages on misaligned memory slots
+ * prevent overflow in largepage calculation
+ * prevent unnecessarily setting guest pages dirty bits under ept
+ * decouple vcpu id from apic id (Gleb Natapov)
+ * improve internal vcpu accessors (Gleb Natapov)
+ * break infinite emulation failure loops
+ * fix mmu audit (Marcelo Tosatti)
+ * generic performance counter msr handling (Andre Przywara, Amit Shah)
+ * improve ept error reporting (Marcelo Tosatti)
+ * disable large pages if ept does not support them (Marcelo Tosatti)
+ * improve simultaneous exception handling (Gleb Natapov)
+ * optimize APIC interrupt request register searching (Gleb Natapov)
+ * fix live migration with large pages (Izik Eidus)
+ * fix racy event propagation in timer (Jan Kiszka)
+ * remove unnecessary atomic test in timer (Jan Kiszka)
+ * optimize cr2 reloads on vmx
+ * drop cr2 save/restore on svm
+ * fix crash when guest uses vmx instructions
+ * implement msrs used by Hyper-V as a guest (Alexander Graf)
+ * implement invlpga instruction (Alexander Graf)
+ * improve nested interrupt injection (Alexander Graf)
+ * convert kvmtrace to use the generic kernel infrastructure (Marcelo Tosatti)
+ * fix concurrent mmu reloads and tlb flushes (Marcelo Tosatti)
+ * fix ia64 build (Jes Sorensen) 
+
+= kvm-86 [20 may 2009] =
+
+ * merge qemu.git
+  * qcow2 corruption fixes
+  * cpuid initialization fixes
+  * numa support
+  * improve rtc time drift compensation
+  * hardware watchdog
+ * merge bochs bios
+ * drop packets if all net links are down (Mark McLoughlin)
+ * fix device assignment error checking (Michael S. Tsirkin)
+ * fix -drive boot= parameter help (Pauline Middelink)
+ * fix tap networking after merge (Mark McLoughlin)
+ * set default configure option for ia64 (Xiantao Zhang)
+ * remove unnecesary differences compared to upstream (Anthony Liguori)
+ * fix build outside source directory (Anthony Liguori)
+ * ppc build fixes (Hollis Blanchard)
+ * revert incorrect ia64 icache sync (Hollis Blanchard)
+ * fix apic id save/load (Glauber Costa)
+  * fixes smp live migration
+ * libkvm cosmetics (Michael S. Tsirkin)
+ * fix virtio-net save/load (Alex Williamson)
+ * allow loading additional acpi tables (Gleb Natapov)
+ * allow loading additional smbios entries (Alex Williamson)
+ * fix dirty tracking on large memory (Glauber Costa)
+  * fixes live migration for guests with a lot of memory
+ * fix device assignment irq error handling (Alex Williamson)
+ * make kvm headers C++ friendly (Nathan Binkert)
+ * remove global page optimization (Marcelo Tosatti)
+  * fixes FreeBSD on shadow paging
+ * move lcall, ljmp, jcc, pio decoding to decode stage (Gleb Natapov)
+ * only skip instruction on task switch when approprite (Gleb Natapov)
+ * kvmclock cosmetics
+ * fix memory region overlap check (Jan Kiszka)
+ * ia64: don't hold slots lock in guest mode (Jes Sorensen)
+ * check cr3 validity on guest restore (Marcelo Tosatti)
+ * ia64: flush all tlbs on mapping change (Xiantao Zhang)
+ * ia64 cosmetics (Jes Sorensen)
+ * interrupt disable fixes for ia64 (Jes Sorensen)
+ * unregister cpu frequency notifiers on module unload (Jan Kiszka)
+ * fix mmu auditing code (Jan Kiszka)
+ * move irq injection logic to common code (Gleb Natapov)
+  * contains several irq fixes
+ * cleanup ept memory type support (Sheng Yang)
+ * enable snoop control for device assignment (Sheng Yang)
+ * disable vmx on system shutdown (Sheng Yang)
+ * fix nx feature reporting
+ * fix efer reads on hosts without efer
+ * fix apic debugging (Glauber Costa)
+ * fix cross vendor migration (Andre Przywara)
+ * drop request_nmi from kvm_stat (Jan Kiszka)
+ * fix MTRR, PAT, MCE, MCA feature reporting
+ * add cr8_legacy, abm, misaligned_sse, sse4, 3dnow prefetch feature reporting
+ * add movbe and popcnt feature reporting
+ * use smp_send_reschedule() to kick guests out of guest mode (Marcelo Tosatti)
+ * device assignment locking fixes (Marcelo Tosatti)
+ * remove port 80 passthrough on svm
+  * fixes hangs on some hp laptops
+ * deal with interrupt shadow state on emulated instructions (Glauber Costa)
+ * properly lock kvm_mmu_change_mmu_pages (Marcelo Tosatti)
+ * properly lock memory slot deletion (Marcelo Tosatti)
+ * expand on make menuconfig help (Robert P. J. Day)
+ * fix s390 memory slot locking vs vcpu run (Carsten Otte)
+ * use hrtimer for wakeup on s390 (Christian Borntraeger)
+ * s390 unlink vcpu on destroy (Christian Borntraeger)
+ * sanity check s390 intercept (Carsten Otte)
+ * s390 verify guest has some memory assigned (Carsten Otte)
+ * do not reexecute software interrupt instructions on intel (Gleb Natapov)
+ * disable cr8 intercepts if tpr patching is active (Gleb Natapov)
+
+= kvm-85 [21 apr 2009] =
+ *  merge qemu-svn
+  * microsoft serial mouse emulation
+  * cpuid fixes
+  * multiple simultaneous vnc client support
+  * allow additions of acpi tables from command line
+  * fix SDL with X.org evdev driver
+  * vnc sasl authentication
+  * fix one qcow2 corruptor
+  * fix qcow2 > 2TB images
+  * use preadv/pwritev when available for zero-copy block devices
+ * make pci mmio page aligned (Weidong Han)
+ * testsuite: MSR_KERNEL_GS_BASE handling
+ * fix extboot with cache=off (Nolan Leake)
+ * add release script
+ * add split qemu and kvm-kmod releases
+ * remove kvm script
+ * don't hardcode tsc_khz on older kernels (Marcelo Tosatti)
+ * count extboot as a disk in bios (Gleb Natapov)
+  * fixes Vista boot from virtio
+ * start/stop vcpus before/after devices (Yaniv Kamay)
+ * ia64 build fixes (Jes Sorensen)
+ * testsuite: test EFER.NXE
+ * ./configure fixes (Mark McLoughlin)
+ * don't use dirty log on ia64 (Yang Zhang)
+ * improve pci address parsing (Weidong Han)
+ * backward compatibility for PAGE_KERNEL_UC on ia64 (Yang Zhang)
+ * backward compatibility for msidef.h on ia64 (Yang Zhang)
+ * fix 4GB+ guest RAM with large pages (Marcelo Tosatti)
+ * clear tap features on initialization
+ * testsuite: jmp/jcc instructions (Gleb Natapov)
+ * fix handling of large pages in assigned devices (Joerg Roedel)
+ * mmu cleanups (Joerg Roedel)
+ * report irq injections to userspace (Gleb Natapov)
+ * set accessed bit on segment selectos on AMD (Andre Przywara)
+  * fixes cross-vendor migrations
+ * fix large page memory leak (Joerg Roedel)
+ * ppc e500 mmucsr0 register emulation (Liu Yu)
+ * support device deassignment (Weidong Han)
+ * fix ia64 msi build errors (Xiantao Zhang)
+ * update msr state when entering long mode (Amit Shah)
+ * fix test for long mode (Amit Shah)
+  * fixes some Solaris x64 variants
+ * fix sparse annotations (Hannes Eder)
+ * don't use highmem pages for vmx msr and pio bitmaps
+ * don't intercept MSR_KERNEL_GS_BASE on Intel
+  * speeds up Windows 2008 x64 somewhat
+ * unify ioapic and msi interrupt delivery (Sheng Yang, Gleb Natapov)
+ * msi-x support (Sheng Yang)
+ * fix kvmclock memory leak (Joerg Roedel)
+ * fix preempt warning in kvmclock (Matt T. Yourst)
+ * guest: skip pit-through-ioapic boot test (Marcelo Tosatti)
+ * stop ioapic code leaking into archs which don't have an ioapic (Christian Borntraeger)
+ * pit cleanups (Marcelo Tosatti)
+ * fix ia64 build (Zhang Yang)
+ * reduce unnecessary shadow update when a guest pte becomes dirty (Joerg Roedel)
+ * Altix SN2 real time clock support (Jes Sorensen)
+ * advertise irq routing table size (Sheng Yang)
+ * rework device assignment code (Sheng Yang, Marcelo Tosatti)
+ * fix missing flush on invlpg emulation (Andrea Arcangeli)
+ * fix ppc e500 mas0 wrong update (Liu Yu)
+ * fix smp instability on ppc e500 (Liu Yu)
+ * fix free_mmu_pages() doing things out of lock (Gleb Natapov)
+ * ignore reads to performance counter EVNTSEL msts (Amit Shah)
+  * fixes Kapersky antivirus failure
+ * clean up AMD interrupt injection (Gleb Natapov)
+ * make vmx module parameters readable, and reflect current setting
+ * simplify module parameter names
+ * fix compatibility mode guests ability to trash EFER
+ * don't unconditionally unhalt vcpu on timer event (Gleb Natapov)
+ * only unhalt vcpu on interrupt if interrupt window is open (Gleb Natapov)
+  * prevents 100% cpu on boot failure
+ * fix incorrect vmcs field sizes on some fields (Eddie Dong)
+ * fix misleading comment (Eddie Dong)
+ * enable external interrupts while in ia64 vmm (Yang Zhang)
+ * fix off-by-one calculating large page count
+ * emulate page fault caused by reserved bits set in guest pte (Eddie Dong, Sheng Yang)
+ * use different shadows when EFER.NXE changes
+ * clean up lapic freeing (Wei Yongjun)
+ * clean up flexpriority related code (Sheng Yang)
+ * fix vmx feature testing (Sheng Yang)
+ * fix PDPTE reserved bit testing (Eddie Dong)
+ * fix handling of a fault during NMI unblocked due to IRET (Gleb Natapov)
+ * clean up vmx interrupt completion (Gleb Natapov)
+ * fix task switch back link pointer (Gleb Natapov)
+ * fix near call emulation (Gleb Natapov)
+ * fix extboot failure after reset (Ryan Harper)
+ * ia64 vga fixes (Xiantao Zhang)
+ * ia64 instruction/data cache synchronization fixes (Xiantao Zhang)
+ * disable global page optimization (Marcelo Tosatti)
+  * fixes FreeBSD failures
+ * fix locking order when entering ia64 guest (Jes Sorensen)
+ * fix PIT mode 0 handling (Marcelo Tosatti)
+
+= kvm-84 [15 fev 2009] =
+
+ * merge qemu-svn
+  * redirect slirp traffic to qemu-char device
+  * slirp fixes
+  * qcow2 fixes
+  * nic link status control
+  * enable ac97 audio by default
+  * add virtio-console device
+  * fix rtc time drift on Windows (-rtc-td-hack option)
+  * add -vga none option for running headless guests
+  * better block device error propagation
+  * fix guests halting when switching desktop workspace
+  * improved display interfaces
+  * better logging support
+  * don't corrupt qcow2 images when out disk space on host
+  * dma api
+  * add pci device vendor ID
+  * vnc improvements
+  * improve Virtual PC disk format support
+  * scsi fixes
+  * multicast filtering for e1000 and virtio-net
+ * add libkvm wrapper for KVM_SET_CPUID2 interface (Amit Shah)
+ * fix cpuid for leaves 4, 11, 13 (Amit Shah)
+ * save ia64 nvam (Yang Zhang)
+ * compile fixes (Mark !McLaughlin, Jan Kiszka)
+ * generic irq routing
+ * build fixes against RHEL 5 hosts (Andrea Arcangeli)
+ * fix build when pc-bios directory is empty (Eduardo Habkost)
+ * improve host version check (Mark !McLaughlin)
+ * drop obsolete eflags conversion to/from qemu emulator (Jan Kiszka)
+ * preallocate memory with -mem-path (John Cooper)
+ * don't register unassigned PCI BARs (Gleb Natapov)
+ * more hrtimer API compatibility
+ * fix build on uniprocessor hosts (Jan Kiszka)
+ * fix build on pre-msi hosts (Jan Kiszka)
+ * allow stopping vm from vcpu thread (Gleb Natapov)
+ * fix cpu and pci hotplug (Gleb Natapov)
+ * ppc updates (Liu Yu)
+ * fix ia64 fp trap handler (Yang Zhang)
+ * fix ia64 vtlb handling (Xiantao Zhang)
+  * enables Windows 2008 on ia64
+ * support translating ia64 PAL arguments (Xiantao Zhang)
+ * implement ia64 PAL calls needed by Windows 2008 (Xiantao Zhang)
+ * map assigned device mmio as uncachable (Sheng Yang)
+ * fix lapic pending count calculation (Marcelo Tosatti)
+ * fix s390 printk (Christian Borntraeger)
+ * fix s390 problem state check (Christian Borntraeger)
+ * fix s390 SIGP set prefix ioctl (Christian Borntraeger)
+ * dynamic ia64 cpu count (Jes Sorensen)
+ * fix lapic build on i386 (Clemens Noss)
+ * make irq ack notifications use routing table (Marcelo Tosatti)
+ * FFXSR support (Alexander Graf)
+ * fix assigned device circular locking dependency (Mark !McLaughlin)
+ * drop unused code from string pio handlers (Jan Kiszka)
+ * fix kvmclock on hosts with unstable tsc (Gerd Hoffman)
+  * reenables Fedora 10 guests on those hosts
+ * enable msi from userspace (Sheng Yang)
+ * remove duplicated code in EPT handler (Sheng Yang)
+ * flush volatile msrs on Intel before emulating rdmsr
+  * fixes cygwin on Windows x64
+
+= kvm-83 [13 jan 2009] =
+
+ * amd iommu support (with Linux 2.6.29+ hosts) (Joerg Roedel)
+ * merge qemu-svn
+  * qcow2 correctness fixes
+  * '-drive serial=...' option
+  * virtio-net migration fixes
+ * fix '--with-patched-kernel' build on Ubuntu (Nolan Leake)
+ * improved tsc handling (Marcelo Tosatti)
+  * should reduce timing errors on older Linux guests
+ * remove cpuid code duplication due to upstream qemu work (Amit Shah)
+ * guest S3 sleep (Gleb Natapov)
+ * load assigned devices option rom (Kechao Liu)
+ * '-no-kvm-pit-reinjection' option to improve timing on RHEL 3 era guests (Marcelo Tosatti)
+ * remove duplicate firmware config interface probe in bios (Sebastian Herbszt)
+ * backward compatibility for marker_synchronize_register() (Eduardo Habkost)
+ * fix compile warning in tpr patching (Mark !McLoughlin)
+ * don't install kvm headers to /usr/local
+ * fix smbios memory size in certain cases (Bill Rieske)
+ * simplify mmu shadow walking function
+ * stop using vmap() on guest pages (annoys ksm) (Izik Eidus)
+ * fix warning on MSR_VM_HSAVE_PA in dmesg
+ * fix i8254 timer count read (Marcelo Tosatti)
+ * ppc e500 core support (Hollis Blanchard)
+ * fix vmx real mode guest state validity checks
+ * make pop instruction emulation a little more generic
+ * implement 'ret far' instruction emulation
+ * properly lock i8354 timer
+ * remove ppc debug support (Hollis Blanchard)
+ * fix race freeing assigned device interrupt (Sheng Yang)
+ * fix pci interrupt in freeing in device assignment (Sheng Yang)
+ * allow disabling msi for assigned devices (Sheng Yang)
+ * emulate amd microcode level msr (Alexander Graf)
+  * helps esx boot on kvm
+ * make page unshadowing a little faster
+ * clear pending pit interrupts when unmasking the timer irq
+  * fixes xen-on-kvm
+ * mmu notifiers release method (Marcelo Tosatti)
+  * fixes large pages support
+ * expose ia64 registers to userspace (Jes Sorensen)
+ * fix type in has_svm() (Joe Perches)
+ * drop unnecessary memory clearing when allocating shadow page (Marcelo Tosatti)
+ * rename "metaphysical" page attribute to "direct"
+ * fix irq routing with -no-kernel-irqchip
+
+= kvm-82 [25 dec 2008] =
+
+ * merge qemu-svn
+   * uuid support
+   * fix CVE-2007-5729 (slirp vulnerability)
+   * fix CVE-2008-2382 (vnc denial of service)
+   * better scsi support
+   * pci subsystem id for pci devices
+     * this will cause Windows guest to rediscover hardware
+   * improved I/O parallelism
+   * ppc kvm support
+   * hpet support
+     * not fully integrated yet
+   * monitor 'info status' command
+ * merge bochs-bios-cvs
+   * uuid support
+   * prepare for S3 sleep
+ * merge vgabios-cvs
+ * much improved guest debugging (Jan Kiszka)
+   * both debugger in guest and debugger in host
+ * fix kvm makefile for separate object dir (Andi Kleen)
+ * nested svm (Alexander Graf)
+   * run kvm in kvm in kvm...
+ * fix ia64 register and stack access from userspace (Jes Sorensen)
+ * don't treat a global pte as global if cr4.pge is clear
+   * fixes Vista x86 smp failure on boot
+ * properly lock virtual i8259 interrupt controller
+ * fix large host pages invlpg/resync
+   * fixes oops when using host hugetlbfs
+ * fix vmload instruction misemulated as lidt
+
+= kvm-81 [16 dec 2008] =
+
+ * merge qemu-svn
+  * fix performance regression with qcow2 files
+  * improve qcow2 data integrity with cache=writethrough
+  * fix display corruption with gnome panel auto-appear
+  * scsi improvements
+ * shld/shrd instruction emulation and unit test (Guillaume Thouvenin)
+ * ppc updates (Hollis Blanchard, Deepa Srinivasan, Christian Ehrhardt)
+ * prepare virtio for upstream merging (Anthony Liguori)
+ * fix uninitialized variable in virtio-net (Anthony Liguori)
+ * fix compile failure on Debian (Amit Shah)
+ * fix display loss in opensuse 11 installer
+ * fix vmmcall emulation on intel (Amit Shah)
+  * fixes amd->intel migration
+ * allow userspace to work with modules from kvm-79 and earlier
+ * fix undefined behaviour copying cpuid signature (Guillaume Thouvenin)
+ * fix build with --kerneldir (Maik Hentsche)
+ * really exit if device assignment fails (Mark !McLoughlin)
+ * fix vga on ia64 (Xiantao Zhang)
+ * simplify nmi injection from userspace (Jan Kiszka)
+ * enable virtio zero-copy (Mark !McLoughlin)
+  * also fixes crash in rare cases
+ * fix display loss on 32-bit hosts
+ * reduce tlb flushing when resyncing pages (Marcelo Tosatti)
+ * don't resync global pages on context switch (Marcelo Tosatti)
+  * improves HIGHMEM performance
+ * prepopulate shadow on invlpg (Marcelo Tosatti)
+ * fix kvmclock when HZ != 1000 (Eduardo Habkost)
+ * fix module unload race oops (Christian Borntraeger)
+ * reduce stack footprint on large hosts (Rusty Russell)
+ * reduce capability reporting code duplication
+ * check for missing pae pdptr on invlpg emulation (Marcelo Tosatti)
+  * fixes solaris 10 oops
+ * fix handlig of ack from irq shared between assigned and emulated devices (Mark !McLoughlin)
+ * fix nmi-vs-irq race for -no-kvm-irqchip (Jan Kiszka)
+
+= kvm-80 [7 dec 2008] =
+
+ * merge qemu-svn
+  * automatic port allocation for vnc and similar
+  * improved cdrom media change handling
+  * improved debugging support
+  * more scsi improvements
+  * e1000 vlan offload
+ * up to 256 vcpus for ia64 (Jes Sorensen)
+ * only request io port permission if device assignment is enabled (Jes Sorensen)
+ * fix in-kernel ioapic reset (Jan Kiszka)
+  * fixes guest reboot failures
+ * fix balloon for systems with page size different from 4K (Hollis Blanchard)
+ * fix bios memory reporting with >32G guests (Bill Rieske)
+ * drop inclusion of compiler.h in external modules (Xiantao Zhang)
+ * use vcpu pointers instead of vcpu numbers (Jes Sorensen)
+ * goodbye bool (Jes Sorensen)
+ * stop using separate structure for cpu state; use qemu's instead (Jes Sorensen)
+ * apic testsuite
+ * fix -no-kvm apic with smp (Jan Kiszka)
+ * clean up userspace nmi injection (Jan Kiszka)
+ * adjust external module for 2.6.28 hosts (Mark !McLoughlin)
+ * much improved large mtu/gso support for virtio-net (Mark !McLoughlin)
+ * simplify x86 emulator stack pop operations
+ * clean up device assignment code (Mark !McLoughlin)
+ * fix extboot returning error incorrectly (Glauber Costa)
+ * constrain device assignment mmio to page alignment (Han Weidong)
+ * ppc speedups (Hollis Blanchard)
+ * fix s390 problem state handling (Christian Borntraeger)
+ * fix interrupt loss when injecting an nmi
+  * fixes Linux guests with nmi watchdog hanging
+ * fix ia64 build (Xiantao Zhang)
+ * fix emergency reboot and kdump on host while running VMs (Eduardo Habkost)
+ * fix syncing of self-referencing ptes (Marcelo Tosatti)
+ * add printk() for ia64 vmm (Xiantao Zhang)
+ * add crashed vm handler for ia64 (Xiantao Zhang)
+ * use correct calling convention into ia64 PAL code (Xiantao Zhang)
+ * request interrupt window after injecting an interrupt if another is pending
+ * plug ppc memory leak when destroying a vm
+ * sign kvmclock as a paravirt operation (Glauber Costa)
+ * MSI support for device assigment (Sheng Yang)
+ * fix shadow pagetables leak (Marcelo Tosatti)
+  * fixes an oops
+ * optimize setting new pte while syncing a page (Marcelo Tosatti)
+ * reduce code duplication in x86 emulator
+ * fix s390 refcounting; allow module unload (Christian Borntraeger)
+ * fix s390 memory leak (Christian Borntraeger)
+ * prevent tracing calls into unloaded module (Wu Fengguang)
+ * fix sparse warnings (Hannes Eder)
+ * clean up irq ack notifiers (Mark !McLoughlin)
+ * powerpc large page support (Hollis Blanchard)
+ * faster powerpc shadow tlb handling (Hollis Blanchard)
+ * reduce powerpc guest tlb miss rate on context switches (Hollis Blanchard)
+ * powerpc exit timing stats (Hollis Blanchard)
+ * fix -no-kvm-irqchip not working with smp (Jan Kiszka)
+ * fix rendering regressions introduced by upstream qemu rendering support
+
+= kvm-79 [12 nov 2008] =
+
+ * merge qemu-svn
+  * fix qcow2 problems with scsi
+  * 'info chardev' monitor command
+ * device assignment userspace (Amit Shah, Muli Ben Yehudah, Ben-Ami Yassour, Weidong Han, Or Sagi, Nir Peleg, Glauber Costa, Xiantao Zhang)
+ * multiple processor infrastructure for ppc (Hollis Blanchard)
+ * fix error handling in eventfd() emulation (Mark !McLoughlin)
+ * handle large mtu with virtio-net (Mark !McLoughlin)
+ * move x86 specific device assignment code to x86 files (Christian Ehrhardt)
+ * fix 'pci_add' command descriptor (Weidong Han)
+ * enable pci function level reset for device assignment (Sheng Yang)
+ * fix incorrect handling of aliases gfns (Izik Eidus)
+ * ppc optimizations (Hollis Blanchard, Christian Ehrhardt)
+ * disallow guests from setting memory type when using EPT (Sheng Yang)
+ * fix cpuid leaf 11 loop termination (Nitin A Kamble)
+ * fix cpuid multiple leaf iteration (Nitin A Kamble)
+ * fix ia64 uniprocessor build (Xiantao Zhang)
+ * fix ppc Kbuild constraints (Hollis Blanchard)
+ * fix pit initialization memory leak
+
+= kvm-78 [2 nov 2008] =
+
+ * fix paravirt kernels due to missing oos flush (Marcelo Tosatti)
+ * code cleanups (Sheng Yang)
+ * fix guest shared interrupts for device assignment (Sheng Yang)
+ * avoid stale asm-offsets.h on ia64 (Xiantao Zhang)
+ * fix ia64 halt emulation (Xiantao Zhang)
+ * extend slot bitmap on i386 (Sheng Yang)
+ * move private memory slots to avoid conflict with device assignment (Sheng Yang)
+ * future-proof device assignment ABI
+ * add emulation and unit tests for add acc, imm instruction (Guillaume Thouvenin)
+ * fix nmi watchdog emulation (Jan Kiszka)
+ * optimize nmi watchdog delivery (Jan Kiszka)
+ * require irq ack notifier to be used with in-kernel irqchip (Sheng Yang)
+ * don't halt non-boot cpu if using in-kernel irqchip (Gleb Natapov)
+ * add cscope definitions (Sheng Yang)
+ * merge qemu-svn
+  * new live migration implementation
+  * usb improvements
+  * migration fixes
+ * read UUID from qemu (Gleb Natapov)
+ * increase max cpu count to 255 for ia64 (Xiantao Zhang)
+ * handle INIT before SIPI (Gleb Natapov)
+ * update ppc for nmi changes (Christian Ehrhardt)
+ * fix external module generation unifdef problem (Sheng Yang)
+ * set 'g' bit of segment descriptor on AMD when necessary (Amit Shah)
+ * set 'busy' bit of task descriptor on AMD when necessary (Amit Shah)
+  * fixes some AMD->Intel live migration failures
+ * use emulator to adjust rip of pio string instructions (Guillaume Thouvenin)
+ * increase rmap preallocation (Marcelo Tosatti)
+  * fixes oops on mmu intensive smp workloads
+ * handle mmio in big real mode (Guillaume Thouvenin)
+ * reorganize ia64 guest data area (Xiantao Zhang)
+ * fix ia64 guest signal mask (Xiantao Zhang)
+ * reduce locking when vcpu is halted (Xiantao Zhang)
+ * update e820 table for ept real mode identity map page (Sheng Yang)
+ * fix external module build with kvmtrace
+ * fix ppc xer access (Christian Ehrhardt)
+ * fix ppc threading (Hollis Blanchard)
+ * implement libcflat for ppc 44x (Hollis Blanchard)
+ * set smp limit for ppc (Hollis Blanchard)
+ * fix ppc memory setup (Christian Ehrhardt)
+
+= kvm-77 [12 oct 2008] =
+
+ * merge bochs-bios-cvs
+ * merge qemu-svn
+  * more -cpu options
+  * faster disk emulation (esp. with scsi/virtio)
+ * improved NMI support (Jan Kiszka)
+ * improve >4GB memory support (Alex Williamson)
+ * memory alias cleanups (Glauber Costa)
+ * fix kvmtrace segfault (Ryota OZAKI)
+ * make external module compile on split source/object configs (Alexander Graf)
+  * allows compiling on opensuse
+ * fix -std-vga regression
+ * fix migration failure at end of migration protocol
+ * map mmio pages for device assignment (Weidong Han)
+ * silence lapic kernel messages (Jan Kiszka)
+ * fix vcpu reset (Gleb Natapov)
+ * fix missed invlpg on EPT-enabled machines with EPT disabled (Marcelo Tosatti)
+ * device assignment on ia64 (Xiantao Zhang)
+ * memory type support on EPT (Sheng Yang)
+
+= kvm-76 [28 sep 2008] =
+
+ * merge qemu-svn
+  * improved usb support
+  * vnc improvements
+  * pass uuid to guest
+  * scsi improvements
+ * change virtio-blk to guest-endian configuration (Liu Yu)
+ * add 'call near absolute' to x86 emulator and testsuite (Mohammed Gamal)
+ * drop support for kernel memory allocation (Glauber Costa)
+ * avoid fiddling with ISA mappings (Jan Kiszka)
+  * improves debugging support
+ * fix external module build on 2.6.22 hosts
+ * make kernel and userspace memory slot count agree (Sheng Yang)
+ * add 'cmp' to x86 emulator testsuite (Mohammed Gamal)
+ * allow 'make sync' from toplevel directory
+ * external module compatibility for get_user_pages_fast() api (Jan Kiszka)
+ * correct mtrr setup with >= 4GB RAM (Alex Williamson)
+ * fix ia64 boot with acpi enabled (Xiantao Zhang)
+ * initialize userspace kvm context (Uri Lublin)
+ * fix ia64 with >= 3GB RAM (Xiantao Zhang)
+ * avoid allocating translated code buffer when using kvm
+ * simplify memory registration (Glauber Costa)
+ * support kvmtrace with external module (Eduardo Habkost)
+ * ia64 init code simplification (Jes Sorensen)
+ * ia64 external module compatibility with older kernels (Xiantao Zhang)
+ * fix live migration due to slot number getting lost (Uri Lublin)
+ * prevent live migration if a device is missing on the target (Uri Lublin)
+ * fix include-compat/asm symlinks (Uri Lublin)
+ * do not execute halted vcpus (Marcelo Tosatti)
+ * fix global tlb flushes with NPT (Joerg Roedel)
+ * fix preemption error on real mode emulation
+ * fix page aging with EPT (Sheng Yang)
+ * simplify locking around ppc shadow tlb page access (Hollis Blanchard)
+ * cleanup redundant vmcs read (Jan Kiszka)
+ * fix 64-bit jmp instruction emulation
+ * move vmx msr definitions to common code
+ * better support for instructions that reference the accumulator (Guillaume Thouvenin)
+ * add cmp acc, imm instruction emulation (Guillaume Thouvenin)
+ * kernel support for device assignment (Allen Kay, Amit Shah, Weidong Han, Ben-Ami Yassour)
+ * switch to using get_user_pages_fast() (Marcelo Tosatti)
+  * nice speedup on 2.6.27+ hosts
+ * build fix for ia64 (Jes Sorensen)
+ * code cleanup (Harvey Harrison)
+ * avoid entering guest after a startup IPI (Gleb Natapov)
+ * simplify 'push reg' instruction emulation (Guillaume Thouvenin)
+ * fix error handling on vcpu creation failure (Glauber Costa)
+ * support Tukwilla ia64 processors (Xiantao Zhang)
+ * fix tlb flush when converting a large page to small pages (Marcelo Tosatti)
+ * out-of-sync shadow (Marcelo Tosatti)
+ * reduce inter-processor interrupt generation when using the PIC (Marcelo Tosatti)
+
+= kvm-75 [10 sep 2008] =
+
+ * add 1280x768 std-vga resolution
+ * ballooning (Anthony Liguori)
+  * requires 2.6.27+ host to work correctly
+ * fix bad memory sizing on ia64 (Xiantao Zhang)
+ * restore option roms to their original content on reset
+  * fixes extboot failures after reset
+ * enable ia64 power manangement (Xiantao Zhang)
+ * add cld/std/cli/sti/clc instructions to testsuite (Mohammed Gamal)
+ * fix compile errors on hosts that lack MADV_DONTFORK
+ * avoid accessing CMOS NVRAM from ACPI AML (Gleb Natapov)
+  * fixes rare reboot failures with Windows
+  * fixes ACPI error messages in Windows event log
+ * add mp state for ia64 (Xiantao Zhang)
+ * add missing prototypes (Jes Sorensen)
+ * fix compiler warnings (Jes Sorensen)
+ * add in/out instructions to emulator (Mohammed Gamal)
+ * use Windows pcr instead of guest's tr for tpr patching cpu id
+  * fixes hibernate/resume with guest smp
+ * account for realmode/npt/ept page faults in statistics
+ * fix locking around dirty log tracking
+ * flush tlbs after fetching the dirty log
+ * fix random segfaults with npt (Joerg Roedel)
+ * fix setting accessed bit on non-speculative sptes
+ * fix tlb flush during page zap
+ * slightly optimize event injection with npt
+ * add MC5_MISC msr support (Joerg Roedel)
+  * fixes Linux bootup warnings
+ * make s390 facility bits future proof (Christian Borntraeger)
+ * improve s390 guest Kconfig help (Christian Borntraeger)
+ * add cld/std instructions to emulator (Mohammed Gamal)
+ * fix address overflow in ept (Sheng Yang)
+ * add statistic for guest irq injections
+ * remove unnecessary remote tlb flush (Joerg Roedel)
+
+= kvm-74 [28 aug 2008] =
+
+ * make real-mode startup state conform to spec
+ * fix scheduling error in experimental big real mode support
+ * fix reboot fault handler exception table entry (Eduardo Habkost)
+ * x86 emulator code cleanup (Roel Kluin)
+ * fix 'neg r/m' instruction emulation forced to byte size
+ * fix shadow ptes corruption on i386 hosts running smp guests
+ * fix kvmtrace ABI breakage (Adrian Bunk)
+ * enable virtio for ia64
+ * add generic shadow page table walker
+ * allocate internal guest memory as MAP_PRIVATE
+ * don't call get_user_pages(.force=1)
+  * paves the way for get_user_pages_fast()
+ * add mov r, imm instructions to the emulator (Mohammed Gamal)
+ * realmode emulator testsuite
+ * ia64 external module support (Xiantao Zhang)
+ * support tap IFF_VNET_HDR (Mark !McLoughlin)
+ * merge qemu-svn
+  * improved usb support
+  * usb auto connect/disconnect
+ * protect against possible corruption during qemu fork() on older hosts (Marcelo Tosatti)
+
+= kvm-73 [21 aug 2008] =
+
+ * merge qemu-svn
+  * improve qcow2 performance with cache=off
+  * ide fixes
+ * ia64 external module (Xiantao Zhang)
+ * external module compatibility with 2.6.27 hosts
+ * fix sysenter msrs save/restore (Alexander Graf)
+ * fix 2.6.26 host support (Nikola Ciprich)
+ * fix linux-user build (Philippe Gerum)
+ * virtio-net speedup (Mark !McLoughlin)
+ * fix ./configure with multiple arguments
+ * support Windows hibernation on non-!FlexPriority hosts
+ * fix makefile dependencies (Sheng Yang)
+ * fix compiler warnings (Jan Kiszka)
+ * work around dhclient checksum offload brokenness (Anthony Liguori)
+ * full swapping support (Andrea Arcangeli)
+  * needs 2.6.27 hosts
+ * internal irq ack notification api (Marcelo Tosatti, Amit Shah, Ben-Ami Yassour, Avi Kivity)
+ * fix pit timer interrupt injection logic (Marcelo Tosatti)
+ * paravirt guest: query tsc frequency from host (Glauber Costa)
+ * pci device assignment (Amit Shah, Ben-Ami Yassour, Weidong Han)
+  * still lacking dma
+ * fix large page crash on z10 mainframes (Christian Borntraeger)
+ * stack usage reduction (Dave Hansen, Sheng Yang)
+ * code cleanup (Sheng Yang)
+ * fix debug register corruption on Intel hosts (Marcelo Tosatti)
+ * fix -no-kvm-irqchip
+ * fix irq acking on pic reset (Marcelo Tosatti)
+ * ignore spurious timer interrupt acks
+ * limit device assignment to privileged user (Amit Shah)
+ * big real mode emulation framework (Mohammed Gamal)
+ * simpify irq injection (Amit Shah)
+ * dummy irq ack notifier for ia64 (Xiantao Zhang)
+
+= kvm-72 [28 jul 2008] =
+
+ * fix ia64 build breakage (Xiantao Zhang)
+ * ppc kvmtrace support (Christian Ehrhardt)
+ * merge qemu-svn
+  * fixes suspend/resume of multiple nics
+  * adds Virtual Distributed Ethernet (vde) support
+ * add 'push mem' to patched tpr instructions
+ * use host kernel anon_inodes support if available
+ * robustify signalfd() emulation
+ * avoid losing the iothread on random signals
+ * fix test for iothread (Jan Kiszka)
+ * remove hypercall device (Anthony Liguori)
+ * remove duplicate monitor command (Anthony Liguori)
+ * remove unused function declaration (Anthony Liguori)
+ * remove unnecessary change to TARGET_PAGE_SIZE (Anthony Liguori)
+ * remove qemu/kvm application decoration (Anthony Liguori)
+ * add 'info kvm' monitor command  (Anthony Liguori)
+ * s390 libkvm port (Carsten Otte)
+ * fix compile warning (Carlo Marcelo Arenas Belon)
+ * fix duplicate #include (Carlo Marcelo Arenas Belon)
+ * adjust external module for 2.6.27 hosts
+ * avoid tpr patching when the stack is not valid (Marcelo Tosatti)
+  * fixes some variant of Windows 2003 SMP
+ * fix extboot stomping on reserved interrupt vectors (H. Peter Anvin)
+ * remove unused -translation option (Anthony Liguori)
+ * fix preemption during copy_from_user_inatomic() on older hosts (Andrea Arcangeli)
+ * fix ppc cpu initialization (Hollis Blanchard)
+ * drop shadow ptes on memslot destruction (Marcelo Tosatti)
+ * improve invalid shadow root page table handling (Marcelo Tosatti)
+ * simplify mmu page zapping
+ * simplify interrupt processing on Intel
+ * remove redundant check for real mode (Mohammed Gamal)
+ * add clflush emulation (Glauber Costa)
+ * fix race setting shadow ptes on i386
+ * consolidate pic isr clearing into a function
+ * consolidate exception interrupt vector #defines (Jan Kiszka)
+ * fix interrupt reinjection in real mode (Jan Kiszka)
+ * unify guest register save/restore code
+ * x86 hardware task switching fixes (Marcelo Tosatti)
+ * optimize vmx by avoiding saving the host stack pointer
+ * fix interrupts being delayed by instruction emulation
+  * improves Vista stability
+ * fix reloading kvm-intel.ko while changing parameters (Sheng Yang)
+ * fix reboot exception entry build bug (Ingo Molnar)
+ * ignore no-op DEBUGCTL msr writes (Alexander Graf)
+  * fixes Netware
+ * fix irq state leak on ia64 (Julia Lawall)
+ * s390 fixes (Carsten Otte, Christian Borntraeger, Martin Schwidefsky)
+ * ppc guest breakpoint support (Hollis Blanchard)
+ * optimize ppc by not saving host tlb state (Hollis Blanchard)
+ * reduce ppc guest tlb writes (Hollis Blanchard)
+ * avoid guest tlb flushes on guest privilege switches (Hollis Blanchard)
+
+= kvm-71 [14 jul 2008] =
+
+ * fix virtio isr clearing (Laurent Vivier)
+ * kvmtrace ppc userspace support (Jerone Young)
+ * avoid fragmenting virtio-blk transfers (Anthony Liguori, Mark !McLoughlin)
+ * ia64 build fixes (Anthony Xu)
+ * remove unnecessary virtio-net printout (Marcelo Tosatti)
+ * remove configure warning about gcc 3 (Carlo Marcelo Arenas Belon)
+ * rhel 5.2/centos 5.2 host support
+ * merge qemu-svn
+  * adds pulseaudio driver
+  * nbd client/server
+ * disable cpu emulation by default on ia64 (Xiantao Zhang)
+ * place test support files in a library (Jerone Young)
+ * fix qemu monitor screendump
+ * fix lost interrupt when changing a device irq
+  * fixes devices going away when disabled and enabled several times
+ * fix oops on shutdown freeing coalesced mmio page (Akio Takebe)
+ * optimize segment register access in emulator
+ * allow run-time enabling of mmu debug
+ * fix host msr corruption when host preempt is enabled
+ * fix kvmclock (Gerd Hoffmann)
+ * rename badly named msrs (Sheng Yang)
+ * fix incorrect usage of vmcs_config when using ept (Sheng Yang)
+ * emulate performance counter msrs on Intel (Chris Lalancette)
+  * allows Linux 2.6.9 guests to boot
+ * optimize vapic locking when disabled (Marcelo Tosatti)
+ * don't allocate dirty bitmap for s390 (Catsten Otte)
+ * fix memory leak on guest exit (Carsten Otte)
+ * update s390 guest base and limit (Christian Borntraeger)
+ * optimize access to guest registers (Marcelo Tosatti)
+ * add memory clobber to hypercalls (Anthony Liguori)
+  * fixes booting guests compiled with gcc 4.3
+ * fix ioapic hang on heavy load (Mark !McLoughlin)
+ * move kvmtrace definitions to common header (Hollis Blanchard)
+ * fix suspend/resume on AMD (Joerg Roedel)
+ * make some functions static (Adrian Bunk)
+ * fix shrinker locking (Marcelo Tosatti)
+ * fix ept tlb flush (Sheng Yang)
+ * fix signal handling on uninitialized vcpus
+ * fix hlt instruction in real mode (Mohammed Gamal)
+ * check pic irq range (Ben-Ami Yassour)
+ * add function to inject irqs into guests (Amit Shah)
+
+= kvm-70 [17 jun 2008] =
+
+ * improve virtio net performance (Anthony Liguori)
+ * enable pci slot identification for OS X (Alexander Graf)
+ * fix guest reset (Jan Kiszka)
+ * code cleanups (Jan Kiszka)
+ * fix userspace compilation on older kernels (Chris Wright)
+ * support running on 2.6.16 hosts (Andrea Arcangeli)
+  * including SLES 10
+ * generate mptable even for uniprocessor guests
+  * helps esx get further along
+ * fix corrupted breakpoints (Jerone Young)
+ * on_vcpu() mechanism to execute a function on a vcpu thread
+ * fix 'info registers' monitor command
+ * fix vcpu register access livelock when a vcpu is spinning
+ * fix stopping on debug events (Jan Kiszka)
+ * fix livelocks in guest debugger (Jan Kiszka)
+ * add mtrr support
+  * helps esx limp a bit more
+ * fix incorrect pmtimer overflow interrupt generation
+ * add 'push imm' instruction to testsuite
+ * fix on_vcpu() during guest debug (Jan Kiszka)
+ * document boot option for drive flag (Carlo Marcelo Arenas Belon)
+ * coalesced mmio support (Laurent Vivier)
+  * should speed up some workloads
+ * allow kprobes to coexist with preempt notifier emulation (Andrea Arcangeli)
+ * allow virtio devices to reset themselves (Marcelo Tosatti)
+ * asynchronous virtio storage device (Marcelo Tosatti)
+  * should improve performance
+ * fix deadlock waiting for I/O completion
+ * merge qemu-svn
+  * remove dependency on gcc 3
+  * vnc client segfault fix
+  * fix vnc problems on resize
+  * qemu-nbd tool
+ * fix libkvm memory slot destruction api (Ben-Ami Yassour)
+ * enable tpr optimization for smp
+  * should drastically speed up Windows XP SMP guests
+ * big-endian kvmtrace support (Li Tan)
+ * remove unneeded variable (Glauber Costa)
+ * convert acpi tables to use the C preprocessor for less repetition
+ * external module compatibility for NMI (Alexander Graf)
+ * fix live migration with new on_vcpu() calls
+ * fix false flooding when a pte points to a page table
+  * improves 2.4 pae guests with CONFIG_HIGHPTE
+ * enable NMI support on Intel (Sheng Yang)
+ * fix zero extension during mmio on ia64 (Jes Sorensen)
+ * fix hypercall return value on AMD
+  * fixes running CONFIG_KVM_GUEST guests
+ * s390: use yield() instead of schedule() (Christian Borntraeger)
+ * s390: fix locking order problem (Christian Borntraeger)
+ * s390: handle machine checks while guest is running (Christian Borntraeger)
+ * s390: fix interrupt delivery (Carsen Otte)
+ * s390: send program check on access error (Carsen Otte)
+ * s390: fix race when idling (Carsen Otte)
+ * ppc: add lwzx/stwz instruction emulation (Hollis Blanchard)
+ * ppc: code cleanup (Hollis Blanchard)
+ * ppc: report bad gfns (Hollis Blanchard)
+ * optimize pio path slightly
+ * improve segment register ordering
+ * migrate pit timer on vcpu migration (Marcelo Tosatti)
+ * emulate jmp far instruction (Guillaume Thouvenin)
+ * emulate mov reg, imm instruction (Guillaume Thouvenin)
+ * emulate mov reg, sreg instruction (Guillaume Thouvenin)
+ * optimize mmu page prefetching
+ * emulate push imm instruction
+ * avoid mmu page prefetching on AMD
+ * allow VMware Server to take over vmx when unloading the module (Eli Collins)
+ * avoid spinning during large guest teardown
+ * fix ioapic interrupt sharing (Marcelo Tosatti)
+ * fix crash on resume from suspend to ram (Andrea Arcangeli)
+ * fix race between timer migration and vcpu migration (Marcelo Tosatti)
+ * close timer injection race when entering guest mode (Marcelo Tosatti)
+ * fix reverse map corruption with large pages (Marcelo Tosatti)
+ * fix large page pte updates on non-pae guests (Marcelo Tosatti)
+ * avoid timer injection if timer already pending (Marcelo Tosatti)
+ * avoid linear rip calculation if not reporting (Glauber Costa)
+ * fix host oops on guest userspace access to guest page table
+ * improve emulation failure reporting
+ * emulate nop and xchg reg, acc (Mohammed Gamal)
+ * handle undecoded rex.b when r/m = 5
+ * simplify r/m and sib decoding
+ * simplify relative rip decoding
+ * avoid segment adjust for lea instruction
+
+= kvm-69 [19 may 2008] =
+
+ * fix kvm guest clock compile error without apic (Glauber Costa)
+ * support PIT mode 3 (Aurelien Jarno)
+  * needed by GNU Hurd
+ * fix host oops emulating smsw on AMD
+ * fake performance counter MSRs on AMD (Chris Lalancette)
+  * fixes RHEL 4 guests
+ * fix virtio compile error on s390 (Heiko Carstens)
+ * fix hlt emulation when PIT is running but not injecting interrupts (Marcelo Tosatti)
+ * ditto for local apic (Marcelo Tosatti)
+ * fix kernel and userspace structure name clash on ia64 (Xiantao Zhang)
+ * fix GVMM module including non-PIC objects (Xiantao Zhang)
+ * 'make mrproper' fix (Andrew Morton)
+ * fix host oops on emergency reboot when hitting virt instructions
+ * simplify host cpu unplug
+ * fix kvm_vcpu_block() state race (Marcelo Tosatti)
+ * set iosapic pin count to 48 for ia64 (Xiantao Zhang)
+ * ppc: fix compile warning (Hollis Blanchard)
+ * ppc: fix lost simultaneous interrupts (Hollis Blanchard)
+ * ppc: log failed DCR accesses (Hollis Blanchard)
+ * ppc: order IRQ bit numbers as per docs (Hollis Blanchard)
+ * ppc: remove IRQ polarity code (Hollis Blanchard)
+ * ppc: remember state of level-triggered interrupts (Hollis Blanchard)
+ * ppc: emulate pci controller on 440 SoC (Hollis Blanchard)
+ * ppc: add pci controller to bamboo platform (Hollis Blanchard)
+ * external module compatibility updates
+ * merge qemu-svn
+  * fix CVE-2007-1320 - Cirrus LGD-54XX "bitblt" heap overflow
+  * allow boot device change from the monitor
+  * reduce spurious vga updates
+  * fix CVE-2008-2004 - format guessing vulnerability
+ * remove merge conflict leftover (Carlo Marcelo Arenas Belon)
+
+= kvm-68 [4 may 2008] =
+
+ * Intel EPT support (Sheng Yang)
+ * Code cleanups (Harvey Harrison)
+ * Fix task switch busy bit setting (Izik Eidus)
+ * Reduce guest idle cpu usage on ppc (Hollis Blanchard)
+ * Support floating point instructions on ppc (Christian Ehrhardt)
+ * Fix lmsw emulation
+    * fixes host oops on AMD
+ * Add PIT mode 4 support (Marcelo Tosatti)
+    * fixes DragonflyBSD
+ * Avoid spurious exceptions on state reload (Jan Kiszka)
+ * Add SVM kvmtrace support (Joerg Roedel)
+ * Avoid schedule-in-atomic on 2.6.26 hosts (Andrea Arcangeli)
+ * Handle vma regions with no backing page (Anthony Liguori)
+    * yet another step on the way to pci device assignment
+ * move external module compatibility code into .c file
+ * build: sync non-x86 kvm headers
+ * avoid using kernel headers; use installed libc headers instead
+ * don't exit iothread berfore all vcpus are stopped (Dor Laor)
+ * libkvm uninitialized variable fix (Marcelo Tosatti)
+ * remove old user/config.mak (Jerone Young)
+ * fix vcpu startup race (Anthony Liguori)
+ * dump all libkvm errors to stderr (Jan Kiszka)
+ * fix cross-compilation (Jerone Young)
+ * fix kvm_show_code() to work on ROM and real-mode (Jan Kiszka)
+ * allow qemu -kernel option with extboot (Mark McLoughlin)
+
+= kvm-67 [28 apr 2008] =
+
+ * s390/ia64: compile fix (Christian Borntraeger)
+ * s390: change virtio interrupt to follow arch specification (Christian Borntraeger)
+ * close vcpu refcounting race (Al Viro)
+ * code cleanups (Hollis Blanchard, Christian Borntraeger)
+ * ppc 44x support (Hollis Blanchard, Jerone Young)
+ * reduce cr8 intercepts on AMD (Joerg Roedel)
+   * speeds up Vista x64
+ * fix locking in paravirt mmu support (Marcelo Tosatti)
+ * fix ppc build on non-44x (Stephen Rothwell)
+ * fix PIT time-drift compensation with multiple guests (Marcelo Tosatti)
+ * merge qemu-svn
+ * spin up vcpu threads before setting lapic contents
+ * pass disk geometery to extboot loader (Ryan Harper)
+ * separate header copying from source copying in 'make sync'
+ * implement 'hypervisor present' cpuid bit
+ * fix address truncation on ia64 (Jes Sorensen)
+ * handle nic/storage hotplug failure gracefully (Chris Wright)
+ * more kvm_stat display options
+ * fix qemu system_powerdown with Linux guests
+
+= kvm-66 [16 apr 2008] =
+
+ * adjust external module for 2.6.25 module locations (Anthony Liguori)
+ * fix userspace compilation failure without kernel pit (Joerg Roedel)
+ * kvmtrace performance monitoring mechanism (Eric Liu)
+ * stop all vcpus before saving their state (Marcelo Tosatti)
+   * fixes smp live migration
+ * save/restore kernel apicbase (Marcelo Tosatti)
+ * block SIG_IPI signals (Marcelo Tosatti)
+ * smsw mem16, lmsw mem16 emulation and unit tests
+ * fix compile warnings (Jerone Young)
+ * fix reset with iothread
+ * ia64 architecture support (Xiantao Zhang, Anthony Xu)
+ * don't assume guest pages are backed by a 'struct page' (Anthony Liguori)
+   * needed for pci device assignment
+ * register kvm's ioctl range
+ * fix hardware task switching buglet (Izik Eidus)
+ * fix mce handling on AMD (Joerg Roedel)
+ * do hardware task switching in hardware when NPT is enabled (Joerg Roedel)
+ * fix timer race waking up a halted vcpu with smp (Marcelo Tosatti)
+ * fix irq race leading to irqs delivery delays (Marcelo Tosatti)
+ * fix triple fault handling on AMD
+ * fix lea instruction emulation
+
+= kvm-65 [6 apr 2008] =
+
+ * fix hotplug build for non-x86 (Xiantao Zhang)
+ * ignore reads from the apic EOI register (Glauber Costa)
+   * fixes Linux 2.6.25-rclate bootup problems
+ * compile fixes (Carlo Marcelo Arenas Belon)
+ * fix ftruncate() on hugetlbfs use on older Linux hosts (Marcelo Tosatti)
+ * endianness fix virtio-block (Anthony Liguori)
+   * fixes virtio-blk on ppc
+ * refactor in-kernel PIT to be a separate device (Anthony Liguori)
+ * separate thread for I/O completions and timers (Marcelo Tosatti)
+ * fix vmmouse smp (Anthony Liguori)
+ * fix loading uninitialized variable into apic registers (Marcelo Tosatti)
+   * fixes apic being disabled on smp Linux guests running X
+ * disable kvm clock on Voyager or SGI Visual WS (Randy Dunlap)
+ * s390 support (Carsten Otte, Martin Schwidefsky, Christian Borntraeger, Heiko Carstens)
+ * fix large pages (Marcelo Tosatti)
+ * speedup msr processing on Intel via msr bitmap (Sheng Yang)
+ * add slab shrinker support (Izik Eidus)
+   * reduces nonswappable footprint under memory pressure
+ * code cleanup (Joerg Roedel)
+ * vm refcounting (Izik Eidus)
+ * only mark a page as accessed if it was really accessed by the guest
+ * drop slots_lock while in guest mode
+   * fixes long latencies with iothread
+ * prepopulate guest pages only after write-protecting them (Marcelo Tosatti)
+   * fixes smp race leading to guest spinning
+
+= kvm-64 [27 mar 2008] =
+
+ * kvm clock fixes (Glauber Costa)
+ * kvm clock enable/disable bit (Glauber Costa)
+ * in kernel pit model (Sheng Yang)
+   * improves timing accuracy for certain guests
+ * fix bad tss handling causing ioperm() to fail on the host
+ * paravirt mmu support (Marcelo Tosatti, Anthony Liguori, Avi Kivity)
+ * set accessed bit on non-speculative shadow ptes
+   * minor performance improvement
+ * fix init_rmode_tss() locking (Marcelo Tosatti)
+ * fix dirty bit being lost when write permissions are removed from a page (Izik Eidus)
+ * code cleanups
+ * module option for disabling flexpriority
+ * fix apic access page memory leak
+ * hardware task switching support (Izik Eidus)
+   * for freedos and similar guests
+ * fix extboot failures under certain conditions (Anthony Liguori)
+ * export vcpu thread ID via qemu monitor (Glauber Costa)
+   * can be used to implement vcpu->cpu pinning
+ * pci hotplug (Marcelo Tosatti)
+   * can now add and remove nics and drives dynamically
+ * fix virtio memory region sizing (Marcelo Tosatti)
+ * fix segfault on disabled virtio nic (Dor Laor)
+ * fix sci interrupt on pmtimer wraparound (Dor Laor, Yaniv Kamay)
+ * fix qemu exit on pci hotplug failure (Ryan Harper)
+ * fix 'make clean' destroying configuration (Ryota Ozaki)
+ * ppc userspace updates (Jerone Young)
+ * improve IDE and SCSI DMA speed
+
+= kvm-63 [5 mar 2008] =
+
+ * portability: make room for the ia64 register stack (Xiantao Zhang)
+ * fix leak when setting the pv clock to an invalid address (Marcelo Tosatti)
+ * detect vcpu triple faults (Joerg Roedel)
+ * fix race when instantiating a shadow pte
+ * fix host crash on guest kexec
+ * code cleanups (Harvey Harrison)
+ * better tsc handling on Intel hosts with stable tscs
+ * cpu hotplug (Glauber Costa)
+ * merge qemu-cvs
+   * new curses display option
+ * change -hugetlb-path to -mem-path (Anthony Liguori)
+ * increase pci support from 6 slots to 32 slots
+ * document ./configure --disable-cpu-emulation (Jerone Young)
+ * fix powerpc cpu initialization (Jerone Young)
+ * simplify host_cpuid() assembly code
+
+= kvm-62 [26 feb 2008] =
+
+ * fix oops running external module on 2.6.25 due to mmdrop (Andrea Arcangeli)
+ * backward compatibility for 2.6.25 desc_struct changes
+ * fix memory alias mixup (Uri Lublin)
+ * add file:// migration protocol (Uri Lublin)
+ * fix reading from character devices with flow control (Jan Kiszka)
+ * large host page support (Marcelo Tosatti)
+ * fix screen corruption with high resolutions (Andreas Winkelbauer)
+ * implement vmware vga for kvm (Soren Hansen, Anthony Liguori)
+ * even more resolutions for -std-vga (Andreas Winkelbauer)
+ * code cleanups (Carlo Marcelo Arenas Belon, Harvey Harrison)
+ * allow up to 16 vcpus (Anthony Liguori, Avi Kivity)
+ * allow up to 16 memory slots
+ * improve vcpu_run error reporting
+ * fix host crash on hosts without EFER (Intel Core not 2s)
+ * drop kvm private segment descriptor in favor of Linux' desc_struct
+ * stat counter for hypercalls (Amit Shah)
+ * fake values for MSR_PERF_STATUS (Alexander Graf)
+   * needed for Darwin/OS X
+ * better root pagetable unpinning (Marcelo Tosatti)
+ * paravirt clock fixes (Glauber Costa, Marcelo Tosatti)
+ * avoid host hang when guest sets APIC timer to zero
+   * also fixes live migration of Windows 2000 guests
+ * fix RHEL 5 i386 smp boot due to timer interrupts being routed to all vcpus
+
+= kvm-61 [19 feb 2008] =
+
+ * paravirtualized clock (Glauber de Oliveira Costa)
+ * mmu debug compile fix (Marcelo Tosatti)
+ * last branch record virtualization on AMD (Joerg Roedel)
+ * fix Windows x64 installer crash on AMD (Joerg Roedel)
+ * use new kvm semaphore instead of mmap_sem (Izik Eidus)
+   * fixes potential deadlock
+ * fix type in vmx header (Ryan Harper)
+ * make the supported cpuid ioctl system-wide instead of per-vm
+ * fix setting cr0 from userspace (Paul Knowles)
+ * add group decoding support to the x86 emulator
+ * nested paging support on AMD (Joerg Roedel)
+ * allow access to EFER on 32-bit hosts (Joerg Roedel)
+   * allows using the nx bit
+ * fix copy_from_user_inatomic() call non-preemptible hosts (Andrea Arcangeli)
+ * fix smp Linux on AMD (Joerg Roedel)
+ * make the code more ppc friendly (Hollis Blanchard)
+ * add virtual processor identifier support (VPID) on Intel (Sheng Yang)
+ * don't expose pio page to host userspace on non-x86
+ * decouple mmio from shadow page tables
+ * make function pointer tables constant (Jan Engelhardt)
+ * merge qemu-cvs
+   * reverse vnc connections
+   * e1000 nic emulation
+   * more audio options
+   * usb serial device emulation
+   * cdrom/dvd improvements
+   * timer tick reduction
+ * e1000 pxe boot rom (Alexey Eremenko)
+ * fix 'make clean'
+ * merge bios from boch-cvs
+   * adds dmi tables
+   * enables acpi on 32-bit Linux guests
+ * workaround qemu tcg breakage on non-x86 (Anthony Liguori, Xiantao Zhang)
+ * adjust external module for removal of fastcall in mainline (Andrea Arcangeli)
+ * improve qemu main loop
+ * fix live migration with tpr optimization
+ * fix external module miscompile with newer kernels (Andrea Arcangeli)
+ * fix external module include directory priority problems (Andrea Arcangeli)
+ * fix 32-bit host userspace on 64-bit host kernels
+ * fix preempt notifier emulation clash with host hardware debug registers (Andrea Arcangeli)
+ * adjust external module for 2.6.25
+ * fix ioapic live migration not transferring some registers (Chris Lalancette)
+ * separate tpr optimization paths for smp and up
+ * pio emulation on mmio for ia64 (Xiantao Zhang)
+ * fix qemu timer rearm fallout from last merge (Anders Melchiorsen)
+ * clean up kvm/qemu interaction (Anthony Liguori)
+ * improve ppc dcr handling (Jerone Young)
+ * fix 64-bit guest migration failure due to bad lm_capable_kernel init (Uri Lublin)
+ * fix bios parallel build (Carlo Marcelo Arenas Belon)
+ * update virtio abi (Anthony Liguori)
+ * support virtio abi versioning (Anthony Liguori)
+ * add powerpc kvm/qemu support (Jerone Young)
+ * support ppc 440 "bamboo" board (Jerone Young)
+ * improve migration error handling (Chris Lalancette)
+ * enable cache on reset in bios
+ * fix up testsuite warnings (Bernhard Kaindl)
+ * fix aio deadlocks with smp guests
+
+= kvm-60 [23 jan 2008] =
+
+ * fix compilation with older kernels (Andi Kleen)
+ * virtio host support (Anthony Liguori, Dor Laor)
+   * includes block and network devices
+ * fix power management timer overflow handling
+ * fix qemu running with older kernels
+ * boot from scsi/virtio (Anthony Liguori)
+ * add 1280x800 resolution to -std-vga
+ * fix acpi sci interrupt generation
+ * compile fixes (Carlo Marcelo Arenas Belon)
+ * update ide cdrom to match qemu (Carlo Marcelo Arenas Belon)
+ * fix extboot on older gcc (Christian Ehrhardt)
+ * powerpc dcr tests (Christian Ehrhardt)
+ * rtl8139 is now the default nic type (Guido Guenther)
+ * acpi power button support (Guido Guenther)
+ * powerpc testsuite harness (Hollis Blanchard)
+ * powerpc libkvm support (Jerone Young)
+ * bump piix4 to rev 3 to avoid slowdown reading pm timer (Marcelo Tosatti)
+ * migration updates (Uri Lublin)
+ * ia64 smp support in qemu (Xiantao Zhang)
+ * fix acpi vapic page on save/restore
+ * move x86 fpu to x86 specific header (Christian Ehrhardt)
+ * minor shadow code simplification(Eddie Dong)
+ * optimize pae pte updates (Eddie Dong, Eric Liu)
+ * simplify shadow hash table indexing (Eddie Dong)
+ * kvm_para.h compile fix (Glauber de Oliveira Costa)
+ * dirty page tracking fix (Izik Eidus)
+ * fix svm lazy fpu switching (Joerg Roedel)
+   * fixes Vista x64 on AMD
+ * only allow vmcall/vmmcall on #UD traps (Sheng Yang)
+ * fix unbounded latency due to a race in the guest entry code
+   * with this fix and a realtime kernel, sub 50usec worst case latencies can be achieved
+ * move apic timer migration to preemptible code
+
+= kvm-59 [3 jan 2008] =
+
+ * merge qemu-cvs
+   * -drive cache=[on|off] option
+   * adds scsi passthrough
+ * ide lba48 support for 120GB+ disk images
+ * widescreen resolutions for -std-vga
+ * libkvm compile fixes (Carlo Marcelo Arenas Belon)
+ * mmu scaling (Marcelo Tosatti, Avi Kivity)
+
+= kvm-58 [27 dec 2007] =
+
+ * add mmu statistics
+ * log data on write to unimplemented msr
+ * fix memory corruption (mapcount error) after host fork() (Izik Eidus)
+ * improve preempt notifier emulation on older kernels (Andrea Arcangeli)
+ * refactor IDE CHS guessing (Anthony Liguori)
+ * testsuite improvements
+ * apic tpr acceleration for Windows guests
+   * disabled on smp for now
+ * fix warnings due to qemu merge (Carlo Marcelo Arenas Belon)
+ * improve support for older kernels (Carlo Marcelo Arenas Belon)
+ * icache sync in qemu after dma for more archs (Christian Ehrhardt)
+ * simplify mmio callback (Christian Ehrhardt)
+ * align gdbstub with qemu-cvs (Jan Kiszka)
+ * fix compile if kernel/include/asm/ preexists (Sheng Yang)
+ * fix migration on i386 hosts (Uri Lublin)
+ * qemu ia64 adjustments (Zhang Xiantao)
+
+= kvm-57 [18 dec 2007] =
+
+ * warn when emulating preempt notifiers
+ * add pio port 0x80 access test to testsuite
+ * merge qemu-cvs
+ * add rtc emulation for ia64 (Xiantao Zhang)
+ * fix qemu memory allocation off-by-one
+ * new kernel source layout (virt/kvm/, arch/x86/kvm/)
+ * coalesce remote tlb flushes when write-protecting guest pages (Eddie Dong)
+ * lapic debug compile fix (Joerg Roedel)
+ * fix smp mmu shadow instantiation race (Marcelo Tosatti)
+ * atomic cmpxchg8b on i386 (Marcelo Tosatti)
+ * throttle vmx_intr_assist() printk (Ryan Harper)
+ * portability (Xiantao Zhang)
+
+= kvm-56 [14 dec 2007] =
+
+ * Generalize exception handling mechanism
+ * fix x86 emulator eflags handling
+ * avoid exit to userspace on cr8 write if using kernel lapic on Intel
+ * fix stack instructions emulation in 64-bit mode
+  * fixes Vista x86
+   * except on Woodcrests
+ * trap cr8 access on amd
+ * mmu simplification
+ * fix setting nx bit on shadow pte
+ * fix inherited mmu permissions
+ * more portability work (Hollis Blanchard, Xiantao Zhang)
+ * add cr8 to 'mov cr' instruction emulation (Joerg Roedel)
+ * exit to userspace on cr8 write if not kernel apic on amd (Joerg Roedel)
+ * atomically set accessed and dirty bit on guest ptes (Marcelo Tosatti)
+ * use ->fault() vma op instead of ->nopage()
+ * remove abi 10 libkvm compatibility
+ * add some x86 emulator tests
+ * add many mmu access tests
+ * fix rpm build on Fedora 8 (Dan Kenigsberg)
+ * fix 'make sync' on debian and derivatives (Ryan Harper)
+ * fix live migration (Uri Lublin, Izik Eidus)
+ * initial ia64 userspace (Xiantao Zhang)
+
+= kvm-55 [4 dec 2007] =
+
+ * remove old hypercall driver (Anthony Liguori)
+ * disable dirty page logging for main memory (Izik Eidus)
+ * fix incorrect page count calculation for dirty logging (Izik Eidus)
+ * improve testsuite 'make clean' (Neo Jia)
+ * compile fix (Sheng Yang)
+ * reorganize x86 emulator main switch
+ * don't bypass mmu on pae cr3 reload if pdptrs changed
+   * fixes Solaris x86
+ * use common defines for EFER (Carlo Marcelo Arenas Belon)
+ * portability (Xiantao Zhang)
+ * fix kvm_init() error path (Xiantao Zhang)
+ * ia64 iosapic support (Xiantao Zhang)
+
+= kvm-54 [27 nov 2007] =
+
+ * fix fpu leak on AMD (Amit Shah)
+   * (on kvm-53, lazy fpu was disabled, so this just improves performance)
+ * prefetch instruction bytes when emulating
+ * implement guest page fault bypass on nonpae
+   * should speed up some 32-bit guests
+ * add a bunch of statistics
+ * avoid unnecessary remote tlb flushes
+   * improves guest smp scaling
+ * avoid mmu reloads on guest tlb flushes
+ * mmu code simplification
+ * disallow using kvm after fork()
+ * fix failures while injecting external interrupts in real mode
+   * fixes Mandrake 9 regression
+ * fix multiple address- and operand- size override prefix emulation
+ * infrastructure for using host cpu features on guest (Dan Kenigsberg)
+   * not used yet by qemu
+ * cmps instruction emulation (Guillaume Thouvenin)
+   * allows OpenBSD to boot
+ * cleanups (Hollis Blanchard)
+ * fix potential memory leak in real-mode smp (Izik Eidus)
+ * reduce unnecessary dirtying of pages (Izik Eidus)
+ * mark guest pages as accessed with the Linux lru (Izik Eidus)
+ * more portability work (Jerone Young, Xiantao Zhang)
+ * allow new vmx features even if not using in-kernel apic (Sheng Yang)
+ * refactor shadow mmu size calculation (Xiantao Zhang)
+ * improve testsuite
+ * beginning of x86 emulator unit test
+ * fix compile warnings (Carlo Marcelo Arenas Belon)
+ * log module version in dmesg on load
+
+= kvm-53 [20 nov 2007] =
+
+ * testsuite: exit on end of test
+ * batch mode for kvm_stat script
+ * compile fixes (Carlo Marcelo Arenas Belon, Joe Perches)
+ * portability (Jerone Young, Zhang Xiantao)
+ * disable lazy fpu on AMD (Amit Shah)
+   * should fix instability on AMD
+   * will cause performance regression, fix in progress
+ * x86 emulator: fix 'push r/m' emulation (Amit Shah)
+ * register use reduction in vmx guest entry
+ * infrastructure for per-vm stats
+   * extends existing per-vcpu stats
+ * add mmu, state switch, emulation statistics
+ * use copy_{to,from}_user to access guest memory (Izik Eidus)
+ * simplify access to guest page tables (Izik Eidus)
+ * fix entry to real mode with segment bases beyond 1MB (Jan Kiszka)
+ * finally kill last use of cr2 in emulator (Sheng Yang)
+
+= kvm-52 [12 nov 2007] =
+
+ * fix efer reload host crash on T2600 and similar processors
+ * revert sleepy interrupt injection
+   * fixes "Fault when IDT_Vectoring"
+ * atomically inject real-mode interrupts
+ * wbinvd exiting on newer Intel processors (Eddie Dong)
+   * fixes real-time issues
+ * fix call/jmp instruction emulation (Izik Eidus)
+   * fixes Vista x64 installation
+ * fix save/restore/migrate with multiple nics
+ * fix build on i386 uniprocessor w/ no ioapic hosts
+ * fix smp_call_function_single() emulation on older hosts
+   * fixes smp guests not booting on RHEL 5 hosts
+ * make qemu/kvm memory allocation match plain qemu more closely (Izik Eidus)
+   * fixes issues with large memory guests
+ * libkvm compile fixes (Carlo Marcelo Arenas Belon, Jerone Young)
+
+
+= kvm-51 [7 nov 2007] =
+
+ * fix some x86 emulator one-byte insns (fixes W2K3 installer again)
+ * fix host hangs with NMI watchdog on AMD
+ * fix guest SMP on AMD
+ * fix dirty page tracking when clearing a guest page (Dor Laor)
+ * more portability work (Hollis Blanchard, Jerone Young)
+ * fix FlexPriority with guest smp (Sheng Yang)
+ * improve rpm specfile (Akio Takebe, Avi Kivity)
+ * fix external module vs portability work (Andrea Arcangeli)
+ * remove elpin bios due to license violation
+ * testsuite shutdown pio port
+ * don't advertise svm on the guest
+ * fix reset with kernel apic (Markus Rechberger)
+
+= kvm-50 [2 nov 2007] =
+
+ * fix smp_call_function_mask() emulation on preemptible kernels
+ * move libkvm into own directory (Hollis Blanchard)
+ * fix save/restore/migrate for new memory slot management (Uri Lublin)
+ * compile fixes (Uri Lublin, Avi Kivity)
+ * fix recursive locking on mmap() (Anthony Liguori)
+ * remove some cr2 dependencies from x86 emulator
+ * further simplify x86 emulator
+ * more portability work (Carsten Otte, Hollis Blanchard)
+ * Intel FlexPriority support (Sheng Yang)
+ * fix dirty page tracking on aliased pages (Uri Lublin)
+
+= kvm-49 [29 oct 2007] =
+
+ * Fix PIT time-drift-fix (only with -no-kvm-irqchip) (Dan Kenigsberg)
+ * Fix vnc auth error with clients <= 3.7 protocol (Dan Kenigsberg)
+ * Don't spin on hlt with interrupts disabled (Dor Laor)
+ * Fix pxe boot (Izik Eidus)
+ * Hide the Intel real-mode tss from userspace (Izik Eidus)
+ * Automatic memory slot management for libkvm (Izik Eidus)
+ * Fix problem with std-vga and 4GB guests (Izik Eidus)
+ * External module compat for smp_call_function_mask() (Laurent Vivier)
+ * More portability work (Jerone Young, Christian Borntraeger, Zhang Xiantao)
+ * Fix sleep-in-atomic-context during vcpu init
+ * Fix 'push imm8' emulation (fixes W2K3 installer)
+ * Intercept invd and wbinvd on AMD
+ * Reduce emulator dependency on cr2 (mov abs insns)
+ * Move page fault processing to common code
+ * Fix rmap memory consumption oops due to increased rmap usage with swap
+ * Fix potential memory leak with kernel-allocated memslots (Izik Eidus)
+ * Export memory slot allocation mechanism (Izik Eidus)
+ * Add kernel-private memslots (Izik Eidus)
+ * Fix local apic divide-by-zero (Kevin Pedretti)
+ * Improve local apic timer wraparound handling (Kevin Pedretti)
+ * Use newly available smp_call_function_mask() (Laurent Vivier)
+ * Micro-optimize register usage on vmentry/vmexit (Laurent Vivier)
+ * Cleanups, compilation fixes (Akio Takebe, Anthony Liguori, Avi Kivity)
+
+
+= kvm-48 [18 oct 2007] =
+
+ * use precise cpu accounting on ppc and s390 (Christian Borntraeger)
+ * make guest time accounting actually work (Laurent Vivier)
+ * fix host memory corruption when setting the guest dirty bit
+ * allow swapping with older userspace (Anthony Liguori)
+ * allow custom memory setup using libkvm (Gerd Hoffmann)
+
+
+= kvm-47 [18 oct 2007] =
+
+ * Reset fixes (Eddie Dong, Avi Kivity)
+ * Portability work (Carsten Otte)
+ * Cleanups (Anthony Liguori, Laurent Vivier)
+ * Simplify guest pagetable dirty bit management
+ * Fix nx bit for huge pages
+ * Fix write access to clean large pages (fixes rmap leak)
+ * Support for Linux 2.6.16 guests (movnti instruction) (Sheng Yang)
+ * Simplify apic timer backlog processing
+ * Move interrupt injection out of critical section
+ * x86 emulator work (Nitin A Kamble)
+ * restore freebsd support on AMD (fix smsw and lmsw) (Aurelien Jarno)
+ * Simplify guest page table walker
+ * Partial guest swapping (Izik Eidus)
+ * kvmctl improvements (Anthony Liguori)
+ * libkvm, qemu compilation against older kernels
+ * guest time accounting (Laurent Vivier)
+ * configure improvements (Carlo Marcelo Arenas Belon)
+ * fix 4GB+ configurations (Izik Eidus)
+ * cross compilation support (Jerone Young)
+
+= kvm-46 [10 oct 2007] =
+
+ * fix host oops on bad guest ioapic accesses
+ * handle NMIs before enabling host interrupts
+ * add general guest memory accessors (Izik Eidus)
+ * allow user control over shadow cache size (Izik Eidus)
+ * auto tune shadow cache size with guest memory (Izik Eidus)
+ * allocate guest memory in userspace instead of in kernel (Izik Eidus)
+ * code style fixes (Mike Day, Anthony Liguori)
+ * lapic cleanups (Rusty Russell)
+ * fix acpi interrupt reporting for FreeBSD
+ * fix color problems on certain displays
+ * Red Hat 7.1 support
+ * vmmouse support (Dan Kenigsberg)
+ * fix sdl window caption when keyboard is captured (Dan Kenigsberg)
+ * improve libkvm configure script (Jerone Young)
+ * improve bios compilation support on x86_64 hosts (Laurent Vivier)
+ * fix acpi processor reporting for Windows 2000 with the ACPI HAL (Sheng Yang)
+
+= kvm-45 [2 oct 2007] =
+
+ * don't use page->private for guest pages (Izik Eidus)
+ * x86 emulator cleanups, simplifications, and fixes (Laurent Vivier, Qing He)
+ * apic round robin delivery mode cleanup (Qing He)
+ * merge qemu-cvs
+ * fix compilation on older kernels (Rusty Russell, Avi Kivity)
+ * reduce tap networking latency
+ * fix FC6 x86_64 booting with -no-kvm
+ * fix code dump on exception
+
+= kvm-44 [23 sep 2007] =
+ * fix smp guest boot
+ * fix IDE emulation bug with newer guest kernels (S.Çağlar Onur)
+ * support VMware server as guest (Ryan Harper)
+ * fix smp race in shadow code (Izik Eidus)
+ * allow guest page faults to bypass kvm on Intel (performance boost)
+
+= kvm-43 [21 sep 2007] =
+
+ * fix ioapic edge-triggered interrupt handling
+
+= kvm-42 [20 sep 2007] =
+
+ * important host oops fix
+ * document -no-kvm-irqchip option in qemu help message (Carlo Marcelo Arenas Belon)
+ * acpi bios: export pci irqs as active high
+ * avoid redelivery of edge-triggered ioapic interrupts if already in service
+ * implement ioapic polarity
+ * fix x86 emulator merge problems (Nitin A Kamble, Laurent Vivier)
+ * fix x86 repne decoding (fixes OpenBSD boot regression) (Laurent Vivier)
+ * install kvm_para.h (Gerd Hoffman)
+
+= kvm-41 [19 sep 2007] =
+
+ * refactor hypercall infrastructure for simplicity and better smp support (Anthony Liguori)
+ * fix ioapic level triggered interrupt redelivers (solves networking stalls)
+ * reduce efer reloads with 32-bit guests; minor performance improvement
+ * split x86 emulator decode and execute stages (Laurent Vivier)
+ * fix pic interrupt delivery (solves time going double speed on x86_64 Linux guests) (Qing He)
+ * adaptive live migration bandwidth limits (Uri Lublin)
+
+= kvm-40 [16 sep 2007] =
+
+ * fix guest reboot (most scenarios)
+ * further x86 emulator work (Nitin A Kamble)
+ * compile fixes for older kernels
+ * make the external module work again
+
+= kvm-39 [12 sep 2007] =
+
+ * provide div64_64() for older kernels
+ * improve emulation failure reporting
+ * more x86 emulator work (push imm8, pushf, call near) (Nitin A Kamble)
+ * don't use TPR shadow on i386 (Sheng Yang)
+
+= kvm-38 [12 sep 2007] =
+
+ * fix fpu indication for Solaris (Amit Shah)
+ * Avoid GFP_NOWAIT allocation in mmu
+ * Fix runtime smp_processor_id() warning in lapic
+ * Move vcpu loop into subarch independent loop
+ * Rename kvm_arch_ops to kvm_x86_ops (Christian Ehrhardt)
+ * Fix missing "genapic" on i386 (Eddie Dong)
+ * Fix lapic hrtimer migration (Qing He)
+ * Fix lapic 64-bit division on i386 (Jindrich Makovicka)
+ * Simplify memory allocation ioctl (Laurent vivier)
+ * Keep control register shadows in sync (Rusty Russell)
+ * Retire invlpg (Rusty Russell)
+ * Expose get_cs_db_l_bits for kvm-lite (Rusty Russell)
+ * Fix network boot (Anthony Liguori)
+ * Round up memory in libkvm (Anthony Liguori)
+ * Fix option ROM loading (Anthony Liguori)
+ * Revert FACP ACPI change for Vista
+ * Fix segfault with -no-kvm
+ * lapic hrtimer external module compatibility (Qing He, Avi Kivity)
+ * improved (still imprefect) reboot
+ * better bios smp detection
+
+= kvm-37 [9 sep 2007] =
+
+ * in-kernel lapic, ioapic, and pic (Eddie Dong, Qing He, Sheng Yang, Gregory Haskins, Dor Laor, Avi Kivity)
+ * split segment reload (vmx microoptimization) (Laurent Vivier)
+ * fix vga redraw regression (Izik Eidus)
+ * fix testsuite compilation with older assemblers (H. Peter Anvin)
+
+= kvm-36 [22 aug 2007] =
+
+ * support guests with more than 2GB of RAM on 64-bit hosts (Izik Eidus)
+ * fix rare host oops on guest context switch
+ * avoid smp_call_function_single() warning on suspend/resume
+ * more real mode emulator work (Nitin A Kamble)
+ * Windows x64 support (Sheng Yang)
+ * close minor signal handling race
+ * carry bios in kvm source tree for easier maintenance
+ * fix -std-vga (Uri Lublin)
+ * advertise kvm in vnc window title (Matthew Kent)
+ * fix Windows SMP guests consuming cpu time when idle (Igor Lvovsky)
+
+= kvm-35 [15 aug 2007] =
+
+ * fix kvm refusing to load on Core processors (Glauber de Oliveira Costa)
+ * improve qemu monitor handling CR/LF sequences (Jim Paris)
+ * fix compile warning in qemu (Luca Tettamanti)
+
+= kvm-34 [13 aug 2007] =
+
+ * make kvm preemptible
+ * allow calling sleeping functions in the kvm exit handlers (Shaohua Li)
+ * this is a first step in getting guest swapping
+ * fix running kvm on nx-incapable host kernel on nx-capable hardware
+ * fix more fallback from the x86 emulator writeback changes (Aurelien Jarno, Avi Kivity)
+ * remove vmx specific code from subarch independent code (Gregory Haskins)
+ * allocate vcpus as needed (Rusty Russell)
+ * consolidate x86 emulator guest read/write code (Laurent Vivier)
+ * cleanup string pio instruction emulation (Laurent Vivier)
+ * ensure all cpus have the same vmx features (Sheng Yang)
+ * version string for external module
+ * disable long mode capability bit on 32-bit kernels
+ * fix qemu -isapc (Uri Lublin)
+ * fixes for smp live migration
+  * this is still raw
+ * fix unhandled wrmsr MSR_CSTAR on i386 (Luca Tettamanti)
+ * some migration fixes (Jim Paris)
+ * the usual cleanups and minor fixes (various but mostly Rusty)
+
+= kvm-33 [23 jul 2007] =
+
+ * fix massive performance regression
+
+= kvm-32 [23 jul 2007] =
+
+ * fix oops with the slub allocator (CONFIG_SLUB)
+ * fix cmov instruction emulation, trashed by the mmio rmw fix
+ * fix rare, silent data corruption on writes that cross a page boundary and touch a page table (Aurelien Jarno, Avi Kivity)
+ * fix race between vm creation and vcpu hotunplug (Rusty Russell)
+ * fix guest turning on pae with invalid pdptres (Rusty Russell)
+ * adapt external module to changed kmem_cache_create() api
+ * allow external module on 2.6.22 i386 nonpae
+ * fix regression in network throughput caused by guest smp changes (Aurelien Jarno, Avi Kivity)
+ * live migration updates (Uri Lublin)
+ * minor cleanups (Nguyen Anh Quynh, Avi Kivity)
+
+= kvm-31 [19 jul 2007] =
+
+ * a few cleanups that somehow evaded kvm-30 (Jeff Dike, Rusty Russell)
+ * allow the external module to compile on older kernels.
+
+= kvm-30 [19 jul 2007] =
+
+ * minor fixes and cleanups  (Jeff Dike, Rusty Russell, Avi Kivity)
+ * kernel pio string write (Eddie Dong)
+ * guest smp kernel fixes
+ * rdmsr and wrmsr real mode emulation
+ * fix real mode shadow pages aliasing nx large page shadows
+ * enable guest smp in qemu
+ * fix external module installer
+ * revert ide enable changes that caused an I/O regression
+
+= kvm-29 [12 jul 2007] =
+
+ * live migration from 32-bit hosts to 64-bit hosts (Uri Lublin)
+ * monotonic timestamp counter on Intel
+ * more real mode support (Nitin A Kamble)
+ * infrastructure for in-kernel PIC and APIC (Gregory Haskins, Eddie Dong)
+ * fix read-modify-write to mmio (fixes F7 installer) (Luca Tettamanti)
+ * fix rebooting a long-running guest
+ * reliably detect if svm was disabled by bios (Joerg Roedel)
+ * suspend/resumes fixes (will not work with older kernels)
+ * fix nx confusion with large pages and real mode
+ * remove dependency on libuuid
+ * fix registers access in monitor/gdbstub (Anthony Liguori)
+ * minor fixes and cleanups (various)
+
+= kvm-28 [10 jun 2007] =
+
+ * fix host oops on guest context switch
+ * many code cleanups (Nguyen Anh Quynh, others)
+ * prepare kernel for guest smp
+ * update libkvm for guest smp
+ * update testsuite for guest smp
+ * emulate hlt in real mode (avoids crash when booting from unformatted disk)
+ * initialize ata ports for Fedora 7 guests (Luca Tettamanti)
+
+= kvm-27 [3 jun 2007] =
+
+ * use slab cache for mmu shadow pages
+ * make shadow pte updates atomic (for guest smp)
+ * general mmu cleanups
+
+= kvm-26 [27 may 2007] =
+
+ * implement wbinvd emulation, triggered by Windows Vista
+ * compile fixes (Markus Rechberger, Avi Kivity)
+
+= kvm-25 [24 may 2007] =
+
+ * massive performance increase (Eddie Dong)
+ * regenerate bios from latest bochs sources, hopefully fixing a regression with some guests
+ * some testsuite work (Anthony Lihuori, Eddie Dong, Avi Kivity)
+ * minor fixes (various)
+
+= kvm-24 [8 may 2007] =
+
+ * fix oops loading kvm-intel module on i386 with highmem
+
+= kvm-23 [7 may 2007] =
+
+ * OpenBSD 4.1 i386 support (Matthew Gregan)
+ * Fix host and guest crashes on reboot
+
+= kvm-22 [6 may 2007] =
+
+ * Significant performance improvements (Anthony Liguori, Eddie Dong, Qing He, Avi Kivity)
+ * Fix longstanding bug: time runs at double speed on x86_64 Linux (Qing He)
+ * Windows Vista 32-bit support (Qing He, Jun Nakajima)
+ * Support for kvm abi 10 modules
+ * Minor updates
+
+= kvm-21 [27 apr 2007] =
+
+ * fix regression on Core (not Core 2) processors
+ * performance improvements (Eddie Dong, Anthony Liguori)
+ * minor fixes
+
+= kvm-20 [24 apr 2007] =
+
+ * Windows 2000 support
+ * performance enhancements
+ * patch against latest kernel tree included in tarball
+ * fix oops with 32-bit nonpae guests
+
+= kvm-19 [16 apr 2007] =
+
+ * bug fixes
+ * memory aliasing api
+
+= kvm-18 [26 mar 2007] =
+
+ * merged new userspace API
+ * revert the optimization which killed some 32-bit Linux guests
+ * reboot support on Intel hosts (AMD are already supported)
+ * better timekeeping under load (Uri Lublin)
+ * other minor fixes and cleanups
+
+= kvm-17 [25 mar 2007] =
+
+ * live migration enhancements (Uri Lublin)
+ * better/working acpi support
+ * revert to unhacked qemu bios
+ * fix some 32-bit nonpae guests (*BSD)
+ * initial ballooning support
+ * random fixes
+
+= kvm-16 [7 mar 2007] =
+
+ * bug fixes (including a nasty one on module load)
+ * use lanana assigned minor device number for /dev/kvm
+
+= kvm-15 [26 feb 2007] =
+
+ * live migration with kvm (Uri Lublin)
+ * based on Anthony Liguori's qemu patches
+ * new userspace interface (work in progress)
+ * the usual random fixes
+
+= kvm-14 [19 feb 2007] =
+
+ * qemu 0.9.0
+ * too many goodies to list
+ * kvm can no longer share qemu's bios on Intel hosts due to real mode trouble.  use the supplied bios.
+ * migration now based on Anthony Liguori's live migration patches (Uri Lublin)
+  * currently, only non-live migration is supported under kvm
+ * handle smi on host on AMD hosts (Joerg Roedel)
+ * random fixes
+
+= kvm-13 [8 feb 2007] =
+
+ * add dirty page tracking in some corner cases for live migration
+ * fix lockups on nx-challenged hosts
+ * host suspend/resume
+  * nobody's testing this, so it's probably broken
+ * host cpu hotplug support
+ * beginning of paravirt support (Ingo Molnar)
+ * guest reboot support (Markus Rechberger, Joerg Roedel)
+ * pio latency reduction (Anthony Liguori)
+ * stone age kernel compatibility (Markus Rechberger)
+ * the usual cleanups and stability fixes
+
+= kvm-12 [23 jan 2007] =
+
+ * More migration work (Uri Lublin)
+ * savevm/loadvm (and migration) work on AMD (Leonard Norrgard)
+ * More guest support
+ * mmu testsuite and fixes
+ * Windows ACPI install/run support (Dor Laor)
+ * Fix host reboot on guest reboot on AMD (Joerg Roedel)
+
+= kvm-11 [11 jan 2007] =
+
+ * stabilization fixes
+ * vmexit profiling (Ingo Molnar; requires Linux 2.6.20+)
+
+= kvm-10 [7 jan 2007] =
+
+ * more hypercall work
+ * cleanup irq handling
+ * shadow page table caching
+ * migration fixes
+ * stabilization fixes
+
+= kvm-9 [31 dec 2006] =
+
+ * API documentation (James Jacobsson)
+ * More stabilization fixes (Yoshimi Ichiyanagi, Ingo Molnar, Nguyen Anh Quynh)
+ * Interactivity improvements (Dor Laor)
+
+= kvm-8 [21 dec 2006] =
+
+ * msr fixes (Michael Riepe)
+ * more guest support (Michael Riepe)
+ * random fixes
+ * fpu state corruption fix on AMD hosts
+
+= kvm-7 [12 dec 2006] =
+
+ * prevent loading arch module on wrong hardware
+ * fix for macbooks
+ * other minor fixes
+
+= kvm-6 [11 dec 2006] =
+
+ * AMD 32-bit host support (Anthony Liguori)
+ * more migration work
+ * stabilization
+ * improved performance
+ * improved guest support on AMD
+
+= kvm-5 [28 nov 2006] =
+
+ * AMD SVM support (x86-64 hosts only)
+ * Preliminary live migration support
+ * 'make install' also installs kernel modules, if selected
+ * random fixes
+
+= kvm-4 [21 nov 2006] =
+
+ * added the msr work
+  * suspend/resume should work now
+ * more vmdk compatibility work
+ * random build updates
+
+= kvm-3 [15 nov 2006] =
+
+[Avi Kivity retained the natural number versioning after he contemplated the
+confusion that can arise from having releases 1, 2, and 0.3]
+
+Kernel module
+ * make exit reason numbers explicit
+ * sync kernel module with -mm tree
+  * asm constraint fixes
+  * userspace interface blurb
+  * segment restore across mode switch (fixes etherboot)
+  * segment asm constraint fix (Bernhard Rosenkraenzer)
+  * segment access cleanup
+
+libkvm:
+ * better error reporting (Simon Kagstrom)
+ * 'make clean'
+ * attributions and license
+
+kvmctl:
+ * add option to launch guest in 32-bit mode
+ * add test programs
+
+qemu/kvm:
+ * autodetect kvm presence (Simon Kagstrom)
+
+General
+ * fix host arch detection on debian
+ * fix ./configure on debian (Gildas)
+ * toplevel 'make clean'
+
+= ?? [9 nov 2006] =
+
+ * much easier to get running, see updated HOWTO
+ * now just one download, get yours while supplies last
+ * single qemu binary for kvm and non-kvm runs (Anthony Liguori)
+ * accompanying external kernel module package has all bugfixes folded in (plus a bit of cosmetics) 
+
+= lkml submission v4 [5 nov 2006] =
+ * [http://lwn.net/Articles/207875/]
+ * detect msrs on host dynamically.  Avoids oopses on non-ia32e capable processors.
+ * web site: http://kvm.sourceforge.net
+ * slightly rediffed
+
+= lkml submission v3 [26 oct 2006] =
+ * [http://uwsg.indiana.edu/hypermail/linux/kernel/0610.3/0747.html]
+ * mailing list: kvm-devel@public.gmane.org (http://lists.sourceforge.net/lists/listinfo/kvm-devel)
+ * applied code review comments
+ * fixed set_sregs() ioctl corrupting guest state if cr0.pe changed (a polite way of saying that loading a saved vm was broken)
+
+= lkml submission v2 [23 oct 2006] =
+ * [http://lwn.net/Articles/205580/]
+ * fixed a lockup on i386 with host memory >= 4GB
+ * finer patch split to conform to vger limits
+ * minor fixes
+ * send through script to avoid mailer damage
+
+= lkml submission v1 [19 oct 2006] =
+
+ * [http://lkml.org/lkml/2006/10/19/146]
--- qemu-kvm-0.12.5+dfsg.orig/debian/TODO
+++ qemu-kvm-0.12.5+dfsg/debian/TODO
@@ -0,0 +1,72 @@
+- Make the kvm-amd / kvm-intel modules load automatically instead of using
+  the init script.  Reportedly kvm modules in recent kernels can be loaded
+  even if other virtualization technologies, such as vmware, are being used
+  (previously the two sets of kernel modules were conflicting with each other).
+  This needs to be verified.
+
+- /etc/init.d/kvm script might replace eth0 with a switch sw0.
+  Config questions to be asked, possibly alternative default network
+  setups supplied etc.
+  Note that this is quite fragile, especially in case of more
+  comples network settings.  Maybe create a script that updates
+  /etc/network/interfaces instead.
+  Mjt: I don't like the whole idea of messing up with networking like this...
+
+- In /etc/kvm/kvm-ifup, be more flexible.  Also don't depend on bridge-utils.
+  (already a bit more flexible than before, maby that's enough...)
+
+- The whole networking should probably be left to various management tools
+  instead, but kvm is useful without such tools.  At least provide some examples,
+  especially how to use networking when running as non-root.
+  Note that many howtos for the subject suggests using sudo to run ifconfig,
+  brctl and the like, -- this is wrong approach, you have to grant whole
+  network configuration to the user in question, but he only need to access
+  one script as root instead of being able to mess with whole networking
+  on the system
+
+- Remove dependency on hal (suggests) and collect necessary info (bios version
+  and computer model) in reportbug directly, it's now trivial thanks new
+  sysfs entries /sys/devices/virtual/dmi/*)
+
+- Why we suggest samba?  If it is only for user-mode networking, is it even
+  worth to mention?  User networking is too slow to be useful.
+
+- check debian/patches/security/leftover.patch
+  (the only old patch left with to-be-defined effect)
+
+- Create a kvm-doc package from the texinfo source of the full manual in
+  qemu/qemu-doc.texi.  The kvm upstream for qemu-doc.texi isn't up to date with
+  the qemu upstream on the manual, though.  Which also needs to be verified if
+  it's still the case with qemu-kvm packages (should be pretty up-to-date).
+  Mjt is not sure if it's worth to create such package when we have the
+  manpages (generated from the same .texi files).
+
+- Review and patch the documentation, look for proper naming.  Right now it
+  all refers to qemu or qemu-doc, so basically s/qemu/kvm/g.  Probably a sort
+  of a sed script during install.  Also mention there what default network
+  script does (see above about networking too)
+
+- Provide some missing manpages: kvm_stat kvmtrace kvmtrace_format kvm-io
+
+- Create a kvm-dev package from the files that are currently removed in rules
+
+- When etheboot package will be updated to include virtio PXE boot roms,
+  Build-depend on it to enable virtio boot roms too.  This is in version 5.4.4.
+
+- Support for sound.  Probably nothing to do since kvm supports sound by its
+  own, provided the right options (guest hardware) are used
+
+- Provide packages for non-x86 arches.  Powerpc, s390.  Need hardware to test.
+
+- kvm/libfdt can't be cleaned up if no configure were run.  Used on ppc.
+  Note that now 'clean' target isn't being executed if no configure step
+  were performed.
+
+- Review SASL support and qemu.sasl in particular.  Sasl is used for vnc.
+  Need to ensure we're using the right name in the source too.
+
+- for !x86 arches it might be necessary to include lintian-overrides file
+  to list things like:
+   qemu-kvm: arch-dependent-file-in-usr-share ./usr/share/kvm/openbios-ppc
+   qemu-kvm: binary-from-other-architecture ./usr/share/kvm/openbios-ppc
+   qemu-kvm: statically-linked-binary ./usr/share/kvm/openbios-ppc
--- qemu-kvm-0.12.5+dfsg.orig/debian/compat
+++ qemu-kvm-0.12.5+dfsg/debian/compat
@@ -0,0 +1 @@
+5
--- qemu-kvm-0.12.5+dfsg.orig/debian/copyright
+++ qemu-kvm-0.12.5+dfsg/debian/copyright
@@ -0,0 +1,83 @@
+This package was debianized by Baruch Even <baruch@debian.org> on
+Tue, 14 Nov 2006 20:49:57 +0200.
+
+Then maintained by:
+  Leonard Norrgård <vinsci@refactor.fi>
+
+Now maintained as a team by:
+  Jan Luebbe <jluebbe@debian.org>
+  Guido Günther <agx@sigxcpu.org>
+  Michael Tokarev <mjt@tls.msk.ru>
+
+The upstream source was downloaded from:
+
+    http://www.linux-kvm.org/
+
+    The source tarball has been repackaged to remove various binary files such as
+    BIOS blobs, PXE boot ROMs and the like. Use debian/rules get-orig-source to
+    produce a clean source tarball.
+
+Upstream Author: Fabrice Bellard <fabrice.bellard@free.fr>
+
+Upstream Maintainers: Avi Kivity <avi@redhat.com>
+                      Anthony Liguori <aliguori@us.ibm.com>
+
+Copyright: Copyright (C) 2006 Qumranet, Inc.
+           Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008  Fabrice Bellard
+
+License:
+
+    QEMU as a whole is released under the GNU General Public License version 2.
+    On Debian systems, the complete text of the GNU General Public License
+    version 2 can be found in the file /usr/share/common-licenses/GPL-2.
+
+    Parts of QEMU have specific licenses which are compatible with the
+    GNU General Public License. Hence each source file contains its own
+    licensing information.
+
+    In particular, the QEMU virtual CPU core library (libqemu.a) is
+    released under the GNU Lesser General Public License version 2 or later.
+    On Debian systems, the complete text of the GNU Lesser General Public 
+    License can be found in the file /usr/share/common-licenses/LGPL.
+
+    Some hardware device emulation sources and other QEMU functionality are
+    released under the BSD license, including (parts of):
+     * aes, bsd-user, sd, slirp, sys-queue
+    Please see the individual files for the license text.
+
+    Some hardware device emulation sources and other QEMU functionality are
+    released under the MIT/X11 (BSD-like) license, including:
+     * sdl, host-utils, vnc, keymaps, ioport, usb, hw/*, net, acl, block,
+       kqemu, monitor, curses, readline, vl, savevm, osdep, audio, tcg,
+       qemu-malloc, qemu-img
+    Please see the individual files for the license text.
+
+    The following points clarify the QEMU license:
+     1) QEMU as a whole is released under the GNU General Public License
+     2) Parts of QEMU have specific licenses which are compatible with the
+        GNU General Public License. Hence each source file contains its own
+        licensing information.
+        In particular, the QEMU virtual CPU core library (libqemu.a) is
+        released under the GNU Lesser General Public License. Many hardware
+        device emulation sources are released under the BSD license.
+     3) The Tiny Code Generator (TCG) is released under the BSD license
+        (see license headers in files).
+     4) QEMU is a trademark of Fabrice Bellard.
+     -- Fabrice Bellard.
+
+    BIOS sources in QEMU:
+       bios.bin: Copyright (C) 2002 MandrakeSoft S.A. and others.  This file
+       is licensed under the GNU LGPL, version 2, or (at your option) any later
+       version.
+       Homepage: http://sourceforge.net/projects/bochs
+
+       vgabios.bin and vgabios-cirrus.bin: (C) 2003 the LGPL VGABios
+       developers Team. These files are licensed under the GNU LGPL, version 2,
+       or (at your option) any later version.
+       Homepage: http://savannah.nongnu.org/projects/vgabios
+
+The Debian packaging is:
+  (C) 2006, Baruch Even <baruch@debian.org>
+  (C) 2006, 2007 Leonard Norrgard <vinsci@refactor.fi>
+  (C) 2007, 2008, 2009 Jan Luebbe <jluebbe@debian.org>
+It is licensed under the GPL v2 (or later), see /usr/share/common-licenses/GPL-2.
--- qemu-kvm-0.12.5+dfsg.orig/debian/README.Debian
+++ qemu-kvm-0.12.5+dfsg/debian/README.Debian
@@ -0,0 +1,102 @@
+KVM for Debian
+--------------
+
+A few bits about history
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+KVM (stands for Kernel Virtual Machine) is a branch of a machine emulator,
+qemu.  It's a qemu modified to use virtualization extensions of modern
+(initially x86) CPUs, to be able to run guest system without emulating the
+CPU, achieving near-native CPU and memory speeds.
+
+The goal of KVM is to eventually merge back to qemu, so it serves as just
+a development branch of qemu.  Many kvm changes are already in qemu, but
+as of this writing (qemu-kvm-0.11.0), the merge is still incomplete, and
+even more, kvm is not feature-complete.
+
+
+There's two numbering schemes and release series names for kvm.  Initially
+kvm were released as numbered snapshots, like kvm-1, kvm-72 and so on.
+These were nothing more than development snapshots, the releases were
+frequent, changes in each release were significant, each release fixed
+many bugs but introduced others.
+
+Later on, the KVM team decided to release a stable series.  At the same time,
+to distinguish between stable and development trees, new naming scheme was
+introduced as well.  The first stable release was qemu-kvm-0.10.0, released
+after kvm-87 and qemu-0.10.0.
+
+Since this time, kvm exists in two forms or two branches, -- kvm and
+qemu-kvm, kvm-nn is a series of development snapshots as before, and
+qemu-kvm-x.yy.z are stable series which receive updates.
+
+Stable releases of Debian will include qemu-kvm packages.  For now
+it is still uncertain if kvm packages will be supported in Debian.
+KVM packages will not be included in stable releases of Debian,
+only qemu-kvm packages will be included.
+
+
+Since KVM is just a modified qemu, the build system of KVM produces
+an executable that's named according to qemu rules.  On x86 platform,
+it's qemu-system-x86_64.  In this package, that binary is installed
+under the name "kvm".  When the Debian package was renamed from kvm
+to qemu-kvm, the executable name did not change.
+
+
+Hardware support
+~~~~~~~~~~~~~~~~
+
+KVM works only on CPUs with virtualization extensions.
+Without these extensions it's nothing more than qemu, it will perform
+full emulation as qemu does, which is slow.
+
+To find out if your system has the necessary hardware support for kvm,
+check for processor flags in /proc/cpuinfo.
+
+For AMD CPUs "svm" flag should be listed.  For Intel CPUs, it's "vmx".
+The following command:
+
+ egrep '^flags.*(vmx|svm)' /proc/cpuinfo
+
+will output nothing if these extensions are either not present of not
+enabled.
+
+Almost all AMD CPUs after and including Athlon X2-64 supports virtualization,
+including most Durons.  Modern Opteron, AthlonII, Phenom and Phenom II
+have it too.
+
+For Intel CPUs things are not this simple.  Even in latest Core2 Duo and
+Core2 Quad series there are models without VT support.  If in doubt check
+Intel documents about your CPU and Wikipedia articles, for example
+http://en.wikipedia.org/wiki/List_of_Intel_Core_2_microprocessors.
+
+Note that in addition to the CPU itself, the BIOS of the system should
+have support for these extensions too, and it should be enabled.  It is
+NOT POSSIBLE for now to turn the extensions on if they're not enabled in
+BIOS or BIOS has no support.  The only option in this case is to
+update the system BIOS.
+
+
+Kernel requirements
+~~~~~~~~~~~~~~~~~~~
+
+KVM requires kernel modules that enables the use of the above mentioned
+extensions to be present and loaded.  For AMD CPUs it is kvm_amd.ko, and
+for Intel CPUs it is kvm_intel.ko.  The startup script in this package
+ensures that the appropriate module is loaded during system startup.
+
+Kernel includes the necessary modules since 2.6.22 version.
+
+In order to run this version of KVM, your system should be running at least
+a 2.6.24 kernel.  However, using a 2.6.28 or more later kernel is highly
+recommended.
+
+
+Miscellaneous
+~~~~~~~~~~~~~
+
+The recommended qemu package contains the script
+/usr/sbin/qemu-make-debian-root, which uses debootstrap to build a Debian disk
+image. See the man page for qemu-make-debian-root. The suggested hal package is
+only used for automatically reporting the system bios version and computer
+model when reporting bugs.
--- qemu-kvm-0.12.5+dfsg.orig/debian/qemu-kvm.udev
+++ qemu-kvm-0.12.5+dfsg/debian/qemu-kvm.udev
@@ -0,0 +1 @@
+KERNEL=="kvm", GROUP="kvm", MODE="0660"
--- qemu-kvm-0.12.5+dfsg.orig/debian/gbp.conf
+++ qemu-kvm-0.12.5+dfsg/debian/gbp.conf
@@ -0,0 +1,20 @@
+# Configuration file for git-buildpackage and friends
+
+# upstream is following the upstream tarballs
+
+# master contains the debian packaging
+
+[DEFAULT]
+# ignore .git and .gbp.conf when building source package
+builder = debuild -i\.git\|\.gbp\.conf -I.git -I.gbp.conf
+# the branch for upstream sources after cleaning
+upstream-branch = upstream
+# the long-lived integration branch where we build the source packages
+debian-branch = master
+# the default tag formats used for git-buildpackage
+upstream-tag = v%(version)s
+debian-tag = v%(version)s
+
+[git-import-orig]
+filter = .gitignore
+
--- qemu-kvm-0.12.5+dfsg.orig/debian/qemu-kvm.bug-script
+++ qemu-kvm-0.12.5+dfsg/debian/qemu-kvm.bug-script
@@ -0,0 +1,16 @@
+#!/bin/sh
+#
+# qemu-kvm reportbug script
+#
+
+exec >&3
+echo
+echo
+
+if [ -r /proc/cpuinfo ]; then
+    echo /proc/cpuinfo:
+    echo
+    cat /proc/cpuinfo
+    echo
+    echo
+fi
--- qemu-kvm-0.12.5+dfsg.orig/debian/watch
+++ qemu-kvm-0.12.5+dfsg/debian/watch
@@ -0,0 +1,3 @@
+version=3
+opts=dversionmangle=s/\+dfsg.*$// \
+  http://qa.debian.org/watch/sf.php/kvm/ qemu-kvm-([\d\.]*).tar.gz
--- qemu-kvm-0.12.5+dfsg.orig/debian/kvm-ifup
+++ qemu-kvm-0.12.5+dfsg/debian/kvm-ifup
@@ -0,0 +1,18 @@
+#! /bin/sh
+# Script to bring a network (tap) device for qemu-kvm up
+# The idea is to add the tap device to the same bridge
+# as we have default routing to.
+
+switch=$(ip route ls | \
+    awk '/^default / {
+          for(i=0;i<NF;i++) { if ($i == "dev") { print $(i+1); exit; } }
+         }'
+        )
+/sbin/ifconfig $1 0.0.0.0 up
+
+# only add the interface to default-route bridge if we
+# have such interface (with default route) and if that
+# interface is actually a bridge.
+if [ -n "$switch" -a -d /sys/class/net/$switch/bridge/. ]; then
+  /usr/sbin/brctl addif $switch $1 || :
+fi
--- qemu-kvm-0.12.5+dfsg.orig/debian/rules
+++ qemu-kvm-0.12.5+dfsg/debian/rules
@@ -0,0 +1,295 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper. 
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+#
+# This version is for a hypothetical package that can build a kernel modules
+# architecture-dependant package via make-kpkg, as well as an
+# architecture-independent module source package, and other packages
+# either dep/indep for things like common files or userspace components
+# needed for the kernel modules.
+
+# Uncomment this to turn on verbose mode. 
+#export DH_VERBOSE=1
+
+# where all bios and other support files are installed
+bdir := /usr/share/kvm
+tbdir := debian/tmp/$(bdir)
+
+DEB_BUILD_ARCH     ?= $(shell dpkg-architecture -qDEB_BUILD_ARCH)
+BASE_ARCH := $(DEB_BUILD_ARCH)
+QEMU_ARCH := $(BASE_ARCH)
+
+ifeq (i386,$(DEB_BUILD_ARCH))
+	BASE_ARCH := x86
+	QEMU_ARCH := i386
+endif
+ifeq (amd64,$(DEB_BUILD_ARCH))
+	BASE_ARCH := x86
+	QEMU_ARCH := x86_64
+endif
+ifeq (x86,$(BASE_ARCH))
+	QEMU_TARGET = x86_64-softmmu
+	QEMU_EXE = $(QEMU_TARGET)/qemu-system-x86_64
+endif
+
+ifeq (powerpc,$(DEB_BUILD_ARCH))
+	QEMU_TARGET = XXXfixme
+	QEMU_EXE = $(QEMU_TAEGET)/qemu-system-ppcemb
+endif
+
+CFLAGS = -Wall -g
+
+ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+	CFLAGS += -O0
+else
+	CFLAGS += -O2
+endif
+ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
+    NUMJOBS = $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS)))
+    MAKEFLAGS += -j$(NUMJOBS)
+endif
+
+# make build the default target
+build:
+
+include /usr/share/quilt/quilt.make
+
+config-host.mak: $(QUILT_STAMPFN)
+	dh_testdir
+
+	./configure --prefix=/usr \
+                    --audio-drv-list="alsa oss sdl pa" \
+                    --audio-card-list="ac97 es1370 sb16 cs4231a adlib gus" \
+                    --with-kvm-trace \
+                    --disable-xen \
+		    --disable-blobs
+	cat config-host.mak
+
+	cd kvm/user/ && ./configure --arch=$(QEMU_ARCH) --prefix=/usr
+
+build: build-stamp
+build-stamp: config-host.mak
+	dh_testdir
+
+# main executable and support tools
+	$(MAKE) V=1
+	$(MAKE) -C kvm/libkvm
+	$(MAKE) -C kvm/user
+
+# arch-specific stuff
+
+ifeq (x86,$(BASE_ARCH))
+	chmod +x roms/seabios/tools/*.py roms/seabios/tools/*.sh
+# seabios (as of 0.5.1) has a rule that builds several targets.
+# when run using several jobs, make tries to run them several times
+# in parallel and breaks.  Needs to be fixed upstream but for now
+# we restrict number of parallel jobs. -- mjt
+	LC_ALL=C $(MAKE) -C roms/seabios V=1 -j1
+	LC_ALL=C $(MAKE) -C kvm/vgabios V=1
+# also pc-bios/optionrom/ but it is being built anyway
+endif
+ifeq (powerpc,$(BASE_ARCH))
+	$(MAKE) -C pc-bios bamboo.dtd
+endif
+
+	touch $@
+
+clean: unpatch
+unpatch: clean-patched
+
+clean-patched:
+	dh_testdir
+	rm -f build-stamp install-stamp
+
+ifeq (x86,$(BASE_ARCH))
+	[ ! -f config-host.mak ] || $(MAKE) -C pc-bios/optionrom clean
+	[ ! -f roms/seabios/Makefile ] || $(MAKE) -C roms/seabios clean
+	rm -f roms/seabios/tools/*.pyc
+# generated file
+	rm -f roms/seabios/src/acpi-dsdt.hex roms/seabios/src/acpi-dsdt.aml
+	[ ! -f kvm/vgabios/Makefile ] || $(MAKE) -C kvm/vgabios clean
+	rm -f kvm/vgabios/*.bin
+endif
+
+	[ ! -f config-host.mak ] || $(MAKE) -C pc-bios clean
+	[ ! -f config-host.mak ] || $(MAKE) -C kvm/libkvm clean
+
+# kvm/user dir is a mess to clean up
+	[ ! -f kvm/user/config.mak ] || $(MAKE) -C kvm/user clean
+	-rm -f kvm/user/config.mak
+	-find kvm/user/test -name '.*.d' -exec rm -f '{}' +
+
+# qemu-monitor.texi is a generated file
+	rm -f qemu-monitor.texi
+
+# top-level distclean should be last since it removes config-host.mak
+	[ ! -f config-host.mak ] || $(MAKE) distclean
+
+	dh_clean
+
+install: install-stamp
+install-stamp: build
+	dh_testdir
+	dh_testroot
+	dh_clean -k
+	dh_installdirs
+
+# qemu builds only a few files and we will rename them all anyway,
+# so install it all here manually.
+
+	install -Dp $(QEMU_EXE) debian/tmp/usr/bin/kvm
+	install -Dp qemu.1 debian/tmp/usr/share/man/man1/kvm.1
+	install -Dp qemu-img debian/tmp/usr/bin/kvm-img
+	install -Dp qemu-img.1 debian/tmp/usr/share/man/man1/kvm-img.1
+	install -Dp qemu-nbd debian/tmp/usr/bin/kvm-nbd
+	install -Dp qemu-nbd.8 debian/tmp/usr/share/man/man8/kvm-nbd.8
+# debugging tool, might be useful for debugging in case of probs @user side
+	install -Dp qemu-io debian/tmp/usr/bin/kvm-io
+
+	install -Dp -m 0755 debian/kvm-ifup debian/tmp/etc/kvm/kvm-ifup
+	install -Dp -m 0755 debian/kvm-ifdown debian/tmp/etc/kvm/kvm-ifdown
+
+	# Install the userspace utilities
+	install -m 0755 kvm/kvm_stat kvm/user/kvmtrace kvm/user/kvmtrace_format \
+		debian/tmp/usr/bin/
+# file `formats' is needed for kvmtrace_format
+	install -Dp -m0644 kvm/user/formats $(tbdir)/formats
+
+	install -d $(tbdir)/keymaps
+	install -p -m0644 pc-bios/keymaps/* $(tbdir)/keymaps/
+
+	install -d debian/tmp/usr/share/doc/qemu-kvm
+	install -p qemu-doc.html qemu-tech.html debian/tmp/usr/share/doc/qemu-kvm
+	install debian/qdev-device-use.txt debian/tmp/usr/share/doc/qemu-kvm
+
+ifeq (x86,$(BASE_ARCH))
+	# copy appropriate bios/ROM files
+	install -m0644 roms/seabios/out/bios.bin $(tbdir)/bios.bin
+# multiboot images (like xen), and extboot like -drive ...,boot=on
+	for f in linuxboot extboot multiboot vapic; do \
+	  install -m0644 pc-bios/optionrom/$$f.bin $(tbdir)/$$f.bin; \
+	done
+	install -m0644 kvm/vgabios/VGABIOS-lgpl-latest.bin \
+		$(tbdir)/vgabios.bin
+	install -m0644 kvm/vgabios/VGABIOS-lgpl-latest.cirrus.bin \
+		$(tbdir)/vgabios-cirrus.bin
+
+# pxe roms are x86-specific
+# etherboot_5.4.4-1 moved roms from /usr/share/etherboot to /usr/lib/etherboot
+# We can have versioned build-depends once 5.4.4-1 enters testing.
+	set -e; brl=; \
+	for d in /usr/lib/etherboot /usr/share/etherboot; do \
+		if [ -d $$d ]; then brl=$$d; break; fi; done; \
+	cp -p $$brl/e1000-82540em.zrom.gz $(tbdir)/pxe-e1000.bin.gz; \
+	cp -p $$brl/rtl8029.zrom.gz $(tbdir)/pxe-ne2k_pci.bin.gz; \
+	cp -p $$brl/pcnet32.zrom.gz $(tbdir)/pxe-pcnet.bin.gz; \
+	cp -p $$brl/rtl8139.zrom.gz $(tbdir)/pxe-rtl8139.bin.gz; \
+	if [ -f $$brl/virtio-net.zrom.gz ]; then \
+	  cp -p $$brl/virtio-net.zrom.gz $(tbdir)/pxe-virtio.bin.gz; \
+	fi
+	gzip -d $(tbdir)/pxe-*.bin.gz
+endif
+
+ifeq (powerpc,$(BASE_ARCH))
+	cp pc-bios/bamboo.dtd debian/tmp/usr/share/kvm/bamboo.dtd
+endif
+
+	dh_install --sourcedir=debian/tmp --list-missing
+
+	touch $@
+
+binary-indep:
+
+binary-arch: install
+	dh_testdir -s
+	dh_testroot -s
+#	dh_installdebconf -s
+	dh_installdocs -s debian/changelog.kvm debian/changelog.upstream-kvm
+	dh_installdocs -s debian/changelog.upstream-qemu-kvm
+#	dh_installexamples -s
+#	dh_installmenu -s
+#	dh_installlogrotate -s
+#	dh_installemacsen -s
+#	dh_installpam -s
+#	dh_installmime -s
+	dh_installinit -s --no-restart-on-upgrade --error-handler=true
+	dh_installudev
+#	dh_installcron -s
+#	dh_installinfo -s
+	dh_bugfiles
+	dh_installchangelogs -s debian/changelog.upstream-qemu-kvm
+	dh_strip -s --dbg-package=qemu-kvm-dbg
+	dh_lintian
+	dh_link -s
+	dh_compress -s
+	dh_fixperms -s
+#	dh_makeshlibs -s
+	dh_installdeb -s
+#	dh_perl -s
+	dh_shlibdeps -s
+	dh_gencontrol -s -Nkvm
+	dh_gencontrol -pkvm -- -v1:$(DEB_VERSION)
+	dh_md5sums -s
+	dh_builddeb -s
+
+binary: binary-indep binary-arch
+
+# get-orig-source adapted from /usr/share/gnome-pkg-tools/1/rules/sf-get-source.mk from the gnome-pkg-tools package
+# copied from CDBS' buildvars
+DEB_SOURCE_PACKAGE ?= $(strip $(shell egrep '^Source: ' debian/control | cut -f 2 -d ':'))
+DEB_VERSION ?= $(shell dpkg-parsechangelog | egrep '^Version:' | cut -f 2 -d ' ')
+DEB_NOEPOCH_VERSION ?= $(shell echo $(DEB_VERSION) | cut -d: -f2-)
+DEB_UPSTREAM_VERSION ?= $(shell echo $(DEB_NOEPOCH_VERSION) | sed 's/+[^-]*-[^-]*$$//')
+
+# where to store the resulting .orig tarball
+DEB_TARBALL_DOWNLOAD_DIR ?= ../tarballs
+TARBALL_EXT ?= tar.gz
+
+#SF_PROJECT ?= $(DEB_SOURCE_PACKAGE)
+SF_PROJECT = kvm
+SF_MODULE ?= $(DEB_SOURCE_PACKAGE)
+SF_TARBALL ?= $(SF_MODULE)-$(DEB_UPSTREAM_VERSION).$(TARBALL_EXT)
+SF_DOWNLOAD_URL ?= http://$$sf_mirror.dl.sourceforge.net/$(SF_PROJECT)/$(SF_TARBALL)
+SF_MIRRORS ?= dfn heanet internap jaist kent mesh nchc ovh puzzle superb-east superb-west surfnet switch ufpr waix
+SF_TARBALL_DESTINATION = $(DEB_TARBALL_DOWNLOAD_DIR)/$(DEB_SOURCE_PACKAGE)_$(DEB_UPSTREAM_VERSION).orig.$(TARBALL_EXT)
+SF_DOWNLOAD_COMMAND ?= for sf_mirror in $(SF_MIRRORS); do wget -nv -T10 -t1 -O $(SF_TARBALL_DESTINATION).tmp $(SF_DOWNLOAD_URL) && break; done
+
+get-orig-tarball: $(SF_TARBALL_DESTINATION)
+$(SF_TARBALL_DESTINATION):
+	dh_testdir
+	@@echo 'Source package:                      $(DEB_SOURCE_PACKAGE)'
+	@@echo 'Source package:                      $(DEB_VERSION)'
+	@@echo 'Source version without epoch:        $(DEB_NOEPOCH_VERSION)'
+	@@echo 'Upstream version (for orig tarball): $(DEB_UPSTREAM_VERSION)'
+	mkdir -p $(DEB_TARBALL_DOWNLOAD_DIR)
+	$(SF_DOWNLOAD_COMMAND)
+	mv $(SF_TARBALL_DESTINATION).tmp $(SF_TARBALL_DESTINATION)
+
+get-orig-source: $(SF_TARBALL_DESTINATION)
+	case "$(TARBALL_EXT)" in \
+	tar.bz2|tbz) \
+	  bzcat $(DEB_TARBALL_DOWNLOAD_DIR)/$(DEB_SOURCE_PACKAGE)_$(DEB_UPSTREAM_VERSION).orig.$(TARBALL_EXT) | \
+	  gzip -9 >$(DEB_TARBALL_DOWNLOAD_DIR)/$(DEB_SOURCE_PACKAGE)_$(DEB_UPSTREAM_VERSION).orig.tar.gz ; \
+	  rm -f $(DEB_TARBALL_DOWNLOAD_DIR)/$(DEB_SOURCE_PACKAGE)_$(DEB_UPSTREAM_VERSION).orig.$(TARBALL_EXT) \
+	  ;;\
+	esac
+	cd $(DEB_TARBALL_DOWNLOAD_DIR) && \
+	  tar xzf $(DEB_SOURCE_PACKAGE)_$(DEB_UPSTREAM_VERSION).orig.tar.gz
+	cd $(DEB_TARBALL_DOWNLOAD_DIR)/$(DEB_SOURCE_PACKAGE)-$(DEB_UPSTREAM_VERSION) && \
+	  rm -f \
+		pc-bios/*.bin \
+		pc-bios/openbios-* \
+		pc-bios/*.dtb \
+		pc-bios/video.x \
+		qemu/pc-bios/extboot.bin
+	cd $(DEB_TARBALL_DOWNLOAD_DIR) && \
+	  tar c $(DEB_SOURCE_PACKAGE)-$(DEB_UPSTREAM_VERSION) | \
+	  gzip -9 >$(DEB_TARBALL_DOWNLOAD_DIR)/$(DEB_SOURCE_PACKAGE)_$(DEB_UPSTREAM_VERSION)+dfsg.orig.tar.gz
+
+
+.PHONY: build clean clean-patched binary-indep binary-arch binary install
+
--- qemu-kvm-0.12.5+dfsg.orig/debian/qemu-kvm.postinst
+++ qemu-kvm-0.12.5+dfsg/debian/qemu-kvm.postinst
@@ -0,0 +1,44 @@
+#!/bin/sh
+# postinst script for kvm
+#
+# see: dh_installdeb(1)
+
+set -e
+
+# summary of how this script can be called:
+#        * <postinst> `configure' <most-recently-configured-version>
+#        * <old-postinst> `abort-upgrade' <new version>
+#        * <conflictor's-postinst> `abort-remove' `in-favour' <package>
+#          <new-version>
+#        * <postinst> `abort-remove'
+#        * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
+#          <failed-install-package> <version> `removing'
+#          <conflicting-package> <version>
+# for details, see http://www.debian.org/doc/debian-policy/ or
+# the debian-policy package
+
+
+case "$1" in
+    configure)
+        # Add the kvm group unless it's already there
+        if ! getent group kvm >/dev/null; then
+            addgroup --quiet --system kvm || true
+        fi
+    ;;
+
+    abort-upgrade|abort-remove|abort-deconfigure)
+    ;;
+
+    *)
+        echo "postinst called with unknown argument \`$1'" >&2
+        exit 1
+    ;;
+esac
+
+# dh_installdeb will replace this with shell code automatically
+# generated by other debhelper scripts.
+
+#DEBHELPER#
+
+exit 0
+
--- qemu-kvm-0.12.5+dfsg.orig/debian/kvm.bug-control
+++ qemu-kvm-0.12.5+dfsg/debian/kvm.bug-control
@@ -0,0 +1 @@
+Submit-As: qemu-kvm
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/revert-all-bdrv_write_sync-changes.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/revert-all-bdrv_write_sync-changes.diff
@@ -0,0 +1,506 @@
+The patches to make all metadata writes (qcow, vmdk etc) syncronous
+makes these formats largely unusable due to insanely slow resulting
+operations - writes become 10..100 times slower.  Reverting these
+changes for now.
+
+commit cdf308d144381c0771a09021610a03b0f38c3144
+Author: Michael Tokarev <mjt@tls.msk.ru>
+Date:   Tue Aug 24 14:26:16 2010 +0400
+
+    reverted all bdrv_(p)write_sync changes
+
+diff --git a/block.c b/block.c
+index 1694780..da95cc6 100644
+--- a/block.c
++++ b/block.c
+@@ -452,8 +452,6 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
+             (flags & (BDRV_O_CACHE_MASK|BDRV_O_NATIVE_AIO));
+     else
+         open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT);
+-
+-    bs->open_flags = open_flags;
+     if (use_bdrv_whitelist && !bdrv_is_whitelisted(drv))
+         ret = -ENOTSUP;
+     else
+@@ -781,43 +779,6 @@ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
+     return count1;
+ }
+ 
+-/*
+- * Writes to the file and ensures that no writes are reordered across this
+- * request (acts as a barrier)
+- *
+- * Returns 0 on success, -errno in error cases.
+- */
+-int bdrv_pwrite_sync(BlockDriverState *bs, int64_t offset,
+-    const void *buf, int count)
+-{
+-    int ret;
+-
+-    ret = bdrv_pwrite(bs, offset, buf, count);
+-    if (ret < 0) {
+-        return ret;
+-    }
+-
+-    /* No flush needed for cache=writethrough, it uses O_DSYNC */
+-    if ((bs->open_flags & BDRV_O_CACHE_MASK) != 0) {
+-        bdrv_flush(bs);
+-    }
+-
+-    return 0;
+-}
+-
+-/*
+- * Writes to the file and ensures that no writes are reordered across this
+- * request (acts as a barrier)
+- *
+- * Returns 0 on success, -errno in error cases.
+- */
+-int bdrv_write_sync(BlockDriverState *bs, int64_t sector_num,
+-    const uint8_t *buf, int nb_sectors)
+-{
+-    return bdrv_pwrite_sync(bs, BDRV_SECTOR_SIZE * sector_num,
+-        buf, BDRV_SECTOR_SIZE * nb_sectors);
+-}
+-
+ /**
+  * Truncate file to 'offset' bytes (needed only for file protocols)
+  */
+diff --git a/block.h b/block.h
+index 762d88a..fa51ddf 100644
+--- a/block.h
++++ b/block.h
+@@ -77,10 +77,6 @@ int bdrv_pread(BlockDriverState *bs, int64_t offset,
+                void *buf, int count);
+ int bdrv_pwrite(BlockDriverState *bs, int64_t offset,
+                 const void *buf, int count);
+-int bdrv_pwrite_sync(BlockDriverState *bs, int64_t offset,
+-    const void *buf, int count);
+-int bdrv_write_sync(BlockDriverState *bs, int64_t sector_num,
+-    const uint8_t *buf, int nb_sectors);
+ int bdrv_truncate(BlockDriverState *bs, int64_t offset);
+ int64_t bdrv_getlength(BlockDriverState *bs);
+ void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
+diff --git a/block/qcow.c b/block/qcow.c
+index 6a4c30f..7fc85ae 100644
+--- a/block/qcow.c
++++ b/block/qcow.c
+@@ -277,9 +277,8 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
+         /* update the L1 entry */
+         s->l1_table[l1_index] = l2_offset;
+         tmp = cpu_to_be64(l2_offset);
+-        if (bdrv_pwrite_sync(s->hd,
+-                s->l1_table_offset + l1_index * sizeof(tmp),
+-                &tmp, sizeof(tmp)) < 0)
++        if (bdrv_pwrite(s->hd, s->l1_table_offset + l1_index * sizeof(tmp),
++                        &tmp, sizeof(tmp)) != sizeof(tmp))
+             return 0;
+         new_l2_table = 1;
+     }
+@@ -307,8 +306,8 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
+     l2_table = s->l2_cache + (min_index << s->l2_bits);
+     if (new_l2_table) {
+         memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
+-        if (bdrv_pwrite_sync(s->hd, l2_offset, l2_table,
+-                s->l2_size * sizeof(uint64_t)) < 0)
++        if (bdrv_pwrite(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
++            s->l2_size * sizeof(uint64_t))
+             return 0;
+     } else {
+         if (bdrv_pread(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
+@@ -373,8 +372,8 @@ static uint64_t get_cluster_offset(BlockDriverState *bs,
+         /* update L2 table */
+         tmp = cpu_to_be64(cluster_offset);
+         l2_table[l2_index] = tmp;
+-        if (bdrv_pwrite_sync(s->hd, l2_offset + l2_index * sizeof(tmp),
+-                &tmp, sizeof(tmp)) < 0)
++        if (bdrv_pwrite(s->hd,
++                        l2_offset + l2_index * sizeof(tmp), &tmp, sizeof(tmp)) != sizeof(tmp))
+             return 0;
+     }
+     return cluster_offset;
+@@ -822,9 +821,8 @@ static int qcow_make_empty(BlockDriverState *bs)
+     int ret;
+ 
+     memset(s->l1_table, 0, l1_length);
+-    if (bdrv_pwrite_sync(s->hd, s->l1_table_offset, s->l1_table,
+-            l1_length) < 0)
+-        return -1;
++    if (bdrv_pwrite(s->hd, s->l1_table_offset, s->l1_table, l1_length) < 0)
++	return -1;
+     ret = bdrv_truncate(s->hd, s->l1_table_offset + l1_length);
+     if (ret < 0)
+         return ret;
+diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
+index 0a555dc..8c67e3c 100644
+--- a/block/qcow2-cluster.c
++++ b/block/qcow2-cluster.c
+@@ -62,8 +62,8 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size)
+ 
+     for(i = 0; i < s->l1_size; i++)
+         new_l1_table[i] = cpu_to_be64(new_l1_table[i]);
+-    ret = bdrv_pwrite_sync(s->hd, new_l1_table_offset, new_l1_table, new_l1_size2);
+-    if (ret < 0)
++    ret = bdrv_pwrite(s->hd, new_l1_table_offset, new_l1_table, new_l1_size2);
++    if (ret != new_l1_size2)
+         goto fail;
+     for(i = 0; i < s->l1_size; i++)
+         new_l1_table[i] = be64_to_cpu(new_l1_table[i]);
+@@ -71,8 +71,8 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size)
+     /* set new table */
+     cpu_to_be32w((uint32_t*)data, new_l1_size);
+     cpu_to_be64w((uint64_t*)(data + 4), new_l1_table_offset);
+-    ret = bdrv_pwrite_sync(s->hd, offsetof(QCowHeader, l1_size), data,sizeof(data));
+-    if (ret < 0) {
++    ret = bdrv_pwrite(s->hd, offsetof(QCowHeader, l1_size), data,sizeof(data));
++    if (ret != sizeof(data)) {
+         goto fail;
+     }
+     qemu_free(s->l1_table);
+@@ -84,7 +84,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size)
+  fail:
+     qemu_free(new_l1_table);
+     qcow2_free_clusters(bs, new_l1_table_offset, new_l1_size2);
+-    return ret;
++    return ret < 0 ? ret : -EIO;
+ }
+ 
+ void qcow2_l2_cache_reset(BlockDriverState *bs)
+@@ -188,17 +188,17 @@ static int write_l1_entry(BDRVQcowState *s, int l1_index)
+ {
+     uint64_t buf[L1_ENTRIES_PER_SECTOR];
+     int l1_start_index;
+-    int i, ret;
++    int i;
+ 
+     l1_start_index = l1_index & ~(L1_ENTRIES_PER_SECTOR - 1);
+     for (i = 0; i < L1_ENTRIES_PER_SECTOR; i++) {
+         buf[i] = cpu_to_be64(s->l1_table[l1_start_index + i]);
+     }
+ 
+-    ret = bdrv_pwrite_sync(s->hd, s->l1_table_offset + 8 * l1_start_index,
+-        buf, sizeof(buf));
+-    if (ret < 0) {
+-        return ret;
++    if (bdrv_pwrite(s->hd, s->l1_table_offset + 8 * l1_start_index,
++        buf, sizeof(buf)) != sizeof(buf))
++    {
++        return -1;
+     }
+ 
+     return 0;
+@@ -221,7 +221,6 @@ static uint64_t *l2_allocate(BlockDriverState *bs, int l1_index)
+     uint64_t old_l2_offset;
+     uint64_t *l2_table;
+     int64_t l2_offset;
+-    int ret;
+ 
+     old_l2_offset = s->l1_table[l1_index];
+ 
+@@ -248,11 +247,10 @@ static uint64_t *l2_allocate(BlockDriverState *bs, int l1_index)
+             goto fail;
+     }
+     /* write the l2 table to the file */
+-    ret = bdrv_pwrite_sync(s->hd, l2_offset, l2_table,
+-        s->l2_size * sizeof(uint64_t));
+-    if (ret < 0) {
++    if (bdrv_pwrite(s->hd, l2_offset,
++                    l2_table, s->l2_size * sizeof(uint64_t)) !=
++        s->l2_size * sizeof(uint64_t))
+         goto fail;
+-    }
+ 
+     /* update the L1 entry */
+     s->l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED;
+@@ -386,8 +384,8 @@ static int copy_sectors(BlockDriverState *bs, uint64_t start_sect,
+                         s->cluster_data, n, 1,
+                         &s->aes_encrypt_key);
+     }
+-    ret = bdrv_write_sync(s->hd, (cluster_offset >> 9) + n_start,
+-        s->cluster_data, n);
++    ret = bdrv_write(s->hd, (cluster_offset >> 9) + n_start,
++                     s->cluster_data, n);
+     if (ret < 0)
+         return ret;
+     return 0;
+@@ -599,10 +597,10 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
+     /* compressed clusters never have the copied flag */
+ 
+     l2_table[l2_index] = cpu_to_be64(cluster_offset);
+-    if (bdrv_pwrite_sync(s->hd,
++    if (bdrv_pwrite(s->hd,
+                     l2_offset + l2_index * sizeof(uint64_t),
+                     l2_table + l2_index,
+-                    sizeof(uint64_t)) < 0)
++                    sizeof(uint64_t)) != sizeof(uint64_t))
+         return 0;
+ 
+     return cluster_offset;
+@@ -620,12 +618,11 @@ static int write_l2_entries(BDRVQcowState *s, uint64_t *l2_table,
+     int start_offset = (8 * l2_index) & ~511;
+     int end_offset = (8 * (l2_index + num) + 511) & ~511;
+     size_t len = end_offset - start_offset;
+-    int ret;
+ 
+-    ret = bdrv_pwrite_sync(s->hd, l2_offset + start_offset,
+-        &l2_table[l2_start_index], len);
+-    if (ret < 0) {
+-        return ret;
++    if (bdrv_pwrite(s->hd, l2_offset + start_offset, &l2_table[l2_start_index],
++        len) != len)
++    {
++        return -1;
+     }
+ 
+     return 0;
+diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
+index 06998da..ff2cf6d 100644
+--- a/block/qcow2-refcount.c
++++ b/block/qcow2-refcount.c
+@@ -42,8 +42,8 @@ static int write_refcount_block(BDRVQcowState *s)
+         return 0;
+     }
+ 
+-    if (bdrv_pwrite_sync(s->hd, s->refcount_block_cache_offset,
+-            s->refcount_block_cache, size) < 0)
++    if (bdrv_pwrite(s->hd, s->refcount_block_cache_offset,
++            s->refcount_block_cache, size) != size)
+     {
+         return -EIO;
+     }
+@@ -246,7 +246,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
+     }
+ 
+     /* Now the new refcount block needs to be written to disk */
+-    ret = bdrv_pwrite_sync(s->hd, new_block, s->refcount_block_cache,
++    ret = bdrv_pwrite(s->hd, new_block, s->refcount_block_cache,
+         s->cluster_size);
+     if (ret < 0) {
+         goto fail_block;
+@@ -255,7 +255,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
+     /* If the refcount table is big enough, just hook the block up there */
+     if (refcount_table_index < s->refcount_table_size) {
+         uint64_t data64 = cpu_to_be64(new_block);
+-        ret = bdrv_pwrite_sync(s->hd,
++        ret = bdrv_pwrite(s->hd,
+             s->refcount_table_offset + refcount_table_index * sizeof(uint64_t),
+             &data64, sizeof(data64));
+         if (ret < 0) {
+@@ -332,7 +332,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
+     }
+ 
+     /* Write refcount blocks to disk */
+-    ret = bdrv_pwrite_sync(s->hd, meta_offset, new_blocks,
++    ret = bdrv_pwrite(s->hd, meta_offset, new_blocks,
+         blocks_clusters * s->cluster_size);
+     qemu_free(new_blocks);
+     if (ret < 0) {
+@@ -344,7 +344,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
+         cpu_to_be64s(&new_table[i]);
+     }
+ 
+-    ret = bdrv_pwrite_sync(s->hd, table_offset, new_table,
++    ret = bdrv_pwrite(s->hd, table_offset, new_table,
+         table_size * sizeof(uint64_t));
+     if (ret < 0) {
+         goto fail_table;
+@@ -358,7 +358,7 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
+     uint8_t data[12];
+     cpu_to_be64w((uint64_t*)data, table_offset);
+     cpu_to_be32w((uint32_t*)(data + 8), table_clusters);
+-    ret = bdrv_pwrite_sync(s->hd, offsetof(QCowHeader, refcount_table_offset),
++    ret = bdrv_pwrite(s->hd, offsetof(QCowHeader, refcount_table_offset),
+         data, sizeof(data));
+     if (ret < 0) {
+         goto fail_table;
+@@ -397,7 +397,6 @@ static int write_refcount_block_entries(BDRVQcowState *s,
+     int64_t refcount_block_offset, int first_index, int last_index)
+ {
+     size_t size;
+-    int ret;
+ 
+     if (cache_refcount_updates) {
+         return 0;
+@@ -412,11 +411,11 @@ static int write_refcount_block_entries(BDRVQcowState *s,
+         & ~(REFCOUNTS_PER_SECTOR - 1);
+ 
+     size = (last_index - first_index) << REFCOUNT_SHIFT;
+-    ret = bdrv_pwrite_sync(s->hd,
++    if (bdrv_pwrite(s->hd,
+         refcount_block_offset + (first_index << REFCOUNT_SHIFT),
+-        &s->refcount_block_cache[first_index], size);
+-    if (ret < 0) {
+-        return ret;
++        &s->refcount_block_cache[first_index], size) != size)
++    {
++        return -EIO;
+     }
+ 
+     return 0;
+@@ -772,8 +771,8 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
+                 }
+             }
+             if (l2_modified) {
+-                if (bdrv_pwrite_sync(s->hd,
+-                                l2_offset, l2_table, l2_size) < 0)
++                if (bdrv_pwrite(s->hd,
++                                l2_offset, l2_table, l2_size) != l2_size)
+                     goto fail;
+             }
+ 
+@@ -794,8 +793,8 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
+     if (l1_modified) {
+         for(i = 0; i < l1_size; i++)
+             cpu_to_be64s(&l1_table[i]);
+-        if (bdrv_pwrite_sync(s->hd, l1_table_offset, l1_table,
+-                        l1_size2) < 0)
++        if (bdrv_pwrite(s->hd, l1_table_offset, l1_table,
++                        l1_size2) != l1_size2)
+             goto fail;
+         for(i = 0; i < l1_size; i++)
+             be64_to_cpus(&l1_table[i]);
+diff --git a/block/qcow2-snapshot.c b/block/qcow2-snapshot.c
+index 64af361..8ddaea2 100644
+--- a/block/qcow2-snapshot.c
++++ b/block/qcow2-snapshot.c
+@@ -158,25 +158,25 @@ static int qcow_write_snapshots(BlockDriverState *bs)
+         h.id_str_size = cpu_to_be16(id_str_size);
+         h.name_size = cpu_to_be16(name_size);
+         offset = align_offset(offset, 8);
+-        if (bdrv_pwrite_sync(s->hd, offset, &h, sizeof(h)) < 0)
++        if (bdrv_pwrite(s->hd, offset, &h, sizeof(h)) != sizeof(h))
+             goto fail;
+         offset += sizeof(h);
+-        if (bdrv_pwrite_sync(s->hd, offset, sn->id_str, id_str_size) < 0)
++        if (bdrv_pwrite(s->hd, offset, sn->id_str, id_str_size) != id_str_size)
+             goto fail;
+         offset += id_str_size;
+-        if (bdrv_pwrite_sync(s->hd, offset, sn->name, name_size) < 0)
++        if (bdrv_pwrite(s->hd, offset, sn->name, name_size) != name_size)
+             goto fail;
+         offset += name_size;
+     }
+ 
+     /* update the various header fields */
+     data64 = cpu_to_be64(snapshots_offset);
+-    if (bdrv_pwrite_sync(s->hd, offsetof(QCowHeader, snapshots_offset),
+-                    &data64, sizeof(data64)) < 0)
++    if (bdrv_pwrite(s->hd, offsetof(QCowHeader, snapshots_offset),
++                    &data64, sizeof(data64)) != sizeof(data64))
+         goto fail;
+     data32 = cpu_to_be32(s->nb_snapshots);
+-    if (bdrv_pwrite_sync(s->hd, offsetof(QCowHeader, nb_snapshots),
+-                    &data32, sizeof(data32)) < 0)
++    if (bdrv_pwrite(s->hd, offsetof(QCowHeader, nb_snapshots),
++                    &data32, sizeof(data32)) != sizeof(data32))
+         goto fail;
+ 
+     /* free the old snapshot table */
+@@ -284,8 +284,9 @@ int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
+     for(i = 0; i < s->l1_size; i++) {
+         l1_table[i] = cpu_to_be64(s->l1_table[i]);
+     }
+-    if (bdrv_pwrite_sync(s->hd, sn->l1_table_offset,
+-                    l1_table, s->l1_size * sizeof(uint64_t)) < 0)
++    if (bdrv_pwrite(s->hd, sn->l1_table_offset,
++                    l1_table, s->l1_size * sizeof(uint64_t)) !=
++        (s->l1_size * sizeof(uint64_t)))
+         goto fail;
+     qemu_free(l1_table);
+     l1_table = NULL;
+@@ -334,8 +335,8 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
+     if (bdrv_pread(s->hd, sn->l1_table_offset,
+                    s->l1_table, l1_size2) != l1_size2)
+         goto fail;
+-    if (bdrv_pwrite_sync(s->hd, s->l1_table_offset,
+-                    s->l1_table, l1_size2) < 0)
++    if (bdrv_pwrite(s->hd, s->l1_table_offset,
++                    s->l1_table, l1_size2) != l1_size2)
+         goto fail;
+     for(i = 0;i < s->l1_size; i++) {
+         be64_to_cpus(&s->l1_table[i]);
+diff --git a/block/vmdk.c b/block/vmdk.c
+index cd87279..d52904a 100644
+--- a/block/vmdk.c
++++ b/block/vmdk.c
+@@ -153,7 +153,7 @@ static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
+         pstrcat(desc, sizeof(desc), tmp_desc);
+     }
+ 
+-    if (bdrv_pwrite_sync(s->hd, 0x200, desc, DESC_SIZE) < 0)
++    if (bdrv_pwrite(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
+         return -1;
+     return 0;
+ }
+@@ -482,14 +482,14 @@ static int vmdk_L2update(BlockDriverState *bs, VmdkMetaData *m_data)
+     BDRVVmdkState *s = bs->opaque;
+ 
+     /* update L2 table */
+-    if (bdrv_pwrite_sync(s->hd, ((int64_t)m_data->l2_offset * 512) + (m_data->l2_index * sizeof(m_data->offset)),
+-                    &(m_data->offset), sizeof(m_data->offset)) < 0)
++    if (bdrv_pwrite(s->hd, ((int64_t)m_data->l2_offset * 512) + (m_data->l2_index * sizeof(m_data->offset)),
++                    &(m_data->offset), sizeof(m_data->offset)) != sizeof(m_data->offset))
+         return -1;
+     /* update backup L2 table */
+     if (s->l1_backup_table_offset != 0) {
+         m_data->l2_offset = s->l1_backup_table[m_data->l1_index];
+-        if (bdrv_pwrite_sync(s->hd, ((int64_t)m_data->l2_offset * 512) + (m_data->l2_index * sizeof(m_data->offset)),
+-                        &(m_data->offset), sizeof(m_data->offset)) < 0)
++        if (bdrv_pwrite(s->hd, ((int64_t)m_data->l2_offset * 512) + (m_data->l2_index * sizeof(m_data->offset)),
++                        &(m_data->offset), sizeof(m_data->offset)) != sizeof(m_data->offset))
+             return -1;
+     }
+ 
+diff --git a/block/vpc.c b/block/vpc.c
+index 9e0acf4..afe6f1a 100644
+--- a/block/vpc.c
++++ b/block/vpc.c
+@@ -266,7 +266,7 @@ static inline int64_t get_sector_offset(BlockDriverState *bs,
+ 
+         s->last_bitmap_offset = bitmap_offset;
+         memset(bitmap, 0xff, s->bitmap_size);
+-        bdrv_pwrite_sync(s->hd, bitmap_offset, bitmap, s->bitmap_size);
++        bdrv_pwrite(s->hd, bitmap_offset, bitmap, s->bitmap_size);
+     }
+ 
+ //    printf("sector: %" PRIx64 ", index: %x, offset: %x, bioff: %" PRIx64 ", bloff: %" PRIx64 "\n",
+@@ -316,7 +316,7 @@ static int rewrite_footer(BlockDriverState* bs)
+     BDRVVPCState *s = bs->opaque;
+     int64_t offset = s->free_data_block_offset;
+ 
+-    ret = bdrv_pwrite_sync(s->hd, offset, s->footer_buf, HEADER_SIZE);
++    ret = bdrv_pwrite(s->hd, offset, s->footer_buf, HEADER_SIZE);
+     if (ret < 0)
+         return ret;
+ 
+@@ -351,8 +351,7 @@ static int64_t alloc_block(BlockDriverState* bs, int64_t sector_num)
+ 
+     // Initialize the block's bitmap
+     memset(bitmap, 0xff, s->bitmap_size);
+-    bdrv_pwrite_sync(s->hd, s->free_data_block_offset, bitmap,
+-        s->bitmap_size);
++    bdrv_pwrite(s->hd, s->free_data_block_offset, bitmap, s->bitmap_size);
+ 
+     // Write new footer (the old one will be overwritten)
+     s->free_data_block_offset += s->block_size + s->bitmap_size;
+@@ -363,7 +362,7 @@ static int64_t alloc_block(BlockDriverState* bs, int64_t sector_num)
+     // Write BAT entry to disk
+     bat_offset = s->bat_offset + (4 * index);
+     bat_value = be32_to_cpu(s->pagetable[index]);
+-    ret = bdrv_pwrite_sync(s->hd, bat_offset, &bat_value, 4);
++    ret = bdrv_pwrite(s->hd, bat_offset, &bat_value, 4);
+     if (ret < 0)
+         goto fail;
+ 
+diff --git a/block_int.h b/block_int.h
+index 631e8c5..9a3b2e0 100644
+--- a/block_int.h
++++ b/block_int.h
+@@ -127,7 +127,6 @@ struct BlockDriverState {
+     int64_t total_sectors; /* if we are reading a disk image, give its
+                               size in sectors */
+     int read_only; /* if true, the media is read only */
+-    int open_flags; /* flags used to open the file, re-used for re-open */
+     int removable; /* if true, the media can be removed */
+     int locked;    /* if true, the media cannot temporarily be ejected */
+     int encrypted; /* if true, the media is encrypted */
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/hotplug-4-ignore-pci-hotplug-requests-for-unpluggable-devices-CVE-2011-1751.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/hotplug-4-ignore-pci-hotplug-requests-for-unpluggable-devices-CVE-2011-1751.diff
@@ -0,0 +1,45 @@
+Refreshed for 0.12 - the code moved from hw/acpi.c to hw/acpi_piix4.c
+in upstream version.
+			-- mjt
+
+Content-Type: text/plain; charset="utf-8"
+MIME-Version: 1.0
+Content-Transfer-Encoding: 7bit
+Subject: Ignore pci unplug requests for unpluggable devices (CVE-2011-1751)
+Date: Wed, 18 May 2011 23:13:13 -0000
+From: Gerd Hoffmann <kraxel@redhat.com>
+X-Patchwork-Id: 96331
+Message-Id: <1305796393-22786-2-git-send-email-kraxel@redhat.com>
+To: qemu-devel@nongnu.org
+Cc: Gerd Hoffmann <kraxel@redhat.com>
+
+This patch makes qemu ignore unplug requests from the guest for pci
+devices which are tagged as non-hotpluggable.  Trouble spot is the
+piix4 chipset with the ISA bridge.  Requests to unplug that one will
+make it go away together with all ISA bus devices, which are not
+prepared to be unplugged and thus don't cleanup, leaving active
+qemu timers behind in free'ed memory.
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+
+---
+hw/acpi_piix4.c |    4 +++-
+ 1 files changed, 3 insertions(+), 1 deletions(-)
+
+--- debian.orig/hw/acpi.c	2011-05-21 16:00:52.903435908 +0400
++++ debian/hw/acpi.c	2011-05-21 16:02:18.359473876 +0400
+@@ -749,11 +749,13 @@ static void pciej_write(void *opaque, ui
+     BusState *bus = opaque;
+     DeviceState *qdev, *next;
+     PCIDevice *dev;
++    PCIDeviceInfo *info;
+     int slot = ffs(val) - 1;
+ 
+     QLIST_FOREACH_SAFE(qdev, &bus->children, sibling, next) {
+         dev = DO_UPCAST(PCIDevice, qdev, qdev);
+-        if (PCI_SLOT(dev->devfn) == slot) {
++        info = container_of(qdev->info, PCIDeviceInfo, qdev);
++        if (PCI_SLOT(dev->devfn) == slot && !info->no_hotplug) {
+             qdev_free(qdev);
+         }
+     }
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/document--incoming-option.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/document--incoming-option.diff
@@ -0,0 +1,22 @@
+diff --git a/qemu-options.hx b/qemu-options.hx
+index e2fbebd..fbce6f2 100644
+--- a/qemu-options.hx
++++ b/qemu-options.hx
+@@ -1893,8 +1893,15 @@ STEXI
+ ETEXI
+ 
+ DEF("incoming", HAS_ARG, QEMU_OPTION_incoming, \
+-    "-incoming p     prepare for incoming migration, listen on port p\n")
+-STEXI
++    "-incoming uri   wait on uri for incoming migration\n")
++STEXI
++@item -incoming @var{uri}
++Do not start CPU at startup, instead wait for migration from another host.
++The @var{uri} is the listening specification, in the form
++@var{protocol}:@var{proto-specific-info}.
++Examples are @code{tcp:localhost:1234}
++and @code{exec:gzip -dc /tmp/image.gz} (don't forget to protect the argument
++from the shell word splitting by using quotes: it should be single argument).
+ ETEXI
+ 
+ DEF("nodefaults", 0, QEMU_OPTION_nodefaults, \
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/series
+++ qemu-kvm-0.12.5+dfsg/debian/patches/series
@@ -0,0 +1,49 @@
+01_use_bios_files_in_usr_share_kvm.patch
+02_use_usr_share_kvm_fixed.patch
+04_use_etc_kvm_kvm-ifup.patch
+06_no_system_linux_kvm_h.patch
+security/leftover.patch
+revert-sdlaudio:-make-it-suck-less.diff
+seabios-0.12.3.diff
+seabios-ps2-fixes.diff
+seabios-mark-irq9-active-high-in-DSDT.diff
+seabios-makefile-depends-on-acpi-dsdt-hex.diff
+573439-fail-to-set-hdd-serial-number.diff
+isa-refine-irq-reservations.patch
+be_more_specific_in_-mem-path_error_messages.diff
+give-useful-error-messages-when-tap-open-fails.diff
+document--incoming-option.diff
+usbkbd-menu-logo-keys.diff
+madv_mergeable-for-old-kernheaders-hack.diff
+sdl-do-not-disable-screensaver.diff
+fix-curses-return-key-when-using--k.diff
+vmstate:-fix-breakage-by-7e72abc382b700a72549e8147bdea413534eeedc.diff
+add-support-for-GET-EVENT-STATUS-NOTIFICATION.diff
+upstream-stable01-make-PIIX-and-ISA-IDE-init-functions-return-the-qdev.diff
+upstream-stable02-fix-CMOS-info-for-drives-defined-with--device.diff
+revert-all-bdrv_write_sync-changes.diff
+CVE-2010-2784-fix-segfault-in-mmio-subpage-handling-code.diff
+QEMUFileBuffered:-indicate-that-were-ready-when-the-underlying-file-is-ready.diff
+scsi:-Dequeue-requests-before-invoking-completion-callback.diff
+fix-100%-CPU-load-when-idle-with-ALSA.diff
+issue-snd_pcm_start-when-capturing-audio.diff
+virtio-blk-fail-unaligned-access-CVE-2011-1750-52c050236e.diff
+revert-vnc-password-semantics-52c18be9e9-CVE-2011-0011.diff
+
+# no_hotplug & pci infrastructure preparation for CVE-2011-1751 fix
+pci-cleanly-backout-of-pci_qdev_init-925fe64ae7.diff
+hotplug-0-acpi_piix4-qdevfy-e8ec0571e1.diff
+hotplug-1-pci-allow-devices-being-tagged-as-not-hotpluggable-180c22e18b.diff
+hotplug-2-piix-tag-as-not-hotpluggable-0965f12da6.diff
+hotplug-3-vga-tag-as-not-hotplugable-be92bbf73d.diff
+# this is the main patch to actually fix CVE-2011-1751
+hotplug-4-ignore-pci-hotplug-requests-for-unpluggable-devices-CVE-2011-1751.diff
+
+cirrus_vga:fix-division-by-0-for-color-expansion-rop-92d675d1c1.diff
+fix-vnc-zlib-overflow.diff
+qdev-dont-hw_error-in-qdev_init_nofail-bd6c9a61.diff
+fix-crash-in-migration-32-bit-51b0c6065a.diff
+virtio-guard-against-negative-vq-notifies-CVE-2011-2512.diff
+virtio-fix-indirect-descriptor-buffer-overflow-CVE-2011-2212.diff
+os-posix-set-groups-properly-for--runas-CVE-2011-2527.diff
+stash-away-SCM_RIGHTS-fd-until-a-getfd-command-arrives-e53f27b9d9.diff
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/vmstate:-fix-breakage-by-7e72abc382b700a72549e8147bdea413534eeedc.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/vmstate:-fix-breakage-by-7e72abc382b700a72549e8147bdea413534eeedc.diff
@@ -0,0 +1,27 @@
+See also https://bugs.launchpad.net/qemu/+bug/494486
+
+commit ae6b2c4ed956c17456e70efefe13ad0ab7db31de
+Author: TeLeMan <geleman@gmail.com>
+Date:   Wed May 12 10:28:51 2010 +0800
+
+    vmstate: fix breakage by 7e72abc382b700a72549e8147bdea413534eeedc
+    
+    cirrus_post_load() will be executed twice when loading vm states and then the
+    wrong physical memory will be registered. This issue may lead to crash qemu.
+    
+    Signed-off-by: TeLeMan <geleman@gmail.com>
+    Acked-by: Juan Quintela <quintela@redhat.com>
+    Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
+
+diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
+index 9f61a01..ba48289 100644
+--- a/hw/cirrus_vga.c
++++ b/hw/cirrus_vga.c
+@@ -2985,7 +2985,6 @@ static const VMStateDescription vmstate_pci_cirrus_vga = {
+     .version_id = 2,
+     .minimum_version_id = 2,
+     .minimum_version_id_old = 2,
+-    .post_load = cirrus_post_load,
+     .fields      = (VMStateField []) {
+         VMSTATE_PCI_DEVICE(dev, PCICirrusVGAState),
+         VMSTATE_STRUCT(cirrus_vga, PCICirrusVGAState, 0,
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/seabios-mark-irq9-active-high-in-DSDT.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/seabios-mark-irq9-active-high-in-DSDT.diff
@@ -0,0 +1,76 @@
+This is source-only patch (dsl), not including dsl (hex) output
+(so only part of 6d5a2172f2b76900572107868ec080400c4f615d is taken).
+This patch fixes system_powerdown for FreeBSD and some other OSes.
+
+commit 6d5a2172f2b76900572107868ec080400c4f615d
+Author: Kevin O'Connor <kevin@koconnor.net>
+Date:   Wed Oct 20 21:59:11 2010 -0400
+
+    mark irq9 active high in DSDT
+    
+    In PIIX4 SCI (irq9) is active high. Seabios marks it so in interrupt
+    override table, but some OSes (FreeBSD) require the same information to
+    be present in DSDT too. Make it so.
+    
+    Signed-off-by: Gleb Natapov <gleb@redhat.com>
+
+diff --git a/src/acpi-dsdt.dsl b/src/acpi-dsdt.dsl
+index bb0a176..dafcf45 100644
+--- a/roms/seabios/src/acpi-dsdt.dsl
++++ b/roms/seabios/src/acpi-dsdt.dsl
+@@ -73,7 +73,7 @@ DefinitionBlock (
+ #define prt_slot3(nr) prt_slot(nr, LNKC, LNKD, LNKA, LNKB)
+                prt_slot0(0x0000),
+                /* Device 1 is power mgmt device, and can only use irq 9 */
+-               Package() { 0x0001ffff, 0, 0, 9 },
++               Package() { 0x0001ffff, 0, LNKS, 0 },
+                Package() { 0x0001ffff, 1, LNKB, 0 },
+                Package() { 0x0001ffff, 2, LNKC, 0 },
+                Package() { 0x0001ffff, 3, LNKD, 0 },
+@@ -634,6 +634,46 @@ DefinitionBlock (
+                     Store (TMP, PRQ3)
+                 }
+         }
++        Device(LNKS){
++                Name(_HID, EISAID("PNP0C0F"))     // PCI interrupt link
++                Name(_UID, 5)
++                Name(_PRS, ResourceTemplate(){
++                    Interrupt (, Level, ActiveHigh, Shared)
++                        { 9 }
++                })
++                Method (_STA, 0, NotSerialized)
++                {
++                    Store (0x0B, Local0)
++                    If (And (0x80, PRQ0, Local1))
++                    {
++                         Store (0x09, Local0)
++                    }
++                    Return (Local0)
++                }
++                Method (_DIS, 0, NotSerialized)
++                {
++                    Or (PRQ0, 0x80, PRQ0)
++                }
++                Method (_CRS, 0, NotSerialized)
++                {
++                    Name (PRR0, ResourceTemplate ()
++                    {
++                        Interrupt (, Level, ActiveHigh, Shared)
++                            {9}
++                    })
++                    CreateDWordField (PRR0, 0x05, TMP)
++                    Store (PRQ0, Local0)
++                    If (LLess (Local0, 0x80))
++                    {
++                        Store (Local0, TMP)
++                    }
++                    Else
++                    {
++                        Store (Zero, TMP)
++                    }
++                    Return (PRR0)
++                }
++        }
+     }
+ 
+     /*
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/add-support-for-GET-EVENT-STATUS-NOTIFICATION.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/add-support-for-GET-EVENT-STATUS-NOTIFICATION.diff
@@ -0,0 +1,49 @@
+commit 253cb7b9909806b83d73269afb9cf0ab3fa2ce2c
+Author: Aurelien Jarno <aurelien@aurel32.net>
+Date:   Mon Jul 19 15:53:35 2010 +0200
+
+    ide/atapi: add support for GET EVENT STATUS NOTIFICATION
+    
+    The GET EVENT STATUS NOTIFICATION is a mandatory command according
+    to MMC-3, even if event status notification is not supported.
+    
+    This patch adds support for this command. It returns NEA ("No Event
+    Available") with an empty "Supported Event Classes" to show that it
+    doesn't event support status notification. If asychronous operation is
+    requested, which requires NCQ support, it returns an error according
+    to the specifications.
+    
+    This fixes HAL support on FreeBSD and derivatives, which fill up the
+    logs every second with:
+    
+      acd0: FAILURE - unknown CMD (0x03) ILLEGAL REQUEST asc=0x20 ascq=0x00
+    
+    Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
+    Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+
+diff --git a/hw/ide/core.c b/hw/ide/core.c
+index e20f2e7..9e1bdd5 100644
+--- a/hw/ide/core.c
++++ b/hw/ide/core.c
+@@ -1643,6 +1643,21 @@ static void ide_atapi_cmd(IDEState *s)
+             ide_atapi_cmd_reply(s, len, max_len);
+             break;
+         }
++    case GPCMD_GET_EVENT_STATUS_NOTIFICATION:
++        max_len = ube16_to_cpu(packet + 7);
++
++        if (packet[1] & 0x01) { /* polling */
++            /* We don't support any event class (yet). */
++            cpu_to_ube16(buf, 0x00); /* No event descriptor returned */
++            buf[2] = 0x80;           /* No Event Available (NEA) */
++            buf[3] = 0x00;           /* Empty supported event classes */
++            ide_atapi_cmd_reply(s, 4, max_len);
++        } else { /* asynchronous mode */
++            /* Only polling is supported, asynchronous mode is not. */
++            ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
++                                ASC_INV_FIELD_IN_CMD_PACKET);
++        }
++        break;
+     default:
+         ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+                             ASC_ILLEGAL_OPCODE);
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/scsi:-Dequeue-requests-before-invoking-completion-callback.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/scsi:-Dequeue-requests-before-invoking-completion-callback.diff
@@ -0,0 +1,68 @@
+commit e8637c9013609271772cc0c3436cb1240cd6b034
+Author: Jan Kiszka <jan.kiszka@siemens.com>
+Date:   Tue Jul 13 14:13:45 2010 +0200
+
+    scsi: Dequeue requests before invoking completion callback
+    
+    The request completion callback of the LSI controller may start the next
+    request that can use the same tag as the completed one. As the latter is
+    still enqueued at that point, scsi_send_command will complain about the
+    tag reuse and cancel the completed request. That will cause a double
+    free later on when the completion path cleans up as well.
+    
+    Fix this by dequeuing the request before invoking the callback.
+    
+    Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
+    Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
+
+diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
+index d69c74c..b860a09 100644
+--- a/hw/scsi-bus.c
++++ b/hw/scsi-bus.c
+@@ -142,6 +142,7 @@ SCSIRequest *scsi_req_alloc(size_t size, SCSIDevice *d, uint32_t tag, uint32_t l
+     req->tag = tag;
+     req->lun = lun;
+     req->status = -1;
++    req->enqueued = true;
+     QTAILQ_INSERT_TAIL(&d->requests, req, next);
+     return req;
+ }
+@@ -158,9 +159,17 @@ SCSIRequest *scsi_req_find(SCSIDevice *d, uint32_t tag)
+     return NULL;
+ }
+ 
++static void scsi_req_dequeue(SCSIRequest *req)
++{
++    if (req->enqueued) {
++        QTAILQ_REMOVE(&req->dev->requests, req, next);
++        req->enqueued = false;
++    }
++}
++
+ void scsi_req_free(SCSIRequest *req)
+ {
+-    QTAILQ_REMOVE(&req->dev->requests, req, next);
++    scsi_req_dequeue(req);
+     qemu_free(req);
+ }
+ 
+@@ -512,6 +521,7 @@ void scsi_req_print(SCSIRequest *req)
+ void scsi_req_complete(SCSIRequest *req)
+ {
+     assert(req->status != -1);
++    scsi_req_dequeue(req);
+     req->bus->complete(req->bus, SCSI_REASON_DONE,
+                        req->tag,
+                        req->status);
+diff --git a/hw/scsi.h b/hw/scsi.h
+index 4fbf1d5..cb06d6d 100644
+--- a/hw/scsi.h
++++ b/hw/scsi.h
+@@ -43,6 +43,7 @@ typedef struct SCSIRequest {
+         enum SCSIXferMode mode;
+     } cmd;
+     BlockDriverAIOCB  *aiocb;
++    bool enqueued;
+     QTAILQ_ENTRY(SCSIRequest) next;
+ } SCSIRequest;
+ 
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/hotplug-1-pci-allow-devices-being-tagged-as-not-hotpluggable-180c22e18b.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/hotplug-1-pci-allow-devices-being-tagged-as-not-hotpluggable-180c22e18b.diff
@@ -0,0 +1,78 @@
+Backported from upstream.  qerror.[ch] trivial changes.
+	-- mjt
+
+commit 180c22e18b0a9be21445271f94347238b0bc0a25
+Author: Gerd Hoffmann <kraxel@redhat.com>
+Date:   Thu Jan 6 15:14:37 2011 +0100
+
+    pci: allow devices being tagged as not hotpluggable.
+    
+    This patch adds a field to PCIDeviceInfo to tag devices as being
+    not hotpluggable.  Any attempt to plug-in or -out such a device
+    will throw an error.
+    
+    Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+    Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+
+--- debian.orig/hw/pci.c	2011-04-26 08:53:39.000000000 +0400
++++ debian/hw/pci.c	2011-05-21 15:52:55.354792693 +0400
+@@ -1479,6 +1479,11 @@ static int pci_qdev_init(DeviceState *qd
+                                      info->header_type);
+     if (pci_dev == NULL)
+         return -1;
++    if (qdev->hotplugged && info->no_hotplug) {
++        qemu_error_new(QERR_DEVICE_NO_HOTPLUG, info->qdev.name);
++        do_pci_unregister_device(pci_dev);
++        return -1;
++    }
+     rc = info->init(pci_dev);
+     if (rc != 0)
+         return rc;
+@@ -1496,6 +1501,12 @@ static int pci_qdev_init(DeviceState *qd
+ static int pci_unplug_device(DeviceState *qdev)
+ {
+     PCIDevice *dev = DO_UPCAST(PCIDevice, qdev, qdev);
++    PCIDeviceInfo *info = container_of(qdev->info, PCIDeviceInfo, qdev);
++
++    if (info->no_hotplug) {
++        qemu_error_new(QERR_DEVICE_NO_HOTPLUG, info->qdev.name);
++        return -1;
++    }
+ 
+     dev->bus->hotplug(dev, 0);
+     return 0;
+--- debian.orig/hw/pci.h	2011-04-26 08:53:39.000000000 +0400
++++ debian/hw/pci.h	2011-05-21 15:49:59.167925019 +0400
+@@ -443,6 +443,9 @@ typedef struct {
+     /* pcie stuff */
+     int is_express;   /* is this device pci express? */
+ 
++    /* device isn't hot-pluggable */
++    int no_hotplug;
++
+     /* rom bar */
+     const char *romfile;
+ } PCIDeviceInfo;
+--- debian.orig/qerror.c	2011-04-26 08:53:39.000000000 +0400
++++ debian/qerror.c	2011-05-21 15:57:06.957191482 +0400
+@@ -120,6 +120,10 @@ static const QErrorStringTable qerror_ta
+         .error_fmt = QERR_VNC_SERVER_FAILED,
+         .desc      = "Could not start VNC server on %(target)",
+     },
++    {
++        .error_fmt = QERR_DEVICE_NO_HOTPLUG,
++        .desc      = "Device '%(device)' does not support hotplugging",
++    },
+     {}
+ };
+ 
+--- debian.orig/qerror.h	2011-04-26 08:53:39.000000000 +0400
++++ debian/qerror.h	2011-05-21 15:57:51.195965390 +0400
+@@ -100,4 +100,7 @@ QError *qobject_to_qerror(const QObject
+ #define QERR_VNC_SERVER_FAILED \
+     "{ 'class': 'VNCServerFailed', 'data': { 'target': %s } }"
+ 
++#define QERR_DEVICE_NO_HOTPLUG \
++    "{ 'class': 'DeviceNoHotplug', 'data': { 'device': %s } }"
++
+ #endif /* QERROR_H */
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/be_more_specific_in_-mem-path_error_messages.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/be_more_specific_in_-mem-path_error_messages.diff
@@ -0,0 +1,49 @@
+From mjt@tls.msk.ru  Tue Mar 16 11:01:47 2010
+Return-Path: <mjt@tls.msk.ru>
+X-Original-To: mjt@tls.msk.ru
+Delivered-To: mjt@tls.msk.ru
+Received: from isrv.corpit.ru (isrv.corpit.ru [81.13.33.159])
+	by paltus.tls.msk.ru (Postfix) with ESMTP id 1780230377
+	for <mjt@tls.msk.ru>; Tue, 16 Mar 2010 11:01:47 +0300 (MSK)
+	(envelope-from mjt@tls.msk.ru)
+Received: from [192.168.88.2] (mjt.vpn.tls.msk.ru [192.168.10.88])
+	by isrv.corpit.ru (Postfix) with ESMTP id F0C8D341A5;
+	Tue, 16 Mar 2010 11:01:46 +0300 (MSK)
+	(envelope-from mjt@tls.msk.ru)
+Message-ID: <4B9F3AEA.8010408@msgid.tls.msk.ru>
+Date: Tue, 16 Mar 2010 11:01:46 +0300
+From: Michael Tokarev <mjt@tls.msk.ru>
+Organization: Telecom Service, JSC
+User-Agent: Mozilla-Thunderbird 2.0.0.22 (X11/20090706)
+MIME-Version: 1.0
+To: qemu-devel <qemu-devel@nongnu.org>
+Subject: [trivial one-liner] be more specific in -mem-path error messages
+X-Enigmail-Version: 0.95.0
+OpenPGP: id=804465C5
+Content-Type: text/plain; charset=ISO-8859-1
+Content-Transfer-Encoding: 7bit
+
+The error message qemu gives when hugetlbfs is not
+accessible is cryptic at best:
+
+  mkstemp: Permission denied
+
+Make it a bit more specific instead:
+
+ unable to create backing store for hugepages: Permission denied
+
+Thanks!
+
+/mjt
+
+diff --git a/exec.c b/exec.c
+index 891e0ee..985bdde 100644
+--- a/exec.c
++++ b/exec.c
+@@ -2569,5 +2569,5 @@ static void *file_ram_alloc(ram_addr_t memory, const char *path)
+     fd = mkstemp(filename);
+     if (fd < 0) {
+-	perror("mkstemp");
++	perror("unable to create backing store for hugepages");
+ 	free(filename);
+ 	return NULL;
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/virtio-blk-fail-unaligned-access-CVE-2011-1750-52c050236e.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/virtio-blk-fail-unaligned-access-CVE-2011-1750-52c050236e.diff
@@ -0,0 +1,51 @@
+Cherry-picked from 52c050236eaa4f0b5e1d160cd66dc18106445c4d.
+In later qemu there's a configuration parameter, logical_block_size,
+which is used in that commit.  But 0.12 does not have that size yet,
+it always operates in 512-byte sectors.  So compare with 512 for 0.12.
+
+ -- mjt
+
+commit 52c050236eaa4f0b5e1d160cd66dc18106445c4d
+Author: Christoph Hellwig <hch@lst.de>
+Date:   Wed Apr 6 20:28:34 2011 +0200
+
+    virtio-blk: fail unaligned requests
+    
+    Like all block drivers virtio-blk should not allow small than block size
+    granularity access.  But given that the protocol specifies a
+    byte unit length field we currently accept such requests, which cause
+    qemu to abort() in lower layers.  Add checks to the main read and
+    write handlers to catch them early.
+    
+    Reported-by: Conor Murphy <conor_murphy_virt@hotmail.com>
+    Tested-by: Conor Murphy <conor_murphy_virt@hotmail.com>
+    Signed-off-by: Christoph Hellwig <hch@lst.de>
+    Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
+    Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+
+diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
+index b14fb99..91e0394 100644
+--- a/hw/virtio-blk.c
++++ b/hw/virtio-blk.c
+@@ -290,6 +290,10 @@ static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb)
+         virtio_blk_rw_complete(req, -EIO);
+         return;
+     }
++    if (req->qiov.size % 512) {
++        virtio_blk_rw_complete(req, -EIO);
++        return;
++    }
+ 
+     if (mrb->num_writes == 32) {
+         virtio_submit_multiwrite(req->dev->bs, mrb);
+@@ -317,6 +321,10 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
+         virtio_blk_rw_complete(req, -EIO);
+         return;
+     }
++    if (req->qiov.size % 512) {
++        virtio_blk_rw_complete(req, -EIO);
++        return;
++    }
+ 
+     acb = bdrv_aio_readv(req->dev->bs, sector, &req->qiov,
+                          req->qiov.size / BDRV_SECTOR_SIZE,
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/fix-vnc-zlib-overflow.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/fix-vnc-zlib-overflow.diff
@@ -0,0 +1,44 @@
+This is a backport from 0.14.
+
+fix 2Gb integer overflow in in VNC tight and zlib encodings
+
+As found by Roland Dreier <roland@purestorage.com> (excellent
+catch!), when amount of VNC compressed data produced by zlib
+and sent to client exceeds 2Gb, integer overflow occurs because
+currently, we calculate amount of data produced at each step by
+comparing saved total_out with new total_out, and total_out is
+something which grows without bounds.  Compare it with previous
+avail_out instead of total_out, and leave total_out alone.
+
+There, there's no actual need to save previous_out value, since
+capacity-offset (which is how that value is calculated) stays
+the same so it can be recalculated again after call to deflate(),
+but whole thing becomes less readable this way.
+
+Reported-by: Roland Dreier <roland@purestorage.com>
+Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
+
+
+diff --git a/vnc.c b/vnc.c
+index 8566a4b..d09de3e 100644
+--- a/vnc.c
++++ b/vnc.c
+@@ -746,8 +746,8 @@ static int vnc_zlib_stop(VncState *vs, int stream_id)
+     zstream->avail_in = vs->zlib.offset;
+     zstream->next_out = vs->output.buffer + vs->output.offset;
+     zstream->avail_out = vs->output.capacity - vs->output.offset;
++    previous_out = zstream->avail_out;
+     zstream->data_type = Z_BINARY;
+-    previous_out = zstream->total_out;
+ 
+     // start encoding
+     if (deflate(zstream, Z_SYNC_FLUSH) != Z_OK) {
+@@ -756,7 +756,7 @@ static int vnc_zlib_stop(VncState *vs, int stream_id)
+     }
+ 
+     vs->output.offset = vs->output.capacity - zstream->avail_out;
+-    return zstream->total_out - previous_out;
++    return previous_out - zstream->avail_out;
+ }
+ 
+ static void send_framebuffer_update_zlib(VncState *vs, int x, int y, int w, int h)
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/qdev-dont-hw_error-in-qdev_init_nofail-bd6c9a61.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/qdev-dont-hw_error-in-qdev_init_nofail-bd6c9a61.diff
@@ -0,0 +1,36 @@
+Cherry-picked from upstream 0.14.  There we use error_report()
+routine which does not exist in 0.12, so change it to qemu_error().
+	-- mjt
+
+commit bd6c9a617d969752c9d3663f6ad29ae6d6d6c402
+Author: Markus Armbruster <armbru@redhat.com>
+Date:   Thu May 27 21:23:08 2010 +0200
+
+    qdev: Don't hw_error() in qdev_init_nofail()
+    
+    Some of the failures are internal errors, and hw_error() is okay then.
+    But the common way to fail is bad user input, e.g. -global
+    isa-fdc.driveA=foo where drive foo has an unsupported rerror value.
+    
+    exit(1) instead.
+    
+    Signed-off-by: Markus Armbruster <armbru@redhat.com>
+    Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+
+diff --git a/hw/qdev.c b/hw/qdev.c
+index 61f999c..00ceada 100644
+--- a/hw/qdev.c
++++ b/hw/qdev.c
+@@ -326,8 +326,10 @@ void qdev_init_nofail(DeviceState *dev)
+ {
+     DeviceInfo *info = dev->info;
+ 
+-    if (qdev_init(dev) < 0)
+-        hw_error("Initialization of device %s failed\n", info->name);
++    if (qdev_init(dev) < 0) {
++        qemu_error("Initialization of device %s failed\n", info->name);
++        exit(1);
++    }
+ }
+ 
+ /* Unlink device from bus and free the structure.  */
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/fix-crash-in-migration-32-bit-51b0c6065a.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/fix-crash-in-migration-32-bit-51b0c6065a.diff
@@ -0,0 +1,109 @@
+Cherry-picked from upstream and backported to 0.12 version,
+added first half of the bugfix for #625571 -- see that
+bugreport for full details.
+	-- mjt
+
+commit 51b0c6065aa6e47a47094d73e24be298a4a7f3a1
+Author: Michael Tokarev <mjt@tls.msk.ru>
+Date:   Tue Apr 26 20:13:49 2011 +0400
+
+    fix crash in migration, 32-bit userspace on 64-bit host
+    
+    This change fixes a long-standing immediate crash (memory corruption
+    and abort in glibc malloc code) in migration on 32bits.
+    
+    The bug is present since this commit:
+    
+      commit 692d9aca97b865b0f7903565274a52606910f129
+      Author: Bruce Rogers <brogers@novell.com>
+      Date:   Wed Sep 23 16:13:18 2009 -0600
+    
+        qemu-kvm: allocate correct size for dirty bitmap
+    
+        The dirty bitmap copied out to userspace is stored in a long array,
+        and gets copied out to userspace accordingly.  This patch accounts
+        for that correctly.  Currently I'm seeing kvm crashing due to writing
+        beyond the end of the alloc'd dirty bitmap memory, because the buffer
+        has the wrong size.
+    
+        Signed-off-by: Bruce Rogers
+        Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
+    
+     --- a/qemu-kvm.c
+     +++ b/qemu-kvm.c
+     @@ int kvm_get_dirty_pages_range(kvm_context_t kvm, unsigned long phys_addr,
+     -            buf = qemu_malloc((slots[i].len / 4096 + 7) / 8 + 2);
+     +            buf = qemu_malloc(BITMAP_SIZE(slots[i].len));
+                 r = kvm_get_map(kvm, KVM_GET_DIRTY_LOG, i, buf);
+    
+    BITMAP_SIZE is now open-coded in that function, like this:
+    
+     size = ALIGN(((mem->memory_size) >> TARGET_PAGE_BITS), HOST_LONG_BITS) / 8;
+    
+    The problem is that HOST_LONG_BITS in 32bit userspace is 32
+    but it's 64 in 64bit kernel.  So userspace aligns this to
+    32, and kernel to 64, but since no length is passed from
+    userspace to kernel on ioctl, kernel uses its size calculation
+    and copies 4 extra bytes to userspace, corrupting memory.
+    
+    Here's how it looks like during migrate execution:
+    
+    our=20, kern=24
+    our=4, kern=8
+    ...
+    our=4, kern=8
+    our=4064, kern=4064
+    our=512, kern=512
+    our=4, kern=8
+    our=20, kern=24
+    our=4, kern=8
+    ...
+    our=4, kern=8
+    our=4064, kern=4064
+    *** glibc detected *** ./x86_64-softmmu/qemu-system-x86_64: realloc(): invalid next size: 0x08f20528 ***
+    
+    (our is userspace size above, kern is the size as calculated
+    by the kernel).
+    
+    Fix this by always aligning to 64 in a hope that no platform will
+    have sizeof(long)>8 any time soon, and add a comment describing it
+    all.  It's a small price to pay for bad kernel design.
+    
+    Alternatively it's possible to fix that in the kernel by using
+    different size calculation depending on the current process.
+    But this becomes quite ugly.
+    
+    Special thanks goes to Stefan Hajnoczi for spotting the fundamental
+    cause of the issue, and to Alexander Graf for his support in #qemu.
+    
+    Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
+    CC: Bruce Rogers <brogers@novell.com>
+    Signed-off-by: Avi Kivity <avi@redhat.com>
+
+Index: debian/kvm-all.c
+===================================================================
+--- debian.orig/kvm-all.c	2011-05-04 17:59:08.350264734 +0400
++++ debian/kvm-all.c	2011-05-04 17:59:16.497669534 +0400
+@@ -312,7 +312,7 @@
+             break;
+         }
+ 
+-        size = ((mem->memory_size >> TARGET_PAGE_BITS) + 7) / 8;
++        size = BITMAP_SIZE(mem->memory_size);
+         if (!d.dirty_bitmap) {
+             d.dirty_bitmap = qemu_malloc(size);
+         } else if (size > allocated_size) {
+Index: debian/qemu-kvm.h
+===================================================================
+--- debian.orig/qemu-kvm.h	2011-05-04 17:59:13.256049613 +0400
++++ debian/qemu-kvm.h	2011-05-04 17:59:16.497669534 +0400
+@@ -1024,7 +1024,8 @@
+ 
+ #define ALIGN(x, y)  (((x)+(y)-1) & ~((y)-1))
+ #ifndef QEMU_KVM_NO_CPU
+-#define BITMAP_SIZE(m) (ALIGN(((m)>>TARGET_PAGE_BITS), HOST_LONG_BITS) / 8)
++/*mjt: see commit 51b0c6065aa6e47a47094d73e24be298a4a7f3a1 */
++#define BITMAP_SIZE(m) (ALIGN(((m)>>TARGET_PAGE_BITS), /*HOST_LONG_BITS*/ 64) / 8)
+ #endif
+ 
+ #ifdef CONFIG_KVM
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/sdl-do-not-disable-screensaver.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/sdl-do-not-disable-screensaver.diff
@@ -0,0 +1,14 @@
+diff --git a/sdl.c b/sdl.c
+index 7912c91..e6f28db 100644
+--- a/sdl.c
++++ b/sdl.c
+@@ -848,6 +848,9 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
+     if (no_frame)
+         gui_noframe = 1;
+ 
++    if (!getenv("SDL_VIDEO_ALLOW_SCREENSAVER"))
++	putenv("SDL_VIDEO_ALLOW_SCREENSAVER=1");
++
+     flags = SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE;
+     if (SDL_Init (flags)) {
+         fprintf(stderr, "Could not initialize SDL - exiting\n");
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/04_use_etc_kvm_kvm-ifup.patch
+++ qemu-kvm-0.12.5+dfsg/debian/patches/04_use_etc_kvm_kvm-ifup.patch
@@ -0,0 +1,29 @@
+Use an independent script to control the network at startup.
+Note that the defines are in two places, one ine in net.h
+and another in net/tap.h.  Remove the one in tap.h while
+we're at it, to stop confusion and compiler warning.
+
+--- a/net.h
++++ b/net.h
+@@ -167,8 +167,8 @@ void net_set_boot_mask(int boot_mask);
+ void net_host_device_add(Monitor *mon, const QDict *qdict);
+ void net_host_device_remove(Monitor *mon, const QDict *qdict);
+ 
+-#define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
+-#define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown"
++#define DEFAULT_NETWORK_SCRIPT "/etc/kvm/kvm-ifup"
++#define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/kvm/kvm-ifdown"
+ #ifdef __sun__
+ #define SMBD_COMMAND "/usr/sfw/sbin/smbd"
+ #else
+--- a/net/tap.h
++++ b/net/tap.h
+@@ -29,8 +29,6 @@
+ #include "qemu-common.h"
+ #include "qemu-option.h"
+ 
+-#define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
+-#define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown"
+ 
+ int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan);
+ 
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/issue-snd_pcm_start-when-capturing-audio.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/issue-snd_pcm_start-when-capturing-audio.diff
@@ -0,0 +1,85 @@
+commit 38cc9b607f85017b095793cab6c129bc9844f441
+Author: Jindrich Makovicka <makovick@gmail.com>
+Date:   Sun Oct 17 20:17:19 2010 +0200
+
+    issue snd_pcm_start() when capturing audio
+    
+    snd_pcm_start() starts the capture process and ensures that the events
+    are delivered to the poll handler. Without the call, capture can be started
+    only when there is simultaneous playback running.
+    
+    Signed-off-by: Jindrich Makovicka <makovick@gmail.com>
+    Signed-off-by: malc <av1474@comtv.ru>
+
+diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c
+index 3ca4078..0741203 100644
+--- a/audio/alsaaudio.c
++++ b/audio/alsaaudio.c
+@@ -843,11 +843,15 @@ static int alsa_init_out (HWVoiceOut *hw, struct audsettings *as)
+     return 0;
+ }
+ 
+-static int alsa_voice_ctl (snd_pcm_t *handle, const char *typ, int pause)
++#define VOICE_CTL_PAUSE 0
++#define VOICE_CTL_PREPARE 1
++#define VOICE_CTL_START 2
++
++static int alsa_voice_ctl (snd_pcm_t *handle, const char *typ, int ctl)
+ {
+     int err;
+ 
+-    if (pause) {
++    if (ctl == VOICE_CTL_PAUSE) {
+         err = snd_pcm_drop (handle);
+         if (err < 0) {
+             alsa_logerr (err, "Could not stop %s\n", typ);
+@@ -860,6 +864,13 @@ static int alsa_voice_ctl (snd_pcm_t *handle, const char *typ, int pause)
+             alsa_logerr (err, "Could not prepare handle for %s\n", typ);
+             return -1;
+         }
++        if (ctl == VOICE_CTL_START) {
++            err = snd_pcm_start(handle);
++            if (err < 0) {
++                alsa_logerr (err, "Could not start handle for %s\n", typ);
++                return -1;
++            }
++        }
+     }
+ 
+     return 0;
+@@ -884,7 +895,7 @@ static int alsa_ctl_out (HWVoiceOut *hw, int cmd, ...)
+                 poll_mode = 0;
+             }
+             hw->poll_mode = poll_mode;
+-            return alsa_voice_ctl (alsa->handle, "playback", 0);
++            return alsa_voice_ctl (alsa->handle, "playback", VOICE_CTL_PREPARE);
+         }
+ 
+     case VOICE_DISABLE:
+@@ -893,7 +904,7 @@ static int alsa_ctl_out (HWVoiceOut *hw, int cmd, ...)
+             hw->poll_mode = 0;
+             alsa_fini_poll (&alsa->pollhlp);
+         }
+-        return alsa_voice_ctl (alsa->handle, "playback", 1);
++        return alsa_voice_ctl (alsa->handle, "playback", VOICE_CTL_PAUSE);
+     }
+ 
+     return -1;
+@@ -1106,7 +1117,7 @@ static int alsa_ctl_in (HWVoiceIn *hw, int cmd, ...)
+             }
+             hw->poll_mode = poll_mode;
+ 
+-            return alsa_voice_ctl (alsa->handle, "capture", 0);
++            return alsa_voice_ctl (alsa->handle, "capture", VOICE_CTL_START);
+         }
+ 
+     case VOICE_DISABLE:
+@@ -1115,7 +1126,7 @@ static int alsa_ctl_in (HWVoiceIn *hw, int cmd, ...)
+             hw->poll_mode = 0;
+             alsa_fini_poll (&alsa->pollhlp);
+         }
+-        return alsa_voice_ctl (alsa->handle, "capture", 1);
++        return alsa_voice_ctl (alsa->handle, "capture", VOICE_CTL_PAUSE);
+     }
+ 
+     return -1;
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/upstream-stable02-fix-CMOS-info-for-drives-defined-with--device.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/upstream-stable02-fix-CMOS-info-for-drives-defined-with--device.diff
@@ -0,0 +1,210 @@
+commit 6394bd0e05441c363ebb73597c74c951378810e6
+Author: Markus Armbruster <armbru@redhat.com>
+Date:   Thu Jun 24 19:58:20 2010 +0200
+
+    pc: Fix CMOS info for drives defined with -device
+    
+    Drives defined with -drive if=ide get get created along with the IDE
+    controller, inside machine->init().  That's before cmos_init().
+    Drives defined with -device get created during generic device init.
+    That's after cmos_init().  Because of that, CMOS has no information on
+    them (type, geometry, translation).  Older versions of Windows such as
+    XP reportedly choke on that.
+    
+    Split off the part of CMOS initialization that needs to know about
+    -device devices, and turn it into a reset handler, so it runs after
+    device creation.
+    
+    Signed-off-by: Markus Armbruster <armbru@redhat.com>
+    Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+    (cherry picked from commit c0897e0cb94e83ec1098867b81870e4f51f225b9)
+
+diff --git a/hw/ide.h b/hw/ide.h
+index f0cb320..4ccb580 100644
+--- a/hw/ide.h
++++ b/hw/ide.h
+@@ -23,4 +23,6 @@ void mmio_ide_init (target_phys_addr_t membase, target_phys_addr_t membase2,
+                     qemu_irq irq, int shift,
+                     DriveInfo *hd0, DriveInfo *hd1);
+ 
++void ide_get_bs(BlockDriverState *bs[], BusState *qbus);
++
+ #endif /* HW_IDE_H */
+diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
+index 0b84a4f..a621d5e 100644
+--- a/hw/ide/qdev.c
++++ b/hw/ide/qdev.c
+@@ -90,6 +90,13 @@ IDEDevice *ide_create_drive(IDEBus *bus, int unit, DriveInfo *drive)
+     return DO_UPCAST(IDEDevice, qdev, dev);
+ }
+ 
++void ide_get_bs(BlockDriverState *bs[], BusState *qbus)
++{
++    IDEBus *bus = DO_UPCAST(IDEBus, qbus, qbus);
++    bs[0] = bus->master ? bus->master->dinfo->bdrv : NULL;
++    bs[1] = bus->slave  ? bus->slave->dinfo->bdrv  : NULL;
++}
++
+ /* --------------------------------- */
+ 
+ typedef struct IDEDrive {
+diff --git a/hw/pc.c b/hw/pc.c
+index 04ff78d..685b2ff 100644
+--- a/hw/pc.c
++++ b/hw/pc.c
+@@ -24,6 +24,7 @@
+ #include "hw.h"
+ #include "pc.h"
+ #include "fdc.h"
++#include "ide.h"
+ #include "pci.h"
+ #include "vmware_vga.h"
+ #include "usb-uhci.h"
+@@ -244,15 +245,66 @@ static int pc_boot_set(void *opaque, const char *boot_device)
+     return(0);
+ }
+ 
+-/* hd_table must contain 4 block drivers */
++typedef struct pc_cmos_init_late_arg {
++    BusState *idebus0, *idebus1;
++} pc_cmos_init_late_arg;
++
++static void pc_cmos_init_late(void *opaque)
++{
++    pc_cmos_init_late_arg *arg = opaque;
++    RTCState *s = rtc_state;
++    int val;
++    BlockDriverState *hd_table[4];
++    int i;
++
++    ide_get_bs(hd_table, arg->idebus0);
++    ide_get_bs(hd_table + 2, arg->idebus1);
++
++    rtc_set_memory(s, 0x12, (hd_table[0] ? 0xf0 : 0) | (hd_table[1] ? 0x0f : 0));
++    if (hd_table[0])
++        cmos_init_hd(0x19, 0x1b, hd_table[0]);
++    if (hd_table[1])
++        cmos_init_hd(0x1a, 0x24, hd_table[1]);
++
++    val = 0;
++    for (i = 0; i < 4; i++) {
++        if (hd_table[i]) {
++            int cylinders, heads, sectors, translation;
++            /* NOTE: bdrv_get_geometry_hint() returns the physical
++                geometry.  It is always such that: 1 <= sects <= 63, 1
++                <= heads <= 16, 1 <= cylinders <= 16383. The BIOS
++                geometry can be different if a translation is done. */
++            translation = bdrv_get_translation_hint(hd_table[i]);
++            if (translation == BIOS_ATA_TRANSLATION_AUTO) {
++                bdrv_get_geometry_hint(hd_table[i], &cylinders, &heads, &sectors);
++                if (cylinders <= 1024 && heads <= 16 && sectors <= 63) {
++                    /* No translation. */
++                    translation = 0;
++                } else {
++                    /* LBA translation. */
++                    translation = 1;
++                }
++            } else {
++                translation--;
++            }
++            val |= translation << (i * 2);
++        }
++    }
++    rtc_set_memory(s, 0x39, val);
++
++    qemu_unregister_reset(pc_cmos_init_late, opaque);
++}
++
+ static void cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
+-                      const char *boot_device, DriveInfo **hd_table)
++                      const char *boot_device,
++                      BusState *idebus0, BusState *idebus1)
+ {
+     RTCState *s = rtc_state;
+     int nbds, bds[3] = { 0, };
+     int val;
+     int fd0, fd1, nb;
+     int i;
++    static pc_cmos_init_late_arg arg;
+ 
+     /* various important CMOS locations needed by PC/Bochs bios */
+ 
+@@ -335,37 +387,9 @@ static void cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
+ 
+     /* hard drives */
+ 
+-    rtc_set_memory(s, 0x12, (hd_table[0] ? 0xf0 : 0) | (hd_table[1] ? 0x0f : 0));
+-    if (hd_table[0])
+-        cmos_init_hd(0x19, 0x1b, hd_table[0]->bdrv);
+-    if (hd_table[1])
+-        cmos_init_hd(0x1a, 0x24, hd_table[1]->bdrv);
+-
+-    val = 0;
+-    for (i = 0; i < 4; i++) {
+-        if (hd_table[i]) {
+-            int cylinders, heads, sectors, translation;
+-            /* NOTE: bdrv_get_geometry_hint() returns the physical
+-                geometry.  It is always such that: 1 <= sects <= 63, 1
+-                <= heads <= 16, 1 <= cylinders <= 16383. The BIOS
+-                geometry can be different if a translation is done. */
+-            translation = bdrv_get_translation_hint(hd_table[i]->bdrv);
+-            if (translation == BIOS_ATA_TRANSLATION_AUTO) {
+-                bdrv_get_geometry_hint(hd_table[i]->bdrv, &cylinders, &heads, &sectors);
+-                if (cylinders <= 1024 && heads <= 16 && sectors <= 63) {
+-                    /* No translation. */
+-                    translation = 0;
+-                } else {
+-                    /* LBA translation. */
+-                    translation = 1;
+-                }
+-            } else {
+-                translation--;
+-            }
+-            val |= translation << (i * 2);
+-        }
+-    }
+-    rtc_set_memory(s, 0x39, val);
++    arg.idebus0 = idebus0;
++    arg.idebus1 = idebus1;
++    qemu_register_reset(pc_cmos_init_late, &arg);
+ }
+ 
+ void ioport_set_a20(int enable)
+@@ -994,6 +1018,7 @@ static void pc_init1(ram_addr_t ram_size,
+     qemu_irq *i8259;
+     IsaIrqState *isa_irq_state;
+     DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
++    BusState *idebus[MAX_IDE_BUS];
+     DriveInfo *fd[MAX_FD];
+     void *fw_cfg;
+ 
+@@ -1187,11 +1212,16 @@ static void pc_init1(ram_addr_t ram_size,
+     }
+ 
+     if (pci_enabled) {
+-        pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
++        PCIDevice *dev;
++        dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1);
++        idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0");
++        idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1");
+     } else {
+         for(i = 0; i < MAX_IDE_BUS; i++) {
+-            isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
+-	                 hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
++            ISADevice *dev;
++            dev = isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
++                               hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]);
++            idebus[i] = qdev_get_child_bus(&dev->qdev, "ide.0");
+         }
+     }
+ 
+@@ -1206,7 +1236,8 @@ static void pc_init1(ram_addr_t ram_size,
+     }
+     floppy_controller = fdctrl_init_isa(fd);
+ 
+-    cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd);
++    cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device,
++              idebus[0], idebus[1]);
+ 
+     if (pci_enabled && usb_enabled) {
+         usb_uhci_piix3_init(pci_bus, piix3_devfn + 2);
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/573439-fail-to-set-hdd-serial-number.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/573439-fail-to-set-hdd-serial-number.diff
@@ -0,0 +1,71 @@
+Subject: Bug#573439: qemu-kvm: fail to set hdd serial number
+Reply-To: Kouichi ONO <kou1.ono@gmail.com>, 573439@bugs.debian.org
+Resent-From: Kouichi ONO <kou1.ono@gmail.com>
+Resent-To: debian-bugs-dist@lists.debian.org
+Resent-CC: kou1.ono@gmail.com, Jan =?UTF-8?Q?L=C3=BCbbe?= <jluebbe@debian.org>
+X-Loop: owner@bugs.debian.org
+Resent-Date: Thu, 11 Mar 2010 14:51:02 +0000
+Resent-Message-ID: <handler.573439.B.126831889524583@bugs.debian.org>
+X-Debian-PR-Message: report 573439
+X-Debian-PR-Package: qemu-kvm
+X-Debian-PR-Keywords:
+X-Debian-PR-Source: qemu-kvm
+Received: via spool by submit@bugs.debian.org id=B.126831889524583 (code B
+ ref -1); Thu, 11 Mar 2010 14:51:02 +0000
+Received: (at submit) by bugs.debian.org; 11 Mar 2010 14:48:15 +0000
+Received: from ey-out-2122.google.com ([74.125.78.25])	by rietz.debian.org
+ with esmtp (Exim 4.63)	(envelope-from <kou1.ono@gmail.com>)	id
+ 1NpjgN-0006Ny-5W	for submit@bugs.debian.org; Thu, 11 Mar 2010 14:48:15
+ +0000
+Received: by ey-out-2122.google.com with SMTP id 4so10035eyf.49        for
+ <submit@bugs.debian.org>; Thu, 11 Mar 2010 06:48:11 -0800 (PST)
+Received: by 10.102.12.27 with SMTP id 27mr577807mul.68.1268318890283; Thu,
+ 11 Mar 2010 06:48:10 -0800 (PST)
+Received: from localhost (x107236.dynamic.ppp.asahi-net.or.jp
+ [122.249.107.236])        by mx.google.com with ESMTPS id
+ n10sm85598mue.42.2010.03.11.06.48.07        (version=SSLv3 cipher=RC4-MD5);
+ Thu, 11 Mar 2010 06:48:09 -0800 (PST)
+Date: Thu, 11 Mar 2010 23:42:00 +0900 (JST)
+Message-ID: <20100311.234200.145758949990685830.kou1.ono@gmail.com>
+From: Kouichi ONO <kou1.ono@gmail.com>
+To: Debian Bug Tracking System <submit@bugs.debian.org>
+X-Mailer: Mew version 7.0.50 on Emacs 23.1.93 / Mule 6.0 (HANACHIRUSATO)
+MIME-Version: 1.0
+Content-Type: Text/Plain; charset=us-ascii
+Content-Transfer-Encoding: 7bit
+Delivered-To: submit@bugs.debian.org
+Resent-Date: Thu, 11 Mar 2010 14:51:05 +0000
+Delivered-To: qemu-kvm@packages.qa.debian.org
+Precedence: list
+X-Loop: qemu-kvm@packages.qa.debian.org
+X-Debian: PTS
+X-Debian-Package: qemu-kvm
+X-PTS-Package: qemu-kvm
+X-PTS-Keyword: bts
+List-Unsubscribe: <mailto:pts@qa.debian.org?body=unsubscribe+qemu-kvm>
+Resent-Sender: Debian QA <qa@master.debian.org>
+
+Package: qemu-kvm
+Version: 0.12.3+dfsg-3
+Severity: normal
+
+Hello,
+
+On version 0.12.3, -drive serial=XXX option does not work.
+Below patch fixes it. 'serial' is pointer, not array.
+
+
+--- qemu-kvm-0.12.3+dfsg/vl.c	2010-02-26 11:34:00.000000000 +0900
++++ qemu-kvm-0.12.3+dfsg.old/vl.c	2010-03-11 02:26:00.134217787 +0900
+@@ -2397,7 +2397,7 @@
+     dinfo->on_write_error = on_write_error;
+     dinfo->opts = opts;
+     if (serial)
+-        strncpy(dinfo->serial, serial, sizeof(serial));
++        strncpy(dinfo->serial, serial, sizeof(dinfo->serial));
+     QTAILQ_INSERT_TAIL(&drives, dinfo, next);
+     if (is_extboot) {
+         extboot_drive = dinfo;
+
+Best Regards,
+Kouichi ONO
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/hotplug-2-piix-tag-as-not-hotpluggable-0965f12da6.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/hotplug-2-piix-tag-as-not-hotpluggable-0965f12da6.diff
@@ -0,0 +1,71 @@
+Trivial backport from upstream (file name change, refreshed offsets)
+	-- mjt
+
+commit 0965f12da61cbfe62252d21a8e6fa309753760e8
+Author: Gerd Hoffmann <kraxel@redhat.com>
+Date:   Thu Jan 6 15:14:38 2011 +0100
+
+    piix: tag as not hotpluggable.
+    
+    This patch tags all pci devices which belong to the piix3/4 chipsets as
+    not hotpluggable (Host bridge, ISA bridge, IDE controller, ACPI bridge).
+    
+    Acked-by: Aurelien Jarno <aurelien@aurel32.net>
+    Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+    Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+
+--- debian.orig/hw/acpi.c	2011-05-21 15:42:37.030310762 +0400
++++ debian/hw/acpi.c	2011-05-21 16:00:52.903435908 +0400
+@@ -583,6 +583,8 @@ static PCIDeviceInfo piix4_pm_info = {
+     .qdev.desc          = "PM",
+     .qdev.size          = sizeof(PIIX4PMState),
+     .qdev.vmsd          = &vmstate_acpi,
++    .qdev.no_user       = 1,
++    .no_hotplug         = 1,
+     .init               = piix4_pm_initfn,
+     .config_write       = pm_write_config,
+     .qdev.props         = (Property[]) {
+--- debian.orig/hw/ide/piix.c	2011-05-21 10:38:07.000000000 +0400
++++ debian/hw/ide/piix.c	2011-05-21 16:00:52.903435908 +0400
+@@ -183,11 +183,13 @@ static PCIDeviceInfo piix_ide_info[] = {
+         .qdev.name    = "piix3-ide",
+         .qdev.size    = sizeof(PCIIDEState),
+         .qdev.no_user = 1,
++        .no_hotplug   = 1,
+         .init         = pci_piix3_ide_initfn,
+     },{
+         .qdev.name    = "piix4-ide",
+         .qdev.size    = sizeof(PCIIDEState),
+         .qdev.no_user = 1,
++        .no_hotplug   = 1,
+         .init         = pci_piix4_ide_initfn,
+     },{
+         /* end of list */
+--- debian.orig/hw/piix4.c	2011-04-26 08:53:39.000000000 +0400
++++ debian/hw/piix4.c	2011-05-21 16:00:52.903435908 +0400
+@@ -115,6 +115,7 @@ static PCIDeviceInfo piix4_info[] = {
+         .qdev.desc    = "ISA bridge",
+         .qdev.size    = sizeof(PCIDevice),
+         .qdev.no_user = 1,
++        .no_hotplug   = 1,
+         .init         = piix4_initfn,
+     },{
+         /* end of list */
+--- debian.orig/hw/piix_pci.c	2011-04-26 08:53:39.000000000 +0400
++++ debian/hw/piix_pci.c	2011-05-21 16:00:52.906770908 +0400
+@@ -347,6 +347,7 @@ static PCIDeviceInfo i440fx_info[] = {
+         .qdev.size    = sizeof(PCII440FXState),
+         .qdev.vmsd    = &vmstate_i440fx,
+         .qdev.no_user = 1,
++        .no_hotplug   = 1,
+         .init         = i440fx_initfn,
+         .config_write = i440fx_write_config,
+     },{
+@@ -355,6 +356,7 @@ static PCIDeviceInfo i440fx_info[] = {
+         .qdev.size    = sizeof(PIIX3State),
+         .qdev.vmsd    = &vmstate_piix3,
+         .qdev.no_user = 1,
++        .no_hotplug   = 1,
+         .init         = piix3_initfn,
+     },{
+         /* end of list */
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/stash-away-SCM_RIGHTS-fd-until-a-getfd-command-arrives-e53f27b9d9.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/stash-away-SCM_RIGHTS-fd-until-a-getfd-command-arrives-e53f27b9d9.diff
@@ -0,0 +1,59 @@
+Refreshed for 0.12:
+
+commit e53f27b9d9df73461308618151fa6e6392aebd85
+Author: Paolo Bonzini <pbonzini@redhat.com>
+Date:   Fri Apr 16 17:25:23 2010 +0200
+
+    stash away SCM_RIGHTS fd until a getfd command arrives
+    
+    If there is already a fd in s->msgfd before recvmsg it is
+    closed by parts that this patch does not touch.  So, only
+    one descriptor can be "leaked" by attaching it to a command
+    other than getfd.
+    
+    Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+    Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
+
+--- a/qemu-char.c
++++ b/qemu-char.c
+@@ -1954,8 +1954,9 @@ static void tcp_chr_process_IAC_bytes(Ch
+ static int tcp_get_msgfd(CharDriverState *chr)
+ {
+     TCPCharDriver *s = chr->opaque;
+-
+-    return s->msgfd;
++    int fd = s->msgfd;
++    s->msgfd = -1;
++    return fd;
+ }
+ 
+ #ifndef _WIN32
+@@ -2043,10 +2044,6 @@ static void tcp_chr_read(void *opaque)
+             tcp_chr_process_IAC_bytes(chr, s, buf, &size);
+         if (size > 0)
+             qemu_chr_read(chr, buf, size);
+-        if (s->msgfd != -1) {
+-            close(s->msgfd);
+-            s->msgfd = -1;
+-        }
+     }
+ }
+ 
+--- a/monitor.c
++++ b/monitor.c
+@@ -2294,15 +2294,6 @@ static void do_getfd(Monitor *mon, const
+         return;
+     }
+ 
+-    fd = dup(fd);
+-    if (fd == -1) {
+-        if (errno == EMFILE)
+-            qemu_error_new(QERR_TOO_MANY_FILES);
+-        else
+-            qemu_error_new(QERR_UNDEFINED_ERROR);
+-        return;
+-    }
+-
+     QLIST_FOREACH(monfd, &mon->fds, next) {
+         if (strcmp(monfd->name, fdname) != 0) {
+             continue;
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/upstream-stable01-make-PIIX-and-ISA-IDE-init-functions-return-the-qdev.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/upstream-stable01-make-PIIX-and-ISA-IDE-init-functions-return-the-qdev.diff
@@ -0,0 +1,101 @@
+commit fa719811ac922ec40a34fe456623963f0312c0e1
+Author: Markus Armbruster <armbru@redhat.com>
+Date:   Thu Jun 24 19:59:29 2010 +0200
+
+    ide: Make PIIX and ISA IDE init functions return the qdev
+    
+    Signed-off-by: Markus Armbruster <armbru@redhat.com>
+    Signed-off-by: Kevin Wolf <kwolf@redhat.com>
+    (cherry picked from commit 57c888664b5eb7edbbce4be98cb1406aa0d85c2b)
+
+diff --git a/hw/ide.h b/hw/ide.h
+index 0e7d540..f0cb320 100644
+--- a/hw/ide.h
++++ b/hw/ide.h
+@@ -1,17 +1,18 @@
+ #ifndef HW_IDE_H
+ #define HW_IDE_H
+ 
+-#include "qdev.h"
++#include "isa.h"
++#include "pci.h"
+ 
+ /* ide-isa.c */
+-int isa_ide_init(int iobase, int iobase2, int isairq,
+-                 DriveInfo *hd0, DriveInfo *hd1);
++ISADevice *isa_ide_init(int iobase, int iobase2, int isairq,
++                        DriveInfo *hd0, DriveInfo *hd1);
+ 
+ /* ide-pci.c */
+ void pci_cmd646_ide_init(PCIBus *bus, DriveInfo **hd_table,
+                          int secondary_ide_enabled);
+-void pci_piix3_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn);
+-void pci_piix4_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn);
++PCIDevice *pci_piix3_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn);
++PCIDevice *pci_piix4_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn);
+ 
+ /* ide-macio.c */
+ int pmac_ide_init (DriveInfo **hd_table, qemu_irq irq,
+diff --git a/hw/ide/isa.c b/hw/ide/isa.c
+index dff7c79..95189d6 100644
+--- a/hw/ide/isa.c
++++ b/hw/ide/isa.c
+@@ -75,8 +75,8 @@ static int isa_ide_initfn(ISADevice *dev)
+     return 0;
+ };
+ 
+-int isa_ide_init(int iobase, int iobase2, int isairq,
+-                 DriveInfo *hd0, DriveInfo *hd1)
++ISADevice *isa_ide_init(int iobase, int iobase2, int isairq,
++                        DriveInfo *hd0, DriveInfo *hd1)
+ {
+     ISADevice *dev;
+     ISAIDEState *s;
+@@ -86,14 +86,14 @@ int isa_ide_init(int iobase, int iobase2, int isairq,
+     qdev_prop_set_uint32(&dev->qdev, "iobase2", iobase2);
+     qdev_prop_set_uint32(&dev->qdev, "irq",     isairq);
+     if (qdev_init(&dev->qdev) < 0)
+-        return -1;
++        return NULL;
+ 
+     s = DO_UPCAST(ISAIDEState, dev, dev);
+     if (hd0)
+         ide_create_drive(&s->bus, 0, hd0);
+     if (hd1)
+         ide_create_drive(&s->bus, 1, hd1);
+-    return 0;
++    return dev;
+ }
+ 
+ static ISADeviceInfo isa_ide_info = {
+diff --git a/hw/ide/piix.c b/hw/ide/piix.c
+index 2776ac3..eab346a 100644
+--- a/hw/ide/piix.c
++++ b/hw/ide/piix.c
+@@ -158,22 +158,24 @@ static int pci_piix4_ide_initfn(PCIDevice *dev)
+ 
+ /* hd_table must contain 4 block drivers */
+ /* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */
+-void pci_piix3_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn)
++PCIDevice *pci_piix3_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn)
+ {
+     PCIDevice *dev;
+ 
+     dev = pci_create_simple(bus, devfn, "piix3-ide");
+     pci_ide_create_devs(dev, hd_table);
++    return dev;
+ }
+ 
+ /* hd_table must contain 4 block drivers */
+ /* NOTE: for the PIIX4, the IRQs and IOports are hardcoded */
+-void pci_piix4_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn)
++PCIDevice *pci_piix4_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn)
+ {
+     PCIDevice *dev;
+ 
+     dev = pci_create_simple(bus, devfn, "piix4-ide");
+     pci_ide_create_devs(dev, hd_table);
++    return dev;
+ }
+ 
+ static PCIDeviceInfo piix_ide_info[] = {
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/virtio-fix-indirect-descriptor-buffer-overflow-CVE-2011-2212.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/virtio-fix-indirect-descriptor-buffer-overflow-CVE-2011-2212.diff
@@ -0,0 +1,43 @@
+Updated for 0.12.
+
+Date: Mon, 11 Jul 2011 16:55:42 +0300
+From: "Michael S. Tsirkin" <mst@redhat.com>
+To: qemu-devel@nongnu.org
+Message-ID: <20110711135542.GA23769@redhat.com>
+Cc: Anthony Liguori <aliguori@us.ibm.com>
+Subject: [Qemu-devel] [PATCH] virtio: fix indirect descriptor buffer overflow
+
+We were previously allowing arbitrarily-long indirect descriptors, which
+could lead to a buffer overflow in qemu-kvm process.
+
+CVE-2011-2212
+
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+---
+ hw/virtio.c |   11 ++++++++++-
+ 1 file changed, 10 insertions(+), 1 deletion(-)
+
+--- a/hw/virtio.c
++++ b/hw/virtio.c
+@@ -392,11 +392,20 @@ int virtqueue_pop(VirtQueue *vq, VirtQue
+         int is_write = 0;
+ 
+         if (vring_desc_flags(desc_pa, i) & VRING_DESC_F_WRITE) {
++            if (elem->in_num >= ARRAY_SIZE(elem->in_sg)) {
++                qemu_error("Too many write descriptors in indirect table\n");
++                exit(1);
++            }
+             elem->in_addr[elem->in_num] = vring_desc_addr(desc_pa, i);
+             sg = &elem->in_sg[elem->in_num++];
+             is_write = 1;
+-        } else
++        } else {
++            if (elem->out_num >= ARRAY_SIZE(elem->out_sg)) {
++                qemu_error("Too many read descriptors in indirect table\n");
++                exit(1);
++            }
+             sg = &elem->out_sg[elem->out_num++];
++        }
+ 
+         /* Grab the first descriptor, and check it's OK. */
+         sg->iov_len = vring_desc_len(desc_pa, i);
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/QEMUFileBuffered:-indicate-that-were-ready-when-the-underlying-file-is-ready.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/QEMUFileBuffered:-indicate-that-were-ready-when-the-underlying-file-is-ready.diff
@@ -0,0 +1,51 @@
+This patch is a modified version. The difference from upstream is the
+change of DPRINTF back to dprintf - it were in lowercase initially, but
+later were changed in qemu-kvm-0.13 to be in upper-case.  For 0.12 I
+changed it back to dprintf (in lowercase).
+
+This fixes Debian bug #597517 -- see http://bugs.debian.org/597517
+
+                                                          -- mjt
+
+commit 5e77aaa0d7d2f4ceaa4fcaf50f3a26d5150f34a6
+Author: Avi Kivity <avi@redhat.com>
+Date:   Wed Jul 7 19:44:22 2010 +0300
+
+    QEMUFileBuffered: indicate that we're ready when the underlying file is ready
+    
+    QEMUFileBuffered stops writing when the underlying QEMUFile is not ready,
+    and tells its producer so.  However, when the underlying QEMUFile becomes
+    ready, it neglects to pass that information along, resulting in stoppage
+    of all data until the next tick (a tenths of a second).
+    
+    Usually this doesn't matter, because most QEMUFiles used with QEMUFileBuffered
+    are almost always ready, but in the case of exec: migration this is not true,
+    due to the small pipe buffers used to connect to the target process.  The
+    result is very slow migration.
+    
+    Fix by detecting the readiness notification and propagating it.  The detection
+    is a little ugly since QEMUFile overloads put_buffer() to send it, but that's
+    the suject for a different patch.
+    
+    Signed-off-by: Avi Kivity <avi@redhat.com>
+    Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
+
+diff --git a/buffered_file.c b/buffered_file.c
+index 54dc6c2..a79264f 100644
+--- a/buffered_file.c
++++ b/buffered_file.c
+@@ -156,6 +156,14 @@ static int buffered_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, in
+         offset = size;
+     }
+ 
++    if (pos == 0 && size == 0) {
++        dprintf("file is ready\n");
++        if (s->bytes_xfer <= s->xfer_limit) {
++            dprintf("notifying client\n");
++            s->put_ready(s->opaque);
++        }
++    }
++
+     return offset;
+ }
+ 
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/seabios-ps2-fixes.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/seabios-ps2-fixes.diff
@@ -0,0 +1,171 @@
+This file contains two commits from seabios git tree
+that fixes some erratic mouse behavour (in particular,
+win95 can't detect mouse without this).  The patches
+are taken as is, but pathnames were changed to reflect
+location of seabios in qemu-kvm sources (roms/seabios).
+
+		-- mjt
+
+commit b9ed5e2ac699982f5cd446d68c8b48732d2d4875
+Author: Kevin O'Connor <kevin@koconnor.net>
+Date:   Sat Mar 13 19:59:24 2010 -0500
+
+    Handle variable length return of ps2 port GETID command.
+    
+    Sometimes GETID returns two bytes, and sometimes one byte.  Handle
+    that properly.
+    
+    This fixes a failure with an msdos mouse driver.
+
+diff --git a/src/ps2port.c b/src/ps2port.c
+index 71a1ba2..4becc2e 100644
+--- a/roms/seabios/src/ps2port.c
++++ b/roms/seabios/src/ps2port.c
+@@ -232,7 +232,7 @@ ps2_command(int aux, int command, u8 *param)
+     yield();
+ 
+     if (command == ATKBD_CMD_RESET_BAT) {
+-        // Reset is special wrt timeouts.
++        // Reset is special wrt timeouts and bytes received.
+ 
+         // Send command.
+         ret = ps2_sendbyte(aux, command, 1000);
+@@ -249,6 +249,29 @@ ps2_command(int aux, int command, u8 *param)
+             // Some devices only respond with one byte on reset.
+             ret = 0;
+         param[1] = ret;
++    } else if (command == ATKBD_CMD_GETID) {
++        // Getid is special wrt bytes received.
++
++        // Send command.
++        ret = ps2_sendbyte(aux, command, 200);
++        if (ret)
++            goto fail;
++
++        // Receive parameters.
++        ret = ps2_recvbyte(aux, 0, 500);
++        if (ret < 0)
++            goto fail;
++        param[0] = ret;
++        if (ret == 0xab || ret == 0xac || ret == 0x2b || ret == 0x5d
++            || ret == 0x60 || ret == 0x47) {
++            // These ids (keyboards) return two bytes.
++            ret = ps2_recvbyte(aux, 0, 500);
++            if (ret < 0)
++                goto fail;
++            param[1] = ret;
++        } else {
++            param[1] = 0;
++        }
+     } else {
+         // Send command.
+         ret = ps2_sendbyte(aux, command, 200);
+
+commit a5d8458fc0e6f5971931d2ffec99d02678af104a
+Author: Kevin O'Connor <kevin@koconnor.net>
+Date:   Sat Mar 13 20:06:34 2010 -0500
+
+    Revert "Unify ps2 port data processing."
+    
+    This reverts commit 84f7b801ba8c0806fac568e59e85af281c0df207.
+    
+    It's not possible to unify ps2 port irq processing because old DOS
+    apps could hook one or both of the kbd/mouse ps2 irqs.
+
+diff --git a/src/ps2port.c b/src/ps2port.c
+index 4becc2e..5954131 100644
+--- a/roms/seabios/src/ps2port.c
++++ b/roms/seabios/src/ps2port.c
+@@ -136,21 +136,6 @@ i8042_aux_write(u8 c)
+ #define PS2_RET_ACK             0xfa
+ #define PS2_RET_NAK             0xfe
+ 
+-static void
+-process_ps2byte(u8 status, u8 data)
+-{
+-    if (!MODE16) {
+-        // Don't pull in all of keyboard/mouse code into 32bit code -
+-        // just discard the data.
+-        dprintf(1, "Discarding ps2 data %x (status=%x)\n", data, status);
+-        return;
+-    }
+-    if (status & I8042_STR_AUXDATA)
+-        process_mouse(data);
+-    else
+-        process_key(data);
+-}
+-
+ static int
+ ps2_recvbyte(int aux, int needack, int timeout)
+ {
+@@ -172,8 +157,8 @@ ps2_recvbyte(int aux, int needack, int timeout)
+                 }
+             }
+ 
+-            // Data not part of this command.
+-            process_ps2byte(status, data);
++            // This data not for us - XXX - just discard it for now.
++            dprintf(1, "Discarding ps2 data %x (status=%x)\n", data, status);
+         }
+ 
+         if (check_time(end)) {
+@@ -331,19 +316,6 @@ aux_command(int command, u8 *param)
+  * IRQ handlers
+  ****************************************************************/
+ 
+-static void
+-process_ps2irq(void)
+-{
+-    u8 status = inb(PORT_PS2_STATUS);
+-    if (!(status & I8042_STR_OBF)) {
+-        dprintf(1, "ps2 irq but no data.\n");
+-        return;
+-    }
+-    u8 data = inb(PORT_PS2_DATA);
+-
+-    process_ps2byte(status, data);
+-}
+-
+ // INT74h : PS/2 mouse hardware interrupt
+ void VISIBLE16
+ handle_74(void)
+@@ -352,7 +324,18 @@ handle_74(void)
+         return;
+ 
+     debug_isr(DEBUG_ISR_74);
+-    process_ps2irq();
++
++    u8 v = inb(PORT_PS2_STATUS);
++    if ((v & (I8042_STR_OBF|I8042_STR_AUXDATA))
++        != (I8042_STR_OBF|I8042_STR_AUXDATA)) {
++        dprintf(1, "mouse irq but no mouse data.\n");
++        goto done;
++    }
++    v = inb(PORT_PS2_DATA);
++
++    process_mouse(v);
++
++done:
+     eoi_pic2();
+ }
+ 
+@@ -364,7 +347,18 @@ handle_09(void)
+         return;
+ 
+     debug_isr(DEBUG_ISR_09);
+-    process_ps2irq();
++
++    // read key from keyboard controller
++    u8 v = inb(PORT_PS2_STATUS);
++    if ((v & (I8042_STR_OBF|I8042_STR_AUXDATA)) != I8042_STR_OBF) {
++        dprintf(1, "keyboard irq but no keyboard data.\n");
++        goto done;
++    }
++    v = inb(PORT_PS2_DATA);
++
++    process_key(v);
++
++done:
+     eoi_pic1();
+ }
+ 
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/virtio-guard-against-negative-vq-notifies-CVE-2011-2512.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/virtio-guard-against-negative-vq-notifies-CVE-2011-2512.diff
@@ -0,0 +1,62 @@
+upstream commit 7157e2e23e89adcd436caeab31fdd6b47eded377
+Author: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
+Date:   Sun May 8 22:29:07 2011 +0100
+
+    virtio: guard against negative vq notifies
+    
+    The virtio_queue_notify() function checks that the virtqueue number is
+    less than the maximum number of virtqueues.  A signed comparison is used
+    but the virtqueue number could be negative if a buggy or malicious guest
+    is run.  This results in memory accesses outside of the virtqueue array.
+    
+    It is risky doing input validation in common code instead of at the
+    guest<->host boundary.  Note that virtio_queue_set_addr(),
+    virtio_queue_get_addr(), virtio_queue_get_num(), and many other virtio
+    functions do *not* validate the virtqueue number argument.
+    
+    Instead of fixing the comparison in virtio_queue_notify(), move the
+    comparison to the virtio bindings (just like VIRTIO_PCI_QUEUE_SEL) where
+    we have a uint32_t value and can avoid ever calling into common virtio
+    code if the virtqueue number is invalid.
+    
+    Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
+    Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+    Backported-to-0.12-by: Michael Tokarev <mjt@tls.msk.ru>
+
+--- a/hw/syborg_virtio.c
++++ b/hw/syborg_virtio.c
+@@ -145,7 +145,9 @@ static void syborg_virtio_writel(void *o
+             vdev->queue_sel = value;
+         break;
+     case SYBORG_VIRTIO_QUEUE_NOTIFY:
+-        virtio_queue_notify(vdev, value);
++        if (value < VIRTIO_PCI_QUEUE_MAX) {
++            virtio_queue_notify(vdev, value);
++        }
+         break;
+     case SYBORG_VIRTIO_STATUS:
+         vdev->status = value & 0xFF;
+--- a/hw/virtio-pci.c
++++ b/hw/virtio-pci.c
+@@ -197,7 +197,9 @@ static void virtio_ioport_write(void *op
+             vdev->queue_sel = val;
+         break;
+     case VIRTIO_PCI_QUEUE_NOTIFY:
+-        virtio_queue_notify(vdev, val);
++        if (val < VIRTIO_PCI_QUEUE_MAX) {
++            virtio_queue_notify(vdev, val);
++        }
+         break;
+     case VIRTIO_PCI_STATUS:
+         vdev->status = val & 0xFF;
+--- a/hw/virtio.c
++++ b/hw/virtio.c
+@@ -558,7 +558,7 @@ int virtio_queue_get_num(VirtIODevice *v
+ 
+ void virtio_queue_notify(VirtIODevice *vdev, int n)
+ {
+-    if (n < VIRTIO_PCI_QUEUE_MAX && vdev->vq[n].vring.desc) {
++    if (vdev->vq[n].vring.desc) {
+         vdev->vq[n].handle_output(vdev, &vdev->vq[n]);
+     }
+ }
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/revert-vnc-password-semantics-52c18be9e9-CVE-2011-0011.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/revert-vnc-password-semantics-52c18be9e9-CVE-2011-0011.diff
@@ -0,0 +1,18 @@
+This patch reverts upstream commit 52c18be9e99dabe295321153fda7fce9f76647ac
+which resulted in disabling all VNC authentication when resetting vnc password
+to empty string.  CVE-2011-0011
+
+--- a/vnc.c
++++ b/vnc.c
+@@ -2461,11 +2461,6 @@ int vnc_display_password(DisplayState *ds, const char *password)
+     if (password && password[0]) {
+         if (!(vs->password = qemu_strdup(password)))
+             return -1;
+-        if (vs->auth == VNC_AUTH_NONE) {
+-            vs->auth = VNC_AUTH_VNC;
+-        }
+-    } else {
+-        vs->auth = VNC_AUTH_NONE;
+     }
+ 
+     return 0;
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/give-useful-error-messages-when-tap-open-fails.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/give-useful-error-messages-when-tap-open-fails.diff
@@ -0,0 +1,51 @@
+From: Michael Tokarev <mjt@tls.msk.ru>
+To: qemu-devel@nongnu.org
+Subject: [PATCH] give some useful error messages when tap open fails
+Message-Id: <20100422092826.EF03612B5C@gandalf.tls.msk.ru>
+Date: Thu, 22 Apr 2010 13:28:26 +0400 (MSD)
+
+In net/tap-linux.c, when manipulation of /dev/net/tun fails, it prints
+(with fprintf) something like this:
+
+  warning: could not open /dev/net/tun: no virtual network emulation
+
+this has 2 issues:
+ 1) it is not a warning really, it's a fatal error (kvm exits after that),
+ 2) there's no indication as of what's actually wrong: printing errno there
+    is helpful.
+
+The patch below removes the "warning" prefix, uses %m (since it's linux,
+%m is available as format modifier), and changes fprintf() to qemu_error().
+Now it prints something like this instead:
+
+ could not configure /dev/net/tun: Device or resource busy
+
+(there are 2 messages like that in the same function)
+
+This fixes Debian bug #578154, see
+http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=578154
+
+Signed-Off-By: Michael Tokarev <mjt@tls.msk.ru>
+
+diff --git a/net/tap-linux.c b/net/tap-linux.c
+index 6af9e82..dbcbe6f 100644
+--- a/net/tap-linux.c
++++ b/net/tap-linux.c
+@@ -39,7 +39,7 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required
+ 
+     TFR(fd = open("/dev/net/tun", O_RDWR));
+     if (fd < 0) {
+-        fprintf(stderr, "warning: could not open /dev/net/tun: no virtual network emulation\n");
++        qemu_error("could not open /dev/net/tun: %m\n");
+         return -1;
+     }
+     memset(&ifr, 0, sizeof(ifr));
+@@ -70,7 +70,7 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required
+         pstrcpy(ifr.ifr_name, IFNAMSIZ, "tap%d");
+     ret = ioctl(fd, TUNSETIFF, (void *) &ifr);
+     if (ret != 0) {
+-        fprintf(stderr, "warning: could not configure /dev/net/tun: no virtual network emulation\n");
++        qemu_error("could not configure /dev/net/tun: %m\n");
+         close(fd);
+         return -1;
+     }
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/hotplug-0-acpi_piix4-qdevfy-e8ec0571e1.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/hotplug-0-acpi_piix4-qdevfy-e8ec0571e1.diff
@@ -0,0 +1,110 @@
+Backported upstream commit.  Quite some stuff changed
+in upstream since 0.12.  -- mjt
+
+commit e8ec0571e16115203f4d6cc7eb31f930167592f8
+Author: Isaku Yamahata <yamahata@valinux.co.jp>
+Date:   Fri May 14 16:29:18 2010 +0900
+
+    acpi_piix4: qdevfy.
+    
+    qdevfy acpi_piix4.
+    
+    Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
+    Acked-by: Gerd Hoffmann <kraxel@redhat.com>
+    Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
+
+--- debian.orig/hw/acpi.c	2011-05-21 14:18:02.000000000 +0400
++++ debian/hw/acpi.c	2011-05-21 15:42:37.030310762 +0400
+@@ -43,6 +43,7 @@ typedef struct PIIX4PMState {
+     QEMUTimer *tmr_timer;
+     int64_t tmr_overflow_time;
+     i2c_bus *smbus;
++    uint32_t smb_io_base;
+     uint8_t smb_stat;
+     uint8_t smb_ctl;
+     uint8_t smb_cmd;
+@@ -500,15 +501,11 @@ static void piix4_powerdown(void *opaque
+ #endif
+ }
+ 
+-i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
+-                       qemu_irq sci_irq)
++static int piix4_pm_initfn(PCIDevice *dev)
+ {
+-    PIIX4PMState *s;
++    PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev, dev);
+     uint8_t *pci_conf;
+ 
+-    s = (PIIX4PMState *)pci_register_device(bus,
+-                                         "PM", sizeof(PIIX4PMState),
+-                                         devfn, NULL, pm_write_config);
+     pm_state = s;
+     pci_conf = s->dev.config;
+     pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
+@@ -548,25 +545,59 @@ i2c_bus *piix4_pm_init(PCIBus *bus, int
+     pci_conf[0x67] = (serial_hds[0] != NULL ? 0x08 : 0) |
+ 	(serial_hds[1] != NULL ? 0x90 : 0);
+ 
+-    pci_conf[0x90] = smb_io_base | 1;
+-    pci_conf[0x91] = smb_io_base >> 8;
++    pci_conf[0x90] = s->smb_io_base | 1;
++    pci_conf[0x91] = s->smb_io_base >> 8;
+     pci_conf[0xd2] = 0x09;
+-    register_ioport_write(smb_io_base, 64, 1, smb_ioport_writeb, s);
+-    register_ioport_read(smb_io_base, 64, 1, smb_ioport_readb, s);
++    register_ioport_write(s->smb_io_base, 64, 1, smb_ioport_writeb, s);
++    register_ioport_read(s->smb_io_base, 64, 1, smb_ioport_readb, s);
+ 
+     s->tmr_timer = qemu_new_timer(vm_clock, pm_tmr_timer, s);
+ 
+     qemu_system_powerdown = *qemu_allocate_irqs(piix4_powerdown, s, 1);
+ 
+-    vmstate_register(0, &vmstate_acpi, s);
+-
+     s->smbus = i2c_init_bus(NULL, "i2c");
+-    s->irq = sci_irq;
+     qemu_register_reset(piix4_reset, s);
+ 
++    return 0;
++}
++
++i2c_bus *piix4_pm_init(PCIBus *bus, int devfn, uint32_t smb_io_base,
++                       qemu_irq sci_irq)
++{
++    PCIDevice *dev;
++    PIIX4PMState *s;
++
++    dev = pci_create(bus, devfn, "PIIX4_PM");
++    qdev_prop_set_uint32(&dev->qdev, "smb_io_base", smb_io_base);
++
++    s = DO_UPCAST(PIIX4PMState, dev, dev);
++    s->irq = sci_irq;
++
++    qdev_init_nofail(&dev->qdev);
++
+     return s->smbus;
+ }
+ 
++static PCIDeviceInfo piix4_pm_info = {
++    .qdev.name          = "PIIX4_PM",
++    .qdev.desc          = "PM",
++    .qdev.size          = sizeof(PIIX4PMState),
++    .qdev.vmsd          = &vmstate_acpi,
++    .init               = piix4_pm_initfn,
++    .config_write       = pm_write_config,
++    .qdev.props         = (Property[]) {
++        DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0),
++        DEFINE_PROP_END_OF_LIST(),
++    }
++};
++
++static void piix4_pm_register(void)
++{
++    pci_qdev_register(&piix4_pm_info);
++}
++
++device_init(piix4_pm_register);
++
+ #define GPE_BASE 0xafe0
+ #define PROC_BASE 0xaf00
+ #define PCI_BASE 0xae00
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/cirrus_vga:fix-division-by-0-for-color-expansion-rop-92d675d1c1.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/cirrus_vga:fix-division-by-0-for-color-expansion-rop-92d675d1c1.diff
@@ -0,0 +1,100 @@
+commit 92d675d1c1f23f3617e24b63c825074a1d1da44b
+Author: Aurelien Jarno <aurelien@aurel32.net>
+Date:   Tue Jan 4 21:58:24 2011 +0100
+
+    cirrus_vga: fix division by 0 for color expansion rop
+    
+    Commit d85d0d3883f5a567fa2969a0396e42e0a662b3fa introduces a regression
+    with Windows ME that leads to a division by 0 and a crash.
+    
+    It uses the color expansion rop with the source pitch set to 0. This is
+    something allowed, as the manual explicitely says "When the source of
+    color-expand data is display memory, the source pitch is ignored.".
+    
+    This patch fixes this regression by computing sx, sy and others
+    variables only if they are going to be used later, that is for a plain
+    copy ROP. It basically consists in moving code.
+    
+    Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
+
+diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
+index 4f5040c..199136c 100644
+--- a/hw/cirrus_vga.c
++++ b/hw/cirrus_vga.c
+@@ -675,43 +675,44 @@ static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
+ {
+     int sx, sy;
+     int dx, dy;
+-    int width, height;
+     int depth;
+     int notify = 0;
+ 
+-    depth = s->vga.get_bpp(&s->vga) / 8;
+-    s->vga.get_resolution(&s->vga, &width, &height);
+-
+-    /* extra x, y */
+-    sx = (src % ABS(s->cirrus_blt_srcpitch)) / depth;
+-    sy = (src / ABS(s->cirrus_blt_srcpitch));
+-    dx = (dst % ABS(s->cirrus_blt_dstpitch)) / depth;
+-    dy = (dst / ABS(s->cirrus_blt_dstpitch));
+-
+-    /* normalize width */
+-    w /= depth;
+-
+-    /* if we're doing a backward copy, we have to adjust
+-       our x/y to be the upper left corner (instead of the lower
+-       right corner) */
+-    if (s->cirrus_blt_dstpitch < 0) {
+-	sx -= (s->cirrus_blt_width / depth) - 1;
+-	dx -= (s->cirrus_blt_width / depth) - 1;
+-	sy -= s->cirrus_blt_height - 1;
+-	dy -= s->cirrus_blt_height - 1;
+-    }
++    /* make sure to only copy if it's a plain copy ROP */
++    if (*s->cirrus_rop == cirrus_bitblt_rop_fwd_src ||
++        *s->cirrus_rop == cirrus_bitblt_rop_bkwd_src) {
+ 
+-    /* are we in the visible portion of memory? */
+-    if (sx >= 0 && sy >= 0 && dx >= 0 && dy >= 0 &&
+-	(sx + w) <= width && (sy + h) <= height &&
+-	(dx + w) <= width && (dy + h) <= height) {
+-	notify = 1;
+-    }
++        int width, height;
++
++        depth = s->vga.get_bpp(&s->vga) / 8;
++        s->vga.get_resolution(&s->vga, &width, &height);
++
++        /* extra x, y */
++        sx = (src % ABS(s->cirrus_blt_srcpitch)) / depth;
++        sy = (src / ABS(s->cirrus_blt_srcpitch));
++        dx = (dst % ABS(s->cirrus_blt_dstpitch)) / depth;
++        dy = (dst / ABS(s->cirrus_blt_dstpitch));
+ 
+-    /* make to sure only copy if it's a plain copy ROP */
+-    if (*s->cirrus_rop != cirrus_bitblt_rop_fwd_src &&
+-	*s->cirrus_rop != cirrus_bitblt_rop_bkwd_src)
+-	notify = 0;
++        /* normalize width */
++        w /= depth;
++
++        /* if we're doing a backward copy, we have to adjust
++           our x/y to be the upper left corner (instead of the lower
++           right corner) */
++        if (s->cirrus_blt_dstpitch < 0) {
++            sx -= (s->cirrus_blt_width / depth) - 1;
++            dx -= (s->cirrus_blt_width / depth) - 1;
++            sy -= s->cirrus_blt_height - 1;
++            dy -= s->cirrus_blt_height - 1;
++        }
++
++        /* are we in the visible portion of memory? */
++        if (sx >= 0 && sy >= 0 && dx >= 0 && dy >= 0 &&
++            (sx + w) <= width && (sy + h) <= height &&
++            (dx + w) <= width && (dy + h) <= height) {
++            notify = 1;
++        }
++    }
+ 
+     /* we have to flush all pending changes so that the copy
+        is generated at the appropriate moment in time */
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/hotplug-3-vga-tag-as-not-hotplugable-be92bbf73d.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/hotplug-3-vga-tag-as-not-hotplugable-be92bbf73d.diff
@@ -0,0 +1,47 @@
+Refreshed line offsets from upstream patch.
+	-- mjt
+
+commit be92bbf73dfd7d8a4786dc5f6c71590f4fbc5a32
+Author: Gerd Hoffmann <kraxel@redhat.com>
+Date:   Thu Jan 6 15:14:39 2011 +0100
+
+    vga: tag as not hotplugable.
+    
+    This patch tags all vga cards as not hotpluggable.  The qemu
+    standard vga will never ever be hotpluggable.  For cirrus + vmware
+    it might be possible to get that work some day.  Todays we can't
+    handle that for a number of reasons though.
+    
+    Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+    Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+
+--- debian.orig/hw/cirrus_vga.c	2011-05-21 10:38:06.988265846 +0400
++++ debian/hw/cirrus_vga.c	2011-05-21 16:01:28.411180032 +0400
+@@ -3241,6 +3241,7 @@ static PCIDeviceInfo cirrus_vga_info = {
+     .qdev.desc    = "Cirrus CLGD 54xx VGA",
+     .qdev.size    = sizeof(PCICirrusVGAState),
+     .qdev.vmsd    = &vmstate_pci_cirrus_vga,
++    .no_hotplug   = 1,
+     .init         = pci_cirrus_vga_initfn,
+     .romfile      = VGABIOS_CIRRUS_FILENAME,
+     .config_write = pci_cirrus_write_config,
+--- debian.orig/hw/vga-pci.c	2011-04-26 08:53:39.000000000 +0400
++++ debian/hw/vga-pci.c	2011-05-21 16:01:28.411180032 +0400
+@@ -131,6 +131,7 @@ static PCIDeviceInfo vga_info = {
+     .qdev.name    = "VGA",
+     .qdev.size    = sizeof(PCIVGAState),
+     .qdev.vmsd    = &vmstate_vga_pci,
++    .no_hotplug   = 1,
+     .init         = pci_vga_initfn,
+     .config_write = pci_vga_write_config,
+     .qdev.props   = (Property[]) {
+--- debian.orig/hw/vmware_vga.c	2011-04-26 08:53:39.000000000 +0400
++++ debian/hw/vmware_vga.c	2011-05-21 16:01:28.411180032 +0400
+@@ -1243,6 +1243,7 @@ static PCIDeviceInfo vmsvga_info = {
+     .qdev.name    = "vmware-svga",
+     .qdev.size    = sizeof(struct pci_vmsvga_state_s),
+     .qdev.vmsd    = &vmstate_vmware_vga,
++    .no_hotplug   = 1,
+     .init         = pci_vmsvga_initfn,
+ };
+ 
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/02_use_usr_share_kvm_fixed.patch
+++ qemu-kvm-0.12.5+dfsg/debian/patches/02_use_usr_share_kvm_fixed.patch
@@ -0,0 +1,26 @@
+--- qemu-kvm-0.11.0/vl.c.orig	2009-08-30 13:10:59.000000000 +0400
++++ qemu-kvm-0.11.0/vl.c	2009-09-23 00:38:42.019021721 +0400
+@@ -4764,6 +4764,8 @@
+ 
+ #endif
+ 
++#ifdef no_find_datadir
++
+ #ifdef _WIN32
+ /* Look for support files in the same directory as the executable.  */
+ static char *find_datadir(const char *argv0)
+@@ -4857,6 +4859,14 @@
+ #undef BUILD_SUFFIX
+ #endif
+ 
++#else /* !no_find_datadir */
++
++/* for a packaged version we want to ensure data is found in a known place.
++ *  Can be specified on command line (-L option) */
++#define find_datadir(argv) "/usr/share/kvm"
++
++#endif /* no_find_datadir */
++
+ char *qemu_find_file(int type, const char *name)
+ {
+     int len;
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/isa-refine-irq-reservations.patch
+++ qemu-kvm-0.12.5+dfsg/debian/patches/isa-refine-irq-reservations.patch
@@ -0,0 +1,77 @@
+This patch is wrong.  Proper fix (for a general case) is to have
+interrupt multiplexor instead.  But for the problem case it were
+looked for it works just fine: the issue is about 3rd and 4th
+guest COM ports which are broken in 0.12+.  COM-port works again
+after applying this patch.
+
+  --- mjt
+
+From 7d5d53e8a23544ac6413487a8ecdd43537ade9f3 Mon Sep 17 00:00:00 2001
+From: Gerd Hoffmann <kraxel@redhat.com>
+Date: Fri, 11 Sep 2009 13:43:46 +0200
+Subject: [PATCH] isa: refine irq reservations
+
+There are a few cases where IRQ sharing on the ISA bus is used and
+possible.  In general only devices of the same kind can do that.
+A few use cases:
+
+  * serial lines 1+3 share irq 4
+  * serial lines 2+4 share irq 3
+  * parallel ports share irq 7
+  * ppc/prep: ide ports share irq 13
+
+This patch refines the irq reservation mechanism for the isa bus to
+handle those cases.  It keeps track of the driver which owns the IRQ in
+question and allows irq sharing for devices handled by the same driver.
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+---
+ hw/isa-bus.c |   16 +++++++++++++---
+ 1 files changed, 13 insertions(+), 3 deletions(-)
+
+diff --git a/hw/isa-bus.c b/hw/isa-bus.c
+index 4d489d2..bd2f69c 100644
+--- a/hw/isa-bus.c
++++ b/hw/isa-bus.c
+@@ -26,6 +26,7 @@ struct ISABus {
+     BusState qbus;
+     qemu_irq *irqs;
+     uint32_t assigned;
++    DeviceInfo *irq_owner[16];
+ };
+ static ISABus *isabus;
+ 
+@@ -71,7 +72,9 @@ qemu_irq isa_reserve_irq(int isairq)
+         exit(1);
+     }
+     if (isabus->assigned & (1 << isairq)) {
+-        fprintf(stderr, "isa irq %d already assigned\n", isairq);
++        DeviceInfo *owner = isabus->irq_owner[isairq];
++        fprintf(stderr, "isa irq %d already assigned (%s)\n",
++                isairq, owner ? owner->name : "unknown");
+         exit(1);
+     }
+     isabus->assigned |= (1 << isairq);
+@@ -82,10 +85,17 @@ void isa_init_irq(ISADevice *dev, qemu_irq *p, int isairq)
+ {
+     assert(dev->nirqs < ARRAY_SIZE(dev->isairq));
+     if (isabus->assigned & (1 << isairq)) {
+-        fprintf(stderr, "isa irq %d already assigned\n", isairq);
+-        exit(1);
++        DeviceInfo *owner = isabus->irq_owner[isairq];
++        if (owner == dev->qdev.info) {
++            /* irq sharing is ok in case the same driver handles both */;
++        } else {
++            fprintf(stderr, "isa irq %d already assigned (%s)\n",
++                    isairq, owner ? owner->name : "unknown");
++            exit(1);
++        }
+     }
+     isabus->assigned |= (1 << isairq);
++    isabus->irq_owner[isairq] = dev->qdev.info;
+     dev->isairq[dev->nirqs] = isairq;
+     *p = isabus->irqs[isairq];
+     dev->nirqs++;
+-- 
+1.6.6.1
+
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/CVE-2010-2784-fix-segfault-in-mmio-subpage-handling-code.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/CVE-2010-2784-fix-segfault-in-mmio-subpage-handling-code.diff
@@ -0,0 +1,34 @@
+cherry-picked from qemu git:
+
+commit 95c318f5e1f88d7e5bcc6deac17330fd4806a2d3
+Author: Gleb Natapov <gleb@redhat.com>
+Date:   Thu Jul 29 10:41:45 2010 +0300
+
+    Fix segfault in mmio subpage handling code.
+    
+    It is possible that subpage mmio is registered over existing memory
+    page. When this happens "memory" will have real memory address and not
+    index into io_mem array so next access to the page will generate
+    segfault. It is uncommon to have some part of a page to be accessed as
+    memory and some as mmio, but qemu shouldn't crash even when guest does
+    stupid things. So lets just pretend that the rest of the page is
+    unassigned if guest configure part of the memory page as mmio.
+    
+    Signed-off-by: Gleb Natapov <gleb@redhat.com>
+    Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
+
+fixes CVE-2010-2784.
+
+--- a/exec.c
++++ b/exec.c
+@@ -3013,7 +3013,9 @@
+     printf("%s: %p start %08x end %08x idx %08x eidx %08x mem %ld\n", __func__,
+            mmio, start, end, idx, eidx, memory);
+ #endif
+-    memory >>= IO_MEM_SHIFT;
++    if ((memory & ~TARGET_PAGE_MASK) == IO_MEM_RAM)
++        memory = IO_MEM_UNASSIGNED;    
++    memory = (memory >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
+     for (; idx <= eidx; idx++) {
+         for (i = 0; i < 4; i++) {
+             if (io_mem_read[memory][i]) {
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/seabios-0.12.3.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/seabios-0.12.3.diff
@@ -0,0 +1,29963 @@
+This is seabios source taken from qemu-0.12.3.tar.gz
+upstream tarball but somehow missed in qemu-kvm-0.12.3.tar.gz.
+
+Ideally there should be no bios sources embedded with qemu or
+qemu-kvm, but for now bios is too closely tied to the rest
+of the qemu-kvm system that making it a separate package is
+too high risk to get non-working/buggy combination.
+
+--- x/roms/seabios/COPYING	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/COPYING	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,674 @@
++                    GNU GENERAL PUBLIC LICENSE
++                       Version 3, 29 June 2007
++
++ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
++ Everyone is permitted to copy and distribute verbatim copies
++ of this license document, but changing it is not allowed.
++
++                            Preamble
++
++  The GNU General Public License is a free, copyleft license for
++software and other kinds of works.
++
++  The licenses for most software and other practical works are designed
++to take away your freedom to share and change the works.  By contrast,
++the GNU General Public License is intended to guarantee your freedom to
++share and change all versions of a program--to make sure it remains free
++software for all its users.  We, the Free Software Foundation, use the
++GNU General Public License for most of our software; it applies also to
++any other work released this way by its authors.  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
++them 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 prevent others from denying you
++these rights or asking you to surrender the rights.  Therefore, you have
++certain responsibilities if you distribute copies of the software, or if
++you modify it: responsibilities to respect the freedom of others.
++
++  For example, if you distribute copies of such a program, whether
++gratis or for a fee, you must pass on to the recipients the same
++freedoms that you received.  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.
++
++  Developers that use the GNU GPL protect your rights with two steps:
++(1) assert copyright on the software, and (2) offer you this License
++giving you legal permission to copy, distribute and/or modify it.
++
++  For the developers' and authors' protection, the GPL clearly explains
++that there is no warranty for this free software.  For both users' and
++authors' sake, the GPL requires that modified versions be marked as
++changed, so that their problems will not be attributed erroneously to
++authors of previous versions.
++
++  Some devices are designed to deny users access to install or run
++modified versions of the software inside them, although the manufacturer
++can do so.  This is fundamentally incompatible with the aim of
++protecting users' freedom to change the software.  The systematic
++pattern of such abuse occurs in the area of products for individuals to
++use, which is precisely where it is most unacceptable.  Therefore, we
++have designed this version of the GPL to prohibit the practice for those
++products.  If such problems arise substantially in other domains, we
++stand ready to extend this provision to those domains in future versions
++of the GPL, as needed to protect the freedom of users.
++
++  Finally, every program is threatened constantly by software patents.
++States should not allow patents to restrict development and use of
++software on general-purpose computers, but in those that do, we wish to
++avoid the special danger that patents applied to a free program could
++make it effectively proprietary.  To prevent this, the GPL assures that
++patents cannot be used to render the program non-free.
++
++  The precise terms and conditions for copying, distribution and
++modification follow.
++
++                       TERMS AND CONDITIONS
++
++  0. Definitions.
++
++  "This License" refers to version 3 of the GNU General Public License.
++
++  "Copyright" also means copyright-like laws that apply to other kinds of
++works, such as semiconductor masks.
++
++  "The Program" refers to any copyrightable work licensed under this
++License.  Each licensee is addressed as "you".  "Licensees" and
++"recipients" may be individuals or organizations.
++
++  To "modify" a work means to copy from or adapt all or part of the work
++in a fashion requiring copyright permission, other than the making of an
++exact copy.  The resulting work is called a "modified version" of the
++earlier work or a work "based on" the earlier work.
++
++  A "covered work" means either the unmodified Program or a work based
++on the Program.
++
++  To "propagate" a work means to do anything with it that, without
++permission, would make you directly or secondarily liable for
++infringement under applicable copyright law, except executing it on a
++computer or modifying a private copy.  Propagation includes copying,
++distribution (with or without modification), making available to the
++public, and in some countries other activities as well.
++
++  To "convey" a work means any kind of propagation that enables other
++parties to make or receive copies.  Mere interaction with a user through
++a computer network, with no transfer of a copy, is not conveying.
++
++  An interactive user interface displays "Appropriate Legal Notices"
++to the extent that it includes a convenient and prominently visible
++feature that (1) displays an appropriate copyright notice, and (2)
++tells the user that there is no warranty for the work (except to the
++extent that warranties are provided), that licensees may convey the
++work under this License, and how to view a copy of this License.  If
++the interface presents a list of user commands or options, such as a
++menu, a prominent item in the list meets this criterion.
++
++  1. Source Code.
++
++  The "source code" for a work means the preferred form of the work
++for making modifications to it.  "Object code" means any non-source
++form of a work.
++
++  A "Standard Interface" means an interface that either is an official
++standard defined by a recognized standards body, or, in the case of
++interfaces specified for a particular programming language, one that
++is widely used among developers working in that language.
++
++  The "System Libraries" of an executable work include anything, other
++than the work as a whole, that (a) is included in the normal form of
++packaging a Major Component, but which is not part of that Major
++Component, and (b) serves only to enable use of the work with that
++Major Component, or to implement a Standard Interface for which an
++implementation is available to the public in source code form.  A
++"Major Component", in this context, means a major essential component
++(kernel, window system, and so on) of the specific operating system
++(if any) on which the executable work runs, or a compiler used to
++produce the work, or an object code interpreter used to run it.
++
++  The "Corresponding Source" for a work in object code form means all
++the source code needed to generate, install, and (for an executable
++work) run the object code and to modify the work, including scripts to
++control those activities.  However, it does not include the work's
++System Libraries, or general-purpose tools or generally available free
++programs which are used unmodified in performing those activities but
++which are not part of the work.  For example, Corresponding Source
++includes interface definition files associated with source files for
++the work, and the source code for shared libraries and dynamically
++linked subprograms that the work is specifically designed to require,
++such as by intimate data communication or control flow between those
++subprograms and other parts of the work.
++
++  The Corresponding Source need not include anything that users
++can regenerate automatically from other parts of the Corresponding
++Source.
++
++  The Corresponding Source for a work in source code form is that
++same work.
++
++  2. Basic Permissions.
++
++  All rights granted under this License are granted for the term of
++copyright on the Program, and are irrevocable provided the stated
++conditions are met.  This License explicitly affirms your unlimited
++permission to run the unmodified Program.  The output from running a
++covered work is covered by this License only if the output, given its
++content, constitutes a covered work.  This License acknowledges your
++rights of fair use or other equivalent, as provided by copyright law.
++
++  You may make, run and propagate covered works that you do not
++convey, without conditions so long as your license otherwise remains
++in force.  You may convey covered works to others for the sole purpose
++of having them make modifications exclusively for you, or provide you
++with facilities for running those works, provided that you comply with
++the terms of this License in conveying all material for which you do
++not control copyright.  Those thus making or running the covered works
++for you must do so exclusively on your behalf, under your direction
++and control, on terms that prohibit them from making any copies of
++your copyrighted material outside their relationship with you.
++
++  Conveying under any other circumstances is permitted solely under
++the conditions stated below.  Sublicensing is not allowed; section 10
++makes it unnecessary.
++
++  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
++
++  No covered work shall be deemed part of an effective technological
++measure under any applicable law fulfilling obligations under article
++11 of the WIPO copyright treaty adopted on 20 December 1996, or
++similar laws prohibiting or restricting circumvention of such
++measures.
++
++  When you convey a covered work, you waive any legal power to forbid
++circumvention of technological measures to the extent such circumvention
++is effected by exercising rights under this License with respect to
++the covered work, and you disclaim any intention to limit operation or
++modification of the work as a means of enforcing, against the work's
++users, your or third parties' legal rights to forbid circumvention of
++technological measures.
++
++  4. Conveying Verbatim Copies.
++
++  You may convey 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;
++keep intact all notices stating that this License and any
++non-permissive terms added in accord with section 7 apply to the code;
++keep intact all notices of the absence of any warranty; and give all
++recipients a copy of this License along with the Program.
++
++  You may charge any price or no price for each copy that you convey,
++and you may offer support or warranty protection for a fee.
++
++  5. Conveying Modified Source Versions.
++
++  You may convey a work based on the Program, or the modifications to
++produce it from the Program, in the form of source code under the
++terms of section 4, provided that you also meet all of these conditions:
++
++    a) The work must carry prominent notices stating that you modified
++    it, and giving a relevant date.
++
++    b) The work must carry prominent notices stating that it is
++    released under this License and any conditions added under section
++    7.  This requirement modifies the requirement in section 4 to
++    "keep intact all notices".
++
++    c) You must license the entire work, as a whole, under this
++    License to anyone who comes into possession of a copy.  This
++    License will therefore apply, along with any applicable section 7
++    additional terms, to the whole of the work, and all its parts,
++    regardless of how they are packaged.  This License gives no
++    permission to license the work in any other way, but it does not
++    invalidate such permission if you have separately received it.
++
++    d) If the work has interactive user interfaces, each must display
++    Appropriate Legal Notices; however, if the Program has interactive
++    interfaces that do not display Appropriate Legal Notices, your
++    work need not make them do so.
++
++  A compilation of a covered work with other separate and independent
++works, which are not by their nature extensions of the covered work,
++and which are not combined with it such as to form a larger program,
++in or on a volume of a storage or distribution medium, is called an
++"aggregate" if the compilation and its resulting copyright are not
++used to limit the access or legal rights of the compilation's users
++beyond what the individual works permit.  Inclusion of a covered work
++in an aggregate does not cause this License to apply to the other
++parts of the aggregate.
++
++  6. Conveying Non-Source Forms.
++
++  You may convey a covered work in object code form under the terms
++of sections 4 and 5, provided that you also convey the
++machine-readable Corresponding Source under the terms of this License,
++in one of these ways:
++
++    a) Convey the object code in, or embodied in, a physical product
++    (including a physical distribution medium), accompanied by the
++    Corresponding Source fixed on a durable physical medium
++    customarily used for software interchange.
++
++    b) Convey the object code in, or embodied in, a physical product
++    (including a physical distribution medium), accompanied by a
++    written offer, valid for at least three years and valid for as
++    long as you offer spare parts or customer support for that product
++    model, to give anyone who possesses the object code either (1) a
++    copy of the Corresponding Source for all the software in the
++    product that is covered by this License, on a durable physical
++    medium customarily used for software interchange, for a price no
++    more than your reasonable cost of physically performing this
++    conveying of source, or (2) access to copy the
++    Corresponding Source from a network server at no charge.
++
++    c) Convey individual copies of the object code with a copy of the
++    written offer to provide the Corresponding Source.  This
++    alternative is allowed only occasionally and noncommercially, and
++    only if you received the object code with such an offer, in accord
++    with subsection 6b.
++
++    d) Convey the object code by offering access from a designated
++    place (gratis or for a charge), and offer equivalent access to the
++    Corresponding Source in the same way through the same place at no
++    further charge.  You need not require recipients to copy the
++    Corresponding Source along with the object code.  If the place to
++    copy the object code is a network server, the Corresponding Source
++    may be on a different server (operated by you or a third party)
++    that supports equivalent copying facilities, provided you maintain
++    clear directions next to the object code saying where to find the
++    Corresponding Source.  Regardless of what server hosts the
++    Corresponding Source, you remain obligated to ensure that it is
++    available for as long as needed to satisfy these requirements.
++
++    e) Convey the object code using peer-to-peer transmission, provided
++    you inform other peers where the object code and Corresponding
++    Source of the work are being offered to the general public at no
++    charge under subsection 6d.
++
++  A separable portion of the object code, whose source code is excluded
++from the Corresponding Source as a System Library, need not be
++included in conveying the object code work.
++
++  A "User Product" is either (1) a "consumer product", which means any
++tangible personal property which is normally used for personal, family,
++or household purposes, or (2) anything designed or sold for incorporation
++into a dwelling.  In determining whether a product is a consumer product,
++doubtful cases shall be resolved in favor of coverage.  For a particular
++product received by a particular user, "normally used" refers to a
++typical or common use of that class of product, regardless of the status
++of the particular user or of the way in which the particular user
++actually uses, or expects or is expected to use, the product.  A product
++is a consumer product regardless of whether the product has substantial
++commercial, industrial or non-consumer uses, unless such uses represent
++the only significant mode of use of the product.
++
++  "Installation Information" for a User Product means any methods,
++procedures, authorization keys, or other information required to install
++and execute modified versions of a covered work in that User Product from
++a modified version of its Corresponding Source.  The information must
++suffice to ensure that the continued functioning of the modified object
++code is in no case prevented or interfered with solely because
++modification has been made.
++
++  If you convey an object code work under this section in, or with, or
++specifically for use in, a User Product, and the conveying occurs as
++part of a transaction in which the right of possession and use of the
++User Product is transferred to the recipient in perpetuity or for a
++fixed term (regardless of how the transaction is characterized), the
++Corresponding Source conveyed under this section must be accompanied
++by the Installation Information.  But this requirement does not apply
++if neither you nor any third party retains the ability to install
++modified object code on the User Product (for example, the work has
++been installed in ROM).
++
++  The requirement to provide Installation Information does not include a
++requirement to continue to provide support service, warranty, or updates
++for a work that has been modified or installed by the recipient, or for
++the User Product in which it has been modified or installed.  Access to a
++network may be denied when the modification itself materially and
++adversely affects the operation of the network or violates the rules and
++protocols for communication across the network.
++
++  Corresponding Source conveyed, and Installation Information provided,
++in accord with this section must be in a format that is publicly
++documented (and with an implementation available to the public in
++source code form), and must require no special password or key for
++unpacking, reading or copying.
++
++  7. Additional Terms.
++
++  "Additional permissions" are terms that supplement the terms of this
++License by making exceptions from one or more of its conditions.
++Additional permissions that are applicable to the entire Program shall
++be treated as though they were included in this License, to the extent
++that they are valid under applicable law.  If additional permissions
++apply only to part of the Program, that part may be used separately
++under those permissions, but the entire Program remains governed by
++this License without regard to the additional permissions.
++
++  When you convey a copy of a covered work, you may at your option
++remove any additional permissions from that copy, or from any part of
++it.  (Additional permissions may be written to require their own
++removal in certain cases when you modify the work.)  You may place
++additional permissions on material, added by you to a covered work,
++for which you have or can give appropriate copyright permission.
++
++  Notwithstanding any other provision of this License, for material you
++add to a covered work, you may (if authorized by the copyright holders of
++that material) supplement the terms of this License with terms:
++
++    a) Disclaiming warranty or limiting liability differently from the
++    terms of sections 15 and 16 of this License; or
++
++    b) Requiring preservation of specified reasonable legal notices or
++    author attributions in that material or in the Appropriate Legal
++    Notices displayed by works containing it; or
++
++    c) Prohibiting misrepresentation of the origin of that material, or
++    requiring that modified versions of such material be marked in
++    reasonable ways as different from the original version; or
++
++    d) Limiting the use for publicity purposes of names of licensors or
++    authors of the material; or
++
++    e) Declining to grant rights under trademark law for use of some
++    trade names, trademarks, or service marks; or
++
++    f) Requiring indemnification of licensors and authors of that
++    material by anyone who conveys the material (or modified versions of
++    it) with contractual assumptions of liability to the recipient, for
++    any liability that these contractual assumptions directly impose on
++    those licensors and authors.
++
++  All other non-permissive additional terms are considered "further
++restrictions" within the meaning of section 10.  If the Program as you
++received it, or any part of it, contains a notice stating that it is
++governed by this License along with a term that is a further
++restriction, you may remove that term.  If a license document contains
++a further restriction but permits relicensing or conveying under this
++License, you may add to a covered work material governed by the terms
++of that license document, provided that the further restriction does
++not survive such relicensing or conveying.
++
++  If you add terms to a covered work in accord with this section, you
++must place, in the relevant source files, a statement of the
++additional terms that apply to those files, or a notice indicating
++where to find the applicable terms.
++
++  Additional terms, permissive or non-permissive, may be stated in the
++form of a separately written license, or stated as exceptions;
++the above requirements apply either way.
++
++  8. Termination.
++
++  You may not propagate or modify a covered work except as expressly
++provided under this License.  Any attempt otherwise to propagate or
++modify it is void, and will automatically terminate your rights under
++this License (including any patent licenses granted under the third
++paragraph of section 11).
++
++  However, if you cease all violation of this License, then your
++license from a particular copyright holder is reinstated (a)
++provisionally, unless and until the copyright holder explicitly and
++finally terminates your license, and (b) permanently, if the copyright
++holder fails to notify you of the violation by some reasonable means
++prior to 60 days after the cessation.
++
++  Moreover, your license from a particular copyright holder is
++reinstated permanently if the copyright holder notifies you of the
++violation by some reasonable means, this is the first time you have
++received notice of violation of this License (for any work) from that
++copyright holder, and you cure the violation prior to 30 days after
++your receipt of the notice.
++
++  Termination of your rights under this section does not terminate the
++licenses of parties who have received copies or rights from you under
++this License.  If your rights have been terminated and not permanently
++reinstated, you do not qualify to receive new licenses for the same
++material under section 10.
++
++  9. Acceptance Not Required for Having Copies.
++
++  You are not required to accept this License in order to receive or
++run a copy of the Program.  Ancillary propagation of a covered work
++occurring solely as a consequence of using peer-to-peer transmission
++to receive a copy likewise does not require acceptance.  However,
++nothing other than this License grants you permission to propagate or
++modify any covered work.  These actions infringe copyright if you do
++not accept this License.  Therefore, by modifying or propagating a
++covered work, you indicate your acceptance of this License to do so.
++
++  10. Automatic Licensing of Downstream Recipients.
++
++  Each time you convey a covered work, the recipient automatically
++receives a license from the original licensors, to run, modify and
++propagate that work, subject to this License.  You are not responsible
++for enforcing compliance by third parties with this License.
++
++  An "entity transaction" is a transaction transferring control of an
++organization, or substantially all assets of one, or subdividing an
++organization, or merging organizations.  If propagation of a covered
++work results from an entity transaction, each party to that
++transaction who receives a copy of the work also receives whatever
++licenses to the work the party's predecessor in interest had or could
++give under the previous paragraph, plus a right to possession of the
++Corresponding Source of the work from the predecessor in interest, if
++the predecessor has it or can get it with reasonable efforts.
++
++  You may not impose any further restrictions on the exercise of the
++rights granted or affirmed under this License.  For example, you may
++not impose a license fee, royalty, or other charge for exercise of
++rights granted under this License, and you may not initiate litigation
++(including a cross-claim or counterclaim in a lawsuit) alleging that
++any patent claim is infringed by making, using, selling, offering for
++sale, or importing the Program or any portion of it.
++
++  11. Patents.
++
++  A "contributor" is a copyright holder who authorizes use under this
++License of the Program or a work on which the Program is based.  The
++work thus licensed is called the contributor's "contributor version".
++
++  A contributor's "essential patent claims" are all patent claims
++owned or controlled by the contributor, whether already acquired or
++hereafter acquired, that would be infringed by some manner, permitted
++by this License, of making, using, or selling its contributor version,
++but do not include claims that would be infringed only as a
++consequence of further modification of the contributor version.  For
++purposes of this definition, "control" includes the right to grant
++patent sublicenses in a manner consistent with the requirements of
++this License.
++
++  Each contributor grants you a non-exclusive, worldwide, royalty-free
++patent license under the contributor's essential patent claims, to
++make, use, sell, offer for sale, import and otherwise run, modify and
++propagate the contents of its contributor version.
++
++  In the following three paragraphs, a "patent license" is any express
++agreement or commitment, however denominated, not to enforce a patent
++(such as an express permission to practice a patent or covenant not to
++sue for patent infringement).  To "grant" such a patent license to a
++party means to make such an agreement or commitment not to enforce a
++patent against the party.
++
++  If you convey a covered work, knowingly relying on a patent license,
++and the Corresponding Source of the work is not available for anyone
++to copy, free of charge and under the terms of this License, through a
++publicly available network server or other readily accessible means,
++then you must either (1) cause the Corresponding Source to be so
++available, or (2) arrange to deprive yourself of the benefit of the
++patent license for this particular work, or (3) arrange, in a manner
++consistent with the requirements of this License, to extend the patent
++license to downstream recipients.  "Knowingly relying" means you have
++actual knowledge that, but for the patent license, your conveying the
++covered work in a country, or your recipient's use of the covered work
++in a country, would infringe one or more identifiable patents in that
++country that you have reason to believe are valid.
++
++  If, pursuant to or in connection with a single transaction or
++arrangement, you convey, or propagate by procuring conveyance of, a
++covered work, and grant a patent license to some of the parties
++receiving the covered work authorizing them to use, propagate, modify
++or convey a specific copy of the covered work, then the patent license
++you grant is automatically extended to all recipients of the covered
++work and works based on it.
++
++  A patent license is "discriminatory" if it does not include within
++the scope of its coverage, prohibits the exercise of, or is
++conditioned on the non-exercise of one or more of the rights that are
++specifically granted under this License.  You may not convey a covered
++work if you are a party to an arrangement with a third party that is
++in the business of distributing software, under which you make payment
++to the third party based on the extent of your activity of conveying
++the work, and under which the third party grants, to any of the
++parties who would receive the covered work from you, a discriminatory
++patent license (a) in connection with copies of the covered work
++conveyed by you (or copies made from those copies), or (b) primarily
++for and in connection with specific products or compilations that
++contain the covered work, unless you entered into that arrangement,
++or that patent license was granted, prior to 28 March 2007.
++
++  Nothing in this License shall be construed as excluding or limiting
++any implied license or other defenses to infringement that may
++otherwise be available to you under applicable patent law.
++
++  12. No Surrender of Others' Freedom.
++
++  If 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 convey a
++covered work so as to satisfy simultaneously your obligations under this
++License and any other pertinent obligations, then as a consequence you may
++not convey it at all.  For example, if you agree to terms that obligate you
++to collect a royalty for further conveying from those to whom you convey
++the Program, the only way you could satisfy both those terms and this
++License would be to refrain entirely from conveying the Program.
++
++  13. Use with the GNU Affero General Public License.
++
++  Notwithstanding any other provision of this License, you have
++permission to link or combine any covered work with a work licensed
++under version 3 of the GNU Affero General Public License into a single
++combined work, and to convey the resulting work.  The terms of this
++License will continue to apply to the part which is the covered work,
++but the special requirements of the GNU Affero General Public License,
++section 13, concerning interaction through a network will apply to the
++combination as such.
++
++  14. Revised Versions of this License.
++
++  The Free Software Foundation may publish revised and/or new versions of
++the GNU 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 that a certain numbered version of the GNU General
++Public License "or any later version" applies to it, you have the
++option of following the terms and conditions either of that numbered
++version or of any later version published by the Free Software
++Foundation.  If the Program does not specify a version number of the
++GNU General Public License, you may choose any version ever published
++by the Free Software Foundation.
++
++  If the Program specifies that a proxy can decide which future
++versions of the GNU General Public License can be used, that proxy's
++public statement of acceptance of a version permanently authorizes you
++to choose that version for the Program.
++
++  Later license versions may give you additional or different
++permissions.  However, no additional obligations are imposed on any
++author or copyright holder as a result of your choosing to follow a
++later version.
++
++  15. Disclaimer of Warranty.
++
++  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.
++
++  16. Limitation of Liability.
++
++  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
++WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
++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.
++
++  17. Interpretation of Sections 15 and 16.
++
++  If the disclaimer of warranty and limitation of liability provided
++above cannot be given local legal effect according to their terms,
++reviewing courts shall apply local law that most closely approximates
++an absolute waiver of all civil liability in connection with the
++Program, unless a warranty or assumption of liability accompanies a
++copy of the Program in return for a fee.
++
++                     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
++state 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 3 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, see <http://www.gnu.org/licenses/>.
++
++Also add information on how to contact you by electronic and paper mail.
++
++  If the program does terminal interaction, make it output a short
++notice like this when it starts in an interactive mode:
++
++    <program>  Copyright (C) <year>  <name of author>
++    This program 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, your program's commands
++might be different; for a GUI interface, you would use an "about box".
++
++  You should also get your employer (if you work as a programmer) or school,
++if any, to sign a "copyright disclaimer" for the program, if necessary.
++For more information on this, and how to apply and follow the GNU GPL, see
++<http://www.gnu.org/licenses/>.
++
++  The GNU 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 Lesser General
++Public License instead of this License.  But first, please read
++<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+--- x/roms/seabios/COPYING.LESSER	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/COPYING.LESSER	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,165 @@
++		   GNU LESSER GENERAL PUBLIC LICENSE
++                       Version 3, 29 June 2007
++
++ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
++ Everyone is permitted to copy and distribute verbatim copies
++ of this license document, but changing it is not allowed.
++
++
++  This version of the GNU Lesser General Public License incorporates
++the terms and conditions of version 3 of the GNU General Public
++License, supplemented by the additional permissions listed below.
++
++  0. Additional Definitions. 
++
++  As used herein, "this License" refers to version 3 of the GNU Lesser
++General Public License, and the "GNU GPL" refers to version 3 of the GNU
++General Public License.
++
++  "The Library" refers to a covered work governed by this License,
++other than an Application or a Combined Work as defined below.
++
++  An "Application" is any work that makes use of an interface provided
++by the Library, but which is not otherwise based on the Library.
++Defining a subclass of a class defined by the Library is deemed a mode
++of using an interface provided by the Library.
++
++  A "Combined Work" is a work produced by combining or linking an
++Application with the Library.  The particular version of the Library
++with which the Combined Work was made is also called the "Linked
++Version".
++
++  The "Minimal Corresponding Source" for a Combined Work means the
++Corresponding Source for the Combined Work, excluding any source code
++for portions of the Combined Work that, considered in isolation, are
++based on the Application, and not on the Linked Version.
++
++  The "Corresponding Application Code" for a Combined Work means the
++object code and/or source code for the Application, including any data
++and utility programs needed for reproducing the Combined Work from the
++Application, but excluding the System Libraries of the Combined Work.
++
++  1. Exception to Section 3 of the GNU GPL.
++
++  You may convey a covered work under sections 3 and 4 of this License
++without being bound by section 3 of the GNU GPL.
++
++  2. Conveying Modified Versions.
++
++  If you modify a copy of the Library, and, in your modifications, a
++facility refers to a function or data to be supplied by an Application
++that uses the facility (other than as an argument passed when the
++facility is invoked), then you may convey a copy of the modified
++version:
++
++   a) under this License, provided that you make a good faith effort to
++   ensure that, in the event an Application does not supply the
++   function or data, the facility still operates, and performs
++   whatever part of its purpose remains meaningful, or
++
++   b) under the GNU GPL, with none of the additional permissions of
++   this License applicable to that copy.
++
++  3. Object Code Incorporating Material from Library Header Files.
++
++  The object code form of an Application may incorporate material from
++a header file that is part of the Library.  You may convey such object
++code under terms of your choice, provided that, if the incorporated
++material is not limited to numerical parameters, data structure
++layouts and accessors, or small macros, inline functions and templates
++(ten or fewer lines in length), you do both of the following:
++
++   a) Give prominent notice with each copy of the object code that the
++   Library is used in it and that the Library and its use are
++   covered by this License.
++
++   b) Accompany the object code with a copy of the GNU GPL and this license
++   document.
++
++  4. Combined Works.
++
++  You may convey a Combined Work under terms of your choice that,
++taken together, effectively do not restrict modification of the
++portions of the Library contained in the Combined Work and reverse
++engineering for debugging such modifications, if you also do each of
++the following:
++
++   a) Give prominent notice with each copy of the Combined Work that
++   the Library is used in it and that the Library and its use are
++   covered by this License.
++
++   b) Accompany the Combined Work with a copy of the GNU GPL and this license
++   document.
++
++   c) For a Combined Work that displays copyright notices during
++   execution, include the copyright notice for the Library among
++   these notices, as well as a reference directing the user to the
++   copies of the GNU GPL and this license document.
++
++   d) Do one of the following:
++
++       0) Convey the Minimal Corresponding Source under the terms of this
++       License, and the Corresponding Application Code in a form
++       suitable for, and under terms that permit, the user to
++       recombine or relink the Application with a modified version of
++       the Linked Version to produce a modified Combined Work, in the
++       manner specified by section 6 of the GNU GPL for conveying
++       Corresponding Source.
++
++       1) Use a suitable shared library mechanism for linking with the
++       Library.  A suitable mechanism is one that (a) uses at run time
++       a copy of the Library already present on the user's computer
++       system, and (b) will operate properly with a modified version
++       of the Library that is interface-compatible with the Linked
++       Version. 
++
++   e) Provide Installation Information, but only if you would otherwise
++   be required to provide such information under section 6 of the
++   GNU GPL, and only to the extent that such information is
++   necessary to install and execute a modified version of the
++   Combined Work produced by recombining or relinking the
++   Application with a modified version of the Linked Version. (If
++   you use option 4d0, the Installation Information must accompany
++   the Minimal Corresponding Source and Corresponding Application
++   Code. If you use option 4d1, you must provide the Installation
++   Information in the manner specified by section 6 of the GNU GPL
++   for conveying Corresponding Source.)
++
++  5. Combined Libraries.
++
++  You may place library facilities that are a work based on the
++Library side by side in a single library together with other library
++facilities that are not Applications and are not covered by this
++License, and convey such a combined library under terms of your
++choice, if you do both of the following:
++
++   a) Accompany the combined library with a copy of the same work based
++   on the Library, uncombined with any other library facilities,
++   conveyed under the terms of this License.
++
++   b) Give prominent notice with the combined library that part of it
++   is a work based on the Library, and explaining where to find the
++   accompanying uncombined form of the same work.
++
++  6. Revised Versions of the GNU Lesser General Public License.
++
++  The Free Software Foundation may publish revised and/or new versions
++of the GNU Lesser General Public License from time to time. Such new
++versions will be similar in spirit to the present version, but may
++differ in detail to address new problems or concerns.
++
++  Each version is given a distinguishing version number. If the
++Library as you received it specifies that a certain numbered version
++of the GNU Lesser General Public License "or any later version"
++applies to it, you have the option of following the terms and
++conditions either of that published version or of any later version
++published by the Free Software Foundation. If the Library as you
++received it does not specify a version number of the GNU Lesser
++General Public License, you may choose any version of the GNU Lesser
++General Public License ever published by the Free Software Foundation.
++
++  If the Library as you received it specifies that a proxy can decide
++whether future versions of the GNU Lesser General Public License shall
++apply, that proxy's public statement of acceptance of any version is
++permanent authorization for you to choose that version for the
++Library.
+--- x/roms/seabios/Makefile	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/Makefile	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,206 @@
++# SeaBIOS build system
++#
++# Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
++#
++# This file may be distributed under the terms of the GNU LGPLv3 license.
++
++# Program version
++VERSION=0.5.1-$(shell date +"%Y%m%d_%H%M%S")-$(shell hostname)
++
++# Output directory
++OUT=out/
++
++# Source files
++SRCBOTH=misc.c pmm.c stacks.c output.c util.c block.c floppy.c ata.c mouse.c \
++        kbd.c pci.c serial.c clock.c pic.c cdrom.c ps2port.c smp.c resume.c \
++        pnpbios.c pirtable.c vgahooks.c ramdisk.c pcibios.c \
++        usb.c usb-uhci.c usb-ohci.c usb-hid.c paravirt.c
++SRC16=$(SRCBOTH) system.c disk.c apm.c font.c
++SRC32FLAT=$(SRCBOTH) post.c shadow.c memmap.c coreboot.c boot.c \
++      acpi.c smm.c mptable.c smbios.c pciinit.c optionroms.c mtrr.c \
++      lzmadecode.c
++SRC32SEG=util.c output.c pci.c pcibios.c apm.c
++
++cc-option = $(shell if test -z "`$(1) $(2) -S -o /dev/null -xc \
++              /dev/null 2>&1`"; then echo "$(2)"; else echo "$(3)"; fi ;)
++
++# Default compiler flags
++COMMONCFLAGS = -Os -MD -Wall -Wno-strict-aliasing -Wold-style-definition \
++               $(call cc-option,$(CC),-Wtype-limits,) \
++               -m32 -march=i386 -mregparm=3 -mpreferred-stack-boundary=2 \
++               -mrtd -minline-all-stringops \
++               -freg-struct-return -ffreestanding -fomit-frame-pointer \
++               -fno-delete-null-pointer-checks \
++               -ffunction-sections -fdata-sections -fno-common
++COMMONCFLAGS += $(call cc-option,$(CC),-nopie,)
++COMMONCFLAGS += $(call cc-option,$(CC),-fno-stack-protector,)
++COMMONCFLAGS += $(call cc-option,$(CC),-fno-stack-protector-all,)
++
++CFLAGS32FLAT = $(COMMONCFLAGS) -g -DMODE16=0 -DMODESEGMENT=0
++CFLAGSSEG = $(COMMONCFLAGS) -DMODESEGMENT=1 -fno-defer-pop \
++            $(call cc-option,$(CC),-fno-jump-tables,-DMANUAL_NO_JUMP_TABLE) \
++            $(call cc-option,$(CC),-fno-tree-switch-conversion,)
++CFLAGS32SEG = $(CFLAGSSEG) -DMODE16=0 -g
++CFLAGS16INC = $(CFLAGSSEG) -DMODE16=1 \
++              $(call cc-option,$(CC),--param large-stack-frame=4,)
++CFLAGS16 = $(CFLAGS16INC) -g
++
++all: $(OUT) $(OUT)bios.bin
++
++# Run with "make V=1" to see the actual compile commands
++ifdef V
++Q=
++else
++Q=@
++endif
++
++OBJCOPY=objcopy
++OBJDUMP=objdump
++STRIP=strip
++
++.PHONY : all FORCE
++
++vpath %.c src vgasrc
++vpath %.S src vgasrc
++
++################ Build rules
++
++# Verify the gcc configuration and test if -fwhole-program works.
++TESTGCC:=$(shell CC=$(CC) tools/test-gcc.sh)
++ifeq "$(TESTGCC)" "-1"
++$(error "Please upgrade GCC")
++endif
++
++ifndef COMPSTRAT
++COMPSTRAT=$(TESTGCC)
++endif
++
++# Do a whole file compile - three methods are supported.
++ifeq "$(COMPSTRAT)" "1"
++# First method - use -fwhole-program without -combine.
++define whole-compile
++@echo "  Compiling whole program $3"
++$(Q)printf '$(foreach i,$2,#include "../$i"\n)' > $3.tmp.c
++$(Q)$(CC) $1 -fwhole-program -DWHOLE_PROGRAM -c $3.tmp.c -o $3
++endef
++else
++ifeq "$(COMPSTRAT)" "2"
++# Second menthod - don't use -fwhole-program at all.
++define whole-compile
++@echo "  Compiling whole program $3"
++$(Q)printf '$(foreach i,$2,#include "../$i"\n)' > $3.tmp.c
++$(Q)$(CC) $1 -c $3.tmp.c -o $3
++endef
++else
++# Third (and preferred) method - use -fwhole-program with -combine
++define whole-compile
++@echo "  Compiling whole program $3"
++$(Q)$(CC) $1 -fwhole-program -DWHOLE_PROGRAM -combine -c $2 -o $3
++endef
++endif
++endif
++
++
++$(OUT)%.s: %.c
++	@echo "  Compiling to assembler $@"
++	$(Q)$(CC) $(CFLAGS16INC) -S -c $< -o $@
++
++$(OUT)%.lds: %.lds.S
++	@echo "  Precompiling $@"
++	$(Q)$(CPP) -P -D__ASSEMBLY__ $< -o $@
++
++$(OUT)asm-offsets.h: $(OUT)asm-offsets.s
++	@echo "  Generating offset file $@"
++	$(Q)./tools/gen-offsets.sh $< $@
++
++
++$(OUT)ccode.16.s: ; $(call whole-compile, $(CFLAGS16) -S, $(addprefix src/, $(SRC16)),$@)
++
++$(OUT)code32seg.o: ; $(call whole-compile, $(CFLAGS32SEG), $(addprefix src/, $(SRC32SEG)),$@)
++
++$(OUT)ccode32flat.o: ; $(call whole-compile, $(CFLAGS32FLAT), $(addprefix src/, $(SRC32FLAT)),$@)
++
++$(OUT)code16.o: romlayout.S $(OUT)ccode.16.s $(OUT)asm-offsets.h
++	@echo "  Compiling (16bit) $@"
++	$(Q)$(CC) $(CFLAGS16INC) -c -D__ASSEMBLY__ $< -o $@
++
++$(OUT)romlayout16.lds $(OUT)romlayout32seg.lds $(OUT)romlayout32flat.lds $(OUT)code32flat.o: $(OUT)ccode32flat.o $(OUT)code32seg.o $(OUT)code16.o tools/layoutrom.py
++	@echo "  Building ld scripts (version \"$(VERSION)\")"
++	$(Q)echo 'const char VERSION[] = "$(VERSION)";' > $(OUT)version.c
++	$(Q)$(CC) $(CFLAGS32FLAT) -c $(OUT)version.c -o $(OUT)version.o
++	$(Q)$(LD) -melf_i386 -r $(OUT)ccode32flat.o $(OUT)version.o -o $(OUT)code32flat.o
++	$(Q)$(OBJDUMP) -thr $(OUT)code32flat.o > $(OUT)code32flat.o.objdump
++	$(Q)$(OBJDUMP) -thr $(OUT)code32seg.o > $(OUT)code32seg.o.objdump
++	$(Q)$(OBJDUMP) -thr $(OUT)code16.o > $(OUT)code16.o.objdump
++	$(Q)./tools/layoutrom.py $(OUT)code16.o.objdump $(OUT)code32seg.o.objdump $(OUT)code32flat.o.objdump $(OUT)romlayout16.lds $(OUT)romlayout32seg.lds $(OUT)romlayout32flat.lds
++
++
++$(OUT)rom16.o: $(OUT)code16.o $(OUT)rom32flat.o $(OUT)romlayout16.lds
++	@echo "  Linking (no relocs) $@"
++	$(Q)$(LD) -r -T $(OUT)romlayout16.lds $< -o $@
++
++$(OUT)rom32seg.o: $(OUT)code32seg.o $(OUT)romlayout32seg.lds
++	@echo "  Linking (no relocs) $@"
++	$(Q)$(LD) -r -T $(OUT)romlayout32seg.lds $< -o $@
++
++$(OUT)rom32flat.o: $(OUT)code32flat.o $(OUT)romlayout32flat.lds
++	@echo "  Linking (no relocs) $@"
++	$(Q)$(LD) -r -T $(OUT)romlayout32flat.lds $< -o $@
++
++$(OUT)rom.o: $(OUT)rom16.o $(OUT)rom32seg.o $(OUT)rom32flat.o $(OUT)rombios16.lds  $(OUT)rombios32seg.lds $(OUT)rombios.lds
++	@echo "  Linking $@"
++	$(Q)$(LD) -T $(OUT)rombios16.lds $(OUT)rom16.o -R $(OUT)rom32seg.o -R $(OUT)rom32flat.o -o $(OUT)rom16.reloc.o
++	$(Q)$(STRIP) $(OUT)rom16.reloc.o -o $(OUT)rom16.final.o
++	$(Q)$(OBJCOPY) --adjust-vma 0xf0000 $(OUT)rom16.o $(OUT)rom16.moved.o
++	$(Q)$(LD) -T $(OUT)rombios32seg.lds $(OUT)rom32seg.o -R $(OUT)rom16.o -R $(OUT)rom32flat.o -o $(OUT)rom32seg.reloc.o
++	$(Q)$(STRIP) $(OUT)rom32seg.reloc.o -o $(OUT)rom32seg.final.o
++	$(Q)$(OBJCOPY) --adjust-vma 0xf0000 $(OUT)rom32seg.o $(OUT)rom32seg.moved.o
++	$(Q)$(LD) -T $(OUT)rombios.lds $(OUT)rom16.final.o $(OUT)rom32seg.final.o $(OUT)rom32flat.o -R $(OUT)rom16.moved.o -R $(OUT)rom32seg.moved.o -o $@
++
++$(OUT)bios.bin.elf $(OUT)bios.bin: $(OUT)rom.o tools/checkrom.py
++	@echo "  Prepping $@"
++	$(Q)$(OBJDUMP) -thr $< > $<.objdump
++	$(Q)$(OBJCOPY) -O binary $< $(OUT)bios.bin.raw
++	$(Q)./tools/checkrom.py $<.objdump $(OUT)bios.bin.raw $(OUT)bios.bin
++	$(Q)$(STRIP) -R .comment $< -o $(OUT)bios.bin.elf
++
++
++################ VGA build rules
++
++# VGA src files
++SRCVGA=src/output.c src/util.c vgasrc/vga.c vgasrc/vgafb.c vgasrc/vgaio.c \
++       vgasrc/vgatables.c vgasrc/vgafonts.c vgasrc/clext.c
++
++$(OUT)vgaccode.16.s: ; $(call whole-compile, $(CFLAGS16) -S -Isrc, $(SRCVGA),$@)
++
++$(OUT)vgalayout16.o: vgaentry.S $(OUT)vgaccode.16.s $(OUT)asm-offsets.h
++	@echo "  Compiling (16bit) $@"
++	$(Q)$(CC) $(CFLAGS16INC) -c -D__ASSEMBLY__ -Isrc $< -o $@
++
++$(OUT)vgarom.o: $(OUT)vgalayout16.o $(OUT)vgalayout.lds
++	@echo "  Linking $@"
++	$(Q)$(LD) --gc-sections -T $(OUT)vgalayout.lds $(OUT)vgalayout16.o -o $@
++
++$(OUT)vgabios.bin.raw: $(OUT)vgarom.o
++	@echo "  Extracting binary $@"
++	$(Q)$(OBJCOPY) -O binary $< $@
++
++$(OUT)vgabios.bin: $(OUT)vgabios.bin.raw tools/buildrom.py
++	@echo "  Finalizing rom $@"
++	$(Q)./tools/buildrom.py $< $@
++
++####### dsdt build rules
++src/acpi-dsdt.hex: src/acpi-dsdt.dsl
++	@echo "Compiling DSDT"
++	$(Q)cpp -P $< > $(OUT)acpi-dsdt.dsl.i
++	$(Q)iasl -tc -p $@ $(OUT)acpi-dsdt.dsl.i
++	$(Q)rm $(OUT)acpi-dsdt.dsl.i
++
++####### Generic rules
++clean:
++	$(Q)rm -rf $(OUT)
++
++$(OUT):
++	$(Q)mkdir $@
++
++-include $(OUT)*.d
+--- x/roms/seabios/README	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/README	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,190 @@
++This code implements an X86 legacy bios.  It is intended to be
++compiled using standard gnu tools (eg, gas and gcc).
++
++To build, one should be able to run "make" in the main directory.  The
++resulting file "out/bios.bin" contains the processed bios image.
++
++
++Testing of images:
++
++To test the bios under bochs, one will need to instruct bochs to use
++the new bios image.  Use the 'romimage' option - for example:
++
++bochs -q 'floppya: 1_44=myfdimage.img' 'romimage: file=out/bios.bin'
++
++To test under qemu, one will need to create a directory with all the
++bios images and then overwrite the main bios image.  For example:
++
++cp /usr/share/qemu/*.bin mybiosdir/
++cp out/bios.bin mybiosdir/
++
++Once this is setup, one can instruct qemu to use the newly created
++directory for rom images.  For example:
++
++qemu -L mybiosdir/ -fda myfdimage.img
++
++
++The following payloads have been tested:
++
++Freedos - see http://www.freedos.org/ .  Useful tests include: booting
++from installation cdrom, installing to hard drive and floppy, making
++sure hard drive and floppy boots then work.  It is also useful to take
++the bootable floppy and hard-drive images, write them to an el-torito
++bootable cdrom using the Linux mkisofs utility, and then boot those
++cdrom images.
++
++Linux - useful hard drive image available from
++http://fabrice.bellard.free.fr/qemu/linux-0.2.img.bz2 .  It is also
++useful to test standard distribution bootup and live cdroms.
++
++NetBSD - useful hard drive image available from
++http://nopid.free.fr/small.ffs.bz2 .  It is also useful to test
++standard distribution installation cdroms.
++
++
++Overview of files:
++
++The src/ directory contains the bios source code.  Several of the
++files are compiled twice - once for 16bit mode and once for 32bit
++mode.  (The build system will remove code that is not needed for a
++particular mode.)
++
++The tools/ directory contains helper utilities for manipulating and
++building the final rom.
++
++The out/ directory is created by the build process - it contains all
++temporary and final files.
++
++
++Build overview:
++
++The 16bit code is compiled via gcc to assembler (file out/ccode.16.s).
++The gcc "-fwhole-program" and "-ffunction-sections -fdata-sections"
++options are used to optimize the process so that gcc can efficiently
++compile and discard unneeded code.  (In the code, one can use the
++macros 'VISIBLE16' and 'VISIBLE32' to instruct a symbol to be
++outputted in 16bit and 32bit mode respectively.)
++
++This resulting assembler code is pulled into romlayout.S.  The gas
++option ".code16gcc" is used prior to including the gcc generated
++assembler - this option enables gcc to generate valid 16 bit code.
++
++The post code (post.c) is entered, via the function _start(), in 32bit
++mode.  The 16bit post vector (in romlayout.S) transitions the cpu into
++32 bit mode before calling the post.c code.
++
++In the last step of compilation, the 32 bit code is merged into the 16
++bit code so that one binary file contains both.  Currently, both 16bit
++and 32bit code will be located in the 64K block at segment 0xf000.
++
++
++GCC 16 bit limitations:
++
++Although the 16bit code is compiled with gcc, developers need to be
++aware of the environment.  In particular, global variables _must_ be
++treated specially.
++
++The code has full access to stack variables and general purpose
++registers.  The entry code in romlayout.S will push the original
++registers on the stack before calling the C code and then pop them off
++(including any required changes) before returning from the interrupt.
++Changes to CS, DS, and ES segment registers in C code is also safe.
++Changes to other segment registers (SS, FS, GS) need to be restored
++manually.
++
++Stack variables (and pointers to stack variables) work as they
++normally do in standard C code.
++
++However, variables stored outside the stack need to be accessed via
++the GET_VAR and SET_VAR macros (or one of the helper macros described
++below).  This is due to the 16bit segment nature of the X86 cpu when
++it is in "real mode".  The C entry code will set DS and SS to point to
++the stack segment.  Variables not on the stack need to be accessed via
++an explicit segment register.  Any other access requires altering one
++of the other segment registers (usually ES) and then accessing the
++variable via that segment register.
++
++There are three low-level ways to access a remote variable:
++GET/SET_VAR, GET/SET_FARVAR, and GET/SET_FLATPTR.  The first set takes
++an explicit segment descriptor (eg, "CS") and offset.  The second set
++will take a segment id and offset, set ES to the segment id, and then
++make the access via the ES segment.  The last method is similar to the
++second, except it takes a pointer that would be valid in 32-bit flat
++mode instead of a segment/offset pair.
++
++Most BIOS variables are stored in global variables, the "BDA", or
++"EBDA" memory areas.  Because this is common, three sets of helper
++macros (GET/SET_GLOBAL, GET/SET_BDA, and GET/SET_EBDA) are available
++to simplify these accesses.
++
++Global variables defined in the C code can be read in 16bit mode if
++the variable declaration is marked with VAR16, VAR16VISIBLE,
++VAR16EXPORT, or VAR16FIXED.  The GET_GLOBAL macro will then allow read
++access to the variable.  Global variables are stored in the 0xf000
++segment, and their values are persistent across soft resets.  Because
++the f-segment is marked read-only during run-time, the 16bit code is
++not permitted to change the value of 16bit variables (use of the
++SET_GLOBAL macro from 16bit mode will cause a link error).  Code
++running in 32bit mode can not access variables with VAR16, but can
++access variables marked with VAR16VISIBLE, VAR16EXPORT, VAR16FIXED, or
++with no marking at all.  The 32bit code can use the GET/SET_GLOBAL
++macros, but they are not required.
++
++
++GCC 16 bit stack limitations:
++
++Another limitation of gcc is its use of 32-bit temporaries.  Gcc will
++allocate 32-bits of space for every variable - even if that variable
++is only defined as a 'u8' or 'u16'.  If one is not careful, using too
++much stack space can break old DOS applications.
++
++There does not appear to be explicit documentation on the minimum
++stack space available for bios calls.  However, Freedos has been
++observed to call into the bios with less than 150 bytes available.
++
++Note that the post code and boot code (irq 18/19) do not have a stack
++limitation because the entry points for these functions transition the
++cpu to 32bit mode and reset the stack to a known state.  Only the
++general purpose 16-bit service entry points are affected.
++
++There are some ways to reduce stack usage: making sure functions are
++tail-recursive often helps, reducing the number of parameters passed
++to functions often helps, sometimes reordering variable declarations
++helps, inlining of functions can sometimes help, and passing of packed
++structures can also help.  It is also possible to transition to/from
++an extra stack stored in the EBDA using the stack_hop helper function.
++
++Some useful stats: the overhead for the entry to a bios handler that
++takes a 'struct bregs' is 42 bytes of stack space (6 bytes from
++interrupt insn, 32 bytes to store registers, and 4 bytes for call
++insn).  An entry to an ISR handler without args takes 30 bytes (6 + 20
+++ 4).
++
++
++Debugging the bios:
++
++The bios will output information messages to a special debug port.
++Under qemu, one can view these messages by enabling the '#define
++DEBUG_BIOS' definition in 'qemu/hw/pc.c'.  Once this is done (and qemu
++is recompiled), one should see status messages on the console.
++
++The gdb-server mechanism of qemu is also useful.  One can use gdb with
++qemu to debug system images.  To use this, add '-s -S' to the qemu
++command line.  For example:
++
++qemu -L mybiosdir/ -fda myfdimage.img -s -S
++
++Then, in another session, run gdb with either out/rom16.o (to debug
++bios 16bit code) or out/rom32.o (to debug bios 32bit code).  For
++example:
++
++gdb out/rom16.o
++
++Once in gdb, use the command "target remote localhost:1234" to have
++gdb connect to qemu.  See the qemu documentation for more information
++on using gdb and qemu in this mode.  Note that gdb seems to get
++breakpoints confused when the cpu is in 16-bit real mode.  This makes
++stepping through the program difficult (though 'step instruction'
++still works).  Also, one may need to set 16bit break points at both
++the cpu address and memory address (eg, break *0x1234 ; break
++*0xf1234).
+--- x/roms/seabios/TODO	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/TODO	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,36 @@
++If POST is rerun, try to do a machine reboot.
++
++Review changes committed to coreboot, virtualbox, qemu, kvm, and bochs
++cvs tip.
++  * bochs cvs (20100104):
++    -- changes synched
++  * coreboot (r3348):    (bochs 20060708)
++    -- no noteworthy enhancements
++  * qemu - now uses SeaBIOS
++  * kvm - now uses SeaBIOS
++  * virtualbox (r13560): (bochs 20061231)
++    -- lots of mouse changes, logo, scsi/etherboot hooks,
++       floppy data rate?, int19 calls post
++
++Possibly move code from entry_post in romlayout.S to C code in
++handle_resume and always call 16bit C code on post.
++
++Audit all sti/cli calls.  Audit all call16 calls to make sure flags is
++setup properly with respect to irqs.
++
++The __call16 code does a long jump to the interrupt trampolines - this
++is unnecessary.
++
++Support PCIv3 roms?  Add support for PCI "configuration code"
++extensions?
++
++Possibly add option to eliminate tsc based delays on emulators.
++
++Add a kconfig style configuration program instead of requiring users
++to modify config.h.
++
++Support usb booting?  Support usb mice?
++
++Add a graphical boot splash screen?
++
++Possibly support sending debug information over EHCI debug port.
+--- x/roms/seabios/src/acpi-dsdt.dsl	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/acpi-dsdt.dsl	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,747 @@
++/*
++ * Bochs/QEMU ACPI DSDT ASL definition
++ *
++ * Copyright (c) 2006 Fabrice Bellard
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License version 2 as published by the Free Software Foundation.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++DefinitionBlock (
++    "acpi-dsdt.aml",    // Output Filename
++    "DSDT",             // Signature
++    0x01,               // DSDT Compliance Revision
++    "BXPC",             // OEMID
++    "BXDSDT",           // TABLE ID
++    0x1                 // OEM Revision
++    )
++{
++    Scope (\)
++    {
++        /* Debug Output */
++        OperationRegion (DBG, SystemIO, 0xb044, 0x04)
++        Field (DBG, DWordAcc, NoLock, Preserve)
++        {
++            DBGL,   32,
++        }
++    }
++
++
++    /* PCI Bus definition */
++    Scope(\_SB) {
++        Device(PCI0) {
++            Name (_HID, EisaId ("PNP0A03"))
++            Name (_ADR, 0x00)
++            Name (_UID, 1)
++            Name(_PRT, Package() {
++                /* PCI IRQ routing table, example from ACPI 2.0a specification,
++                   section 6.2.8.1 */
++                /* Note: we provide the same info as the PCI routing
++                   table of the Bochs BIOS */
++#define prt_slot(nr, lnk0, lnk1, lnk2, lnk3) \
++       Package() { nr##ffff, 0, lnk0, 0 }, \
++       Package() { nr##ffff, 1, lnk1, 0 }, \
++       Package() { nr##ffff, 2, lnk2, 0 }, \
++       Package() { nr##ffff, 3, lnk3, 0 }
++
++#define prt_slot0(nr) prt_slot(nr, LNKD, LNKA, LNKB, LNKC)
++#define prt_slot1(nr) prt_slot(nr, LNKA, LNKB, LNKC, LNKD)
++#define prt_slot2(nr) prt_slot(nr, LNKB, LNKC, LNKD, LNKA)
++#define prt_slot3(nr) prt_slot(nr, LNKC, LNKD, LNKA, LNKB)
++               prt_slot0(0x0000),
++               /* Device 1 is power mgmt device, and can only use irq 9 */
++               Package() { 0x0001ffff, 0, 0, 9 },
++               Package() { 0x0001ffff, 1, LNKB, 0 },
++               Package() { 0x0001ffff, 2, LNKC, 0 },
++               Package() { 0x0001ffff, 3, LNKD, 0 },
++               prt_slot2(0x0002),
++               prt_slot3(0x0003),
++               prt_slot0(0x0004),
++               prt_slot1(0x0005),
++               prt_slot2(0x0006),
++               prt_slot3(0x0007),
++               prt_slot0(0x0008),
++               prt_slot1(0x0009),
++               prt_slot2(0x000a),
++               prt_slot3(0x000b),
++               prt_slot0(0x000c),
++               prt_slot1(0x000d),
++               prt_slot2(0x000e),
++               prt_slot3(0x000f),
++               prt_slot0(0x0010),
++               prt_slot1(0x0011),
++               prt_slot2(0x0012),
++               prt_slot3(0x0013),
++               prt_slot0(0x0014),
++               prt_slot1(0x0015),
++               prt_slot2(0x0016),
++               prt_slot3(0x0017),
++               prt_slot0(0x0018),
++               prt_slot1(0x0019),
++               prt_slot2(0x001a),
++               prt_slot3(0x001b),
++               prt_slot0(0x001c),
++               prt_slot1(0x001d),
++               prt_slot2(0x001e),
++               prt_slot3(0x001f),
++            })
++
++            OperationRegion(PCST, SystemIO, 0xae00, 0x08)
++            Field (PCST, DWordAcc, NoLock, WriteAsZeros)
++            {
++                PCIU, 32,
++                PCID, 32,
++            }
++
++            OperationRegion(SEJ, SystemIO, 0xae08, 0x04)
++            Field (SEJ, DWordAcc, NoLock, WriteAsZeros)
++            {
++                B0EJ, 32,
++            }
++
++#define hotplug_slot(name, nr) \
++            Device (S##name) {                    \
++               Name (_ADR, nr##0000)              \
++               Method (_EJ0,1) {                  \
++                    Store(ShiftLeft(1, nr), B0EJ) \
++                    Return (0x0)                  \
++               }                                  \
++               Name (_SUN, name)                  \
++            }
++
++	    hotplug_slot(1, 0x0001)
++	    hotplug_slot(2, 0x0002)
++	    hotplug_slot(3, 0x0003)
++	    hotplug_slot(4, 0x0004)
++	    hotplug_slot(5, 0x0005)
++	    hotplug_slot(6, 0x0006)
++	    hotplug_slot(7, 0x0007)
++	    hotplug_slot(8, 0x0008)
++	    hotplug_slot(9, 0x0009)
++	    hotplug_slot(10, 0x000a)
++	    hotplug_slot(11, 0x000b)
++	    hotplug_slot(12, 0x000c)
++	    hotplug_slot(13, 0x000d)
++	    hotplug_slot(14, 0x000e)
++	    hotplug_slot(15, 0x000f)
++	    hotplug_slot(16, 0x0010)
++	    hotplug_slot(17, 0x0011)
++	    hotplug_slot(18, 0x0012)
++	    hotplug_slot(19, 0x0013)
++	    hotplug_slot(20, 0x0014)
++	    hotplug_slot(21, 0x0015)
++	    hotplug_slot(22, 0x0016)
++	    hotplug_slot(23, 0x0017)
++	    hotplug_slot(24, 0x0018)
++	    hotplug_slot(25, 0x0019)
++	    hotplug_slot(26, 0x001a)
++	    hotplug_slot(27, 0x001b)
++	    hotplug_slot(28, 0x001c)
++	    hotplug_slot(29, 0x001d)
++	    hotplug_slot(30, 0x001e)
++	    hotplug_slot(31, 0x001f)
++
++            Name (_CRS, ResourceTemplate ()
++            {
++                WordBusNumber (ResourceProducer, MinFixed, MaxFixed, PosDecode,
++                    0x0000,             // Address Space Granularity
++                    0x0000,             // Address Range Minimum
++                    0x00FF,             // Address Range Maximum
++                    0x0000,             // Address Translation Offset
++                    0x0100,             // Address Length
++                    ,, )
++                IO (Decode16,
++                    0x0CF8,             // Address Range Minimum
++                    0x0CF8,             // Address Range Maximum
++                    0x01,               // Address Alignment
++                    0x08,               // Address Length
++                    )
++                WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
++                    0x0000,             // Address Space Granularity
++                    0x0000,             // Address Range Minimum
++                    0x0CF7,             // Address Range Maximum
++                    0x0000,             // Address Translation Offset
++                    0x0CF8,             // Address Length
++                    ,, , TypeStatic)
++                WordIO (ResourceProducer, MinFixed, MaxFixed, PosDecode, EntireRange,
++                    0x0000,             // Address Space Granularity
++                    0x0D00,             // Address Range Minimum
++                    0xFFFF,             // Address Range Maximum
++                    0x0000,             // Address Translation Offset
++                    0xF300,             // Address Length
++                    ,, , TypeStatic)
++                DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, Cacheable, ReadWrite,
++                    0x00000000,         // Address Space Granularity
++                    0x000A0000,         // Address Range Minimum
++                    0x000BFFFF,         // Address Range Maximum
++                    0x00000000,         // Address Translation Offset
++                    0x00020000,         // Address Length
++                    ,, , AddressRangeMemory, TypeStatic)
++                DWordMemory (ResourceProducer, PosDecode, MinFixed, MaxFixed, NonCacheable, ReadWrite,
++                    0x00000000,         // Address Space Granularity
++                    0xE0000000,         // Address Range Minimum
++                    0xFEBFFFFF,         // Address Range Maximum
++                    0x00000000,         // Address Translation Offset
++                    0x1EC00000,         // Address Length
++                    ,, , AddressRangeMemory, TypeStatic)
++            })
++        }
++
++        Device(HPET) {
++            Name(_HID,  EISAID("PNP0103"))
++            Name(_UID, 0)
++            Method (_STA, 0, NotSerialized) {
++                    Return(0x0F)
++            }
++            Name(_CRS, ResourceTemplate() {
++                DWordMemory(
++                    ResourceConsumer, PosDecode, MinFixed, MaxFixed,
++                    NonCacheable, ReadWrite,
++                    0x00000000,
++                    0xFED00000,
++                    0xFED003FF,
++                    0x00000000,
++                    0x00000400 /* 1K memory: FED00000 - FED003FF */
++                )
++            })
++        }
++    }
++
++    Scope(\_SB.PCI0) {
++        Device (VGA) {
++                 Name (_ADR, 0x00020000)
++                 Method (_S1D, 0, NotSerialized)
++                 {
++                         Return (0x00)
++                 }
++                 Method (_S2D, 0, NotSerialized)
++                 {
++                         Return (0x00)
++                 }
++                 Method (_S3D, 0, NotSerialized)
++                 {
++                         Return (0x00)
++                 }
++        }
++
++	/* PIIX3 ISA bridge */
++        Device (ISA) {
++            Name (_ADR, 0x00010000)
++
++            /* PIIX PCI to ISA irq remapping */
++            OperationRegion (P40C, PCI_Config, 0x60, 0x04)
++
++            /* Real-time clock */
++            Device (RTC)
++            {
++                Name (_HID, EisaId ("PNP0B00"))
++                Name (_CRS, ResourceTemplate ()
++                {
++                    IO (Decode16, 0x0070, 0x0070, 0x10, 0x02)
++                    IRQNoFlags () {8}
++                    IO (Decode16, 0x0072, 0x0072, 0x02, 0x06)
++                })
++            }
++
++            /* Keyboard seems to be important for WinXP install */
++            Device (KBD)
++            {
++                Name (_HID, EisaId ("PNP0303"))
++                Method (_STA, 0, NotSerialized)
++                {
++                    Return (0x0f)
++                }
++
++                Method (_CRS, 0, NotSerialized)
++                {
++                     Name (TMP, ResourceTemplate ()
++                     {
++                    IO (Decode16,
++                        0x0060,             // Address Range Minimum
++                        0x0060,             // Address Range Maximum
++                        0x01,               // Address Alignment
++                        0x01,               // Address Length
++                        )
++                    IO (Decode16,
++                        0x0064,             // Address Range Minimum
++                        0x0064,             // Address Range Maximum
++                        0x01,               // Address Alignment
++                        0x01,               // Address Length
++                        )
++                    IRQNoFlags ()
++                        {1}
++                    })
++                    Return (TMP)
++                }
++            }
++
++	    /* PS/2 mouse */
++            Device (MOU)
++            {
++                Name (_HID, EisaId ("PNP0F13"))
++                Method (_STA, 0, NotSerialized)
++                {
++                    Return (0x0f)
++                }
++
++                Method (_CRS, 0, NotSerialized)
++                {
++                    Name (TMP, ResourceTemplate ()
++                    {
++                         IRQNoFlags () {12}
++                    })
++                    Return (TMP)
++                }
++            }
++
++	    /* PS/2 floppy controller */
++	    Device (FDC0)
++	    {
++	        Name (_HID, EisaId ("PNP0700"))
++		Method (_STA, 0, NotSerialized)
++		{
++		    Return (0x0F)
++		}
++		Method (_CRS, 0, NotSerialized)
++		{
++		    Name (BUF0, ResourceTemplate ()
++                    {
++                        IO (Decode16, 0x03F2, 0x03F2, 0x00, 0x04)
++                        IO (Decode16, 0x03F7, 0x03F7, 0x00, 0x01)
++                        IRQNoFlags () {6}
++                        DMA (Compatibility, NotBusMaster, Transfer8) {2}
++                    })
++		    Return (BUF0)
++		}
++	    }
++
++	    /* Parallel port */
++	    Device (LPT)
++	    {
++	        Name (_HID, EisaId ("PNP0400"))
++		Method (_STA, 0, NotSerialized)
++		{
++		    Store (\_SB.PCI0.PX13.DRSA, Local0)
++		    And (Local0, 0x80000000, Local0)
++		    If (LEqual (Local0, 0))
++		    {
++			Return (0x00)
++		    }
++		    Else
++		    {
++			Return (0x0F)
++		    }
++		}
++		Method (_CRS, 0, NotSerialized)
++		{
++		    Name (BUF0, ResourceTemplate ()
++                    {
++			IO (Decode16, 0x0378, 0x0378, 0x08, 0x08)
++			IRQNoFlags () {7}
++		    })
++		    Return (BUF0)
++		}
++	    }
++
++	    /* Serial Ports */
++	    Device (COM1)
++	    {
++	        Name (_HID, EisaId ("PNP0501"))
++		Name (_UID, 0x01)
++		Method (_STA, 0, NotSerialized)
++		{
++		    Store (\_SB.PCI0.PX13.DRSC, Local0)
++		    And (Local0, 0x08000000, Local0)
++		    If (LEqual (Local0, 0))
++		    {
++			Return (0x00)
++		    }
++		    Else
++		    {
++			Return (0x0F)
++		    }
++		}
++		Method (_CRS, 0, NotSerialized)
++		{
++		    Name (BUF0, ResourceTemplate ()
++                    {
++			IO (Decode16, 0x03F8, 0x03F8, 0x00, 0x08)
++                	IRQNoFlags () {4}
++		    })
++		    Return (BUF0)
++		}
++	    }
++
++	    Device (COM2)
++	    {
++	        Name (_HID, EisaId ("PNP0501"))
++		Name (_UID, 0x02)
++		Method (_STA, 0, NotSerialized)
++		{
++		    Store (\_SB.PCI0.PX13.DRSC, Local0)
++		    And (Local0, 0x80000000, Local0)
++		    If (LEqual (Local0, 0))
++		    {
++			Return (0x00)
++		    }
++		    Else
++		    {
++			Return (0x0F)
++		    }
++		}
++		Method (_CRS, 0, NotSerialized)
++		{
++		    Name (BUF0, ResourceTemplate ()
++                    {
++			IO (Decode16, 0x02F8, 0x02F8, 0x00, 0x08)
++                	IRQNoFlags () {3}
++		    })
++		    Return (BUF0)
++		}
++	    }
++        }
++
++	/* PIIX4 PM */
++        Device (PX13) {
++	    Name (_ADR, 0x00010003)
++
++	    OperationRegion (P13C, PCI_Config, 0x5c, 0x24)
++	    Field (P13C, DWordAcc, NoLock, Preserve)
++	    {
++		DRSA, 32,
++		DRSB, 32,
++		DRSC, 32,
++		DRSE, 32,
++		DRSF, 32,
++		DRSG, 32,
++		DRSH, 32,
++		DRSI, 32,
++		DRSJ, 32
++	    }
++	}
++    }
++
++    /* PCI IRQs */
++    Scope(\_SB) {
++         Field (\_SB.PCI0.ISA.P40C, ByteAcc, NoLock, Preserve)
++         {
++             PRQ0,   8,
++             PRQ1,   8,
++             PRQ2,   8,
++             PRQ3,   8
++         }
++
++        Device(LNKA){
++                Name(_HID, EISAID("PNP0C0F"))     // PCI interrupt link
++                Name(_UID, 1)
++                Name(_PRS, ResourceTemplate(){
++                    Interrupt (, Level, ActiveHigh, Shared)
++                        { 5, 10, 11 }
++                })
++                Method (_STA, 0, NotSerialized)
++                {
++                    Store (0x0B, Local0)
++                    If (And (0x80, PRQ0, Local1))
++                    {
++                         Store (0x09, Local0)
++                    }
++                    Return (Local0)
++                }
++                Method (_DIS, 0, NotSerialized)
++                {
++                    Or (PRQ0, 0x80, PRQ0)
++                }
++                Method (_CRS, 0, NotSerialized)
++                {
++                    Name (PRR0, ResourceTemplate ()
++                    {
++                        Interrupt (, Level, ActiveHigh, Shared)
++                            {1}
++                    })
++                    CreateDWordField (PRR0, 0x05, TMP)
++                    Store (PRQ0, Local0)
++                    If (LLess (Local0, 0x80))
++                    {
++                        Store (Local0, TMP)
++                    }
++                    Else
++                    {
++                        Store (Zero, TMP)
++                    }
++                    Return (PRR0)
++                }
++                Method (_SRS, 1, NotSerialized)
++                {
++                    CreateDWordField (Arg0, 0x05, TMP)
++                    Store (TMP, PRQ0)
++                }
++        }
++        Device(LNKB){
++                Name(_HID, EISAID("PNP0C0F"))     // PCI interrupt link
++                Name(_UID, 2)
++                Name(_PRS, ResourceTemplate(){
++                    Interrupt (, Level, ActiveHigh, Shared)
++                        { 5, 10, 11 }
++                })
++                Method (_STA, 0, NotSerialized)
++                {
++                    Store (0x0B, Local0)
++                    If (And (0x80, PRQ1, Local1))
++                    {
++                         Store (0x09, Local0)
++                    }
++                    Return (Local0)
++                }
++                Method (_DIS, 0, NotSerialized)
++                {
++                    Or (PRQ1, 0x80, PRQ1)
++                }
++                Method (_CRS, 0, NotSerialized)
++                {
++                    Name (PRR0, ResourceTemplate ()
++                    {
++                        Interrupt (, Level, ActiveHigh, Shared)
++                            {1}
++                    })
++                    CreateDWordField (PRR0, 0x05, TMP)
++                    Store (PRQ1, Local0)
++                    If (LLess (Local0, 0x80))
++                    {
++                        Store (Local0, TMP)
++                    }
++                    Else
++                    {
++                        Store (Zero, TMP)
++                    }
++                    Return (PRR0)
++                }
++                Method (_SRS, 1, NotSerialized)
++                {
++                    CreateDWordField (Arg0, 0x05, TMP)
++                    Store (TMP, PRQ1)
++                }
++        }
++        Device(LNKC){
++                Name(_HID, EISAID("PNP0C0F"))     // PCI interrupt link
++                Name(_UID, 3)
++                Name(_PRS, ResourceTemplate(){
++                    Interrupt (, Level, ActiveHigh, Shared)
++                        { 5, 10, 11 }
++                })
++                Method (_STA, 0, NotSerialized)
++                {
++                    Store (0x0B, Local0)
++                    If (And (0x80, PRQ2, Local1))
++                    {
++                         Store (0x09, Local0)
++                    }
++                    Return (Local0)
++                }
++                Method (_DIS, 0, NotSerialized)
++                {
++                    Or (PRQ2, 0x80, PRQ2)
++                }
++                Method (_CRS, 0, NotSerialized)
++                {
++                    Name (PRR0, ResourceTemplate ()
++                    {
++                        Interrupt (, Level, ActiveHigh, Shared)
++                            {1}
++                    })
++                    CreateDWordField (PRR0, 0x05, TMP)
++                    Store (PRQ2, Local0)
++                    If (LLess (Local0, 0x80))
++                    {
++                        Store (Local0, TMP)
++                    }
++                    Else
++                    {
++                        Store (Zero, TMP)
++                    }
++                    Return (PRR0)
++                }
++                Method (_SRS, 1, NotSerialized)
++                {
++                    CreateDWordField (Arg0, 0x05, TMP)
++                    Store (TMP, PRQ2)
++                }
++        }
++        Device(LNKD){
++                Name(_HID, EISAID("PNP0C0F"))     // PCI interrupt link
++                Name(_UID, 4)
++                Name(_PRS, ResourceTemplate(){
++                    Interrupt (, Level, ActiveHigh, Shared)
++                        { 5, 10, 11 }
++                })
++                Method (_STA, 0, NotSerialized)
++                {
++                    Store (0x0B, Local0)
++                    If (And (0x80, PRQ3, Local1))
++                    {
++                         Store (0x09, Local0)
++                    }
++                    Return (Local0)
++                }
++                Method (_DIS, 0, NotSerialized)
++                {
++                    Or (PRQ3, 0x80, PRQ3)
++                }
++                Method (_CRS, 0, NotSerialized)
++                {
++                    Name (PRR0, ResourceTemplate ()
++                    {
++                        Interrupt (, Level, ActiveHigh, Shared)
++                            {1}
++                    })
++                    CreateDWordField (PRR0, 0x05, TMP)
++                    Store (PRQ3, Local0)
++                    If (LLess (Local0, 0x80))
++                    {
++                        Store (Local0, TMP)
++                    }
++                    Else
++                    {
++                        Store (Zero, TMP)
++                    }
++                    Return (PRR0)
++                }
++                Method (_SRS, 1, NotSerialized)
++                {
++                    CreateDWordField (Arg0, 0x05, TMP)
++                    Store (TMP, PRQ3)
++                }
++        }
++    }
++
++    /*
++     * S3 (suspend-to-ram), S4 (suspend-to-disk) and S5 (power-off) type codes:
++     * must match piix4 emulation.
++     */
++    Name (\_S3, Package (0x04)
++    {
++        0x01,  /* PM1a_CNT.SLP_TYP */
++        0x01,  /* PM1b_CNT.SLP_TYP */
++        Zero,  /* reserved */
++        Zero   /* reserved */
++    })
++    Name (\_S4, Package (0x04)
++    {
++        Zero,  /* PM1a_CNT.SLP_TYP */
++        Zero,  /* PM1b_CNT.SLP_TYP */
++        Zero,  /* reserved */
++        Zero   /* reserved */
++    })
++    Name (\_S5, Package (0x04)
++    {
++        Zero,  /* PM1a_CNT.SLP_TYP */
++        Zero,  /* PM1b_CNT.SLP_TYP */
++        Zero,  /* reserved */
++        Zero   /* reserved */
++    })
++
++    Scope (\_GPE)
++    {
++        Name(_HID, "ACPI0006")
++
++        Method(_L00) {
++            Return(0x01)
++        }
++
++#define gen_pci_hotplug(nr)                                       \
++            If (And(\_SB.PCI0.PCIU, ShiftLeft(1, nr))) {          \
++                Notify(\_SB.PCI0.S##nr, 1)                        \
++            }                                                     \
++            If (And(\_SB.PCI0.PCID, ShiftLeft(1, nr))) {          \
++                Notify(\_SB.PCI0.S##nr, 3)                        \
++            }
++
++        Method(_L01) {
++            gen_pci_hotplug(1)
++            gen_pci_hotplug(2)
++            gen_pci_hotplug(3)
++            gen_pci_hotplug(4)
++            gen_pci_hotplug(5)
++            gen_pci_hotplug(6)
++            gen_pci_hotplug(7)
++            gen_pci_hotplug(8)
++            gen_pci_hotplug(9)
++            gen_pci_hotplug(10)
++            gen_pci_hotplug(11)
++            gen_pci_hotplug(12)
++            gen_pci_hotplug(13)
++            gen_pci_hotplug(14)
++            gen_pci_hotplug(15)
++            gen_pci_hotplug(16)
++            gen_pci_hotplug(17)
++            gen_pci_hotplug(18)
++            gen_pci_hotplug(19)
++            gen_pci_hotplug(20)
++            gen_pci_hotplug(21)
++            gen_pci_hotplug(22)
++            gen_pci_hotplug(23)
++            gen_pci_hotplug(24)
++            gen_pci_hotplug(25)
++            gen_pci_hotplug(26)
++            gen_pci_hotplug(27)
++            gen_pci_hotplug(28)
++            gen_pci_hotplug(29)
++            gen_pci_hotplug(30)
++            gen_pci_hotplug(31)
++
++            Return (0x01)
++
++        }
++        Method(_L02) {
++            Return(0x01)
++        }
++        Method(_L03) {
++            Return(0x01)
++        }
++        Method(_L04) {
++            Return(0x01)
++        }
++        Method(_L05) {
++            Return(0x01)
++        }
++        Method(_L06) {
++            Return(0x01)
++        }
++        Method(_L07) {
++            Return(0x01)
++        }
++        Method(_L08) {
++            Return(0x01)
++        }
++        Method(_L09) {
++            Return(0x01)
++        }
++        Method(_L0A) {
++            Return(0x01)
++        }
++        Method(_L0B) {
++            Return(0x01)
++        }
++        Method(_L0C) {
++            Return(0x01)
++        }
++        Method(_L0D) {
++            Return(0x01)
++        }
++        Method(_L0E) {
++            Return(0x01)
++        }
++        Method(_L0F) {
++            Return(0x01)
++        }
++    }
++
++}
+--- x/roms/seabios/src/acpi.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/acpi.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,707 @@
++// Support for generating ACPI tables (on emulators)
++//
++// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2006 Fabrice Bellard
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "acpi.h" // struct rsdp_descriptor
++#include "util.h" // memcpy
++#include "pci.h" // pci_find_device
++#include "biosvar.h" // GET_EBDA
++#include "pci_ids.h" // PCI_VENDOR_ID_INTEL
++#include "pci_regs.h" // PCI_INTERRUPT_LINE
++#include "paravirt.h"
++
++/****************************************************/
++/* ACPI tables init */
++
++/* Table structure from Linux kernel (the ACPI tables are under the
++   BSD license) */
++
++#define ACPI_TABLE_HEADER_DEF   /* ACPI common table header */ \
++    u32 signature;          /* ACPI signature (4 ASCII characters) */ \
++    u32 length;                 /* Length of table, in bytes, including header */ \
++    u8  revision;               /* ACPI Specification minor version # */ \
++    u8  checksum;               /* To make sum of entire table == 0 */ \
++    u8  oem_id [6];             /* OEM identification */ \
++    u8  oem_table_id [8];       /* OEM table identification */ \
++    u32 oem_revision;           /* OEM revision number */ \
++    u8  asl_compiler_id [4];    /* ASL compiler vendor ID */ \
++    u32 asl_compiler_revision;  /* ASL compiler revision number */
++
++
++struct acpi_table_header         /* ACPI common table header */
++{
++    ACPI_TABLE_HEADER_DEF
++} PACKED;
++
++/*
++ * ACPI 1.0 Root System Description Table (RSDT)
++ */
++#define RSDT_SIGNATURE 0x54445352 // RSDT
++struct rsdt_descriptor_rev1
++{
++    ACPI_TABLE_HEADER_DEF       /* ACPI common table header */
++    u32 table_offset_entry[0];  /* Array of pointers to other */
++    /* ACPI tables */
++} PACKED;
++
++/*
++ * ACPI 1.0 Firmware ACPI Control Structure (FACS)
++ */
++#define FACS_SIGNATURE 0x53434146 // FACS
++struct facs_descriptor_rev1
++{
++    u32 signature;           /* ACPI Signature */
++    u32 length;                 /* Length of structure, in bytes */
++    u32 hardware_signature;     /* Hardware configuration signature */
++    u32 firmware_waking_vector; /* ACPI OS waking vector */
++    u32 global_lock;            /* Global Lock */
++    u32 S4bios_f        : 1;    /* Indicates if S4BIOS support is present */
++    u32 reserved1       : 31;   /* Must be 0 */
++    u8  resverved3 [40];        /* Reserved - must be zero */
++} PACKED;
++
++
++/*
++ * ACPI 1.0 Fixed ACPI Description Table (FADT)
++ */
++#define FACP_SIGNATURE 0x50434146 // FACP
++struct fadt_descriptor_rev1
++{
++    ACPI_TABLE_HEADER_DEF     /* ACPI common table header */
++    u32 firmware_ctrl;          /* Physical address of FACS */
++    u32 dsdt;                   /* Physical address of DSDT */
++    u8  model;                  /* System Interrupt Model */
++    u8  reserved1;              /* Reserved */
++    u16 sci_int;                /* System vector of SCI interrupt */
++    u32 smi_cmd;                /* Port address of SMI command port */
++    u8  acpi_enable;            /* Value to write to smi_cmd to enable ACPI */
++    u8  acpi_disable;           /* Value to write to smi_cmd to disable ACPI */
++    u8  S4bios_req;             /* Value to write to SMI CMD to enter S4BIOS state */
++    u8  reserved2;              /* Reserved - must be zero */
++    u32 pm1a_evt_blk;           /* Port address of Power Mgt 1a acpi_event Reg Blk */
++    u32 pm1b_evt_blk;           /* Port address of Power Mgt 1b acpi_event Reg Blk */
++    u32 pm1a_cnt_blk;           /* Port address of Power Mgt 1a Control Reg Blk */
++    u32 pm1b_cnt_blk;           /* Port address of Power Mgt 1b Control Reg Blk */
++    u32 pm2_cnt_blk;            /* Port address of Power Mgt 2 Control Reg Blk */
++    u32 pm_tmr_blk;             /* Port address of Power Mgt Timer Ctrl Reg Blk */
++    u32 gpe0_blk;               /* Port addr of General Purpose acpi_event 0 Reg Blk */
++    u32 gpe1_blk;               /* Port addr of General Purpose acpi_event 1 Reg Blk */
++    u8  pm1_evt_len;            /* Byte length of ports at pm1_x_evt_blk */
++    u8  pm1_cnt_len;            /* Byte length of ports at pm1_x_cnt_blk */
++    u8  pm2_cnt_len;            /* Byte Length of ports at pm2_cnt_blk */
++    u8  pm_tmr_len;             /* Byte Length of ports at pm_tm_blk */
++    u8  gpe0_blk_len;           /* Byte Length of ports at gpe0_blk */
++    u8  gpe1_blk_len;           /* Byte Length of ports at gpe1_blk */
++    u8  gpe1_base;              /* Offset in gpe model where gpe1 events start */
++    u8  reserved3;              /* Reserved */
++    u16 plvl2_lat;              /* Worst case HW latency to enter/exit C2 state */
++    u16 plvl3_lat;              /* Worst case HW latency to enter/exit C3 state */
++    u16 flush_size;             /* Size of area read to flush caches */
++    u16 flush_stride;           /* Stride used in flushing caches */
++    u8  duty_offset;            /* Bit location of duty cycle field in p_cnt reg */
++    u8  duty_width;             /* Bit width of duty cycle field in p_cnt reg */
++    u8  day_alrm;               /* Index to day-of-month alarm in RTC CMOS RAM */
++    u8  mon_alrm;               /* Index to month-of-year alarm in RTC CMOS RAM */
++    u8  century;                /* Index to century in RTC CMOS RAM */
++    u8  reserved4;              /* Reserved */
++    u8  reserved4a;             /* Reserved */
++    u8  reserved4b;             /* Reserved */
++#if 0
++    u32 wb_invd         : 1;    /* The wbinvd instruction works properly */
++    u32 wb_invd_flush   : 1;    /* The wbinvd flushes but does not invalidate */
++    u32 proc_c1         : 1;    /* All processors support C1 state */
++    u32 plvl2_up        : 1;    /* C2 state works on MP system */
++    u32 pwr_button      : 1;    /* Power button is handled as a generic feature */
++    u32 sleep_button    : 1;    /* Sleep button is handled as a generic feature, or not present */
++    u32 fixed_rTC       : 1;    /* RTC wakeup stat not in fixed register space */
++    u32 rtcs4           : 1;    /* RTC wakeup stat not possible from S4 */
++    u32 tmr_val_ext     : 1;    /* The tmr_val width is 32 bits (0 = 24 bits) */
++    u32 reserved5       : 23;   /* Reserved - must be zero */
++#else
++    u32 flags;
++#endif
++} PACKED;
++
++/*
++ * MADT values and structures
++ */
++
++/* Values for MADT PCATCompat */
++
++#define DUAL_PIC                0
++#define MULTIPLE_APIC           1
++
++
++/* Master MADT */
++
++#define APIC_SIGNATURE 0x43495041 // APIC
++struct multiple_apic_table
++{
++    ACPI_TABLE_HEADER_DEF     /* ACPI common table header */
++    u32 local_apic_address;     /* Physical address of local APIC */
++#if 0
++    u32 PCATcompat      : 1;    /* A one indicates system also has dual 8259s */
++    u32 reserved1       : 31;
++#else
++    u32 flags;
++#endif
++} PACKED;
++
++
++/* Values for Type in APIC sub-headers */
++
++#define APIC_PROCESSOR          0
++#define APIC_IO                 1
++#define APIC_XRUPT_OVERRIDE     2
++#define APIC_NMI                3
++#define APIC_LOCAL_NMI          4
++#define APIC_ADDRESS_OVERRIDE   5
++#define APIC_IO_SAPIC           6
++#define APIC_LOCAL_SAPIC        7
++#define APIC_XRUPT_SOURCE       8
++#define APIC_RESERVED           9           /* 9 and greater are reserved */
++
++/*
++ * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE)
++ */
++#define ACPI_SUB_HEADER_DEF   /* Common ACPI sub-structure header */\
++    u8  type;                               \
++    u8  length;
++
++/* Sub-structures for MADT */
++
++struct madt_processor_apic
++{
++    ACPI_SUB_HEADER_DEF
++    u8  processor_id;           /* ACPI processor id */
++    u8  local_apic_id;          /* Processor's local APIC id */
++#if 0
++    u32 processor_enabled: 1;   /* Processor is usable if set */
++    u32 reserved2       : 31;   /* Reserved, must be zero */
++#else
++    u32 flags;
++#endif
++} PACKED;
++
++struct madt_io_apic
++{
++    ACPI_SUB_HEADER_DEF
++    u8  io_apic_id;             /* I/O APIC ID */
++    u8  reserved;               /* Reserved - must be zero */
++    u32 address;                /* APIC physical address */
++    u32 interrupt;              /* Global system interrupt where INTI
++                                 * lines start */
++} PACKED;
++
++/* IRQs 5,9,10,11 */
++#define PCI_ISA_IRQ_MASK    0x0e20
++
++struct madt_intsrcovr {
++    ACPI_SUB_HEADER_DEF
++    u8  bus;
++    u8  source;
++    u32 gsi;
++    u16 flags;
++} PACKED;
++
++/*
++ * ACPI 2.0 Generic Address Space definition.
++ */
++struct acpi_20_generic_address {
++    u8  address_space_id;
++    u8  register_bit_width;
++    u8  register_bit_offset;
++    u8  reserved;
++    u64 address;
++} PACKED;
++
++/*
++ * HPET Description Table
++ */
++struct acpi_20_hpet {
++    ACPI_TABLE_HEADER_DEF                    /* ACPI common table header */
++    u32           timer_block_id;
++    struct acpi_20_generic_address addr;
++    u8            hpet_number;
++    u16           min_tick;
++    u8            page_protect;
++} PACKED;
++#define ACPI_HPET_ADDRESS 0xFED00000UL
++
++/*
++ * SRAT (NUMA topology description) table
++ */
++
++#define SRAT_PROCESSOR          0
++#define SRAT_MEMORY             1
++
++struct system_resource_affinity_table
++{
++    ACPI_TABLE_HEADER_DEF
++    u32    reserved1;
++    u32    reserved2[2];
++} PACKED;
++
++struct srat_processor_affinity
++{
++    ACPI_SUB_HEADER_DEF
++    u8     proximity_lo;
++    u8     local_apic_id;
++    u32    flags;
++    u8     local_sapic_eid;
++    u8     proximity_hi[3];
++    u32    reserved;
++} PACKED;
++
++struct srat_memory_affinity
++{
++    ACPI_SUB_HEADER_DEF
++    u8     proximity[4];
++    u16    reserved1;
++    u32    base_addr_low,base_addr_high;
++    u32    length_low,length_high;
++    u32    reserved2;
++    u32    flags;
++    u32    reserved3[2];
++} PACKED;
++
++#include "acpi-dsdt.hex"
++
++static inline u16 cpu_to_le16(u16 x)
++{
++    return x;
++}
++
++static inline u32 cpu_to_le32(u32 x)
++{
++    return x;
++}
++
++static void
++build_header(struct acpi_table_header *h, u32 sig, int len, u8 rev)
++{
++    h->signature = sig;
++    h->length = cpu_to_le32(len);
++    h->revision = rev;
++    memcpy(h->oem_id, CONFIG_APPNAME6, 6);
++    memcpy(h->oem_table_id, CONFIG_APPNAME4, 4);
++    memcpy(h->asl_compiler_id, CONFIG_APPNAME4, 4);
++    memcpy(h->oem_table_id + 4, (void*)&sig, 4);
++    h->oem_revision = cpu_to_le32(1);
++    h->asl_compiler_revision = cpu_to_le32(1);
++    h->checksum -= checksum(h, len);
++}
++
++static void*
++build_fadt(int bdf)
++{
++    struct fadt_descriptor_rev1 *fadt = malloc_high(sizeof(*fadt));
++    struct facs_descriptor_rev1 *facs = memalign_high(64, sizeof(*facs));
++    void *dsdt = malloc_high(sizeof(AmlCode));
++
++    if (!fadt || !facs || !dsdt) {
++        dprintf(1, "Not enough memory for fadt!\n");
++        return NULL;
++    }
++
++    /* FACS */
++    memset(facs, 0, sizeof(*facs));
++    facs->signature = FACS_SIGNATURE;
++    facs->length = cpu_to_le32(sizeof(*facs));
++
++    /* DSDT */
++    memcpy(dsdt, AmlCode, sizeof(AmlCode));
++
++    /* FADT */
++    memset(fadt, 0, sizeof(*fadt));
++    fadt->firmware_ctrl = cpu_to_le32((u32)facs);
++    fadt->dsdt = cpu_to_le32((u32)dsdt);
++    fadt->model = 1;
++    fadt->reserved1 = 0;
++    int pm_sci_int = pci_config_readb(bdf, PCI_INTERRUPT_LINE);
++    fadt->sci_int = cpu_to_le16(pm_sci_int);
++    fadt->smi_cmd = cpu_to_le32(PORT_SMI_CMD);
++    fadt->acpi_enable = 0xf1;
++    fadt->acpi_disable = 0xf0;
++    fadt->pm1a_evt_blk = cpu_to_le32(PORT_ACPI_PM_BASE);
++    fadt->pm1a_cnt_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x04);
++    fadt->pm_tmr_blk = cpu_to_le32(PORT_ACPI_PM_BASE + 0x08);
++    fadt->pm1_evt_len = 4;
++    fadt->pm1_cnt_len = 2;
++    fadt->pm_tmr_len = 4;
++    fadt->plvl2_lat = cpu_to_le16(0xfff); // C2 state not supported
++    fadt->plvl3_lat = cpu_to_le16(0xfff); // C3 state not supported
++    fadt->gpe0_blk = cpu_to_le32(0xafe0);
++    fadt->gpe0_blk_len = 4;
++    /* WBINVD + PROC_C1 + SLP_BUTTON + FIX_RTC */
++    fadt->flags = cpu_to_le32((1 << 0) | (1 << 2) | (1 << 5) | (1 << 6));
++
++    build_header((void*)fadt, FACP_SIGNATURE, sizeof(*fadt), 1);
++
++    return fadt;
++}
++
++static void*
++build_madt(void)
++{
++    int madt_size = (sizeof(struct multiple_apic_table)
++                     + sizeof(struct madt_processor_apic) * MaxCountCPUs
++                     + sizeof(struct madt_io_apic)
++                     + sizeof(struct madt_intsrcovr) * 16);
++    struct multiple_apic_table *madt = malloc_high(madt_size);
++    if (!madt) {
++        dprintf(1, "Not enough memory for madt!\n");
++        return NULL;
++    }
++    memset(madt, 0, madt_size);
++    madt->local_apic_address = cpu_to_le32(BUILD_APIC_ADDR);
++    madt->flags = cpu_to_le32(1);
++    struct madt_processor_apic *apic = (void*)&madt[1];
++    int i;
++    for (i=0; i<MaxCountCPUs; i++) {
++        apic->type = APIC_PROCESSOR;
++        apic->length = sizeof(*apic);
++        apic->processor_id = i;
++        apic->local_apic_id = i;
++        if (i < CountCPUs)
++            apic->flags = cpu_to_le32(1);
++        else
++            apic->flags = cpu_to_le32(0);
++        apic++;
++    }
++    struct madt_io_apic *io_apic = (void*)apic;
++    io_apic->type = APIC_IO;
++    io_apic->length = sizeof(*io_apic);
++    io_apic->io_apic_id = CountCPUs;
++    io_apic->address = cpu_to_le32(BUILD_IOAPIC_ADDR);
++    io_apic->interrupt = cpu_to_le32(0);
++
++    struct madt_intsrcovr *intsrcovr = (void*)&io_apic[1];
++    if (qemu_cfg_irq0_override()) {
++        memset(intsrcovr, 0, sizeof(*intsrcovr));
++        intsrcovr->type   = APIC_XRUPT_OVERRIDE;
++        intsrcovr->length = sizeof(*intsrcovr);
++        intsrcovr->source = 0;
++        intsrcovr->gsi    = 2;
++        intsrcovr->flags  = 0; /* conforms to bus specifications */
++        intsrcovr++;
++    }
++    for (i = 1; i < 16; i++) {
++        if (!(PCI_ISA_IRQ_MASK & (1 << i)))
++            /* No need for a INT source override structure. */
++            continue;
++        memset(intsrcovr, 0, sizeof(*intsrcovr));
++        intsrcovr->type   = APIC_XRUPT_OVERRIDE;
++        intsrcovr->length = sizeof(*intsrcovr);
++        intsrcovr->source = i;
++        intsrcovr->gsi    = i;
++        intsrcovr->flags  = 0xd; /* active high, level triggered */
++        intsrcovr++;
++    }
++
++    build_header((void*)madt, APIC_SIGNATURE, (void*)intsrcovr - (void*)madt, 1);
++    return madt;
++}
++
++#define SSDT_SIGNATURE 0x54445353 // SSDT
++static void*
++build_ssdt(void)
++{
++    int acpi_cpus = MaxCountCPUs > 0xff ? 0xff : MaxCountCPUs;
++    // calculate the length of processor block and scope block
++    // excluding PkgLength
++    int cpu_length = 13 * acpi_cpus + 4;
++
++    int length = sizeof(struct acpi_table_header) + 3 + cpu_length;
++    u8 *ssdt = malloc_high(length);
++    if (! ssdt) {
++        dprintf(1, "No space for ssdt!\n");
++        return NULL;
++    }
++
++    u8 *ssdt_ptr = ssdt;
++    ssdt_ptr[9] = 0; // checksum;
++    ssdt_ptr += sizeof(struct acpi_table_header);
++
++    // build processor scope header
++    *(ssdt_ptr++) = 0x10; // ScopeOp
++    if (cpu_length <= 0x3e) {
++        /* Handle 1-4 CPUs with one byte encoding */
++        *(ssdt_ptr++) = cpu_length + 1;
++    } else {
++        /* Handle 5-314 CPUs with two byte encoding */
++        *(ssdt_ptr++) = 0x40 | ((cpu_length + 2) & 0xf);
++        *(ssdt_ptr++) = (cpu_length + 2) >> 4;
++    }
++    *(ssdt_ptr++) = '_'; // Name
++    *(ssdt_ptr++) = 'P';
++    *(ssdt_ptr++) = 'R';
++    *(ssdt_ptr++) = '_';
++
++    // build object for each processor
++    int i;
++    for (i=0; i<acpi_cpus; i++) {
++        *(ssdt_ptr++) = 0x5B; // ProcessorOp
++        *(ssdt_ptr++) = 0x83;
++        *(ssdt_ptr++) = 0x0B; // Length
++        *(ssdt_ptr++) = 'C';  // Name (CPUxx)
++        *(ssdt_ptr++) = 'P';
++        if ((i & 0xf0) != 0)
++            *(ssdt_ptr++) = (i >> 4) < 0xa ? (i >> 4) + '0' : (i >> 4) + 'A' - 0xa;
++        else
++            *(ssdt_ptr++) = 'U';
++        *(ssdt_ptr++) = (i & 0xf) < 0xa ? (i & 0xf) + '0' : (i & 0xf) + 'A' - 0xa;
++        *(ssdt_ptr++) = i;
++        *(ssdt_ptr++) = 0x10; // Processor block address
++        *(ssdt_ptr++) = 0xb0;
++        *(ssdt_ptr++) = 0;
++        *(ssdt_ptr++) = 0;
++        *(ssdt_ptr++) = 6;    // Processor block length
++    }
++
++    build_header((void*)ssdt, SSDT_SIGNATURE, ssdt_ptr - ssdt, 1);
++
++    return ssdt;
++}
++
++#define HPET_SIGNATURE 0x54455048 //HPET
++static void*
++build_hpet(void)
++{
++    struct acpi_20_hpet *hpet = malloc_high(sizeof(*hpet));
++    if (!hpet) {
++        dprintf(1, "Not enough memory for hpet!\n");
++        return NULL;
++    }
++
++    memset(hpet, 0, sizeof(*hpet));
++    /* Note timer_block_id value must be kept in sync with value advertised by
++     * emulated hpet
++     */
++    hpet->timer_block_id = cpu_to_le32(0x8086a201);
++    hpet->addr.address = cpu_to_le32(ACPI_HPET_ADDRESS);
++    build_header((void*)hpet, HPET_SIGNATURE, sizeof(*hpet), 1);
++
++    return hpet;
++}
++
++static void
++acpi_build_srat_memory(struct srat_memory_affinity *numamem,
++                       u64 base, u64 len, int node, int enabled)
++{
++    numamem->type = SRAT_MEMORY;
++    numamem->length = sizeof(*numamem);
++    memset (numamem->proximity, 0 ,4);
++    numamem->proximity[0] = node;
++    numamem->flags = cpu_to_le32(!!enabled);
++    numamem->base_addr_low = base & 0xFFFFFFFF;
++    numamem->base_addr_high = base >> 32;
++    numamem->length_low = len & 0xFFFFFFFF;
++    numamem->length_high = len >> 32;
++}
++
++#define SRAT_SIGNATURE 0x54415253 //HPET
++static void *
++build_srat(void)
++{
++    int nb_numa_nodes = qemu_cfg_get_numa_nodes();
++
++    if (nb_numa_nodes == 0)
++        return NULL;
++
++    u64 *numadata = malloc_tmphigh(sizeof(u64) * (MaxCountCPUs + nb_numa_nodes));
++    if (!numadata) {
++        dprintf(1, "Not enough memory for read numa data from VM!\n");
++        return NULL;
++    }
++
++    qemu_cfg_get_numa_data(numadata, MaxCountCPUs + nb_numa_nodes);
++
++    struct system_resource_affinity_table *srat;
++    int srat_size = sizeof(*srat) +
++        sizeof(struct srat_processor_affinity) * MaxCountCPUs +
++        sizeof(struct srat_memory_affinity) * (nb_numa_nodes + 2);
++
++    srat = malloc_high(srat_size);
++    if (!srat) {
++        dprintf(1, "Not enough memory for srat table!\n");
++        return NULL;
++    }
++
++    memset(srat, 0, srat_size);
++    srat->reserved1=1;
++    struct srat_processor_affinity *core = (void*)(srat + 1);
++    int i;
++    u64 curnode;
++
++    for (i = 0; i < MaxCountCPUs; ++i) {
++        core->type = SRAT_PROCESSOR;
++        core->length = sizeof(*core);
++        core->local_apic_id = i;
++        curnode = *numadata++;
++        core->proximity_lo = curnode;
++        memset(core->proximity_hi, 0, 3);
++        core->local_sapic_eid = 0;
++        if (i < CountCPUs)
++            core->flags = cpu_to_le32(1);
++        else
++            core->flags = 0;
++        core++;
++    }
++
++
++    /* the memory map is a bit tricky, it contains at least one hole
++     * from 640k-1M and possibly another one from 3.5G-4G.
++     */
++    struct srat_memory_affinity *numamem = (void*)core;
++    int slots = 0;
++    u64 mem_len, mem_base, next_base = 0;
++
++    acpi_build_srat_memory(numamem, 0, 640*1024, 0, 1);
++    next_base = 1024 * 1024;
++    numamem++;
++    slots++;
++    for (i = 1; i < nb_numa_nodes + 1; ++i) {
++        mem_base = next_base;
++        mem_len = *numadata++;
++        if (i == 1)
++            mem_len -= 1024 * 1024;
++        next_base = mem_base + mem_len;
++
++        /* Cut out the PCI hole */
++        if (mem_base <= RamSize && next_base > RamSize) {
++            mem_len -= next_base - RamSize;
++            if (mem_len > 0) {
++                acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1);
++                numamem++;
++                slots++;
++            }
++            mem_base = 1ULL << 32;
++            mem_len = next_base - RamSize;
++            next_base += (1ULL << 32) - RamSize;
++        }
++        acpi_build_srat_memory(numamem, mem_base, mem_len, i-1, 1);
++        numamem++;
++        slots++;
++    }
++    for (; slots < nb_numa_nodes + 2; slots++) {
++        acpi_build_srat_memory(numamem, 0, 0, 0, 0);
++        numamem++;
++    }
++
++    build_header((void*)srat, SRAT_SIGNATURE, srat_size, 1);
++
++    return srat;
++}
++
++struct rsdp_descriptor *RsdpAddr;
++
++#define MAX_ACPI_TABLES 20
++void
++acpi_bios_init(void)
++{
++    if (! CONFIG_ACPI)
++        return;
++
++    dprintf(3, "init ACPI tables\n");
++
++    // This code is hardcoded for PIIX4 Power Management device.
++    int bdf = pci_find_device(PCI_VENDOR_ID_INTEL
++                              , PCI_DEVICE_ID_INTEL_82371AB_3);
++    if (bdf < 0)
++        // Device not found
++        return;
++
++    // Create initial rsdt table
++    struct rsdp_descriptor *rsdp = malloc_fseg(sizeof(*rsdp));
++    if (!rsdp) {
++        dprintf(1, "Not enough memory for acpi rsdp table!\n");
++        return;
++    }
++
++    u32 tables[MAX_ACPI_TABLES], tbl_idx = 0;
++
++#define ACPI_INIT_TABLE(X)                                   \
++    do {                                                     \
++        tables[tbl_idx] = (u32)(X);                          \
++        if (tables[tbl_idx])                                 \
++            tbl_idx++;                                       \
++    } while(0)
++
++    // Add tables
++    ACPI_INIT_TABLE(build_fadt(bdf));
++    ACPI_INIT_TABLE(build_ssdt());
++    ACPI_INIT_TABLE(build_madt());
++    ACPI_INIT_TABLE(build_hpet());
++    ACPI_INIT_TABLE(build_srat());
++
++    u16 i, external_tables = qemu_cfg_acpi_additional_tables();
++
++    for(i = 0; i < external_tables; i++) {
++        u16 len = qemu_cfg_next_acpi_table_len();
++        void *addr = malloc_high(len);
++        if (!addr) {
++            dprintf(1, "Not enough memory for ext acpi table of size %d!\n"
++                    , len);
++            continue;
++        }
++        ACPI_INIT_TABLE(qemu_cfg_next_acpi_table_load(addr, len));
++        if (tbl_idx == MAX_ACPI_TABLES) {
++            dprintf(1, "Too many external tables!\n");
++            break;
++        }
++    }
++
++    struct rsdt_descriptor_rev1 *rsdt;
++    size_t rsdt_len = sizeof(*rsdt) + sizeof(u32) * tbl_idx;
++    rsdt = malloc_high(rsdt_len);
++
++    if (!rsdt) {
++        dprintf(1, "Not enough memory for acpi rsdt table!\n");
++        return;
++    }
++    memset(rsdt, 0, rsdt_len);
++    memcpy(rsdt->table_offset_entry, tables, sizeof(u32) * tbl_idx);
++
++    build_header((void*)rsdt, RSDT_SIGNATURE, rsdt_len, 1);
++
++    // Build rsdp pointer table
++    memset(rsdp, 0, sizeof(*rsdp));
++    rsdp->signature = RSDP_SIGNATURE;
++    memcpy(rsdp->oem_id, CONFIG_APPNAME6, 6);
++    rsdp->rsdt_physical_address = cpu_to_le32((u32)rsdt);
++    rsdp->checksum -= checksum(rsdp, 20);
++    RsdpAddr = rsdp;
++    dprintf(1, "ACPI tables: RSDP=%p RSDT=%p\n", rsdp, rsdt);
++}
++
++u32
++find_resume_vector(void)
++{
++    dprintf(4, "rsdp=%p\n", RsdpAddr);
++    if (!RsdpAddr || RsdpAddr->signature != RSDP_SIGNATURE)
++        return 0;
++    struct rsdt_descriptor_rev1 *rsdt = (void*)RsdpAddr->rsdt_physical_address;
++    dprintf(4, "rsdt=%p\n", rsdt);
++    if (!rsdt || rsdt->signature != RSDT_SIGNATURE)
++        return 0;
++    void *end = (void*)rsdt + rsdt->length;
++    int i;
++    for (i=0; (void*)&rsdt->table_offset_entry[i] < end; i++) {
++        struct fadt_descriptor_rev1 *fadt = (void*)rsdt->table_offset_entry[i];
++        if (!fadt || fadt->signature != FACP_SIGNATURE)
++            continue;
++        dprintf(4, "fadt=%p\n", fadt);
++        struct facs_descriptor_rev1 *facs = (void*)fadt->firmware_ctrl;
++        dprintf(4, "facs=%p\n", facs);
++        if (! facs || facs->signature != FACS_SIGNATURE)
++            return 0;
++        // Found it.
++        dprintf(4, "resume addr=%d\n", facs->firmware_waking_vector);
++        return facs->firmware_waking_vector;
++    }
++    return 0;
++}
+--- x/roms/seabios/src/acpi.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/acpi.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,25 @@
++#ifndef __ACPI_H
++#define __ACPI_H
++
++#include "types.h" // u32
++
++void acpi_bios_init(void);
++u32 find_resume_vector(void);
++
++#define RSDP_SIGNATURE 0x2052545020445352LL // "RSD PTR "
++
++struct rsdp_descriptor {        /* Root System Descriptor Pointer */
++    u64 signature;              /* ACPI signature, contains "RSD PTR " */
++    u8  checksum;               /* To make sum of struct == 0 */
++    u8  oem_id [6];             /* OEM identification */
++    u8  revision;               /* Must be 0 for 1.0, 2 for 2.0 */
++    u32 rsdt_physical_address;  /* 32-bit physical address of RSDT */
++    u32 length;                 /* XSDT Length in bytes including hdr */
++    u64 xsdt_physical_address;  /* 64-bit physical address of XSDT */
++    u8  extended_checksum;      /* Checksum of entire table */
++    u8  reserved [3];           /* Reserved field must be 0 */
++};
++
++extern struct rsdp_descriptor *RsdpAddr;
++
++#endif // acpi.h
+--- x/roms/seabios/src/apm.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/apm.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,232 @@
++// Basic support for apmbios callbacks.
++//
++// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2005 Struan Bartlett
++// Copyright (C) 2004 Fabrice Bellard
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "farptr.h" // GET_VAR
++#include "bregs.h" // struct bregs
++#include "ioport.h" // outb
++#include "util.h" // wait_irq
++#include "config.h" // CONFIG_*
++#include "biosvar.h" // GET_GLOBAL
++
++static void
++out_str(const char *str_cs)
++{
++    if (CONFIG_COREBOOT) {
++        dprintf(1, "APM request '%s'\n", str_cs);
++        return;
++    }
++
++    u8 *s = (u8*)str_cs;
++    for (;;) {
++        u8 c = GET_GLOBAL(*s);
++        if (!c)
++            break;
++        outb(c, PORT_BIOS_APM);
++        s++;
++    }
++}
++
++// APM installation check
++static void
++handle_155300(struct bregs *regs)
++{
++    regs->ah = 1; // APM major version
++    regs->al = 2; // APM minor version
++    regs->bh = 'P';
++    regs->bl = 'M';
++    // bit 0 : 16 bit interface supported
++    // bit 1 : 32 bit interface supported
++    regs->cx = 0x03;
++    set_success(regs);
++}
++
++// APM real mode interface connect
++static void
++handle_155301(struct bregs *regs)
++{
++    set_success(regs);
++}
++
++// Assembler entry points defined in romlayout.S
++extern void apm16protected_entry(void);
++extern void apm32protected_entry(void);
++
++// APM 16 bit protected mode interface connect
++static void
++handle_155302(struct bregs *regs)
++{
++    regs->bx = (u32)apm16protected_entry;
++    regs->ax = SEG_BIOS; // 16 bit code segment base
++    regs->si = 0xfff0;   // 16 bit code segment size
++    regs->cx = SEG_BIOS; // data segment address
++    regs->di = 0xfff0;   // data segment length
++    set_success(regs);
++}
++
++// APM 32 bit protected mode interface connect
++static void
++handle_155303(struct bregs *regs)
++{
++    regs->ax = SEG_BIOS; // 32 bit code segment base
++    regs->ebx = (u32)apm32protected_entry;
++    regs->cx = SEG_BIOS; // 16 bit code segment base
++    // 32 bit code segment size (low 16 bits)
++    // 16 bit code segment size (high 16 bits)
++    regs->esi = 0xfff0fff0;
++    regs->dx = SEG_BIOS; // data segment address
++    regs->di = 0xfff0; // data segment length
++    set_success(regs);
++}
++
++// APM interface disconnect
++static void
++handle_155304(struct bregs *regs)
++{
++    set_success(regs);
++}
++
++// APM cpu idle
++static void
++handle_155305(struct bregs *regs)
++{
++    wait_irq();
++    set_success(regs);
++}
++
++// APM cpu busy
++static void
++handle_155306(struct bregs *regs)
++{
++    set_success(regs);
++}
++
++// APM Set Power State
++static void
++handle_155307(struct bregs *regs)
++{
++    if (regs->bx != 1) {
++        set_success(regs);
++        return;
++    }
++    switch (regs->cx) {
++    case 1:
++        out_str("Standby");
++        break;
++    case 2:
++        out_str("Suspend");
++        break;
++    case 3:
++        irq_disable();
++        out_str("Shutdown");
++        for (;;)
++            hlt();
++        break;
++    }
++    set_success(regs);
++}
++
++static void
++handle_155308(struct bregs *regs)
++{
++    set_success(regs);
++}
++
++// Get Power Status
++static void
++handle_15530a(struct bregs *regs)
++{
++    regs->bh = 0x01; // on line
++    regs->bl = 0xff; // unknown battery status
++    regs->ch = 0x80; // no system battery
++    regs->cl = 0xff; // unknown remaining time
++    regs->dx = 0xffff; // unknown remaining time
++    regs->si = 0x00; // zero battery
++    set_success(regs);
++}
++
++#define RET_ENOEVENT 0x80
++
++// Get PM Event
++static void
++handle_15530b(struct bregs *regs)
++{
++    set_code_invalid_silent(regs, RET_ENOEVENT);
++}
++
++// APM Driver Version
++static void
++handle_15530e(struct bregs *regs)
++{
++    regs->ah = 1;
++    regs->al = 2;
++    set_success(regs);
++}
++
++// APM Engage / Disengage
++static void
++handle_15530f(struct bregs *regs)
++{
++    set_success(regs);
++}
++
++// APM Get Capabilities
++static void
++handle_155310(struct bregs *regs)
++{
++    regs->bl = 0;
++    regs->cx = 0;
++    set_success(regs);
++}
++
++static void
++handle_1553XX(struct bregs *regs)
++{
++    set_unimplemented(regs);
++}
++
++void
++handle_1553(struct bregs *regs)
++{
++    if (! CONFIG_APMBIOS) {
++        set_code_invalid(regs, RET_EUNSUPPORTED);
++        return;
++    }
++
++    //debug_stub(regs);
++    switch (regs->al) {
++    case 0x00: handle_155300(regs); break;
++    case 0x01: handle_155301(regs); break;
++    case 0x02: handle_155302(regs); break;
++    case 0x03: handle_155303(regs); break;
++    case 0x04: handle_155304(regs); break;
++    case 0x05: handle_155305(regs); break;
++    case 0x06: handle_155306(regs); break;
++    case 0x07: handle_155307(regs); break;
++    case 0x08: handle_155308(regs); break;
++    case 0x0a: handle_15530a(regs); break;
++    case 0x0b: handle_15530b(regs); break;
++    case 0x0e: handle_15530e(regs); break;
++    case 0x0f: handle_15530f(regs); break;
++    case 0x10: handle_155310(regs); break;
++    default:   handle_1553XX(regs); break;
++    }
++}
++
++void VISIBLE16
++handle_apm16(struct bregs *regs)
++{
++    debug_enter(regs, DEBUG_HDL_apm);
++    handle_1553(regs);
++}
++
++void VISIBLE32SEG
++handle_apm32(struct bregs *regs)
++{
++    debug_enter(regs, DEBUG_HDL_apm);
++    handle_1553(regs);
++}
+--- x/roms/seabios/src/asm-offsets.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/asm-offsets.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,31 @@
++// Generate assembler offsets.
++
++#include "gen-defs.h" // OFFSET
++#include "bregs.h" // struct bregs
++#include "biosvar.h" // struct bios_data_area_s
++
++/* workaround for a warning with -Wmissing-prototypes */
++void foo(void) VISIBLE16;
++
++void foo(void)
++{
++    COMMENT("BREGS");
++    OFFSET(BREGS_es, bregs, es);
++    OFFSET(BREGS_ds, bregs, ds);
++    OFFSET(BREGS_eax, bregs, eax);
++    OFFSET(BREGS_ebx, bregs, ebx);
++    OFFSET(BREGS_ecx, bregs, ecx);
++    OFFSET(BREGS_edx, bregs, edx);
++    OFFSET(BREGS_ebp, bregs, ebp);
++    OFFSET(BREGS_esi, bregs, esi);
++    OFFSET(BREGS_edi, bregs, edi);
++    OFFSET(BREGS_flags, bregs, flags);
++    OFFSET(BREGS_code, bregs, code);
++
++    COMMENT("BDA");
++    OFFSET(BDA_ebda_seg, bios_data_area_s, ebda_seg);
++
++    COMMENT("EBDA");
++    DEFINE(EBDA_OFFSET_TOP_STACK, EBDA_OFFSET_TOP_STACK);
++    DEFINE(EBDA_SEGMENT_START, EBDA_SEGMENT_START);
++}
+--- x/roms/seabios/src/ata.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/ata.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,1068 @@
++// Low level ATA disk access
++//
++// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2002  MandrakeSoft S.A.
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "types.h" // u8
++#include "ioport.h" // inb
++#include "util.h" // dprintf
++#include "cmos.h" // inb_cmos
++#include "pic.h" // enable_hwirq
++#include "biosvar.h" // GET_EBDA
++#include "pci.h" // foreachpci
++#include "pci_ids.h" // PCI_CLASS_STORAGE_OTHER
++#include "pci_regs.h" // PCI_INTERRUPT_LINE
++#include "boot.h" // add_bcv_hd
++#include "disk.h" // struct ata_s
++#include "ata.h" // ATA_CB_STAT
++
++#define IDE_TIMEOUT 32000 //32 seconds max for IDE ops
++
++struct ata_channel_s ATA_channels[CONFIG_MAX_ATA_INTERFACES] VAR16VISIBLE;
++
++
++/****************************************************************
++ * Helper functions
++ ****************************************************************/
++
++// Wait for the specified ide state
++static inline int
++await_ide(u8 mask, u8 flags, u16 base, u16 timeout)
++{
++    u64 end = calc_future_tsc(timeout);
++    for (;;) {
++        u8 status = inb(base+ATA_CB_STAT);
++        if ((status & mask) == flags)
++            return status;
++        if (check_time(end)) {
++            dprintf(1, "IDE time out\n");
++            return -1;
++        }
++        yield();
++    }
++}
++
++// Wait for the device to be not-busy.
++static int
++await_not_bsy(u16 base)
++{
++    return await_ide(ATA_CB_STAT_BSY, 0, base, IDE_TIMEOUT);
++}
++
++// Wait for the device to be ready.
++static int
++await_rdy(u16 base)
++{
++    return await_ide(ATA_CB_STAT_RDY, ATA_CB_STAT_RDY, base, IDE_TIMEOUT);
++}
++
++// Wait for ide state - pauses for one ata cycle first.
++static inline int
++pause_await_not_bsy(u16 iobase1, u16 iobase2)
++{
++    // Wait one PIO transfer cycle.
++    inb(iobase2 + ATA_CB_ASTAT);
++
++    return await_not_bsy(iobase1);
++}
++
++// Wait for ide state - pause for 400ns first.
++static inline int
++ndelay_await_not_bsy(u16 iobase1)
++{
++    ndelay(400);
++    return await_not_bsy(iobase1);
++}
++
++// Reset a drive
++static void
++ata_reset(struct drive_s *drive_g)
++{
++    u8 ataid = GET_GLOBAL(drive_g->cntl_id);
++    u8 channel = ataid / 2;
++    u8 slave = ataid % 2;
++    u16 iobase1 = GET_GLOBAL(ATA_channels[channel].iobase1);
++    u16 iobase2 = GET_GLOBAL(ATA_channels[channel].iobase2);
++
++    dprintf(6, "ata_reset drive=%p\n", drive_g);
++    // Pulse SRST
++    outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN | ATA_CB_DC_SRST, iobase2+ATA_CB_DC);
++    udelay(5);
++    outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2+ATA_CB_DC);
++    msleep(2);
++
++    // wait for device to become not busy.
++    int status = await_not_bsy(iobase1);
++    if (status < 0)
++        goto done;
++    if (slave) {
++        // Change device.
++        u64 end = calc_future_tsc(IDE_TIMEOUT);
++        for (;;) {
++            outb(ATA_CB_DH_DEV1, iobase1 + ATA_CB_DH);
++            status = ndelay_await_not_bsy(iobase1);
++            if (status < 0)
++                goto done;
++            if (inb(iobase1 + ATA_CB_DH) == ATA_CB_DH_DEV1)
++                break;
++            // Change drive request failed to take effect - retry.
++            if (check_time(end)) {
++                dprintf(1, "ata_reset slave time out\n");
++                goto done;
++            }
++        }
++    } else {
++        // QEMU doesn't reset dh on reset, so set it explicitly.
++        outb(ATA_CB_DH_DEV0, iobase1 + ATA_CB_DH);
++    }
++
++    // On a user-reset request, wait for RDY if it is an ATA device.
++    u8 type=GET_GLOBAL(drive_g->type);
++    if (type == DTYPE_ATA)
++        status = await_rdy(iobase1);
++
++done:
++    // Enable interrupts
++    outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC);
++
++    dprintf(6, "ata_reset exit status=%x\n", status);
++}
++
++// Check for drive RDY for 16bit interface command.
++static int
++isready(struct drive_s *drive_g)
++{
++    // Read the status from controller
++    u8 ataid = GET_GLOBAL(drive_g->cntl_id);
++    u8 channel = ataid / 2;
++    u16 iobase1 = GET_GLOBAL(ATA_channels[channel].iobase1);
++    u8 status = inb(iobase1 + ATA_CB_STAT);
++    if ((status & (ATA_CB_STAT_BSY|ATA_CB_STAT_RDY)) == ATA_CB_STAT_RDY)
++        return DISK_RET_SUCCESS;
++    return DISK_RET_ENOTREADY;
++}
++
++// Default 16bit command demuxer for ATA and ATAPI devices.
++static int
++process_ata_misc_op(struct disk_op_s *op)
++{
++    if (!CONFIG_ATA)
++        return 0;
++
++    switch (op->command) {
++    case CMD_RESET:
++        ata_reset(op->drive_g);
++        return DISK_RET_SUCCESS;
++    case CMD_ISREADY:
++        return isready(op->drive_g);
++    case CMD_FORMAT:
++    case CMD_VERIFY:
++    case CMD_SEEK:
++        return DISK_RET_SUCCESS;
++    default:
++        op->count = 0;
++        return DISK_RET_EPARAM;
++    }
++}
++
++
++/****************************************************************
++ * ATA send command
++ ****************************************************************/
++
++struct ata_pio_command {
++    u8 feature;
++    u8 sector_count;
++    u8 lba_low;
++    u8 lba_mid;
++    u8 lba_high;
++    u8 device;
++    u8 command;
++
++    u8 feature2;
++    u8 sector_count2;
++    u8 lba_low2;
++    u8 lba_mid2;
++    u8 lba_high2;
++};
++
++// Send an ata command to the drive.
++static int
++send_cmd(struct drive_s *drive_g, struct ata_pio_command *cmd)
++{
++    u8 ataid = GET_GLOBAL(drive_g->cntl_id);
++    u8 channel = ataid / 2;
++    u8 slave = ataid % 2;
++    u16 iobase1 = GET_GLOBAL(ATA_channels[channel].iobase1);
++
++    // Select device
++    int status = await_not_bsy(iobase1);
++    if (status < 0)
++        return status;
++    u8 newdh = ((cmd->device & ~ATA_CB_DH_DEV1)
++                | (slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0));
++    u8 olddh = inb(iobase1 + ATA_CB_DH);
++    outb(newdh, iobase1 + ATA_CB_DH);
++    if ((olddh ^ newdh) & (1<<4)) {
++        // Was a device change - wait for device to become not busy.
++        status = ndelay_await_not_bsy(iobase1);
++        if (status < 0)
++            return status;
++    }
++
++    // Check for ATA_CMD_(READ|WRITE)_(SECTORS|DMA)_EXT commands.
++    if ((cmd->command & ~0x11) == ATA_CMD_READ_SECTORS_EXT) {
++        outb(cmd->feature2, iobase1 + ATA_CB_FR);
++        outb(cmd->sector_count2, iobase1 + ATA_CB_SC);
++        outb(cmd->lba_low2, iobase1 + ATA_CB_SN);
++        outb(cmd->lba_mid2, iobase1 + ATA_CB_CL);
++        outb(cmd->lba_high2, iobase1 + ATA_CB_CH);
++    }
++    outb(cmd->feature, iobase1 + ATA_CB_FR);
++    outb(cmd->sector_count, iobase1 + ATA_CB_SC);
++    outb(cmd->lba_low, iobase1 + ATA_CB_SN);
++    outb(cmd->lba_mid, iobase1 + ATA_CB_CL);
++    outb(cmd->lba_high, iobase1 + ATA_CB_CH);
++    outb(cmd->command, iobase1 + ATA_CB_CMD);
++
++    return 0;
++}
++
++// Wait for data after calling 'send_cmd'.
++static int
++ata_wait_data(u16 iobase1)
++{
++    int status = ndelay_await_not_bsy(iobase1);
++    if (status < 0)
++        return status;
++
++    if (status & ATA_CB_STAT_ERR) {
++        dprintf(6, "send_cmd : read error (status=%02x err=%02x)\n"
++                , status, inb(iobase1 + ATA_CB_ERR));
++        return -4;
++    }
++    if (!(status & ATA_CB_STAT_DRQ)) {
++        dprintf(6, "send_cmd : DRQ not set (status %02x)\n", status);
++        return -5;
++    }
++
++    return 0;
++}
++
++// Send an ata command that does not transfer any further data.
++int
++ata_cmd_nondata(struct drive_s *drive_g, struct ata_pio_command *cmd)
++{
++    u8 ataid = GET_GLOBAL(drive_g->cntl_id);
++    u8 channel = ataid / 2;
++    u16 iobase1 = GET_GLOBAL(ATA_channels[channel].iobase1);
++    u16 iobase2 = GET_GLOBAL(ATA_channels[channel].iobase2);
++
++    // Disable interrupts
++    outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2 + ATA_CB_DC);
++
++    int ret = send_cmd(drive_g, cmd);
++    if (ret)
++        goto fail;
++    ret = ndelay_await_not_bsy(iobase1);
++    if (ret < 0)
++        goto fail;
++
++    if (ret & ATA_CB_STAT_ERR) {
++        dprintf(6, "nondata cmd : read error (status=%02x err=%02x)\n"
++                , ret, inb(iobase1 + ATA_CB_ERR));
++        ret = -4;
++        goto fail;
++    }
++    if (ret & ATA_CB_STAT_DRQ) {
++        dprintf(6, "nondata cmd : DRQ set (status %02x)\n", ret);
++        ret = -5;
++        goto fail;
++    }
++
++fail:
++    // Enable interrupts
++    outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC);
++
++    return ret;
++}
++
++
++/****************************************************************
++ * ATA PIO transfers
++ ****************************************************************/
++
++// Transfer 'op->count' blocks (of 'blocksize' bytes) to/from drive
++// 'op->drive_g'.
++static int
++ata_pio_transfer(struct disk_op_s *op, int iswrite, int blocksize)
++{
++    dprintf(16, "ata_pio_transfer id=%p write=%d count=%d bs=%d buf=%p\n"
++            , op->drive_g, iswrite, op->count, blocksize, op->buf_fl);
++
++    u8 ataid = GET_GLOBAL(op->drive_g->cntl_id);
++    u8 channel = ataid / 2;
++    u16 iobase1 = GET_GLOBAL(ATA_channels[channel].iobase1);
++    u16 iobase2 = GET_GLOBAL(ATA_channels[channel].iobase2);
++    int count = op->count;
++    void *buf_fl = op->buf_fl;
++    int status;
++    for (;;) {
++        if (iswrite) {
++            // Write data to controller
++            dprintf(16, "Write sector id=%p dest=%p\n", op->drive_g, buf_fl);
++            if (CONFIG_ATA_PIO32)
++                outsl_fl(iobase1, buf_fl, blocksize / 4);
++            else
++                outsw_fl(iobase1, buf_fl, blocksize / 2);
++        } else {
++            // Read data from controller
++            dprintf(16, "Read sector id=%p dest=%p\n", op->drive_g, buf_fl);
++            if (CONFIG_ATA_PIO32)
++                insl_fl(iobase1, buf_fl, blocksize / 4);
++            else
++                insw_fl(iobase1, buf_fl, blocksize / 2);
++        }
++        buf_fl += blocksize;
++
++        status = pause_await_not_bsy(iobase1, iobase2);
++        if (status < 0) {
++            // Error
++            op->count -= count;
++            return status;
++        }
++
++        count--;
++        if (!count)
++            break;
++        status &= (ATA_CB_STAT_BSY | ATA_CB_STAT_DRQ | ATA_CB_STAT_ERR);
++        if (status != ATA_CB_STAT_DRQ) {
++            dprintf(6, "ata_pio_transfer : more sectors left (status %02x)\n"
++                    , status);
++            op->count -= count;
++            return -6;
++        }
++    }
++
++    status &= (ATA_CB_STAT_BSY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ
++               | ATA_CB_STAT_ERR);
++    if (!iswrite)
++        status &= ~ATA_CB_STAT_DF;
++    if (status != 0) {
++        dprintf(6, "ata_pio_transfer : no sectors left (status %02x)\n", status);
++        return -7;
++    }
++
++    return 0;
++}
++
++
++/****************************************************************
++ * ATA DMA transfers
++ ****************************************************************/
++
++#define BM_CMD    0
++#define  BM_CMD_MEMWRITE  0x08
++#define  BM_CMD_START     0x01
++#define BM_STATUS 2
++#define  BM_STATUS_IRQ    0x04
++#define  BM_STATUS_ERROR  0x02
++#define  BM_STATUS_ACTIVE 0x01
++#define BM_TABLE  4
++
++struct sff_dma_prd {
++    u32 buf_fl;
++    u32 count;
++};
++
++// Check if DMA available and setup transfer if so.
++static int
++ata_try_dma(struct disk_op_s *op, int iswrite, int blocksize)
++{
++    u32 dest = (u32)op->buf_fl;
++    if (dest & 1)
++        // Need minimum alignment of 1.
++        return -1;
++    u8 ataid = GET_GLOBAL(op->drive_g->cntl_id);
++    u8 channel = ataid / 2;
++    u16 iomaster = GET_GLOBAL(ATA_channels[channel].iomaster);
++    if (! iomaster)
++        return -1;
++    u32 bytes = op->count * blocksize;
++    if (! bytes)
++        return -1;
++
++    // Build PRD dma structure.
++    struct sff_dma_prd *dma = MAKE_FLATPTR(
++        get_ebda_seg()
++        , (void*)offsetof(struct extended_bios_data_area_s, extra_stack));
++    struct sff_dma_prd *origdma = dma;
++    while (bytes) {
++        if (dma >= &origdma[16])
++            // Too many descriptors..
++            return -1;
++        u32 count = bytes;
++        if (count > 0x10000)
++            count = 0x10000;
++        u32 max = 0x10000 - (dest & 0xffff);
++        if (count > max)
++            count = max;
++
++        SET_FLATPTR(dma->buf_fl, dest);
++        bytes -= count;
++        if (!bytes)
++            // Last descriptor.
++            count |= 1<<31;
++        dprintf(16, "dma@%p: %08x %08x\n", dma, dest, count);
++        dest += count;
++        SET_FLATPTR(dma->count, count);
++        dma++;
++    }
++
++    // Program bus-master controller.
++    outl((u32)origdma, iomaster + BM_TABLE);
++    u8 oldcmd = inb(iomaster + BM_CMD) & ~(BM_CMD_MEMWRITE|BM_CMD_START);
++    outb(oldcmd | (iswrite ? 0x00 : BM_CMD_MEMWRITE), iomaster + BM_CMD);
++    outb(BM_STATUS_ERROR|BM_STATUS_IRQ, iomaster + BM_STATUS);
++
++    return 0;
++}
++
++// Transfer data using DMA.
++static int
++ata_dma_transfer(struct disk_op_s *op)
++{
++    dprintf(16, "ata_dma_transfer id=%p buf=%p\n"
++            , op->drive_g, op->buf_fl);
++
++    u8 ataid = GET_GLOBAL(op->drive_g->cntl_id);
++    u8 channel = ataid / 2;
++    u16 iomaster = GET_GLOBAL(ATA_channels[channel].iomaster);
++
++    // Start bus-master controller.
++    u8 oldcmd = inb(iomaster + BM_CMD);
++    outb(oldcmd | BM_CMD_START, iomaster + BM_CMD);
++
++    u64 end = calc_future_tsc(IDE_TIMEOUT);
++    u8 status;
++    for (;;) {
++        status = inb(iomaster + BM_STATUS);
++        if (status & BM_STATUS_IRQ)
++            break;
++        // Transfer in progress
++        if (check_time(end)) {
++            // Timeout.
++            dprintf(1, "IDE DMA timeout\n");
++            break;
++        }
++        yield();
++    }
++    outb(oldcmd & ~BM_CMD_START, iomaster + BM_CMD);
++
++    u16 iobase1 = GET_GLOBAL(ATA_channels[channel].iobase1);
++    u16 iobase2 = GET_GLOBAL(ATA_channels[channel].iobase2);
++    int idestatus = pause_await_not_bsy(iobase1, iobase2);
++
++    if ((status & (BM_STATUS_IRQ|BM_STATUS_ACTIVE)) == BM_STATUS_IRQ
++        && idestatus >= 0x00
++        && (idestatus & (ATA_CB_STAT_BSY | ATA_CB_STAT_DF | ATA_CB_STAT_DRQ
++                         | ATA_CB_STAT_ERR)) == 0x00)
++        // Success.
++        return 0;
++
++    dprintf(6, "IDE DMA error (dma=%x ide=%x/%x/%x)\n", status, idestatus
++            , inb(iobase2 + ATA_CB_ASTAT), inb(iobase1 + ATA_CB_ERR));
++    op->count = 0;
++    return -1;
++}
++
++
++/****************************************************************
++ * ATA hard drive functions
++ ****************************************************************/
++
++// Transfer data to harddrive using PIO protocol.
++static int
++ata_pio_cmd_data(struct disk_op_s *op, int iswrite, struct ata_pio_command *cmd)
++{
++    u8 ataid = GET_GLOBAL(op->drive_g->cntl_id);
++    u8 channel = ataid / 2;
++    u16 iobase1 = GET_GLOBAL(ATA_channels[channel].iobase1);
++    u16 iobase2 = GET_GLOBAL(ATA_channels[channel].iobase2);
++
++    // Disable interrupts
++    outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2 + ATA_CB_DC);
++
++    int ret = send_cmd(op->drive_g, cmd);
++    if (ret)
++        goto fail;
++    ret = ata_wait_data(iobase1);
++    if (ret)
++        goto fail;
++    ret = ata_pio_transfer(op, iswrite, DISK_SECTOR_SIZE);
++
++fail:
++    // Enable interrupts
++    outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC);
++    return ret;
++}
++
++// Transfer data to harddrive using DMA protocol.
++static int
++ata_dma_cmd_data(struct disk_op_s *op, struct ata_pio_command *cmd)
++{
++    int ret = send_cmd(op->drive_g, cmd);
++    if (ret)
++        return ret;
++    return ata_dma_transfer(op);
++}
++
++// Read/write count blocks from a harddrive.
++static int
++ata_readwrite(struct disk_op_s *op, int iswrite)
++{
++    u64 lba = op->lba;
++
++    int usepio = ata_try_dma(op, iswrite, DISK_SECTOR_SIZE);
++
++    struct ata_pio_command cmd;
++    memset(&cmd, 0, sizeof(cmd));
++
++    if (op->count >= (1<<8) || lba + op->count >= (1<<28)) {
++        cmd.sector_count2 = op->count >> 8;
++        cmd.lba_low2 = lba >> 24;
++        cmd.lba_mid2 = lba >> 32;
++        cmd.lba_high2 = lba >> 40;
++        lba &= 0xffffff;
++
++        if (usepio)
++            cmd.command = (iswrite ? ATA_CMD_WRITE_SECTORS_EXT
++                           : ATA_CMD_READ_SECTORS_EXT);
++        else
++            cmd.command = (iswrite ? ATA_CMD_WRITE_DMA_EXT
++                           : ATA_CMD_READ_DMA_EXT);
++    } else {
++        if (usepio)
++            cmd.command = (iswrite ? ATA_CMD_WRITE_SECTORS
++                           : ATA_CMD_READ_SECTORS);
++        else
++            cmd.command = (iswrite ? ATA_CMD_WRITE_DMA
++                           : ATA_CMD_READ_DMA);
++    }
++
++    cmd.sector_count = op->count;
++    cmd.lba_low = lba;
++    cmd.lba_mid = lba >> 8;
++    cmd.lba_high = lba >> 16;
++    cmd.device = ((lba >> 24) & 0xf) | ATA_CB_DH_LBA;
++
++    int ret;
++    if (usepio)
++        ret = ata_pio_cmd_data(op, iswrite, &cmd);
++    else
++        ret = ata_dma_cmd_data(op, &cmd);
++    if (ret)
++        return DISK_RET_EBADTRACK;
++    return DISK_RET_SUCCESS;
++}
++
++// 16bit command demuxer for ATA harddrives.
++int
++process_ata_op(struct disk_op_s *op)
++{
++    if (!CONFIG_ATA)
++        return 0;
++
++    switch (op->command) {
++    case CMD_READ:
++        return ata_readwrite(op, 0);
++    case CMD_WRITE:
++        return ata_readwrite(op, 1);
++    default:
++        return process_ata_misc_op(op);
++    }
++}
++
++
++/****************************************************************
++ * ATAPI functions
++ ****************************************************************/
++
++// Low-level atapi command transmit function.
++static int
++atapi_cmd_data(struct disk_op_s *op, u8 *cmdbuf, u8 cmdlen, u16 blocksize)
++{
++    u8 ataid = GET_GLOBAL(op->drive_g->cntl_id);
++    u8 channel = ataid / 2;
++    u16 iobase1 = GET_GLOBAL(ATA_channels[channel].iobase1);
++    u16 iobase2 = GET_GLOBAL(ATA_channels[channel].iobase2);
++
++    struct ata_pio_command cmd;
++    memset(&cmd, 0, sizeof(cmd));
++    cmd.lba_mid = blocksize;
++    cmd.lba_high = blocksize >> 8;
++    cmd.command = ATA_CMD_PACKET;
++
++    // Disable interrupts
++    outb(ATA_CB_DC_HD15 | ATA_CB_DC_NIEN, iobase2 + ATA_CB_DC);
++
++    int ret = send_cmd(op->drive_g, &cmd);
++    if (ret)
++        goto fail;
++    ret = ata_wait_data(iobase1);
++    if (ret)
++        goto fail;
++
++    // Send command to device
++    outsw_fl(iobase1, MAKE_FLATPTR(GET_SEG(SS), cmdbuf), cmdlen / 2);
++
++    int status = pause_await_not_bsy(iobase1, iobase2);
++    if (status < 0) {
++        ret = status;
++        goto fail;
++    }
++
++    if (status & ATA_CB_STAT_ERR) {
++        u8 err = inb(iobase1 + ATA_CB_ERR);
++        // skip "Not Ready"
++        if (err != 0x20)
++            dprintf(6, "send_atapi_cmd : read error (status=%02x err=%02x)\n"
++                    , status, err);
++        ret = -2;
++        goto fail;
++    }
++    if (!(status & ATA_CB_STAT_DRQ)) {
++        dprintf(6, "send_atapi_cmd : DRQ not set (status %02x)\n", status);
++        ret = -3;
++        goto fail;
++    }
++
++    ret = ata_pio_transfer(op, 0, blocksize);
++
++fail:
++    // Enable interrupts
++    outb(ATA_CB_DC_HD15, iobase2+ATA_CB_DC);
++    return ret;
++}
++
++// Read sectors from the cdrom.
++int
++cdrom_read(struct disk_op_s *op)
++{
++    u8 atacmd[12];
++    memset(atacmd, 0, sizeof(atacmd));
++    atacmd[0]=0x28;                         // READ command
++    atacmd[7]=(op->count & 0xff00) >> 8;    // Sectors
++    atacmd[8]=(op->count & 0x00ff);
++    atacmd[2]=(op->lba & 0xff000000) >> 24; // LBA
++    atacmd[3]=(op->lba & 0x00ff0000) >> 16;
++    atacmd[4]=(op->lba & 0x0000ff00) >> 8;
++    atacmd[5]=(op->lba & 0x000000ff);
++
++    return atapi_cmd_data(op, atacmd, sizeof(atacmd), CDROM_SECTOR_SIZE);
++}
++
++// 16bit command demuxer for ATAPI cdroms.
++int
++process_atapi_op(struct disk_op_s *op)
++{
++    int ret;
++    switch (op->command) {
++    case CMD_READ:
++        ret = cdrom_read(op);
++        if (ret)
++            return DISK_RET_EBADTRACK;
++        return DISK_RET_SUCCESS;
++    case CMD_FORMAT:
++    case CMD_WRITE:
++        return DISK_RET_EWRITEPROTECT;
++    default:
++        return process_ata_misc_op(op);
++    }
++}
++
++// Send a simple atapi command to a drive.
++int
++ata_cmd_packet(struct drive_s *drive_g, u8 *cmdbuf, u8 cmdlen
++               , u32 length, void *buf_fl)
++{
++    struct disk_op_s dop;
++    memset(&dop, 0, sizeof(dop));
++    dop.drive_g = drive_g;
++    dop.count = 1;
++    dop.buf_fl = buf_fl;
++
++    return atapi_cmd_data(&dop, cmdbuf, cmdlen, length);
++}
++
++
++/****************************************************************
++ * ATA detect and init
++ ****************************************************************/
++
++// Send an identify device or identify device packet command.
++static int
++send_ata_identity(struct drive_s *drive_g, u16 *buffer, int command)
++{
++    memset(buffer, 0, DISK_SECTOR_SIZE);
++
++    struct disk_op_s dop;
++    memset(&dop, 0, sizeof(dop));
++    dop.drive_g = drive_g;
++    dop.count = 1;
++    dop.lba = 1;
++    dop.buf_fl = MAKE_FLATPTR(GET_SEG(SS), buffer);
++
++    struct ata_pio_command cmd;
++    memset(&cmd, 0, sizeof(cmd));
++    cmd.command = command;
++
++    return ata_pio_cmd_data(&dop, 0, &cmd);
++}
++
++// Extract the ATA/ATAPI version info.
++static int
++extract_version(u16 *buffer)
++{
++    // Extract ATA/ATAPI version.
++    u16 ataversion = buffer[80];
++    u8 version;
++    for (version=15; version>0; version--)
++        if (ataversion & (1<<version))
++            break;
++    return version;
++}
++
++// Extract common information from IDENTIFY commands.
++static void
++extract_identify(struct drive_s *drive_g, u16 *buffer)
++{
++    dprintf(3, "Identify w0=%x w2=%x\n", buffer[0], buffer[2]);
++
++    // Read model name
++    char *model = drive_g->model;
++    int maxsize = ARRAY_SIZE(drive_g->model);
++    int i;
++    for (i=0; i<maxsize/2; i++) {
++        u16 v = buffer[27+i];
++        model[i*2] = v >> 8;
++        model[i*2+1] = v & 0xff;
++    }
++    model[maxsize-1] = 0x00;
++
++    // Trim trailing spaces from model name.
++    for (i=maxsize-2; i>0 && model[i] == 0x20; i--)
++        model[i] = 0x00;
++
++    // Common flags.
++    SET_GLOBAL(drive_g->removable, (buffer[0] & 0x80) ? 1 : 0);
++    SET_GLOBAL(drive_g->cntl_info, extract_version(buffer));
++}
++
++// Print out a description of the given atapi drive.
++void
++describe_atapi(struct drive_s *drive_g)
++{
++    u8 ataid = drive_g->cntl_id;
++    u8 channel = ataid / 2;
++    u8 slave = ataid % 2;
++    u8 version = drive_g->cntl_info;
++    int iscd = drive_g->floppy_type;
++    printf("ata%d-%d: %s ATAPI-%d %s", channel, slave
++           , drive_g->model, version
++           , (iscd ? "CD-Rom/DVD-Rom" : "Device"));
++}
++
++// Detect if the given drive is an atapi - initialize it if so.
++static struct drive_s *
++init_drive_atapi(struct drive_s *dummy, u16 *buffer)
++{
++    // Send an IDENTIFY_DEVICE_PACKET command to device
++    int ret = send_ata_identity(dummy, buffer, ATA_CMD_IDENTIFY_PACKET_DEVICE);
++    if (ret)
++        return NULL;
++
++    // Success - setup as ATAPI.
++    struct drive_s *drive_g = allocDrive();
++    if (! drive_g)
++        return NULL;
++    SET_GLOBAL(drive_g->cntl_id, dummy->cntl_id);
++    extract_identify(drive_g, buffer);
++    SET_GLOBAL(drive_g->type, DTYPE_ATAPI);
++    SET_GLOBAL(drive_g->blksize, CDROM_SECTOR_SIZE);
++    SET_GLOBAL(drive_g->sectors, (u64)-1);
++    u8 iscd = ((buffer[0] >> 8) & 0x1f) == 0x05;
++    SET_GLOBAL(drive_g->floppy_type, iscd);
++
++    // fill cdidmap
++    if (iscd)
++        map_cd_drive(drive_g);
++
++    return drive_g;
++}
++
++// Print out a description of the given ata drive.
++void
++describe_ata(struct drive_s *drive_g)
++{
++    u8 ataid = drive_g->cntl_id;
++    u8 channel = ataid / 2;
++    u8 slave = ataid % 2;
++    u64 sectors = drive_g->sectors;
++    u8 version = drive_g->cntl_info;
++    char *model = drive_g->model;
++    printf("ata%d-%d: %s ATA-%d Hard-Disk", channel, slave, model, version);
++    u64 sizeinmb = sectors >> 11;
++    if (sizeinmb < (1 << 16))
++        printf(" (%u MiBytes)", (u32)sizeinmb);
++    else
++        printf(" (%u GiBytes)", (u32)(sizeinmb >> 10));
++}
++
++// Detect if the given drive is a regular ata drive - initialize it if so.
++static struct drive_s *
++init_drive_ata(struct drive_s *dummy, u16 *buffer)
++{
++    // Send an IDENTIFY_DEVICE command to device
++    int ret = send_ata_identity(dummy, buffer, ATA_CMD_IDENTIFY_DEVICE);
++    if (ret)
++        return NULL;
++
++    // Success - setup as ATA.
++    struct drive_s *drive_g = allocDrive();
++    if (! drive_g)
++        return NULL;
++    SET_GLOBAL(drive_g->cntl_id, dummy->cntl_id);
++    extract_identify(drive_g, buffer);
++    SET_GLOBAL(drive_g->type, DTYPE_ATA);
++    SET_GLOBAL(drive_g->blksize, DISK_SECTOR_SIZE);
++
++    SET_GLOBAL(drive_g->pchs.cylinders, buffer[1]);
++    SET_GLOBAL(drive_g->pchs.heads, buffer[3]);
++    SET_GLOBAL(drive_g->pchs.spt, buffer[6]);
++
++    u64 sectors;
++    if (buffer[83] & (1 << 10)) // word 83 - lba48 support
++        sectors = *(u64*)&buffer[100]; // word 100-103
++    else
++        sectors = *(u32*)&buffer[60]; // word 60 and word 61
++    SET_GLOBAL(drive_g->sectors, sectors);
++
++    // Setup disk geometry translation.
++    setup_translation(drive_g);
++
++    // Register with bcv system.
++    add_bcv_internal(drive_g);
++
++    return drive_g;
++}
++
++static u64 SpinupEnd;
++
++// Wait for non-busy status and check for "floating bus" condition.
++static int
++powerup_await_non_bsy(u16 base)
++{
++    u8 orstatus = 0;
++    u8 status;
++    for (;;) {
++        status = inb(base+ATA_CB_STAT);
++        if (!(status & ATA_CB_STAT_BSY))
++            break;
++        orstatus |= status;
++        if (orstatus == 0xff) {
++            dprintf(1, "powerup IDE floating\n");
++            return orstatus;
++        }
++        if (check_time(SpinupEnd)) {
++            dprintf(1, "powerup IDE time out\n");
++            return -1;
++        }
++        yield();
++    }
++    dprintf(6, "powerup iobase=%x st=%x\n", base, status);
++    return status;
++}
++
++// Detect any drives attached to a given controller.
++static void
++ata_detect(void *data)
++{
++    struct ata_channel_s *atachannel = data;
++    int startid = (atachannel - ATA_channels) * 2;
++    struct drive_s dummy;
++    memset(&dummy, 0, sizeof(dummy));
++    // Device detection
++    int ataid, last_reset_ataid=-1;
++    for (ataid=startid; ataid<startid+2; ataid++) {
++        u8 channel = ataid / 2;
++        u8 slave = ataid % 2;
++
++        u16 iobase1 = GET_GLOBAL(ATA_channels[channel].iobase1);
++        if (!iobase1)
++            break;
++
++        // Wait for not-bsy.
++        int status = powerup_await_non_bsy(iobase1);
++        if (status < 0)
++            continue;
++        u8 newdh = slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0;
++        outb(newdh, iobase1+ATA_CB_DH);
++        ndelay(400);
++        status = powerup_await_non_bsy(iobase1);
++        if (status < 0)
++            continue;
++
++        // Check if ioport registers look valid.
++        outb(newdh, iobase1+ATA_CB_DH);
++        u8 dh = inb(iobase1+ATA_CB_DH);
++        outb(0x55, iobase1+ATA_CB_SC);
++        outb(0xaa, iobase1+ATA_CB_SN);
++        u8 sc = inb(iobase1+ATA_CB_SC);
++        u8 sn = inb(iobase1+ATA_CB_SN);
++        dprintf(6, "ata_detect ataid=%d sc=%x sn=%x dh=%x\n"
++                , ataid, sc, sn, dh);
++        if (sc != 0x55 || sn != 0xaa || dh != newdh)
++            continue;
++
++        // Prepare new drive.
++        dummy.cntl_id = ataid;
++
++        // reset the channel
++        if (slave && ataid == last_reset_ataid + 1) {
++            // The drive was just reset - no need to reset it again.
++        } else {
++            ata_reset(&dummy);
++            last_reset_ataid = ataid;
++        }
++
++        // check for ATAPI
++        u16 buffer[256];
++        struct drive_s *drive_g = init_drive_atapi(&dummy, buffer);
++        if (!drive_g) {
++            // Didn't find an ATAPI drive - look for ATA drive.
++            u8 st = inb(iobase1+ATA_CB_STAT);
++            if (!st)
++                // Status not set - can't be a valid drive.
++                continue;
++
++            // Wait for RDY.
++            int ret = await_rdy(iobase1);
++            if (ret < 0)
++                continue;
++
++            // check for ATA.
++            drive_g = init_drive_ata(&dummy, buffer);
++            if (!drive_g)
++                // No ATA drive found
++                continue;
++        }
++
++        u16 resetresult = buffer[93];
++        dprintf(6, "ata_detect resetresult=%04x\n", resetresult);
++        if (!slave && (resetresult & 0xdf61) == 0x4041)
++            // resetresult looks valid and device 0 is responding to
++            // device 1 requests - device 1 must not be present - skip
++            // detection.
++            ataid++;
++    }
++}
++
++// Initialize an ata controller and detect its drives.
++static void
++init_controller(struct ata_channel_s *atachannel
++                , int bdf, int irq, u32 port1, u32 port2, u32 master)
++{
++    SET_GLOBAL(atachannel->irq, irq);
++    SET_GLOBAL(atachannel->pci_bdf, bdf);
++    SET_GLOBAL(atachannel->iobase1, port1);
++    SET_GLOBAL(atachannel->iobase2, port2);
++    SET_GLOBAL(atachannel->iomaster, master);
++    dprintf(1, "ATA controller %d at %x/%x/%x (irq %d dev %x)\n"
++            , atachannel - ATA_channels, port1, port2, master, irq, bdf);
++    run_thread(ata_detect, atachannel);
++}
++
++#define IRQ_ATA1 14
++#define IRQ_ATA2 15
++
++// Locate and init ata controllers.
++static void
++ata_init(void)
++{
++    // Scan PCI bus for ATA adapters
++    int count=0, pcicount=0;
++    int bdf, max;
++    foreachpci(bdf, max) {
++        pcicount++;
++        if (pci_config_readw(bdf, PCI_CLASS_DEVICE) != PCI_CLASS_STORAGE_IDE)
++            continue;
++        if (count >= ARRAY_SIZE(ATA_channels))
++            break;
++
++        u8 pciirq = pci_config_readb(bdf, PCI_INTERRUPT_LINE);
++        u8 prog_if = pci_config_readb(bdf, PCI_CLASS_PROG);
++        int master = 0;
++        if (prog_if & 0x80) {
++            // Check for bus-mastering.
++            u32 bar = pci_config_readl(bdf, PCI_BASE_ADDRESS_4);
++            if (bar & PCI_BASE_ADDRESS_SPACE_IO) {
++                master = bar & PCI_BASE_ADDRESS_IO_MASK;
++                pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER);
++            }
++        }
++
++        u32 port1, port2, irq;
++        if (prog_if & 1) {
++            port1 = pci_config_readl(bdf, PCI_BASE_ADDRESS_0) & ~3;
++            port2 = pci_config_readl(bdf, PCI_BASE_ADDRESS_1) & ~3;
++            irq = pciirq;
++        } else {
++            port1 = PORT_ATA1_CMD_BASE;
++            port2 = PORT_ATA1_CTRL_BASE;
++            irq = IRQ_ATA1;
++        }
++        init_controller(&ATA_channels[count], bdf, irq, port1, port2, master);
++        count++;
++
++        if (prog_if & 4) {
++            port1 = pci_config_readl(bdf, PCI_BASE_ADDRESS_2) & ~3;
++            port2 = pci_config_readl(bdf, PCI_BASE_ADDRESS_3) & ~3;
++            irq = pciirq;
++        } else {
++            port1 = PORT_ATA2_CMD_BASE;
++            port2 = PORT_ATA2_CTRL_BASE;
++            irq = IRQ_ATA2;
++        }
++        init_controller(&ATA_channels[count], bdf, irq, port1, port2
++                        , master ? master + 8 : 0);
++        count++;
++    }
++
++    if (!CONFIG_COREBOOT && !pcicount && ARRAY_SIZE(ATA_channels) >= 2) {
++        // No PCI devices found - probably a QEMU "-M isapc" machine.
++        // Try using ISA ports for ATA controllers.
++        init_controller(&ATA_channels[0], -1, IRQ_ATA1
++                        , PORT_ATA1_CMD_BASE, PORT_ATA1_CTRL_BASE, 0);
++        init_controller(&ATA_channels[1], -1, IRQ_ATA2
++                        , PORT_ATA2_CMD_BASE, PORT_ATA2_CTRL_BASE, 0);
++    }
++}
++
++void
++ata_setup(void)
++{
++    if (!CONFIG_ATA)
++        return;
++
++    dprintf(3, "init hard drives\n");
++
++    SpinupEnd = calc_future_tsc(IDE_TIMEOUT);
++    ata_init();
++
++    SET_BDA(disk_control_byte, 0xc0);
++
++    enable_hwirq(14, entry_76);
++}
+--- x/roms/seabios/src/ata.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/ata.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,149 @@
++#ifndef __ATA_H
++#define __ATA_H
++
++#include "types.h" // u8
++#include "config.h" // CONFIG_MAX_ATA_INTERFACES
++
++struct ata_channel_s {
++    u16 iobase1;
++    u16 iobase2;
++    u16 iomaster;
++    u8  irq;
++    int pci_bdf;
++};
++
++// ata.c
++extern struct ata_channel_s ATA_channels[CONFIG_MAX_ATA_INTERFACES];
++int cdrom_read(struct disk_op_s *op);
++int ata_cmd_packet(struct drive_s *drive_g, u8 *cmdbuf, u8 cmdlen
++                   , u32 length, void *buf_fl);
++void ata_setup(void);
++int process_ata_op(struct disk_op_s *op);
++int process_atapi_op(struct disk_op_s *op);
++void describe_ata(struct drive_s *drive_g);
++void describe_atapi(struct drive_s *drive_g);
++
++// Global defines -- ATA register and register bits.
++// command block & control block regs
++#define ATA_CB_DATA  0   // data reg         in/out pio_base_addr1+0
++#define ATA_CB_ERR   1   // error            in     pio_base_addr1+1
++#define ATA_CB_FR    1   // feature reg         out pio_base_addr1+1
++#define ATA_CB_SC    2   // sector count     in/out pio_base_addr1+2
++#define ATA_CB_SN    3   // sector number    in/out pio_base_addr1+3
++#define ATA_CB_CL    4   // cylinder low     in/out pio_base_addr1+4
++#define ATA_CB_CH    5   // cylinder high    in/out pio_base_addr1+5
++#define ATA_CB_DH    6   // device head      in/out pio_base_addr1+6
++#define ATA_CB_STAT  7   // primary status   in     pio_base_addr1+7
++#define ATA_CB_CMD   7   // command             out pio_base_addr1+7
++
++#define ATA_CB_ASTAT 2   // alternate status in     pio_base_addr2+2
++#define ATA_CB_DC    2   // device control      out pio_base_addr2+2
++#define ATA_CB_DA    3   // device address   in     pio_base_addr2+3
++
++#define ATA_CB_ER_ICRC 0x80    // ATA Ultra DMA bad CRC
++#define ATA_CB_ER_BBK  0x80    // ATA bad block
++#define ATA_CB_ER_UNC  0x40    // ATA uncorrected error
++#define ATA_CB_ER_MC   0x20    // ATA media change
++#define ATA_CB_ER_IDNF 0x10    // ATA id not found
++#define ATA_CB_ER_MCR  0x08    // ATA media change request
++#define ATA_CB_ER_ABRT 0x04    // ATA command aborted
++#define ATA_CB_ER_NTK0 0x02    // ATA track 0 not found
++#define ATA_CB_ER_NDAM 0x01    // ATA address mark not found
++
++#define ATA_CB_ER_P_SNSKEY 0xf0   // ATAPI sense key (mask)
++#define ATA_CB_ER_P_MCR    0x08   // ATAPI Media Change Request
++#define ATA_CB_ER_P_ABRT   0x04   // ATAPI command abort
++#define ATA_CB_ER_P_EOM    0x02   // ATAPI End of Media
++#define ATA_CB_ER_P_ILI    0x01   // ATAPI Illegal Length Indication
++
++// ATAPI Interrupt Reason bits in the Sector Count reg (CB_SC)
++#define ATA_CB_SC_P_TAG    0xf8   // ATAPI tag (mask)
++#define ATA_CB_SC_P_REL    0x04   // ATAPI release
++#define ATA_CB_SC_P_IO     0x02   // ATAPI I/O
++#define ATA_CB_SC_P_CD     0x01   // ATAPI C/D
++
++// bits 7-4 of the device/head (CB_DH) reg
++#define ATA_CB_DH_DEV0 0xa0    // select device 0
++#define ATA_CB_DH_DEV1 0xb0    // select device 1
++#define ATA_CB_DH_LBA 0x40    // use LBA
++
++// status reg (CB_STAT and CB_ASTAT) bits
++#define ATA_CB_STAT_BSY  0x80  // busy
++#define ATA_CB_STAT_RDY  0x40  // ready
++#define ATA_CB_STAT_DF   0x20  // device fault
++#define ATA_CB_STAT_WFT  0x20  // write fault (old name)
++#define ATA_CB_STAT_SKC  0x10  // seek complete
++#define ATA_CB_STAT_SERV 0x10  // service
++#define ATA_CB_STAT_DRQ  0x08  // data request
++#define ATA_CB_STAT_CORR 0x04  // corrected
++#define ATA_CB_STAT_IDX  0x02  // index
++#define ATA_CB_STAT_ERR  0x01  // error (ATA)
++#define ATA_CB_STAT_CHK  0x01  // check (ATAPI)
++
++// device control reg (CB_DC) bits
++#define ATA_CB_DC_HD15   0x08  // bit should always be set to one
++#define ATA_CB_DC_SRST   0x04  // soft reset
++#define ATA_CB_DC_NIEN   0x02  // disable interrupts
++
++// Most mandtory and optional ATA commands (from ATA-3),
++#define ATA_CMD_CFA_ERASE_SECTORS            0xC0
++#define ATA_CMD_CFA_REQUEST_EXT_ERR_CODE     0x03
++#define ATA_CMD_CFA_TRANSLATE_SECTOR         0x87
++#define ATA_CMD_CFA_WRITE_MULTIPLE_WO_ERASE  0xCD
++#define ATA_CMD_CFA_WRITE_SECTORS_WO_ERASE   0x38
++#define ATA_CMD_CHECK_POWER_MODE1            0xE5
++#define ATA_CMD_CHECK_POWER_MODE2            0x98
++#define ATA_CMD_DEVICE_RESET                 0x08
++#define ATA_CMD_EXECUTE_DEVICE_DIAGNOSTIC    0x90
++#define ATA_CMD_FLUSH_CACHE                  0xE7
++#define ATA_CMD_FORMAT_TRACK                 0x50
++#define ATA_CMD_IDENTIFY_DEVICE              0xEC
++#define ATA_CMD_IDENTIFY_PACKET_DEVICE       0xA1
++#define ATA_CMD_IDLE1                        0xE3
++#define ATA_CMD_IDLE2                        0x97
++#define ATA_CMD_IDLE_IMMEDIATE1              0xE1
++#define ATA_CMD_IDLE_IMMEDIATE2              0x95
++#define ATA_CMD_INITIALIZE_DRIVE_PARAMETERS  0x91
++#define ATA_CMD_INITIALIZE_DEVICE_PARAMETERS 0x91
++#define ATA_CMD_NOP                          0x00
++#define ATA_CMD_PACKET                       0xA0
++#define ATA_CMD_READ_BUFFER                  0xE4
++#define ATA_CMD_READ_DMA                     0xC8
++#define ATA_CMD_READ_DMA_EXT                 0x25
++#define ATA_CMD_READ_DMA_QUEUED              0xC7
++#define ATA_CMD_READ_DMA_QUEUED_EXT          0x26
++#define ATA_CMD_READ_LOG_EXT                 0x2F
++#define ATA_CMD_READ_MULTIPLE                0xC4
++#define ATA_CMD_READ_MULTIPLE_EXT            0x29
++#define ATA_CMD_READ_NATIVE_MAX_ADDRESS      0xF8
++#define ATA_CMD_READ_NATIVE_MAX_ADDRESS_EXT  0x27
++#define ATA_CMD_READ_SECTORS                 0x20
++#define ATA_CMD_READ_SECTORS_EXT             0x24
++#define ATA_CMD_READ_VERIFY_SECTORS          0x40
++#define ATA_CMD_READ_VERIFY_SECTORS_EXT      0x42
++#define ATA_CMD_RECALIBRATE                  0x10
++#define ATA_CMD_REQUEST_SENSE                0x03
++#define ATA_CMD_SEEK                         0x70
++#define ATA_CMD_SET_FEATURES                 0xEF
++#define ATA_CMD_SET_MAX                      0xF9
++#define ATA_CMD_SET_MAX_ADDRESS_EXT          0x37
++#define ATA_CMD_SET_MULTIPLE_MODE            0xC6
++#define ATA_CMD_SLEEP1                       0xE6
++#define ATA_CMD_SLEEP2                       0x99
++#define ATA_CMD_STANDBY1                     0xE2
++#define ATA_CMD_STANDBY2                     0x96
++#define ATA_CMD_STANDBY_IMMEDIATE1           0xE0
++#define ATA_CMD_STANDBY_IMMEDIATE2           0x94
++#define ATA_CMD_WRITE_BUFFER                 0xE8
++#define ATA_CMD_WRITE_DMA                    0xCA
++#define ATA_CMD_WRITE_DMA_EXT                0x35
++#define ATA_CMD_WRITE_DMA_QUEUED             0xCC
++#define ATA_CMD_WRITE_DMA_QUEUED_EXT         0x36
++#define ATA_CMD_WRITE_LOG_EXT                0x3F
++#define ATA_CMD_WRITE_MULTIPLE               0xC5
++#define ATA_CMD_WRITE_MULTIPLE_EXT           0x39
++#define ATA_CMD_WRITE_SECTORS                0x30
++#define ATA_CMD_WRITE_SECTORS_EXT            0x34
++#define ATA_CMD_WRITE_VERIFY                 0x3C
++
++#endif // ata.h
+--- x/roms/seabios/src/biosvar.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/biosvar.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,313 @@
++// Variable layouts of bios.
++//
++// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++#ifndef __BIOSVAR_H
++#define __BIOSVAR_H
++
++#include "types.h" // u8
++#include "farptr.h" // GET_FARVAR
++#include "config.h" // CONFIG_*
++#include "disk.h" // struct chs_s
++
++
++/****************************************************************
++ * Interupt vector table
++ ****************************************************************/
++
++struct rmode_IVT {
++    struct segoff_s ivec[256];
++};
++
++#define GET_IVT(vector)                                         \
++    GET_FARVAR(SEG_IVT, ((struct rmode_IVT *)0)->ivec[vector])
++#define SET_IVT(vector, segoff)                                         \
++    SET_FARVAR(SEG_IVT, ((struct rmode_IVT *)0)->ivec[vector], segoff)
++
++
++/****************************************************************
++ * Bios Data Area (BDA)
++ ****************************************************************/
++
++struct bios_data_area_s {
++    // 40:00
++    u16 port_com[4];
++    u16 port_lpt[3];
++    u16 ebda_seg;
++    // 40:10
++    u16 equipment_list_flags;
++    u8 pad1;
++    u16 mem_size_kb;
++    u8 pad2;
++    u8 ps2_ctrl_flag;
++    u8 kbd_flag0;
++    u8 kbd_flag1;
++    u8 alt_keypad;
++    u16 kbd_buf_head;
++    u16 kbd_buf_tail;
++    // 40:1e
++    u8 kbd_buf[32];
++    u8 floppy_recalibration_status;
++    u8 floppy_motor_status;
++    // 40:40
++    u8 floppy_motor_counter;
++    u8 floppy_last_status;
++    u8 floppy_return_status[7];
++    u8 video_mode;
++    u16 video_cols;
++    u16 video_pagesize;
++    u16 video_pagestart;
++    // 40:50
++    u16 cursor_pos[8];
++    // 40:60
++    u16 cursor_type;
++    u8 video_page;
++    u16 crtc_address;
++    u8 video_msr;
++    u8 video_pal;
++    struct segoff_s jump;
++    u8 other_6b;
++    u32 timer_counter;
++    // 40:70
++    u8 timer_rollover;
++    u8 break_flag;
++    u16 soft_reset_flag;
++    u8 disk_last_status;
++    u8 hdcount;
++    u8 disk_control_byte;
++    u8 port_disk;
++    u8 lpt_timeout[4];
++    u8 com_timeout[4];
++    // 40:80
++    u16 kbd_buf_start_offset;
++    u16 kbd_buf_end_offset;
++    u8 video_rows;
++    u16 char_height;
++    u8 video_ctl;
++    u8 video_switches;
++    u8 modeset_ctl;
++    u8 dcc_index;
++    u8 floppy_last_data_rate;
++    u8 disk_status_controller;
++    u8 disk_error_controller;
++    u8 disk_interrupt_flag;
++    u8 floppy_harddisk_info;
++    // 40:90
++    u8 floppy_media_state[4];
++    u8 floppy_track[2];
++    u8 kbd_flag2;
++    u8 kbd_led;
++    struct segoff_s user_wait_complete_flag;
++    u32 user_wait_timeout;
++    // 40:A0
++    u8 rtc_wait_flag;
++    u8 other_a1[7];
++    struct segoff_s video_savetable;
++    u8 other_ac[4];
++    // 40:B0
++    u8 other_b0[10];
++    u16 vbe_mode;
++} PACKED;
++
++// BDA floppy_recalibration_status bitdefs
++#define FRS_TIMEOUT (1<<7)
++
++// BDA rtc_wait_flag bitdefs
++#define RWS_WAIT_PENDING (1<<0)
++#define RWS_WAIT_ELAPSED (1<<7)
++
++// BDA floppy_media_state bitdefs
++#define FMS_DRIVE_STATE_MASK        (0x07)
++#define FMS_MEDIA_DRIVE_ESTABLISHED (1<<4)
++#define FMS_DOUBLE_STEPPING         (1<<5)
++#define FMS_DATA_RATE_MASK          (0xc0)
++
++// Accessor functions
++#define GET_BDA(var) \
++    GET_FARVAR(SEG_BDA, ((struct bios_data_area_s *)0)->var)
++#define SET_BDA(var, val) \
++    SET_FARVAR(SEG_BDA, ((struct bios_data_area_s *)0)->var, (val))
++#define CLEARBITS_BDA(var, val) do {                                    \
++        typeof(((struct bios_data_area_s *)0)->var) __val = GET_BDA(var); \
++        SET_BDA(var, (__val & ~(val)));                                 \
++    } while (0)
++#define SETBITS_BDA(var, val) do {                                      \
++        typeof(((struct bios_data_area_s *)0)->var) __val = GET_BDA(var); \
++        SET_BDA(var, (__val | (val)));                                  \
++    } while (0)
++
++
++/****************************************************************
++ * Extended Bios Data Area (EBDA)
++ ****************************************************************/
++
++// DPTE definition
++struct dpte_s {
++    u16 iobase1;
++    u16 iobase2;
++    u8  prefix;
++    u8  unused;
++    u8  irq;
++    u8  blkcount;
++    u8  dma;
++    u8  pio;
++    u16 options;
++    u16 reserved;
++    u8  revision;
++    u8  checksum;
++};
++
++// ElTorito Device Emulation data
++struct cdemu_s {
++    struct drive_s *emulated_drive;
++    u32 ilba;
++    u16 buffer_segment;
++    u16 load_segment;
++    u16 sector_count;
++    u8  active;
++    u8  media;
++    u8  emulated_extdrive;
++
++    // Virtual device
++    struct chs_s lchs;
++};
++
++struct fdpt_s {
++    u16 cylinders;
++    u8 heads;
++    u8 a0h_signature;
++    u8 phys_sectors;
++    u16 precompensation;
++    u8 reserved;
++    u8 drive_control_byte;
++    u16 phys_cylinders;
++    u8 phys_heads;
++    u16 landing_zone;
++    u8 sectors;
++    u8 checksum;
++} PACKED;
++
++struct extended_bios_data_area_s {
++    u8 size;
++    u8 reserved1[0x21];
++    struct segoff_s far_call_pointer;
++    u8 mouse_flag1;
++    u8 mouse_flag2;
++    u8 mouse_data[0x08];
++    // 0x30
++    u8 other1[0x0d];
++
++    // 0x3d
++    struct fdpt_s fdpt[2];
++
++    // 0x5d
++    u8 other2[0xC4];
++
++    // 0x121 - Begin custom storage.
++    u8 ps2ctr;
++    int RTCusers;
++
++    // El Torito Emulation data
++    struct cdemu_s cdemu;
++
++    // Buffer for disk DPTE table
++    struct dpte_s dpte;
++
++    // Locks for removable devices
++    u8 cdrom_locks[CONFIG_MAX_EXTDRIVE];
++
++    u16 boot_sequence;
++
++    // Stack space available for code that needs it.
++    u8 extra_stack[512] __aligned(8);
++
++    u8 cdemu_buf[2048 * !!CONFIG_CDROM_EMU];
++} PACKED;
++
++// The initial size and location of EBDA
++#define EBDA_SIZE_START \
++    DIV_ROUND_UP(sizeof(struct extended_bios_data_area_s), 1024)
++#define EBDA_SEGMENT_START \
++    FLATPTR_TO_SEG(BUILD_LOWRAM_END - EBDA_SIZE_START*1024)
++
++// Accessor functions
++static inline u16 get_ebda_seg(void) {
++    return GET_BDA(ebda_seg);
++}
++static inline struct extended_bios_data_area_s *
++get_ebda_ptr(void)
++{
++    ASSERT32FLAT();
++    return MAKE_FLATPTR(get_ebda_seg(), 0);
++}
++#define GET_EBDA2(eseg, var)                                            \
++    GET_FARVAR(eseg, ((struct extended_bios_data_area_s *)0)->var)
++#define SET_EBDA2(eseg, var, val)                                       \
++    SET_FARVAR(eseg, ((struct extended_bios_data_area_s *)0)->var, (val))
++#define GET_EBDA(var)                           \
++    GET_EBDA2(get_ebda_seg(), var)
++#define SET_EBDA(var, val)                      \
++    SET_EBDA2(get_ebda_seg(), var, (val))
++
++#define EBDA_OFFSET_TOP_STACK                                   \
++    offsetof(struct extended_bios_data_area_s, extra_stack[     \
++                 FIELD_SIZEOF(struct extended_bios_data_area_s  \
++                              , extra_stack)])
++
++
++/****************************************************************
++ * Global variables
++ ****************************************************************/
++
++#if MODE16 == 0 && MODESEGMENT == 1
++// In 32bit segmented mode %cs may not be readable and the code may be
++// relocated.  The entry code sets up %gs with a readable segment and
++// the code offset can be determined by get_global_offset().
++#define GLOBAL_SEGREG GS
++static inline u32 __attribute_const get_global_offset(void) {
++    u32 ret;
++    asm("  calll 1f\n"
++        "1:popl %0\n"
++        "  subl $1b, %0"
++        : "=r"(ret));
++    return ret;
++}
++#else
++#define GLOBAL_SEGREG CS
++static inline u32 __attribute_const get_global_offset(void) {
++    return 0;
++}
++#endif
++static inline u16 get_global_seg(void) {
++    return GET_SEG(GLOBAL_SEGREG);
++}
++#define GET_GLOBAL(var)                                                 \
++    GET_VAR(GLOBAL_SEGREG, *(typeof(&(var)))((void*)&(var)              \
++                                             + get_global_offset()))
++#define SET_GLOBAL(var, val) do {               \
++        ASSERT32FLAT();                         \
++        (var) = (val);                          \
++    } while (0)
++#if MODESEGMENT
++#define ADJUST_GLOBAL_PTR(var) (var)
++#else
++#define ADJUST_GLOBAL_PTR(var) ((typeof(var))((void*)var - BUILD_BIOS_ADDR))
++#endif
++
++
++/****************************************************************
++ * Bios Config Table
++ ****************************************************************/
++
++struct bios_config_table_s {
++    u16 size;
++    u8 model;
++    u8 submodel;
++    u8 biosrev;
++    u8 feature1, feature2, feature3, feature4, feature5;
++} PACKED;
++
++extern struct bios_config_table_s BIOS_CONFIG_TABLE __aligned(1);
++
++#endif // __BIOSVAR_H
+--- x/roms/seabios/src/block.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/block.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,375 @@
++// Disk setup and access
++//
++// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2002  MandrakeSoft S.A.
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "disk.h" // struct ata_s
++#include "biosvar.h" // GET_GLOBAL
++#include "cmos.h" // inb_cmos
++#include "util.h" // dprintf
++#include "ata.h" // process_ata_op
++
++struct drives_s Drives VAR16VISIBLE;
++
++struct drive_s *
++getDrive(u8 exttype, u8 extdriveoffset)
++{
++    // basic check : device has to be defined
++    if (extdriveoffset >= ARRAY_SIZE(Drives.idmap[0]))
++        return NULL;
++
++    // Get the ata channel
++    u8 driveid = GET_GLOBAL(Drives.idmap[exttype][extdriveoffset]);
++
++    // basic check : device has to be valid
++    if (driveid >= ARRAY_SIZE(Drives.drives))
++        return NULL;
++
++    return &Drives.drives[driveid];
++}
++
++struct drive_s *
++allocDrive(void)
++{
++    int driveid = Drives.drivecount;
++    if (driveid >= ARRAY_SIZE(Drives.drives))
++        return NULL;
++    Drives.drivecount++;
++    struct drive_s *drive_g = &Drives.drives[driveid];
++    memset(drive_g, 0, sizeof(*drive_g));
++    return drive_g;
++}
++
++
++/****************************************************************
++ * Disk geometry translation
++ ****************************************************************/
++
++static u8
++get_translation(struct drive_s *drive_g)
++{
++    u8 type = GET_GLOBAL(drive_g->type);
++    if (! CONFIG_COREBOOT && type == DTYPE_ATA) {
++        // Emulators pass in the translation info via nvram.
++        u8 ataid = GET_GLOBAL(drive_g->cntl_id);
++        u8 channel = ataid / 2;
++        u8 translation = inb_cmos(CMOS_BIOS_DISKTRANSFLAG + channel/2);
++        translation >>= 2 * (ataid % 4);
++        translation &= 0x03;
++        return translation;
++    }
++
++    // On COREBOOT, use a heuristic to determine translation type.
++    u16 heads = GET_GLOBAL(drive_g->pchs.heads);
++    u16 cylinders = GET_GLOBAL(drive_g->pchs.cylinders);
++    u16 spt = GET_GLOBAL(drive_g->pchs.spt);
++
++    if (cylinders <= 1024 && heads <= 16 && spt <= 63)
++        return TRANSLATION_NONE;
++    if (cylinders * heads <= 131072)
++        return TRANSLATION_LARGE;
++    return TRANSLATION_LBA;
++}
++
++void
++setup_translation(struct drive_s *drive_g)
++{
++    u8 translation = get_translation(drive_g);
++    SET_GLOBAL(drive_g->translation, translation);
++
++    u8 ataid = GET_GLOBAL(drive_g->cntl_id);
++    u8 channel = ataid / 2;
++    u8 slave = ataid % 2;
++    u16 heads = GET_GLOBAL(drive_g->pchs.heads);
++    u16 cylinders = GET_GLOBAL(drive_g->pchs.cylinders);
++    u16 spt = GET_GLOBAL(drive_g->pchs.spt);
++    u64 sectors = GET_GLOBAL(drive_g->sectors);
++    const char *desc = NULL;
++
++    switch (translation) {
++    default:
++    case TRANSLATION_NONE:
++        desc = "none";
++        break;
++    case TRANSLATION_LBA:
++        desc = "lba";
++        spt = 63;
++        if (sectors > 63*255*1024) {
++            heads = 255;
++            cylinders = 1024;
++            break;
++        }
++        u32 sect = (u32)sectors / 63;
++        heads = sect / 1024;
++        if (heads>128)
++            heads = 255;
++        else if (heads>64)
++            heads = 128;
++        else if (heads>32)
++            heads = 64;
++        else if (heads>16)
++            heads = 32;
++        else
++            heads = 16;
++        cylinders = sect / heads;
++        break;
++    case TRANSLATION_RECHS:
++        desc = "r-echs";
++        // Take care not to overflow
++        if (heads==16) {
++            if (cylinders>61439)
++                cylinders=61439;
++            heads=15;
++            cylinders = (u16)((u32)(cylinders)*16/15);
++        }
++        // then go through the large bitshift process
++    case TRANSLATION_LARGE:
++        if (translation == TRANSLATION_LARGE)
++            desc = "large";
++        while (cylinders > 1024) {
++            cylinders >>= 1;
++            heads <<= 1;
++
++            // If we max out the head count
++            if (heads > 127)
++                break;
++        }
++        break;
++    }
++    // clip to 1024 cylinders in lchs
++    if (cylinders > 1024)
++        cylinders = 1024;
++    dprintf(1, "ata%d-%d: PCHS=%u/%d/%d translation=%s LCHS=%d/%d/%d\n"
++            , channel, slave
++            , drive_g->pchs.cylinders, drive_g->pchs.heads, drive_g->pchs.spt
++            , desc
++            , cylinders, heads, spt);
++
++    SET_GLOBAL(drive_g->lchs.heads, heads);
++    SET_GLOBAL(drive_g->lchs.cylinders, cylinders);
++    SET_GLOBAL(drive_g->lchs.spt, spt);
++}
++
++
++/****************************************************************
++ * Drive mapping
++ ****************************************************************/
++
++// Fill in Fixed Disk Parameter Table (located in ebda).
++static void
++fill_fdpt(struct drive_s *drive_g, int hdid)
++{
++    if (hdid > 1)
++        return;
++
++    u16 nlc   = GET_GLOBAL(drive_g->lchs.cylinders);
++    u16 nlh   = GET_GLOBAL(drive_g->lchs.heads);
++    u16 nlspt = GET_GLOBAL(drive_g->lchs.spt);
++
++    u16 npc   = GET_GLOBAL(drive_g->pchs.cylinders);
++    u16 nph   = GET_GLOBAL(drive_g->pchs.heads);
++    u16 npspt = GET_GLOBAL(drive_g->pchs.spt);
++
++    struct fdpt_s *fdpt = &get_ebda_ptr()->fdpt[hdid];
++    fdpt->precompensation = 0xffff;
++    fdpt->drive_control_byte = 0xc0 | ((nph > 8) << 3);
++    fdpt->landing_zone = npc;
++    fdpt->cylinders = nlc;
++    fdpt->heads = nlh;
++    fdpt->sectors = nlspt;
++
++    if (nlc != npc || nlh != nph || nlspt != npspt) {
++        // Logical mapping present - use extended structure.
++
++        // complies with Phoenix style Translated Fixed Disk Parameter
++        // Table (FDPT)
++        fdpt->phys_cylinders = npc;
++        fdpt->phys_heads = nph;
++        fdpt->phys_sectors = npspt;
++        fdpt->a0h_signature = 0xa0;
++
++        // Checksum structure.
++        fdpt->checksum -= checksum(fdpt, sizeof(*fdpt));
++    }
++
++    if (hdid == 0)
++        SET_IVT(0x41, SEGOFF(get_ebda_seg(), offsetof(
++                                 struct extended_bios_data_area_s, fdpt[0])));
++    else
++        SET_IVT(0x46, SEGOFF(get_ebda_seg(), offsetof(
++                                 struct extended_bios_data_area_s, fdpt[1])));
++}
++
++// Map a drive (that was registered via add_bcv_hd)
++void
++map_hd_drive(struct drive_s *drive_g)
++{
++    // fill hdidmap
++    u8 hdcount = GET_BDA(hdcount);
++    if (hdcount >= ARRAY_SIZE(Drives.idmap[0]))
++        return;
++    dprintf(3, "Mapping hd drive %p to %d\n", drive_g, hdcount);
++    int driveid = drive_g - Drives.drives;
++    SET_GLOBAL(Drives.idmap[EXTTYPE_HD][hdcount], driveid);
++    SET_BDA(hdcount, hdcount + 1);
++
++    // Fill "fdpt" structure.
++    fill_fdpt(drive_g, hdcount);
++}
++
++// Find spot to add a drive
++static void
++add_ordered_drive(u8 *idmap, u8 *count, struct drive_s *drive_g)
++{
++    if (*count >= ARRAY_SIZE(Drives.idmap[0])) {
++        dprintf(1, "No room to map drive %p\n", drive_g);
++        return;
++    }
++    u8 *pos = &idmap[*count];
++    *count = *count + 1;
++    if (CONFIG_THREADS) {
++        // Add to idmap with assured drive order.
++        u8 *end = pos;
++        for (;;) {
++            u8 *prev = pos - 1;
++            if (prev < idmap)
++                break;
++            struct drive_s *prevdrive = &Drives.drives[*prev];
++            if (prevdrive->type < drive_g->type
++                || (prevdrive->type == drive_g->type
++                    && prevdrive->cntl_id < drive_g->cntl_id))
++                break;
++            pos--;
++        }
++        if (pos != end)
++            memmove(pos+1, pos, (void*)end-(void*)pos);
++    }
++    *pos = drive_g - Drives.drives;
++}
++
++// Map a cd
++void
++map_cd_drive(struct drive_s *drive_g)
++{
++    dprintf(3, "Mapping cd drive %p\n", drive_g);
++    add_ordered_drive(Drives.idmap[EXTTYPE_CD], &Drives.cdcount, drive_g);
++}
++
++// Map a floppy
++void
++map_floppy_drive(struct drive_s *drive_g)
++{
++    // fill idmap
++    dprintf(3, "Mapping floppy drive %p\n", drive_g);
++    add_ordered_drive(Drives.idmap[EXTTYPE_FLOPPY], &Drives.floppycount
++                      , drive_g);
++
++    // Update equipment word bits for floppy
++    if (Drives.floppycount == 1) {
++        // 1 drive, ready for boot
++        SETBITS_BDA(equipment_list_flags, 0x01);
++        SET_BDA(floppy_harddisk_info, 0x07);
++    } else if (Drives.floppycount >= 2) {
++        // 2 drives, ready for boot
++        SETBITS_BDA(equipment_list_flags, 0x41);
++        SET_BDA(floppy_harddisk_info, 0x77);
++    }
++}
++
++// Show a one line description (without trailing newline) of a drive.
++void
++describe_drive(struct drive_s *drive_g)
++{
++    ASSERT32FLAT();
++    u8 type = GET_GLOBAL(drive_g->type);
++    switch (type) {
++    case DTYPE_FLOPPY:
++        describe_floppy(drive_g);
++        break;
++    case DTYPE_ATA:
++        describe_ata(drive_g);
++        break;
++    case DTYPE_ATAPI:
++        describe_atapi(drive_g);
++        break;
++    case DTYPE_RAMDISK:
++        describe_ramdisk(drive_g);
++        break;
++    default:
++        printf("Unknown");
++        break;
++    }
++}
++
++
++/****************************************************************
++ * 16bit calling interface
++ ****************************************************************/
++
++// Execute a disk_op request.
++int
++process_op(struct disk_op_s *op)
++{
++    u8 type = GET_GLOBAL(op->drive_g->type);
++    switch (type) {
++    case DTYPE_FLOPPY:
++        return process_floppy_op(op);
++    case DTYPE_ATA:
++        return process_ata_op(op);
++    case DTYPE_ATAPI:
++        return process_atapi_op(op);
++    case DTYPE_RAMDISK:
++        return process_ramdisk_op(op);
++    case DTYPE_CDEMU:
++        return process_cdemu_op(op);
++    default:
++        op->count = 0;
++        return DISK_RET_EPARAM;
++    }
++}
++
++// Execute a "disk_op_s" request - this runs on a stack in the ebda.
++static int
++__send_disk_op(struct disk_op_s *op_far, u16 op_seg)
++{
++    struct disk_op_s dop;
++    memcpy_far(GET_SEG(SS), &dop
++               , op_seg, op_far
++               , sizeof(dop));
++
++    dprintf(DEBUG_HDL_13, "disk_op d=%p lba=%d buf=%p count=%d cmd=%d\n"
++            , dop.drive_g, (u32)dop.lba, dop.buf_fl
++            , dop.count, dop.command);
++
++    int status = process_op(&dop);
++
++    // Update count with total sectors transferred.
++    SET_FARVAR(op_seg, op_far->count, dop.count);
++
++    return status;
++}
++
++// Execute a "disk_op_s" request by jumping to a stack in the ebda.
++int
++send_disk_op(struct disk_op_s *op)
++{
++    if (! CONFIG_DRIVES)
++        return -1;
++    ASSERT16();
++
++    return stack_hop((u32)op, GET_SEG(SS), 0, __send_disk_op);
++}
++
++
++/****************************************************************
++ * Setup
++ ****************************************************************/
++
++void
++drive_setup(void)
++{
++    memset(&Drives, 0, sizeof(Drives));
++    memset(&Drives.idmap, 0xff, sizeof(Drives.idmap));
++}
+--- x/roms/seabios/src/boot.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/boot.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,508 @@
++// Code to load disk image and start system boot.
++//
++// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2002  MandrakeSoft S.A.
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "util.h" // dprintf
++#include "biosvar.h" // GET_EBDA
++#include "config.h" // CONFIG_*
++#include "disk.h" // cdrom_boot
++#include "bregs.h" // struct bregs
++#include "boot.h" // struct ipl_s
++#include "cmos.h" // inb_cmos
++#include "paravirt.h"
++
++struct ipl_s IPL;
++
++
++/****************************************************************
++ * IPL and BCV handlers
++ ****************************************************************/
++
++void
++boot_setup(void)
++{
++    if (! CONFIG_BOOT)
++        return;
++    dprintf(3, "init boot device ordering\n");
++
++    memset(&IPL, 0, sizeof(IPL));
++
++    // Floppy drive
++    struct ipl_entry_s *ie = &IPL.bev[0];
++    ie->type = IPL_TYPE_FLOPPY;
++    ie->description = "Floppy";
++    ie++;
++
++    // First HDD
++    ie->type = IPL_TYPE_HARDDISK;
++    ie->description = "Hard Disk";
++    ie++;
++
++    // CDROM
++    if (CONFIG_CDROM_BOOT) {
++        ie->type = IPL_TYPE_CDROM;
++        ie->description = "CD-Rom";
++        ie++;
++    }
++
++    if (CONFIG_COREBOOT_FLASH) {
++        ie->type = IPL_TYPE_CBFS;
++        ie->description = "CBFS";
++        ie++;
++    }
++
++    IPL.bevcount = ie - IPL.bev;
++    SET_EBDA(boot_sequence, 0xffff);
++    if (CONFIG_COREBOOT) {
++        // XXX - hardcode defaults for coreboot.
++        IPL.bootorder = 0x87654231;
++        IPL.checkfloppysig = 1;
++    } else {
++        // On emulators, get boot order from nvram.
++        IPL.bootorder = (inb_cmos(CMOS_BIOS_BOOTFLAG2)
++                         | ((inb_cmos(CMOS_BIOS_BOOTFLAG1) & 0xf0) << 4));
++        if (!(inb_cmos(CMOS_BIOS_BOOTFLAG1) & 1))
++            IPL.checkfloppysig = 1;
++    }
++}
++
++// Add a BEV vector for a given pnp compatible option rom.
++void
++add_bev(u16 seg, u16 bev, u16 desc)
++{
++    if (! CONFIG_BOOT)
++        return;
++    if (IPL.bevcount >= ARRAY_SIZE(IPL.bev))
++        return;
++
++    struct ipl_entry_s *ie = &IPL.bev[IPL.bevcount++];
++    ie->type = IPL_TYPE_BEV;
++    ie->vector = (seg << 16) | bev;
++    const char *d = "Unknown";
++    if (desc)
++        d = MAKE_FLATPTR(seg, desc);
++    ie->description = d;
++}
++
++// Add a bcv entry for an expansion card harddrive or legacy option rom
++void
++add_bcv(u16 seg, u16 ip, u16 desc)
++{
++    if (! CONFIG_BOOT)
++        return;
++    if (IPL.bcvcount >= ARRAY_SIZE(IPL.bcv))
++        return;
++
++    struct ipl_entry_s *ie = &IPL.bcv[IPL.bcvcount++];
++    ie->type = BCV_TYPE_EXTERNAL;
++    ie->vector = (seg << 16) | ip;
++    const char *d = "Legacy option rom";
++    if (desc)
++        d = MAKE_FLATPTR(seg, desc);
++    ie->description = d;
++}
++
++// Add a bcv entry for an internal harddrive
++void
++add_bcv_internal(struct drive_s *drive_g)
++{
++    if (! CONFIG_BOOT)
++        return;
++    if (IPL.bcvcount >= ARRAY_SIZE(IPL.bcv))
++        return;
++
++    struct ipl_entry_s *ie = &IPL.bcv[IPL.bcvcount++];
++    if (CONFIG_THREADS) {
++        // Add to bcv list with assured drive order.
++        struct ipl_entry_s *end = ie;
++        for (;;) {
++            struct ipl_entry_s *prev = ie - 1;
++            if (prev < IPL.bcv || prev->type != BCV_TYPE_INTERNAL)
++                break;
++            struct drive_s *prevdrive = (void*)prev->vector;
++            if (prevdrive->type < drive_g->type
++                || (prevdrive->type == drive_g->type
++                    && prevdrive->cntl_id < drive_g->cntl_id))
++                break;
++            ie--;
++        }
++        if (ie != end)
++            memmove(ie+1, ie, (void*)end-(void*)ie);
++    }
++    ie->type = BCV_TYPE_INTERNAL;
++    ie->vector = (u32)drive_g;
++    ie->description = "";
++}
++
++
++/****************************************************************
++ * Boot menu and BCV execution
++ ****************************************************************/
++
++// Show a generic menu item
++static int
++menu_show_default(struct ipl_entry_s *ie, int menupos)
++{
++    char desc[33];
++    printf("%d. %s\n", menupos
++           , strtcpy(desc, ie->description, ARRAY_SIZE(desc)));
++    return 1;
++}
++
++// Show floppy menu item - but only if there exists a floppy drive.
++static int
++menu_show_floppy(struct ipl_entry_s *ie, int menupos)
++{
++    int i;
++    for (i = 0; i < Drives.floppycount; i++) {
++        struct drive_s *drive_g = getDrive(EXTTYPE_FLOPPY, i);
++        printf("%d. Floppy [", menupos + i);
++        describe_drive(drive_g);
++        printf("]\n");
++    }
++    return Drives.floppycount;
++}
++
++// Show menu items from BCV list.
++static int
++menu_show_harddisk(struct ipl_entry_s *ie, int menupos)
++{
++    int i;
++    for (i = 0; i < IPL.bcvcount; i++) {
++        struct ipl_entry_s *ie = &IPL.bcv[i];
++        switch (ie->type) {
++        case BCV_TYPE_INTERNAL:
++            printf("%d. ", menupos + i);
++            describe_drive((void*)ie->vector);
++            printf("\n");
++            break;
++        default:
++            menu_show_default(ie, menupos+i);
++            break;
++        }
++    }
++    return IPL.bcvcount;
++}
++
++// Show cdrom menu item - but only if there exists a cdrom drive.
++static int
++menu_show_cdrom(struct ipl_entry_s *ie, int menupos)
++{
++    int i;
++    for (i = 0; i < Drives.cdcount; i++) {
++        struct drive_s *drive_g = getDrive(EXTTYPE_CD, i);
++        printf("%d. CD-Rom [", menupos + i);
++        describe_drive(drive_g);
++        printf("]\n");
++    }
++    return Drives.cdcount;
++}
++
++// Show coreboot-fs menu item.
++static int
++menu_show_cbfs(struct ipl_entry_s *ie, int menupos)
++{
++    int count = 0;
++    struct cbfs_file *file = NULL;
++    for (;;) {
++        file = cbfs_findprefix("img/", file);
++        if (!file)
++            break;
++        const char *filename = cbfs_filename(file);
++        printf("%d. Payload [%s]\n", menupos + count, &filename[4]);
++        count++;
++        if (count > 8)
++            break;
++    }
++    return count;
++}
++
++// Show IPL option menu.
++static void
++interactive_bootmenu(void)
++{
++    if (! CONFIG_BOOTMENU || ! qemu_cfg_show_boot_menu())
++        return;
++
++    while (get_keystroke(0) >= 0)
++        ;
++
++    printf("Press F12 for boot menu.\n\n");
++
++    int scan_code = get_keystroke(CONFIG_BOOTMENU_WAIT);
++    if (scan_code != 0x86)
++        /* not F12 */
++        return;
++
++    while (get_keystroke(0) >= 0)
++        ;
++
++    printf("Select boot device:\n\n");
++
++    int subcount[ARRAY_SIZE(IPL.bev)];
++    int menupos = 1;
++    int i;
++    for (i = 0; i < IPL.bevcount; i++) {
++        struct ipl_entry_s *ie = &IPL.bev[i];
++        int sc;
++        switch (ie->type) {
++        case IPL_TYPE_FLOPPY:
++            sc = menu_show_floppy(ie, menupos);
++            break;
++        case IPL_TYPE_HARDDISK:
++            sc = menu_show_harddisk(ie, menupos);
++            break;
++        case IPL_TYPE_CDROM:
++            sc = menu_show_cdrom(ie, menupos);
++            break;
++        case IPL_TYPE_CBFS:
++            sc = menu_show_cbfs(ie, menupos);
++            break;
++        default:
++            sc = menu_show_default(ie, menupos);
++            break;
++        }
++        subcount[i] = sc;
++        menupos += sc;
++    }
++
++    for (;;) {
++        scan_code = get_keystroke(1000);
++        if (scan_code == 0x01)
++            // ESC
++            break;
++        if (scan_code < 1 || scan_code > menupos)
++            continue;
++        int choice = scan_code - 1;
++
++        // Find out which IPL this was for.
++        int bev = 0;
++        while (choice > subcount[bev]) {
++            choice -= subcount[bev];
++            bev++;
++        }
++        IPL.bev[bev].subchoice = choice-1;
++
++        // Add user choice to the boot order.
++        IPL.bootorder = (IPL.bootorder << 4) | (bev+1);
++        break;
++    }
++    printf("\n");
++}
++
++// Run the specified bcv.
++static void
++run_bcv(struct ipl_entry_s *ie)
++{
++    switch (ie->type) {
++    case BCV_TYPE_INTERNAL:
++        map_hd_drive((void*)ie->vector);
++        break;
++    case BCV_TYPE_EXTERNAL:
++        call_bcv(ie->vector >> 16, ie->vector & 0xffff);
++        break;
++    }
++}
++
++// Prepare for boot - show menu and run bcvs.
++void
++boot_prep(void)
++{
++    if (! CONFIG_BOOT)
++        return;
++
++    // XXX - show available drives?
++
++    // Allow user to modify BCV/IPL order.
++    interactive_bootmenu();
++
++    // Setup floppy boot order
++    int override = IPL.bev[0].subchoice;
++    int tmp = Drives.idmap[EXTTYPE_FLOPPY][0];
++    Drives.idmap[EXTTYPE_FLOPPY][0] = Drives.idmap[EXTTYPE_FLOPPY][override];
++    Drives.idmap[EXTTYPE_FLOPPY][override] = tmp;
++
++    // Run BCVs
++    override = IPL.bev[1].subchoice;
++    if (override < IPL.bcvcount)
++        run_bcv(&IPL.bcv[override]);
++    int i;
++    for (i=0; i<IPL.bcvcount; i++)
++        if (i != override)
++            run_bcv(&IPL.bcv[i]);
++}
++
++
++/****************************************************************
++ * Boot code (int 18/19)
++ ****************************************************************/
++
++// Jump to a bootup entry point.
++static void
++call_boot_entry(u16 bootseg, u16 bootip, u8 bootdrv)
++{
++    dprintf(1, "Booting from %04x:%04x\n", bootseg, bootip);
++
++    struct bregs br;
++    memset(&br, 0, sizeof(br));
++    br.flags = F_IF;
++    br.code = SEGOFF(bootseg, bootip);
++    // Set the magic number in ax and the boot drive in dl.
++    br.dl = bootdrv;
++    br.ax = 0xaa55;
++    call16(&br);
++}
++
++// Boot from a disk (either floppy or harddrive)
++static void
++boot_disk(u8 bootdrv, int checksig)
++{
++    u16 bootseg = 0x07c0;
++
++    // Read sector
++    struct bregs br;
++    memset(&br, 0, sizeof(br));
++    br.flags = F_IF;
++    br.dl = bootdrv;
++    br.es = bootseg;
++    br.ah = 2;
++    br.al = 1;
++    br.cl = 1;
++    call16_int(0x13, &br);
++
++    if (br.flags & F_CF) {
++        printf("Boot failed: could not read the boot disk\n\n");
++        return;
++    }
++
++    if (checksig) {
++        struct mbr_s *mbr = (void*)0;
++        if (GET_FARVAR(bootseg, mbr->signature) != MBR_SIGNATURE) {
++            printf("Boot failed: not a bootable disk\n\n");
++            return;
++        }
++    }
++
++    /* Canonicalize bootseg:bootip */
++    u16 bootip = (bootseg & 0x0fff) << 4;
++    bootseg &= 0xf000;
++
++    call_boot_entry(bootseg, bootip, bootdrv);
++}
++
++// Boot from a CD-ROM
++static void
++boot_cdrom(struct ipl_entry_s *ie)
++{
++    if (! CONFIG_CDROM_BOOT)
++        return;
++    int status = cdrom_boot(ie->subchoice);
++    if (status) {
++        printf("Boot failed: Could not read from CDROM (code %04x)\n", status);
++        return;
++    }
++
++    u16 ebda_seg = get_ebda_seg();
++    u8 bootdrv = GET_EBDA2(ebda_seg, cdemu.emulated_extdrive);
++    u16 bootseg = GET_EBDA2(ebda_seg, cdemu.load_segment);
++    /* Canonicalize bootseg:bootip */
++    u16 bootip = (bootseg & 0x0fff) << 4;
++    bootseg &= 0xf000;
++
++    call_boot_entry(bootseg, bootip, bootdrv);
++}
++
++// Boot from a CBFS payload
++static void
++boot_cbfs(struct ipl_entry_s *ie)
++{
++    if (! CONFIG_COREBOOT_FLASH)
++        return;
++    int count = ie->subchoice;
++    struct cbfs_file *file = NULL;
++    for (;;) {
++        file = cbfs_findprefix("img/", file);
++        if (!file)
++            return;
++        if (count--)
++            continue;
++        cbfs_run_payload(file);
++    }
++}
++
++static void
++do_boot(u16 seq_nr)
++{
++    if (! CONFIG_BOOT)
++        panic("Boot support not compiled in.\n");
++
++    u32 bootdev = IPL.bootorder;
++    bootdev >>= 4 * seq_nr;
++    bootdev &= 0xf;
++
++    /* Translate bootdev to an IPL table offset by subtracting 1 */
++    bootdev -= 1;
++
++    if (bootdev >= IPL.bevcount) {
++        printf("No bootable device.\n");
++        // Loop with irqs enabled - this allows ctrl+alt+delete to work.
++        for (;;)
++            biosusleep(1000000);
++    }
++
++    /* Do the loading, and set up vector as a far pointer to the boot
++     * address, and bootdrv as the boot drive */
++    struct ipl_entry_s *ie = &IPL.bev[bootdev];
++    char desc[33];
++    printf("Booting from %s...\n"
++           , strtcpy(desc, ie->description, ARRAY_SIZE(desc)));
++
++    switch(ie->type) {
++    case IPL_TYPE_FLOPPY:
++        boot_disk(0x00, IPL.checkfloppysig);
++        break;
++    case IPL_TYPE_HARDDISK:
++        boot_disk(0x80, 1);
++        break;
++    case IPL_TYPE_CDROM:
++        boot_cdrom(ie);
++        break;
++    case IPL_TYPE_CBFS:
++        boot_cbfs(ie);
++        break;
++    case IPL_TYPE_BEV:
++        call_boot_entry(ie->vector >> 16, ie->vector & 0xffff, 0);
++        break;
++    }
++
++    // Boot failed: invoke the boot recovery function
++    struct bregs br;
++    memset(&br, 0, sizeof(br));
++    br.flags = F_IF;
++    call16_int(0x18, &br);
++}
++
++// Boot Failure recovery: try the next device.
++void VISIBLE32FLAT
++handle_18(void)
++{
++    debug_serial_setup();
++    debug_enter(NULL, DEBUG_HDL_18);
++    u16 ebda_seg = get_ebda_seg();
++    u16 seq = GET_EBDA2(ebda_seg, boot_sequence) + 1;
++    SET_EBDA2(ebda_seg, boot_sequence, seq);
++    do_boot(seq);
++}
++
++// INT 19h Boot Load Service Entry Point
++void VISIBLE32FLAT
++handle_19(void)
++{
++    debug_serial_setup();
++    debug_enter(NULL, DEBUG_HDL_19);
++    SET_EBDA(boot_sequence, 0);
++    do_boot(0);
++}
+--- x/roms/seabios/src/boot.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/boot.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,48 @@
++// Storage for boot definitions.
++#ifndef __BOOT_H
++#define __BOOT_H
++
++
++/****************************************************************
++ * Initial Program Load (IPL)
++ ****************************************************************/
++
++struct ipl_entry_s {
++    u16 type;
++    u16 subchoice;
++    u32 vector;
++    const char *description;
++};
++
++struct ipl_s {
++    struct ipl_entry_s bev[8];
++    struct ipl_entry_s bcv[8];
++    int bevcount, bcvcount;
++    u32 bootorder;
++    int checkfloppysig;
++};
++
++#define IPL_TYPE_FLOPPY      0x01
++#define IPL_TYPE_HARDDISK    0x02
++#define IPL_TYPE_CDROM       0x03
++#define IPL_TYPE_CBFS        0x20
++#define IPL_TYPE_BEV         0x80
++
++#define BCV_TYPE_EXTERNAL    0x80
++#define BCV_TYPE_INTERNAL    0x02
++
++
++/****************************************************************
++ * Function defs
++ ****************************************************************/
++
++// boot.c
++extern struct ipl_s IPL;
++void boot_setup(void);
++void add_bev(u16 seg, u16 bev, u16 desc);
++void add_bcv(u16 seg, u16 ip, u16 desc);
++struct drive_s;
++void add_bcv_internal(struct drive_s *drive_g);
++void boot_prep(void);
++
++#endif // __BOOT_H
+--- x/roms/seabios/src/bregs.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/bregs.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,119 @@
++// Structure layout of cpu registers the the bios uses.
++//
++// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#ifndef __BREGS_H
++#define __BREGS_H
++
++// CPU flag bitdefs
++#define F_CF (1<<0)
++#define F_ZF (1<<6)
++#define F_IF (1<<9)
++
++// CR0 flags
++#define CR0_PG (1<<31) // Paging
++#define CR0_CD (1<<30) // Cache disable
++#define CR0_NW (1<<29) // Not Write-through
++#define CR0_PE (1<<0)  // Protection enable
++
++
++#ifndef __ASSEMBLY__
++
++#include "farptr.h" // struct segoff_s
++
++/****************************************************************
++ * Registers saved/restored in romlayout.S
++ ****************************************************************/
++
++#include "types.h" // u16
++
++#define UREG(ER, R, RH, RL) union { u32 ER; struct { u16 R; u16 R ## _hi; }; struct { u8 RL; u8 RH; u8 R ## _hilo; u8 R ## _hihi; }; }
++
++// Layout of registers passed in to irq handlers.  Note that this
++// layout corresponds to code in romlayout.S - don't change it here
++// without also updating the assembler code.
++struct bregs {
++    u16 ds;
++    u16 es;
++    UREG(edi, di, di_hi, di_lo);
++    UREG(esi, si, si_hi, si_lo);
++    UREG(ebp, bp, bp_hi, bp_lo);
++    UREG(ebx, bx, bh, bl);
++    UREG(edx, dx, dh, dl);
++    UREG(ecx, cx, ch, cl);
++    UREG(eax, ax, ah, al);
++    struct segoff_s code;
++    u16 flags;
++} PACKED;
++
++
++/****************************************************************
++ * Helper functions
++ ****************************************************************/
++
++static inline void
++set_cf(struct bregs *regs, int cond)
++{
++    if (cond)
++        regs->flags |= F_CF;
++    else
++        regs->flags &= ~F_CF;
++}
++
++// Frequently used return codes
++#define RET_EUNSUPPORTED 0x86
++
++static inline void
++set_success(struct bregs *regs)
++{
++    set_cf(regs, 0);
++}
++
++static inline void
++set_code_success(struct bregs *regs)
++{
++    regs->ah = 0;
++    set_cf(regs, 0);
++}
++
++static inline void
++set_invalid_silent(struct bregs *regs)
++{
++    set_cf(regs, 1);
++}
++
++static inline void
++set_code_invalid_silent(struct bregs *regs, u8 code)
++{
++    regs->ah = code;
++    set_cf(regs, 1);
++}
++
++#define warn_invalid(regs)                      \
++    __warn_invalid((regs), __LINE__, __func__)
++#define set_invalid(regs)                       \
++    __set_invalid((regs), __LINE__, __func__)
++#define set_code_invalid(regs, code)                                    \
++    __set_code_invalid((regs), (code) | (__LINE__ << 8), __func__)
++
++#define warn_unimplemented(regs)                        \
++    __warn_unimplemented((regs), __LINE__, __func__)
++#define set_unimplemented(regs)                         \
++    __set_unimplemented((regs), __LINE__, __func__)
++#define set_code_unimplemented(regs, code)                              \
++    __set_code_unimplemented((regs), (code) | (__LINE__ << 8), __func__)
++
++// output.c
++void __warn_invalid(struct bregs *regs, int lineno, const char *fname);
++void __warn_unimplemented(struct bregs *regs, int lineno, const char *fname);
++void __set_invalid(struct bregs *regs, int lineno, const char *fname);
++void __set_unimplemented(struct bregs *regs, int lineno, const char *fname);
++void __set_code_invalid(struct bregs *regs, u32 linecode, const char *fname);
++void __set_code_unimplemented(struct bregs *regs, u32 linecode
++                              , const char *fname);
++
++#endif // !__ASSEMBLY__
++
++#endif // bregs.h
+--- x/roms/seabios/src/cdrom.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/cdrom.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,406 @@
++// Support for booting from cdroms (the "El Torito" spec).
++//
++// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2002  MandrakeSoft S.A.
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "disk.h" // cdrom_13
++#include "util.h" // memset
++#include "bregs.h" // struct bregs
++#include "biosvar.h" // GET_EBDA
++#include "ata.h" // ATA_CMD_REQUEST_SENSE
++
++
++/****************************************************************
++ * CD emulation
++ ****************************************************************/
++
++static int
++cdemu_read(struct disk_op_s *op)
++{
++    u16 ebda_seg = get_ebda_seg();
++    struct drive_s *drive_g = GET_EBDA2(ebda_seg, cdemu.emulated_drive);
++    struct disk_op_s dop;
++    dop.drive_g = drive_g;
++    dop.command = op->command;
++    dop.lba = GET_EBDA2(ebda_seg, cdemu.ilba) + op->lba / 4;
++
++    int count = op->count;
++    op->count = 0;
++    u8 *cdbuf_far = (void*)offsetof(struct extended_bios_data_area_s, cdemu_buf);
++
++    if (op->lba & 3) {
++        // Partial read of first block.
++        dop.count = 1;
++        dop.buf_fl = MAKE_FLATPTR(ebda_seg, cdbuf_far);
++        int ret = process_op(&dop);
++        if (ret)
++            return ret;
++        u8 thiscount = 4 - (op->lba & 3);
++        if (thiscount > count)
++            thiscount = count;
++        count -= thiscount;
++        memcpy_far(FLATPTR_TO_SEG(op->buf_fl)
++                   , (void*)FLATPTR_TO_OFFSET(op->buf_fl)
++                   , ebda_seg, cdbuf_far + (op->lba & 3) * 512
++                   , thiscount * 512);
++        op->buf_fl += thiscount * 512;
++        op->count += thiscount;
++        dop.lba++;
++    }
++
++    if (count > 3) {
++        // Read n number of regular blocks.
++        dop.count = count / 4;
++        dop.buf_fl = op->buf_fl;
++        int ret = process_op(&dop);
++        op->count += dop.count * 4;
++        if (ret)
++            return ret;
++        u8 thiscount = count & ~3;
++        count &= 3;
++        op->buf_fl += thiscount * 512;
++        dop.lba += thiscount / 4;
++    }
++
++    if (count) {
++        // Partial read on last block.
++        dop.count = 1;
++        dop.buf_fl = MAKE_FLATPTR(ebda_seg, cdbuf_far);
++        int ret = process_op(&dop);
++        if (ret)
++            return ret;
++        u8 thiscount = count;
++        memcpy_far(FLATPTR_TO_SEG(op->buf_fl)
++                   , (void*)FLATPTR_TO_OFFSET(op->buf_fl)
++                   , ebda_seg, cdbuf_far, thiscount * 512);
++        op->count += thiscount;
++    }
++
++    return DISK_RET_SUCCESS;
++}
++
++int
++process_cdemu_op(struct disk_op_s *op)
++{
++    if (!CONFIG_CDROM_EMU)
++        return 0;
++
++    switch (op->command) {
++    case CMD_READ:
++        return cdemu_read(op);
++    case CMD_WRITE:
++    case CMD_FORMAT:
++        return DISK_RET_EWRITEPROTECT;
++    case CMD_VERIFY:
++    case CMD_RESET:
++    case CMD_SEEK:
++    case CMD_ISREADY:
++        return DISK_RET_SUCCESS;
++    default:
++        op->count = 0;
++        return DISK_RET_EPARAM;
++    }
++}
++
++struct drive_s *cdemu_drive VAR16VISIBLE;
++
++void
++cdemu_setup(void)
++{
++    if (!CONFIG_CDROM_EMU)
++        return;
++
++    struct drive_s *drive_g = allocDrive();
++    if (!drive_g) {
++        cdemu_drive = NULL;
++        return;
++    }
++    cdemu_drive = ADJUST_GLOBAL_PTR(drive_g);
++    drive_g->type = DTYPE_CDEMU;
++    drive_g->blksize = DISK_SECTOR_SIZE;
++    drive_g->sectors = (u64)-1;
++}
++
++struct eltorito_s {
++    u8 size;
++    u8 media;
++    u8 emulated_drive;
++    u8 controller_index;
++    u32 ilba;
++    u16 device_spec;
++    u16 buffer_segment;
++    u16 load_segment;
++    u16 sector_count;
++    u8 cylinders;
++    u8 sectors;
++    u8 heads;
++};
++
++#define SET_INT13ET(regs,var,val)                                      \
++    SET_FARVAR((regs)->ds, ((struct eltorito_s*)((regs)->si+0))->var, (val))
++
++// ElTorito - Terminate disk emu
++void
++cdemu_134b(struct bregs *regs)
++{
++    // FIXME ElTorito Hardcoded
++    u16 ebda_seg = get_ebda_seg();
++    SET_INT13ET(regs, size, 0x13);
++    SET_INT13ET(regs, media, GET_EBDA2(ebda_seg, cdemu.media));
++    SET_INT13ET(regs, emulated_drive
++                , GET_EBDA2(ebda_seg, cdemu.emulated_extdrive));
++    struct drive_s *drive_g = GET_EBDA2(ebda_seg, cdemu.emulated_drive);
++    u8 cntl_id = GET_GLOBAL(drive_g->cntl_id);
++    SET_INT13ET(regs, controller_index, cntl_id / 2);
++    SET_INT13ET(regs, device_spec, cntl_id % 2);
++    SET_INT13ET(regs, ilba, GET_EBDA2(ebda_seg, cdemu.ilba));
++    SET_INT13ET(regs, buffer_segment, GET_EBDA2(ebda_seg, cdemu.buffer_segment));
++    SET_INT13ET(regs, load_segment, GET_EBDA2(ebda_seg, cdemu.load_segment));
++    SET_INT13ET(regs, sector_count, GET_EBDA2(ebda_seg, cdemu.sector_count));
++    SET_INT13ET(regs, cylinders, GET_EBDA2(ebda_seg, cdemu.lchs.cylinders));
++    SET_INT13ET(regs, sectors, GET_EBDA2(ebda_seg, cdemu.lchs.spt));
++    SET_INT13ET(regs, heads, GET_EBDA2(ebda_seg, cdemu.lchs.heads));
++
++    // If we have to terminate emulation
++    if (regs->al == 0x00) {
++        // FIXME ElTorito Various. Should be handled accordingly to spec
++        SET_EBDA2(ebda_seg, cdemu.active, 0x00); // bye bye
++    }
++
++    disk_ret(regs, DISK_RET_SUCCESS);
++}
++
++
++/****************************************************************
++ * CD booting
++ ****************************************************************/
++
++// Request SENSE
++static int
++atapi_get_sense(struct drive_s *drive_g, u8 *asc, u8 *ascq)
++{
++    u8 atacmd[12], buffer[18];
++    memset(atacmd, 0, sizeof(atacmd));
++    atacmd[0] = ATA_CMD_REQUEST_SENSE;
++    atacmd[4] = sizeof(buffer);
++    int ret = ata_cmd_packet(drive_g, atacmd, sizeof(atacmd), sizeof(buffer)
++                             , MAKE_FLATPTR(GET_SEG(SS), buffer));
++    if (ret)
++        return ret;
++
++    *asc = buffer[12];
++    *ascq = buffer[13];
++
++    return 0;
++}
++
++// Request capacity
++static int
++atapi_read_capacity(struct drive_s *drive_g, u32 *blksize, u32 *sectors)
++{
++    u8 packet[12], buf[8];
++    memset(packet, 0, sizeof(packet));
++    packet[0] = 0x25; /* READ CAPACITY */
++    int ret = ata_cmd_packet(drive_g, packet, sizeof(packet), sizeof(buf)
++                             , MAKE_FLATPTR(GET_SEG(SS), buf));
++    if (ret)
++        return ret;
++
++    *blksize = (((u32)buf[4] << 24) | ((u32)buf[5] << 16)
++                | ((u32)buf[6] << 8) | ((u32)buf[7] << 0));
++    *sectors = (((u32)buf[0] << 24) | ((u32)buf[1] << 16)
++                | ((u32)buf[2] << 8) | ((u32)buf[3] << 0));
++
++    return 0;
++}
++
++static int
++atapi_is_ready(struct drive_s *drive_g)
++{
++    dprintf(6, "atapi_is_ready (drive=%p)\n", drive_g);
++
++    /* Retry READ CAPACITY for 5 seconds unless MEDIUM NOT PRESENT is
++     * reported by the device.  If the device reports "IN PROGRESS",
++     * 30 seconds is added. */
++    u32 blksize, sectors;
++    int in_progress = 0;
++    u64 end = calc_future_tsc(5000);
++    for (;;) {
++        if (check_time(end)) {
++            dprintf(1, "read capacity failed\n");
++            return -1;
++        }
++
++        int ret = atapi_read_capacity(drive_g, &blksize, &sectors);
++        if (!ret)
++            // Success
++            break;
++
++        u8 asc, ascq;
++        ret = atapi_get_sense(drive_g, &asc, &ascq);
++        if (ret)
++            // Error - retry.
++            continue;
++
++        // Sense succeeded.
++        if (asc == 0x3a) { /* MEDIUM NOT PRESENT */
++            dprintf(1, "Device reports MEDIUM NOT PRESENT\n");
++            return -1;
++        }
++
++        if (asc == 0x04 && ascq == 0x01 && !in_progress) {
++            /* IN PROGRESS OF BECOMING READY */
++            printf("Waiting for device to detect medium... ");
++            /* Allow 30 seconds more */
++            end = calc_future_tsc(30000);
++            in_progress = 1;
++        }
++    }
++
++    if (blksize != GET_GLOBAL(drive_g->blksize)) {
++        printf("Unsupported sector size %u\n", blksize);
++        return -1;
++    }
++
++    dprintf(6, "sectors=%u\n", sectors);
++    printf("%dMB medium detected\n", sectors>>(20-11));
++    return 0;
++}
++
++int
++cdrom_boot(int cdid)
++{
++    struct drive_s *drive_g = getDrive(EXTTYPE_CD, cdid);
++    if (!drive_g)
++        return 1;
++
++    int ret = atapi_is_ready(drive_g);
++    if (ret)
++        dprintf(1, "atapi_is_ready returned %d\n", ret);
++
++    // Read the Boot Record Volume Descriptor
++    u8 buffer[2048];
++    struct disk_op_s dop;
++    memset(&dop, 0, sizeof(dop));
++    dop.drive_g = drive_g;
++    dop.lba = 0x11;
++    dop.count = 1;
++    dop.buf_fl = MAKE_FLATPTR(GET_SEG(SS), buffer);
++    ret = cdrom_read(&dop);
++    if (ret)
++        return 3;
++
++    // Validity checks
++    if (buffer[0])
++        return 4;
++    if (strcmp((char*)&buffer[1], "CD001\001EL TORITO SPECIFICATION") != 0)
++        return 5;
++
++    // ok, now we calculate the Boot catalog address
++    u32 lba = *(u32*)&buffer[0x47];
++
++    // And we read the Boot Catalog
++    dop.lba = lba;
++    ret = cdrom_read(&dop);
++    if (ret)
++        return 7;
++
++    // Validation entry
++    if (buffer[0x00] != 0x01)
++        return 8;   // Header
++    if (buffer[0x01] != 0x00)
++        return 9;   // Platform
++    if (buffer[0x1E] != 0x55)
++        return 10;  // key 1
++    if (buffer[0x1F] != 0xAA)
++        return 10;  // key 2
++
++    // Initial/Default Entry
++    if (buffer[0x20] != 0x88)
++        return 11; // Bootable
++
++    u16 ebda_seg = get_ebda_seg();
++    u8 media = buffer[0x21];
++    SET_EBDA2(ebda_seg, cdemu.media, media);
++
++    SET_EBDA2(ebda_seg, cdemu.emulated_drive, ADJUST_GLOBAL_PTR(drive_g));
++
++    u16 boot_segment = *(u16*)&buffer[0x22];
++    if (!boot_segment)
++        boot_segment = 0x07C0;
++    SET_EBDA2(ebda_seg, cdemu.load_segment, boot_segment);
++    SET_EBDA2(ebda_seg, cdemu.buffer_segment, 0x0000);
++
++    u16 nbsectors = *(u16*)&buffer[0x26];
++    SET_EBDA2(ebda_seg, cdemu.sector_count, nbsectors);
++
++    lba = *(u32*)&buffer[0x28];
++    SET_EBDA2(ebda_seg, cdemu.ilba, lba);
++
++    // And we read the image in memory
++    dop.lba = lba;
++    dop.count = DIV_ROUND_UP(nbsectors, 4);
++    dop.buf_fl = MAKE_FLATPTR(boot_segment, 0);
++    ret = cdrom_read(&dop);
++    if (ret)
++        return 12;
++
++    if (media == 0) {
++        // No emulation requested - return success.
++        SET_EBDA2(ebda_seg, cdemu.emulated_extdrive, EXTSTART_CD + cdid);
++        return 0;
++    }
++
++    // Emulation of a floppy/harddisk requested
++    if (! CONFIG_CDROM_EMU || !cdemu_drive)
++        return 13;
++
++    // Set emulated drive id and increase bios installed hardware
++    // number of devices
++    if (media < 4) {
++        // Floppy emulation
++        SET_EBDA2(ebda_seg, cdemu.emulated_extdrive, 0x00);
++        SETBITS_BDA(equipment_list_flags, 0x41);
++
++        switch (media) {
++        case 0x01:  // 1.2M floppy
++            SET_EBDA2(ebda_seg, cdemu.lchs.spt, 15);
++            SET_EBDA2(ebda_seg, cdemu.lchs.cylinders, 80);
++            SET_EBDA2(ebda_seg, cdemu.lchs.heads, 2);
++            break;
++        case 0x02:  // 1.44M floppy
++            SET_EBDA2(ebda_seg, cdemu.lchs.spt, 18);
++            SET_EBDA2(ebda_seg, cdemu.lchs.cylinders, 80);
++            SET_EBDA2(ebda_seg, cdemu.lchs.heads, 2);
++            break;
++        case 0x03:  // 2.88M floppy
++            SET_EBDA2(ebda_seg, cdemu.lchs.spt, 36);
++            SET_EBDA2(ebda_seg, cdemu.lchs.cylinders, 80);
++            SET_EBDA2(ebda_seg, cdemu.lchs.heads, 2);
++            break;
++        }
++    } else {
++        // Harddrive emulation
++        SET_EBDA2(ebda_seg, cdemu.emulated_extdrive, 0x80);
++        SET_BDA(hdcount, GET_BDA(hdcount) + 1);
++
++        // Peak at partition table to get chs.
++        struct mbr_s *mbr = (void*)0;
++        u8 sptcyl = GET_FARVAR(boot_segment, mbr->partitions[0].last.sptcyl);
++        u8 cyllow = GET_FARVAR(boot_segment, mbr->partitions[0].last.cyllow);
++        u8 heads = GET_FARVAR(boot_segment, mbr->partitions[0].last.heads);
++
++        SET_EBDA2(ebda_seg, cdemu.lchs.spt, sptcyl & 0x3f);
++        SET_EBDA2(ebda_seg, cdemu.lchs.cylinders
++                  , ((sptcyl<<2)&0x300) + cyllow + 1);
++        SET_EBDA2(ebda_seg, cdemu.lchs.heads, heads + 1);
++    }
++
++    // everything is ok, so from now on, the emulation is active
++    SET_EBDA2(ebda_seg, cdemu.active, 0x01);
++    dprintf(6, "cdemu media=%d\n", media);
++
++    return 0;
++}
+--- x/roms/seabios/src/clock.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/clock.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,623 @@
++// 16bit code to handle system clocks.
++//
++// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2002  MandrakeSoft S.A.
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "biosvar.h" // SET_BDA
++#include "util.h" // debug_enter
++#include "disk.h" // floppy_tick
++#include "cmos.h" // inb_cmos
++#include "pic.h" // eoi_pic1
++#include "bregs.h" // struct bregs
++#include "biosvar.h" // GET_GLOBAL
++#include "usb-hid.h" // usb_check_key
++
++// RTC register flags
++#define RTC_A_UIP 0x80
++
++#define RTC_B_SET  0x80
++#define RTC_B_PIE  0x40
++#define RTC_B_AIE  0x20
++#define RTC_B_UIE  0x10
++#define RTC_B_BIN  0x04
++#define RTC_B_24HR 0x02
++#define RTC_B_DSE  0x01
++
++
++// Bits for PORT_PS2_CTRLB
++#define PPCB_T2GATE (1<<0)
++#define PPCB_SPKR   (1<<1)
++#define PPCB_T2OUT  (1<<5)
++
++// Bits for PORT_PIT_MODE
++#define PM_SEL_TIMER0   (0<<6)
++#define PM_SEL_TIMER1   (1<<6)
++#define PM_SEL_TIMER2   (2<<6)
++#define PM_SEL_READBACK (3<<6)
++#define PM_ACCESS_LATCH  (0<<4)
++#define PM_ACCESS_LOBYTE (1<<4)
++#define PM_ACCESS_HIBYTE (2<<4)
++#define PM_ACCESS_WORD   (3<<4)
++#define PM_MODE0 (0<<1)
++#define PM_MODE1 (1<<1)
++#define PM_MODE2 (2<<1)
++#define PM_MODE3 (3<<1)
++#define PM_MODE4 (4<<1)
++#define PM_MODE5 (5<<1)
++#define PM_CNT_BINARY (0<<0)
++#define PM_CNT_BCD    (1<<0)
++
++
++/****************************************************************
++ * TSC timer
++ ****************************************************************/
++
++#define PIT_TICK_RATE 1193180   // Underlying HZ of PIT
++#define PIT_TICK_INTERVAL 65536 // Default interval for 18.2Hz timer
++#define TICKS_PER_DAY (u32)((u64)60*60*24*PIT_TICK_RATE / PIT_TICK_INTERVAL)
++#define CALIBRATE_COUNT 0x800   // Approx 1.7ms
++
++u32 cpu_khz VAR16VISIBLE;
++
++static void
++calibrate_tsc(void)
++{
++    // Setup "timer2"
++    u8 orig = inb(PORT_PS2_CTRLB);
++    outb((orig & ~PPCB_SPKR) | PPCB_T2GATE, PORT_PS2_CTRLB);
++    /* binary, mode 0, LSB/MSB, Ch 2 */
++    outb(PM_SEL_TIMER2|PM_ACCESS_WORD|PM_MODE0|PM_CNT_BINARY, PORT_PIT_MODE);
++    /* LSB of ticks */
++    outb(CALIBRATE_COUNT & 0xFF, PORT_PIT_COUNTER2);
++    /* MSB of ticks */
++    outb(CALIBRATE_COUNT >> 8, PORT_PIT_COUNTER2);
++
++    u64 start = rdtscll();
++    while ((inb(PORT_PS2_CTRLB) & PPCB_T2OUT) == 0)
++        ;
++    u64 end = rdtscll();
++
++    // Restore PORT_PS2_CTRLB
++    outb(orig, PORT_PS2_CTRLB);
++
++    // Store calibrated cpu khz.
++    u64 diff = end - start;
++    dprintf(6, "tsc calibrate start=%u end=%u diff=%u\n"
++            , (u32)start, (u32)end, (u32)diff);
++    u32 hz = diff * PIT_TICK_RATE / CALIBRATE_COUNT;
++    SET_GLOBAL(cpu_khz, hz / 1000);
++
++    dprintf(1, "CPU Mhz=%u\n", hz / 1000000);
++}
++
++static void
++tscdelay(u64 diff)
++{
++    u64 start = rdtscll();
++    u64 end = start + diff;
++    while (!check_time(end))
++        cpu_relax();
++}
++
++static void
++tscsleep(u64 diff)
++{
++    u64 start = rdtscll();
++    u64 end = start + diff;
++    while (!check_time(end))
++        yield();
++}
++
++void ndelay(u32 count) {
++    tscdelay(count * GET_GLOBAL(cpu_khz) / 1000000);
++}
++void udelay(u32 count) {
++    tscdelay(count * GET_GLOBAL(cpu_khz) / 1000);
++}
++void mdelay(u32 count) {
++    tscdelay(count * GET_GLOBAL(cpu_khz));
++}
++
++void nsleep(u32 count) {
++    tscsleep(count * GET_GLOBAL(cpu_khz) / 1000000);
++}
++void usleep(u32 count) {
++    tscsleep(count * GET_GLOBAL(cpu_khz) / 1000);
++}
++void msleep(u32 count) {
++    tscsleep(count * GET_GLOBAL(cpu_khz));
++}
++
++// Return the TSC value that is 'msecs' time in the future.
++u64
++calc_future_tsc(u32 msecs)
++{
++    u32 khz = GET_GLOBAL(cpu_khz);
++    return rdtscll() + ((u64)khz * msecs);
++}
++u64
++calc_future_tsc_usec(u32 usecs)
++{
++    u32 khz = GET_GLOBAL(cpu_khz);
++    return rdtscll() + ((u64)(khz/1000) * usecs);
++}
++
++
++/****************************************************************
++ * Init
++ ****************************************************************/
++
++static int
++rtc_updating(void)
++{
++    // This function checks to see if the update-in-progress bit
++    // is set in CMOS Status Register A.  If not, it returns 0.
++    // If it is set, it tries to wait until there is a transition
++    // to 0, and will return 0 if such a transition occurs.  A -1
++    // is returned only after timing out.  The maximum period
++    // that this bit should be set is constrained to (1984+244)
++    // useconds, so we wait for 3 msec max.
++
++    if ((inb_cmos(CMOS_STATUS_A) & RTC_A_UIP) == 0)
++        return 0;
++    u64 end = calc_future_tsc(3);
++    do {
++        if ((inb_cmos(CMOS_STATUS_A) & RTC_A_UIP) == 0)
++            return 0;
++    } while (!check_time(end));
++
++    // update-in-progress never transitioned to 0
++    return -1;
++}
++
++static void
++pit_setup(void)
++{
++    // timer0: binary count, 16bit count, mode 2
++    outb(PM_SEL_TIMER0|PM_ACCESS_WORD|PM_MODE2|PM_CNT_BINARY, PORT_PIT_MODE);
++    // maximum count of 0000H = 18.2Hz
++    outb(0x0, PORT_PIT_COUNTER0);
++    outb(0x0, PORT_PIT_COUNTER0);
++}
++
++static void
++init_rtc(void)
++{
++    outb_cmos(0x26, CMOS_STATUS_A);    // 32,768Khz src, 976.5625us updates
++    u8 regB = inb_cmos(CMOS_STATUS_B);
++    outb_cmos((regB & RTC_B_DSE) | RTC_B_24HR, CMOS_STATUS_B);
++    inb_cmos(CMOS_STATUS_C);
++    inb_cmos(CMOS_STATUS_D);
++}
++
++static u32
++bcd2bin(u8 val)
++{
++    return (val & 0xf) + ((val >> 4) * 10);
++}
++
++void
++timer_setup(void)
++{
++    dprintf(3, "init timer\n");
++    calibrate_tsc();
++    pit_setup();
++
++    init_rtc();
++    rtc_updating();
++    u32 seconds = bcd2bin(inb_cmos(CMOS_RTC_SECONDS));
++    u32 minutes = bcd2bin(inb_cmos(CMOS_RTC_MINUTES));
++    u32 hours = bcd2bin(inb_cmos(CMOS_RTC_HOURS));
++    u32 ticks = (hours * 60 + minutes) * 60 + seconds;
++    ticks = ((u64)ticks * PIT_TICK_RATE) / PIT_TICK_INTERVAL;
++    SET_BDA(timer_counter, ticks);
++    SET_BDA(timer_rollover, 0);
++
++    enable_hwirq(0, entry_08);
++    enable_hwirq(8, entry_70);
++}
++
++
++/****************************************************************
++ * Standard clock functions
++ ****************************************************************/
++
++// get current clock count
++static void
++handle_1a00(struct bregs *regs)
++{
++    u32 ticks = GET_BDA(timer_counter);
++    regs->cx = ticks >> 16;
++    regs->dx = ticks;
++    regs->al = GET_BDA(timer_rollover);
++    SET_BDA(timer_rollover, 0); // reset flag
++    set_success(regs);
++}
++
++// Set Current Clock Count
++static void
++handle_1a01(struct bregs *regs)
++{
++    u32 ticks = (regs->cx << 16) | regs->dx;
++    SET_BDA(timer_counter, ticks);
++    SET_BDA(timer_rollover, 0); // reset flag
++    // XXX - should use set_code_success()?
++    regs->ah = 0;
++    set_success(regs);
++}
++
++// Read CMOS Time
++static void
++handle_1a02(struct bregs *regs)
++{
++    if (rtc_updating()) {
++        set_invalid(regs);
++        return;
++    }
++
++    regs->dh = inb_cmos(CMOS_RTC_SECONDS);
++    regs->cl = inb_cmos(CMOS_RTC_MINUTES);
++    regs->ch = inb_cmos(CMOS_RTC_HOURS);
++    regs->dl = inb_cmos(CMOS_STATUS_B) & RTC_B_DSE;
++    regs->ah = 0;
++    regs->al = regs->ch;
++    set_success(regs);
++}
++
++// Set CMOS Time
++static void
++handle_1a03(struct bregs *regs)
++{
++    // Using a debugger, I notice the following masking/setting
++    // of bits in Status Register B, by setting Reg B to
++    // a few values and getting its value after INT 1A was called.
++    //
++    //        try#1       try#2       try#3
++    // before 1111 1101   0111 1101   0000 0000
++    // after  0110 0010   0110 0010   0000 0010
++    //
++    // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1
++    // My assumption: RegB = ((RegB & 01100000b) | 00000010b)
++    if (rtc_updating()) {
++        init_rtc();
++        // fall through as if an update were not in progress
++    }
++    outb_cmos(regs->dh, CMOS_RTC_SECONDS);
++    outb_cmos(regs->cl, CMOS_RTC_MINUTES);
++    outb_cmos(regs->ch, CMOS_RTC_HOURS);
++    // Set Daylight Savings time enabled bit to requested value
++    u8 val8 = ((inb_cmos(CMOS_STATUS_B) & (RTC_B_PIE|RTC_B_AIE))
++               | RTC_B_24HR | (regs->dl & RTC_B_DSE));
++    outb_cmos(val8, CMOS_STATUS_B);
++    regs->ah = 0;
++    regs->al = val8; // val last written to Reg B
++    set_success(regs);
++}
++
++// Read CMOS Date
++static void
++handle_1a04(struct bregs *regs)
++{
++    regs->ah = 0;
++    if (rtc_updating()) {
++        set_invalid(regs);
++        return;
++    }
++    regs->cl = inb_cmos(CMOS_RTC_YEAR);
++    regs->dh = inb_cmos(CMOS_RTC_MONTH);
++    regs->dl = inb_cmos(CMOS_RTC_DAY_MONTH);
++    if (CONFIG_COREBOOT) {
++        if (regs->cl > 0x80)
++            regs->ch = 0x19;
++        else
++            regs->ch = 0x20;
++    } else {
++        regs->ch = inb_cmos(CMOS_CENTURY);
++    }
++    regs->al = regs->ch;
++    set_success(regs);
++}
++
++// Set CMOS Date
++static void
++handle_1a05(struct bregs *regs)
++{
++    // Using a debugger, I notice the following masking/setting
++    // of bits in Status Register B, by setting Reg B to
++    // a few values and getting its value after INT 1A was called.
++    //
++    //        try#1       try#2       try#3       try#4
++    // before 1111 1101   0111 1101   0000 0010   0000 0000
++    // after  0110 1101   0111 1101   0000 0010   0000 0000
++    //
++    // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1
++    // My assumption: RegB = (RegB & 01111111b)
++    if (rtc_updating()) {
++        init_rtc();
++        set_invalid(regs);
++        return;
++    }
++    outb_cmos(regs->cl, CMOS_RTC_YEAR);
++    outb_cmos(regs->dh, CMOS_RTC_MONTH);
++    outb_cmos(regs->dl, CMOS_RTC_DAY_MONTH);
++    if (!CONFIG_COREBOOT)
++        outb_cmos(regs->ch, CMOS_CENTURY);
++    // clear halt-clock bit
++    u8 val8 = inb_cmos(CMOS_STATUS_B) & ~RTC_B_SET;
++    outb_cmos(val8, CMOS_STATUS_B);
++    regs->ah = 0;
++    regs->al = val8; // AL = val last written to Reg B
++    set_success(regs);
++}
++
++// Set Alarm Time in CMOS
++static void
++handle_1a06(struct bregs *regs)
++{
++    // Using a debugger, I notice the following masking/setting
++    // of bits in Status Register B, by setting Reg B to
++    // a few values and getting its value after INT 1A was called.
++    //
++    //        try#1       try#2       try#3
++    // before 1101 1111   0101 1111   0000 0000
++    // after  0110 1111   0111 1111   0010 0000
++    //
++    // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1
++    // My assumption: RegB = ((RegB & 01111111b) | 00100000b)
++    u8 val8 = inb_cmos(CMOS_STATUS_B); // Get Status Reg B
++    regs->ax = 0;
++    if (val8 & RTC_B_AIE) {
++        // Alarm interrupt enabled already
++        set_invalid(regs);
++        return;
++    }
++    if (rtc_updating()) {
++        init_rtc();
++        // fall through as if an update were not in progress
++    }
++    outb_cmos(regs->dh, CMOS_RTC_SECONDS_ALARM);
++    outb_cmos(regs->cl, CMOS_RTC_MINUTES_ALARM);
++    outb_cmos(regs->ch, CMOS_RTC_HOURS_ALARM);
++    // enable Status Reg B alarm bit, clear halt clock bit
++    outb_cmos((val8 & ~RTC_B_SET) | RTC_B_AIE, CMOS_STATUS_B);
++    set_success(regs);
++}
++
++// Turn off Alarm
++static void
++handle_1a07(struct bregs *regs)
++{
++    // Using a debugger, I notice the following masking/setting
++    // of bits in Status Register B, by setting Reg B to
++    // a few values and getting its value after INT 1A was called.
++    //
++    //        try#1       try#2       try#3       try#4
++    // before 1111 1101   0111 1101   0010 0000   0010 0010
++    // after  0100 0101   0101 0101   0000 0000   0000 0010
++    //
++    // Bit4 in try#1 flipped in hardware (forced low) due to bit7=1
++    // My assumption: RegB = (RegB & 01010111b)
++    u8 val8 = inb_cmos(CMOS_STATUS_B); // Get Status Reg B
++    // clear clock-halt bit, disable alarm bit
++    outb_cmos(val8 & ~(RTC_B_SET|RTC_B_AIE), CMOS_STATUS_B);
++    regs->ah = 0;
++    regs->al = val8; // val last written to Reg B
++    set_success(regs);
++}
++
++// Unsupported
++static void
++handle_1aXX(struct bregs *regs)
++{
++    set_unimplemented(regs);
++}
++
++// INT 1Ah Time-of-day Service Entry Point
++void VISIBLE16
++handle_1a(struct bregs *regs)
++{
++    debug_enter(regs, DEBUG_HDL_1a);
++    switch (regs->ah) {
++    case 0x00: handle_1a00(regs); break;
++    case 0x01: handle_1a01(regs); break;
++    case 0x02: handle_1a02(regs); break;
++    case 0x03: handle_1a03(regs); break;
++    case 0x04: handle_1a04(regs); break;
++    case 0x05: handle_1a05(regs); break;
++    case 0x06: handle_1a06(regs); break;
++    case 0x07: handle_1a07(regs); break;
++    case 0xb1: handle_1ab1(regs); break;
++    default:   handle_1aXX(regs); break;
++    }
++}
++
++// INT 08h System Timer ISR Entry Point
++void VISIBLE16
++handle_08(void)
++{
++    debug_isr(DEBUG_ISR_08);
++
++    floppy_tick();
++
++    u32 counter = GET_BDA(timer_counter);
++    counter++;
++    // compare to one days worth of timer ticks at 18.2 hz
++    if (counter >= TICKS_PER_DAY) {
++        // there has been a midnight rollover at this point
++        counter = 0;
++        SET_BDA(timer_rollover, GET_BDA(timer_rollover) + 1);
++    }
++
++    SET_BDA(timer_counter, counter);
++
++    usb_check_key();
++
++    // chain to user timer tick INT #0x1c
++    u32 eax=0, flags;
++    call16_simpint(0x1c, &eax, &flags);
++
++    eoi_pic1();
++}
++
++
++/****************************************************************
++ * Periodic timer
++ ****************************************************************/
++
++void
++useRTC(void)
++{
++    u16 ebda_seg = get_ebda_seg();
++    int count = GET_EBDA2(ebda_seg, RTCusers);
++    SET_EBDA2(ebda_seg, RTCusers, count+1);
++    if (count)
++        return;
++    // Turn on the Periodic Interrupt timer
++    u8 bRegister = inb_cmos(CMOS_STATUS_B);
++    outb_cmos(bRegister | RTC_B_PIE, CMOS_STATUS_B);
++}
++
++void
++releaseRTC(void)
++{
++    u16 ebda_seg = get_ebda_seg();
++    int count = GET_EBDA2(ebda_seg, RTCusers);
++    SET_EBDA2(ebda_seg, RTCusers, count-1);
++    if (count != 1)
++        return;
++    // Clear the Periodic Interrupt.
++    u8 bRegister = inb_cmos(CMOS_STATUS_B);
++    outb_cmos(bRegister & ~RTC_B_PIE, CMOS_STATUS_B);
++}
++
++static int
++set_usertimer(u32 usecs, u16 seg, u16 offset)
++{
++    if (GET_BDA(rtc_wait_flag) & RWS_WAIT_PENDING)
++        return -1;
++
++    // Interval not already set.
++    SET_BDA(rtc_wait_flag, RWS_WAIT_PENDING);  // Set status byte.
++    SET_BDA(user_wait_complete_flag, SEGOFF(seg, offset));
++    SET_BDA(user_wait_timeout, usecs);
++    useRTC();
++    return 0;
++}
++
++static void
++clear_usertimer(void)
++{
++    if (!(GET_BDA(rtc_wait_flag) & RWS_WAIT_PENDING))
++        return;
++    // Turn off status byte.
++    SET_BDA(rtc_wait_flag, 0);
++    releaseRTC();
++}
++
++#define RET_ECLOCKINUSE  0x83
++
++// Wait for CX:DX microseconds
++void
++handle_1586(struct bregs *regs)
++{
++    // Use the rtc to wait for the specified time.
++    u8 statusflag = 0;
++    u32 count = (regs->cx << 16) | regs->dx;
++    int ret = set_usertimer(count, GET_SEG(SS), (u32)&statusflag);
++    if (ret) {
++        set_code_invalid(regs, RET_ECLOCKINUSE);
++        return;
++    }
++    while (!statusflag)
++        wait_irq();
++    set_success(regs);
++}
++
++// Set Interval requested.
++static void
++handle_158300(struct bregs *regs)
++{
++    int ret = set_usertimer((regs->cx << 16) | regs->dx, regs->es, regs->bx);
++    if (ret)
++        // Interval already set.
++        set_code_invalid(regs, RET_EUNSUPPORTED);
++    else
++        set_success(regs);
++}
++
++// Clear interval requested
++static void
++handle_158301(struct bregs *regs)
++{
++    clear_usertimer();
++    set_success(regs);
++}
++
++static void
++handle_1583XX(struct bregs *regs)
++{
++    set_code_unimplemented(regs, RET_EUNSUPPORTED);
++    regs->al--;
++}
++
++void
++handle_1583(struct bregs *regs)
++{
++    switch (regs->al) {
++    case 0x00: handle_158300(regs); break;
++    case 0x01: handle_158301(regs); break;
++    default:   handle_1583XX(regs); break;
++    }
++}
++
++#define USEC_PER_RTC DIV_ROUND_CLOSEST(1000000, 1024)
++
++// int70h: IRQ8 - CMOS RTC
++void VISIBLE16
++handle_70(void)
++{
++    debug_isr(DEBUG_ISR_70);
++
++    // Check which modes are enabled and have occurred.
++    u8 registerB = inb_cmos(CMOS_STATUS_B);
++    u8 registerC = inb_cmos(CMOS_STATUS_C);
++
++    if (!(registerB & (RTC_B_PIE|RTC_B_AIE)))
++        goto done;
++    if (registerC & RTC_B_AIE) {
++        // Handle Alarm Interrupt.
++        u32 eax=0, flags;
++        call16_simpint(0x4a, &eax, &flags);
++    }
++    if (!(registerC & RTC_B_PIE))
++        goto done;
++
++    // Handle Periodic Interrupt.
++
++    check_preempt();
++
++    if (!GET_BDA(rtc_wait_flag))
++        goto done;
++
++    // Wait Interval (Int 15, AH=83) active.
++    u32 time = GET_BDA(user_wait_timeout);  // Time left in microseconds.
++    if (time < USEC_PER_RTC) {
++        // Done waiting - write to specified flag byte.
++        struct segoff_s segoff = GET_BDA(user_wait_complete_flag);
++        u16 ptr_seg = segoff.seg;
++        u8 *ptr_far = (u8*)(segoff.offset+0);
++        u8 oldval = GET_FARVAR(ptr_seg, *ptr_far);
++        SET_FARVAR(ptr_seg, *ptr_far, oldval | 0x80);
++
++        clear_usertimer();
++    } else {
++        // Continue waiting.
++        time -= USEC_PER_RTC;
++        SET_BDA(user_wait_timeout, time);
++    }
++
++done:
++    eoi_pic2();
++}
+--- x/roms/seabios/src/cmos.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/cmos.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,74 @@
++// Definitions for X86 CMOS non-volatile memory access.
++//
++// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++#ifndef __CMOS_H
++#define __CMOS_H
++
++#define CMOS_RTC_SECONDS         0x00
++#define CMOS_RTC_SECONDS_ALARM   0x01
++#define CMOS_RTC_MINUTES         0x02
++#define CMOS_RTC_MINUTES_ALARM   0x03
++#define CMOS_RTC_HOURS           0x04
++#define CMOS_RTC_HOURS_ALARM     0x05
++#define CMOS_RTC_DAY_WEEK        0x06
++#define CMOS_RTC_DAY_MONTH       0x07
++#define CMOS_RTC_MONTH           0x08
++#define CMOS_RTC_YEAR            0x09
++#define CMOS_STATUS_A            0x0a
++#define CMOS_STATUS_B            0x0b
++#define CMOS_STATUS_C            0x0c
++#define CMOS_STATUS_D            0x0d
++#define CMOS_RESET_CODE          0x0f
++#define CMOS_FLOPPY_DRIVE_TYPE   0x10
++#define CMOS_DISK_DATA           0x12
++#define CMOS_EQUIPMENT_INFO      0x14
++#define CMOS_DISK_DRIVE1_TYPE    0x19
++#define CMOS_DISK_DRIVE2_TYPE    0x1a
++#define CMOS_DISK_DRIVE1_CYL     0x1b
++#define CMOS_DISK_DRIVE2_CYL     0x24
++#define CMOS_MEM_EXTMEM_LOW      0x30
++#define CMOS_MEM_EXTMEM_HIGH     0x31
++#define CMOS_CENTURY             0x32
++#define CMOS_MEM_EXTMEM2_LOW     0x34
++#define CMOS_MEM_EXTMEM2_HIGH    0x35
++#define CMOS_BIOS_BOOTFLAG1      0x38
++#define CMOS_BIOS_DISKTRANSFLAG  0x39
++#define CMOS_BIOS_BOOTFLAG2      0x3d
++#define CMOS_MEM_HIGHMEM_LOW     0x5b
++#define CMOS_MEM_HIGHMEM_MID     0x5c
++#define CMOS_MEM_HIGHMEM_HIGH    0x5d
++#define CMOS_BIOS_SMP_COUNT      0x5f
++
++// CMOS_FLOPPY_DRIVE_TYPE bitdefs
++#define CFD_NO_DRIVE 0
++#define CFD_360KB    1
++#define CFD_12MB     2
++#define CFD_720KB    3
++#define CFD_144MB    4
++#define CFD_288MB    5
++
++#ifndef __ASSEMBLY__
++
++#include "ioport.h" // inb, outb
++
++static inline u8
++inb_cmos(u8 reg)
++{
++    reg |= NMI_DISABLE_BIT;
++    outb(reg, PORT_CMOS_INDEX);
++    return inb(PORT_CMOS_DATA);
++}
++
++static inline void
++outb_cmos(u8 val, u8 reg)
++{
++    reg |= NMI_DISABLE_BIT;
++    outb(reg, PORT_CMOS_INDEX);
++    outb(val, PORT_CMOS_DATA);
++}
++
++#endif // !__ASSEMBLY__
++
++#endif // cmos.h
+--- x/roms/seabios/src/config.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/config.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,203 @@
++#ifndef __CONFIG_H
++#define __CONFIG_H
++
++// Configuration definitions.
++
++//#define CONFIG_APPNAME  "QEMU"
++//#define CONFIG_CPUNAME8 "QEMUCPU "
++//#define CONFIG_APPNAME6 "QEMU  "
++//#define CONFIG_APPNAME4 "QEMU"
++#define CONFIG_APPNAME  "Bochs"
++#define CONFIG_CPUNAME8 "BOCHSCPU"
++#define CONFIG_APPNAME6 "BOCHS "
++#define CONFIG_APPNAME4 "BXPC"
++
++// Configure as a coreboot payload.
++#define CONFIG_COREBOOT 0
++
++// Control how verbose debug output is.
++#define CONFIG_DEBUG_LEVEL 1
++// Send debugging information to serial port
++#define CONFIG_DEBUG_SERIAL 0
++// Screen writes are also sent to debug ports.
++#define CONFIG_SCREEN_AND_DEBUG 1
++
++// Support running hardware initialization in parallel
++#define CONFIG_THREADS 1
++// Allow hardware init to run in parallel with optionrom execution
++#define CONFIG_THREAD_OPTIONROMS 0
++// Support int13 disk/floppy drive functions
++#define CONFIG_DRIVES 1
++// Support floppy drive access
++#define CONFIG_FLOPPY 1
++// Support USB devices
++#define CONFIG_USB 1
++// Support USB UHCI controllers
++#define CONFIG_USB_UHCI 1
++// Support USB OHCI controllers
++#define CONFIG_USB_OHCI 1
++// Support USB keyboards
++#define CONFIG_USB_KEYBOARD 1
++// Support PS2 ports (keyboard and mouse)
++#define CONFIG_PS2PORT 1
++// Support for IDE disk code
++#define CONFIG_ATA 1
++// Use 32bit PIO accesses on ATA (minor optimization on PCI transfers)
++#define CONFIG_ATA_PIO32 0
++// Support for booting from a CD
++#define CONFIG_CDROM_BOOT 1
++// Support for emulating a boot CD as a floppy/harddrive
++#define CONFIG_CDROM_EMU 1
++// Support int 1a/b1 PCI BIOS calls
++#define CONFIG_PCIBIOS 1
++// Support int 15/53 APM BIOS calls
++#define CONFIG_APMBIOS 1
++// Support PnP BIOS entry point.
++#define CONFIG_PNPBIOS 1
++// Support Post Memory Manager (PMM) entry point.
++#define CONFIG_PMM 1
++// Support int 19/18 system bootup support
++#define CONFIG_BOOT 1
++// Support an interactive boot menu at end of post.
++#define CONFIG_BOOTMENU 1
++// Amount of time (in ms) to wait at menu before selecting normal boot.
++#define CONFIG_BOOTMENU_WAIT 2500
++// Support int 14 serial port calls
++#define CONFIG_SERIAL 1
++// Support int 17 parallel port calls
++#define CONFIG_LPT 1
++// Support int 16 keyboard calls
++#define CONFIG_KEYBOARD 1
++// Support calling int155f on each keyboard event
++#define CONFIG_KBD_CALL_INT15_4F 1
++// Disable A20 on 16bit boot
++#define CONFIG_DISABLE_A20 0
++// Support for int15c2 mouse calls
++#define CONFIG_MOUSE 1
++// If the target machine has multiple independent root buses, the
++// extra buses may be specified here.
++#define CONFIG_PCI_ROOT1 0x00
++#define CONFIG_PCI_ROOT2 0x00
++// Support searching coreboot flash format.
++#define CONFIG_COREBOOT_FLASH 0
++// Support floppy images in the coreboot flash.
++#define CONFIG_FLASH_FLOPPY 1
++// Support the lzma decompression algorighm.
++#define CONFIG_LZMA 1
++// Support finding and running option roms during post.
++#define CONFIG_OPTIONROMS 1
++// Set if option roms are already copied to 0xc0000-0xf0000
++#define CONFIG_OPTIONROMS_DEPLOYED 0
++// When option roms are not pre-deployed, SeaBIOS can copy an optionrom
++// from flash for up to 2 devices.
++#define OPTIONROM_VENDEV_1 0x00000000
++#define OPTIONROM_MEM_1 0x00000000
++#define OPTIONROM_VENDEV_2 0x00000000
++#define OPTIONROM_MEM_2 0x00000000
++
++// Support generation of a PIR table in 0xf000 segment (for emulators)
++#define CONFIG_PIRTABLE 1
++// Support generation of MPTable (for emulators)
++#define CONFIG_MPTABLE 1
++// Support generation of SM BIOS tables (for emulators)
++#define CONFIG_SMBIOS 1
++// Support finding a UUID (for smbios) via "magic" outl sequence.
++#define CONFIG_UUID_BACKDOOR 1
++// Support generation of ACPI tables (for emulators)
++#define CONFIG_ACPI 1
++// Support bios callbacks specific to via vgabios.
++#define CONFIG_VGAHOOKS 0
++// Support S3 resume handler.
++#define CONFIG_S3_RESUME 1
++// Run the vga rom during S3 resume.
++#define CONFIG_S3_RESUME_VGA_INIT 0
++// define it if the (emulated) hardware supports SMM mode
++#define CONFIG_USE_SMM 1
++// Maximum number of map entries in the e820 map
++#define CONFIG_MAX_E820 32
++// Space to reserve in f-segment for run-time built bios tables.
++#define CONFIG_MAX_BIOSTABLE 2048
++// Space to reserve in high-memory for tables
++#define CONFIG_MAX_HIGHTABLE (64*1024)
++
++// Maximum number of ATA controllers to support
++#define CONFIG_MAX_ATA_INTERFACES 4
++// Maximum number of internal drives supported
++#define CONFIG_MAX_DRIVES 8
++// Largest supported externaly facing drive id
++#define CONFIG_MAX_EXTDRIVE 16
++
++#define CONFIG_MODEL_ID      0xFC
++#define CONFIG_SUBMODEL_ID   0x00
++#define CONFIG_BIOS_REVISION 0x01
++
++// Various memory addresses used by the code.
++#define BUILD_STACK_ADDR          0x7000
++#define BUILD_S3RESUME_STACK_ADDR 0x1000
++#define BUILD_AP_BOOT_ADDR        0x10000
++#define BUILD_EBDA_MINIMUM        0x90000
++#define BUILD_LOWRAM_END          0xa0000
++#define BUILD_ROM_START           0xc0000
++#define BUILD_BIOS_ADDR           0xf0000
++#define BUILD_BIOS_SIZE           0x10000
++// 32KB for shadow ram copying (works around emulator deficiencies)
++#define BUILD_BIOS_TMP_ADDR       0x30000
++#define BUILD_MAX_HIGHMEM         0xe0000000
++#define BUILD_PCIMEM_START        0xf0000000
++
++#define BUILD_APIC_ADDR           0xfee00000
++#define BUILD_IOAPIC_ADDR         0xfec00000
++
++#define BUILD_SMM_INIT_ADDR       0x38000
++#define BUILD_SMM_ADDR            0xa8000
++#define BUILD_SMM_SIZE            0x8000
++
++// Important real-mode segments
++#define SEG_IVT      0x0000
++#define SEG_BDA      0x0040
++#define SEG_BIOS     0xf000
++
++// Segment definitions in protected mode (see rombios32_gdt in misc.c)
++#define SEG32_MODE32_CS    (1 << 3)
++#define SEG32_MODE32_DS    (2 << 3)
++#define SEG32_MODE16_CS    (3 << 3)
++#define SEG32_MODE16_DS    (4 << 3)
++#define SEG32_MODE16BIG_CS (5 << 3)
++#define SEG32_MODE16BIG_DS (6 << 3)
++
++// Debugging levels.  If non-zero and CONFIG_DEBUG_LEVEL is greater
++// than the specified value, then the corresponding irq handler will
++// report every enter event.
++#define DEBUG_ISR_02 1
++#define DEBUG_HDL_05 1
++#define DEBUG_ISR_08 20
++#define DEBUG_ISR_09 9
++#define DEBUG_ISR_0e 9
++#define DEBUG_HDL_10 20
++#define DEBUG_HDL_11 2
++#define DEBUG_HDL_12 2
++#define DEBUG_HDL_13 10
++#define DEBUG_HDL_14 2
++#define DEBUG_HDL_15 9
++#define DEBUG_HDL_16 9
++#define DEBUG_HDL_17 2
++#define DEBUG_HDL_18 1
++#define DEBUG_HDL_19 1
++#define DEBUG_HDL_1a 9
++#define DEBUG_HDL_40 1
++#define DEBUG_ISR_70 9
++#define DEBUG_ISR_74 9
++#define DEBUG_ISR_75 1
++#define DEBUG_ISR_76 10
++#define DEBUG_ISR_hwpic1 5
++#define DEBUG_ISR_hwpic2 5
++#define DEBUG_HDL_pnp 1
++#define DEBUG_HDL_pmm 1
++#define DEBUG_HDL_pcibios32 9
++#define DEBUG_HDL_apm 9
++
++#define DEBUG_unimplemented 2
++#define DEBUG_invalid 3
++#define DEBUG_thread 2
++
++#endif // config.h
+--- x/roms/seabios/src/coreboot.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/coreboot.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,621 @@
++// Coreboot interface support.
++//
++// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "memmap.h" // add_e820
++#include "util.h" // dprintf
++#include "pci.h" // struct pir_header
++#include "acpi.h" // struct rsdp_descriptor
++#include "mptable.h" // MPTABLE_SIGNATURE
++#include "biosvar.h" // GET_EBDA
++#include "lzmadecode.h" // LzmaDecode
++#include "smbios.h" // smbios_init
++
++
++/****************************************************************
++ * Memory map
++ ****************************************************************/
++
++struct cb_header {
++    u32 signature;
++    u32 header_bytes;
++    u32 header_checksum;
++    u32 table_bytes;
++    u32 table_checksum;
++    u32 table_entries;
++};
++
++#define CB_SIGNATURE 0x4f49424C // "LBIO"
++
++struct cb_memory_range {
++    u64 start;
++    u64 size;
++    u32 type;
++};
++
++#define CB_MEM_TABLE    16
++
++struct cb_memory {
++    u32 tag;
++    u32 size;
++    struct cb_memory_range map[0];
++};
++
++#define CB_TAG_MEMORY 0x01
++
++#define MEM_RANGE_COUNT(_rec) \
++        (((_rec)->size - sizeof(*(_rec))) / sizeof((_rec)->map[0]))
++
++struct cb_mainboard {
++    u32 tag;
++    u32 size;
++    u8  vendor_idx;
++    u8  part_idx;
++    char  strings[0];
++};
++
++#define CB_TAG_MAINBOARD 0x0003
++
++struct cb_forward {
++    u32 tag;
++    u32 size;
++    u64 forward;
++};
++
++#define CB_TAG_FORWARD 0x11
++
++static u16
++ipchksum(char *buf, int count)
++{
++    u16 *p = (u16*)buf;
++    u32 sum = 0;
++    while (count > 1) {
++        sum += *p++;
++        count -= 2;
++    }
++    if (count)
++        sum += *(u8*)p;
++    sum = (sum >> 16) + (sum & 0xffff);
++    sum += (sum >> 16);
++    return ~sum;
++}
++
++// Try to locate the coreboot header in a given address range.
++static struct cb_header *
++find_cb_header(char *addr, int len)
++{
++    char *end = addr + len;
++    for (; addr < end; addr += 16) {
++        struct cb_header *cbh = (struct cb_header *)addr;
++        if (cbh->signature != CB_SIGNATURE)
++            continue;
++        if (! cbh->table_bytes)
++            continue;
++        if (ipchksum(addr, sizeof(*cbh)) != 0)
++            continue;
++        if (ipchksum(addr + sizeof(*cbh), cbh->table_bytes)
++            != cbh->table_checksum)
++            continue;
++        return cbh;
++    }
++    return NULL;
++}
++
++// Try to find the coreboot memory table in the given coreboot table.
++static void *
++find_cb_subtable(struct cb_header *cbh, u32 tag)
++{
++    char *tbl = (char *)cbh + sizeof(*cbh);
++    int i;
++    for (i=0; i<cbh->table_entries; i++) {
++        struct cb_memory *cbm = (struct cb_memory *)tbl;
++        tbl += cbm->size;
++        if (cbm->tag == tag)
++            return cbm;
++    }
++    return NULL;
++}
++
++static struct cb_memory *CBMemTable;
++
++// Populate max ram and e820 map info by scanning for a coreboot table.
++static void
++coreboot_fill_map(void)
++{
++    dprintf(3, "Attempting to find coreboot table\n");
++
++    CBMemTable = NULL;
++
++    // Find coreboot table.
++    struct cb_header *cbh = find_cb_header(0, 0x1000);
++    if (!cbh)
++        goto fail;
++    struct cb_forward *cbf = find_cb_subtable(cbh, CB_TAG_FORWARD);
++    if (cbf) {
++        dprintf(3, "Found coreboot table forwarder.\n");
++        cbh = find_cb_header((char *)((u32)cbf->forward), 0x100);
++        if (!cbh)
++            goto fail;
++    }
++    dprintf(3, "Now attempting to find coreboot memory map\n");
++    struct cb_memory *cbm = CBMemTable = find_cb_subtable(cbh, CB_TAG_MEMORY);
++    if (!cbm)
++        goto fail;
++
++    u64 maxram = 0, maxram_over4G = 0;
++    int i, count = MEM_RANGE_COUNT(cbm);
++    for (i=0; i<count; i++) {
++        struct cb_memory_range *m = &cbm->map[i];
++        u32 type = m->type;
++        if (type == CB_MEM_TABLE) {
++            type = E820_RESERVED;
++        } else if (type == E820_ACPI || type == E820_RAM) {
++            u64 end = m->start + m->size;
++            if (end > 0x100000000ull) {
++                end -= 0x100000000ull;
++                if (end > maxram_over4G)
++                    maxram_over4G = end;
++            } else if (end > maxram)
++                maxram = end;
++        }
++        add_e820(m->start, m->size, type);
++    }
++
++    RamSize = maxram;
++    RamSizeOver4G = maxram_over4G;
++
++    // Ughh - coreboot likes to set a map at 0x0000-0x1000, but this
++    // confuses grub.  So, override it.
++    add_e820(0, 16*1024, E820_RAM);
++
++    struct cb_mainboard *cbmb = find_cb_subtable(cbh, CB_TAG_MAINBOARD);
++    if (cbmb) {
++        const char *vendor = &cbmb->strings[cbmb->vendor_idx];
++        const char *part = &cbmb->strings[cbmb->part_idx];
++        dprintf(1, "Found mainboard %s %s\n", vendor, part);
++
++        vgahook_setup(vendor, part);
++    }
++
++    return;
++
++fail:
++    // No table found..  Use 16Megs as a dummy value.
++    dprintf(1, "Unable to find coreboot table!\n");
++    RamSize = 16*1024*1024;
++    RamSizeOver4G = 0;
++    add_e820(0, 16*1024*1024, E820_RAM);
++    return;
++}
++
++
++/****************************************************************
++ * BIOS table copying
++ ****************************************************************/
++
++static void
++copy_pir(void *pos)
++{
++    struct pir_header *p = pos;
++    if (p->signature != PIR_SIGNATURE)
++        return;
++    if (PirOffset)
++        return;
++    if (p->size < sizeof(*p))
++        return;
++    if (checksum(pos, p->size) != 0)
++        return;
++    void *newpos = malloc_fseg(p->size);
++    if (!newpos) {
++        dprintf(1, "No room to copy PIR table!\n");
++        return;
++    }
++    dprintf(1, "Copying PIR from %p to %p\n", pos, newpos);
++    memcpy(newpos, pos, p->size);
++    PirOffset = (u32)newpos - BUILD_BIOS_ADDR;
++}
++
++static void
++copy_mptable(void *pos)
++{
++    struct mptable_floating_s *p = pos;
++    if (p->signature != MPTABLE_SIGNATURE)
++        return;
++    if (!p->physaddr)
++        return;
++    if (checksum(pos, sizeof(*p)) != 0)
++        return;
++    u32 length = p->length * 16;
++    u16 mpclength = ((struct mptable_config_s *)p->physaddr)->length;
++    struct mptable_floating_s *newpos = malloc_fseg(length + mpclength);
++    if (!newpos) {
++        dprintf(1, "No room to copy MPTABLE!\n");
++        return;
++    }
++    dprintf(1, "Copying MPTABLE from %p/%x to %p\n", pos, p->physaddr, newpos);
++    memcpy(newpos, pos, length);
++    newpos->physaddr = (u32)newpos + length;
++    newpos->checksum -= checksum(newpos, sizeof(*newpos));
++    memcpy((void*)newpos + length, (void*)p->physaddr, mpclength);
++}
++
++static void
++copy_acpi_rsdp(void *pos)
++{
++    if (RsdpAddr)
++        return;
++    struct rsdp_descriptor *p = pos;
++    if (p->signature != RSDP_SIGNATURE)
++        return;
++    u32 length = 20;
++    if (checksum(pos, length) != 0)
++        return;
++    if (p->revision > 1) {
++        length = p->length;
++        if (checksum(pos, length) != 0)
++            return;
++    }
++    void *newpos = malloc_fseg(length);
++    if (!newpos) {
++        dprintf(1, "No room to copy ACPI RSDP table!\n");
++        return;
++    }
++    dprintf(1, "Copying ACPI RSDP from %p to %p\n", pos, newpos);
++    memcpy(newpos, pos, length);
++    RsdpAddr = newpos;
++}
++
++// Attempt to find (and relocate) any standard bios tables found in a
++// given address range.
++static void
++scan_tables(u32 start, u32 size)
++{
++    void *p = (void*)ALIGN(start, 16);
++    void *end = (void*)start + size;
++    for (; p<end; p += 16) {
++        copy_pir(p);
++        copy_mptable(p);
++        copy_acpi_rsdp(p);
++    }
++}
++
++void
++coreboot_copy_biostable(void)
++{
++    struct cb_memory *cbm = CBMemTable;
++    if (! CONFIG_COREBOOT || !cbm)
++        return;
++
++    dprintf(3, "Relocating coreboot bios tables\n");
++
++    // Init variables set in coreboot table memory scan.
++    PirOffset = 0;
++    RsdpAddr = 0;
++
++    // Scan CB_MEM_TABLE areas for bios tables.
++    int i, count = MEM_RANGE_COUNT(cbm);
++    for (i=0; i<count; i++) {
++        struct cb_memory_range *m = &cbm->map[i];
++        if (m->type == CB_MEM_TABLE)
++            scan_tables(m->start, m->size);
++    }
++
++    // XXX - just create dummy smbios table for now - should detect if
++    // smbios/dmi table is found from coreboot and use that instead.
++    smbios_init();
++}
++
++
++/****************************************************************
++ * ulzma
++ ****************************************************************/
++
++// Uncompress data in flash to an area of memory.
++static int
++ulzma(u8 *dst, u32 maxlen, const u8 *src, u32 srclen)
++{
++    dprintf(3, "Uncompressing data %d@%p to %d@%p\n", srclen, src, maxlen, dst);
++    CLzmaDecoderState state;
++    int ret = LzmaDecodeProperties(&state.Properties, src, LZMA_PROPERTIES_SIZE);
++    if (ret != LZMA_RESULT_OK) {
++        dprintf(1, "LzmaDecodeProperties error - %d\n", ret);
++        return -1;
++    }
++    u8 scratch[15980];
++    int need = (LzmaGetNumProbs(&state.Properties) * sizeof(CProb));
++    if (need > sizeof(scratch)) {
++        dprintf(1, "LzmaDecode need %d have %d\n", need, sizeof(scratch));
++        return -1;
++    }
++    state.Probs = (CProb *)scratch;
++
++    u32 dstlen = *(u32*)(src + LZMA_PROPERTIES_SIZE);
++    if (dstlen > maxlen) {
++        dprintf(1, "LzmaDecode too large (max %d need %d)\n", maxlen, dstlen);
++        return -1;
++    }
++    u32 inProcessed, outProcessed;
++    ret = LzmaDecode(&state, src + LZMA_PROPERTIES_SIZE + 8, srclen
++                     , &inProcessed, dst, dstlen, &outProcessed);
++    if (ret) {
++        dprintf(1, "LzmaDecode returned %d\n", ret);
++        return -1;
++    }
++    return dstlen;
++}
++
++
++/****************************************************************
++ * Coreboot flash format
++ ****************************************************************/
++
++#define CBFS_HEADER_MAGIC 0x4F524243
++#define CBFS_HEADPTR_ADDR 0xFFFFFFFc
++#define CBFS_VERSION1 0x31313131
++
++struct cbfs_header {
++    u32 magic;
++    u32 version;
++    u32 romsize;
++    u32 bootblocksize;
++    u32 align;
++    u32 offset;
++    u32 pad[2];
++} PACKED;
++
++static struct cbfs_header *CBHDR;
++
++static void
++cbfs_setup(void)
++{
++    if (! CONFIG_COREBOOT_FLASH)
++        return;
++
++    CBHDR = *(void **)CBFS_HEADPTR_ADDR;
++    if (CBHDR->magic != htonl(CBFS_HEADER_MAGIC)) {
++        dprintf(1, "Unable to find CBFS (got %x not %x)\n"
++                , CBHDR->magic, htonl(CBFS_HEADER_MAGIC));
++        CBHDR = NULL;
++        return;
++    }
++
++    dprintf(1, "Found CBFS header at %p\n", CBHDR);
++}
++
++#define CBFS_FILE_MAGIC 0x455649484352414cLL // LARCHIVE
++
++struct cbfs_file {
++    u64 magic;
++    u32 len;
++    u32 type;
++    u32 checksum;
++    u32 offset;
++    char filename[0];
++} PACKED;
++
++// Verify a cbfs entry looks valid.
++static struct cbfs_file *
++cbfs_verify(struct cbfs_file *file)
++{
++    if (file < (struct cbfs_file *)(0xFFFFFFFF - ntohl(CBHDR->romsize)))
++        return NULL;
++    u64 magic = file->magic;
++    if (magic == CBFS_FILE_MAGIC) {
++        dprintf(5, "Found CBFS file %s\n", file->filename);
++        return file;
++    }
++    return NULL;
++}
++
++// Return the first file in the CBFS archive
++static struct cbfs_file *
++cbfs_getfirst(void)
++{
++    if (! CBHDR)
++        return NULL;
++    return cbfs_verify((void *)(0 - ntohl(CBHDR->romsize) + ntohl(CBHDR->offset)));
++}
++
++// Return the file after the given file.
++static struct cbfs_file *
++cbfs_getnext(struct cbfs_file *file)
++{
++    file = (void*)file + ALIGN(ntohl(file->len) + ntohl(file->offset), ntohl(CBHDR->align));
++    return cbfs_verify(file);
++}
++
++// Find the file with the given filename.
++struct cbfs_file *
++cbfs_findfile(const char *fname)
++{
++    dprintf(3, "Searching CBFS for %s\n", fname);
++    struct cbfs_file *file;
++    for (file = cbfs_getfirst(); file; file = cbfs_getnext(file))
++        if (strcmp(fname, file->filename) == 0)
++            return file;
++    return NULL;
++}
++
++// Find next file with the given filename prefix.
++struct cbfs_file *
++cbfs_findprefix(const char *prefix, struct cbfs_file *last)
++{
++    if (! CONFIG_COREBOOT_FLASH)
++        return NULL;
++
++    dprintf(3, "Searching CBFS for prefix %s\n", prefix);
++    int len = strlen(prefix);
++    struct cbfs_file *file;
++    if (! last)
++        file = cbfs_getfirst();
++    else
++        file = cbfs_getnext(last);
++    for (; file; file = cbfs_getnext(file))
++        if (memcmp(prefix, file->filename, len) == 0)
++            return file;
++    return NULL;
++}
++
++// Find a file with the given filename (possibly with ".lzma" extension).
++static struct cbfs_file *
++cbfs_finddatafile(const char *fname)
++{
++    int fnlen = strlen(fname);
++    struct cbfs_file *file = NULL;
++    for (;;) {
++        file = cbfs_findprefix(fname, file);
++        if (!file)
++            return NULL;
++        if (file->filename[fnlen] == '\0'
++            || strcmp(&file->filename[fnlen], ".lzma") == 0)
++            return file;
++    }
++}
++
++// Determine whether the file has a ".lzma" extension.
++static int
++cbfs_iscomp(struct cbfs_file *file)
++{
++    int fnamelen = strlen(file->filename);
++    return fnamelen > 5 && strcmp(&file->filename[fnamelen-5], ".lzma") == 0;
++}
++
++// Return the filename of a given file.
++const char *
++cbfs_filename(struct cbfs_file *file)
++{
++    return file->filename;
++}
++
++// Determine the uncompressed size of a datafile.
++u32
++cbfs_datasize(struct cbfs_file *file)
++{
++    void *src = (void*)file + ntohl(file->offset);
++    if (cbfs_iscomp(file))
++        return *(u32*)(src + LZMA_PROPERTIES_SIZE);
++    return ntohl(file->len);
++}
++
++// Copy a file to memory (uncompressing if necessary)
++int
++cbfs_copyfile(struct cbfs_file *file, void *dst, u32 maxlen)
++{
++    if (! CONFIG_COREBOOT_FLASH || !file)
++        return -1;
++
++    u32 size = ntohl(file->len);
++    void *src = (void*)file + ntohl(file->offset);
++    if (cbfs_iscomp(file)) {
++        // Compressed - copy to temp ram and uncompress it.
++        u32 asize = ALIGN(size, 4);
++        void *temp = malloc_tmphigh(asize);
++        if (!temp)
++            return -1;
++        iomemcpy(temp, src, asize);
++        int ret = ulzma(dst, maxlen, temp, size);
++        yield();
++        free(temp);
++        return ret;
++    }
++
++    // Not compressed.
++    dprintf(3, "Copying data %d@%p to %d@%p\n", size, src, maxlen, dst);
++    if (size > maxlen) {
++        dprintf(1, "File too big to copy\n");
++        return -1;
++    }
++    iomemcpy(dst, src, size);
++    return size;
++}
++
++// Find and copy the optionrom for the given vendor/device id.
++int
++cbfs_copy_optionrom(void *dst, u32 maxlen, u32 vendev)
++{
++    if (! CONFIG_COREBOOT_FLASH)
++        return -1;
++
++    char fname[17];
++    snprintf(fname, sizeof(fname), "pci%04x,%04x.rom"
++             , (u16)vendev, vendev >> 16);
++    return cbfs_copyfile(cbfs_finddatafile(fname), dst, maxlen);
++}
++
++struct cbfs_payload_segment {
++    u32 type;
++    u32 compression;
++    u32 offset;
++    u64 load_addr;
++    u32 len;
++    u32 mem_len;
++} PACKED;
++
++#define PAYLOAD_SEGMENT_BSS    0x20535342
++#define PAYLOAD_SEGMENT_ENTRY  0x52544E45
++
++#define CBFS_COMPRESS_NONE  0
++#define CBFS_COMPRESS_LZMA  1
++
++struct cbfs_payload {
++    struct cbfs_payload_segment segments[1];
++};
++
++void
++cbfs_run_payload(struct cbfs_file *file)
++{
++    if (!CONFIG_COREBOOT_FLASH || !file)
++        return;
++    dprintf(1, "Run %s\n", file->filename);
++    struct cbfs_payload *pay = (void*)file + ntohl(file->offset);
++    struct cbfs_payload_segment *seg = pay->segments;
++    for (;;) {
++        void *src = (void*)pay + ntohl(seg->offset);
++        void *dest = (void*)ntohl((u32)seg->load_addr);
++        u32 src_len = ntohl(seg->len);
++        u32 dest_len = ntohl(seg->mem_len);
++        switch (seg->type) {
++        case PAYLOAD_SEGMENT_BSS:
++            dprintf(3, "BSS segment %d@%p\n", dest_len, dest);
++            memset(dest, 0, dest_len);
++            break;
++        case PAYLOAD_SEGMENT_ENTRY: {
++            dprintf(1, "Calling addr %p\n", dest);
++            void (*func)() = dest;
++            func();
++            return;
++        }
++        default:
++            dprintf(3, "Segment %x %d@%p -> %d@%p\n"
++                    , seg->type, src_len, src, dest_len, dest);
++            if (seg->compression == htonl(CBFS_COMPRESS_NONE)) {
++                if (src_len > dest_len)
++                    src_len = dest_len;
++                memcpy(dest, src, src_len);
++            } else if (CONFIG_LZMA
++                       && seg->compression == htonl(CBFS_COMPRESS_LZMA)) {
++                int ret = ulzma(dest, dest_len, src, src_len);
++                if (ret < 0)
++                    return;
++                src_len = ret;
++            } else {
++                dprintf(1, "No support for compression type %x\n"
++                        , seg->compression);
++                return;
++            }
++            if (dest_len > src_len)
++                memset(dest + src_len, 0, dest_len - src_len);
++            break;
++        }
++        seg++;
++    }
++}
++
++void
++coreboot_setup(void)
++{
++    coreboot_fill_map();
++    cbfs_setup();
++}
+--- x/roms/seabios/src/disk.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/disk.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,863 @@
++// 16bit code to access hard drives.
++//
++// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2002  MandrakeSoft S.A.
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "disk.h" // floppy_13
++#include "biosvar.h" // SET_BDA
++#include "config.h" // CONFIG_*
++#include "util.h" // debug_enter
++#include "pic.h" // eoi_pic2
++#include "bregs.h" // struct bregs
++#include "pci.h" // pci_bdf_to_bus
++#include "ata.h" // ATA_CB_DC
++
++
++/****************************************************************
++ * Helper functions
++ ****************************************************************/
++
++void
++__disk_ret(struct bregs *regs, u32 linecode, const char *fname)
++{
++    u8 code = linecode;
++    if (regs->dl < EXTSTART_HD)
++        SET_BDA(floppy_last_status, code);
++    else
++        SET_BDA(disk_last_status, code);
++    if (code)
++        __set_code_invalid(regs, linecode, fname);
++    else
++        set_code_success(regs);
++}
++
++void
++__disk_ret_unimplemented(struct bregs *regs, u32 linecode, const char *fname)
++{
++    u8 code = linecode;
++    if (regs->dl < EXTSTART_HD)
++        SET_BDA(floppy_last_status, code);
++    else
++        SET_BDA(disk_last_status, code);
++    __set_code_unimplemented(regs, linecode, fname);
++}
++
++static void
++__disk_stub(struct bregs *regs, int lineno, const char *fname)
++{
++    __warn_unimplemented(regs, lineno, fname);
++    __disk_ret(regs, DISK_RET_SUCCESS | (lineno << 8), fname);
++}
++
++#define DISK_STUB(regs)                         \
++    __disk_stub((regs), __LINE__, __func__)
++
++// Get the cylinders/heads/sectors for the given drive.
++static void
++fillLCHS(struct drive_s *drive_g, u16 *nlc, u16 *nlh, u16 *nlspt)
++{
++    if (CONFIG_CDROM_EMU && drive_g == GET_GLOBAL(cdemu_drive)) {
++        // Emulated drive - get info from ebda.  (It's not possible to
++        // populate the geometry directly in the driveid because the
++        // geometry is only known after the bios segment is made
++        // read-only).
++        u16 ebda_seg = get_ebda_seg();
++        *nlc = GET_EBDA2(ebda_seg, cdemu.lchs.cylinders);
++        *nlh = GET_EBDA2(ebda_seg, cdemu.lchs.heads);
++        *nlspt = GET_EBDA2(ebda_seg, cdemu.lchs.spt);
++        return;
++    }
++    *nlc = GET_GLOBAL(drive_g->lchs.cylinders);
++    *nlh = GET_GLOBAL(drive_g->lchs.heads);
++    *nlspt = GET_GLOBAL(drive_g->lchs.spt);
++}
++
++// Perform read/write/verify using old-style chs accesses
++static void
++basic_access(struct bregs *regs, struct drive_s *drive_g, u16 command)
++{
++    struct disk_op_s dop;
++    dop.drive_g = drive_g;
++    dop.command = command;
++
++    u8 count = regs->al;
++    u16 cylinder = regs->ch | ((((u16)regs->cl) << 2) & 0x300);
++    u16 sector = regs->cl & 0x3f;
++    u16 head = regs->dh;
++
++    if (count > 128 || count == 0 || sector == 0) {
++        dprintf(1, "int13_harddisk: function %02x, parameter out of range!\n"
++                , regs->ah);
++        disk_ret(regs, DISK_RET_EPARAM);
++        return;
++    }
++    dop.count = count;
++
++    u16 nlc, nlh, nlspt;
++    fillLCHS(drive_g, &nlc, &nlh, &nlspt);
++
++    // sanity check on cyl heads, sec
++    if (cylinder >= nlc || head >= nlh || sector > nlspt) {
++        dprintf(1, "int13_harddisk: function %02x, parameters out of"
++                " range %04x/%04x/%04x!\n"
++                , regs->ah, cylinder, head, sector);
++        disk_ret(regs, DISK_RET_EPARAM);
++        return;
++    }
++
++    // translate lchs to lba
++    dop.lba = (((((u32)cylinder * (u32)nlh) + (u32)head) * (u32)nlspt)
++               + (u32)sector - 1);
++
++    dop.buf_fl = MAKE_FLATPTR(regs->es, regs->bx);
++
++    int status = send_disk_op(&dop);
++
++    regs->al = dop.count;
++
++    disk_ret(regs, status);
++}
++
++// Perform read/write/verify using new-style "int13ext" accesses.
++static void
++extended_access(struct bregs *regs, struct drive_s *drive_g, u16 command)
++{
++    struct disk_op_s dop;
++    // Get lba and check.
++    dop.lba = GET_INT13EXT(regs, lba);
++    dop.command = command;
++    dop.drive_g = drive_g;
++    if (dop.lba >= GET_GLOBAL(drive_g->sectors)) {
++        dprintf(1, "int13_harddisk: function %02x. LBA out of range\n"
++                , regs->ah);
++        disk_ret(regs, DISK_RET_EPARAM);
++        return;
++    }
++
++    dop.buf_fl = SEGOFF_TO_FLATPTR(GET_INT13EXT(regs, data));
++    dop.count = GET_INT13EXT(regs, count);
++
++    int status = send_disk_op(&dop);
++
++    SET_INT13EXT(regs, count, dop.count);
++
++    disk_ret(regs, status);
++}
++
++
++/****************************************************************
++ * Hard Drive functions
++ ****************************************************************/
++
++// disk controller reset
++static void
++disk_1300(struct bregs *regs, struct drive_s *drive_g)
++{
++    struct disk_op_s dop;
++    dop.drive_g = drive_g;
++    dop.command = CMD_RESET;
++    int status = send_disk_op(&dop);
++    disk_ret(regs, status);
++}
++
++// read disk status
++static void
++disk_1301(struct bregs *regs, struct drive_s *drive_g)
++{
++    u8 v;
++    if (regs->dl < EXTSTART_HD)
++        // Floppy
++        v = GET_BDA(floppy_last_status);
++    else
++        v = GET_BDA(disk_last_status);
++    regs->ah = v;
++    set_cf(regs, v);
++    // XXX - clear disk_last_status?
++}
++
++// read disk sectors
++static void
++disk_1302(struct bregs *regs, struct drive_s *drive_g)
++{
++    basic_access(regs, drive_g, CMD_READ);
++}
++
++// write disk sectors
++static void
++disk_1303(struct bregs *regs, struct drive_s *drive_g)
++{
++    basic_access(regs, drive_g, CMD_WRITE);
++}
++
++// verify disk sectors
++static void
++disk_1304(struct bregs *regs, struct drive_s *drive_g)
++{
++    basic_access(regs, drive_g, CMD_VERIFY);
++}
++
++// format disk track
++static void
++disk_1305(struct bregs *regs, struct drive_s *drive_g)
++{
++    debug_stub(regs);
++
++    u16 nlc, nlh, nlspt;
++    fillLCHS(drive_g, &nlc, &nlh, &nlspt);
++
++    u8 num_sectors = regs->al;
++    u8 head        = regs->dh;
++
++    if (head >= nlh || num_sectors == 0 || num_sectors > nlspt) {
++        disk_ret(regs, DISK_RET_EPARAM);
++        return;
++    }
++
++    struct disk_op_s dop;
++    dop.drive_g = drive_g;
++    dop.command = CMD_FORMAT;
++    dop.lba = head;
++    dop.count = num_sectors;
++    dop.buf_fl = MAKE_FLATPTR(regs->es, regs->bx);
++    int status = send_disk_op(&dop);
++    disk_ret(regs, status);
++}
++
++// read disk drive parameters
++static void
++disk_1308(struct bregs *regs, struct drive_s *drive_g)
++{
++    u16 ebda_seg = get_ebda_seg();
++    // Get logical geometry from table
++    u16 nlc, nlh, nlspt;
++    fillLCHS(drive_g, &nlc, &nlh, &nlspt);
++    nlc--;
++    nlh--;
++    u8 count;
++    if (regs->dl < EXTSTART_HD) {
++        // Floppy
++        count = GET_GLOBAL(Drives.floppycount);
++
++        if (CONFIG_CDROM_EMU && drive_g == GET_GLOBAL(cdemu_drive))
++            regs->bx = GET_EBDA2(ebda_seg, cdemu.media) * 2;
++        else
++            regs->bx = GET_GLOBAL(drive_g->floppy_type);
++
++        // set es & di to point to 11 byte diskette param table in ROM
++        regs->es = SEG_BIOS;
++        regs->di = (u32)&diskette_param_table2;
++    } else if (regs->dl < EXTSTART_CD) {
++        // Hard drive
++        count = GET_BDA(hdcount);
++        nlc--;  // last sector reserved
++    } else {
++        // Not supported on CDROM
++        disk_ret(regs, DISK_RET_EPARAM);
++        return;
++    }
++
++    if (CONFIG_CDROM_EMU && GET_EBDA2(ebda_seg, cdemu.active)) {
++        u8 emudrive = GET_EBDA2(ebda_seg, cdemu.emulated_extdrive);
++        if (((emudrive ^ regs->dl) & 0x80) == 0)
++            // Note extra drive due to emulation.
++            count++;
++        if (regs->dl < EXTSTART_HD && count > 2)
++            // Max of two floppy drives.
++            count = 2;
++    }
++
++    regs->al = 0;
++    regs->ch = nlc & 0xff;
++    regs->cl = ((nlc >> 2) & 0xc0) | (nlspt & 0x3f);
++    regs->dh = nlh;
++
++    disk_ret(regs, DISK_RET_SUCCESS);
++    regs->dl = count;
++}
++
++// initialize drive parameters
++static void
++disk_1309(struct bregs *regs, struct drive_s *drive_g)
++{
++    DISK_STUB(regs);
++}
++
++// seek to specified cylinder
++static void
++disk_130c(struct bregs *regs, struct drive_s *drive_g)
++{
++    DISK_STUB(regs);
++}
++
++// alternate disk reset
++static void
++disk_130d(struct bregs *regs, struct drive_s *drive_g)
++{
++    DISK_STUB(regs);
++}
++
++// check drive ready
++static void
++disk_1310(struct bregs *regs, struct drive_s *drive_g)
++{
++    // should look at 40:8E also???
++
++    struct disk_op_s dop;
++    dop.drive_g = drive_g;
++    dop.command = CMD_ISREADY;
++    int status = send_disk_op(&dop);
++    disk_ret(regs, status);
++}
++
++// recalibrate
++static void
++disk_1311(struct bregs *regs, struct drive_s *drive_g)
++{
++    DISK_STUB(regs);
++}
++
++// controller internal diagnostic
++static void
++disk_1314(struct bregs *regs, struct drive_s *drive_g)
++{
++    DISK_STUB(regs);
++}
++
++// read disk drive size
++static void
++disk_1315(struct bregs *regs, struct drive_s *drive_g)
++{
++    disk_ret(regs, DISK_RET_SUCCESS);
++    if (regs->dl < EXTSTART_HD || regs->dl >= EXTSTART_CD) {
++        // Floppy or cdrom
++        regs->ah = 1;
++        return;
++    }
++    // Hard drive
++
++    // Get logical geometry from table
++    u16 nlc, nlh, nlspt;
++    fillLCHS(drive_g, &nlc, &nlh, &nlspt);
++
++    // Compute sector count seen by int13
++    u32 lba = (u32)(nlc - 1) * (u32)nlh * (u32)nlspt;
++    regs->cx = lba >> 16;
++    regs->dx = lba & 0xffff;
++    regs->ah = 3; // hard disk accessible
++}
++
++static void
++disk_1316(struct bregs *regs, struct drive_s *drive_g)
++{
++    if (regs->dl >= EXTSTART_HD) {
++        // Hard drive
++        disk_ret(regs, DISK_RET_EPARAM);
++        return;
++    }
++    disk_ret(regs, DISK_RET_ECHANGED);
++}
++
++// IBM/MS installation check
++static void
++disk_1341(struct bregs *regs, struct drive_s *drive_g)
++{
++    regs->bx = 0xaa55;  // install check
++    regs->cx = 0x0007;  // ext disk access and edd, removable supported
++    disk_ret(regs, DISK_RET_SUCCESS);
++    regs->ah = 0x30;    // EDD 3.0
++}
++
++// IBM/MS extended read
++static void
++disk_1342(struct bregs *regs, struct drive_s *drive_g)
++{
++    extended_access(regs, drive_g, CMD_READ);
++}
++
++// IBM/MS extended write
++static void
++disk_1343(struct bregs *regs, struct drive_s *drive_g)
++{
++    extended_access(regs, drive_g, CMD_WRITE);
++}
++
++// IBM/MS verify
++static void
++disk_1344(struct bregs *regs, struct drive_s *drive_g)
++{
++    extended_access(regs, drive_g, CMD_VERIFY);
++}
++
++// lock
++static void
++disk_134500(struct bregs *regs, struct drive_s *drive_g)
++{
++    u16 ebda_seg = get_ebda_seg();
++    int cdid = regs->dl - EXTSTART_CD;
++    u8 locks = GET_EBDA2(ebda_seg, cdrom_locks[cdid]);
++    if (locks == 0xff) {
++        regs->al = 1;
++        disk_ret(regs, DISK_RET_ETOOMANYLOCKS);
++        return;
++    }
++    SET_EBDA2(ebda_seg, cdrom_locks[cdid], locks + 1);
++    regs->al = 1;
++    disk_ret(regs, DISK_RET_SUCCESS);
++}
++
++// unlock
++static void
++disk_134501(struct bregs *regs, struct drive_s *drive_g)
++{
++    u16 ebda_seg = get_ebda_seg();
++    int cdid = regs->dl - EXTSTART_CD;
++    u8 locks = GET_EBDA2(ebda_seg, cdrom_locks[cdid]);
++    if (locks == 0x00) {
++        regs->al = 0;
++        disk_ret(regs, DISK_RET_ENOTLOCKED);
++        return;
++    }
++    locks--;
++    SET_EBDA2(ebda_seg, cdrom_locks[cdid], locks);
++    regs->al = (locks ? 1 : 0);
++    disk_ret(regs, DISK_RET_SUCCESS);
++}
++
++// status
++static void
++disk_134502(struct bregs *regs, struct drive_s *drive_g)
++{
++    int cdid = regs->dl - EXTSTART_CD;
++    u8 locks = GET_EBDA(cdrom_locks[cdid]);
++    regs->al = (locks ? 1 : 0);
++    disk_ret(regs, DISK_RET_SUCCESS);
++}
++
++static void
++disk_1345XX(struct bregs *regs, struct drive_s *drive_g)
++{
++    disk_ret_unimplemented(regs, DISK_RET_EPARAM);
++}
++
++// IBM/MS lock/unlock drive
++static void
++disk_1345(struct bregs *regs, struct drive_s *drive_g)
++{
++    if (regs->dl < EXTSTART_CD) {
++        // Always success for HD
++        disk_ret(regs, DISK_RET_SUCCESS);
++        return;
++    }
++
++    switch (regs->al) {
++    case 0x00: disk_134500(regs, drive_g); break;
++    case 0x01: disk_134501(regs, drive_g); break;
++    case 0x02: disk_134502(regs, drive_g); break;
++    default:   disk_1345XX(regs, drive_g); break;
++    }
++}
++
++// IBM/MS eject media
++static void
++disk_1346(struct bregs *regs, struct drive_s *drive_g)
++{
++    if (regs->dl < EXTSTART_CD) {
++        // Volume Not Removable
++        disk_ret(regs, DISK_RET_ENOTREMOVABLE);
++        return;
++    }
++
++    int cdid = regs->dl - EXTSTART_CD;
++    u8 locks = GET_EBDA(cdrom_locks[cdid]);
++    if (locks != 0) {
++        disk_ret(regs, DISK_RET_ELOCKED);
++        return;
++    }
++
++    // FIXME should handle 0x31 no media in device
++    // FIXME should handle 0xb5 valid request failed
++
++    // Call removable media eject
++    struct bregs br;
++    memset(&br, 0, sizeof(br));
++    br.ah = 0x52;
++    call16_int(0x15, &br);
++
++    if (br.ah || br.flags & F_CF) {
++        disk_ret(regs, DISK_RET_ELOCKED);
++        return;
++    }
++    disk_ret(regs, DISK_RET_SUCCESS);
++}
++
++// IBM/MS extended seek
++static void
++disk_1347(struct bregs *regs, struct drive_s *drive_g)
++{
++    extended_access(regs, drive_g, CMD_SEEK);
++}
++
++// IBM/MS get drive parameters
++static void
++disk_1348(struct bregs *regs, struct drive_s *drive_g)
++{
++    u16 size = GET_INT13DPT(regs, size);
++
++    // Buffer is too small
++    if (size < 26) {
++        disk_ret(regs, DISK_RET_EPARAM);
++        return;
++    }
++
++    // EDD 1.x
++
++    u8  type    = GET_GLOBAL(drive_g->type);
++    u16 npc     = GET_GLOBAL(drive_g->pchs.cylinders);
++    u16 nph     = GET_GLOBAL(drive_g->pchs.heads);
++    u16 npspt   = GET_GLOBAL(drive_g->pchs.spt);
++    u64 lba     = GET_GLOBAL(drive_g->sectors);
++    u16 blksize = GET_GLOBAL(drive_g->blksize);
++
++    dprintf(DEBUG_HDL_13, "disk_1348 size=%d t=%d chs=%d,%d,%d lba=%d bs=%d\n"
++            , size, type, npc, nph, npspt, (u32)lba, blksize);
++
++    SET_INT13DPT(regs, size, 26);
++    if (type == DTYPE_ATAPI) {
++        // 0x74 = removable, media change, lockable, max values
++        SET_INT13DPT(regs, infos, 0x74);
++        SET_INT13DPT(regs, cylinders, 0xffffffff);
++        SET_INT13DPT(regs, heads, 0xffffffff);
++        SET_INT13DPT(regs, spt, 0xffffffff);
++        SET_INT13DPT(regs, sector_count, (u64)-1);
++    } else {
++        if (lba > (u64)npspt*nph*0x3fff) {
++            SET_INT13DPT(regs, infos, 0x00); // geometry is invalid
++            SET_INT13DPT(regs, cylinders, 0x3fff);
++        } else {
++            SET_INT13DPT(regs, infos, 0x02); // geometry is valid
++            SET_INT13DPT(regs, cylinders, (u32)npc);
++        }
++        SET_INT13DPT(regs, heads, (u32)nph);
++        SET_INT13DPT(regs, spt, (u32)npspt);
++        SET_INT13DPT(regs, sector_count, lba);
++    }
++    SET_INT13DPT(regs, blksize, blksize);
++
++    if (size < 30 || (type != DTYPE_ATA && type != DTYPE_ATAPI)) {
++        disk_ret(regs, DISK_RET_SUCCESS);
++        return;
++    }
++
++    // EDD 2.x
++
++    u16 ebda_seg = get_ebda_seg();
++    SET_INT13DPT(regs, size, 30);
++
++    SET_INT13DPT(regs, dpte_segment, ebda_seg);
++    SET_INT13DPT(regs, dpte_offset
++                 , offsetof(struct extended_bios_data_area_s, dpte));
++
++    // Fill in dpte
++    u8 ataid = GET_GLOBAL(drive_g->cntl_id);
++    u8 channel = ataid / 2;
++    u8 slave = ataid % 2;
++    u16 iobase1 = GET_GLOBAL(ATA_channels[channel].iobase1);
++    u16 iobase2 = GET_GLOBAL(ATA_channels[channel].iobase2);
++    u8 irq = GET_GLOBAL(ATA_channels[channel].irq);
++
++    u16 options = 0;
++    if (type == DTYPE_ATA) {
++        u8 translation = GET_GLOBAL(drive_g->translation);
++        if (translation != TRANSLATION_NONE) {
++            options |= 1<<3; // CHS translation
++            if (translation == TRANSLATION_LBA)
++                options |= 1<<9;
++            if (translation == TRANSLATION_RECHS)
++                options |= 3<<9;
++        }
++    } else {
++        // ATAPI
++        options |= 1<<5; // removable device
++        options |= 1<<6; // atapi device
++    }
++    options |= 1<<4; // lba translation
++    if (CONFIG_ATA_PIO32)
++        options |= 1<<7;
++
++    SET_EBDA2(ebda_seg, dpte.iobase1, iobase1);
++    SET_EBDA2(ebda_seg, dpte.iobase2, iobase2 + ATA_CB_DC);
++    SET_EBDA2(ebda_seg, dpte.prefix, ((slave ? ATA_CB_DH_DEV1 : ATA_CB_DH_DEV0)
++                                      | ATA_CB_DH_LBA));
++    SET_EBDA2(ebda_seg, dpte.unused, 0xcb);
++    SET_EBDA2(ebda_seg, dpte.irq, irq);
++    SET_EBDA2(ebda_seg, dpte.blkcount, 1);
++    SET_EBDA2(ebda_seg, dpte.dma, 0);
++    SET_EBDA2(ebda_seg, dpte.pio, 0);
++    SET_EBDA2(ebda_seg, dpte.options, options);
++    SET_EBDA2(ebda_seg, dpte.reserved, 0);
++    SET_EBDA2(ebda_seg, dpte.revision, 0x11);
++
++    u8 sum = checksum_far(
++        ebda_seg, (void*)offsetof(struct extended_bios_data_area_s, dpte), 15);
++    SET_EBDA2(ebda_seg, dpte.checksum, -sum);
++
++    if (size < 66) {
++        disk_ret(regs, DISK_RET_SUCCESS);
++        return;
++    }
++
++    // EDD 3.x
++    SET_INT13DPT(regs, key, 0xbedd);
++    SET_INT13DPT(regs, dpi_length, 36);
++    SET_INT13DPT(regs, reserved1, 0);
++    SET_INT13DPT(regs, reserved2, 0);
++
++    int bdf = GET_GLOBAL(ATA_channels[channel].pci_bdf);
++    if (bdf != -1) {
++        SET_INT13DPT(regs, host_bus[0], 'P');
++        SET_INT13DPT(regs, host_bus[1], 'C');
++        SET_INT13DPT(regs, host_bus[2], 'I');
++        SET_INT13DPT(regs, host_bus[3], 0);
++
++        u32 path = (pci_bdf_to_bus(bdf) | (pci_bdf_to_dev(bdf) << 8)
++                    | (pci_bdf_to_fn(bdf) << 16));
++        SET_INT13DPT(regs, iface_path, path);
++    } else {
++        // ISA
++        SET_INT13DPT(regs, host_bus[0], 'I');
++        SET_INT13DPT(regs, host_bus[1], 'S');
++        SET_INT13DPT(regs, host_bus[2], 'A');
++        SET_INT13DPT(regs, host_bus[3], 0);
++
++        SET_INT13DPT(regs, iface_path, iobase1);
++    }
++
++    SET_INT13DPT(regs, iface_type[0], 'A');
++    SET_INT13DPT(regs, iface_type[1], 'T');
++    SET_INT13DPT(regs, iface_type[2], 'A');
++    SET_INT13DPT(regs, iface_type[3], 0);
++    SET_INT13DPT(regs, iface_type[4], 0);
++    SET_INT13DPT(regs, iface_type[5], 0);
++    SET_INT13DPT(regs, iface_type[6], 0);
++    SET_INT13DPT(regs, iface_type[7], 0);
++
++    SET_INT13DPT(regs, device_path, slave);
++
++    SET_INT13DPT(regs, checksum
++                 , -checksum_far(regs->ds, (void*)(regs->si+30), 35));
++
++    disk_ret(regs, DISK_RET_SUCCESS);
++}
++
++// IBM/MS extended media change
++static void
++disk_1349(struct bregs *regs, struct drive_s *drive_g)
++{
++    if (regs->dl < EXTSTART_CD) {
++        // Always success for HD
++        disk_ret(regs, DISK_RET_SUCCESS);
++        return;
++    }
++    set_invalid(regs);
++    // always send changed ??
++    regs->ah = DISK_RET_ECHANGED;
++}
++
++static void
++disk_134e01(struct bregs *regs, struct drive_s *drive_g)
++{
++    disk_ret(regs, DISK_RET_SUCCESS);
++}
++
++static void
++disk_134e03(struct bregs *regs, struct drive_s *drive_g)
++{
++    disk_ret(regs, DISK_RET_SUCCESS);
++}
++
++static void
++disk_134e04(struct bregs *regs, struct drive_s *drive_g)
++{
++    disk_ret(regs, DISK_RET_SUCCESS);
++}
++
++static void
++disk_134e06(struct bregs *regs, struct drive_s *drive_g)
++{
++    disk_ret(regs, DISK_RET_SUCCESS);
++}
++
++static void
++disk_134eXX(struct bregs *regs, struct drive_s *drive_g)
++{
++    disk_ret(regs, DISK_RET_EPARAM);
++}
++
++// IBM/MS set hardware configuration
++static void
++disk_134e(struct bregs *regs, struct drive_s *drive_g)
++{
++    switch (regs->al) {
++    case 0x01: disk_134e01(regs, drive_g); break;
++    case 0x03: disk_134e03(regs, drive_g); break;
++    case 0x04: disk_134e04(regs, drive_g); break;
++    case 0x06: disk_134e06(regs, drive_g); break;
++    default:   disk_134eXX(regs, drive_g); break;
++    }
++}
++
++static void
++disk_13XX(struct bregs *regs, struct drive_s *drive_g)
++{
++    disk_ret_unimplemented(regs, DISK_RET_EPARAM);
++}
++
++static void
++disk_13(struct bregs *regs, struct drive_s *drive_g)
++{
++    //debug_stub(regs);
++
++    // clear completion flag
++    SET_BDA(disk_interrupt_flag, 0);
++
++    switch (regs->ah) {
++    case 0x00: disk_1300(regs, drive_g); break;
++    case 0x01: disk_1301(regs, drive_g); break;
++    case 0x02: disk_1302(regs, drive_g); break;
++    case 0x03: disk_1303(regs, drive_g); break;
++    case 0x04: disk_1304(regs, drive_g); break;
++    case 0x05: disk_1305(regs, drive_g); break;
++    case 0x08: disk_1308(regs, drive_g); break;
++    case 0x09: disk_1309(regs, drive_g); break;
++    case 0x0c: disk_130c(regs, drive_g); break;
++    case 0x0d: disk_130d(regs, drive_g); break;
++    case 0x10: disk_1310(regs, drive_g); break;
++    case 0x11: disk_1311(regs, drive_g); break;
++    case 0x14: disk_1314(regs, drive_g); break;
++    case 0x15: disk_1315(regs, drive_g); break;
++    case 0x16: disk_1316(regs, drive_g); break;
++    case 0x41: disk_1341(regs, drive_g); break;
++    case 0x42: disk_1342(regs, drive_g); break;
++    case 0x43: disk_1343(regs, drive_g); break;
++    case 0x44: disk_1344(regs, drive_g); break;
++    case 0x45: disk_1345(regs, drive_g); break;
++    case 0x46: disk_1346(regs, drive_g); break;
++    case 0x47: disk_1347(regs, drive_g); break;
++    case 0x48: disk_1348(regs, drive_g); break;
++    case 0x49: disk_1349(regs, drive_g); break;
++    case 0x4e: disk_134e(regs, drive_g); break;
++    default:   disk_13XX(regs, drive_g); break;
++    }
++}
++
++static void
++floppy_13(struct bregs *regs, struct drive_s *drive_g)
++{
++    // Only limited commands are supported on floppies.
++    switch (regs->ah) {
++    case 0x00:
++    case 0x01:
++    case 0x02:
++    case 0x03:
++    case 0x04:
++    case 0x05:
++    case 0x08:
++    case 0x15:
++    case 0x16:
++        disk_13(regs, drive_g);
++        break;
++    default:   disk_13XX(regs, drive_g); break;
++    }
++}
++
++
++/****************************************************************
++ * Entry points
++ ****************************************************************/
++
++static void
++handle_legacy_disk(struct bregs *regs, u8 extdrive)
++{
++    if (! CONFIG_DRIVES) {
++        // XXX - support handle_1301 anyway?
++        disk_ret(regs, DISK_RET_EPARAM);
++        return;
++    }
++
++    if (extdrive < EXTSTART_HD) {
++        struct drive_s *drive_g = getDrive(EXTTYPE_FLOPPY, extdrive);
++        if (!drive_g)
++            goto fail;
++        floppy_13(regs, drive_g);
++        return;
++    }
++
++    struct drive_s *drive_g;
++    if (extdrive >= EXTSTART_CD)
++        drive_g = getDrive(EXTTYPE_CD, extdrive - EXTSTART_CD);
++    else
++        drive_g = getDrive(EXTTYPE_HD, extdrive - EXTSTART_HD);
++    if (!drive_g)
++        goto fail;
++    disk_13(regs, drive_g);
++    return;
++
++fail:
++    // XXX - support 1301/1308/1315 anyway?
++    disk_ret(regs, DISK_RET_EPARAM);
++}
++
++void VISIBLE16
++handle_40(struct bregs *regs)
++{
++    debug_enter(regs, DEBUG_HDL_40);
++    handle_legacy_disk(regs, regs->dl);
++}
++
++// INT 13h Fixed Disk Services Entry Point
++void VISIBLE16
++handle_13(struct bregs *regs)
++{
++    debug_enter(regs, DEBUG_HDL_13);
++    u8 extdrive = regs->dl;
++
++    if (CONFIG_CDROM_EMU) {
++        if (regs->ah == 0x4b) {
++            cdemu_134b(regs);
++            return;
++        }
++        u16 ebda_seg = get_ebda_seg();
++        if (GET_EBDA2(ebda_seg, cdemu.active)) {
++            u8 emudrive = GET_EBDA2(ebda_seg, cdemu.emulated_extdrive);
++            if (extdrive == emudrive) {
++                // Access to an emulated drive.
++                struct drive_s *cdemu = GET_GLOBAL(cdemu_drive);
++                if (regs->ah > 0x16) {
++                    // Only old-style commands supported.
++                    disk_13XX(regs, cdemu);
++                    return;
++                }
++                disk_13(regs, cdemu);
++                return;
++            }
++            if (extdrive < EXTSTART_CD && ((emudrive ^ extdrive) & 0x80) == 0)
++                // Adjust id to make room for emulated drive.
++                extdrive--;
++        }
++    }
++    handle_legacy_disk(regs, extdrive);
++}
++
++// record completion in BIOS task complete flag
++void VISIBLE16
++handle_76(void)
++{
++    debug_isr(DEBUG_ISR_76);
++    SET_BDA(disk_interrupt_flag, 0xff);
++    eoi_pic2();
++}
++
++// Old Fixed Disk Parameter Table (newer tables are in the ebda).
++struct fdpt_s OldFDPT VAR16FIXED(0xe401);
+--- x/roms/seabios/src/disk.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/disk.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,264 @@
++// Definitions for X86 bios disks.
++//
++// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++#ifndef __DISK_H
++#define __DISK_H
++
++#include "types.h" // u8
++#include "config.h" // CONFIG_*
++#include "farptr.h" // struct segoff_s
++
++#define DISK_RET_SUCCESS       0x00
++#define DISK_RET_EPARAM        0x01
++#define DISK_RET_EADDRNOTFOUND 0x02
++#define DISK_RET_EWRITEPROTECT 0x03
++#define DISK_RET_ECHANGED      0x06
++#define DISK_RET_EBOUNDARY     0x09
++#define DISK_RET_EBADTRACK     0x0c
++#define DISK_RET_ECONTROLLER   0x20
++#define DISK_RET_ETIMEOUT      0x80
++#define DISK_RET_ENOTLOCKED    0xb0
++#define DISK_RET_ELOCKED       0xb1
++#define DISK_RET_ENOTREMOVABLE 0xb2
++#define DISK_RET_ETOOMANYLOCKS 0xb4
++#define DISK_RET_EMEDIA        0xC0
++#define DISK_RET_ENOTREADY     0xAA
++
++
++/****************************************************************
++ * Interface structs
++ ****************************************************************/
++
++// Bios disk structures.
++struct int13ext_s {
++    u8  size;
++    u8  reserved;
++    u16 count;
++    struct segoff_s data;
++    u64 lba;
++} PACKED;
++
++#define GET_INT13EXT(regs,var)                                          \
++    GET_FARVAR((regs)->ds, ((struct int13ext_s*)((regs)->si+0))->var)
++#define SET_INT13EXT(regs,var,val)                                      \
++    SET_FARVAR((regs)->ds, ((struct int13ext_s*)((regs)->si+0))->var, (val))
++
++// Disk Physical Table definition
++struct int13dpt_s {
++    u16 size;
++    u16 infos;
++    u32 cylinders;
++    u32 heads;
++    u32 spt;
++    u64 sector_count;
++    u16 blksize;
++    u16 dpte_offset;
++    u16 dpte_segment;
++    u16 key;
++    u8  dpi_length;
++    u8  reserved1;
++    u16 reserved2;
++    u8  host_bus[4];
++    u8  iface_type[8];
++    u64 iface_path;
++    u64 device_path;
++    u8  reserved3;
++    u8  checksum;
++} PACKED;
++
++#define GET_INT13DPT(regs,var)                                          \
++    GET_FARVAR((regs)->ds, ((struct int13dpt_s*)((regs)->si+0))->var)
++#define SET_INT13DPT(regs,var,val)                                      \
++    SET_FARVAR((regs)->ds, ((struct int13dpt_s*)((regs)->si+0))->var, (val))
++
++// Floppy "Disk Base Table"
++struct floppy_dbt_s {
++    u8 specify1;
++    u8 specify2;
++    u8 shutoff_ticks;
++    u8 bps_code;
++    u8 sectors;
++    u8 interblock_len;
++    u8 data_len;
++    u8 gap_len;
++    u8 fill_byte;
++    u8 settle_time;
++    u8 startup_time;
++} PACKED;
++
++struct floppy_ext_dbt_s {
++    struct floppy_dbt_s dbt;
++    // Extra fields
++    u8 max_track;
++    u8 data_rate;
++    u8 drive_type;
++} PACKED;
++
++// Helper function for setting up a return code.
++struct bregs;
++void __disk_ret(struct bregs *regs, u32 linecode, const char *fname);
++#define disk_ret(regs, code) \
++    __disk_ret((regs), (code) | (__LINE__ << 8), __func__)
++void __disk_ret_unimplemented(struct bregs *regs, u32 linecode
++                              , const char *fname);
++#define disk_ret_unimplemented(regs, code) \
++    __disk_ret_unimplemented((regs), (code) | (__LINE__ << 8), __func__)
++
++
++/****************************************************************
++ * Master boot record
++ ****************************************************************/
++
++struct packed_chs_s {
++    u8 heads;
++    u8 sptcyl;
++    u8 cyllow;
++};
++
++struct partition_s {
++    u8 status;
++    struct packed_chs_s first;
++    u8 type;
++    struct packed_chs_s last;
++    u32 lba;
++    u32 count;
++} PACKED;
++
++struct mbr_s {
++    u8 code[440];
++    // 0x01b8
++    u32 diskseg;
++    // 0x01bc
++    u16 null;
++    // 0x01be
++    struct partition_s partitions[4];
++    // 0x01fe
++    u16 signature;
++} PACKED;
++
++#define MBR_SIGNATURE 0xaa55
++
++
++/****************************************************************
++ * Disk command request
++ ****************************************************************/
++
++struct disk_op_s {
++    u64 lba;
++    void *buf_fl;
++    struct drive_s *drive_g;
++    u16 count;
++    u8 command;
++};
++
++#define CMD_RESET   0x00
++#define CMD_READ    0x02
++#define CMD_WRITE   0x03
++#define CMD_VERIFY  0x04
++#define CMD_FORMAT  0x05
++#define CMD_SEEK    0x07
++#define CMD_ISREADY 0x10
++
++
++/****************************************************************
++ * Global storage
++ ****************************************************************/
++
++struct chs_s {
++    u16 heads;      // # heads
++    u16 cylinders;  // # cylinders
++    u16 spt;        // # sectors / track
++};
++
++struct drive_s {
++    u8  type;         // Detected type of drive (ata/atapi/none)
++    u8  removable;    // Removable device flag
++    u16 blksize;      // block size
++    u32 cntl_id;
++    u32 cntl_info;
++    u8  floppy_type;  // Type of floppy (only for floppy drives).
++
++    char model[41];
++
++    u8  translation;  // type of translation
++    struct chs_s  lchs;         // Logical CHS
++    struct chs_s  pchs;         // Physical CHS
++
++    u64 sectors;      // Total sectors count
++};
++
++#define DISK_SECTOR_SIZE  512
++#define CDROM_SECTOR_SIZE 2048
++
++#define DTYPE_NONE     0x00
++#define DTYPE_FLOPPY   0x01
++#define DTYPE_ATA      0x02
++#define DTYPE_ATAPI    0x03
++#define DTYPE_RAMDISK  0x04
++#define DTYPE_CDEMU    0x05
++
++#define TRANSLATION_NONE  0
++#define TRANSLATION_LBA   1
++#define TRANSLATION_LARGE 2
++#define TRANSLATION_RECHS 3
++
++struct drives_s {
++    // info on each internally handled drive
++    struct drive_s drives[CONFIG_MAX_DRIVES];
++    u8 drivecount;
++    //
++    // map between bios floppy/hd/cd id and driveid index into drives[]
++    u8 floppycount;
++    u8 cdcount;
++    u8 idmap[3][CONFIG_MAX_EXTDRIVE];
++};
++
++#define EXTTYPE_FLOPPY 0
++#define EXTTYPE_HD 1
++#define EXTTYPE_CD 2
++
++#define EXTSTART_HD 0x80
++#define EXTSTART_CD 0xE0
++
++
++/****************************************************************
++ * Function defs
++ ****************************************************************/
++
++// block.c
++extern struct drives_s Drives;
++struct drive_s *getDrive(u8 exttype, u8 extdriveoffset);
++struct drive_s *allocDrive(void);
++void setup_translation(struct drive_s *drive_g);
++void map_floppy_drive(struct drive_s *drive_g);
++void map_hd_drive(struct drive_s *drive_g);
++void map_cd_drive(struct drive_s *drive_g);
++void describe_drive(struct drive_s *drive_g);
++int process_op(struct disk_op_s *op);
++int send_disk_op(struct disk_op_s *op);
++void drive_setup(void);
++
++// floppy.c
++extern struct floppy_ext_dbt_s diskette_param_table2;
++void floppy_setup(void);
++struct drive_s *addFloppy(int floppyid, int ftype, int driver);
++void describe_floppy(struct drive_s *drive_g);
++int find_floppy_type(u32 size);
++int process_floppy_op(struct disk_op_s *op);
++void floppy_tick(void);
++
++// cdrom.c
++extern struct drive_s *cdemu_drive;
++int process_cdemu_op(struct disk_op_s *op);
++void cdemu_setup(void);
++void cdemu_134b(struct bregs *regs);
++int cdrom_boot(int cdid);
++
++// ramdisk.c
++void describe_ramdisk(struct drive_s *drive_g);
++void ramdisk_setup(void);
++int process_ramdisk_op(struct disk_op_s *op);
++
++#endif // disk.h
+--- x/roms/seabios/src/entryfuncs.S	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/entryfuncs.S	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,173 @@
++// Macros for entering C code
++//
++// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++
++/****************************************************************
++ * Entry macros
++ ****************************************************************/
++
++        // Call a C function - this does the minimal work necessary to
++        // call into C.  It sets up %ds, backs up %es, and backs up
++        // those registers that are call clobbered by the C compiler.
++        .macro ENTRY cfunc
++        cli         // In case something far-calls instead of using "int"
++        cld
++        pushl %eax              // Save registers clobbered by C code
++        pushl %ecx
++        pushl %edx
++        pushw %es
++        pushw %ds
++        movw %ss, %ax           // Move %ss to %ds
++        movw %ax, %ds
++        pushl %esp              // Backup %esp, then clear high bits
++        movzwl %sp, %esp
++        calll \cfunc
++        popl %esp               // Restore %esp (including high bits)
++        popw %ds                // Restore registers saved above
++        popw %es
++        popl %edx
++        popl %ecx
++        popl %eax
++        .endm
++
++        // As above, but get calling function from stack.
++        .macro ENTRY_ST
++        cli
++        cld
++        pushl %ecx
++        pushl %edx
++        pushw %es
++        pushw %ds
++        movw %ss, %cx           // Move %ss to %ds
++        movw %cx, %ds
++        pushl %esp              // Backup %esp, then clear high bits
++        movzwl %sp, %esp
++        movl 16(%esp), %ecx     // Get calling function
++        movl %eax, 16(%esp)     // Save %eax
++        calll *%ecx
++        popl %esp               // Restore %esp (including high bits)
++        popw %ds                // Restore registers saved above
++        popw %es
++        popl %edx
++        popl %ecx
++        popl %eax
++        .endm
++
++        // Call a C function with current register list as an
++        // argument.  This backs up the registers and sets %eax
++        // to point to the backup.  On return, the registers are
++        // restored from the structure.
++        .macro ENTRY_ARG cfunc
++        cli
++        cld
++        pushl %eax              // Save registers (matches struct bregs)
++        pushl %ecx
++        pushl %edx
++        pushl %ebx
++        pushl %ebp
++        pushl %esi
++        pushl %edi
++        pushw %es
++        pushw %ds
++        movw %ss, %ax           // Move %ss to %ds
++        movw %ax, %ds
++        movl %esp, %ebx         // Backup %esp, then zero high bits
++        movzwl %sp, %esp
++        movl %esp, %eax         // First arg is pointer to struct bregs
++        calll \cfunc
++        movl %ebx, %esp         // Restore %esp (including high bits)
++        popw %ds                // Restore registers (from struct bregs)
++        popw %es
++        popl %edi
++        popl %esi
++        popl %ebp
++        popl %ebx
++        popl %edx
++        popl %ecx
++        popl %eax
++        .endm
++
++        // As above, but get calling function from stack.
++        .macro ENTRY_ARG_ST
++        cli
++        cld
++        pushl %ecx
++        pushl %edx
++        pushl %ebx
++        pushl %ebp
++        pushl %esi
++        pushl %edi
++        pushw %es
++        pushw %ds
++        movw %ss, %cx           // Move %ss to %ds
++        movw %cx, %ds
++        movl %esp, %ebx         // Backup %esp, then zero high bits
++        movzwl %sp, %esp
++        movl 28(%esp), %ecx     // Get calling function
++        movl %eax, 28(%esp)     // Save %eax
++        movl %esp, %eax         // First arg is pointer to struct bregs
++        calll *%ecx
++        movl %ebx, %esp         // Restore %esp (including high bits)
++        popw %ds                // Restore registers (from struct bregs)
++        popw %es
++        popl %edi
++        popl %esi
++        popl %ebp
++        popl %ebx
++        popl %edx
++        popl %ecx
++        popl %eax
++        .endm
++
++        // Same as ENTRY_ARG, but don't mangle %esp
++        .macro ENTRY_ARG_ESP cfunc
++        cli
++        cld
++        pushl %eax              // Save registers (matches struct bregs)
++        pushl %ecx
++        pushl %edx
++        pushl %ebx
++        pushl %ebp
++        pushl %esi
++        pushl %edi
++        pushw %es
++        pushw %ds
++        movw %ss, %ax           // Move %ss to %ds
++        movw %ax, %ds
++        movl %esp, %eax         // First arg is pointer to struct bregs
++        calll \cfunc
++        popw %ds                // Restore registers (from struct bregs)
++        popw %es
++        popl %edi
++        popl %esi
++        popl %ebp
++        popl %ebx
++        popl %edx
++        popl %ecx
++        popl %eax
++        .endm
++
++        // Reset stack, transition to 32bit mode, and call a C function.
++        // Clobbers %ax
++        .macro ENTRY_INTO32 cfunc
++        xorw %ax, %ax
++        movw %ax, %ss
++        movl $ BUILD_STACK_ADDR , %esp
++        pushl $ \cfunc
++        jmp transition32
++        .endm
++
++        // Declare a function
++        .macro DECLFUNC func
++        .section .text.asm.\func
++        .global \func
++        .endm
++
++        // Declare an exported function
++        .macro EXPORTFUNC func
++        .section .text.asm.export.\func
++        .global \func
++        .endm
+--- x/roms/seabios/src/farptr.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/farptr.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,204 @@
++// Code to access multiple segments within gcc.
++//
++// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++#ifndef __FARPTR_H
++#define __FARPTR_H
++
++#include "ioport.h" // insb
++
++// Dummy definitions used to make sure gcc understands dependencies
++// between SET_SEG and GET/READ/WRITE_SEG macros.
++extern u16 __segment_ES, __segment_CS, __segment_DS, __segment_SS;
++extern u16 __segment_FS, __segment_GS;
++
++// Low level macros for reading/writing memory via a segment selector.
++#define READ8_SEG(prefix, SEG, value, var)                      \
++    __asm__(prefix "movb %%" #SEG ":%1, %b0" : "=Qi"(value)     \
++            : "m"(var), "m"(__segment_ ## SEG))
++#define READ16_SEG(prefix, SEG, value, var)                     \
++    __asm__(prefix "movw %%" #SEG ":%1, %w0" : "=ri"(value)     \
++            : "m"(var), "m"(__segment_ ## SEG))
++#define READ32_SEG(prefix, SEG, value, var)                     \
++    __asm__(prefix "movl %%" #SEG ":%1, %0" : "=ri"(value)      \
++            : "m"(var), "m"(__segment_ ## SEG))
++#define READ64_SEG(prefix, SEG, value, var) do {                \
++        union u64_u32_u __value;                                \
++        union u64_u32_u *__r64_ptr = (union u64_u32_u *)&(var); \
++        READ32_SEG(prefix, SEG, __value.hi, __r64_ptr->hi);     \
++        READ32_SEG(prefix, SEG, __value.lo, __r64_ptr->lo);     \
++        *(u64*)&(value) = __value.val;                          \
++    } while (0)
++#define WRITE8_SEG(prefix, SEG, var, value)                     \
++    __asm__(prefix "movb %b1, %%" #SEG ":%0" : "=m"(var)        \
++            : "Q"(value), "m"(__segment_ ## SEG))
++#define WRITE16_SEG(prefix, SEG, var, value)                    \
++    __asm__(prefix "movw %w1, %%" #SEG ":%0" : "=m"(var)        \
++            : "r"(value), "m"(__segment_ ## SEG))
++#define WRITE32_SEG(prefix, SEG, var, value)                    \
++    __asm__(prefix "movl %1, %%" #SEG ":%0" : "=m"(var)         \
++            : "r"(value), "m"(__segment_ ## SEG))
++#define WRITE64_SEG(prefix, SEG, var, value) do {               \
++        union u64_u32_u __value;                                \
++        union u64_u32_u *__w64_ptr = (union u64_u32_u *)&(var); \
++        typeof(var) __value_tmp = (value);                      \
++        __value.val = *(u64*)&__value_tmp;                      \
++        WRITE32_SEG(prefix, SEG, __w64_ptr->hi, __value.hi);    \
++        WRITE32_SEG(prefix, SEG, __w64_ptr->lo, __value.lo);    \
++    } while (0)
++
++// Macros for automatically choosing the appropriate memory size
++// access method.
++extern void __force_link_error__unknown_type(void);
++
++#define __GET_VAR(prefix, seg, var) ({          \
++    typeof(var) __val;                          \
++    if (sizeof(__val) == 1)                     \
++        READ8_SEG(prefix, seg, __val, var);     \
++    else if (sizeof(__val) == 2)                \
++        READ16_SEG(prefix, seg, __val, var);    \
++    else if (sizeof(__val) == 4)                \
++        READ32_SEG(prefix, seg, __val, var);    \
++    else if (sizeof(__val) == 8)                \
++        READ64_SEG(prefix, seg, __val, var);    \
++    else                                        \
++        __force_link_error__unknown_type();     \
++    __val; })
++
++#define __SET_VAR(prefix, seg, var, val) do {           \
++        if (sizeof(var) == 1)                           \
++            WRITE8_SEG(prefix, seg, var, (val));        \
++        else if (sizeof(var) == 2)                      \
++            WRITE16_SEG(prefix, seg, var, (val));       \
++        else if (sizeof(var) == 4)                      \
++            WRITE32_SEG(prefix, seg, var, (val));       \
++        else if (sizeof(var) == 8)                      \
++            WRITE64_SEG(prefix, seg, var, (val));       \
++        else                                            \
++            __force_link_error__unknown_type();         \
++    } while (0)
++
++// Low level macros for getting/setting a segment register.
++#define __SET_SEG(SEG, value)                                   \
++    __asm__("movw %w1, %%" #SEG : "=m"(__segment_ ## SEG)       \
++            : "rm"(value))
++#define __GET_SEG(SEG) ({                                       \
++    u16 __seg;                                                  \
++    __asm__("movw %%" #SEG ", %w0" : "=rm"(__seg)               \
++            : "m"(__segment_ ## SEG));                          \
++    __seg;})
++
++// Macros for accessing a variable in another segment.  (They
++// automatically update the %es segment and then make the appropriate
++// access.)
++#define __GET_FARVAR(seg, var) ({               \
++    SET_SEG(ES, (seg));                         \
++    GET_VAR(ES, (var)); })
++#define __SET_FARVAR(seg, var, val) do {        \
++        typeof(var) __sfv_val = (val);          \
++        SET_SEG(ES, (seg));                     \
++        SET_VAR(ES, (var), __sfv_val);          \
++    } while (0)
++
++// Macros for accesssing a 32bit flat mode pointer from 16bit real
++// mode.  (They automatically update the %es segment, break the
++// pointer into segment/offset, and then make the access.)
++#define __GET_FLATPTR(ptr) ({                                   \
++    typeof(&(ptr)) __ptr = &(ptr);                              \
++    GET_FARVAR(FLATPTR_TO_SEG(__ptr)                            \
++               , *(typeof(__ptr))FLATPTR_TO_OFFSET(__ptr)); })
++#define __SET_FLATPTR(ptr, val) do {                            \
++        typeof (&(ptr)) __ptr = &(ptr);                         \
++        SET_FARVAR(FLATPTR_TO_SEG(__ptr)                        \
++                   , *(typeof(__ptr))FLATPTR_TO_OFFSET(__ptr)   \
++                   , (val));                                    \
++    } while (0)
++
++// Macros for converting to/from 32bit flat mode pointers to their
++// equivalent 16bit segment/offset values.
++#define FLATPTR_TO_SEG(p) (((u32)(p)) >> 4)
++#define FLATPTR_TO_OFFSET(p) (((u32)(p)) & 0xf)
++#define MAKE_FLATPTR(seg,off) ((void*)(((u32)(seg)<<4)+(u32)(off)))
++
++
++#if MODESEGMENT == 1
++
++// Definitions when using segmented mode.
++#define GET_FARVAR(seg, var) __GET_FARVAR((seg), (var))
++#define SET_FARVAR(seg, var, val) __SET_FARVAR((seg), (var), (val))
++#define GET_VAR(seg, var) __GET_VAR("", seg, (var))
++#define SET_VAR(seg, var, val) __SET_VAR("", seg, (var), (val))
++#define SET_SEG(SEG, value) __SET_SEG(SEG, (value))
++#define GET_SEG(SEG) __GET_SEG(SEG)
++#define GET_FLATPTR(ptr) __GET_FLATPTR(ptr)
++#define SET_FLATPTR(ptr, val) __SET_FLATPTR((ptr), (val))
++
++static inline void insb_fl(u16 port, void *ptr_fl, u16 count) {
++    SET_SEG(ES, FLATPTR_TO_SEG(ptr_fl));
++    insb(port, (u8*)FLATPTR_TO_OFFSET(ptr_fl), count);
++}
++static inline void insw_fl(u16 port, void *ptr_fl, u16 count) {
++    SET_SEG(ES, FLATPTR_TO_SEG(ptr_fl));
++    insw(port, (u16*)FLATPTR_TO_OFFSET(ptr_fl), count);
++}
++static inline void insl_fl(u16 port, void *ptr_fl, u16 count) {
++    SET_SEG(ES, FLATPTR_TO_SEG(ptr_fl));
++    insl(port, (u32*)FLATPTR_TO_OFFSET(ptr_fl), count);
++}
++static inline void outsb_fl(u16 port, void *ptr_fl, u16 count) {
++    SET_SEG(ES, FLATPTR_TO_SEG(ptr_fl));
++    outsb(port, (u8*)FLATPTR_TO_OFFSET(ptr_fl), count);
++}
++static inline void outsw_fl(u16 port, void *ptr_fl, u16 count) {
++    SET_SEG(ES, FLATPTR_TO_SEG(ptr_fl));
++    outsw(port, (u16*)FLATPTR_TO_OFFSET(ptr_fl), count);
++}
++static inline void outsl_fl(u16 port, void *ptr_fl, u16 count) {
++    SET_SEG(ES, FLATPTR_TO_SEG(ptr_fl));
++    outsl(port, (u32*)FLATPTR_TO_OFFSET(ptr_fl), count);
++}
++
++#else
++
++// In 32-bit flat mode there is no need to mess with the segments.
++#define GET_FARVAR(seg, var) \
++    (*((typeof(&(var)))MAKE_FLATPTR((seg), &(var))))
++#define SET_FARVAR(seg, var, val) \
++    do { GET_FARVAR((seg), (var)) = (val); } while (0)
++#define GET_VAR(seg, var) (var)
++#define SET_VAR(seg, var, val) do { (var) = (val); } while (0)
++#define SET_SEG(SEG, value) ((void)(value))
++#define GET_SEG(SEG) 0
++#define GET_FLATPTR(ptr) (ptr)
++#define SET_FLATPTR(ptr, val) do { (ptr) = (val); } while (0)
++
++#define insb_fl(port, ptr_fl, count) insb(port, ptr_fl, count)
++#define insw_fl(port, ptr_fl, count) insw(port, ptr_fl, count)
++#define insl_fl(port, ptr_fl, count) insl(port, ptr_fl, count)
++#define outsb_fl(port, ptr_fl, count) outsb(port, ptr_fl, count)
++#define outsw_fl(port, ptr_fl, count) outsw(port, ptr_fl, count)
++#define outsl_fl(port, ptr_fl, count) outsl(port, ptr_fl, count)
++
++#endif
++
++// Definition for common 16bit segment/offset pointers.
++struct segoff_s {
++    union {
++        struct {
++            u16 offset;
++            u16 seg;
++        };
++        u32 segoff;
++    };
++};
++#define SEGOFF(s,o) ({struct segoff_s __so; __so.offset=(o); __so.seg=(s); __so;})
++
++static inline struct segoff_s FLATPTR_TO_SEGOFF(void *p) {
++    return SEGOFF(FLATPTR_TO_SEG(p), FLATPTR_TO_OFFSET(p));
++}
++static inline void *SEGOFF_TO_FLATPTR(struct segoff_s so) {
++    return MAKE_FLATPTR(so.seg, so.offset);
++}
++
++#endif // farptr.h
+--- x/roms/seabios/src/floppy.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/floppy.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,610 @@
++// 16bit code to access floppy drives.
++//
++// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2002  MandrakeSoft S.A.
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "types.h" // u8
++#include "disk.h" // DISK_RET_SUCCESS
++#include "config.h" // CONFIG_FLOPPY
++#include "biosvar.h" // SET_BDA
++#include "util.h" // wait_irq
++#include "cmos.h" // inb_cmos
++#include "pic.h" // eoi_pic1
++#include "bregs.h" // struct bregs
++
++#define FLOPPY_SIZE_CODE 0x02 // 512 byte sectors
++#define FLOPPY_DATALEN 0xff   // Not used - because size code is 0x02
++#define FLOPPY_MOTOR_TICKS 37 // ~2 seconds
++#define FLOPPY_FILLBYTE 0xf6
++#define FLOPPY_GAPLEN 0x1B
++#define FLOPPY_FORMAT_GAPLEN 0x6c
++
++// New diskette parameter table adding 3 parameters from IBM
++// Since no provisions are made for multiple drive types, most
++// values in this table are ignored.  I set parameters for 1.44M
++// floppy here
++struct floppy_ext_dbt_s diskette_param_table2 VAR16VISIBLE = {
++    .dbt = {
++        .specify1       = 0xAF, // step rate 12ms, head unload 240ms
++        .specify2       = 0x02, // head load time 4ms, DMA used
++        .shutoff_ticks  = FLOPPY_MOTOR_TICKS, // ~2 seconds
++        .bps_code       = FLOPPY_SIZE_CODE,
++        .sectors        = 18,
++        .interblock_len = FLOPPY_GAPLEN,
++        .data_len       = FLOPPY_DATALEN,
++        .gap_len        = FLOPPY_FORMAT_GAPLEN,
++        .fill_byte      = FLOPPY_FILLBYTE,
++        .settle_time    = 0x0F, // 15ms
++        .startup_time   = 0x08, // 1 second
++    },
++    .max_track      = 79,   // maximum track
++    .data_rate      = 0,    // data transfer rate
++    .drive_type     = 4,    // drive type in cmos
++};
++
++// Since no provisions are made for multiple drive types, most
++// values in this table are ignored.  I set parameters for 1.44M
++// floppy here
++struct floppy_dbt_s diskette_param_table VAR16FIXED(0xefc7) = {
++    .specify1       = 0xAF,
++    .specify2       = 0x02,
++    .shutoff_ticks  = FLOPPY_MOTOR_TICKS,
++    .bps_code       = FLOPPY_SIZE_CODE,
++    .sectors        = 18,
++    .interblock_len = FLOPPY_GAPLEN,
++    .data_len       = FLOPPY_DATALEN,
++    .gap_len        = FLOPPY_FORMAT_GAPLEN,
++    .fill_byte      = FLOPPY_FILLBYTE,
++    .settle_time    = 0x0F,
++    .startup_time   = 0x08,
++};
++
++struct floppyinfo_s {
++    struct chs_s chs;
++    u8 config_data;
++    u8 media_state;
++};
++
++struct floppyinfo_s FloppyInfo[] VAR16VISIBLE = {
++    // Unknown
++    { {0, 0, 0}, 0x00, 0x00},
++    // 1 - 360KB, 5.25" - 2 heads, 40 tracks, 9 sectors
++    { {2, 40, 9}, 0x00, 0x25},
++    // 2 - 1.2MB, 5.25" - 2 heads, 80 tracks, 15 sectors
++    { {2, 80, 15}, 0x00, 0x25},
++    // 3 - 720KB, 3.5"  - 2 heads, 80 tracks, 9 sectors
++    { {2, 80, 9}, 0x00, 0x17},
++    // 4 - 1.44MB, 3.5" - 2 heads, 80 tracks, 18 sectors
++    { {2, 80, 18}, 0x00, 0x17},
++    // 5 - 2.88MB, 3.5" - 2 heads, 80 tracks, 36 sectors
++    { {2, 80, 36}, 0xCC, 0xD7},
++    // 6 - 160k, 5.25"  - 1 heads, 40 tracks, 8 sectors
++    { {1, 40, 8}, 0x00, 0x27},
++    // 7 - 180k, 5.25"  - 1 heads, 40 tracks, 9 sectors
++    { {1, 40, 9}, 0x00, 0x27},
++    // 8 - 320k, 5.25"  - 2 heads, 40 tracks, 8 sectors
++    { {2, 40, 8}, 0x00, 0x27},
++};
++
++struct drive_s *
++addFloppy(int floppyid, int ftype, int driver)
++{
++    if (ftype <= 0 || ftype >= ARRAY_SIZE(FloppyInfo)) {
++        dprintf(1, "Bad floppy type %d\n", ftype);
++        return NULL;
++    }
++
++    struct drive_s *drive_g = allocDrive();
++    if (!drive_g)
++        return NULL;
++    drive_g->cntl_id = floppyid;
++    drive_g->type = driver;
++    drive_g->blksize = DISK_SECTOR_SIZE;
++    drive_g->floppy_type = ftype;
++    drive_g->sectors = (u64)-1;
++
++    memcpy(&drive_g->lchs, &FloppyInfo[ftype].chs
++           , sizeof(FloppyInfo[ftype].chs));
++
++    map_floppy_drive(drive_g);
++    return drive_g;
++}
++
++void
++describe_floppy(struct drive_s *drive_g)
++{
++    printf("drive %c", 'A' + drive_g->cntl_id);
++}
++
++void
++floppy_setup(void)
++{
++    if (! CONFIG_FLOPPY)
++        return;
++    dprintf(3, "init floppy drives\n");
++
++    if (CONFIG_COREBOOT) {
++        // XXX - disable floppies on coreboot for now.
++    } else {
++        u8 type = inb_cmos(CMOS_FLOPPY_DRIVE_TYPE);
++        if (type & 0xf0)
++            addFloppy(0, type >> 4, DTYPE_FLOPPY);
++        if (type & 0x0f)
++            addFloppy(1, type & 0x0f, DTYPE_FLOPPY);
++    }
++
++    outb(0x02, PORT_DMA1_MASK_REG);
++
++    enable_hwirq(6, entry_0e);
++}
++
++// Find a floppy type that matches a given image size.
++int
++find_floppy_type(u32 size)
++{
++    int i;
++    for (i=1; i<ARRAY_SIZE(FloppyInfo); i++) {
++        struct chs_s *c = &FloppyInfo[i].chs;
++        if (c->cylinders * c->heads * c->spt * DISK_SECTOR_SIZE == size)
++            return i;
++    }
++    return -1;
++}
++
++
++/****************************************************************
++ * Low-level floppy IO
++ ****************************************************************/
++
++static void
++floppy_reset_controller(void)
++{
++    // Reset controller
++    u8 val8 = inb(PORT_FD_DOR);
++    outb(val8 & ~0x04, PORT_FD_DOR);
++    outb(val8 | 0x04, PORT_FD_DOR);
++
++    // Wait for controller to come out of reset
++    while ((inb(PORT_FD_STATUS) & 0xc0) != 0x80)
++        ;
++}
++
++static int
++wait_floppy_irq(void)
++{
++    ASSERT16();
++    u8 v;
++    for (;;) {
++        if (!GET_BDA(floppy_motor_counter))
++            return -1;
++        v = GET_BDA(floppy_recalibration_status);
++        if (v & FRS_TIMEOUT)
++            break;
++        wait_irq();
++    }
++
++    v &= ~FRS_TIMEOUT;
++    SET_BDA(floppy_recalibration_status, v);
++    return 0;
++}
++
++static void
++floppy_prepare_controller(u8 floppyid)
++{
++    CLEARBITS_BDA(floppy_recalibration_status, FRS_TIMEOUT);
++
++    // turn on motor of selected drive, DMA & int enabled, normal operation
++    u8 prev_reset = inb(PORT_FD_DOR) & 0x04;
++    u8 dor = 0x10;
++    if (floppyid)
++        dor = 0x20;
++    dor |= 0x0c;
++    dor |= floppyid;
++    outb(dor, PORT_FD_DOR);
++
++    // reset the disk motor timeout value of INT 08
++    SET_BDA(floppy_motor_counter, FLOPPY_MOTOR_TICKS);
++
++    // wait for drive readiness
++    while ((inb(PORT_FD_STATUS) & 0xc0) != 0x80)
++        ;
++
++    if (!prev_reset)
++        wait_floppy_irq();
++}
++
++static int
++floppy_pio(u8 *cmd, u8 cmdlen)
++{
++    floppy_prepare_controller(cmd[1] & 1);
++
++    // send command to controller
++    u8 i;
++    for (i=0; i<cmdlen; i++)
++        outb(cmd[i], PORT_FD_DATA);
++
++    int ret = wait_floppy_irq();
++    if (ret) {
++        floppy_reset_controller();
++        return -1;
++    }
++
++    return 0;
++}
++
++static int
++floppy_cmd(struct disk_op_s *op, u16 count, u8 *cmd, u8 cmdlen)
++{
++    // es:bx = pointer to where to place information from diskette
++    u32 addr = (u32)op->buf_fl;
++
++    // check for 64K boundary overrun
++    u16 end = count - 1;
++    u32 last_addr = addr + end;
++    if ((addr >> 16) != (last_addr >> 16))
++        return DISK_RET_EBOUNDARY;
++
++    u8 mode_register = 0x4a; // single mode, increment, autoinit disable,
++    if (cmd[0] == 0xe6)
++        // read
++        mode_register = 0x46;
++
++    //DEBUGF("floppy dma c2\n");
++    outb(0x06, PORT_DMA1_MASK_REG);
++    outb(0x00, PORT_DMA1_CLEAR_FF_REG); // clear flip-flop
++    outb(addr, PORT_DMA_ADDR_2);
++    outb(addr>>8, PORT_DMA_ADDR_2);
++    outb(0x00, PORT_DMA1_CLEAR_FF_REG); // clear flip-flop
++    outb(end, PORT_DMA_CNT_2);
++    outb(end>>8, PORT_DMA_CNT_2);
++
++    // port 0b: DMA-1 Mode Register
++    // transfer type=write, channel 2
++    outb(mode_register, PORT_DMA1_MODE_REG);
++
++    // port 81: DMA-1 Page Register, channel 2
++    outb(addr>>16, PORT_DMA_PAGE_2);
++
++    outb(0x02, PORT_DMA1_MASK_REG); // unmask channel 2
++
++    int ret = floppy_pio(cmd, cmdlen);
++    if (ret)
++        return DISK_RET_ETIMEOUT;
++
++    // check port 3f4 for accessibility to status bytes
++    if ((inb(PORT_FD_STATUS) & 0xc0) != 0xc0)
++        return DISK_RET_ECONTROLLER;
++
++    // read 7 return status bytes from controller
++    u8 i;
++    for (i=0; i<7; i++) {
++        u8 v = inb(PORT_FD_DATA);
++        cmd[i] = v;
++        SET_BDA(floppy_return_status[i], v);
++    }
++
++    return DISK_RET_SUCCESS;
++}
++
++
++/****************************************************************
++ * Floppy media sense
++ ****************************************************************/
++
++static inline void
++set_diskette_current_cyl(u8 floppyid, u8 cyl)
++{
++    SET_BDA(floppy_track[floppyid], cyl);
++}
++
++static void
++floppy_drive_recal(u8 floppyid)
++{
++    // send Recalibrate command (2 bytes) to controller
++    u8 data[12];
++    data[0] = 0x07;  // 07: Recalibrate
++    data[1] = floppyid; // 0=drive0, 1=drive1
++    floppy_pio(data, 2);
++
++    SETBITS_BDA(floppy_recalibration_status, 1<<floppyid);
++    set_diskette_current_cyl(floppyid, 0);
++}
++
++static int
++floppy_media_sense(struct drive_s *drive_g)
++{
++    // for now cheat and get drive type from CMOS,
++    // assume media is same as drive type
++
++    // ** config_data **
++    // Bitfields for diskette media control:
++    // Bit(s)  Description (Table M0028)
++    //  7-6  last data rate set by controller
++    //        00=500kbps, 01=300kbps, 10=250kbps, 11=1Mbps
++    //  5-4  last diskette drive step rate selected
++    //        00=0Ch, 01=0Dh, 10=0Eh, 11=0Ah
++    //  3-2  {data rate at start of operation}
++    //  1-0  reserved
++
++    // ** media_state **
++    // Bitfields for diskette drive media state:
++    // Bit(s)  Description (Table M0030)
++    //  7-6  data rate
++    //    00=500kbps, 01=300kbps, 10=250kbps, 11=1Mbps
++    //  5  double stepping required (e.g. 360kB in 1.2MB)
++    //  4  media type established
++    //  3  drive capable of supporting 4MB media
++    //  2-0  on exit from BIOS, contains
++    //    000 trying 360kB in 360kB
++    //    001 trying 360kB in 1.2MB
++    //    010 trying 1.2MB in 1.2MB
++    //    011 360kB in 360kB established
++    //    100 360kB in 1.2MB established
++    //    101 1.2MB in 1.2MB established
++    //    110 reserved
++    //    111 all other formats/drives
++
++    u8 ftype = GET_GLOBAL(drive_g->floppy_type);
++    SET_BDA(floppy_last_data_rate, GET_GLOBAL(FloppyInfo[ftype].config_data));
++    u8 floppyid = GET_GLOBAL(drive_g->cntl_id);
++    SET_BDA(floppy_media_state[floppyid]
++            , GET_GLOBAL(FloppyInfo[ftype].media_state));
++    return DISK_RET_SUCCESS;
++}
++
++static int
++check_recal_drive(struct drive_s *drive_g)
++{
++    u8 floppyid = GET_GLOBAL(drive_g->cntl_id);
++    if ((GET_BDA(floppy_recalibration_status) & (1<<floppyid))
++        && (GET_BDA(floppy_media_state[floppyid]) & FMS_MEDIA_DRIVE_ESTABLISHED))
++        // Media is known.
++        return DISK_RET_SUCCESS;
++
++    // Recalibrate drive.
++    floppy_drive_recal(floppyid);
++
++    // Sense media.
++    return floppy_media_sense(drive_g);
++}
++
++
++/****************************************************************
++ * Floppy handlers
++ ****************************************************************/
++
++static void
++lba2chs(struct disk_op_s *op, u8 *track, u8 *sector, u8 *head)
++{
++    u32 lba = op->lba;
++
++    u32 tmp = lba + 1;
++    u16 nlspt = GET_GLOBAL(op->drive_g->lchs.spt);
++    *sector = tmp % nlspt;
++
++    tmp /= nlspt;
++    u16 nlh = GET_GLOBAL(op->drive_g->lchs.heads);
++    *head = tmp % nlh;
++
++    tmp /= nlh;
++    *track = tmp;
++}
++
++// diskette controller reset
++static int
++floppy_reset(struct disk_op_s *op)
++{
++    u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id);
++    set_diskette_current_cyl(floppyid, 0); // current cylinder
++    return DISK_RET_SUCCESS;
++}
++
++// Read Diskette Sectors
++static int
++floppy_read(struct disk_op_s *op)
++{
++    int res = check_recal_drive(op->drive_g);
++    if (res)
++        goto fail;
++
++    u8 track, sector, head;
++    lba2chs(op, &track, &sector, &head);
++
++    // send read-normal-data command (9 bytes) to controller
++    u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id);
++    u8 data[12];
++    data[0] = 0xe6; // e6: read normal data
++    data[1] = (head << 2) | floppyid; // HD DR1 DR2
++    data[2] = track;
++    data[3] = head;
++    data[4] = sector;
++    data[5] = FLOPPY_SIZE_CODE;
++    data[6] = sector + op->count - 1; // last sector to read on track
++    data[7] = FLOPPY_GAPLEN;
++    data[8] = FLOPPY_DATALEN;
++
++    res = floppy_cmd(op, op->count * DISK_SECTOR_SIZE, data, 9);
++    if (res)
++        goto fail;
++
++    if (data[0] & 0xc0) {
++        res = DISK_RET_ECONTROLLER;
++        goto fail;
++    }
++
++    // ??? should track be new val from return_status[3] ?
++    set_diskette_current_cyl(floppyid, track);
++    return DISK_RET_SUCCESS;
++fail:
++    op->count = 0; // no sectors read
++    return res;
++}
++
++// Write Diskette Sectors
++static int
++floppy_write(struct disk_op_s *op)
++{
++    int res = check_recal_drive(op->drive_g);
++    if (res)
++        goto fail;
++
++    u8 track, sector, head;
++    lba2chs(op, &track, &sector, &head);
++
++    // send write-normal-data command (9 bytes) to controller
++    u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id);
++    u8 data[12];
++    data[0] = 0xc5; // c5: write normal data
++    data[1] = (head << 2) | floppyid; // HD DR1 DR2
++    data[2] = track;
++    data[3] = head;
++    data[4] = sector;
++    data[5] = FLOPPY_SIZE_CODE;
++    data[6] = sector + op->count - 1; // last sector to write on track
++    data[7] = FLOPPY_GAPLEN;
++    data[8] = FLOPPY_DATALEN;
++
++    res = floppy_cmd(op, op->count * DISK_SECTOR_SIZE, data, 9);
++    if (res)
++        goto fail;
++
++    if (data[0] & 0xc0) {
++        if (data[1] & 0x02)
++            res = DISK_RET_EWRITEPROTECT;
++        else
++            res = DISK_RET_ECONTROLLER;
++        goto fail;
++    }
++
++    // ??? should track be new val from return_status[3] ?
++    set_diskette_current_cyl(floppyid, track);
++    return DISK_RET_SUCCESS;
++fail:
++    op->count = 0; // no sectors read
++    return res;
++}
++
++// Verify Diskette Sectors
++static int
++floppy_verify(struct disk_op_s *op)
++{
++    int res = check_recal_drive(op->drive_g);
++    if (res)
++        goto fail;
++
++    u8 track, sector, head;
++    lba2chs(op, &track, &sector, &head);
++
++    // ??? should track be new val from return_status[3] ?
++    u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id);
++    set_diskette_current_cyl(floppyid, track);
++    return DISK_RET_SUCCESS;
++fail:
++    op->count = 0; // no sectors read
++    return res;
++}
++
++// format diskette track
++static int
++floppy_format(struct disk_op_s *op)
++{
++    int ret = check_recal_drive(op->drive_g);
++    if (ret)
++        return ret;
++
++    u8 head = op->lba;
++
++    // send format-track command (6 bytes) to controller
++    u8 floppyid = GET_GLOBAL(op->drive_g->cntl_id);
++    u8 data[12];
++    data[0] = 0x4d; // 4d: format track
++    data[1] = (head << 2) | floppyid; // HD DR1 DR2
++    data[2] = FLOPPY_SIZE_CODE;
++    data[3] = op->count; // number of sectors per track
++    data[4] = FLOPPY_FORMAT_GAPLEN;
++    data[5] = FLOPPY_FILLBYTE;
++
++    ret = floppy_cmd(op, op->count * 4, data, 6);
++    if (ret)
++        return ret;
++
++    if (data[0] & 0xc0) {
++        if (data[1] & 0x02)
++            return DISK_RET_EWRITEPROTECT;
++        return DISK_RET_ECONTROLLER;
++    }
++
++    set_diskette_current_cyl(floppyid, 0);
++    return DISK_RET_SUCCESS;
++}
++
++int
++process_floppy_op(struct disk_op_s *op)
++{
++    if (!CONFIG_FLOPPY)
++        return 0;
++
++    switch (op->command) {
++    case CMD_RESET:
++        return floppy_reset(op);
++    case CMD_READ:
++        return floppy_read(op);
++    case CMD_WRITE:
++        return floppy_write(op);
++    case CMD_VERIFY:
++        return floppy_verify(op);
++    case CMD_FORMAT:
++        return floppy_format(op);
++    default:
++        op->count = 0;
++        return DISK_RET_EPARAM;
++    }
++}
++
++
++/****************************************************************
++ * HW irqs
++ ****************************************************************/
++
++// INT 0Eh Diskette Hardware ISR Entry Point
++void VISIBLE16
++handle_0e(void)
++{
++    debug_isr(DEBUG_ISR_0e);
++    if (! CONFIG_FLOPPY)
++        goto done;
++
++    if ((inb(PORT_FD_STATUS) & 0xc0) != 0xc0) {
++        outb(0x08, PORT_FD_DATA); // sense interrupt status
++        while ((inb(PORT_FD_STATUS) & 0xc0) != 0xc0)
++            ;
++        do {
++            inb(PORT_FD_DATA);
++        } while ((inb(PORT_FD_STATUS) & 0xc0) == 0xc0);
++    }
++    // diskette interrupt has occurred
++    SETBITS_BDA(floppy_recalibration_status, FRS_TIMEOUT);
++
++done:
++    eoi_pic1();
++}
++
++// Called from int08 handler.
++void
++floppy_tick(void)
++{
++    if (! CONFIG_FLOPPY)
++        return;
++
++    // time to turn off drive(s)?
++    u8 fcount = GET_BDA(floppy_motor_counter);
++    if (fcount) {
++        fcount--;
++        SET_BDA(floppy_motor_counter, fcount);
++        if (fcount == 0)
++            // turn motor(s) off
++            outb(inb(PORT_FD_DOR) & 0xcf, PORT_FD_DOR);
++    }
++}
+--- x/roms/seabios/src/font.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/font.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,139 @@
++#include "types.h" // u8
++
++// Character Font for 320x200 & 640x200 Graphics (lower 128 characters)
++
++/*
++ * This font comes from the fntcol16.zip package (c) by  Joseph Gil
++ * found at ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip
++ * This font is public domain
++ */
++u8 vgafont8[128*8] VAR16FIXED(0xfa6e) = {
++    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++    0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e,
++    0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e,
++    0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00,
++    0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00,
++    0x38, 0x7c, 0x38, 0xfe, 0xfe, 0x7c, 0x38, 0x7c,
++    0x10, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x7c,
++    0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00,
++    0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff,
++    0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00,
++    0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff,
++    0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78,
++    0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18,
++    0x3f, 0x33, 0x3f, 0x30, 0x30, 0x70, 0xf0, 0xe0,
++    0x7f, 0x63, 0x7f, 0x63, 0x63, 0x67, 0xe6, 0xc0,
++    0x99, 0x5a, 0x3c, 0xe7, 0xe7, 0x3c, 0x5a, 0x99,
++    0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00,
++    0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00,
++    0x18, 0x3c, 0x7e, 0x18, 0x18, 0x7e, 0x3c, 0x18,
++    0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00,
++    0x7f, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x00,
++    0x3e, 0x63, 0x38, 0x6c, 0x6c, 0x38, 0xcc, 0x78,
++    0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00,
++    0x18, 0x3c, 0x7e, 0x18, 0x7e, 0x3c, 0x18, 0xff,
++    0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00,
++    0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00,
++    0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00,
++    0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00,
++    0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00,
++    0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00,
++    0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00,
++    0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00, 0x00,
++    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++    0x30, 0x78, 0x78, 0x30, 0x30, 0x00, 0x30, 0x00,
++    0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
++    0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00,
++    0x30, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x30, 0x00,
++    0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00,
++    0x38, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0x76, 0x00,
++    0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
++    0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00,
++    0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00,
++    0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00,
++    0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00,
++    0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60,
++    0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00,
++    0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00,
++    0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00,
++    0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0x7c, 0x00,
++    0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00,
++    0x78, 0xcc, 0x0c, 0x38, 0x60, 0xcc, 0xfc, 0x00,
++    0x78, 0xcc, 0x0c, 0x38, 0x0c, 0xcc, 0x78, 0x00,
++    0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00,
++    0xfc, 0xc0, 0xf8, 0x0c, 0x0c, 0xcc, 0x78, 0x00,
++    0x38, 0x60, 0xc0, 0xf8, 0xcc, 0xcc, 0x78, 0x00,
++    0xfc, 0xcc, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00,
++    0x78, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0x78, 0x00,
++    0x78, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0x70, 0x00,
++    0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00,
++    0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60,
++    0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00,
++    0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00,
++    0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00,
++    0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00,
++    0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x78, 0x00,
++    0x30, 0x78, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0x00,
++    0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00,
++    0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00,
++    0xf8, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00,
++    0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00,
++    0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00,
++    0x3c, 0x66, 0xc0, 0xc0, 0xce, 0x66, 0x3e, 0x00,
++    0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0xcc, 0x00,
++    0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
++    0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00,
++    0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00,
++    0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00,
++    0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00,
++    0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00,
++    0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00,
++    0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00,
++    0x78, 0xcc, 0xcc, 0xcc, 0xdc, 0x78, 0x1c, 0x00,
++    0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00,
++    0x78, 0xcc, 0xe0, 0x70, 0x1c, 0xcc, 0x78, 0x00,
++    0xfc, 0xb4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
++    0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0x00,
++    0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00,
++    0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00,
++    0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00,
++    0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x78, 0x00,
++    0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00,
++    0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00,
++    0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00,
++    0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00,
++    0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
++    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
++    0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
++    0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00,
++    0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xdc, 0x00,
++    0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x00,
++    0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00,
++    0x00, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00,
++    0x38, 0x6c, 0x60, 0xf0, 0x60, 0x60, 0xf0, 0x00,
++    0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
++    0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00,
++    0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
++    0x0c, 0x00, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78,
++    0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00,
++    0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
++    0x00, 0x00, 0xcc, 0xfe, 0xfe, 0xd6, 0xc6, 0x00,
++    0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x00,
++    0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00,
++    0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0,
++    0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e,
++    0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0xf0, 0x00,
++    0x00, 0x00, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x00,
++    0x10, 0x30, 0x7c, 0x30, 0x30, 0x34, 0x18, 0x00,
++    0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00,
++    0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00,
++    0x00, 0x00, 0xc6, 0xd6, 0xfe, 0xfe, 0x6c, 0x00,
++    0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00,
++    0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
++    0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00,
++    0x1c, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x1c, 0x00,
++    0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00,
++    0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00,
++    0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++    0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00,
++};
+--- x/roms/seabios/src/gen-defs.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/gen-defs.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,19 @@
++// Tool for building defintions accessible from assembler code.  This
++// is based on code from the Linux Kernel.
++#ifndef __GEN_DEFS_H
++#define __GEN_DEFS_H
++
++
++#define DEFINE(sym, val) \
++    asm volatile("\n->" #sym " %0 " #val : : "i" (val))
++
++#define BLANK() \
++    asm volatile("\n->" : : )
++
++#define OFFSET(sym, str, mem) \
++    DEFINE(sym, offsetof(struct str, mem))
++
++#define COMMENT(x) \
++    asm volatile("\n->#" x)
++
++#endif // gen-defs.h
+--- x/roms/seabios/src/ioport.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/ioport.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,134 @@
++// Definitions for X86 IO port access.
++//
++// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++#ifndef __IOPORT_H
++#define __IOPORT_H
++
++#define PORT_DMA_ADDR_2        0x0004
++#define PORT_DMA_CNT_2         0x0005
++#define PORT_DMA1_MASK_REG     0x000a
++#define PORT_DMA1_MODE_REG     0x000b
++#define PORT_DMA1_CLEAR_FF_REG 0x000c
++#define PORT_DMA1_MASTER_CLEAR 0x000d
++#define PORT_PIC1_CMD          0x0020
++#define PORT_PIC1_DATA         0x0021
++#define PORT_PIT_COUNTER0      0x0040
++#define PORT_PIT_COUNTER1      0x0041
++#define PORT_PIT_COUNTER2      0x0042
++#define PORT_PIT_MODE          0x0043
++#define PORT_PS2_DATA          0x0060
++#define PORT_PS2_CTRLB         0x0061
++#define PORT_PS2_STATUS        0x0064
++#define PORT_CMOS_INDEX        0x0070
++#define PORT_CMOS_DATA         0x0071
++#define PORT_DIAG              0x0080
++#define PORT_DMA_PAGE_2        0x0081
++#define PORT_A20               0x0092
++#define PORT_PIC2_CMD          0x00a0
++#define PORT_PIC2_DATA         0x00a1
++#define PORT_SMI_CMD           0x00b2
++#define PORT_SMI_STATUS        0x00b3
++#define PORT_DMA2_MASK_REG     0x00d4
++#define PORT_DMA2_MODE_REG     0x00d6
++#define PORT_DMA2_MASTER_CLEAR 0x00da
++#define PORT_MATH_CLEAR        0x00f0
++#define PORT_ATA2_CMD_BASE     0x0170
++#define PORT_ATA1_CMD_BASE     0x01f0
++#define PORT_LPT2              0x0278
++#define PORT_SERIAL4           0x02e8
++#define PORT_SERIAL2           0x02f8
++#define PORT_ATA2_CTRL_BASE    0x0374
++#define PORT_LPT1              0x0378
++#define PORT_SERIAL3           0x03e8
++#define PORT_ATA1_CTRL_BASE    0x03f4
++#define PORT_FD_DOR            0x03f2
++#define PORT_FD_STATUS         0x03f4
++#define PORT_FD_DATA           0x03f5
++#define PORT_HD_DATA           0x03f6
++#define PORT_FD_DIR            0x03f7
++#define PORT_SERIAL1           0x03f8
++#define PORT_PCI_CMD           0x0cf8
++#define PORT_PCI_DATA          0x0cfc
++#define PORT_BIOS_DEBUG        0x0402
++#define PORT_QEMU_CFG_CTL      0x0510
++#define PORT_QEMU_CFG_DATA     0x0511
++#define PORT_ACPI_PM_BASE      0xb000
++#define PORT_SMB_BASE          0xb100
++#define PORT_BIOS_APM          0x8900
++
++// Serial port offsets
++#define SEROFF_DATA    0
++#define SEROFF_DLL     0
++#define SEROFF_IER     1
++#define SEROFF_DLH     1
++#define SEROFF_IIR     2
++#define SEROFF_LCR     3
++#define SEROFF_LSR     5
++#define SEROFF_MSR     6
++
++// PORT_A20 bitdefs
++#define A20_ENABLE_BIT 0x02
++
++// PORT_CMOS_INDEX nmi disable bit
++#define NMI_DISABLE_BIT 0x80
++
++#ifndef __ASSEMBLY__
++
++#include "types.h" // u8
++
++static inline void outb(u8 value, u16 port) {
++    __asm__ __volatile__("outb %b0, %w1" : : "a"(value), "Nd"(port));
++}
++static inline void outw(u16 value, u16 port) {
++    __asm__ __volatile__("outw %w0, %w1" : : "a"(value), "Nd"(port));
++}
++static inline void outl(u32 value, u16 port) {
++    __asm__ __volatile__("outl %0, %w1" : : "a"(value), "Nd"(port));
++}
++static inline u8 inb(u16 port) {
++    u8 value;
++    __asm__ __volatile__("inb %w1, %b0" : "=a"(value) : "Nd"(port));
++    return value;
++}
++static inline u16 inw(u16 port) {
++    u16 value;
++    __asm__ __volatile__("inw %w1, %w0" : "=a"(value) : "Nd"(port));
++    return value;
++}
++static inline u32 inl(u16 port) {
++    u32 value;
++    __asm__ __volatile__("inl %w1, %0" : "=a"(value) : "Nd"(port));
++    return value;
++}
++
++static inline void insb(u16 port, u8 *data, u32 count) {
++    asm volatile("rep insb (%%dx), %%es:(%%edi)"
++                 : "+c"(count), "+D"(data) : "d"(port) : "memory");
++}
++static inline void insw(u16 port, u16 *data, u32 count) {
++    asm volatile("rep insw (%%dx), %%es:(%%edi)"
++                 : "+c"(count), "+D"(data) : "d"(port) : "memory");
++}
++static inline void insl(u16 port, u32 *data, u32 count) {
++    asm volatile("rep insl (%%dx), %%es:(%%edi)"
++                 : "+c"(count), "+D"(data) : "d"(port) : "memory");
++}
++// XXX - outs not limited to es segment
++static inline void outsb(u16 port, u8 *data, u32 count) {
++    asm volatile("rep outsb %%es:(%%esi), (%%dx)"
++                 : "+c"(count), "+S"(data) : "d"(port) : "memory");
++}
++static inline void outsw(u16 port, u16 *data, u32 count) {
++    asm volatile("rep outsw %%es:(%%esi), (%%dx)"
++                 : "+c"(count), "+S"(data) : "d"(port) : "memory");
++}
++static inline void outsl(u16 port, u32 *data, u32 count) {
++    asm volatile("rep outsl %%es:(%%esi), (%%dx)"
++                 : "+c"(count), "+S"(data) : "d"(port) : "memory");
++}
++
++#endif // !__ASSEMBLY__
++
++#endif // ioport.h
+--- x/roms/seabios/src/kbd.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/kbd.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,561 @@
++// 16bit code to handle keyboard requests.
++//
++// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2002  MandrakeSoft S.A.
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "biosvar.h" // GET_BDA
++#include "util.h" // debug_enter
++#include "config.h" // CONFIG_*
++#include "bregs.h" // struct bregs
++#include "ps2port.h" // kbd_command
++
++// Bit definitions for BDA kbd_flag[012]
++#define KF0_RSHIFT       (1<<0)
++#define KF0_LSHIFT       (1<<1)
++#define KF0_CTRLACTIVE   (1<<2)
++#define KF0_ALTACTIVE    (1<<3)
++#define KF0_SCROLLACTIVE (1<<4)
++#define KF0_NUMACTIVE    (1<<5)
++#define KF0_CAPSACTIVE   (1<<6)
++
++#define KF1_LCTRL        (1<<0)
++#define KF1_LALT         (1<<1)
++#define KF1_PAUSEACTIVE  (1<<3)
++#define KF1_SCROLL       (1<<4)
++#define KF1_NUM          (1<<5)
++#define KF1_CAPS         (1<<6)
++
++#define KF2_LAST_E1    (1<<0)
++#define KF2_LAST_E0    (1<<1)
++#define KF2_RCTRL      (1<<2)
++#define KF2_RALT       (1<<3)
++#define KF2_101KBD     (1<<4)
++
++void
++kbd_setup(void)
++{
++    dprintf(3, "init keyboard\n");
++    u16 x = offsetof(struct bios_data_area_s, kbd_buf);
++    SET_BDA(kbd_flag2, KF2_101KBD);
++    SET_BDA(kbd_buf_head, x);
++    SET_BDA(kbd_buf_tail, x);
++    SET_BDA(kbd_buf_start_offset, x);
++
++    SET_BDA(kbd_buf_end_offset
++            , x + FIELD_SIZEOF(struct bios_data_area_s, kbd_buf));
++}
++
++static u8
++enqueue_key(u8 scan_code, u8 ascii_code)
++{
++    u16 buffer_start = GET_BDA(kbd_buf_start_offset);
++    u16 buffer_end   = GET_BDA(kbd_buf_end_offset);
++
++    u16 buffer_head = GET_BDA(kbd_buf_head);
++    u16 buffer_tail = GET_BDA(kbd_buf_tail);
++
++    u16 temp_tail = buffer_tail;
++    buffer_tail += 2;
++    if (buffer_tail >= buffer_end)
++        buffer_tail = buffer_start;
++
++    if (buffer_tail == buffer_head)
++        return 0;
++
++    SET_FARVAR(SEG_BDA, *(u8*)(temp_tail+0), ascii_code);
++    SET_FARVAR(SEG_BDA, *(u8*)(temp_tail+1), scan_code);
++    SET_BDA(kbd_buf_tail, buffer_tail);
++    return 1;
++}
++
++static void
++dequeue_key(struct bregs *regs, int incr, int extended)
++{
++    u16 buffer_head;
++    u16 buffer_tail;
++    for (;;) {
++        buffer_head = GET_BDA(kbd_buf_head);
++        buffer_tail = GET_BDA(kbd_buf_tail);
++
++        if (buffer_head != buffer_tail)
++            break;
++        if (!incr) {
++            regs->flags |= F_ZF;
++            return;
++        }
++        wait_irq();
++    }
++
++    u8 ascii_code = GET_FARVAR(SEG_BDA, *(u8*)(buffer_head+0));
++    u8 scan_code  = GET_FARVAR(SEG_BDA, *(u8*)(buffer_head+1));
++    if ((ascii_code == 0xF0 && scan_code != 0)
++        || (ascii_code == 0xE0 && !extended))
++        ascii_code = 0;
++    regs->ax = (scan_code << 8) | ascii_code;
++
++    if (!incr) {
++        regs->flags &= ~F_ZF;
++        return;
++    }
++    u16 buffer_start = GET_BDA(kbd_buf_start_offset);
++    u16 buffer_end   = GET_BDA(kbd_buf_end_offset);
++
++    buffer_head += 2;
++    if (buffer_head >= buffer_end)
++        buffer_head = buffer_start;
++    SET_BDA(kbd_buf_head, buffer_head);
++}
++
++// read keyboard input
++static void
++handle_1600(struct bregs *regs)
++{
++    dequeue_key(regs, 1, 0);
++}
++
++// check keyboard status
++static void
++handle_1601(struct bregs *regs)
++{
++    dequeue_key(regs, 0, 0);
++}
++
++// get shift flag status
++static void
++handle_1602(struct bregs *regs)
++{
++    regs->al = GET_BDA(kbd_flag0);
++}
++
++// store key-stroke into buffer
++static void
++handle_1605(struct bregs *regs)
++{
++    regs->al = !enqueue_key(regs->ch, regs->cl);
++}
++
++// GET KEYBOARD FUNCTIONALITY
++static void
++handle_1609(struct bregs *regs)
++{
++    // bit Bochs Description
++    //  7    0   reserved
++    //  6    0   INT 16/AH=20h-22h supported (122-key keyboard support)
++    //  5    1   INT 16/AH=10h-12h supported (enhanced keyboard support)
++    //  4    1   INT 16/AH=0Ah supported
++    //  3    0   INT 16/AX=0306h supported
++    //  2    0   INT 16/AX=0305h supported
++    //  1    0   INT 16/AX=0304h supported
++    //  0    0   INT 16/AX=0300h supported
++    //
++    regs->al = 0x30;
++}
++
++// GET KEYBOARD ID
++static void
++handle_160a(struct bregs *regs)
++{
++    u8 param[2];
++    int ret = kbd_command(ATKBD_CMD_GETID, param);
++    if (ret) {
++        regs->bx = 0;
++        return;
++    }
++    regs->bx = (param[1] << 8) | param[0];
++}
++
++// read MF-II keyboard input
++static void
++handle_1610(struct bregs *regs)
++{
++    dequeue_key(regs, 1, 1);
++}
++
++// check MF-II keyboard status
++static void
++handle_1611(struct bregs *regs)
++{
++    dequeue_key(regs, 0, 1);
++}
++
++// get extended keyboard status
++static void
++handle_1612(struct bregs *regs)
++{
++    regs->al = GET_BDA(kbd_flag0);
++    regs->ah = ((GET_BDA(kbd_flag1) & ~(KF2_RCTRL|KF2_RALT))
++                | (GET_BDA(kbd_flag2) & (KF2_RCTRL|KF2_RALT)));
++    //BX_DEBUG_INT16("int16: func 12 sending %04x\n",AX);
++}
++
++static void
++handle_166f(struct bregs *regs)
++{
++    if (regs->al == 0x08)
++        // unsupported, aka normal keyboard
++        regs->ah = 2;
++}
++
++// keyboard capability check called by DOS 5.0+ keyb
++static void
++handle_1692(struct bregs *regs)
++{
++    // function int16 ah=0x10-0x12 supported
++    regs->ah = 0x80;
++}
++
++// 122 keys capability check called by DOS 5.0+ keyb
++static void
++handle_16a2(struct bregs *regs)
++{
++    // don't change AH : function int16 ah=0x20-0x22 NOT supported
++}
++
++static void
++handle_16XX(struct bregs *regs)
++{
++    warn_unimplemented(regs);
++}
++
++static void
++set_leds(void)
++{
++    u8 shift_flags = (GET_BDA(kbd_flag0) >> 4) & 0x07;
++    u8 kbd_led = GET_BDA(kbd_led);
++    u8 led_flags = kbd_led & 0x07;
++    if (shift_flags == led_flags)
++        return;
++
++    int ret = kbd_command(ATKBD_CMD_SETLEDS, &shift_flags);
++    if (ret)
++        // Error
++        return;
++    kbd_led = (kbd_led & ~0x07) | shift_flags;
++    SET_BDA(kbd_led, kbd_led);
++}
++
++// INT 16h Keyboard Service Entry Point
++void VISIBLE16
++handle_16(struct bregs *regs)
++{
++    debug_enter(regs, DEBUG_HDL_16);
++    if (! CONFIG_KEYBOARD)
++        return;
++
++    // XXX - set_leds should be called from irq handler
++    set_leds();
++
++    switch (regs->ah) {
++    case 0x00: handle_1600(regs); break;
++    case 0x01: handle_1601(regs); break;
++    case 0x02: handle_1602(regs); break;
++    case 0x05: handle_1605(regs); break;
++    case 0x09: handle_1609(regs); break;
++    case 0x0a: handle_160a(regs); break;
++    case 0x10: handle_1610(regs); break;
++    case 0x11: handle_1611(regs); break;
++    case 0x12: handle_1612(regs); break;
++    case 0x92: handle_1692(regs); break;
++    case 0xa2: handle_16a2(regs); break;
++    case 0x6f: handle_166f(regs); break;
++    default:   handle_16XX(regs); break;
++    }
++}
++
++#define none 0
++#define MNUM KF0_NUMACTIVE
++#define MCAP KF0_CAPSACTIVE
++
++static struct scaninfo {
++    u16 normal;
++    u16 shift;
++    u16 control;
++    u16 alt;
++    u8 lock_flags;
++} scan_to_scanascii[] VAR16 = {
++    {   none,   none,   none,   none, none },
++    { 0x011b, 0x011b, 0x011b, 0x0100, none }, /* escape */
++    { 0x0231, 0x0221,   none, 0x7800, none }, /* 1! */
++    { 0x0332, 0x0340, 0x0300, 0x7900, none }, /* 2@ */
++    { 0x0433, 0x0423,   none, 0x7a00, none }, /* 3# */
++    { 0x0534, 0x0524,   none, 0x7b00, none }, /* 4$ */
++    { 0x0635, 0x0625,   none, 0x7c00, none }, /* 5% */
++    { 0x0736, 0x075e, 0x071e, 0x7d00, none }, /* 6^ */
++    { 0x0837, 0x0826,   none, 0x7e00, none }, /* 7& */
++    { 0x0938, 0x092a,   none, 0x7f00, none }, /* 8* */
++    { 0x0a39, 0x0a28,   none, 0x8000, none }, /* 9( */
++    { 0x0b30, 0x0b29,   none, 0x8100, none }, /* 0) */
++    { 0x0c2d, 0x0c5f, 0x0c1f, 0x8200, none }, /* -_ */
++    { 0x0d3d, 0x0d2b,   none, 0x8300, none }, /* =+ */
++    { 0x0e08, 0x0e08, 0x0e7f,   none, none }, /* backspace */
++    { 0x0f09, 0x0f00,   none,   none, none }, /* tab */
++    { 0x1071, 0x1051, 0x1011, 0x1000, MCAP }, /* Q */
++    { 0x1177, 0x1157, 0x1117, 0x1100, MCAP }, /* W */
++    { 0x1265, 0x1245, 0x1205, 0x1200, MCAP }, /* E */
++    { 0x1372, 0x1352, 0x1312, 0x1300, MCAP }, /* R */
++    { 0x1474, 0x1454, 0x1414, 0x1400, MCAP }, /* T */
++    { 0x1579, 0x1559, 0x1519, 0x1500, MCAP }, /* Y */
++    { 0x1675, 0x1655, 0x1615, 0x1600, MCAP }, /* U */
++    { 0x1769, 0x1749, 0x1709, 0x1700, MCAP }, /* I */
++    { 0x186f, 0x184f, 0x180f, 0x1800, MCAP }, /* O */
++    { 0x1970, 0x1950, 0x1910, 0x1900, MCAP }, /* P */
++    { 0x1a5b, 0x1a7b, 0x1a1b,   none, none }, /* [{ */
++    { 0x1b5d, 0x1b7d, 0x1b1d,   none, none }, /* ]} */
++    { 0x1c0d, 0x1c0d, 0x1c0a,   none, none }, /* Enter */
++    {   none,   none,   none,   none, none }, /* L Ctrl */
++    { 0x1e61, 0x1e41, 0x1e01, 0x1e00, MCAP }, /* A */
++    { 0x1f73, 0x1f53, 0x1f13, 0x1f00, MCAP }, /* S */
++    { 0x2064, 0x2044, 0x2004, 0x2000, MCAP }, /* D */
++    { 0x2166, 0x2146, 0x2106, 0x2100, MCAP }, /* F */
++    { 0x2267, 0x2247, 0x2207, 0x2200, MCAP }, /* G */
++    { 0x2368, 0x2348, 0x2308, 0x2300, MCAP }, /* H */
++    { 0x246a, 0x244a, 0x240a, 0x2400, MCAP }, /* J */
++    { 0x256b, 0x254b, 0x250b, 0x2500, MCAP }, /* K */
++    { 0x266c, 0x264c, 0x260c, 0x2600, MCAP }, /* L */
++    { 0x273b, 0x273a,   none,   none, none }, /* ;: */
++    { 0x2827, 0x2822,   none,   none, none }, /* '" */
++    { 0x2960, 0x297e,   none,   none, none }, /* `~ */
++    {   none,   none,   none,   none, none }, /* L shift */
++    { 0x2b5c, 0x2b7c, 0x2b1c,   none, none }, /* |\ */
++    { 0x2c7a, 0x2c5a, 0x2c1a, 0x2c00, MCAP }, /* Z */
++    { 0x2d78, 0x2d58, 0x2d18, 0x2d00, MCAP }, /* X */
++    { 0x2e63, 0x2e43, 0x2e03, 0x2e00, MCAP }, /* C */
++    { 0x2f76, 0x2f56, 0x2f16, 0x2f00, MCAP }, /* V */
++    { 0x3062, 0x3042, 0x3002, 0x3000, MCAP }, /* B */
++    { 0x316e, 0x314e, 0x310e, 0x3100, MCAP }, /* N */
++    { 0x326d, 0x324d, 0x320d, 0x3200, MCAP }, /* M */
++    { 0x332c, 0x333c,   none,   none, none }, /* ,< */
++    { 0x342e, 0x343e,   none,   none, none }, /* .> */
++    { 0x352f, 0x353f,   none,   none, none }, /* /? */
++    {   none,   none,   none,   none, none }, /* R Shift */
++    { 0x372a, 0x372a,   none,   none, none }, /* * */
++    {   none,   none,   none,   none, none }, /* L Alt */
++    { 0x3920, 0x3920, 0x3920, 0x3920, none }, /* space */
++    {   none,   none,   none,   none, none }, /* caps lock */
++    { 0x3b00, 0x5400, 0x5e00, 0x6800, none }, /* F1 */
++    { 0x3c00, 0x5500, 0x5f00, 0x6900, none }, /* F2 */
++    { 0x3d00, 0x5600, 0x6000, 0x6a00, none }, /* F3 */
++    { 0x3e00, 0x5700, 0x6100, 0x6b00, none }, /* F4 */
++    { 0x3f00, 0x5800, 0x6200, 0x6c00, none }, /* F5 */
++    { 0x4000, 0x5900, 0x6300, 0x6d00, none }, /* F6 */
++    { 0x4100, 0x5a00, 0x6400, 0x6e00, none }, /* F7 */
++    { 0x4200, 0x5b00, 0x6500, 0x6f00, none }, /* F8 */
++    { 0x4300, 0x5c00, 0x6600, 0x7000, none }, /* F9 */
++    { 0x4400, 0x5d00, 0x6700, 0x7100, none }, /* F10 */
++    {   none,   none,   none,   none, none }, /* Num Lock */
++    {   none,   none,   none,   none, none }, /* Scroll Lock */
++    { 0x4700, 0x4737, 0x7700,   none, MNUM }, /* 7 Home */
++    { 0x4800, 0x4838,   none,   none, MNUM }, /* 8 UP */
++    { 0x4900, 0x4939, 0x8400,   none, MNUM }, /* 9 PgUp */
++    { 0x4a2d, 0x4a2d,   none,   none, none }, /* - */
++    { 0x4b00, 0x4b34, 0x7300,   none, MNUM }, /* 4 Left */
++    { 0x4c00, 0x4c35,   none,   none, MNUM }, /* 5 */
++    { 0x4d00, 0x4d36, 0x7400,   none, MNUM }, /* 6 Right */
++    { 0x4e2b, 0x4e2b,   none,   none, none }, /* + */
++    { 0x4f00, 0x4f31, 0x7500,   none, MNUM }, /* 1 End */
++    { 0x5000, 0x5032,   none,   none, MNUM }, /* 2 Down */
++    { 0x5100, 0x5133, 0x7600,   none, MNUM }, /* 3 PgDn */
++    { 0x5200, 0x5230,   none,   none, MNUM }, /* 0 Ins */
++    { 0x5300, 0x532e,   none,   none, MNUM }, /* Del */
++    {   none,   none,   none,   none, none },
++    {   none,   none,   none,   none, none },
++    { 0x565c, 0x567c,   none,   none, none }, /* \| */
++    { 0x8500, 0x8700, 0x8900, 0x8b00, none }, /* F11 */
++    { 0x8600, 0x8800, 0x8a00, 0x8c00, none }, /* F12 */
++};
++
++// Handle a scancode read from the ps2 port.  Note that "noinline" is
++// used to make sure the call to call16_simpint in process_key doesn't
++// have the overhead of this function's stack.
++static void noinline
++__process_key(u8 scancode)
++{
++    u8 flags0 = GET_BDA(kbd_flag0);
++    u8 flags1 = GET_BDA(kbd_flag1);
++    u8 flags2 = GET_BDA(kbd_flag2);
++
++    if (flags2 & KF2_LAST_E1) {
++        // Part of "pause" key (sequence is e1 1d 45 e1 9d c5)
++        if ((scancode & ~0x80) == 0x1d)
++            // Second key of sequence
++            return;
++        // Third key of sequence - clear flag.
++        flags2 &= ~KF2_LAST_E1;
++        SET_BDA(kbd_flag2, flags2);
++
++        if (scancode == 0xc5) {
++            // Final key in sequence.
++
++            // XXX - do actual pause.
++        }
++        return;
++    }
++
++    // XXX - PrtScr should cause int 0x05
++    // XXX - Ctrl+Break should cause int 0x1B
++    // XXX - SysReq should cause int 0x15/0x85
++
++    switch (scancode) {
++    case 0x00:
++        dprintf(1, "KBD: int09 handler: AL=0\n");
++        return;
++
++    case 0x3a: /* Caps Lock press */
++        flags0 ^= KF0_CAPSACTIVE;
++        flags1 |= KF1_CAPS;
++        break;
++    case 0xba: /* Caps Lock release */
++        flags1 &= ~KF1_CAPS;
++        break;
++
++    case 0x2a: /* L Shift press */
++        flags0 |= KF0_LSHIFT;
++        break;
++    case 0xaa: /* L Shift release */
++        flags0 &= ~KF0_LSHIFT;
++        break;
++
++    case 0x36: /* R Shift press */
++        flags0 |= KF0_RSHIFT;
++        break;
++    case 0xb6: /* R Shift release */
++        flags0 &= ~KF0_RSHIFT;
++        break;
++
++    case 0x1d: /* Ctrl press */
++        flags0 |= KF0_CTRLACTIVE;
++        if (flags2 & KF2_LAST_E0)
++            flags2 |= KF2_RCTRL;
++        else
++            flags1 |= KF1_LCTRL;
++        break;
++    case 0x9d: /* Ctrl release */
++        flags0 &= ~KF0_CTRLACTIVE;
++        if (flags2 & KF2_LAST_E0)
++            flags2 &= ~KF2_RCTRL;
++        else
++            flags1 &= ~KF1_LCTRL;
++        break;
++
++    case 0x38: /* Alt press */
++        flags0 |= KF0_ALTACTIVE;
++        if (flags2 & KF2_LAST_E0)
++            flags2 |= KF2_RALT;
++        else
++            flags1 |= KF1_LALT;
++        break;
++    case 0xb8: /* Alt release */
++        flags0 &= ~KF0_ALTACTIVE;
++        if (flags2 & KF2_LAST_E0)
++            flags2 &= ~KF2_RALT;
++        else
++            flags1 &= ~KF1_LALT;
++        break;
++
++    case 0x45: /* Num Lock press */
++        flags1 |= KF1_NUM;
++        flags0 ^= KF0_NUMACTIVE;
++        break;
++    case 0xc5: /* Num Lock release */
++        flags1 &= ~KF1_NUM;
++        break;
++
++    case 0x46: /* Scroll Lock press */
++        flags1 |= KF1_SCROLL;
++        flags0 ^= KF0_SCROLLACTIVE;
++        break;
++    case 0xc6: /* Scroll Lock release */
++        flags1 &= ~KF1_SCROLL;
++        break;
++
++    case 0xe0:
++        // Extended key
++        flags2 |= KF2_LAST_E0;
++        SET_BDA(kbd_flag2, flags2);
++        return;
++    case 0xe1:
++        // Start of pause key sequence
++        flags2 |= KF2_LAST_E1;
++        break;
++
++    default:
++        if (scancode & 0x80)
++            // toss key releases
++            break;
++        if (scancode == 0x53
++            && ((flags0 & (KF0_CTRLACTIVE|KF0_ALTACTIVE))
++                == (KF0_CTRLACTIVE|KF0_ALTACTIVE))) {
++            // Ctrl+alt+del - reset machine.
++            SET_BDA(soft_reset_flag, 0x1234);
++            reset_vector();
++        }
++        if (scancode >= ARRAY_SIZE(scan_to_scanascii)) {
++            dprintf(1, "KBD: int09h_handler(): unknown scancode read: 0x%02x!\n"
++                    , scancode);
++            return;
++        }
++        u8 asciicode;
++        struct scaninfo *info = &scan_to_scanascii[scancode];
++        if (flags0 & KF0_ALTACTIVE) {
++            asciicode = GET_GLOBAL(info->alt);
++            scancode = GET_GLOBAL(info->alt) >> 8;
++        } else if (flags0 & KF0_CTRLACTIVE) {
++            asciicode = GET_GLOBAL(info->control);
++            scancode = GET_GLOBAL(info->control) >> 8;
++        } else if (flags2 & KF2_LAST_E0
++                   && scancode >= 0x47 && scancode <= 0x53) {
++            /* extended keys handling */
++            asciicode = 0xe0;
++            scancode = GET_GLOBAL(info->normal) >> 8;
++        } else if (flags0 & (KF0_RSHIFT|KF0_LSHIFT)) {
++            /* check if lock state should be ignored because a SHIFT
++             * key is pressed */
++
++            if (flags0 & GET_GLOBAL(info->lock_flags)) {
++                asciicode = GET_GLOBAL(info->normal);
++                scancode = GET_GLOBAL(info->normal) >> 8;
++            } else {
++                asciicode = GET_GLOBAL(info->shift);
++                scancode = GET_GLOBAL(info->shift) >> 8;
++            }
++        } else {
++            /* check if lock is on */
++            if (flags0 & GET_GLOBAL(info->lock_flags)) {
++                asciicode = GET_GLOBAL(info->shift);
++                scancode = GET_GLOBAL(info->shift) >> 8;
++            } else {
++                asciicode = GET_GLOBAL(info->normal);
++                scancode = GET_GLOBAL(info->normal) >> 8;
++            }
++        }
++        if (scancode==0 && asciicode==0)
++            dprintf(1, "KBD: scancode & asciicode are zero?\n");
++        enqueue_key(scancode, asciicode);
++        break;
++    }
++    flags2 &= ~KF2_LAST_E0;
++
++    SET_BDA(kbd_flag0, flags0);
++    SET_BDA(kbd_flag1, flags1);
++    SET_BDA(kbd_flag2, flags2);
++}
++
++void
++process_key(u8 key)
++{
++    if (!CONFIG_KEYBOARD)
++        return;
++
++    if (CONFIG_KBD_CALL_INT15_4F) {
++        // allow for keyboard intercept
++        u32 eax = (0x4f << 8) | key;
++        u32 flags;
++        call16_simpint(0x15, &eax, &flags);
++        if (!(flags & F_CF))
++            return;
++        key = eax;
++    }
++    __process_key(key);
++}
+--- x/roms/seabios/src/lzmadecode.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/lzmadecode.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,398 @@
++/*
++  LzmaDecode.c
++  LZMA Decoder (optimized for Speed version)
++  
++  LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
++  http://www.7-zip.org/
++
++  LZMA SDK is licensed under two licenses:
++  1) GNU Lesser General Public License (GNU LGPL)
++  2) Common Public License (CPL)
++  It means that you can select one of these two licenses and 
++  follow rules of that license.
++
++  SPECIAL EXCEPTION:
++  Igor Pavlov, as the author of this Code, expressly permits you to 
++  statically or dynamically link your Code (or bind by name) to the 
++  interfaces of this file without subjecting your linked Code to the 
++  terms of the CPL or GNU LGPL. Any modifications or additions 
++  to this file, however, are subject to the LGPL or CPL terms.
++*/
++
++#include "lzmadecode.h"
++
++#define kNumTopBits 24
++#define kTopValue ((UInt32)1 << kNumTopBits)
++
++#define kNumBitModelTotalBits 11
++#define kBitModelTotal (1 << kNumBitModelTotalBits)
++#define kNumMoveBits 5
++
++#define RC_READ_BYTE (*Buffer++)
++
++#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \
++  { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }}
++
++
++#define RC_TEST { if (Buffer == BufferLim) return LZMA_RESULT_DATA_ERROR; }
++
++#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2
++ 
++
++#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
++
++#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
++#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
++#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
++
++#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
++  { UpdateBit0(p); mi <<= 1; A0; } else \
++  { UpdateBit1(p); mi = (mi + mi) + 1; A1; } 
++  
++#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)               
++
++#define RangeDecoderBitTreeDecode(probs, numLevels, res) \
++  { int i = numLevels; res = 1; \
++  do { CProb *cp = probs + res; RC_GET_BIT(cp, res) } while(--i != 0); \
++  res -= (1 << numLevels); }
++
++
++#define kNumPosBitsMax 4
++#define kNumPosStatesMax (1 << kNumPosBitsMax)
++
++#define kLenNumLowBits 3
++#define kLenNumLowSymbols (1 << kLenNumLowBits)
++#define kLenNumMidBits 3
++#define kLenNumMidSymbols (1 << kLenNumMidBits)
++#define kLenNumHighBits 8
++#define kLenNumHighSymbols (1 << kLenNumHighBits)
++
++#define LenChoice 0
++#define LenChoice2 (LenChoice + 1)
++#define LenLow (LenChoice2 + 1)
++#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
++#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
++#define kNumLenProbs (LenHigh + kLenNumHighSymbols) 
++
++
++#define kNumStates 12
++#define kNumLitStates 7
++
++#define kStartPosModelIndex 4
++#define kEndPosModelIndex 14
++#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
++
++#define kNumPosSlotBits 6
++#define kNumLenToPosStates 4
++
++#define kNumAlignBits 4
++#define kAlignTableSize (1 << kNumAlignBits)
++
++#define kMatchMinLen 2
++
++#define IsMatch 0
++#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
++#define IsRepG0 (IsRep + kNumStates)
++#define IsRepG1 (IsRepG0 + kNumStates)
++#define IsRepG2 (IsRepG1 + kNumStates)
++#define IsRep0Long (IsRepG2 + kNumStates)
++#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
++#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
++#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
++#define LenCoder (Align + kAlignTableSize)
++#define RepLenCoder (LenCoder + kNumLenProbs)
++#define Literal (RepLenCoder + kNumLenProbs)
++
++#if Literal != LZMA_BASE_SIZE
++StopCompilingDueBUG
++#endif
++
++int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size)
++{
++  unsigned char prop0;
++  if (size < LZMA_PROPERTIES_SIZE)
++    return LZMA_RESULT_DATA_ERROR;
++  prop0 = propsData[0];
++  if (prop0 >= (9 * 5 * 5))
++    return LZMA_RESULT_DATA_ERROR;
++  {
++    for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5));
++    for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9);
++    propsRes->lc = prop0;
++    /*
++    unsigned char remainder = (unsigned char)(prop0 / 9);
++    propsRes->lc = prop0 % 9;
++    propsRes->pb = remainder / 5;
++    propsRes->lp = remainder % 5;
++    */
++  }
++
++  return LZMA_RESULT_OK;
++}
++
++#define kLzmaStreamWasFinishedId (-1)
++
++int LzmaDecode(CLzmaDecoderState *vs,
++    const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
++    unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed)
++{
++  CProb *p = vs->Probs;
++  SizeT nowPos = 0;
++  Byte previousByte = 0;
++  UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1;
++  UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1;
++  int lc = vs->Properties.lc;
++
++
++  int state = 0;
++  UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
++  int len = 0;
++  const Byte *Buffer;
++  const Byte *BufferLim;
++  UInt32 Range;
++  UInt32 Code;
++
++  *inSizeProcessed = 0;
++  *outSizeProcessed = 0;
++
++  {
++    UInt32 i;
++    UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp));
++    for (i = 0; i < numProbs; i++)
++      p[i] = kBitModelTotal >> 1;
++  }
++  
++  RC_INIT(inStream, inSize);
++
++
++  while(nowPos < outSize)
++  {
++    CProb *prob;
++    UInt32 bound;
++    int posState = (int)(
++        (nowPos 
++        )
++        & posStateMask);
++
++    prob = p + IsMatch + (state << kNumPosBitsMax) + posState;
++    IfBit0(prob)
++    {
++      int symbol = 1;
++      UpdateBit0(prob)
++      prob = p + Literal + (LZMA_LIT_SIZE * 
++        (((
++        (nowPos 
++        )
++        & literalPosMask) << lc) + (previousByte >> (8 - lc))));
++
++      if (state >= kNumLitStates)
++      {
++        int matchByte;
++        matchByte = outStream[nowPos - rep0];
++        do
++        {
++          int bit;
++          CProb *probLit;
++          matchByte <<= 1;
++          bit = (matchByte & 0x100);
++          probLit = prob + 0x100 + bit + symbol;
++          RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break)
++        }
++        while (symbol < 0x100);
++      }
++      while (symbol < 0x100)
++      {
++        CProb *probLit = prob + symbol;
++        RC_GET_BIT(probLit, symbol)
++      }
++      previousByte = (Byte)symbol;
++
++      outStream[nowPos++] = previousByte;
++      if (state < 4) state = 0;
++      else if (state < 10) state -= 3;
++      else state -= 6;
++    }
++    else             
++    {
++      UpdateBit1(prob);
++      prob = p + IsRep + state;
++      IfBit0(prob)
++      {
++        UpdateBit0(prob);
++        rep3 = rep2;
++        rep2 = rep1;
++        rep1 = rep0;
++        state = state < kNumLitStates ? 0 : 3;
++        prob = p + LenCoder;
++      }
++      else
++      {
++        UpdateBit1(prob);
++        prob = p + IsRepG0 + state;
++        IfBit0(prob)
++        {
++          UpdateBit0(prob);
++          prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState;
++          IfBit0(prob)
++          {
++            UpdateBit0(prob);
++            
++            if (nowPos == 0)
++              return LZMA_RESULT_DATA_ERROR;
++            
++            state = state < kNumLitStates ? 9 : 11;
++            previousByte = outStream[nowPos - rep0];
++            outStream[nowPos++] = previousByte;
++
++            continue;
++          }
++          else
++          {
++            UpdateBit1(prob);
++          }
++        }
++        else
++        {
++          UInt32 distance;
++          UpdateBit1(prob);
++          prob = p + IsRepG1 + state;
++          IfBit0(prob)
++          {
++            UpdateBit0(prob);
++            distance = rep1;
++          }
++          else 
++          {
++            UpdateBit1(prob);
++            prob = p + IsRepG2 + state;
++            IfBit0(prob)
++            {
++              UpdateBit0(prob);
++              distance = rep2;
++            }
++            else
++            {
++              UpdateBit1(prob);
++              distance = rep3;
++              rep3 = rep2;
++            }
++            rep2 = rep1;
++          }
++          rep1 = rep0;
++          rep0 = distance;
++        }
++        state = state < kNumLitStates ? 8 : 11;
++        prob = p + RepLenCoder;
++      }
++      {
++        int numBits, offset;
++        CProb *probLen = prob + LenChoice;
++        IfBit0(probLen)
++        {
++          UpdateBit0(probLen);
++          probLen = prob + LenLow + (posState << kLenNumLowBits);
++          offset = 0;
++          numBits = kLenNumLowBits;
++        }
++        else
++        {
++          UpdateBit1(probLen);
++          probLen = prob + LenChoice2;
++          IfBit0(probLen)
++          {
++            UpdateBit0(probLen);
++            probLen = prob + LenMid + (posState << kLenNumMidBits);
++            offset = kLenNumLowSymbols;
++            numBits = kLenNumMidBits;
++          }
++          else
++          {
++            UpdateBit1(probLen);
++            probLen = prob + LenHigh;
++            offset = kLenNumLowSymbols + kLenNumMidSymbols;
++            numBits = kLenNumHighBits;
++          }
++        }
++        RangeDecoderBitTreeDecode(probLen, numBits, len);
++        len += offset;
++      }
++
++      if (state < 4)
++      {
++        int posSlot;
++        state += kNumLitStates;
++        prob = p + PosSlot +
++            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << 
++            kNumPosSlotBits);
++        RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot);
++        if (posSlot >= kStartPosModelIndex)
++        {
++          int numDirectBits = ((posSlot >> 1) - 1);
++          rep0 = (2 | ((UInt32)posSlot & 1));
++          if (posSlot < kEndPosModelIndex)
++          {
++            rep0 <<= numDirectBits;
++            prob = p + SpecPos + rep0 - posSlot - 1;
++          }
++          else
++          {
++            numDirectBits -= kNumAlignBits;
++            do
++            {
++              RC_NORMALIZE
++              Range >>= 1;
++              rep0 <<= 1;
++              if (Code >= Range)
++              {
++                Code -= Range;
++                rep0 |= 1;
++              }
++            }
++            while (--numDirectBits != 0);
++            prob = p + Align;
++            rep0 <<= kNumAlignBits;
++            numDirectBits = kNumAlignBits;
++          }
++          {
++            int i = 1;
++            int mi = 1;
++            do
++            {
++              CProb *prob3 = prob + mi;
++              RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
++              i <<= 1;
++            }
++            while(--numDirectBits != 0);
++          }
++        }
++        else
++          rep0 = posSlot;
++        if (++rep0 == (UInt32)(0))
++        {
++          /* it's for stream version */
++          len = kLzmaStreamWasFinishedId;
++          break;
++        }
++      }
++
++      len += kMatchMinLen;
++      if (rep0 > nowPos)
++        return LZMA_RESULT_DATA_ERROR;
++
++
++      do
++      {
++        previousByte = outStream[nowPos - rep0];
++        len--;
++        outStream[nowPos++] = previousByte;
++      }
++      while(len != 0 && nowPos < outSize);
++    }
++  }
++  RC_NORMALIZE;
++
++
++  *inSizeProcessed = (SizeT)(Buffer - inStream);
++  *outSizeProcessed = nowPos;
++  return LZMA_RESULT_OK;
++}
+--- x/roms/seabios/src/lzmadecode.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/lzmadecode.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,67 @@
++/* 
++  LzmaDecode.h
++  LZMA Decoder interface
++
++  LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01)
++  http://www.7-zip.org/
++
++  LZMA SDK is licensed under two licenses:
++  1) GNU Lesser General Public License (GNU LGPL)
++  2) Common Public License (CPL)
++  It means that you can select one of these two licenses and 
++  follow rules of that license.
++
++  SPECIAL EXCEPTION:
++  Igor Pavlov, as the author of this code, expressly permits you to 
++  statically or dynamically link your code (or bind by name) to the 
++  interfaces of this file without subjecting your linked code to the 
++  terms of the CPL or GNU LGPL. Any modifications or additions 
++  to this file, however, are subject to the LGPL or CPL terms.
++*/
++
++#ifndef __LZMADECODE_H
++#define __LZMADECODE_H
++
++typedef unsigned char Byte;
++typedef unsigned short UInt16;
++typedef unsigned int UInt32;
++typedef UInt32 SizeT;
++
++#define CProb UInt16
++
++#define LZMA_RESULT_OK 0
++#define LZMA_RESULT_DATA_ERROR 1
++
++
++#define LZMA_BASE_SIZE 1846
++#define LZMA_LIT_SIZE 768
++
++#define LZMA_PROPERTIES_SIZE 5
++
++typedef struct _CLzmaProperties
++{
++  int lc;
++  int lp;
++  int pb;
++}CLzmaProperties;
++
++int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size);
++
++#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp)))
++
++#define kLzmaNeedInitId (-2)
++
++typedef struct _CLzmaDecoderState
++{
++  CLzmaProperties Properties;
++  CProb *Probs;
++
++
++} CLzmaDecoderState;
++
++
++int LzmaDecode(CLzmaDecoderState *vs,
++    const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed,
++    unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed);
++
++#endif
+--- x/roms/seabios/src/memmap.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/memmap.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,151 @@
++// Support for building memory maps suitable for int 15 e820 calls.
++//
++// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "memmap.h" // struct e820entry
++#include "util.h" // dprintf.h
++#include "biosvar.h" // SET_EBDA
++
++
++/****************************************************************
++ * e820 memory map
++ ****************************************************************/
++
++// Remove an entry from the e820_list.
++static void
++remove_e820(int i)
++{
++    e820_count--;
++    memmove(&e820_list[i], &e820_list[i+1]
++            , sizeof(e820_list[0]) * (e820_count - i));
++}
++
++// Insert an entry in the e820_list at the given position.
++static void
++insert_e820(int i, u64 start, u64 size, u32 type)
++{
++    if (e820_count >= CONFIG_MAX_E820) {
++        dprintf(1, "Overflowed e820 list!\n");
++        return;
++    }
++
++    memmove(&e820_list[i+1], &e820_list[i]
++            , sizeof(e820_list[0]) * (e820_count - i));
++    e820_count++;
++    struct e820entry *e = &e820_list[i];
++    e->start = start;
++    e->size = size;
++    e->type = type;
++}
++
++// Show the current e820_list.
++static void
++dump_map(void)
++{
++    dprintf(1, "e820 map has %d items:\n", e820_count);
++    int i;
++    for (i=0; i<e820_count; i++) {
++        struct e820entry *e = &e820_list[i];
++        u64 e_end = e->start + e->size;
++        dprintf(1, "  %d: %08x%08x - %08x%08x = %d\n", i
++                , (u32)(e->start >> 32), (u32)e->start
++                , (u32)(e_end >> 32), (u32)e_end
++                , e->type);
++    }
++}
++
++// Add a new entry to the list.  This scans for overlaps and keeps the
++// list sorted.
++void
++add_e820(u64 start, u64 size, u32 type)
++{
++    dprintf(8, "Add to e820 map: %08x %08x %d\n", (u32)start, (u32)size, type);
++
++    if (! size)
++        // Huh?  Nothing to do.
++        return;
++
++    // Find position of new item (splitting existing item if needed).
++    u64 end = start + size;
++    int i;
++    for (i=0; i<e820_count; i++) {
++        struct e820entry *e = &e820_list[i];
++        u64 e_end = e->start + e->size;
++        if (start > e_end)
++            continue;
++        // Found position - check if an existing item needs to be split.
++        if (start > e->start) {
++            if (type == e->type) {
++                // Same type - merge them.
++                size += start - e->start;
++                start = e->start;
++            } else {
++                // Split existing item.
++                e->size = start - e->start;
++                i++;
++                if (e_end > end)
++                    insert_e820(i, end, e_end - end, e->type);
++            }
++        }
++        break;
++    }
++    // Remove/adjust existing items that are overlapping.
++    while (i<e820_count) {
++        struct e820entry *e = &e820_list[i];
++        if (end < e->start)
++            // No overlap - done.
++            break;
++        u64 e_end = e->start + e->size;
++        if (end >= e_end) {
++            // Existing item completely overlapped - remove it.
++            remove_e820(i);
++            continue;
++        }
++        // Not completely overlapped - adjust its start.
++        e->start = end;
++        e->size = e_end - end;
++        if (type == e->type) {
++            // Same type - merge them.
++            size += e->size;
++            remove_e820(i);
++        }
++        break;
++    }
++    // Insert new item.
++    if (type != E820_HOLE)
++        insert_e820(i, start, size, type);
++    //dump_map();
++}
++
++// Find highest area of 32bit memory that can hold the given size.
++struct e820entry *
++find_high_area(u32 size)
++{
++    int i;
++    for (i=e820_count-1; i>=0; i--) {
++        struct e820entry *e = &e820_list[i];
++        u64 end = e->start + e->size;
++        if (e->type != E820_RAM || end > 0xffffffff || e->size < size)
++            continue;
++        if (end < 1024*1024 + size)
++            break;
++        return e;
++    }
++    return NULL;
++}
++
++// Prep for memmap stuff - init bios table locations.
++void
++memmap_setup(void)
++{
++    e820_count = 0;
++}
++
++// Report on final memory locations.
++void
++memmap_finalize(void)
++{
++    dump_map();
++}
+--- x/roms/seabios/src/memmap.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/memmap.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,34 @@
++#ifndef __E820MAP_H
++#define __E820MAP_H
++
++#include "types.h" // u64
++
++#define E820_RAM          1
++#define E820_RESERVED     2
++#define E820_ACPI         3
++#define E820_NVS          4
++#define E820_UNUSABLE     5
++#define E820_HOLE         ((u32)-1) // Useful for removing entries
++
++struct e820entry {
++    u64 start;
++    u64 size;
++    u32 type;
++};
++
++void add_e820(u64 start, u64 size, u32 type);
++void memmap_setup(void);
++void memmap_finalize(void);
++struct e820entry *find_high_area(u32 size);
++
++// A typical OS page size
++#define PAGE_SIZE 4096
++
++// e820 map storage (defined in system.c)
++extern struct e820entry e820_list[];
++extern int e820_count;
++
++// Space for exported bios tables (defined in misc.c)
++extern char BiosTableSpace[];
++
++#endif // e820map.h
+--- x/roms/seabios/src/misc.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/misc.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,190 @@
++// Code for misc 16bit handlers and variables.
++//
++// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2002  MandrakeSoft S.A.
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "bregs.h" // struct bregs
++#include "biosvar.h" // GET_BDA
++#include "util.h" // debug_enter
++#include "pic.h" // enable_hwirq
++
++// Amount of continuous ram under 4Gig
++u32 RamSize VAR16VISIBLE;
++// Amount of continuous ram >4Gig
++u64 RamSizeOver4G;
++// Space for bios tables built an run-time.
++char BiosTableSpace[CONFIG_MAX_BIOSTABLE] __aligned(MALLOC_MIN_ALIGN) VAR16VISIBLE;
++
++
++/****************************************************************
++ * Misc 16bit ISRs
++ ****************************************************************/
++
++// INT 12h Memory Size Service Entry Point
++void VISIBLE16
++handle_12(struct bregs *regs)
++{
++    debug_enter(regs, DEBUG_HDL_12);
++    regs->ax = GET_BDA(mem_size_kb);
++}
++
++// INT 11h Equipment List Service Entry Point
++void VISIBLE16
++handle_11(struct bregs *regs)
++{
++    debug_enter(regs, DEBUG_HDL_11);
++    regs->ax = GET_BDA(equipment_list_flags);
++}
++
++// INT 05h Print Screen Service Entry Point
++void VISIBLE16
++handle_05(struct bregs *regs)
++{
++    debug_enter(regs, DEBUG_HDL_05);
++}
++
++// INT 10h Video Support Service Entry Point
++void VISIBLE16
++handle_10(struct bregs *regs)
++{
++    debug_enter(regs, DEBUG_HDL_10);
++    // dont do anything, since the VGA BIOS handles int10h requests
++}
++
++// NMI handler
++void VISIBLE16
++handle_02(void)
++{
++    debug_isr(DEBUG_ISR_02);
++}
++
++void
++mathcp_setup(void)
++{
++    dprintf(3, "math cp init\n");
++    // 80x87 coprocessor installed
++    SETBITS_BDA(equipment_list_flags, 0x02);
++    enable_hwirq(13, entry_75);
++}
++
++// INT 75 - IRQ13 - MATH COPROCESSOR EXCEPTION
++void VISIBLE16
++handle_75(void)
++{
++    debug_isr(DEBUG_ISR_75);
++
++    // clear irq13
++    outb(0, PORT_MATH_CLEAR);
++    // clear interrupt
++    eoi_pic2();
++    // legacy nmi call
++    u32 eax=0, flags;
++    call16_simpint(0x02, &eax, &flags);
++}
++
++
++/****************************************************************
++ * BIOS_CONFIG_TABLE
++ ****************************************************************/
++
++// DMA channel 3 used by hard disk BIOS
++#define CBT_F1_DMA3USED (1<<7)
++// 2nd interrupt controller (8259) installed
++#define CBT_F1_2NDPIC   (1<<6)
++// Real-Time Clock installed
++#define CBT_F1_RTC      (1<<5)
++// INT 15/AH=4Fh called upon INT 09h
++#define CBT_F1_INT154F  (1<<4)
++// wait for external event (INT 15/AH=41h) supported
++#define CBT_F1_WAITEXT  (1<<3)
++// extended BIOS area allocated (usually at top of RAM)
++#define CBT_F1_EBDA     (1<<2)
++// bus is Micro Channel instead of ISA
++#define CBT_F1_MCA      (1<<1)
++// system has dual bus (Micro Channel + ISA)
++#define CBT_F1_MCAISA   (1<<0)
++
++// INT 16/AH=09h (keyboard functionality) supported
++#define CBT_F2_INT1609  (1<<6)
++
++struct bios_config_table_s BIOS_CONFIG_TABLE VAR16FIXED(0xe6f5) = {
++    .size     = sizeof(BIOS_CONFIG_TABLE) - 2,
++    .model    = CONFIG_MODEL_ID,
++    .submodel = CONFIG_SUBMODEL_ID,
++    .biosrev  = CONFIG_BIOS_REVISION,
++    .feature1 = (
++        CBT_F1_2NDPIC | CBT_F1_RTC | CBT_F1_EBDA
++        | (CONFIG_KBD_CALL_INT15_4F ? CBT_F1_INT154F : 0)),
++    .feature2 = CBT_F2_INT1609,
++    .feature3 = 0,
++    .feature4 = 0,
++    .feature5 = 0,
++};
++
++
++/****************************************************************
++ * GDT and IDT tables
++ ****************************************************************/
++
++// Real mode IDT descriptor
++struct descloc_s rmode_IDT_info VAR16VISIBLE = {
++    .length = sizeof(struct rmode_IVT) - 1,
++    .addr = (u32)MAKE_FLATPTR(SEG_IVT, 0),
++};
++
++// Dummy IDT that forces a machine shutdown if an irq happens in
++// protected mode.
++u8 dummy_IDT VAR16VISIBLE;
++
++// Protected mode IDT descriptor
++struct descloc_s pmode_IDT_info VAR16VISIBLE = {
++    .length = sizeof(dummy_IDT) - 1,
++    .addr = (u32)MAKE_FLATPTR(SEG_BIOS, &dummy_IDT),
++};
++
++// GDT
++u64 rombios32_gdt[] VAR16VISIBLE __aligned(8) = {
++    // First entry can't be used.
++    0x0000000000000000LL,
++    // 32 bit flat code segment (SEG32_MODE32_CS)
++    GDT_LIMIT(0xfffff) | GDT_CODE | GDT_B | GDT_G,
++    // 32 bit flat data segment (SEG32_MODE32_DS)
++    GDT_LIMIT(0xfffff) | GDT_DATA | GDT_B | GDT_G,
++    // 16 bit code segment base=0xf0000 limit=0xffff (SEG32_MODE16_CS)
++    GDT_LIMIT(BUILD_BIOS_SIZE-1) | GDT_CODE | GDT_BASE(BUILD_BIOS_ADDR),
++    // 16 bit data segment base=0x0 limit=0xffff (SEG32_MODE16_DS)
++    GDT_LIMIT(0x0ffff) | GDT_DATA,
++    // 16 bit code segment base=0 limit=0xffffffff (SEG32_MODE16BIG_CS)
++    GDT_LIMIT(0xfffff) | GDT_CODE | GDT_G,
++    // 16 bit data segment base=0 limit=0xffffffff (SEG32_MODE16BIG_DS)
++    GDT_LIMIT(0xfffff) | GDT_DATA | GDT_G,
++};
++
++// GDT descriptor
++struct descloc_s rombios32_gdt_48 VAR16VISIBLE = {
++    .length = sizeof(rombios32_gdt) - 1,
++    .addr = (u32)MAKE_FLATPTR(SEG_BIOS, rombios32_gdt),
++};
++
++
++/****************************************************************
++ * Misc fixed vars
++ ****************************************************************/
++
++char BiosCopyright[] VAR16FIXED(0xff00) =
++    "(c) 2002 MandrakeSoft S.A. Written by Kevin Lawton & the Bochs team.";
++
++// BIOS build date
++char BiosDate[] VAR16FIXED(0xfff5) = "06/23/99";
++
++u8 BiosModelId VAR16FIXED(0xfffe) = CONFIG_MODEL_ID;
++
++u8 BiosChecksum VAR16FIXED(0xffff);
++
++// XXX - Initial Interrupt Vector Offsets Loaded by POST
++u8 InitVectors[13] VAR16FIXED(0xfef3);
++
++// XXX - INT 1D - SYSTEM DATA - VIDEO PARAMETER TABLES
++u8 VideoParams[88] VAR16FIXED(0xf0a4);
+--- x/roms/seabios/src/mouse.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/mouse.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,333 @@
++// 16bit code to handle mouse events.
++//
++// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2002  MandrakeSoft S.A.
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "biosvar.h" // GET_EBDA
++#include "util.h" // debug_isr
++#include "pic.h" // eoi_pic2
++#include "bregs.h" // struct bregs
++#include "ps2port.h" // aux_command
++
++void
++mouse_setup(void)
++{
++    if (! CONFIG_MOUSE)
++        return;
++    dprintf(3, "init mouse\n");
++    // pointing device installed
++    SETBITS_BDA(equipment_list_flags, 0x04);
++}
++
++#define RET_SUCCESS      0x00
++#define RET_EINVFUNCTION 0x01
++#define RET_EINVINPUT    0x02
++#define RET_EINTERFACE   0x03
++#define RET_ENEEDRESEND  0x04
++#define RET_ENOHANDLER   0x05
++
++static int
++disable_mouse(u16 ebda_seg)
++{
++    u8 ps2ctr = GET_EBDA2(ebda_seg, ps2ctr);
++    ps2ctr |= I8042_CTR_AUXDIS;
++    ps2ctr &= ~I8042_CTR_AUXINT;
++    SET_EBDA2(ebda_seg, ps2ctr, ps2ctr);
++
++    return aux_command(PSMOUSE_CMD_DISABLE, NULL);
++}
++
++// Disable Mouse
++static void
++mouse_15c20000(struct bregs *regs)
++{
++    u16 ebda_seg = get_ebda_seg();
++    int ret = disable_mouse(ebda_seg);
++    if (ret)
++        set_code_invalid(regs, RET_ENEEDRESEND);
++    else
++        set_code_success(regs);
++}
++
++// Enable Mouse
++static void
++mouse_15c20001(struct bregs *regs)
++{
++    u16 ebda_seg = get_ebda_seg();
++    u8 mouse_flags_2 = GET_EBDA2(ebda_seg, mouse_flag2);
++    if ((mouse_flags_2 & 0x80) == 0) {
++        set_code_invalid(regs, RET_ENOHANDLER);
++        return;
++    }
++
++    u8 ps2ctr = GET_EBDA2(ebda_seg, ps2ctr);
++    ps2ctr &= ~I8042_CTR_AUXDIS;
++    ps2ctr |= I8042_CTR_AUXINT;
++    SET_EBDA2(ebda_seg, ps2ctr, ps2ctr);
++
++    int ret = aux_command(PSMOUSE_CMD_ENABLE, NULL);
++    if (ret)
++        set_code_invalid(regs, RET_ENEEDRESEND);
++    else
++        set_code_success(regs);
++}
++
++static void
++mouse_15c200XX(struct bregs *regs)
++{
++    set_code_unimplemented(regs, RET_EINVFUNCTION);
++}
++
++// Disable/Enable Mouse
++static void
++mouse_15c200(struct bregs *regs)
++{
++    switch (regs->bh) {
++    case 0x00: mouse_15c20000(regs); break;
++    case 0x01: mouse_15c20001(regs); break;
++    default:   mouse_15c200XX(regs); break;
++    }
++}
++
++// Reset Mouse
++static void
++mouse_15c201(struct bregs *regs)
++{
++    u8 param[2];
++    int ret = aux_command(PSMOUSE_CMD_RESET_BAT, param);
++    if (ret) {
++        set_code_invalid(regs, RET_ENEEDRESEND);
++        return;
++    }
++    regs->bl = param[0];
++    regs->bh = param[1];
++    set_code_success(regs);
++}
++
++// Set Sample Rate
++static void
++mouse_15c202(struct bregs *regs)
++{
++    static u8 VAR16 sample_rates[7] = {10, 20, 40, 60, 80, 100, 200};
++    if (regs->bh >= ARRAY_SIZE(sample_rates)) {
++        set_code_invalid(regs, RET_EINVINPUT);
++        return;
++    }
++    u8 mouse_data1 = GET_GLOBAL(sample_rates[regs->bh]);
++    int ret = aux_command(PSMOUSE_CMD_SETRATE, &mouse_data1);
++    if (ret)
++        set_code_invalid(regs, RET_ENEEDRESEND);
++    else
++        set_code_success(regs);
++}
++
++// Set Resolution
++static void
++mouse_15c203(struct bregs *regs)
++{
++    // BH:
++    //      0 =  25 dpi, 1 count  per millimeter
++    //      1 =  50 dpi, 2 counts per millimeter
++    //      2 = 100 dpi, 4 counts per millimeter
++    //      3 = 200 dpi, 8 counts per millimeter
++    if (regs->bh >= 4) {
++        set_code_invalid(regs, RET_EINVINPUT);
++        return;
++    }
++    u8 param = regs->bh;
++    int ret = aux_command(PSMOUSE_CMD_SETRES, &param);
++    if (ret)
++        set_code_invalid(regs, RET_ENEEDRESEND);
++    else
++        set_code_success(regs);
++}
++
++// Get Device ID
++static void
++mouse_15c204(struct bregs *regs)
++{
++    u8 param[2];
++    int ret = aux_command(PSMOUSE_CMD_GETID, param);
++    if (ret) {
++        set_code_invalid(regs, RET_ENEEDRESEND);
++        return;
++    }
++    regs->bh = param[0];
++    set_code_success(regs);
++}
++
++// Initialize Mouse
++static void
++mouse_15c205(struct bregs *regs)
++{
++    if (regs->bh != 3) {
++        set_code_invalid(regs, RET_EINTERFACE);
++        return;
++    }
++    u16 ebda_seg = get_ebda_seg();
++    SET_EBDA2(ebda_seg, mouse_flag1, 0x00);
++    SET_EBDA2(ebda_seg, mouse_flag2, regs->bh);
++
++    // Reset Mouse
++    mouse_15c201(regs);
++}
++
++// Return Status
++static void
++mouse_15c20600(struct bregs *regs)
++{
++    u8 param[3];
++    int ret = aux_command(PSMOUSE_CMD_GETINFO, param);
++    if (ret) {
++        set_code_invalid(regs, RET_ENEEDRESEND);
++        return;
++    }
++    regs->bl = param[0];
++    regs->cl = param[1];
++    regs->dl = param[2];
++    set_code_success(regs);
++}
++
++// Set Scaling Factor to 1:1
++static void
++mouse_15c20601(struct bregs *regs)
++{
++    int ret = aux_command(PSMOUSE_CMD_SETSCALE11, NULL);
++    if (ret)
++        set_code_invalid(regs, RET_ENEEDRESEND);
++    else
++        set_code_success(regs);
++}
++
++// Set Scaling Factor to 2:1
++static void
++mouse_15c20602(struct bregs *regs)
++{
++    int ret = aux_command(PSMOUSE_CMD_SETSCALE21, NULL);
++    if (ret)
++        set_code_invalid(regs, RET_ENEEDRESEND);
++    else
++        set_code_success(regs);
++}
++
++static void
++mouse_15c206XX(struct bregs *regs)
++{
++    set_code_unimplemented(regs, RET_EINVFUNCTION);
++}
++
++// Return Status & Set Scaling Factor...
++static void
++mouse_15c206(struct bregs *regs)
++{
++    switch (regs->bh) {
++    case 0x00: mouse_15c20600(regs); break;
++    case 0x01: mouse_15c20601(regs); break;
++    case 0x02: mouse_15c20602(regs); break;
++    default:   mouse_15c206XX(regs); break;
++    }
++}
++
++// Set Mouse Handler Address
++static void
++mouse_15c207(struct bregs *regs)
++{
++    struct segoff_s farptr = SEGOFF(regs->es, regs->bx);
++    u16 ebda_seg = get_ebda_seg();
++    u8 mouse_flags_2 = GET_EBDA2(ebda_seg, mouse_flag2);
++    if (! farptr.segoff) {
++        /* remove handler */
++        if ((mouse_flags_2 & 0x80) != 0) {
++            mouse_flags_2 &= ~0x80;
++            disable_mouse(ebda_seg);
++        }
++    } else {
++        /* install handler */
++        mouse_flags_2 |= 0x80;
++    }
++    SET_EBDA2(ebda_seg, mouse_flag2, mouse_flags_2);
++    SET_EBDA2(ebda_seg, far_call_pointer, farptr);
++    set_code_success(regs);
++}
++
++static void
++mouse_15c2XX(struct bregs *regs)
++{
++    set_code_unimplemented(regs, RET_EINVFUNCTION);
++}
++
++void
++handle_15c2(struct bregs *regs)
++{
++    //debug_stub(regs);
++
++    if (! CONFIG_MOUSE) {
++        set_code_invalid(regs, RET_EUNSUPPORTED);
++        return;
++    }
++
++    switch (regs->al) {
++    case 0x00: mouse_15c200(regs); break;
++    case 0x01: mouse_15c201(regs); break;
++    case 0x02: mouse_15c202(regs); break;
++    case 0x03: mouse_15c203(regs); break;
++    case 0x04: mouse_15c204(regs); break;
++    case 0x05: mouse_15c205(regs); break;
++    case 0x06: mouse_15c206(regs); break;
++    case 0x07: mouse_15c207(regs); break;
++    default:   mouse_15c2XX(regs); break;
++    }
++}
++
++void
++process_mouse(u8 data)
++{
++    if (!CONFIG_MOUSE)
++        return;
++
++    u16 ebda_seg = get_ebda_seg();
++    u8 mouse_flags_1 = GET_EBDA2(ebda_seg, mouse_flag1);
++    u8 mouse_flags_2 = GET_EBDA2(ebda_seg, mouse_flag2);
++
++    if (! (mouse_flags_2 & 0x80))
++        // far call handler not installed
++        return;
++
++    u8 package_count = mouse_flags_2 & 0x07;
++    u8 index = mouse_flags_1 & 0x07;
++    SET_EBDA2(ebda_seg, mouse_data[index], data);
++
++    if ((index+1) < package_count) {
++        mouse_flags_1++;
++        SET_EBDA2(ebda_seg, mouse_flag1, mouse_flags_1);
++        return;
++    }
++
++    //BX_DEBUG_INT74("int74_function: make_farcall=1\n");
++    u16 status = GET_EBDA2(ebda_seg, mouse_data[0]);
++    u16 X      = GET_EBDA2(ebda_seg, mouse_data[1]);
++    u16 Y      = GET_EBDA2(ebda_seg, mouse_data[2]);
++    SET_EBDA2(ebda_seg, mouse_flag1, 0);
++
++    struct segoff_s func = GET_EBDA2(ebda_seg, far_call_pointer);
++
++    asm volatile(
++        "sti\n"
++
++        "pushl %0\n"
++        "pushw %w1\n"  // status
++        "pushw %w2\n"  // X
++        "pushw %w3\n"  // Y
++        "pushw $0\n"   // Z
++        "lcallw *8(%%esp)\n"
++        "addl $12, %%esp\n"
++
++        "cli\n"
++        "cld\n"
++        :
++        : "r"(func.segoff), "r"(status), "r"(X), "r"(Y)
++        : "cc"
++        );
++}
+--- x/roms/seabios/src/mptable.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/mptable.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,207 @@
++// MPTable generation (on emulators)
++//
++// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2006 Fabrice Bellard
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "util.h" // dprintf
++#include "config.h" // CONFIG_*
++#include "mptable.h" // MPTABLE_SIGNATURE
++#include "paravirt.h" // qemu_cfg_irq0_override
++#include "pci.h"
++#include "pci_regs.h"
++
++void
++mptable_init(void)
++{
++    if (! CONFIG_MPTABLE)
++        return;
++
++    dprintf(3, "init MPTable\n");
++
++    // Config structure in temp area.
++    struct mptable_config_s *config = malloc_tmphigh(32*1024);
++    if (!config) {
++        dprintf(1, "No space for temp mptable\n");
++        return;
++    }
++    memset(config, 0, sizeof(*config));
++    config->signature = MPCONFIG_SIGNATURE;
++    config->spec = 4;
++    memcpy(config->oemid, CONFIG_CPUNAME8, sizeof(config->oemid));
++    memcpy(config->productid, "0.1         ", sizeof(config->productid));
++    config->lapic = BUILD_APIC_ADDR;
++
++    // Detect cpu info
++    u32 cpuid_signature, ebx, ecx, cpuid_features;
++    cpuid(1, &cpuid_signature, &ebx, &ecx, &cpuid_features);
++    int pkgcpus = 1;
++    if (cpuid_features & (1 << 28)) {
++        /* Only populate the MPS tables with the first logical CPU in
++           each package */
++        pkgcpus = (ebx >> 16) & 0xff;
++        pkgcpus = 1 << (__fls(pkgcpus - 1) + 1); /* round up to power of 2 */
++    }
++
++    // CPU definitions.
++    struct mpt_cpu *cpus = (void*)&config[1], *cpu = cpus;
++    int i;
++    for (i = 0; i < MaxCountCPUs; i+=pkgcpus) {
++        memset(cpu, 0, sizeof(*cpu));
++        cpu->type = MPT_TYPE_CPU;
++        cpu->apicid = i;
++        cpu->apicver = 0x11;
++        /* cpu flags: enabled, bootstrap cpu */
++        cpu->cpuflag = (i < CountCPUs) | ((i == 0) << 1);
++        if (cpuid_signature) {
++            cpu->cpusignature = cpuid_signature;
++            cpu->featureflag = cpuid_features;
++        } else {
++            cpu->cpusignature = 0x600;
++            cpu->featureflag = 0x201;
++        }
++        cpu++;
++    }
++    int entrycount = cpu - cpus;
++
++    // PCI buses
++    struct mpt_bus *bus = (void*)cpu;
++    int bdf, max, lastbus = -1;
++    foreachpci(bdf, max) {
++        int curbus = pci_bdf_to_bus(bdf);
++        if (curbus == lastbus)
++            continue;
++        lastbus = curbus;
++        memset(bus, 0, sizeof(*bus));
++        bus->type = MPT_TYPE_BUS;
++        bus->busid = curbus;
++        memcpy(bus->bustype, "PCI   ", sizeof(bus->bustype));
++        bus++;
++        entrycount++;
++    }
++
++    /* isa bus */
++    int isabusid;
++    memset(bus, 0, sizeof(*bus));
++    bus->type = MPT_TYPE_BUS;
++    isabusid = bus->busid = lastbus + 1;
++    memcpy(bus->bustype, "ISA   ", sizeof(bus->bustype));
++    entrycount++;
++
++    /* ioapic */
++    u8 ioapic_id = CountCPUs;
++    struct mpt_ioapic *ioapic = (void*)&bus[1];
++    memset(ioapic, 0, sizeof(*ioapic));
++    ioapic->type = MPT_TYPE_IOAPIC;
++    ioapic->apicid = ioapic_id;
++    ioapic->apicver = 0x11;
++    ioapic->flags = 1; // enable
++    ioapic->apicaddr = BUILD_IOAPIC_ADDR;
++    entrycount++;
++
++    /* irqs */
++    struct mpt_intsrc *intsrcs = (void*)&ioapic[1], *intsrc = intsrcs;
++    int dev = -1;
++    unsigned short mask = 0, pinmask = 0;
++
++    foreachpci(bdf, max) {
++        int pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN);
++        int irq = pci_config_readb(bdf, PCI_INTERRUPT_LINE);
++        if (pin == 0)
++            continue;
++        if (dev != pci_bdf_to_busdev(bdf)) {
++            dev = pci_bdf_to_busdev(bdf);
++            pinmask = 0;
++        }
++        if (pinmask & (1 << pin)) /* pin was seen already */
++            continue;
++        pinmask |= (1 << pin);
++        mask |= (1 << irq);
++        memset(intsrc, 0, sizeof(*intsrc));
++        intsrc->type = MPT_TYPE_INTSRC;
++        intsrc->irqtype = 0; /* INT */
++        intsrc->irqflag = 1; /* active high */
++        intsrc->srcbus = pci_bdf_to_bus(bdf); /* PCI bus */
++        intsrc->srcbusirq = (pci_bdf_to_dev(bdf) << 2) | (pin - 1);
++        intsrc->dstapic = ioapic_id;
++        intsrc->dstirq = irq;
++        intsrc++;
++    }
++
++    for (i = 0; i < 16; i++) {
++        memset(intsrc, 0, sizeof(*intsrc));
++        if (mask & (1 << i))
++            continue;
++        intsrc->type = MPT_TYPE_INTSRC;
++        intsrc->irqtype = 0; /* INT */
++        intsrc->irqflag = 0; /* conform to bus spec */
++        intsrc->srcbus = isabusid; /* ISA bus */
++        intsrc->srcbusirq = i;
++        intsrc->dstapic = ioapic_id;
++        intsrc->dstirq = i;
++        if (qemu_cfg_irq0_override()) {
++            /* Destination 2 is covered by irq0->inti2 override (i ==
++               0). Source IRQ 2 is unused */
++            if (i == 0)
++                intsrc->dstirq = 2;
++            else if (i == 2)
++                intsrc--;
++        }
++        intsrc++;
++    }
++    entrycount += intsrc - intsrcs;
++
++    /* Local interrupt assignment */
++    intsrc->type = MPT_TYPE_LOCAL_INT;
++    intsrc->irqtype = 3; /* ExtINT */
++    intsrc->irqflag = 0; /* PO, EL default */
++    intsrc->srcbus = isabusid; /* ISA */
++    intsrc->srcbusirq = 0;
++    intsrc->dstapic = 0; /* BSP == APIC #0 */
++    intsrc->dstirq = 0; /* LINTIN0 */
++    intsrc++;
++    entrycount++;
++
++    intsrc->type = MPT_TYPE_LOCAL_INT;
++    intsrc->irqtype = 1; /* NMI */
++    intsrc->irqflag = 0; /* PO, EL default */
++    intsrc->srcbus = isabusid; /* ISA */
++    intsrc->srcbusirq = 0;
++    intsrc->dstapic = 0; /* BSP == APIC #0 */
++    intsrc->dstirq = 1; /* LINTIN1 */
++    intsrc++;
++    entrycount++;
++
++    // Finalize config structure.
++    int length = (void*)intsrc - (void*)config;
++    config->entrycount = entrycount;
++    config->length = length;
++    config->checksum -= checksum(config, length);
++
++    // Allocate final memory locations.  (In theory the config
++    // structure can go in high memory, but Linux kernels before
++    // v2.6.30 crash with that.)
++    struct mptable_config_s *finalconfig = malloc_fseg(length);
++    struct mptable_floating_s *floating = malloc_fseg(sizeof(*floating));
++    if (!finalconfig || !floating) {
++        dprintf(1, "No room for MPTABLE!\n");
++        free(config);
++        free(finalconfig);
++        free(floating);
++        return;
++    }
++    memcpy(finalconfig, config, length);
++    free(config);
++
++    /* floating pointer structure */
++    memset(floating, 0, sizeof(*floating));
++    floating->signature = MPTABLE_SIGNATURE;
++    floating->physaddr = (u32)finalconfig;
++    floating->length = 1;
++    floating->spec_rev = 4;
++    floating->checksum -= checksum(floating, sizeof(*floating));
++
++    dprintf(1, "MP table addr=%p MPC table addr=%p size=%d\n",
++            floating, finalconfig, length);
++}
+--- x/roms/seabios/src/mptable.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/mptable.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,80 @@
++#ifndef __MPTABLE_H
++#define __MPTABLE_H
++
++#include "types.h" // u32
++
++#define MPTABLE_SIGNATURE 0x5f504d5f  // "_MP_"
++
++struct mptable_floating_s {
++    u32 signature;
++    u32 physaddr;
++    u8 length;
++    u8 spec_rev;
++    u8 checksum;
++    u8 feature1;
++    u8 feature2;
++    u8 reserved[3];
++};
++
++#define MPCONFIG_SIGNATURE 0x504d4350  // "PCMP"
++
++struct mptable_config_s {
++    u32 signature;
++    u16 length;
++    u8 spec;
++    u8 checksum;
++    char oemid[8];
++    char productid[12];
++    u32 oemptr;
++    u16 oemsize;
++    u16 entrycount;
++    u32 lapic;
++    u16 exttable_length;
++    u8 exttable_checksum;
++    u8 reserved;
++} PACKED;
++
++#define MPT_TYPE_CPU 0
++#define MPT_TYPE_BUS 1
++#define MPT_TYPE_IOAPIC 2
++#define MPT_TYPE_INTSRC 3
++#define MPT_TYPE_LOCAL_INT 4
++
++struct mpt_cpu {
++    u8 type;
++    u8 apicid;
++    u8 apicver;
++    u8 cpuflag;
++    u32 cpusignature;
++    u32 featureflag;
++    u32 reserved[2];
++} PACKED;
++
++struct mpt_bus {
++    u8 type;
++    u8 busid;
++    char bustype[6];
++} PACKED;
++
++struct mpt_ioapic {
++    u8 type;
++    u8 apicid;
++    u8 apicver;
++    u8 flags;
++    u32 apicaddr;
++} PACKED;
++
++struct mpt_intsrc {
++    u8 type;
++    u8 irqtype;
++    u16 irqflag;
++    u8 srcbus;
++    u8 srcbusirq;
++    u8 dstapic;
++    u8 dstirq;
++} PACKED;
++
++// mptable.c
++void mptable_init(void);
++
++#endif // mptable.h
+--- x/roms/seabios/src/mtrr.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/mtrr.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,102 @@
++// Initialize MTRRs - mostly useful on KVM.
++//
++// Copyright (C) 2006 Fabrice Bellard
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "util.h" // dprintf
++#include "biosvar.h" // GET_EBDA
++
++#define MSR_MTRRcap                    0x000000fe
++#define MSR_MTRRfix64K_00000           0x00000250
++#define MSR_MTRRfix16K_80000           0x00000258
++#define MSR_MTRRfix16K_A0000           0x00000259
++#define MSR_MTRRfix4K_C0000            0x00000268
++#define MSR_MTRRfix4K_C8000            0x00000269
++#define MSR_MTRRfix4K_D0000            0x0000026a
++#define MSR_MTRRfix4K_D8000            0x0000026b
++#define MSR_MTRRfix4K_E0000            0x0000026c
++#define MSR_MTRRfix4K_E8000            0x0000026d
++#define MSR_MTRRfix4K_F0000            0x0000026e
++#define MSR_MTRRfix4K_F8000            0x0000026f
++#define MSR_MTRRdefType                0x000002ff
++
++#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg))
++#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1)
++
++#define MTRR_MEMTYPE_UC 0
++#define MTRR_MEMTYPE_WC 1
++#define MTRR_MEMTYPE_WT 4
++#define MTRR_MEMTYPE_WP 5
++#define MTRR_MEMTYPE_WB 6
++
++void mtrr_setup(void)
++{
++    if (CONFIG_COREBOOT)
++        return;
++
++    u32 eax, ebx, ecx, edx, cpuid_features;
++    cpuid(1, &eax, &ebx, &ecx, &cpuid_features);
++    if (!(cpuid_features & CPUID_MTRR))
++        return;
++    if (!(cpuid_features & CPUID_MSR))
++        return;
++
++    dprintf(3, "init mtrr\n");
++
++    u32 mtrr_cap = rdmsr(MSR_MTRRcap);
++    int vcnt = mtrr_cap & 0xff;
++    int fix = mtrr_cap & 0x100;
++    if (!vcnt || !fix)
++       return;
++
++    // Disable MTRRs
++    wrmsr_smp(MSR_MTRRdefType, 0);
++
++    // Set fixed MTRRs
++    union u64b {
++        u8 valb[8];
++        u64 val;
++    } u;
++    u.val = 0;
++    int i;
++    for (i = 0; i < 8; i++)
++        if (RamSize >= 65536 * (i + 1))
++            u.valb[i] = MTRR_MEMTYPE_WB;
++    wrmsr_smp(MSR_MTRRfix64K_00000, u.val);
++    u.val = 0;
++    for (i = 0; i < 8; i++)
++        if (RamSize >= 0x80000 + 16384 * (i + 1))
++            u.valb[i] = MTRR_MEMTYPE_WB;
++    wrmsr_smp(MSR_MTRRfix16K_80000, u.val);
++    wrmsr_smp(MSR_MTRRfix16K_A0000, 0);   // 0xA0000-0xC0000 is uncached
++    int j;
++    for (j = 0; j < 8; j++) {
++        u.val = 0;
++        for (i = 0; i < 8; i++)
++            if (RamSize >= 0xC0000 + j * 0x8000 + 4096 * (i + 1))
++                u.valb[i] = MTRR_MEMTYPE_WP;
++        wrmsr_smp(MSR_MTRRfix4K_C0000 + j, u.val);
++    }
++
++    // Set variable MTRRs
++    int phys_bits = 36;
++    cpuid(0x80000000u, &eax, &ebx, &ecx, &edx);
++    if (eax >= 0x80000008) {
++            /* Get physical bits from leaf 0x80000008 (if available) */
++            cpuid(0x80000008u, &eax, &ebx, &ecx, &edx);
++            phys_bits = eax & 0xff;
++    }
++    u64 phys_mask = ((1ull << phys_bits) - 1);
++    for (i=0; i<vcnt; i++) {
++        wrmsr_smp(MTRRphysBase_MSR(i), 0);
++        wrmsr_smp(MTRRphysMask_MSR(i), 0);
++    }
++    /* Mark 3.5-4GB as UC, anything not specified defaults to WB */
++    wrmsr_smp(MTRRphysBase_MSR(0), BUILD_MAX_HIGHMEM | MTRR_MEMTYPE_UC);
++    wrmsr_smp(MTRRphysMask_MSR(0)
++              , (-((1ull<<32)-BUILD_MAX_HIGHMEM) & phys_mask) | 0x800);
++
++    // Enable fixed and variable MTRRs; set default type.
++    wrmsr_smp(MSR_MTRRdefType, 0xc00 | MTRR_MEMTYPE_WB);
++}
+--- x/roms/seabios/src/optionroms.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/optionroms.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,488 @@
++// Option rom scanning code.
++//
++// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2002  MandrakeSoft S.A.
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "bregs.h" // struct bregs
++#include "farptr.h" // FLATPTR_TO_SEG
++#include "config.h" // CONFIG_*
++#include "util.h" // dprintf
++#include "pci.h" // foreachpci
++#include "pci_regs.h" // PCI_ROM_ADDRESS
++#include "pci_ids.h" // PCI_CLASS_DISPLAY_VGA
++#include "boot.h" // IPL
++#include "paravirt.h" // qemu_cfg_*
++
++
++/****************************************************************
++ * Definitions
++ ****************************************************************/
++
++struct rom_header {
++    u16 signature;
++    u8 size;
++    u8 initVector[4];
++    u8 reserved[17];
++    u16 pcioffset;
++    u16 pnpoffset;
++} PACKED;
++
++struct pci_data {
++    u32 signature;
++    u16 vendor;
++    u16 device;
++    u16 vitaldata;
++    u16 dlen;
++    u8 drevision;
++    u8 class_lo;
++    u16 class_hi;
++    u16 ilen;
++    u16 irevision;
++    u8 type;
++    u8 indicator;
++    u16 reserved;
++} PACKED;
++
++struct pnp_data {
++    u32 signature;
++    u8 revision;
++    u8 len;
++    u16 nextoffset;
++    u8 reserved_08;
++    u8 checksum;
++    u32 devid;
++    u16 manufacturer;
++    u16 productname;
++    u8 type_lo;
++    u16 type_hi;
++    u8 dev_flags;
++    u16 bcv;
++    u16 dv;
++    u16 bev;
++    u16 reserved_1c;
++    u16 staticresource;
++} PACKED;
++
++#define OPTION_ROM_SIGNATURE 0xaa55
++#define OPTION_ROM_ALIGN 2048
++#define OPTION_ROM_INITVECTOR offsetof(struct rom_header, initVector[0])
++#define PCI_ROM_SIGNATURE 0x52494350 // PCIR
++#define PCIROM_CODETYPE_X86 0
++
++// The end of the last deployed rom.
++u32 RomEnd;
++
++
++/****************************************************************
++ * Helper functions
++ ****************************************************************/
++
++// Execute a given option rom.
++static void
++__callrom(struct rom_header *rom, u16 offset, u16 bdf)
++{
++    u16 seg = FLATPTR_TO_SEG(rom);
++    dprintf(1, "Running option rom at %04x:%04x\n", seg, offset);
++
++    struct bregs br;
++    memset(&br, 0, sizeof(br));
++    br.flags = F_IF;
++    br.ax = bdf;
++    br.bx = 0xffff;
++    br.dx = 0xffff;
++    br.es = SEG_BIOS;
++    br.di = get_pnp_offset();
++    br.code = SEGOFF(seg, offset);
++    start_preempt();
++    call16big(&br);
++    finish_preempt();
++
++    debug_serial_setup();
++}
++
++// Execute a given option rom at the standard entry vector.
++static void
++callrom(struct rom_header *rom, u16 bdf)
++{
++    __callrom(rom, OPTION_ROM_INITVECTOR, bdf);
++}
++
++// Execute a BCV option rom registered via add_bcv().
++void
++call_bcv(u16 seg, u16 ip)
++{
++    __callrom(MAKE_FLATPTR(seg, 0), ip, 0);
++}
++
++// Verify that an option rom looks valid
++static int
++is_valid_rom(struct rom_header *rom)
++{
++    dprintf(6, "Checking rom %p (sig %x size %d)\n"
++            , rom, rom->signature, rom->size);
++    if (rom->signature != OPTION_ROM_SIGNATURE)
++        return 0;
++    if (! rom->size)
++        return 0;
++    u32 len = rom->size * 512;
++    u8 sum = checksum(rom, len);
++    if (sum != 0) {
++        dprintf(1, "Found option rom with bad checksum: loc=%p len=%d sum=%x\n"
++                , rom, len, sum);
++        return 0;
++    }
++    return 1;
++}
++
++// Check if a valid option rom has a pnp struct; return it if so.
++static struct pnp_data *
++get_pnp_rom(struct rom_header *rom)
++{
++    struct pnp_data *pnp = (void*)((u8*)rom + rom->pnpoffset);
++    if (pnp->signature != PNP_SIGNATURE)
++        return NULL;
++    return pnp;
++}
++
++// Check for multiple pnp option rom headers.
++static struct pnp_data *
++get_pnp_next(struct rom_header *rom, struct pnp_data *pnp)
++{
++    if (! pnp->nextoffset)
++        return NULL;
++    pnp = (void*)((u8*)rom + pnp->nextoffset);
++    if (pnp->signature != PNP_SIGNATURE)
++        return NULL;
++    return pnp;
++}
++
++// Check if a valid option rom has a pci struct; return it if so.
++static struct pci_data *
++get_pci_rom(struct rom_header *rom)
++{
++    struct pci_data *pci = (void*)((u32)rom + rom->pcioffset);
++    if (pci->signature != PCI_ROM_SIGNATURE)
++        return NULL;
++    return pci;
++}
++
++// Return the memory position up to which roms may be located.
++static inline u32
++max_rom(void)
++{
++    extern u8 code32flat_start[];
++    if ((u32)code32flat_start > BUILD_BIOS_ADDR)
++        return BUILD_BIOS_ADDR;
++    return (u32)code32flat_start;
++}
++
++// Copy a rom to its permanent location below 1MiB
++static struct rom_header *
++copy_rom(struct rom_header *rom)
++{
++    u32 romsize = rom->size * 512;
++    if (RomEnd + romsize > max_rom()) {
++        // Option rom doesn't fit.
++        dprintf(1, "Option rom %p doesn't fit.\n", rom);
++        return NULL;
++    }
++    dprintf(4, "Copying option rom (size %d) from %p to %x\n"
++            , romsize, rom, RomEnd);
++    iomemcpy((void*)RomEnd, rom, romsize);
++    return (void*)RomEnd;
++}
++
++// Run rom init code and note rom size.
++static int
++init_optionrom(struct rom_header *rom, u16 bdf, int isvga)
++{
++    if (! is_valid_rom(rom))
++        return -1;
++
++    if (isvga || get_pnp_rom(rom))
++        // Only init vga and PnP roms here.
++        callrom(rom, bdf);
++
++    RomEnd = (u32)rom + ALIGN(rom->size * 512, OPTION_ROM_ALIGN);
++
++    return 0;
++}
++
++
++/****************************************************************
++ * Roms in CBFS
++ ****************************************************************/
++
++// Check if an option rom is at a hardcoded location or in CBFS.
++static struct rom_header *
++lookup_hardcode(u32 vendev)
++{
++    if (OPTIONROM_VENDEV_1
++        && ((OPTIONROM_VENDEV_1 >> 16)
++            | ((OPTIONROM_VENDEV_1 & 0xffff)) << 16) == vendev)
++        return copy_rom((void*)OPTIONROM_MEM_1);
++    if (OPTIONROM_VENDEV_2
++        && ((OPTIONROM_VENDEV_2 >> 16)
++            | ((OPTIONROM_VENDEV_2 & 0xffff)) << 16) == vendev)
++        return copy_rom((void*)OPTIONROM_MEM_2);
++    int ret = cbfs_copy_optionrom((void*)RomEnd, max_rom() - RomEnd, vendev);
++    if (ret < 0)
++        return NULL;
++    return (void*)RomEnd;
++}
++
++// Run all roms in a given CBFS directory.
++static void
++run_cbfs_roms(const char *prefix, int isvga)
++{
++    struct cbfs_file *file = NULL;
++    for (;;) {
++        file = cbfs_findprefix(prefix, file);
++        if (!file)
++            break;
++        int ret = cbfs_copyfile(file, (void*)RomEnd, max_rom() - RomEnd);
++        if (ret > 0)
++            init_optionrom((void*)RomEnd, 0, isvga);
++    }
++}
++
++static void
++run_qemu_roms(const char *prefix, int isvga)
++{
++    struct QemuCfgFile entry;
++    int plen = strlen(prefix);
++    int rc, dlen;
++
++    rc = qemu_cfg_first_file(&entry);
++    while (rc > 0) {
++        if (memcmp(prefix, entry.name, plen) == 0) {
++            dlen = qemu_cfg_read_file(&entry, (void*)RomEnd, max_rom() - RomEnd);
++            if (dlen > 0) {
++                dprintf(1, "init qemu rom: %s\n", entry.name);
++                init_optionrom((void*)RomEnd, 0, isvga);
++            }
++        }
++        rc = qemu_cfg_next_file(&entry);
++    }
++}
++
++
++/****************************************************************
++ * PCI roms
++ ****************************************************************/
++
++// Map the option rom of a given PCI device.
++static struct rom_header *
++map_pcirom(u16 bdf, u32 vendev)
++{
++    dprintf(6, "Attempting to map option rom on dev %02x:%02x.%x\n"
++            , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf));
++
++    u8 htype = pci_config_readb(bdf, PCI_HEADER_TYPE);
++    if ((htype & 0x7f) != PCI_HEADER_TYPE_NORMAL) {
++        dprintf(6, "Skipping non-normal pci device (type=%x)\n", htype);
++        return NULL;
++    }
++
++    u32 orig = pci_config_readl(bdf, PCI_ROM_ADDRESS);
++    pci_config_writel(bdf, PCI_ROM_ADDRESS, ~PCI_ROM_ADDRESS_ENABLE);
++    u32 sz = pci_config_readl(bdf, PCI_ROM_ADDRESS);
++
++    dprintf(6, "Option rom sizing returned %x %x\n", orig, sz);
++    orig &= ~PCI_ROM_ADDRESS_ENABLE;
++    if (!sz || sz == 0xffffffff)
++        goto fail;
++
++    if (orig == sz || (u32)(orig + 4*1024*1024) < 20*1024*1024) {
++        // Don't try to map to a pci addresses at its max, in the last
++        // 4MiB of ram, or the first 16MiB of ram.
++        dprintf(6, "Preset rom address doesn't look valid\n");
++        goto fail;
++    }
++
++    // Looks like a rom - enable it.
++    pci_config_writel(bdf, PCI_ROM_ADDRESS, orig | PCI_ROM_ADDRESS_ENABLE);
++
++    struct rom_header *rom = (void*)orig;
++    for (;;) {
++        dprintf(5, "Inspecting possible rom at %p (dv=%08x bdf=%x)\n"
++                , rom, vendev, bdf);
++        if (rom->signature != OPTION_ROM_SIGNATURE) {
++            dprintf(6, "No option rom signature (got %x)\n", rom->signature);
++            goto fail;
++        }
++        struct pci_data *pci = get_pci_rom(rom);
++        if (! pci) {
++            dprintf(6, "No valid pci signature found\n");
++            goto fail;
++        }
++
++        u32 vd = (pci->device << 16) | pci->vendor;
++        if (vd == vendev && pci->type == PCIROM_CODETYPE_X86)
++            // A match
++            break;
++        dprintf(6, "Didn't match dev/ven (got %08x) or type (got %d)\n"
++                , vd, pci->type);
++        if (pci->indicator & 0x80) {
++            dprintf(6, "No more images left\n");
++            goto fail;
++        }
++        rom = (void*)((u32)rom + pci->ilen * 512);
++    }
++
++    rom = copy_rom(rom);
++    pci_config_writel(bdf, PCI_ROM_ADDRESS, orig);
++    return rom;
++fail:
++    // Not valid - restore original and exit.
++    pci_config_writel(bdf, PCI_ROM_ADDRESS, orig);
++    return NULL;
++}
++
++// Attempt to map and initialize the option rom on a given PCI device.
++static int
++init_pcirom(u16 bdf, int isvga)
++{
++    u32 vendev = pci_config_readl(bdf, PCI_VENDOR_ID);
++    dprintf(4, "Attempting to init PCI bdf %02x:%02x.%x (dev/ven %08x)\n"
++            , pci_bdf_to_bus(bdf), pci_bdf_to_dev(bdf), pci_bdf_to_fn(bdf)
++            , vendev);
++    struct rom_header *rom = lookup_hardcode(vendev);
++    if (! rom)
++        rom = map_pcirom(bdf, vendev);
++    if (! rom)
++        // No ROM present.
++        return -1;
++    return init_optionrom(rom, bdf, isvga);
++}
++
++
++/****************************************************************
++ * Non-VGA option rom init
++ ****************************************************************/
++
++void
++optionrom_setup(void)
++{
++    if (! CONFIG_OPTIONROMS)
++        return;
++
++    dprintf(1, "Scan for option roms\n");
++
++    u32 post_vga = RomEnd;
++
++    if (CONFIG_OPTIONROMS_DEPLOYED) {
++        // Option roms are already deployed on the system.
++        u32 pos = RomEnd;
++        while (pos < max_rom()) {
++            int ret = init_optionrom((void*)pos, 0, 0);
++            if (ret)
++                pos += OPTION_ROM_ALIGN;
++            else
++                pos = RomEnd;
++        }
++    } else {
++        // Find and deploy PCI roms.
++        int bdf, max;
++        foreachpci(bdf, max) {
++            u16 v = pci_config_readw(bdf, PCI_CLASS_DEVICE);
++            if (v == 0x0000 || v == 0xffff || v == PCI_CLASS_DISPLAY_VGA
++                || (CONFIG_ATA && v == PCI_CLASS_STORAGE_IDE))
++                continue;
++            init_pcirom(bdf, 0);
++        }
++
++        // Find and deploy CBFS roms not associated with a device.
++        run_cbfs_roms("genroms/", 0);
++        run_qemu_roms("genroms/", 0);
++    }
++
++    // All option roms found and deployed - now build BEV/BCV vectors.
++
++    u32 pos = post_vga;
++    while (pos < RomEnd) {
++        struct rom_header *rom = (void*)pos;
++        if (! is_valid_rom(rom)) {
++            pos += OPTION_ROM_ALIGN;
++            continue;
++        }
++        pos += ALIGN(rom->size * 512, OPTION_ROM_ALIGN);
++        struct pnp_data *pnp = get_pnp_rom(rom);
++        if (! pnp) {
++            // Legacy rom.
++            add_bcv(FLATPTR_TO_SEG(rom), OPTION_ROM_INITVECTOR, 0);
++            continue;
++        }
++        // PnP rom.
++        if (pnp->bev)
++            // Can boot system - add to IPL list.
++            add_bev(FLATPTR_TO_SEG(rom), pnp->bev, pnp->productname);
++        else
++            // Check for BCV (there may be multiple).
++            while (pnp && pnp->bcv) {
++                add_bcv(FLATPTR_TO_SEG(rom), pnp->bcv, pnp->productname);
++                pnp = get_pnp_next(rom, pnp);
++            }
++    }
++}
++
++
++/****************************************************************
++ * VGA init
++ ****************************************************************/
++
++// Call into vga code to turn on console.
++void
++vga_setup(void)
++{
++    VGAbdf = -1;
++    RomEnd = BUILD_ROM_START;
++
++    if (! CONFIG_OPTIONROMS)
++        return;
++
++    dprintf(1, "Scan for VGA option rom\n");
++
++    if (CONFIG_OPTIONROMS_DEPLOYED) {
++        // Option roms are already deployed on the system.
++        init_optionrom((void*)BUILD_ROM_START, 0, 1);
++    } else {
++        // Find and deploy PCI VGA rom.
++        int bdf = VGAbdf = pci_find_vga();
++        if (bdf >= 0)
++            init_pcirom(bdf, 1);
++
++        // Find and deploy CBFS vga-style roms not associated with a device.
++        run_cbfs_roms("vgaroms/", 1);
++        run_qemu_roms("vgaroms/", 1);
++    }
++
++    if (RomEnd == BUILD_ROM_START) {
++        // No VGA rom found
++        RomEnd += OPTION_ROM_ALIGN;
++        return;
++    }
++
++    dprintf(1, "Turning on vga console\n");
++    struct bregs br;
++    memset(&br, 0, sizeof(br));
++    br.flags = F_IF;
++    br.ax = 0x0003;
++    call16_int(0x10, &br);
++
++    // Write to screen.
++    printf("Starting SeaBIOS (version %s)\n\n", VERSION);
++}
++
++void
++s3_resume_vga_init(void)
++{
++    if (!CONFIG_S3_RESUME_VGA_INIT)
++        return;
++    struct rom_header *rom = (void*)BUILD_ROM_START;
++    if (! is_valid_rom(rom))
++        return;
++    callrom(rom, 0);
++}
+--- x/roms/seabios/src/output.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/output.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,525 @@
++// Raw screen writing and debug output code.
++//
++// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include <stdarg.h> // va_list
++
++#include "farptr.h" // GET_VAR
++#include "util.h" // printf
++#include "bregs.h" // struct bregs
++#include "config.h" // CONFIG_*
++#include "biosvar.h" // GET_GLOBAL
++
++struct putcinfo {
++    void (*func)(struct putcinfo *info, char c);
++};
++
++
++/****************************************************************
++ * Debug output
++ ****************************************************************/
++
++#define DEBUG_PORT PORT_SERIAL1
++#define DEBUG_TIMEOUT 100000
++
++void
++debug_serial_setup(void)
++{
++    if (!CONFIG_DEBUG_SERIAL)
++        return;
++    // setup for serial logging: 8N1
++    u8 oldparam, newparam = 0x03;
++    oldparam = inb(DEBUG_PORT+SEROFF_LCR);
++    outb(newparam, DEBUG_PORT+SEROFF_LCR);
++    // Disable irqs
++    u8 oldier, newier = 0;
++    oldier = inb(DEBUG_PORT+SEROFF_IER);
++    outb(newier, DEBUG_PORT+SEROFF_IER);
++
++    if (oldparam != newparam || oldier != newier)
++        dprintf(1, "Changing serial settings was %x/%x now %x/%x\n"
++                , oldparam, oldier, newparam, newier);
++}
++
++// Write a character to the serial port.
++static void
++debug_serial(char c)
++{
++    if (!CONFIG_DEBUG_SERIAL)
++        return;
++    int timeout = DEBUG_TIMEOUT;
++    while ((inb(DEBUG_PORT+SEROFF_LSR) & 0x60) != 0x60)
++        if (!timeout--)
++            // Ran out of time.
++            return;
++    outb(c, DEBUG_PORT+SEROFF_DATA);
++}
++
++// Make sure all serial port writes have been completely sent.
++static void
++debug_serial_flush(void)
++{
++    if (!CONFIG_DEBUG_SERIAL)
++        return;
++    int timeout = DEBUG_TIMEOUT;
++    while ((inb(DEBUG_PORT+SEROFF_LSR) & 0x40) != 0x40)
++        if (!timeout--)
++            // Ran out of time.
++            return;
++}
++
++// Write a character to debug port(s).
++static void
++putc_debug(struct putcinfo *action, char c)
++{
++    if (! CONFIG_DEBUG_LEVEL)
++        return;
++    if (! CONFIG_COREBOOT)
++        // Send character to debug port.
++        outb(c, PORT_BIOS_DEBUG);
++    if (c == '\n')
++        debug_serial('\r');
++    debug_serial(c);
++}
++
++// In segmented mode just need a dummy variable (putc_debug is always
++// used anyway), and in 32bit flat mode need a pointer to the 32bit
++// instance of putc_debug().
++#if MODE16
++static struct putcinfo debuginfo VAR16;
++#elif MODESEGMENT
++static struct putcinfo debuginfo VAR32SEG;
++#else
++static struct putcinfo debuginfo = { putc_debug };
++#endif
++
++
++/****************************************************************
++ * Screen writing
++ ****************************************************************/
++
++// Show a character on the screen.
++static void
++screenc(char c)
++{
++    struct bregs br;
++    memset(&br, 0, sizeof(br));
++    br.flags = F_IF;
++    br.ah = 0x0e;
++    br.al = c;
++    call16_int(0x10, &br);
++}
++
++// Handle a character from a printf request.
++static void
++putc_screen(struct putcinfo *action, char c)
++{
++    if (CONFIG_SCREEN_AND_DEBUG)
++        putc_debug(&debuginfo, c);
++    if (c == '\n')
++        screenc('\r');
++    screenc(c);
++}
++
++static struct putcinfo screeninfo = { putc_screen };
++
++
++/****************************************************************
++ * Xprintf code
++ ****************************************************************/
++
++// Output a character.
++static void
++putc(struct putcinfo *action, char c)
++{
++    if (MODESEGMENT) {
++        // Only debugging output supported in segmented mode.
++        putc_debug(action, c);
++        return;
++    }
++
++    void (*func)(struct putcinfo *info, char c) = GET_GLOBAL(action->func);
++    func(action, c);
++}
++
++// Ouptut a string.
++static void
++puts(struct putcinfo *action, const char *s)
++{
++    for (; *s; s++)
++        putc(action, *s);
++}
++
++// Output a string that is in the CS segment.
++static void
++puts_cs(struct putcinfo *action, const char *s)
++{
++    char *vs = (char*)s;
++    for (;; vs++) {
++        char c = GET_GLOBAL(*vs);
++        if (!c)
++            break;
++        putc(action, c);
++    }
++}
++
++// Output an unsigned integer.
++static void
++putuint(struct putcinfo *action, u32 val)
++{
++    char buf[12];
++    char *d = &buf[sizeof(buf) - 1];
++    *d-- = '\0';
++    for (;;) {
++        *d = (val % 10) + '0';
++        val /= 10;
++        if (!val)
++            break;
++        d--;
++    }
++    puts(action, d);
++}
++
++// Output a single digit hex character.
++static inline void
++putsinglehex(struct putcinfo *action, u32 val)
++{
++    if (val <= 9)
++        val = '0' + val;
++    else
++        val = 'a' + val - 10;
++    putc(action, val);
++}
++
++// Output an integer in hexadecimal.
++static void
++puthex(struct putcinfo *action, u32 val, int width)
++{
++    if (!width) {
++        u32 tmp = val;
++        width = 1;
++        if (tmp > 0xffff) {
++            width += 4;
++            tmp >>= 16;
++        }
++        if (tmp > 0xff) {
++            width += 2;
++            tmp >>= 8;
++        }
++        if (tmp > 0xf)
++            width += 1;
++    }
++
++    switch (width) {
++    default: putsinglehex(action, (val >> 28) & 0xf);
++    case 7:  putsinglehex(action, (val >> 24) & 0xf);
++    case 6:  putsinglehex(action, (val >> 20) & 0xf);
++    case 5:  putsinglehex(action, (val >> 16) & 0xf);
++    case 4:  putsinglehex(action, (val >> 12) & 0xf);
++    case 3:  putsinglehex(action, (val >> 8) & 0xf);
++    case 2:  putsinglehex(action, (val >> 4) & 0xf);
++    case 1:  putsinglehex(action, (val >> 0) & 0xf);
++    }
++}
++
++static inline int
++isdigit(u8 c)
++{
++    return ((u8)(c - '0')) < 10;
++}
++
++static void
++bvprintf(struct putcinfo *action, const char *fmt, va_list args)
++{
++    const char *s = fmt;
++    for (;; s++) {
++        char c = GET_GLOBAL(*(u8*)s);
++        if (!c)
++            break;
++        if (c != '%') {
++            putc(action, c);
++            continue;
++        }
++        const char *n = s+1;
++        int field_width = 0;
++        for (;;) {
++            c = GET_GLOBAL(*(u8*)n);
++            if (!isdigit(c))
++                break;
++            field_width = field_width * 10 + c - '0';
++            n++;
++        }
++        if (c == 'l') {
++            // Ignore long format indicator
++            n++;
++            c = GET_GLOBAL(*(u8*)n);
++        }
++        s32 val;
++        const char *sarg;
++        switch (c) {
++        case '%':
++            putc(action, '%');
++            break;
++        case 'd':
++            val = va_arg(args, s32);
++            if (val < 0) {
++                putc(action, '-');
++                val = -val;
++            }
++            putuint(action, val);
++            break;
++        case 'u':
++            val = va_arg(args, s32);
++            putuint(action, val);
++            break;
++        case 'p':
++            /* %p always has 0x prepended */
++            putc(action, '0');
++            putc(action, 'x');
++            field_width = 8;
++        case 'x':
++            val = va_arg(args, s32);
++            puthex(action, val, field_width);
++            break;
++        case 'c':
++            val = va_arg(args, int);
++            putc(action, val);
++            break;
++        case '.':
++            // Hack to support "%.s" - meaning string on stack.
++            if (GET_GLOBAL(*(u8*)(n+1)) != 's')
++                break;
++            n++;
++            sarg = va_arg(args, const char *);
++            puts(action, sarg);
++            break;
++        case 's':
++            sarg = va_arg(args, const char *);
++            puts_cs(action, sarg);
++            break;
++        default:
++            putc(action, '%');
++            n = s;
++        }
++        s = n;
++    }
++}
++
++void
++panic(const char *fmt, ...)
++{
++    if (CONFIG_DEBUG_LEVEL) {
++        va_list args;
++        va_start(args, fmt);
++        bvprintf(&debuginfo, fmt, args);
++        va_end(args);
++        debug_serial_flush();
++    }
++
++    // XXX - use PANIC PORT.
++    irq_disable();
++    for (;;)
++        hlt();
++}
++
++void
++__dprintf(const char *fmt, ...)
++{
++    if (!MODESEGMENT && CONFIG_THREADS && CONFIG_DEBUG_LEVEL >= DEBUG_thread
++        && *fmt != '\\' && *fmt != '/') {
++        struct thread_info *cur = getCurThread();
++        if (cur != &MainThread) {
++            // Show "thread id" for this debug message.
++            putc_debug(&debuginfo, '|');
++            puthex(&debuginfo, (u32)cur, 8);
++            putc_debug(&debuginfo, '|');
++            putc_debug(&debuginfo, ' ');
++        }
++    }
++
++    va_list args;
++    va_start(args, fmt);
++    bvprintf(&debuginfo, fmt, args);
++    va_end(args);
++    debug_serial_flush();
++}
++
++void
++printf(const char *fmt, ...)
++{
++    ASSERT32FLAT();
++    va_list args;
++    va_start(args, fmt);
++    bvprintf(&screeninfo, fmt, args);
++    va_end(args);
++    if (CONFIG_SCREEN_AND_DEBUG)
++        debug_serial_flush();
++}
++
++
++/****************************************************************
++ * snprintf
++ ****************************************************************/
++
++struct snprintfinfo {
++    struct putcinfo info;
++    char *str, *end;
++};
++
++static void
++putc_str(struct putcinfo *info, char c)
++{
++    struct snprintfinfo *sinfo = container_of(info, struct snprintfinfo, info);
++    if (sinfo->str >= sinfo->end)
++        return;
++    *sinfo->str = c;
++    sinfo->str++;
++}
++
++// Build a formatted string.  Note, this function returns the actual
++// number of bytes used (not including null) even in the overflow
++// case.
++int
++snprintf(char *str, size_t size, const char *fmt, ...)
++{
++    ASSERT32FLAT();
++    if (!size)
++        return 0;
++    struct snprintfinfo sinfo = { { putc_str }, str, str + size };
++    va_list args;
++    va_start(args, fmt);
++    bvprintf(&sinfo.info, fmt, args);
++    va_end(args);
++    char *end = sinfo.str;
++    if (end >= sinfo.end)
++        end = sinfo.end - 1;
++    *end = '\0';
++    return end - str;
++}
++
++
++/****************************************************************
++ * Misc helpers
++ ****************************************************************/
++
++void
++hexdump(const void *d, int len)
++{
++    int count=0;
++    while (len > 0) {
++        if (count % 8 == 0) {
++            putc(&debuginfo, '\n');
++            puthex(&debuginfo, count*4, 8);
++            putc(&debuginfo, ':');
++        } else {
++            putc(&debuginfo, ' ');
++        }
++        puthex(&debuginfo, *(u32*)d, 8);
++        count++;
++        len-=4;
++        d+=4;
++    }
++    putc(&debuginfo, '\n');
++    debug_serial_flush();
++}
++
++static void
++dump_regs(struct bregs *regs)
++{
++    if (!regs) {
++        dprintf(1, "  NULL\n");
++        return;
++    }
++    dprintf(1, "   a=%08x  b=%08x  c=%08x  d=%08x ds=%04x es=%04x ss=%04x\n"
++            , regs->eax, regs->ebx, regs->ecx, regs->edx
++            , regs->ds, regs->es, GET_SEG(SS));
++    dprintf(1, "  si=%08x di=%08x bp=%08x sp=%08x cs=%04x ip=%04x  f=%04x\n"
++            , regs->esi, regs->edi, regs->ebp, (u32)&regs[1]
++            , regs->code.seg, regs->code.offset, regs->flags);
++}
++
++// Report entry to an Interrupt Service Routine (ISR).
++void
++__debug_isr(const char *fname)
++{
++    puts_cs(&debuginfo, fname);
++    putc(&debuginfo, '\n');
++    debug_serial_flush();
++}
++
++// Function called on handler startup.
++void
++__debug_enter(struct bregs *regs, const char *fname)
++{
++    dprintf(1, "enter %s:\n", fname);
++    dump_regs(regs);
++}
++
++// Send debugging output info.
++void
++__debug_stub(struct bregs *regs, int lineno, const char *fname)
++{
++    dprintf(1, "stub %s:%d:\n", fname, lineno);
++    dump_regs(regs);
++}
++
++// Report on an invalid parameter.
++void
++__warn_invalid(struct bregs *regs, int lineno, const char *fname)
++{
++    if (CONFIG_DEBUG_LEVEL >= DEBUG_invalid) {
++        dprintf(1, "invalid %s:%d:\n", fname, lineno);
++        dump_regs(regs);
++    }
++}
++
++// Report on an unimplemented feature.
++void
++__warn_unimplemented(struct bregs *regs, int lineno, const char *fname)
++{
++    if (CONFIG_DEBUG_LEVEL >= DEBUG_unimplemented) {
++        dprintf(1, "unimplemented %s:%d:\n", fname, lineno);
++        dump_regs(regs);
++    }
++}
++
++// Report a handler reporting an invalid parameter to the caller.
++void
++__set_invalid(struct bregs *regs, int lineno, const char *fname)
++{
++    __warn_invalid(regs, lineno, fname);
++    set_invalid_silent(regs);
++}
++
++// Report a call of an unimplemented function.
++void
++__set_unimplemented(struct bregs *regs, int lineno, const char *fname)
++{
++    __warn_unimplemented(regs, lineno, fname);
++    set_invalid_silent(regs);
++}
++
++// Report a handler reporting an invalid parameter code to the
++// caller.  Note, the lineno and return code are encoded in the same
++// parameter as gcc does a better job of scheduling function calls
++// when there are 3 or less parameters.
++void
++__set_code_invalid(struct bregs *regs, u32 linecode, const char *fname)
++{
++    u8 code = linecode;
++    u32 lineno = linecode >> 8;
++    __warn_invalid(regs, lineno, fname);
++    set_code_invalid_silent(regs, code);
++}
++
++// Report a call of an unimplemented function.
++void
++__set_code_unimplemented(struct bregs *regs, u32 linecode, const char *fname)
++{
++    u8 code = linecode;
++    u32 lineno = linecode >> 8;
++    __warn_unimplemented(regs, lineno, fname);
++    set_code_invalid_silent(regs, code);
++}
+--- x/roms/seabios/src/paravirt.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/paravirt.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,326 @@
++// Paravirtualization support.
++//
++// Copyright (C) 2009 Red Hat Inc.
++//
++// Authors:
++//  Gleb Natapov <gnatapov@redhat.com>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "config.h" // CONFIG_COREBOOT
++#include "util.h" // ntoh[ls]
++#include "ioport.h" // outw
++#include "paravirt.h" // qemu_cfg_port_probe
++#include "smbios.h" // struct smbios_structure_header
++
++int qemu_cfg_present;
++
++static void
++qemu_cfg_select(u16 f)
++{
++    outw(f, PORT_QEMU_CFG_CTL);
++}
++
++static void
++qemu_cfg_read(u8 *buf, int len)
++{
++    while (len--)
++        *(buf++) = inb(PORT_QEMU_CFG_DATA);
++}
++
++static void
++qemu_cfg_skip(int len)
++{
++    while (len--)
++        inb(PORT_QEMU_CFG_DATA);
++}
++
++static void
++qemu_cfg_read_entry(void *buf, int e, int len)
++{
++    qemu_cfg_select(e);
++    qemu_cfg_read(buf, len);
++}
++
++void qemu_cfg_port_probe(void)
++{
++    char *sig = "QEMU";
++    int i;
++
++    if (CONFIG_COREBOOT)
++        return;
++
++    qemu_cfg_present = 1;
++
++    qemu_cfg_select(QEMU_CFG_SIGNATURE);
++
++    for (i = 0; i < 4; i++)
++        if (inb(PORT_QEMU_CFG_DATA) != sig[i]) {
++            qemu_cfg_present = 0;
++            break;
++        }
++    dprintf(4, "qemu_cfg_present=%d\n", qemu_cfg_present);
++}
++
++void qemu_cfg_get_uuid(u8 *uuid)
++{
++    if (!qemu_cfg_present)
++        return;
++
++    qemu_cfg_read_entry(uuid, QEMU_CFG_UUID, 16);
++}
++
++int qemu_cfg_show_boot_menu(void)
++{
++    u16 v;
++    if (!qemu_cfg_present)
++        return 1;
++
++    qemu_cfg_read_entry(&v, QEMU_CFG_BOOT_MENU, sizeof(v));
++
++    return v;
++}
++
++int qemu_cfg_irq0_override(void)
++{
++    u8 v;
++
++    if (!qemu_cfg_present)
++        return 0;
++
++    qemu_cfg_read_entry(&v, QEMU_CFG_IRQ0_OVERRIDE, sizeof(v));
++
++    return v;
++}
++
++u16 qemu_cfg_acpi_additional_tables(void)
++{
++    u16 cnt;
++
++    if (!qemu_cfg_present)
++        return 0;
++
++    qemu_cfg_read_entry(&cnt, QEMU_CFG_ACPI_TABLES, sizeof(cnt));
++
++    return cnt;
++}
++
++u16 qemu_cfg_next_acpi_table_len(void)
++{
++    u16 len;
++
++    qemu_cfg_read((u8*)&len, sizeof(len));
++
++    return len;
++}
++
++void* qemu_cfg_next_acpi_table_load(void *addr, u16 len)
++{
++    qemu_cfg_read(addr, len);
++    return addr;
++}
++
++u16 qemu_cfg_smbios_entries(void)
++{
++    u16 cnt;
++
++    if (!qemu_cfg_present)
++        return 0;
++
++    qemu_cfg_read_entry(&cnt, QEMU_CFG_SMBIOS_ENTRIES, sizeof(cnt));
++
++    return cnt;
++}
++
++struct smbios_header {
++    u16 length;
++    u8 type;
++} PACKED;
++
++struct smbios_field {
++    struct smbios_header header;
++    u8 type;
++    u16 offset;
++    u8 data[];
++} PACKED;
++
++struct smbios_table {
++    struct smbios_header header;
++    u8 data[];
++} PACKED;
++
++#define SMBIOS_FIELD_ENTRY 0
++#define SMBIOS_TABLE_ENTRY 1
++
++size_t qemu_cfg_smbios_load_field(int type, size_t offset, void *addr)
++{
++    int i;
++
++    for (i = qemu_cfg_smbios_entries(); i > 0; i--) {
++        struct smbios_field field;
++
++        qemu_cfg_read((u8 *)&field, sizeof(struct smbios_header));
++        field.header.length -= sizeof(struct smbios_header);
++
++        if (field.header.type != SMBIOS_FIELD_ENTRY) {
++            qemu_cfg_skip(field.header.length);
++            continue;
++        }
++
++        qemu_cfg_read((u8 *)&field.type,
++                      sizeof(field) - sizeof(struct smbios_header));
++        field.header.length -= sizeof(field) - sizeof(struct smbios_header);
++
++        if (field.type != type || field.offset != offset) {
++            qemu_cfg_skip(field.header.length);
++            continue;
++        }
++
++        qemu_cfg_read(addr, field.header.length);
++        return (size_t)field.header.length;
++    }
++    return 0;
++}
++
++int qemu_cfg_smbios_load_external(int type, char **p, unsigned *nr_structs,
++                                  unsigned *max_struct_size, char *end)
++{
++    static u64 used_bitmap[4] = { 0 };
++    char *start = *p;
++    int i;
++
++    /* Check if we've already reported these tables */
++    if (used_bitmap[(type >> 6) & 0x3] & (1ULL << (type & 0x3f)))
++        return 1;
++
++    /* Don't introduce spurious end markers */
++    if (type == 127)
++        return 0;
++
++    for (i = qemu_cfg_smbios_entries(); i > 0; i--) {
++        struct smbios_table table;
++        struct smbios_structure_header *header = (void *)*p;
++        int string;
++
++        qemu_cfg_read((u8 *)&table, sizeof(struct smbios_header));
++        table.header.length -= sizeof(struct smbios_header);
++
++        if (table.header.type != SMBIOS_TABLE_ENTRY) {
++            qemu_cfg_skip(table.header.length);
++            continue;
++        }
++
++        if (end - *p < sizeof(struct smbios_structure_header)) {
++            dprintf(1, "No more memory for additional smbios tables\n");
++            break;
++        }
++
++        qemu_cfg_read((u8 *)*p, sizeof(struct smbios_structure_header));
++        table.header.length -= sizeof(struct smbios_structure_header);
++
++        if (header->type != type) {
++            qemu_cfg_skip(table.header.length);
++            continue;
++        }
++
++        *p += sizeof(struct smbios_structure_header);
++
++        /* Entries end with a double NULL char, if there's a string at
++         * the end (length is greater than formatted length), the string
++         * terminator provides the first NULL. */
++        string = header->length < table.header.length +
++                 sizeof(struct smbios_structure_header);
++
++        /* Read the rest and terminate the entry */
++        if (end - *p < table.header.length) {
++            dprintf(1, "No memory for smbios table %d\n", header->type);
++            *p -= sizeof(struct smbios_structure_header);
++            continue;
++        }
++        qemu_cfg_read((u8 *)*p, table.header.length);
++        *p += table.header.length;
++        *((u8*)*p) = 0;
++        (*p)++;
++        if (!string) {
++            *((u8*)*p) = 0;
++            (*p)++;
++        }
++
++        (*nr_structs)++;
++        if (*p - (char *)header > *max_struct_size)
++            *max_struct_size = *p - (char *)header;
++    }
++
++    if (start != *p) {
++        /* Mark that we've reported on this type */
++        used_bitmap[(type >> 6) & 0x3] |= (1ULL << (type & 0x3f));
++        return 1;
++    }
++
++    return 0;
++}
++
++int qemu_cfg_get_numa_nodes(void)
++{
++    u64 cnt;
++
++    qemu_cfg_read_entry(&cnt, QEMU_CFG_NUMA, sizeof(cnt));
++
++    return (int)cnt;
++}
++
++void qemu_cfg_get_numa_data(u64 *data, int n)
++{
++    int i;
++
++    for (i = 0; i < n; i++)
++        qemu_cfg_read((u8*)(data + i), sizeof(u64));
++}
++
++u16 qemu_cfg_get_max_cpus(void)
++{
++    u16 cnt;
++
++    if (!qemu_cfg_present)
++        return 0;
++
++    qemu_cfg_read_entry(&cnt, QEMU_CFG_MAX_CPUS, sizeof(cnt));
++
++    return cnt;
++}
++
++u16 qemu_cfg_first_file(QemuCfgFile *entry)
++{
++    memset(entry, 0, sizeof(*entry));
++    return qemu_cfg_next_file(entry);
++}
++
++u16 qemu_cfg_next_file(QemuCfgFile *entry)
++{
++    u16 last = ntohs(entry->select);
++    u32 e,count;
++
++    if (!qemu_cfg_present)
++        return 0;
++
++    qemu_cfg_read_entry(&count, QEMU_CFG_FILE_DIR, sizeof(count));
++    for (e = 0; e < ntohl(count); e++) {
++        qemu_cfg_read((void*)entry, sizeof(*entry));
++        if (ntohs(entry->select) > last) {
++            return 1;
++        }
++    }
++    return 0;
++}
++
++u32 qemu_cfg_read_file(QemuCfgFile *entry, void *dst, u32 maxlen)
++{
++    int len = ntohl(entry->size);
++
++    if (!qemu_cfg_present)
++        return 0;
++    if (len > maxlen)
++        return 0;
++    qemu_cfg_read_entry(dst, ntohs(entry->select), len);
++    return len;
++}
+--- x/roms/seabios/src/paravirt.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/paravirt.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,68 @@
++#ifndef __PV_H
++#define __PV_H
++
++#include "util.h"
++
++/* This CPUID returns the signature 'KVMKVMKVM' in ebx, ecx, and edx.  It
++ * should be used to determine that a VM is running under KVM.
++ */
++#define KVM_CPUID_SIGNATURE     0x40000000
++
++static inline int kvm_para_available(void)
++{
++    unsigned int eax, ebx, ecx, edx;
++    char signature[13];
++
++    cpuid(KVM_CPUID_SIGNATURE, &eax, &ebx, &ecx, &edx);
++    memcpy(signature + 0, &ebx, 4);
++    memcpy(signature + 4, &ecx, 4);
++    memcpy(signature + 8, &edx, 4);
++    signature[12] = 0;
++
++    if (strcmp(signature, "KVMKVMKVM") == 0)
++        return 1;
++
++    return 0;
++}
++
++#define QEMU_CFG_SIGNATURE		0x00
++#define QEMU_CFG_ID			0x01
++#define QEMU_CFG_UUID			0x02
++#define QEMU_CFG_NUMA			0x0d
++#define QEMU_CFG_BOOT_MENU		0x0e
++#define QEMU_CFG_MAX_CPUS		0x0f
++#define QEMU_CFG_FILE_DIR               0x19
++#define QEMU_CFG_ARCH_LOCAL		0x8000
++#define QEMU_CFG_ACPI_TABLES		(QEMU_CFG_ARCH_LOCAL + 0)
++#define QEMU_CFG_SMBIOS_ENTRIES		(QEMU_CFG_ARCH_LOCAL + 1)
++#define QEMU_CFG_IRQ0_OVERRIDE		(QEMU_CFG_ARCH_LOCAL + 2)
++
++extern int qemu_cfg_present;
++
++void qemu_cfg_port_probe(void);
++int qemu_cfg_show_boot_menu(void);
++void qemu_cfg_get_uuid(u8 *uuid);
++int qemu_cfg_irq0_override(void);
++u16 qemu_cfg_acpi_additional_tables(void);
++u16 qemu_cfg_next_acpi_table_len(void);
++void *qemu_cfg_next_acpi_table_load(void *addr, u16 len);
++u16 qemu_cfg_smbios_entries(void);
++size_t qemu_cfg_smbios_load_field(int type, size_t offset, void *addr);
++int qemu_cfg_smbios_load_external(int type, char **p, unsigned *nr_structs,
++                                  unsigned *max_struct_size, char *end);
++int qemu_cfg_get_numa_nodes(void);
++void qemu_cfg_get_numa_data(u64 *data, int n);
++u16 qemu_cfg_get_max_cpus(void);
++
++typedef struct QemuCfgFile {
++    u32  size;        /* file size */
++    u16  select;      /* write this to 0x510 to read it */
++    u16  reserved;
++    char name[56];
++} QemuCfgFile;
++
++u16 qemu_cfg_first_file(QemuCfgFile *entry);
++u16 qemu_cfg_next_file(QemuCfgFile *entry);
++u32 qemu_cfg_read_file(QemuCfgFile *entry, void *dst, u32 maxlen);
++
++#endif
+--- x/roms/seabios/src/pci.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/pci.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,185 @@
++// PCI config space access functions.
++//
++// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2002  MandrakeSoft S.A.
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "pci.h" // pci_config_writel
++#include "ioport.h" // outl
++#include "util.h" // dprintf
++#include "config.h" // CONFIG_*
++#include "pci_regs.h" // PCI_VENDOR_ID
++#include "pci_ids.h" // PCI_CLASS_DISPLAY_VGA
++
++void pci_config_writel(u16 bdf, u32 addr, u32 val)
++{
++    outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
++    outl(val, PORT_PCI_DATA);
++}
++
++void pci_config_writew(u16 bdf, u32 addr, u16 val)
++{
++    outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
++    outw(val, PORT_PCI_DATA + (addr & 2));
++}
++
++void pci_config_writeb(u16 bdf, u32 addr, u8 val)
++{
++    outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
++    outb(val, PORT_PCI_DATA + (addr & 3));
++}
++
++u32 pci_config_readl(u16 bdf, u32 addr)
++{
++    outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
++    return inl(PORT_PCI_DATA);
++}
++
++u16 pci_config_readw(u16 bdf, u32 addr)
++{
++    outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
++    return inw(PORT_PCI_DATA + (addr & 2));
++}
++
++u8 pci_config_readb(u16 bdf, u32 addr)
++{
++    outl(0x80000000 | (bdf << 8) | (addr & 0xfc), PORT_PCI_CMD);
++    return inb(PORT_PCI_DATA + (addr & 3));
++}
++
++void
++pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on)
++{
++    u16 val = pci_config_readw(bdf, addr);
++    val = (val & ~off) | on;
++    pci_config_writew(bdf, addr, val);
++}
++
++// Helper function for foreachpci() macro - return next device
++int
++pci_next(int bdf, int *pmax)
++{
++    if (pci_bdf_to_fn(bdf) == 1
++        && (pci_config_readb(bdf-1, PCI_HEADER_TYPE) & 0x80) == 0)
++        // Last found device wasn't a multi-function device - skip to
++        // the next device.
++        bdf += 7;
++
++    int max = *pmax;
++    for (;;) {
++        if (bdf >= max) {
++            if (CONFIG_PCI_ROOT1 && bdf <= (CONFIG_PCI_ROOT1 << 8))
++                bdf = CONFIG_PCI_ROOT1 << 8;
++            else if (CONFIG_PCI_ROOT2 && bdf <= (CONFIG_PCI_ROOT2 << 8))
++                bdf = CONFIG_PCI_ROOT2 << 8;
++            else
++            	return -1;
++            *pmax = max = bdf + 0x0100;
++        }
++
++        u16 v = pci_config_readw(bdf, PCI_VENDOR_ID);
++        if (v != 0x0000 && v != 0xffff)
++            // Device is present.
++            break;
++
++        if (pci_bdf_to_fn(bdf) == 0)
++            bdf += 8;
++        else
++            bdf += 1;
++    }
++
++    // Check if found device is a bridge.
++    u32 v = pci_config_readb(bdf, PCI_HEADER_TYPE);
++    v &= 0x7f;
++    if (v == PCI_HEADER_TYPE_BRIDGE || v == PCI_HEADER_TYPE_CARDBUS) {
++        v = pci_config_readl(bdf, PCI_PRIMARY_BUS);
++        int newmax = (v & 0xff00) + 0x0100;
++        if (newmax > max)
++            *pmax = newmax;
++    }
++
++    return bdf;
++}
++
++// Find a vga device with legacy address decoding enabled.
++int
++pci_find_vga(void)
++{
++    int bdf = 0x0000, max = 0x0100;
++    for (;;) {
++        if (bdf >= max) {
++            if (CONFIG_PCI_ROOT1 && bdf <= (CONFIG_PCI_ROOT1 << 8))
++                bdf = CONFIG_PCI_ROOT1 << 8;
++            else if (CONFIG_PCI_ROOT2 && bdf <= (CONFIG_PCI_ROOT2 << 8))
++                bdf = CONFIG_PCI_ROOT2 << 8;
++            else
++            	return -1;
++            max = bdf + 0x0100;
++        }
++
++        u16 cls = pci_config_readw(bdf, PCI_CLASS_DEVICE);
++        if (cls == 0x0000 || cls == 0xffff) {
++            // Device not present.
++            if (pci_bdf_to_fn(bdf) == 0)
++                bdf += 8;
++            else
++                bdf += 1;
++            continue;
++        }
++        if (cls == PCI_CLASS_DISPLAY_VGA) {
++            u16 cmd = pci_config_readw(bdf, PCI_COMMAND);
++            if (cmd & PCI_COMMAND_IO && cmd & PCI_COMMAND_MEMORY)
++                // Found active vga card
++                return bdf;
++        }
++
++        // Check if device is a bridge.
++        u8 hdr = pci_config_readb(bdf, PCI_HEADER_TYPE);
++        u8 ht = hdr & 0x7f;
++        if (ht == PCI_HEADER_TYPE_BRIDGE || ht == PCI_HEADER_TYPE_CARDBUS) {
++            u32 ctrl = pci_config_readb(bdf, PCI_BRIDGE_CONTROL);
++            if (ctrl & PCI_BRIDGE_CTL_VGA) {
++                // Found a VGA enabled bridge.
++                u32 pbus = pci_config_readl(bdf, PCI_PRIMARY_BUS);
++                bdf = (pbus & 0xff00);
++                max = bdf + 0x100;
++                continue;
++            }
++        }
++
++        if (pci_bdf_to_fn(bdf) == 0 && (hdr & 0x80) == 0)
++            // Last found device wasn't a multi-function device - skip to
++            // the next device.
++            bdf += 8;
++        else
++            bdf += 1;
++    }
++}
++
++// Search for a device with the specified vendor and device ids.
++int
++pci_find_device(u16 vendid, u16 devid)
++{
++    u32 id = (devid << 16) | vendid;
++    int bdf, max;
++    foreachpci(bdf, max) {
++        u32 v = pci_config_readl(bdf, PCI_VENDOR_ID);
++        if (v == id)
++            return bdf;
++    }
++    return -1;
++}
++
++// Search for a device with the specified class id.
++int
++pci_find_class(u16 classid)
++{
++    int bdf, max;
++    foreachpci(bdf, max) {
++        u16 v = pci_config_readw(bdf, PCI_CLASS_DEVICE);
++        if (v == classid)
++            return bdf;
++    }
++    return -1;
++}
+--- x/roms/seabios/src/pci.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/pci.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,83 @@
++#ifndef __PCI_H
++#define __PCI_H
++
++#include "types.h" // u32
++
++static inline u8 pci_bdf_to_bus(u16 bdf) {
++    return bdf >> 8;
++}
++static inline u8 pci_bdf_to_devfn(u16 bdf) {
++    return bdf & 0xff;
++}
++static inline u16 pci_bdf_to_busdev(u16 bdf) {
++    return bdf & ~0x07;
++}
++static inline u8 pci_bdf_to_dev(u16 bdf) {
++    return (bdf >> 3) & 0x1f;
++}
++static inline u8 pci_bdf_to_fn(u16 bdf) {
++    return bdf & 0x07;
++}
++static inline u16 pci_to_bdf(int bus, int dev, int fn) {
++    return (bus<<8) | (dev<<3) | fn;
++}
++
++void pci_config_writel(u16 bdf, u32 addr, u32 val);
++void pci_config_writew(u16 bdf, u32 addr, u16 val);
++void pci_config_writeb(u16 bdf, u32 addr, u8 val);
++u32 pci_config_readl(u16 bdf, u32 addr);
++u16 pci_config_readw(u16 bdf, u32 addr);
++u8 pci_config_readb(u16 bdf, u32 addr);
++void pci_config_maskw(u16 bdf, u32 addr, u16 off, u16 on);
++
++int pci_find_vga(void);
++int pci_find_device(u16 vendid, u16 devid);
++int pci_find_class(u16 classid);
++
++int pci_next(int bdf, int *pmax);
++#define foreachpci(BDF, MAX)                    \
++    for (MAX=0x0100, BDF=pci_next(0, &MAX)      \
++         ; BDF >= 0                             \
++         ; BDF=pci_next(BDF+1, &MAX))
++
++// pirtable.c
++void create_pirtable(void);
++
++
++/****************************************************************
++ * PIR table
++ ****************************************************************/
++
++extern u16 PirOffset;
++
++struct link_info {
++    u8 link;
++    u16 bitmap;
++} PACKED;
++
++struct pir_slot {
++    u8 bus;
++    u8 dev;
++    struct link_info links[4];
++    u8 slot_nr;
++    u8 reserved;
++} PACKED;
++
++struct pir_header {
++    u32 signature;
++    u16 version;
++    u16 size;
++    u8 router_bus;
++    u8 router_devfunc;
++    u16 exclusive_irqs;
++    u32 compatible_devid;
++    u32 miniport_data;
++    u8 reserved[11];
++    u8 checksum;
++    struct pir_slot slots[0];
++} PACKED;
++
++#define PIR_SIGNATURE 0x52495024 // $PIR
++
++
++#endif
+--- x/roms/seabios/src/pci_ids.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/pci_ids.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,2607 @@
++/*
++ *	PCI Class, Vendor and Device IDs
++ *
++ *	Please keep sorted.
++ */
++
++/* Device classes and subclasses */
++
++#define PCI_CLASS_NOT_DEFINED		0x0000
++#define PCI_CLASS_NOT_DEFINED_VGA	0x0001
++
++#define PCI_BASE_CLASS_STORAGE		0x01
++#define PCI_CLASS_STORAGE_SCSI		0x0100
++#define PCI_CLASS_STORAGE_IDE		0x0101
++#define PCI_CLASS_STORAGE_FLOPPY	0x0102
++#define PCI_CLASS_STORAGE_IPI		0x0103
++#define PCI_CLASS_STORAGE_RAID		0x0104
++#define PCI_CLASS_STORAGE_SATA		0x0106
++#define PCI_CLASS_STORAGE_SATA_AHCI	0x010601
++#define PCI_CLASS_STORAGE_SAS		0x0107
++#define PCI_CLASS_STORAGE_OTHER		0x0180
++
++#define PCI_BASE_CLASS_NETWORK		0x02
++#define PCI_CLASS_NETWORK_ETHERNET	0x0200
++#define PCI_CLASS_NETWORK_TOKEN_RING	0x0201
++#define PCI_CLASS_NETWORK_FDDI		0x0202
++#define PCI_CLASS_NETWORK_ATM		0x0203
++#define PCI_CLASS_NETWORK_OTHER		0x0280
++
++#define PCI_BASE_CLASS_DISPLAY		0x03
++#define PCI_CLASS_DISPLAY_VGA		0x0300
++#define PCI_CLASS_DISPLAY_XGA		0x0301
++#define PCI_CLASS_DISPLAY_3D		0x0302
++#define PCI_CLASS_DISPLAY_OTHER		0x0380
++
++#define PCI_BASE_CLASS_MULTIMEDIA	0x04
++#define PCI_CLASS_MULTIMEDIA_VIDEO	0x0400
++#define PCI_CLASS_MULTIMEDIA_AUDIO	0x0401
++#define PCI_CLASS_MULTIMEDIA_PHONE	0x0402
++#define PCI_CLASS_MULTIMEDIA_OTHER	0x0480
++
++#define PCI_BASE_CLASS_MEMORY		0x05
++#define PCI_CLASS_MEMORY_RAM		0x0500
++#define PCI_CLASS_MEMORY_FLASH		0x0501
++#define PCI_CLASS_MEMORY_OTHER		0x0580
++
++#define PCI_BASE_CLASS_BRIDGE		0x06
++#define PCI_CLASS_BRIDGE_HOST		0x0600
++#define PCI_CLASS_BRIDGE_ISA		0x0601
++#define PCI_CLASS_BRIDGE_EISA		0x0602
++#define PCI_CLASS_BRIDGE_MC		0x0603
++#define PCI_CLASS_BRIDGE_PCI		0x0604
++#define PCI_CLASS_BRIDGE_PCMCIA		0x0605
++#define PCI_CLASS_BRIDGE_NUBUS		0x0606
++#define PCI_CLASS_BRIDGE_CARDBUS	0x0607
++#define PCI_CLASS_BRIDGE_RACEWAY	0x0608
++#define PCI_CLASS_BRIDGE_OTHER		0x0680
++
++#define PCI_BASE_CLASS_COMMUNICATION	0x07
++#define PCI_CLASS_COMMUNICATION_SERIAL	0x0700
++#define PCI_CLASS_COMMUNICATION_PARALLEL 0x0701
++#define PCI_CLASS_COMMUNICATION_MULTISERIAL 0x0702
++#define PCI_CLASS_COMMUNICATION_MODEM	0x0703
++#define PCI_CLASS_COMMUNICATION_OTHER	0x0780
++
++#define PCI_BASE_CLASS_SYSTEM		0x08
++#define PCI_CLASS_SYSTEM_PIC		0x0800
++#define PCI_CLASS_SYSTEM_PIC_IOAPIC	0x080010
++#define PCI_CLASS_SYSTEM_PIC_IOXAPIC	0x080020
++#define PCI_CLASS_SYSTEM_DMA		0x0801
++#define PCI_CLASS_SYSTEM_TIMER		0x0802
++#define PCI_CLASS_SYSTEM_RTC		0x0803
++#define PCI_CLASS_SYSTEM_PCI_HOTPLUG	0x0804
++#define PCI_CLASS_SYSTEM_SDHCI		0x0805
++#define PCI_CLASS_SYSTEM_OTHER		0x0880
++
++#define PCI_BASE_CLASS_INPUT		0x09
++#define PCI_CLASS_INPUT_KEYBOARD	0x0900
++#define PCI_CLASS_INPUT_PEN		0x0901
++#define PCI_CLASS_INPUT_MOUSE		0x0902
++#define PCI_CLASS_INPUT_SCANNER		0x0903
++#define PCI_CLASS_INPUT_GAMEPORT	0x0904
++#define PCI_CLASS_INPUT_OTHER		0x0980
++
++#define PCI_BASE_CLASS_DOCKING		0x0a
++#define PCI_CLASS_DOCKING_GENERIC	0x0a00
++#define PCI_CLASS_DOCKING_OTHER		0x0a80
++
++#define PCI_BASE_CLASS_PROCESSOR	0x0b
++#define PCI_CLASS_PROCESSOR_386		0x0b00
++#define PCI_CLASS_PROCESSOR_486		0x0b01
++#define PCI_CLASS_PROCESSOR_PENTIUM	0x0b02
++#define PCI_CLASS_PROCESSOR_ALPHA	0x0b10
++#define PCI_CLASS_PROCESSOR_POWERPC	0x0b20
++#define PCI_CLASS_PROCESSOR_MIPS	0x0b30
++#define PCI_CLASS_PROCESSOR_CO		0x0b40
++
++#define PCI_BASE_CLASS_SERIAL		0x0c
++#define PCI_CLASS_SERIAL_FIREWIRE	0x0c00
++#define PCI_CLASS_SERIAL_FIREWIRE_OHCI	0x0c0010
++#define PCI_CLASS_SERIAL_ACCESS		0x0c01
++#define PCI_CLASS_SERIAL_SSA		0x0c02
++#define PCI_CLASS_SERIAL_USB		0x0c03
++#define PCI_CLASS_SERIAL_USB_UHCI	0x0c0300
++#define PCI_CLASS_SERIAL_USB_OHCI	0x0c0310
++#define PCI_CLASS_SERIAL_USB_EHCI	0x0c0320
++#define PCI_CLASS_SERIAL_FIBER		0x0c04
++#define PCI_CLASS_SERIAL_SMBUS		0x0c05
++
++#define PCI_BASE_CLASS_WIRELESS			0x0d
++#define PCI_CLASS_WIRELESS_RF_CONTROLLER	0x0d10
++#define PCI_CLASS_WIRELESS_WHCI			0x0d1010
++
++#define PCI_BASE_CLASS_INTELLIGENT	0x0e
++#define PCI_CLASS_INTELLIGENT_I2O	0x0e00
++
++#define PCI_BASE_CLASS_SATELLITE	0x0f
++#define PCI_CLASS_SATELLITE_TV		0x0f00
++#define PCI_CLASS_SATELLITE_AUDIO	0x0f01
++#define PCI_CLASS_SATELLITE_VOICE	0x0f03
++#define PCI_CLASS_SATELLITE_DATA	0x0f04
++
++#define PCI_BASE_CLASS_CRYPT		0x10
++#define PCI_CLASS_CRYPT_NETWORK		0x1000
++#define PCI_CLASS_CRYPT_ENTERTAINMENT	0x1001
++#define PCI_CLASS_CRYPT_OTHER		0x1080
++
++#define PCI_BASE_CLASS_SIGNAL_PROCESSING 0x11
++#define PCI_CLASS_SP_DPIO		0x1100
++#define PCI_CLASS_SP_OTHER		0x1180
++
++#define PCI_CLASS_OTHERS		0xff
++
++/* Vendors and devices.  Sort key: vendor first, device next. */
++
++#define PCI_VENDOR_ID_TTTECH		0x0357
++#define PCI_DEVICE_ID_TTTECH_MC322	0x000a
++
++#define PCI_VENDOR_ID_DYNALINK		0x0675
++#define PCI_DEVICE_ID_DYNALINK_IS64PH	0x1702
++
++#define PCI_VENDOR_ID_BERKOM			0x0871
++#define PCI_DEVICE_ID_BERKOM_A1T		0xffa1
++#define PCI_DEVICE_ID_BERKOM_T_CONCEPT		0xffa2
++#define PCI_DEVICE_ID_BERKOM_A4T		0xffa4
++#define PCI_DEVICE_ID_BERKOM_SCITEL_QUADRO	0xffa8
++
++#define PCI_VENDOR_ID_COMPAQ		0x0e11
++#define PCI_DEVICE_ID_COMPAQ_TOKENRING	0x0508
++#define PCI_DEVICE_ID_COMPAQ_TACHYON	0xa0fc
++#define PCI_DEVICE_ID_COMPAQ_SMART2P	0xae10
++#define PCI_DEVICE_ID_COMPAQ_NETEL100	0xae32
++#define PCI_DEVICE_ID_COMPAQ_NETEL10	0xae34
++#define PCI_DEVICE_ID_COMPAQ_TRIFLEX_IDE 0xae33
++#define PCI_DEVICE_ID_COMPAQ_NETFLEX3I	0xae35
++#define PCI_DEVICE_ID_COMPAQ_NETEL100D	0xae40
++#define PCI_DEVICE_ID_COMPAQ_NETEL100PI	0xae43
++#define PCI_DEVICE_ID_COMPAQ_NETEL100I	0xb011
++#define PCI_DEVICE_ID_COMPAQ_CISS	0xb060
++#define PCI_DEVICE_ID_COMPAQ_CISSB	0xb178
++#define PCI_DEVICE_ID_COMPAQ_CISSC	0x46
++#define PCI_DEVICE_ID_COMPAQ_THUNDER	0xf130
++#define PCI_DEVICE_ID_COMPAQ_NETFLEX3B	0xf150
++
++#define PCI_VENDOR_ID_NCR		0x1000
++#define PCI_VENDOR_ID_LSI_LOGIC		0x1000
++#define PCI_DEVICE_ID_NCR_53C810	0x0001
++#define PCI_DEVICE_ID_NCR_53C820	0x0002
++#define PCI_DEVICE_ID_NCR_53C825	0x0003
++#define PCI_DEVICE_ID_NCR_53C815	0x0004
++#define PCI_DEVICE_ID_LSI_53C810AP	0x0005
++#define PCI_DEVICE_ID_NCR_53C860	0x0006
++#define PCI_DEVICE_ID_LSI_53C1510	0x000a
++#define PCI_DEVICE_ID_NCR_53C896	0x000b
++#define PCI_DEVICE_ID_NCR_53C895	0x000c
++#define PCI_DEVICE_ID_NCR_53C885	0x000d
++#define PCI_DEVICE_ID_NCR_53C875	0x000f
++#define PCI_DEVICE_ID_NCR_53C1510	0x0010
++#define PCI_DEVICE_ID_LSI_53C895A	0x0012
++#define PCI_DEVICE_ID_LSI_53C875A	0x0013
++#define PCI_DEVICE_ID_LSI_53C1010_33	0x0020
++#define PCI_DEVICE_ID_LSI_53C1010_66	0x0021
++#define PCI_DEVICE_ID_LSI_53C1030	0x0030
++#define PCI_DEVICE_ID_LSI_1030_53C1035	0x0032
++#define PCI_DEVICE_ID_LSI_53C1035	0x0040
++#define PCI_DEVICE_ID_NCR_53C875J	0x008f
++#define PCI_DEVICE_ID_LSI_FC909		0x0621
++#define PCI_DEVICE_ID_LSI_FC929		0x0622
++#define PCI_DEVICE_ID_LSI_FC929_LAN	0x0623
++#define PCI_DEVICE_ID_LSI_FC919		0x0624
++#define PCI_DEVICE_ID_LSI_FC919_LAN	0x0625
++#define PCI_DEVICE_ID_LSI_FC929X	0x0626
++#define PCI_DEVICE_ID_LSI_FC939X	0x0642
++#define PCI_DEVICE_ID_LSI_FC949X	0x0640
++#define PCI_DEVICE_ID_LSI_FC949ES	0x0646
++#define PCI_DEVICE_ID_LSI_FC919X	0x0628
++#define PCI_DEVICE_ID_NCR_YELLOWFIN	0x0701
++#define PCI_DEVICE_ID_LSI_61C102	0x0901
++#define PCI_DEVICE_ID_LSI_63C815	0x1000
++#define PCI_DEVICE_ID_LSI_SAS1064	0x0050
++#define PCI_DEVICE_ID_LSI_SAS1064R	0x0411
++#define PCI_DEVICE_ID_LSI_SAS1066	0x005E
++#define PCI_DEVICE_ID_LSI_SAS1068	0x0054
++#define PCI_DEVICE_ID_LSI_SAS1064A	0x005C
++#define PCI_DEVICE_ID_LSI_SAS1064E	0x0056
++#define PCI_DEVICE_ID_LSI_SAS1066E	0x005A
++#define PCI_DEVICE_ID_LSI_SAS1068E	0x0058
++#define PCI_DEVICE_ID_LSI_SAS1078	0x0060
++
++#define PCI_VENDOR_ID_ATI		0x1002
++/* Mach64 */
++#define PCI_DEVICE_ID_ATI_68800		0x4158
++#define PCI_DEVICE_ID_ATI_215CT222	0x4354
++#define PCI_DEVICE_ID_ATI_210888CX	0x4358
++#define PCI_DEVICE_ID_ATI_215ET222	0x4554
++/* Mach64 / Rage */
++#define PCI_DEVICE_ID_ATI_215GB		0x4742
++#define PCI_DEVICE_ID_ATI_215GD		0x4744
++#define PCI_DEVICE_ID_ATI_215GI		0x4749
++#define PCI_DEVICE_ID_ATI_215GP		0x4750
++#define PCI_DEVICE_ID_ATI_215GQ		0x4751
++#define PCI_DEVICE_ID_ATI_215XL		0x4752
++#define PCI_DEVICE_ID_ATI_215GT		0x4754
++#define PCI_DEVICE_ID_ATI_215GTB	0x4755
++#define PCI_DEVICE_ID_ATI_215_IV	0x4756
++#define PCI_DEVICE_ID_ATI_215_IW	0x4757
++#define PCI_DEVICE_ID_ATI_215_IZ	0x475A
++#define PCI_DEVICE_ID_ATI_210888GX	0x4758
++#define PCI_DEVICE_ID_ATI_215_LB	0x4c42
++#define PCI_DEVICE_ID_ATI_215_LD	0x4c44
++#define PCI_DEVICE_ID_ATI_215_LG	0x4c47
++#define PCI_DEVICE_ID_ATI_215_LI	0x4c49
++#define PCI_DEVICE_ID_ATI_215_LM	0x4c4D
++#define PCI_DEVICE_ID_ATI_215_LN	0x4c4E
++#define PCI_DEVICE_ID_ATI_215_LR	0x4c52
++#define PCI_DEVICE_ID_ATI_215_LS	0x4c53
++#define PCI_DEVICE_ID_ATI_264_LT	0x4c54
++/* Mach64 VT */
++#define PCI_DEVICE_ID_ATI_264VT		0x5654
++#define PCI_DEVICE_ID_ATI_264VU		0x5655
++#define PCI_DEVICE_ID_ATI_264VV		0x5656
++/* Rage128 GL */
++#define PCI_DEVICE_ID_ATI_RAGE128_RE	0x5245
++#define PCI_DEVICE_ID_ATI_RAGE128_RF	0x5246
++#define PCI_DEVICE_ID_ATI_RAGE128_RG	0x5247
++/* Rage128 VR */
++#define PCI_DEVICE_ID_ATI_RAGE128_RK	0x524b
++#define PCI_DEVICE_ID_ATI_RAGE128_RL	0x524c
++#define PCI_DEVICE_ID_ATI_RAGE128_SE	0x5345
++#define PCI_DEVICE_ID_ATI_RAGE128_SF	0x5346
++#define PCI_DEVICE_ID_ATI_RAGE128_SG	0x5347
++#define PCI_DEVICE_ID_ATI_RAGE128_SH	0x5348
++#define PCI_DEVICE_ID_ATI_RAGE128_SK	0x534b
++#define PCI_DEVICE_ID_ATI_RAGE128_SL	0x534c
++#define PCI_DEVICE_ID_ATI_RAGE128_SM	0x534d
++#define PCI_DEVICE_ID_ATI_RAGE128_SN	0x534e
++/* Rage128 Ultra */
++#define PCI_DEVICE_ID_ATI_RAGE128_TF	0x5446
++#define PCI_DEVICE_ID_ATI_RAGE128_TL	0x544c
++#define PCI_DEVICE_ID_ATI_RAGE128_TR	0x5452
++#define PCI_DEVICE_ID_ATI_RAGE128_TS	0x5453
++#define PCI_DEVICE_ID_ATI_RAGE128_TT	0x5454
++#define PCI_DEVICE_ID_ATI_RAGE128_TU	0x5455
++/* Rage128 M3 */
++#define PCI_DEVICE_ID_ATI_RAGE128_LE	0x4c45
++#define PCI_DEVICE_ID_ATI_RAGE128_LF	0x4c46
++/* Rage128 M4 */
++#define PCI_DEVICE_ID_ATI_RAGE128_MF    0x4d46
++#define PCI_DEVICE_ID_ATI_RAGE128_ML    0x4d4c
++/* Rage128 Pro GL */
++#define PCI_DEVICE_ID_ATI_RAGE128_PA	0x5041
++#define PCI_DEVICE_ID_ATI_RAGE128_PB	0x5042
++#define PCI_DEVICE_ID_ATI_RAGE128_PC	0x5043
++#define PCI_DEVICE_ID_ATI_RAGE128_PD	0x5044
++#define PCI_DEVICE_ID_ATI_RAGE128_PE	0x5045
++#define PCI_DEVICE_ID_ATI_RAGE128_PF	0x5046
++/* Rage128 Pro VR */
++#define PCI_DEVICE_ID_ATI_RAGE128_PG	0x5047
++#define PCI_DEVICE_ID_ATI_RAGE128_PH	0x5048
++#define PCI_DEVICE_ID_ATI_RAGE128_PI	0x5049
++#define PCI_DEVICE_ID_ATI_RAGE128_PJ	0x504A
++#define PCI_DEVICE_ID_ATI_RAGE128_PK	0x504B
++#define PCI_DEVICE_ID_ATI_RAGE128_PL	0x504C
++#define PCI_DEVICE_ID_ATI_RAGE128_PM	0x504D
++#define PCI_DEVICE_ID_ATI_RAGE128_PN	0x504E
++#define PCI_DEVICE_ID_ATI_RAGE128_PO	0x504F
++#define PCI_DEVICE_ID_ATI_RAGE128_PP	0x5050
++#define PCI_DEVICE_ID_ATI_RAGE128_PQ	0x5051
++#define PCI_DEVICE_ID_ATI_RAGE128_PR	0x5052
++#define PCI_DEVICE_ID_ATI_RAGE128_PS	0x5053
++#define PCI_DEVICE_ID_ATI_RAGE128_PT	0x5054
++#define PCI_DEVICE_ID_ATI_RAGE128_PU	0x5055
++#define PCI_DEVICE_ID_ATI_RAGE128_PV	0x5056
++#define PCI_DEVICE_ID_ATI_RAGE128_PW	0x5057
++#define PCI_DEVICE_ID_ATI_RAGE128_PX	0x5058
++/* Rage128 M4 */
++/* Radeon R100 */
++#define PCI_DEVICE_ID_ATI_RADEON_QD	0x5144
++#define PCI_DEVICE_ID_ATI_RADEON_QE	0x5145
++#define PCI_DEVICE_ID_ATI_RADEON_QF	0x5146
++#define PCI_DEVICE_ID_ATI_RADEON_QG	0x5147
++/* Radeon RV100 (VE) */
++#define PCI_DEVICE_ID_ATI_RADEON_QY	0x5159
++#define PCI_DEVICE_ID_ATI_RADEON_QZ	0x515a
++/* Radeon R200 (8500) */
++#define PCI_DEVICE_ID_ATI_RADEON_QL	0x514c
++#define PCI_DEVICE_ID_ATI_RADEON_QN	0x514e
++#define PCI_DEVICE_ID_ATI_RADEON_QO	0x514f
++#define PCI_DEVICE_ID_ATI_RADEON_Ql	0x516c
++#define PCI_DEVICE_ID_ATI_RADEON_BB	0x4242
++/* Radeon R200 (9100) */
++#define PCI_DEVICE_ID_ATI_RADEON_QM	0x514d
++/* Radeon RV200 (7500) */
++#define PCI_DEVICE_ID_ATI_RADEON_QW	0x5157
++#define PCI_DEVICE_ID_ATI_RADEON_QX	0x5158
++/* Radeon NV-100 */
++/* Radeon RV250 (9000) */
++#define PCI_DEVICE_ID_ATI_RADEON_Id	0x4964
++#define PCI_DEVICE_ID_ATI_RADEON_Ie	0x4965
++#define PCI_DEVICE_ID_ATI_RADEON_If	0x4966
++#define PCI_DEVICE_ID_ATI_RADEON_Ig	0x4967
++/* Radeon RV280 (9200) */
++#define PCI_DEVICE_ID_ATI_RADEON_Ya	0x5961
++#define PCI_DEVICE_ID_ATI_RADEON_Yd	0x5964
++/* Radeon R300 (9500) */
++/* Radeon R300 (9700) */
++#define PCI_DEVICE_ID_ATI_RADEON_ND	0x4e44
++#define PCI_DEVICE_ID_ATI_RADEON_NE	0x4e45
++#define PCI_DEVICE_ID_ATI_RADEON_NF	0x4e46
++#define PCI_DEVICE_ID_ATI_RADEON_NG	0x4e47
++/* Radeon R350 (9800) */
++/* Radeon RV350 (9600) */
++/* Radeon M6 */
++#define PCI_DEVICE_ID_ATI_RADEON_LY	0x4c59
++#define PCI_DEVICE_ID_ATI_RADEON_LZ	0x4c5a
++/* Radeon M7 */
++#define PCI_DEVICE_ID_ATI_RADEON_LW	0x4c57
++#define PCI_DEVICE_ID_ATI_RADEON_LX	0x4c58
++/* Radeon M9 */
++#define PCI_DEVICE_ID_ATI_RADEON_Ld	0x4c64
++#define PCI_DEVICE_ID_ATI_RADEON_Le	0x4c65
++#define PCI_DEVICE_ID_ATI_RADEON_Lf	0x4c66
++#define PCI_DEVICE_ID_ATI_RADEON_Lg	0x4c67
++/* Radeon */
++/* RadeonIGP */
++#define PCI_DEVICE_ID_ATI_RS100		0xcab0
++#define PCI_DEVICE_ID_ATI_RS200		0xcab2
++#define PCI_DEVICE_ID_ATI_RS200_B	0xcbb2
++#define PCI_DEVICE_ID_ATI_RS250		0xcab3
++#define PCI_DEVICE_ID_ATI_RS300_100	0x5830
++#define PCI_DEVICE_ID_ATI_RS300_133	0x5831
++#define PCI_DEVICE_ID_ATI_RS300_166	0x5832
++#define PCI_DEVICE_ID_ATI_RS300_200	0x5833
++#define PCI_DEVICE_ID_ATI_RS350_100     0x7830
++#define PCI_DEVICE_ID_ATI_RS350_133     0x7831
++#define PCI_DEVICE_ID_ATI_RS350_166     0x7832
++#define PCI_DEVICE_ID_ATI_RS350_200     0x7833
++#define PCI_DEVICE_ID_ATI_RS400_100     0x5a30
++#define PCI_DEVICE_ID_ATI_RS400_133     0x5a31
++#define PCI_DEVICE_ID_ATI_RS400_166     0x5a32
++#define PCI_DEVICE_ID_ATI_RS400_200     0x5a33
++#define PCI_DEVICE_ID_ATI_RS480         0x5950
++/* ATI IXP Chipset */
++#define PCI_DEVICE_ID_ATI_IXP200_IDE	0x4349
++#define PCI_DEVICE_ID_ATI_IXP200_SMBUS	0x4353
++#define PCI_DEVICE_ID_ATI_IXP300_SMBUS	0x4363
++#define PCI_DEVICE_ID_ATI_IXP300_IDE	0x4369
++#define PCI_DEVICE_ID_ATI_IXP300_SATA   0x436e
++#define PCI_DEVICE_ID_ATI_IXP400_SMBUS	0x4372
++#define PCI_DEVICE_ID_ATI_IXP400_IDE	0x4376
++#define PCI_DEVICE_ID_ATI_IXP400_SATA   0x4379
++#define PCI_DEVICE_ID_ATI_IXP400_SATA2	0x437a
++#define PCI_DEVICE_ID_ATI_IXP600_SATA	0x4380
++#define PCI_DEVICE_ID_ATI_SBX00_SMBUS	0x4385
++#define PCI_DEVICE_ID_ATI_IXP600_IDE	0x438c
++#define PCI_DEVICE_ID_ATI_IXP700_SATA	0x4390
++#define PCI_DEVICE_ID_ATI_IXP700_IDE	0x439c
++
++#define PCI_VENDOR_ID_VLSI		0x1004
++#define PCI_DEVICE_ID_VLSI_82C592	0x0005
++#define PCI_DEVICE_ID_VLSI_82C593	0x0006
++#define PCI_DEVICE_ID_VLSI_82C594	0x0007
++#define PCI_DEVICE_ID_VLSI_82C597	0x0009
++#define PCI_DEVICE_ID_VLSI_82C541	0x000c
++#define PCI_DEVICE_ID_VLSI_82C543	0x000d
++#define PCI_DEVICE_ID_VLSI_82C532	0x0101
++#define PCI_DEVICE_ID_VLSI_82C534	0x0102
++#define PCI_DEVICE_ID_VLSI_82C535	0x0104
++#define PCI_DEVICE_ID_VLSI_82C147	0x0105
++#define PCI_DEVICE_ID_VLSI_VAS96011	0x0702
++
++#define PCI_VENDOR_ID_ADL		0x1005
++#define PCI_DEVICE_ID_ADL_2301		0x2301
++
++#define PCI_VENDOR_ID_NS		0x100b
++#define PCI_DEVICE_ID_NS_87415		0x0002
++#define PCI_DEVICE_ID_NS_87560_LIO	0x000e
++#define PCI_DEVICE_ID_NS_87560_USB	0x0012
++#define PCI_DEVICE_ID_NS_83815		0x0020
++#define PCI_DEVICE_ID_NS_83820		0x0022
++#define PCI_DEVICE_ID_NS_CS5535_ISA	0x002b
++#define PCI_DEVICE_ID_NS_CS5535_IDE	0x002d
++#define PCI_DEVICE_ID_NS_CS5535_AUDIO	0x002e
++#define PCI_DEVICE_ID_NS_CS5535_USB	0x002f
++#define PCI_DEVICE_ID_NS_GX_VIDEO	0x0030
++#define PCI_DEVICE_ID_NS_SATURN		0x0035
++#define PCI_DEVICE_ID_NS_SCx200_BRIDGE	0x0500
++#define PCI_DEVICE_ID_NS_SCx200_SMI	0x0501
++#define PCI_DEVICE_ID_NS_SCx200_IDE	0x0502
++#define PCI_DEVICE_ID_NS_SCx200_AUDIO	0x0503
++#define PCI_DEVICE_ID_NS_SCx200_VIDEO	0x0504
++#define PCI_DEVICE_ID_NS_SCx200_XBUS	0x0505
++#define PCI_DEVICE_ID_NS_SC1100_BRIDGE	0x0510
++#define PCI_DEVICE_ID_NS_SC1100_SMI	0x0511
++#define PCI_DEVICE_ID_NS_SC1100_XBUS	0x0515
++#define PCI_DEVICE_ID_NS_87410		0xd001
++
++#define PCI_DEVICE_ID_NS_GX_HOST_BRIDGE  0x0028
++
++#define PCI_VENDOR_ID_TSENG		0x100c
++#define PCI_DEVICE_ID_TSENG_W32P_2	0x3202
++#define PCI_DEVICE_ID_TSENG_W32P_b	0x3205
++#define PCI_DEVICE_ID_TSENG_W32P_c	0x3206
++#define PCI_DEVICE_ID_TSENG_W32P_d	0x3207
++#define PCI_DEVICE_ID_TSENG_ET6000	0x3208
++
++#define PCI_VENDOR_ID_WEITEK		0x100e
++#define PCI_DEVICE_ID_WEITEK_P9000	0x9001
++#define PCI_DEVICE_ID_WEITEK_P9100	0x9100
++
++#define PCI_VENDOR_ID_DEC		0x1011
++#define PCI_DEVICE_ID_DEC_BRD		0x0001
++#define PCI_DEVICE_ID_DEC_TULIP		0x0002
++#define PCI_DEVICE_ID_DEC_TGA		0x0004
++#define PCI_DEVICE_ID_DEC_TULIP_FAST	0x0009
++#define PCI_DEVICE_ID_DEC_TGA2		0x000D
++#define PCI_DEVICE_ID_DEC_FDDI		0x000F
++#define PCI_DEVICE_ID_DEC_TULIP_PLUS	0x0014
++#define PCI_DEVICE_ID_DEC_21142		0x0019
++#define PCI_DEVICE_ID_DEC_21052		0x0021
++#define PCI_DEVICE_ID_DEC_21150		0x0022
++#define PCI_DEVICE_ID_DEC_21152		0x0024
++#define PCI_DEVICE_ID_DEC_21153		0x0025
++#define PCI_DEVICE_ID_DEC_21154		0x0026
++#define PCI_DEVICE_ID_DEC_21285		0x1065
++#define PCI_DEVICE_ID_COMPAQ_42XX	0x0046
++
++#define PCI_VENDOR_ID_CIRRUS		0x1013
++#define PCI_DEVICE_ID_CIRRUS_7548	0x0038
++#define PCI_DEVICE_ID_CIRRUS_5430	0x00a0
++#define PCI_DEVICE_ID_CIRRUS_5434_4	0x00a4
++#define PCI_DEVICE_ID_CIRRUS_5434_8	0x00a8
++#define PCI_DEVICE_ID_CIRRUS_5436	0x00ac
++#define PCI_DEVICE_ID_CIRRUS_5446	0x00b8
++#define PCI_DEVICE_ID_CIRRUS_5480	0x00bc
++#define PCI_DEVICE_ID_CIRRUS_5462	0x00d0
++#define PCI_DEVICE_ID_CIRRUS_5464	0x00d4
++#define PCI_DEVICE_ID_CIRRUS_5465	0x00d6
++#define PCI_DEVICE_ID_CIRRUS_6729	0x1100
++#define PCI_DEVICE_ID_CIRRUS_6832	0x1110
++#define PCI_DEVICE_ID_CIRRUS_7543	0x1202
++#define PCI_DEVICE_ID_CIRRUS_4610	0x6001
++#define PCI_DEVICE_ID_CIRRUS_4612	0x6003
++#define PCI_DEVICE_ID_CIRRUS_4615	0x6004
++
++#define PCI_VENDOR_ID_IBM		0x1014
++#define PCI_DEVICE_ID_IBM_TR		0x0018
++#define PCI_DEVICE_ID_IBM_TR_WAKE	0x003e
++#define PCI_DEVICE_ID_IBM_CPC710_PCI64	0x00fc
++#define PCI_DEVICE_ID_IBM_SNIPE		0x0180
++#define PCI_DEVICE_ID_IBM_CITRINE		0x028C
++#define PCI_DEVICE_ID_IBM_GEMSTONE		0xB166
++#define PCI_DEVICE_ID_IBM_OBSIDIAN		0x02BD
++#define PCI_DEVICE_ID_IBM_ICOM_DEV_ID_1	0x0031
++#define PCI_DEVICE_ID_IBM_ICOM_DEV_ID_2	0x0219
++#define PCI_DEVICE_ID_IBM_ICOM_V2_TWO_PORTS_RVX		0x021A
++#define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM	0x0251
++#define PCI_DEVICE_ID_IBM_ICOM_V2_ONE_PORT_RVX_ONE_PORT_MDM_PCIE 0x0361
++#define PCI_DEVICE_ID_IBM_ICOM_FOUR_PORT_MODEL	0x252
++
++#define PCI_VENDOR_ID_UNISYS		0x1018
++#define PCI_DEVICE_ID_UNISYS_DMA_DIRECTOR 0x001C
++
++#define PCI_VENDOR_ID_COMPEX2		0x101a /* pci.ids says "AT&T GIS (NCR)" */
++#define PCI_DEVICE_ID_COMPEX2_100VG	0x0005
++
++#define PCI_VENDOR_ID_WD		0x101c
++#define PCI_DEVICE_ID_WD_90C		0xc24a
++
++#define PCI_VENDOR_ID_AMI		0x101e
++#define PCI_DEVICE_ID_AMI_MEGARAID3	0x1960
++#define PCI_DEVICE_ID_AMI_MEGARAID	0x9010
++#define PCI_DEVICE_ID_AMI_MEGARAID2	0x9060
++
++#define PCI_VENDOR_ID_AMD		0x1022
++#define PCI_DEVICE_ID_AMD_K8_NB		0x1100
++#define PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP	0x1101
++#define PCI_DEVICE_ID_AMD_K8_NB_MEMCTL	0x1102
++#define PCI_DEVICE_ID_AMD_K8_NB_MISC	0x1103
++#define PCI_DEVICE_ID_AMD_10H_NB_HT	0x1200
++#define PCI_DEVICE_ID_AMD_10H_NB_MAP	0x1201
++#define PCI_DEVICE_ID_AMD_10H_NB_DRAM	0x1202
++#define PCI_DEVICE_ID_AMD_10H_NB_MISC	0x1203
++#define PCI_DEVICE_ID_AMD_10H_NB_LINK	0x1204
++#define PCI_DEVICE_ID_AMD_11H_NB_HT	0x1300
++#define PCI_DEVICE_ID_AMD_11H_NB_MAP	0x1301
++#define PCI_DEVICE_ID_AMD_11H_NB_DRAM	0x1302
++#define PCI_DEVICE_ID_AMD_11H_NB_MISC	0x1303
++#define PCI_DEVICE_ID_AMD_11H_NB_LINK	0x1304
++#define PCI_DEVICE_ID_AMD_LANCE		0x2000
++#define PCI_DEVICE_ID_AMD_LANCE_HOME	0x2001
++#define PCI_DEVICE_ID_AMD_SCSI		0x2020
++#define PCI_DEVICE_ID_AMD_SERENADE	0x36c0
++#define PCI_DEVICE_ID_AMD_FE_GATE_7006	0x7006
++#define PCI_DEVICE_ID_AMD_FE_GATE_7007	0x7007
++#define PCI_DEVICE_ID_AMD_FE_GATE_700C	0x700C
++#define PCI_DEVICE_ID_AMD_FE_GATE_700E	0x700E
++#define PCI_DEVICE_ID_AMD_COBRA_7401	0x7401
++#define PCI_DEVICE_ID_AMD_VIPER_7409	0x7409
++#define PCI_DEVICE_ID_AMD_VIPER_740B	0x740B
++#define PCI_DEVICE_ID_AMD_VIPER_7410	0x7410
++#define PCI_DEVICE_ID_AMD_VIPER_7411	0x7411
++#define PCI_DEVICE_ID_AMD_VIPER_7413	0x7413
++#define PCI_DEVICE_ID_AMD_VIPER_7440	0x7440
++#define PCI_DEVICE_ID_AMD_OPUS_7441	0x7441
++#define PCI_DEVICE_ID_AMD_OPUS_7443	0x7443
++#define PCI_DEVICE_ID_AMD_VIPER_7443	0x7443
++#define PCI_DEVICE_ID_AMD_OPUS_7445	0x7445
++#define PCI_DEVICE_ID_AMD_8111_LPC	0x7468
++#define PCI_DEVICE_ID_AMD_8111_IDE	0x7469
++#define PCI_DEVICE_ID_AMD_8111_SMBUS2	0x746a
++#define PCI_DEVICE_ID_AMD_8111_SMBUS	0x746b
++#define PCI_DEVICE_ID_AMD_8111_AUDIO	0x746d
++#define PCI_DEVICE_ID_AMD_8151_0	0x7454
++#define PCI_DEVICE_ID_AMD_8131_BRIDGE	0x7450
++#define PCI_DEVICE_ID_AMD_8131_APIC	0x7451
++#define PCI_DEVICE_ID_AMD_8132_BRIDGE	0x7458
++#define PCI_DEVICE_ID_AMD_CS5536_ISA    0x2090
++#define PCI_DEVICE_ID_AMD_CS5536_FLASH  0x2091
++#define PCI_DEVICE_ID_AMD_CS5536_AUDIO  0x2093
++#define PCI_DEVICE_ID_AMD_CS5536_OHC    0x2094
++#define PCI_DEVICE_ID_AMD_CS5536_EHC    0x2095
++#define PCI_DEVICE_ID_AMD_CS5536_UDC    0x2096
++#define PCI_DEVICE_ID_AMD_CS5536_UOC    0x2097
++#define PCI_DEVICE_ID_AMD_CS5536_IDE    0x209A
++
++#define PCI_DEVICE_ID_AMD_LX_VIDEO  0x2081
++#define PCI_DEVICE_ID_AMD_LX_AES    0x2082
++
++#define PCI_VENDOR_ID_TRIDENT		0x1023
++#define PCI_DEVICE_ID_TRIDENT_4DWAVE_DX	0x2000
++#define PCI_DEVICE_ID_TRIDENT_4DWAVE_NX	0x2001
++#define PCI_DEVICE_ID_TRIDENT_9320	0x9320
++#define PCI_DEVICE_ID_TRIDENT_9388	0x9388
++#define PCI_DEVICE_ID_TRIDENT_9397	0x9397
++#define PCI_DEVICE_ID_TRIDENT_939A	0x939A
++#define PCI_DEVICE_ID_TRIDENT_9520	0x9520
++#define PCI_DEVICE_ID_TRIDENT_9525	0x9525
++#define PCI_DEVICE_ID_TRIDENT_9420	0x9420
++#define PCI_DEVICE_ID_TRIDENT_9440	0x9440
++#define PCI_DEVICE_ID_TRIDENT_9660	0x9660
++#define PCI_DEVICE_ID_TRIDENT_9750	0x9750
++#define PCI_DEVICE_ID_TRIDENT_9850	0x9850
++#define PCI_DEVICE_ID_TRIDENT_9880	0x9880
++#define PCI_DEVICE_ID_TRIDENT_8400	0x8400
++#define PCI_DEVICE_ID_TRIDENT_8420	0x8420
++#define PCI_DEVICE_ID_TRIDENT_8500	0x8500
++
++#define PCI_VENDOR_ID_AI		0x1025
++#define PCI_DEVICE_ID_AI_M1435		0x1435
++
++#define PCI_VENDOR_ID_DELL		0x1028
++#define PCI_DEVICE_ID_DELL_RACIII	0x0008
++#define PCI_DEVICE_ID_DELL_RAC4		0x0012
++#define PCI_DEVICE_ID_DELL_PERC5	0x0015
++
++#define PCI_VENDOR_ID_MATROX		0x102B
++#define PCI_DEVICE_ID_MATROX_MGA_2	0x0518
++#define PCI_DEVICE_ID_MATROX_MIL	0x0519
++#define PCI_DEVICE_ID_MATROX_MYS	0x051A
++#define PCI_DEVICE_ID_MATROX_MIL_2	0x051b
++#define PCI_DEVICE_ID_MATROX_MYS_AGP	0x051e
++#define PCI_DEVICE_ID_MATROX_MIL_2_AGP	0x051f
++#define PCI_DEVICE_ID_MATROX_MGA_IMP	0x0d10
++#define PCI_DEVICE_ID_MATROX_G100_MM	0x1000
++#define PCI_DEVICE_ID_MATROX_G100_AGP	0x1001
++#define PCI_DEVICE_ID_MATROX_G200_PCI	0x0520
++#define PCI_DEVICE_ID_MATROX_G200_AGP	0x0521
++#define	PCI_DEVICE_ID_MATROX_G400	0x0525
++#define	PCI_DEVICE_ID_MATROX_G200EV_PCI	0x0530
++#define PCI_DEVICE_ID_MATROX_G550	0x2527
++#define PCI_DEVICE_ID_MATROX_VIA	0x4536
++
++#define PCI_VENDOR_ID_CT		0x102c
++#define PCI_DEVICE_ID_CT_69000		0x00c0
++#define PCI_DEVICE_ID_CT_65545		0x00d8
++#define PCI_DEVICE_ID_CT_65548		0x00dc
++#define PCI_DEVICE_ID_CT_65550		0x00e0
++#define PCI_DEVICE_ID_CT_65554		0x00e4
++#define PCI_DEVICE_ID_CT_65555		0x00e5
++
++#define PCI_VENDOR_ID_MIRO		0x1031
++#define PCI_DEVICE_ID_MIRO_36050	0x5601
++#define PCI_DEVICE_ID_MIRO_DC10PLUS	0x7efe
++#define PCI_DEVICE_ID_MIRO_DC30PLUS	0xd801
++
++#define PCI_VENDOR_ID_NEC		0x1033
++#define PCI_DEVICE_ID_NEC_CBUS_1	0x0001 /* PCI-Cbus Bridge */
++#define PCI_DEVICE_ID_NEC_LOCAL		0x0002 /* Local Bridge */
++#define PCI_DEVICE_ID_NEC_ATM		0x0003 /* ATM LAN Controller */
++#define PCI_DEVICE_ID_NEC_R4000		0x0004 /* R4000 Bridge */
++#define PCI_DEVICE_ID_NEC_486		0x0005 /* 486 Like Peripheral Bus Bridge */
++#define PCI_DEVICE_ID_NEC_ACCEL_1	0x0006 /* Graphic Accelerator */
++#define PCI_DEVICE_ID_NEC_UXBUS		0x0007 /* UX-Bus Bridge */
++#define PCI_DEVICE_ID_NEC_ACCEL_2	0x0008 /* Graphic Accelerator */
++#define PCI_DEVICE_ID_NEC_GRAPH		0x0009 /* PCI-CoreGraph Bridge */
++#define PCI_DEVICE_ID_NEC_VL		0x0016 /* PCI-VL Bridge */
++#define PCI_DEVICE_ID_NEC_STARALPHA2	0x002c /* STAR ALPHA2 */
++#define PCI_DEVICE_ID_NEC_CBUS_2	0x002d /* PCI-Cbus Bridge */
++#define PCI_DEVICE_ID_NEC_USB		0x0035 /* PCI-USB Host */
++#define PCI_DEVICE_ID_NEC_CBUS_3	0x003b
++#define PCI_DEVICE_ID_NEC_NAPCCARD	0x003e
++#define PCI_DEVICE_ID_NEC_PCX2		0x0046 /* PowerVR */
++#define PCI_DEVICE_ID_NEC_VRC5476       0x009b
++#define PCI_DEVICE_ID_NEC_VRC4173	0x00a5
++#define PCI_DEVICE_ID_NEC_VRC5477_AC97  0x00a6
++#define PCI_DEVICE_ID_NEC_PC9821CS01    0x800c /* PC-9821-CS01 */
++#define PCI_DEVICE_ID_NEC_PC9821NRB06   0x800d /* PC-9821NR-B06 */
++
++#define PCI_VENDOR_ID_FD		0x1036
++#define PCI_DEVICE_ID_FD_36C70		0x0000
++
++#define PCI_VENDOR_ID_SI		0x1039
++#define PCI_DEVICE_ID_SI_5591_AGP	0x0001
++#define PCI_DEVICE_ID_SI_6202		0x0002
++#define PCI_DEVICE_ID_SI_503		0x0008
++#define PCI_DEVICE_ID_SI_ACPI		0x0009
++#define PCI_DEVICE_ID_SI_SMBUS		0x0016
++#define PCI_DEVICE_ID_SI_LPC		0x0018
++#define PCI_DEVICE_ID_SI_5597_VGA	0x0200
++#define PCI_DEVICE_ID_SI_6205		0x0205
++#define PCI_DEVICE_ID_SI_501		0x0406
++#define PCI_DEVICE_ID_SI_496		0x0496
++#define PCI_DEVICE_ID_SI_300		0x0300
++#define PCI_DEVICE_ID_SI_315H		0x0310
++#define PCI_DEVICE_ID_SI_315		0x0315
++#define PCI_DEVICE_ID_SI_315PRO		0x0325
++#define PCI_DEVICE_ID_SI_530		0x0530
++#define PCI_DEVICE_ID_SI_540		0x0540
++#define PCI_DEVICE_ID_SI_550		0x0550
++#define PCI_DEVICE_ID_SI_540_VGA	0x5300
++#define PCI_DEVICE_ID_SI_550_VGA	0x5315
++#define PCI_DEVICE_ID_SI_620		0x0620
++#define PCI_DEVICE_ID_SI_630		0x0630
++#define PCI_DEVICE_ID_SI_633		0x0633
++#define PCI_DEVICE_ID_SI_635		0x0635
++#define PCI_DEVICE_ID_SI_640		0x0640
++#define PCI_DEVICE_ID_SI_645		0x0645
++#define PCI_DEVICE_ID_SI_646		0x0646
++#define PCI_DEVICE_ID_SI_648		0x0648
++#define PCI_DEVICE_ID_SI_650		0x0650
++#define PCI_DEVICE_ID_SI_651		0x0651
++#define PCI_DEVICE_ID_SI_655		0x0655
++#define PCI_DEVICE_ID_SI_661		0x0661
++#define PCI_DEVICE_ID_SI_730		0x0730
++#define PCI_DEVICE_ID_SI_733		0x0733
++#define PCI_DEVICE_ID_SI_630_VGA	0x6300
++#define PCI_DEVICE_ID_SI_735		0x0735
++#define PCI_DEVICE_ID_SI_740		0x0740
++#define PCI_DEVICE_ID_SI_741		0x0741
++#define PCI_DEVICE_ID_SI_745		0x0745
++#define PCI_DEVICE_ID_SI_746		0x0746
++#define PCI_DEVICE_ID_SI_755		0x0755
++#define PCI_DEVICE_ID_SI_760		0x0760
++#define PCI_DEVICE_ID_SI_900		0x0900
++#define PCI_DEVICE_ID_SI_961		0x0961
++#define PCI_DEVICE_ID_SI_962		0x0962
++#define PCI_DEVICE_ID_SI_963		0x0963
++#define PCI_DEVICE_ID_SI_965		0x0965
++#define PCI_DEVICE_ID_SI_966		0x0966
++#define PCI_DEVICE_ID_SI_968		0x0968
++#define PCI_DEVICE_ID_SI_1180		0x1180
++#define PCI_DEVICE_ID_SI_5511		0x5511
++#define PCI_DEVICE_ID_SI_5513		0x5513
++#define PCI_DEVICE_ID_SI_5517		0x5517
++#define PCI_DEVICE_ID_SI_5518		0x5518
++#define PCI_DEVICE_ID_SI_5571		0x5571
++#define PCI_DEVICE_ID_SI_5581		0x5581
++#define PCI_DEVICE_ID_SI_5582		0x5582
++#define PCI_DEVICE_ID_SI_5591		0x5591
++#define PCI_DEVICE_ID_SI_5596		0x5596
++#define PCI_DEVICE_ID_SI_5597		0x5597
++#define PCI_DEVICE_ID_SI_5598		0x5598
++#define PCI_DEVICE_ID_SI_5600		0x5600
++#define PCI_DEVICE_ID_SI_7012		0x7012
++#define PCI_DEVICE_ID_SI_7013		0x7013
++#define PCI_DEVICE_ID_SI_7016		0x7016
++#define PCI_DEVICE_ID_SI_7018		0x7018
++
++#define PCI_VENDOR_ID_HP		0x103c
++#define PCI_DEVICE_ID_HP_VISUALIZE_EG	0x1005
++#define PCI_DEVICE_ID_HP_VISUALIZE_FX6	0x1006
++#define PCI_DEVICE_ID_HP_VISUALIZE_FX4	0x1008
++#define PCI_DEVICE_ID_HP_VISUALIZE_FX2	0x100a
++#define PCI_DEVICE_ID_HP_TACHYON	0x1028
++#define PCI_DEVICE_ID_HP_TACHLITE	0x1029
++#define PCI_DEVICE_ID_HP_J2585A		0x1030
++#define PCI_DEVICE_ID_HP_J2585B		0x1031
++#define PCI_DEVICE_ID_HP_J2973A		0x1040
++#define PCI_DEVICE_ID_HP_J2970A		0x1042
++#define PCI_DEVICE_ID_HP_DIVA		0x1048
++#define PCI_DEVICE_ID_HP_DIVA_TOSCA1	0x1049
++#define PCI_DEVICE_ID_HP_DIVA_TOSCA2	0x104A
++#define PCI_DEVICE_ID_HP_DIVA_MAESTRO	0x104B
++#define PCI_DEVICE_ID_HP_REO_IOC	0x10f1
++#define PCI_DEVICE_ID_HP_VISUALIZE_FXE	0x108b
++#define PCI_DEVICE_ID_HP_DIVA_HALFDOME	0x1223
++#define PCI_DEVICE_ID_HP_DIVA_KEYSTONE	0x1226
++#define PCI_DEVICE_ID_HP_DIVA_POWERBAR	0x1227
++#define PCI_DEVICE_ID_HP_ZX1_IOC	0x122a
++#define PCI_DEVICE_ID_HP_PCIX_LBA	0x122e
++#define PCI_DEVICE_ID_HP_SX1000_IOC	0x127c
++#define PCI_DEVICE_ID_HP_DIVA_EVEREST	0x1282
++#define PCI_DEVICE_ID_HP_DIVA_AUX	0x1290
++#define PCI_DEVICE_ID_HP_DIVA_RMP3	0x1301
++#define PCI_DEVICE_ID_HP_DIVA_HURRICANE	0x132a
++#define PCI_DEVICE_ID_HP_CISSA		0x3220
++#define PCI_DEVICE_ID_HP_CISSC		0x3230
++#define PCI_DEVICE_ID_HP_CISSD		0x3238
++#define PCI_DEVICE_ID_HP_CISSE		0x323a
++#define PCI_DEVICE_ID_HP_ZX2_IOC	0x4031
++
++#define PCI_VENDOR_ID_PCTECH		0x1042
++#define PCI_DEVICE_ID_PCTECH_RZ1000	0x1000
++#define PCI_DEVICE_ID_PCTECH_RZ1001	0x1001
++#define PCI_DEVICE_ID_PCTECH_SAMURAI_IDE 0x3020
++
++#define PCI_VENDOR_ID_ASUSTEK		0x1043
++#define PCI_DEVICE_ID_ASUSTEK_0675	0x0675
++
++#define PCI_VENDOR_ID_DPT		0x1044
++#define PCI_DEVICE_ID_DPT		0xa400
++
++#define PCI_VENDOR_ID_OPTI		0x1045
++#define PCI_DEVICE_ID_OPTI_82C558	0xc558
++#define PCI_DEVICE_ID_OPTI_82C621	0xc621
++#define PCI_DEVICE_ID_OPTI_82C700	0xc700
++#define PCI_DEVICE_ID_OPTI_82C825	0xd568
++
++#define PCI_VENDOR_ID_ELSA		0x1048
++#define PCI_DEVICE_ID_ELSA_MICROLINK	0x1000
++#define PCI_DEVICE_ID_ELSA_QS3000	0x3000
++
++#define PCI_VENDOR_ID_BUSLOGIC		      0x104B
++#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER_NC 0x0140
++#define PCI_DEVICE_ID_BUSLOGIC_MULTIMASTER    0x1040
++#define PCI_DEVICE_ID_BUSLOGIC_FLASHPOINT     0x8130
++
++#define PCI_VENDOR_ID_TI		0x104c
++#define PCI_DEVICE_ID_TI_TVP4020	0x3d07
++#define PCI_DEVICE_ID_TI_4450		0x8011
++#define PCI_DEVICE_ID_TI_TSB43AB22	0x8023
++#define PCI_DEVICE_ID_TI_XX21_XX11	0x8031
++#define PCI_DEVICE_ID_TI_XX21_XX11_FM	0x8033
++#define PCI_DEVICE_ID_TI_XX21_XX11_SD	0x8034
++#define PCI_DEVICE_ID_TI_X515		0x8036
++#define PCI_DEVICE_ID_TI_XX12		0x8039
++#define PCI_DEVICE_ID_TI_XX12_FM	0x803b
++#define PCI_DEVICE_ID_TI_1130		0xac12
++#define PCI_DEVICE_ID_TI_1031		0xac13
++#define PCI_DEVICE_ID_TI_1131		0xac15
++#define PCI_DEVICE_ID_TI_1250		0xac16
++#define PCI_DEVICE_ID_TI_1220		0xac17
++#define PCI_DEVICE_ID_TI_1221		0xac19
++#define PCI_DEVICE_ID_TI_1210		0xac1a
++#define PCI_DEVICE_ID_TI_1450		0xac1b
++#define PCI_DEVICE_ID_TI_1225		0xac1c
++#define PCI_DEVICE_ID_TI_1251A		0xac1d
++#define PCI_DEVICE_ID_TI_1211		0xac1e
++#define PCI_DEVICE_ID_TI_1251B		0xac1f
++#define PCI_DEVICE_ID_TI_4410		0xac41
++#define PCI_DEVICE_ID_TI_4451		0xac42
++#define PCI_DEVICE_ID_TI_4510		0xac44
++#define PCI_DEVICE_ID_TI_4520		0xac46
++#define PCI_DEVICE_ID_TI_7510		0xac47
++#define PCI_DEVICE_ID_TI_7610		0xac48
++#define PCI_DEVICE_ID_TI_7410		0xac49
++#define PCI_DEVICE_ID_TI_1410		0xac50
++#define PCI_DEVICE_ID_TI_1420		0xac51
++#define PCI_DEVICE_ID_TI_1451A		0xac52
++#define PCI_DEVICE_ID_TI_1620		0xac54
++#define PCI_DEVICE_ID_TI_1520		0xac55
++#define PCI_DEVICE_ID_TI_1510		0xac56
++#define PCI_DEVICE_ID_TI_X620		0xac8d
++#define PCI_DEVICE_ID_TI_X420		0xac8e
++#define PCI_DEVICE_ID_TI_XX20_FM	0xac8f
++
++#define PCI_VENDOR_ID_SONY		0x104d
++
++/* Winbond have two vendor IDs! See 0x10ad as well */
++#define PCI_VENDOR_ID_WINBOND2		0x1050
++#define PCI_DEVICE_ID_WINBOND2_89C940F	0x5a5a
++#define PCI_DEVICE_ID_WINBOND2_6692	0x6692
++
++#define PCI_VENDOR_ID_ANIGMA		0x1051
++#define PCI_DEVICE_ID_ANIGMA_MC145575	0x0100
++  
++#define PCI_VENDOR_ID_EFAR		0x1055
++#define PCI_DEVICE_ID_EFAR_SLC90E66_1	0x9130
++#define PCI_DEVICE_ID_EFAR_SLC90E66_3	0x9463
++
++#define PCI_VENDOR_ID_MOTOROLA		0x1057
++#define PCI_DEVICE_ID_MOTOROLA_MPC105	0x0001
++#define PCI_DEVICE_ID_MOTOROLA_MPC106	0x0002
++#define PCI_DEVICE_ID_MOTOROLA_MPC107	0x0004
++#define PCI_DEVICE_ID_MOTOROLA_RAVEN	0x4801
++#define PCI_DEVICE_ID_MOTOROLA_FALCON	0x4802
++#define PCI_DEVICE_ID_MOTOROLA_HAWK	0x4803
++#define PCI_DEVICE_ID_MOTOROLA_HARRIER	0x480b
++#define PCI_DEVICE_ID_MOTOROLA_MPC5200	0x5803
++#define PCI_DEVICE_ID_MOTOROLA_MPC5200B	0x5809
++
++#define PCI_VENDOR_ID_PROMISE		0x105a
++#define PCI_DEVICE_ID_PROMISE_20265	0x0d30
++#define PCI_DEVICE_ID_PROMISE_20267	0x4d30
++#define PCI_DEVICE_ID_PROMISE_20246	0x4d33
++#define PCI_DEVICE_ID_PROMISE_20262	0x4d38
++#define PCI_DEVICE_ID_PROMISE_20263	0x0D38
++#define PCI_DEVICE_ID_PROMISE_20268	0x4d68
++#define PCI_DEVICE_ID_PROMISE_20269	0x4d69
++#define PCI_DEVICE_ID_PROMISE_20270	0x6268
++#define PCI_DEVICE_ID_PROMISE_20271	0x6269
++#define PCI_DEVICE_ID_PROMISE_20275	0x1275
++#define PCI_DEVICE_ID_PROMISE_20276	0x5275
++#define PCI_DEVICE_ID_PROMISE_20277	0x7275
++
++#define PCI_VENDOR_ID_UMC		0x1060
++#define PCI_DEVICE_ID_UMC_UM8673F	0x0101
++#define PCI_DEVICE_ID_UMC_UM8886BF	0x673a
++#define PCI_DEVICE_ID_UMC_UM8886A	0x886a
++
++#define PCI_VENDOR_ID_PICOPOWER		0x1066
++#define PCI_DEVICE_ID_PICOPOWER_PT86C523	0x0002
++#define PCI_DEVICE_ID_PICOPOWER_PT86C523BBP	0x8002
++
++#define PCI_VENDOR_ID_MYLEX		0x1069
++#define PCI_DEVICE_ID_MYLEX_DAC960_P	0x0001
++#define PCI_DEVICE_ID_MYLEX_DAC960_PD	0x0002
++#define PCI_DEVICE_ID_MYLEX_DAC960_PG	0x0010
++#define PCI_DEVICE_ID_MYLEX_DAC960_LA	0x0020
++#define PCI_DEVICE_ID_MYLEX_DAC960_LP	0x0050
++#define PCI_DEVICE_ID_MYLEX_DAC960_BA	0xBA56
++#define PCI_DEVICE_ID_MYLEX_DAC960_GEM	0xB166
++
++#define PCI_VENDOR_ID_APPLE		0x106b
++#define PCI_DEVICE_ID_APPLE_BANDIT	0x0001
++#define PCI_DEVICE_ID_APPLE_HYDRA	0x000e
++#define PCI_DEVICE_ID_APPLE_UNI_N_FW	0x0018
++#define PCI_DEVICE_ID_APPLE_UNI_N_AGP	0x0020
++#define PCI_DEVICE_ID_APPLE_UNI_N_GMAC	0x0021
++#define PCI_DEVICE_ID_APPLE_UNI_N_GMACP	0x0024
++#define PCI_DEVICE_ID_APPLE_UNI_N_AGP_P	0x0027
++#define PCI_DEVICE_ID_APPLE_UNI_N_AGP15	0x002d
++#define PCI_DEVICE_ID_APPLE_UNI_N_PCI15	0x002e
++#define PCI_DEVICE_ID_APPLE_UNI_N_GMAC2	0x0032
++#define PCI_DEVICE_ID_APPLE_UNI_N_ATA	0x0033
++#define PCI_DEVICE_ID_APPLE_UNI_N_AGP2	0x0034
++#define PCI_DEVICE_ID_APPLE_IPID_ATA100	0x003b
++#define PCI_DEVICE_ID_APPLE_K2_ATA100	0x0043
++#define PCI_DEVICE_ID_APPLE_U3_AGP	0x004b
++#define PCI_DEVICE_ID_APPLE_K2_GMAC	0x004c
++#define PCI_DEVICE_ID_APPLE_SH_ATA      0x0050
++#define PCI_DEVICE_ID_APPLE_SH_SUNGEM   0x0051
++#define PCI_DEVICE_ID_APPLE_U3L_AGP	0x0058
++#define PCI_DEVICE_ID_APPLE_U3H_AGP	0x0059
++#define PCI_DEVICE_ID_APPLE_IPID2_AGP	0x0066
++#define PCI_DEVICE_ID_APPLE_IPID2_ATA	0x0069
++#define PCI_DEVICE_ID_APPLE_IPID2_FW	0x006a
++#define PCI_DEVICE_ID_APPLE_IPID2_GMAC	0x006b
++#define PCI_DEVICE_ID_APPLE_TIGON3	0x1645
++
++#define PCI_VENDOR_ID_YAMAHA		0x1073
++#define PCI_DEVICE_ID_YAMAHA_724	0x0004
++#define PCI_DEVICE_ID_YAMAHA_724F	0x000d
++#define PCI_DEVICE_ID_YAMAHA_740	0x000a
++#define PCI_DEVICE_ID_YAMAHA_740C	0x000c
++#define PCI_DEVICE_ID_YAMAHA_744	0x0010
++#define PCI_DEVICE_ID_YAMAHA_754	0x0012
++
++#define PCI_VENDOR_ID_QLOGIC		0x1077
++#define PCI_DEVICE_ID_QLOGIC_ISP10160	0x1016
++#define PCI_DEVICE_ID_QLOGIC_ISP1020	0x1020
++#define PCI_DEVICE_ID_QLOGIC_ISP1080	0x1080
++#define PCI_DEVICE_ID_QLOGIC_ISP12160	0x1216
++#define PCI_DEVICE_ID_QLOGIC_ISP1240	0x1240
++#define PCI_DEVICE_ID_QLOGIC_ISP1280	0x1280
++#define PCI_DEVICE_ID_QLOGIC_ISP2100	0x2100
++#define PCI_DEVICE_ID_QLOGIC_ISP2200	0x2200
++#define PCI_DEVICE_ID_QLOGIC_ISP2300	0x2300
++#define PCI_DEVICE_ID_QLOGIC_ISP2312	0x2312
++#define PCI_DEVICE_ID_QLOGIC_ISP2322	0x2322
++#define PCI_DEVICE_ID_QLOGIC_ISP6312	0x6312
++#define PCI_DEVICE_ID_QLOGIC_ISP6322	0x6322
++#define PCI_DEVICE_ID_QLOGIC_ISP2422	0x2422
++#define PCI_DEVICE_ID_QLOGIC_ISP2432	0x2432
++#define PCI_DEVICE_ID_QLOGIC_ISP2512	0x2512
++#define PCI_DEVICE_ID_QLOGIC_ISP2522	0x2522
++#define PCI_DEVICE_ID_QLOGIC_ISP5422	0x5422
++#define PCI_DEVICE_ID_QLOGIC_ISP5432	0x5432
++
++#define PCI_VENDOR_ID_CYRIX		0x1078
++#define PCI_DEVICE_ID_CYRIX_5510	0x0000
++#define PCI_DEVICE_ID_CYRIX_PCI_MASTER	0x0001
++#define PCI_DEVICE_ID_CYRIX_5520	0x0002
++#define PCI_DEVICE_ID_CYRIX_5530_LEGACY	0x0100
++#define PCI_DEVICE_ID_CYRIX_5530_IDE	0x0102
++#define PCI_DEVICE_ID_CYRIX_5530_AUDIO	0x0103
++#define PCI_DEVICE_ID_CYRIX_5530_VIDEO	0x0104
++
++#define PCI_VENDOR_ID_CONTAQ		0x1080
++#define PCI_DEVICE_ID_CONTAQ_82C693	0xc693
++
++#define PCI_VENDOR_ID_OLICOM		0x108d
++#define PCI_DEVICE_ID_OLICOM_OC2325	0x0012
++#define PCI_DEVICE_ID_OLICOM_OC2183	0x0013
++#define PCI_DEVICE_ID_OLICOM_OC2326	0x0014
++
++#define PCI_VENDOR_ID_SUN		0x108e
++#define PCI_DEVICE_ID_SUN_EBUS		0x1000
++#define PCI_DEVICE_ID_SUN_HAPPYMEAL	0x1001
++#define PCI_DEVICE_ID_SUN_RIO_EBUS	0x1100
++#define PCI_DEVICE_ID_SUN_RIO_GEM	0x1101
++#define PCI_DEVICE_ID_SUN_RIO_1394	0x1102
++#define PCI_DEVICE_ID_SUN_RIO_USB	0x1103
++#define PCI_DEVICE_ID_SUN_GEM		0x2bad
++#define PCI_DEVICE_ID_SUN_SIMBA		0x5000
++#define PCI_DEVICE_ID_SUN_PBM		0x8000
++#define PCI_DEVICE_ID_SUN_SCHIZO	0x8001
++#define PCI_DEVICE_ID_SUN_SABRE		0xa000
++#define PCI_DEVICE_ID_SUN_HUMMINGBIRD	0xa001
++#define PCI_DEVICE_ID_SUN_TOMATILLO	0xa801
++#define PCI_DEVICE_ID_SUN_CASSINI	0xabba
++
++#define PCI_VENDOR_ID_CMD		0x1095
++#define PCI_DEVICE_ID_CMD_643		0x0643
++#define PCI_DEVICE_ID_CMD_646		0x0646
++#define PCI_DEVICE_ID_CMD_648		0x0648
++#define PCI_DEVICE_ID_CMD_649		0x0649
++
++#define PCI_DEVICE_ID_SII_680		0x0680
++#define PCI_DEVICE_ID_SII_3112		0x3112
++#define PCI_DEVICE_ID_SII_1210SA	0x0240
++
++#define PCI_VENDOR_ID_BROOKTREE		0x109e
++#define PCI_DEVICE_ID_BROOKTREE_878	0x0878
++#define PCI_DEVICE_ID_BROOKTREE_879	0x0879
++
++#define PCI_VENDOR_ID_SGI		0x10a9
++#define PCI_DEVICE_ID_SGI_IOC3		0x0003
++#define PCI_DEVICE_ID_SGI_LITHIUM	0x1002
++#define PCI_DEVICE_ID_SGI_IOC4		0x100a
++
++#define PCI_VENDOR_ID_WINBOND		0x10ad
++#define PCI_DEVICE_ID_WINBOND_82C105	0x0105
++#define PCI_DEVICE_ID_WINBOND_83C553	0x0565
++
++#define PCI_VENDOR_ID_PLX		0x10b5
++#define PCI_DEVICE_ID_PLX_R685		0x1030
++#define PCI_DEVICE_ID_PLX_ROMULUS	0x106a
++#define PCI_DEVICE_ID_PLX_SPCOM800	0x1076
++#define PCI_DEVICE_ID_PLX_1077		0x1077
++#define PCI_DEVICE_ID_PLX_SPCOM200	0x1103
++#define PCI_DEVICE_ID_PLX_DJINN_ITOO	0x1151
++#define PCI_DEVICE_ID_PLX_R753		0x1152
++#define PCI_DEVICE_ID_PLX_OLITEC	0x1187
++#define PCI_DEVICE_ID_PLX_PCI200SYN	0x3196
++#define PCI_DEVICE_ID_PLX_9030          0x9030
++#define PCI_DEVICE_ID_PLX_9050		0x9050
++#define PCI_DEVICE_ID_PLX_9080		0x9080
++#define PCI_DEVICE_ID_PLX_GTEK_SERIAL2	0xa001
++
++#define PCI_VENDOR_ID_MADGE		0x10b6
++#define PCI_DEVICE_ID_MADGE_MK2		0x0002
++
++#define PCI_VENDOR_ID_3COM		0x10b7
++#define PCI_DEVICE_ID_3COM_3C985	0x0001
++#define PCI_DEVICE_ID_3COM_3C940	0x1700
++#define PCI_DEVICE_ID_3COM_3C339	0x3390
++#define PCI_DEVICE_ID_3COM_3C359	0x3590
++#define PCI_DEVICE_ID_3COM_3C940B	0x80eb
++#define PCI_DEVICE_ID_3COM_3CR990	0x9900
++#define PCI_DEVICE_ID_3COM_3CR990_TX_95	0x9902
++#define PCI_DEVICE_ID_3COM_3CR990_TX_97	0x9903
++#define PCI_DEVICE_ID_3COM_3CR990B	0x9904
++#define PCI_DEVICE_ID_3COM_3CR990_FX	0x9905
++#define PCI_DEVICE_ID_3COM_3CR990SVR95	0x9908
++#define PCI_DEVICE_ID_3COM_3CR990SVR97	0x9909
++#define PCI_DEVICE_ID_3COM_3CR990SVR	0x990a
++
++#define PCI_VENDOR_ID_AL		0x10b9
++#define PCI_DEVICE_ID_AL_M1533		0x1533
++#define PCI_DEVICE_ID_AL_M1535 		0x1535
++#define PCI_DEVICE_ID_AL_M1541		0x1541
++#define PCI_DEVICE_ID_AL_M1563		0x1563
++#define PCI_DEVICE_ID_AL_M1621		0x1621
++#define PCI_DEVICE_ID_AL_M1631		0x1631
++#define PCI_DEVICE_ID_AL_M1632		0x1632
++#define PCI_DEVICE_ID_AL_M1641		0x1641
++#define PCI_DEVICE_ID_AL_M1644		0x1644
++#define PCI_DEVICE_ID_AL_M1647		0x1647
++#define PCI_DEVICE_ID_AL_M1651		0x1651
++#define PCI_DEVICE_ID_AL_M1671		0x1671
++#define PCI_DEVICE_ID_AL_M1681		0x1681
++#define PCI_DEVICE_ID_AL_M1683		0x1683
++#define PCI_DEVICE_ID_AL_M1689		0x1689
++#define PCI_DEVICE_ID_AL_M5219		0x5219
++#define PCI_DEVICE_ID_AL_M5228		0x5228
++#define PCI_DEVICE_ID_AL_M5229		0x5229
++#define PCI_DEVICE_ID_AL_M5451		0x5451
++#define PCI_DEVICE_ID_AL_M7101		0x7101
++
++#define PCI_VENDOR_ID_NEOMAGIC		0x10c8
++#define PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO 0x8005
++#define PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO 0x8006
++#define PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO 0x8016
++
++#define PCI_VENDOR_ID_TCONRAD		0x10da
++#define PCI_DEVICE_ID_TCONRAD_TOKENRING	0x0508
++
++#define PCI_VENDOR_ID_NVIDIA			0x10de
++#define PCI_DEVICE_ID_NVIDIA_TNT		0x0020
++#define PCI_DEVICE_ID_NVIDIA_TNT2		0x0028
++#define PCI_DEVICE_ID_NVIDIA_UTNT2		0x0029
++#define PCI_DEVICE_ID_NVIDIA_TNT_UNKNOWN        0x002a
++#define PCI_DEVICE_ID_NVIDIA_VTNT2		0x002C
++#define PCI_DEVICE_ID_NVIDIA_UVTNT2		0x002D
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS	0x0034
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE	0x0035
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA	0x0036
++#define PCI_DEVICE_ID_NVIDIA_NVENET_10		0x0037
++#define PCI_DEVICE_ID_NVIDIA_NVENET_11		0x0038
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SATA2	0x003e
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_ULTRA 0x0040
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800       0x0041
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_LE    0x0042
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800_GT    0x0045
++#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_4000     0x004E
++#define PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS	0x0052
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE	0x0053
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA	0x0054
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_SATA2	0x0055
++#define PCI_DEVICE_ID_NVIDIA_NVENET_8		0x0056
++#define PCI_DEVICE_ID_NVIDIA_NVENET_9		0x0057
++#define PCI_DEVICE_ID_NVIDIA_CK804_AUDIO	0x0059
++#define PCI_DEVICE_ID_NVIDIA_CK804_PCIE		0x005d
++#define PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS	0x0064
++#define PCI_DEVICE_ID_NVIDIA_NFORCE2_IDE	0x0065
++#define PCI_DEVICE_ID_NVIDIA_NVENET_2		0x0066
++#define PCI_DEVICE_ID_NVIDIA_MCP2_MODEM		0x0069
++#define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO		0x006a
++#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS	0x0084
++#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_IDE	0x0085
++#define PCI_DEVICE_ID_NVIDIA_NVENET_4		0x0086
++#define PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM	0x0089
++#define PCI_DEVICE_ID_NVIDIA_CK8_AUDIO		0x008a
++#define PCI_DEVICE_ID_NVIDIA_NVENET_5		0x008c
++#define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA	0x008e
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GT   0x0090
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GTX	0x0091
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800   0x0098
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800_GTX 0x0099
++#define PCI_DEVICE_ID_NVIDIA_ITNT2		0x00A0
++#define PCI_DEVICE_ID_GEFORCE_6800A             0x00c1
++#define PCI_DEVICE_ID_GEFORCE_6800A_LE          0x00c2
++#define PCI_DEVICE_ID_GEFORCE_GO_6800           0x00c8
++#define PCI_DEVICE_ID_GEFORCE_GO_6800_ULTRA     0x00c9
++#define PCI_DEVICE_ID_QUADRO_FX_GO1400          0x00cc
++#define PCI_DEVICE_ID_QUADRO_FX_1400            0x00ce
++#define PCI_DEVICE_ID_NVIDIA_NFORCE3		0x00d1
++#define PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS	0x00d4
++#define PCI_DEVICE_ID_NVIDIA_NFORCE3_IDE	0x00d5
++#define PCI_DEVICE_ID_NVIDIA_NVENET_3		0x00d6
++#define PCI_DEVICE_ID_NVIDIA_MCP3_MODEM		0x00d9
++#define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO		0x00da
++#define PCI_DEVICE_ID_NVIDIA_NVENET_7		0x00df
++#define PCI_DEVICE_ID_NVIDIA_NFORCE3S		0x00e1
++#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA	0x00e3
++#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS	0x00e4
++#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_IDE	0x00e5
++#define PCI_DEVICE_ID_NVIDIA_NVENET_6		0x00e6
++#define PCI_DEVICE_ID_NVIDIA_CK8S_AUDIO		0x00ea
++#define PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2	0x00ee
++#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_ALT1 0x00f0
++#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT1 0x00f1
++#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6600_ALT2 0x00f2
++#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6200_ALT1 0x00f3
++#define PCIE_DEVICE_ID_NVIDIA_GEFORCE_6800_GT   0x00f9
++#define PCIE_DEVICE_ID_NVIDIA_QUADRO_NVS280	0x00fd
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR	0x0100
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR	0x0101
++#define PCI_DEVICE_ID_NVIDIA_QUADRO		0x0103
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX	0x0110
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2	0x0111
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO	0x0112
++#define PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR	0x0113
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6600_GT	0x0140
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6600	0x0141
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6610_XL	0x0145
++#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_540	0x014E
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6200	0x014F
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS	0x0150
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2	0x0151
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA	0x0152
++#define PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO	0x0153
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6200_TURBOCACHE 0x0161
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200    0x0164
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250    0x0166
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6200_1  0x0167
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_6250_1  0x0168
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460	0x0170
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440	0x0171
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420	0x0172
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_SE	0x0173
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO	0x0174
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO	0x0175
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32 0x0176
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_460_GO    0x0177
++#define PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL	0x0178
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64 0x0179
++#define PCI_DEVICE_ID_NVIDIA_QUADRO4_200	0x017A
++#define PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL	0x017B
++#define PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL	0x017C
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_410_GO_M16 0x017D
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440_8X 0x0181
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440SE_8X 0x0182
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420_8X 0x0183
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_4000   0x0185
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_448_GO    0x0186
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_488_GO    0x0187
++#define PCI_DEVICE_ID_NVIDIA_QUADRO4_580_XGL    0x0188
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_MAC    0x0189
++#define PCI_DEVICE_ID_NVIDIA_QUADRO4_280_NVS    0x018A
++#define PCI_DEVICE_ID_NVIDIA_QUADRO4_380_XGL    0x018B
++#define PCI_DEVICE_ID_NVIDIA_IGEFORCE2		0x01a0
++#define PCI_DEVICE_ID_NVIDIA_NFORCE		0x01a4
++#define PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO		0x01b1
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS	0x01b4
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_IDE		0x01bc
++#define PCI_DEVICE_ID_NVIDIA_MCP1_MODEM		0x01c1
++#define PCI_DEVICE_ID_NVIDIA_NVENET_1		0x01c3
++#define PCI_DEVICE_ID_NVIDIA_NFORCE2		0x01e0
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE3		0x0200
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE3_1		0x0201
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE3_2		0x0202
++#define PCI_DEVICE_ID_NVIDIA_QUADRO_DDC		0x0203
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B      0x0211
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_LE   0x0212
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_GT   0x0215
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600	0x0250
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400	0x0251
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200	0x0253
++#define PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL	0x0258
++#define PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL	0x0259
++#define PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL	0x025B
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS	0x0264
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE	0x0265
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA	0x0266
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2	0x0267
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS	0x0368
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_IDE	0x036E
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA	0x037E
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SATA2	0x037F
++#define PCI_DEVICE_ID_NVIDIA_NVENET_12		0x0268
++#define PCI_DEVICE_ID_NVIDIA_NVENET_13		0x0269
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800	0x0280
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800_8X    0x0281
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800SE     0x0282
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_4200_GO       0x0286
++#define PCI_DEVICE_ID_NVIDIA_QUADRO4_980_XGL        0x0288
++#define PCI_DEVICE_ID_NVIDIA_QUADRO4_780_XGL        0x0289
++#define PCI_DEVICE_ID_NVIDIA_QUADRO4_700_GOGL       0x028C
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800_ULTRA  0x0301
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5800        0x0302
++#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_2000         0x0308
++#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1000         0x0309
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600_ULTRA  0x0311
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600        0x0312
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5600SE      0x0314
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5600      0x031A
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5650      0x031B
++#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO700        0x031C
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200        0x0320
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_ULTRA  0x0321
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200_1      0x0322
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5200SE      0x0323
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5200      0x0324
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250      0x0325
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5500        0x0326
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5100        0x0327
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5250_32   0x0328
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO_5200	    0x0329
++#define PCI_DEVICE_ID_NVIDIA_QUADRO_NVS_280_PCI     0x032A
++#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_500          0x032B
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5300      0x032C
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5100      0x032D
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900_ULTRA  0x0330
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900        0x0331
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900XT      0x0332
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5950_ULTRA  0x0333
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5900ZT      0x0334
++#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_3000         0x0338
++#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_700          0x033F
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700_ULTRA  0x0341
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700        0x0342
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700LE      0x0343
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_5700VE      0x0344
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_1    0x0347
++#define PCI_DEVICE_ID_NVIDIA_GEFORCE_FX_GO5700_2    0x0348
++#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_GO1000       0x034C
++#define PCI_DEVICE_ID_NVIDIA_QUADRO_FX_1100         0x034E
++#define PCI_DEVICE_ID_NVIDIA_NVENET_14              0x0372
++#define PCI_DEVICE_ID_NVIDIA_NVENET_15              0x0373
++#define PCI_DEVICE_ID_NVIDIA_NVENET_16              0x03E5
++#define PCI_DEVICE_ID_NVIDIA_NVENET_17              0x03E6
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA      0x03E7
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SMBUS	    0x03EB
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE       0x03EC
++#define PCI_DEVICE_ID_NVIDIA_NVENET_18              0x03EE
++#define PCI_DEVICE_ID_NVIDIA_NVENET_19              0x03EF
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA2     0x03F6
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SATA3     0x03F7
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_SMBUS	    0x0446
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE	    0x0448
++#define PCI_DEVICE_ID_NVIDIA_NVENET_20              0x0450
++#define PCI_DEVICE_ID_NVIDIA_NVENET_21              0x0451
++#define PCI_DEVICE_ID_NVIDIA_NVENET_22              0x0452
++#define PCI_DEVICE_ID_NVIDIA_NVENET_23              0x0453
++#define PCI_DEVICE_ID_NVIDIA_NVENET_24              0x054C
++#define PCI_DEVICE_ID_NVIDIA_NVENET_25              0x054D
++#define PCI_DEVICE_ID_NVIDIA_NVENET_26              0x054E
++#define PCI_DEVICE_ID_NVIDIA_NVENET_27              0x054F
++#define PCI_DEVICE_ID_NVIDIA_NVENET_28              0x07DC
++#define PCI_DEVICE_ID_NVIDIA_NVENET_29              0x07DD
++#define PCI_DEVICE_ID_NVIDIA_NVENET_30              0x07DE
++#define PCI_DEVICE_ID_NVIDIA_NVENET_31              0x07DF
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE       0x0560
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE       0x056C
++#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE       0x0759
++#define PCI_DEVICE_ID_NVIDIA_NVENET_32              0x0760
++#define PCI_DEVICE_ID_NVIDIA_NVENET_33              0x0761
++#define PCI_DEVICE_ID_NVIDIA_NVENET_34              0x0762
++#define PCI_DEVICE_ID_NVIDIA_NVENET_35              0x0763
++#define PCI_DEVICE_ID_NVIDIA_NVENET_36              0x0AB0
++#define PCI_DEVICE_ID_NVIDIA_NVENET_37              0x0AB1
++#define PCI_DEVICE_ID_NVIDIA_NVENET_38              0x0AB2
++#define PCI_DEVICE_ID_NVIDIA_NVENET_39              0x0AB3
++
++#define PCI_VENDOR_ID_IMS		0x10e0
++#define PCI_DEVICE_ID_IMS_TT128		0x9128
++#define PCI_DEVICE_ID_IMS_TT3D		0x9135
++
++#define PCI_VENDOR_ID_INTERG		0x10ea
++#define PCI_DEVICE_ID_INTERG_1682	0x1682
++#define PCI_DEVICE_ID_INTERG_2000	0x2000
++#define PCI_DEVICE_ID_INTERG_2010	0x2010
++#define PCI_DEVICE_ID_INTERG_5000	0x5000
++#define PCI_DEVICE_ID_INTERG_5050	0x5050
++
++#define PCI_VENDOR_ID_REALTEK		0x10ec
++#define PCI_DEVICE_ID_REALTEK_8139	0x8139
++
++#define PCI_VENDOR_ID_XILINX		0x10ee
++#define PCI_DEVICE_ID_RME_DIGI96	0x3fc0
++#define PCI_DEVICE_ID_RME_DIGI96_8	0x3fc1
++#define PCI_DEVICE_ID_RME_DIGI96_8_PRO	0x3fc2
++#define PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST 0x3fc3
++#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP 0x3fc5
++#define PCI_DEVICE_ID_XILINX_HAMMERFALL_DSP_MADI 0x3fc6
++
++#define PCI_VENDOR_ID_INIT		0x1101
++
++#define PCI_VENDOR_ID_CREATIVE		0x1102 /* duplicate: ECTIVA */
++#define PCI_DEVICE_ID_CREATIVE_EMU10K1	0x0002
++
++#define PCI_VENDOR_ID_ECTIVA		0x1102 /* duplicate: CREATIVE */
++#define PCI_DEVICE_ID_ECTIVA_EV1938	0x8938
++
++#define PCI_VENDOR_ID_TTI		0x1103
++#define PCI_DEVICE_ID_TTI_HPT343	0x0003
++#define PCI_DEVICE_ID_TTI_HPT366	0x0004
++#define PCI_DEVICE_ID_TTI_HPT372	0x0005
++#define PCI_DEVICE_ID_TTI_HPT302	0x0006
++#define PCI_DEVICE_ID_TTI_HPT371	0x0007
++#define PCI_DEVICE_ID_TTI_HPT374	0x0008
++#define PCI_DEVICE_ID_TTI_HPT372N	0x0009	/* apparently a 372N variant? */
++
++#define PCI_VENDOR_ID_VIA		0x1106
++#define PCI_DEVICE_ID_VIA_8763_0	0x0198
++#define PCI_DEVICE_ID_VIA_8380_0	0x0204
++#define PCI_DEVICE_ID_VIA_3238_0	0x0238
++#define PCI_DEVICE_ID_VIA_PT880		0x0258
++#define PCI_DEVICE_ID_VIA_PT880ULTRA	0x0308
++#define PCI_DEVICE_ID_VIA_PX8X0_0	0x0259
++#define PCI_DEVICE_ID_VIA_3269_0	0x0269
++#define PCI_DEVICE_ID_VIA_K8T800PRO_0	0x0282
++#define PCI_DEVICE_ID_VIA_3296_0	0x0296
++#define PCI_DEVICE_ID_VIA_8363_0	0x0305
++#define PCI_DEVICE_ID_VIA_P4M800CE	0x0314
++#define PCI_DEVICE_ID_VIA_P4M890	0x0327
++#define PCI_DEVICE_ID_VIA_VT3324	0x0324
++#define PCI_DEVICE_ID_VIA_VT3336	0x0336
++#define PCI_DEVICE_ID_VIA_VT3351	0x0351
++#define PCI_DEVICE_ID_VIA_VT3364	0x0364
++#define PCI_DEVICE_ID_VIA_8371_0	0x0391
++#define PCI_DEVICE_ID_VIA_8501_0	0x0501
++#define PCI_DEVICE_ID_VIA_82C561	0x0561
++#define PCI_DEVICE_ID_VIA_82C586_1	0x0571
++#define PCI_DEVICE_ID_VIA_82C576	0x0576
++#define PCI_DEVICE_ID_VIA_82C586_0	0x0586
++#define PCI_DEVICE_ID_VIA_82C596	0x0596
++#define PCI_DEVICE_ID_VIA_82C597_0	0x0597
++#define PCI_DEVICE_ID_VIA_82C598_0	0x0598
++#define PCI_DEVICE_ID_VIA_8601_0	0x0601
++#define PCI_DEVICE_ID_VIA_8605_0	0x0605
++#define PCI_DEVICE_ID_VIA_82C686	0x0686
++#define PCI_DEVICE_ID_VIA_82C691_0	0x0691
++#define PCI_DEVICE_ID_VIA_82C576_1	0x1571
++#define PCI_DEVICE_ID_VIA_82C586_2	0x3038
++#define PCI_DEVICE_ID_VIA_82C586_3	0x3040
++#define PCI_DEVICE_ID_VIA_82C596_3	0x3050
++#define PCI_DEVICE_ID_VIA_82C596B_3	0x3051
++#define PCI_DEVICE_ID_VIA_82C686_4	0x3057
++#define PCI_DEVICE_ID_VIA_82C686_5	0x3058
++#define PCI_DEVICE_ID_VIA_8233_5	0x3059
++#define PCI_DEVICE_ID_VIA_8233_0	0x3074
++#define PCI_DEVICE_ID_VIA_8633_0	0x3091
++#define PCI_DEVICE_ID_VIA_8367_0	0x3099
++#define PCI_DEVICE_ID_VIA_8653_0	0x3101
++#define PCI_DEVICE_ID_VIA_8622		0x3102
++#define PCI_DEVICE_ID_VIA_8235_USB_2	0x3104
++#define PCI_DEVICE_ID_VIA_8233C_0	0x3109
++#define PCI_DEVICE_ID_VIA_8361		0x3112
++#define PCI_DEVICE_ID_VIA_XM266		0x3116
++#define PCI_DEVICE_ID_VIA_612X		0x3119
++#define PCI_DEVICE_ID_VIA_862X_0	0x3123
++#define PCI_DEVICE_ID_VIA_8753_0	0x3128
++#define PCI_DEVICE_ID_VIA_8233A		0x3147
++#define PCI_DEVICE_ID_VIA_8703_51_0	0x3148
++#define PCI_DEVICE_ID_VIA_8237_SATA	0x3149
++#define PCI_DEVICE_ID_VIA_XN266		0x3156
++#define PCI_DEVICE_ID_VIA_6410		0x3164
++#define PCI_DEVICE_ID_VIA_8754C_0	0x3168
++#define PCI_DEVICE_ID_VIA_8235		0x3177
++#define PCI_DEVICE_ID_VIA_8385_0	0x3188
++#define PCI_DEVICE_ID_VIA_8377_0	0x3189
++#define PCI_DEVICE_ID_VIA_8378_0	0x3205
++#define PCI_DEVICE_ID_VIA_8783_0	0x3208
++#define PCI_DEVICE_ID_VIA_8237		0x3227
++#define PCI_DEVICE_ID_VIA_8251		0x3287
++#define PCI_DEVICE_ID_VIA_8237A		0x3337
++#define PCI_DEVICE_ID_VIA_8237S		0x3372
++#define PCI_DEVICE_ID_VIA_SATA_EIDE	0x5324
++#define PCI_DEVICE_ID_VIA_8231		0x8231
++#define PCI_DEVICE_ID_VIA_8231_4	0x8235
++#define PCI_DEVICE_ID_VIA_8365_1	0x8305
++#define PCI_DEVICE_ID_VIA_CX700		0x8324
++#define PCI_DEVICE_ID_VIA_CX700_IDE	0x0581
++#define PCI_DEVICE_ID_VIA_VX800		0x8353
++#define PCI_DEVICE_ID_VIA_8371_1	0x8391
++#define PCI_DEVICE_ID_VIA_82C598_1	0x8598
++#define PCI_DEVICE_ID_VIA_838X_1	0xB188
++#define PCI_DEVICE_ID_VIA_83_87XX_1	0xB198
++
++#define PCI_VENDOR_ID_SIEMENS           0x110A
++#define PCI_DEVICE_ID_SIEMENS_DSCC4     0x2102
++
++#define PCI_VENDOR_ID_VORTEX		0x1119
++#define PCI_DEVICE_ID_VORTEX_GDT60x0	0x0000
++#define PCI_DEVICE_ID_VORTEX_GDT6000B	0x0001
++#define PCI_DEVICE_ID_VORTEX_GDT6x10	0x0002
++#define PCI_DEVICE_ID_VORTEX_GDT6x20	0x0003
++#define PCI_DEVICE_ID_VORTEX_GDT6530	0x0004
++#define PCI_DEVICE_ID_VORTEX_GDT6550	0x0005
++#define PCI_DEVICE_ID_VORTEX_GDT6x17	0x0006
++#define PCI_DEVICE_ID_VORTEX_GDT6x27	0x0007
++#define PCI_DEVICE_ID_VORTEX_GDT6537	0x0008
++#define PCI_DEVICE_ID_VORTEX_GDT6557	0x0009
++#define PCI_DEVICE_ID_VORTEX_GDT6x15	0x000a
++#define PCI_DEVICE_ID_VORTEX_GDT6x25	0x000b
++#define PCI_DEVICE_ID_VORTEX_GDT6535	0x000c
++#define PCI_DEVICE_ID_VORTEX_GDT6555	0x000d
++#define PCI_DEVICE_ID_VORTEX_GDT6x17RP	0x0100
++#define PCI_DEVICE_ID_VORTEX_GDT6x27RP	0x0101
++#define PCI_DEVICE_ID_VORTEX_GDT6537RP	0x0102
++#define PCI_DEVICE_ID_VORTEX_GDT6557RP	0x0103
++#define PCI_DEVICE_ID_VORTEX_GDT6x11RP	0x0104
++#define PCI_DEVICE_ID_VORTEX_GDT6x21RP	0x0105
++
++#define PCI_VENDOR_ID_EF		0x111a
++#define PCI_DEVICE_ID_EF_ATM_FPGA	0x0000
++#define PCI_DEVICE_ID_EF_ATM_ASIC	0x0002
++#define PCI_DEVICE_ID_EF_ATM_LANAI2	0x0003
++#define PCI_DEVICE_ID_EF_ATM_LANAIHB	0x0005
++
++#define PCI_VENDOR_ID_IDT		0x111d
++#define PCI_DEVICE_ID_IDT_IDT77201	0x0001
++
++#define PCI_VENDOR_ID_FORE		0x1127
++#define PCI_DEVICE_ID_FORE_PCA200E	0x0300
++
++#define PCI_VENDOR_ID_PHILIPS		0x1131
++#define PCI_DEVICE_ID_PHILIPS_SAA7146	0x7146
++#define PCI_DEVICE_ID_PHILIPS_SAA9730	0x9730
++
++#define PCI_VENDOR_ID_EICON		0x1133
++#define PCI_DEVICE_ID_EICON_DIVA20	0xe002
++#define PCI_DEVICE_ID_EICON_DIVA20_U	0xe004
++#define PCI_DEVICE_ID_EICON_DIVA201	0xe005
++#define PCI_DEVICE_ID_EICON_DIVA202	0xe00b
++#define PCI_DEVICE_ID_EICON_MAESTRA	0xe010
++#define PCI_DEVICE_ID_EICON_MAESTRAQ	0xe012
++#define PCI_DEVICE_ID_EICON_MAESTRAQ_U	0xe013
++#define PCI_DEVICE_ID_EICON_MAESTRAP	0xe014
++
++#define PCI_VENDOR_ID_CISCO		0x1137
++
++#define PCI_VENDOR_ID_ZIATECH		0x1138
++#define PCI_DEVICE_ID_ZIATECH_5550_HC	0x5550
++ 
++
++#define PCI_VENDOR_ID_SYSKONNECT	0x1148
++#define PCI_DEVICE_ID_SYSKONNECT_TR	0x4200
++#define PCI_DEVICE_ID_SYSKONNECT_GE	0x4300
++#define PCI_DEVICE_ID_SYSKONNECT_YU	0x4320
++#define PCI_DEVICE_ID_SYSKONNECT_9DXX	0x4400
++#define PCI_DEVICE_ID_SYSKONNECT_9MXX	0x4500
++
++#define PCI_VENDOR_ID_DIGI		0x114f
++#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_E	0x0070
++#define PCI_DEVICE_ID_DIGI_DF_M_E	0x0071
++#define PCI_DEVICE_ID_DIGI_DF_M_IOM2_A	0x0072
++#define PCI_DEVICE_ID_DIGI_DF_M_A	0x0073
++#define PCI_DEVICE_ID_NEO_2DB9          0x00C8
++#define PCI_DEVICE_ID_NEO_2DB9PRI       0x00C9
++#define PCI_DEVICE_ID_NEO_2RJ45         0x00CA
++#define PCI_DEVICE_ID_NEO_2RJ45PRI      0x00CB
++#define PCIE_DEVICE_ID_NEO_4_IBM        0x00F4
++
++#define PCI_VENDOR_ID_XIRCOM		0x115d
++#define PCI_DEVICE_ID_XIRCOM_RBM56G	0x0101
++#define PCI_DEVICE_ID_XIRCOM_X3201_MDM	0x0103
++
++#define PCI_VENDOR_ID_SERVERWORKS	  0x1166
++#define PCI_DEVICE_ID_SERVERWORKS_HE	  0x0008
++#define PCI_DEVICE_ID_SERVERWORKS_LE	  0x0009
++#define PCI_DEVICE_ID_SERVERWORKS_GCNB_LE 0x0017
++#define PCI_DEVICE_ID_SERVERWORKS_HT1000_PXB	0x0036
++#define PCI_DEVICE_ID_SERVERWORKS_EPB	  0x0103
++#define PCI_DEVICE_ID_SERVERWORKS_HT2000_PCIE	0x0132
++#define PCI_DEVICE_ID_SERVERWORKS_OSB4	  0x0200
++#define PCI_DEVICE_ID_SERVERWORKS_CSB5	  0x0201
++#define PCI_DEVICE_ID_SERVERWORKS_CSB6    0x0203
++#define PCI_DEVICE_ID_SERVERWORKS_HT1000SB 0x0205
++#define PCI_DEVICE_ID_SERVERWORKS_OSB4IDE 0x0211
++#define PCI_DEVICE_ID_SERVERWORKS_CSB5IDE 0x0212
++#define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE 0x0213
++#define PCI_DEVICE_ID_SERVERWORKS_HT1000IDE 0x0214
++#define PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2 0x0217
++#define PCI_DEVICE_ID_SERVERWORKS_CSB6LPC 0x0227
++
++#define PCI_VENDOR_ID_SBE		0x1176
++#define PCI_DEVICE_ID_SBE_WANXL100	0x0301
++#define PCI_DEVICE_ID_SBE_WANXL200	0x0302
++#define PCI_DEVICE_ID_SBE_WANXL400	0x0104
++
++#define PCI_VENDOR_ID_TOSHIBA		0x1179
++#define PCI_DEVICE_ID_TOSHIBA_PICCOLO	0x0102
++#define PCI_DEVICE_ID_TOSHIBA_PICCOLO_1	0x0103
++#define PCI_DEVICE_ID_TOSHIBA_PICCOLO_2	0x0105
++#define PCI_DEVICE_ID_TOSHIBA_TOPIC95	0x060a
++#define PCI_DEVICE_ID_TOSHIBA_TOPIC97	0x060f
++#define PCI_DEVICE_ID_TOSHIBA_TOPIC100	0x0617
++
++#define PCI_VENDOR_ID_TOSHIBA_2		0x102f
++#define PCI_DEVICE_ID_TOSHIBA_TC35815CF	0x0030
++#define PCI_DEVICE_ID_TOSHIBA_TC35815_NWU	0x0031
++#define PCI_DEVICE_ID_TOSHIBA_TC35815_TX4939	0x0032
++#define PCI_DEVICE_ID_TOSHIBA_TC86C001_IDE	0x0105
++#define PCI_DEVICE_ID_TOSHIBA_TC86C001_MISC	0x0108
++#define PCI_DEVICE_ID_TOSHIBA_SPIDER_NET 0x01b3
++
++#define PCI_VENDOR_ID_ATTO		0x117c
++
++#define PCI_VENDOR_ID_RICOH		0x1180
++#define PCI_DEVICE_ID_RICOH_RL5C465	0x0465
++#define PCI_DEVICE_ID_RICOH_RL5C466	0x0466
++#define PCI_DEVICE_ID_RICOH_RL5C475	0x0475
++#define PCI_DEVICE_ID_RICOH_RL5C476	0x0476
++#define PCI_DEVICE_ID_RICOH_RL5C478	0x0478
++#define PCI_DEVICE_ID_RICOH_R5C822	0x0822
++#define PCI_DEVICE_ID_RICOH_R5C832	0x0832
++#define PCI_DEVICE_ID_RICOH_R5C843	0x0843
++
++#define PCI_VENDOR_ID_DLINK		0x1186
++#define PCI_DEVICE_ID_DLINK_DGE510T	0x4c00
++
++#define PCI_VENDOR_ID_ARTOP		0x1191
++#define PCI_DEVICE_ID_ARTOP_ATP850UF	0x0005
++#define PCI_DEVICE_ID_ARTOP_ATP860	0x0006
++#define PCI_DEVICE_ID_ARTOP_ATP860R	0x0007
++#define PCI_DEVICE_ID_ARTOP_ATP865	0x0008
++#define PCI_DEVICE_ID_ARTOP_ATP865R	0x0009
++#define PCI_DEVICE_ID_ARTOP_AEC7610	0x8002
++#define PCI_DEVICE_ID_ARTOP_AEC7612UW	0x8010
++#define PCI_DEVICE_ID_ARTOP_AEC7612U	0x8020
++#define PCI_DEVICE_ID_ARTOP_AEC7612S	0x8030
++#define PCI_DEVICE_ID_ARTOP_AEC7612D	0x8040
++#define PCI_DEVICE_ID_ARTOP_AEC7612SUW	0x8050
++#define PCI_DEVICE_ID_ARTOP_8060	0x8060
++
++#define PCI_VENDOR_ID_ZEITNET		0x1193
++#define PCI_DEVICE_ID_ZEITNET_1221	0x0001
++#define PCI_DEVICE_ID_ZEITNET_1225	0x0002
++
++#define PCI_VENDOR_ID_FUJITSU_ME	0x119e
++#define PCI_DEVICE_ID_FUJITSU_FS155	0x0001
++#define PCI_DEVICE_ID_FUJITSU_FS50	0x0003
++
++#define PCI_SUBVENDOR_ID_KEYSPAN	0x11a9
++#define PCI_SUBDEVICE_ID_KEYSPAN_SX2	0x5334
++
++#define PCI_VENDOR_ID_MARVELL		0x11ab
++#define PCI_DEVICE_ID_MARVELL_GT64111	0x4146
++#define PCI_DEVICE_ID_MARVELL_GT64260	0x6430
++#define PCI_DEVICE_ID_MARVELL_MV64360	0x6460
++#define PCI_DEVICE_ID_MARVELL_MV64460	0x6480
++#define PCI_DEVICE_ID_MARVELL_88ALP01_NAND	0x4100
++#define PCI_DEVICE_ID_MARVELL_88ALP01_SD	0x4101
++#define PCI_DEVICE_ID_MARVELL_88ALP01_CCIC	0x4102
++
++#define PCI_VENDOR_ID_V3		0x11b0
++#define PCI_DEVICE_ID_V3_V960		0x0001
++#define PCI_DEVICE_ID_V3_V351		0x0002
++
++#define PCI_VENDOR_ID_ATT		0x11c1
++#define PCI_DEVICE_ID_ATT_VENUS_MODEM	0x480
++
++#define PCI_VENDOR_ID_SPECIALIX		0x11cb
++#define PCI_DEVICE_ID_SPECIALIX_IO8	0x2000
++#define PCI_DEVICE_ID_SPECIALIX_RIO	0x8000
++#define PCI_SUBDEVICE_ID_SPECIALIX_SPEED4 0xa004
++
++#define PCI_VENDOR_ID_ANALOG_DEVICES	0x11d4
++#define PCI_DEVICE_ID_AD1889JS		0x1889
++
++#define PCI_DEVICE_ID_SEGA_BBA		0x1234
++
++#define PCI_VENDOR_ID_ZORAN		0x11de
++#define PCI_DEVICE_ID_ZORAN_36057	0x6057
++#define PCI_DEVICE_ID_ZORAN_36120	0x6120
++
++#define PCI_VENDOR_ID_COMPEX		0x11f6
++#define PCI_DEVICE_ID_COMPEX_ENET100VG4	0x0112
++
++#define PCI_VENDOR_ID_RP		0x11fe
++#define PCI_DEVICE_ID_RP32INTF		0x0001
++#define PCI_DEVICE_ID_RP8INTF		0x0002
++#define PCI_DEVICE_ID_RP16INTF		0x0003
++#define PCI_DEVICE_ID_RP4QUAD		0x0004
++#define PCI_DEVICE_ID_RP8OCTA		0x0005
++#define PCI_DEVICE_ID_RP8J		0x0006
++#define PCI_DEVICE_ID_RP4J		0x0007
++#define PCI_DEVICE_ID_RP8SNI		0x0008	
++#define PCI_DEVICE_ID_RP16SNI		0x0009	
++#define PCI_DEVICE_ID_RPP4		0x000A
++#define PCI_DEVICE_ID_RPP8		0x000B
++#define PCI_DEVICE_ID_RP4M		0x000D
++#define PCI_DEVICE_ID_RP2_232		0x000E
++#define PCI_DEVICE_ID_RP2_422		0x000F
++#define PCI_DEVICE_ID_URP32INTF		0x0801
++#define PCI_DEVICE_ID_URP8INTF		0x0802
++#define PCI_DEVICE_ID_URP16INTF		0x0803
++#define PCI_DEVICE_ID_URP8OCTA		0x0805
++#define PCI_DEVICE_ID_UPCI_RM3_8PORT	0x080C       
++#define PCI_DEVICE_ID_UPCI_RM3_4PORT	0x080D
++#define PCI_DEVICE_ID_CRP16INTF		0x0903       
++
++#define PCI_VENDOR_ID_CYCLADES		0x120e
++#define PCI_DEVICE_ID_CYCLOM_Y_Lo	0x0100
++#define PCI_DEVICE_ID_CYCLOM_Y_Hi	0x0101
++#define PCI_DEVICE_ID_CYCLOM_4Y_Lo	0x0102
++#define PCI_DEVICE_ID_CYCLOM_4Y_Hi	0x0103
++#define PCI_DEVICE_ID_CYCLOM_8Y_Lo	0x0104
++#define PCI_DEVICE_ID_CYCLOM_8Y_Hi	0x0105
++#define PCI_DEVICE_ID_CYCLOM_Z_Lo	0x0200
++#define PCI_DEVICE_ID_CYCLOM_Z_Hi	0x0201
++#define PCI_DEVICE_ID_PC300_RX_2	0x0300
++#define PCI_DEVICE_ID_PC300_RX_1	0x0301
++#define PCI_DEVICE_ID_PC300_TE_2	0x0310
++#define PCI_DEVICE_ID_PC300_TE_1	0x0311
++#define PCI_DEVICE_ID_PC300_TE_M_2	0x0320
++#define PCI_DEVICE_ID_PC300_TE_M_1	0x0321
++
++#define PCI_VENDOR_ID_ESSENTIAL		0x120f
++#define PCI_DEVICE_ID_ESSENTIAL_ROADRUNNER	0x0001
++
++#define PCI_VENDOR_ID_O2		0x1217
++#define PCI_DEVICE_ID_O2_6729		0x6729
++#define PCI_DEVICE_ID_O2_6730		0x673a
++#define PCI_DEVICE_ID_O2_6832		0x6832
++#define PCI_DEVICE_ID_O2_6836		0x6836
++
++#define PCI_VENDOR_ID_3DFX		0x121a
++#define PCI_DEVICE_ID_3DFX_VOODOO	0x0001
++#define PCI_DEVICE_ID_3DFX_VOODOO2	0x0002
++#define PCI_DEVICE_ID_3DFX_BANSHEE	0x0003
++#define PCI_DEVICE_ID_3DFX_VOODOO3	0x0005
++#define PCI_DEVICE_ID_3DFX_VOODOO5	0x0009
++
++#define PCI_VENDOR_ID_AVM		0x1244
++#define PCI_DEVICE_ID_AVM_B1		0x0700
++#define PCI_DEVICE_ID_AVM_C4		0x0800
++#define PCI_DEVICE_ID_AVM_A1		0x0a00
++#define PCI_DEVICE_ID_AVM_A1_V2		0x0e00
++#define PCI_DEVICE_ID_AVM_C2		0x1100
++#define PCI_DEVICE_ID_AVM_T1		0x1200
++
++#define PCI_VENDOR_ID_STALLION		0x124d
++
++/* Allied Telesyn */
++#define PCI_VENDOR_ID_AT    		0x1259
++#define PCI_SUBDEVICE_ID_AT_2700FX	0x2701
++#define PCI_SUBDEVICE_ID_AT_2701FX	0x2703
++
++#define PCI_VENDOR_ID_ESS		0x125d
++#define PCI_DEVICE_ID_ESS_ESS1968	0x1968
++#define PCI_DEVICE_ID_ESS_ESS1978	0x1978
++#define PCI_DEVICE_ID_ESS_ALLEGRO_1	0x1988
++#define PCI_DEVICE_ID_ESS_ALLEGRO	0x1989
++#define PCI_DEVICE_ID_ESS_CANYON3D_2LE	0x1990
++#define PCI_DEVICE_ID_ESS_CANYON3D_2	0x1992
++#define PCI_DEVICE_ID_ESS_MAESTRO3	0x1998
++#define PCI_DEVICE_ID_ESS_MAESTRO3_1	0x1999
++#define PCI_DEVICE_ID_ESS_MAESTRO3_HW	0x199a
++#define PCI_DEVICE_ID_ESS_MAESTRO3_2	0x199b
++
++#define PCI_VENDOR_ID_SATSAGEM		0x1267
++#define PCI_DEVICE_ID_SATSAGEM_NICCY	0x1016
++
++#define PCI_VENDOR_ID_ENSONIQ		0x1274
++#define PCI_DEVICE_ID_ENSONIQ_CT5880	0x5880
++#define PCI_DEVICE_ID_ENSONIQ_ES1370	0x5000
++#define PCI_DEVICE_ID_ENSONIQ_ES1371	0x1371
++
++#define PCI_VENDOR_ID_TRANSMETA		0x1279
++#define PCI_DEVICE_ID_EFFICEON		0x0060
++
++#define PCI_VENDOR_ID_ROCKWELL		0x127A
++
++#define PCI_VENDOR_ID_ITE		0x1283
++#define PCI_DEVICE_ID_ITE_8211		0x8211
++#define PCI_DEVICE_ID_ITE_8212		0x8212
++#define PCI_DEVICE_ID_ITE_8213		0x8213
++#define PCI_DEVICE_ID_ITE_8152		0x8152
++#define PCI_DEVICE_ID_ITE_8872		0x8872
++#define PCI_DEVICE_ID_ITE_IT8330G_0	0xe886
++
++/* formerly Platform Tech */
++#define PCI_DEVICE_ID_ESS_ESS0100	0x0100
++
++#define PCI_VENDOR_ID_ALTEON		0x12ae
++
++#define PCI_SUBVENDOR_ID_CONNECT_TECH			0x12c4
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232		0x0001
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232		0x0002
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232		0x0003
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485		0x0004
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4	0x0005
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485		0x0006
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2	0x0007
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485		0x0008
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_2_6	0x0009
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1	0x000A
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1	0x000B
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_20MHZ		0x000C
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_PTM		0x000D
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_NT960PCI		0x0100
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_2		0x0201
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_4		0x0202
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_232	0x0300
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_232	0x0301
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_232	0x0302
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_1_1	0x0310
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_2	0x0311
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_4	0x0312
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2	0x0320
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4	0x0321
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8	0x0322
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_2_485	0x0330
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_4_485	0x0331
++#define PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_485	0x0332
++
++#define PCI_VENDOR_ID_NVIDIA_SGS	0x12d2
++#define PCI_DEVICE_ID_NVIDIA_SGS_RIVA128 0x0018
++
++#define PCI_SUBVENDOR_ID_CHASE_PCIFAST		0x12E0
++#define PCI_SUBDEVICE_ID_CHASE_PCIFAST4		0x0031
++#define PCI_SUBDEVICE_ID_CHASE_PCIFAST8		0x0021
++#define PCI_SUBDEVICE_ID_CHASE_PCIFAST16	0x0011
++#define PCI_SUBDEVICE_ID_CHASE_PCIFAST16FMC	0x0041
++#define PCI_SUBVENDOR_ID_CHASE_PCIRAS		0x124D
++#define PCI_SUBDEVICE_ID_CHASE_PCIRAS4		0xF001
++#define PCI_SUBDEVICE_ID_CHASE_PCIRAS8		0xF010
++
++#define PCI_VENDOR_ID_AUREAL		0x12eb
++#define PCI_DEVICE_ID_AUREAL_VORTEX_1	0x0001
++#define PCI_DEVICE_ID_AUREAL_VORTEX_2	0x0002
++#define PCI_DEVICE_ID_AUREAL_ADVANTAGE	0x0003
++
++#define PCI_VENDOR_ID_ELECTRONICDESIGNGMBH 0x12f8
++#define PCI_DEVICE_ID_LML_33R10		0x8a02
++
++#define PCI_VENDOR_ID_ESDGMBH		0x12fe
++#define PCI_DEVICE_ID_ESDGMBH_CPCIASIO4 0x0111
++
++#define PCI_VENDOR_ID_SIIG		0x131f
++#define PCI_SUBVENDOR_ID_SIIG		0x131f
++#define PCI_DEVICE_ID_SIIG_1S_10x_550	0x1000
++#define PCI_DEVICE_ID_SIIG_1S_10x_650	0x1001
++#define PCI_DEVICE_ID_SIIG_1S_10x_850	0x1002
++#define PCI_DEVICE_ID_SIIG_1S1P_10x_550	0x1010
++#define PCI_DEVICE_ID_SIIG_1S1P_10x_650	0x1011
++#define PCI_DEVICE_ID_SIIG_1S1P_10x_850	0x1012
++#define PCI_DEVICE_ID_SIIG_1P_10x	0x1020
++#define PCI_DEVICE_ID_SIIG_2P_10x	0x1021
++#define PCI_DEVICE_ID_SIIG_2S_10x_550	0x1030
++#define PCI_DEVICE_ID_SIIG_2S_10x_650	0x1031
++#define PCI_DEVICE_ID_SIIG_2S_10x_850	0x1032
++#define PCI_DEVICE_ID_SIIG_2S1P_10x_550	0x1034
++#define PCI_DEVICE_ID_SIIG_2S1P_10x_650	0x1035
++#define PCI_DEVICE_ID_SIIG_2S1P_10x_850	0x1036
++#define PCI_DEVICE_ID_SIIG_4S_10x_550	0x1050
++#define PCI_DEVICE_ID_SIIG_4S_10x_650	0x1051
++#define PCI_DEVICE_ID_SIIG_4S_10x_850	0x1052
++#define PCI_DEVICE_ID_SIIG_1S_20x_550	0x2000
++#define PCI_DEVICE_ID_SIIG_1S_20x_650	0x2001
++#define PCI_DEVICE_ID_SIIG_1S_20x_850	0x2002
++#define PCI_DEVICE_ID_SIIG_1P_20x	0x2020
++#define PCI_DEVICE_ID_SIIG_2P_20x	0x2021
++#define PCI_DEVICE_ID_SIIG_2S_20x_550	0x2030
++#define PCI_DEVICE_ID_SIIG_2S_20x_650	0x2031
++#define PCI_DEVICE_ID_SIIG_2S_20x_850	0x2032
++#define PCI_DEVICE_ID_SIIG_2P1S_20x_550	0x2040
++#define PCI_DEVICE_ID_SIIG_2P1S_20x_650	0x2041
++#define PCI_DEVICE_ID_SIIG_2P1S_20x_850	0x2042
++#define PCI_DEVICE_ID_SIIG_1S1P_20x_550	0x2010
++#define PCI_DEVICE_ID_SIIG_1S1P_20x_650	0x2011
++#define PCI_DEVICE_ID_SIIG_1S1P_20x_850	0x2012
++#define PCI_DEVICE_ID_SIIG_4S_20x_550	0x2050
++#define PCI_DEVICE_ID_SIIG_4S_20x_650	0x2051
++#define PCI_DEVICE_ID_SIIG_4S_20x_850	0x2052
++#define PCI_DEVICE_ID_SIIG_2S1P_20x_550	0x2060
++#define PCI_DEVICE_ID_SIIG_2S1P_20x_650	0x2061
++#define PCI_DEVICE_ID_SIIG_2S1P_20x_850	0x2062
++#define PCI_DEVICE_ID_SIIG_8S_20x_550	0x2080
++#define PCI_DEVICE_ID_SIIG_8S_20x_650	0x2081
++#define PCI_DEVICE_ID_SIIG_8S_20x_850	0x2082
++#define PCI_SUBDEVICE_ID_SIIG_QUARTET_SERIAL	0x2050
++
++#define PCI_VENDOR_ID_RADISYS		0x1331
++
++#define PCI_VENDOR_ID_MICRO_MEMORY		0x1332
++#define PCI_DEVICE_ID_MICRO_MEMORY_5415CN	0x5415
++#define PCI_DEVICE_ID_MICRO_MEMORY_5425CN	0x5425
++#define PCI_DEVICE_ID_MICRO_MEMORY_6155		0x6155
++
++#define PCI_VENDOR_ID_DOMEX		0x134a
++#define PCI_DEVICE_ID_DOMEX_DMX3191D	0x0001
++
++#define PCI_VENDOR_ID_INTASHIELD	0x135a
++#define PCI_DEVICE_ID_INTASHIELD_IS200	0x0d80
++#define PCI_DEVICE_ID_INTASHIELD_IS400	0x0dc0
++
++#define PCI_VENDOR_ID_QUATECH		0x135C
++#define PCI_DEVICE_ID_QUATECH_QSC100	0x0010
++#define PCI_DEVICE_ID_QUATECH_DSC100	0x0020
++#define PCI_DEVICE_ID_QUATECH_ESC100D	0x0050
++#define PCI_DEVICE_ID_QUATECH_ESC100M	0x0060
++#define PCI_DEVICE_ID_QUATECH_SPPXP_100 0x0278
++
++#define PCI_VENDOR_ID_SEALEVEL		0x135e
++#define PCI_DEVICE_ID_SEALEVEL_U530	0x7101
++#define PCI_DEVICE_ID_SEALEVEL_UCOMM2	0x7201
++#define PCI_DEVICE_ID_SEALEVEL_UCOMM422	0x7402
++#define PCI_DEVICE_ID_SEALEVEL_UCOMM232	0x7202
++#define PCI_DEVICE_ID_SEALEVEL_COMM4	0x7401
++#define PCI_DEVICE_ID_SEALEVEL_COMM8	0x7801
++#define PCI_DEVICE_ID_SEALEVEL_UCOMM8	0x7804
++
++#define PCI_VENDOR_ID_HYPERCOPE		0x1365
++#define PCI_DEVICE_ID_HYPERCOPE_PLX	0x9050
++#define PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO	0x0104
++#define PCI_SUBDEVICE_ID_HYPERCOPE_ERGO		0x0106
++#define PCI_SUBDEVICE_ID_HYPERCOPE_METRO	0x0107
++#define PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2	0x0108
++
++#define PCI_VENDOR_ID_KAWASAKI		0x136b
++#define PCI_DEVICE_ID_MCHIP_KL5A72002	0xff01
++
++#define PCI_VENDOR_ID_CNET		0x1371
++#define PCI_DEVICE_ID_CNET_GIGACARD	0x434e
++
++#define PCI_VENDOR_ID_LMC		0x1376
++#define PCI_DEVICE_ID_LMC_HSSI		0x0003
++#define PCI_DEVICE_ID_LMC_DS3		0x0004
++#define PCI_DEVICE_ID_LMC_SSI		0x0005
++#define PCI_DEVICE_ID_LMC_T1		0x0006
++
++#define PCI_VENDOR_ID_NETGEAR		0x1385
++#define PCI_DEVICE_ID_NETGEAR_GA620	0x620a
++
++#define PCI_VENDOR_ID_APPLICOM		0x1389
++#define PCI_DEVICE_ID_APPLICOM_PCIGENERIC 0x0001
++#define PCI_DEVICE_ID_APPLICOM_PCI2000IBS_CAN 0x0002
++#define PCI_DEVICE_ID_APPLICOM_PCI2000PFB 0x0003
++
++#define PCI_VENDOR_ID_MOXA		0x1393
++#define PCI_DEVICE_ID_MOXA_RC7000	0x0001
++#define PCI_DEVICE_ID_MOXA_CP102	0x1020
++#define PCI_DEVICE_ID_MOXA_CP102UL	0x1021
++#define PCI_DEVICE_ID_MOXA_CP102U	0x1022
++#define PCI_DEVICE_ID_MOXA_C104		0x1040
++#define PCI_DEVICE_ID_MOXA_CP104U	0x1041
++#define PCI_DEVICE_ID_MOXA_CP104JU	0x1042
++#define PCI_DEVICE_ID_MOXA_CP104EL	0x1043
++#define PCI_DEVICE_ID_MOXA_CT114	0x1140
++#define PCI_DEVICE_ID_MOXA_CP114	0x1141
++#define PCI_DEVICE_ID_MOXA_CP118U	0x1180
++#define PCI_DEVICE_ID_MOXA_CP118EL	0x1181
++#define PCI_DEVICE_ID_MOXA_CP132	0x1320
++#define PCI_DEVICE_ID_MOXA_CP132U	0x1321
++#define PCI_DEVICE_ID_MOXA_CP134U	0x1340
++#define PCI_DEVICE_ID_MOXA_C168		0x1680
++#define PCI_DEVICE_ID_MOXA_CP168U	0x1681
++#define PCI_DEVICE_ID_MOXA_CP168EL	0x1682
++#define PCI_DEVICE_ID_MOXA_CP204J	0x2040
++#define PCI_DEVICE_ID_MOXA_C218		0x2180
++#define PCI_DEVICE_ID_MOXA_C320		0x3200
++
++#define PCI_VENDOR_ID_CCD		0x1397
++#define PCI_DEVICE_ID_CCD_HFC4S		0x08B4
++#define PCI_SUBDEVICE_ID_CCD_PMX2S	0x1234
++#define PCI_DEVICE_ID_CCD_HFC8S		0x16B8
++#define PCI_DEVICE_ID_CCD_2BD0		0x2bd0
++#define PCI_DEVICE_ID_CCD_HFCE1		0x30B1
++#define PCI_SUBDEVICE_ID_CCD_SPD4S	0x3136
++#define PCI_SUBDEVICE_ID_CCD_SPDE1	0x3137
++#define PCI_DEVICE_ID_CCD_B000		0xb000
++#define PCI_DEVICE_ID_CCD_B006		0xb006
++#define PCI_DEVICE_ID_CCD_B007		0xb007
++#define PCI_DEVICE_ID_CCD_B008		0xb008
++#define PCI_DEVICE_ID_CCD_B009		0xb009
++#define PCI_DEVICE_ID_CCD_B00A		0xb00a
++#define PCI_DEVICE_ID_CCD_B00B		0xb00b
++#define PCI_DEVICE_ID_CCD_B00C		0xb00c
++#define PCI_DEVICE_ID_CCD_B100		0xb100
++#define PCI_SUBDEVICE_ID_CCD_IOB4ST	0xB520
++#define PCI_SUBDEVICE_ID_CCD_IOB8STR	0xB521
++#define PCI_SUBDEVICE_ID_CCD_IOB8ST	0xB522
++#define PCI_SUBDEVICE_ID_CCD_IOB1E1	0xB523
++#define PCI_SUBDEVICE_ID_CCD_SWYX4S	0xB540
++#define PCI_SUBDEVICE_ID_CCD_JH4S20	0xB550
++#define PCI_SUBDEVICE_ID_CCD_IOB8ST_1	0xB552
++#define PCI_SUBDEVICE_ID_CCD_BN4S	0xB560
++#define PCI_SUBDEVICE_ID_CCD_BN8S	0xB562
++#define PCI_SUBDEVICE_ID_CCD_BNE1	0xB563
++#define PCI_SUBDEVICE_ID_CCD_BNE1D	0xB564
++#define PCI_SUBDEVICE_ID_CCD_BNE1DP	0xB565
++#define PCI_SUBDEVICE_ID_CCD_BN2S	0xB566
++#define PCI_SUBDEVICE_ID_CCD_BN1SM	0xB567
++#define PCI_SUBDEVICE_ID_CCD_BN4SM	0xB568
++#define PCI_SUBDEVICE_ID_CCD_BN2SM	0xB569
++#define PCI_SUBDEVICE_ID_CCD_BNE1M	0xB56A
++#define PCI_SUBDEVICE_ID_CCD_BN8SP	0xB56B
++#define PCI_SUBDEVICE_ID_CCD_HFC4S	0xB620
++#define PCI_SUBDEVICE_ID_CCD_HFC8S	0xB622
++#define PCI_DEVICE_ID_CCD_B700		0xb700
++#define PCI_DEVICE_ID_CCD_B701		0xb701
++#define PCI_SUBDEVICE_ID_CCD_HFCE1	0xC523
++#define PCI_SUBDEVICE_ID_CCD_OV2S	0xE884
++#define PCI_SUBDEVICE_ID_CCD_OV4S	0xE888
++#define PCI_SUBDEVICE_ID_CCD_OV8S	0xE998
++
++#define PCI_VENDOR_ID_EXAR		0x13a8
++#define PCI_DEVICE_ID_EXAR_XR17C152	0x0152
++#define PCI_DEVICE_ID_EXAR_XR17C154	0x0154
++#define PCI_DEVICE_ID_EXAR_XR17C158	0x0158
++
++#define PCI_VENDOR_ID_MICROGATE		0x13c0
++#define PCI_DEVICE_ID_MICROGATE_USC	0x0010
++#define PCI_DEVICE_ID_MICROGATE_SCA	0x0030
++
++#define PCI_VENDOR_ID_3WARE		0x13C1
++#define PCI_DEVICE_ID_3WARE_1000	0x1000
++#define PCI_DEVICE_ID_3WARE_7000	0x1001
++#define PCI_DEVICE_ID_3WARE_9000	0x1002
++
++#define PCI_VENDOR_ID_IOMEGA		0x13ca
++#define PCI_DEVICE_ID_IOMEGA_BUZ	0x4231
++
++#define PCI_VENDOR_ID_ABOCOM		0x13D1
++#define PCI_DEVICE_ID_ABOCOM_2BD1       0x2BD1
++
++#define PCI_VENDOR_ID_SUNDANCE		0x13f0
++
++#define PCI_VENDOR_ID_CMEDIA		0x13f6
++#define PCI_DEVICE_ID_CMEDIA_CM8338A	0x0100
++#define PCI_DEVICE_ID_CMEDIA_CM8338B	0x0101
++#define PCI_DEVICE_ID_CMEDIA_CM8738	0x0111
++#define PCI_DEVICE_ID_CMEDIA_CM8738B	0x0112
++
++#define PCI_VENDOR_ID_LAVA		0x1407
++#define PCI_DEVICE_ID_LAVA_DSERIAL	0x0100 /* 2x 16550 */
++#define PCI_DEVICE_ID_LAVA_QUATRO_A	0x0101 /* 2x 16550, half of 4 port */
++#define PCI_DEVICE_ID_LAVA_QUATRO_B	0x0102 /* 2x 16550, half of 4 port */
++#define PCI_DEVICE_ID_LAVA_OCTO_A	0x0180 /* 4x 16550A, half of 8 port */
++#define PCI_DEVICE_ID_LAVA_OCTO_B	0x0181 /* 4x 16550A, half of 8 port */
++#define PCI_DEVICE_ID_LAVA_PORT_PLUS	0x0200 /* 2x 16650 */
++#define PCI_DEVICE_ID_LAVA_QUAD_A	0x0201 /* 2x 16650, half of 4 port */
++#define PCI_DEVICE_ID_LAVA_QUAD_B	0x0202 /* 2x 16650, half of 4 port */
++#define PCI_DEVICE_ID_LAVA_SSERIAL	0x0500 /* 1x 16550 */
++#define PCI_DEVICE_ID_LAVA_PORT_650	0x0600 /* 1x 16650 */
++#define PCI_DEVICE_ID_LAVA_PARALLEL	0x8000
++#define PCI_DEVICE_ID_LAVA_DUAL_PAR_A	0x8002 /* The Lava Dual Parallel is */
++#define PCI_DEVICE_ID_LAVA_DUAL_PAR_B	0x8003 /* two PCI devices on a card */
++#define PCI_DEVICE_ID_LAVA_BOCA_IOPPAR	0x8800
++
++#define PCI_VENDOR_ID_TIMEDIA		0x1409
++#define PCI_DEVICE_ID_TIMEDIA_1889	0x7168
++
++#define PCI_VENDOR_ID_ICE		0x1412
++#define PCI_DEVICE_ID_ICE_1712		0x1712
++#define PCI_DEVICE_ID_VT1724		0x1724
++
++#define PCI_VENDOR_ID_OXSEMI		0x1415
++#define PCI_DEVICE_ID_OXSEMI_12PCI840	0x8403
++#define PCI_DEVICE_ID_OXSEMI_PCIe840		0xC000
++#define PCI_DEVICE_ID_OXSEMI_PCIe840_G		0xC004
++#define PCI_DEVICE_ID_OXSEMI_PCIe952_0		0xC100
++#define PCI_DEVICE_ID_OXSEMI_PCIe952_0_G	0xC104
++#define PCI_DEVICE_ID_OXSEMI_PCIe952_1		0xC110
++#define PCI_DEVICE_ID_OXSEMI_PCIe952_1_G	0xC114
++#define PCI_DEVICE_ID_OXSEMI_PCIe952_1_U	0xC118
++#define PCI_DEVICE_ID_OXSEMI_PCIe952_1_GU	0xC11C
++#define PCI_DEVICE_ID_OXSEMI_16PCI954	0x9501
++#define PCI_DEVICE_ID_OXSEMI_16PCI95N	0x9511
++#define PCI_DEVICE_ID_OXSEMI_16PCI954PP	0x9513
++#define PCI_DEVICE_ID_OXSEMI_16PCI952	0x9521
++#define PCI_DEVICE_ID_OXSEMI_16PCI952PP	0x9523
++
++#define PCI_VENDOR_ID_CHELSIO		0x1425
++
++#define PCI_VENDOR_ID_SAMSUNG		0x144d
++
++#define PCI_VENDOR_ID_MYRICOM		0x14c1
++
++#define PCI_VENDOR_ID_TITAN		0x14D2
++#define PCI_DEVICE_ID_TITAN_010L	0x8001
++#define PCI_DEVICE_ID_TITAN_100L	0x8010
++#define PCI_DEVICE_ID_TITAN_110L	0x8011
++#define PCI_DEVICE_ID_TITAN_200L	0x8020
++#define PCI_DEVICE_ID_TITAN_210L	0x8021
++#define PCI_DEVICE_ID_TITAN_400L	0x8040
++#define PCI_DEVICE_ID_TITAN_800L	0x8080
++#define PCI_DEVICE_ID_TITAN_100		0xA001
++#define PCI_DEVICE_ID_TITAN_200		0xA005
++#define PCI_DEVICE_ID_TITAN_400		0xA003
++#define PCI_DEVICE_ID_TITAN_800B	0xA004
++
++#define PCI_VENDOR_ID_PANACOM		0x14d4
++#define PCI_DEVICE_ID_PANACOM_QUADMODEM	0x0400
++#define PCI_DEVICE_ID_PANACOM_DUALMODEM	0x0402
++
++#define PCI_VENDOR_ID_SIPACKETS		0x14d9
++#define PCI_DEVICE_ID_SP1011		0x0010
++
++#define PCI_VENDOR_ID_AFAVLAB		0x14db
++#define PCI_DEVICE_ID_AFAVLAB_P028	0x2180
++#define PCI_DEVICE_ID_AFAVLAB_P030	0x2182
++#define PCI_SUBDEVICE_ID_AFAVLAB_P061		0x2150
++
++#define PCI_VENDOR_ID_BROADCOM		0x14e4
++#define PCI_DEVICE_ID_TIGON3_5752	0x1600
++#define PCI_DEVICE_ID_TIGON3_5752M	0x1601
++#define PCI_DEVICE_ID_NX2_5709		0x1639
++#define PCI_DEVICE_ID_NX2_5709S		0x163a
++#define PCI_DEVICE_ID_TIGON3_5700	0x1644
++#define PCI_DEVICE_ID_TIGON3_5701	0x1645
++#define PCI_DEVICE_ID_TIGON3_5702	0x1646
++#define PCI_DEVICE_ID_TIGON3_5703	0x1647
++#define PCI_DEVICE_ID_TIGON3_5704	0x1648
++#define PCI_DEVICE_ID_TIGON3_5704S_2	0x1649
++#define PCI_DEVICE_ID_NX2_5706		0x164a
++#define PCI_DEVICE_ID_NX2_5708		0x164c
++#define PCI_DEVICE_ID_TIGON3_5702FE	0x164d
++#define PCI_DEVICE_ID_NX2_57710		0x164e
++#define PCI_DEVICE_ID_NX2_57711		0x164f
++#define PCI_DEVICE_ID_NX2_57711E	0x1650
++#define PCI_DEVICE_ID_TIGON3_5705	0x1653
++#define PCI_DEVICE_ID_TIGON3_5705_2	0x1654
++#define PCI_DEVICE_ID_TIGON3_5720	0x1658
++#define PCI_DEVICE_ID_TIGON3_5721	0x1659
++#define PCI_DEVICE_ID_TIGON3_5722	0x165a
++#define PCI_DEVICE_ID_TIGON3_5723	0x165b
++#define PCI_DEVICE_ID_TIGON3_5705M	0x165d
++#define PCI_DEVICE_ID_TIGON3_5705M_2	0x165e
++#define PCI_DEVICE_ID_TIGON3_5714	0x1668
++#define PCI_DEVICE_ID_TIGON3_5714S	0x1669
++#define PCI_DEVICE_ID_TIGON3_5780	0x166a
++#define PCI_DEVICE_ID_TIGON3_5780S	0x166b
++#define PCI_DEVICE_ID_TIGON3_5705F	0x166e
++#define PCI_DEVICE_ID_TIGON3_5754M	0x1672
++#define PCI_DEVICE_ID_TIGON3_5755M	0x1673
++#define PCI_DEVICE_ID_TIGON3_5756	0x1674
++#define PCI_DEVICE_ID_TIGON3_5750	0x1676
++#define PCI_DEVICE_ID_TIGON3_5751	0x1677
++#define PCI_DEVICE_ID_TIGON3_5715	0x1678
++#define PCI_DEVICE_ID_TIGON3_5715S	0x1679
++#define PCI_DEVICE_ID_TIGON3_5754	0x167a
++#define PCI_DEVICE_ID_TIGON3_5755	0x167b
++#define PCI_DEVICE_ID_TIGON3_5750M	0x167c
++#define PCI_DEVICE_ID_TIGON3_5751M	0x167d
++#define PCI_DEVICE_ID_TIGON3_5751F	0x167e
++#define PCI_DEVICE_ID_TIGON3_5787F	0x167f
++#define PCI_DEVICE_ID_TIGON3_5761E	0x1680
++#define PCI_DEVICE_ID_TIGON3_5761	0x1681
++#define PCI_DEVICE_ID_TIGON3_5764	0x1684
++#define PCI_DEVICE_ID_TIGON3_5787M	0x1693
++#define PCI_DEVICE_ID_TIGON3_5782	0x1696
++#define PCI_DEVICE_ID_TIGON3_5784	0x1698
++#define PCI_DEVICE_ID_TIGON3_5785	0x1699
++#define PCI_DEVICE_ID_TIGON3_5786	0x169a
++#define PCI_DEVICE_ID_TIGON3_5787	0x169b
++#define PCI_DEVICE_ID_TIGON3_5788	0x169c
++#define PCI_DEVICE_ID_TIGON3_5789	0x169d
++#define PCI_DEVICE_ID_TIGON3_5702X	0x16a6
++#define PCI_DEVICE_ID_TIGON3_5703X	0x16a7
++#define PCI_DEVICE_ID_TIGON3_5704S	0x16a8
++#define PCI_DEVICE_ID_NX2_5706S		0x16aa
++#define PCI_DEVICE_ID_NX2_5708S		0x16ac
++#define PCI_DEVICE_ID_TIGON3_5702A3	0x16c6
++#define PCI_DEVICE_ID_TIGON3_5703A3	0x16c7
++#define PCI_DEVICE_ID_TIGON3_5781	0x16dd
++#define PCI_DEVICE_ID_TIGON3_5753	0x16f7
++#define PCI_DEVICE_ID_TIGON3_5753M	0x16fd
++#define PCI_DEVICE_ID_TIGON3_5753F	0x16fe
++#define PCI_DEVICE_ID_TIGON3_5901	0x170d
++#define PCI_DEVICE_ID_BCM4401B1		0x170c
++#define PCI_DEVICE_ID_TIGON3_5901_2	0x170e
++#define PCI_DEVICE_ID_TIGON3_5906	0x1712
++#define PCI_DEVICE_ID_TIGON3_5906M	0x1713
++#define PCI_DEVICE_ID_BCM4401		0x4401
++#define PCI_DEVICE_ID_BCM4401B0		0x4402
++
++#define PCI_VENDOR_ID_TOPIC		0x151f
++#define PCI_DEVICE_ID_TOPIC_TP560	0x0000
++
++#define PCI_VENDOR_ID_MAINPINE		0x1522
++#define PCI_DEVICE_ID_MAINPINE_PBRIDGE	0x0100
++#define PCI_VENDOR_ID_ENE		0x1524
++#define PCI_DEVICE_ID_ENE_CB712_SD	0x0550
++#define PCI_DEVICE_ID_ENE_CB712_SD_2	0x0551
++#define PCI_DEVICE_ID_ENE_CB714_SD	0x0750
++#define PCI_DEVICE_ID_ENE_CB714_SD_2	0x0751
++#define PCI_DEVICE_ID_ENE_1211		0x1211
++#define PCI_DEVICE_ID_ENE_1225		0x1225
++#define PCI_DEVICE_ID_ENE_1410		0x1410
++#define PCI_DEVICE_ID_ENE_710		0x1411
++#define PCI_DEVICE_ID_ENE_712		0x1412
++#define PCI_DEVICE_ID_ENE_1420		0x1420
++#define PCI_DEVICE_ID_ENE_720		0x1421
++#define PCI_DEVICE_ID_ENE_722		0x1422
++
++#define PCI_SUBVENDOR_ID_PERLE          0x155f
++#define PCI_SUBDEVICE_ID_PCI_RAS4       0xf001
++#define PCI_SUBDEVICE_ID_PCI_RAS8       0xf010
++
++#define PCI_VENDOR_ID_SYBA		0x1592
++#define PCI_DEVICE_ID_SYBA_2P_EPP	0x0782
++#define PCI_DEVICE_ID_SYBA_1P_ECP	0x0783
++
++#define PCI_VENDOR_ID_MORETON		0x15aa
++#define PCI_DEVICE_ID_RASTEL_2PORT	0x2000
++
++#define PCI_VENDOR_ID_ZOLTRIX		0x15b0
++#define PCI_DEVICE_ID_ZOLTRIX_2BD0	0x2bd0 
++
++#define PCI_VENDOR_ID_MELLANOX		0x15b3
++#define PCI_DEVICE_ID_MELLANOX_TAVOR	0x5a44
++#define PCI_DEVICE_ID_MELLANOX_TAVOR_BRIDGE	0x5a46
++#define PCI_DEVICE_ID_MELLANOX_ARBEL_COMPAT 0x6278
++#define PCI_DEVICE_ID_MELLANOX_ARBEL	0x6282
++#define PCI_DEVICE_ID_MELLANOX_SINAI_OLD 0x5e8c
++#define PCI_DEVICE_ID_MELLANOX_SINAI	0x6274
++
++#define PCI_VENDOR_ID_QUICKNET		0x15e2
++#define PCI_DEVICE_ID_QUICKNET_XJ	0x0500
++
++/*
++ * ADDI-DATA GmbH communication cards <info@addi-data.com>
++ */
++#define PCI_VENDOR_ID_ADDIDATA_OLD             0x10E8
++#define PCI_VENDOR_ID_ADDIDATA                 0x15B8
++#define PCI_DEVICE_ID_ADDIDATA_APCI7500        0x7000
++#define PCI_DEVICE_ID_ADDIDATA_APCI7420        0x7001
++#define PCI_DEVICE_ID_ADDIDATA_APCI7300        0x7002
++#define PCI_DEVICE_ID_ADDIDATA_APCI7800        0x818E
++#define PCI_DEVICE_ID_ADDIDATA_APCI7500_2      0x7009
++#define PCI_DEVICE_ID_ADDIDATA_APCI7420_2      0x700A
++#define PCI_DEVICE_ID_ADDIDATA_APCI7300_2      0x700B
++#define PCI_DEVICE_ID_ADDIDATA_APCI7500_3      0x700C
++#define PCI_DEVICE_ID_ADDIDATA_APCI7420_3      0x700D
++#define PCI_DEVICE_ID_ADDIDATA_APCI7300_3      0x700E
++#define PCI_DEVICE_ID_ADDIDATA_APCI7800_3      0x700F
++
++#define PCI_VENDOR_ID_PDC		0x15e9
++
++#define PCI_VENDOR_ID_FARSITE           0x1619
++#define PCI_DEVICE_ID_FARSITE_T2P       0x0400
++#define PCI_DEVICE_ID_FARSITE_T4P       0x0440
++#define PCI_DEVICE_ID_FARSITE_T1U       0x0610
++#define PCI_DEVICE_ID_FARSITE_T2U       0x0620
++#define PCI_DEVICE_ID_FARSITE_T4U       0x0640
++#define PCI_DEVICE_ID_FARSITE_TE1       0x1610
++#define PCI_DEVICE_ID_FARSITE_TE1C      0x1612
++
++#define PCI_VENDOR_ID_ARIMA		0x161f
++
++#define PCI_VENDOR_ID_BROCADE		0x1657
++
++#define PCI_VENDOR_ID_SIBYTE		0x166d
++#define PCI_DEVICE_ID_BCM1250_PCI	0x0001
++#define PCI_DEVICE_ID_BCM1250_HT	0x0002
++
++#define PCI_VENDOR_ID_ATHEROS		0x168c
++
++#define PCI_VENDOR_ID_NETCELL		0x169c
++#define PCI_DEVICE_ID_REVOLUTION	0x0044
++
++#define PCI_VENDOR_ID_CENATEK		0x16CA
++#define PCI_DEVICE_ID_CENATEK_IDE	0x0001
++
++#define PCI_VENDOR_ID_VITESSE		0x1725
++#define PCI_DEVICE_ID_VITESSE_VSC7174	0x7174
++
++#define PCI_VENDOR_ID_LINKSYS		0x1737
++#define PCI_DEVICE_ID_LINKSYS_EG1064	0x1064
++
++#define PCI_VENDOR_ID_ALTIMA		0x173b
++#define PCI_DEVICE_ID_ALTIMA_AC1000	0x03e8
++#define PCI_DEVICE_ID_ALTIMA_AC1001	0x03e9
++#define PCI_DEVICE_ID_ALTIMA_AC9100	0x03ea
++#define PCI_DEVICE_ID_ALTIMA_AC1003	0x03eb
++
++#define PCI_VENDOR_ID_BELKIN		0x1799
++#define PCI_DEVICE_ID_BELKIN_F5D7010V7	0x701f
++
++#define PCI_VENDOR_ID_RDC		0x17f3
++#define PCI_DEVICE_ID_RDC_R6020		0x6020
++#define PCI_DEVICE_ID_RDC_R6030		0x6030
++#define PCI_DEVICE_ID_RDC_R6040		0x6040
++#define PCI_DEVICE_ID_RDC_R6060		0x6060
++#define PCI_DEVICE_ID_RDC_R6061		0x6061
++
++#define PCI_VENDOR_ID_LENOVO		0x17aa
++
++#define PCI_VENDOR_ID_ARECA		0x17d3
++#define PCI_DEVICE_ID_ARECA_1110	0x1110
++#define PCI_DEVICE_ID_ARECA_1120	0x1120
++#define PCI_DEVICE_ID_ARECA_1130	0x1130
++#define PCI_DEVICE_ID_ARECA_1160	0x1160
++#define PCI_DEVICE_ID_ARECA_1170	0x1170
++#define PCI_DEVICE_ID_ARECA_1200	0x1200
++#define PCI_DEVICE_ID_ARECA_1201	0x1201
++#define PCI_DEVICE_ID_ARECA_1202	0x1202
++#define PCI_DEVICE_ID_ARECA_1210	0x1210
++#define PCI_DEVICE_ID_ARECA_1220	0x1220
++#define PCI_DEVICE_ID_ARECA_1230	0x1230
++#define PCI_DEVICE_ID_ARECA_1260	0x1260
++#define PCI_DEVICE_ID_ARECA_1270	0x1270
++#define PCI_DEVICE_ID_ARECA_1280	0x1280
++#define PCI_DEVICE_ID_ARECA_1380	0x1380
++#define PCI_DEVICE_ID_ARECA_1381	0x1381
++#define PCI_DEVICE_ID_ARECA_1680	0x1680
++#define PCI_DEVICE_ID_ARECA_1681	0x1681
++
++#define PCI_VENDOR_ID_S2IO		0x17d5
++#define	PCI_DEVICE_ID_S2IO_WIN		0x5731
++#define	PCI_DEVICE_ID_S2IO_UNI		0x5831
++#define PCI_DEVICE_ID_HERC_WIN		0x5732
++#define PCI_DEVICE_ID_HERC_UNI		0x5832
++
++#define PCI_VENDOR_ID_SITECOM		0x182d
++#define PCI_DEVICE_ID_SITECOM_DC105V2	0x3069
++
++#define PCI_VENDOR_ID_TOPSPIN		0x1867
++
++#define PCI_VENDOR_ID_TDI               0x192E
++#define PCI_DEVICE_ID_TDI_EHCI          0x0101
++
++#define PCI_VENDOR_ID_FREESCALE		0x1957
++#define PCI_DEVICE_ID_MPC8548E		0x0012
++#define PCI_DEVICE_ID_MPC8548		0x0013
++#define PCI_DEVICE_ID_MPC8543E		0x0014
++#define PCI_DEVICE_ID_MPC8543		0x0015
++#define PCI_DEVICE_ID_MPC8547E		0x0018
++#define PCI_DEVICE_ID_MPC8545E		0x0019
++#define PCI_DEVICE_ID_MPC8545		0x001a
++#define PCI_DEVICE_ID_MPC8568E		0x0020
++#define PCI_DEVICE_ID_MPC8568		0x0021
++#define PCI_DEVICE_ID_MPC8567E		0x0022
++#define PCI_DEVICE_ID_MPC8567		0x0023
++#define PCI_DEVICE_ID_MPC8533E		0x0030
++#define PCI_DEVICE_ID_MPC8533		0x0031
++#define PCI_DEVICE_ID_MPC8544E		0x0032
++#define PCI_DEVICE_ID_MPC8544		0x0033
++#define PCI_DEVICE_ID_MPC8572E		0x0040
++#define PCI_DEVICE_ID_MPC8572		0x0041
++#define PCI_DEVICE_ID_MPC8536E		0x0050
++#define PCI_DEVICE_ID_MPC8536		0x0051
++#define PCI_DEVICE_ID_MPC8641		0x7010
++#define PCI_DEVICE_ID_MPC8641D		0x7011
++#define PCI_DEVICE_ID_MPC8610		0x7018
++
++#define PCI_VENDOR_ID_PASEMI		0x1959
++
++#define PCI_VENDOR_ID_ATTANSIC		0x1969
++#define PCI_DEVICE_ID_ATTANSIC_L1	0x1048
++#define PCI_DEVICE_ID_ATTANSIC_L2	0x2048
++
++#define PCI_VENDOR_ID_JMICRON		0x197B
++#define PCI_DEVICE_ID_JMICRON_JMB360	0x2360
++#define PCI_DEVICE_ID_JMICRON_JMB361	0x2361
++#define PCI_DEVICE_ID_JMICRON_JMB363	0x2363
++#define PCI_DEVICE_ID_JMICRON_JMB365	0x2365
++#define PCI_DEVICE_ID_JMICRON_JMB366	0x2366
++#define PCI_DEVICE_ID_JMICRON_JMB368	0x2368
++#define PCI_DEVICE_ID_JMICRON_JMB38X_SD	0x2381
++#define PCI_DEVICE_ID_JMICRON_JMB38X_MMC 0x2382
++#define PCI_DEVICE_ID_JMICRON_JMB38X_MS	0x2383
++
++#define PCI_VENDOR_ID_KORENIX		0x1982
++#define PCI_DEVICE_ID_KORENIX_JETCARDF0	0x1600
++#define PCI_DEVICE_ID_KORENIX_JETCARDF1	0x16ff
++
++#define PCI_VENDOR_ID_TEKRAM		0x1de1
++#define PCI_DEVICE_ID_TEKRAM_DC290	0xdc29
++
++#define PCI_VENDOR_ID_TEHUTI		0x1fc9
++#define PCI_DEVICE_ID_TEHUTI_3009	0x3009
++#define PCI_DEVICE_ID_TEHUTI_3010	0x3010
++#define PCI_DEVICE_ID_TEHUTI_3014	0x3014
++
++#define PCI_VENDOR_ID_HINT             0x3388
++#define PCI_DEVICE_ID_HINT_VXPROII_IDE 0x8013
++
++#define PCI_VENDOR_ID_3DLABS		0x3d3d
++#define PCI_DEVICE_ID_3DLABS_PERMEDIA2	0x0007
++#define PCI_DEVICE_ID_3DLABS_PERMEDIA2V	0x0009
++
++#define PCI_VENDOR_ID_NETXEN		0x4040
++#define PCI_DEVICE_ID_NX2031_10GXSR	0x0001
++#define PCI_DEVICE_ID_NX2031_10GCX4	0x0002
++#define PCI_DEVICE_ID_NX2031_4GCU	0x0003
++#define PCI_DEVICE_ID_NX2031_IMEZ	0x0004
++#define PCI_DEVICE_ID_NX2031_HMEZ	0x0005
++#define PCI_DEVICE_ID_NX2031_XG_MGMT	0x0024
++#define PCI_DEVICE_ID_NX2031_XG_MGMT2	0x0025
++#define PCI_DEVICE_ID_NX3031		0x0100
++
++#define PCI_VENDOR_ID_AKS		0x416c
++#define PCI_DEVICE_ID_AKS_ALADDINCARD	0x0100
++
++#define PCI_VENDOR_ID_S3		0x5333
++#define PCI_DEVICE_ID_S3_TRIO		0x8811
++#define PCI_DEVICE_ID_S3_868		0x8880
++#define PCI_DEVICE_ID_S3_968		0x88f0
++#define PCI_DEVICE_ID_S3_SAVAGE4	0x8a25
++#define PCI_DEVICE_ID_S3_PROSAVAGE8	0x8d04
++#define PCI_DEVICE_ID_S3_SONICVIBES	0xca00
++
++#define PCI_VENDOR_ID_DUNORD		0x5544
++#define PCI_DEVICE_ID_DUNORD_I3000	0x0001
++
++#define PCI_VENDOR_ID_DCI		0x6666
++#define PCI_DEVICE_ID_DCI_PCCOM4	0x0001
++#define PCI_DEVICE_ID_DCI_PCCOM8	0x0002
++#define PCI_DEVICE_ID_DCI_PCCOM2	0x0004
++
++#define PCI_VENDOR_ID_INTEL		0x8086
++#define PCI_DEVICE_ID_INTEL_EESSC	0x0008
++#define PCI_DEVICE_ID_INTEL_PXHD_0	0x0320
++#define PCI_DEVICE_ID_INTEL_PXHD_1	0x0321
++#define PCI_DEVICE_ID_INTEL_PXH_0	0x0329
++#define PCI_DEVICE_ID_INTEL_PXH_1	0x032A
++#define PCI_DEVICE_ID_INTEL_PXHV	0x032C
++#define PCI_DEVICE_ID_INTEL_82375	0x0482
++#define PCI_DEVICE_ID_INTEL_82424	0x0483
++#define PCI_DEVICE_ID_INTEL_82378	0x0484
++#define PCI_DEVICE_ID_INTEL_I960	0x0960
++#define PCI_DEVICE_ID_INTEL_I960RM	0x0962
++#define PCI_DEVICE_ID_INTEL_82815_MC	0x1130
++#define PCI_DEVICE_ID_INTEL_82815_CGC	0x1132
++#define PCI_DEVICE_ID_INTEL_82092AA_0	0x1221
++#define PCI_DEVICE_ID_INTEL_7505_0	0x2550  
++#define PCI_DEVICE_ID_INTEL_7205_0	0x255d
++#define PCI_DEVICE_ID_INTEL_82437	0x122d
++#define PCI_DEVICE_ID_INTEL_82371FB_0	0x122e
++#define PCI_DEVICE_ID_INTEL_82371FB_1	0x1230
++#define PCI_DEVICE_ID_INTEL_82371MX	0x1234
++#define PCI_DEVICE_ID_INTEL_82441	0x1237
++#define PCI_DEVICE_ID_INTEL_82380FB	0x124b
++#define PCI_DEVICE_ID_INTEL_82439	0x1250
++#define PCI_DEVICE_ID_INTEL_80960_RP	0x1960
++#define PCI_DEVICE_ID_INTEL_82840_HB	0x1a21
++#define PCI_DEVICE_ID_INTEL_82845_HB	0x1a30
++#define PCI_DEVICE_ID_INTEL_IOAT	0x1a38
++#define PCI_DEVICE_ID_INTEL_82801AA_0	0x2410
++#define PCI_DEVICE_ID_INTEL_82801AA_1	0x2411
++#define PCI_DEVICE_ID_INTEL_82801AA_3	0x2413
++#define PCI_DEVICE_ID_INTEL_82801AA_5	0x2415
++#define PCI_DEVICE_ID_INTEL_82801AA_6	0x2416
++#define PCI_DEVICE_ID_INTEL_82801AA_8	0x2418
++#define PCI_DEVICE_ID_INTEL_82801AB_0	0x2420
++#define PCI_DEVICE_ID_INTEL_82801AB_1	0x2421
++#define PCI_DEVICE_ID_INTEL_82801AB_3	0x2423
++#define PCI_DEVICE_ID_INTEL_82801AB_5	0x2425
++#define PCI_DEVICE_ID_INTEL_82801AB_6	0x2426
++#define PCI_DEVICE_ID_INTEL_82801AB_8	0x2428
++#define PCI_DEVICE_ID_INTEL_82801BA_0	0x2440
++#define PCI_DEVICE_ID_INTEL_82801BA_2	0x2443
++#define PCI_DEVICE_ID_INTEL_82801BA_4	0x2445
++#define PCI_DEVICE_ID_INTEL_82801BA_6	0x2448
++#define PCI_DEVICE_ID_INTEL_82801BA_8	0x244a
++#define PCI_DEVICE_ID_INTEL_82801BA_9	0x244b
++#define PCI_DEVICE_ID_INTEL_82801BA_10	0x244c
++#define PCI_DEVICE_ID_INTEL_82801BA_11	0x244e
++#define PCI_DEVICE_ID_INTEL_82801E_0	0x2450
++#define PCI_DEVICE_ID_INTEL_82801E_11	0x245b
++#define PCI_DEVICE_ID_INTEL_82801CA_0	0x2480
++#define PCI_DEVICE_ID_INTEL_82801CA_3	0x2483
++#define PCI_DEVICE_ID_INTEL_82801CA_5	0x2485
++#define PCI_DEVICE_ID_INTEL_82801CA_6	0x2486
++#define PCI_DEVICE_ID_INTEL_82801CA_10	0x248a
++#define PCI_DEVICE_ID_INTEL_82801CA_11	0x248b
++#define PCI_DEVICE_ID_INTEL_82801CA_12	0x248c
++#define PCI_DEVICE_ID_INTEL_82801DB_0	0x24c0
++#define PCI_DEVICE_ID_INTEL_82801DB_1	0x24c1
++#define PCI_DEVICE_ID_INTEL_82801DB_3	0x24c3
++#define PCI_DEVICE_ID_INTEL_82801DB_5	0x24c5
++#define PCI_DEVICE_ID_INTEL_82801DB_6	0x24c6
++#define PCI_DEVICE_ID_INTEL_82801DB_9	0x24c9
++#define PCI_DEVICE_ID_INTEL_82801DB_10	0x24ca
++#define PCI_DEVICE_ID_INTEL_82801DB_11	0x24cb
++#define PCI_DEVICE_ID_INTEL_82801DB_12  0x24cc
++#define PCI_DEVICE_ID_INTEL_82801EB_0	0x24d0
++#define PCI_DEVICE_ID_INTEL_82801EB_1	0x24d1
++#define PCI_DEVICE_ID_INTEL_82801EB_3	0x24d3
++#define PCI_DEVICE_ID_INTEL_82801EB_5	0x24d5
++#define PCI_DEVICE_ID_INTEL_82801EB_6	0x24d6
++#define PCI_DEVICE_ID_INTEL_82801EB_11	0x24db
++#define PCI_DEVICE_ID_INTEL_82801EB_12	0x24dc
++#define PCI_DEVICE_ID_INTEL_82801EB_13	0x24dd
++#define PCI_DEVICE_ID_INTEL_ESB_1	0x25a1
++#define PCI_DEVICE_ID_INTEL_ESB_2	0x25a2
++#define PCI_DEVICE_ID_INTEL_ESB_4	0x25a4
++#define PCI_DEVICE_ID_INTEL_ESB_5	0x25a6
++#define PCI_DEVICE_ID_INTEL_ESB_9	0x25ab
++#define PCI_DEVICE_ID_INTEL_82820_HB	0x2500
++#define PCI_DEVICE_ID_INTEL_82820_UP_HB	0x2501
++#define PCI_DEVICE_ID_INTEL_82850_HB	0x2530
++#define PCI_DEVICE_ID_INTEL_82860_HB	0x2531
++#define PCI_DEVICE_ID_INTEL_E7501_MCH	0x254c
++#define PCI_DEVICE_ID_INTEL_82845G_HB	0x2560
++#define PCI_DEVICE_ID_INTEL_82845G_IG	0x2562
++#define PCI_DEVICE_ID_INTEL_82865_HB	0x2570
++#define PCI_DEVICE_ID_INTEL_82865_IG	0x2572
++#define PCI_DEVICE_ID_INTEL_82875_HB	0x2578
++#define PCI_DEVICE_ID_INTEL_82915G_HB	0x2580
++#define PCI_DEVICE_ID_INTEL_82915G_IG	0x2582
++#define PCI_DEVICE_ID_INTEL_82915GM_HB	0x2590
++#define PCI_DEVICE_ID_INTEL_82915GM_IG	0x2592
++#define PCI_DEVICE_ID_INTEL_5000_ERR	0x25F0
++#define PCI_DEVICE_ID_INTEL_5000_FBD0	0x25F5
++#define PCI_DEVICE_ID_INTEL_5000_FBD1	0x25F6
++#define PCI_DEVICE_ID_INTEL_82945G_HB	0x2770
++#define PCI_DEVICE_ID_INTEL_82945G_IG	0x2772
++#define PCI_DEVICE_ID_INTEL_3000_HB	0x2778
++#define PCI_DEVICE_ID_INTEL_82945GM_HB	0x27A0
++#define PCI_DEVICE_ID_INTEL_82945GM_IG	0x27A2
++#define PCI_DEVICE_ID_INTEL_ICH6_0	0x2640
++#define PCI_DEVICE_ID_INTEL_ICH6_1	0x2641
++#define PCI_DEVICE_ID_INTEL_ICH6_2	0x2642
++#define PCI_DEVICE_ID_INTEL_ICH6_16	0x266a
++#define PCI_DEVICE_ID_INTEL_ICH6_17	0x266d
++#define PCI_DEVICE_ID_INTEL_ICH6_18	0x266e
++#define PCI_DEVICE_ID_INTEL_ICH6_19	0x266f
++#define PCI_DEVICE_ID_INTEL_ESB2_0	0x2670
++#define PCI_DEVICE_ID_INTEL_ESB2_14	0x2698
++#define PCI_DEVICE_ID_INTEL_ESB2_17	0x269b
++#define PCI_DEVICE_ID_INTEL_ESB2_18	0x269e
++#define PCI_DEVICE_ID_INTEL_ICH7_0	0x27b8
++#define PCI_DEVICE_ID_INTEL_ICH7_1	0x27b9
++#define PCI_DEVICE_ID_INTEL_ICH7_30	0x27b0
++#define PCI_DEVICE_ID_INTEL_ICH7_31	0x27bd
++#define PCI_DEVICE_ID_INTEL_ICH7_17	0x27da
++#define PCI_DEVICE_ID_INTEL_ICH7_19	0x27dd
++#define PCI_DEVICE_ID_INTEL_ICH7_20	0x27de
++#define PCI_DEVICE_ID_INTEL_ICH7_21	0x27df
++#define PCI_DEVICE_ID_INTEL_ICH8_0	0x2810
++#define PCI_DEVICE_ID_INTEL_ICH8_1	0x2811
++#define PCI_DEVICE_ID_INTEL_ICH8_2	0x2812
++#define PCI_DEVICE_ID_INTEL_ICH8_3	0x2814
++#define PCI_DEVICE_ID_INTEL_ICH8_4	0x2815
++#define PCI_DEVICE_ID_INTEL_ICH8_5	0x283e
++#define PCI_DEVICE_ID_INTEL_ICH8_6	0x2850
++#define PCI_DEVICE_ID_INTEL_ICH9_0	0x2910
++#define PCI_DEVICE_ID_INTEL_ICH9_1	0x2917
++#define PCI_DEVICE_ID_INTEL_ICH9_2	0x2912
++#define PCI_DEVICE_ID_INTEL_ICH9_3	0x2913
++#define PCI_DEVICE_ID_INTEL_ICH9_4	0x2914
++#define PCI_DEVICE_ID_INTEL_ICH9_5	0x2919
++#define PCI_DEVICE_ID_INTEL_ICH9_6	0x2930
++#define PCI_DEVICE_ID_INTEL_ICH9_7	0x2916
++#define PCI_DEVICE_ID_INTEL_ICH9_8	0x2918
++#define PCI_DEVICE_ID_INTEL_82855PM_HB	0x3340
++#define PCI_DEVICE_ID_INTEL_IOAT_TBG4	0x3429
++#define PCI_DEVICE_ID_INTEL_IOAT_TBG5	0x342a
++#define PCI_DEVICE_ID_INTEL_IOAT_TBG6	0x342b
++#define PCI_DEVICE_ID_INTEL_IOAT_TBG7	0x342c
++#define PCI_DEVICE_ID_INTEL_IOAT_TBG0	0x3430
++#define PCI_DEVICE_ID_INTEL_IOAT_TBG1	0x3431
++#define PCI_DEVICE_ID_INTEL_IOAT_TBG2	0x3432
++#define PCI_DEVICE_ID_INTEL_IOAT_TBG3	0x3433
++#define PCI_DEVICE_ID_INTEL_82830_HB	0x3575
++#define PCI_DEVICE_ID_INTEL_82830_CGC	0x3577
++#define PCI_DEVICE_ID_INTEL_82855GM_HB	0x3580
++#define PCI_DEVICE_ID_INTEL_82855GM_IG	0x3582
++#define PCI_DEVICE_ID_INTEL_E7520_MCH	0x3590
++#define PCI_DEVICE_ID_INTEL_E7320_MCH	0x3592
++#define PCI_DEVICE_ID_INTEL_MCH_PA	0x3595
++#define PCI_DEVICE_ID_INTEL_MCH_PA1	0x3596
++#define PCI_DEVICE_ID_INTEL_MCH_PB	0x3597
++#define PCI_DEVICE_ID_INTEL_MCH_PB1	0x3598
++#define PCI_DEVICE_ID_INTEL_MCH_PC	0x3599
++#define PCI_DEVICE_ID_INTEL_MCH_PC1	0x359a
++#define PCI_DEVICE_ID_INTEL_E7525_MCH	0x359e
++#define PCI_DEVICE_ID_INTEL_IOAT_CNB	0x360b
++#define PCI_DEVICE_ID_INTEL_FBD_CNB	0x360c
++#define PCI_DEVICE_ID_INTEL_ICH10_0	0x3a14
++#define PCI_DEVICE_ID_INTEL_ICH10_1	0x3a16
++#define PCI_DEVICE_ID_INTEL_ICH10_2	0x3a18
++#define PCI_DEVICE_ID_INTEL_ICH10_3	0x3a1a
++#define PCI_DEVICE_ID_INTEL_ICH10_4	0x3a30
++#define PCI_DEVICE_ID_INTEL_ICH10_5	0x3a60
++#define PCI_DEVICE_ID_INTEL_PCH_LPC_MIN	0x3b00
++#define PCI_DEVICE_ID_INTEL_PCH_LPC_MAX	0x3b1f
++#define PCI_DEVICE_ID_INTEL_PCH_SMBUS	0x3b30
++#define PCI_DEVICE_ID_INTEL_IOAT_SNB	0x402f
++#define PCI_DEVICE_ID_INTEL_5100_16	0x65f0
++#define PCI_DEVICE_ID_INTEL_5100_21	0x65f5
++#define PCI_DEVICE_ID_INTEL_5100_22	0x65f6
++#define PCI_DEVICE_ID_INTEL_5400_ERR	0x4030
++#define PCI_DEVICE_ID_INTEL_5400_FBD0	0x4035
++#define PCI_DEVICE_ID_INTEL_5400_FBD1	0x4036
++#define PCI_DEVICE_ID_INTEL_IOAT_SCNB	0x65ff
++#define PCI_DEVICE_ID_INTEL_TOLAPAI_0	0x5031
++#define PCI_DEVICE_ID_INTEL_TOLAPAI_1	0x5032
++#define PCI_DEVICE_ID_INTEL_82371SB_0	0x7000
++#define PCI_DEVICE_ID_INTEL_82371SB_1	0x7010
++#define PCI_DEVICE_ID_INTEL_82371SB_2	0x7020
++#define PCI_DEVICE_ID_INTEL_82437VX	0x7030
++#define PCI_DEVICE_ID_INTEL_82439TX	0x7100
++#define PCI_DEVICE_ID_INTEL_82371AB_0	0x7110
++#define PCI_DEVICE_ID_INTEL_82371AB	0x7111
++#define PCI_DEVICE_ID_INTEL_82371AB_2	0x7112
++#define PCI_DEVICE_ID_INTEL_82371AB_3	0x7113
++#define PCI_DEVICE_ID_INTEL_82810_MC1	0x7120
++#define PCI_DEVICE_ID_INTEL_82810_IG1	0x7121
++#define PCI_DEVICE_ID_INTEL_82810_MC3	0x7122
++#define PCI_DEVICE_ID_INTEL_82810_IG3	0x7123
++#define PCI_DEVICE_ID_INTEL_82810E_MC	0x7124
++#define PCI_DEVICE_ID_INTEL_82810E_IG	0x7125
++#define PCI_DEVICE_ID_INTEL_82443LX_0	0x7180
++#define PCI_DEVICE_ID_INTEL_82443LX_1	0x7181
++#define PCI_DEVICE_ID_INTEL_82443BX_0	0x7190
++#define PCI_DEVICE_ID_INTEL_82443BX_1	0x7191
++#define PCI_DEVICE_ID_INTEL_82443BX_2	0x7192
++#define PCI_DEVICE_ID_INTEL_440MX	0x7195
++#define PCI_DEVICE_ID_INTEL_440MX_6	0x7196
++#define PCI_DEVICE_ID_INTEL_82443MX_0	0x7198
++#define PCI_DEVICE_ID_INTEL_82443MX_1	0x7199
++#define PCI_DEVICE_ID_INTEL_82443MX_3	0x719b
++#define PCI_DEVICE_ID_INTEL_82443GX_0	0x71a0
++#define PCI_DEVICE_ID_INTEL_82443GX_2	0x71a2
++#define PCI_DEVICE_ID_INTEL_82372FB_1	0x7601
++#define PCI_DEVICE_ID_INTEL_SCH_LPC	0x8119
++#define PCI_DEVICE_ID_INTEL_SCH_IDE	0x811a
++#define PCI_DEVICE_ID_INTEL_82454GX	0x84c4
++#define PCI_DEVICE_ID_INTEL_82450GX	0x84c5
++#define PCI_DEVICE_ID_INTEL_82451NX	0x84ca
++#define PCI_DEVICE_ID_INTEL_82454NX     0x84cb
++#define PCI_DEVICE_ID_INTEL_84460GX	0x84ea
++#define PCI_DEVICE_ID_INTEL_IXP4XX	0x8500
++#define PCI_DEVICE_ID_INTEL_IXP2800	0x9004
++#define PCI_DEVICE_ID_INTEL_S21152BB	0xb152
++
++#define PCI_VENDOR_ID_SCALEMP		0x8686
++#define PCI_DEVICE_ID_SCALEMP_VSMP_CTL	0x1010
++
++#define PCI_VENDOR_ID_COMPUTONE		0x8e0e
++#define PCI_DEVICE_ID_COMPUTONE_IP2EX	0x0291
++#define PCI_DEVICE_ID_COMPUTONE_PG	0x0302
++#define PCI_SUBVENDOR_ID_COMPUTONE	0x8e0e
++#define PCI_SUBDEVICE_ID_COMPUTONE_PG4	0x0001
++#define PCI_SUBDEVICE_ID_COMPUTONE_PG8	0x0002
++#define PCI_SUBDEVICE_ID_COMPUTONE_PG6	0x0003
++
++#define PCI_VENDOR_ID_KTI		0x8e2e
++
++#define PCI_VENDOR_ID_ADAPTEC		0x9004
++#define PCI_DEVICE_ID_ADAPTEC_7810	0x1078
++#define PCI_DEVICE_ID_ADAPTEC_7821	0x2178
++#define PCI_DEVICE_ID_ADAPTEC_38602	0x3860
++#define PCI_DEVICE_ID_ADAPTEC_7850	0x5078
++#define PCI_DEVICE_ID_ADAPTEC_7855	0x5578
++#define PCI_DEVICE_ID_ADAPTEC_3860	0x6038
++#define PCI_DEVICE_ID_ADAPTEC_1480A	0x6075
++#define PCI_DEVICE_ID_ADAPTEC_7860	0x6078
++#define PCI_DEVICE_ID_ADAPTEC_7861	0x6178
++#define PCI_DEVICE_ID_ADAPTEC_7870	0x7078
++#define PCI_DEVICE_ID_ADAPTEC_7871	0x7178
++#define PCI_DEVICE_ID_ADAPTEC_7872	0x7278
++#define PCI_DEVICE_ID_ADAPTEC_7873	0x7378
++#define PCI_DEVICE_ID_ADAPTEC_7874	0x7478
++#define PCI_DEVICE_ID_ADAPTEC_7895	0x7895
++#define PCI_DEVICE_ID_ADAPTEC_7880	0x8078
++#define PCI_DEVICE_ID_ADAPTEC_7881	0x8178
++#define PCI_DEVICE_ID_ADAPTEC_7882	0x8278
++#define PCI_DEVICE_ID_ADAPTEC_7883	0x8378
++#define PCI_DEVICE_ID_ADAPTEC_7884	0x8478
++#define PCI_DEVICE_ID_ADAPTEC_7885	0x8578
++#define PCI_DEVICE_ID_ADAPTEC_7886	0x8678
++#define PCI_DEVICE_ID_ADAPTEC_7887	0x8778
++#define PCI_DEVICE_ID_ADAPTEC_7888	0x8878
++
++#define PCI_VENDOR_ID_ADAPTEC2		0x9005
++#define PCI_DEVICE_ID_ADAPTEC2_2940U2	0x0010
++#define PCI_DEVICE_ID_ADAPTEC2_2930U2	0x0011
++#define PCI_DEVICE_ID_ADAPTEC2_7890B	0x0013
++#define PCI_DEVICE_ID_ADAPTEC2_7890	0x001f
++#define PCI_DEVICE_ID_ADAPTEC2_3940U2	0x0050
++#define PCI_DEVICE_ID_ADAPTEC2_3950U2D	0x0051
++#define PCI_DEVICE_ID_ADAPTEC2_7896	0x005f
++#define PCI_DEVICE_ID_ADAPTEC2_7892A	0x0080
++#define PCI_DEVICE_ID_ADAPTEC2_7892B	0x0081
++#define PCI_DEVICE_ID_ADAPTEC2_7892D	0x0083
++#define PCI_DEVICE_ID_ADAPTEC2_7892P	0x008f
++#define PCI_DEVICE_ID_ADAPTEC2_7899A	0x00c0
++#define PCI_DEVICE_ID_ADAPTEC2_7899B	0x00c1
++#define PCI_DEVICE_ID_ADAPTEC2_7899D	0x00c3
++#define PCI_DEVICE_ID_ADAPTEC2_7899P	0x00cf
++#define PCI_DEVICE_ID_ADAPTEC2_OBSIDIAN   0x0500
++#define PCI_DEVICE_ID_ADAPTEC2_SCAMP	0x0503
++
++#define PCI_VENDOR_ID_HOLTEK		0x9412
++#define PCI_DEVICE_ID_HOLTEK_6565	0x6565
++
++#define PCI_VENDOR_ID_NETMOS		0x9710
++#define PCI_DEVICE_ID_NETMOS_9705	0x9705
++#define PCI_DEVICE_ID_NETMOS_9715	0x9715
++#define PCI_DEVICE_ID_NETMOS_9735	0x9735
++#define PCI_DEVICE_ID_NETMOS_9745	0x9745
++#define PCI_DEVICE_ID_NETMOS_9755	0x9755
++#define PCI_DEVICE_ID_NETMOS_9805	0x9805
++#define PCI_DEVICE_ID_NETMOS_9815	0x9815
++#define PCI_DEVICE_ID_NETMOS_9835	0x9835
++#define PCI_DEVICE_ID_NETMOS_9845	0x9845
++#define PCI_DEVICE_ID_NETMOS_9855	0x9855
++
++#define PCI_VENDOR_ID_3COM_2		0xa727
++
++#define PCI_VENDOR_ID_DIGIUM		0xd161
++#define PCI_DEVICE_ID_DIGIUM_HFC4S	0xb410
++
++#define PCI_SUBVENDOR_ID_EXSYS		0xd84d
++#define PCI_SUBDEVICE_ID_EXSYS_4014	0x4014
++#define PCI_SUBDEVICE_ID_EXSYS_4055	0x4055
++
++#define PCI_VENDOR_ID_TIGERJET		0xe159
++#define PCI_DEVICE_ID_TIGERJET_300	0x0001
++#define PCI_DEVICE_ID_TIGERJET_100	0x0002
++
++#define PCI_VENDOR_ID_XILINX_RME	0xea60
++#define PCI_DEVICE_ID_RME_DIGI32	0x9896
++#define PCI_DEVICE_ID_RME_DIGI32_PRO	0x9897
++#define PCI_DEVICE_ID_RME_DIGI32_8	0x9898
+--- x/roms/seabios/src/pci_regs.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/pci_regs.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,556 @@
++/*
++ *	pci_regs.h
++ *
++ *	PCI standard defines
++ *	Copyright 1994, Drew Eckhardt
++ *	Copyright 1997--1999 Martin Mares <mj@ucw.cz>
++ *
++ *	For more information, please consult the following manuals (look at
++ *	http://www.pcisig.com/ for how to get them):
++ *
++ *	PCI BIOS Specification
++ *	PCI Local Bus Specification
++ *	PCI to PCI Bridge Specification
++ *	PCI System Design Guide
++ *
++ * 	For hypertransport information, please consult the following manuals
++ * 	from http://www.hypertransport.org
++ *
++ *	The Hypertransport I/O Link Specification
++ */
++
++#ifndef LINUX_PCI_REGS_H
++#define LINUX_PCI_REGS_H
++
++/*
++ * Under PCI, each device has 256 bytes of configuration address space,
++ * of which the first 64 bytes are standardized as follows:
++ */
++#define PCI_VENDOR_ID		0x00	/* 16 bits */
++#define PCI_DEVICE_ID		0x02	/* 16 bits */
++#define PCI_COMMAND		0x04	/* 16 bits */
++#define  PCI_COMMAND_IO		0x1	/* Enable response in I/O space */
++#define  PCI_COMMAND_MEMORY	0x2	/* Enable response in Memory space */
++#define  PCI_COMMAND_MASTER	0x4	/* Enable bus mastering */
++#define  PCI_COMMAND_SPECIAL	0x8	/* Enable response to special cycles */
++#define  PCI_COMMAND_INVALIDATE	0x10	/* Use memory write and invalidate */
++#define  PCI_COMMAND_VGA_PALETTE 0x20	/* Enable palette snooping */
++#define  PCI_COMMAND_PARITY	0x40	/* Enable parity checking */
++#define  PCI_COMMAND_WAIT 	0x80	/* Enable address/data stepping */
++#define  PCI_COMMAND_SERR	0x100	/* Enable SERR */
++#define  PCI_COMMAND_FAST_BACK	0x200	/* Enable back-to-back writes */
++#define  PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
++
++#define PCI_STATUS		0x06	/* 16 bits */
++#define  PCI_STATUS_CAP_LIST	0x10	/* Support Capability List */
++#define  PCI_STATUS_66MHZ	0x20	/* Support 66 Mhz PCI 2.1 bus */
++#define  PCI_STATUS_UDF		0x40	/* Support User Definable Features [obsolete] */
++#define  PCI_STATUS_FAST_BACK	0x80	/* Accept fast-back to back */
++#define  PCI_STATUS_PARITY	0x100	/* Detected parity error */
++#define  PCI_STATUS_DEVSEL_MASK	0x600	/* DEVSEL timing */
++#define  PCI_STATUS_DEVSEL_FAST		0x000
++#define  PCI_STATUS_DEVSEL_MEDIUM	0x200
++#define  PCI_STATUS_DEVSEL_SLOW		0x400
++#define  PCI_STATUS_SIG_TARGET_ABORT	0x800 /* Set on target abort */
++#define  PCI_STATUS_REC_TARGET_ABORT	0x1000 /* Master ack of " */
++#define  PCI_STATUS_REC_MASTER_ABORT	0x2000 /* Set on master abort */
++#define  PCI_STATUS_SIG_SYSTEM_ERROR	0x4000 /* Set when we drive SERR */
++#define  PCI_STATUS_DETECTED_PARITY	0x8000 /* Set on parity error */
++
++#define PCI_CLASS_REVISION	0x08	/* High 24 bits are class, low 8 revision */
++#define PCI_REVISION_ID		0x08	/* Revision ID */
++#define PCI_CLASS_PROG		0x09	/* Reg. Level Programming Interface */
++#define PCI_CLASS_DEVICE	0x0a	/* Device class */
++
++#define PCI_CACHE_LINE_SIZE	0x0c	/* 8 bits */
++#define PCI_LATENCY_TIMER	0x0d	/* 8 bits */
++#define PCI_HEADER_TYPE		0x0e	/* 8 bits */
++#define  PCI_HEADER_TYPE_NORMAL		0
++#define  PCI_HEADER_TYPE_BRIDGE		1
++#define  PCI_HEADER_TYPE_CARDBUS	2
++
++#define PCI_BIST		0x0f	/* 8 bits */
++#define  PCI_BIST_CODE_MASK	0x0f	/* Return result */
++#define  PCI_BIST_START		0x40	/* 1 to start BIST, 2 secs or less */
++#define  PCI_BIST_CAPABLE	0x80	/* 1 if BIST capable */
++
++/*
++ * Base addresses specify locations in memory or I/O space.
++ * Decoded size can be determined by writing a value of
++ * 0xffffffff to the register, and reading it back.  Only
++ * 1 bits are decoded.
++ */
++#define PCI_BASE_ADDRESS_0	0x10	/* 32 bits */
++#define PCI_BASE_ADDRESS_1	0x14	/* 32 bits [htype 0,1 only] */
++#define PCI_BASE_ADDRESS_2	0x18	/* 32 bits [htype 0 only] */
++#define PCI_BASE_ADDRESS_3	0x1c	/* 32 bits */
++#define PCI_BASE_ADDRESS_4	0x20	/* 32 bits */
++#define PCI_BASE_ADDRESS_5	0x24	/* 32 bits */
++#define  PCI_BASE_ADDRESS_SPACE		0x01	/* 0 = memory, 1 = I/O */
++#define  PCI_BASE_ADDRESS_SPACE_IO	0x01
++#define  PCI_BASE_ADDRESS_SPACE_MEMORY	0x00
++#define  PCI_BASE_ADDRESS_MEM_TYPE_MASK	0x06
++#define  PCI_BASE_ADDRESS_MEM_TYPE_32	0x00	/* 32 bit address */
++#define  PCI_BASE_ADDRESS_MEM_TYPE_1M	0x02	/* Below 1M [obsolete] */
++#define  PCI_BASE_ADDRESS_MEM_TYPE_64	0x04	/* 64 bit address */
++#define  PCI_BASE_ADDRESS_MEM_PREFETCH	0x08	/* prefetchable? */
++#define  PCI_BASE_ADDRESS_MEM_MASK	(~0x0fUL)
++#define  PCI_BASE_ADDRESS_IO_MASK	(~0x03UL)
++/* bit 1 is reserved if address_space = 1 */
++
++/* Header type 0 (normal devices) */
++#define PCI_CARDBUS_CIS		0x28
++#define PCI_SUBSYSTEM_VENDOR_ID	0x2c
++#define PCI_SUBSYSTEM_ID	0x2e
++#define PCI_ROM_ADDRESS		0x30	/* Bits 31..11 are address, 10..1 reserved */
++#define  PCI_ROM_ADDRESS_ENABLE	0x01
++#define PCI_ROM_ADDRESS_MASK	(~0x7ffUL)
++
++#define PCI_CAPABILITY_LIST	0x34	/* Offset of first capability list entry */
++
++/* 0x35-0x3b are reserved */
++#define PCI_INTERRUPT_LINE	0x3c	/* 8 bits */
++#define PCI_INTERRUPT_PIN	0x3d	/* 8 bits */
++#define PCI_MIN_GNT		0x3e	/* 8 bits */
++#define PCI_MAX_LAT		0x3f	/* 8 bits */
++
++/* Header type 1 (PCI-to-PCI bridges) */
++#define PCI_PRIMARY_BUS		0x18	/* Primary bus number */
++#define PCI_SECONDARY_BUS	0x19	/* Secondary bus number */
++#define PCI_SUBORDINATE_BUS	0x1a	/* Highest bus number behind the bridge */
++#define PCI_SEC_LATENCY_TIMER	0x1b	/* Latency timer for secondary interface */
++#define PCI_IO_BASE		0x1c	/* I/O range behind the bridge */
++#define PCI_IO_LIMIT		0x1d
++#define  PCI_IO_RANGE_TYPE_MASK	0x0fUL	/* I/O bridging type */
++#define  PCI_IO_RANGE_TYPE_16	0x00
++#define  PCI_IO_RANGE_TYPE_32	0x01
++#define  PCI_IO_RANGE_MASK	(~0x0fUL)
++#define PCI_SEC_STATUS		0x1e	/* Secondary status register, only bit 14 used */
++#define PCI_MEMORY_BASE		0x20	/* Memory range behind */
++#define PCI_MEMORY_LIMIT	0x22
++#define  PCI_MEMORY_RANGE_TYPE_MASK 0x0fUL
++#define  PCI_MEMORY_RANGE_MASK	(~0x0fUL)
++#define PCI_PREF_MEMORY_BASE	0x24	/* Prefetchable memory range behind */
++#define PCI_PREF_MEMORY_LIMIT	0x26
++#define  PCI_PREF_RANGE_TYPE_MASK 0x0fUL
++#define  PCI_PREF_RANGE_TYPE_32	0x00
++#define  PCI_PREF_RANGE_TYPE_64	0x01
++#define  PCI_PREF_RANGE_MASK	(~0x0fUL)
++#define PCI_PREF_BASE_UPPER32	0x28	/* Upper half of prefetchable memory range */
++#define PCI_PREF_LIMIT_UPPER32	0x2c
++#define PCI_IO_BASE_UPPER16	0x30	/* Upper half of I/O addresses */
++#define PCI_IO_LIMIT_UPPER16	0x32
++/* 0x34 same as for htype 0 */
++/* 0x35-0x3b is reserved */
++#define PCI_ROM_ADDRESS1	0x38	/* Same as PCI_ROM_ADDRESS, but for htype 1 */
++/* 0x3c-0x3d are same as for htype 0 */
++#define PCI_BRIDGE_CONTROL	0x3e
++#define  PCI_BRIDGE_CTL_PARITY	0x01	/* Enable parity detection on secondary interface */
++#define  PCI_BRIDGE_CTL_SERR	0x02	/* The same for SERR forwarding */
++#define  PCI_BRIDGE_CTL_ISA	0x04	/* Enable ISA mode */
++#define  PCI_BRIDGE_CTL_VGA	0x08	/* Forward VGA addresses */
++#define  PCI_BRIDGE_CTL_MASTER_ABORT	0x20  /* Report master aborts */
++#define  PCI_BRIDGE_CTL_BUS_RESET	0x40	/* Secondary bus reset */
++#define  PCI_BRIDGE_CTL_FAST_BACK	0x80	/* Fast Back2Back enabled on secondary interface */
++
++/* Header type 2 (CardBus bridges) */
++#define PCI_CB_CAPABILITY_LIST	0x14
++/* 0x15 reserved */
++#define PCI_CB_SEC_STATUS	0x16	/* Secondary status */
++#define PCI_CB_PRIMARY_BUS	0x18	/* PCI bus number */
++#define PCI_CB_CARD_BUS		0x19	/* CardBus bus number */
++#define PCI_CB_SUBORDINATE_BUS	0x1a	/* Subordinate bus number */
++#define PCI_CB_LATENCY_TIMER	0x1b	/* CardBus latency timer */
++#define PCI_CB_MEMORY_BASE_0	0x1c
++#define PCI_CB_MEMORY_LIMIT_0	0x20
++#define PCI_CB_MEMORY_BASE_1	0x24
++#define PCI_CB_MEMORY_LIMIT_1	0x28
++#define PCI_CB_IO_BASE_0	0x2c
++#define PCI_CB_IO_BASE_0_HI	0x2e
++#define PCI_CB_IO_LIMIT_0	0x30
++#define PCI_CB_IO_LIMIT_0_HI	0x32
++#define PCI_CB_IO_BASE_1	0x34
++#define PCI_CB_IO_BASE_1_HI	0x36
++#define PCI_CB_IO_LIMIT_1	0x38
++#define PCI_CB_IO_LIMIT_1_HI	0x3a
++#define  PCI_CB_IO_RANGE_MASK	(~0x03UL)
++/* 0x3c-0x3d are same as for htype 0 */
++#define PCI_CB_BRIDGE_CONTROL	0x3e
++#define  PCI_CB_BRIDGE_CTL_PARITY	0x01	/* Similar to standard bridge control register */
++#define  PCI_CB_BRIDGE_CTL_SERR		0x02
++#define  PCI_CB_BRIDGE_CTL_ISA		0x04
++#define  PCI_CB_BRIDGE_CTL_VGA		0x08
++#define  PCI_CB_BRIDGE_CTL_MASTER_ABORT	0x20
++#define  PCI_CB_BRIDGE_CTL_CB_RESET	0x40	/* CardBus reset */
++#define  PCI_CB_BRIDGE_CTL_16BIT_INT	0x80	/* Enable interrupt for 16-bit cards */
++#define  PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100	/* Prefetch enable for both memory regions */
++#define  PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200
++#define  PCI_CB_BRIDGE_CTL_POST_WRITES	0x400
++#define PCI_CB_SUBSYSTEM_VENDOR_ID	0x40
++#define PCI_CB_SUBSYSTEM_ID		0x42
++#define PCI_CB_LEGACY_MODE_BASE		0x44	/* 16-bit PC Card legacy mode base address (ExCa) */
++/* 0x48-0x7f reserved */
++
++/* Capability lists */
++
++#define PCI_CAP_LIST_ID		0	/* Capability ID */
++#define  PCI_CAP_ID_PM		0x01	/* Power Management */
++#define  PCI_CAP_ID_AGP		0x02	/* Accelerated Graphics Port */
++#define  PCI_CAP_ID_VPD		0x03	/* Vital Product Data */
++#define  PCI_CAP_ID_SLOTID	0x04	/* Slot Identification */
++#define  PCI_CAP_ID_MSI		0x05	/* Message Signalled Interrupts */
++#define  PCI_CAP_ID_CHSWP	0x06	/* CompactPCI HotSwap */
++#define  PCI_CAP_ID_PCIX	0x07	/* PCI-X */
++#define  PCI_CAP_ID_HT		0x08	/* HyperTransport */
++#define  PCI_CAP_ID_VNDR	0x09	/* Vendor specific */
++#define  PCI_CAP_ID_DBG		0x0A	/* Debug port */
++#define  PCI_CAP_ID_CCRC	0x0B	/* CompactPCI Central Resource Control */
++#define  PCI_CAP_ID_SHPC 	0x0C	/* PCI Standard Hot-Plug Controller */
++#define  PCI_CAP_ID_SSVID	0x0D	/* Bridge subsystem vendor/device ID */
++#define  PCI_CAP_ID_AGP3	0x0E	/* AGP Target PCI-PCI bridge */
++#define  PCI_CAP_ID_EXP 	0x10	/* PCI Express */
++#define  PCI_CAP_ID_MSIX	0x11	/* MSI-X */
++#define PCI_CAP_LIST_NEXT	1	/* Next capability in the list */
++#define PCI_CAP_FLAGS		2	/* Capability defined flags (16 bits) */
++#define PCI_CAP_SIZEOF		4
++
++/* Power Management Registers */
++
++#define PCI_PM_PMC		2	/* PM Capabilities Register */
++#define  PCI_PM_CAP_VER_MASK	0x0007	/* Version */
++#define  PCI_PM_CAP_PME_CLOCK	0x0008	/* PME clock required */
++#define  PCI_PM_CAP_RESERVED    0x0010  /* Reserved field */
++#define  PCI_PM_CAP_DSI		0x0020	/* Device specific initialization */
++#define  PCI_PM_CAP_AUX_POWER	0x01C0	/* Auxilliary power support mask */
++#define  PCI_PM_CAP_D1		0x0200	/* D1 power state support */
++#define  PCI_PM_CAP_D2		0x0400	/* D2 power state support */
++#define  PCI_PM_CAP_PME		0x0800	/* PME pin supported */
++#define  PCI_PM_CAP_PME_MASK	0xF800	/* PME Mask of all supported states */
++#define  PCI_PM_CAP_PME_D0	0x0800	/* PME# from D0 */
++#define  PCI_PM_CAP_PME_D1	0x1000	/* PME# from D1 */
++#define  PCI_PM_CAP_PME_D2	0x2000	/* PME# from D2 */
++#define  PCI_PM_CAP_PME_D3	0x4000	/* PME# from D3 (hot) */
++#define  PCI_PM_CAP_PME_D3cold	0x8000	/* PME# from D3 (cold) */
++#define  PCI_PM_CAP_PME_SHIFT	11	/* Start of the PME Mask in PMC */
++#define PCI_PM_CTRL		4	/* PM control and status register */
++#define  PCI_PM_CTRL_STATE_MASK	0x0003	/* Current power state (D0 to D3) */
++#define  PCI_PM_CTRL_NO_SOFT_RESET	0x0004	/* No reset for D3hot->D0 */
++#define  PCI_PM_CTRL_PME_ENABLE	0x0100	/* PME pin enable */
++#define  PCI_PM_CTRL_DATA_SEL_MASK	0x1e00	/* Data select (??) */
++#define  PCI_PM_CTRL_DATA_SCALE_MASK	0x6000	/* Data scale (??) */
++#define  PCI_PM_CTRL_PME_STATUS	0x8000	/* PME pin status */
++#define PCI_PM_PPB_EXTENSIONS	6	/* PPB support extensions (??) */
++#define  PCI_PM_PPB_B2_B3	0x40	/* Stop clock when in D3hot (??) */
++#define  PCI_PM_BPCC_ENABLE	0x80	/* Bus power/clock control enable (??) */
++#define PCI_PM_DATA_REGISTER	7	/* (??) */
++#define PCI_PM_SIZEOF		8
++
++/* AGP registers */
++
++#define PCI_AGP_VERSION		2	/* BCD version number */
++#define PCI_AGP_RFU		3	/* Rest of capability flags */
++#define PCI_AGP_STATUS		4	/* Status register */
++#define  PCI_AGP_STATUS_RQ_MASK	0xff000000	/* Maximum number of requests - 1 */
++#define  PCI_AGP_STATUS_SBA	0x0200	/* Sideband addressing supported */
++#define  PCI_AGP_STATUS_64BIT	0x0020	/* 64-bit addressing supported */
++#define  PCI_AGP_STATUS_FW	0x0010	/* FW transfers supported */
++#define  PCI_AGP_STATUS_RATE4	0x0004	/* 4x transfer rate supported */
++#define  PCI_AGP_STATUS_RATE2	0x0002	/* 2x transfer rate supported */
++#define  PCI_AGP_STATUS_RATE1	0x0001	/* 1x transfer rate supported */
++#define PCI_AGP_COMMAND		8	/* Control register */
++#define  PCI_AGP_COMMAND_RQ_MASK 0xff000000  /* Master: Maximum number of requests */
++#define  PCI_AGP_COMMAND_SBA	0x0200	/* Sideband addressing enabled */
++#define  PCI_AGP_COMMAND_AGP	0x0100	/* Allow processing of AGP transactions */
++#define  PCI_AGP_COMMAND_64BIT	0x0020 	/* Allow processing of 64-bit addresses */
++#define  PCI_AGP_COMMAND_FW	0x0010 	/* Force FW transfers */
++#define  PCI_AGP_COMMAND_RATE4	0x0004	/* Use 4x rate */
++#define  PCI_AGP_COMMAND_RATE2	0x0002	/* Use 2x rate */
++#define  PCI_AGP_COMMAND_RATE1	0x0001	/* Use 1x rate */
++#define PCI_AGP_SIZEOF		12
++
++/* Vital Product Data */
++
++#define PCI_VPD_ADDR		2	/* Address to access (15 bits!) */
++#define  PCI_VPD_ADDR_MASK	0x7fff	/* Address mask */
++#define  PCI_VPD_ADDR_F		0x8000	/* Write 0, 1 indicates completion */
++#define PCI_VPD_DATA		4	/* 32-bits of data returned here */
++
++/* Slot Identification */
++
++#define PCI_SID_ESR		2	/* Expansion Slot Register */
++#define  PCI_SID_ESR_NSLOTS	0x1f	/* Number of expansion slots available */
++#define  PCI_SID_ESR_FIC	0x20	/* First In Chassis Flag */
++#define PCI_SID_CHASSIS_NR	3	/* Chassis Number */
++
++/* Message Signalled Interrupts registers */
++
++#define PCI_MSI_FLAGS		2	/* Various flags */
++#define  PCI_MSI_FLAGS_64BIT	0x80	/* 64-bit addresses allowed */
++#define  PCI_MSI_FLAGS_QSIZE	0x70	/* Message queue size configured */
++#define  PCI_MSI_FLAGS_QMASK	0x0e	/* Maximum queue size available */
++#define  PCI_MSI_FLAGS_ENABLE	0x01	/* MSI feature enabled */
++#define  PCI_MSI_FLAGS_MASKBIT	0x100	/* 64-bit mask bits allowed */
++#define PCI_MSI_RFU		3	/* Rest of capability flags */
++#define PCI_MSI_ADDRESS_LO	4	/* Lower 32 bits */
++#define PCI_MSI_ADDRESS_HI	8	/* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
++#define PCI_MSI_DATA_32		8	/* 16 bits of data for 32-bit devices */
++#define PCI_MSI_DATA_64		12	/* 16 bits of data for 64-bit devices */
++#define PCI_MSI_MASK_BIT	16	/* Mask bits register */
++
++/* MSI-X registers (these are at offset PCI_MSIX_FLAGS) */
++#define PCI_MSIX_FLAGS		2
++#define  PCI_MSIX_FLAGS_QSIZE	0x7FF
++#define  PCI_MSIX_FLAGS_ENABLE	(1 << 15)
++#define  PCI_MSIX_FLAGS_MASKALL	(1 << 14)
++#define PCI_MSIX_FLAGS_BIRMASK	(7 << 0)
++#define PCI_MSIX_FLAGS_BITMASK	(1 << 0)
++
++/* CompactPCI Hotswap Register */
++
++#define PCI_CHSWP_CSR		2	/* Control and Status Register */
++#define  PCI_CHSWP_DHA		0x01	/* Device Hiding Arm */
++#define  PCI_CHSWP_EIM		0x02	/* ENUM# Signal Mask */
++#define  PCI_CHSWP_PIE		0x04	/* Pending Insert or Extract */
++#define  PCI_CHSWP_LOO		0x08	/* LED On / Off */
++#define  PCI_CHSWP_PI		0x30	/* Programming Interface */
++#define  PCI_CHSWP_EXT		0x40	/* ENUM# status - extraction */
++#define  PCI_CHSWP_INS		0x80	/* ENUM# status - insertion */
++
++/* PCI-X registers */
++
++#define PCI_X_CMD		2	/* Modes & Features */
++#define  PCI_X_CMD_DPERR_E	0x0001	/* Data Parity Error Recovery Enable */
++#define  PCI_X_CMD_ERO		0x0002	/* Enable Relaxed Ordering */
++#define  PCI_X_CMD_READ_512	0x0000	/* 512 byte maximum read byte count */
++#define  PCI_X_CMD_READ_1K	0x0004	/* 1Kbyte maximum read byte count */
++#define  PCI_X_CMD_READ_2K	0x0008	/* 2Kbyte maximum read byte count */
++#define  PCI_X_CMD_READ_4K	0x000c	/* 4Kbyte maximum read byte count */
++#define  PCI_X_CMD_MAX_READ	0x000c	/* Max Memory Read Byte Count */
++				/* Max # of outstanding split transactions */
++#define  PCI_X_CMD_SPLIT_1	0x0000	/* Max 1 */
++#define  PCI_X_CMD_SPLIT_2	0x0010	/* Max 2 */
++#define  PCI_X_CMD_SPLIT_3	0x0020	/* Max 3 */
++#define  PCI_X_CMD_SPLIT_4	0x0030	/* Max 4 */
++#define  PCI_X_CMD_SPLIT_8	0x0040	/* Max 8 */
++#define  PCI_X_CMD_SPLIT_12	0x0050	/* Max 12 */
++#define  PCI_X_CMD_SPLIT_16	0x0060	/* Max 16 */
++#define  PCI_X_CMD_SPLIT_32	0x0070	/* Max 32 */
++#define  PCI_X_CMD_MAX_SPLIT	0x0070	/* Max Outstanding Split Transactions */
++#define  PCI_X_CMD_VERSION(x) 	(((x) >> 12) & 3) /* Version */
++#define PCI_X_STATUS		4	/* PCI-X capabilities */
++#define  PCI_X_STATUS_DEVFN	0x000000ff	/* A copy of devfn */
++#define  PCI_X_STATUS_BUS	0x0000ff00	/* A copy of bus nr */
++#define  PCI_X_STATUS_64BIT	0x00010000	/* 64-bit device */
++#define  PCI_X_STATUS_133MHZ	0x00020000	/* 133 MHz capable */
++#define  PCI_X_STATUS_SPL_DISC	0x00040000	/* Split Completion Discarded */
++#define  PCI_X_STATUS_UNX_SPL	0x00080000	/* Unexpected Split Completion */
++#define  PCI_X_STATUS_COMPLEX	0x00100000	/* Device Complexity */
++#define  PCI_X_STATUS_MAX_READ	0x00600000	/* Designed Max Memory Read Count */
++#define  PCI_X_STATUS_MAX_SPLIT	0x03800000	/* Designed Max Outstanding Split Transactions */
++#define  PCI_X_STATUS_MAX_CUM	0x1c000000	/* Designed Max Cumulative Read Size */
++#define  PCI_X_STATUS_SPL_ERR	0x20000000	/* Rcvd Split Completion Error Msg */
++#define  PCI_X_STATUS_266MHZ	0x40000000	/* 266 MHz capable */
++#define  PCI_X_STATUS_533MHZ	0x80000000	/* 533 MHz capable */
++
++/* PCI Express capability registers */
++
++#define PCI_EXP_FLAGS		2	/* Capabilities register */
++#define PCI_EXP_FLAGS_VERS	0x000f	/* Capability version */
++#define PCI_EXP_FLAGS_TYPE	0x00f0	/* Device/Port type */
++#define  PCI_EXP_TYPE_ENDPOINT	0x0	/* Express Endpoint */
++#define  PCI_EXP_TYPE_LEG_END	0x1	/* Legacy Endpoint */
++#define  PCI_EXP_TYPE_ROOT_PORT 0x4	/* Root Port */
++#define  PCI_EXP_TYPE_UPSTREAM	0x5	/* Upstream Port */
++#define  PCI_EXP_TYPE_DOWNSTREAM 0x6	/* Downstream Port */
++#define  PCI_EXP_TYPE_PCI_BRIDGE 0x7	/* PCI/PCI-X Bridge */
++#define PCI_EXP_FLAGS_SLOT	0x0100	/* Slot implemented */
++#define PCI_EXP_FLAGS_IRQ	0x3e00	/* Interrupt message number */
++#define PCI_EXP_DEVCAP		4	/* Device capabilities */
++#define  PCI_EXP_DEVCAP_PAYLOAD	0x07	/* Max_Payload_Size */
++#define  PCI_EXP_DEVCAP_PHANTOM	0x18	/* Phantom functions */
++#define  PCI_EXP_DEVCAP_EXT_TAG	0x20	/* Extended tags */
++#define  PCI_EXP_DEVCAP_L0S	0x1c0	/* L0s Acceptable Latency */
++#define  PCI_EXP_DEVCAP_L1	0xe00	/* L1 Acceptable Latency */
++#define  PCI_EXP_DEVCAP_ATN_BUT	0x1000	/* Attention Button Present */
++#define  PCI_EXP_DEVCAP_ATN_IND	0x2000	/* Attention Indicator Present */
++#define  PCI_EXP_DEVCAP_PWR_IND	0x4000	/* Power Indicator Present */
++#define  PCI_EXP_DEVCAP_RBER	0x8000	/* Role-Based Error Reporting */
++#define  PCI_EXP_DEVCAP_PWR_VAL	0x3fc0000 /* Slot Power Limit Value */
++#define  PCI_EXP_DEVCAP_PWR_SCL	0xc000000 /* Slot Power Limit Scale */
++#define  PCI_EXP_DEVCAP_FLR     0x10000000 /* Function Level Reset */
++#define PCI_EXP_DEVCTL		8	/* Device Control */
++#define  PCI_EXP_DEVCTL_CERE	0x0001	/* Correctable Error Reporting En. */
++#define  PCI_EXP_DEVCTL_NFERE	0x0002	/* Non-Fatal Error Reporting Enable */
++#define  PCI_EXP_DEVCTL_FERE	0x0004	/* Fatal Error Reporting Enable */
++#define  PCI_EXP_DEVCTL_URRE	0x0008	/* Unsupported Request Reporting En. */
++#define  PCI_EXP_DEVCTL_RELAX_EN 0x0010 /* Enable relaxed ordering */
++#define  PCI_EXP_DEVCTL_PAYLOAD	0x00e0	/* Max_Payload_Size */
++#define  PCI_EXP_DEVCTL_EXT_TAG	0x0100	/* Extended Tag Field Enable */
++#define  PCI_EXP_DEVCTL_PHANTOM	0x0200	/* Phantom Functions Enable */
++#define  PCI_EXP_DEVCTL_AUX_PME	0x0400	/* Auxiliary Power PM Enable */
++#define  PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800  /* Enable No Snoop */
++#define  PCI_EXP_DEVCTL_READRQ	0x7000	/* Max_Read_Request_Size */
++#define  PCI_EXP_DEVCTL_BCR_FLR 0x8000  /* Bridge Configuration Retry / FLR */
++#define PCI_EXP_DEVSTA		10	/* Device Status */
++#define  PCI_EXP_DEVSTA_CED	0x01	/* Correctable Error Detected */
++#define  PCI_EXP_DEVSTA_NFED	0x02	/* Non-Fatal Error Detected */
++#define  PCI_EXP_DEVSTA_FED	0x04	/* Fatal Error Detected */
++#define  PCI_EXP_DEVSTA_URD	0x08	/* Unsupported Request Detected */
++#define  PCI_EXP_DEVSTA_AUXPD	0x10	/* AUX Power Detected */
++#define  PCI_EXP_DEVSTA_TRPND	0x20	/* Transactions Pending */
++#define PCI_EXP_LNKCAP		12	/* Link Capabilities */
++#define  PCI_EXP_LNKCAP_ASPMS	0xc00	/* ASPM Support */
++#define  PCI_EXP_LNKCAP_L0SEL	0x7000	/* L0s Exit Latency */
++#define  PCI_EXP_LNKCAP_L1EL	0x38000	/* L1 Exit Latency */
++#define  PCI_EXP_LNKCAP_CLKPM	0x40000	/* L1 Clock Power Management */
++#define PCI_EXP_LNKCTL		16	/* Link Control */
++#define  PCI_EXP_LNKCTL_RL	0x20	/* Retrain Link */
++#define  PCI_EXP_LNKCTL_CCC	0x40	/* Common Clock COnfiguration */
++#define  PCI_EXP_LNKCTL_CLKREQ_EN 0x100	/* Enable clkreq */
++#define PCI_EXP_LNKSTA		18	/* Link Status */
++#define  PCI_EXP_LNKSTA_LT	0x800	/* Link Training */
++#define  PCI_EXP_LNKSTA_SLC	0x1000	/* Slot Clock Configuration */
++#define PCI_EXP_SLTCAP		20	/* Slot Capabilities */
++#define PCI_EXP_SLTCTL		24	/* Slot Control */
++#define PCI_EXP_SLTSTA		26	/* Slot Status */
++#define PCI_EXP_RTCTL		28	/* Root Control */
++#define  PCI_EXP_RTCTL_SECEE	0x01	/* System Error on Correctable Error */
++#define  PCI_EXP_RTCTL_SENFEE	0x02	/* System Error on Non-Fatal Error */
++#define  PCI_EXP_RTCTL_SEFEE	0x04	/* System Error on Fatal Error */
++#define  PCI_EXP_RTCTL_PMEIE	0x08	/* PME Interrupt Enable */
++#define  PCI_EXP_RTCTL_CRSSVE	0x10	/* CRS Software Visibility Enable */
++#define PCI_EXP_RTCAP		30	/* Root Capabilities */
++#define PCI_EXP_RTSTA		32	/* Root Status */
++#define PCI_EXP_DEVCAP2		36	/* Device Capabilities 2 */
++#define  PCI_EXP_DEVCAP2_ARI	0x20	/* Alternative Routing-ID */
++#define PCI_EXP_DEVCTL2		40	/* Device Control 2 */
++#define  PCI_EXP_DEVCTL2_ARI	0x20	/* Alternative Routing-ID */
++
++/* Extended Capabilities (PCI-X 2.0 and Express) */
++#define PCI_EXT_CAP_ID(header)		(header & 0x0000ffff)
++#define PCI_EXT_CAP_VER(header)		((header >> 16) & 0xf)
++#define PCI_EXT_CAP_NEXT(header)	((header >> 20) & 0xffc)
++
++#define PCI_EXT_CAP_ID_ERR	1
++#define PCI_EXT_CAP_ID_VC	2
++#define PCI_EXT_CAP_ID_DSN	3
++#define PCI_EXT_CAP_ID_PWR	4
++#define PCI_EXT_CAP_ID_ARI	14
++
++/* Advanced Error Reporting */
++#define PCI_ERR_UNCOR_STATUS	4	/* Uncorrectable Error Status */
++#define  PCI_ERR_UNC_TRAIN	0x00000001	/* Training */
++#define  PCI_ERR_UNC_DLP	0x00000010	/* Data Link Protocol */
++#define  PCI_ERR_UNC_POISON_TLP	0x00001000	/* Poisoned TLP */
++#define  PCI_ERR_UNC_FCP	0x00002000	/* Flow Control Protocol */
++#define  PCI_ERR_UNC_COMP_TIME	0x00004000	/* Completion Timeout */
++#define  PCI_ERR_UNC_COMP_ABORT	0x00008000	/* Completer Abort */
++#define  PCI_ERR_UNC_UNX_COMP	0x00010000	/* Unexpected Completion */
++#define  PCI_ERR_UNC_RX_OVER	0x00020000	/* Receiver Overflow */
++#define  PCI_ERR_UNC_MALF_TLP	0x00040000	/* Malformed TLP */
++#define  PCI_ERR_UNC_ECRC	0x00080000	/* ECRC Error Status */
++#define  PCI_ERR_UNC_UNSUP	0x00100000	/* Unsupported Request */
++#define PCI_ERR_UNCOR_MASK	8	/* Uncorrectable Error Mask */
++	/* Same bits as above */
++#define PCI_ERR_UNCOR_SEVER	12	/* Uncorrectable Error Severity */
++	/* Same bits as above */
++#define PCI_ERR_COR_STATUS	16	/* Correctable Error Status */
++#define  PCI_ERR_COR_RCVR	0x00000001	/* Receiver Error Status */
++#define  PCI_ERR_COR_BAD_TLP	0x00000040	/* Bad TLP Status */
++#define  PCI_ERR_COR_BAD_DLLP	0x00000080	/* Bad DLLP Status */
++#define  PCI_ERR_COR_REP_ROLL	0x00000100	/* REPLAY_NUM Rollover */
++#define  PCI_ERR_COR_REP_TIMER	0x00001000	/* Replay Timer Timeout */
++#define PCI_ERR_COR_MASK	20	/* Correctable Error Mask */
++	/* Same bits as above */
++#define PCI_ERR_CAP		24	/* Advanced Error Capabilities */
++#define  PCI_ERR_CAP_FEP(x)	((x) & 31)	/* First Error Pointer */
++#define  PCI_ERR_CAP_ECRC_GENC	0x00000020	/* ECRC Generation Capable */
++#define  PCI_ERR_CAP_ECRC_GENE	0x00000040	/* ECRC Generation Enable */
++#define  PCI_ERR_CAP_ECRC_CHKC	0x00000080	/* ECRC Check Capable */
++#define  PCI_ERR_CAP_ECRC_CHKE	0x00000100	/* ECRC Check Enable */
++#define PCI_ERR_HEADER_LOG	28	/* Header Log Register (16 bytes) */
++#define PCI_ERR_ROOT_COMMAND	44	/* Root Error Command */
++/* Correctable Err Reporting Enable */
++#define PCI_ERR_ROOT_CMD_COR_EN		0x00000001
++/* Non-fatal Err Reporting Enable */
++#define PCI_ERR_ROOT_CMD_NONFATAL_EN	0x00000002
++/* Fatal Err Reporting Enable */
++#define PCI_ERR_ROOT_CMD_FATAL_EN	0x00000004
++#define PCI_ERR_ROOT_STATUS	48
++#define PCI_ERR_ROOT_COR_RCV		0x00000001	/* ERR_COR Received */
++/* Multi ERR_COR Received */
++#define PCI_ERR_ROOT_MULTI_COR_RCV	0x00000002
++/* ERR_FATAL/NONFATAL Recevied */
++#define PCI_ERR_ROOT_UNCOR_RCV		0x00000004
++/* Multi ERR_FATAL/NONFATAL Recevied */
++#define PCI_ERR_ROOT_MULTI_UNCOR_RCV	0x00000008
++#define PCI_ERR_ROOT_FIRST_FATAL	0x00000010	/* First Fatal */
++#define PCI_ERR_ROOT_NONFATAL_RCV	0x00000020	/* Non-Fatal Received */
++#define PCI_ERR_ROOT_FATAL_RCV		0x00000040	/* Fatal Received */
++#define PCI_ERR_ROOT_COR_SRC	52
++#define PCI_ERR_ROOT_SRC	54
++
++/* Virtual Channel */
++#define PCI_VC_PORT_REG1	4
++#define PCI_VC_PORT_REG2	8
++#define PCI_VC_PORT_CTRL	12
++#define PCI_VC_PORT_STATUS	14
++#define PCI_VC_RES_CAP		16
++#define PCI_VC_RES_CTRL		20
++#define PCI_VC_RES_STATUS	26
++
++/* Power Budgeting */
++#define PCI_PWR_DSR		4	/* Data Select Register */
++#define PCI_PWR_DATA		8	/* Data Register */
++#define  PCI_PWR_DATA_BASE(x)	((x) & 0xff)	    /* Base Power */
++#define  PCI_PWR_DATA_SCALE(x)	(((x) >> 8) & 3)    /* Data Scale */
++#define  PCI_PWR_DATA_PM_SUB(x)	(((x) >> 10) & 7)   /* PM Sub State */
++#define  PCI_PWR_DATA_PM_STATE(x) (((x) >> 13) & 3) /* PM State */
++#define  PCI_PWR_DATA_TYPE(x)	(((x) >> 15) & 7)   /* Type */
++#define  PCI_PWR_DATA_RAIL(x)	(((x) >> 18) & 7)   /* Power Rail */
++#define PCI_PWR_CAP		12	/* Capability */
++#define  PCI_PWR_CAP_BUDGET(x)	((x) & 1)	/* Included in system budget */
++
++/*
++ * Hypertransport sub capability types
++ *
++ * Unfortunately there are both 3 bit and 5 bit capability types defined
++ * in the HT spec, catering for that is a little messy. You probably don't
++ * want to use these directly, just use pci_find_ht_capability() and it
++ * will do the right thing for you.
++ */
++#define HT_3BIT_CAP_MASK	0xE0
++#define HT_CAPTYPE_SLAVE	0x00	/* Slave/Primary link configuration */
++#define HT_CAPTYPE_HOST		0x20	/* Host/Secondary link configuration */
++
++#define HT_5BIT_CAP_MASK	0xF8
++#define HT_CAPTYPE_IRQ		0x80	/* IRQ Configuration */
++#define HT_CAPTYPE_REMAPPING_40	0xA0	/* 40 bit address remapping */
++#define HT_CAPTYPE_REMAPPING_64 0xA2	/* 64 bit address remapping */
++#define HT_CAPTYPE_UNITID_CLUMP	0x90	/* Unit ID clumping */
++#define HT_CAPTYPE_EXTCONF	0x98	/* Extended Configuration Space Access */
++#define HT_CAPTYPE_MSI_MAPPING	0xA8	/* MSI Mapping Capability */
++#define  HT_MSI_FLAGS		0x02		/* Offset to flags */
++#define  HT_MSI_FLAGS_ENABLE	0x1		/* Mapping enable */
++#define  HT_MSI_FLAGS_FIXED	0x2		/* Fixed mapping only */
++#define  HT_MSI_FIXED_ADDR	0x00000000FEE00000ULL	/* Fixed addr */
++#define  HT_MSI_ADDR_LO		0x04		/* Offset to low addr bits */
++#define  HT_MSI_ADDR_LO_MASK	0xFFF00000	/* Low address bit mask */
++#define  HT_MSI_ADDR_HI		0x08		/* Offset to high addr bits */
++#define HT_CAPTYPE_DIRECT_ROUTE	0xB0	/* Direct routing configuration */
++#define HT_CAPTYPE_VCSET	0xB8	/* Virtual Channel configuration */
++#define HT_CAPTYPE_ERROR_RETRY	0xC0	/* Retry on error configuration */
++#define HT_CAPTYPE_GEN3		0xD0	/* Generation 3 hypertransport configuration */
++#define HT_CAPTYPE_PM		0xE0	/* Hypertransport powermanagement configuration */
++
++/* Alternative Routing-ID Interpretation */
++#define PCI_ARI_CAP		0x04	/* ARI Capability Register */
++#define  PCI_ARI_CAP_MFVC	0x0001	/* MFVC Function Groups Capability */
++#define  PCI_ARI_CAP_ACS	0x0002	/* ACS Function Groups Capability */
++#define  PCI_ARI_CAP_NFN(x)	(((x) >> 8) & 0xff) /* Next Function Number */
++#define PCI_ARI_CTRL		0x06	/* ARI Control Register */
++#define  PCI_ARI_CTRL_MFVC	0x0001	/* MFVC Function Groups Enable */
++#define  PCI_ARI_CTRL_ACS	0x0002	/* ACS Function Groups Enable */
++#define  PCI_ARI_CTRL_FG(x)	(((x) >> 4) & 7) /* Function Group */
++
++#endif /* LINUX_PCI_REGS_H */
+--- x/roms/seabios/src/pcibios.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/pcibios.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,234 @@
++// PCI BIOS (int 1a/b1) calls
++//
++// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2002  MandrakeSoft S.A.
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "types.h" // u32
++#include "util.h" // handle_1ab1
++#include "pci.h" // pci_config_readl
++#include "bregs.h" // struct bregs
++#include "biosvar.h" // GET_EBDA
++#include "pci_regs.h" // PCI_VENDOR_ID
++
++// romlayout.S
++extern void bios32_entry(void);
++extern void pcibios32_entry(void);
++
++#define RET_FUNC_NOT_SUPPORTED 0x81
++#define RET_BAD_VENDOR_ID      0x83
++#define RET_DEVICE_NOT_FOUND   0x86
++#define RET_BUFFER_TOO_SMALL   0x89
++
++// installation check
++static void
++handle_1ab101(struct bregs *regs)
++{
++    // Find max bus.
++    int bdf, max;
++    foreachpci(bdf, max) {
++    }
++
++    regs->al = 0x01; // Flags - "Config Mechanism #1" supported.
++    regs->bx = 0x0210; // PCI version 2.10
++    regs->cl = pci_bdf_to_bus(max - 1);
++    regs->edx = 0x20494350; // "PCI "
++    regs->edi = (u32)pcibios32_entry + BUILD_BIOS_ADDR;
++    set_code_success(regs);
++}
++
++// find pci device
++static void
++handle_1ab102(struct bregs *regs)
++{
++    u32 id = (regs->cx << 16) | regs->dx;
++    int count = regs->si;
++    int bdf, max;
++    foreachpci(bdf, max) {
++        u32 v = pci_config_readl(bdf, PCI_VENDOR_ID);
++        if (v != id)
++            continue;
++        if (count--)
++            continue;
++        regs->bx = bdf;
++        set_code_success(regs);
++        return;
++    }
++    set_code_invalid(regs, RET_DEVICE_NOT_FOUND);
++}
++
++// find class code
++static void
++handle_1ab103(struct bregs *regs)
++{
++    int count = regs->si;
++    u32 classprog = regs->ecx;
++    int bdf, max;
++    foreachpci(bdf, max) {
++        u32 v = pci_config_readl(bdf, PCI_CLASS_REVISION);
++        if ((v>>8) != classprog)
++            continue;
++        if (count--)
++            continue;
++        regs->bx = bdf;
++        set_code_success(regs);
++        return;
++    }
++    set_code_invalid(regs, RET_DEVICE_NOT_FOUND);
++}
++
++// read configuration byte
++static void
++handle_1ab108(struct bregs *regs)
++{
++    regs->cl = pci_config_readb(regs->bx, regs->di);
++    set_code_success(regs);
++}
++
++// read configuration word
++static void
++handle_1ab109(struct bregs *regs)
++{
++    regs->cx = pci_config_readw(regs->bx, regs->di);
++    set_code_success(regs);
++}
++
++// read configuration dword
++static void
++handle_1ab10a(struct bregs *regs)
++{
++    regs->ecx = pci_config_readl(regs->bx, regs->di);
++    set_code_success(regs);
++}
++
++// write configuration byte
++static void
++handle_1ab10b(struct bregs *regs)
++{
++    pci_config_writeb(regs->bx, regs->di, regs->cl);
++    set_code_success(regs);
++}
++
++// write configuration word
++static void
++handle_1ab10c(struct bregs *regs)
++{
++    pci_config_writew(regs->bx, regs->di, regs->cx);
++    set_code_success(regs);
++}
++
++// write configuration dword
++static void
++handle_1ab10d(struct bregs *regs)
++{
++    pci_config_writel(regs->bx, regs->di, regs->ecx);
++    set_code_success(regs);
++}
++
++// get irq routing options
++static void
++handle_1ab10e(struct bregs *regs)
++{
++    struct pir_header *pirtable_g = (void*)(GET_GLOBAL(PirOffset) + 0);
++    if (! pirtable_g) {
++        set_code_invalid(regs, RET_FUNC_NOT_SUPPORTED);
++        return;
++    }
++
++    struct param_s {
++        u16 size;
++        u16 buf_off;
++        u16 buf_seg;
++    } *param_far = (void*)(regs->di+0);
++
++    // Validate and update size.
++    u16 bufsize = GET_FARVAR(regs->es, param_far->size);
++    u16 pirsize = GET_GLOBAL(pirtable_g->size) - sizeof(struct pir_header);
++    SET_FARVAR(regs->es, param_far->size, pirsize);
++    if (bufsize < pirsize) {
++        set_code_invalid(regs, RET_BUFFER_TOO_SMALL);
++        return;
++    }
++
++    // Get dest buffer.
++    void *buf_far = (void*)(GET_FARVAR(regs->es, param_far->buf_off)+0);
++    u16 buf_seg = GET_FARVAR(regs->es, param_far->buf_seg);
++
++    // Memcpy pir table slots to dest buffer.
++    memcpy_far(buf_seg, buf_far
++               , get_global_seg()
++               , (void*)(pirtable_g->slots) + get_global_offset()
++               , pirsize);
++
++    // XXX - bochs bios sets bx to (1 << 9) | (1 << 11)
++    regs->bx = GET_GLOBAL(pirtable_g->exclusive_irqs);
++    set_code_success(regs);
++}
++
++static void
++handle_1ab1XX(struct bregs *regs)
++{
++    set_code_unimplemented(regs, RET_FUNC_NOT_SUPPORTED);
++}
++
++void
++handle_1ab1(struct bregs *regs)
++{
++    //debug_stub(regs);
++
++    if (! CONFIG_PCIBIOS) {
++        set_invalid(regs);
++        return;
++    }
++
++    switch (regs->al) {
++    case 0x01: handle_1ab101(regs); break;
++    case 0x02: handle_1ab102(regs); break;
++    case 0x03: handle_1ab103(regs); break;
++    case 0x08: handle_1ab108(regs); break;
++    case 0x09: handle_1ab109(regs); break;
++    case 0x0a: handle_1ab10a(regs); break;
++    case 0x0b: handle_1ab10b(regs); break;
++    case 0x0c: handle_1ab10c(regs); break;
++    case 0x0d: handle_1ab10d(regs); break;
++    case 0x0e: handle_1ab10e(regs); break;
++    default:   handle_1ab1XX(regs); break;
++    }
++}
++
++
++/****************************************************************
++ * 32bit interface
++ ****************************************************************/
++
++// Entry point for 32bit pci bios functions.
++void VISIBLE32SEG
++handle_pcibios32(struct bregs *regs)
++{
++    debug_enter(regs, DEBUG_HDL_pcibios32);
++    handle_1ab1(regs);
++}
++
++struct bios32_s {
++    u32 signature;
++    u32 entry;
++    u8 version;
++    u8 length;
++    u8 checksum;
++    u8 reserved[5];
++} PACKED;
++
++struct bios32_s BIOS32HEADER __aligned(16) VAR16EXPORT = {
++    .signature = 0x5f32335f, // _32_
++    .length = sizeof(BIOS32HEADER) / 16,
++};
++
++void
++bios32_setup(void)
++{
++    dprintf(3, "init bios32\n");
++
++    BIOS32HEADER.entry = (u32)bios32_entry;
++    BIOS32HEADER.checksum -= checksum(&BIOS32HEADER, sizeof(BIOS32HEADER));
++}
+--- x/roms/seabios/src/pciinit.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/pciinit.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,206 @@
++// Initialize PCI devices (on emulators)
++//
++// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2006 Fabrice Bellard
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "util.h" // dprintf
++#include "pci.h" // pci_config_readl
++#include "biosvar.h" // GET_EBDA
++#include "pci_ids.h" // PCI_VENDOR_ID_INTEL
++#include "pci_regs.h" // PCI_COMMAND
++
++#define PCI_ROM_SLOT 6
++#define PCI_NUM_REGIONS 7
++
++static u32 pci_bios_io_addr;
++static u32 pci_bios_mem_addr;
++/* host irqs corresponding to PCI irqs A-D */
++static u8 pci_irqs[4] = {
++    10, 10, 11, 11
++};
++
++static void pci_set_io_region_addr(u16 bdf, int region_num, u32 addr)
++{
++    u32 ofs, old_addr;
++
++    if (region_num == PCI_ROM_SLOT) {
++        ofs = PCI_ROM_ADDRESS;
++    } else {
++        ofs = PCI_BASE_ADDRESS_0 + region_num * 4;
++    }
++
++    old_addr = pci_config_readl(bdf, ofs);
++
++    pci_config_writel(bdf, ofs, addr);
++    dprintf(1, "region %d: 0x%08x\n", region_num, addr);
++}
++
++/* return the global irq number corresponding to a given device irq
++   pin. We could also use the bus number to have a more precise
++   mapping. */
++static int pci_slot_get_pirq(u16 bdf, int irq_num)
++{
++    int slot_addend = pci_bdf_to_dev(bdf) - 1;
++    return (irq_num + slot_addend) & 3;
++}
++
++static void pci_bios_init_bridges(u16 bdf)
++{
++    u16 vendor_id = pci_config_readw(bdf, PCI_VENDOR_ID);
++    u16 device_id = pci_config_readw(bdf, PCI_DEVICE_ID);
++
++    if (vendor_id == PCI_VENDOR_ID_INTEL
++        && (device_id == PCI_DEVICE_ID_INTEL_82371SB_0
++            || device_id == PCI_DEVICE_ID_INTEL_82371AB_0)) {
++        int i, irq;
++        u8 elcr[2];
++
++        /* PIIX3/PIIX4 PCI to ISA bridge */
++
++        elcr[0] = 0x00;
++        elcr[1] = 0x00;
++        for (i = 0; i < 4; i++) {
++            irq = pci_irqs[i];
++            /* set to trigger level */
++            elcr[irq >> 3] |= (1 << (irq & 7));
++            /* activate irq remapping in PIIX */
++            pci_config_writeb(bdf, 0x60 + i, irq);
++        }
++        outb(elcr[0], 0x4d0);
++        outb(elcr[1], 0x4d1);
++        dprintf(1, "PIIX3/PIIX4 init: elcr=%02x %02x\n",
++                elcr[0], elcr[1]);
++    }
++}
++
++static void pci_bios_init_device(u16 bdf)
++{
++    int class;
++    u32 *paddr;
++    int i, pin, pic_irq, vendor_id, device_id;
++
++    class = pci_config_readw(bdf, PCI_CLASS_DEVICE);
++    vendor_id = pci_config_readw(bdf, PCI_VENDOR_ID);
++    device_id = pci_config_readw(bdf, PCI_DEVICE_ID);
++    dprintf(1, "PCI: bus=%d devfn=0x%02x: vendor_id=0x%04x device_id=0x%04x\n"
++            , pci_bdf_to_bus(bdf), pci_bdf_to_devfn(bdf), vendor_id, device_id);
++    switch (class) {
++    case PCI_CLASS_STORAGE_IDE:
++        if (vendor_id == PCI_VENDOR_ID_INTEL
++            && (device_id == PCI_DEVICE_ID_INTEL_82371SB_1
++                || device_id == PCI_DEVICE_ID_INTEL_82371AB)) {
++            /* PIIX3/PIIX4 IDE */
++            pci_config_writew(bdf, 0x40, 0x8000); // enable IDE0
++            pci_config_writew(bdf, 0x42, 0x8000); // enable IDE1
++            goto default_map;
++        } else {
++            /* IDE: we map it as in ISA mode */
++            pci_set_io_region_addr(bdf, 0, PORT_ATA1_CMD_BASE);
++            pci_set_io_region_addr(bdf, 1, PORT_ATA1_CTRL_BASE);
++            pci_set_io_region_addr(bdf, 2, PORT_ATA2_CMD_BASE);
++            pci_set_io_region_addr(bdf, 3, PORT_ATA2_CTRL_BASE);
++        }
++        break;
++    case PCI_CLASS_SYSTEM_PIC:
++        /* PIC */
++        if (vendor_id == PCI_VENDOR_ID_IBM) {
++            /* IBM */
++            if (device_id == 0x0046 || device_id == 0xFFFF) {
++                /* MPIC & MPIC2 */
++                pci_set_io_region_addr(bdf, 0, 0x80800000 + 0x00040000);
++            }
++        }
++        break;
++    case 0xff00:
++        if (vendor_id == PCI_VENDOR_ID_APPLE &&
++            (device_id == 0x0017 || device_id == 0x0022)) {
++            /* macio bridge */
++            pci_set_io_region_addr(bdf, 0, 0x80800000);
++        }
++        break;
++    default:
++    default_map:
++        /* default memory mappings */
++        for (i = 0; i < PCI_NUM_REGIONS; i++) {
++            int ofs;
++            if (i == PCI_ROM_SLOT)
++                ofs = PCI_ROM_ADDRESS;
++            else
++                ofs = PCI_BASE_ADDRESS_0 + i * 4;
++
++            u32 old = pci_config_readl(bdf, ofs);
++            u32 mask;
++            if (i == PCI_ROM_SLOT) {
++                mask = PCI_ROM_ADDRESS_MASK;
++                pci_config_writel(bdf, ofs, mask);
++            } else {
++                if (old & PCI_BASE_ADDRESS_SPACE_IO)
++                    mask = PCI_BASE_ADDRESS_IO_MASK;
++                else
++                    mask = PCI_BASE_ADDRESS_MEM_MASK;
++                pci_config_writel(bdf, ofs, ~0);
++            }
++            u32 val = pci_config_readl(bdf, ofs);
++            pci_config_writel(bdf, ofs, old);
++
++            if (val != 0) {
++                u32 size = (~(val & mask)) + 1;
++                if (val & PCI_BASE_ADDRESS_SPACE_IO)
++                    paddr = &pci_bios_io_addr;
++                else
++                    paddr = &pci_bios_mem_addr;
++                *paddr = ALIGN(*paddr, size);
++                pci_set_io_region_addr(bdf, i, *paddr);
++                *paddr += size;
++            }
++        }
++        break;
++    }
++
++    /* enable memory mappings */
++    pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
++
++    /* map the interrupt */
++    pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN);
++    if (pin != 0) {
++        pin = pci_slot_get_pirq(bdf, pin - 1);
++        pic_irq = pci_irqs[pin];
++        pci_config_writeb(bdf, PCI_INTERRUPT_LINE, pic_irq);
++    }
++
++    if (vendor_id == PCI_VENDOR_ID_INTEL
++        && device_id == PCI_DEVICE_ID_INTEL_82371AB_3) {
++        /* PIIX4 Power Management device (for ACPI) */
++
++        // acpi sci is hardwired to 9
++        pci_config_writeb(bdf, PCI_INTERRUPT_LINE, 9);
++
++        pci_config_writel(bdf, 0x40, PORT_ACPI_PM_BASE | 1);
++        pci_config_writeb(bdf, 0x80, 0x01); /* enable PM io space */
++        pci_config_writel(bdf, 0x90, PORT_SMB_BASE | 1);
++        pci_config_writeb(bdf, 0xd2, 0x09); /* enable SMBus io space */
++    }
++}
++
++void
++pci_setup(void)
++{
++    if (CONFIG_COREBOOT)
++        // Already done by coreboot.
++        return;
++
++    dprintf(3, "pci setup\n");
++
++    pci_bios_io_addr = 0xc000;
++    pci_bios_mem_addr = BUILD_PCIMEM_START;
++
++    int bdf, max;
++    foreachpci(bdf, max) {
++        pci_bios_init_bridges(bdf);
++    }
++    foreachpci(bdf, max) {
++        pci_bios_init_device(bdf);
++    }
++}
+--- x/roms/seabios/src/pic.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/pic.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,52 @@
++// Helpers for working with i8259 interrupt controller.
++//
++// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2002  MandrakeSoft S.A.
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "pic.h" // get_pic1_isr
++#include "util.h" // dprintf
++#include "config.h" // CONFIG_*
++
++void
++set_pics(u8 irq0, u8 irq8)
++{
++    // Send ICW1 (select OCW1 + will send ICW4)
++    outb(0x11, PORT_PIC1_CMD);
++    outb(0x11, PORT_PIC2_CMD);
++    // Send ICW2 (base irqs: 0x08-0x0f for irq0-7, 0x70-0x77 for irq8-15)
++    outb(irq0, PORT_PIC1_DATA);
++    outb(irq8, PORT_PIC2_DATA);
++    // Send ICW3 (cascaded pic ids)
++    outb(0x04, PORT_PIC1_DATA);
++    outb(0x02, PORT_PIC2_DATA);
++    // Send ICW4 (enable 8086 mode)
++    outb(0x01, PORT_PIC1_DATA);
++    outb(0x01, PORT_PIC2_DATA);
++    // Mask all irqs (except cascaded PIC2 irq)
++    outb(~PIC1_IRQ2, PORT_PIC1_DATA);
++    outb(~0, PORT_PIC2_DATA);
++}
++
++void
++pic_setup(void)
++{
++    dprintf(3, "init pic\n");
++    set_pics(0x08, 0x70);
++}
++
++// Handler for otherwise unused hardware irqs.
++void VISIBLE16
++handle_hwpic1(struct bregs *regs)
++{
++    dprintf(DEBUG_ISR_hwpic1, "handle_hwpic1 irq=%x\n", get_pic1_isr());
++    eoi_pic1();
++}
++
++void VISIBLE16
++handle_hwpic2(struct bregs *regs)
++{
++    dprintf(DEBUG_ISR_hwpic2, "handle_hwpic2 irq=%x\n", get_pic2_isr());
++    eoi_pic2();
++}
+--- x/roms/seabios/src/pic.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/pic.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,104 @@
++// Helpers for working with i8259 interrupt controller.
++//
++// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2002  MandrakeSoft S.A.
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++#ifndef __PIC_H
++#define __PIC_H
++
++#include "ioport.h" // PORT_PIC*
++
++// PORT_PIC1 bitdefs
++#define PIC1_IRQ0  (1<<0)
++#define PIC1_IRQ1  (1<<1)
++#define PIC1_IRQ2  (1<<2)
++#define PIC1_IRQ5  (1<<5)
++#define PIC1_IRQ6  (1<<6)
++// PORT_PIC2 bitdefs
++#define PIC2_IRQ8  (1<<0)
++#define PIC2_IRQ12 (1<<4)
++#define PIC2_IRQ13 (1<<5)
++#define PIC2_IRQ14 (1<<6)
++
++static inline void
++eoi_pic1(void)
++{
++    // Send eoi (select OCW2 + eoi)
++    outb(0x20, PORT_PIC1_CMD);
++}
++
++static inline void
++eoi_pic2(void)
++{
++    // Send eoi (select OCW2 + eoi)
++    outb(0x20, PORT_PIC2_CMD);
++    eoi_pic1();
++}
++
++static inline void
++unmask_pic1(u8 irq)
++{
++    outb(inb(PORT_PIC1_DATA) & ~irq, PORT_PIC1_DATA);
++}
++
++static inline void
++unmask_pic2(u8 irq)
++{
++    outb(inb(PORT_PIC2_DATA) & ~irq, PORT_PIC2_DATA);
++}
++
++static inline void
++mask_pic1(u8 irq)
++{
++    outb(inb(PORT_PIC1_DATA) | irq, PORT_PIC1_DATA);
++}
++
++static inline void
++mask_pic2(u8 irq)
++{
++    outb(inb(PORT_PIC2_DATA) | irq, PORT_PIC2_DATA);
++}
++
++static inline u8
++get_pic1_isr(void)
++{
++    // 0x0b == select OCW1 + read ISR
++    outb(0x0b, PORT_PIC1_CMD);
++    return inb(PORT_PIC1_CMD);
++}
++
++static inline u8
++get_pic2_isr(void)
++{
++    // 0x0b == select OCW1 + read ISR
++    outb(0x0b, PORT_PIC2_CMD);
++    return inb(PORT_PIC2_CMD);
++}
++
++// post.c
++void __set_irq(int vector, void *loc);
++
++static inline void
++__enable_hwirq(int hwirq, void (*func)(void))
++{
++    int vector;
++    if (hwirq < 8) {
++        unmask_pic1(1 << hwirq);
++        vector = 0x08 + hwirq;
++    } else {
++        unmask_pic2(1 << (hwirq - 8));
++        vector = 0x70 + hwirq - 8;
++    }
++    __set_irq(vector, func);
++}
++
++#define enable_hwirq(irq, func) do {            \
++        extern void func (void);                \
++        __enable_hwirq(irq, func);              \
++    } while (0)
++
++void set_pics(u8 irq0, u8 irq8);
++void pic_setup(void);
++
++#endif // pic.h
+--- x/roms/seabios/src/pirtable.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/pirtable.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,105 @@
++// PIR table generation (for emulators)
++//
++// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2002  MandrakeSoft S.A.
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "pci.h" // struct pir_header
++#include "util.h" // checksum
++#include "biosvar.h" // SET_EBDA
++
++u16 PirOffset VAR16VISIBLE;
++
++struct pir_table {
++    struct pir_header pir;
++    struct pir_slot slots[6];
++} PACKED;
++
++extern struct pir_table PIR_TABLE;
++#if CONFIG_PIRTABLE && !CONFIG_COREBOOT
++struct pir_table PIR_TABLE __aligned(16) VAR16EXPORT = {
++    .pir = {
++        .version = 0x0100,
++        .size = sizeof(struct pir_table),
++        .router_devfunc = 0x08,
++        .compatible_devid = 0x122e8086,
++    },
++    .slots = {
++        {
++            // first slot entry PCI-to-ISA (embedded)
++            .dev = 1<<3,
++            .links = {
++                {.link = 0x60, .bitmap = 0xdef8}, // INTA#
++                {.link = 0x61, .bitmap = 0xdef8}, // INTB#
++                {.link = 0x62, .bitmap = 0xdef8}, // INTC#
++                {.link = 0x63, .bitmap = 0xdef8}, // INTD#
++            },
++            .slot_nr = 0, // embedded
++        }, {
++            // second slot entry: 1st PCI slot
++            .dev = 2<<3,
++            .links = {
++                {.link = 0x61, .bitmap = 0xdef8}, // INTA#
++                {.link = 0x62, .bitmap = 0xdef8}, // INTB#
++                {.link = 0x63, .bitmap = 0xdef8}, // INTC#
++                {.link = 0x60, .bitmap = 0xdef8}, // INTD#
++            },
++            .slot_nr = 1,
++        }, {
++            // third slot entry: 2nd PCI slot
++            .dev = 3<<3,
++            .links = {
++                {.link = 0x62, .bitmap = 0xdef8}, // INTA#
++                {.link = 0x63, .bitmap = 0xdef8}, // INTB#
++                {.link = 0x60, .bitmap = 0xdef8}, // INTC#
++                {.link = 0x61, .bitmap = 0xdef8}, // INTD#
++            },
++            .slot_nr = 2,
++        }, {
++            // 4th slot entry: 3rd PCI slot
++            .dev = 4<<3,
++            .links = {
++                {.link = 0x63, .bitmap = 0xdef8}, // INTA#
++                {.link = 0x60, .bitmap = 0xdef8}, // INTB#
++                {.link = 0x61, .bitmap = 0xdef8}, // INTC#
++                {.link = 0x62, .bitmap = 0xdef8}, // INTD#
++            },
++            .slot_nr = 3,
++        }, {
++            // 5th slot entry: 4rd PCI slot
++            .dev = 5<<3,
++            .links = {
++                {.link = 0x60, .bitmap = 0xdef8}, // INTA#
++                {.link = 0x61, .bitmap = 0xdef8}, // INTB#
++                {.link = 0x62, .bitmap = 0xdef8}, // INTC#
++                {.link = 0x63, .bitmap = 0xdef8}, // INTD#
++            },
++            .slot_nr = 4,
++        }, {
++            // 6th slot entry: 5rd PCI slot
++            .dev = 6<<3,
++            .links = {
++                {.link = 0x61, .bitmap = 0xdef8}, // INTA#
++                {.link = 0x62, .bitmap = 0xdef8}, // INTB#
++                {.link = 0x63, .bitmap = 0xdef8}, // INTC#
++                {.link = 0x60, .bitmap = 0xdef8}, // INTD#
++            },
++            .slot_nr = 5,
++        },
++    }
++};
++#endif // CONFIG_PIRTABLE && !CONFIG_COREBOOT
++
++void
++create_pirtable(void)
++{
++    if (! CONFIG_PIRTABLE)
++        return;
++
++    dprintf(3, "init PIR table\n");
++
++    PIR_TABLE.pir.signature = PIR_SIGNATURE;
++    PIR_TABLE.pir.checksum -= checksum(&PIR_TABLE, sizeof(PIR_TABLE));
++    PirOffset = (u32)&PIR_TABLE.pir - BUILD_BIOS_ADDR;
++}
+--- x/roms/seabios/src/pmm.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/pmm.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,510 @@
++// Post memory manager (PMM) calls
++//
++// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "util.h" // checksum
++#include "config.h" // BUILD_BIOS_ADDR
++#include "memmap.h" // find_high_area
++#include "farptr.h" // GET_FARVAR
++#include "biosvar.h" // GET_BDA
++
++
++#if MODESEGMENT
++// The 16bit pmm entry points runs in "big real" mode, and can
++// therefore read/write to the 32bit malloc variables.
++#define GET_PMMVAR(var) ({                      \
++            SET_SEG(ES, 0);                     \
++            __GET_VAR("addr32 ", ES, (var)); })
++#define SET_PMMVAR(var, val) do {               \
++        SET_SEG(ES, 0);                         \
++        __SET_VAR("addr32 ", ES, (var), (val)); \
++    } while (0)
++#else
++#define GET_PMMVAR(var) (var)
++#define SET_PMMVAR(var, val) do { (var) = (val); } while (0)
++#endif
++
++// Zone definitions
++struct zone_s {
++    u32 top, bottom, cur;
++};
++
++struct zone_s ZoneLow VAR32FLATVISIBLE, ZoneHigh VAR32FLATVISIBLE;
++struct zone_s ZoneFSeg VAR32FLATVISIBLE;
++struct zone_s ZoneTmpLow VAR32FLATVISIBLE, ZoneTmpHigh VAR32FLATVISIBLE;
++
++struct zone_s *Zones[] VAR32FLATVISIBLE = {
++    &ZoneTmpLow, &ZoneLow, &ZoneFSeg, &ZoneTmpHigh, &ZoneHigh
++};
++
++
++/****************************************************************
++ * ebda movement
++ ****************************************************************/
++
++// Move ebda
++static int
++relocate_ebda(u32 newebda, u32 oldebda, u8 ebda_size)
++{
++    u32 lowram = GET_BDA(mem_size_kb) * 1024;
++    if (oldebda != lowram)
++        // EBDA isn't at end of ram - give up.
++        return -1;
++
++    // Do copy
++    if (MODESEGMENT)
++        memcpy_far(FLATPTR_TO_SEG(newebda)
++                   , (void*)FLATPTR_TO_OFFSET(newebda)
++                   , FLATPTR_TO_SEG(oldebda)
++                   , (void*)FLATPTR_TO_OFFSET(oldebda)
++                   , ebda_size * 1024);
++    else
++        memmove((void*)newebda, (void*)oldebda, ebda_size * 1024);
++
++    // Update indexes
++    dprintf(1, "ebda moved from %x to %x\n", oldebda, newebda);
++    SET_BDA(mem_size_kb, newebda / 1024);
++    SET_BDA(ebda_seg, FLATPTR_TO_SEG(newebda));
++    return 0;
++}
++
++// Support expanding the ZoneLow dynamically.
++static void
++zonelow_expand(u32 size, u32 align)
++{
++    u32 oldpos = GET_PMMVAR(ZoneLow.cur);
++    u32 newpos = ALIGN_DOWN(oldpos - size, align);
++    u32 bottom = GET_PMMVAR(ZoneLow.bottom);
++    if (newpos >= bottom && newpos <= oldpos)
++        // Space already present.
++        return;
++    u16 ebda_seg = get_ebda_seg();
++    u32 ebda_pos = (u32)MAKE_FLATPTR(ebda_seg, 0);
++    u8 ebda_size = GET_EBDA2(ebda_seg, size);
++    u32 ebda_end = ebda_pos + ebda_size * 1024;
++    if (ebda_end != bottom) {
++        // Something else is after ebda - can't use any existing space.
++        oldpos = ebda_end;
++        newpos = ALIGN_DOWN(oldpos - size, align);
++    }
++    u32 newbottom = ALIGN_DOWN(newpos, 1024);
++    u32 newebda = ALIGN_DOWN(newbottom - ebda_size * 1024, 1024);
++    if (newebda < BUILD_EBDA_MINIMUM)
++        // Not enough space.
++        return;
++
++    // Move ebda
++    int ret = relocate_ebda(newebda, ebda_pos, ebda_size);
++    if (ret)
++        return;
++
++    // Update zone
++    SET_PMMVAR(ZoneLow.cur, oldpos);
++    SET_PMMVAR(ZoneLow.bottom, newbottom);
++}
++
++
++/****************************************************************
++ * zone allocations
++ ****************************************************************/
++
++// Obtain memory from a given zone.
++static void *
++zone_malloc(struct zone_s *zone, u32 size, u32 align)
++{
++    u32 oldpos = GET_PMMVAR(zone->cur);
++    u32 newpos = ALIGN_DOWN(oldpos - size, align);
++    if (newpos < GET_PMMVAR(zone->bottom) || newpos > oldpos)
++        // No space
++        return NULL;
++    SET_PMMVAR(zone->cur, newpos);
++    return (void*)newpos;
++}
++
++// Find the zone that contains the given data block.
++static struct zone_s *
++zone_find(void *data)
++{
++    int i;
++    for (i=0; i<ARRAY_SIZE(Zones); i++) {
++        struct zone_s *zone = GET_PMMVAR(Zones[i]);
++        if ((u32)data >= GET_PMMVAR(zone->cur)
++            && (u32)data < GET_PMMVAR(zone->top))
++            return zone;
++    }
++    return NULL;
++}
++
++// Return memory to a zone (if it was the last to be allocated).
++static int
++zone_free(void *data, u32 olddata)
++{
++    struct zone_s *zone = zone_find(data);
++    if (!zone || !data || GET_PMMVAR(zone->cur) != (u32)data)
++        return -1;
++    SET_PMMVAR(zone->cur, olddata);
++    return 0;
++}
++
++// Report the status of all the zones.
++static void
++dumpZones(void)
++{
++    int i;
++    for (i=0; i<ARRAY_SIZE(Zones); i++) {
++        struct zone_s *zone = Zones[i];
++        u32 used = zone->top - zone->cur;
++        u32 avail = zone->top - zone->bottom;
++        u32 pct = avail ? ((100 * used) / avail) : 0;
++        dprintf(2, "zone %d: %08x-%08x used=%d (%d%%)\n"
++                , i, zone->bottom, zone->top, used, pct);
++    }
++}
++
++
++/****************************************************************
++ * tracked memory allocations
++ ****************************************************************/
++
++// Information on PMM tracked allocations
++struct pmmalloc_s {
++    void *data;
++    u32 olddata;
++    u32 handle;
++    u32 oldallocdata;
++    struct pmmalloc_s *next;
++};
++
++struct pmmalloc_s *PMMAllocs VAR32FLATVISIBLE;
++
++// Allocate memory from the given zone and track it as a PMM allocation
++void *
++pmm_malloc(struct zone_s *zone, u32 handle, u32 size, u32 align)
++{
++    u32 oldallocdata = GET_PMMVAR(ZoneTmpHigh.cur);
++    struct pmmalloc_s *info = zone_malloc(&ZoneTmpHigh, sizeof(*info)
++                                          , MALLOC_MIN_ALIGN);
++    if (!info) {
++        oldallocdata = GET_PMMVAR(ZoneTmpLow.cur);
++        info = zone_malloc(&ZoneTmpLow, sizeof(*info), MALLOC_MIN_ALIGN);
++        if (!info)
++            return NULL;
++    }
++    if (zone == &ZoneLow)
++        zonelow_expand(size, align);
++    u32 olddata = GET_PMMVAR(zone->cur);
++    void *data = zone_malloc(zone, size, align);
++    if (! data) {
++        zone_free(info, oldallocdata);
++        return NULL;
++    }
++    dprintf(8, "pmm_malloc zone=%p handle=%x size=%d align=%x"
++            " ret=%p (info=%p)\n"
++            , zone, handle, size, align
++            , data, info);
++    SET_PMMVAR(info->data, data);
++    SET_PMMVAR(info->olddata, olddata);
++    SET_PMMVAR(info->handle, handle);
++    SET_PMMVAR(info->oldallocdata, oldallocdata);
++    SET_PMMVAR(info->next, GET_PMMVAR(PMMAllocs));
++    SET_PMMVAR(PMMAllocs, info);
++    return data;
++}
++
++// Free a raw data block (either from a zone or from pmm alloc list).
++static void
++pmm_free_data(void *data, u32 olddata)
++{
++    int ret = zone_free(data, olddata);
++    if (!ret)
++        // Success - done.
++        return;
++    struct pmmalloc_s *info;
++    for (info=GET_PMMVAR(PMMAllocs); info; info = GET_PMMVAR(info->next))
++        if (GET_PMMVAR(info->olddata) == (u32)data) {
++            SET_PMMVAR(info->olddata, olddata);
++            return;
++        } else if (GET_PMMVAR(info->oldallocdata) == (u32)data) {
++            SET_PMMVAR(info->oldallocdata, olddata);
++            return;
++        }
++}
++
++// Free a data block allocated with pmm_malloc
++int
++pmm_free(void *data)
++{
++    struct pmmalloc_s **pinfo = &PMMAllocs;
++    for (;;) {
++        struct pmmalloc_s *info = GET_PMMVAR(*pinfo);
++        if (!info)
++            return -1;
++        if (GET_PMMVAR(info->data) == data) {
++            SET_PMMVAR(*pinfo, GET_PMMVAR(info->next));
++            u32 oldallocdata = GET_PMMVAR(info->oldallocdata);
++            u32 olddata = GET_PMMVAR(info->olddata);
++            pmm_free_data(data, olddata);
++            pmm_free_data(info, oldallocdata);
++            dprintf(8, "pmm_free data=%p olddata=%p oldallocdata=%p info=%p\n"
++                    , data, (void*)olddata, (void*)oldallocdata, info);
++            return 0;
++        }
++        pinfo = &info->next;
++    }
++}
++
++// Find the amount of free space in a given zone.
++static u32
++pmm_getspace(struct zone_s *zone)
++{
++    // XXX - doesn't account for ZoneLow being able to grow.
++    u32 space = GET_PMMVAR(zone->cur) - GET_PMMVAR(zone->bottom);
++    if (zone != &ZoneTmpHigh && zone != &ZoneTmpLow)
++        return space;
++    // Account for space needed for PMM tracking.
++    u32 reserve = ALIGN(sizeof(struct pmmalloc_s), MALLOC_MIN_ALIGN);
++    if (space <= reserve)
++        return 0;
++    return space - reserve;
++}
++
++// Find the data block allocated with pmm_malloc with a given handle.
++static void *
++pmm_find(u32 handle)
++{
++    struct pmmalloc_s *info;
++    for (info=GET_PMMVAR(PMMAllocs); info; info = GET_PMMVAR(info->next))
++        if (GET_PMMVAR(info->handle) == handle)
++            return GET_PMMVAR(info->data);
++    return NULL;
++}
++
++void
++malloc_setup(void)
++{
++    ASSERT32FLAT();
++    dprintf(3, "malloc setup\n");
++
++    PMMAllocs = NULL;
++
++    // Memory in 0xf0000 area.
++    extern u8 code32flat_start[];
++    if ((u32)code32flat_start > BUILD_BIOS_ADDR)
++        // Clear unused parts of f-segment
++        memset((void*)BUILD_BIOS_ADDR, 0
++               , (u32)code32flat_start - BUILD_BIOS_ADDR);
++    memset(BiosTableSpace, 0, CONFIG_MAX_BIOSTABLE);
++    ZoneFSeg.bottom = (u32)BiosTableSpace;
++    ZoneFSeg.top = ZoneFSeg.cur = ZoneFSeg.bottom + CONFIG_MAX_BIOSTABLE;
++
++    // Memory under 1Meg.
++    ZoneTmpLow.bottom = BUILD_STACK_ADDR;
++    ZoneTmpLow.top = ZoneTmpLow.cur = BUILD_EBDA_MINIMUM;
++
++    // Permanent memory under 1Meg.
++    ZoneLow.bottom = ZoneLow.top = ZoneLow.cur = BUILD_LOWRAM_END;
++
++    // Find memory at the top of ram.
++    struct e820entry *e = find_high_area(CONFIG_MAX_HIGHTABLE+MALLOC_MIN_ALIGN);
++    if (!e) {
++        // No memory above 1Meg
++        memset(&ZoneHigh, 0, sizeof(ZoneHigh));
++        memset(&ZoneTmpHigh, 0, sizeof(ZoneTmpHigh));
++        return;
++    }
++    u32 top = e->start + e->size, bottom = e->start;
++
++    // Memory at top of ram.
++    ZoneHigh.bottom = ALIGN(top - CONFIG_MAX_HIGHTABLE, MALLOC_MIN_ALIGN);
++    ZoneHigh.top = ZoneHigh.cur = ZoneHigh.bottom + CONFIG_MAX_HIGHTABLE;
++    add_e820(ZoneHigh.bottom, CONFIG_MAX_HIGHTABLE, E820_RESERVED);
++
++    // Memory above 1Meg
++    ZoneTmpHigh.bottom = ALIGN(bottom, MALLOC_MIN_ALIGN);
++    ZoneTmpHigh.top = ZoneTmpHigh.cur = ZoneHigh.bottom;
++}
++
++void
++malloc_finalize(void)
++{
++    dprintf(3, "malloc finalize\n");
++
++    dumpZones();
++
++    // Reserve more low-mem if needed.
++    u32 endlow = GET_BDA(mem_size_kb)*1024;
++    add_e820(endlow, BUILD_LOWRAM_END-endlow, E820_RESERVED);
++
++    // Give back unused high ram.
++    u32 giveback = ALIGN_DOWN(ZoneHigh.cur - ZoneHigh.bottom, PAGE_SIZE);
++    add_e820(ZoneHigh.bottom, giveback, E820_RAM);
++    dprintf(1, "Returned %d bytes of ZoneHigh\n", giveback);
++
++    // Clear low-memory allocations.
++    memset((void*)ZoneTmpLow.bottom, 0, ZoneTmpLow.top - ZoneTmpLow.bottom);
++}
++
++
++/****************************************************************
++ * pmm interface
++ ****************************************************************/
++
++struct pmmheader {
++    u32 signature;
++    u8 version;
++    u8 length;
++    u8 checksum;
++    u16 entry_offset;
++    u16 entry_seg;
++    u8 reserved[5];
++} PACKED;
++
++extern struct pmmheader PMMHEADER;
++
++#define PMM_SIGNATURE 0x4d4d5024 // $PMM
++
++#if CONFIG_PMM
++struct pmmheader PMMHEADER __aligned(16) VAR16EXPORT = {
++    .version = 0x01,
++    .length = sizeof(PMMHEADER),
++    .entry_seg = SEG_BIOS,
++};
++#endif
++
++#define PMM_FUNCTION_NOT_SUPPORTED 0xffffffff
++
++// PMM - allocate
++static u32
++handle_pmm00(u16 *args)
++{
++    u32 length = *(u32*)&args[1], handle = *(u32*)&args[3];
++    u16 flags = args[5];
++    dprintf(3, "pmm00: length=%x handle=%x flags=%x\n"
++            , length, handle, flags);
++    struct zone_s *lowzone = &ZoneTmpLow, *highzone = &ZoneTmpHigh;
++    if (flags & 8) {
++        // Permanent memory request.
++        lowzone = &ZoneLow;
++        highzone = &ZoneHigh;
++    }
++    if (!length) {
++        // Memory size request
++        switch (flags & 3) {
++        default:
++        case 0:
++            return 0;
++        case 1:
++            return pmm_getspace(lowzone);
++        case 2:
++            return pmm_getspace(highzone);
++        case 3: {
++            u32 spacelow = pmm_getspace(lowzone);
++            u32 spacehigh = pmm_getspace(highzone);
++            if (spacelow > spacehigh)
++                return spacelow;
++            return spacehigh;
++        }
++        }
++    }
++    u32 size = length * 16;
++    if ((s32)size <= 0)
++        return 0;
++    u32 align = MALLOC_MIN_ALIGN;
++    if (flags & 4) {
++        align = 1<<__ffs(size);
++        if (align < MALLOC_MIN_ALIGN)
++            align = MALLOC_MIN_ALIGN;
++    }
++    switch (flags & 3) {
++    default:
++    case 0:
++        return 0;
++    case 1:
++        return (u32)pmm_malloc(lowzone, handle, size, align);
++    case 2:
++        return (u32)pmm_malloc(highzone, handle, size, align);
++    case 3: {
++        void *data = pmm_malloc(lowzone, handle, size, align);
++        if (data)
++            return (u32)data;
++        return (u32)pmm_malloc(highzone, handle, size, align);
++    }
++    }
++}
++
++// PMM - find
++static u32
++handle_pmm01(u16 *args)
++{
++    u32 handle = *(u32*)&args[1];
++    dprintf(3, "pmm01: handle=%x\n", handle);
++    if (handle == PMM_DEFAULT_HANDLE)
++        return 0;
++    return (u32)pmm_find(handle);
++}
++
++// PMM - deallocate
++static u32
++handle_pmm02(u16 *args)
++{
++    u32 buffer = *(u32*)&args[1];
++    dprintf(3, "pmm02: buffer=%x\n", buffer);
++    int ret = pmm_free((void*)buffer);
++    if (ret)
++        // Error
++        return 1;
++    return 0;
++}
++
++static u32
++handle_pmmXX(u16 *args)
++{
++    return PMM_FUNCTION_NOT_SUPPORTED;
++}
++
++u32 VISIBLE16
++handle_pmm(u16 *args)
++{
++    if (! CONFIG_PMM)
++        return PMM_FUNCTION_NOT_SUPPORTED;
++
++    u16 arg1 = args[0];
++    dprintf(DEBUG_HDL_pmm, "pmm call arg1=%x\n", arg1);
++
++    switch (arg1) {
++    case 0x00: return handle_pmm00(args);
++    case 0x01: return handle_pmm01(args);
++    case 0x02: return handle_pmm02(args);
++    default:   return handle_pmmXX(args);
++    }
++}
++
++// romlayout.S
++extern void entry_pmm(void);
++
++void
++pmm_setup(void)
++{
++    if (! CONFIG_PMM)
++        return;
++
++    dprintf(3, "init PMM\n");
++
++    PMMHEADER.signature = PMM_SIGNATURE;
++    PMMHEADER.entry_offset = (u32)entry_pmm - BUILD_BIOS_ADDR;
++    PMMHEADER.checksum -= checksum(&PMMHEADER, sizeof(PMMHEADER));
++}
++
++void
++pmm_finalize(void)
++{
++    if (! CONFIG_PMM)
++        return;
++
++    dprintf(3, "finalize PMM\n");
++
++    PMMHEADER.signature = 0;
++    PMMHEADER.entry_offset = 0;
++}
+--- x/roms/seabios/src/pnpbios.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/pnpbios.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,103 @@
++// PNP BIOS calls
++//
++// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "util.h" // checksum
++#include "config.h" // BUILD_BIOS_ADDR
++#include "farptr.h" // SET_FARVAR
++
++struct pnpheader {
++    u32 signature;
++    u8 version;
++    u8 length;
++    u16 control;
++    u8 checksum;
++    u32 eventloc;
++    u16 real_ip;
++    u16 real_cs;
++    u16 prot_ip;
++    u32 prot_base;
++    u32 oemid;
++    u16 real_ds;
++    u32 prot_database;
++} PACKED;
++
++extern struct pnpheader PNPHEADER;
++extern char pnp_string[];
++
++#if CONFIG_PNPBIOS
++struct pnpheader PNPHEADER __aligned(16) VAR16EXPORT = {
++    .signature = PNP_SIGNATURE,
++    .version = 0x10,
++    .length = sizeof(PNPHEADER),
++    .real_cs = SEG_BIOS,
++    .prot_base = BUILD_BIOS_ADDR,
++    .real_ds = SEG_BIOS,
++    .prot_database = BUILD_BIOS_ADDR,
++};
++#else
++// We need a copy of this string in the 0xf000 segment, but we are not
++// actually a PnP BIOS, so make sure it is *not* aligned, so OSes will
++// not see it if they scan.
++char pnp_string[] __aligned(2) VAR16VISIBLE = " $PnP";
++#endif
++
++#define FUNCTION_NOT_SUPPORTED 0x82
++
++// BBS - Get Version and Installation Check
++static u16
++handle_pnp60(u16 *args)
++{
++    u16 version_ptr = args[1];
++    u16 version_seg = args[2];
++    SET_FARVAR(version_seg, *(u16*)(version_ptr+0), 0x0101);
++    return 0;
++}
++
++static u16
++handle_pnpXX(u16 *args)
++{
++    return FUNCTION_NOT_SUPPORTED;
++}
++
++u16 VISIBLE16
++handle_pnp(u16 *args)
++{
++    if (! CONFIG_PNPBIOS)
++        return FUNCTION_NOT_SUPPORTED;
++
++    u16 arg1 = args[0];
++    dprintf(DEBUG_HDL_pnp, "pnp call arg1=%x\n", arg1);
++
++    switch (arg1) {
++    case 0x60: return handle_pnp60(args);
++    default:   return handle_pnpXX(args);
++    }
++}
++
++u16
++get_pnp_offset(void)
++{
++    if (! CONFIG_PNPBIOS)
++        return (u32)pnp_string + 1 - BUILD_BIOS_ADDR;
++    return (u32)&PNPHEADER - BUILD_BIOS_ADDR;
++}
++
++// romlayout.S
++extern void entry_pnp_real(void);
++extern void entry_pnp_prot(void);
++
++void
++pnp_setup(void)
++{
++    if (! CONFIG_PNPBIOS)
++        return;
++
++    dprintf(3, "init PNPBIOS table\n");
++
++    PNPHEADER.real_ip = (u32)entry_pnp_real - BUILD_BIOS_ADDR;
++    PNPHEADER.prot_ip = (u32)entry_pnp_prot - BUILD_BIOS_ADDR;
++    PNPHEADER.checksum -= checksum(&PNPHEADER, sizeof(PNPHEADER));
++}
+--- x/roms/seabios/src/post.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/post.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,264 @@
++// 32bit code to Power On Self Test (POST) a machine.
++//
++// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2002  MandrakeSoft S.A.
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "ioport.h" // PORT_*
++#include "config.h" // CONFIG_*
++#include "cmos.h" // CMOS_*
++#include "util.h" // memset
++#include "biosvar.h" // struct bios_data_area_s
++#include "disk.h" // floppy_drive_setup
++#include "ata.h" // ata_setup
++#include "memmap.h" // add_e820
++#include "pic.h" // pic_setup
++#include "pci.h" // create_pirtable
++#include "acpi.h" // acpi_bios_init
++#include "bregs.h" // struct bregs
++#include "mptable.h" // mptable_init
++#include "boot.h" // IPL
++#include "usb.h" // usb_setup
++#include "smbios.h" // smbios_init
++#include "paravirt.h" // qemu_cfg_port_probe
++#include "ps2port.h" // ps2port_setup
++
++void
++__set_irq(int vector, void *loc)
++{
++    SET_IVT(vector, SEGOFF(SEG_BIOS, (u32)loc - BUILD_BIOS_ADDR));
++}
++
++#define set_irq(vector, func) do {              \
++        extern void func (void);                \
++        __set_irq(vector, func);                \
++    } while (0)
++
++static void
++init_ivt(void)
++{
++    dprintf(3, "init ivt\n");
++
++    // Initialize all vectors to the default handler.
++    int i;
++    for (i=0; i<256; i++)
++        set_irq(i, entry_iret_official);
++
++    // Initialize all hw vectors to a default hw handler.
++    for (i=0x08; i<=0x0f; i++)
++        set_irq(i, entry_hwpic1);
++    for (i=0x70; i<=0x77; i++)
++        set_irq(i, entry_hwpic2);
++
++    // Initialize software handlers.
++    set_irq(0x02, entry_02);
++    set_irq(0x10, entry_10);
++    set_irq(0x11, entry_11);
++    set_irq(0x12, entry_12);
++    set_irq(0x13, entry_13_official);
++    set_irq(0x14, entry_14);
++    set_irq(0x15, entry_15);
++    set_irq(0x16, entry_16);
++    set_irq(0x17, entry_17);
++    set_irq(0x18, entry_18);
++    set_irq(0x19, entry_19_official);
++    set_irq(0x1a, entry_1a);
++    set_irq(0x40, entry_40);
++
++    // INT 60h-66h reserved for user interrupt
++    for (i=0x60; i<=0x66; i++)
++        SET_IVT(i, SEGOFF(0, 0));
++
++    // set vector 0x79 to zero
++    // this is used by 'gardian angel' protection system
++    SET_IVT(0x79, SEGOFF(0, 0));
++
++    __set_irq(0x1E, &diskette_param_table2);
++}
++
++static void
++init_bda(void)
++{
++    dprintf(3, "init bda\n");
++
++    struct bios_data_area_s *bda = MAKE_FLATPTR(SEG_BDA, 0);
++    memset(bda, 0, sizeof(*bda));
++
++    int esize = EBDA_SIZE_START;
++    SET_BDA(mem_size_kb, BUILD_LOWRAM_END/1024 - esize);
++    u16 eseg = EBDA_SEGMENT_START;
++    SET_BDA(ebda_seg, eseg);
++
++    // Init ebda
++    struct extended_bios_data_area_s *ebda = get_ebda_ptr();
++    memset(ebda, 0, sizeof(*ebda));
++    ebda->size = esize;
++}
++
++static void
++ram_probe(void)
++{
++    dprintf(3, "Find memory size\n");
++    if (CONFIG_COREBOOT) {
++        coreboot_setup();
++    } else {
++        // On emulators, get memory size from nvram.
++        u32 rs = ((inb_cmos(CMOS_MEM_EXTMEM2_LOW) << 16)
++                  | (inb_cmos(CMOS_MEM_EXTMEM2_HIGH) << 24));
++        if (rs)
++            rs += 16 * 1024 * 1024;
++        else
++            rs = (((inb_cmos(CMOS_MEM_EXTMEM_LOW) << 10)
++                   | (inb_cmos(CMOS_MEM_EXTMEM_HIGH) << 18))
++                  + 1 * 1024 * 1024);
++        RamSize = rs;
++        add_e820(0, rs, E820_RAM);
++
++        // Check for memory over 4Gig
++        u64 high = ((inb_cmos(CMOS_MEM_HIGHMEM_LOW) << 16)
++                    | ((u32)inb_cmos(CMOS_MEM_HIGHMEM_MID) << 24)
++                    | ((u64)inb_cmos(CMOS_MEM_HIGHMEM_HIGH) << 32));
++        RamSizeOver4G = high;
++        add_e820(0x100000000ull, high, E820_RAM);
++
++        /* reserve 256KB BIOS area at the end of 4 GB */
++        add_e820(0xfffc0000, 256*1024, E820_RESERVED);
++    }
++
++    // Don't declare any memory between 0xa0000 and 0x100000
++    add_e820(BUILD_LOWRAM_END, BUILD_BIOS_ADDR-BUILD_LOWRAM_END, E820_HOLE);
++
++    // Mark known areas as reserved.
++    u16 ebda_seg = get_ebda_seg();
++    add_e820((u32)MAKE_FLATPTR(ebda_seg, 0), GET_EBDA2(ebda_seg, size) * 1024
++             , E820_RESERVED);
++    add_e820(BUILD_BIOS_ADDR, BUILD_BIOS_SIZE, E820_RESERVED);
++
++    if (kvm_para_available())
++        // 4 pages before the bios, 3 pages for vmx tss pages, the
++        // other page for EPT real mode pagetable
++        add_e820(0xfffbc000, 4*4096, E820_RESERVED);
++
++    dprintf(1, "Ram Size=0x%08x (0x%08x%08x high)\n"
++            , RamSize, (u32)(RamSizeOver4G >> 32), (u32)RamSizeOver4G);
++}
++
++static void
++init_bios_tables(void)
++{
++    if (CONFIG_COREBOOT) {
++        coreboot_copy_biostable();
++        return;
++    }
++
++    create_pirtable();
++
++    mptable_init();
++
++    smbios_init();
++
++    acpi_bios_init();
++}
++
++// Main setup code.
++static void
++post(void)
++{
++    // Detect and init ram.
++    init_ivt();
++    init_bda();
++    memmap_setup();
++    ram_probe();
++    malloc_setup();
++    thread_setup();
++
++    // Init base pc hardware.
++    pic_setup();
++    timer_setup();
++    mathcp_setup();
++
++    // Initialize smp
++    qemu_cfg_port_probe();
++    smp_probe_setup();
++    mtrr_setup();
++    smp_probe();
++
++    // Initialize pci
++    pci_setup();
++    smm_init();
++
++    // Setup interfaces that option roms may need
++    bios32_setup();
++    pmm_setup();
++    pnp_setup();
++    kbd_setup();
++    mouse_setup();
++    init_bios_tables();
++
++    // Run vga option rom (if running synchronously)
++    if (!CONFIG_THREADS || !CONFIG_THREAD_OPTIONROMS)
++        vga_setup();
++
++    // Initialize hardware devices
++    usb_setup();
++    ps2port_setup();
++    lpt_setup();
++    serial_setup();
++
++    boot_setup();
++    drive_setup();
++    cdemu_setup();
++    floppy_setup();
++    ata_setup();
++    ramdisk_setup();
++
++    // Run option roms
++    if (CONFIG_THREADS && CONFIG_THREAD_OPTIONROMS) {
++        // Run option roms while hw init still in progress.
++        vga_setup();
++        optionrom_setup();
++        wait_threads();
++    } else {
++        // Wait for hw init to finish and run non-vga option roms.
++        wait_threads();
++        optionrom_setup();
++    }
++
++    // Run BCVs and show optional boot menu
++    boot_prep();
++
++    // Finalize data structures before boot
++    pmm_finalize();
++    malloc_finalize();
++    memmap_finalize();
++}
++
++// 32-bit entry point.
++void VISIBLE32FLAT
++_start(void)
++{
++    init_dma();
++
++    debug_serial_setup();
++    dprintf(1, "Start bios (version %s)\n", VERSION);
++
++    // Allow writes to modify bios area (0xf0000)
++    make_bios_writable();
++
++    // Perform main setup code.
++    post();
++
++    // Setup bios checksum.
++    BiosChecksum -= checksum((u8*)BUILD_BIOS_ADDR, BUILD_BIOS_SIZE);
++
++    // Write protect bios memory.
++    make_bios_readonly();
++
++    // Invoke int 19 to start boot process.
++    dprintf(3, "Jump to int19\n");
++    struct bregs br;
++    memset(&br, 0, sizeof(br));
++    br.flags = F_IF;
++    call16_int(0x19, &br);
++}
+--- x/roms/seabios/src/ps2port.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/ps2port.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,427 @@
++// Support for handling the PS/2 mouse/keyboard ports.
++//
++// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
++// Several ideas taken from code Copyright (c) 1999-2004 Vojtech Pavlik
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "ioport.h" // inb
++#include "util.h" // dprintf
++#include "biosvar.h" // GET_EBDA
++#include "ps2port.h" // kbd_command
++#include "pic.h" // eoi_pic1
++
++
++/****************************************************************
++ * Low level i8042 commands.
++ ****************************************************************/
++
++// Timeout value.
++#define I8042_CTL_TIMEOUT       10000
++
++#define I8042_BUFFER_SIZE       16
++
++static int
++i8042_wait_read(void)
++{
++    dprintf(7, "i8042_wait_read\n");
++    int i;
++    for (i=0; i<I8042_CTL_TIMEOUT; i++) {
++        u8 status = inb(PORT_PS2_STATUS);
++        if (status & I8042_STR_OBF)
++            return 0;
++        udelay(50);
++    }
++    dprintf(1, "i8042 timeout on wait read\n");
++    return -1;
++}
++
++static int
++i8042_wait_write(void)
++{
++    dprintf(7, "i8042_wait_write\n");
++    int i;
++    for (i=0; i<I8042_CTL_TIMEOUT; i++) {
++        u8 status = inb(PORT_PS2_STATUS);
++        if (! (status & I8042_STR_IBF))
++            return 0;
++        udelay(50);
++    }
++    dprintf(1, "i8042 timeout on wait write\n");
++    return -1;
++}
++
++int
++i8042_flush(void)
++{
++    dprintf(7, "i8042_flush\n");
++    int i;
++    for (i=0; i<I8042_BUFFER_SIZE; i++) {
++        u8 status = inb(PORT_PS2_STATUS);
++        if (! (status & I8042_STR_OBF))
++            return 0;
++        udelay(50);
++        u8 data = inb(PORT_PS2_DATA);
++        dprintf(7, "i8042 flushed %x (status=%x)\n", data, status);
++    }
++
++    dprintf(1, "i8042 timeout on flush\n");
++    return -1;
++}
++
++static int
++__i8042_command(int command, u8 *param)
++{
++    int receive = (command >> 8) & 0xf;
++    int send = (command >> 12) & 0xf;
++
++    // Send the command.
++    int ret = i8042_wait_write();
++    if (ret)
++        return ret;
++    outb(command, PORT_PS2_STATUS);
++
++    // Send parameters (if any).
++    int i;
++    for (i = 0; i < send; i++) {
++        ret = i8042_wait_write();
++        if (ret)
++            return ret;
++        outb(param[i], PORT_PS2_DATA);
++    }
++
++    // Receive parameters (if any).
++    for (i = 0; i < receive; i++) {
++        ret = i8042_wait_read();
++        if (ret)
++            return ret;
++        param[i] = inb(PORT_PS2_DATA);
++        dprintf(7, "i8042 param=%x\n", param[i]);
++    }
++
++    return 0;
++}
++
++int
++i8042_command(int command, u8 *param)
++{
++    dprintf(7, "i8042_command cmd=%x\n", command);
++    int ret = __i8042_command(command, param);
++    if (ret)
++        dprintf(2, "i8042 command %x failed\n", command);
++    return ret;
++}
++
++static int
++i8042_kbd_write(u8 c)
++{
++    dprintf(7, "i8042_kbd_write c=%d\n", c);
++    int ret = i8042_wait_write();
++    if (! ret)
++        outb(c, PORT_PS2_DATA);
++    return ret;
++}
++
++static int
++i8042_aux_write(u8 c)
++{
++    return i8042_command(I8042_CMD_AUX_SEND, &c);
++}
++
++
++/****************************************************************
++ * Device commands.
++ ****************************************************************/
++
++#define PS2_RET_ACK             0xfa
++#define PS2_RET_NAK             0xfe
++
++static void
++process_ps2byte(u8 status, u8 data)
++{
++    if (!MODE16) {
++        // Don't pull in all of keyboard/mouse code into 32bit code -
++        // just discard the data.
++        dprintf(1, "Discarding ps2 data %x (status=%x)\n", data, status);
++        return;
++    }
++    if (status & I8042_STR_AUXDATA)
++        process_mouse(data);
++    else
++        process_key(data);
++}
++
++static int
++ps2_recvbyte(int aux, int needack, int timeout)
++{
++    u64 end = calc_future_tsc(timeout);
++    for (;;) {
++        u8 status = inb(PORT_PS2_STATUS);
++        if (status & I8042_STR_OBF) {
++            u8 data = inb(PORT_PS2_DATA);
++            dprintf(7, "ps2 read %x\n", data);
++
++            if (!!(status & I8042_STR_AUXDATA) == aux) {
++                if (!needack)
++                    return data;
++                if (data == PS2_RET_ACK)
++                    return data;
++                if (data == PS2_RET_NAK) {
++                    dprintf(1, "Got ps2 nak (status=%x)\n", status);
++                    return data;
++                }
++            }
++
++            // Data not part of this command.
++            process_ps2byte(status, data);
++        }
++
++        if (check_time(end)) {
++            dprintf(1, "ps2_recvbyte timeout\n");
++            return -1;
++        }
++        yield();
++    }
++}
++
++static int
++ps2_sendbyte(int aux, u8 command, int timeout)
++{
++    dprintf(7, "ps2_sendbyte aux=%d cmd=%x\n", aux, command);
++    int ret;
++    if (aux)
++        ret = i8042_aux_write(command);
++    else
++        ret = i8042_kbd_write(command);
++    if (ret)
++        return ret;
++
++    // Read ack.
++    ret = ps2_recvbyte(aux, 1, timeout);
++    if (ret < 0)
++        return ret;
++    if (ret != PS2_RET_ACK)
++        return -1;
++
++    return 0;
++}
++
++static int
++ps2_command(int aux, int command, u8 *param)
++{
++    int ret2;
++    int receive = (command >> 8) & 0xf;
++    int send = (command >> 12) & 0xf;
++
++    // Disable interrupts and keyboard/mouse.
++    u8 ps2ctr = GET_EBDA(ps2ctr);
++    u8 newctr = ps2ctr;
++    if (aux)
++        newctr |= I8042_CTR_KBDDIS;
++    else
++        newctr |= I8042_CTR_AUXDIS;
++    newctr &= ~(I8042_CTR_KBDINT|I8042_CTR_AUXINT);
++    dprintf(6, "i8042 ctr old=%x new=%x\n", ps2ctr, newctr);
++    int ret = i8042_command(I8042_CMD_CTL_WCTR, &newctr);
++    if (ret)
++        return ret;
++
++    if (command == ATKBD_CMD_RESET_BAT) {
++        // Reset is special wrt timeouts.
++
++        // Send command.
++        ret = ps2_sendbyte(aux, command, 1000);
++        if (ret)
++            goto fail;
++
++        // Receive parameters.
++        ret = ps2_recvbyte(aux, 0, 4000);
++        if (ret < 0)
++            goto fail;
++        param[0] = ret;
++        ret = ps2_recvbyte(aux, 0, 100);
++        if (ret < 0)
++            // Some devices only respond with one byte on reset.
++            ret = 0;
++        param[1] = ret;
++    } else {
++        // Send command.
++        ret = ps2_sendbyte(aux, command, 200);
++        if (ret)
++            goto fail;
++
++        // Send parameters (if any).
++        int i;
++        for (i = 0; i < send; i++) {
++            ret = ps2_sendbyte(aux, param[i], 200);
++            if (ret)
++                goto fail;
++        }
++
++        // Receive parameters (if any).
++        for (i = 0; i < receive; i++) {
++            ret = ps2_recvbyte(aux, 0, 500);
++            if (ret < 0)
++                goto fail;
++            param[i] = ret;
++        }
++    }
++
++    ret = 0;
++
++fail:
++    // Restore interrupts and keyboard/mouse.
++    ret2 = i8042_command(I8042_CMD_CTL_WCTR, &ps2ctr);
++    if (ret2)
++        return ret2;
++
++    return ret;
++}
++
++int
++kbd_command(int command, u8 *param)
++{
++    dprintf(7, "kbd_command cmd=%x\n", command);
++    int ret = ps2_command(0, command, param);
++    if (ret)
++        dprintf(2, "keyboard command %x failed\n", command);
++    return ret;
++}
++
++int
++aux_command(int command, u8 *param)
++{
++    dprintf(7, "aux_command cmd=%x\n", command);
++    int ret = ps2_command(1, command, param);
++    if (ret)
++        dprintf(2, "mouse command %x failed\n", command);
++    return ret;
++}
++
++
++/****************************************************************
++ * IRQ handlers
++ ****************************************************************/
++
++static void
++process_ps2irq(void)
++{
++    u8 status = inb(PORT_PS2_STATUS);
++    if (!(status & I8042_STR_OBF)) {
++        dprintf(1, "ps2 irq but no data.\n");
++        return;
++    }
++    u8 data = inb(PORT_PS2_DATA);
++
++    process_ps2byte(status, data);
++}
++
++// INT74h : PS/2 mouse hardware interrupt
++void VISIBLE16
++handle_74(void)
++{
++    if (! CONFIG_PS2PORT)
++        return;
++
++    debug_isr(DEBUG_ISR_74);
++    process_ps2irq();
++    eoi_pic2();
++}
++
++// INT09h : Keyboard Hardware Service Entry Point
++void VISIBLE16
++handle_09(void)
++{
++    if (! CONFIG_PS2PORT)
++        return;
++
++    debug_isr(DEBUG_ISR_09);
++    process_ps2irq();
++    eoi_pic1();
++}
++
++
++/****************************************************************
++ * Setup
++ ****************************************************************/
++
++static void
++keyboard_init(void *data)
++{
++    /* flush incoming keys */
++    int ret = i8042_flush();
++    if (ret)
++        return;
++
++    // Controller self-test.
++    u8 param[2];
++    ret = i8042_command(I8042_CMD_CTL_TEST, param);
++    if (ret)
++        return;
++    if (param[0] != 0x55) {
++        dprintf(1, "i8042 self test failed (got %x not 0x55)\n", param[0]);
++        return;
++    }
++
++    // Controller keyboard test.
++    ret = i8042_command(I8042_CMD_KBD_TEST, param);
++    if (ret)
++        return;
++    if (param[0] != 0x00) {
++        dprintf(1, "i8042 keyboard test failed (got %x not 0x00)\n", param[0]);
++        return;
++    }
++
++    // Enable keyboard and mouse ports.
++    ret = i8042_command(I8042_CMD_KBD_ENABLE, NULL);
++    if (ret)
++        return;
++    ret = i8042_command(I8042_CMD_AUX_ENABLE, NULL);
++    if (ret)
++        return;
++
++
++    /* ------------------- keyboard side ------------------------*/
++    /* reset keyboard and self test  (keyboard side) */
++    ret = kbd_command(ATKBD_CMD_RESET_BAT, param);
++    if (ret)
++        return;
++    if (param[0] != 0xaa) {
++        dprintf(1, "keyboard self test failed (got %x not 0xaa)\n", param[0]);
++        return;
++    }
++
++    /* Disable keyboard */
++    ret = kbd_command(ATKBD_CMD_RESET_DIS, NULL);
++    if (ret)
++        return;
++
++    // Set scancode command (mode 2)
++    param[0] = 0x02;
++    ret = kbd_command(ATKBD_CMD_SSCANSET, param);
++    if (ret)
++        return;
++
++    // Keyboard Mode: scan code convert, disable mouse, enable IRQ 1
++    SET_EBDA(ps2ctr, I8042_CTR_AUXDIS | I8042_CTR_XLATE | I8042_CTR_KBDINT);
++
++    /* Enable keyboard */
++    ret = kbd_command(ATKBD_CMD_ENABLE, NULL);
++    if (ret)
++        return;
++
++    dprintf(1, "keyboard initialized\n");
++}
++
++void
++ps2port_setup(void)
++{
++    if (! CONFIG_PS2PORT)
++        return;
++    dprintf(3, "init ps2port\n");
++
++    enable_hwirq(1, entry_09);
++    enable_hwirq(12, entry_74);
++
++    run_thread(keyboard_init, NULL);
++}
+--- x/roms/seabios/src/ps2port.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/ps2port.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,64 @@
++// Basic ps2 port (keyboard/mouse) command handling.
++#ifndef __PS2PORT_H
++#define __PS2PORT_H
++
++#include "types.h" // u8
++
++// Standard commands.
++#define I8042_CMD_CTL_RCTR      0x0120
++#define I8042_CMD_CTL_WCTR      0x1060
++#define I8042_CMD_CTL_TEST      0x01aa
++
++#define I8042_CMD_KBD_TEST      0x01ab
++#define I8042_CMD_KBD_DISABLE   0x00ad
++#define I8042_CMD_KBD_ENABLE    0x00ae
++
++#define I8042_CMD_AUX_DISABLE   0x00a7
++#define I8042_CMD_AUX_ENABLE    0x00a8
++#define I8042_CMD_AUX_SEND      0x10d4
++
++// Keyboard commands
++#define ATKBD_CMD_SETLEDS       0x10ed
++#define ATKBD_CMD_SSCANSET      0x10f0
++#define ATKBD_CMD_GETID         0x02f2
++#define ATKBD_CMD_ENABLE        0x00f4
++#define ATKBD_CMD_RESET_DIS     0x00f5
++#define ATKBD_CMD_RESET_BAT     0x02ff
++
++// Mouse commands
++#define PSMOUSE_CMD_SETSCALE11  0x00e6
++#define PSMOUSE_CMD_SETSCALE21  0x00e7
++#define PSMOUSE_CMD_SETRES      0x10e8
++#define PSMOUSE_CMD_GETINFO     0x03e9
++#define PSMOUSE_CMD_GETID       0x02f2
++#define PSMOUSE_CMD_SETRATE     0x10f3
++#define PSMOUSE_CMD_ENABLE      0x00f4
++#define PSMOUSE_CMD_DISABLE     0x00f5
++#define PSMOUSE_CMD_RESET_BAT   0x02ff
++
++// Status register bits.
++#define I8042_STR_PARITY        0x80
++#define I8042_STR_TIMEOUT       0x40
++#define I8042_STR_AUXDATA       0x20
++#define I8042_STR_KEYLOCK       0x10
++#define I8042_STR_CMDDAT        0x08
++#define I8042_STR_MUXERR        0x04
++#define I8042_STR_IBF           0x02
++#define I8042_STR_OBF           0x01
++
++// Control register bits.
++#define I8042_CTR_KBDINT        0x01
++#define I8042_CTR_AUXINT        0x02
++#define I8042_CTR_IGNKEYLOCK    0x08
++#define I8042_CTR_KBDDIS        0x10
++#define I8042_CTR_AUXDIS        0x20
++#define I8042_CTR_XLATE         0x40
++
++// functions
++int i8042_flush(void);
++int i8042_command(int command, u8 *param);
++int kbd_command(int command, u8 *param);
++int aux_command(int command, u8 *param);
++void ps2port_setup(void);
++
++#endif // ps2port.h
+--- x/roms/seabios/src/ramdisk.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/ramdisk.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,106 @@
++// Code for emulating a drive via high-memory accesses.
++//
++// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "disk.h" // process_ramdisk_op
++#include "util.h" // dprintf
++#include "memmap.h" // add_e820
++#include "biosvar.h" // GET_GLOBAL
++#include "bregs.h" // struct bregs
++
++void
++describe_ramdisk(struct drive_s *drive_g)
++{
++    printf("%s", drive_g->model);
++}
++
++void
++ramdisk_setup(void)
++{
++    if (!CONFIG_COREBOOT_FLASH || !CONFIG_FLASH_FLOPPY)
++        return;
++
++    // Find image.
++    struct cbfs_file *file = cbfs_findprefix("floppyimg/", NULL);
++    if (!file)
++        return;
++    u32 size = cbfs_datasize(file);
++    dprintf(3, "Found floppy file %s of size %d\n", cbfs_filename(file), size);
++    int ftype = find_floppy_type(size);
++    if (ftype < 0) {
++        dprintf(3, "No floppy type found for ramdisk size\n");
++        return;
++    }
++
++    // Allocate ram for image.
++    void *pos = memalign_tmphigh(PAGE_SIZE, size);
++    if (!pos) {
++        dprintf(3, "Not enough memory for ramdisk\n");
++        return;
++    }
++    add_e820((u32)pos, size, E820_RESERVED);
++
++    // Copy image into ram.
++    cbfs_copyfile(file, pos, size);
++
++    // Setup driver.
++    dprintf(1, "Mapping CBFS floppy %s to addr %p\n", cbfs_filename(file), pos);
++    struct drive_s *drive_g = addFloppy((u32)pos, ftype, DTYPE_RAMDISK);
++    if (drive_g)
++        strtcpy(drive_g->model, cbfs_filename(file), ARRAY_SIZE(drive_g->model));
++}
++
++static int
++ramdisk_copy(struct disk_op_s *op, int iswrite)
++{
++    u32 offset = GET_GLOBAL(op->drive_g->cntl_id);
++    offset += (u32)op->lba * DISK_SECTOR_SIZE;
++    u64 opd = GDT_DATA | GDT_LIMIT(0xfffff) | GDT_BASE((u32)op->buf_fl);
++    u64 ramd = GDT_DATA | GDT_LIMIT(0xfffff) | GDT_BASE(offset);
++
++    u64 gdt[6];
++    if (iswrite) {
++        gdt[2] = opd;
++        gdt[3] = ramd;
++    } else {
++        gdt[2] = ramd;
++        gdt[3] = opd;
++    }
++
++    // Call int 1587 to copy data.
++    struct bregs br;
++    memset(&br, 0, sizeof(br));
++    br.flags = F_CF|F_IF;
++    br.ah = 0x87;
++    br.es = GET_SEG(SS);
++    br.si = (u32)gdt;
++    br.cx = op->count * DISK_SECTOR_SIZE / 2;
++    call16_int(0x15, &br);
++
++    if (br.flags & F_CF)
++        return DISK_RET_EBADTRACK;
++    return DISK_RET_SUCCESS;
++}
++
++int
++process_ramdisk_op(struct disk_op_s *op)
++{
++    if (!CONFIG_COREBOOT_FLASH || !CONFIG_FLASH_FLOPPY)
++        return 0;
++
++    switch (op->command) {
++    case CMD_READ:
++        return ramdisk_copy(op, 0);
++    case CMD_WRITE:
++        return ramdisk_copy(op, 1);
++    case CMD_VERIFY:
++    case CMD_FORMAT:
++    case CMD_RESET:
++        return DISK_RET_SUCCESS;
++    default:
++        op->count = 0;
++        return DISK_RET_EPARAM;
++    }
++}
+--- x/roms/seabios/src/resume.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/resume.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,124 @@
++// Code for handling calls to "post" that are resume related.
++//
++// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "util.h" // dprintf
++#include "ioport.h" // outb
++#include "pic.h" // eoi_pic2
++#include "biosvar.h" // struct bios_data_area_s
++#include "bregs.h" // struct bregs
++#include "acpi.h" // find_resume_vector
++
++// Reset DMA controller
++void
++init_dma(void)
++{
++    // first reset the DMA controllers
++    outb(0, PORT_DMA1_MASTER_CLEAR);
++    outb(0, PORT_DMA2_MASTER_CLEAR);
++
++    // then initialize the DMA controllers
++    outb(0xc0, PORT_DMA2_MODE_REG);
++    outb(0x00, PORT_DMA2_MASK_REG);
++}
++
++// Handler for post calls that look like a resume.
++void VISIBLE16
++handle_resume(u8 status)
++{
++    init_dma();
++
++    debug_serial_setup();
++    dprintf(1, "In resume (status=%d)\n", status);
++
++    switch (status) {
++    case 0xfe:
++        if (CONFIG_S3_RESUME) {
++            // S3 resume request.  Jump to 32bit mode to handle the resume.
++            asm volatile(
++                "movw %w1, %%ss\n"
++                "movl %0, %%esp\n"
++                "pushl $s3_resume\n"
++                "jmp transition32\n"
++                : : "i"(BUILD_S3RESUME_STACK_ADDR), "r"(0)
++                );
++            break;
++        }
++        // NO BREAK
++    case 0x00:
++    case 0x0d ... 0xfd:
++    case 0xff:
++        // Normal post - now that status has been cleared a reset will
++        // run regular boot code..
++        reset_vector();
++        break;
++
++    case 0x05:
++        // flush keyboard (issue EOI) and jump via 40h:0067h
++        eoi_pic2();
++        // NO BREAK
++    case 0x0a:
++#define BDA_JUMP (((struct bios_data_area_s *)0)->jump)
++        // resume execution by jump via 40h:0067h
++        asm volatile(
++            "movw %w1, %%ds\n"
++            "ljmpw *%0\n"
++            : : "m"(BDA_JUMP), "r"(SEG_BDA)
++            );
++        break;
++
++    case 0x0b:
++        // resume execution via IRET via 40h:0067h
++        asm volatile(
++            "movw %w1, %%ds\n"
++            "lssw %0, %%sp\n"
++            "iretw\n"
++            : : "m"(BDA_JUMP), "r"(SEG_BDA)
++            );
++        break;
++
++    case 0x0c:
++        // resume execution via RETF via 40h:0067h
++        asm volatile(
++            "movw %w1, %%ds\n"
++            "lssw %0, %%sp\n"
++            "lretw\n"
++            : : "m"(BDA_JUMP), "r"(SEG_BDA)
++            );
++        break;
++    }
++
++    panic("Unimplemented shutdown status: %02x\n", status);
++}
++
++void VISIBLE32FLAT
++s3_resume(void)
++{
++    if (!CONFIG_S3_RESUME)
++        panic("S3 resume support not compiled in.\n");
++
++    dprintf(1, "In 32bit resume\n");
++
++    smm_init();
++
++    s3_resume_vga_init();
++
++    make_bios_readonly();
++
++    u32 s3_resume_vector = find_resume_vector();
++
++    // Invoke the resume vector.
++    struct bregs br;
++    memset(&br, 0, sizeof(br));
++    if (s3_resume_vector) {
++        dprintf(1, "Jump to resume vector (%x)\n", s3_resume_vector);
++        br.code = FLATPTR_TO_SEGOFF((void*)s3_resume_vector);
++    } else {
++        dprintf(1, "No resume vector set!\n");
++        // Jump to the post vector to restart with a normal boot.
++        br.code = SEGOFF(SEG_BIOS, (u32)reset_vector - BUILD_BIOS_ADDR);
++    }
++    call16big(&br);
++}
+--- x/roms/seabios/src/rombios.lds.S	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/rombios.lds.S	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,30 @@
++// Linker definitions for merging 16 and 32 bit code
++//
++// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "config.h" // BUILD_BIOS_ADDR
++
++OUTPUT_FORMAT("elf32-i386")
++OUTPUT_ARCH("i386")
++ENTRY(post32)
++SECTIONS
++{
++        .text code32flat_start : {
++                *(.text32flat)
++
++                . = code32seg_start + BUILD_BIOS_ADDR - code32flat_start ;
++                *(.text32seg)
++
++                . = data16_start + BUILD_BIOS_ADDR - code32flat_start ;
++                *(.data16)
++                . = text16_start + BUILD_BIOS_ADDR - code32flat_start ;
++                *(.text16)
++                final_text16_end = . ;
++                }
++        /DISCARD/ : {
++                *(.text*) *(.data*) *(.bss*) *(.rodata*)
++                *(COMMON) *(.discard*) *(.eh_frame)
++                }
++}
+--- x/roms/seabios/src/rombios16.lds.S	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/rombios16.lds.S	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,18 @@
++// Linker definitions for 16bit code
++//
++// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
++OUTPUT_ARCH("i386")
++SECTIONS
++{
++        .data16 data16_start : {
++                *(.data16)
++                }
++        .text16 text16_start : {
++                *(.text16)
++                }
++        /DISCARD/ : { *(.discard*) }
++}
+--- x/roms/seabios/src/rombios32seg.lds.S	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/rombios32seg.lds.S	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,15 @@
++// Linker definitions for 32bit segmented code
++//
++// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
++OUTPUT_ARCH("i386")
++SECTIONS
++{
++        .text32seg code32seg_start : {
++                *(.text32seg)
++        }
++        /DISCARD/ : { *(.discard*) }
++}
+--- x/roms/seabios/src/romlayout.S	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/romlayout.S	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,582 @@
++// Rom layout and bios assembler to C interface.
++//
++// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2002  MandrakeSoft S.A.
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++
++/****************************************************************
++ * Include of 16bit C code
++ ****************************************************************/
++
++        .code16gcc
++.include "out/ccode.16.s"
++
++#include "config.h" // CONFIG_*
++#include "ioport.h" // PORT_A20
++#include "bregs.h" // CR0_*
++#include "cmos.h" // CMOS_RESET_CODE
++#include "../out/asm-offsets.h" // BREGS_*
++#include "entryfuncs.S" // ENTRY_*
++
++
++/****************************************************************
++ * Call trampolines
++ ****************************************************************/
++
++// Place CPU into 32bit mode from 16bit mode.
++// Clobbers: ecx, flags, segment registers, cr0, idt/gdt
++        DECLFUNC transition32
++transition32:
++        movl %eax, %ecx
++
++        // Disable irqs (and clear direction flag)
++        cli
++        cld
++
++        // Disable nmi
++        movl $CMOS_RESET_CODE|NMI_DISABLE_BIT, %eax
++        outb %al, $PORT_CMOS_INDEX
++        inb $PORT_CMOS_DATA, %al
++
++        // enable a20
++        inb $PORT_A20, %al
++        orb $A20_ENABLE_BIT, %al
++        outb %al, $PORT_A20
++
++        // Set segment descriptors
++        lidtw %cs:pmode_IDT_info
++        lgdtw %cs:rombios32_gdt_48
++
++        // Enable protected mode
++        movl %cr0, %eax
++        orl $CR0_PE, %eax
++        movl %eax, %cr0
++
++        // start 32bit protected mode code
++        ljmpl $SEG32_MODE32_CS, $(BUILD_BIOS_ADDR + 1f)
++
++        .code32
++1:
++        // init data segments
++        movl $SEG32_MODE32_DS, %eax
++        movw %ax, %ds
++        movw %ax, %es
++        movw %ax, %ss
++        movw %ax, %fs
++        movw %ax, %gs
++
++        movl %ecx, %eax
++        retl
++
++// Place CPU into 16bit mode from 32bit mode.
++// Clobbers: ecx, flags, segment registers, cr0, idt/gdt
++        DECLFUNC transition16
++        .global transition16big
++transition16:
++        movl %eax, %ecx
++
++        // restore data segment limits to 0xffff
++        movl $SEG32_MODE16_DS, %eax
++        movw %ax, %ds
++        movw %ax, %es
++        movw %ax, %ss
++        movw %ax, %fs
++        movw %ax, %gs
++
++#if CONFIG_DISABLE_A20
++        // disable a20
++        inb $PORT_A20, %al
++        andb $~A20_ENABLE_BIT, %al
++        outb %al, $PORT_A20
++#endif
++
++        // Jump to 16bit mode
++        ljmpw $SEG32_MODE16_CS, $1f
++
++transition16big:
++        movl %eax, %ecx
++
++        movl $SEG32_MODE16BIG_DS, %eax
++        movw %ax, %ds
++        movw %ax, %es
++        movw %ax, %ss
++        movw %ax, %fs
++        movw %ax, %gs
++
++        ljmpl $SEG32_MODE16BIG_CS, $(BUILD_BIOS_ADDR + 1f)
++
++        .code16gcc
++1:
++        // Disable protected mode
++        movl %cr0, %eax
++        andl $~CR0_PE, %eax
++        movl %eax, %cr0
++
++        // far jump to flush CPU queue after transition to real mode
++        ljmpw $SEG_BIOS, $2f
++
++2:
++        // restore IDT to normal real-mode defaults
++        lidtw %cs:rmode_IDT_info
++
++        // Clear segment registers
++        xorw %ax, %ax
++        movw %ax, %fs
++        movw %ax, %gs
++        movw %ax, %es
++        movw %ax, %ds
++        movw %ax, %ss  // Assume stack is in segment 0
++
++        movl %ecx, %eax
++        retl
++
++// Call a 16bit function from 16bit mode with a specified cpu register state
++// %eax = address of struct bregs
++// Clobbers: %e[bcd]x, %e[ds]i, flags
++        DECLFUNC __call16
++__call16:
++        // Save %eax, %ebp
++        pushl %ebp
++        pushl %eax
++
++        // Setup for iretw call
++        pushw %cs
++        pushw $1f               // return point
++        pushw BREGS_flags(%eax) // flags
++        pushl BREGS_code(%eax)  // CS:IP
++
++        // Load calling registers.
++        movl BREGS_edi(%eax), %edi
++        movl BREGS_esi(%eax), %esi
++        movl BREGS_ebp(%eax), %ebp
++        movl BREGS_ebx(%eax), %ebx
++        movl BREGS_edx(%eax), %edx
++        movl BREGS_ecx(%eax), %ecx
++        movw BREGS_es(%eax), %es
++        movw BREGS_ds(%eax), %ds
++        movl %ss:BREGS_eax(%eax), %eax
++
++        // Invoke call
++        iretw                   // XXX - just do a lcalll
++1:
++        // Store flags, eax, ecx
++        pushfw
++        pushl %eax
++        movl 0x06(%esp), %eax
++        movl %ecx, %ss:BREGS_ecx(%eax)
++        movw %ds, %ss:BREGS_ds(%eax)
++        movw %ss, %cx
++        movw %cx, %ds           // Restore %ds == %ss
++        popl %ecx
++        movl %ecx, BREGS_eax(%eax)
++        popw %cx
++        movw %cx, BREGS_flags(%eax)
++
++        // Store remaining registers
++        movw %es, BREGS_es(%eax)
++        movl %edi, BREGS_edi(%eax)
++        movl %esi, BREGS_esi(%eax)
++        movl %ebp, BREGS_ebp(%eax)
++        movl %ebx, BREGS_ebx(%eax)
++        movl %edx, BREGS_edx(%eax)
++
++        // Remove %eax, restore %ebp
++        popl %eax
++        popl %ebp
++
++        retl
++
++// Call a 16bit function from 32bit mode.
++// %eax = address of struct bregs
++// Clobbers: %e[bcd]x, %e[ds]i, flags, segment registers, idt/gdt
++        DECLFUNC __call16_from32
++        .global __call16big_from32
++        .code32
++__call16_from32:
++        pushl $1f
++        jmp transition16
++__call16big_from32:
++        pushl $1f
++        jmp transition16big
++
++        // Make call.
++        .code16gcc
++1:      calll __call16
++        // Return via transition32
++        jmp transition32
++
++// IRQ trampolines
++        .macro IRQ_TRAMPOLINE num
++        DECLFUNC irq_trampoline_0x\num
++        irq_trampoline_0x\num :
++        int $0x\num
++        lretw
++        .endm
++
++        IRQ_TRAMPOLINE 10
++        IRQ_TRAMPOLINE 13
++        IRQ_TRAMPOLINE 15
++        IRQ_TRAMPOLINE 16
++        IRQ_TRAMPOLINE 18
++        IRQ_TRAMPOLINE 19
++
++
++/****************************************************************
++ * POST entry point
++ ****************************************************************/
++
++        DECLFUNC entry_post
++entry_post:
++        // Enable cache
++        movl %cr0, %eax
++        andl $~(CR0_CD|CR0_NW), %eax
++        movl %eax, %cr0
++
++        // Disable interrupts
++        cli
++        cld
++
++        // Check for restart indicator.
++        movl $CMOS_RESET_CODE|NMI_DISABLE_BIT, %eax
++        outb %al, $PORT_CMOS_INDEX
++        inb $PORT_CMOS_DATA, %al
++        cmpb $0x0, %al
++        jnz 1f
++
++        // Normal entry point
++        ENTRY_INTO32 _start
++
++        // Entry point when a post call looks like a resume.
++1:
++        // Save old shutdown status.
++        movl %eax, %ebx
++
++        // Clear shutdown status register.
++        movl $CMOS_RESET_CODE|NMI_DISABLE_BIT, %eax
++        outb %al, $PORT_CMOS_INDEX
++        xorl %eax, %eax
++        outb %al, $PORT_CMOS_DATA
++
++        // Use a stack in EBDA
++        movw $SEG_BDA, %ax
++        movw %ax, %ds
++        movw BDA_ebda_seg, %ax
++
++        cmpw $EBDA_SEGMENT_START, %ax
++        jle 2f
++        // EBDA segment doesn't look valid - use startup value.
++        movw $EBDA_SEGMENT_START, %ax
++
++2:      movw %ax, %ds
++        movw %ax, %ss
++        movl $EBDA_OFFSET_TOP_STACK, %esp
++
++        // Call handler.
++        movl %ebx, %eax
++        jmp handle_resume
++
++
++/****************************************************************
++ * Misc. entry points.
++ ****************************************************************/
++
++// PMM entry point
++        DECLFUNC entry_pmm
++entry_pmm:
++        pushl %esp              // Backup %esp, then clear high bits
++        movzwl %sp, %esp
++        pushfl                  // Save registers clobbered by C code
++        cli
++        cld
++        pushl %eax
++        pushl %ecx
++        pushl %edx
++        pushw %es
++        pushw %ds
++        movw %ss, %cx           // Move %ss to %ds
++        movw %cx, %ds
++        leal 28(%esp), %eax     // %eax points to start of args
++        calll handle_pmm
++        movw %ax, 12(%esp)      // Modify %ax:%dx to return %eax
++        shrl $16, %eax
++        movw %ax, 4(%esp)
++        popw %ds                // Restore saved registers
++        popw %es
++        popl %edx
++        popl %ecx
++        popl %eax
++        popfl
++        popl %esp
++        lretw
++
++// PnP entry points
++        DECLFUNC entry_pnp_real
++        .global entry_pnp_prot
++entry_pnp_prot:
++        pushl %esp
++        jmp 1f
++entry_pnp_real:
++        pushl %esp              // Backup %esp, then clear high bits
++        movzwl %sp, %esp
++1:
++        pushfl                  // Save registers clobbered by C code
++        cli
++        cld
++        pushl %eax
++        pushl %ecx
++        pushl %edx
++        pushw %es
++        pushw %ds
++        movw %ss, %cx           // Move %ss to %ds
++        movw %cx, %ds
++        leal 28(%esp), %eax     // %eax points to start of u16 args
++        calll handle_pnp
++        movw %ax, 12(%esp)      // Modify %eax to return %ax
++        popw %ds
++        popw %es
++        popl %edx
++        popl %ecx
++        popl %eax
++        popfl
++        popl %esp
++        lretw
++
++// APM entry points
++        DECLFUNC apm16protected_entry
++apm16protected_entry:
++        pushfw          // save flags
++        pushl %eax      // dummy
++        ENTRY_ARG handle_apm16
++        addw $4, %sp    // pop dummy
++        popfw           // restore flags
++        lretw
++
++        .code32
++        DECLFUNC apm32protected_entry
++apm32protected_entry:
++        pushfl
++        pushl %gs
++        pushl %cs               // Move second descriptor after %cs to %gs
++        addl $16, (%esp)
++        popl %gs
++        ENTRY_ARG_ESP handle_apm32
++        popl %gs
++        popfl
++        lretl
++
++// PCI-BIOS 32bit entry point
++        DECLFUNC pcibios32_entry
++pcibios32_entry:
++        pushfl
++        pushl %gs               // Backup %gs and set %gs=%ds
++        pushl %ds
++        popl %gs
++        ENTRY_ARG_ESP handle_pcibios32
++        popl %gs
++        popfl
++        lretl
++
++// BIOS32 support
++        EXPORTFUNC bios32_entry
++bios32_entry:
++        pushfl
++#if CONFIG_PCIBIOS
++        // Check for PCI-BIOS request
++        cmpl $0x49435024, %eax // $PCI
++        jne 1f
++        movl $BUILD_BIOS_ADDR, %ebx
++        movl $BUILD_BIOS_SIZE, %ecx
++        movl $pcibios32_entry, %edx
++        xorb %al, %al
++        jmp 2f
++#endif
++        // Unknown request
++1:      movb $0x80, %al
++        // Return to caller
++2:      popfl
++        lretl
++
++// 32bit elf entry point
++        EXPORTFUNC post32
++post32:
++        cli
++        cld
++        lidtl (BUILD_BIOS_ADDR + pmode_IDT_info)
++        lgdtl (BUILD_BIOS_ADDR + rombios32_gdt_48)
++        movl $SEG32_MODE32_DS, %eax
++        movw %ax, %ds
++        movw %ax, %es
++        movw %ax, %fs
++        movw %ax, %gs
++        movw %ax, %ss
++        movl $BUILD_STACK_ADDR, %esp
++        ljmpl $SEG32_MODE32_CS, $_start
++
++        .code16gcc
++
++
++/****************************************************************
++ * Interrupt entry points
++ ****************************************************************/
++
++        // Define an entry point for an interrupt (no args passed).
++        .macro IRQ_ENTRY num
++        .global entry_\num
++        entry_\num :
++        pushl $ handle_\num
++        jmp irqentry
++        .endm
++
++        // Define an entry point for an interrupt (can read/modify args).
++        .macro IRQ_ENTRY_ARG num
++        .global entry_\num
++        entry_\num :
++        pushl $ handle_\num
++        jmp irqentryarg
++        .endm
++
++        // Macros that put each handler into its own section
++        .macro DECL_IRQ_ENTRY num
++        DECLFUNC entry_\num
++        IRQ_ENTRY \num
++        .endm
++        .macro DECL_IRQ_ENTRY_ARG num
++        DECLFUNC entry_\num
++        IRQ_ENTRY_ARG \num
++        .endm
++
++        // Main entry point for interrupts without args
++        DECLFUNC irqentry
++irqentry:
++        ENTRY_ST
++        iretw
++
++        // Main entry point for interrupts with args
++        DECLFUNC irqentryarg
++irqentryarg:
++        ENTRY_ARG_ST
++        iretw
++
++        DECL_IRQ_ENTRY_ARG 13
++        DECL_IRQ_ENTRY 76
++        DECL_IRQ_ENTRY 70
++        DECL_IRQ_ENTRY 74
++        DECL_IRQ_ENTRY 75
++        DECL_IRQ_ENTRY hwpic1
++        DECL_IRQ_ENTRY hwpic2
++
++        // int 18/19 are special - they reset stack and call into 32bit mode.
++        DECLFUNC entry_19
++entry_19:
++        ENTRY_INTO32 handle_19
++
++        DECLFUNC entry_18
++entry_18:
++        ENTRY_INTO32 handle_18
++
++
++/****************************************************************
++ * Fixed position entry points
++ ****************************************************************/
++
++        // Specify a location in the fixed part of bios area.
++        .macro ORG addr
++        .section .fixedaddr.\addr
++        .endm
++
++        ORG 0xe05b
++entry_post_official:
++        jmp entry_post
++
++        ORG 0xe2c3
++        IRQ_ENTRY 02
++
++        ORG 0xe3fe
++        .global entry_13_official
++entry_13_official:
++        jmp entry_13
++
++        // 0xe401 - OldFDPT in disk.c
++
++        ORG 0xe6f2
++        .global entry_19_official
++entry_19_official:
++        jmp entry_19
++
++        // 0xe6f5 - BIOS_CONFIG_TABLE in misc.c
++
++        // 0xe729 - BaudTable in serial.c
++
++        ORG 0xe739
++        IRQ_ENTRY_ARG 14
++
++        ORG 0xe82e
++        IRQ_ENTRY_ARG 16
++
++        ORG 0xe987
++        IRQ_ENTRY 09
++
++        ORG 0xec59
++        IRQ_ENTRY_ARG 40
++
++        ORG 0xef57
++        IRQ_ENTRY 0e
++
++        // 0xefc7 - diskette_param_table in floppy.c
++
++        ORG 0xefd2
++        IRQ_ENTRY_ARG 17
++
++        ORG 0xf045
++entry_10_0x0f:
++        // XXX - INT 10 Functions 0-Fh Entry Point
++        iretw
++
++        ORG 0xf065
++        IRQ_ENTRY_ARG 10
++
++        // 0xf0a4 - VideoParams in misc.c
++
++        ORG 0xf841
++        IRQ_ENTRY_ARG 12
++
++        ORG 0xf84d
++        IRQ_ENTRY_ARG 11
++
++        ORG 0xf859
++        IRQ_ENTRY_ARG 15
++
++        // 0xfa6e - vgafont8 in font.c
++
++        ORG 0xfe6e
++        IRQ_ENTRY_ARG 1a
++
++        ORG 0xfea5
++        IRQ_ENTRY 08
++
++        // 0xfef3 - InitVectors in misc.c
++
++        // 0xff00 - BiosCopyright in misc.c
++
++        ORG 0xff53
++        .global entry_iret_official
++entry_iret_official:
++        iretw
++
++        ORG 0xff54
++        IRQ_ENTRY_ARG 05
++
++        ORG 0xfff0 // Power-up Entry Point
++        .global reset_vector
++reset_vector:
++        ljmpw $SEG_BIOS, $entry_post_official
++
++        // 0xfff5 - BiosDate in misc.c
++
++        // 0xfffe - BiosModelId in misc.c
++
++        // 0xffff - BiosChecksum in misc.c
++
++        .end
+--- x/roms/seabios/src/serial.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/serial.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,340 @@
++// 16bit code to handle serial and printer services.
++//
++// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2002  MandrakeSoft S.A.
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "biosvar.h" // SET_BDA
++#include "util.h" // debug_enter
++#include "bregs.h" // struct bregs
++
++// Timers based on 18.2Hz clock irq.
++struct tick_timer_s {
++    u16 last_tick, remaining;
++};
++
++struct tick_timer_s
++initTickTimer(u16 count)
++{
++    struct tick_timer_s tt = {GET_BDA(timer_counter), count};
++    return tt;
++}
++
++int
++checkTickTimer(struct tick_timer_s *tt)
++{
++    u16 timer = GET_BDA(timer_counter);
++    if (tt->last_tick != timer) {
++        tt->last_tick = timer;
++        tt->last_tick--;
++        if (!tt->last_tick)
++            return 1;
++    }
++    return 0;
++}
++
++
++/****************************************************************
++ * COM ports
++ ****************************************************************/
++
++static u16
++detect_serial(u16 port, u8 timeout, u8 count)
++{
++    outb(0x02, port+SEROFF_IER);
++    u8 ier = inb(port+SEROFF_IER);
++    if (ier != 0x02)
++        return 0;
++    u8 iir = inb(port+SEROFF_IIR);
++    if ((iir & 0x3f) != 0x02)
++        return 0;
++
++    outb(0x00, port+SEROFF_IER);
++    SET_BDA(port_com[count], port);
++    SET_BDA(com_timeout[count], timeout);
++    return 1;
++}
++
++void
++serial_setup(void)
++{
++    if (! CONFIG_SERIAL)
++        return;
++    dprintf(3, "init serial\n");
++
++    u16 count = 0;
++    count += detect_serial(PORT_SERIAL1, 0x0a, count);
++    count += detect_serial(PORT_SERIAL2, 0x0a, count);
++    count += detect_serial(PORT_SERIAL3, 0x0a, count);
++    count += detect_serial(PORT_SERIAL4, 0x0a, count);
++    dprintf(1, "Found %d serial ports\n", count);
++
++    // Equipment word bits 9..11 determing # serial ports
++    u16 eqb = GET_BDA(equipment_list_flags);
++    SET_BDA(equipment_list_flags, (eqb & 0xf1ff) | (count << 9));
++}
++
++static u16
++getComAddr(struct bregs *regs)
++{
++    if (regs->dx >= 4) {
++        set_invalid(regs);
++        return 0;
++    }
++    u16 addr = GET_BDA(port_com[regs->dx]);
++    if (! addr)
++        set_invalid(regs);
++    return addr;
++}
++
++// SERIAL - INITIALIZE PORT
++static void
++handle_1400(struct bregs *regs)
++{
++    u16 addr = getComAddr(regs);
++    if (!addr)
++        return;
++    outb(inb(addr+SEROFF_LCR) | 0x80, addr+SEROFF_LCR);
++    if ((regs->al & 0xE0) == 0) {
++        outb(0x17, addr+SEROFF_DLL);
++        outb(0x04, addr+SEROFF_DLH);
++    } else {
++        u16 val16 = 0x600 >> ((regs->al & 0xE0) >> 5);
++        outb(val16 & 0xFF, addr+SEROFF_DLL);
++        outb(val16 >> 8, addr+SEROFF_DLH);
++    }
++    outb(regs->al & 0x1F, addr+SEROFF_LCR);
++    regs->ah = inb(addr+SEROFF_LSR);
++    regs->al = inb(addr+SEROFF_MSR);
++    set_success(regs);
++}
++
++// SERIAL - WRITE CHARACTER TO PORT
++static void
++handle_1401(struct bregs *regs)
++{
++    u16 addr = getComAddr(regs);
++    if (!addr)
++        return;
++    struct tick_timer_s tt = initTickTimer(GET_BDA(com_timeout[regs->dx]));
++    for (;;) {
++        u8 lsr = inb(addr+SEROFF_LSR);
++        if ((lsr & 0x60) == 0x60) {
++            // Success - can write data
++            outb(regs->al, addr+SEROFF_DATA);
++            // XXX - reread lsr?
++            regs->ah = lsr;
++            break;
++        }
++        if (checkTickTimer(&tt)) {
++            // Timed out - can't write data.
++            regs->ah = lsr | 0x80;
++            break;
++        }
++        yield();
++    }
++    set_success(regs);
++}
++
++// SERIAL - READ CHARACTER FROM PORT
++static void
++handle_1402(struct bregs *regs)
++{
++    u16 addr = getComAddr(regs);
++    if (!addr)
++        return;
++    struct tick_timer_s tt = initTickTimer(GET_BDA(com_timeout[regs->dx]));
++    for (;;) {
++        u8 lsr = inb(addr+SEROFF_LSR);
++        if (lsr & 0x01) {
++            // Success - can read data
++            regs->al = inb(addr+SEROFF_DATA);
++            regs->ah = lsr;
++            break;
++        }
++        if (checkTickTimer(&tt)) {
++            // Timed out - can't read data.
++            regs->ah = lsr | 0x80;
++            break;
++        }
++        yield();
++    }
++    set_success(regs);
++}
++
++// SERIAL - GET PORT STATUS
++static void
++handle_1403(struct bregs *regs)
++{
++    u16 addr = getComAddr(regs);
++    if (!addr)
++        return;
++    regs->ah = inb(addr+SEROFF_LSR);
++    regs->al = inb(addr+SEROFF_MSR);
++    set_success(regs);
++}
++
++static void
++handle_14XX(struct bregs *regs)
++{
++    set_unimplemented(regs);
++}
++
++// INT 14h Serial Communications Service Entry Point
++void VISIBLE16
++handle_14(struct bregs *regs)
++{
++    debug_enter(regs, DEBUG_HDL_14);
++    if (! CONFIG_SERIAL) {
++        handle_14XX(regs);
++        return;
++    }
++
++    switch (regs->ah) {
++    case 0x00: handle_1400(regs); break;
++    case 0x01: handle_1401(regs); break;
++    case 0x02: handle_1402(regs); break;
++    case 0x03: handle_1403(regs); break;
++    default:   handle_14XX(regs); break;
++    }
++}
++
++// XXX - Baud Rate Generator Table
++u8 BaudTable[16] VAR16FIXED(0xe729);
++
++
++/****************************************************************
++ * LPT ports
++ ****************************************************************/
++
++static u16
++detect_parport(u16 port, u8 timeout, u8 count)
++{
++    // clear input mode
++    outb(inb(port+2) & 0xdf, port+2);
++
++    outb(0xaa, port);
++    if (inb(port) != 0xaa)
++        // Not present
++        return 0;
++    SET_BDA(port_lpt[count], port);
++    SET_BDA(lpt_timeout[count], timeout);
++    return 1;
++}
++
++void
++lpt_setup(void)
++{
++    if (! CONFIG_LPT)
++        return;
++    dprintf(3, "init lpt\n");
++
++    u16 count = 0;
++    count += detect_parport(PORT_LPT1, 0x14, count);
++    count += detect_parport(PORT_LPT2, 0x14, count);
++    dprintf(1, "Found %d lpt ports\n", count);
++
++    // Equipment word bits 14..15 determing # parallel ports
++    u16 eqb = GET_BDA(equipment_list_flags);
++    SET_BDA(equipment_list_flags, (eqb & 0x3fff) | (count << 14));
++}
++
++static u16
++getLptAddr(struct bregs *regs)
++{
++    if (regs->dx >= 3) {
++        set_invalid(regs);
++        return 0;
++    }
++    u16 addr = GET_BDA(port_lpt[regs->dx]);
++    if (! addr)
++        set_invalid(regs);
++    return addr;
++}
++
++// INT 17 - PRINTER - WRITE CHARACTER
++static void
++handle_1700(struct bregs *regs)
++{
++    u16 addr = getLptAddr(regs);
++    if (!addr)
++        return;
++
++    struct tick_timer_s tt = initTickTimer(GET_BDA(lpt_timeout[regs->dx]));
++
++    outb(regs->al, addr);
++    u8 val8 = inb(addr+2);
++    outb(val8 | 0x01, addr+2); // send strobe
++    udelay(5);
++    outb(val8 & ~0x01, addr+2);
++
++    for (;;) {
++        u8 v = inb(addr+1);
++        if (!(v & 0x40)) {
++            // Success
++            regs->ah = v ^ 0x48;
++            break;
++        }
++        if (checkTickTimer(&tt)) {
++            // Timeout
++            regs->ah = (v ^ 0x48) | 0x01;
++            break;
++        }
++        yield();
++    }
++
++    set_success(regs);
++}
++
++// INT 17 - PRINTER - INITIALIZE PORT
++static void
++handle_1701(struct bregs *regs)
++{
++    u16 addr = getLptAddr(regs);
++    if (!addr)
++        return;
++
++    u8 val8 = inb(addr+2);
++    outb(val8 & ~0x04, addr+2); // send init
++    udelay(5);
++    outb(val8 | 0x04, addr+2);
++
++    regs->ah = inb(addr+1) ^ 0x48;
++    set_success(regs);
++}
++
++// INT 17 - PRINTER - GET STATUS
++static void
++handle_1702(struct bregs *regs)
++{
++    u16 addr = getLptAddr(regs);
++    if (!addr)
++        return;
++    regs->ah = inb(addr+1) ^ 0x48;
++    set_success(regs);
++}
++
++static void
++handle_17XX(struct bregs *regs)
++{
++    set_unimplemented(regs);
++}
++
++// INT17h : Printer Service Entry Point
++void VISIBLE16
++handle_17(struct bregs *regs)
++{
++    debug_enter(regs, DEBUG_HDL_17);
++    if (! CONFIG_LPT) {
++        handle_17XX(regs);
++        return;
++    }
++
++    switch (regs->ah) {
++    case 0x00: handle_1700(regs); break;
++    case 0x01: handle_1701(regs); break;
++    case 0x02: handle_1702(regs); break;
++    default:   handle_17XX(regs); break;
++    }
++}
+--- x/roms/seabios/src/shadow.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/shadow.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,121 @@
++// Support for enabling/disabling BIOS ram shadowing.
++//
++// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2006 Fabrice Bellard
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "util.h" // memcpy
++#include "pci.h" // pci_config_writeb
++#include "config.h" // CONFIG_*
++#include "pci_ids.h" // PCI_VENDOR_ID_INTEL
++
++// Test if 'addr' is in the range from 'start'..'start+size'
++#define IN_RANGE(addr, start, size) ({   \
++            u32 __addr = (addr);         \
++            u32 __start = (start);       \
++            u32 __size = (size);         \
++            (__addr - __start < __size); \
++        })
++
++// On the emulators, the bios at 0xf0000 is also at 0xffff0000
++#define BIOS_SRC_ADDR 0xffff0000
++
++// Enable shadowing and copy bios.
++static void
++__make_bios_writable(u16 bdf)
++{
++    // Make ram from 0xc0000-0xf0000 writable
++    int clear = 0;
++    int i;
++    for (i=0; i<6; i++) {
++        int reg = pci_config_readb(bdf, 0x5a + i);
++        if ((reg & 0x11) != 0x11) {
++            // Need to copy optionroms to work around qemu implementation
++            void *mem = (void*)(BUILD_ROM_START + i * 32*1024);
++            memcpy((void*)BUILD_BIOS_TMP_ADDR, mem, 32*1024);
++            pci_config_writeb(bdf, 0x5a + i, 0x33);
++            memcpy(mem, (void*)BUILD_BIOS_TMP_ADDR, 32*1024);
++            clear = 1;
++        } else {
++            pci_config_writeb(bdf, 0x5a + i, 0x33);
++        }
++    }
++    if (clear)
++        memset((void*)BUILD_BIOS_TMP_ADDR, 0, 32*1024);
++
++    // Make ram from 0xf0000-0x100000 writable
++    int reg = pci_config_readb(bdf, 0x59);
++    pci_config_writeb(bdf, 0x59, 0x30);
++    if (reg & 0x10)
++        // Ram already present.
++        return;
++
++    // Copy bios.
++    memcpy((void*)BUILD_BIOS_ADDR, (void*)BIOS_SRC_ADDR, BUILD_BIOS_SIZE);
++}
++
++// Make the 0xc0000-0x100000 area read/writable.
++void
++make_bios_writable(void)
++{
++    if (CONFIG_COREBOOT)
++        return;
++
++    dprintf(3, "enabling shadow ram\n");
++
++    // Locate chip controlling ram shadowing.
++    int bdf = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441);
++    if (bdf < 0) {
++        dprintf(1, "Unable to unlock ram - bridge not found\n");
++        return;
++    }
++
++    int reg = pci_config_readb(bdf, 0x59);
++    if (!(reg & 0x10)) {
++        // QEMU doesn't fully implement the piix shadow capabilities -
++        // if ram isn't backing the bios segment when shadowing is
++        // disabled, the code itself wont be in memory.  So, run the
++        // code from the high-memory flash location.
++        u32 pos = (u32)__make_bios_writable - BUILD_BIOS_ADDR + BIOS_SRC_ADDR;
++        void (*func)(u16 bdf) = (void*)pos;
++        func(bdf);
++        return;
++    }
++    // Ram already present - just enable writes
++    __make_bios_writable(bdf);
++}
++
++// Make the BIOS code segment area (0xf0000) read-only.
++void
++make_bios_readonly(void)
++{
++    if (CONFIG_COREBOOT)
++        return;
++
++    dprintf(3, "locking shadow ram\n");
++
++    int bdf = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441);
++    if (bdf < 0) {
++        dprintf(1, "Unable to lock ram - bridge not found\n");
++        return;
++    }
++
++    // Flush any pending writes before locking memory.
++    wbinvd();
++
++    // Write protect roms from 0xc0000-0xf0000
++    int i;
++    for (i=0; i<6; i++) {
++        u32 mem = BUILD_ROM_START + i * 32*1024;
++        if (RomEnd <= mem + 16*1024) {
++            if (RomEnd > mem)
++                pci_config_writeb(bdf, 0x5a + i, 0x31);
++            break;
++        }
++        pci_config_writeb(bdf, 0x5a + i, 0x11);
++    }
++
++    // Write protect 0xf0000-0x100000
++    pci_config_writeb(bdf, 0x59, 0x10);
++}
+--- x/roms/seabios/src/smbios.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/smbios.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,436 @@
++// smbios table generation (on emulators)
++//
++// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2006 Fabrice Bellard
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "util.h" // dprintf
++#include "biosvar.h" // GET_EBDA
++#include "paravirt.h" // qemu_cfg_smbios_load_field
++#include "smbios.h" // struct smbios_entry_point
++
++static void
++smbios_entry_point_init(u16 max_structure_size,
++                        u16 structure_table_length,
++                        void *structure_table_address,
++                        u16 number_of_structures)
++{
++    struct smbios_entry_point *ep = malloc_fseg(sizeof(*ep));
++    void *finaltable = malloc_high(structure_table_length);
++    if (!ep || !finaltable) {
++        dprintf(1, "No space for smbios tables!\n");
++        free(ep);
++        free(finaltable);
++        return;
++    }
++    memcpy(finaltable, structure_table_address, structure_table_length);
++
++    memcpy(ep->anchor_string, "_SM_", 4);
++    ep->length = 0x1f;
++    ep->smbios_major_version = 2;
++    ep->smbios_minor_version = 4;
++    ep->max_structure_size = max_structure_size;
++    ep->entry_point_revision = 0;
++    memset(ep->formatted_area, 0, 5);
++    memcpy(ep->intermediate_anchor_string, "_DMI_", 5);
++
++    ep->structure_table_length = structure_table_length;
++    ep->structure_table_address = (u32)finaltable;
++    ep->number_of_structures = number_of_structures;
++    ep->smbios_bcd_revision = 0x24;
++
++    ep->checksum -= checksum(ep, 0x10);
++
++    ep->intermediate_checksum -= checksum((void*)ep + 0x10, ep->length - 0x10);
++
++    dprintf(1, "SMBIOS ptr=%p table=%p\n", ep, finaltable);
++}
++
++#define load_str_field_with_default(type, field, def)                   \
++    do {                                                                \
++        size = qemu_cfg_smbios_load_field(type,                         \
++                                 offsetof(struct smbios_type_##type,    \
++                                          field), end);                 \
++        if (size > 0) {                                                 \
++            end += size;                                                \
++        } else {                                                        \
++            memcpy(end, def, sizeof(def));                              \
++            end += sizeof(def);                                         \
++        }                                                               \
++        p->field = ++str_index;                                         \
++    } while (0)
++
++#define load_str_field_or_skip(type, field) \
++    do {                                                                \
++        size = qemu_cfg_smbios_load_field(type,                         \
++                                 offsetof(struct smbios_type_##type,    \
++                                          field), end);                 \
++        if (size > 0) {                                                 \
++            end += size;                                                \
++            p->field = ++str_index;                                     \
++        } else {                                                        \
++            p->field = 0;                                               \
++        }                                                               \
++    } while (0)
++
++/* Type 0 -- BIOS Information */
++#define RELEASE_DATE_STR "01/01/2007"
++static void *
++smbios_init_type_0(void *start)
++{
++    struct smbios_type_0 *p = (struct smbios_type_0 *)start;
++    char *end = (char *)start + sizeof(struct smbios_type_0);
++    size_t size;
++    int str_index = 0;
++
++    p->header.type = 0;
++    p->header.length = sizeof(struct smbios_type_0);
++    p->header.handle = 0;
++
++    load_str_field_with_default(0, vendor_str, CONFIG_APPNAME);
++    load_str_field_with_default(0, bios_version_str, CONFIG_APPNAME);
++
++    p->bios_starting_address_segment = 0xe800;
++
++    load_str_field_with_default(0, bios_release_date_str, RELEASE_DATE_STR);
++
++    p->bios_rom_size = 0; /* FIXME */
++
++    memset(p->bios_characteristics, 0, 8);
++    p->bios_characteristics[0] = 0x08; /* BIOS characteristics not supported */
++    p->bios_characteristics_extension_bytes[0] = 0;
++    /* Enable targeted content distribution. Needed for SVVP */
++    p->bios_characteristics_extension_bytes[1] = 4;
++
++    if (!qemu_cfg_smbios_load_field(0, offsetof(struct smbios_type_0,
++                                                system_bios_major_release),
++                                    &p->system_bios_major_release))
++        p->system_bios_major_release = 1;
++
++    if (!qemu_cfg_smbios_load_field(0, offsetof(struct smbios_type_0,
++                                                system_bios_minor_release),
++                                    &p->system_bios_minor_release))
++        p->system_bios_minor_release = 0;
++
++    p->embedded_controller_major_release = 0xff;
++    p->embedded_controller_minor_release = 0xff;
++
++    *end = 0;
++    end++;
++
++    return end;
++}
++
++/* Type 1 -- System Information */
++static void *
++smbios_init_type_1(void *start)
++{
++    struct smbios_type_1 *p = (struct smbios_type_1 *)start;
++    char *end = (char *)start + sizeof(struct smbios_type_1);
++    size_t size;
++    int str_index = 0;
++
++    p->header.type = 1;
++    p->header.length = sizeof(struct smbios_type_1);
++    p->header.handle = 0x100;
++
++    load_str_field_with_default(1, manufacturer_str, CONFIG_APPNAME);
++    load_str_field_with_default(1, product_name_str, CONFIG_APPNAME);
++    load_str_field_or_skip(1, version_str);
++    load_str_field_or_skip(1, serial_number_str);
++
++    size = qemu_cfg_smbios_load_field(1, offsetof(struct smbios_type_1,
++                                                  uuid), &p->uuid);
++    if (size == 0)
++        memset(p->uuid, 0, 16);
++
++    p->wake_up_type = 0x06; /* power switch */
++
++    load_str_field_or_skip(1, sku_number_str);
++    load_str_field_or_skip(1, family_str);
++
++    *end = 0;
++    end++;
++    if (!str_index) {
++        *end = 0;
++        end++;
++    }
++
++    return end;
++}
++
++/* Type 3 -- System Enclosure */
++static void *
++smbios_init_type_3(void *start)
++{
++    struct smbios_type_3 *p = (struct smbios_type_3 *)start;
++
++    p->header.type = 3;
++    p->header.length = sizeof(struct smbios_type_3);
++    p->header.handle = 0x300;
++
++    p->manufacturer_str = 1;
++    p->type = 0x01; /* other */
++    p->version_str = 0;
++    p->serial_number_str = 0;
++    p->asset_tag_number_str = 0;
++    p->boot_up_state = 0x03; /* safe */
++    p->power_supply_state = 0x03; /* safe */
++    p->thermal_state = 0x03; /* safe */
++    p->security_status = 0x02; /* unknown */
++    p->oem_defined = 0;
++    p->height = 0;
++    p->number_of_power_cords = 0;
++    p->contained_element_count = 0;
++
++    start += sizeof(struct smbios_type_3);
++    memcpy((char *)start, CONFIG_APPNAME"\0\0", sizeof(CONFIG_APPNAME) + 1);
++
++    return start + sizeof(CONFIG_APPNAME) + 1;
++}
++
++/* Type 4 -- Processor Information */
++static void *
++smbios_init_type_4(void *start, unsigned int cpu_number)
++{
++    struct smbios_type_4 *p = (struct smbios_type_4 *)start;
++
++    p->header.type = 4;
++    p->header.length = sizeof(struct smbios_type_4);
++    p->header.handle = 0x400 + cpu_number;
++
++    p->socket_designation_str = 1;
++    p->processor_type = 0x03; /* CPU */
++    p->processor_family = 0x01; /* other */
++    p->processor_manufacturer_str = 2;
++
++    u32 cpuid_signature, ebx, ecx, cpuid_features;
++    cpuid(1, &cpuid_signature, &ebx, &ecx, &cpuid_features);
++    p->processor_id[0] = cpuid_signature;
++    p->processor_id[1] = cpuid_features;
++
++    p->processor_version_str = 0;
++    p->voltage = 0;
++    p->external_clock = 0;
++
++    p->max_speed = 2000;
++    p->current_speed = 2000;
++
++    p->status = 0x41; /* socket populated, CPU enabled */
++    p->processor_upgrade = 0x01; /* other */
++
++    p->l1_cache_handle = 0xffff; /* cache information structure not provided */
++    p->l2_cache_handle = 0xffff;
++    p->l3_cache_handle = 0xffff;
++
++    start += sizeof(struct smbios_type_4);
++
++    snprintf((char*)start, 6, "CPU%2x", cpu_number);
++    start += 6;
++    memcpy((char *)start, CONFIG_APPNAME"\0\0", sizeof(CONFIG_APPNAME) + 1);
++
++    return start + sizeof(CONFIG_APPNAME) + 1;
++}
++
++/* Type 16 -- Physical Memory Array */
++static void *
++smbios_init_type_16(void *start, u32 memory_size_mb, int nr_mem_devs)
++{
++    struct smbios_type_16 *p = (struct smbios_type_16*)start;
++
++    p->header.type = 16;
++    p->header.length = sizeof(struct smbios_type_16);
++    p->header.handle = 0x1000;
++
++    p->location = 0x01; /* other */
++    p->use = 0x03; /* system memory */
++    p->error_correction = 0x06; /* Multi-bit ECC to make Microsoft happy */
++    p->maximum_capacity = memory_size_mb * 1024;
++    p->memory_error_information_handle = 0xfffe; /* none provided */
++    p->number_of_memory_devices = nr_mem_devs;
++
++    start += sizeof(struct smbios_type_16);
++    *((u16 *)start) = 0;
++
++    return start + 2;
++}
++
++/* Type 17 -- Memory Device */
++static void *
++smbios_init_type_17(void *start, u32 memory_size_mb, int instance)
++{
++    struct smbios_type_17 *p = (struct smbios_type_17 *)start;
++
++    p->header.type = 17;
++    p->header.length = sizeof(struct smbios_type_17);
++    p->header.handle = 0x1100 + instance;
++
++    p->physical_memory_array_handle = 0x1000;
++    p->total_width = 64;
++    p->data_width = 64;
++/* TODO: should assert in case something is wrong   ASSERT((memory_size_mb & ~0x7fff) == 0); */
++    p->size = memory_size_mb;
++    p->form_factor = 0x09; /* DIMM */
++    p->device_set = 0;
++    p->device_locator_str = 1;
++    p->bank_locator_str = 0;
++    p->memory_type = 0x07; /* RAM */
++    p->type_detail = 0;
++
++    start += sizeof(struct smbios_type_17);
++    memcpy((char *)start, "DIMM 0", 7);
++    ((char*)start)[5] += instance;
++    start += 7;
++    *((u8 *)start) = 0;
++
++    return start+1;
++}
++
++/* Type 19 -- Memory Array Mapped Address */
++static void *
++smbios_init_type_19(void *start, u32 memory_size_mb, int instance)
++{
++    struct smbios_type_19 *p = (struct smbios_type_19 *)start;
++
++    p->header.type = 19;
++    p->header.length = sizeof(struct smbios_type_19);
++    p->header.handle = 0x1300 + instance;
++
++    p->starting_address = instance << 24;
++    p->ending_address = p->starting_address + (memory_size_mb << 10) - 1;
++    p->memory_array_handle = 0x1000;
++    p->partition_width = 1;
++
++    start += sizeof(struct smbios_type_19);
++    *((u16 *)start) = 0;
++
++    return start + 2;
++}
++
++/* Type 20 -- Memory Device Mapped Address */
++static void *
++smbios_init_type_20(void *start, u32 memory_size_mb, int instance)
++{
++    struct smbios_type_20 *p = (struct smbios_type_20 *)start;
++
++    p->header.type = 20;
++    p->header.length = sizeof(struct smbios_type_20);
++    p->header.handle = 0x1400 + instance;
++
++    p->starting_address = instance << 24;
++    p->ending_address = p->starting_address + (memory_size_mb << 10) - 1;
++    p->memory_device_handle = 0x1100 + instance;
++    p->memory_array_mapped_address_handle = 0x1300 + instance;
++    p->partition_row_position = 1;
++    p->interleave_position = 0;
++    p->interleaved_data_depth = 0;
++
++    start += sizeof(struct smbios_type_20);
++
++    *((u16 *)start) = 0;
++    return start+2;
++}
++
++/* Type 32 -- System Boot Information */
++static void *
++smbios_init_type_32(void *start)
++{
++    struct smbios_type_32 *p = (struct smbios_type_32 *)start;
++
++    p->header.type = 32;
++    p->header.length = sizeof(struct smbios_type_32);
++    p->header.handle = 0x2000;
++    memset(p->reserved, 0, 6);
++    p->boot_status = 0; /* no errors detected */
++
++    start += sizeof(struct smbios_type_32);
++    *((u16 *)start) = 0;
++
++    return start+2;
++}
++
++/* Type 127 -- End of Table */
++static void *
++smbios_init_type_127(void *start)
++{
++    struct smbios_type_127 *p = (struct smbios_type_127 *)start;
++
++    p->header.type = 127;
++    p->header.length = sizeof(struct smbios_type_127);
++    p->header.handle = 0x7f00;
++
++    start += sizeof(struct smbios_type_127);
++    *((u16 *)start) = 0;
++
++    return start + 2;
++}
++
++#define TEMPSMBIOSSIZE (32 * 1024)
++
++void
++smbios_init(void)
++{
++    if (! CONFIG_SMBIOS)
++        return;
++
++    dprintf(3, "init SMBIOS tables\n");
++
++    char *start = malloc_tmphigh(TEMPSMBIOSSIZE);
++    if (! start) {
++        dprintf(1, "No memory for temp smbios table\n");
++        return;
++    }
++
++    u32 nr_structs = 0, max_struct_size = 0;
++    char *q, *p = start;
++    char *end = start + TEMPSMBIOSSIZE - sizeof(struct smbios_type_127);
++
++#define add_struct(type, args...)                                       \
++    do {                                                                \
++        if (!qemu_cfg_smbios_load_external(type, &p, &nr_structs,       \
++                                           &max_struct_size, end)) {    \
++            q = smbios_init_type_##type(args);                          \
++            nr_structs++;                                               \
++            if ((q - p) > max_struct_size)                              \
++                max_struct_size = q - p;                                \
++            p = q;                                                      \
++        }                                                               \
++    } while (0)
++
++    add_struct(0, p);
++    add_struct(1, p);
++    add_struct(3, p);
++
++    int cpu_num;
++    for (cpu_num = 1; cpu_num <= MaxCountCPUs; cpu_num++)
++        add_struct(4, p, cpu_num);
++    u64 memsize = RamSizeOver4G;
++    if (memsize)
++        memsize += 0x100000000ull;
++    else
++        memsize = RamSize;
++    memsize = memsize / (1024 * 1024);
++    int nr_mem_devs = (memsize + 0x3fff) >> 14;
++    add_struct(16, p, memsize, nr_mem_devs);
++    int i;
++    for (i = 0; i < nr_mem_devs; i++) {
++        u32 dev_memsize = ((i == (nr_mem_devs - 1))
++                           ? (((memsize-1) & 0x3fff)+1) : 0x4000);
++        add_struct(17, p, dev_memsize, i);
++        add_struct(19, p, dev_memsize, i);
++        add_struct(20, p, dev_memsize, i);
++    }
++
++    add_struct(32, p);
++    /* Add any remaining provided entries before the end marker */
++    for (i = 0; i < 256; i++)
++        qemu_cfg_smbios_load_external(i, &p, &nr_structs, &max_struct_size,
++                                      end);
++    add_struct(127, p);
++
++#undef add_struct
++
++    smbios_entry_point_init(max_struct_size, p - start, start, nr_structs);
++    free(start);
++}
+--- x/roms/seabios/src/smbios.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/smbios.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,166 @@
++#ifndef __SMBIOS_H
++#define __SMBIOS_H
++
++// smbios.c
++void smbios_init(void);
++
++/* SMBIOS entry point -- must be written to a 16-bit aligned address
++   between 0xf0000 and 0xfffff.
++ */
++struct smbios_entry_point {
++    char anchor_string[4];
++    u8 checksum;
++    u8 length;
++    u8 smbios_major_version;
++    u8 smbios_minor_version;
++    u16 max_structure_size;
++    u8 entry_point_revision;
++    u8 formatted_area[5];
++    char intermediate_anchor_string[5];
++    u8 intermediate_checksum;
++    u16 structure_table_length;
++    u32 structure_table_address;
++    u16 number_of_structures;
++    u8 smbios_bcd_revision;
++} PACKED;
++
++/* This goes at the beginning of every SMBIOS structure. */
++struct smbios_structure_header {
++    u8 type;
++    u8 length;
++    u16 handle;
++} PACKED;
++
++/* SMBIOS type 0 - BIOS Information */
++struct smbios_type_0 {
++    struct smbios_structure_header header;
++    u8 vendor_str;
++    u8 bios_version_str;
++    u16 bios_starting_address_segment;
++    u8 bios_release_date_str;
++    u8 bios_rom_size;
++    u8 bios_characteristics[8];
++    u8 bios_characteristics_extension_bytes[2];
++    u8 system_bios_major_release;
++    u8 system_bios_minor_release;
++    u8 embedded_controller_major_release;
++    u8 embedded_controller_minor_release;
++} PACKED;
++
++/* SMBIOS type 1 - System Information */
++struct smbios_type_1 {
++    struct smbios_structure_header header;
++    u8 manufacturer_str;
++    u8 product_name_str;
++    u8 version_str;
++    u8 serial_number_str;
++    u8 uuid[16];
++    u8 wake_up_type;
++    u8 sku_number_str;
++    u8 family_str;
++} PACKED;
++
++/* SMBIOS type 3 - System Enclosure (v2.3) */
++struct smbios_type_3 {
++    struct smbios_structure_header header;
++    u8 manufacturer_str;
++    u8 type;
++    u8 version_str;
++    u8 serial_number_str;
++    u8 asset_tag_number_str;
++    u8 boot_up_state;
++    u8 power_supply_state;
++    u8 thermal_state;
++    u8 security_status;
++    u32 oem_defined;
++    u8 height;
++    u8 number_of_power_cords;
++    u8 contained_element_count;
++    // contained elements follow
++} PACKED;
++
++/* SMBIOS type 4 - Processor Information (v2.0) */
++struct smbios_type_4 {
++    struct smbios_structure_header header;
++    u8 socket_designation_str;
++    u8 processor_type;
++    u8 processor_family;
++    u8 processor_manufacturer_str;
++    u32 processor_id[2];
++    u8 processor_version_str;
++    u8 voltage;
++    u16 external_clock;
++    u16 max_speed;
++    u16 current_speed;
++    u8 status;
++    u8 processor_upgrade;
++    u16 l1_cache_handle;
++    u16 l2_cache_handle;
++    u16 l3_cache_handle;
++} PACKED;
++
++/* SMBIOS type 16 - Physical Memory Array
++ *   Associated with one type 17 (Memory Device).
++ */
++struct smbios_type_16 {
++    struct smbios_structure_header header;
++    u8 location;
++    u8 use;
++    u8 error_correction;
++    u32 maximum_capacity;
++    u16 memory_error_information_handle;
++    u16 number_of_memory_devices;
++} PACKED;
++
++/* SMBIOS type 17 - Memory Device
++ *   Associated with one type 19
++ */
++struct smbios_type_17 {
++    struct smbios_structure_header header;
++    u16 physical_memory_array_handle;
++    u16 memory_error_information_handle;
++    u16 total_width;
++    u16 data_width;
++    u16 size;
++    u8 form_factor;
++    u8 device_set;
++    u8 device_locator_str;
++    u8 bank_locator_str;
++    u8 memory_type;
++    u16 type_detail;
++} PACKED;
++
++/* SMBIOS type 19 - Memory Array Mapped Address */
++struct smbios_type_19 {
++    struct smbios_structure_header header;
++    u32 starting_address;
++    u32 ending_address;
++    u16 memory_array_handle;
++    u8 partition_width;
++} PACKED;
++
++/* SMBIOS type 20 - Memory Device Mapped Address */
++struct smbios_type_20 {
++    struct smbios_structure_header header;
++    u32 starting_address;
++    u32 ending_address;
++    u16 memory_device_handle;
++    u16 memory_array_mapped_address_handle;
++    u8 partition_row_position;
++    u8 interleave_position;
++    u8 interleaved_data_depth;
++} PACKED;
++
++/* SMBIOS type 32 - System Boot Information */
++struct smbios_type_32 {
++    struct smbios_structure_header header;
++    u8 reserved[6];
++    u8 boot_status;
++} PACKED;
++
++/* SMBIOS type 127 -- End-of-table */
++struct smbios_type_127 {
++    struct smbios_structure_header header;
++} PACKED;
++
++#endif // smbios.h
+--- x/roms/seabios/src/smm.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/smm.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,135 @@
++// System Management Mode support (on emulators)
++//
++// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2006 Fabrice Bellard
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "pci.h" // pci_config_writel
++#include "util.h" // wbinvd
++#include "config.h" // CONFIG_*
++#include "ioport.h" // outb
++#include "pci_ids.h" // PCI_VENDOR_ID_INTEL
++
++ASM32FLAT(
++    ".global smm_relocation_start\n"
++    ".global smm_relocation_end\n"
++    ".global smm_code_start\n"
++    ".global smm_code_end\n"
++    "  .code16\n"
++
++    /* code to relocate SMBASE to 0xa0000 */
++    "smm_relocation_start:\n"
++    "  mov $" __stringify(BUILD_SMM_INIT_ADDR) " + 0x7efc, %ebx\n"
++    "  addr32 mov (%ebx), %al\n"  /* revision ID to see if x86_64 or x86 */
++    "  cmp $0x64, %al\n"
++    "  je 1f\n"
++    "  mov $" __stringify(BUILD_SMM_INIT_ADDR) " + 0x7ef8, %ebx\n"
++    "  jmp 2f\n"
++    "1:\n"
++    "  mov $" __stringify(BUILD_SMM_INIT_ADDR) " + 0x7f00, %ebx\n"
++    "2:\n"
++    "  movl $" __stringify(BUILD_SMM_ADDR) " - 0x8000, %eax\n"
++    "  addr32 movl %eax, (%ebx)\n"
++    /* indicate to the BIOS that the SMM code was executed */
++    "  mov $0x00, %al\n"
++    "  movw $" __stringify(PORT_SMI_STATUS) ", %dx\n"
++    "  outb %al, %dx\n"
++    "  rsm\n"
++    "smm_relocation_end:\n"
++
++    /* minimal SMM code to enable or disable ACPI */
++    "smm_code_start:\n"
++    "  movw $" __stringify(PORT_SMI_CMD) ", %dx\n"
++    "  inb %dx, %al\n"
++    "  cmp $0xf0, %al\n"
++    "  jne 1f\n"
++
++    /* ACPI disable */
++    "  mov $" __stringify(PORT_ACPI_PM_BASE) " + 0x04, %dx\n" /* PMCNTRL */
++    "  inw %dx, %ax\n"
++    "  andw $~1, %ax\n"
++    "  outw %ax, %dx\n"
++
++    "  jmp 2f\n"
++
++    "1:\n"
++    "  cmp $0xf1, %al\n"
++    "  jne 2f\n"
++
++    /* ACPI enable */
++    "  mov $" __stringify(PORT_ACPI_PM_BASE) " + 0x04, %dx\n" /* PMCNTRL */
++    "  inw %dx, %ax\n"
++    "  orw $1, %ax\n"
++    "  outw %ax, %dx\n"
++
++    "2:\n"
++    "  rsm\n"
++    "smm_code_end:\n"
++    "  .code32\n"
++    );
++
++extern u8 smm_relocation_start, smm_relocation_end;
++extern u8 smm_code_start, smm_code_end;
++
++void
++smm_init(void)
++{
++    if (CONFIG_COREBOOT)
++        // SMM only supported on emulators.
++        return;
++    if (!CONFIG_USE_SMM)
++        return;
++
++    dprintf(3, "init smm\n");
++
++    // This code is hardcoded for PIIX4 Power Management device.
++    int bdf = pci_find_device(PCI_VENDOR_ID_INTEL
++                              , PCI_DEVICE_ID_INTEL_82371AB_3);
++    if (bdf < 0)
++        // Device not found
++        return;
++    int i440_bdf = pci_find_device(PCI_VENDOR_ID_INTEL
++                                   , PCI_DEVICE_ID_INTEL_82441);
++    if (i440_bdf < 0)
++        return;
++
++    /* check if SMM init is already done */
++    u32 value = pci_config_readl(bdf, 0x58);
++    if (value & (1 << 25))
++        return;
++
++    /* enable the SMM memory window */
++    pci_config_writeb(i440_bdf, 0x72, 0x02 | 0x48);
++
++    /* save original memory content */
++    memcpy((void *)BUILD_SMM_ADDR, (void *)BUILD_SMM_INIT_ADDR, BUILD_SMM_SIZE);
++
++    /* copy the SMM relocation code */
++    memcpy((void *)BUILD_SMM_INIT_ADDR, &smm_relocation_start,
++           &smm_relocation_end - &smm_relocation_start);
++
++    /* enable SMI generation when writing to the APMC register */
++    pci_config_writel(bdf, 0x58, value | (1 << 25));
++
++    /* init APM status port */
++    outb(0x01, PORT_SMI_STATUS);
++
++    /* raise an SMI interrupt */
++    outb(0x00, PORT_SMI_CMD);
++
++    /* wait until SMM code executed */
++    while (inb(PORT_SMI_STATUS) != 0x00)
++        ;
++
++    /* restore original memory content */
++    memcpy((void *)BUILD_SMM_INIT_ADDR, (void *)BUILD_SMM_ADDR, BUILD_SMM_SIZE);
++
++    /* copy the SMM code */
++    memcpy((void *)BUILD_SMM_ADDR, &smm_code_start
++           , &smm_code_end - &smm_code_start);
++    wbinvd();
++
++    /* close the SMM memory window and enable normal SMM */
++    pci_config_writeb(i440_bdf, 0x72, 0x02 | 0x08);
++}
+--- x/roms/seabios/src/smp.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/smp.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,136 @@
++// CPU count detection
++//
++// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2006 Fabrice Bellard
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "util.h" // dprintf
++#include "config.h" // CONFIG_*
++#include "cmos.h" // CMOS_BIOS_SMP_COUNT
++#include "paravirt.h"
++
++#define APIC_ICR_LOW ((u8*)BUILD_APIC_ADDR + 0x300)
++#define APIC_SVR     ((u8*)BUILD_APIC_ADDR + 0x0F0)
++#define APIC_LINT0   ((u8*)BUILD_APIC_ADDR + 0x350)
++#define APIC_LINT1   ((u8*)BUILD_APIC_ADDR + 0x360)
++
++#define APIC_ENABLED 0x0100
++
++struct { u32 ecx, eax, edx; } smp_mtrr[16] VAR16VISIBLE;
++u32 smp_mtrr_count VAR16VISIBLE;
++
++void
++wrmsr_smp(u32 index, u64 val)
++{
++    wrmsr(index, val);
++    if (smp_mtrr_count >= ARRAY_SIZE(smp_mtrr))
++        return;
++    smp_mtrr[smp_mtrr_count].ecx = index;
++    smp_mtrr[smp_mtrr_count].eax = val;
++    smp_mtrr[smp_mtrr_count].edx = val >> 32;
++    smp_mtrr_count++;
++}
++
++u32 CountCPUs VAR16VISIBLE;
++u32 MaxCountCPUs VAR16VISIBLE;
++extern void smp_ap_boot_code(void);
++ASM16(
++    "  .global smp_ap_boot_code\n"
++    "smp_ap_boot_code:\n"
++
++    // Setup data segment
++    "  movw $" __stringify(SEG_BIOS) ", %ax\n"
++    "  movw %ax, %ds\n"
++
++    // MTRR setup
++    "  movl $smp_mtrr, %esi\n"
++    "  movl smp_mtrr_count, %ebx\n"
++    "1:testl %ebx, %ebx\n"
++    "  jz 2f\n"
++    "  movl 0(%esi), %ecx\n"
++    "  movl 4(%esi), %eax\n"
++    "  movl 8(%esi), %edx\n"
++    "  wrmsr\n"
++    "  addl $12, %esi\n"
++    "  decl %ebx\n"
++    "  jmp 1b\n"
++    "2:\n"
++
++    // Increment the cpu counter
++    "  lock incl CountCPUs\n"
++
++    // Halt the processor.
++    "1:hlt\n"
++    "  jmp 1b\n"
++    );
++
++// find and initialize the CPUs by launching a SIPI to them
++void
++smp_probe(void)
++{
++    ASSERT32FLAT();
++    u32 eax, ebx, ecx, cpuid_features;
++    cpuid(1, &eax, &ebx, &ecx, &cpuid_features);
++    if (! (cpuid_features & CPUID_APIC)) {
++        // No apic - only the main cpu is present.
++        dprintf(1, "No apic - only the main cpu is present.\n");
++        CountCPUs= 1;
++        MaxCountCPUs = 1;
++        return;
++    }
++
++    // Init the counter.
++    writel(&CountCPUs, 1);
++
++    // Setup jump trampoline to counter code.
++    u64 old = *(u64*)BUILD_AP_BOOT_ADDR;
++    // ljmpw $SEG_BIOS, $(smp_ap_boot_code - BUILD_BIOS_ADDR)
++    u64 new = (0xea | ((u64)SEG_BIOS<<24)
++               | (((u32)smp_ap_boot_code - BUILD_BIOS_ADDR) << 8));
++    *(u64*)BUILD_AP_BOOT_ADDR = new;
++
++    // enable local APIC
++    u32 val = readl(APIC_SVR);
++    writel(APIC_SVR, val | APIC_ENABLED);
++
++    if (! CONFIG_COREBOOT) {
++        /* Set LINT0 as Ext_INT, level triggered */
++        writel(APIC_LINT0, 0x8700);
++
++        /* Set LINT1 as NMI, level triggered */
++        writel(APIC_LINT1, 0x8400);
++    }
++
++    // broadcast SIPI
++    writel(APIC_ICR_LOW, 0x000C4500);
++    u32 sipi_vector = BUILD_AP_BOOT_ADDR >> 12;
++    writel(APIC_ICR_LOW, 0x000C4600 | sipi_vector);
++
++    // Wait for other CPUs to process the SIPI.
++    if (CONFIG_COREBOOT) {
++        msleep(10);
++    } else {
++        u8 cmos_smp_count = inb_cmos(CMOS_BIOS_SMP_COUNT);
++        while (cmos_smp_count + 1 != readl(&CountCPUs))
++             ;
++    }
++
++    // Restore memory.
++    *(u64*)BUILD_AP_BOOT_ADDR = old;
++
++    MaxCountCPUs = qemu_cfg_get_max_cpus();
++    if (!MaxCountCPUs || MaxCountCPUs < CountCPUs)
++        MaxCountCPUs = CountCPUs;
++
++    dprintf(1, "Found %d cpu(s) max supported %d cpu(s)\n", readl(&CountCPUs),
++        MaxCountCPUs);
++}
++
++// Reset variables to zero
++void
++smp_probe_setup(void)
++{
++    CountCPUs = 0;
++    smp_mtrr_count = 0;
++}
+--- x/roms/seabios/src/stacks.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/stacks.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,301 @@
++// Code for manipulating stack locations.
++//
++// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "biosvar.h" // get_ebda_seg
++#include "util.h" // dprintf
++#include "bregs.h" // CR0_PE
++
++static inline u32 getcr0(void) {
++    u32 cr0;
++    asm("movl %%cr0, %0" : "=r"(cr0));
++    return cr0;
++}
++static inline void sgdt(struct descloc_s *desc) {
++    asm("sgdtl %0" : "=m"(*desc));
++}
++static inline void lgdt(struct descloc_s *desc) {
++    asm("lgdtl %0" : : "m"(*desc) : "memory");
++}
++
++// Call a 32bit SeaBIOS function from a 16bit SeaBIOS function.
++static inline int
++call32(void *func)
++{
++    ASSERT16();
++    u32 cr0 = getcr0();
++    if (cr0 & CR0_PE)
++        // Called in 16bit protected mode?!
++        return -1;
++
++    // Backup cmos index register and disable nmi
++    u8 cmosindex = inb(PORT_CMOS_INDEX);
++    outb(cmosindex | NMI_DISABLE_BIT, PORT_CMOS_INDEX);
++    inb(PORT_CMOS_DATA);
++
++    // Backup fs/gs and gdt
++    u16 fs = GET_SEG(FS), gs = GET_SEG(GS);
++    struct descloc_s gdt;
++    sgdt(&gdt);
++
++    func -= BUILD_BIOS_ADDR;
++    u32 bkup_ss, bkup_esp;
++    asm volatile(
++        // Backup ss/esp / set esp to flat stack location
++        "  movl %%ss, %0\n"
++        "  movl %%esp, %1\n"
++        "  shll $4, %0\n"
++        "  addl %0, %%esp\n"
++        "  movl %%ss, %0\n"
++
++        // Transition to 32bit mode, call func, return to 16bit
++        "  pushl $(" __stringify(BUILD_BIOS_ADDR) " + 1f)\n"
++        "  jmp transition32\n"
++        "  .code32\n"
++        "1:calll %2\n"
++        "  pushl $2f\n"
++        "  jmp transition16big\n"
++
++        // Restore ds/ss/esp
++        "  .code16gcc\n"
++        "2:movl %0, %%ds\n"
++        "  movl %0, %%ss\n"
++        "  movl %1, %%esp\n"
++        : "=&r" (bkup_ss), "=&r" (bkup_esp)
++        : "m" (*(u8*)func)
++        : "eax", "ecx", "edx", "cc", "memory");
++
++    // Restore gdt and fs/gs
++    lgdt(&gdt);
++    SET_SEG(FS, fs);
++    SET_SEG(GS, gs);
++
++    // Restore cmos index register
++    outb(cmosindex, PORT_CMOS_INDEX);
++    inb(PORT_CMOS_DATA);
++    return 0;
++}
++
++
++/****************************************************************
++ * Stack in EBDA
++ ****************************************************************/
++
++// Switch to the extra stack in ebda and call a function.
++inline u32
++stack_hop(u32 eax, u32 edx, u32 ecx, void *func)
++{
++    ASSERT16();
++    u16 ebda_seg = get_ebda_seg(), bkup_ss;
++    u32 bkup_esp;
++    asm volatile(
++        // Backup current %ss/%esp values.
++        "movw %%ss, %w3\n"
++        "movl %%esp, %4\n"
++        // Copy ebda seg to %ds/%ss and set %esp
++        "movw %w6, %%ds\n"
++        "movw %w6, %%ss\n"
++        "movl %5, %%esp\n"
++        // Call func
++        "calll %7\n"
++        // Restore segments and stack
++        "movw %w3, %%ds\n"
++        "movw %w3, %%ss\n"
++        "movl %4, %%esp"
++        : "+a" (eax), "+d" (edx), "+c" (ecx), "=&r" (bkup_ss), "=&r" (bkup_esp)
++        : "i" (EBDA_OFFSET_TOP_STACK), "r" (ebda_seg), "m" (*(u8*)func)
++        : "cc", "memory");
++    return eax;
++}
++
++
++/****************************************************************
++ * Threads
++ ****************************************************************/
++
++#define THREADSTACKSIZE 4096
++
++struct thread_info {
++    struct thread_info *next;
++    void *stackpos;
++};
++
++struct thread_info VAR16VISIBLE MainThread;
++int VAR16VISIBLE CanPreempt;
++
++void
++thread_setup(void)
++{
++    MainThread.next = &MainThread;
++    MainThread.stackpos = NULL;
++    CanPreempt = 0;
++}
++
++// Return the 'struct thread_info' for the currently running thread.
++struct thread_info *
++getCurThread(void)
++{
++    u32 esp = getesp();
++    if (esp <= BUILD_STACK_ADDR)
++        return &MainThread;
++    return (void*)ALIGN_DOWN(esp, THREADSTACKSIZE);
++}
++
++// Switch to next thread stack.
++static void
++switch_next(struct thread_info *cur)
++{
++    struct thread_info *next = cur->next;
++    if (cur == next)
++        // Nothing to do.
++        return;
++    asm volatile(
++        "  pushl $1f\n"                 // store return pc
++        "  pushl %%ebp\n"               // backup %ebp
++        "  movl %%esp, 4(%%eax)\n"      // cur->stackpos = %esp
++        "  movl 4(%%ecx), %%esp\n"      // %esp = next->stackpos
++        "  popl %%ebp\n"                // restore %ebp
++        "  retl\n"                      // restore pc
++        "1:\n"
++        : "+a"(cur), "+c"(next)
++        :
++        : "ebx", "edx", "esi", "edi", "cc", "memory");
++}
++
++// Briefly permit irqs to occur.
++void
++yield(void)
++{
++    if (MODESEGMENT || !CONFIG_THREADS) {
++        // Just directly check irqs.
++        check_irqs();
++        return;
++    }
++    struct thread_info *cur = getCurThread();
++    if (cur == &MainThread)
++        // Permit irqs to fire
++        check_irqs();
++
++    // Switch to the next thread
++    switch_next(cur);
++}
++
++// Last thing called from a thread (called on "next" stack).
++static void
++__end_thread(struct thread_info *old)
++{
++    struct thread_info *pos = &MainThread;
++    while (pos->next != old)
++        pos = pos->next;
++    pos->next = old->next;
++    free(old);
++    dprintf(DEBUG_thread, "\\%08x/ End thread\n", (u32)old);
++}
++
++// Create a new thread and start executing 'func' in it.
++void
++run_thread(void (*func)(void*), void *data)
++{
++    ASSERT32FLAT();
++    if (! CONFIG_THREADS)
++        goto fail;
++    struct thread_info *thread;
++    thread = memalign_tmphigh(THREADSTACKSIZE, THREADSTACKSIZE);
++    if (!thread)
++        goto fail;
++
++    thread->stackpos = (void*)thread + THREADSTACKSIZE;
++    struct thread_info *cur = getCurThread();
++    thread->next = cur->next;
++    cur->next = thread;
++
++    dprintf(DEBUG_thread, "/%08x\\ Start thread\n", (u32)thread);
++    asm volatile(
++        // Start thread
++        "  pushl $1f\n"                 // store return pc
++        "  pushl %%ebp\n"               // backup %ebp
++        "  movl %%esp, 4(%%edx)\n"      // cur->stackpos = %esp
++        "  movl 4(%%ebx), %%esp\n"      // %esp = thread->stackpos
++        "  calll *%%ecx\n"              // Call func
++
++        // End thread
++        "  movl (%%ebx), %%ecx\n"       // %ecx = thread->next
++        "  movl 4(%%ecx), %%esp\n"      // %esp = next->stackpos
++        "  movl %%ebx, %%eax\n"
++        "  calll %4\n"                  // call __end_thread(thread)
++        "  popl %%ebp\n"                // restore %ebp
++        "  retl\n"                      // restore pc
++        "1:\n"
++        : "+a"(data), "+c"(func), "+b"(thread), "+d"(cur)
++        : "m"(*(u8*)__end_thread)
++        : "esi", "edi", "cc", "memory");
++    return;
++
++fail:
++    func(data);
++}
++
++// Wait for all threads (other than the main thread) to complete.
++void
++wait_threads(void)
++{
++    ASSERT32FLAT();
++    if (! CONFIG_THREADS)
++        return;
++    while (MainThread.next != &MainThread)
++        yield();
++}
++
++
++/****************************************************************
++ * Thread preemption
++ ****************************************************************/
++
++static u32 PreemptCount;
++
++// Turn on RTC irqs and arrange for them to check the 32bit threads.
++void
++start_preempt(void)
++{
++    if (! CONFIG_THREADS || ! CONFIG_THREAD_OPTIONROMS)
++        return;
++    CanPreempt = 1;
++    PreemptCount = 0;
++    useRTC();
++}
++
++// Turn off RTC irqs / stop checking for thread execution.
++void
++finish_preempt(void)
++{
++    if (! CONFIG_THREADS || ! CONFIG_THREAD_OPTIONROMS)
++        return;
++    CanPreempt = 0;
++    releaseRTC();
++    dprintf(1, "Done preempt - %d checks\n", PreemptCount);
++}
++
++extern void yield_preempt(void);
++#if MODESEGMENT == 0
++// Try to execute 32bit threads.
++void VISIBLE32FLAT
++yield_preempt(void)
++{
++    PreemptCount++;
++    switch_next(&MainThread);
++}
++#endif
++
++// 16bit code that checks if threads are pending and executes them if so.
++void
++check_preempt(void)
++{
++    if (! CONFIG_THREADS || ! CONFIG_THREAD_OPTIONROMS
++        || !GET_GLOBAL(CanPreempt)
++        || GET_GLOBAL(MainThread.next) == &MainThread)
++        return;
++
++    call32(yield_preempt);
++}
+--- x/roms/seabios/src/system.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/system.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,360 @@
++// Handler for int 0x15 "system" calls
++//
++// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2002  MandrakeSoft S.A.
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "util.h" // memcpy_far
++#include "biosvar.h" // BIOS_CONFIG_TABLE
++#include "ioport.h" // inb
++#include "memmap.h" // E820_RAM
++#include "pic.h" // eoi_pic2
++#include "bregs.h" // struct bregs
++
++// Use PS2 System Control port A to set A20 enable
++static inline u8
++set_a20(u8 cond)
++{
++    // get current setting first
++    u8 newval, oldval = inb(PORT_A20);
++    if (cond)
++        newval = oldval | A20_ENABLE_BIT;
++    else
++        newval = oldval & ~A20_ENABLE_BIT;
++    outb(newval, PORT_A20);
++
++    return (oldval & A20_ENABLE_BIT) != 0;
++}
++
++static void
++handle_152400(struct bregs *regs)
++{
++    set_a20(0);
++    set_code_success(regs);
++}
++
++static void
++handle_152401(struct bregs *regs)
++{
++    set_a20(1);
++    set_code_success(regs);
++}
++
++static void
++handle_152402(struct bregs *regs)
++{
++    regs->al = (inb(PORT_A20) & A20_ENABLE_BIT) != 0;
++    set_code_success(regs);
++}
++
++static void
++handle_152403(struct bregs *regs)
++{
++    regs->bx = 3;
++    set_code_success(regs);
++}
++
++static void
++handle_1524XX(struct bregs *regs)
++{
++    set_code_unimplemented(regs, RET_EUNSUPPORTED);
++}
++
++static void
++handle_1524(struct bregs *regs)
++{
++    switch (regs->al) {
++    case 0x00: handle_152400(regs); break;
++    case 0x01: handle_152401(regs); break;
++    case 0x02: handle_152402(regs); break;
++    case 0x03: handle_152403(regs); break;
++    default:   handle_1524XX(regs); break;
++    }
++}
++
++// removable media eject
++static void
++handle_1552(struct bregs *regs)
++{
++    set_code_success(regs);
++}
++
++static void
++handle_1587(struct bregs *regs)
++{
++    // +++ should probably have descriptor checks
++    // +++ should have exception handlers
++
++    u8 prev_a20_enable = set_a20(1); // enable A20 line
++
++    // 128K max of transfer on 386+ ???
++    // source == destination ???
++
++    // ES:SI points to descriptor table
++    // offset   use     initially  comments
++    // ==============================================
++    // 00..07   Unused  zeros      Null descriptor
++    // 08..0f   GDT     zeros      filled in by BIOS
++    // 10..17   source  ssssssss   source of data
++    // 18..1f   dest    dddddddd   destination of data
++    // 20..27   CS      zeros      filled in by BIOS
++    // 28..2f   SS      zeros      filled in by BIOS
++
++// check for access rights of source & dest here
++
++    // Initialize GDT descriptor
++    u32 si = regs->si;
++    u64 *gdt_far = (void*)si;
++    u16 gdt_seg = regs->es;
++    u32 loc = (u32)MAKE_FLATPTR(gdt_seg, gdt_far);
++    SET_FARVAR(gdt_seg, gdt_far[1], GDT_DATA | GDT_LIMIT((6*sizeof(u64))-1)
++               | GDT_BASE(loc));
++    // Initialize CS descriptor
++    SET_FARVAR(gdt_seg, gdt_far[4], GDT_CODE | GDT_LIMIT(BUILD_BIOS_SIZE-1)
++               | GDT_BASE(BUILD_BIOS_ADDR));
++    // Initialize SS descriptor
++    loc = (u32)MAKE_FLATPTR(GET_SEG(SS), 0);
++    SET_FARVAR(gdt_seg, gdt_far[5], GDT_DATA | GDT_LIMIT(0x0ffff)
++               | GDT_BASE(loc));
++
++    u16 count = regs->cx;
++    asm volatile(
++        // Load new descriptor tables
++        "  lgdtw %%es:(1<<3)(%%si)\n"
++        "  lidtw %%cs:pmode_IDT_info\n"
++
++        // Enable protected mode
++        "  movl %%cr0, %%eax\n"
++        "  orl $" __stringify(CR0_PE) ", %%eax\n"
++        "  movl %%eax, %%cr0\n"
++
++        // far jump to flush CPU queue after transition to protected mode
++        "  ljmpw $(4<<3), $1f\n"
++
++        // GDT points to valid descriptor table, now load DS, ES
++        "1:movw $(2<<3), %%ax\n" // 2nd descriptor in table, TI=GDT, RPL=00
++        "  movw %%ax, %%ds\n"
++        "  movw $(3<<3), %%ax\n" // 3rd descriptor in table, TI=GDT, RPL=00
++        "  movw %%ax, %%es\n"
++
++        // move CX words from DS:SI to ES:DI
++        "  xorw %%si, %%si\n"
++        "  xorw %%di, %%di\n"
++        "  rep movsw\n"
++
++        // Disable protected mode
++        "  movl %%cr0, %%eax\n"
++        "  andl $~" __stringify(CR0_PE) ", %%eax\n"
++        "  movl %%eax, %%cr0\n"
++
++        // far jump to flush CPU queue after transition to real mode
++        "  ljmpw $" __stringify(SEG_BIOS) ", $2f\n"
++
++        // restore IDT to normal real-mode defaults
++        "2:lidtw %%cs:rmode_IDT_info\n"
++
++        // Restore %ds (from %ss)
++        "  movw %%ss, %%ax\n"
++        "  movw %%ax, %%ds\n"
++        : "+c"(count), "+S"(si)
++        : : "eax", "di", "cc"); // XXX - also clobbers %es
++
++    set_a20(prev_a20_enable);
++
++    set_code_success(regs);
++}
++
++// Get the amount of extended memory (above 1M)
++static void
++handle_1588(struct bregs *regs)
++{
++    u32 rs = GET_GLOBAL(RamSize);
++
++    // According to Ralf Brown's interrupt the limit should be 15M,
++    // but real machines mostly return max. 63M.
++    if (rs > 64*1024*1024)
++        regs->ax = 63 * 1024;
++    else
++        regs->ax = (rs - 1*1024*1024) / 1024;
++    set_success(regs);
++}
++
++// Switch to protected mode
++static void
++handle_1589(struct bregs *regs)
++{
++    set_a20(1);
++
++    set_pics(regs->bl, regs->bh);
++
++    u64 *gdt_far = (void*)(regs->si + 0);
++    u16 gdt_seg = regs->es;
++    SET_FARVAR(gdt_seg, gdt_far[7], GDT_CODE | GDT_LIMIT(BUILD_BIOS_SIZE-1)
++               | GDT_BASE(BUILD_BIOS_ADDR));
++
++    regs->ds = 3<<3; // 3rd gdt descriptor is %ds
++    regs->es = 4<<3; // 4th gdt descriptor is %es
++    regs->code.seg = 6<<3; // 6th gdt descriptor is %cs
++
++    set_code_success(regs);
++
++    asm volatile(
++        // Load new descriptor tables
++        "  lgdtw %%es:(1<<3)(%%si)\n"
++        "  lidtw %%es:(2<<3)(%%si)\n"
++
++        // Enable protected mode
++        "  movl %%cr0, %%eax\n"
++        "  orl $" __stringify(CR0_PE) ", %%eax\n"
++        "  movl %%eax, %%cr0\n"
++
++        // far jump to flush CPU queue after transition to protected mode
++        "  ljmpw $(7<<3), $1f\n"
++
++        // GDT points to valid descriptor table, now load SS
++        "1:movw $(5<<3), %%ax\n"
++        "  movw %%ax, %%ds\n"
++        "  movw %%ax, %%ss\n"
++        :
++        : "S"(gdt_far)
++        : "eax", "cc");
++}
++
++// Device busy interrupt.  Called by Int 16h when no key available
++static void
++handle_1590(struct bregs *regs)
++{
++}
++
++// Interrupt complete.  Called by Int 16h when key becomes available
++static void
++handle_1591(struct bregs *regs)
++{
++}
++
++// keyboard intercept
++static void
++handle_154f(struct bregs *regs)
++{
++    set_invalid_silent(regs);
++}
++
++static void
++handle_15c0(struct bregs *regs)
++{
++    regs->es = SEG_BIOS;
++    regs->bx = (u32)&BIOS_CONFIG_TABLE;
++    set_code_success(regs);
++}
++
++static void
++handle_15c1(struct bregs *regs)
++{
++    regs->es = get_ebda_seg();
++    set_success(regs);
++}
++
++static void
++handle_15e801(struct bregs *regs)
++{
++    // my real system sets ax and bx to 0
++    // this is confirmed by Ralph Brown list
++    // but syslinux v1.48 is known to behave
++    // strangely if ax is set to 0
++    // regs.u.r16.ax = 0;
++    // regs.u.r16.bx = 0;
++
++    u32 rs = GET_GLOBAL(RamSize);
++
++    // Get the amount of extended memory (above 1M)
++    if (rs > 16*1024*1024) {
++        // limit to 15M
++        regs->cx = 15*1024;
++        // Get the amount of extended memory above 16M in 64k blocks
++        regs->dx = (rs - 16*1024*1024) / (64*1024);
++    } else {
++        regs->cx = (rs - 1*1024*1024) / 1024;
++        regs->dx = 0;
++    }
++
++    // Set configured memory equal to extended memory
++    regs->ax = regs->cx;
++    regs->bx = regs->dx;
++
++    set_success(regs);
++}
++
++// Info on e820 map location and size.
++struct e820entry e820_list[CONFIG_MAX_E820] VAR16VISIBLE;
++int e820_count VAR16VISIBLE;
++
++static void
++handle_15e820(struct bregs *regs)
++{
++    int count = GET_GLOBAL(e820_count);
++    if (regs->edx != 0x534D4150 || regs->bx >= count
++        || regs->ecx < sizeof(e820_list[0])) {
++        set_code_invalid(regs, RET_EUNSUPPORTED);
++        return;
++    }
++
++    memcpy_far(regs->es, (void*)(regs->di+0)
++               , get_global_seg(), &e820_list[regs->bx]
++               , sizeof(e820_list[0]));
++    if (regs->bx == count-1)
++        regs->ebx = 0;
++    else
++        regs->ebx++;
++    regs->eax = 0x534D4150;
++    regs->ecx = sizeof(e820_list[0]);
++    set_success(regs);
++}
++
++static void
++handle_15e8XX(struct bregs *regs)
++{
++    set_code_unimplemented(regs, RET_EUNSUPPORTED);
++}
++
++static void
++handle_15e8(struct bregs *regs)
++{
++    switch (regs->al) {
++    case 0x01: handle_15e801(regs); break;
++    case 0x20: handle_15e820(regs); break;
++    default:   handle_15e8XX(regs); break;
++    }
++}
++
++static void
++handle_15XX(struct bregs *regs)
++{
++    set_code_unimplemented(regs, RET_EUNSUPPORTED);
++}
++
++// INT 15h System Services Entry Point
++void VISIBLE16
++handle_15(struct bregs *regs)
++{
++    debug_enter(regs, DEBUG_HDL_15);
++    switch (regs->ah) {
++    case 0x24: handle_1524(regs); break;
++    case 0x4f: handle_154f(regs); break;
++    case 0x52: handle_1552(regs); break;
++    case 0x53: handle_1553(regs); break;
++    case 0x5f: handle_155f(regs); break;
++    case 0x83: handle_1583(regs); break;
++    case 0x86: handle_1586(regs); break;
++    case 0x87: handle_1587(regs); break;
++    case 0x88: handle_1588(regs); break;
++    case 0x89: handle_1589(regs); break;
++    case 0x90: handle_1590(regs); break;
++    case 0x91: handle_1591(regs); break;
++    case 0xc0: handle_15c0(regs); break;
++    case 0xc1: handle_15c1(regs); break;
++    case 0xc2: handle_15c2(regs); break;
++    case 0xe8: handle_15e8(regs); break;
++    default:   handle_15XX(regs); break;
++    }
++}
+--- x/roms/seabios/src/types.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/types.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,134 @@
++// Basic type definitions for X86 cpus.
++//
++// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++#ifndef __TYPES_H
++#define __TYPES_H
++
++typedef unsigned char u8;
++typedef signed char s8;
++typedef unsigned short u16;
++typedef signed short s16;
++typedef unsigned int u32;
++typedef signed int s32;
++typedef unsigned long long u64;
++typedef signed long long s64;
++typedef u32 size_t;
++
++union u64_u32_u {
++    struct { u32 hi, lo; };
++    u64 val;
++};
++
++#ifdef MANUAL_NO_JUMP_TABLE
++# define default case 775324556: asm(""); default
++#endif
++
++#ifdef WHOLE_PROGRAM
++# define __VISIBLE __attribute__((externally_visible))
++#else
++# define __VISIBLE
++#endif
++
++#define UNIQSEC __FILE__ "." __stringify(__LINE__)
++
++#define __noreturn __attribute__((noreturn))
++extern void __force_link_error__only_in_32bit_flat(void) __noreturn;
++extern void __force_link_error__only_in_32bit_segmented(void) __noreturn;
++extern void __force_link_error__only_in_16bit(void) __noreturn;
++
++#define __ASM(code) asm(".section .text.asm." UNIQSEC "\n\t" code)
++
++#if MODE16 == 1
++// Notes a function as externally visible in the 16bit code chunk.
++# define VISIBLE16 __VISIBLE
++// Notes a function as externally visible in the 32bit flat code chunk.
++# define VISIBLE32FLAT __section(".discard.func32flat." UNIQSEC) noinline __weak
++// Notes a function as externally visible in the 32bit segmented code chunk.
++# define VISIBLE32SEG __section(".discard.func32seg." UNIQSEC) noinline __weak
++// Designate a variable as (only) visible to 16bit code.
++# define VAR16 __section(".data16." UNIQSEC)
++// Designate a variable as visible to 16bit, 32bit, and assembler code.
++# define VAR16VISIBLE VAR16 __VISIBLE
++// Designate a variable as externally visible (in addition to all internal code).
++# define VAR16EXPORT __section(".data16.export." UNIQSEC) __VISIBLE
++// Designate a variable at a specific 16bit address
++# define VAR16FIXED(addr) __aligned(1) __VISIBLE __section(".fixedaddr." __stringify(addr))
++// Designate a variable as (only) visible to 32bit segmented code.
++# define VAR32SEG __section(".discard.var32seg." UNIQSEC)
++// Designate a 32bit variable also available in 16bit "big real" mode.
++# define VAR32FLATVISIBLE __section(".discard.var32flat." UNIQSEC) __VISIBLE __weak
++// Designate top-level assembler as 16bit only.
++# define ASM16(code) __ASM(code)
++// Designate top-level assembler as 32bit flat only.
++# define ASM32FLAT(code)
++// Compile time check for a given mode.
++# define ASSERT16() do { } while (0)
++# define ASSERT32SEG() __force_link_error__only_in_32bit_segmented()
++# define ASSERT32FLAT() __force_link_error__only_in_32bit_flat()
++#elif MODESEGMENT == 1
++# define VISIBLE16 __section(".discard.func16." UNIQSEC) noinline __weak
++# define VISIBLE32FLAT __section(".discard.func32flat." UNIQSEC) noinline __weak
++# define VISIBLE32SEG __VISIBLE
++# define VAR16 __section(".discard.var16." UNIQSEC)
++# define VAR16VISIBLE VAR16 __VISIBLE __weak
++# define VAR16EXPORT VAR16VISIBLE
++# define VAR16FIXED(addr) VAR16VISIBLE
++# define VAR32SEG __section(".data32seg." UNIQSEC)
++# define VAR32FLATVISIBLE __section(".discard.var32flat." UNIQSEC) __VISIBLE __weak
++# define ASM16(code)
++# define ASM32FLAT(code)
++# define ASSERT16() __force_link_error__only_in_16bit()
++# define ASSERT32SEG() do { } while (0)
++# define ASSERT32FLAT() __force_link_error__only_in_32bit_flat()
++#else
++# define VISIBLE16 __section(".discard.func16." UNIQSEC) noinline __weak
++# define VISIBLE32FLAT __VISIBLE
++# define VISIBLE32SEG __section(".discard.func32seg." UNIQSEC) noinline __weak
++# define VAR16 __section(".discard.var16." UNIQSEC)
++# define VAR16VISIBLE VAR16 __VISIBLE __weak
++# define VAR16EXPORT VAR16VISIBLE
++# define VAR16FIXED(addr) VAR16VISIBLE
++# define VAR32SEG __section(".discard.var32seg." UNIQSEC)
++# define VAR32FLATVISIBLE __VISIBLE
++# define ASM16(code)
++# define ASM32FLAT(code) __ASM(code)
++# define ASSERT16() __force_link_error__only_in_16bit()
++# define ASSERT32SEG() __force_link_error__only_in_32bit_segmented()
++# define ASSERT32FLAT() do { } while (0)
++#endif
++
++#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
++#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
++#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
++#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
++#define DIV_ROUND_CLOSEST(x, divisor)({                 \
++            typeof(divisor) __divisor = divisor;        \
++            (((x) + ((__divisor) / 2)) / (__divisor));  \
++        })
++#define ALIGN(x,a)              __ALIGN_MASK(x,(typeof(x))(a)-1)
++#define __ALIGN_MASK(x,mask)    (((x)+(mask))&~(mask))
++#define ALIGN_DOWN(x,a)         ((x) & ~((typeof(x))(a)-1))
++#define container_of(ptr, type, member) ({                      \
++        const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
++        (type *)( (char *)__mptr - offsetof(type,member) );})
++
++#define NULL ((void*)0)
++
++#define __weak __attribute__((weak))
++#define __section(S) __attribute__((section(S)))
++
++#define PACKED __attribute__((packed))
++#define __aligned(x) __attribute__((aligned(x)))
++
++#define barrier() __asm__ __volatile__("": : :"memory")
++
++#define noinline __attribute__((noinline))
++#define __always_inline inline __attribute__((always_inline))
++#define __attribute_const __attribute__((__const__))
++
++#define __stringify_1(x)        #x
++#define __stringify(x)          __stringify_1(x)
++
++#endif // types.h
+--- x/roms/seabios/src/usb-hid.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/usb-hid.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,186 @@
++// Code for handling USB Human Interface Devices (HID).
++//
++// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "util.h" // dprintf
++#include "usb-hid.h" // usb_keyboard_setup
++#include "config.h" // CONFIG_*
++#include "usb.h" // usb_ctrlrequest
++#include "biosvar.h" // GET_GLOBAL
++
++struct usb_pipe *keyboard_pipe VAR16VISIBLE;
++
++
++/****************************************************************
++ * Setup
++ ****************************************************************/
++
++static int
++set_protocol(u32 endp, u16 val)
++{
++    struct usb_ctrlrequest req;
++    req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
++    req.bRequest = HID_REQ_SET_PROTOCOL;
++    req.wValue = val;
++    req.wIndex = 0;
++    req.wLength = 0;
++    return send_default_control(endp, &req, NULL);
++}
++
++static int
++set_idle(u32 endp, u8 val)
++{
++    struct usb_ctrlrequest req;
++    req.bRequestType = USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
++    req.bRequest = HID_REQ_SET_IDLE;
++    req.wValue = val<<8;
++    req.wIndex = 0;
++    req.wLength = 0;
++    return send_default_control(endp, &req, NULL);
++}
++
++int
++usb_keyboard_init(u32 endp, struct usb_interface_descriptor *iface, int imax)
++{
++    if (! CONFIG_USB_KEYBOARD)
++        return -1;
++    if (keyboard_pipe)
++        // XXX - this enables the first found keyboard (could be random)
++        return -1;
++    dprintf(2, "usb_keyboard_setup %x\n", endp);
++
++    struct usb_endpoint_descriptor *epdesc = (void*)&iface[1];
++    for (;;) {
++        if ((void*)epdesc >= (void*)iface + imax
++            || epdesc->bDescriptorType == USB_DT_INTERFACE) {
++            dprintf(1, "No keyboard intr in?\n");
++            return -1;
++        }
++        if (epdesc->bDescriptorType == USB_DT_ENDPOINT
++            && (epdesc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN
++            && ((epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
++                == USB_ENDPOINT_XFER_INT)
++            && epdesc->wMaxPacketSize == 8)
++            break;
++        epdesc = (void*)epdesc + epdesc->bLength;
++    }
++    u32 inendp = mkendp(endp2cntl(endp), endp2devaddr(endp)
++                        , epdesc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK
++                        , endp2speed(endp), epdesc->wMaxPacketSize);
++
++    // Enable "boot" protocol.
++    int ret = set_protocol(endp, 1);
++    if (ret)
++        return -1;
++    // Only send reports on a new key event.
++    ret = set_idle(endp, 0);
++    if (ret)
++        return -1;
++
++    struct usb_pipe *pipe = alloc_intr_pipe(inendp, epdesc->bInterval);
++    if (!pipe)
++        return -1;
++    keyboard_pipe = pipe;
++
++    return 0;
++}
++
++void
++usb_keyboard_setup(void)
++{
++    if (! CONFIG_USB_KEYBOARD)
++        return;
++    keyboard_pipe = NULL;
++}
++
++
++/****************************************************************
++ * Keyboard events
++ ****************************************************************/
++
++static u16 KeyToScanCode[] VAR16 = {
++    0x0000, 0x0000, 0x0000, 0x0000, 0x001e, 0x0030, 0x002e, 0x0020,
++    0x0012, 0x0021, 0x0022, 0x0023, 0x0017, 0x0024, 0x0025, 0x0026,
++    0x0032, 0x0031, 0x0018, 0x0019, 0x0010, 0x0013, 0x001f, 0x0014,
++    0x0016, 0x002f, 0x0011, 0x002d, 0x0015, 0x002c, 0x0002, 0x0003,
++    0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b,
++    0x001c, 0x0001, 0x000e, 0x000f, 0x0039, 0x000c, 0x000d, 0x001a,
++    0x001b, 0x002b, 0x0000, 0x0027, 0x0028, 0x0029, 0x0033, 0x0034,
++    0x0035, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, 0x0040,
++    0x0041, 0x0042, 0x0043, 0x0044, 0x0057, 0x0058, 0xe037, 0x0046,
++    0xe11d, 0xe052, 0xe047, 0xe049, 0xe053, 0xe04f, 0xe051, 0xe04d,
++    0xe04b, 0xe050, 0xe048, 0x0045, 0xe035, 0x0037, 0x004a, 0x004e,
++    0xe01c, 0x004f, 0x0050, 0x0051, 0x004b, 0x004c, 0x004d, 0x0047,
++    0x0048, 0x0049, 0x0052, 0x0053
++};
++
++static u16 ModifierToScanCode[] VAR16 = {
++    //lcntl, lshift, lalt, lgui, rcntl, rshift, ralt, rgui
++    0x001d, 0x002a, 0x0038, 0xe05b, 0xe01d, 0x0036, 0xe038, 0xe05c
++};
++
++struct keyevent {
++    u8 modifiers;
++    u8 reserved;
++    u8 keys[6];
++};
++
++static void
++prockeys(u16 keys)
++{
++    if (keys > 0xff) {
++        u8 key = keys>>8;
++        if (key == 0xe1) {
++            // Pause key
++            process_key(0xe1);
++            process_key(0x1d | (keys & 0x80));
++            process_key(0x45 | (keys & 0x80));
++            return;
++        }
++        process_key(key);
++    }
++    process_key(keys);
++}
++
++static void
++handle_key(struct keyevent *data)
++{
++    dprintf(5, "Got key %x %x\n", data->modifiers, data->keys[0]);
++    // XXX
++    int i;
++    for (i=0; i<8; i++)
++        if (data->modifiers & (1<<i))
++            prockeys(GET_GLOBAL(ModifierToScanCode[i]));
++    for (i=0; i<ARRAY_SIZE(data->keys); i++) {
++        u8 key = data->keys[i];
++        if (key >= ARRAY_SIZE(KeyToScanCode))
++            continue;
++        key = GET_GLOBAL(KeyToScanCode[key]);
++        if (!key)
++            continue;
++        prockeys(key);
++    }
++    for (i=0; i<8; i++)
++        if (data->modifiers & (1<<i))
++            prockeys(GET_GLOBAL(ModifierToScanCode[i]) | 0x80);
++}
++
++void
++usb_check_key(void)
++{
++    if (! CONFIG_USB_KEYBOARD)
++        return;
++    struct usb_pipe *pipe = GET_GLOBAL(keyboard_pipe);
++    if (!pipe)
++        return;
++
++    for (;;) {
++        struct keyevent data;
++        int ret = usb_poll_intr(pipe, &data);
++        if (ret)
++            break;
++        handle_key(&data);
++    }
++}
+--- x/roms/seabios/src/usb-hid.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/usb-hid.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,27 @@
++#ifndef __USB_HID_H
++#define __USB_HID_H
++
++// usb-hid.c
++struct usb_interface_descriptor;
++int usb_keyboard_init(u32 endp, struct usb_interface_descriptor *iface
++                      , int imax);
++void usb_keyboard_setup(void);
++void usb_check_key(void);
++
++
++/****************************************************************
++ * hid flags
++ ****************************************************************/
++
++#define USB_INTERFACE_SUBCLASS_BOOT     1
++#define USB_INTERFACE_PROTOCOL_KEYBOARD 1
++#define USB_INTERFACE_PROTOCOL_MOUSE    2
++
++#define HID_REQ_GET_REPORT              0x01
++#define HID_REQ_GET_IDLE                0x02
++#define HID_REQ_GET_PROTOCOL            0x03
++#define HID_REQ_SET_REPORT              0x09
++#define HID_REQ_SET_IDLE                0x0A
++#define HID_REQ_SET_PROTOCOL            0x0B
++
++#endif // ush-hid.h
+--- x/roms/seabios/src/usb-ohci.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/usb-ohci.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,337 @@
++// Code for handling OHCI USB controllers.
++//
++// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "util.h" // dprintf
++#include "pci.h" // pci_bdf_to_bus
++#include "config.h" // CONFIG_*
++#include "usb-ohci.h" // struct ohci_hcca
++#include "pci_regs.h" // PCI_BASE_ADDRESS_0
++#include "usb.h" // struct usb_s
++#include "farptr.h" // GET_FLATPTR
++
++#define FIT                     (1 << 31)
++
++static int
++start_ohci(struct usb_s *cntl, struct ohci_hcca *hcca)
++{
++    u32 oldfminterval = readl(&cntl->ohci.regs->fminterval);
++    u32 oldrwc = readl(&cntl->ohci.regs->control) & OHCI_CTRL_RWC;
++
++    // XXX - check if already running?
++
++    // Do reset
++    writel(&cntl->ohci.regs->control, OHCI_USB_RESET | oldrwc);
++    readl(&cntl->ohci.regs->control); // flush writes
++    msleep(50);
++
++    // Do software init (min 10us, max 2ms)
++    u64 end = calc_future_tsc_usec(10);
++    writel(&cntl->ohci.regs->cmdstatus, OHCI_HCR);
++    for (;;) {
++        u32 status = readl(&cntl->ohci.regs->cmdstatus);
++        if (! status & OHCI_HCR)
++            break;
++        if (check_time(end)) {
++            dprintf(1, "Timeout on ohci software reset\n");
++            return -1;
++        }
++    }
++
++    // Init memory
++    writel(&cntl->ohci.regs->ed_controlhead, (u32)cntl->ohci.control_ed);
++    writel(&cntl->ohci.regs->ed_bulkhead, 0);
++    writel(&cntl->ohci.regs->hcca, (u32)hcca);
++
++    // Init fminterval
++    u32 fi = oldfminterval & 0x3fff;
++    writel(&cntl->ohci.regs->fminterval
++           , (((oldfminterval & FIT) ^ FIT)
++              | fi | (((6 * (fi - 210)) / 7) << 16)));
++    writel(&cntl->ohci.regs->periodicstart, ((9 * fi) / 10) & 0x3fff);
++    readl(&cntl->ohci.regs->control); // flush writes
++
++    // XXX - verify that fminterval was setup correctly.
++
++    // Go into operational state
++    writel(&cntl->ohci.regs->control
++           , (OHCI_CTRL_CBSR | OHCI_CTRL_CLE | OHCI_CTRL_PLE
++              | OHCI_USB_OPER | oldrwc));
++    readl(&cntl->ohci.regs->control); // flush writes
++
++    return 0;
++}
++
++static void
++stop_ohci(struct usb_s *cntl)
++{
++    u32 oldrwc = readl(&cntl->ohci.regs->control) & OHCI_CTRL_RWC;
++    writel(&cntl->ohci.regs->control, oldrwc);
++    readl(&cntl->ohci.regs->control); // flush writes
++}
++
++// Find any devices connected to the root hub.
++static int
++check_ohci_ports(struct usb_s *cntl)
++{
++    // Turn on power for all devices on roothub.
++    u32 rha = readl(&cntl->ohci.regs->roothub_a);
++    rha &= ~(RH_A_PSM | RH_A_OCPM);
++    writel(&cntl->ohci.regs->roothub_status, RH_HS_LPSC);
++    writel(&cntl->ohci.regs->roothub_b, RH_B_PPCM);
++    msleep((rha >> 24) * 2);
++
++    // Count and reset connected devices
++    int ports = rha & RH_A_NDP;
++    int totalcount = 0;
++    int i;
++    for (i=0; i<ports; i++)
++        if (readl(&cntl->ohci.regs->roothub_portstatus[i]) & RH_PS_CCS) {
++            writel(&cntl->ohci.regs->roothub_portstatus[i], RH_PS_PRS);
++            totalcount++;
++        }
++    if (!totalcount)
++        // No devices connected
++        goto shutdown;
++
++    msleep(60);    // XXX - should poll instead of using timer.
++
++    totalcount = 0;
++    for (i=0; i<ports; i++) {
++        u32 sts = readl(&cntl->ohci.regs->roothub_portstatus[i]);
++        if ((sts & (RH_PS_CCS|RH_PS_PES)) == (RH_PS_CCS|RH_PS_PES)) {
++            int count = configure_usb_device(cntl, !!(sts & RH_PS_LSDA));
++            if (! count)
++                // Shutdown port
++                writel(&cntl->ohci.regs->roothub_portstatus[i]
++                       , RH_PS_CCS|RH_PS_LSDA);
++            totalcount += count;
++        }
++    }
++    if (!totalcount)
++        goto shutdown;
++
++    return totalcount;
++
++shutdown:
++    // Turn off power to all ports
++    writel(&cntl->ohci.regs->roothub_status, RH_HS_LPS);
++    return 0;
++}
++
++void
++ohci_init(void *data)
++{
++    if (! CONFIG_USB_OHCI)
++        return;
++    struct usb_s *cntl = data;
++
++    // XXX - don't call pci_config_XXX from a thread
++    cntl->type = USB_TYPE_OHCI;
++    u32 baseaddr = pci_config_readl(cntl->bdf, PCI_BASE_ADDRESS_0);
++    cntl->ohci.regs = (void*)(baseaddr & PCI_BASE_ADDRESS_MEM_MASK);
++
++    dprintf(3, "OHCI init on dev %02x:%02x.%x (regs=%p)\n"
++            , pci_bdf_to_bus(cntl->bdf), pci_bdf_to_dev(cntl->bdf)
++            , pci_bdf_to_fn(cntl->bdf), cntl->ohci.regs);
++
++    // Enable bus mastering and memory access.
++    pci_config_maskw(cntl->bdf, PCI_COMMAND
++                     , 0, PCI_COMMAND_MASTER|PCI_COMMAND_MEMORY);
++
++    // XXX - check for and disable SMM control?
++
++    // Disable interrupts
++    writel(&cntl->ohci.regs->intrdisable, ~0);
++    writel(&cntl->ohci.regs->intrstatus, ~0);
++
++    // Allocate memory
++    struct ohci_hcca *hcca = memalign_high(256, sizeof(*hcca));
++    struct ohci_ed *control_ed = malloc_high(sizeof(*control_ed));
++    if (!hcca || !control_ed) {
++        dprintf(1, "No ram for ohci init\n");
++        return;
++    }
++    memset(hcca, 0, sizeof(*hcca));
++    memset(control_ed, 0, sizeof(*control_ed));
++    control_ed->hwINFO = ED_SKIP;
++    cntl->ohci.control_ed = control_ed;
++
++    int ret = start_ohci(cntl, hcca);
++    if (ret)
++        goto err;
++
++    int count = check_ohci_ports(cntl);
++    if (! count)
++        goto err;
++    return;
++
++err:
++    stop_ohci(cntl);
++    free(hcca);
++    free(control_ed);
++}
++
++static int
++wait_ed(struct ohci_ed *ed)
++{
++    // XXX - 500ms just a guess
++    u64 end = calc_future_tsc(500);
++    for (;;) {
++        if (ed->hwHeadP == ed->hwTailP)
++            return 0;
++        if (check_time(end)) {
++            dprintf(1, "Timeout on wait_ed %p\n", ed);
++            return -1;
++        }
++        yield();
++    }
++}
++
++int
++ohci_control(u32 endp, int dir, const void *cmd, int cmdsize
++             , void *data, int datasize)
++{
++    if (! CONFIG_USB_OHCI)
++        return -1;
++
++    dprintf(5, "ohci_control %x\n", endp);
++    struct usb_s *cntl = endp2cntl(endp);
++    int maxpacket = endp2maxsize(endp);
++    int lowspeed = endp2speed(endp);
++    int devaddr = endp2devaddr(endp) | (endp2ep(endp) << 7);
++
++    // Setup transfer descriptors
++    struct ohci_td *tds = malloc_tmphigh(sizeof(*tds) * 3);
++    tds[0].hwINFO = TD_DP_SETUP | TD_T_DATA0 | TD_CC;
++    tds[0].hwCBP = (u32)cmd;
++    tds[0].hwNextTD = (u32)&tds[1];
++    tds[0].hwBE = (u32)cmd + cmdsize - 1;
++    tds[1].hwINFO = (dir ? TD_DP_IN : TD_DP_OUT) | TD_T_DATA1 | TD_CC;
++    tds[1].hwCBP = datasize ? (u32)data : 0;
++    tds[1].hwNextTD = (u32)&tds[2];
++    tds[1].hwBE = (u32)data + datasize - 1;
++    tds[2].hwINFO = (dir ? TD_DP_OUT : TD_DP_IN) | TD_T_DATA1 | TD_CC;
++    tds[2].hwCBP = 0;
++    tds[2].hwNextTD = (u32)&tds[3];
++    tds[2].hwBE = 0;
++
++    // Transfer data
++    struct ohci_ed *ed = cntl->ohci.control_ed;
++    ed->hwINFO = ED_SKIP;
++    barrier();
++    ed->hwHeadP = (u32)&tds[0];
++    ed->hwTailP = (u32)&tds[3];
++    barrier();
++    ed->hwINFO = devaddr | (maxpacket << 16) | (lowspeed ? ED_LOWSPEED : 0);
++    writel(&cntl->ohci.regs->cmdstatus, OHCI_CLF);
++
++    int ret = wait_ed(ed);
++    ed->hwINFO = ED_SKIP;
++    if (ret)
++        usleep(1); // XXX - in case controller still accessing tds
++    free(tds);
++    return ret;
++}
++
++struct ohci_pipe {
++    struct ohci_ed ed;
++    struct usb_pipe pipe;
++    void *data;
++    int count;
++    struct ohci_td *tds;
++};
++
++struct usb_pipe *
++ohci_alloc_intr_pipe(u32 endp, int period)
++{
++    if (! CONFIG_USB_OHCI)
++        return NULL;
++
++    dprintf(7, "ohci_alloc_intr_pipe %x %d\n", endp, period);
++    struct usb_s *cntl = endp2cntl(endp);
++    int maxpacket = endp2maxsize(endp);
++    int lowspeed = endp2speed(endp);
++    int devaddr = endp2devaddr(endp) | (endp2ep(endp) << 7);
++    // XXX - just grab 20 for now.
++    int count = 20;
++    struct ohci_pipe *pipe = malloc_low(sizeof(*pipe));
++    struct ohci_td *tds = malloc_low(sizeof(*tds) * count);
++    void *data = malloc_low(maxpacket * count);
++    if (!pipe || !tds || !data)
++        goto err;
++
++    struct ohci_ed *ed = &pipe->ed;
++    ed->hwHeadP = (u32)&tds[0];
++    ed->hwTailP = (u32)&tds[count-1];
++    ed->hwINFO = devaddr | (maxpacket << 16) | (lowspeed ? ED_LOWSPEED : 0);
++    ed->hwNextED = 0;
++
++    int i;
++    for (i=0; i<count-1; i++) {
++        tds[i].hwINFO = TD_DP_IN | TD_T_TOGGLE | TD_CC;
++        tds[i].hwCBP = (u32)data + maxpacket * i;
++        tds[i].hwNextTD = (u32)&tds[i+1];
++        tds[i].hwBE = tds[i].hwCBP + maxpacket - 1;
++    }
++
++    // XXX - need schedule - just add to primary list for now.
++    barrier();
++    struct ohci_hcca *hcca = (void*)cntl->ohci.regs->hcca;
++    for (i=0; i<ARRAY_SIZE(hcca->int_table); i++)
++        hcca->int_table[i] = (u32)ed;
++
++    pipe->data = data;
++    pipe->count = count;
++    pipe->tds = tds;
++    pipe->pipe.endp = endp;
++    return &pipe->pipe;
++
++err:
++    free(pipe);
++    free(tds);
++    free(data);
++    return NULL;
++}
++
++int
++ohci_poll_intr(struct usb_pipe *pipe, void *data)
++{
++    ASSERT16();
++    if (! CONFIG_USB_OHCI)
++        return -1;
++
++    struct ohci_pipe *p = container_of(pipe, struct ohci_pipe, pipe);
++    struct ohci_td *tds = GET_FLATPTR(p->tds);
++    struct ohci_td *head = (void*)GET_FLATPTR(p->ed.hwHeadP);
++    struct ohci_td *tail = (void*)GET_FLATPTR(p->ed.hwTailP);
++    int count = GET_FLATPTR(p->count);
++    int pos = (tail - tds + 1) % count;
++    struct ohci_td *next = &tds[pos];
++    if (head == next)
++        // No intrs found.
++        return -1;
++    // XXX - check for errors.
++
++    // Copy data.
++    u32 endp = GET_FLATPTR(p->pipe.endp);
++    int maxpacket = endp2maxsize(endp);
++    void *pipedata = GET_FLATPTR(p->data);
++    void *intrdata = pipedata + maxpacket * pos;
++    memcpy_far(GET_SEG(SS), data
++               , FLATPTR_TO_SEG(intrdata), (void*)FLATPTR_TO_OFFSET(intrdata)
++               , maxpacket);
++
++    // Reenable this td.
++    SET_FLATPTR(tail->hwINFO, TD_DP_IN | TD_T_TOGGLE | TD_CC);
++    intrdata = pipedata + maxpacket * (tail-tds);
++    SET_FLATPTR(tail->hwCBP, (u32)intrdata);
++    SET_FLATPTR(tail->hwNextTD, (u32)next);
++    SET_FLATPTR(tail->hwBE, (u32)intrdata + maxpacket - 1);
++
++    SET_FLATPTR(p->ed.hwTailP, (u32)next);
++
++    return 0;
++}
+--- x/roms/seabios/src/usb-ohci.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/usb-ohci.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,138 @@
++#ifndef __USB_OHCI_H
++#define __USB_OHCI_H
++
++// usb-ohci.c
++struct usb_s;
++void ohci_init(void *data);
++int ohci_control(u32 endp, int dir, const void *cmd, int cmdsize
++                 , void *data, int datasize);
++struct usb_pipe *ohci_alloc_intr_pipe(u32 endp, int period);
++int ohci_poll_intr(struct usb_pipe *pipe, void *data);
++
++
++/****************************************************************
++ * ohci structs and flags
++ ****************************************************************/
++
++struct ohci_ed {
++    u32 hwINFO;
++    u32 hwTailP;
++    u32 hwHeadP;
++    u32 hwNextED;
++} PACKED;
++
++#define ED_ISO          (1 << 15)
++#define ED_SKIP         (1 << 14)
++#define ED_LOWSPEED     (1 << 13)
++#define ED_OUT          (0x01 << 11)
++#define ED_IN           (0x02 << 11)
++
++#define ED_C            (0x02)
++#define ED_H            (0x01)
++
++struct ohci_td {
++    u32 hwINFO;
++    u32 hwCBP;
++    u32 hwNextTD;
++    u32 hwBE;
++} PACKED;
++
++#define TD_CC       0xf0000000
++#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f)
++#define TD_DI       0x00E00000
++
++#define TD_DONE     0x00020000
++#define TD_ISO      0x00010000
++
++#define TD_EC       0x0C000000
++#define TD_T        0x03000000
++#define TD_T_DATA0  0x02000000
++#define TD_T_DATA1  0x03000000
++#define TD_T_TOGGLE 0x00000000
++#define TD_DP       0x00180000
++#define TD_DP_SETUP 0x00000000
++#define TD_DP_IN    0x00100000
++#define TD_DP_OUT   0x00080000
++
++#define TD_R        0x00040000
++
++struct ohci_hcca {
++    u32  int_table[32];
++    u32  frame_no;
++    u32  done_head;
++    u8   reserved[120];
++} PACKED;
++
++struct ohci_regs {
++    u32  revision;
++    u32  control;
++    u32  cmdstatus;
++    u32  intrstatus;
++    u32  intrenable;
++    u32  intrdisable;
++
++    u32  hcca;
++    u32  ed_periodcurrent;
++    u32  ed_controlhead;
++    u32  ed_controlcurrent;
++    u32  ed_bulkhead;
++    u32  ed_bulkcurrent;
++    u32  donehead;
++
++    u32  fminterval;
++    u32  fmremaining;
++    u32  fmnumber;
++    u32  periodicstart;
++    u32  lsthresh;
++
++    u32  roothub_a;
++    u32  roothub_b;
++    u32  roothub_status;
++    u32  roothub_portstatus[15];
++} PACKED;
++
++#define OHCI_CTRL_CBSR  (3 << 0)
++#define OHCI_CTRL_PLE   (1 << 2)
++#define OHCI_CTRL_CLE   (1 << 4)
++#define OHCI_CTRL_HCFS  (3 << 6)
++#       define OHCI_USB_RESET   (0 << 6)
++#       define OHCI_USB_OPER    (2 << 6)
++#define OHCI_CTRL_RWC   (1 << 9)
++
++#define OHCI_HCR        (1 << 0)
++#define OHCI_CLF        (1 << 1)
++
++#define OHCI_INTR_MIE   (1 << 31)
++
++#define RH_PS_CCS            0x00000001
++#define RH_PS_PES            0x00000002
++#define RH_PS_PSS            0x00000004
++#define RH_PS_POCI           0x00000008
++#define RH_PS_PRS            0x00000010
++#define RH_PS_PPS            0x00000100
++#define RH_PS_LSDA           0x00000200
++#define RH_PS_CSC            0x00010000
++#define RH_PS_PESC           0x00020000
++#define RH_PS_PSSC           0x00040000
++#define RH_PS_OCIC           0x00080000
++#define RH_PS_PRSC           0x00100000
++
++#define RH_HS_LPS            0x00000001
++#define RH_HS_OCI            0x00000002
++#define RH_HS_DRWE           0x00008000
++#define RH_HS_LPSC           0x00010000
++#define RH_HS_OCIC           0x00020000
++#define RH_HS_CRWE           0x80000000
++
++#define RH_B_DR         0x0000ffff
++#define RH_B_PPCM       0xffff0000
++
++#define RH_A_NDP        (0xff << 0)
++#define RH_A_PSM        (1 << 8)
++#define RH_A_NPS        (1 << 9)
++#define RH_A_DT         (1 << 10)
++#define RH_A_OCPM       (1 << 11)
++#define RH_A_NOCP       (1 << 12)
++#define RH_A_POTPGT     (0xff << 24)
++
++#endif // usb-ohci.h
+--- x/roms/seabios/src/usb-uhci.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/usb-uhci.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,305 @@
++// Code for handling UHCI USB controllers.
++//
++// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "util.h" // dprintf
++#include "pci.h" // pci_bdf_to_bus
++#include "config.h" // CONFIG_*
++#include "ioport.h" // outw
++#include "usb-uhci.h" // USBLEGSUP
++#include "pci_regs.h" // PCI_BASE_ADDRESS_4
++#include "usb.h" // struct usb_s
++#include "farptr.h" // GET_FLATPTR
++
++static void
++reset_uhci(struct usb_s *cntl)
++{
++    // XXX - don't reset if not needed.
++
++    // Reset PIRQ and SMI
++    pci_config_writew(cntl->bdf, USBLEGSUP, USBLEGSUP_RWC);
++
++    // Reset the HC
++    outw(USBCMD_HCRESET, cntl->uhci.iobase + USBCMD);
++    udelay(5);
++
++    // Disable interrupts and commands (just to be safe).
++    outw(0, cntl->uhci.iobase + USBINTR);
++    outw(0, cntl->uhci.iobase + USBCMD);
++}
++
++static void
++configure_uhci(struct usb_s *cntl)
++{
++    // Allocate ram for schedule storage
++    struct uhci_td *term_td = malloc_high(sizeof(*term_td));
++    struct uhci_framelist *fl = memalign_high(sizeof(*fl), sizeof(*fl));
++    struct uhci_qh *data_qh = malloc_low(sizeof(*data_qh));
++    struct uhci_qh *term_qh = malloc_high(sizeof(*term_qh));
++    if (!term_td || !fl || !data_qh || !term_qh) {
++        dprintf(1, "No ram for uhci init\n");
++        return;
++    }
++
++    // Work around for PIIX errata
++    memset(term_td, 0, sizeof(*term_td));
++    term_td->link = UHCI_PTR_TERM;
++    term_td->token = (uhci_explen(0) | (0x7f << TD_TOKEN_DEVADDR_SHIFT)
++                      | USB_PID_IN);
++    memset(term_qh, 0, sizeof(*term_qh));
++    term_qh->element = (u32)term_td;
++    term_qh->link = UHCI_PTR_TERM;
++
++    // Setup primary queue head.
++    memset(data_qh, 0, sizeof(*data_qh));
++    data_qh->element = UHCI_PTR_TERM;
++    data_qh->link = (u32)term_qh | UHCI_PTR_QH;
++    cntl->uhci.qh = data_qh;
++
++    // Set schedule to point to primary queue head
++    int i;
++    for (i=0; i<ARRAY_SIZE(fl->links); i++) {
++        fl->links[i] = (u32)data_qh | UHCI_PTR_QH;
++    }
++
++    // Set the frame length to the default: 1 ms exactly
++    outb(USBSOF_DEFAULT, cntl->uhci.iobase + USBSOF);
++
++    // Store the frame list base address
++    outl((u32)fl->links, cntl->uhci.iobase + USBFLBASEADD);
++
++    // Set the current frame number
++    outw(0, cntl->uhci.iobase + USBFRNUM);
++}
++
++static void
++start_uhci(struct usb_s *cntl)
++{
++    // Mark as configured and running with a 64-byte max packet.
++    outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, cntl->uhci.iobase + USBCMD);
++}
++
++// Find any devices connected to the root hub.
++static int
++check_ports(struct usb_s *cntl)
++{
++    u16 port1 = inw(cntl->uhci.iobase + USBPORTSC1);
++    u16 port2 = inw(cntl->uhci.iobase + USBPORTSC2);
++
++    if (!((port1 & USBPORTSC_CCS) || (port2 & USBPORTSC_CCS)))
++        // No devices
++        return 0;
++
++    // reset ports
++    if (port1 & USBPORTSC_CCS)
++        outw(USBPORTSC_PR, cntl->uhci.iobase + USBPORTSC1);
++    if (port2 & USBPORTSC_CCS)
++        outw(USBPORTSC_PR, cntl->uhci.iobase + USBPORTSC2);
++    msleep(50);
++    outw(0, cntl->uhci.iobase + USBPORTSC1);
++    outw(0, cntl->uhci.iobase + USBPORTSC2);
++    msleep(10);
++
++    // Configure ports
++    int totalcount = 0;
++    port1 = inw(cntl->uhci.iobase + USBPORTSC1);
++    if (port1 & USBPORTSC_CCS) {
++        outw(USBPORTSC_PE, cntl->uhci.iobase + USBPORTSC1);
++        int count = configure_usb_device(cntl, !!(port1 & USBPORTSC_LSDA));
++        if (! count)
++            outw(0, cntl->uhci.iobase + USBPORTSC1);
++        totalcount += count;
++    }
++    port2 = inw(cntl->uhci.iobase + USBPORTSC2);
++    if (port2 & USBPORTSC_CCS) {
++        outw(USBPORTSC_PE, cntl->uhci.iobase + USBPORTSC2);
++        int count = configure_usb_device(cntl, !!(port2 & USBPORTSC_LSDA));
++        if (! count)
++            outw(0, cntl->uhci.iobase + USBPORTSC2);
++        totalcount += count;
++    }
++    return totalcount;
++}
++
++void
++uhci_init(void *data)
++{
++    if (! CONFIG_USB_UHCI)
++        return;
++    struct usb_s *cntl = data;
++
++    // XXX - don't call pci_config_XXX from a thread
++    cntl->type = USB_TYPE_UHCI;
++    cntl->uhci.iobase = (pci_config_readl(cntl->bdf, PCI_BASE_ADDRESS_4)
++                         & PCI_BASE_ADDRESS_IO_MASK);
++
++    dprintf(3, "UHCI init on dev %02x:%02x.%x (io=%x)\n"
++            , pci_bdf_to_bus(cntl->bdf), pci_bdf_to_dev(cntl->bdf)
++            , pci_bdf_to_fn(cntl->bdf), cntl->uhci.iobase);
++
++    pci_config_maskw(cntl->bdf, PCI_COMMAND, 0, PCI_COMMAND_MASTER);
++
++    reset_uhci(cntl);
++    configure_uhci(cntl);
++    start_uhci(cntl);
++
++    int count = check_ports(cntl);
++    if (! count) {
++        // XXX - no devices; free data structures.
++    }
++}
++
++static int
++wait_qh(struct usb_s *cntl, struct uhci_qh *qh)
++{
++    // XXX - 500ms just a guess
++    u64 end = calc_future_tsc(500);
++    for (;;) {
++        if (qh->element & UHCI_PTR_TERM)
++            return 0;
++        if (check_time(end)) {
++            struct uhci_td *td = (void*)(qh->element & ~UHCI_PTR_BITS);
++            dprintf(1, "Timeout on wait_qh %p (td=%p s=%x c=%x/%x)\n"
++                    , qh, td, td->status
++                    , inw(cntl->uhci.iobase + USBCMD)
++                    , inw(cntl->uhci.iobase + USBSTS));
++            return -1;
++        }
++        yield();
++    }
++}
++
++int
++uhci_control(u32 endp, int dir, const void *cmd, int cmdsize
++             , void *data, int datasize)
++{
++    if (! CONFIG_USB_UHCI)
++        return -1;
++
++    dprintf(5, "uhci_control %x\n", endp);
++    struct usb_s *cntl = endp2cntl(endp);
++    int maxpacket = endp2maxsize(endp);
++    int lowspeed = endp2speed(endp);
++    int devaddr = endp2devaddr(endp) | (endp2ep(endp) << 7);
++
++    // Setup transfer descriptors
++    int count = 2 + DIV_ROUND_UP(datasize, maxpacket);
++    struct uhci_td *tds = malloc_tmphigh(sizeof(*tds) * count);
++
++    tds[0].link = (u32)&tds[1] | UHCI_PTR_DEPTH;
++    tds[0].status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0)
++                     | TD_CTRL_ACTIVE);
++    tds[0].token = (uhci_explen(cmdsize) | (devaddr << TD_TOKEN_DEVADDR_SHIFT)
++                    | USB_PID_SETUP);
++    tds[0].buffer = (void*)cmd;
++    int toggle = TD_TOKEN_TOGGLE;
++    int i;
++    for (i=1; i<count-1; i++) {
++        tds[i].link = (u32)&tds[i+1] | UHCI_PTR_DEPTH;
++        tds[i].status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0)
++                         | TD_CTRL_ACTIVE);
++        int len = (i == count-2 ? (datasize - (i-1)*maxpacket) : maxpacket);
++        tds[i].token = (uhci_explen(len) | toggle
++                        | (devaddr << TD_TOKEN_DEVADDR_SHIFT)
++                        | (dir ? USB_PID_IN : USB_PID_OUT));
++        tds[i].buffer = data + (i-1) * maxpacket;
++        toggle ^= TD_TOKEN_TOGGLE;
++    }
++    tds[i].link = UHCI_PTR_TERM;
++    tds[i].status = (uhci_maxerr(0) | (lowspeed ? TD_CTRL_LS : 0)
++                     | TD_CTRL_ACTIVE);
++    tds[i].token = (uhci_explen(0) | TD_TOKEN_TOGGLE
++                    | (devaddr << TD_TOKEN_DEVADDR_SHIFT)
++                    | (dir ? USB_PID_OUT : USB_PID_IN));
++    tds[i].buffer = 0;
++
++    // Transfer data
++    struct uhci_qh *data_qh = cntl->uhci.qh;
++    data_qh->element = (u32)&tds[0];
++    int ret = wait_qh(cntl, data_qh);
++    if (ret) {
++        data_qh->element = UHCI_PTR_TERM;
++        // XXX - leak tds
++        return ret;
++    }
++    free(tds);
++    return 0;
++}
++
++struct usb_pipe *
++uhci_alloc_intr_pipe(u32 endp, int period)
++{
++    if (! CONFIG_USB_UHCI)
++        return NULL;
++
++    dprintf(7, "uhci_alloc_intr_pipe %x %d\n", endp, period);
++    struct usb_s *cntl = endp2cntl(endp);
++    int maxpacket = endp2maxsize(endp);
++    int lowspeed = endp2speed(endp);
++    int devaddr = endp2devaddr(endp) | (endp2ep(endp) << 7);
++    // XXX - just grab 20 for now.
++    int count = 20;
++    struct uhci_qh *qh = malloc_low(sizeof(*qh));
++    struct uhci_td *tds = malloc_low(sizeof(*tds) * count);
++    if (!qh || !tds)
++        return NULL;
++    if (maxpacket > sizeof(tds[0].data))
++        // XXX - free qh/tds
++        return NULL;
++
++    qh->element = (u32)tds;
++    int toggle = 0;
++    int i;
++    for (i=0; i<count; i++) {
++        tds[i].link = (i==count-1 ? (u32)&tds[0] : (u32)&tds[i+1]);
++        tds[i].status = (uhci_maxerr(3) | (lowspeed ? TD_CTRL_LS : 0)
++                         | TD_CTRL_ACTIVE);
++        tds[i].token = (uhci_explen(maxpacket) | toggle
++                        | (devaddr << TD_TOKEN_DEVADDR_SHIFT)
++                        | USB_PID_IN);
++        tds[i].buffer = &tds[i].data;
++        toggle ^= TD_TOKEN_TOGGLE;
++    }
++
++    qh->next_td = &tds[0];
++    qh->pipe.endp = endp;
++
++    // XXX - need schedule - just add to primary list for now.
++    struct uhci_qh *data_qh = cntl->uhci.qh;
++    qh->link = data_qh->link;
++    data_qh->link = (u32)qh | UHCI_PTR_QH;
++
++    return &qh->pipe;
++}
++
++int
++uhci_poll_intr(struct usb_pipe *pipe, void *data)
++{
++    ASSERT16();
++    if (! CONFIG_USB_UHCI)
++        return -1;
++
++    struct uhci_qh *qh = container_of(pipe, struct uhci_qh, pipe);
++    struct uhci_td *td = GET_FLATPTR(qh->next_td);
++    u32 status = GET_FLATPTR(td->status);
++    u32 token = GET_FLATPTR(td->token);
++    if (status & TD_CTRL_ACTIVE)
++        // No intrs found.
++        return -1;
++    // XXX - check for errors.
++
++    // Copy data.
++    memcpy_far(GET_SEG(SS), data
++               , FLATPTR_TO_SEG(td->data), (void*)FLATPTR_TO_OFFSET(td->data)
++               , uhci_expected_length(token));
++
++    // Reenable this td.
++    u32 next = GET_FLATPTR(td->link);
++    SET_FLATPTR(td->status, (uhci_maxerr(0) | (status & TD_CTRL_LS)
++                             | TD_CTRL_ACTIVE));
++    SET_FLATPTR(qh->next_td, (void*)(next & ~UHCI_PTR_BITS));
++
++    return 0;
++}
+--- x/roms/seabios/src/usb-uhci.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/usb-uhci.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,133 @@
++#ifndef __USB_UHCI_H
++#define __USB_UHCI_H
++
++#include "usb.h" // struct usb_pipe
++
++// usb-uhci.c
++struct usb_s;
++void uhci_init(void *data);
++int uhci_control(u32 endp, int dir, const void *cmd, int cmdsize
++                 , void *data, int datasize);
++struct usb_pipe *uhci_alloc_intr_pipe(u32 endp, int period);
++int uhci_poll_intr(struct usb_pipe *pipe, void *data);
++
++
++/****************************************************************
++ * uhci structs and flags
++ ****************************************************************/
++
++/* USB port status and control registers */
++#define USBPORTSC1      16
++#define USBPORTSC2      18
++#define   USBPORTSC_CCS         0x0001  /* Current Connect Status
++                                         * ("device present") */
++#define   USBPORTSC_CSC         0x0002  /* Connect Status Change */
++#define   USBPORTSC_PE          0x0004  /* Port Enable */
++#define   USBPORTSC_PEC         0x0008  /* Port Enable Change */
++#define   USBPORTSC_DPLUS       0x0010  /* D+ high (line status) */
++#define   USBPORTSC_DMINUS      0x0020  /* D- high (line status) */
++#define   USBPORTSC_RD          0x0040  /* Resume Detect */
++#define   USBPORTSC_RES1        0x0080  /* reserved, always 1 */
++#define   USBPORTSC_LSDA        0x0100  /* Low Speed Device Attached */
++#define   USBPORTSC_PR          0x0200  /* Port Reset */
++
++/* Legacy support register */
++#define USBLEGSUP               0xc0
++#define   USBLEGSUP_RWC         0x8f00  /* the R/WC bits */
++
++/* Command register */
++#define USBCMD          0
++#define   USBCMD_RS             0x0001  /* Run/Stop */
++#define   USBCMD_HCRESET        0x0002  /* Host reset */
++#define   USBCMD_GRESET         0x0004  /* Global reset */
++#define   USBCMD_EGSM           0x0008  /* Global Suspend Mode */
++#define   USBCMD_FGR            0x0010  /* Force Global Resume */
++#define   USBCMD_SWDBG          0x0020  /* SW Debug mode */
++#define   USBCMD_CF             0x0040  /* Config Flag (sw only) */
++#define   USBCMD_MAXP           0x0080  /* Max Packet (0 = 32, 1 = 64) */
++
++/* Status register */
++#define USBSTS          2
++#define   USBSTS_USBINT         0x0001  /* Interrupt due to IOC */
++#define   USBSTS_ERROR          0x0002  /* Interrupt due to error */
++#define   USBSTS_RD             0x0004  /* Resume Detect */
++#define   USBSTS_HSE            0x0008  /* Host System Error: PCI problems */
++#define   USBSTS_HCPE           0x0010  /* Host Controller Process Error:
++                                         * the schedule is buggy */
++#define   USBSTS_HCH            0x0020  /* HC Halted */
++
++/* Interrupt enable register */
++#define USBINTR         4
++#define   USBINTR_TIMEOUT       0x0001  /* Timeout/CRC error enable */
++#define   USBINTR_RESUME        0x0002  /* Resume interrupt enable */
++#define   USBINTR_IOC           0x0004  /* Interrupt On Complete enable */
++#define   USBINTR_SP            0x0008  /* Short packet interrupt enable */
++
++#define USBFRNUM        6
++#define USBFLBASEADD    8
++#define USBSOF          12
++#define   USBSOF_DEFAULT        64      /* Frame length is exactly 1 ms */
++
++struct uhci_framelist {
++    u32 links[1024];
++} PACKED;
++
++#define TD_CTRL_SPD             (1 << 29)       /* Short Packet Detect */
++#define TD_CTRL_C_ERR_MASK      (3 << 27)       /* Error Counter bits */
++#define TD_CTRL_C_ERR_SHIFT     27
++#define TD_CTRL_LS              (1 << 26)       /* Low Speed Device */
++#define TD_CTRL_IOS             (1 << 25)       /* Isochronous Select */
++#define TD_CTRL_IOC             (1 << 24)       /* Interrupt on Complete */
++#define TD_CTRL_ACTIVE          (1 << 23)       /* TD Active */
++#define TD_CTRL_STALLED         (1 << 22)       /* TD Stalled */
++#define TD_CTRL_DBUFERR         (1 << 21)       /* Data Buffer Error */
++#define TD_CTRL_BABBLE          (1 << 20)       /* Babble Detected */
++#define TD_CTRL_NAK             (1 << 19)       /* NAK Received */
++#define TD_CTRL_CRCTIMEO        (1 << 18)       /* CRC/Time Out Error */
++#define TD_CTRL_BITSTUFF        (1 << 17)       /* Bit Stuff Error */
++#define TD_CTRL_ACTLEN_MASK     0x7FF   /* actual length, encoded as n - 1 */
++
++#define TD_CTRL_ANY_ERROR       (TD_CTRL_STALLED | TD_CTRL_DBUFERR | \
++                                 TD_CTRL_BABBLE | TD_CTRL_CRCTIME | \
++                                 TD_CTRL_BITSTUFF)
++#define uhci_maxerr(err)                ((err) << TD_CTRL_C_ERR_SHIFT)
++
++#define TD_TOKEN_DEVADDR_SHIFT  8
++#define TD_TOKEN_TOGGLE_SHIFT   19
++#define TD_TOKEN_TOGGLE         (1 << 19)
++#define TD_TOKEN_EXPLEN_SHIFT   21
++#define TD_TOKEN_EXPLEN_MASK    0x7FF   /* expected length, encoded as n-1 */
++#define TD_TOKEN_PID_MASK       0xFF
++
++#define uhci_explen(len)        ((((len) - 1) & TD_TOKEN_EXPLEN_MASK) << \
++                                        TD_TOKEN_EXPLEN_SHIFT)
++
++#define uhci_expected_length(token) ((((token) >> TD_TOKEN_EXPLEN_SHIFT) + \
++                                        1) & TD_TOKEN_EXPLEN_MASK)
++
++struct uhci_td {
++    u32 link;
++    u32 status;
++    u32 token;
++    void *buffer;
++
++    // Software fields
++    u32 data[4];
++} PACKED;
++
++struct uhci_qh {
++    u32 link;
++    u32 element;
++
++    // Software fields
++    struct uhci_td *next_td;
++    struct usb_pipe pipe;
++} PACKED;
++
++#define UHCI_PTR_BITS           0x000F
++#define UHCI_PTR_TERM           0x0001
++#define UHCI_PTR_QH             0x0002
++#define UHCI_PTR_DEPTH          0x0004
++#define UHCI_PTR_BREADTH        0x0000
++
++#endif // usb-uhci.h
+--- x/roms/seabios/src/usb.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/usb.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,230 @@
++// Main code for handling USB controllers and devices.
++//
++// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "util.h" // dprintf
++#include "pci.h" // foreachpci
++#include "config.h" // CONFIG_*
++#include "pci_regs.h" // PCI_CLASS_REVISION
++#include "pci_ids.h" // PCI_CLASS_SERIAL_USB_UHCI
++#include "usb-uhci.h" // uhci_init
++#include "usb-ohci.h" // ohci_init
++#include "usb-hid.h" // usb_keyboard_setup
++#include "usb.h" // struct usb_s
++#include "biosvar.h" // GET_GLOBAL
++
++struct usb_s USBControllers[16] VAR16VISIBLE;
++
++static int
++send_control(u32 endp, int dir, const void *cmd, int cmdsize
++             , void *data, int datasize)
++{
++    struct usb_s *cntl = endp2cntl(endp);
++    switch (cntl->type) {
++    default:
++    case USB_TYPE_UHCI:
++        return uhci_control(endp, dir, cmd, cmdsize, data, datasize);
++    case USB_TYPE_OHCI:
++        return ohci_control(endp, dir, cmd, cmdsize, data, datasize);
++    }
++}
++
++struct usb_pipe *
++alloc_intr_pipe(u32 endp, int period)
++{
++    struct usb_s *cntl = endp2cntl(endp);
++    switch (cntl->type) {
++    default:
++    case USB_TYPE_UHCI:
++        return uhci_alloc_intr_pipe(endp, period);
++    case USB_TYPE_OHCI:
++        return ohci_alloc_intr_pipe(endp, period);
++    }
++}
++
++int
++usb_poll_intr(struct usb_pipe *pipe, void *data)
++{
++    u32 endp = GET_FLATPTR(pipe->endp);
++    struct usb_s *cntl = endp2cntl(endp);
++    switch (GET_GLOBAL(cntl->type)) {
++    default:
++    case USB_TYPE_UHCI:
++        return uhci_poll_intr(pipe, data);
++    case USB_TYPE_OHCI:
++        return ohci_poll_intr(pipe, data);
++    }
++}
++
++int
++send_default_control(u32 endp, const struct usb_ctrlrequest *req, void *data)
++{
++    return send_control(endp, req->bRequestType & USB_DIR_IN
++                        , req, sizeof(*req), data, req->wLength);
++}
++
++// Get the first 8 bytes of the device descriptor.
++static int
++get_device_info8(struct usb_device_descriptor *dinfo, u32 endp)
++{
++    struct usb_ctrlrequest req;
++    req.bRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
++    req.bRequest = USB_REQ_GET_DESCRIPTOR;
++    req.wValue = USB_DT_DEVICE<<8;
++    req.wIndex = 0;
++    req.wLength = 8;
++    return send_default_control(endp, &req, dinfo);
++}
++
++static struct usb_config_descriptor *
++get_device_config(u32 endp)
++{
++    struct usb_config_descriptor cfg;
++
++    struct usb_ctrlrequest req;
++    req.bRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
++    req.bRequest = USB_REQ_GET_DESCRIPTOR;
++    req.wValue = USB_DT_CONFIG<<8;
++    req.wIndex = 0;
++    req.wLength = sizeof(cfg);
++    int ret = send_default_control(endp, &req, &cfg);
++    if (ret)
++        return NULL;
++
++    void *config = malloc_tmphigh(cfg.wTotalLength);
++    if (!config)
++        return NULL;
++    req.wLength = cfg.wTotalLength;
++    ret = send_default_control(endp, &req, config);
++    if (ret)
++        return NULL;
++    //hexdump(config, cfg.wTotalLength);
++    return config;
++}
++
++static u32
++set_address(u32 endp)
++{
++    dprintf(3, "set_address %x\n", endp);
++    struct usb_s *cntl = endp2cntl(endp);
++    if (cntl->maxaddr >= USB_MAXADDR)
++        return 0;
++
++    struct usb_ctrlrequest req;
++    req.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
++    req.bRequest = USB_REQ_SET_ADDRESS;
++    req.wValue = cntl->maxaddr + 1;
++    req.wIndex = 0;
++    req.wLength = 0;
++    int ret = send_default_control(endp, &req, NULL);
++    if (ret)
++        return 0;
++    msleep(2);
++
++    cntl->maxaddr++;
++    return mkendp(cntl, cntl->maxaddr, 0, endp2speed(endp), endp2maxsize(endp));
++}
++
++static int
++set_configuration(u32 endp, u16 val)
++{
++    struct usb_ctrlrequest req;
++    req.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
++    req.bRequest = USB_REQ_SET_CONFIGURATION;
++    req.wValue = val;
++    req.wIndex = 0;
++    req.wLength = 0;
++    return send_default_control(endp, &req, NULL);
++}
++
++// Called for every found device - see if a driver is available for
++// this device and do setup if so.
++int
++configure_usb_device(struct usb_s *cntl, int lowspeed)
++{
++    dprintf(1, "config_usb: %p %d\n", cntl, lowspeed);
++
++    // Get device info
++    u32 endp = mkendp(cntl, 0, 0, lowspeed, 8);
++    struct usb_device_descriptor dinfo;
++    int ret = get_device_info8(&dinfo, endp);
++    if (ret)
++        return 0;
++    dprintf(3, "device rev=%04x cls=%02x sub=%02x proto=%02x size=%02x\n"
++            , dinfo.bcdUSB, dinfo.bDeviceClass, dinfo.bDeviceSubClass
++            , dinfo.bDeviceProtocol, dinfo.bMaxPacketSize0);
++    if (dinfo.bMaxPacketSize0 < 8 || dinfo.bMaxPacketSize0 > 64)
++        return 0;
++    endp = mkendp(cntl, 0, 0, lowspeed, dinfo.bMaxPacketSize0);
++
++    // Get configuration
++    struct usb_config_descriptor *config = get_device_config(endp);
++    if (!config)
++        return 0;
++
++    // Determine if a driver exists for this device - only look at the
++    // first interface of the first configuration.
++    struct usb_interface_descriptor *iface = (void*)(&config[1]);
++    if (iface->bInterfaceClass != USB_CLASS_HID
++        || iface->bInterfaceSubClass != USB_INTERFACE_SUBCLASS_BOOT
++        || iface->bInterfaceProtocol != USB_INTERFACE_PROTOCOL_KEYBOARD)
++        // Not a "boot" keyboard
++        goto fail;
++
++    // Set the address and configure device.
++    endp = set_address(endp);
++    if (!endp)
++        goto fail;
++    ret = set_configuration(endp, config->bConfigurationValue);
++    if (ret)
++        goto fail;
++
++    // Configure driver.
++    ret = usb_keyboard_init(endp, iface, ((void*)config + config->wTotalLength
++                                          - (void*)iface));
++    if (ret)
++        goto fail;
++
++    free(config);
++    return 1;
++fail:
++    free(config);
++    return 0;
++}
++
++void
++usb_setup(void)
++{
++    if (! CONFIG_USB)
++        return;
++
++    dprintf(3, "init usb\n");
++
++    usb_keyboard_setup();
++
++    // Look for USB controllers
++    int count = 0;
++    int bdf, max;
++    foreachpci(bdf, max) {
++        u32 code = pci_config_readl(bdf, PCI_CLASS_REVISION) >> 8;
++
++        if (code >> 8 != PCI_CLASS_SERIAL_USB)
++            continue;
++
++        struct usb_s *cntl = &USBControllers[count];
++        cntl->bdf = bdf;
++
++        if (code == PCI_CLASS_SERIAL_USB_UHCI)
++            run_thread(uhci_init, cntl);
++        else if (code == PCI_CLASS_SERIAL_USB_OHCI)
++            run_thread(ohci_init, cntl);
++        else
++            continue;
++
++        count++;
++        if (count >= ARRAY_SIZE(USBControllers))
++            break;
++    }
++}
+--- x/roms/seabios/src/usb.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/usb.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,198 @@
++// USB functions and data.
++#ifndef __USB_H
++#define __USB_H
++
++// Local information for a usb controller.
++struct usb_s {
++    u8 type;
++    u8 maxaddr;
++    u16 bdf;
++
++    union {
++        struct {
++            u16 iobase;
++            void *qh;
++        } uhci;
++        struct {
++            struct ohci_regs *regs;
++            void *control_ed;
++        } ohci;
++    };
++};
++
++#define USB_TYPE_UHCI 1
++#define USB_TYPE_OHCI 2
++
++extern struct usb_s USBControllers[];
++
++struct usb_pipe {
++    u32 endp;
++};
++
++#define USB_MAXADDR 127
++
++// usb.c
++void usb_setup(void);
++int configure_usb_device(struct usb_s *cntl, int lowspeed);
++struct usb_ctrlrequest;
++int send_default_control(u32 endp, const struct usb_ctrlrequest *req
++                         , void *data);
++struct usb_pipe *alloc_intr_pipe(u32 endp, int period);
++int usb_poll_intr(struct usb_pipe *pipe, void *data);
++
++
++/****************************************************************
++ * endpoint definition
++ ****************************************************************/
++
++static inline u32
++mkendp(struct usb_s *cntl, u8 devaddr, u8 ep, u8 lowspeed, u8 maxsize)
++{
++    u8 bus = cntl-USBControllers;
++    u8 size = __ffs(maxsize);
++    return (size<<25) | (lowspeed<<24) | (bus<<16) | (devaddr<<8) | ep;
++}
++
++static inline u8 endp2ep(u32 endp) {
++    return endp;
++}
++static inline u8 endp2devaddr(u32 endp) {
++    return endp>>8;
++}
++static inline struct usb_s *endp2cntl(u32 endp) {
++    u8 bus = endp>>16;
++    return &USBControllers[bus];
++}
++static inline u8 endp2speed(u32 endp) {
++    return (endp>>24) & 1;
++}
++static inline u8 endp2maxsize(u32 endp) {
++    return 1 << (endp>>25);
++}
++
++
++/****************************************************************
++ * usb structs and flags
++ ****************************************************************/
++
++#define USB_PID_OUT                     0xe1
++#define USB_PID_IN                      0x69
++#define USB_PID_SETUP                   0x2d
++
++#define USB_DIR_OUT                     0               /* to device */
++#define USB_DIR_IN                      0x80            /* to host */
++
++#define USB_TYPE_MASK                   (0x03 << 5)
++#define USB_TYPE_STANDARD               (0x00 << 5)
++#define USB_TYPE_CLASS                  (0x01 << 5)
++#define USB_TYPE_VENDOR                 (0x02 << 5)
++#define USB_TYPE_RESERVED               (0x03 << 5)
++
++#define USB_RECIP_MASK                  0x1f
++#define USB_RECIP_DEVICE                0x00
++#define USB_RECIP_INTERFACE             0x01
++#define USB_RECIP_ENDPOINT              0x02
++#define USB_RECIP_OTHER                 0x03
++
++#define USB_REQ_GET_STATUS              0x00
++#define USB_REQ_CLEAR_FEATURE           0x01
++#define USB_REQ_SET_FEATURE             0x03
++#define USB_REQ_SET_ADDRESS             0x05
++#define USB_REQ_GET_DESCRIPTOR          0x06
++#define USB_REQ_SET_DESCRIPTOR          0x07
++#define USB_REQ_GET_CONFIGURATION       0x08
++#define USB_REQ_SET_CONFIGURATION       0x09
++#define USB_REQ_GET_INTERFACE           0x0A
++#define USB_REQ_SET_INTERFACE           0x0B
++#define USB_REQ_SYNCH_FRAME             0x0C
++
++struct usb_ctrlrequest {
++    u8 bRequestType;
++    u8 bRequest;
++    u16 wValue;
++    u16 wIndex;
++    u16 wLength;
++} PACKED;
++
++#define USB_DT_DEVICE                   0x01
++#define USB_DT_CONFIG                   0x02
++#define USB_DT_STRING                   0x03
++#define USB_DT_INTERFACE                0x04
++#define USB_DT_ENDPOINT                 0x05
++#define USB_DT_DEVICE_QUALIFIER         0x06
++#define USB_DT_OTHER_SPEED_CONFIG       0x07
++
++struct usb_device_descriptor {
++    u8  bLength;
++    u8  bDescriptorType;
++
++    u16 bcdUSB;
++    u8  bDeviceClass;
++    u8  bDeviceSubClass;
++    u8  bDeviceProtocol;
++    u8  bMaxPacketSize0;
++    u16 idVendor;
++    u16 idProduct;
++    u16 bcdDevice;
++    u8  iManufacturer;
++    u8  iProduct;
++    u8  iSerialNumber;
++    u8  bNumConfigurations;
++} PACKED;
++
++#define USB_CLASS_PER_INTERFACE         0       /* for DeviceClass */
++#define USB_CLASS_AUDIO                 1
++#define USB_CLASS_COMM                  2
++#define USB_CLASS_HID                   3
++#define USB_CLASS_PHYSICAL              5
++#define USB_CLASS_STILL_IMAGE           6
++#define USB_CLASS_PRINTER               7
++#define USB_CLASS_MASS_STORAGE          8
++#define USB_CLASS_HUB                   9
++
++struct usb_config_descriptor {
++    u8  bLength;
++    u8  bDescriptorType;
++
++    u16 wTotalLength;
++    u8  bNumInterfaces;
++    u8  bConfigurationValue;
++    u8  iConfiguration;
++    u8  bmAttributes;
++    u8  bMaxPower;
++} PACKED;
++
++struct usb_interface_descriptor {
++    u8  bLength;
++    u8  bDescriptorType;
++
++    u8  bInterfaceNumber;
++    u8  bAlternateSetting;
++    u8  bNumEndpoints;
++    u8  bInterfaceClass;
++    u8  bInterfaceSubClass;
++    u8  bInterfaceProtocol;
++    u8  iInterface;
++} PACKED;
++
++struct usb_endpoint_descriptor {
++    u8  bLength;
++    u8  bDescriptorType;
++
++    u8  bEndpointAddress;
++    u8  bmAttributes;
++    u16 wMaxPacketSize;
++    u8  bInterval;
++} PACKED;
++
++#define USB_ENDPOINT_NUMBER_MASK        0x0f    /* in bEndpointAddress */
++#define USB_ENDPOINT_DIR_MASK           0x80
++
++#define USB_ENDPOINT_XFERTYPE_MASK      0x03    /* in bmAttributes */
++#define USB_ENDPOINT_XFER_CONTROL       0
++#define USB_ENDPOINT_XFER_ISOC          1
++#define USB_ENDPOINT_XFER_BULK          2
++#define USB_ENDPOINT_XFER_INT           3
++#define USB_ENDPOINT_MAX_ADJUSTABLE     0x80
++
++#endif // usb.h
+--- x/roms/seabios/src/util.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/util.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,324 @@
++// Misc utility functions.
++//
++// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "util.h" // call16
++#include "bregs.h" // struct bregs
++#include "config.h" // BUILD_STACK_ADDR
++
++
++/****************************************************************
++ * 16bit calls
++ ****************************************************************/
++
++// Call a function with a specified register state.  Note that on
++// return, the interrupt enable/disable flag may be altered.
++inline void
++call16(struct bregs *callregs)
++{
++    if (!MODESEGMENT && getesp() > BUILD_STACK_ADDR)
++        panic("call16 with invalid stack\n");
++    asm volatile(
++#if MODE16 == 1
++        "calll __call16\n"
++        "cli\n"
++        "cld"
++#else
++        "calll __call16_from32"
++#endif
++        : "+a" (callregs), "+m" (*callregs)
++        :
++        : "ebx", "ecx", "edx", "esi", "edi", "cc", "memory");
++}
++
++inline void
++call16big(struct bregs *callregs)
++{
++    ASSERT32FLAT();
++    if (getesp() > BUILD_STACK_ADDR)
++        panic("call16 with invalid stack\n");
++    asm volatile(
++        "calll __call16big_from32"
++        : "+a" (callregs), "+m" (*callregs)
++        :
++        : "ebx", "ecx", "edx", "esi", "edi", "cc", "memory");
++}
++
++inline void
++__call16_int(struct bregs *callregs, u16 offset)
++{
++    if (MODESEGMENT)
++        callregs->code.seg = GET_SEG(CS);
++    else
++        callregs->code.seg = SEG_BIOS;
++    callregs->code.offset = offset;
++    call16(callregs);
++}
++
++// 16bit trampoline for enabling irqs from 32bit mode.
++ASM16(
++    "  .global trampoline_checkirqs\n"
++    "trampoline_checkirqs:\n"
++    "  rep ; nop\n"
++    "  lretw"
++    );
++
++void
++check_irqs(void)
++{
++    if (MODE16) {
++        asm volatile(
++            "sti\n"
++            "nop\n"
++            "rep ; nop\n"
++            "cli\n"
++            "cld\n"
++            : : :"memory");
++    } else {
++        extern void trampoline_checkirqs();
++        struct bregs br;
++        br.flags = F_IF;
++        br.code.seg = SEG_BIOS;
++        br.code.offset = (u32)&trampoline_checkirqs;
++        call16big(&br);
++    }
++}
++
++
++/****************************************************************
++ * String ops
++ ****************************************************************/
++
++// Sum the bytes in the specified area.
++u8
++checksum_far(u16 buf_seg, void *buf_far, u32 len)
++{
++    SET_SEG(ES, buf_seg);
++    u32 i;
++    u8 sum = 0;
++    for (i=0; i<len; i++)
++        sum += GET_VAR(ES, ((u8*)buf_far)[i]);
++    return sum;
++}
++
++u8
++checksum(void *buf, u32 len)
++{
++    return checksum_far(GET_SEG(SS), buf, len);
++}
++
++size_t
++strlen(const char *s)
++{
++    if (__builtin_constant_p(s))
++        return __builtin_strlen(s);
++    const char *p = s;
++    while (*p)
++        p++;
++    return p-s;
++}
++
++// Compare two areas of memory.
++int
++memcmp(const void *s1, const void *s2, size_t n)
++{
++    while (n) {
++        if (*(u8*)s1 != *(u8*)s2)
++            return *(u8*)s1 < *(u8*)s2 ? -1 : 1;
++        s1++;
++        s2++;
++        n--;
++    }
++    return 0;
++}
++
++// Compare two strings.
++int
++strcmp(const char *s1, const char *s2)
++{
++    for (;;) {
++        if (*s1 != *s2)
++            return *s1 < *s2 ? -1 : 1;
++        if (! *s1)
++            return 0;
++        s1++;
++        s2++;
++    }
++}
++
++inline void
++memset_far(u16 d_seg, void *d_far, u8 c, size_t len)
++{
++    SET_SEG(ES, d_seg);
++    asm volatile(
++        "rep stosb %%es:(%%di)"
++        : "+c"(len), "+D"(d_far)
++        : "a"(c)
++        : "cc", "memory");
++}
++
++inline void
++memset16_far(u16 d_seg, void *d_far, u16 c, size_t len)
++{
++    len /= 2;
++    SET_SEG(ES, d_seg);
++    asm volatile(
++        "rep stosw %%es:(%%di)"
++        : "+c"(len), "+D"(d_far)
++        : "a"(c)
++        : "cc", "memory");
++}
++
++void *
++memset(void *s, int c, size_t n)
++{
++    while (n)
++        ((char *)s)[--n] = c;
++    return s;
++}
++
++inline void
++memcpy_far(u16 d_seg, void *d_far, u16 s_seg, const void *s_far, size_t len)
++{
++    SET_SEG(ES, d_seg);
++    u16 bkup_ds;
++    asm volatile(
++        "movw %%ds, %w0\n"
++        "movw %w4, %%ds\n"
++        "rep movsb (%%si),%%es:(%%di)\n"
++        "movw %w0, %%ds"
++        : "=&r"(bkup_ds), "+c"(len), "+S"(s_far), "+D"(d_far)
++        : "r"(s_seg)
++        : "cc", "memory");
++}
++
++void *
++#undef memcpy
++memcpy(void *d1, const void *s1, size_t len)
++#if MODESEGMENT == 0
++#define memcpy __builtin_memcpy
++#endif
++{
++    SET_SEG(ES, GET_SEG(SS));
++    void *d = d1;
++    if (((u32)d1 | (u32)s1 | len) & 3) {
++        // non-aligned memcpy
++        asm volatile(
++            "rep movsb (%%esi),%%es:(%%edi)"
++            : "+c"(len), "+S"(s1), "+D"(d)
++            : : "cc", "memory");
++        return d1;
++    }
++    // Common case - use 4-byte copy
++    len /= 4;
++    asm volatile(
++        "rep movsl (%%esi),%%es:(%%edi)"
++        : "+c"(len), "+S"(s1), "+D"(d)
++        : : "cc", "memory");
++    return d1;
++}
++
++// Copy from memory mapped IO.  IO mem is very slow, so yield
++// periodically.  'len' must be 4 byte aligned.
++void
++iomemcpy(void *d, const void *s, u32 len)
++{
++    yield();
++    while (len) {
++        u32 copylen = len;
++        if (copylen > 2048)
++            copylen = 2048;
++        len -= copylen;
++        copylen /= 4;
++        asm volatile(
++            "rep movsl (%%esi),%%es:(%%edi)"
++            : "+c"(copylen), "+S"(s), "+D"(d)
++            : : "cc", "memory");
++        yield();
++    }
++}
++
++void *
++memmove(void *d, const void *s, size_t len)
++{
++    if (s >= d)
++        return memcpy(d, s, len);
++
++    d += len-1;
++    s += len-1;
++    while (len--) {
++        *(char*)d = *(char*)s;
++        d--;
++        s--;
++    }
++
++    return d;
++}
++
++// Copy a string - truncating it if necessary.
++char *
++strtcpy(char *dest, const char *src, size_t len)
++{
++    char *d = dest;
++    while (len-- && *src != '\0')
++        *d++ = *src++;
++    *d = '\0';
++    return dest;
++}
++
++
++/****************************************************************
++ * Keyboard calls
++ ****************************************************************/
++
++// Wait for 'usec' microseconds using (with irqs enabled) using int 1586.
++void
++biosusleep(u32 usec)
++{
++    struct bregs br;
++    memset(&br, 0, sizeof(br));
++    br.flags = F_IF;
++    br.ah = 0x86;
++    br.cx = usec >> 16;
++    br.dx = usec;
++    call16_int(0x15, &br);
++}
++
++// See if a keystroke is pending in the keyboard buffer.
++static int
++check_for_keystroke(void)
++{
++    struct bregs br;
++    memset(&br, 0, sizeof(br));
++    br.flags = F_IF;
++    br.ah = 1;
++    call16_int(0x16, &br);
++    return !(br.flags & F_ZF);
++}
++
++// Return a keystroke - waiting forever if necessary.
++static int
++get_raw_keystroke(void)
++{
++    struct bregs br;
++    memset(&br, 0, sizeof(br));
++    br.flags = F_IF;
++    call16_int(0x16, &br);
++    return br.ah;
++}
++
++// Read a keystroke - waiting up to 'msec' milliseconds.
++int
++get_keystroke(int msec)
++{
++    for (;;) {
++        if (check_for_keystroke())
++            return get_raw_keystroke();
++        if (msec <= 0)
++            return -1;
++        biosusleep(50*1000);
++        msec -= 50;
++    }
++}
+--- x/roms/seabios/src/util.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/util.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,377 @@
++// Basic x86 asm functions and function defs.
++//
++// Copyright (C) 2008,2009  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++#ifndef __UTIL_H
++#define __UTIL_H
++
++#include "types.h" // u32
++
++static inline void irq_disable(void)
++{
++    asm volatile("cli": : :"memory");
++}
++
++static inline void irq_enable(void)
++{
++    asm volatile("sti": : :"memory");
++}
++
++static inline unsigned long irq_save(void)
++{
++    unsigned long flags;
++    asm volatile("pushfl ; popl %0" : "=g" (flags));
++    irq_disable();
++    return flags;
++}
++
++static inline void irq_restore(unsigned long flags)
++{
++    asm volatile("pushl %0 ; popfl" : : "g" (flags) : "memory", "cc");
++}
++
++static inline void cpu_relax(void)
++{
++    asm volatile("rep ; nop": : :"memory");
++}
++
++// Atomically enable irqs and sleep until an irq; then re-disable irqs.
++static inline void wait_irq(void)
++{
++    asm volatile("sti ; hlt ; cli ; cld": : :"memory");
++}
++
++static inline void nop(void)
++{
++    asm volatile("nop");
++}
++
++static inline void hlt(void)
++{
++    asm volatile("hlt");
++}
++
++static inline void wbinvd(void)
++{
++    asm volatile("wbinvd");
++}
++
++#define CPUID_MSR (1 << 5)
++#define CPUID_APIC (1 << 9)
++#define CPUID_MTRR (1 << 12)
++static inline void cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
++{
++    asm("cpuid"
++        : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
++        : "0" (index));
++}
++
++static inline u64 rdmsr(u32 index)
++{
++    u64 ret;
++    asm ("rdmsr" : "=A"(ret) : "c"(index));
++    return ret;
++}
++
++static inline void wrmsr(u32 index, u64 val)
++{
++    asm volatile ("wrmsr" : : "c"(index), "A"(val));
++}
++
++static inline u64 rdtscll(void)
++{
++    u64 val;
++    asm volatile("rdtsc" : "=A" (val));
++    return val;
++}
++
++static inline u32 __ffs(u32 word)
++{
++    asm("bsf %1,%0"
++        : "=r" (word)
++        : "rm" (word));
++    return word;
++}
++static inline u32 __fls(u32 word)
++{
++    asm("bsr %1,%0"
++        : "=r" (word)
++        : "rm" (word));
++    return word;
++}
++
++static inline u32 getesp(void) {
++    u32 esp;
++    asm("movl %%esp, %0" : "=rm"(esp));
++    return esp;
++}
++
++static inline void writel(void *addr, u32 val) {
++    *(volatile u32 *)addr = val;
++}
++static inline void writew(void *addr, u16 val) {
++    *(volatile u16 *)addr = val;
++}
++static inline void writeb(void *addr, u8 val) {
++    *(volatile u8 *)addr = val;
++}
++static inline u32 readl(const void *addr) {
++    return *(volatile const u32 *)addr;
++}
++static inline u16 readw(const void *addr) {
++    return *(volatile const u16 *)addr;
++}
++static inline u8 readb(const void *addr) {
++    return *(volatile const u8 *)addr;
++}
++
++#define call16_simpint(nr, peax, pflags) do {                           \
++        ASSERT16();                                                     \
++        asm volatile(                                                   \
++            "stc\n"                                                     \
++            "int %2\n"                                                  \
++            "pushfl\n"                                                  \
++            "popl %1\n"                                                 \
++            "cli\n"                                                     \
++            "cld"                                                       \
++            : "+a"(*peax), "=r"(*pflags)                                \
++            : "i"(nr)                                                   \
++            : "cc", "memory");                                          \
++    } while (0)
++
++// GDT bit manipulation
++#define GDT_BASE(v)  ((((u64)(v) & 0xff000000) << 32)           \
++                      | (((u64)(v) & 0x00ffffff) << 16))
++#define GDT_LIMIT(v) ((((u64)(v) & 0x000f0000) << 32)   \
++                      | (((u64)(v) & 0x0000ffff) << 0))
++#define GDT_CODE     (0x9bULL << 40) // Code segment - P,R,A bits also set
++#define GDT_DATA     (0x93ULL << 40) // Data segment - W,A bits also set
++#define GDT_B        (0x1ULL << 54)  // Big flag
++#define GDT_G        (0x1ULL << 55)  // Granularity flag
++
++struct descloc_s {
++    u16 length;
++    u32 addr;
++} PACKED;
++
++// util.c
++struct bregs;
++inline void call16(struct bregs *callregs);
++inline void call16big(struct bregs *callregs);
++inline void __call16_int(struct bregs *callregs, u16 offset);
++#define call16_int(nr, callregs) do {                           \
++        extern void irq_trampoline_ ##nr ();                    \
++        __call16_int((callregs), (u32)&irq_trampoline_ ##nr );  \
++    } while (0)
++void check_irqs(void);
++u8 checksum_far(u16 buf_seg, void *buf_far, u32 len);
++u8 checksum(void *buf, u32 len);
++size_t strlen(const char *s);
++int memcmp(const void *s1, const void *s2, size_t n);
++int strcmp(const char *s1, const char *s2);
++inline void memset_far(u16 d_seg, void *d_far, u8 c, size_t len);
++inline void memset16_far(u16 d_seg, void *d_far, u16 c, size_t len);
++void *memset(void *s, int c, size_t n);
++inline void memcpy_far(u16 d_seg, void *d_far
++                       , u16 s_seg, const void *s_far, size_t len);
++void *memcpy(void *d1, const void *s1, size_t len);
++#if MODESEGMENT == 0
++#define memcpy __builtin_memcpy
++#endif
++void iomemcpy(void *d, const void *s, u32 len);
++void *memmove(void *d, const void *s, size_t len);
++char *strtcpy(char *dest, const char *src, size_t len);
++void biosusleep(u32 usec);
++int get_keystroke(int msec);
++
++// stacks.c
++inline u32 stack_hop(u32 eax, u32 edx, u32 ecx, void *func);
++extern struct thread_info MainThread;
++void thread_setup(void);
++struct thread_info *getCurThread(void);
++void yield(void);
++void run_thread(void (*func)(void*), void *data);
++void wait_threads(void);
++void start_preempt(void);
++void finish_preempt(void);
++void check_preempt(void);
++
++// output.c
++void debug_serial_setup(void);
++void panic(const char *fmt, ...)
++    __attribute__ ((format (printf, 1, 2))) __noreturn;
++void printf(const char *fmt, ...)
++    __attribute__ ((format (printf, 1, 2)));
++void __dprintf(const char *fmt, ...)
++    __attribute__ ((format (printf, 1, 2)));
++int snprintf(char *str, size_t size, const char *fmt, ...)
++    __attribute__ ((format (printf, 3, 4)));
++#define dprintf(lvl, fmt, args...) do {                         \
++        if (CONFIG_DEBUG_LEVEL && (lvl) <= CONFIG_DEBUG_LEVEL)  \
++            __dprintf((fmt) , ##args );                         \
++    } while (0)
++void __debug_enter(struct bregs *regs, const char *fname);
++void __debug_stub(struct bregs *regs, int lineno, const char *fname);
++void __debug_isr(const char *fname);
++#define debug_enter(regs, lvl) do {                     \
++        if ((lvl) && (lvl) <= CONFIG_DEBUG_LEVEL)       \
++            __debug_enter((regs), __func__);            \
++    } while (0)
++#define debug_isr(lvl) do {                             \
++        if ((lvl) && (lvl) <= CONFIG_DEBUG_LEVEL)       \
++            __debug_isr(__func__);                      \
++    } while (0)
++#define debug_stub(regs)                        \
++    __debug_stub((regs), __LINE__, __func__)
++void hexdump(const void *d, int len);
++
++// kbd.c
++void kbd_setup(void);
++void handle_15c2(struct bregs *regs);
++void process_key(u8 key);
++
++// mouse.c
++void mouse_setup(void);
++void process_mouse(u8 data);
++
++// system.c
++extern u32 RamSize;
++extern u64 RamSizeOver4G;
++void mathcp_setup(void);
++
++// serial.c
++void serial_setup(void);
++void lpt_setup(void);
++
++// clock.c
++static inline int check_time(u64 end) {
++    return (s64)(rdtscll() - end) > 0;
++}
++void timer_setup(void);
++void ndelay(u32 count);
++void udelay(u32 count);
++void mdelay(u32 count);
++void nsleep(u32 count);
++void usleep(u32 count);
++void msleep(u32 count);
++u64 calc_future_tsc(u32 msecs);
++u64 calc_future_tsc_usec(u32 usecs);
++void handle_1583(struct bregs *regs);
++void handle_1586(struct bregs *regs);
++void useRTC(void);
++void releaseRTC(void);
++
++// apm.c
++void handle_1553(struct bregs *regs);
++
++// pcibios.c
++void handle_1ab1(struct bregs *regs);
++void bios32_setup(void);
++
++// shadow.c
++void make_bios_writable(void);
++void make_bios_readonly(void);
++
++// pciinit.c
++void pci_setup(void);
++
++// smm.c
++void smm_init(void);
++
++// smp.c
++extern u32 CountCPUs;
++extern u32 MaxCountCPUs;
++void wrmsr_smp(u32 index, u64 val);
++void smp_probe(void);
++void smp_probe_setup(void);
++
++// coreboot.c
++struct cbfs_file;
++struct cbfs_file *cbfs_findprefix(const char *prefix, struct cbfs_file *last);
++u32 cbfs_datasize(struct cbfs_file *file);
++const char *cbfs_filename(struct cbfs_file *file);
++int cbfs_copyfile(struct cbfs_file *file, void *dst, u32 maxlen);
++int cbfs_copy_optionrom(void *dst, u32 maxlen, u32 vendev);
++void cbfs_run_payload(struct cbfs_file *file);
++
++void coreboot_copy_biostable(void);
++void coreboot_setup(void);
++
++// vgahooks.c
++extern int VGAbdf;
++void handle_155f(struct bregs *regs);
++void vgahook_setup(const char *vendor, const char *part);
++
++// optionroms.c
++void call_bcv(u16 seg, u16 ip);
++void optionrom_setup(void);
++void vga_setup(void);
++void s3_resume_vga_init(void);
++extern u32 RomEnd;
++
++// resume.c
++void init_dma(void);
++
++// pnpbios.c
++#define PNP_SIGNATURE 0x506e5024 // $PnP
++u16 get_pnp_offset(void);
++void pnp_setup(void);
++
++// pmm.c
++extern struct zone_s ZoneLow, ZoneHigh, ZoneFSeg, ZoneTmpLow, ZoneTmpHigh;
++void malloc_setup(void);
++void malloc_finalize(void);
++void *pmm_malloc(struct zone_s *zone, u32 handle, u32 size, u32 align);
++int pmm_free(void *data);
++void pmm_setup(void);
++void pmm_finalize(void);
++#define PMM_DEFAULT_HANDLE 0xFFFFFFFF
++// Minimum alignment of malloc'd memory
++#define MALLOC_MIN_ALIGN 16
++// Helper functions for memory allocation.
++static inline void *malloc_low(u32 size) {
++    return pmm_malloc(&ZoneLow, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN);
++}
++static inline void *malloc_high(u32 size) {
++    return pmm_malloc(&ZoneHigh, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN);
++}
++static inline void *malloc_fseg(u32 size) {
++    return pmm_malloc(&ZoneFSeg, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN);
++}
++static inline void *malloc_tmphigh(u32 size) {
++    return pmm_malloc(&ZoneTmpHigh, PMM_DEFAULT_HANDLE, size, MALLOC_MIN_ALIGN);
++}
++static inline void *memalign_low(u32 align, u32 size) {
++    return pmm_malloc(&ZoneLow, PMM_DEFAULT_HANDLE, size, align);
++}
++static inline void *memalign_high(u32 align, u32 size) {
++    return pmm_malloc(&ZoneHigh, PMM_DEFAULT_HANDLE, size, align);
++}
++static inline void *memalign_tmphigh(u32 align, u32 size) {
++    return pmm_malloc(&ZoneTmpHigh, PMM_DEFAULT_HANDLE, size, align);
++}
++static inline void free(void *data) {
++    pmm_free(data);
++}
++
++// mtrr.c
++void mtrr_setup(void);
++
++// romlayout.S
++void reset_vector(void) __noreturn;
++
++// misc.c
++extern u8 BiosChecksum;
++
++// version (auto generated file out/version.c)
++extern const char VERSION[];
++
++// XXX - optimize
++#define ntohl(x) ((((x)&0xff)<<24) | (((x)&0xff00)<<8) | \
++                  (((x)&0xff0000) >> 8) | (((x)&0xff000000) >> 24))
++#define htonl(x) ntohl(x)
++#define ntohs(x) ((((x)&0xff)<<8) | (((x)&0xff00)>>8))
++#define htons(x) ntohs(x)
++
++#endif // util.h
+--- x/roms/seabios/src/vgahooks.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/src/vgahooks.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,193 @@
++// Hooks for via vgabios calls into main bios.
++//
++// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "bregs.h" // set_code_invalid
++#include "biosvar.h" // GET_GLOBAL
++#include "pci.h" // pci_find_device
++#include "pci_regs.h" // PCI_VENDOR_ID
++#include "pci_ids.h" // PCI_VENDOR_ID_VIA
++#include "util.h" // handle_155f
++#include "config.h" // CONFIG_*
++
++// The Bus/Dev/Fn of the primary VGA device.
++int VGAbdf VAR16VISIBLE;
++// Coreboot board detected.
++int CBmainboard VAR16VISIBLE;
++
++static void
++handle_155fXX(struct bregs *regs)
++{
++    set_code_unimplemented(regs, RET_EUNSUPPORTED);
++}
++
++
++/****************************************************************
++ * Via hooks
++ ****************************************************************/
++
++static void
++via_155f01(struct bregs *regs)
++{
++    regs->eax = 0x5f;
++    regs->cl = 2; // panel type =  2 = 1024 * 768
++    set_success(regs);
++    dprintf(1, "Warning: VGA panel type is hardcoded\n");
++}
++
++static void
++via_155f02(struct bregs *regs)
++{
++    regs->eax = 0x5f;
++    regs->bx = 2;
++    regs->cx = 0x401;  // PAL + crt only
++    regs->dx = 0;  // TV Layout - default
++    set_success(regs);
++    dprintf(1, "Warning: VGA TV/CRT output type is hardcoded\n");
++}
++
++static int
++getFBSize(u16 bdf)
++{
++    /* FB config */
++    u8 reg = pci_config_readb(bdf, 0xa1);
++
++    /* GFX disabled ? */
++    if (!(reg & 0x80))
++        return -1;
++
++    static u8 mem_power[] VAR16 = {0, 3, 4, 5, 6, 7, 8, 9};
++    return GET_GLOBAL(mem_power[(reg >> 4) & 0x7]);
++}
++
++static int
++getViaRamSpeed(u16 bdf)
++{
++    return (pci_config_readb(bdf, 0x90) & 0x07) + 3;
++}
++
++static int
++getAMDRamSpeed(void)
++{
++    int bdf = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MEMCTL);
++    if (bdf < 0)
++        return -1;
++
++    /* mem clk 0 = DDR2 400 */
++    return (pci_config_readb(bdf, 0x94) & 0x7) + 6;
++}
++
++/* int 0x15 - 5f18
++
++   ECX = unknown/dont care
++   EBX[3..0] Frame Buffer Size 2^N MiB
++   EBX[7..4] Memory speed:
++       0: SDR  66Mhz
++       1: SDR 100Mhz
++       2: SDR 133Mhz
++       3: DDR 100Mhz (PC1600 or DDR200)
++       4: DDR 133Mhz (PC2100 or DDR266)
++       5: DDR 166Mhz (PC2700 or DDR333)
++       6: DDR 200Mhz (PC3200 or DDR400)
++       7: DDR2 133Mhz (DDR2 533)
++       8: DDR2 166Mhz (DDR2 667)
++       9: DDR2 200Mhz (DDR2 800)
++       A: DDR2 233Mhz (DDR2 1066)
++       B: and above: Unknown
++   EBX[?..8] Total memory size?
++   EAX = 0x5f for success
++*/
++
++#define PCI_DEVICE_ID_VIA_K8M890CE_3    0x3336
++#define PCI_DEVICE_ID_VIA_VX855_MEMCTRL 0x3409
++
++static void
++via_155f18(struct bregs *regs)
++{
++    int ramspeed, fbsize;
++
++    int bdf = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_K8M890CE_3);
++    if (bdf >= 0) {
++        fbsize = getFBSize(bdf);
++        ramspeed = getAMDRamSpeed();
++        goto done;
++    }
++    bdf = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855_MEMCTRL);
++    if (bdf >= 0) {
++        fbsize = getFBSize(bdf);
++        ramspeed = getViaRamSpeed(bdf);
++        goto done;
++    }
++
++    dprintf(1, "Warning: VGA memory size and speed is hardcoded\n");
++    fbsize = 5; // 32M frame buffer
++    ramspeed = 4; // MCLK = DDR266
++
++done:
++    if (fbsize < 0 || ramspeed < 0) {
++        set_code_invalid(regs, RET_EUNSUPPORTED);
++        return;
++    }
++    regs->eax = 0x5f;
++    regs->ebx = 0x500 | (ramspeed << 4) | fbsize;
++    regs->ecx = 0x060;
++    set_success(regs);
++}
++
++static void
++via_155f19(struct bregs *regs)
++{
++    set_invalid_silent(regs);
++}
++
++static void
++via_155f(struct bregs *regs)
++{
++    switch (regs->al) {
++    case 0x01: via_155f01(regs); break;
++    case 0x02: via_155f02(regs); break;
++    case 0x18: via_155f18(regs); break;
++    case 0x19: via_155f19(regs); break;
++    default:   handle_155fXX(regs); break;
++    }
++}
++
++
++/****************************************************************
++ * Entry and setup
++ ****************************************************************/
++
++// Main 16bit entry point
++void
++handle_155f(struct bregs *regs)
++{
++    if (! CONFIG_VGAHOOKS)
++        goto fail;
++
++    // XXX - Use this value later.
++    //int cbmb = GET_GLOBAL(CBmainboard);
++
++    int bdf = GET_GLOBAL(VGAbdf);
++    if (bdf < 0)
++        goto fail;
++    u16 vendor = pci_config_readw(bdf, PCI_VENDOR_ID);
++    if (vendor == PCI_VENDOR_ID_VIA) {
++        via_155f(regs);
++        return;
++    }
++
++fail:
++    handle_155fXX(regs);
++}
++
++// Setup
++void
++vgahook_setup(const char *vendor, const char *part)
++{
++    if (! CONFIG_VGAHOOKS)
++        return;
++    // XXX - add support later.
++    CBmainboard = 0;
++}
+--- x/roms/seabios/tools/buildrom.py	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/tools/buildrom.py	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,43 @@
++#!/usr/bin/env python
++# Fill in checksum/size of an option rom, and pad it to proper length.
++#
++# Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
++#
++# This file may be distributed under the terms of the GNU GPLv3 license.
++
++import sys
++
++def alignpos(pos, alignbytes):
++    mask = alignbytes - 1
++    return (pos + mask) & ~mask
++
++def checksum(data):
++    ords = map(ord, data)
++    return sum(ords)
++
++def main():
++    inname = sys.argv[1]
++    outname = sys.argv[2]
++
++    # Read data in
++    f = open(inname, 'rb')
++    data = f.read()
++    count = len(data)
++
++    # Pad to a 512 byte boundary
++    data += "\0" * (alignpos(count, 512) - count)
++    count = len(data)
++
++    # Fill in size field; clear checksum field
++    data = data[:2] + chr(count/512) + data[3:6] + "\0" + data[7:]
++
++    # Checksum rom
++    newsum = (256 - checksum(data)) & 0xff
++    data = data[:6] + chr(newsum) + data[7:]
++
++    # Write new rom
++    f = open(outname, 'wb')
++    f.write(data)
++
++if __name__ == '__main__':
++    main()
+--- x/roms/seabios/tools/checkrom.py	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/tools/checkrom.py	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,68 @@
++#!/usr/bin/env python
++# Script to check a bios image and report info on it.
++#
++# Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
++#
++# This file may be distributed under the terms of the GNU GPLv3 license.
++
++import sys
++import layoutrom
++
++def main():
++    # Get args
++    objinfo, rawfile, outfile = sys.argv[1:]
++
++    # Read in symbols
++    objinfofile = open(objinfo, 'rb')
++    symbols = layoutrom.parseObjDump(objinfofile)[1]
++    syms = {}
++    for name, (addr, section) in symbols.items():
++        syms[name] = addr
++
++    # Read in raw file
++    f = open(rawfile, 'rb')
++    rawdata = f.read()
++    f.close()
++    datasize = len(rawdata)
++    finalsize = 64*1024
++    if datasize > 64*1024:
++        finalsize = 128*1024
++
++    # Sanity checks
++    c16e = syms['text16_end'] + 0xf0000
++    f16e = syms['final_text16_end']
++    if c16e != f16e:
++        print "Error!  16bit code moved during linking (0x%x vs 0x%x)" % (
++            c16e, f16e)
++        sys.exit(1)
++    if datasize > finalsize:
++        print "Error!  Code is too big (0x%x vs 0x%x)" % (
++            datasize, finalsize)
++        sys.exit(1)
++    actualdatasize = f16e - syms['code32flat_start']
++    if datasize != actualdatasize:
++        print "Error!  Unknown extra data (0x%x vs 0x%x)" % (
++            datasize, actualdatasize)
++        sys.exit(1)
++
++    # Print statistics
++    sizefree = syms['freespace_end'] - syms['freespace_start']
++    size16 = syms['text16_end'] - syms['data16_start']
++    size32seg = syms['code32seg_end'] - syms['code32seg_start']
++    size32flat = syms['code32flat_end'] - syms['code32flat_start']
++    totalc = size16+size32seg+size32flat
++    print "16bit size:           %d" % size16
++    print "32bit segmented size: %d" % size32seg
++    print "32bit flat size:      %d" % size32flat
++    print "Total size: %d  Free space: %d  Percent used: %.1f%% (%dKiB rom)" % (
++        totalc, sizefree + finalsize - datasize
++        , (totalc / float(finalsize)) * 100.0
++        , finalsize / 1024)
++
++    # Write final file
++    f = open(outfile, 'wb')
++    f.write(("\0" * (finalsize - datasize)) + rawdata)
++    f.close()
++
++if __name__ == '__main__':
++    main()
+--- x/roms/seabios/tools/checkstack.py	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/tools/checkstack.py	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,147 @@
++#!/usr/bin/env python
++# Script that tries to find how much stack space each function in an
++# object is using.
++#
++# Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
++#
++# This file may be distributed under the terms of the GNU GPLv3 license.
++
++# Usage:
++#   objdump -m i386 -M i8086 -M suffix -d out/rom16.reloc.o | tools/checkstack.py
++
++import sys
++import re
++
++# List of functions we can assume are never called.
++#IGNORE = ['panic', '__dprintf', '__send_disk_op']
++IGNORE = ['panic', '__send_disk_op']
++
++# Find out maximum stack usage for a function
++def calcmaxstack(funcs, funcaddr):
++    info = funcs[funcaddr]
++    # Find max of all nested calls.
++    max = info[1]
++    info[2] = max
++    for insnaddr, calladdr, usage in info[3]:
++        callinfo = funcs[calladdr]
++        if callinfo[2] is None:
++            calcmaxstack(funcs, calladdr)
++        if callinfo[0].split('.')[0] in IGNORE:
++            # This called function is ignored - don't contribute it to
++            # the max stack.
++            continue
++        totusage = usage + callinfo[2]
++        if totusage > max:
++            max = totusage
++    info[2] = max
++
++hex_s = r'[0-9a-f]+'
++re_func = re.compile(r'^(?P<funcaddr>' + hex_s + r') <(?P<func>.*)>:$')
++re_asm = re.compile(
++    r'^[ ]*(?P<insnaddr>' + hex_s
++    + r'):\t.*\t(addr32 )?(?P<insn>.+?)[ ]*((?P<calladdr>' + hex_s
++    + r') <(?P<ref>.*)>)?$')
++re_usestack = re.compile(
++    r'^(push[f]?[lw])|(sub.* [$](?P<num>0x' + hex_s + r'),%esp)$')
++
++def calc():
++    # funcs[funcaddr] = [funcname, basicstackusage, maxstackusage
++    #                    , [(addr, callfname, stackusage), ...]]
++    funcs = {-1: ['<indirect>', 0, 0, []]}
++    cur = None
++    atstart = 0
++    stackusage = 0
++
++    # Parse input lines
++    for line in sys.stdin.readlines():
++        m = re_func.match(line)
++        if m is not None:
++            # Found function
++            funcaddr = int(m.group('funcaddr'), 16)
++            funcs[funcaddr] = cur = [m.group('func'), 0, None, []]
++            stackusage = 0
++            atstart = 1
++            subfuncs = {}
++            continue
++        m = re_asm.match(line)
++        if m is not None:
++            insn = m.group('insn')
++
++            im = re_usestack.match(insn)
++            if im is not None:
++                if insn[:5] == 'pushl' or insn[:6] == 'pushfl':
++                    stackusage += 4
++                    continue
++                elif insn[:5] == 'pushw' or insn[:6] == 'pushfw':
++                    stackusage += 2
++                    continue
++                stackusage += int(im.group('num'), 16)
++
++            if atstart:
++                if insn == 'movl   %esp,%ebp':
++                    # Still part of initial header
++                    continue
++                cur[1] = stackusage
++                atstart = 0
++
++            calladdr = m.group('calladdr')
++            if calladdr is None:
++                if insn[:6] == 'lcallw':
++                    stackusage += 4
++                    calladdr = -1
++                else:
++                    # misc instruction - just ignore
++                    continue
++            else:
++                # Jump or call insn
++                calladdr = int(calladdr, 16)
++                ref = m.group('ref')
++                if '+' in ref:
++                    # Inter-function jump - reset stack usage to
++                    # preamble usage
++                    stackusage = cur[1]
++                    continue
++                if insn[:1] == 'j':
++                    # Tail call
++                    stackusage = 0
++                elif insn[:5] == 'calll':
++                    stackusage += 4
++                else:
++                    print "unknown call", ref
++            if (calladdr, stackusage) not in subfuncs:
++                cur[3].append((m.group('insnaddr'), calladdr, stackusage))
++                subfuncs[(calladdr, stackusage)] = 1
++            # Reset stack usage to preamble usage
++            stackusage = cur[1]
++
++            continue
++
++        #print "other", repr(line)
++
++    # Calculate maxstackusage
++    bynames = {}
++    for funcaddr, info in funcs.items():
++        bynames[info[0]] = info
++        if info[2] is not None:
++            continue
++        calcmaxstack(funcs, funcaddr)
++
++    # Show all functions
++    funcnames = bynames.keys()
++    funcnames.sort()
++    for funcname in funcnames:
++        name, basicusage, maxusage, calls = bynames[funcname]
++        if maxusage == 0:
++            continue
++        print "\n%s[%d,%d]:" % (funcname, basicusage, maxusage)
++        for insnaddr, calladdr, stackusage in calls:
++            callinfo = funcs[calladdr]
++            print "    %04s:%-40s [%d+%d,%d]" % (
++                insnaddr, callinfo[0], stackusage, callinfo[1]
++                , stackusage+callinfo[2])
++
++def main():
++    calc()
++
++if __name__ == '__main__':
++    main()
+--- x/roms/seabios/tools/checksum.py	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/tools/checksum.py	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,16 @@
++#!/usr/bin/env python
++# Script to report the checksum of a file.
++#
++# Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
++#
++# This file may be distributed under the terms of the GNU GPLv3 license.
++
++import sys
++
++def main():
++    data = sys.stdin.read()
++    ords = map(ord, data)
++    print "sum=%x\n" % sum(ords)
++
++if __name__ == '__main__':
++    main()
+--- x/roms/seabios/tools/gen-offsets.sh	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/tools/gen-offsets.sh	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,17 @@
++:
++# Extract definitions from an assembler file.  This is based on code
++# from the Linux Kernel.
++INFILE=$1
++OUTFILE=$2
++cat > "$OUTFILE" <<EOF
++// This is an auto-generated file.  DO NOT EDIT!
++// Generated with "$0 $@"
++#ifndef __ASM_OFFSETS_H
++#define __ASM_OFFSETS_H
++EOF
++sed -ne "/^->/{s:->#\(.*\):/* \1 */:; \
++        s:^->\([^ ]*\) [\$\#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \
++        s:->::; p;}" < "$INFILE" >> "$OUTFILE"
++cat >> "$OUTFILE" <<EOF
++#endif // asm-offsets.h
++EOF
+--- x/roms/seabios/tools/layoutrom.py	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/tools/layoutrom.py	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,399 @@
++#!/usr/bin/env python
++# Script to analyze code and arrange ld sections.
++#
++# Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
++#
++# This file may be distributed under the terms of the GNU GPLv3 license.
++
++import sys
++
++# Align 'pos' to 'alignbytes' offset
++def alignpos(pos, alignbytes):
++    mask = alignbytes - 1
++    return (pos + mask) & ~mask
++
++# LD script headers/trailers
++COMMONHEADER = """
++/* DO NOT EDIT!  This is an autogenerated file.  See tools/layoutrom.py. */
++OUTPUT_FORMAT("elf32-i386")
++OUTPUT_ARCH("i386")
++SECTIONS
++{
++"""
++COMMONTRAILER = """
++}
++"""
++
++
++######################################################################
++# 16bit fixed address section fitting
++######################################################################
++
++# Get the maximum start position for a list of sections that end at an
++# address.
++def getSectionsStart(sections, endaddr, minalign=1):
++    totspace = 0
++    for size, align, name in sections:
++        if align > minalign:
++            minalign = align
++        totspace = alignpos(totspace, align) + size
++    return (endaddr - totspace) / minalign * minalign
++
++# Write LD script includes for the given sections
++def outSections(file, sections):
++    for size, align, name in sections:
++        file.write("*(%s)\n" % (name,))
++
++# The 16bit code can't exceed 64K of space.
++MAXPOS = 64*1024
++
++# Layout the 16bit code.  This ensures sections with fixed offset
++# requirements are placed in the correct location.  It also places the
++# 16bit code as high as possible in the f-segment.
++def doLayout16(sections, outname):
++    textsections = []
++    rodatasections = []
++    datasections = []
++    # fixedsections = [(addr, sectioninfo, extasectionslist), ...]
++    fixedsections = []
++    # canrelocate = [(sectioninfo, list), ...]
++    canrelocate = []
++
++    # Find desired sections.
++    for section in sections:
++        size, align, name = section
++        if name[:11] == '.fixedaddr.':
++            addr = int(name[11:], 16)
++            fixedsections.append((addr, section, []))
++            if align != 1:
++                print "Error: Fixed section %s has non-zero alignment (%d)" % (
++                    name, align)
++                sys.exit(1)
++        if name[:6] == '.text.':
++            textsections.append(section)
++            canrelocate.append((section, textsections))
++        if name[:17] == '.rodata.__func__.' or name == '.rodata.str1.1':
++            rodatasections.append(section)
++            #canrelocate.append((section, rodatasections))
++        if name[:8] == '.data16.':
++            datasections.append(section)
++            #canrelocate.append((section, datasections))
++
++    # Find freespace in fixed address area
++    fixedsections.sort()
++    # fixedAddr = [(freespace, sectioninfo), ...]
++    fixedAddr = []
++    for i in range(len(fixedsections)):
++        fixedsectioninfo = fixedsections[i]
++        addr, section, extrasectionslist = fixedsectioninfo
++        if i == len(fixedsections) - 1:
++            nextaddr = MAXPOS
++        else:
++            nextaddr = fixedsections[i+1][0]
++        avail = nextaddr - addr - section[0]
++        fixedAddr.append((avail, fixedsectioninfo))
++
++    # Attempt to fit other sections into fixed area
++    fixedAddr.sort()
++    canrelocate.sort()
++    totalused = 0
++    for freespace, fixedsectioninfo in fixedAddr:
++        fixedaddr, fixedsection, extrasections = fixedsectioninfo
++        addpos = fixedaddr + fixedsection[0]
++        totalused += fixedsection[0]
++        nextfixedaddr = addpos + freespace
++#        print "Filling section %x uses %d, next=%x, available=%d" % (
++#            fixedaddr, fixedsection[0], nextfixedaddr, freespace)
++        while 1:
++            canfit = None
++            for fixedaddrinfo in canrelocate:
++                fitsection, inlist = fixedaddrinfo
++                fitsize, fitalign, fitname = fitsection
++                if addpos + fitsize > nextfixedaddr:
++                    # Can't fit and nothing else will fit.
++                    break
++                fitnextaddr = alignpos(addpos, fitalign) + fitsize
++#                print "Test %s - %x vs %x" % (
++#                    fitname, fitnextaddr, nextfixedaddr)
++                if fitnextaddr > nextfixedaddr:
++                    # This item can't fit.
++                    continue
++                canfit = (fitnextaddr, fixedaddrinfo)
++            if canfit is None:
++                break
++            # Found a section that can fit.
++            fitnextaddr, fixedaddrinfo = canfit
++            canrelocate.remove(fixedaddrinfo)
++            fitsection, inlist = fixedaddrinfo
++            inlist.remove(fitsection)
++            extrasections.append(fitsection)
++            addpos = fitnextaddr
++            totalused += fitsection[0]
++#            print "    Adding %s (size %d align %d) pos=%x avail=%d" % (
++#                fitsection[2], fitsection[0], fitsection[1]
++#                , fitnextaddr, nextfixedaddr - fitnextaddr)
++    firstfixed = fixedsections[0][0]
++
++    # Report stats
++    total = MAXPOS-firstfixed
++    slack = total - totalused
++    print ("Fixed space: 0x%x-0x%x  total: %d  slack: %d"
++           "  Percent slack: %.1f%%" % (
++            firstfixed, MAXPOS, total, slack,
++            (float(slack) / total) * 100.0))
++
++    # Find start positions
++    text16_start = getSectionsStart(textsections, firstfixed)
++    data16_start = getSectionsStart(rodatasections + datasections, text16_start)
++
++    # Write header and regular sections
++    output = open(outname, 'wb')
++    output.write(COMMONHEADER + """
++        data16_start = 0x%x ;
++        .data16 data16_start : {
++""" % data16_start)
++    outSections(output, datasections)
++    output.write("code16_rodata = . ;\n")
++    outSections(output, rodatasections)
++    output.write("""
++        }
++
++        text16_start = 0x%x ;
++        .text16 text16_start : {
++""" % text16_start)
++    outSections(output, textsections)
++
++    # Write fixed sections
++    for addr, section, extrasections in fixedsections:
++        name = section[2]
++        output.write(". = ( 0x%x - text16_start ) ;\n" % (addr,))
++        output.write("*(%s)\n" % (name,))
++        for extrasection in extrasections:
++            output.write("*(%s)\n" % (extrasection[2],))
++
++    # Write trailer
++    output.write("""
++                text16_end = ABSOLUTE(.) ;
++        }
++
++        /* Discard regular data sections to force a link error if
++         * 16bit code attempts to access data not marked with VAR16
++         */
++        /DISCARD/ : { *(.text*) *(.rodata*) *(.data*) *(.bss*) *(COMMON) }
++""" + COMMONTRAILER)
++
++    return data16_start
++
++
++######################################################################
++# 32bit section outputting
++######################################################################
++
++# Return the subset of sections with a given name prefix
++def getSectionsPrefix(sections, prefix):
++    lp = len(prefix)
++    out = []
++    for size, align, name in sections:
++        if name[:lp] == prefix:
++            out.append((size, align, name))
++    return out
++
++# Layout the 32bit segmented code.  This places the code as high as possible.
++def doLayout32seg(sections, outname, endat):
++    # Find sections to output
++    textsections = getSectionsPrefix(sections, '.text.')
++    rodatasections = (getSectionsPrefix(sections, '.rodata.str1.1')
++                      + getSectionsPrefix(sections, '.rodata.__func__.'))
++    datasections = getSectionsPrefix(sections, '.data32seg.')
++    startat = getSectionsStart(
++        textsections + rodatasections + datasections, endat)
++
++    # Write sections
++    output = open(outname, 'wb')
++    output.write(COMMONHEADER + """
++        code32seg_start = 0x%x ;
++        .text32seg code32seg_start : {
++                freespace_end = . ;
++""" % startat)
++
++    outSections(output, textsections)
++    output.write("code32seg_rodata = . ;\n")
++    outSections(output, rodatasections)
++    outSections(output, datasections)
++
++    output.write("""
++                code32seg_end = ABSOLUTE(.) ;
++        }
++        /DISCARD/ : { *(.text*) *(.rodata*) *(.data*) *(.bss*) *(COMMON) }
++""" + COMMONTRAILER)
++    return startat
++
++# Layout the 32bit flat code.  This places the code as high as possible.
++def doLayout32flat(sections, outname, endat):
++    endat += 0xf0000
++    # Find sections to output
++    textsections = getSectionsPrefix(sections, '.text.')
++    rodatasections = getSectionsPrefix(sections, '.rodata')
++    datasections = getSectionsPrefix(sections, '.data.')
++    bsssections = getSectionsPrefix(sections, '.bss.')
++    startat = getSectionsStart(
++        textsections + rodatasections + datasections + bsssections, endat, 512)
++
++    # Write sections
++    output = open(outname, 'wb')
++    output.write(COMMONHEADER + """
++        code32flat_start = 0x%x ;
++        .text32flat code32flat_start : {
++""" % startat)
++
++    outSections(output, textsections)
++    output.write("code32_rodata = . ;\n")
++    outSections(output, rodatasections)
++    outSections(output, datasections)
++    outSections(output, bsssections)
++
++    output.write("""
++                freespace_start = . ;
++                code32flat_end = ABSOLUTE(.) ;
++        }
++""" + COMMONTRAILER)
++    return startat
++
++
++######################################################################
++# Section garbage collection
++######################################################################
++
++def getSectionsList(info, names):
++    out = []
++    for i in info[0]:
++        size, align, section = i
++        if section not in names:
++#            print "gc", section
++            continue
++        out.append(i)
++    return out
++
++# Find and keep the section associated with a symbol (if available).
++def keepsymbol(symbol, infos, pos):
++    addr, section = infos[pos][1].get(symbol, (None, None))
++    if section is None or '*' in section or section[:9] == '.discard.':
++        return -1
++    keepsection(section, infos, pos)
++    return 0
++
++# Note required section, and recursively set all referenced sections
++# as required.
++def keepsection(name, infos, pos=0):
++    if name in infos[pos][3]:
++        # Already kept - nothing to do.
++        return
++    infos[pos][3].append(name)
++    relocs = infos[pos][2].get(name)
++    if relocs is None:
++        return
++    # Keep all sections that this section points to
++    for symbol in relocs:
++        ret = keepsymbol(symbol, infos, pos)
++        if not ret:
++            continue
++        # Not in primary sections - it may be a cross 16/32 reference
++        ret = keepsymbol(symbol, infos, (pos+1)%3)
++        if not ret:
++            continue
++        ret = keepsymbol(symbol, infos, (pos+2)%3)
++        if not ret:
++            continue
++
++# Determine which sections are actually referenced and need to be
++# placed into the output file.
++def gc(info16, info32seg, info32flat):
++    # infos = ((sections, symbols, relocs, keep sections), ...)
++    infos = ((info16[0], info16[1], info16[2], []),
++             (info32seg[0], info32seg[1], info32seg[2], []),
++             (info32flat[0], info32flat[1], info32flat[2], []))
++    # Start by keeping sections that are globally visible.
++    for size, align, section in info16[0]:
++        if section[:11] == '.fixedaddr.' or '.export.' in section:
++            keepsection(section, infos)
++    # Return sections found.
++    sections16 = getSectionsList(info16, infos[0][3])
++    sections32seg = getSectionsList(info32seg, infos[1][3])
++    sections32flat = getSectionsList(info32flat, infos[2][3])
++    return sections16, sections32seg, sections32flat
++
++
++######################################################################
++# Startup and input parsing
++######################################################################
++
++# Read in output from objdump
++def parseObjDump(file):
++    # sections = [(size, align, section), ...]
++    sections = []
++    # symbols[symbol] = section
++    symbols = {}
++    # relocs[section] = [symbol, ...]
++    relocs = {}
++
++    state = None
++    for line in file.readlines():
++        line = line.rstrip()
++        if line == 'Sections:':
++            state = 'section'
++            continue
++        if line == 'SYMBOL TABLE:':
++            state = 'symbol'
++            continue
++        if line[:24] == 'RELOCATION RECORDS FOR [':
++            state = 'reloc'
++            relocsection = line[24:-2]
++            continue
++
++        if state == 'section':
++            try:
++                idx, name, size, vma, lma, fileoff, align = line.split()
++                if align[:3] != '2**':
++                    continue
++                sections.append((int(size, 16), 2**int(align[3:]), name))
++            except:
++                pass
++            continue
++        if state == 'symbol':
++            try:
++                section, off, symbol = line[17:].split()
++                off = int(off, 16)
++                addr = int(line[:8], 16)
++                symbols[symbol] = addr, section
++            except:
++                pass
++            continue
++        if state == 'reloc':
++            try:
++                off, type, symbol = line.split()
++                off = int(off, 16)
++                relocs.setdefault(relocsection, []).append(symbol)
++            except:
++                pass
++    return sections, symbols, relocs
++
++def main():
++    # Get output name
++    in16, in32seg, in32flat, out16, out32seg, out32flat = sys.argv[1:]
++
++    infile16 = open(in16, 'rb')
++    infile32seg = open(in32seg, 'rb')
++    infile32flat = open(in32flat, 'rb')
++
++    info16 = parseObjDump(infile16)
++    info32seg = parseObjDump(infile32seg)
++    info32flat = parseObjDump(infile32flat)
++
++    sections16, sections32seg, sections32flat = gc(info16, info32seg, info32flat)
++
++    start16 = doLayout16(sections16, out16)
++    start32seg = doLayout32seg(sections32seg, out32seg, start16)
++    doLayout32flat(sections32flat, out32flat, start32seg)
++
++if __name__ == '__main__':
++    main()
+--- x/roms/seabios/tools/readserial.py	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/tools/readserial.py	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,110 @@
++#!/usr/bin/env python
++# Script that can read from a serial device and show timestamps.
++#
++# Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
++#
++# This file may be distributed under the terms of the GNU GPLv3 license.
++
++# Usage:
++#   tools/readserial.py /dev/ttyUSB0 115200
++
++import sys
++import time
++import select
++import serial
++
++# Reset time counter after this much idle time.
++RESTARTINTERVAL = 60
++# Alter timing reports based on how much time would be spent writing
++# to serial.
++ADJUSTBAUD = 1
++# Number of bits in a transmitted byte - 8N1 is 1 start bit + 8 data
++# bits + 1 stop bit.
++BITSPERBYTE = 10
++
++def readserial(infile, logfile, baudrate):
++    lasttime = 0
++    byteadjust = 0.0
++    if ADJUSTBAUD:
++        byteadjust = float(BITSPERBYTE) / baudrate
++    while 1:
++        # Read data
++        try:
++            res = select.select([infile, sys.stdin], [], [])
++        except KeyboardInterrupt:
++            sys.stdout.write("\n")
++            break
++        if sys.stdin in res[0]:
++            # Got keyboard input - force reset on next serial input
++            sys.stdin.read(1)
++            lasttime = 0
++            if len(res[0]) == 1:
++                continue
++        d = infile.read(4096)
++        datatime = time.time()
++
++        datatime -= len(d) * byteadjust
++
++        # Reset start time if no data for some time
++        if datatime - lasttime > RESTARTINTERVAL:
++            starttime = datatime
++            charcount = 0
++            isnewline = 1
++            msg = "\n\n======= %s (adjust=%d)\n" % (
++                time.asctime(time.localtime(datatime)), ADJUSTBAUD)
++            sys.stdout.write(msg)
++            logfile.write(msg)
++        lasttime = datatime
++
++        # Translate unprintable chars; add timestamps
++        out = ""
++        for c in d:
++            if isnewline:
++                delta = datatime - starttime - (charcount * byteadjust)
++                out += "%06.3f: " % delta
++                isnewline = 0
++            oc = ord(c)
++            charcount += 1
++            datatime += byteadjust
++            if oc == 0x0d:
++                continue
++            if oc == 0x00:
++                out += "<00>\n"
++                isnewline = 1
++                continue
++            if oc == 0x0a:
++                out += "\n"
++                isnewline = 1
++                continue
++            if oc < 0x20 or oc >= 0x7f and oc != 0x09:
++                out += "<%02x>" % oc
++                continue
++            out += c
++
++        sys.stdout.write(out)
++        sys.stdout.flush()
++        logfile.write(out)
++        logfile.flush()
++
++def printUsage():
++    print "Usage:\n   %s [<serialdevice> [<baud>]]" % (sys.argv[0],)
++    sys.exit(1)
++
++def main():
++    serialport = 0
++    baud = 115200
++    if len(sys.argv) > 3:
++        printUsage()
++    if len(sys.argv) > 1:
++        serialport = sys.argv[1]
++    if len(sys.argv) > 2:
++        baud = int(sys.argv[2])
++
++    ser = serial.Serial(serialport, baud, timeout=0)
++
++    logname = time.strftime("seriallog-%Y%m%d_%H%M%S.log")
++    f = open(logname, 'wb')
++    readserial(ser, f, baud)
++
++if __name__ == '__main__':
++    main()
+--- x/roms/seabios/tools/test-gcc.sh	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/tools/test-gcc.sh	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,88 @@
++#!/bin/sh
++# Script to test if gcc "-fwhole-program" works properly.
++
++mkdir -p out
++TMPFILE1=out/tmp_testcompile1.c
++TMPFILE1o=out/tmp_testcompile1.o
++TMPFILE2=out/tmp_testcompile2.c
++TMPFILE2o=out/tmp_testcompile2.o
++TMPFILE3o=out/tmp_testcompile3.o
++
++# Test for "-fwhole-program".  Older versions of gcc (pre v4.1) don't
++# support the whole-program optimization - detect that.
++$CC -fwhole-program -S -o /dev/null -xc /dev/null > /dev/null 2>&1
++if [ $? -ne 0 ]; then
++    echo "  Working around no -fwhole-program" > /dev/fd/2
++    echo 2
++    exit 0
++fi
++
++# Test if "visible" variables and functions are marked global.  On
++# OpenSuse 10.3 "visible" variables declared with "extern" first
++# aren't marked as global in the resulting assembler.  On Ubuntu 7.10
++# "visible" functions aren't marked as global in the resulting
++# assembler.
++cat - > $TMPFILE1 <<EOF
++void __attribute__((externally_visible)) t1() { }
++extern unsigned char v1;
++unsigned char v1 __attribute__((section(".data16.foo.19"))) __attribute__((externally_visible));
++EOF
++$CC -Os -c -fwhole-program $TMPFILE1 -o $TMPFILE1o > /dev/null 2>&1
++cat - > $TMPFILE2 <<EOF
++void t1();
++extern unsigned char v1;
++int __attribute__((externally_visible)) main() { t1(); return v1; }
++EOF
++$CC -Os -c -fwhole-program $TMPFILE2 -o $TMPFILE2o > /dev/null 2>&1
++$CC -nostdlib -Os $TMPFILE1o $TMPFILE2o -o $TMPFILE3o > /dev/null 2>&1
++if [ $? -ne 0 ]; then
++    echo "  Working around non-functional -fwhole-program" > /dev/fd/2
++    echo 2
++    exit 0
++fi
++
++# Test if "-combine" works.  On Ubuntu 8.04 the compiler doesn't work
++# correctly with combine and the "struct bregs" register due to the
++# anonymous unions and structs.  On Fedora Core 12 the compiler throws
++# an internal compiler error when multiple files access global
++# variables with debugging enabled.
++cat - > $TMPFILE1 <<EOF
++// Look for anonymous union/struct failure
++struct ts { union { int u1; struct { int u2; }; }; };
++void func1(struct ts *r);
++
++// Look for global variable failure.
++struct s1_s { int v; } g1;
++void __attribute__((externally_visible)) func2() {
++    struct s1_s *l1 = &g1;
++    l1->v=0;
++}
++EOF
++cat - > $TMPFILE2 <<EOF
++struct ts { union { int u1; struct { int u2; }; }; };
++void func1(struct ts *r);
++
++extern struct s1_s g1;
++void func3() {
++    &g1;
++}
++EOF
++$CC -O -g -fwhole-program -combine -c $TMPFILE1 $TMPFILE2 -o $TMPFILE1o > /dev/null 2>&1
++if [ $? -eq 0 ]; then
++    echo 0
++else
++    echo "  Working around non-functional -combine" > /dev/fd/2
++    echo 1
++fi
++
++# Also, on several compilers, -combine fails if code is emitted with a
++# reference to an extern variable that is later found to be externally
++# visible - the compiler does not mark those variables as global.
++# This is being worked around by ordering the compile objects to avoid
++# this case.
++
++# Also, the Ubuntu 8.04 compiler has a bug causing corruption when the
++# "ebp" register is clobberred in an "asm" statement.  The code has
++# been modified to not clobber "ebp" - no test is available yet.
++
++rm -f $TMPFILE1 $TMPFILE1o $TMPFILE2 $TMPFILE2o $TMPFILE3o
+--- x/roms/seabios/vgasrc/clext.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/vgasrc/clext.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,390 @@
++//  QEMU Cirrus CLGD 54xx VGABIOS Extension.
++//
++// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
++//  Copyright (c) 2004 Makoto Suzuki (suzu)
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "vgatables.h" // cirrus_init
++#include "biosvar.h" // GET_GLOBAL
++#include "util.h" // dprintf
++
++struct cirrus_mode_s {
++    /* + 0 */
++    u16 mode;
++    u16 width;
++    u16 height;
++    u16 depth;
++    /* + 8 */
++    u16 hidden_dac; /* 0x3c6 */
++    u16 *seq; /* 0x3c4 */
++    u16 *graph; /* 0x3ce */
++    u16 *crtc; /* 0x3d4 */
++    /* +16 */
++    u8 bitsperpixel;
++    u8 vesacolortype;
++    u8 vesaredmask;
++    u8 vesaredpos;
++    u8 vesagreenmask;
++    u8 vesagreenpos;
++    u8 vesabluemask;
++    u8 vesabluepos;
++    /* +24 */
++    u8 vesareservedmask;
++    u8 vesareservedpos;
++};
++
++/* VGA */
++static u16 cseq_vga[] VAR16 = {0x0007,0xffff};
++static u16 cgraph_vga[] VAR16 = {0x0009,0x000a,0x000b,0xffff};
++static u16 ccrtc_vga[] VAR16 = {0x001a,0x001b,0x001d,0xffff};
++
++/* extensions */
++static u16 cgraph_svgacolor[] VAR16 = {
++    0x0000,0x0001,0x0002,0x0003,0x0004,0x4005,0x0506,0x0f07,0xff08,
++    0x0009,0x000a,0x000b,
++    0xffff
++};
++/* 640x480x8 */
++static u16 cseq_640x480x8[] VAR16 = {
++    0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107,
++    0x580b,0x580c,0x580d,0x580e,
++    0x0412,0x0013,0x2017,
++    0x331b,0x331c,0x331d,0x331e,
++    0xffff
++};
++static u16 ccrtc_640x480x8[] VAR16 = {
++    0x2c11,
++    0x5f00,0x4f01,0x4f02,0x8003,0x5204,0x1e05,0x0b06,0x3e07,
++    0x4009,0x000c,0x000d,
++    0xea10,0xdf12,0x5013,0x4014,0xdf15,0x0b16,0xc317,0xff18,
++    0x001a,0x221b,0x001d,
++    0xffff
++};
++/* 640x480x16 */
++static u16 cseq_640x480x16[] VAR16 = {
++    0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1707,
++    0x580b,0x580c,0x580d,0x580e,
++    0x0412,0x0013,0x2017,
++    0x331b,0x331c,0x331d,0x331e,
++    0xffff
++};
++static u16 ccrtc_640x480x16[] VAR16 = {
++    0x2c11,
++    0x5f00,0x4f01,0x4f02,0x8003,0x5204,0x1e05,0x0b06,0x3e07,
++    0x4009,0x000c,0x000d,
++    0xea10,0xdf12,0xa013,0x4014,0xdf15,0x0b16,0xc317,0xff18,
++    0x001a,0x221b,0x001d,
++    0xffff
++};
++/* 640x480x24 */
++static u16 cseq_640x480x24[] VAR16 = {
++    0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1507,
++    0x580b,0x580c,0x580d,0x580e,
++    0x0412,0x0013,0x2017,
++    0x331b,0x331c,0x331d,0x331e,
++    0xffff
++};
++static u16 ccrtc_640x480x24[] VAR16 = {
++    0x2c11,
++    0x5f00,0x4f01,0x4f02,0x8003,0x5204,0x1e05,0x0b06,0x3e07,
++    0x4009,0x000c,0x000d,
++    0xea10,0xdf12,0x0013,0x4014,0xdf15,0x0b16,0xc317,0xff18,
++    0x001a,0x321b,0x001d,
++    0xffff
++};
++/* 800x600x8 */
++static u16 cseq_800x600x8[] VAR16 = {
++    0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107,
++    0x230b,0x230c,0x230d,0x230e,
++    0x0412,0x0013,0x2017,
++    0x141b,0x141c,0x141d,0x141e,
++    0xffff
++};
++static u16 ccrtc_800x600x8[] VAR16 = {
++    0x2311,0x7d00,0x6301,0x6302,0x8003,0x6b04,0x1a05,0x9806,0xf007,
++    0x6009,0x000c,0x000d,
++    0x7d10,0x5712,0x6413,0x4014,0x5715,0x9816,0xc317,0xff18,
++    0x001a,0x221b,0x001d,
++    0xffff
++};
++/* 800x600x16 */
++static u16 cseq_800x600x16[] VAR16 = {
++    0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1707,
++    0x230b,0x230c,0x230d,0x230e,
++    0x0412,0x0013,0x2017,
++    0x141b,0x141c,0x141d,0x141e,
++    0xffff
++};
++static u16 ccrtc_800x600x16[] VAR16 = {
++    0x2311,0x7d00,0x6301,0x6302,0x8003,0x6b04,0x1a05,0x9806,0xf007,
++    0x6009,0x000c,0x000d,
++    0x7d10,0x5712,0xc813,0x4014,0x5715,0x9816,0xc317,0xff18,
++    0x001a,0x221b,0x001d,
++    0xffff
++};
++/* 800x600x24 */
++static u16 cseq_800x600x24[] VAR16 = {
++    0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1507,
++    0x230b,0x230c,0x230d,0x230e,
++    0x0412,0x0013,0x2017,
++    0x141b,0x141c,0x141d,0x141e,
++    0xffff
++};
++static u16 ccrtc_800x600x24[] VAR16 = {
++    0x2311,0x7d00,0x6301,0x6302,0x8003,0x6b04,0x1a05,0x9806,0xf007,
++    0x6009,0x000c,0x000d,
++    0x7d10,0x5712,0x2c13,0x4014,0x5715,0x9816,0xc317,0xff18,
++    0x001a,0x321b,0x001d,
++    0xffff
++};
++/* 1024x768x8 */
++static u16 cseq_1024x768x8[] VAR16 = {
++    0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107,
++    0x760b,0x760c,0x760d,0x760e,
++    0x0412,0x0013,0x2017,
++    0x341b,0x341c,0x341d,0x341e,
++    0xffff
++};
++static u16 ccrtc_1024x768x8[] VAR16 = {
++    0x2911,0xa300,0x7f01,0x7f02,0x8603,0x8304,0x9405,0x2406,0xf507,
++    0x6009,0x000c,0x000d,
++    0x0310,0xff12,0x8013,0x4014,0xff15,0x2416,0xc317,0xff18,
++    0x001a,0x221b,0x001d,
++    0xffff
++};
++/* 1024x768x16 */
++static u16 cseq_1024x768x16[] VAR16 = {
++    0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1707,
++    0x760b,0x760c,0x760d,0x760e,
++    0x0412,0x0013,0x2017,
++    0x341b,0x341c,0x341d,0x341e,
++    0xffff
++};
++static u16 ccrtc_1024x768x16[] VAR16 = {
++    0x2911,0xa300,0x7f01,0x7f02,0x8603,0x8304,0x9405,0x2406,0xf507,
++    0x6009,0x000c,0x000d,
++    0x0310,0xff12,0x0013,0x4014,0xff15,0x2416,0xc317,0xff18,
++    0x001a,0x321b,0x001d,
++    0xffff
++};
++/* 1024x768x24 */
++static u16 cseq_1024x768x24[] VAR16 = {
++    0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1507,
++    0x760b,0x760c,0x760d,0x760e,
++    0x0412,0x0013,0x2017,
++    0x341b,0x341c,0x341d,0x341e,
++    0xffff
++};
++static u16 ccrtc_1024x768x24[] VAR16 = {
++    0x2911,0xa300,0x7f01,0x7f02,0x8603,0x8304,0x9405,0x2406,0xf507,
++    0x6009,0x000c,0x000d,
++    0x0310,0xff12,0x8013,0x4014,0xff15,0x2416,0xc317,0xff18,
++    0x001a,0x321b,0x001d,
++    0xffff
++};
++/* 1280x1024x8 */
++static u16 cseq_1280x1024x8[] VAR16 = {
++    0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107,
++    0x760b,0x760c,0x760d,0x760e,
++    0x0412,0x0013,0x2017,
++    0x341b,0x341c,0x341d,0x341e,
++    0xffff
++};
++static u16 ccrtc_1280x1024x8[] VAR16 = {
++    0x2911,0xc300,0x9f01,0x9f02,0x8603,0x8304,0x9405,0x2406,0xf707,
++    0x6009,0x000c,0x000d,
++    0x0310,0xff12,0xa013,0x4014,0xff15,0x2416,0xc317,0xff18,
++    0x001a,0x221b,0x001d,
++    0xffff
++};
++/* 1280x1024x16 */
++static u16 cseq_1280x1024x16[] VAR16 = {
++    0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1707,
++    0x760b,0x760c,0x760d,0x760e,
++    0x0412,0x0013,0x2017,
++    0x341b,0x341c,0x341d,0x341e,
++    0xffff
++};
++static u16 ccrtc_1280x1024x16[] VAR16 = {
++    0x2911,0xc300,0x9f01,0x9f02,0x8603,0x8304,0x9405,0x2406,0xf707,
++    0x6009,0x000c,0x000d,
++    0x0310,0xff12,0x4013,0x4014,0xff15,0x2416,0xc317,0xff18,
++    0x001a,0x321b,0x001d,
++    0xffff
++};
++
++/* 1600x1200x8 */
++static u16 cseq_1600x1200x8[] VAR16 = {
++    0x0300,0x2101,0x0f02,0x0003,0x0e04,0x1107,
++    0x760b,0x760c,0x760d,0x760e,
++    0x0412,0x0013,0x2017,
++    0x341b,0x341c,0x341d,0x341e,
++    0xffff
++};
++static u16 ccrtc_1600x1200x8[] VAR16 = {
++    0x2911,0xc300,0x9f01,0x9f02,0x8603,0x8304,0x9405,0x2406,0xf707,
++    0x6009,0x000c,0x000d,
++    0x0310,0xff12,0xa013,0x4014,0xff15,0x2416,0xc317,0xff18,
++    0x001a,0x221b,0x001d,
++    0xffff
++};
++
++static struct cirrus_mode_s cirrus_modes[] VAR16 = {
++    {0x5f,640,480,8,0x00,
++     cseq_640x480x8,cgraph_svgacolor,ccrtc_640x480x8,8,
++     4,0,0,0,0,0,0,0,0},
++    {0x64,640,480,16,0xe1,
++     cseq_640x480x16,cgraph_svgacolor,ccrtc_640x480x16,16,
++     6,5,11,6,5,5,0,0,0},
++    {0x66,640,480,15,0xf0,
++     cseq_640x480x16,cgraph_svgacolor,ccrtc_640x480x16,16,
++     6,5,10,5,5,5,0,1,15},
++    {0x71,640,480,24,0xe5,
++     cseq_640x480x24,cgraph_svgacolor,ccrtc_640x480x24,24,
++     6,8,16,8,8,8,0,0,0},
++
++    {0x5c,800,600,8,0x00,
++     cseq_800x600x8,cgraph_svgacolor,ccrtc_800x600x8,8,
++     4,0,0,0,0,0,0,0,0},
++    {0x65,800,600,16,0xe1,
++     cseq_800x600x16,cgraph_svgacolor,ccrtc_800x600x16,16,
++     6,5,11,6,5,5,0,0,0},
++    {0x67,800,600,15,0xf0,
++     cseq_800x600x16,cgraph_svgacolor,ccrtc_800x600x16,16,
++     6,5,10,5,5,5,0,1,15},
++
++    {0x60,1024,768,8,0x00,
++     cseq_1024x768x8,cgraph_svgacolor,ccrtc_1024x768x8,8,
++     4,0,0,0,0,0,0,0,0},
++    {0x74,1024,768,16,0xe1,
++     cseq_1024x768x16,cgraph_svgacolor,ccrtc_1024x768x16,16,
++     6,5,11,6,5,5,0,0,0},
++    {0x68,1024,768,15,0xf0,
++     cseq_1024x768x16,cgraph_svgacolor,ccrtc_1024x768x16,16,
++     6,5,10,5,5,5,0,1,15},
++
++    {0x78,800,600,24,0xe5,
++     cseq_800x600x24,cgraph_svgacolor,ccrtc_800x600x24,24,
++     6,8,16,8,8,8,0,0,0},
++    {0x79,1024,768,24,0xe5,
++     cseq_1024x768x24,cgraph_svgacolor,ccrtc_1024x768x24,24,
++     6,8,16,8,8,8,0,0,0},
++
++    {0x6d,1280,1024,8,0x00,
++     cseq_1280x1024x8,cgraph_svgacolor,ccrtc_1280x1024x8,8,
++     4,0,0,0,0,0,0,0,0},
++    {0x69,1280,1024,15,0xf0,
++     cseq_1280x1024x16,cgraph_svgacolor,ccrtc_1280x1024x16,16,
++     6,5,10,5,5,5,0,1,15},
++    {0x75,1280,1024,16,0xe1,
++     cseq_1280x1024x16,cgraph_svgacolor,ccrtc_1280x1024x16,16,
++     6,5,11,6,5,5,0,0,0},
++
++    {0x7b,1600,1200,8,0x00,
++     cseq_1600x1200x8,cgraph_svgacolor,ccrtc_1600x1200x8,8,
++     4,0,0,0,0,0,0,0,0},
++
++    {0xfe,0,0,0,0,cseq_vga,cgraph_vga,ccrtc_vga,0,
++     0xff,0,0,0,0,0,0,0,0},
++};
++
++static struct cirrus_mode_s *
++cirrus_get_modeentry(u8 mode)
++{
++    struct cirrus_mode_s *table_g = cirrus_modes;
++    while (table_g < &cirrus_modes[ARRAY_SIZE(cirrus_modes)]) {
++        u16 tmode = GET_GLOBAL(table_g->mode);
++        if (tmode == mode)
++            return table_g;
++        table_g++;
++    }
++    return NULL;
++}
++
++static void
++cirrus_switch_mode_setregs(u16 *data, u16 port)
++{
++    for (;;) {
++        u16 val = GET_GLOBAL(*data);
++        if (val == 0xffff)
++            return;
++        outw(val, port);
++        data++;
++    }
++}
++
++static u16
++cirrus_get_crtc(void)
++{
++    if (inb(VGAREG_READ_MISC_OUTPUT) & 1)
++        return VGAREG_VGA_CRTC_ADDRESS;
++    return VGAREG_MDA_CRTC_ADDRESS;
++}
++
++static void
++cirrus_switch_mode(struct cirrus_mode_s *table)
++{
++    // Unlock cirrus special
++    outw(0x1206, VGAREG_SEQU_ADDRESS);
++    cirrus_switch_mode_setregs(GET_GLOBAL(table->seq), VGAREG_SEQU_ADDRESS);
++    cirrus_switch_mode_setregs(GET_GLOBAL(table->graph), VGAREG_GRDC_ADDRESS);
++    cirrus_switch_mode_setregs(GET_GLOBAL(table->crtc), cirrus_get_crtc());
++
++    outb(0x00, VGAREG_PEL_MASK);
++    inb(VGAREG_PEL_MASK);
++    inb(VGAREG_PEL_MASK);
++    inb(VGAREG_PEL_MASK);
++    inb(VGAREG_PEL_MASK);
++    outb(GET_GLOBAL(table->hidden_dac), VGAREG_PEL_MASK);
++    outb(0xff, VGAREG_PEL_MASK);
++
++    u8 vesacolortype = GET_GLOBAL(table->vesacolortype);
++    u8 v = vgahw_get_single_palette_reg(0x10) & 0xfe;
++    if (vesacolortype == 3)
++        v |= 0x41;
++    else if (vesacolortype)
++        v |= 0x01;
++    vgahw_set_single_palette_reg(0x10, v);
++}
++
++void
++cirrus_set_video_mode(u8 mode)
++{
++    dprintf(1, "cirrus mode %d\n", mode);
++    SET_BDA(vbe_mode, 0);
++    struct cirrus_mode_s *table_g = cirrus_get_modeentry(mode & 0x7f);
++    if (table_g) {
++        //XXX - cirrus_set_video_mode_extended(table);
++        return;
++    }
++    table_g = cirrus_get_modeentry(0xfe);
++    cirrus_switch_mode(table_g);
++    dprintf(1, "cirrus mode switch regular\n");
++}
++
++static int
++cirrus_check(void)
++{
++    outw(0x9206, VGAREG_SEQU_ADDRESS);
++    return inb(VGAREG_SEQU_DATA) == 0x12;
++}
++
++void
++cirrus_init(void)
++{
++    dprintf(1, "cirrus init\n");
++    if (! cirrus_check())
++        return;
++    dprintf(1, "cirrus init 2\n");
++
++    // memory setup
++    outb(0x0f, VGAREG_SEQU_ADDRESS);
++    u8 v = inb(VGAREG_SEQU_DATA);
++    outb(((v & 0x18) << 8) | 0x0a, VGAREG_SEQU_ADDRESS);
++    // set vga mode
++    outw(0x0007, VGAREG_SEQU_ADDRESS);
++    // reset bitblt
++    outw(0x0431, VGAREG_GRDC_ADDRESS);
++    outw(0x0031, VGAREG_GRDC_ADDRESS);
++}
+--- x/roms/seabios/vgasrc/vga.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/vgasrc/vga.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,1387 @@
++// VGA bios implementation
++//
++// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2001-2008 the LGPL VGABios developers Team
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++
++// TODO:
++//  * review correctness of converted asm by comparing with RBIL
++//
++//  * convert vbe/clext code
++
++#include "bregs.h" // struct bregs
++#include "biosvar.h" // GET_BDA
++#include "util.h" // memset
++#include "vgatables.h" // find_vga_entry
++
++// XXX
++#define CONFIG_VBE 0
++#define CONFIG_CIRRUS 0
++
++// XXX
++#define DEBUG_VGA_POST 1
++#define DEBUG_VGA_10 3
++
++#define SET_VGA(var, val) SET_FARVAR(get_global_seg(), (var), (val))
++
++
++/****************************************************************
++ * Helper functions
++ ****************************************************************/
++
++static inline void
++call16_vgaint(u32 eax, u32 ebx)
++{
++    asm volatile(
++        "int $0x10\n"
++        "cli\n"
++        "cld"
++        :
++        : "a"(eax), "b"(ebx)
++        : "cc", "memory");
++}
++
++static void
++perform_gray_scale_summing(u16 start, u16 count)
++{
++    vgahw_screen_disable();
++    int i;
++    for (i = start; i < start+count; i++) {
++        u8 rgb[3];
++        vgahw_get_dac_regs(GET_SEG(SS), rgb, i, 1);
++
++        // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue )
++        u16 intensity = ((77 * rgb[0] + 151 * rgb[1] + 28 * rgb[2]) + 0x80) >> 8;
++        if (intensity > 0x3f)
++            intensity = 0x3f;
++
++        vgahw_set_dac_regs(GET_SEG(SS), rgb, i, 1);
++    }
++    vgahw_screen_enable();
++}
++
++static void
++set_cursor_shape(u8 start, u8 end)
++{
++    start &= 0x3f;
++    end &= 0x1f;
++
++    u16 curs = (start << 8) + end;
++    SET_BDA(cursor_type, curs);
++
++    u8 modeset_ctl = GET_BDA(modeset_ctl);
++    u16 cheight = GET_BDA(char_height);
++    if ((modeset_ctl & 0x01) && (cheight > 8) && (end < 8) && (start < 0x20)) {
++        if (end != (start + 1))
++            start = ((start + 1) * cheight / 8) - 1;
++        else
++            start = ((end + 1) * cheight / 8) - 2;
++        end = ((end + 1) * cheight / 8) - 1;
++    }
++    vgahw_set_cursor_shape(start, end);
++}
++
++static u16
++get_cursor_shape(u8 page)
++{
++    if (page > 7)
++        return 0;
++    // FIXME should handle VGA 14/16 lines
++    return GET_BDA(cursor_type);
++}
++
++static void
++set_cursor_pos(struct cursorpos cp)
++{
++    // Should not happen...
++    if (cp.page > 7)
++        return;
++
++    // Bios cursor pos
++    SET_BDA(cursor_pos[cp.page], (cp.y << 8) | cp.x);
++
++    // Set the hardware cursor
++    u8 current = GET_BDA(video_page);
++    if (cp.page != current)
++        return;
++
++    // Get the dimensions
++    u16 nbcols = GET_BDA(video_cols);
++    u16 nbrows = GET_BDA(video_rows) + 1;
++
++    // Calculate the address knowing nbcols nbrows and page num
++    u16 address = (SCREEN_IO_START(nbcols, nbrows, cp.page)
++                   + cp.x + cp.y * nbcols);
++
++    vgahw_set_cursor_pos(address);
++}
++
++static struct cursorpos
++get_cursor_pos(u8 page)
++{
++    if (page == 0xff)
++        // special case - use current page
++        page = GET_BDA(video_page);
++    if (page > 7) {
++        struct cursorpos cp = { 0, 0, 0xfe };
++        return cp;
++    }
++    // FIXME should handle VGA 14/16 lines
++    u16 xy = GET_BDA(cursor_pos[page]);
++    struct cursorpos cp = {xy, xy>>8, page};
++    return cp;
++}
++
++static void
++set_active_page(u8 page)
++{
++    if (page > 7)
++        return;
++
++    // Get the mode
++    struct vgamode_s *vmode_g = find_vga_entry(GET_BDA(video_mode));
++    if (!vmode_g)
++        return;
++
++    // Get pos curs pos for the right page
++    struct cursorpos cp = get_cursor_pos(page);
++
++    u16 address;
++    if (GET_GLOBAL(vmode_g->memmodel) & TEXT) {
++        // Get the dimensions
++        u16 nbcols = GET_BDA(video_cols);
++        u16 nbrows = GET_BDA(video_rows) + 1;
++
++        // Calculate the address knowing nbcols nbrows and page num
++        address = SCREEN_MEM_START(nbcols, nbrows, page);
++        SET_BDA(video_pagestart, address);
++
++        // Start address
++        address = SCREEN_IO_START(nbcols, nbrows, page);
++    } else {
++        struct VideoParam_s *vparam_g = GET_GLOBAL(vmode_g->vparam);
++        address = page * GET_GLOBAL(vparam_g->slength);
++    }
++
++    vgahw_set_active_page(address);
++
++    // And change the BIOS page
++    SET_BDA(video_page, page);
++
++    dprintf(1, "Set active page %02x address %04x\n", page, address);
++
++    // Display the cursor, now the page is active
++    set_cursor_pos(cp);
++}
++
++static void
++set_scan_lines(u8 lines)
++{
++    vgahw_set_scan_lines(lines);
++    if (lines == 8)
++        set_cursor_shape(0x06, 0x07);
++    else
++        set_cursor_shape(lines - 4, lines - 3);
++    SET_BDA(char_height, lines);
++    u16 vde = vgahw_get_vde();
++    u8 rows = vde / lines;
++    SET_BDA(video_rows, rows - 1);
++    u16 cols = GET_BDA(video_cols);
++    SET_BDA(video_pagesize, rows * cols * 2);
++}
++
++
++/****************************************************************
++ * Character writing
++ ****************************************************************/
++
++// Scroll the screen one line.  This function is designed to be called
++// tail-recursive to reduce stack usage.
++static void noinline
++scroll_one(u16 nbrows, u16 nbcols, u8 page)
++{
++    struct cursorpos ul = {0, 0, page};
++    struct cursorpos lr = {nbcols-1, nbrows-1, page};
++    vgafb_scroll(1, -1, ul, lr);
++}
++
++// Write a character to the screen at a given position.  Implement
++// special characters and scroll the screen if necessary.
++static void
++write_teletype(struct cursorpos *pcp, struct carattr ca)
++{
++    struct cursorpos cp = *pcp;
++
++    // Get the dimensions
++    u16 nbrows = GET_BDA(video_rows) + 1;
++    u16 nbcols = GET_BDA(video_cols);
++
++    switch (ca.car) {
++    case 7:
++        //FIXME should beep
++        break;
++    case 8:
++        if (cp.x > 0)
++            cp.x--;
++        break;
++    case '\r':
++        cp.x = 0;
++        break;
++    case '\n':
++        cp.y++;
++        break;
++    case '\t':
++        do {
++            struct carattr dummyca = {' ', ca.attr, ca.use_attr};
++            vgafb_write_char(cp, dummyca);
++            cp.x++;
++        } while (cp.x < nbcols && cp.x % 8);
++        break;
++    default:
++        vgafb_write_char(cp, ca);
++        cp.x++;
++    }
++
++    // Do we need to wrap ?
++    if (cp.x == nbcols) {
++        cp.x = 0;
++        cp.y++;
++    }
++    // Do we need to scroll ?
++    if (cp.y < nbrows) {
++        *pcp = cp;
++        return;
++    }
++    // Scroll screen
++    cp.y--;
++    *pcp = cp;
++    scroll_one(nbrows, nbcols, cp.page);
++}
++
++// Write out a buffer of alternating characters and attributes.
++static void
++write_attr_string(struct cursorpos *pcp, u16 count, u16 seg, u8 *offset_far)
++{
++    while (count--) {
++        u8 car = GET_FARVAR(seg, *offset_far);
++        offset_far++;
++        u8 attr = GET_FARVAR(seg, *offset_far);
++        offset_far++;
++
++        struct carattr ca = {car, attr, 1};
++        write_teletype(pcp, ca);
++    }
++}
++
++// Write out a buffer of characters.
++static void
++write_string(struct cursorpos *pcp, u8 attr, u16 count, u16 seg, u8 *offset_far)
++{
++    while (count--) {
++        u8 car = GET_FARVAR(seg, *offset_far);
++        offset_far++;
++
++        struct carattr ca = {car, attr, 1};
++        write_teletype(pcp, ca);
++    }
++}
++
++
++/****************************************************************
++ * Save and restore bda state
++ ****************************************************************/
++
++static void
++save_bda_state(u16 seg, struct saveBDAstate *info)
++{
++    SET_FARVAR(seg, info->video_mode, GET_BDA(video_mode));
++    SET_FARVAR(seg, info->video_cols, GET_BDA(video_cols));
++    SET_FARVAR(seg, info->video_pagesize, GET_BDA(video_pagesize));
++    SET_FARVAR(seg, info->crtc_address, GET_BDA(crtc_address));
++    SET_FARVAR(seg, info->video_rows, GET_BDA(video_rows));
++    SET_FARVAR(seg, info->char_height, GET_BDA(char_height));
++    SET_FARVAR(seg, info->video_ctl, GET_BDA(video_ctl));
++    SET_FARVAR(seg, info->video_switches, GET_BDA(video_switches));
++    SET_FARVAR(seg, info->modeset_ctl, GET_BDA(modeset_ctl));
++    SET_FARVAR(seg, info->cursor_type, GET_BDA(cursor_type));
++    u16 i;
++    for (i=0; i<8; i++)
++        SET_FARVAR(seg, info->cursor_pos[i], GET_BDA(cursor_pos[i]));
++    SET_FARVAR(seg, info->video_pagestart, GET_BDA(video_pagestart));
++    SET_FARVAR(seg, info->video_page, GET_BDA(video_page));
++    /* current font */
++    SET_FARVAR(seg, info->font0, GET_IVT(0x1f));
++    SET_FARVAR(seg, info->font1, GET_IVT(0x43));
++}
++
++static void
++restore_bda_state(u16 seg, struct saveBDAstate *info)
++{
++    SET_BDA(video_mode, GET_FARVAR(seg, info->video_mode));
++    SET_BDA(video_cols, GET_FARVAR(seg, info->video_cols));
++    SET_BDA(video_pagesize, GET_FARVAR(seg, info->video_pagesize));
++    SET_BDA(crtc_address, GET_FARVAR(seg, info->crtc_address));
++    SET_BDA(video_rows, GET_FARVAR(seg, info->video_rows));
++    SET_BDA(char_height, GET_FARVAR(seg, info->char_height));
++    SET_BDA(video_ctl, GET_FARVAR(seg, info->video_ctl));
++    SET_BDA(video_switches, GET_FARVAR(seg, info->video_switches));
++    SET_BDA(modeset_ctl, GET_FARVAR(seg, info->modeset_ctl));
++    SET_BDA(cursor_type, GET_FARVAR(seg, info->cursor_type));
++    u16 i;
++    for (i = 0; i < 8; i++)
++        SET_BDA(cursor_pos[i], GET_FARVAR(seg, info->cursor_pos[i]));
++    SET_BDA(video_pagestart, GET_FARVAR(seg, info->video_pagestart));
++    SET_BDA(video_page, GET_FARVAR(seg, info->video_page));
++    /* current font */
++    SET_IVT(0x1f, GET_FARVAR(seg, info->font0));
++    SET_IVT(0x43, GET_FARVAR(seg, info->font1));
++}
++
++
++/****************************************************************
++ * VGA int 10 handler
++ ****************************************************************/
++
++// set video mode
++static void
++handle_1000(struct bregs *regs)
++{
++    u8 noclearmem = regs->al & 0x80;
++    u8 mode = regs->al & 0x7f;
++
++    // Set regs->al
++    if (mode > 7)
++        regs->al = 0x20;
++    else if (mode == 6)
++        regs->al = 0x3f;
++    else
++        regs->al = 0x30;
++
++    if (CONFIG_CIRRUS)
++        cirrus_set_video_mode(mode);
++
++    if (CONFIG_VBE)
++        if (vbe_has_vbe_display())
++            dispi_set_enable(VBE_DISPI_DISABLED);
++
++    // find the entry in the video modes
++    struct vgamode_s *vmode_g = find_vga_entry(mode);
++    dprintf(1, "mode search %02x found %p\n", mode, vmode_g);
++    if (!vmode_g)
++        return;
++
++    // Read the bios mode set control
++    u8 modeset_ctl = GET_BDA(modeset_ctl);
++
++    // Then we know the number of lines
++// FIXME
++
++    // if palette loading (bit 3 of modeset ctl = 0)
++    if ((modeset_ctl & 0x08) == 0) {    // Set the PEL mask
++        vgahw_set_pel_mask(GET_GLOBAL(vmode_g->pelmask));
++
++        // From which palette
++        u8 *palette_g = GET_GLOBAL(vmode_g->dac);
++        u16 palsize = GET_GLOBAL(vmode_g->dacsize) / 3;
++
++        // Always 256*3 values
++        vgahw_set_dac_regs(get_global_seg(), palette_g, 0, palsize);
++        u16 i;
++        for (i = palsize; i < 0x0100; i++) {
++            static u8 rgb[3] VAR16;
++            vgahw_set_dac_regs(get_global_seg(), rgb, i, 1);
++        }
++
++        if ((modeset_ctl & 0x02) == 0x02)
++            perform_gray_scale_summing(0x00, 0x100);
++    }
++
++    struct VideoParam_s *vparam_g = GET_GLOBAL(vmode_g->vparam);
++    vgahw_set_mode(vparam_g);
++
++    if (noclearmem == 0x00)
++        clear_screen(vmode_g);
++
++    // Set CRTC address VGA or MDA
++    u16 crtc_addr = VGAREG_VGA_CRTC_ADDRESS;
++    if (GET_GLOBAL(vmode_g->memmodel) == MTEXT)
++        crtc_addr = VGAREG_MDA_CRTC_ADDRESS;
++
++    // Set the BIOS mem
++    u16 cheight = GET_GLOBAL(vparam_g->cheight);
++    SET_BDA(video_mode, mode);
++    SET_BDA(video_cols, GET_GLOBAL(vparam_g->twidth));
++    SET_BDA(video_pagesize, GET_GLOBAL(vparam_g->slength));
++    SET_BDA(crtc_address, crtc_addr);
++    SET_BDA(video_rows, GET_GLOBAL(vparam_g->theightm1));
++    SET_BDA(char_height, cheight);
++    SET_BDA(video_ctl, (0x60 | noclearmem));
++    SET_BDA(video_switches, 0xF9);
++    SET_BDA(modeset_ctl, GET_BDA(modeset_ctl) & 0x7f);
++
++    // FIXME We nearly have the good tables. to be reworked
++    SET_BDA(dcc_index, 0x08);   // 8 is VGA should be ok for now
++    SET_BDA(video_savetable
++            , SEGOFF(get_global_seg(), (u32)video_save_pointer_table));
++
++    // FIXME
++    SET_BDA(video_msr, 0x00); // Unavailable on vanilla vga, but...
++    SET_BDA(video_pal, 0x00); // Unavailable on vanilla vga, but...
++
++    // Set cursor shape
++    if (GET_GLOBAL(vmode_g->memmodel) & TEXT)
++        set_cursor_shape(0x06, 0x07);
++    // Set cursor pos for page 0..7
++    int i;
++    for (i = 0; i < 8; i++) {
++        struct cursorpos cp = {0, 0, i};
++        set_cursor_pos(cp);
++    }
++
++    // Set active page 0
++    set_active_page(0x00);
++
++    // Write the fonts in memory
++    if (GET_GLOBAL(vmode_g->memmodel) & TEXT) {
++        call16_vgaint(0x1104, 0);
++        call16_vgaint(0x1103, 0);
++    }
++    // Set the ints 0x1F and 0x43
++    SET_IVT(0x1f, SEGOFF(get_global_seg(), (u32)&vgafont8[128 * 8]));
++
++    switch (cheight) {
++    case 8:
++        SET_IVT(0x43, SEGOFF(get_global_seg(), (u32)vgafont8));
++        break;
++    case 14:
++        SET_IVT(0x43, SEGOFF(get_global_seg(), (u32)vgafont14));
++        break;
++    case 16:
++        SET_IVT(0x43, SEGOFF(get_global_seg(), (u32)vgafont16));
++        break;
++    }
++}
++
++static void
++handle_1001(struct bregs *regs)
++{
++    set_cursor_shape(regs->ch, regs->cl);
++}
++
++static void
++handle_1002(struct bregs *regs)
++{
++    struct cursorpos cp = {regs->dl, regs->dh, regs->bh};
++    set_cursor_pos(cp);
++}
++
++static void
++handle_1003(struct bregs *regs)
++{
++    regs->cx = get_cursor_shape(regs->bh);
++    struct cursorpos cp = get_cursor_pos(regs->bh);
++    regs->dl = cp.x;
++    regs->dh = cp.y;
++}
++
++// Read light pen pos (unimplemented)
++static void
++handle_1004(struct bregs *regs)
++{
++    debug_stub(regs);
++    regs->ax = regs->bx = regs->cx = regs->dx = 0;
++}
++
++static void
++handle_1005(struct bregs *regs)
++{
++    set_active_page(regs->al);
++}
++
++static void
++verify_scroll(struct bregs *regs, int dir)
++{
++    u8 page = GET_BDA(video_page);
++    struct cursorpos ul = {regs->cl, regs->ch, page};
++    struct cursorpos lr = {regs->dl, regs->dh, page};
++
++    u16 nbrows = GET_BDA(video_rows) + 1;
++    if (lr.y >= nbrows)
++        lr.y = nbrows - 1;
++    u16 nbcols = GET_BDA(video_cols);
++    if (lr.x >= nbcols)
++        lr.x = nbcols - 1;
++
++    if (ul.x > lr.x || ul.y > lr.y)
++        return;
++
++    u16 nblines = regs->al;
++    if (!nblines || nblines > lr.y - ul.y + 1)
++        nblines = lr.y - ul.y + 1;
++
++    vgafb_scroll(dir * nblines, regs->bh, ul, lr);
++}
++
++static void
++handle_1006(struct bregs *regs)
++{
++    verify_scroll(regs, 1);
++}
++
++static void
++handle_1007(struct bregs *regs)
++{
++    verify_scroll(regs, -1);
++}
++
++static void
++handle_1008(struct bregs *regs)
++{
++    struct carattr ca = vgafb_read_char(get_cursor_pos(regs->bh));
++    regs->al = ca.car;
++    regs->ah = ca.attr;
++}
++
++static void noinline
++write_chars(u8 page, struct carattr ca, u16 count)
++{
++    struct cursorpos cp = get_cursor_pos(page);
++    while (count--) {
++        vgafb_write_char(cp, ca);
++        cp.x++;
++    }
++}
++
++static void
++handle_1009(struct bregs *regs)
++{
++    struct carattr ca = {regs->al, regs->bl, 1};
++    write_chars(regs->bh, ca, regs->cx);
++}
++
++static void
++handle_100a(struct bregs *regs)
++{
++    struct carattr ca = {regs->al, regs->bl, 0};
++    write_chars(regs->bh, ca, regs->cx);
++}
++
++
++static void
++handle_100b00(struct bregs *regs)
++{
++    vgahw_set_border_color(regs->bl);
++}
++
++static void
++handle_100b01(struct bregs *regs)
++{
++    vgahw_set_palette(regs->bl);
++}
++
++static void
++handle_100bXX(struct bregs *regs)
++{
++    debug_stub(regs);
++}
++
++static void
++handle_100b(struct bregs *regs)
++{
++    switch (regs->bh) {
++    case 0x00: handle_100b00(regs); break;
++    case 0x01: handle_100b01(regs); break;
++    default:   handle_100bXX(regs); break;
++    }
++}
++
++
++static void
++handle_100c(struct bregs *regs)
++{
++    // XXX - page (regs->bh) is unused
++    vgafb_write_pixel(regs->al, regs->cx, regs->dx);
++}
++
++static void
++handle_100d(struct bregs *regs)
++{
++    // XXX - page (regs->bh) is unused
++    regs->al = vgafb_read_pixel(regs->cx, regs->dx);
++}
++
++static void noinline
++handle_100e(struct bregs *regs)
++{
++    // Ralf Brown Interrupt list is WRONG on bh(page)
++    // We do output only on the current page !
++    struct carattr ca = {regs->al, regs->bl, 0};
++    struct cursorpos cp = get_cursor_pos(0xff);
++    write_teletype(&cp, ca);
++    set_cursor_pos(cp);
++}
++
++static void
++handle_100f(struct bregs *regs)
++{
++    regs->bh = GET_BDA(video_page);
++    regs->al = GET_BDA(video_mode) | (GET_BDA(video_ctl) & 0x80);
++    regs->ah = GET_BDA(video_cols);
++}
++
++
++static void
++handle_101000(struct bregs *regs)
++{
++    if (regs->bl > 0x14)
++        return;
++    vgahw_set_single_palette_reg(regs->bl, regs->bh);
++}
++
++static void
++handle_101001(struct bregs *regs)
++{
++    vgahw_set_overscan_border_color(regs->bh);
++}
++
++static void
++handle_101002(struct bregs *regs)
++{
++    vgahw_set_all_palette_reg(regs->es, (u8*)(regs->dx + 0));
++}
++
++static void
++handle_101003(struct bregs *regs)
++{
++    vgahw_toggle_intensity(regs->bl);
++}
++
++static void
++handle_101007(struct bregs *regs)
++{
++    if (regs->bl > 0x14)
++        return;
++    regs->bh = vgahw_get_single_palette_reg(regs->bl);
++}
++
++static void
++handle_101008(struct bregs *regs)
++{
++    regs->bh = vgahw_get_overscan_border_color();
++}
++
++static void
++handle_101009(struct bregs *regs)
++{
++    vgahw_get_all_palette_reg(regs->es, (u8*)(regs->dx + 0));
++}
++
++static void noinline
++handle_101010(struct bregs *regs)
++{
++    u8 rgb[3] = {regs->dh, regs->ch, regs->cl};
++    vgahw_set_dac_regs(GET_SEG(SS), rgb, regs->bx, 1);
++}
++
++static void
++handle_101012(struct bregs *regs)
++{
++    vgahw_set_dac_regs(regs->es, (u8*)(regs->dx + 0), regs->bx, regs->cx);
++}
++
++static void
++handle_101013(struct bregs *regs)
++{
++    vgahw_select_video_dac_color_page(regs->bl, regs->bh);
++}
++
++static void noinline
++handle_101015(struct bregs *regs)
++{
++    u8 rgb[3];
++    vgahw_get_dac_regs(GET_SEG(SS), rgb, regs->bx, 1);
++    regs->dh = rgb[0];
++    regs->ch = rgb[1];
++    regs->cl = rgb[2];
++}
++
++static void
++handle_101017(struct bregs *regs)
++{
++    vgahw_get_dac_regs(regs->es, (u8*)(regs->dx + 0), regs->bx, regs->cx);
++}
++
++static void
++handle_101018(struct bregs *regs)
++{
++    vgahw_set_pel_mask(regs->bl);
++}
++
++static void
++handle_101019(struct bregs *regs)
++{
++    regs->bl = vgahw_get_pel_mask();
++}
++
++static void
++handle_10101a(struct bregs *regs)
++{
++    vgahw_read_video_dac_state(&regs->bl, &regs->bh);
++}
++
++static void
++handle_10101b(struct bregs *regs)
++{
++    perform_gray_scale_summing(regs->bx, regs->cx);
++}
++
++static void
++handle_1010XX(struct bregs *regs)
++{
++    debug_stub(regs);
++}
++
++static void
++handle_1010(struct bregs *regs)
++{
++    switch (regs->al) {
++    case 0x00: handle_101000(regs); break;
++    case 0x01: handle_101001(regs); break;
++    case 0x02: handle_101002(regs); break;
++    case 0x03: handle_101003(regs); break;
++    case 0x07: handle_101007(regs); break;
++    case 0x08: handle_101008(regs); break;
++    case 0x09: handle_101009(regs); break;
++    case 0x10: handle_101010(regs); break;
++    case 0x12: handle_101012(regs); break;
++    case 0x13: handle_101013(regs); break;
++    case 0x15: handle_101015(regs); break;
++    case 0x17: handle_101017(regs); break;
++    case 0x18: handle_101018(regs); break;
++    case 0x19: handle_101019(regs); break;
++    case 0x1a: handle_10101a(regs); break;
++    case 0x1b: handle_10101b(regs); break;
++    default:   handle_1010XX(regs); break;
++    }
++}
++
++
++static void
++handle_101100(struct bregs *regs)
++{
++    vgafb_load_font(regs->es, (void*)(regs->bp+0), regs->cx
++                    , regs->dx, regs->bl, regs->bh);
++}
++
++static void
++handle_101101(struct bregs *regs)
++{
++    vgafb_load_font(get_global_seg(), vgafont14, 0x100, 0, regs->bl, 14);
++}
++
++static void
++handle_101102(struct bregs *regs)
++{
++    vgafb_load_font(get_global_seg(), vgafont8, 0x100, 0, regs->bl, 8);
++}
++
++static void
++handle_101103(struct bregs *regs)
++{
++    vgahw_set_text_block_specifier(regs->bl);
++}
++
++static void
++handle_101104(struct bregs *regs)
++{
++    vgafb_load_font(get_global_seg(), vgafont16, 0x100, 0, regs->bl, 16);
++}
++
++static void
++handle_101110(struct bregs *regs)
++{
++    vgafb_load_font(regs->es, (void*)(regs->bp+0), regs->cx
++                    , regs->dx, regs->bl, regs->bh);
++    set_scan_lines(regs->bh);
++}
++
++static void
++handle_101111(struct bregs *regs)
++{
++    vgafb_load_font(get_global_seg(), vgafont14, 0x100, 0, regs->bl, 14);
++    set_scan_lines(14);
++}
++
++static void
++handle_101112(struct bregs *regs)
++{
++    vgafb_load_font(get_global_seg(), vgafont8, 0x100, 0, regs->bl, 8);
++    set_scan_lines(8);
++}
++
++static void
++handle_101114(struct bregs *regs)
++{
++    vgafb_load_font(get_global_seg(), vgafont16, 0x100, 0, regs->bl, 16);
++    set_scan_lines(16);
++}
++
++static void
++handle_101130(struct bregs *regs)
++{
++    switch (regs->bh) {
++    case 0x00: {
++        struct segoff_s so = GET_IVT(0x1f);
++        regs->es = so.seg;
++        regs->bp = so.offset;
++        break;
++    }
++    case 0x01: {
++        struct segoff_s so = GET_IVT(0x43);
++        regs->es = so.seg;
++        regs->bp = so.offset;
++        break;
++    }
++    case 0x02:
++        regs->es = get_global_seg();
++        regs->bp = (u32)vgafont14;
++        break;
++    case 0x03:
++        regs->es = get_global_seg();
++        regs->bp = (u32)vgafont8;
++        break;
++    case 0x04:
++        regs->es = get_global_seg();
++        regs->bp = (u32)vgafont8 + 128 * 8;
++        break;
++    case 0x05:
++        regs->es = get_global_seg();
++        regs->bp = (u32)vgafont14alt;
++        break;
++    case 0x06:
++        regs->es = get_global_seg();
++        regs->bp = (u32)vgafont16;
++        break;
++    case 0x07:
++        regs->es = get_global_seg();
++        regs->bp = (u32)vgafont16alt;
++        break;
++    default:
++        dprintf(1, "Get font info BH(%02x) was discarded\n", regs->bh);
++        return;
++    }
++    // Set byte/char of on screen font
++    regs->cx = GET_BDA(char_height) & 0xff;
++
++    // Set Highest char row
++    regs->dx = GET_BDA(video_rows);
++}
++
++static void
++handle_1011XX(struct bregs *regs)
++{
++    debug_stub(regs);
++}
++
++static void
++handle_1011(struct bregs *regs)
++{
++    switch (regs->al) {
++    case 0x00: handle_101100(regs); break;
++    case 0x01: handle_101101(regs); break;
++    case 0x02: handle_101102(regs); break;
++    case 0x03: handle_101103(regs); break;
++    case 0x04: handle_101104(regs); break;
++    case 0x10: handle_101110(regs); break;
++    case 0x11: handle_101111(regs); break;
++    case 0x12: handle_101112(regs); break;
++    case 0x14: handle_101114(regs); break;
++    case 0x30: handle_101130(regs); break;
++    default:   handle_1011XX(regs); break;
++    }
++}
++
++
++static void
++handle_101210(struct bregs *regs)
++{
++    u16 crtc_addr = GET_BDA(crtc_address);
++    if (crtc_addr == VGAREG_MDA_CRTC_ADDRESS)
++        regs->bx = 0x0103;
++    else
++        regs->bx = 0x0003;
++    regs->cx = GET_BDA(video_switches) & 0x0f;
++}
++
++static void
++handle_101230(struct bregs *regs)
++{
++    u8 mctl = GET_BDA(modeset_ctl);
++    u8 vswt = GET_BDA(video_switches);
++    switch (regs->al) {
++    case 0x00:
++        // 200 lines
++        mctl = (mctl & ~0x10) | 0x80;
++        vswt = (vswt & ~0x0f) | 0x08;
++        break;
++    case 0x01:
++        // 350 lines
++        mctl &= ~0x90;
++        vswt = (vswt & ~0x0f) | 0x09;
++        break;
++    case 0x02:
++        // 400 lines
++        mctl = (mctl & ~0x80) | 0x10;
++        vswt = (vswt & ~0x0f) | 0x09;
++        break;
++    default:
++        dprintf(1, "Select vert res (%02x) was discarded\n", regs->al);
++        break;
++    }
++    SET_BDA(modeset_ctl, mctl);
++    SET_BDA(video_switches, vswt);
++    regs->al = 0x12;
++}
++
++static void
++handle_101231(struct bregs *regs)
++{
++    u8 v = (regs->al & 0x01) << 3;
++    u8 mctl = GET_BDA(video_ctl) & ~0x08;
++    SET_BDA(video_ctl, mctl | v);
++    regs->al = 0x12;
++}
++
++static void
++handle_101232(struct bregs *regs)
++{
++    vgahw_enable_video_addressing(regs->al);
++    regs->al = 0x12;
++}
++
++static void
++handle_101233(struct bregs *regs)
++{
++    u8 v = ((regs->al << 1) & 0x02) ^ 0x02;
++    u8 v2 = GET_BDA(modeset_ctl) & ~0x02;
++    SET_BDA(modeset_ctl, v | v2);
++    regs->al = 0x12;
++}
++
++static void
++handle_101234(struct bregs *regs)
++{
++    u8 v = (regs->al & 0x01) ^ 0x01;
++    u8 v2 = GET_BDA(modeset_ctl) & ~0x01;
++    SET_BDA(modeset_ctl, v | v2);
++    regs->al = 0x12;
++}
++
++static void
++handle_101235(struct bregs *regs)
++{
++    debug_stub(regs);
++    regs->al = 0x12;
++}
++
++static void
++handle_101236(struct bregs *regs)
++{
++    debug_stub(regs);
++    regs->al = 0x12;
++}
++
++static void
++handle_1012XX(struct bregs *regs)
++{
++    debug_stub(regs);
++}
++
++static void
++handle_1012(struct bregs *regs)
++{
++    switch (regs->bl) {
++    case 0x10: handle_101210(regs); break;
++    case 0x30: handle_101230(regs); break;
++    case 0x31: handle_101231(regs); break;
++    case 0x32: handle_101232(regs); break;
++    case 0x33: handle_101233(regs); break;
++    case 0x34: handle_101234(regs); break;
++    case 0x35: handle_101235(regs); break;
++    case 0x36: handle_101236(regs); break;
++    default:   handle_1012XX(regs); break;
++    }
++
++    // XXX - cirrus has 1280, 1281, 1282, 1285, 129a, 12a0, 12a1, 12a2, 12ae
++}
++
++
++// Write string
++static void noinline
++handle_1013(struct bregs *regs)
++{
++    struct cursorpos cp = {regs->dl, regs->dh, regs->bh};
++    // if row=0xff special case : use current cursor position
++    if (cp.y == 0xff)
++        cp = get_cursor_pos(cp.page);
++    u8 flag = regs->al;
++    if (flag & 2)
++        write_attr_string(&cp, regs->cx, regs->es, (void*)(regs->bp + 0));
++    else
++        write_string(&cp, regs->bl, regs->cx, regs->es, (void*)(regs->bp + 0));
++
++    if (flag & 1)
++        set_cursor_pos(cp);
++}
++
++
++static void
++handle_101a00(struct bregs *regs)
++{
++    regs->bx = GET_BDA(dcc_index);
++    regs->al = 0x1a;
++}
++
++static void
++handle_101a01(struct bregs *regs)
++{
++    SET_BDA(dcc_index, regs->bl);
++    dprintf(1, "Alternate Display code (%02x) was discarded\n", regs->bh);
++    regs->al = 0x1a;
++}
++
++static void
++handle_101aXX(struct bregs *regs)
++{
++    debug_stub(regs);
++}
++
++static void
++handle_101a(struct bregs *regs)
++{
++    switch (regs->al) {
++    case 0x00: handle_101a00(regs); break;
++    case 0x01: handle_101a01(regs); break;
++    default:   handle_101aXX(regs); break;
++    }
++}
++
++
++struct funcInfo {
++    u16 static_functionality_off;
++    u16 static_functionality_seg;
++    u8 bda_0x49[30];
++    u8 bda_0x84[3];
++    u8 dcc_index;
++    u8 dcc_alt;
++    u16 colors;
++    u8 pages;
++    u8 scan_lines;
++    u8 primary_char;
++    u8 secondar_char;
++    u8 misc;
++    u8 non_vga_mode;
++    u8 reserved_2f[2];
++    u8 video_mem;
++    u8 save_flags;
++    u8 disp_info;
++    u8 reserved_34[12];
++};
++
++static void
++handle_101b(struct bregs *regs)
++{
++    u16 seg = regs->es;
++    struct funcInfo *info = (void*)(regs->di+0);
++    memset_far(seg, info, 0, sizeof(*info));
++    // Address of static functionality table
++    SET_FARVAR(seg, info->static_functionality_off, (u32)static_functionality);
++    SET_FARVAR(seg, info->static_functionality_seg, get_global_seg());
++
++    // Hard coded copy from BIOS area. Should it be cleaner ?
++    memcpy_far(seg, info->bda_0x49, SEG_BDA, (void*)0x49
++               , sizeof(info->bda_0x49));
++    memcpy_far(seg, info->bda_0x84, SEG_BDA, (void*)0x84
++               , sizeof(info->bda_0x84));
++
++    SET_FARVAR(seg, info->dcc_index, GET_BDA(dcc_index));
++    SET_FARVAR(seg, info->colors, 16);
++    SET_FARVAR(seg, info->pages, 8);
++    SET_FARVAR(seg, info->scan_lines, 2);
++    SET_FARVAR(seg, info->video_mem, 3);
++    regs->al = 0x1B;
++}
++
++
++static void
++handle_101c00(struct bregs *regs)
++{
++    u16 flags = regs->cx;
++    u16 size = 0;
++    if (flags & 1)
++        size += sizeof(struct saveVideoHardware);
++    if (flags & 2)
++        size += sizeof(struct saveBDAstate);
++    if (flags & 4)
++        size += sizeof(struct saveDACcolors);
++    regs->bx = size;
++    regs->al = 0x1c;
++}
++
++static void
++handle_101c01(struct bregs *regs)
++{
++    u16 flags = regs->cx;
++    u16 seg = regs->es;
++    void *data = (void*)(regs->bx+0);
++    if (flags & 1) {
++        vgahw_save_state(seg, data);
++        data += sizeof(struct saveVideoHardware);
++    }
++    if (flags & 2) {
++        save_bda_state(seg, data);
++        data += sizeof(struct saveBDAstate);
++    }
++    if (flags & 4)
++        vgahw_save_dac_state(seg, data);
++    regs->al = 0x1c;
++}
++
++static void
++handle_101c02(struct bregs *regs)
++{
++    u16 flags = regs->cx;
++    u16 seg = regs->es;
++    void *data = (void*)(regs->bx+0);
++    if (flags & 1) {
++        vgahw_restore_state(seg, data);
++        data += sizeof(struct saveVideoHardware);
++    }
++    if (flags & 2) {
++        restore_bda_state(seg, data);
++        data += sizeof(struct saveBDAstate);
++    }
++    if (flags & 4)
++        vgahw_restore_dac_state(seg, data);
++    regs->al = 0x1c;
++}
++
++static void
++handle_101cXX(struct bregs *regs)
++{
++    debug_stub(regs);
++}
++
++static void
++handle_101c(struct bregs *regs)
++{
++    switch (regs->al) {
++    case 0x00: handle_101c00(regs); break;
++    case 0x01: handle_101c01(regs); break;
++    case 0x02: handle_101c02(regs); break;
++    default:   handle_101cXX(regs); break;
++    }
++}
++
++
++static void
++handle_104f00(struct bregs *regs)
++{
++    // XXX - vbe_biosfn_return_controller_information(&AX,ES,DI);
++    // XXX - OR cirrus_vesa_00h
++}
++
++static void
++handle_104f01(struct bregs *regs)
++{
++    // XXX - vbe_biosfn_return_mode_information(&AX,CX,ES,DI);
++    // XXX - OR cirrus_vesa_01h
++}
++
++static void
++handle_104f02(struct bregs *regs)
++{
++    // XXX - vbe_biosfn_set_mode(&AX,BX,ES,DI);
++    // XXX - OR cirrus_vesa_02h
++}
++
++static void
++handle_104f03(struct bregs *regs)
++{
++    // XXX - vbe_biosfn_return_current_mode
++    // XXX - OR cirrus_vesa_03h
++}
++
++static void
++handle_104f04(struct bregs *regs)
++{
++    // XXX - vbe_biosfn_save_restore_state(&AX, CX, DX, ES, &BX);
++}
++
++static void
++handle_104f05(struct bregs *regs)
++{
++    // XXX - vbe_biosfn_display_window_control
++    // XXX - OR cirrus_vesa_05h
++}
++
++static void
++handle_104f06(struct bregs *regs)
++{
++    // XXX - vbe_biosfn_set_get_logical_scan_line_length
++    // XXX - OR cirrus_vesa_06h
++}
++
++static void
++handle_104f07(struct bregs *regs)
++{
++    // XXX - vbe_biosfn_set_get_display_start
++    // XXX - OR cirrus_vesa_07h
++}
++
++static void
++handle_104f08(struct bregs *regs)
++{
++    // XXX - vbe_biosfn_set_get_dac_palette_format
++}
++
++static void
++handle_104f0a(struct bregs *regs)
++{
++    // XXX - vbe_biosfn_return_protected_mode_interface
++}
++
++static void
++handle_104fXX(struct bregs *regs)
++{
++    debug_stub(regs);
++    regs->ax = 0x0100;
++}
++
++static void
++handle_104f(struct bregs *regs)
++{
++    if (! CONFIG_VBE || !vbe_has_vbe_display()) {
++        handle_104fXX(regs);
++        return;
++    }
++
++    switch (regs->al) {
++    case 0x00: handle_104f00(regs); break;
++    case 0x01: handle_104f01(regs); break;
++    case 0x02: handle_104f02(regs); break;
++    case 0x03: handle_104f03(regs); break;
++    case 0x04: handle_104f04(regs); break;
++    case 0x05: handle_104f05(regs); break;
++    case 0x06: handle_104f06(regs); break;
++    case 0x07: handle_104f07(regs); break;
++    case 0x08: handle_104f08(regs); break;
++    case 0x0a: handle_104f0a(regs); break;
++    default:   handle_104fXX(regs); break;
++    }
++}
++
++
++static void
++handle_10XX(struct bregs *regs)
++{
++    debug_stub(regs);
++}
++
++// INT 10h Video Support Service Entry Point
++void VISIBLE16
++handle_10(struct bregs *regs)
++{
++    debug_enter(regs, DEBUG_VGA_10);
++    switch (regs->ah) {
++    case 0x00: handle_1000(regs); break;
++    case 0x01: handle_1001(regs); break;
++    case 0x02: handle_1002(regs); break;
++    case 0x03: handle_1003(regs); break;
++    case 0x04: handle_1004(regs); break;
++    case 0x05: handle_1005(regs); break;
++    case 0x06: handle_1006(regs); break;
++    case 0x07: handle_1007(regs); break;
++    case 0x08: handle_1008(regs); break;
++    case 0x09: handle_1009(regs); break;
++    case 0x0a: handle_100a(regs); break;
++    case 0x0b: handle_100b(regs); break;
++    case 0x0c: handle_100c(regs); break;
++    case 0x0d: handle_100d(regs); break;
++    case 0x0e: handle_100e(regs); break;
++    case 0x0f: handle_100f(regs); break;
++    case 0x10: handle_1010(regs); break;
++    case 0x11: handle_1011(regs); break;
++    case 0x12: handle_1012(regs); break;
++    case 0x13: handle_1013(regs); break;
++    case 0x1a: handle_101a(regs); break;
++    case 0x1b: handle_101b(regs); break;
++    case 0x1c: handle_101c(regs); break;
++    case 0x4f: handle_104f(regs); break;
++    default:   handle_10XX(regs); break;
++    }
++}
++
++
++/****************************************************************
++ * VGA post
++ ****************************************************************/
++
++static void
++init_bios_area(void)
++{
++    // init detected hardware BIOS Area
++    // set 80x25 color (not clear from RBIL but usual)
++    u16 eqf = GET_BDA(equipment_list_flags);
++    SET_BDA(equipment_list_flags, (eqf & 0xffcf) | 0x20);
++
++    // Just for the first int10 find its children
++
++    // the default char height
++    SET_BDA(char_height, 0x10);
++
++    // Clear the screen
++    SET_BDA(video_ctl, 0x60);
++
++    // Set the basic screen we have
++    SET_BDA(video_switches, 0xf9);
++
++    // Set the basic modeset options
++    SET_BDA(modeset_ctl, 0x51);
++
++    // Set the  default MSR
++    SET_BDA(video_msr, 0x09);
++}
++
++void VISIBLE16
++vga_post(struct bregs *regs)
++{
++    debug_enter(regs, DEBUG_VGA_POST);
++
++    vgahw_init();
++
++    init_bios_area();
++
++    if (CONFIG_VBE)
++        vbe_init();
++
++    extern void entry_10(void);
++    SET_IVT(0x10, SEGOFF(get_global_seg(), (u32)entry_10));
++
++    if (CONFIG_CIRRUS)
++        cirrus_init();
++
++    // XXX - clear screen and display info
++
++    // XXX: fill it
++    SET_VGA(video_save_pointer_table[0], (u32)video_param_table);
++    SET_VGA(video_save_pointer_table[1], get_global_seg());
++
++    // Fixup checksum
++    extern u8 _rom_header_size, _rom_header_checksum;
++    SET_VGA(_rom_header_checksum, 0);
++    u8 sum = -checksum_far(get_global_seg(), 0, _rom_header_size * 512);
++    SET_VGA(_rom_header_checksum, sum);
++}
+--- x/roms/seabios/vgasrc/vgaentry.S	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/vgasrc/vgaentry.S	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,48 @@
++// Rom layout and bios assembler to C interface.
++//
++// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++
++/****************************************************************
++ * Include of 16bit C code
++ ****************************************************************/
++
++        .code16gcc
++.include "out/vgaccode.16.s"
++
++#include "entryfuncs.S" // ENTRY_*
++
++
++/****************************************************************
++ * Rom Header
++ ****************************************************************/
++
++        .section .rom.header
++        .global _rom_header, _rom_header_size, _rom_header_checksum
++_rom_header:
++        .word 0xaa55
++_rom_header_size:
++        .byte 0
++_rom_header_entry:
++        jmp _optionrom_entry
++_rom_header_checksum:
++        .byte 0
++_rom_header_other:
++        .space 21
++
++
++/****************************************************************
++ * Entry points
++ ****************************************************************/
++
++        DECLFUNC _optionrom_entry
++_optionrom_entry:
++        ENTRY_ARG vga_post
++        lretw
++
++        DECLFUNC entry_10
++entry_10:
++        ENTRY_ARG handle_10
++        iretw
+--- x/roms/seabios/vgasrc/vgafb.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/vgasrc/vgafb.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,512 @@
++// Code for manipulating VGA framebuffers.
++//
++// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2001-2008 the LGPL VGABios developers Team
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "biosvar.h" // GET_BDA
++#include "util.h" // memset_far
++#include "vgatables.h" // find_vga_entry
++
++
++/****************************************************************
++ * Screen scrolling
++ ****************************************************************/
++
++static inline void *
++memcpy_stride(u16 seg, void *dst, void *src, int copylen, int stride, int lines)
++{
++    for (; lines; lines--, dst+=stride, src+=stride)
++        memcpy_far(seg, dst, seg, src, copylen);
++    return dst;
++}
++
++static inline void
++memset_stride(u16 seg, void *dst, u8 val, int setlen, int stride, int lines)
++{
++    for (; lines; lines--, dst+=stride)
++        memset_far(seg, dst, val, setlen);
++}
++
++static inline void
++memset16_stride(u16 seg, void *dst, u16 val, int setlen, int stride, int lines)
++{
++    for (; lines; lines--, dst+=stride)
++        memset16_far(seg, dst, val, setlen);
++}
++
++static void
++scroll_pl4(struct vgamode_s *vmode_g, int nblines, int attr
++           , struct cursorpos ul, struct cursorpos lr)
++{
++    struct VideoParam_s *vparam_g = GET_GLOBAL(vmode_g->vparam);
++    u8 cheight = GET_GLOBAL(vparam_g->cheight);
++    int stride = GET_BDA(video_cols);
++    void *src_far, *dest_far;
++    if (nblines >= 0) {
++        dest_far = (void*)(ul.y * cheight * stride + ul.x);
++        src_far = dest_far + nblines * cheight * stride;
++    } else {
++        // Scroll down
++        nblines = -nblines;
++        dest_far = (void*)(lr.y * cheight * stride + ul.x);
++        src_far = dest_far - nblines * cheight * stride;
++        stride = -stride;
++    }
++    int cols = lr.x - ul.x + 1;
++    int rows = lr.y - ul.y + 1;
++    if (nblines < rows) {
++        vgahw_grdc_write(0x05, 0x01);
++        dest_far = memcpy_stride(SEG_GRAPH, dest_far, src_far, cols, stride
++                                 , (rows - nblines) * cheight);
++    }
++    if (attr < 0)
++        attr = 0;
++    vgahw_grdc_write(0x05, 0x02);
++    memset_stride(SEG_GRAPH, dest_far, attr, cols, stride, nblines * cheight);
++    vgahw_grdc_write(0x05, 0x00);
++}
++
++static void
++scroll_cga(struct vgamode_s *vmode_g, int nblines, int attr
++            , struct cursorpos ul, struct cursorpos lr)
++{
++    struct VideoParam_s *vparam_g = GET_GLOBAL(vmode_g->vparam);
++    u8 cheight = GET_GLOBAL(vparam_g->cheight);
++    u8 bpp = GET_GLOBAL(vmode_g->pixbits);
++    int stride = GET_BDA(video_cols) * bpp;
++    void *src_far, *dest_far;
++    if (nblines >= 0) {
++        dest_far = (void*)(ul.y * cheight * stride + ul.x * bpp);
++        src_far = dest_far + nblines * cheight * stride;
++    } else {
++        // Scroll down
++        nblines = -nblines;
++        dest_far = (void*)(lr.y * cheight * stride + ul.x * bpp);
++        src_far = dest_far - nblines * cheight * stride;
++        stride = -stride;
++    }
++    int cols = (lr.x - ul.x + 1) * bpp;
++    int rows = lr.y - ul.y + 1;
++    if (nblines < rows) {
++        memcpy_stride(SEG_CTEXT, dest_far + 0x2000, src_far + 0x2000, cols
++                      , stride, (rows - nblines) * cheight / 2);
++        dest_far = memcpy_stride(SEG_CTEXT, dest_far, src_far, cols
++                                 , stride, (rows - nblines) * cheight / 2);
++    }
++    if (attr < 0)
++        attr = 0;
++    memset_stride(SEG_CTEXT, dest_far + 0x2000, attr, cols
++                  , stride, nblines * cheight / 2);
++    memset_stride(SEG_CTEXT, dest_far, attr, cols
++                  , stride, nblines * cheight / 2);
++}
++
++static void
++scroll_text(struct vgamode_s *vmode_g, int nblines, int attr
++            , struct cursorpos ul, struct cursorpos lr)
++{
++    u16 nbrows = GET_BDA(video_rows) + 1;
++    u16 nbcols = GET_BDA(video_cols);
++    void *src_far, *dest_far = (void*)SCREEN_MEM_START(nbcols, nbrows, ul.page);
++    int stride = nbcols * 2;
++    if (nblines >= 0) {
++        dest_far += ul.y * stride + ul.x * 2;
++        src_far = dest_far + nblines * stride;
++    } else {
++        // Scroll down
++        nblines = -nblines;
++        dest_far += lr.y * stride + ul.x * 2;
++        src_far = dest_far - nblines * stride;
++        stride = -stride;
++    }
++    int cols = (lr.x - ul.x + 1) * 2;
++    int rows = lr.y - ul.y + 1;
++    u16 seg = GET_GLOBAL(vmode_g->sstart);
++    if (nblines < rows)
++        dest_far = memcpy_stride(seg, dest_far, src_far, cols, stride
++                                 , (rows - nblines));
++    if (attr < 0)
++        attr = 0x07;
++    attr = (attr << 8) | ' ';
++    memset16_stride(seg, dest_far, attr, cols, stride, nblines);
++}
++
++void
++vgafb_scroll(int nblines, int attr, struct cursorpos ul, struct cursorpos lr)
++{
++    // Get the mode
++    struct vgamode_s *vmode_g = find_vga_entry(GET_BDA(video_mode));
++    if (!vmode_g)
++        return;
++
++    // FIXME gfx mode not complete
++    switch (GET_GLOBAL(vmode_g->memmodel)) {
++    case CTEXT:
++    case MTEXT:
++        scroll_text(vmode_g, nblines, attr, ul, lr);
++        break;
++    case PLANAR4:
++    case PLANAR1:
++        scroll_pl4(vmode_g, nblines, attr, ul, lr);
++        break;
++    case CGA:
++        scroll_cga(vmode_g, nblines, attr, ul, lr);
++        break;
++    default:
++        dprintf(1, "Scroll in graphics mode\n");
++    }
++}
++
++void
++clear_screen(struct vgamode_s *vmode_g)
++{
++    switch (GET_GLOBAL(vmode_g->memmodel)) {
++    case CTEXT:
++    case MTEXT:
++        memset16_far(GET_GLOBAL(vmode_g->sstart), 0, 0x0720, 32*1024);
++        break;
++    case CGA:
++        memset16_far(GET_GLOBAL(vmode_g->sstart), 0, 0x0000, 32*1024);
++        break;
++    default:
++        // XXX - old code gets/sets/restores sequ register 2 to 0xf -
++        // but it should always be 0xf anyway.
++        memset16_far(GET_GLOBAL(vmode_g->sstart), 0, 0x0000, 64*1024);
++    }
++}
++
++
++/****************************************************************
++ * Read/write characters to screen
++ ****************************************************************/
++
++static void
++write_gfx_char_pl4(struct vgamode_s *vmode_g
++                   , struct cursorpos cp, struct carattr ca)
++{
++    u16 nbcols = GET_BDA(video_cols);
++    if (cp.x >= nbcols)
++        return;
++
++    struct VideoParam_s *vparam_g = GET_GLOBAL(vmode_g->vparam);
++    u8 cheight = GET_GLOBAL(vparam_g->cheight);
++    u8 *fdata_g;
++    switch (cheight) {
++    case 14:
++        fdata_g = vgafont14;
++        break;
++    case 16:
++        fdata_g = vgafont16;
++        break;
++    default:
++        fdata_g = vgafont8;
++    }
++    u16 addr = cp.x + cp.y * cheight * nbcols;
++    u16 src = ca.car * cheight;
++    vgahw_sequ_write(0x02, 0x0f);
++    vgahw_grdc_write(0x05, 0x02);
++    if (ca.attr & 0x80)
++        vgahw_grdc_write(0x03, 0x18);
++    else
++        vgahw_grdc_write(0x03, 0x00);
++    u8 i;
++    for (i = 0; i < cheight; i++) {
++        u8 *dest_far = (void*)(addr + i * nbcols);
++        u8 j;
++        for (j = 0; j < 8; j++) {
++            u8 mask = 0x80 >> j;
++            vgahw_grdc_write(0x08, mask);
++            GET_FARVAR(SEG_GRAPH, *dest_far);
++            if (GET_GLOBAL(fdata_g[src + i]) & mask)
++                SET_FARVAR(SEG_GRAPH, *dest_far, ca.attr & 0x0f);
++            else
++                SET_FARVAR(SEG_GRAPH, *dest_far, 0x00);
++        }
++    }
++    vgahw_grdc_write(0x08, 0xff);
++    vgahw_grdc_write(0x05, 0x00);
++    vgahw_grdc_write(0x03, 0x00);
++}
++
++static void
++write_gfx_char_cga(struct vgamode_s *vmode_g
++                   , struct cursorpos cp, struct carattr ca)
++{
++    u16 nbcols = GET_BDA(video_cols);
++    if (cp.x >= nbcols)
++        return;
++
++    u8 *fdata_g = vgafont8;
++    u8 bpp = GET_GLOBAL(vmode_g->pixbits);
++    u16 addr = (cp.x * bpp) + cp.y * 320;
++    u16 src = ca.car * 8;
++    u8 i;
++    for (i = 0; i < 8; i++) {
++        u8 *dest_far = (void*)(addr + (i >> 1) * 80);
++        if (i & 1)
++            dest_far += 0x2000;
++        u8 mask = 0x80;
++        if (bpp == 1) {
++            u8 data = 0;
++            if (ca.attr & 0x80)
++                data = GET_FARVAR(SEG_CTEXT, *dest_far);
++            u8 j;
++            for (j = 0; j < 8; j++) {
++                if (GET_GLOBAL(fdata_g[src + i]) & mask) {
++                    if (ca.attr & 0x80)
++                        data ^= (ca.attr & 0x01) << (7 - j);
++                    else
++                        data |= (ca.attr & 0x01) << (7 - j);
++                }
++                mask >>= 1;
++            }
++            SET_FARVAR(SEG_CTEXT, *dest_far, data);
++        } else {
++            while (mask > 0) {
++                u8 data = 0;
++                if (ca.attr & 0x80)
++                    data = GET_FARVAR(SEG_CTEXT, *dest_far);
++                u8 j;
++                for (j = 0; j < 4; j++) {
++                    if (GET_GLOBAL(fdata_g[src + i]) & mask) {
++                        if (ca.attr & 0x80)
++                            data ^= (ca.attr & 0x03) << ((3 - j) * 2);
++                        else
++                            data |= (ca.attr & 0x03) << ((3 - j) * 2);
++                    }
++                    mask >>= 1;
++                }
++                SET_FARVAR(SEG_CTEXT, *dest_far, data);
++                dest_far += 1;
++            }
++        }
++    }
++}
++
++static void
++write_gfx_char_lin(struct vgamode_s *vmode_g
++                   , struct cursorpos cp, struct carattr ca)
++{
++    // Get the dimensions
++    u16 nbcols = GET_BDA(video_cols);
++    if (cp.x >= nbcols)
++        return;
++
++    u8 *fdata_g = vgafont8;
++    u16 addr = cp.x * 8 + cp.y * nbcols * 64;
++    u16 src = ca.car * 8;
++    u8 i;
++    for (i = 0; i < 8; i++) {
++        u8 *dest_far = (void*)(addr + i * nbcols * 8);
++        u8 mask = 0x80;
++        u8 j;
++        for (j = 0; j < 8; j++) {
++            u8 data = 0x00;
++            if (GET_GLOBAL(fdata_g[src + i]) & mask)
++                data = ca.attr;
++            SET_FARVAR(SEG_GRAPH, dest_far[j], data);
++            mask >>= 1;
++        }
++    }
++}
++
++static void
++write_text_char(struct vgamode_s *vmode_g
++                , struct cursorpos cp, struct carattr ca)
++{
++    // Get the dimensions
++    u16 nbrows = GET_BDA(video_rows) + 1;
++    u16 nbcols = GET_BDA(video_cols);
++
++    // Compute the address
++    void *address_far = (void*)(SCREEN_MEM_START(nbcols, nbrows, cp.page)
++                                + (cp.x + cp.y * nbcols) * 2);
++
++    if (ca.use_attr) {
++        u16 dummy = (ca.attr << 8) | ca.car;
++        SET_FARVAR(GET_GLOBAL(vmode_g->sstart), *(u16*)address_far, dummy);
++    } else {
++        SET_FARVAR(GET_GLOBAL(vmode_g->sstart), *(u8*)address_far, ca.car);
++    }
++}
++
++void
++vgafb_write_char(struct cursorpos cp, struct carattr ca)
++{
++    // Get the mode
++    struct vgamode_s *vmode_g = find_vga_entry(GET_BDA(video_mode));
++    if (!vmode_g)
++        return;
++
++    // FIXME gfx mode not complete
++    switch (GET_GLOBAL(vmode_g->memmodel)) {
++    case CTEXT:
++    case MTEXT:
++        write_text_char(vmode_g, cp, ca);
++        break;
++    case PLANAR4:
++    case PLANAR1:
++        write_gfx_char_pl4(vmode_g, cp, ca);
++        break;
++    case CGA:
++        write_gfx_char_cga(vmode_g, cp, ca);
++        break;
++    case LINEAR8:
++        write_gfx_char_lin(vmode_g, cp, ca);
++        break;
++    }
++}
++
++struct carattr
++vgafb_read_char(struct cursorpos cp)
++{
++    // Get the mode
++    struct vgamode_s *vmode_g = find_vga_entry(GET_BDA(video_mode));
++    if (!vmode_g)
++        goto fail;
++
++    if (!(GET_GLOBAL(vmode_g->memmodel) & TEXT)) {
++        // FIXME gfx mode
++        dprintf(1, "Read char in graphics mode\n");
++        goto fail;
++    }
++
++    // Get the dimensions
++    u16 nbrows = GET_BDA(video_rows) + 1;
++    u16 nbcols = GET_BDA(video_cols);
++
++    // Compute the address
++    u16 *address_far = (void*)(SCREEN_MEM_START(nbcols, nbrows, cp.page)
++                               + (cp.x + cp.y * nbcols) * 2);
++    u16 v = GET_FARVAR(GET_GLOBAL(vmode_g->sstart), *address_far);
++    struct carattr ca = {v, v>>8, 0};
++    return ca;
++
++fail: ;
++    struct carattr ca2 = {0, 0, 0};
++    return ca2;
++}
++
++
++/****************************************************************
++ * Read/write pixels
++ ****************************************************************/
++
++void
++vgafb_write_pixel(u8 color, u16 x, u16 y)
++{
++    // Get the mode
++    struct vgamode_s *vmode_g = find_vga_entry(GET_BDA(video_mode));
++    if (!vmode_g)
++        return;
++    if (GET_GLOBAL(vmode_g->memmodel) & TEXT)
++        return;
++
++    u8 *addr_far, mask, attr, data;
++    switch (GET_GLOBAL(vmode_g->memmodel)) {
++    case PLANAR4:
++    case PLANAR1:
++        addr_far = (void*)(x / 8 + y * GET_BDA(video_cols));
++        mask = 0x80 >> (x & 0x07);
++        vgahw_grdc_write(0x08, mask);
++        vgahw_grdc_write(0x05, 0x02);
++        data = GET_FARVAR(SEG_GRAPH, *addr_far);
++        if (color & 0x80)
++            vgahw_grdc_write(0x03, 0x18);
++        SET_FARVAR(SEG_GRAPH, *addr_far, color);
++        vgahw_grdc_write(0x08, 0xff);
++        vgahw_grdc_write(0x05, 0x00);
++        vgahw_grdc_write(0x03, 0x00);
++        break;
++    case CGA:
++        if (GET_GLOBAL(vmode_g->pixbits) == 2)
++            addr_far = (void*)((x >> 2) + (y >> 1) * 80);
++        else
++            addr_far = (void*)((x >> 3) + (y >> 1) * 80);
++        if (y & 1)
++            addr_far += 0x2000;
++        data = GET_FARVAR(SEG_CTEXT, *addr_far);
++        if (GET_GLOBAL(vmode_g->pixbits) == 2) {
++            attr = (color & 0x03) << ((3 - (x & 0x03)) * 2);
++            mask = 0x03 << ((3 - (x & 0x03)) * 2);
++        } else {
++            attr = (color & 0x01) << (7 - (x & 0x07));
++            mask = 0x01 << (7 - (x & 0x07));
++        }
++        if (color & 0x80) {
++            data ^= attr;
++        } else {
++            data &= ~mask;
++            data |= attr;
++        }
++        SET_FARVAR(SEG_CTEXT, *addr_far, data);
++        break;
++    case LINEAR8:
++        addr_far = (void*)(x + y * (GET_BDA(video_cols) * 8));
++        SET_FARVAR(SEG_GRAPH, *addr_far, color);
++        break;
++    }
++}
++
++u8
++vgafb_read_pixel(u16 x, u16 y)
++{
++    // Get the mode
++    struct vgamode_s *vmode_g = find_vga_entry(GET_BDA(video_mode));
++    if (!vmode_g)
++        return 0;
++    if (GET_GLOBAL(vmode_g->memmodel) & TEXT)
++        return 0;
++
++    u8 *addr_far, mask, attr=0, data, i;
++    switch (GET_GLOBAL(vmode_g->memmodel)) {
++    case PLANAR4:
++    case PLANAR1:
++        addr_far = (void*)(x / 8 + y * GET_BDA(video_cols));
++        mask = 0x80 >> (x & 0x07);
++        attr = 0x00;
++        for (i = 0; i < 4; i++) {
++            vgahw_grdc_write(0x04, i);
++            data = GET_FARVAR(SEG_GRAPH, *addr_far) & mask;
++            if (data > 0)
++                attr |= (0x01 << i);
++        }
++        break;
++    case CGA:
++        addr_far = (void*)((x >> 2) + (y >> 1) * 80);
++        if (y & 1)
++            addr_far += 0x2000;
++        data = GET_FARVAR(SEG_CTEXT, *addr_far);
++        if (GET_GLOBAL(vmode_g->pixbits) == 2)
++            attr = (data >> ((3 - (x & 0x03)) * 2)) & 0x03;
++        else
++            attr = (data >> (7 - (x & 0x07))) & 0x01;
++        break;
++    case LINEAR8:
++        addr_far = (void*)(x + y * (GET_BDA(video_cols) * 8));
++        attr = GET_FARVAR(SEG_GRAPH, *addr_far);
++        break;
++    }
++    return attr;
++}
++
++
++/****************************************************************
++ * Font loading
++ ****************************************************************/
++
++void
++vgafb_load_font(u16 seg, void *src_far, u16 count
++                , u16 start, u8 destflags, u8 fontsize)
++{
++    get_font_access();
++    u16 blockaddr = ((destflags & 0x03) << 14) + ((destflags & 0x04) << 11);
++    void *dest_far = (void*)(blockaddr + start*32);
++    u16 i;
++    for (i = 0; i < count; i++)
++        memcpy_far(SEG_GRAPH, dest_far + i*32
++                   , seg, src_far + i*fontsize, fontsize);
++    release_font_access();
++}
+--- x/roms/seabios/vgasrc/vgafonts.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/vgasrc/vgafonts.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,785 @@
++#include "vgatables.h" // vgafont8
++
++/*
++ * These fonts come from ftp://ftp.simtel.net/pub/simtelnet/msdos/screen/fntcol16.zip
++ * The package is (c) by Joseph Gil
++ * The individual fonts are public domain
++ */
++u8 vgafont8[256 * 8] VAR16 = {
++    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++    0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e,
++    0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e,
++    0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00,
++    0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00,
++    0x38, 0x7c, 0x38, 0xfe, 0xfe, 0x7c, 0x38, 0x7c,
++    0x10, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x7c,
++    0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00,
++    0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff,
++    0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00,
++    0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff,
++    0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78,
++    0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18,
++    0x3f, 0x33, 0x3f, 0x30, 0x30, 0x70, 0xf0, 0xe0,
++    0x7f, 0x63, 0x7f, 0x63, 0x63, 0x67, 0xe6, 0xc0,
++    0x99, 0x5a, 0x3c, 0xe7, 0xe7, 0x3c, 0x5a, 0x99,
++    0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00,
++    0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00,
++    0x18, 0x3c, 0x7e, 0x18, 0x18, 0x7e, 0x3c, 0x18,
++    0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00,
++    0x7f, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x00,
++    0x3e, 0x63, 0x38, 0x6c, 0x6c, 0x38, 0xcc, 0x78,
++    0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00,
++    0x18, 0x3c, 0x7e, 0x18, 0x7e, 0x3c, 0x18, 0xff,
++    0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x00,
++    0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00,
++    0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00,
++    0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00,
++    0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00,
++    0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00,
++    0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x00, 0x00,
++    0x00, 0xff, 0xff, 0x7e, 0x3c, 0x18, 0x00, 0x00,
++    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++    0x30, 0x78, 0x78, 0x30, 0x30, 0x00, 0x30, 0x00,
++    0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00,
++    0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00,
++    0x30, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x30, 0x00,
++    0x00, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xc6, 0x00,
++    0x38, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0x76, 0x00,
++    0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
++    0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00,
++    0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00,
++    0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00,
++    0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00,
++    0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x60,
++    0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00,
++    0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00,
++    0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00,
++    0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0x7c, 0x00,
++    0x30, 0x70, 0x30, 0x30, 0x30, 0x30, 0xfc, 0x00,
++    0x78, 0xcc, 0x0c, 0x38, 0x60, 0xcc, 0xfc, 0x00,
++    0x78, 0xcc, 0x0c, 0x38, 0x0c, 0xcc, 0x78, 0x00,
++    0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00,
++    0xfc, 0xc0, 0xf8, 0x0c, 0x0c, 0xcc, 0x78, 0x00,
++    0x38, 0x60, 0xc0, 0xf8, 0xcc, 0xcc, 0x78, 0x00,
++    0xfc, 0xcc, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00,
++    0x78, 0xcc, 0xcc, 0x78, 0xcc, 0xcc, 0x78, 0x00,
++    0x78, 0xcc, 0xcc, 0x7c, 0x0c, 0x18, 0x70, 0x00,
++    0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00,
++    0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x60,
++    0x18, 0x30, 0x60, 0xc0, 0x60, 0x30, 0x18, 0x00,
++    0x00, 0x00, 0xfc, 0x00, 0x00, 0xfc, 0x00, 0x00,
++    0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00,
++    0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00,
++    0x7c, 0xc6, 0xde, 0xde, 0xde, 0xc0, 0x78, 0x00,
++    0x30, 0x78, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0x00,
++    0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00,
++    0x3c, 0x66, 0xc0, 0xc0, 0xc0, 0x66, 0x3c, 0x00,
++    0xf8, 0x6c, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00,
++    0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00,
++    0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00,
++    0x3c, 0x66, 0xc0, 0xc0, 0xce, 0x66, 0x3e, 0x00,
++    0xcc, 0xcc, 0xcc, 0xfc, 0xcc, 0xcc, 0xcc, 0x00,
++    0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
++    0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00,
++    0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00,
++    0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00,
++    0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0x00,
++    0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00,
++    0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00,
++    0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00,
++    0x78, 0xcc, 0xcc, 0xcc, 0xdc, 0x78, 0x1c, 0x00,
++    0xfc, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0xe6, 0x00,
++    0x78, 0xcc, 0xe0, 0x70, 0x1c, 0xcc, 0x78, 0x00,
++    0xfc, 0xb4, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
++    0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xfc, 0x00,
++    0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00,
++    0xc6, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x00,
++    0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00,
++    0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x30, 0x78, 0x00,
++    0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00,
++    0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00,
++    0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00,
++    0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00,
++    0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00,
++    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
++    0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
++    0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00,
++    0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0xdc, 0x00,
++    0x00, 0x00, 0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x00,
++    0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00,
++    0x00, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00,
++    0x38, 0x6c, 0x60, 0xf0, 0x60, 0x60, 0xf0, 0x00,
++    0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
++    0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00,
++    0x30, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
++    0x0c, 0x00, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78,
++    0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00,
++    0x70, 0x30, 0x30, 0x30, 0x30, 0x30, 0x78, 0x00,
++    0x00, 0x00, 0xcc, 0xfe, 0xfe, 0xd6, 0xc6, 0x00,
++    0x00, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0xcc, 0x00,
++    0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00,
++    0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0,
++    0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e,
++    0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0xf0, 0x00,
++    0x00, 0x00, 0x7c, 0xc0, 0x78, 0x0c, 0xf8, 0x00,
++    0x10, 0x30, 0x7c, 0x30, 0x30, 0x34, 0x18, 0x00,
++    0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00,
++    0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x78, 0x30, 0x00,
++    0x00, 0x00, 0xc6, 0xd6, 0xfe, 0xfe, 0x6c, 0x00,
++    0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00,
++    0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
++    0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00,
++    0x1c, 0x30, 0x30, 0xe0, 0x30, 0x30, 0x1c, 0x00,
++    0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00,
++    0xe0, 0x30, 0x30, 0x1c, 0x30, 0x30, 0xe0, 0x00,
++    0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++    0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00,
++    0x78, 0xcc, 0xc0, 0xcc, 0x78, 0x18, 0x0c, 0x78,
++    0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00,
++    0x1c, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00,
++    0x7e, 0xc3, 0x3c, 0x06, 0x3e, 0x66, 0x3f, 0x00,
++    0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00,
++    0xe0, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00,
++    0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00,
++    0x00, 0x00, 0x78, 0xc0, 0xc0, 0x78, 0x0c, 0x38,
++    0x7e, 0xc3, 0x3c, 0x66, 0x7e, 0x60, 0x3c, 0x00,
++    0xcc, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00,
++    0xe0, 0x00, 0x78, 0xcc, 0xfc, 0xc0, 0x78, 0x00,
++    0xcc, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
++    0x7c, 0xc6, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00,
++    0xe0, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
++    0xc6, 0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00,
++    0x30, 0x30, 0x00, 0x78, 0xcc, 0xfc, 0xcc, 0x00,
++    0x1c, 0x00, 0xfc, 0x60, 0x78, 0x60, 0xfc, 0x00,
++    0x00, 0x00, 0x7f, 0x0c, 0x7f, 0xcc, 0x7f, 0x00,
++    0x3e, 0x6c, 0xcc, 0xfe, 0xcc, 0xcc, 0xce, 0x00,
++    0x78, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00,
++    0x00, 0xcc, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00,
++    0x00, 0xe0, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00,
++    0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00,
++    0x00, 0xe0, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00,
++    0x00, 0xcc, 0x00, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
++    0xc3, 0x18, 0x3c, 0x66, 0x66, 0x3c, 0x18, 0x00,
++    0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00,
++    0x18, 0x18, 0x7e, 0xc0, 0xc0, 0x7e, 0x18, 0x18,
++    0x38, 0x6c, 0x64, 0xf0, 0x60, 0xe6, 0xfc, 0x00,
++    0xcc, 0xcc, 0x78, 0xfc, 0x30, 0xfc, 0x30, 0x30,
++    0xf8, 0xcc, 0xcc, 0xfa, 0xc6, 0xcf, 0xc6, 0xc7,
++    0x0e, 0x1b, 0x18, 0x3c, 0x18, 0x18, 0xd8, 0x70,
++    0x1c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x7e, 0x00,
++    0x38, 0x00, 0x70, 0x30, 0x30, 0x30, 0x78, 0x00,
++    0x00, 0x1c, 0x00, 0x78, 0xcc, 0xcc, 0x78, 0x00,
++    0x00, 0x1c, 0x00, 0xcc, 0xcc, 0xcc, 0x7e, 0x00,
++    0x00, 0xf8, 0x00, 0xf8, 0xcc, 0xcc, 0xcc, 0x00,
++    0xfc, 0x00, 0xcc, 0xec, 0xfc, 0xdc, 0xcc, 0x00,
++    0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00,
++    0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00,
++    0x30, 0x00, 0x30, 0x60, 0xc0, 0xcc, 0x78, 0x00,
++    0x00, 0x00, 0x00, 0xfc, 0xc0, 0xc0, 0x00, 0x00,
++    0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00,
++    0xc3, 0xc6, 0xcc, 0xde, 0x33, 0x66, 0xcc, 0x0f,
++    0xc3, 0xc6, 0xcc, 0xdb, 0x37, 0x6f, 0xcf, 0x03,
++    0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00,
++    0x00, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x00, 0x00,
++    0x00, 0xcc, 0x66, 0x33, 0x66, 0xcc, 0x00, 0x00,
++    0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88,
++    0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
++    0xdb, 0x77, 0xdb, 0xee, 0xdb, 0x77, 0xdb, 0xee,
++    0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++    0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18,
++    0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18,
++    0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36,
++    0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36,
++    0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18,
++    0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36,
++    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++    0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36,
++    0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00,
++    0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00,
++    0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00,
++    0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18,
++    0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00,
++    0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00,
++    0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18,
++    0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18,
++    0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
++    0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18,
++    0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18,
++    0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36,
++    0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00,
++    0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36,
++    0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00,
++    0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36,
++    0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36,
++    0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
++    0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36,
++    0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
++    0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00,
++    0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18,
++    0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36,
++    0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00,
++    0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00,
++    0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18,
++    0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36,
++    0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36,
++    0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18,
++    0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00,
++    0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18,
++    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++    0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
++    0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
++    0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
++    0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
++    0x00, 0x00, 0x76, 0xdc, 0xc8, 0xdc, 0x76, 0x00,
++    0x00, 0x78, 0xcc, 0xf8, 0xcc, 0xf8, 0xc0, 0xc0,
++    0x00, 0xfc, 0xcc, 0xc0, 0xc0, 0xc0, 0xc0, 0x00,
++    0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00,
++    0xfc, 0xcc, 0x60, 0x30, 0x60, 0xcc, 0xfc, 0x00,
++    0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0x70, 0x00,
++    0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0xc0,
++    0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x00,
++    0xfc, 0x30, 0x78, 0xcc, 0xcc, 0x78, 0x30, 0xfc,
++    0x38, 0x6c, 0xc6, 0xfe, 0xc6, 0x6c, 0x38, 0x00,
++    0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x6c, 0xee, 0x00,
++    0x1c, 0x30, 0x18, 0x7c, 0xcc, 0xcc, 0x78, 0x00,
++    0x00, 0x00, 0x7e, 0xdb, 0xdb, 0x7e, 0x00, 0x00,
++    0x06, 0x0c, 0x7e, 0xdb, 0xdb, 0x7e, 0x60, 0xc0,
++    0x38, 0x60, 0xc0, 0xf8, 0xc0, 0x60, 0x38, 0x00,
++    0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x00,
++    0x00, 0xfc, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x00,
++    0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0xfc, 0x00,
++    0x60, 0x30, 0x18, 0x30, 0x60, 0x00, 0xfc, 0x00,
++    0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0xfc, 0x00,
++    0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18,
++    0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70,
++    0x30, 0x30, 0x00, 0xfc, 0x00, 0x30, 0x30, 0x00,
++    0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00,
++    0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
++    0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
++    0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
++    0x0f, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x1c,
++    0x78, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00,
++    0x70, 0x18, 0x30, 0x60, 0x78, 0x00, 0x00, 0x00,
++    0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
++    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
++};
++
++u8 vgafont14[256 * 14] VAR16 = {
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, 0x7e, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0x7e, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
++ 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff,
++ 0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00,
++ 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x02, 0x06, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00,
++ 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00,
++ 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x28, 0x6c, 0xfe, 0x6c, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
++ 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00,
++ 0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x66, 0xc6, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
++ 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7c, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xe6, 0x66, 0x6c, 0x6c, 0x78, 0x6c, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xc6, 0xee, 0xfe, 0xfe, 0xd6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00,
++ 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xd6, 0xfe, 0x7c, 0x6c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0xc6, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xfe, 0xc6, 0x8c, 0x18, 0x30, 0x60, 0xc2, 0xc6, 0xfe, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00,
++ 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00,
++ 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00,
++ 0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00,
++ 0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0xfe, 0xd6, 0xd6, 0xd6, 0xc6, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x70, 0x1c, 0xc6, 0x7c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x6c, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x66, 0xfe, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00,
++ 0x00, 0x00, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
++ 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
++ 0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
++ 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
++ 0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00,
++ 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xcc, 0xcc, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
++ 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x66, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
++ 0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
++ 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
++ 0x00, 0xc6, 0xc6, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00,
++ 0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x00, 0x00,
++ 0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0xcc, 0x76, 0x36, 0x7e, 0xd8, 0xd8, 0x6e, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00,
++ 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xc6, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
++ 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
++ 0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
++ 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xc6, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00,
++ 0x00, 0xc6, 0xc6, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00,
++ 0x00, 0xc6, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
++ 0x00, 0x18, 0x18, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00,
++ 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00,
++ 0x00, 0xf8, 0xcc, 0xcc, 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0xcc, 0xc6, 0x00, 0x00, 0x00,
++ 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00,
++ 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
++ 0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00,
++ 0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
++ 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00,
++ 0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0x00, 0x00, 0x00,
++ 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0xc0, 0xc0, 0xc6, 0xcc, 0xd8, 0x30, 0x60, 0xdc, 0x86, 0x0c, 0x18, 0x3e, 0x00,
++ 0x00, 0xc0, 0xc0, 0xc6, 0xcc, 0xd8, 0x30, 0x66, 0xce, 0x9e, 0x3e, 0x06, 0x06, 0x00,
++ 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
++ 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
++ 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
++ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfc, 0xc6, 0xc6, 0xfc, 0xc0, 0xc0, 0x40, 0x00,
++ 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00,
++ 0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
++};
++
++u8 vgafont16[256 * 16] VAR16 = {
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0x00, 0x00, 0x1e, 0x0e, 0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, 0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7f, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
++ 0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, 0x18, 0x18, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, 0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xdb, 0xdb, 0xc3, 0xc3, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xde, 0xde, 0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xf8, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xc3, 0xe7, 0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x0c, 0x0e, 0x00, 0x00,
++ 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00,
++ 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00,
++ 0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xe0, 0x60, 0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00,
++ 0x00, 0x00, 0xe0, 0x60, 0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00,
++ 0x00, 0x00, 0xe0, 0x60, 0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, 0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, 0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x10, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00,
++ 0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x10, 0x38, 0x6c, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x38, 0x6c, 0x38, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, 0x3c, 0x00, 0x00, 0x00,
++ 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x18, 0x3c, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
++ 0x38, 0x6c, 0x38, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
++ 0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, 0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x3e, 0x6c, 0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xc6, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00,
++ 0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x18, 0x18, 0x7e, 0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0x70, 0x00, 0x00,
++ 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x0c, 0x18, 0x30, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x76, 0xdc, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00,
++ 0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, 0x0c, 0x1f, 0x00, 0x00,
++ 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00,
++ 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44,
++ 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
++ 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
++ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
++ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
++ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, 0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
++};
++u8 vgafont14alt[1] VAR16;
++u8 vgafont16alt[1] VAR16;
+--- x/roms/seabios/vgasrc/vgaio.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/vgasrc/vgaio.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,555 @@
++// VGA io port access
++//
++// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2001-2008 the LGPL VGABios developers Team
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "ioport.h" // outb
++#include "farptr.h" // SET_FARVAR
++#include "biosvar.h" // GET_BDA
++#include "vgatables.h" // VGAREG_*
++
++// TODO
++//  * replace direct in/out calls with wrapper functions
++
++
++/****************************************************************
++ * Attribute control
++ ****************************************************************/
++
++void
++vgahw_screen_disable(void)
++{
++    inb(VGAREG_ACTL_RESET);
++    outb(0x00, VGAREG_ACTL_ADDRESS);
++}
++
++void
++vgahw_screen_enable(void)
++{
++    inb(VGAREG_ACTL_RESET);
++    outb(0x20, VGAREG_ACTL_ADDRESS);
++}
++
++void
++vgahw_set_border_color(u8 color)
++{
++    inb(VGAREG_ACTL_RESET);
++    outb(0x00, VGAREG_ACTL_ADDRESS);
++    u8 v1 = color & 0x0f;
++    if (v1 & 0x08)
++        v1 += 0x08;
++    outb(v1, VGAREG_ACTL_WRITE_DATA);
++
++    u8 v2 = color & 0x10;
++    int i;
++    for (i = 1; i < 4; i++) {
++        outb(i, VGAREG_ACTL_ADDRESS);
++
++        u8 cur = inb(VGAREG_ACTL_READ_DATA);
++        cur &= 0xef;
++        cur |= v2;
++        outb(cur, VGAREG_ACTL_WRITE_DATA);
++    }
++    outb(0x20, VGAREG_ACTL_ADDRESS);
++}
++
++void
++vgahw_set_overscan_border_color(u8 color)
++{
++    inb(VGAREG_ACTL_RESET);
++    outb(0x11, VGAREG_ACTL_ADDRESS);
++    outb(color, VGAREG_ACTL_WRITE_DATA);
++    outb(0x20, VGAREG_ACTL_ADDRESS);
++}
++
++u8
++vgahw_get_overscan_border_color(void)
++{
++    inb(VGAREG_ACTL_RESET);
++    outb(0x11, VGAREG_ACTL_ADDRESS);
++    u8 v = inb(VGAREG_ACTL_READ_DATA);
++    inb(VGAREG_ACTL_RESET);
++    outb(0x20, VGAREG_ACTL_ADDRESS);
++    return v;
++}
++
++void
++vgahw_set_palette(u8 palid)
++{
++    inb(VGAREG_ACTL_RESET);
++    palid &= 0x01;
++    int i;
++    for (i = 1; i < 4; i++) {
++        outb(i, VGAREG_ACTL_ADDRESS);
++
++        u8 v = inb(VGAREG_ACTL_READ_DATA);
++        v &= 0xfe;
++        v |= palid;
++        outb(v, VGAREG_ACTL_WRITE_DATA);
++    }
++    outb(0x20, VGAREG_ACTL_ADDRESS);
++}
++
++void
++vgahw_set_single_palette_reg(u8 reg, u8 val)
++{
++    inb(VGAREG_ACTL_RESET);
++    outb(reg, VGAREG_ACTL_ADDRESS);
++    outb(val, VGAREG_ACTL_WRITE_DATA);
++    outb(0x20, VGAREG_ACTL_ADDRESS);
++}
++
++u8
++vgahw_get_single_palette_reg(u8 reg)
++{
++    inb(VGAREG_ACTL_RESET);
++    outb(reg, VGAREG_ACTL_ADDRESS);
++    u8 v = inb(VGAREG_ACTL_READ_DATA);
++    inb(VGAREG_ACTL_RESET);
++    outb(0x20, VGAREG_ACTL_ADDRESS);
++    return v;
++}
++
++void
++vgahw_set_all_palette_reg(u16 seg, u8 *data_far)
++{
++    inb(VGAREG_ACTL_RESET);
++    int i;
++    for (i = 0; i < 0x10; i++) {
++        outb(i, VGAREG_ACTL_ADDRESS);
++        u8 val = GET_FARVAR(seg, *data_far);
++        outb(val, VGAREG_ACTL_WRITE_DATA);
++        data_far++;
++    }
++    outb(0x11, VGAREG_ACTL_ADDRESS);
++    outb(GET_FARVAR(seg, *data_far), VGAREG_ACTL_WRITE_DATA);
++    outb(0x20, VGAREG_ACTL_ADDRESS);
++}
++
++void
++vgahw_get_all_palette_reg(u16 seg, u8 *data_far)
++{
++    int i;
++    for (i = 0; i < 0x10; i++) {
++        inb(VGAREG_ACTL_RESET);
++        outb(i, VGAREG_ACTL_ADDRESS);
++        SET_FARVAR(seg, *data_far, inb(VGAREG_ACTL_READ_DATA));
++        data_far++;
++    }
++    inb(VGAREG_ACTL_RESET);
++    outb(0x11, VGAREG_ACTL_ADDRESS);
++    SET_FARVAR(seg, *data_far, inb(VGAREG_ACTL_READ_DATA));
++    inb(VGAREG_ACTL_RESET);
++    outb(0x20, VGAREG_ACTL_ADDRESS);
++}
++
++void
++vgahw_toggle_intensity(u8 flag)
++{
++    inb(VGAREG_ACTL_RESET);
++    outb(0x10, VGAREG_ACTL_ADDRESS);
++    u8 val = (inb(VGAREG_ACTL_READ_DATA) & 0xf7) | ((flag & 0x01) << 3);
++    outb(val, VGAREG_ACTL_WRITE_DATA);
++    outb(0x20, VGAREG_ACTL_ADDRESS);
++}
++
++void
++vgahw_select_video_dac_color_page(u8 flag, u8 data)
++{
++    inb(VGAREG_ACTL_RESET);
++    outb(0x10, VGAREG_ACTL_ADDRESS);
++    u8 val = inb(VGAREG_ACTL_READ_DATA);
++    if (!(flag & 0x01)) {
++        // select paging mode
++        val = (val & 0x7f) | (data << 7);
++        outb(val, VGAREG_ACTL_WRITE_DATA);
++        outb(0x20, VGAREG_ACTL_ADDRESS);
++        return;
++    }
++    // select page
++    inb(VGAREG_ACTL_RESET);
++    outb(0x14, VGAREG_ACTL_ADDRESS);
++    if (!(val & 0x80))
++        data <<= 2;
++    data &= 0x0f;
++    outb(data, VGAREG_ACTL_WRITE_DATA);
++    outb(0x20, VGAREG_ACTL_ADDRESS);
++}
++
++void
++vgahw_read_video_dac_state(u8 *pmode, u8 *curpage)
++{
++    inb(VGAREG_ACTL_RESET);
++    outb(0x10, VGAREG_ACTL_ADDRESS);
++    u8 val1 = inb(VGAREG_ACTL_READ_DATA) >> 7;
++
++    inb(VGAREG_ACTL_RESET);
++    outb(0x14, VGAREG_ACTL_ADDRESS);
++    u8 val2 = inb(VGAREG_ACTL_READ_DATA) & 0x0f;
++    if (!(val1 & 0x01))
++        val2 >>= 2;
++
++    inb(VGAREG_ACTL_RESET);
++    outb(0x20, VGAREG_ACTL_ADDRESS);
++
++    *pmode = val1;
++    *curpage = val2;
++}
++
++
++/****************************************************************
++ * DAC control
++ ****************************************************************/
++
++void
++vgahw_set_dac_regs(u16 seg, u8 *data_far, u8 start, int count)
++{
++    outb(start, VGAREG_DAC_WRITE_ADDRESS);
++    while (count) {
++        outb(GET_FARVAR(seg, *data_far), VGAREG_DAC_DATA);
++        data_far++;
++        outb(GET_FARVAR(seg, *data_far), VGAREG_DAC_DATA);
++        data_far++;
++        outb(GET_FARVAR(seg, *data_far), VGAREG_DAC_DATA);
++        data_far++;
++        count--;
++    }
++}
++
++void
++vgahw_get_dac_regs(u16 seg, u8 *data_far, u8 start, int count)
++{
++    outb(start, VGAREG_DAC_READ_ADDRESS);
++    while (count) {
++        SET_FARVAR(seg, *data_far, inb(VGAREG_DAC_DATA));
++        data_far++;
++        SET_FARVAR(seg, *data_far, inb(VGAREG_DAC_DATA));
++        data_far++;
++        SET_FARVAR(seg, *data_far, inb(VGAREG_DAC_DATA));
++        data_far++;
++        count--;
++    }
++}
++
++void
++vgahw_set_pel_mask(u8 val)
++{
++    outb(val, VGAREG_PEL_MASK);
++}
++
++u8
++vgahw_get_pel_mask(void)
++{
++    return inb(VGAREG_PEL_MASK);
++}
++
++void
++vgahw_save_dac_state(u16 seg, struct saveDACcolors *info)
++{
++    /* XXX: check this */
++    SET_FARVAR(seg, info->rwmode, inb(VGAREG_DAC_STATE));
++    SET_FARVAR(seg, info->peladdr, inb(VGAREG_DAC_WRITE_ADDRESS));
++    SET_FARVAR(seg, info->pelmask, inb(VGAREG_PEL_MASK));
++    vgahw_get_dac_regs(seg, info->dac, 0, 256);
++    SET_FARVAR(seg, info->color_select, 0);
++}
++
++void
++vgahw_restore_dac_state(u16 seg, struct saveDACcolors *info)
++{
++    outb(GET_FARVAR(seg, info->pelmask), VGAREG_PEL_MASK);
++    vgahw_set_dac_regs(seg, info->dac, 0, 256);
++    outb(GET_FARVAR(seg, info->peladdr), VGAREG_DAC_WRITE_ADDRESS);
++}
++
++
++/****************************************************************
++ * Memory control
++ ****************************************************************/
++
++void
++vgahw_sequ_write(u8 index, u8 value)
++{
++    outw((value<<8) | index, VGAREG_SEQU_ADDRESS);
++}
++
++void
++vgahw_grdc_write(u8 index, u8 value)
++{
++    outw((value<<8) | index, VGAREG_GRDC_ADDRESS);
++}
++
++void
++vgahw_set_text_block_specifier(u8 spec)
++{
++    outw((spec << 8) | 0x03, VGAREG_SEQU_ADDRESS);
++}
++
++void
++get_font_access(void)
++{
++    outw(0x0100, VGAREG_SEQU_ADDRESS);
++    outw(0x0402, VGAREG_SEQU_ADDRESS);
++    outw(0x0704, VGAREG_SEQU_ADDRESS);
++    outw(0x0300, VGAREG_SEQU_ADDRESS);
++    outw(0x0204, VGAREG_GRDC_ADDRESS);
++    outw(0x0005, VGAREG_GRDC_ADDRESS);
++    outw(0x0406, VGAREG_GRDC_ADDRESS);
++}
++
++void
++release_font_access(void)
++{
++    outw(0x0100, VGAREG_SEQU_ADDRESS);
++    outw(0x0302, VGAREG_SEQU_ADDRESS);
++    outw(0x0304, VGAREG_SEQU_ADDRESS);
++    outw(0x0300, VGAREG_SEQU_ADDRESS);
++    u16 v = (inw(VGAREG_READ_MISC_OUTPUT) & 0x01) ? 0x0e : 0x0a;
++    outw((v << 8) | 0x06, VGAREG_GRDC_ADDRESS);
++    outw(0x0004, VGAREG_GRDC_ADDRESS);
++    outw(0x1005, VGAREG_GRDC_ADDRESS);
++}
++
++
++/****************************************************************
++ * CRTC registers
++ ****************************************************************/
++
++static u16
++get_crtc(void)
++{
++    return GET_BDA(crtc_address);
++}
++
++void
++vgahw_set_cursor_shape(u8 start, u8 end)
++{
++    u16 crtc_addr = get_crtc();
++    outb(0x0a, crtc_addr);
++    outb(start, crtc_addr + 1);
++    outb(0x0b, crtc_addr);
++    outb(end, crtc_addr + 1);
++}
++
++void
++vgahw_set_active_page(u16 address)
++{
++    u16 crtc_addr = get_crtc();
++    outb(0x0c, crtc_addr);
++    outb((address & 0xff00) >> 8, crtc_addr + 1);
++    outb(0x0d, crtc_addr);
++    outb(address & 0x00ff, crtc_addr + 1);
++}
++
++void
++vgahw_set_cursor_pos(u16 address)
++{
++    u16 crtc_addr = get_crtc();
++    outb(0x0e, crtc_addr);
++    outb((address & 0xff00) >> 8, crtc_addr + 1);
++    outb(0x0f, crtc_addr);
++    outb(address & 0x00ff, crtc_addr + 1);
++}
++
++void
++vgahw_set_scan_lines(u8 lines)
++{
++    u16 crtc_addr = get_crtc();
++    outb(0x09, crtc_addr);
++    u8 crtc_r9 = inb(crtc_addr + 1);
++    crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1);
++    outb(crtc_r9, crtc_addr + 1);
++}
++
++// Get vertical display end
++u16
++vgahw_get_vde(void)
++{
++    u16 crtc_addr = get_crtc();
++    outb(0x12, crtc_addr);
++    u16 vde = inb(crtc_addr + 1);
++    outb(0x07, crtc_addr);
++    u8 ovl = inb(crtc_addr + 1);
++    vde += (((ovl & 0x02) << 7) + ((ovl & 0x40) << 3) + 1);
++    return vde;
++}
++
++
++/****************************************************************
++ * Save/Restore/Set state
++ ****************************************************************/
++
++void
++vgahw_save_state(u16 seg, struct saveVideoHardware *info)
++{
++    u16 crtc_addr = get_crtc();
++    SET_FARVAR(seg, info->sequ_index, inb(VGAREG_SEQU_ADDRESS));
++    SET_FARVAR(seg, info->crtc_index, inb(crtc_addr));
++    SET_FARVAR(seg, info->grdc_index, inb(VGAREG_GRDC_ADDRESS));
++    inb(VGAREG_ACTL_RESET);
++    u16 ar_index = inb(VGAREG_ACTL_ADDRESS);
++    SET_FARVAR(seg, info->actl_index, ar_index);
++    SET_FARVAR(seg, info->feature, inb(VGAREG_READ_FEATURE_CTL));
++
++    u16 i;
++    for (i=0; i<4; i++) {
++        outb(i+1, VGAREG_SEQU_ADDRESS);
++        SET_FARVAR(seg, info->sequ_regs[i], inb(VGAREG_SEQU_DATA));
++    }
++    outb(0, VGAREG_SEQU_ADDRESS);
++    SET_FARVAR(seg, info->sequ0, inb(VGAREG_SEQU_DATA));
++
++    for (i=0; i<25; i++) {
++        outb(i, crtc_addr);
++        SET_FARVAR(seg, info->crtc_regs[i], inb(crtc_addr + 1));
++    }
++
++    for (i=0; i<20; i++) {
++        inb(VGAREG_ACTL_RESET);
++        outb(i | (ar_index & 0x20), VGAREG_ACTL_ADDRESS);
++        SET_FARVAR(seg, info->actl_regs[i], inb(VGAREG_ACTL_READ_DATA));
++    }
++    inb(VGAREG_ACTL_RESET);
++
++    for (i=0; i<9; i++) {
++        outb(i, VGAREG_GRDC_ADDRESS);
++        SET_FARVAR(seg, info->grdc_regs[i], inb(VGAREG_GRDC_DATA));
++    }
++
++    SET_FARVAR(seg, info->crtc_addr, crtc_addr);
++
++    /* XXX: read plane latches */
++    for (i=0; i<4; i++)
++        SET_FARVAR(seg, info->plane_latch[i], 0);
++}
++
++void
++vgahw_restore_state(u16 seg, struct saveVideoHardware *info)
++{
++    // Reset Attribute Ctl flip-flop
++    inb(VGAREG_ACTL_RESET);
++
++    u16 crtc_addr = GET_FARVAR(seg, info->crtc_addr);
++
++    u16 i;
++    for (i=0; i<4; i++) {
++        outb(i+1, VGAREG_SEQU_ADDRESS);
++        outb(GET_FARVAR(seg, info->sequ_regs[i]), VGAREG_SEQU_DATA);
++    }
++    outb(0, VGAREG_SEQU_ADDRESS);
++    outb(GET_FARVAR(seg, info->sequ0), VGAREG_SEQU_DATA);
++
++    // Disable CRTC write protection
++    outw(0x0011, crtc_addr);
++    // Set CRTC regs
++    for (i=0; i<25; i++)
++        if (i != 0x11) {
++            outb(i, crtc_addr);
++            outb(GET_FARVAR(seg, info->crtc_regs[i]), crtc_addr + 1);
++        }
++    // select crtc base address
++    u16 v = inb(VGAREG_READ_MISC_OUTPUT) & ~0x01;
++    if (crtc_addr == VGAREG_VGA_CRTC_ADDRESS)
++        v |= 0x01;
++    outb(v, VGAREG_WRITE_MISC_OUTPUT);
++
++    // enable write protection if needed
++    outb(0x11, crtc_addr);
++    outb(GET_FARVAR(seg, info->crtc_regs[0x11]), crtc_addr + 1);
++
++    // Set Attribute Ctl
++    u16 ar_index = GET_FARVAR(seg, info->actl_index);
++    inb(VGAREG_ACTL_RESET);
++    for (i=0; i<20; i++) {
++        outb(i | (ar_index & 0x20), VGAREG_ACTL_ADDRESS);
++        outb(GET_FARVAR(seg, info->actl_regs[i]), VGAREG_ACTL_WRITE_DATA);
++    }
++    outb(ar_index, VGAREG_ACTL_ADDRESS);
++    inb(VGAREG_ACTL_RESET);
++
++    for (i=0; i<9; i++) {
++        outb(i, VGAREG_GRDC_ADDRESS);
++        outb(GET_FARVAR(seg, info->grdc_regs[i]), VGAREG_GRDC_DATA);
++    }
++
++    outb(GET_FARVAR(seg, info->sequ_index), VGAREG_SEQU_ADDRESS);
++    outb(GET_FARVAR(seg, info->crtc_index), crtc_addr);
++    outb(GET_FARVAR(seg, info->grdc_index), VGAREG_GRDC_ADDRESS);
++    outb(GET_FARVAR(seg, info->feature), crtc_addr - 0x4 + 0xa);
++}
++
++void
++vgahw_set_mode(struct VideoParam_s *vparam_g)
++{
++    // Reset Attribute Ctl flip-flop
++    inb(VGAREG_ACTL_RESET);
++
++    // Set Attribute Ctl
++    u16 i;
++    for (i = 0; i <= 0x13; i++) {
++        outb(i, VGAREG_ACTL_ADDRESS);
++        outb(GET_GLOBAL(vparam_g->actl_regs[i]), VGAREG_ACTL_WRITE_DATA);
++    }
++    outb(0x14, VGAREG_ACTL_ADDRESS);
++    outb(0x00, VGAREG_ACTL_WRITE_DATA);
++
++    // Set Sequencer Ctl
++    outb(0, VGAREG_SEQU_ADDRESS);
++    outb(0x03, VGAREG_SEQU_DATA);
++    for (i = 1; i <= 4; i++) {
++        outb(i, VGAREG_SEQU_ADDRESS);
++        outb(GET_GLOBAL(vparam_g->sequ_regs[i - 1]), VGAREG_SEQU_DATA);
++    }
++
++    // Set Grafx Ctl
++    for (i = 0; i <= 8; i++) {
++        outb(i, VGAREG_GRDC_ADDRESS);
++        outb(GET_GLOBAL(vparam_g->grdc_regs[i]), VGAREG_GRDC_DATA);
++    }
++
++    // Set CRTC address VGA or MDA
++    u8 miscreg = GET_GLOBAL(vparam_g->miscreg);
++    u16 crtc_addr = VGAREG_VGA_CRTC_ADDRESS;
++    if (!(miscreg & 1))
++        crtc_addr = VGAREG_MDA_CRTC_ADDRESS;
++
++    // Disable CRTC write protection
++    outw(0x0011, crtc_addr);
++    // Set CRTC regs
++    for (i = 0; i <= 0x18; i++) {
++        outb(i, crtc_addr);
++        outb(GET_GLOBAL(vparam_g->crtc_regs[i]), crtc_addr + 1);
++    }
++
++    // Set the misc register
++    outb(miscreg, VGAREG_WRITE_MISC_OUTPUT);
++
++    // Enable video
++    outb(0x20, VGAREG_ACTL_ADDRESS);
++    inb(VGAREG_ACTL_RESET);
++}
++
++
++/****************************************************************
++ * Misc
++ ****************************************************************/
++
++void
++vgahw_enable_video_addressing(u8 disable)
++{
++    u8 v = (disable & 1) ? 0x00 : 0x02;
++    u8 v2 = inb(VGAREG_READ_MISC_OUTPUT) & ~0x02;
++    outb(v | v2, VGAREG_WRITE_MISC_OUTPUT);
++}
++
++void
++vgahw_init(void)
++{
++    // switch to color mode and enable CPU access 480 lines
++    outb(0xc3, VGAREG_WRITE_MISC_OUTPUT);
++    // more than 64k 3C4/04
++    outb(0x04, VGAREG_SEQU_ADDRESS);
++    outb(0x02, VGAREG_SEQU_DATA);
++}
+--- x/roms/seabios/vgasrc/vgalayout.lds.S	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/vgasrc/vgalayout.lds.S	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,24 @@
++// Linker definitions for an option rom
++//
++// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
++OUTPUT_ARCH("i386")
++ENTRY(_optionrom_entry)
++SECTIONS
++{
++        .text 0 : {
++                KEEP(*(.rom.header))
++                *(.text.*)
++                _rodata = . ;
++                *(.rodata.__func__.*)
++                *(.rodata.str1.1)
++                *(.data16.*)
++                }
++
++        // Discard regular data sections to force a link error if
++        // 16bit code attempts to access data not marked with VAR16.
++        /DISCARD/ : { *(.text*) *(.rodata*) *(.data*) *(.bss*) *(COMMON) }
++}
+--- x/roms/seabios/vgasrc/vgatables.c	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/vgasrc/vgatables.c	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,438 @@
++// Tables used by VGA bios
++//
++// Copyright (C) 2009  Kevin O'Connor <kevin@koconnor.net>
++// Copyright (C) 2001-2008 the LGPL VGABios developers Team
++//
++// This file may be distributed under the terms of the GNU LGPLv3 license.
++
++#include "vgatables.h" // struct VideoParamTableEntry_s
++#include "biosvar.h" // GET_GLOBAL
++
++
++/****************************************************************
++ * Video parameter table
++ ****************************************************************/
++
++struct VideoParam_s video_param_table[] VAR16 = {
++    // index=0x00 no mode defined
++    {},
++    // index=0x01 no mode defined
++    {},
++    // index=0x02 no mode defined
++    {},
++    // index=0x03 no mode defined
++    {},
++    // index=0x04 vga mode 0x04
++    { 40, 24, 8, 0x0800,      /* tw, th-1, ch, slength */
++      { 0x09, 0x03, 0x00, 0x02 },    /* sequ_regs */
++      0x63,                      /* miscreg */
++      { 0x2d, 0x27, 0x28, 0x90, 0x2b, 0x80, 0xbf, 0x1f,
++        0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++        0x9c, 0x8e, 0x8f, 0x14, 0x00, 0x96, 0xb9, 0xa2,
++        0xff },                      /* crtc_regs */
++      { 0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07,
++        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
++        0x01, 0x00, 0x03, 0x00 },    /* actl_regs */
++      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0f, 0x0f, 0xff }, /* grdc_regs */
++    },
++    /* index=0x05 vga mode 0x05 */
++    { 40, 24, 8, 0x0800,     /* tw, th-1, ch, slength */
++      { 0x09, 0x03, 0x00, 0x02 },    /* sequ_regs */
++      0x63,                      /* miscreg */
++      { 0x2d, 0x27, 0x28, 0x90, 0x2b, 0x80, 0xbf, 0x1f,
++        0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++        0x9c, 0x8e, 0x8f, 0x14, 0x00, 0x96, 0xb9, 0xa2,
++        0xff },                      /* crtc_regs */
++      { 0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07,
++        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
++        0x01, 0x00, 0x03, 0x00 },    /* actl_regs */
++      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0f, 0x0f, 0xff }, /* grdc_regs */
++    },
++    /* index=0x06 vga mode 0x06 */
++    { 80, 24, 8, 0x1000,     /* tw, th-1, ch, slength */
++      { 0x01, 0x01, 0x00, 0x06 },    /* sequ_regs */
++      0x63,                      /* miscreg */
++      { 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f,
++        0x00, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++        0x9c, 0x8e, 0x8f, 0x28, 0x00, 0x96, 0xb9, 0xc2,
++        0xff },                      /* crtc_regs */
++      { 0x00, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
++        0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
++        0x01, 0x00, 0x01, 0x00 },    /* actl_regs */
++      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x0f, 0xff }, /* grdc_regs */
++     },
++    /* index=0x07 vga mode 0x07 */
++    { 80, 24, 16, 0x1000,    /* tw, th-1, ch, slength */
++      { 0x00, 0x03, 0x00, 0x02 },    /* sequ_regs */
++      0x66,                      /* miscreg */
++      { 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
++        0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
++        0x9c, 0x8e, 0x8f, 0x28, 0x0f, 0x96, 0xb9, 0xa3,
++        0xff },                      /* crtc_regs */
++      { 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
++        0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++        0x0e, 0x00, 0x0f, 0x08 },    /* actl_regs */
++      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0a, 0x0f, 0xff }, /* grdc_regs */
++     },
++    /* index=0x08 no mode defined */
++    {},
++    /* index=0x09 no mode defined */
++    {},
++    /* index=0x0a no mode defined */
++    {},
++    /* index=0x0b no mode defined */
++    {},
++    /* index=0x0c no mode defined */
++    {},
++    /* index=0x0d vga mode 0x0d */
++    { 40, 24, 8, 0x2000,     /* tw, th-1, ch, slength */
++      { 0x09, 0x0f, 0x00, 0x06 },    /* sequ_regs */
++      0x63,                      /* miscreg */
++      { 0x2d, 0x27, 0x28, 0x90, 0x2b, 0x80, 0xbf, 0x1f,
++        0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++        0x9c, 0x8e, 0x8f, 0x14, 0x00, 0x96, 0xb9, 0xe3,
++        0xff },                      /* crtc_regs */
++      { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
++        0x01, 0x00, 0x0f, 0x00 },    /* actl_regs */
++      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff }, /* grdc_regs */
++     },
++    /* index=0x0e vga mode 0x0e */
++    { 80, 24, 8, 0x4000,     /* tw, th-1, ch, slength */
++      { 0x01, 0x0f, 0x00, 0x06 },    /* sequ_regs */
++      0x63,                      /* miscreg */
++      { 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f,
++        0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++        0x9c, 0x8e, 0x8f, 0x28, 0x00, 0x96, 0xb9, 0xe3,
++        0xff },                      /* crtc_regs */
++      { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
++        0x01, 0x00, 0x0f, 0x00 },    /* actl_regs */
++      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff }, /* grdc_regs */
++     },
++    /* index=0x0f no mode defined */
++    {},
++    /* index=0x10 no mode defined */
++    {},
++    /* index=0x11 vga mode 0x0f */
++    { 80, 24, 14, 0x8000,    /* tw, th-1, ch, slength */
++      { 0x01, 0x0f, 0x00, 0x06 },    /* sequ_regs */
++      0xa3,                      /* miscreg */
++      { 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f,
++        0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++        0x83, 0x85, 0x5d, 0x28, 0x0f, 0x63, 0xba, 0xe3,
++        0xff },                      /* crtc_regs */
++      { 0x00, 0x08, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00,
++        0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
++        0x01, 0x00, 0x01, 0x00 },    /* actl_regs */
++      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff }, /* grdc_regs */
++     },
++    /* index=0x12 vga mode 0x10 */
++    { 80, 24, 14, 0x8000,    /* tw, th-1, ch, slength */
++      { 0x01, 0x0f, 0x00, 0x06 },    /* sequ_regs */
++      0xa3,                      /* miscreg */
++      { 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f,
++        0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++        0x83, 0x85, 0x5d, 0x28, 0x0f, 0x63, 0xba, 0xe3,
++        0xff },                      /* crtc_regs */
++      { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
++        0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
++        0x01, 0x00, 0x0f, 0x00 },    /* actl_regs */
++      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff }, /* grdc_regs */
++     },
++    /* index=0x13 no mode defined */
++    {},
++    /* index=0x14 no mode defined */
++    {},
++    /* index=0x15 no mode defined */
++    {},
++    /* index=0x16 no mode defined */
++    {},
++    /* index=0x17 vga mode 0x01 */
++    { 40, 24, 16, 0x0800,    /* tw, th-1, ch, slength */
++      { 0x08, 0x03, 0x00, 0x02 },    /* sequ_regs */
++      0x67,                      /* miscreg */
++      { 0x2d, 0x27, 0x28, 0x90, 0x2b, 0xa0, 0xbf, 0x1f,
++        0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
++        0x9c, 0x8e, 0x8f, 0x14, 0x1f, 0x96, 0xb9, 0xa3,
++        0xff },                      /* crtc_regs */
++      { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
++        0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
++        0x0c, 0x00, 0x0f, 0x08 },    /* actl_regs */
++      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x0f, 0xff }, /* grdc_regs */
++    },
++    /* index=0x18 vga mode 0x03 */
++    { 80, 24, 16, 0x1000,    /* tw, th-1, ch, slength */
++      { 0x00, 0x03, 0x00, 0x02 },    /* sequ_regs */
++      0x67,                      /* miscreg */
++      { 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
++        0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
++        0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96, 0xb9, 0xa3,
++        0xff },                      /* crtc_regs */
++      { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
++        0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
++        0x0c, 0x00, 0x0f, 0x08 },    /* actl_regs */
++      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x0f, 0xff }, /* grdc_regs */
++     },
++    /* index=0x19 vga mode 0x07 */
++    { 80, 24, 16, 0x1000,    /* tw, th-1, ch, slength */
++      { 0x00, 0x03, 0x00, 0x02 },    /* sequ_regs */
++      0x66,                      /* miscreg */
++      { 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f,
++        0x00, 0x4f, 0x0d, 0x0e, 0x00, 0x00, 0x00, 0x00,
++        0x9c, 0x8e, 0x8f, 0x28, 0x0f, 0x96, 0xb9, 0xa3,
++        0xff },                      /* crtc_regs */
++      { 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
++        0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
++        0x0e, 0x00, 0x0f, 0x08 },    /* actl_regs */
++      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0a, 0x0f, 0xff }, /* grdc_regs */
++    },
++    /* index=0x1a vga mode 0x11 */
++    { 80, 29, 16, 0x0000,    /* tw, th-1, ch, slength */
++      { 0x01, 0x0f, 0x00, 0x06 },    /* sequ_regs */
++      0xe3,                      /* miscreg */
++      { 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
++        0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++        0xea, 0x8c, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3,
++        0xff },                      /* crtc_regs */
++      { 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f,
++        0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f,
++        0x01, 0x00, 0x0f, 0x00 },    /* actl_regs */
++      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff }, /* grdc_regs */
++    },
++    /* index=0x1b vga mode 0x12 */
++    { 80, 29, 16, 0x0000,    /* tw, th-1, ch, slength */
++      { 0x01, 0x0f, 0x00, 0x06 },    /* sequ_regs */
++      0xe3,                      /* miscreg */
++      { 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0x0b, 0x3e,
++        0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++        0xea, 0x8c, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3,
++        0xff },                      /* crtc_regs */
++      { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
++        0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
++        0x01, 0x00, 0x0f, 0x00 },    /* actl_regs */
++      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff }, /* grdc_regs */
++     },
++    /* index=0x1c vga mode 0x13 */
++    { 40, 24, 8, 0x0000,     /* tw, th-1, ch, slength */
++      { 0x01, 0x0f, 0x00, 0x0e },    /* sequ_regs */
++      0x63,                      /* miscreg */
++      { 0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f,
++        0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++        0x9c, 0x8e, 0x8f, 0x28, 0x40, 0x96, 0xb9, 0xa3,
++        0xff },                      /* crtc_regs */
++      { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
++        0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
++        0x41, 0x00, 0x0f, 0x00 },    /* actl_regs */
++      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 0xff }, /* grdc_regs */
++     },
++    /* index=0x1d vga mode 0x6a */
++    { 100, 36, 16, 0x0000,   /* tw, th-1, ch, slength */
++      { 0x01, 0x0f, 0x00, 0x06 },    /* sequ_regs */
++      0xe3,                      /* miscreg */
++      { 0x7f, 0x63, 0x63, 0x83, 0x6b, 0x1b, 0x72, 0xf0,
++        0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++        0x59, 0x8d, 0x57, 0x32, 0x00, 0x57, 0x73, 0xe3,
++        0xff },                      /* crtc_regs */
++      { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
++        0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
++        0x01, 0x00, 0x0f, 0x00 },    /* actl_regs */
++      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 0xff }, /* grdc_regs */
++     },
++};
++
++
++/****************************************************************
++ * Palette definitions
++ ****************************************************************/
++
++/* Mono */
++static u8 palette0[] VAR16 = {
++  0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00,
++  0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00,
++  0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
++  0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
++  0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
++  0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
++  0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f,
++  0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f,
++  0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00,
++  0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00,
++  0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
++  0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
++  0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
++  0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a, 0x2a,0x2a,0x2a,
++  0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f,
++  0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f, 0x3f,0x3f,0x3f
++};
++
++static u8 palette1[] VAR16 = {
++  0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a,
++  0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a,
++  0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a,
++  0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a,
++  0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f,
++  0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f,
++  0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f,
++  0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f,
++  0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a,
++  0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a,
++  0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a,
++  0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a,
++  0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f,
++  0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f,
++  0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f,
++  0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f
++};
++
++static u8 palette2[] VAR16 = {
++  0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a,
++  0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x2a,0x00, 0x2a,0x2a,0x2a,
++  0x00,0x00,0x15, 0x00,0x00,0x3f, 0x00,0x2a,0x15, 0x00,0x2a,0x3f,
++  0x2a,0x00,0x15, 0x2a,0x00,0x3f, 0x2a,0x2a,0x15, 0x2a,0x2a,0x3f,
++  0x00,0x15,0x00, 0x00,0x15,0x2a, 0x00,0x3f,0x00, 0x00,0x3f,0x2a,
++  0x2a,0x15,0x00, 0x2a,0x15,0x2a, 0x2a,0x3f,0x00, 0x2a,0x3f,0x2a,
++  0x00,0x15,0x15, 0x00,0x15,0x3f, 0x00,0x3f,0x15, 0x00,0x3f,0x3f,
++  0x2a,0x15,0x15, 0x2a,0x15,0x3f, 0x2a,0x3f,0x15, 0x2a,0x3f,0x3f,
++  0x15,0x00,0x00, 0x15,0x00,0x2a, 0x15,0x2a,0x00, 0x15,0x2a,0x2a,
++  0x3f,0x00,0x00, 0x3f,0x00,0x2a, 0x3f,0x2a,0x00, 0x3f,0x2a,0x2a,
++  0x15,0x00,0x15, 0x15,0x00,0x3f, 0x15,0x2a,0x15, 0x15,0x2a,0x3f,
++  0x3f,0x00,0x15, 0x3f,0x00,0x3f, 0x3f,0x2a,0x15, 0x3f,0x2a,0x3f,
++  0x15,0x15,0x00, 0x15,0x15,0x2a, 0x15,0x3f,0x00, 0x15,0x3f,0x2a,
++  0x3f,0x15,0x00, 0x3f,0x15,0x2a, 0x3f,0x3f,0x00, 0x3f,0x3f,0x2a,
++  0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f,
++  0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f
++};
++
++static u8 palette3[] VAR16 = {
++  0x00,0x00,0x00, 0x00,0x00,0x2a, 0x00,0x2a,0x00, 0x00,0x2a,0x2a,
++  0x2a,0x00,0x00, 0x2a,0x00,0x2a, 0x2a,0x15,0x00, 0x2a,0x2a,0x2a,
++  0x15,0x15,0x15, 0x15,0x15,0x3f, 0x15,0x3f,0x15, 0x15,0x3f,0x3f,
++  0x3f,0x15,0x15, 0x3f,0x15,0x3f, 0x3f,0x3f,0x15, 0x3f,0x3f,0x3f,
++  0x00,0x00,0x00, 0x05,0x05,0x05, 0x08,0x08,0x08, 0x0b,0x0b,0x0b,
++  0x0e,0x0e,0x0e, 0x11,0x11,0x11, 0x14,0x14,0x14, 0x18,0x18,0x18,
++  0x1c,0x1c,0x1c, 0x20,0x20,0x20, 0x24,0x24,0x24, 0x28,0x28,0x28,
++  0x2d,0x2d,0x2d, 0x32,0x32,0x32, 0x38,0x38,0x38, 0x3f,0x3f,0x3f,
++  0x00,0x00,0x3f, 0x10,0x00,0x3f, 0x1f,0x00,0x3f, 0x2f,0x00,0x3f,
++  0x3f,0x00,0x3f, 0x3f,0x00,0x2f, 0x3f,0x00,0x1f, 0x3f,0x00,0x10,
++  0x3f,0x00,0x00, 0x3f,0x10,0x00, 0x3f,0x1f,0x00, 0x3f,0x2f,0x00,
++  0x3f,0x3f,0x00, 0x2f,0x3f,0x00, 0x1f,0x3f,0x00, 0x10,0x3f,0x00,
++  0x00,0x3f,0x00, 0x00,0x3f,0x10, 0x00,0x3f,0x1f, 0x00,0x3f,0x2f,
++  0x00,0x3f,0x3f, 0x00,0x2f,0x3f, 0x00,0x1f,0x3f, 0x00,0x10,0x3f,
++  0x1f,0x1f,0x3f, 0x27,0x1f,0x3f, 0x2f,0x1f,0x3f, 0x37,0x1f,0x3f,
++  0x3f,0x1f,0x3f, 0x3f,0x1f,0x37, 0x3f,0x1f,0x2f, 0x3f,0x1f,0x27,
++
++  0x3f,0x1f,0x1f, 0x3f,0x27,0x1f, 0x3f,0x2f,0x1f, 0x3f,0x37,0x1f,
++  0x3f,0x3f,0x1f, 0x37,0x3f,0x1f, 0x2f,0x3f,0x1f, 0x27,0x3f,0x1f,
++  0x1f,0x3f,0x1f, 0x1f,0x3f,0x27, 0x1f,0x3f,0x2f, 0x1f,0x3f,0x37,
++  0x1f,0x3f,0x3f, 0x1f,0x37,0x3f, 0x1f,0x2f,0x3f, 0x1f,0x27,0x3f,
++  0x2d,0x2d,0x3f, 0x31,0x2d,0x3f, 0x36,0x2d,0x3f, 0x3a,0x2d,0x3f,
++  0x3f,0x2d,0x3f, 0x3f,0x2d,0x3a, 0x3f,0x2d,0x36, 0x3f,0x2d,0x31,
++  0x3f,0x2d,0x2d, 0x3f,0x31,0x2d, 0x3f,0x36,0x2d, 0x3f,0x3a,0x2d,
++  0x3f,0x3f,0x2d, 0x3a,0x3f,0x2d, 0x36,0x3f,0x2d, 0x31,0x3f,0x2d,
++  0x2d,0x3f,0x2d, 0x2d,0x3f,0x31, 0x2d,0x3f,0x36, 0x2d,0x3f,0x3a,
++  0x2d,0x3f,0x3f, 0x2d,0x3a,0x3f, 0x2d,0x36,0x3f, 0x2d,0x31,0x3f,
++  0x00,0x00,0x1c, 0x07,0x00,0x1c, 0x0e,0x00,0x1c, 0x15,0x00,0x1c,
++  0x1c,0x00,0x1c, 0x1c,0x00,0x15, 0x1c,0x00,0x0e, 0x1c,0x00,0x07,
++  0x1c,0x00,0x00, 0x1c,0x07,0x00, 0x1c,0x0e,0x00, 0x1c,0x15,0x00,
++  0x1c,0x1c,0x00, 0x15,0x1c,0x00, 0x0e,0x1c,0x00, 0x07,0x1c,0x00,
++  0x00,0x1c,0x00, 0x00,0x1c,0x07, 0x00,0x1c,0x0e, 0x00,0x1c,0x15,
++  0x00,0x1c,0x1c, 0x00,0x15,0x1c, 0x00,0x0e,0x1c, 0x00,0x07,0x1c,
++
++  0x0e,0x0e,0x1c, 0x11,0x0e,0x1c, 0x15,0x0e,0x1c, 0x18,0x0e,0x1c,
++  0x1c,0x0e,0x1c, 0x1c,0x0e,0x18, 0x1c,0x0e,0x15, 0x1c,0x0e,0x11,
++  0x1c,0x0e,0x0e, 0x1c,0x11,0x0e, 0x1c,0x15,0x0e, 0x1c,0x18,0x0e,
++  0x1c,0x1c,0x0e, 0x18,0x1c,0x0e, 0x15,0x1c,0x0e, 0x11,0x1c,0x0e,
++  0x0e,0x1c,0x0e, 0x0e,0x1c,0x11, 0x0e,0x1c,0x15, 0x0e,0x1c,0x18,
++  0x0e,0x1c,0x1c, 0x0e,0x18,0x1c, 0x0e,0x15,0x1c, 0x0e,0x11,0x1c,
++  0x14,0x14,0x1c, 0x16,0x14,0x1c, 0x18,0x14,0x1c, 0x1a,0x14,0x1c,
++  0x1c,0x14,0x1c, 0x1c,0x14,0x1a, 0x1c,0x14,0x18, 0x1c,0x14,0x16,
++  0x1c,0x14,0x14, 0x1c,0x16,0x14, 0x1c,0x18,0x14, 0x1c,0x1a,0x14,
++  0x1c,0x1c,0x14, 0x1a,0x1c,0x14, 0x18,0x1c,0x14, 0x16,0x1c,0x14,
++  0x14,0x1c,0x14, 0x14,0x1c,0x16, 0x14,0x1c,0x18, 0x14,0x1c,0x1a,
++  0x14,0x1c,0x1c, 0x14,0x1a,0x1c, 0x14,0x18,0x1c, 0x14,0x16,0x1c,
++  0x00,0x00,0x10, 0x04,0x00,0x10, 0x08,0x00,0x10, 0x0c,0x00,0x10,
++  0x10,0x00,0x10, 0x10,0x00,0x0c, 0x10,0x00,0x08, 0x10,0x00,0x04,
++  0x10,0x00,0x00, 0x10,0x04,0x00, 0x10,0x08,0x00, 0x10,0x0c,0x00,
++  0x10,0x10,0x00, 0x0c,0x10,0x00, 0x08,0x10,0x00, 0x04,0x10,0x00,
++
++  0x00,0x10,0x00, 0x00,0x10,0x04, 0x00,0x10,0x08, 0x00,0x10,0x0c,
++  0x00,0x10,0x10, 0x00,0x0c,0x10, 0x00,0x08,0x10, 0x00,0x04,0x10,
++  0x08,0x08,0x10, 0x0a,0x08,0x10, 0x0c,0x08,0x10, 0x0e,0x08,0x10,
++  0x10,0x08,0x10, 0x10,0x08,0x0e, 0x10,0x08,0x0c, 0x10,0x08,0x0a,
++  0x10,0x08,0x08, 0x10,0x0a,0x08, 0x10,0x0c,0x08, 0x10,0x0e,0x08,
++  0x10,0x10,0x08, 0x0e,0x10,0x08, 0x0c,0x10,0x08, 0x0a,0x10,0x08,
++  0x08,0x10,0x08, 0x08,0x10,0x0a, 0x08,0x10,0x0c, 0x08,0x10,0x0e,
++  0x08,0x10,0x10, 0x08,0x0e,0x10, 0x08,0x0c,0x10, 0x08,0x0a,0x10,
++  0x0b,0x0b,0x10, 0x0c,0x0b,0x10, 0x0d,0x0b,0x10, 0x0f,0x0b,0x10,
++  0x10,0x0b,0x10, 0x10,0x0b,0x0f, 0x10,0x0b,0x0d, 0x10,0x0b,0x0c,
++  0x10,0x0b,0x0b, 0x10,0x0c,0x0b, 0x10,0x0d,0x0b, 0x10,0x0f,0x0b,
++  0x10,0x10,0x0b, 0x0f,0x10,0x0b, 0x0d,0x10,0x0b, 0x0c,0x10,0x0b,
++  0x0b,0x10,0x0b, 0x0b,0x10,0x0c, 0x0b,0x10,0x0d, 0x0b,0x10,0x0f,
++  0x0b,0x10,0x10, 0x0b,0x0f,0x10, 0x0b,0x0d,0x10, 0x0b,0x0c,0x10,
++  0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00,
++  0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00, 0x00,0x00,0x00
++};
++
++
++/****************************************************************
++ * Video mode list
++ ****************************************************************/
++
++#define PAL(x) x, sizeof(x)
++#define VPARAM(x) &video_param_table[x]
++
++static struct vgamode_s vga_modes[] VAR16 = {
++    //mode vparam        model bits  sstart     pelm  dac
++    {0x00, VPARAM(0x17), CTEXT,   4, SEG_CTEXT, 0xFF, PAL(palette2)},
++    {0x01, VPARAM(0x17), CTEXT,   4, SEG_CTEXT, 0xFF, PAL(palette2)},
++    {0x02, VPARAM(0x18), CTEXT,   4, SEG_CTEXT, 0xFF, PAL(palette2)},
++    {0x03, VPARAM(0x18), CTEXT,   4, SEG_CTEXT, 0xFF, PAL(palette2)},
++    {0x04, VPARAM(0x04), CGA,     2, SEG_CTEXT, 0xFF, PAL(palette1)},
++    {0x05, VPARAM(0x05), CGA,     2, SEG_CTEXT, 0xFF, PAL(palette1)},
++    {0x06, VPARAM(0x06), CGA,     1, SEG_CTEXT, 0xFF, PAL(palette1)},
++    {0x07, VPARAM(0x07), MTEXT,   4, SEG_MTEXT, 0xFF, PAL(palette0)},
++    {0x0D, VPARAM(0x0d), PLANAR4, 4, SEG_GRAPH, 0xFF, PAL(palette1)},
++    {0x0E, VPARAM(0x0e), PLANAR4, 4, SEG_GRAPH, 0xFF, PAL(palette1)},
++    {0x0F, VPARAM(0x11), PLANAR1, 1, SEG_GRAPH, 0xFF, PAL(palette0)},
++    {0x10, VPARAM(0x12), PLANAR4, 4, SEG_GRAPH, 0xFF, PAL(palette2)},
++    {0x11, VPARAM(0x1a), PLANAR1, 1, SEG_GRAPH, 0xFF, PAL(palette2)},
++    {0x12, VPARAM(0x1b), PLANAR4, 4, SEG_GRAPH, 0xFF, PAL(palette2)},
++    {0x13, VPARAM(0x1c), LINEAR8, 8, SEG_GRAPH, 0xFF, PAL(palette3)},
++    {0x6A, VPARAM(0x1d), PLANAR4, 4, SEG_GRAPH, 0xFF, PAL(palette2)},
++};
++
++struct vgamode_s *
++find_vga_entry(u8 mode)
++{
++    int i;
++    for (i = 0; i < ARRAY_SIZE(vga_modes); i++) {
++        struct vgamode_s *vmode_g = &vga_modes[i];
++        if (GET_GLOBAL(vmode_g->svgamode) == mode)
++            return vmode_g;
++    }
++    return NULL;
++}
++
++u16 video_save_pointer_table[14] VAR16;
++
++
++/****************************************************************
++ * Static functionality table
++ ****************************************************************/
++
++u8 static_functionality[0x10] VAR16 = {
++ /* 0 */ 0xff,  // All modes supported #1
++ /* 1 */ 0xe0,  // All modes supported #2
++ /* 2 */ 0x0f,  // All modes supported #3
++ /* 3 */ 0x00, 0x00, 0x00, 0x00,  // reserved
++ /* 7 */ 0x07,  // 200, 350, 400 scan lines
++ /* 8 */ 0x02,  // mamimum number of visible charsets in text mode
++ /* 9 */ 0x08,  // total number of charset blocks in text mode
++ /* a */ 0xe7,  // Change to add new functions
++ /* b */ 0x0c,  // Change to add new functions
++ /* c */ 0x00,  // reserved
++ /* d */ 0x00,  // reserved
++ /* e */ 0x00,  // Change to add new functions
++ /* f */ 0x00   // reserved
++};
+--- x/roms/seabios/vgasrc/vgatables.h	1970-01-01 03:00:00.000000000 +0300
++++ qemu-0.12.3/roms/seabios/vgasrc/vgatables.h	2010-02-23 23:55:55.000000000 +0300
+@@ -0,0 +1,217 @@
++#ifndef __VGATABLES_H
++#define __VGATABLES_H
++
++#include "types.h" // u8
++#include "farptr.h" // struct segoff_s
++
++/*
++ *
++ * VGA registers
++ *
++ */
++#define VGAREG_ACTL_ADDRESS            0x3c0
++#define VGAREG_ACTL_WRITE_DATA         0x3c0
++#define VGAREG_ACTL_READ_DATA          0x3c1
++
++#define VGAREG_INPUT_STATUS            0x3c2
++#define VGAREG_WRITE_MISC_OUTPUT       0x3c2
++#define VGAREG_VIDEO_ENABLE            0x3c3
++#define VGAREG_SEQU_ADDRESS            0x3c4
++#define VGAREG_SEQU_DATA               0x3c5
++
++#define VGAREG_PEL_MASK                0x3c6
++#define VGAREG_DAC_STATE               0x3c7
++#define VGAREG_DAC_READ_ADDRESS        0x3c7
++#define VGAREG_DAC_WRITE_ADDRESS       0x3c8
++#define VGAREG_DAC_DATA                0x3c9
++
++#define VGAREG_READ_FEATURE_CTL        0x3ca
++#define VGAREG_READ_MISC_OUTPUT        0x3cc
++
++#define VGAREG_GRDC_ADDRESS            0x3ce
++#define VGAREG_GRDC_DATA               0x3cf
++
++#define VGAREG_MDA_CRTC_ADDRESS        0x3b4
++#define VGAREG_MDA_CRTC_DATA           0x3b5
++#define VGAREG_VGA_CRTC_ADDRESS        0x3d4
++#define VGAREG_VGA_CRTC_DATA           0x3d5
++
++#define VGAREG_MDA_WRITE_FEATURE_CTL   0x3ba
++#define VGAREG_VGA_WRITE_FEATURE_CTL   0x3da
++#define VGAREG_ACTL_RESET              0x3da
++
++#define VGAREG_MDA_MODECTL             0x3b8
++#define VGAREG_CGA_MODECTL             0x3d8
++#define VGAREG_CGA_PALETTE             0x3d9
++
++/* Video memory */
++#define SEG_GRAPH 0xA000
++#define SEG_CTEXT 0xB800
++#define SEG_MTEXT 0xB000
++
++/*
++ * Tables of default values for each mode
++ */
++#define TEXT       0x80
++
++#define CTEXT      (0x00 | TEXT)
++#define MTEXT      (0x01 | TEXT)
++#define CGA        0x02
++#define PLANAR1    0x03
++#define PLANAR4    0x04
++#define LINEAR8    0x05
++
++// for SVGA
++#define LINEAR15   0x10
++#define LINEAR16   0x11
++#define LINEAR24   0x12
++#define LINEAR32   0x13
++
++#define SCREEN_IO_START(x,y,p) (((((x)*(y)) | 0x00ff) + 1) * (p))
++#define SCREEN_MEM_START(x,y,p) SCREEN_IO_START(((x)*2),(y),(p))
++
++/* standard BIOS Video Parameter Table */
++struct VideoParam_s {
++    u8 twidth;
++    u8 theightm1;
++    u8 cheight;
++    u16 slength;
++    u8 sequ_regs[4];
++    u8 miscreg;
++    u8 crtc_regs[25];
++    u8 actl_regs[20];
++    u8 grdc_regs[9];
++} PACKED;
++
++struct vgamode_s {
++    u8 svgamode;
++    struct VideoParam_s *vparam;
++    u8 memmodel;    /* CTEXT,MTEXT,CGA,PL1,PL2,PL4,P8,P15,P16,P24,P32 */
++    u8 pixbits;
++    u16 sstart;
++    u8 pelmask;
++    u8 *dac;
++    u16 dacsize;
++};
++
++struct saveVideoHardware {
++    u8 sequ_index;
++    u8 crtc_index;
++    u8 grdc_index;
++    u8 actl_index;
++    u8 feature;
++    u8 sequ_regs[4];
++    u8 sequ0;
++    u8 crtc_regs[25];
++    u8 actl_regs[20];
++    u8 grdc_regs[9];
++    u16 crtc_addr;
++    u8 plane_latch[4];
++};
++
++struct saveBDAstate {
++    u8 video_mode;
++    u16 video_cols;
++    u16 video_pagesize;
++    u16 crtc_address;
++    u8 video_rows;
++    u16 char_height;
++    u8 video_ctl;
++    u8 video_switches;
++    u8 modeset_ctl;
++    u16 cursor_type;
++    u16 cursor_pos[8];
++    u16 video_pagestart;
++    u8 video_page;
++    /* current font */
++    struct segoff_s font0;
++    struct segoff_s font1;
++};
++
++struct saveDACcolors {
++    u8 rwmode;
++    u8 peladdr;
++    u8 pelmask;
++    u8 dac[768];
++    u8 color_select;
++};
++
++// vgatables.c
++struct vgamode_s *find_vga_entry(u8 mode);
++extern u16 video_save_pointer_table[];
++extern struct VideoParam_s video_param_table[];
++extern u8 static_functionality[];
++
++// vgafonts.c
++extern u8 vgafont8[];
++extern u8 vgafont14[];
++extern u8 vgafont16[];
++extern u8 vgafont14alt[];
++extern u8 vgafont16alt[];
++
++// vga.c
++struct carattr {
++    u8 car, attr, use_attr;
++};
++struct cursorpos {
++    u8 x, y, page;
++};
++
++// vgafb.c
++void clear_screen(struct vgamode_s *vmode_g);
++void vgafb_scroll(int nblines, int attr
++                  , struct cursorpos ul, struct cursorpos lr);
++void vgafb_write_char(struct cursorpos cp, struct carattr ca);
++struct carattr vgafb_read_char(struct cursorpos cp);
++void vgafb_write_pixel(u8 color, u16 x, u16 y);
++u8 vgafb_read_pixel(u16 x, u16 y);
++void vgafb_load_font(u16 seg, void *src_far, u16 count
++                     , u16 start, u8 destflags, u8 fontsize);
++
++// vgaio.c
++void vgahw_screen_disable(void);
++void vgahw_screen_enable(void);
++void vgahw_set_border_color(u8 color);
++void vgahw_set_overscan_border_color(u8 color);
++u8 vgahw_get_overscan_border_color(void);
++void vgahw_set_palette(u8 palid);
++void vgahw_set_single_palette_reg(u8 reg, u8 val);
++u8 vgahw_get_single_palette_reg(u8 reg);
++void vgahw_set_all_palette_reg(u16 seg, u8 *data_far);
++void vgahw_get_all_palette_reg(u16 seg, u8 *data_far);
++void vgahw_toggle_intensity(u8 flag);
++void vgahw_select_video_dac_color_page(u8 flag, u8 data);
++void vgahw_read_video_dac_state(u8 *pmode, u8 *curpage);
++void vgahw_set_dac_regs(u16 seg, u8 *data_far, u8 start, int count);
++void vgahw_get_dac_regs(u16 seg, u8 *data_far, u8 start, int count);
++void vgahw_set_pel_mask(u8 val);
++u8 vgahw_get_pel_mask(void);
++void vgahw_save_dac_state(u16 seg, struct saveDACcolors *info);
++void vgahw_restore_dac_state(u16 seg, struct saveDACcolors *info);
++void vgahw_sequ_write(u8 index, u8 value);
++void vgahw_grdc_write(u8 index, u8 value);
++void vgahw_set_text_block_specifier(u8 spec);
++void get_font_access(void);
++void release_font_access(void);
++void vgahw_set_cursor_shape(u8 start, u8 end);
++void vgahw_set_active_page(u16 address);
++void vgahw_set_cursor_pos(u16 address);
++void vgahw_set_scan_lines(u8 lines);
++u16 vgahw_get_vde(void);
++void vgahw_save_state(u16 seg, struct saveVideoHardware *info);
++void vgahw_restore_state(u16 seg, struct saveVideoHardware *info);
++void vgahw_set_mode(struct VideoParam_s *vparam_g);
++void vgahw_enable_video_addressing(u8 disable);
++void vgahw_init(void);
++
++// clext.c
++void cirrus_set_video_mode(u8 mode);
++void cirrus_init(void);
++
++// vbe.c -- not implemented yet.
++#define VBE_DISPI_DISABLED              0x00
++void dispi_set_enable(int enable);
++void vbe_init(void);
++int vbe_has_vbe_display(void);
++
++#endif // vgatables.h
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/06_no_system_linux_kvm_h.patch
+++ qemu-kvm-0.12.5+dfsg/debian/patches/06_no_system_linux_kvm_h.patch
@@ -0,0 +1,19 @@
+
+Avoid including system header for linux/kvm.h - otherwise we will fail
+when the system has older headers than what we're really trying to
+compile, for example a Linux 2.6.20 host with 2.6.20 Linux headers
+installed would fail.
+
+Index: libkvm/libkvm.h
+===================================================================
+--- a/kvm/libkvm/libkvm.h.orig	2008-11-26 16:04:21.000000000 +0100
++++ b/kvm/libkvm/libkvm.h	2008-11-27 09:37:43.000000000 +0100
+@@ -15,7 +15,7 @@
+ #define __user /* temporary, until installed via make headers_install */
+ #endif
+ 
+-#include <linux/kvm.h>
++#include "linux/kvm.h"
+ 
+ #include <signal.h>
+ 
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/usbkbd-menu-logo-keys.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/usbkbd-menu-logo-keys.diff
@@ -0,0 +1,15 @@
+Patch from http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=578846
+Mjt is not sure if it's the right way, but it definitely fixes the
+problem and usb keyboard starts behaving nicely too.
+
+--- a/hw/usb-hid.c
++++ b/hw/usb-hid.c
+@@ -397,7 +397,7 @@
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x4a,
+     0x52, 0x4b, 0x00, 0x50, 0x00, 0x4f, 0x00, 0x4d,
+     0x51, 0x4e, 0x49, 0x4c, 0x00, 0x00, 0x00, 0x00,
+-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++    0x00, 0x00, 0x00, 0xe3, 0xe7, 0x65, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/pci-cleanly-backout-of-pci_qdev_init-925fe64ae7.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/pci-cleanly-backout-of-pci_qdev_init-925fe64ae7.diff
@@ -0,0 +1,57 @@
+commit 925fe64ae7b487fdb7bd56fcab63e2f87653c226
+Author: Alex Williamson <alex.williamson@redhat.com>
+Date:   Tue May 11 06:44:21 2010 -0400
+
+    pci: cleanly backout of pci_qdev_init()
+    
+    If the init function of a device fails, as might happen with device
+    assignment, we never undo the work done by do_pci_register_device().
+    This not only causes a bit of a memory leak, but also leaves a bogus
+    pointer in the bus devices array that can cause a segfault or
+    garbage data from 'info pci'.
+    
+    Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
+    Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+
+diff --git a/hw/pci.c b/hw/pci.c
+index f167436..3ca5f09 100644
+--- a/hw/pci.c
++++ b/hw/pci.c
+@@ -625,6 +625,13 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
+     return pci_dev;
+ }
+ 
++static void do_pci_unregister_device(PCIDevice *pci_dev)
++{
++    qemu_free_irqs(pci_dev->irq);
++    pci_dev->bus->devices[pci_dev->devfn] = NULL;
++    pci_config_free(pci_dev);
++}
++
+ PCIDevice *pci_register_device(PCIBus *bus, const char *name,
+                                int instance_size, int devfn,
+                                PCIConfigReadFunc *config_read,
+@@ -680,10 +687,7 @@ static int pci_unregister_device(DeviceState *dev)
+         return ret;
+ 
+     pci_unregister_io_regions(pci_dev);
+-
+-    qemu_free_irqs(pci_dev->irq);
+-    pci_dev->bus->devices[pci_dev->devfn] = NULL;
+-    pci_config_free(pci_dev);
++    do_pci_unregister_device(pci_dev);
+     return 0;
+ }
+ 
+@@ -1652,8 +1656,10 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
+     if (pci_dev == NULL)
+         return -1;
+     rc = info->init(pci_dev);
+-    if (rc != 0)
++    if (rc != 0) {
++        do_pci_unregister_device(pci_dev);
+         return rc;
++    }
+ 
+     /* rom loading */
+     if (pci_dev->romfile == NULL && info->romfile != NULL)
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/01_use_bios_files_in_usr_share_kvm.patch
+++ qemu-kvm-0.12.5+dfsg/debian/patches/01_use_bios_files_in_usr_share_kvm.patch
@@ -0,0 +1,13 @@
+Index: kvm/qemu/configure
+===================================================================
+--- kvm.orig/configure	2008-12-30 18:09:10.000000000 +0100
++++ kvm/configure	2008-12-30 18:10:18.000000000 +0100
+@@ -1096,7 +1096,7 @@
+       prefix="/usr/local"
+   fi
+   mansuffix="/share/man"
+-  datasuffix="/share/qemu"
++  datasuffix="/share/kvm"
+   docsuffix="/share/doc/qemu"
+   binsuffix="/bin"
+ fi
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/fix-curses-return-key-when-using--k.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/fix-curses-return-key-when-using--k.diff
@@ -0,0 +1,29 @@
+commit 942cef3799d9f3c4fd0fd77a21b7eca220281af9
+Author: Samuel Thibault <samuel.thibault@gnu.org>
+Date:   Sun Feb 28 15:35:19 2010 +0100
+
+    Fix curses return key when using -k
+    
+    Hello,
+    
+    There is a small incoherency in curses_keys.h, which makes it fail to
+    emit \n when using e.g. -k fr: curses2keysym transforms \r and 0x157
+    into \n, but name2keysym binds \r with Return, not \n.  The patch below
+    fixes that.
+    
+    Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
+    Signed-off-by: Andrzej Zaborowski <andrew.zaborowski@intel.com>
+
+diff --git a/curses_keys.h b/curses_keys.h
+index a6e41cf..6030720 100644
+--- a/curses_keys.h
++++ b/curses_keys.h
+@@ -446,7 +446,7 @@ static const name2keysym_t name2keysym[] = {
+     /* Special keys */
+     { "BackSpace", 0x07f },
+     { "Tab", '\t' },
+-    { "Return", '\r' },
++    { "Return", '\n' },
+     { "Right", 0x105 },
+     { "Left", 0x104 },
+     { "Up", 0x103 },
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/os-posix-set-groups-properly-for--runas-CVE-2011-2527.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/os-posix-set-groups-properly-for--runas-CVE-2011-2527.diff
@@ -0,0 +1,51 @@
+Refreshed for 0.12 (the code was in vl.c in 0.12)
+		-- mjt
+
+Subject: os-posix: set groups properly for -runas
+Date: Fri, 08 Jul 2011 23:22:07 -0000
+From: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
+Message-Id: <1310203327-27069-1-git-send-email-stefanha@linux.vnet.ibm.com>
+To: <qemu-devel@nongnu.org>
+Cc: Bug 807893 <807893@bugs.launchpad.net>,
+	Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
+
+Andrew Griffiths reports that -runas does not set supplementary group
+IDs.  This means that gid 0 (root) is not dropped when switching to an
+unprivileged user.
+
+Add an initgroups(3) call to use the -runas user's /etc/groups
+membership to update the supplementary group IDs.
+
+Signed-off-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
+Acked-by: Chris Wright <chrisw@sous-sol.org>
+
+---
+Note this needs compile testing on various POSIX host platforms.  Tested on
+Linux.  Should work on BSD and Solaris.  initgroups(3) is SVr4/BSD but not in
+POSIX.
+
+ vl.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/vl.c
++++ b/vl.c
+@@ -35,6 +35,7 @@
+ #ifndef _WIN32
+ #include <libgen.h>
+ #include <pwd.h>
++#include <grp.h>
+ #include <sys/times.h>
+ #include <sys/wait.h>
+ #include <termios.h>
+@@ -6240,6 +6241,11 @@ int main(int argc, char **argv, char **e
+             fprintf(stderr, "Failed to setgid(%d)\n", pwd->pw_gid);
+             exit(1);
+         }
++        if (initgroups(pwd->pw_name, pwd->pw_gid) < 0) {
++            fprintf(stderr, "Failed to initgroups(\"%s\", %d)\n",
++                    pwd->pw_name, pwd->pw_gid);
++            exit(1);
++        }
+         if (setuid(pwd->pw_uid) < 0) {
+             fprintf(stderr, "Failed to setuid(%d)\n", pwd->pw_uid);
+             exit(1);
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/seabios-makefile-depends-on-acpi-dsdt-hex.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/seabios-makefile-depends-on-acpi-dsdt-hex.diff
@@ -0,0 +1,7 @@
+--- a/roms/seabios/Makefile.orig	2010-11-10 13:24:13.544436665 +0300
++++ a/roms/seabios/Makefile	2010-11-10 13:35:20.313738669 +0300
+@@ -121,2 +121,4 @@
+ $(OUT)ccode32flat.o: ; $(call whole-compile, $(CFLAGS32FLAT), $(addprefix src/, $(SRC32FLAT)),$@)
++# it includes a generated dsdt
++$(OUT)ccode32flat.o: src/acpi-dsdt.hex
+ 
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/revert-sdlaudio:-make-it-suck-less.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/revert-sdlaudio:-make-it-suck-less.diff
@@ -0,0 +1,140 @@
+commit ff5414990645653bf43bf64adfc1ca77ffb9edcb
+Author: malc <av1474@comtv.ru>
+Date:   Sun Jan 17 00:25:29 2010 +0300
+
+    Revert "sdlaudio: make it suck less"
+    
+    This reverts commit 4839abe78fd466a3cf06faa7c362154afd5404f1.
+    
+    The commit was badly broken, Gentoo has sdl as the default driver,
+    consequently 5 gentoo users have hit the breakage and were kind enough
+    to report, so thank you:
+    
+    Claes Gyllenswrd
+    vekin
+    Chris
+    
+    But above all thanks to Toralf Foerster who actually provied enough
+    information to pinpoint the breakage to sdlaudio.
+    
+    http://bugs.gentoo.org/show_bug.cgi?id=294269
+
+diff --git a/audio/sdlaudio.c b/audio/sdlaudio.c
+index aa39c33..8e7e5cb 100644
+--- a/audio/sdlaudio.c
++++ b/audio/sdlaudio.c
+@@ -41,8 +41,8 @@
+ typedef struct SDLVoiceOut {
+     HWVoiceOut hw;
+     int live;
++    int rpos;
+     int decr;
+-    int pending;
+ } SDLVoiceOut;
+ 
+ static struct {
+@@ -225,10 +225,6 @@ static void sdl_callback (void *opaque, Uint8 *buf, int len)
+     HWVoiceOut *hw = &sdl->hw;
+     int samples = len >> hw->info.shift;
+ 
+-    if (sdl_lock (s, "sdl_callback")) {
+-        return;
+-    }
+-
+     if (s->exit) {
+         return;
+     }
+@@ -236,34 +232,49 @@ static void sdl_callback (void *opaque, Uint8 *buf, int len)
+     while (samples) {
+         int to_mix, decr;
+ 
+-        while (!sdl->pending) {
+-            if (sdl_unlock (s, "sdl_callback")) {
+-                return;
+-            }
+-
+-            sdl_wait (s, "sdl_callback");
+-            if (s->exit) {
+-                return;
+-            }
+-
+-            if (sdl_lock (s, "sdl_callback")) {
+-                return;
+-            }
+-            sdl->pending += sdl->live;
+-            sdl->live = 0;
++        /* dolog ("in callback samples=%d\n", samples); */
++        sdl_wait (s, "sdl_callback");
++        if (s->exit) {
++            return;
++        }
++
++        if (sdl_lock (s, "sdl_callback")) {
++            return;
++        }
++
++        if (audio_bug (AUDIO_FUNC, sdl->live < 0 || sdl->live > hw->samples)) {
++            dolog ("sdl->live=%d hw->samples=%d\n",
++                   sdl->live, hw->samples);
++            return;
++        }
++
++        if (!sdl->live) {
++            goto again;
+         }
+ 
+-        to_mix = audio_MIN (samples, sdl->pending);
+-        decr = audio_pcm_hw_clip_out (hw, buf, to_mix, 0);
+-        buf += decr << hw->info.shift;
++        /* dolog ("in callback live=%d\n", live); */
++        to_mix = audio_MIN (samples, sdl->live);
++        decr = to_mix;
++        while (to_mix) {
++            int chunk = audio_MIN (to_mix, hw->samples - hw->rpos);
++            struct st_sample *src = hw->mix_buf + hw->rpos;
++
++            /* dolog ("in callback to_mix %d, chunk %d\n", to_mix, chunk); */
++            hw->clip (buf, src, chunk);
++            sdl->rpos = (sdl->rpos + chunk) % hw->samples;
++            to_mix -= chunk;
++            buf += chunk << hw->info.shift;
++        }
+         samples -= decr;
++        sdl->live -= decr;
+         sdl->decr += decr;
+-        sdl->pending -= decr;
+-    }
+ 
+-    if (sdl_unlock (s, "sdl_callback")) {
+-        return;
++    again:
++        if (sdl_unlock (s, "sdl_callback")) {
++            return;
++        }
+     }
++    /* dolog ("done len=%d\n", len); */
+ }
+ 
+ static int sdl_write_out (SWVoiceOut *sw, void *buf, int len)
+@@ -281,9 +292,18 @@ static int sdl_run_out (HWVoiceOut *hw, int live)
+         return 0;
+     }
+ 
+-    sdl->live = live;
+-    decr = sdl->decr;
+-    sdl->decr = 0;
++    if (sdl->decr > live) {
++        ldebug ("sdl->decr %d live %d sdl->live %d\n",
++                sdl->decr,
++                live,
++                sdl->live);
++    }
++
++    decr = audio_MIN (sdl->decr, live);
++    sdl->decr -= decr;
++
++    sdl->live = live - decr;
++    hw->rpos = sdl->rpos;
+ 
+     if (sdl->live > 0) {
+         sdl_unlock_and_post (s, "sdl_run_out");
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/madv_mergeable-for-old-kernheaders-hack.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/madv_mergeable-for-old-kernheaders-hack.diff
@@ -0,0 +1,19 @@
+diff --git a/exec.c b/exec.c
+index 4bae1d9..586f53f 100644
+--- a/exec.c
++++ b/exec.c
+@@ -2546,6 +2546,14 @@ ram_addr_t qemu_ram_alloc(ram_addr_t size)
+ #else
+         new_block->host = qemu_vmalloc(size);
+ #endif
++#ifndef MADV_MERGEABLE
++/* This is a hack to enable functionality even when compiled with old
++ * kernel headers.  On real old kernel it will have no effect (the
++ * syscall below will fail with ENOSYS, but on more recent headers
++ * it will work.  This is in order to keep -stable with more recent
++ * kernel happy, mostly for -bpo. */
++#define MADV_MERGEABLE 12
++#endif
+ #ifdef MADV_MERGEABLE
+         madvise(new_block->host, size, MADV_MERGEABLE);
+ #endif
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/fix-100%-CPU-load-when-idle-with-ALSA.diff
+++ qemu-kvm-0.12.5+dfsg/debian/patches/fix-100%-CPU-load-when-idle-with-ALSA.diff
@@ -0,0 +1,27 @@
+commit 22d948a2d97434192018bdabaf0a50cda7f994be
+Author: Jindrich Makovicka <makovick@gmail.com>
+Date:   Sun Oct 17 19:28:14 2010 +0200
+
+    fix 100% CPU load when idle with ALSA
+    
+    Playback control function did not disable polling when playback stops.
+    Caused busy spinning of the main loop due to unprocessed events.
+    
+    Signed-off-by: Jindrich Makovicka <makovick@gmail.com>
+    Signed-off-by: malc <av1474@comtv.ru>
+
+diff --git a/audio/alsaaudio.c b/audio/alsaaudio.c
+index f0171f9..3ca4078 100644
+--- a/audio/alsaaudio.c
++++ b/audio/alsaaudio.c
+@@ -889,6 +889,10 @@ static int alsa_ctl_out (HWVoiceOut *hw, int cmd, ...)
+ 
+     case VOICE_DISABLE:
+         ldebug ("disabling voice\n");
++        if (hw->poll_mode) {
++            hw->poll_mode = 0;
++            alsa_fini_poll (&alsa->pollhlp);
++        }
+         return alsa_voice_ctl (alsa->handle, "playback", 1);
+     }
+ 
--- qemu-kvm-0.12.5+dfsg.orig/debian/patches/security/leftover.patch
+++ qemu-kvm-0.12.5+dfsg/debian/patches/security/leftover.patch
@@ -0,0 +1,44 @@
+Index: kvm/qemu/hw/dma.c
+===================================================================
+--- kvm.orig/hw/dma.c	2008-11-29 09:36:57.000000000 +0100
++++ kvm/hw/dma.c	2008-11-29 17:12:30.000000000 +0100
+@@ -349,9 +349,11 @@
+ #endif
+
+     r = dma_controllers[ncont].regs + ichan;
+-    n = r->transfer_handler (r->opaque, ichan + (ncont << 2),
+-                             r->now[COUNT], (r->base[COUNT] + 1) << ncont);
+-    r->now[COUNT] = n;
++    if (r->transfer_handler) {
++        n = r->transfer_handler (r->opaque, ichan + (ncont << 2),
++                                 r->now[COUNT], (r->base[COUNT] + 1) << ncont);
++        r->now[COUNT] = n;
++    }
+     ldebug ("dma_pos %d size %d\n", n, (r->base[COUNT] + 1) << ncont);
+ }
+
+Index: kvm/qemu/hw/pc.c
+===================================================================
+--- kvm.orig/hw/pc.c	2008-11-29 09:36:57.000000000 +0100
++++ kvm/hw/pc.c	2008-11-29 17:12:30.000000000 +0100
+@@ -387,7 +387,8 @@
+     case 0x400:
+     case 0x401:
+         fprintf(stderr, "BIOS panic at rombios.c, line %d\n", val);
+-        exit(1);
++        /* according to documentation, these can be safely ignored */
++        break;
+     case 0x402:
+     case 0x403:
+ #ifdef DEBUG_BIOS
+@@ -410,8 +411,9 @@
+         /* LGPL'ed VGA BIOS messages */
+     case 0x501:
+     case 0x502:
++        /* according to documentation, these can be safely ignored */
+         fprintf(stderr, "VGA BIOS panic, line %d\n", val);
+-        exit(1);
++        break;
+     case 0x500:
+     case 0x503:
+ #ifdef DEBUG_BIOS
