ia64/xen-unstable

changeset 15112:7caa6c1cabc8

merge with xen-unstable.hg
author Alex Williamson <alex.williamson@hp.com>
date Wed May 16 10:59:01 2007 -0600 (2007-05-16)
parents afb27041a2ce d4a0706d6747
children 2d26b66901d2
files tools/ioemu/.CVS/Entries.Log tools/ioemu/README.distrib tools/ioemu/hw/acpi-dsdt.dsl tools/ioemu/hw/acpi-dsdt.hex tools/ioemu/hw/lance.c tools/ioemu/ia64_intrinsic.h tools/ioemu/patches/qemu-infrastructure tools/ioemu/patches/vnc-access-monitor-vt tools/ioemu/patches/vnc-listen-specific-interface tools/ioemu/patches/vnc-numpad-handling xen/arch/ia64/xen/mm.c xen/arch/x86/trampoline.S xen/include/public/foreign/reference.size
line diff
     1.1 --- a/tools/check/Makefile	Wed May 16 10:42:07 2007 -0600
     1.2 +++ b/tools/check/Makefile	Wed May 16 10:59:01 2007 -0600
     1.3 @@ -7,7 +7,7 @@ all: build
     1.4  # Check this machine is OK for building on.
     1.5  .PHONY: build
     1.6  build:
     1.7 -	XENFB_TOOLS=$(XENFB_TOOLS) ./chk build
     1.8 +	XENFB_TOOLS=$(XENFB_TOOLS) LIBXENAPI_BINDINGS=$(LIBXENAPI_BINDINGS) ./chk build
     1.9  
    1.10  # Check this machine is OK for installing on.
    1.11  # DO NOT use this check from 'make install' in the parent
    1.12 @@ -15,7 +15,7 @@ build:
    1.13  # copy rather than actually installing.
    1.14  .PHONY: install
    1.15  install:
    1.16 -	XENFB_TOOLS=$(XENFB_TOOLS) ./chk install
    1.17 +	XENFB_TOOLS=$(XENFB_TOOLS) LIBXENAPI_BINDINGS=$(LIBXENAPI_BINDINGS) ./chk install
    1.18  
    1.19  .PHONY: clean
    1.20  clean:
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/tools/check/check_curl	Wed May 16 10:59:01 2007 -0600
     2.3 @@ -0,0 +1,38 @@
     2.4 +#!/bin/sh
     2.5 +# CHECK-BUILD CHECK-INSTALL
     2.6 +
     2.7 +if [ ! "$LIBXENAPI_BINDINGS" = "y" ]
     2.8 +then
     2.9 +    echo -n "unused, "
    2.10 +    exit 0
    2.11 +fi
    2.12 +
    2.13 +RC=0
    2.14 +
    2.15 +CURL_CONFIG="$(which curl-config)"
    2.16 +tmpfile=$(mktemp)
    2.17 +
    2.18 +if test -z ${CURL_CONFIG}; then
    2.19 +    RC=1
    2.20 +else
    2.21 +    ${CURL_CONFIG} --libs 2>&1 > /dev/null
    2.22 +    RC=$?
    2.23 +fi
    2.24 +
    2.25 +if test $RC -ne 0; then
    2.26 +    echo "FAILED"
    2.27 +	echo " *** curl-config is missing. "
    2.28 +    echo " *** Please install curl-devel."
    2.29 +elif ! ld $($CURL_CONFIG --libs) -o $tmpfile >/dev/null 2>&1; then
    2.30 +    echo "FAILED"
    2.31 +    echo " *** dependency libraries for curl are missing: "
    2.32 +    RC=1
    2.33 +    for i in $(ld $($CURL_CONFIG --libs) -o $tmpfile 2>&1 >/dev/null); do
    2.34 +        case $i in
    2.35 +        -l*) echo lib${i#-l}
    2.36 +        esac
    2.37 +    done
    2.38 +fi
    2.39 +rm -f $tmpfile
    2.40 +
    2.41 +exit $RC
     3.1 --- a/tools/check/check_libvncserver	Wed May 16 10:42:07 2007 -0600
     3.2 +++ b/tools/check/check_libvncserver	Wed May 16 10:59:01 2007 -0600
     3.3 @@ -10,6 +10,7 @@ fi
     3.4  RC=0
     3.5  
     3.6  LIBVNCSERVER_CONFIG="$(which libvncserver-config)"
     3.7 +tmpfile=$(mktemp)
     3.8  
     3.9  if test -z ${LIBVNCSERVER_CONFIG}; then 
    3.10      RC=1
    3.11 @@ -22,6 +23,16 @@ if test $RC -ne 0; then
    3.12      echo "FAILED"
    3.13  	echo " *** libvncserver-config is missing. "
    3.14      echo " *** Please install libvncserver."
    3.15 +elif ! ld $($LIBVNCSERVER_CONFIG --libs) -o $tmpfile >/dev/null 2>&1; then
    3.16 +    echo "FAILED"
    3.17 +    echo " *** dependency libraries for libvncserver are missing: "
    3.18 +    RC=1
    3.19 +    for i in $(ld $($LIBVNCSERVER_CONFIG --libs) -o $tmpfile 2>&1 >/dev/null); do
    3.20 +        case $i in
    3.21 +        -l*) echo lib${i#-l}
    3.22 +        esac
    3.23 +    done
    3.24  fi
    3.25 +rm -f $tmpfile
    3.26  
    3.27  exit $RC
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/check/check_xml2	Wed May 16 10:59:01 2007 -0600
     4.3 @@ -0,0 +1,38 @@
     4.4 +#!/bin/sh
     4.5 +# CHECK-BUILD CHECK-INSTALL
     4.6 +
     4.7 +if [ ! "$LIBXENAPI_BINDINGS" = "y" ]
     4.8 +then
     4.9 +    echo -n "unused, "
    4.10 +    exit 0
    4.11 +fi
    4.12 +
    4.13 +RC=0
    4.14 +
    4.15 +XML2_CONFIG="$(which xml2-config)"
    4.16 +tmpfile=$(mktemp)
    4.17 +
    4.18 +if test -z ${XML2_CONFIG}; then
    4.19 +    RC=1
    4.20 +else
    4.21 +    ${XML2_CONFIG} --libs 2>&1 > /dev/null
    4.22 +    RC=$?
    4.23 +fi
    4.24 +
    4.25 +if test $RC -ne 0; then
    4.26 +    echo "FAILED"
    4.27 +	echo " *** xml2-config is missing. "
    4.28 +    echo " *** Please install libxml2-devel."
    4.29 +elif ! ld $($XML2_CONFIG --libs) -o $tmpfile >/dev/null 2>&1; then
    4.30 +    echo "FAILED"
    4.31 +    echo " *** dependency libraries for xml2 are missing: "
    4.32 +    RC=1
    4.33 +    for i in $(ld $($XML2_CONFIG --libs) -o $tmpfile 2>&1 >/dev/null); do
    4.34 +        case $i in
    4.35 +        -l*) echo lib${i#-l}
    4.36 +        esac
    4.37 +    done
    4.38 +fi
    4.39 +rm -f $tmpfile
    4.40 +
    4.41 +exit $RC
     5.1 --- a/tools/examples/vtpm-impl	Wed May 16 10:42:07 2007 -0600
     5.2 +++ b/tools/examples/vtpm-impl	Wed May 16 10:59:01 2007 -0600
     5.3 @@ -83,7 +83,7 @@ function vtpm_manager_cmd() {
     5.4   release_lock vtpm_mgr
     5.5  
     5.6   #return whether the command was successful
     5.7 - if [ $resp_hex ne $TPM_SUCCESS ]; then
     5.8 + if [ $resp_hex -ne $TPM_SUCCESS ]; then
     5.9     vtpm_fatal_error=1
    5.10     false
    5.11    else
     6.1 --- a/tools/firmware/hvmloader/acpi/dsdt.asl	Wed May 16 10:42:07 2007 -0600
     6.2 +++ b/tools/firmware/hvmloader/acpi/dsdt.asl	Wed May 16 10:59:01 2007 -0600
     6.3 @@ -27,13 +27,13 @@ DefinitionBlock ("DSDT.aml", "DSDT", 2, 
     6.4      Name (\APCL, 0x00010000)
     6.5      Name (\PUID, 0x00)
     6.6  
     6.7 -    /* Poweroff support - ties in with qemu emulation */
     6.8 +    /* S5 (power-off) type codes: must match with piix4 emulation! */
     6.9      Name (\_S5, Package (0x04)
    6.10      {
    6.11 -        0x07,
    6.12 -        0x07,
    6.13 -        0x00,
    6.14 -        0x00
    6.15 +        0x07,  /* PM1a_CNT.SLP_TYP */
    6.16 +        0x07,  /* PM1b_CNT.SLP_TYP */
    6.17 +        0x00,  /* reserved */
    6.18 +        0x00   /* reserved */
    6.19      })
    6.20  
    6.21      Name(PICD, 0)
     7.1 --- a/tools/firmware/hvmloader/acpi/dsdt.c	Wed May 16 10:42:07 2007 -0600
     7.2 +++ b/tools/firmware/hvmloader/acpi/dsdt.c	Wed May 16 10:59:01 2007 -0600
     7.3 @@ -1,11 +1,11 @@
     7.4  /*
     7.5   * 
     7.6   * Intel ACPI Component Architecture
     7.7 - * ASL Optimizing Compiler version 20060707 [Feb 16 2007]
     7.8 + * ASL Optimizing Compiler version 20060707 [Dec 30 2006]
     7.9   * Copyright (C) 2000 - 2006 Intel Corporation
    7.10   * Supports ACPI Specification Revision 3.0a
    7.11   * 
    7.12 - * Compilation of "dsdt.asl" - Mon Feb 26 11:09:49 2007
    7.13 + * Compilation of "dsdt.asl" - Sat May 12 16:13:55 2007
    7.14   * 
    7.15   * C source code output
    7.16   *
     8.1 --- a/tools/ioemu/.CVS/Entries	Wed May 16 10:42:07 2007 -0600
     8.2 +++ b/tools/ioemu/.CVS/Entries	Wed May 16 10:59:01 2007 -0600
     8.3 @@ -1,109 +1,117 @@
     8.4  D/audio////
     8.5  D/hw////
     8.6 -D/linux-user////
     8.7  D/pc-bios////
     8.8 -D/slirp////
     8.9 -D/target-arm////
    8.10  D/target-i386////
    8.11 -D/target-ppc////
    8.12 -D/target-sparc////
    8.13  D/tests////
    8.14  D/fpu////
    8.15  D/keymaps////
    8.16 +/.cvsignore/1.16/Thu May  3 17:17:53 2007//Trelease_0_9_0
    8.17 +/COPYING/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
    8.18 +/COPYING.LIB/1.2/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
    8.19 +/Changelog/1.128/Thu May  3 17:17:53 2007//Trelease_0_9_0
    8.20 +/LICENSE/1.3/Thu May  3 17:17:53 2007//Trelease_0_9_0
    8.21 +/Makefile/1.112/Thu May  3 17:17:53 2007//Trelease_0_9_0
    8.22 +/Makefile.target/1.144/Thu May  3 17:17:53 2007//Trelease_0_9_0
    8.23 +/README/1.12/Wed Oct 18 10:11:20 2006//Trelease_0_9_0
    8.24 +/TODO/1.39/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
    8.25 +/VERSION/1.30/Thu May  3 17:17:53 2007//Trelease_0_9_0
    8.26 +/a.out.h/1.2/Wed Oct 18 10:11:20 2006//Trelease_0_9_0
    8.27 +/aes.c/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
    8.28 +/aes.h/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
    8.29 +/alpha-dis.c/1.3/Thu May  3 17:17:54 2007//Trelease_0_9_0
    8.30 +/alpha.ld/1.1/Thu May  3 17:17:54 2007//Trelease_0_9_0
    8.31 +/arm-dis.c/1.3/Thu May  3 17:17:54 2007//Trelease_0_9_0
    8.32 +/arm-semi.c/1.2/Sun Jan 28 03:10:55 2007//Trelease_0_9_0
    8.33 +/arm.ld/1.2/Thu May  3 17:17:54 2007//Trelease_0_9_0
    8.34 +/block-bochs.c/1.3/Thu May  3 17:17:54 2007//Trelease_0_9_0
    8.35 +/block-cloop.c/1.4/Thu May  3 17:17:54 2007//Trelease_0_9_0
    8.36 +/block-cow.c/1.7/Thu May  3 17:17:54 2007//Trelease_0_9_0
    8.37 +/block-dmg.c/1.5/Thu May  3 17:17:54 2007//Trelease_0_9_0
    8.38 +/block-qcow.c/1.11/Thu May  3 17:17:54 2007//Trelease_0_9_0
    8.39 +/block-qcow2.c/1.4/Mon Aug  7 02:38:06 2006//Trelease_0_9_0
    8.40 +/block-raw.c/1.17/Thu Jan 18 00:22:11 2007//Trelease_0_9_0
    8.41 +/block-vmdk.c/1.10/Thu May  3 17:17:55 2007//Trelease_0_9_0
    8.42 +/block-vpc.c/1.4/Thu May  3 17:17:55 2007//Trelease_0_9_0
    8.43 +/block-vvfat.c/1.8/Thu May  3 17:17:55 2007//Trelease_0_9_0
    8.44 +/block.c/1.42/Thu May  3 17:17:55 2007//Trelease_0_9_0
    8.45 +/block_int.h/1.10/Thu May  3 17:17:55 2007//Trelease_0_9_0
    8.46 +/bswap.h/1.5/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
    8.47 +/check_ops.sh/1.1/Sun Jan  7 19:38:08 2007//Trelease_0_9_0
    8.48 +/cocoa.m/1.10/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
    8.49 +/configure/1.120/Thu May  3 17:17:55 2007//Trelease_0_9_0
    8.50 +/console.c/1.11/Thu May  3 17:17:55 2007//Trelease_0_9_0
    8.51 +/cpu-all.h/1.60/Thu May  3 17:17:55 2007//Trelease_0_9_0
    8.52 +/cpu-defs.h/1.17/Thu May  3 17:17:55 2007//Trelease_0_9_0
    8.53 +/cpu-exec.c/1.93/Thu May  3 17:17:55 2007//Trelease_0_9_0
    8.54 +/cutils.c/1.1/Sun Jan  7 22:04:40 2007//Trelease_0_9_0
    8.55 +/dis-asm.h/1.11/Wed Oct 18 10:11:20 2006//Trelease_0_9_0
    8.56 +/disas.c/1.34/Thu May  3 17:17:55 2007//Trelease_0_9_0
    8.57 +/disas.h/1.7/Thu May  3 17:17:36 2007//Trelease_0_9_0
    8.58 +/dyngen-exec.h/1.31/Thu May  3 17:17:55 2007//Trelease_0_9_0
    8.59 +/dyngen-op.h/1.1/Wed Oct 18 10:11:20 2006//Trelease_0_9_0
    8.60 +/dyngen.c/1.47/Thu May  3 17:17:55 2007//Trelease_0_9_0
    8.61 +/dyngen.h/1.12/Thu May  3 17:17:55 2007//Trelease_0_9_0
    8.62 +/elf.h/1.8/Thu May  3 17:17:55 2007//Trelease_0_9_0
    8.63 +/elf_ops.h/1.5/Thu May  3 17:17:55 2007//Trelease_0_9_0
    8.64 +/exec-all.h/1.49/Thu May  3 17:17:55 2007//Trelease_0_9_0
    8.65 +/exec.c/1.85/Thu May  3 17:17:55 2007//Trelease_0_9_0
    8.66 +/gdbstub.c/1.47/Thu May  3 17:17:55 2007//Trelease_0_9_0
    8.67 +/gdbstub.h/1.5/Thu May  3 17:17:55 2007//Trelease_0_9_0
    8.68 +/hostregs_helper.h/1.1/Sun Feb  4 13:37:44 2007//Trelease_0_9_0
    8.69 +/i386-dis.c/1.5/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
    8.70 +/i386-vl.ld/1.3/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
    8.71 +/i386.ld/1.2/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
    8.72 +/ia64.ld/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
    8.73 +/keymaps.c/1.2/Thu May  3 17:17:34 2007//Trelease_0_9_0
    8.74 +/kqemu.c/1.15/Thu May  3 17:17:55 2007//Trelease_0_9_0
    8.75 +/kqemu.h/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
    8.76 +/loader.c/1.4/Thu May  3 17:17:55 2007//Trelease_0_9_0
    8.77 +/m68k-dis.c/1.1/Thu May  3 17:17:56 2007//Trelease_0_9_0
    8.78 +/m68k.ld/1.1/Thu May  3 17:17:56 2007//Trelease_0_9_0
    8.79 +/mips-dis.c/1.4/Thu May  3 17:17:57 2007//Trelease_0_9_0
    8.80 +/monitor.c/1.64/Thu May  3 17:17:57 2007//Trelease_0_9_0
    8.81 +/osdep.c/1.15/Thu May  3 17:17:57 2007//Trelease_0_9_0
    8.82 +/osdep.h/1.8/Thu May  3 17:17:57 2007//Trelease_0_9_0
    8.83 +/ppc-dis.c/1.7/Thu May  3 17:17:58 2007//Trelease_0_9_0
    8.84 +/ppc.ld/1.2/Thu May  3 17:17:58 2007//Trelease_0_9_0
    8.85 +/qemu-binfmt-conf.sh/1.4/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
    8.86 +/qemu-doc.texi/1.128/Thu May  3 17:17:58 2007//Trelease_0_9_0
    8.87 +/qemu-img.c/1.16/Thu May  3 17:17:58 2007//Trelease_0_9_0
    8.88 +/qemu-img.texi/1.3/Thu May  3 17:17:58 2007//Trelease_0_9_0
    8.89 +/qemu-tech.texi/1.9/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
    8.90 +/qemu_socket.h/1.2/Thu May  3 17:17:58 2007//Trelease_0_9_0
    8.91 +/readline.c/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
    8.92 +/s390.ld/1.1/Thu May  3 17:17:58 2007//Trelease_0_9_0
    8.93 +/sdl.c/1.34/Thu May  3 17:17:58 2007//Trelease_0_9_0
    8.94 +/sdl_keysym.h/1.3/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
    8.95 +/sh4-dis.c/1.1/Thu May  3 17:17:58 2007//Trelease_0_9_0
    8.96 +/softmmu_exec.h/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
    8.97 +/softmmu_header.h/1.13/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
    8.98 +/softmmu_template.h/1.16/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
    8.99 +/sparc-dis.c/1.3/Thu May  3 17:17:59 2007//Trelease_0_9_0
   8.100 +/sparc.ld/1.1/Thu May  3 17:17:59 2007//Trelease_0_9_0
   8.101 +/sparc64.ld/1.1/Fri Aug  4 21:55:15 2006//Trelease_0_9_0
   8.102 +/tap-win32.c/1.4/Thu May  3 17:17:59 2007//Trelease_0_9_0
   8.103 +/texi2pod.pl/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
   8.104 +/thunk.c/1.6/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
   8.105 +/thunk.h/1.13/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
   8.106 +/translate-all.c/1.15/Thu May  3 17:17:59 2007//Trelease_0_9_0
   8.107 +/translate-op.c/1.1/Wed Oct 18 10:11:21 2006//Trelease_0_9_0
   8.108 +/usb-linux.c/1.10/Thu May  3 17:17:59 2007//Trelease_0_9_0
   8.109 +/vgafont.h/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
   8.110 +/vl.c/1.248/Thu May  3 17:17:59 2007//Trelease_0_9_0
   8.111 +/vl.h/1.184/Thu May  3 17:17:59 2007//Trelease_0_9_0
   8.112 +/vnc.c/1.12/Thu May  3 17:17:59 2007//Trelease_0_9_0
   8.113 +/vnc_keysym.h/1.2/Thu May  3 17:17:59 2007//Trelease_0_9_0
   8.114 +/vnchextile.h/1.3/Thu May  3 17:17:59 2007//Trelease_0_9_0
   8.115 +/x86_64.ld/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_9_0
   8.116 +/x_keymap.c/1.1/Wed Jan 24 21:40:21 2007//Trelease_0_9_0
   8.117 +D/darwin-user////
   8.118 +D/linux-user////
   8.119 +D/slirp////
   8.120 +D/target-arm////
   8.121 +D/target-m68k////
   8.122  D/target-mips////
   8.123 +D/target-ppc////
   8.124  D/target-sh4////
   8.125 -/.cvsignore/1.14/Sun Aug  6 01:03:44 2006//Trelease_0_8_2
   8.126 -/COPYING/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
   8.127 -/COPYING.LIB/1.2/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
   8.128 -/Changelog/1.121/Sun Aug  6 01:03:44 2006//Trelease_0_8_2
   8.129 -/LICENSE/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
   8.130 -/Makefile/1.104/Sun Aug  6 01:03:44 2006//Trelease_0_8_2
   8.131 -/Makefile.target/1.121/Sun Aug  6 01:03:44 2006//Trelease_0_8_2
   8.132 -/README/1.12/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
   8.133 -/README.distrib/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
   8.134 -/TODO/1.39/Sun Aug  6 01:03:44 2006//Trelease_0_8_2
   8.135 -/VERSION/1.29/Sun Aug  6 01:03:44 2006//Trelease_0_8_2
   8.136 -/a.out.h/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
   8.137 -/aes.c/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
   8.138 -/aes.h/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
   8.139 -/alpha-dis.c/1.3/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.140 -/alpha.ld/1.1/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.141 -/arm-dis.c/1.3/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.142 -/arm.ld/1.1/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.143 -/block-bochs.c/1.1/Sun Aug  6 00:55:02 2006//Trelease_0_8_2
   8.144 -/block-cloop.c/1.3/Sun Aug  6 00:55:02 2006//Trelease_0_8_2
   8.145 -/block-cow.c/1.6/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.146 -/block-dmg.c/1.4/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
   8.147 -/block-qcow.c/1.7/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.148 -/block-vmdk.c/1.8/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.149 -/block-vpc.c/1.3/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.150 -/block-vvfat.c/1.6/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.151 -/block.c/1.28/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.152 -/block_int.h/1.5/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.153 -/bswap.h/1.5/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
   8.154 -/cocoa.m/1.10/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.155 -/configure/1.110/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.156 -/console.c/1.8/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.157 -/cpu-all.h/1.57/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.158 -/cpu-defs.h/1.16/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.159 -/cpu-exec.c/1.83/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.160 -/dis-asm.h/1.11/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
   8.161 -/disas.c/1.31/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.162 -/disas.h/1.7/Sun Aug  6 00:55:03 2006//Trelease_0_8_2
   8.163 -/dyngen-exec.h/1.29/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.164 -/dyngen-op.h/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
   8.165 -/dyngen.c/1.45/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.166 -/dyngen.h/1.11/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.167 -/elf.h/1.7/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.168 -/elf_ops.h/1.3/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
   8.169 -/exec-all.h/1.48/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.170 -/exec.c/1.82/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.171 -/gdbstub.c/1.40/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.172 -/gdbstub.h/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
   8.173 -/i386-dis.c/1.5/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
   8.174 -/i386-vl.ld/1.3/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
   8.175 -/i386.ld/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
   8.176 -/ia64.ld/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
   8.177 -/keymaps.c/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
   8.178 -/kqemu.c/1.12/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.179 -/kqemu.h/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
   8.180 -/linux-2.6.9-qemu-fast.patch/1.1/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.181 -/loader.c/1.3/Sun Aug  6 01:03:45 2006//Trelease_0_8_2
   8.182 -/m68k-dis.c/1.1/Sun Aug  6 01:03:46 2006//Trelease_0_8_2
   8.183 -/m68k.ld/1.1/Sun Aug  6 01:03:46 2006//Trelease_0_8_2
   8.184 -/mips-dis.c/1.4/Sun Aug  6 01:03:47 2006//Trelease_0_8_2
   8.185 -/monitor.c/1.54/Sun Aug  6 01:03:47 2006//Trelease_0_8_2
   8.186 -/osdep.c/1.11/Sun Aug  6 01:03:47 2006//Trelease_0_8_2
   8.187 -/osdep.h/1.6/Sun Aug  6 01:03:47 2006//Trelease_0_8_2
   8.188 -/ppc-dis.c/1.7/Sun Aug  6 01:03:48 2006//Trelease_0_8_2
   8.189 -/ppc.ld/1.2/Sun Aug  6 01:03:48 2006//Trelease_0_8_2
   8.190 -/qemu-binfmt-conf.sh/1.4/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
   8.191 -/qemu-doc.texi/1.100/Sun Aug  6 01:03:48 2006//Trelease_0_8_2
   8.192 -/qemu-img.c/1.10/Sun Aug  6 01:03:48 2006//Trelease_0_8_2
   8.193 -/qemu-img.texi/1.2/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
   8.194 -/qemu-tech.texi/1.9/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
   8.195 -/qemu_socket.h/1.1/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
   8.196 -/readline.c/1.1/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
   8.197 -/s390.ld/1.1/Sun Aug  6 01:03:48 2006//Trelease_0_8_2
   8.198 -/sdl.c/1.29/Sun Aug  6 01:03:48 2006//Trelease_0_8_2
   8.199 -/sdl_keysym.h/1.3/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
   8.200 -/sh4-dis.c/1.1/Sun Aug  6 01:03:48 2006//Trelease_0_8_2
   8.201 -/softmmu_exec.h/1.1/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
   8.202 -/softmmu_header.h/1.13/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
   8.203 -/softmmu_template.h/1.16/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
   8.204 -/sparc-dis.c/1.3/Sun Aug  6 01:03:49 2006//Trelease_0_8_2
   8.205 -/sparc.ld/1.1/Sun Aug  6 01:03:49 2006//Trelease_0_8_2
   8.206 -/tap-win32.c/1.3/Sun Aug  6 01:03:49 2006//Trelease_0_8_2
   8.207 -/texi2pod.pl/1.1/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
   8.208 -/thunk.c/1.6/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
   8.209 -/thunk.h/1.13/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
   8.210 -/translate-all.c/1.14/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
   8.211 -/translate-op.c/1.1/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
   8.212 -/usb-linux.c/1.8/Sun Aug  6 01:03:49 2006//Trelease_0_8_2
   8.213 -/vgafont.h/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
   8.214 -/vl.c/1.202/Sun Aug  6 01:03:49 2006//Trelease_0_8_2
   8.215 -/vl.h/1.136/Sun Aug  6 01:03:49 2006//Trelease_0_8_2
   8.216 -/vnc.c/1.7/Sun Aug  6 01:03:49 2006//Trelease_0_8_2
   8.217 -/vnc_keysym.h/1.1/Fri Jul 14 12:43:46 2006//Trelease_0_8_2
   8.218 -/vnchextile.h/1.2/Sun Aug  6 01:03:49 2006//Trelease_0_8_2
   8.219 -/x86_64.ld/1.1/Thu Jul 13 09:23:22 2006//Trelease_0_8_2
   8.220 +D/target-sparc////
     9.1 --- a/tools/ioemu/.CVS/Entries.Log	Wed May 16 10:42:07 2007 -0600
     9.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.3 @@ -1,7 +0,0 @@
     9.4 -A D/linux-user////
     9.5 -A D/slirp////
     9.6 -A D/target-arm////
     9.7 -A D/target-mips////
     9.8 -A D/target-ppc////
     9.9 -A D/target-sh4////
    9.10 -A D/target-sparc////
    10.1 --- a/tools/ioemu/.CVS/Tag	Wed May 16 10:42:07 2007 -0600
    10.2 +++ b/tools/ioemu/.CVS/Tag	Wed May 16 10:59:01 2007 -0600
    10.3 @@ -1,1 +1,1 @@
    10.4 -Nrelease_0_8_2
    10.5 +Nrelease_0_9_0
    11.1 --- a/tools/ioemu/.cvsignore	Wed May 16 10:42:07 2007 -0600
    11.2 +++ b/tools/ioemu/.cvsignore	Wed May 16 10:59:01 2007 -0600
    11.3 @@ -1,14 +1,16 @@
    11.4 -arm-user
    11.5 +arm-linux-user
    11.6  arm-softmmu
    11.7 -armeb-user
    11.8 +armeb-linux-user
    11.9  config-host.*
   11.10  dyngen
   11.11  i386
   11.12  i386-softmmu
   11.13 -i386-user
   11.14 +i386-darwin-user
   11.15 +i386-linux-user
   11.16  ppc-softmmu
   11.17  ppc64-softmmu
   11.18 -ppc-user
   11.19 +ppc-darwin-user
   11.20 +ppc-linux-user
   11.21  qemu-doc.html
   11.22  qemu-tech.html
   11.23  qemu-doc.info
   11.24 @@ -17,18 +19,19 @@ qemu.1
   11.25  qemu.pod
   11.26  qemu-img.1
   11.27  qemu-img.pod
   11.28 -sparc-user
   11.29 +sparc-linux-user
   11.30  qemu-img
   11.31  sparc-softmmu
   11.32  x86_64-softmmu
   11.33 -sparc64-user
   11.34 +sparc64-linux-user
   11.35  sparc64-softmmu
   11.36  mips-softmmu
   11.37  mipsel-softmmu
   11.38 -mips-user
   11.39 -mipsel-user
   11.40 +mips-linux-user
   11.41 +mipsel-linux-user
   11.42 +m68k-linux-user
   11.43  .gdbinit
   11.44 -sh4-user
   11.45 +sh4-linux-user
   11.46  sh4-softmmu
   11.47  *.aux
   11.48  *.cp
    12.1 --- a/tools/ioemu/Changelog	Wed May 16 10:42:07 2007 -0600
    12.2 +++ b/tools/ioemu/Changelog	Wed May 16 10:59:01 2007 -0600
    12.3 @@ -1,3 +1,21 @@
    12.4 +version 0.9.0:
    12.5 +
    12.6 +  - Support for relative paths in backing files for disk images
    12.7 +  - Async file I/O API
    12.8 +  - New qcow2 disk image format
    12.9 +  - Support of multiple VM snapshots
   12.10 +  - Linux: specific host CDROM and floppy support
   12.11 +  - SMM support
   12.12 +  - Moved PCI init, MP table init and ACPI table init to Bochs BIOS
   12.13 +  - Support for MIPS32 Release 2 instruction set (Thiemo Seufer)
   12.14 +  - MIPS Malta system emulation (Aurelien Jarno, Stefan Weil)
   12.15 +  - Darwin userspace emulation (Pierre d'Herbemont)
   12.16 +  - m68k user support (Paul Brook)
   12.17 +  - several x86 and x86_64 emulation fixes
   12.18 +  - Mouse relative offset VNC extension (Anthony Liguori)
   12.19 +  - PXE boot support (Anthony Liguori)
   12.20 +  - '-daemonize' option (Anthony Liguori)
   12.21 +
   12.22  version 0.8.2:
   12.23  
   12.24    - ACPI support
    13.1 --- a/tools/ioemu/LICENSE	Wed May 16 10:42:07 2007 -0600
    13.2 +++ b/tools/ioemu/LICENSE	Wed May 16 10:59:01 2007 -0600
    13.3 @@ -1,11 +1,14 @@
    13.4 -The following points clarify the QEMU licenses:
    13.5 +The following points clarify the QEMU license:
    13.6 +
    13.7 +1) QEMU as a whole is released under the GNU General Public License
    13.8  
    13.9 -1) The QEMU virtual CPU core library (libqemu.a) and the QEMU PC
   13.10 -   system emulator are released under the GNU Lesser General Public
   13.11 -   License.
   13.12 +2) Parts of QEMU have specific licenses which are compatible with the
   13.13 +GNU General Public License. Hence each source file contains its own
   13.14 +licensing information.
   13.15  
   13.16 -2) The Linux user mode QEMU emulator is released under the GNU General
   13.17 -   Public License.
   13.18 +In particular, the QEMU virtual CPU core library (libqemu.a) is
   13.19 +released under the GNU Lesser General Public License. Many hardware
   13.20 +device emulation sources are released under the BSD license.
   13.21  
   13.22  3) QEMU is a trademark of Fabrice Bellard.
   13.23  
    14.1 --- a/tools/ioemu/Makefile	Wed May 16 10:42:07 2007 -0600
    14.2 +++ b/tools/ioemu/Makefile	Wed May 16 10:59:01 2007 -0600
    14.3 @@ -8,19 +8,18 @@ include $(XEN_ROOT)/tools/Rules.mk
    14.4  .PHONY: all clean distclean dvi info install install-doc tar tarbin \
    14.5  	speed test test2 html dvi info
    14.6  
    14.7 -CFLAGS+=-Wall -O2 -g -fno-strict-aliasing -I.
    14.8 -ifdef CONFIG_DARWIN
    14.9 -CFLAGS+= -mdynamic-no-pic
   14.10 -endif
   14.11 +BASE_CFLAGS=
   14.12 +BASE_LDFLAGS=
   14.13 +
   14.14 +BASE_CFLAGS += $(OS_CFLAGS)
   14.15  ifeq ($(ARCH),sparc)
   14.16 -CFLAGS+=-mcpu=ultrasparc
   14.17 +BASE_CFLAGS += -mcpu=ultrasparc
   14.18  endif
   14.19 -LDFLAGS=-g
   14.20 +CPPFLAGS += -I. -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
   14.21  LIBS=
   14.22 -DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
   14.23  TOOLS=qemu-img$(EXESUF)
   14.24  ifdef CONFIG_STATIC
   14.25 -LDFLAGS+=-static
   14.26 +BASE_LDFLAGS += -static
   14.27  endif
   14.28  ifdef BUILD_DOCS
   14.29  DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1
   14.30 @@ -28,6 +27,14 @@ else
   14.31  DOCS=
   14.32  endif
   14.33  
   14.34 +ifndef CONFIG_DARWIN
   14.35 +ifndef CONFIG_WIN32
   14.36 +ifndef CONFIG_SOLARIS
   14.37 +LIBS+=-lrt
   14.38 +endif
   14.39 +endif
   14.40 +endif
   14.41 +
   14.42  TOOLS=
   14.43  
   14.44  all: $(TOOLS) $(DOCS) recurse-all
   14.45 @@ -36,12 +43,12 @@ subdir-%:
   14.46  	$(MAKE) -C $(subst subdir-,,$@) all
   14.47  
   14.48  recurse-all: $(patsubst %,subdir-%, $(TARGET_DIRS))
   14.49 -        
   14.50 -qemu-img$(EXESUF): qemu-img.c block.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c
   14.51 -	$(CC) -DQEMU_TOOL $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ -lz $(LIBS)
   14.52 +
   14.53 +qemu-img$(EXESUF): qemu-img.c cutils.c block.c block-raw.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c block-dmg.c block-bochs.c block-vpc.c block-vvfat.c block-qcow2.c
   14.54 +	$(CC) -DQEMU_TOOL $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) $(LDFLAGS) $(BASE_LDFLAGS) -o $@ $^ -lz $(LIBS)
   14.55  
   14.56  dyngen$(EXESUF): dyngen.c
   14.57 -	$(HOST_CC) $(CFLAGS) $(DEFINES) -o $@ $^
   14.58 +	$(HOST_CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -o $@ $^
   14.59  
   14.60  clean:
   14.61  # avoid old build problems by removing potentially incorrect old files
   14.62 @@ -65,7 +72,7 @@ common  de-ch  es     fo  fr-ca  hu     
   14.63  
   14.64  install-doc: $(DOCS)
   14.65  	mkdir -p "$(DESTDIR)$(docdir)"
   14.66 -	$(INSTALL_DATA) qemu-doc.html  qemu-tech.html "$(DESTDIR)$(docdir)"
   14.67 +	$(INSTALL_DATA) -m 644 qemu-doc.html  qemu-tech.html "$(DESTDIR)$(docdir)"
   14.68  ifndef CONFIG_WIN32
   14.69  	mkdir -p "$(DESTDIR)$(mandir)/man1"
   14.70  	$(INSTALL_DATA) qemu.1 qemu-img.1 "$(DESTDIR)$(mandir)/man1"
   14.71 @@ -76,13 +83,14 @@ install: all $(if $(BUILD_DOCS),install-
   14.72  #	$(INSTALL) -m 755 -s $(TOOLS) "$(DESTDIR)$(bindir)"
   14.73  #	mkdir -p "$(DESTDIR)$(datadir)"
   14.74  #	for x in bios.bin vgabios.bin vgabios-cirrus.bin ppc_rom.bin \
   14.75 -#			video.x openbios-sparc32 linux_boot.bin; do \
   14.76 -#		$(INSTALL_DATA) $(SRC_PATH)/pc-bios/$$x "$(DESTDIR)$(datadir)"; \
   14.77 +#		video.x openbios-sparc32 linux_boot.bin pxe-ne2k_pci.bin \
   14.78 +#		pxe-rtl8139.bin pxe-pcnet.bin; do \
   14.79 +#		$(INSTALL) -m 644 $(SRC_PATH)/pc-bios/$$x "$(DESTDIR)$(datadir)"; \
   14.80  #	done
   14.81  ifndef CONFIG_WIN32
   14.82  	mkdir -p "$(DESTDIR)$(datadir)/keymaps"
   14.83  	for x in $(KEYMAPS); do \
   14.84 -		$(INSTALL_DATA) $(SRC_PATH)/keymaps/$$x "$(DESTDIR)$(datadir)/keymaps"; \
   14.85 +		$(INSTALL_DATA) -m 644 $(SRC_PATH)/keymaps/$$x "$(DESTDIR)$(datadir)/keymaps"; \
   14.86  	done
   14.87  endif
   14.88  	for d in $(TARGET_DIRS); do \
   14.89 @@ -125,7 +133,8 @@ dvi: qemu-doc.dvi qemu-tech.dvi
   14.90  
   14.91  html: qemu-doc.html qemu-tech.html
   14.92  
   14.93 -FILE=qemu-$(shell cat VERSION)
   14.94 +VERSION ?= $(shell cat VERSION)
   14.95 +FILE = qemu-$(VERSION)
   14.96  
   14.97  # tar release (use 'make -k tar' on a checkouted tree)
   14.98  tar:
   14.99 @@ -159,6 +168,9 @@ tarbin:
  14.100  	$(datadir)/video.x \
  14.101  	$(datadir)/openbios-sparc32 \
  14.102  	$(datadir)/linux_boot.bin \
  14.103 +        $(datadir)/pxe-ne2k_pci.bin \
  14.104 +	$(datadir)/pxe-rtl8139.bin \
  14.105 +        $(datadir)/pxe-pcnet.bin \
  14.106  	$(docdir)/qemu-doc.html \
  14.107  	$(docdir)/qemu-tech.html \
  14.108  	$(mandir)/man1/qemu.1 $(mandir)/man1/qemu-img.1 )
    15.1 --- a/tools/ioemu/Makefile.target	Wed May 16 10:42:07 2007 -0600
    15.2 +++ b/tools/ioemu/Makefile.target	Wed May 16 10:59:01 2007 -0600
    15.3 @@ -15,21 +15,24 @@ TARGET_BASE_ARCH:=sparc
    15.4  endif
    15.5  TARGET_PATH=$(SRC_PATH)/target-$(TARGET_BASE_ARCH)$(TARGET_SUB)
    15.6  VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw:$(SRC_PATH)/audio
    15.7 -DEFINES=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH)
    15.8 -DEFINES+= -I$(XEN_ROOT)/tools/libxc
    15.9 -DEFINES+= -I$(XEN_ROOT)/tools/xenstore
   15.10 -ifdef CONFIG_USER_ONLY
   15.11 +CPPFLAGS=-I. -I.. -I$(TARGET_PATH) -I$(SRC_PATH)
   15.12 +CPPFLAGS+= -I$(XEN_ROOT)/tools/libxc
   15.13 +CPPFLAGS+= -I$(XEN_ROOT)/tools/xenstore
   15.14 +ifdef CONFIG_DARWIN_USER
   15.15 +VPATH+=:$(SRC_PATH)/darwin-user
   15.16 +CPPFLAGS+=-I$(SRC_PATH)/darwin-user -I$(SRC_PATH)/darwin-user/$(TARGET_ARCH)
   15.17 +endif
   15.18 +ifdef CONFIG_LINUX_USER
   15.19  VPATH+=:$(SRC_PATH)/linux-user
   15.20 -DEFINES+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ARCH)
   15.21 +CPPFLAGS+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ARCH)
   15.22  endif
   15.23 -CFLAGS+=-Wall -O2 -g -fno-strict-aliasing
   15.24 +BASE_CFLAGS=
   15.25 +BASE_LDFLAGS=
   15.26  SSE2 := $(call cc-option,$(CC),-msse2,)
   15.27  ifeq ($(SSE2),-msse2)
   15.28  CFLAGS += -DUSE_SSE2=1 -msse2
   15.29  endif
   15.30 -CFLAGS+= $(LOCAL_CFLAGS)
   15.31  #CFLAGS+=-Werror
   15.32 -LDFLAGS=-g
   15.33  LIBS=
   15.34  HELPER_CFLAGS=$(CFLAGS)
   15.35  DYNGEN=../dyngen$(EXESUF)
   15.36 @@ -74,18 +77,20 @@ endif
   15.37  endif # !CONFIG_USER_ONLY
   15.38  
   15.39  ifdef CONFIG_STATIC
   15.40 -LDFLAGS+=-static
   15.41 +BASE_LDFLAGS+=-static
   15.42  endif
   15.43  
   15.44 +# We require -O2 to avoid the stack setup prologue in EXIT_TB
   15.45 +OP_CFLAGS = -Wall -O2 -g -fno-strict-aliasing
   15.46 +
   15.47  ifeq ($(ARCH),i386)
   15.48 -CFLAGS+=-fomit-frame-pointer
   15.49 -OP_CFLAGS=$(CFLAGS) -mpreferred-stack-boundary=2
   15.50 +HELPER_CFLAGS+=-fomit-frame-pointer
   15.51 +OP_CFLAGS+=-mpreferred-stack-boundary=2 -fomit-frame-pointer
   15.52  ifeq ($(HAVE_GCC3_OPTIONS),yes)
   15.53  OP_CFLAGS+= -falign-functions=0 -fno-gcse
   15.54  else
   15.55  OP_CFLAGS+= -malign-functions=0
   15.56  endif
   15.57 -
   15.58  ifdef TARGET_GPROF
   15.59  USE_I386_LD=y
   15.60  endif
   15.61 @@ -93,76 +98,80 @@ ifdef CONFIG_STATIC
   15.62  USE_I386_LD=y
   15.63  endif
   15.64  ifdef USE_I386_LD
   15.65 -LDFLAGS+=-Wl,-T,$(SRC_PATH)/i386.ld
   15.66 +BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
   15.67  else
   15.68 +ifdef CONFIG_LINUX_USER
   15.69  # WARNING: this LDFLAGS is _very_ tricky : qemu is an ELF shared object
   15.70  # that the kernel ELF loader considers as an executable. I think this
   15.71  # is the simplest way to make it self virtualizable!
   15.72 -LDFLAGS+=-Wl,-shared
   15.73 +BASE_LDFLAGS+=-Wl,-shared
   15.74 +endif
   15.75  endif
   15.76  endif
   15.77  
   15.78  ifeq ($(ARCH),x86_64)
   15.79 -OP_CFLAGS=$(CFLAGS) -falign-functions=0
   15.80 -LDFLAGS+=-Wl,-T,$(SRC_PATH)/x86_64.ld
   15.81 +BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
   15.82  endif
   15.83  
   15.84  ifeq ($(ARCH),ppc)
   15.85 -CFLAGS+= -D__powerpc__
   15.86 -OP_CFLAGS=$(CFLAGS)
   15.87 -LDFLAGS+=-Wl,-T,$(SRC_PATH)/ppc.ld
   15.88 +CPPFLAGS+= -D__powerpc__
   15.89 +ifdef CONFIG_LINUX_USER
   15.90 +BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
   15.91 +endif
   15.92  endif
   15.93  
   15.94  ifeq ($(ARCH),s390)
   15.95 -OP_CFLAGS=$(CFLAGS)
   15.96 -LDFLAGS+=-Wl,-T,$(SRC_PATH)/s390.ld
   15.97 +BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
   15.98  endif
   15.99  
  15.100  ifeq ($(ARCH),sparc)
  15.101  ifeq ($(CONFIG_SOLARIS),yes)
  15.102 -CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g2 -ffixed-g3
  15.103 -LDFLAGS+=-m32
  15.104 -OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -fno-omit-frame-pointer -ffixed-i0
  15.105 +BASE_CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g2 -ffixed-g3
  15.106 +BASE_LDFLAGS+=-m32
  15.107 +OP_CFLAGS+=-fno-delayed-branch -fno-omit-frame-pointer -ffixed-i0
  15.108  else
  15.109 -CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
  15.110 -LDFLAGS+=-m32
  15.111 -OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0
  15.112 +BASE_CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
  15.113 +BASE_LDFLAGS+=-m32
  15.114 +OP_CFLAGS+=-fno-delayed-branch -ffixed-i0
  15.115  HELPER_CFLAGS=$(CFLAGS) -ffixed-i0 -mflat
  15.116  # -static is used to avoid g1/g3 usage by the dynamic linker
  15.117 -LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc.ld -static
  15.118 +BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld -static
  15.119  endif
  15.120  endif
  15.121  
  15.122  ifeq ($(ARCH),sparc64)
  15.123 -CFLAGS+=-mcpu=ultrasparc -m64 -ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7
  15.124 -LDFLAGS+=-m64
  15.125 -LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc64.ld
  15.126 -OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0
  15.127 +BASE_CFLAGS+=-mcpu=ultrasparc -m64 -ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7
  15.128 +BASE_LDFLAGS+=-m64
  15.129 +BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
  15.130 +OP_CFLAGS+=-mcpu=ultrasparc -m64 -ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7 -fno-delayed-branch -ffixed-i0
  15.131  endif
  15.132  
  15.133  ifeq ($(ARCH),alpha)
  15.134 -# -msmall-data is not used because we want two-instruction relocations
  15.135 -# for the constant constructions
  15.136 -OP_CFLAGS=-Wall -O2 -g
  15.137 +# -msmall-data is not used for OP_CFLAGS because we want two-instruction
  15.138 +# relocations for the constant constructions
  15.139  # Ensure there's only a single GP
  15.140 -CFLAGS += -msmall-data
  15.141 -LDFLAGS+=-Wl,-T,$(SRC_PATH)/alpha.ld
  15.142 +BASE_CFLAGS+=-msmall-data
  15.143 +BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
  15.144  endif
  15.145  
  15.146  ifeq ($(ARCH),ia64)
  15.147 -CFLAGS += -mno-sdata
  15.148 -OP_CFLAGS=$(CFLAGS)
  15.149 -LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/ia64.ld
  15.150 +BASE_CFLAGS+=-mno-sdata
  15.151 +OP_CFLAGS+=-mno-sdata
  15.152 +BASE_LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/$(ARCH).ld
  15.153  endif
  15.154  
  15.155  ifeq ($(ARCH),arm)
  15.156 -OP_CFLAGS=$(CFLAGS) -mno-sched-prolog -fno-omit-frame-pointer
  15.157 -LDFLAGS+=-Wl,-T,$(SRC_PATH)/arm.ld
  15.158 +OP_CFLAGS+=-mno-sched-prolog -fno-omit-frame-pointer
  15.159 +BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
  15.160  endif
  15.161  
  15.162  ifeq ($(ARCH),m68k)
  15.163 -OP_CFLAGS=$(CFLAGS) -fomit-frame-pointer
  15.164 -LDFLAGS+=-Wl,-T,m68k.ld
  15.165 +OP_CFLAGS+=-fomit-frame-pointer
  15.166 +BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
  15.167 +endif
  15.168 +
  15.169 +ifeq ($(ARCH),mips)
  15.170 +BASE_LDFLAGS+=-Wl,-T,$(SRC_PATH)/$(ARCH).ld
  15.171  endif
  15.172  
  15.173  ifeq ($(HAVE_GCC3_OPTIONS),yes)
  15.174 @@ -171,14 +180,20 @@ OP_CFLAGS+=-fno-reorder-blocks -fno-opti
  15.175  endif
  15.176  
  15.177  ifeq ($(CONFIG_DARWIN),yes)
  15.178 -OP_CFLAGS+= -mdynamic-no-pic
  15.179  LIBS+=-lmx
  15.180  endif
  15.181  
  15.182 +ifdef CONFIG_DARWIN_USER
  15.183 +# Leave some space for the regular program loading zone
  15.184 +BASE_LDFLAGS+=-Wl,-segaddr,__STD_PROG_ZONE,0x1000 -image_base 0x0e000000
  15.185 +endif
  15.186 +
  15.187 +OP_CFLAGS+=$(OS_CFLAGS)
  15.188 +
  15.189  #########################################################
  15.190  
  15.191 -DEFINES+=-D_GNU_SOURCE
  15.192 -#-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
  15.193 +CPPFLAGS+=-D_GNU_SOURCE
  15.194 +# -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
  15.195  LIBS+=-lm
  15.196  LIBS+=-L../../libxc -lxenctrl -lxenguest
  15.197  LIBS+=-L../../xenstore -lxenstore
  15.198 @@ -195,10 +210,11 @@ endif
  15.199  
  15.200  # profiling code
  15.201  ifdef TARGET_GPROF
  15.202 -LDFLAGS+=-p
  15.203 -main.o: CFLAGS+=-p
  15.204 +BASE_LDFLAGS+=-p
  15.205 +main.o: BASE_CFLAGS+=-p
  15.206  endif
  15.207  
  15.208 +ifdef CONFIG_LINUX_USER
  15.209  OBJS= main.o syscall.o mmap.o signal.o path.o osdep.o thunk.o \
  15.210        elfload.o linuxload.o
  15.211  ifdef TARGET_HAS_BFLT
  15.212 @@ -213,6 +229,15 @@ OBJS+=nwfpe/fpa11.o nwfpe/fpa11_cpdo.o \
  15.213  nwfpe/fpa11_cpdt.o nwfpe/fpa11_cprt.o nwfpe/fpopcode.o nwfpe/single_cpdo.o \
  15.214   nwfpe/double_cpdo.o nwfpe/extended_cpdo.o arm-semi.o
  15.215  endif
  15.216 +ifeq ($(TARGET_ARCH), m68k)
  15.217 +OBJS+= m68k-sim.o m68k-semi.o
  15.218 +endif
  15.219 +endif #CONFIG_LINUX_USER
  15.220 +
  15.221 +ifdef CONFIG_DARWIN_USER
  15.222 +OBJS= main.o commpage.o machload.o mmap.o osdep.o signal.o syscall.o thunk.o
  15.223 +endif
  15.224 +
  15.225  SRCS:= $(OBJS:.o=.c)
  15.226  OBJS+= libqemu.a
  15.227  
  15.228 @@ -224,7 +249,7 @@ LIBOBJS+=fpu/softfloat.o
  15.229  else
  15.230  LIBOBJS+=fpu/softfloat-native.o
  15.231  endif
  15.232 -DEFINES+=-I$(SRC_PATH)/fpu
  15.233 +CPPFLAGS+=-I$(SRC_PATH)/fpu
  15.234  
  15.235  ifeq ($(TARGET_ARCH), i386)
  15.236  LIBOBJS+=helper.o helper2.o
  15.237 @@ -257,6 +282,10 @@ ifeq ($(TARGET_BASE_ARCH), sh4)
  15.238  LIBOBJS+= op_helper.o helper.o
  15.239  endif
  15.240  
  15.241 +ifeq ($(TARGET_BASE_ARCH), m68k)
  15.242 +LIBOBJS+= helper.o
  15.243 +endif
  15.244 +
  15.245  # NOTE: the disassembler code is only needed for debugging
  15.246  LIBOBJS+=disas.o 
  15.247  ifeq ($(findstring i386, $(TARGET_ARCH) $(ARCH)),i386)
  15.248 @@ -304,7 +333,7 @@ endif
  15.249  all: $(PROGS)
  15.250  
  15.251  $(QEMU_USER): $(OBJS)
  15.252 -	$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^  $(LIBS)
  15.253 +	$(CC) $(CFLAGS) $(LDFLAGS) $(BASE_LDFLAGS) -o $@ $^  $(LIBS)
  15.254  ifeq ($(ARCH),alpha)
  15.255  # Mark as 32 bit binary, i. e. it will be mapped into the low 31 bit of
  15.256  # the address space (31 bit so sign extending doesn't matter)
  15.257 @@ -312,8 +341,10 @@ ifeq ($(ARCH),alpha)
  15.258  endif
  15.259  
  15.260  # must use static linking to avoid leaving stuff in virtual address space
  15.261 -VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o
  15.262 -VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o
  15.263 +VL_OBJS=vl.o osdep.o readline.o monitor.o pci.o console.o isa_mmio.o
  15.264 +VL_OBJS+=cutils.o
  15.265 +VL_OBJS+=block.o block-raw.o
  15.266 +VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o block-bochs.o block-vpc.o block-vvfat.o block-qcow2.o
  15.267  ifdef CONFIG_WIN32
  15.268  VL_OBJS+=tap-win32.o
  15.269  endif
  15.270 @@ -339,7 +370,7 @@ LIBS += -lole32 -ldxguid
  15.271  endif
  15.272  ifdef CONFIG_FMOD
  15.273  AUDIODRV += fmodaudio.o
  15.274 -audio.o fmodaudio.o: DEFINES := -I$(CONFIG_FMOD_INC) $(DEFINES)
  15.275 +audio.o fmodaudio.o: CPPFLAGS := -I$(CONFIG_FMOD_INC) $(CPPFLAGS)
  15.276  LIBS += $(CONFIG_FMOD_LIB)
  15.277  endif
  15.278  ifdef CONFIG_ADLIB
  15.279 @@ -365,23 +396,25 @@ else
  15.280  VL_OBJS+= fdc.o serial.o pc.o
  15.281  endif
  15.282  VL_OBJS+= cirrus_vga.o mixeng.o parallel.o acpi.o
  15.283 -VL_OBJS+= usb-uhci.o
  15.284 +VL_OBJS+= usb-uhci.o smbus_eeprom.o
  15.285  VL_OBJS+= piix4acpi.o
  15.286  VL_OBJS+= xenstore.o
  15.287  VL_OBJS+= xen_platform.o
  15.288  VL_OBJS+= tpm_tis.o
  15.289 -DEFINES += -DHAS_AUDIO
  15.290 +CPPFLAGS += -DHAS_AUDIO
  15.291  endif
  15.292  ifeq ($(TARGET_BASE_ARCH), ppc)
  15.293  VL_OBJS+= ppc.o ide.o pckbd.o ps2.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
  15.294  VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
  15.295  VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o heathrow_pic.o mixeng.o
  15.296  VL_OBJS+= grackle_pci.o prep_pci.o unin_pci.o
  15.297 -DEFINES += -DHAS_AUDIO
  15.298 +CPPFLAGS += -DHAS_AUDIO
  15.299  endif
  15.300  ifeq ($(TARGET_ARCH), mips)
  15.301 -VL_OBJS+= mips_r4k.o dma.o vga.o serial.o i8254.o i8259.o
  15.302 -#VL_OBJS+= #ide.o pckbd.o fdc.o m48t59.o
  15.303 +VL_OBJS+= mips_r4k.o mips_malta.o mips_timer.o mips_int.o dma.o vga.o serial.o i8254.o i8259.o
  15.304 +VL_OBJS+= ide.o gt64xxx.o pckbd.o ps2.o fdc.o mc146818rtc.o usb-uhci.o acpi.o
  15.305 +VL_OBJS+= piix_pci.o parallel.o mixeng.o cirrus_vga.o $(SOUND_HW) $(AUDIODRV)
  15.306 +DEFINES += -DHAS_AUDIO
  15.307  endif
  15.308  ifeq ($(TARGET_BASE_ARCH), sparc)
  15.309  ifeq ($(TARGET_ARCH), sparc64)
  15.310 @@ -389,14 +422,17 @@ VL_OBJS+= sun4u.o ide.o pckbd.o ps2.o vg
  15.311  VL_OBJS+= fdc.o mc146818rtc.o serial.o m48t59.o
  15.312  VL_OBJS+= cirrus_vga.o parallel.o
  15.313  else
  15.314 -VL_OBJS+= sun4m.o tcx.o lance.o iommu.o m48t59.o slavio_intctl.o
  15.315 -VL_OBJS+= slavio_timer.o slavio_serial.o slavio_misc.o fdc.o esp.o
  15.316 +VL_OBJS+= sun4m.o tcx.o pcnet.o iommu.o m48t59.o slavio_intctl.o
  15.317 +VL_OBJS+= slavio_timer.o slavio_serial.o slavio_misc.o fdc.o esp.o sparc32_dma.o
  15.318 +VL_OBJS+= cs4231.o
  15.319  endif
  15.320  endif
  15.321  ifeq ($(TARGET_BASE_ARCH), arm)
  15.322  VL_OBJS+= integratorcp.o versatilepb.o ps2.o smc91c111.o arm_pic.o arm_timer.o
  15.323  VL_OBJS+= arm_boot.o pl011.o pl050.o pl080.o pl110.o pl190.o
  15.324  VL_OBJS+= versatile_pci.o
  15.325 +VL_OBJS+= arm_gic.o realview.o arm_sysctl.o
  15.326 +VL_OBJS+= arm-semi.o
  15.327  endif
  15.328  ifeq ($(TARGET_BASE_ARCH), sh4)
  15.329  VL_OBJS+= shix.o sh7750.o sh7750_regnames.o tc58128.o
  15.330 @@ -405,7 +441,7 @@ ifdef CONFIG_GDBSTUB
  15.331  VL_OBJS+=gdbstub.o 
  15.332  endif
  15.333  ifdef CONFIG_SDL
  15.334 -VL_OBJS+=sdl.o
  15.335 +VL_OBJS+=sdl.o x_keymap.o
  15.336  endif
  15.337  VL_OBJS+=vnc.o
  15.338  VL_OBJS+=d3des.o
  15.339 @@ -417,7 +453,7 @@ COCOA_LIBS+=-framework CoreAudio
  15.340  endif
  15.341  endif
  15.342  ifdef CONFIG_SLIRP
  15.343 -DEFINES+=-I$(SRC_PATH)/slirp
  15.344 +CPPFLAGS+=-I$(SRC_PATH)/slirp
  15.345  SLIRP_OBJS=cksum.o if.o ip_icmp.o ip_input.o ip_output.o \
  15.346  slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o \
  15.347  tcp_subr.o tcp_timer.o udp.o bootp.o debug.o tftp.o
  15.348 @@ -440,7 +476,7 @@ endif
  15.349  endif
  15.350  endif
  15.351  ifdef TARGET_GPROF
  15.352 -vl.o: CFLAGS+=-p
  15.353 +vl.o: BASE_CFLAGS+=-p
  15.354  VL_LDFLAGS+=-p
  15.355  endif
  15.356  
  15.357 @@ -461,25 +497,25 @@ endif
  15.358  	$(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(COCOA_LIBS) $(VL_LIBS)
  15.359  
  15.360  cocoa.o: cocoa.m
  15.361 -	$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
  15.362 +	$(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
  15.363  
  15.364  sdl.o: sdl.c keymaps.c sdl_keysym.h
  15.365 -	$(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $<
  15.366 +	$(CC) $(CFLAGS) $(CPPFLAGS) $(SDL_CFLAGS) $(BASE_CFLAGS) -c -o $@ $<
  15.367  
  15.368  vnc.o: vnc.c keymaps.c sdl_keysym.h vnchextile.h
  15.369 -	$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
  15.370 +	$(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
  15.371  
  15.372  d3des.o: d3des.c d3des.h
  15.373  	$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
  15.374  
  15.375  sdlaudio.o: sdlaudio.c
  15.376 -	$(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $<
  15.377 +	$(CC) $(CFLAGS) $(CPPFLAGS) $(SDL_CFLAGS) $(BASE_CFLAGS) -c -o $@ $<
  15.378  
  15.379  depend: $(SRCS)
  15.380 -	$(CC) -MM $(CFLAGS) $(DEFINES) $^ 1>.depend
  15.381 +	$(CC) -MM $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) $^ 1>.depend
  15.382  
  15.383  vldepend: $(VL_OBJS:.o=.c)
  15.384 -	$(CC) -MM $(CFLAGS) $(DEFINES) $^ 1>.depend
  15.385 +	$(CC) -MM $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) $^ 1>.depend
  15.386  
  15.387  # libqemu 
  15.388  
  15.389 @@ -503,10 +539,26 @@ gen-op.h: op.o $(DYNGEN)
  15.390  	$(DYNGEN) -g -o $@ $<
  15.391  
  15.392  op.o: op.c
  15.393 -	$(CC) $(OP_CFLAGS) $(DEFINES) -c -o $@ $<
  15.394 +	$(CC) $(OP_CFLAGS) $(CPPFLAGS) -c -o $@ $<
  15.395  
  15.396 +# HELPER_CFLAGS is used for all the code compiled with static register
  15.397 +# variables
  15.398 +ifeq ($(TARGET_BASE_ARCH), i386)
  15.399 +# XXX: rename helper.c to op_helper.c
  15.400  helper.o: helper.c
  15.401 -	$(CC) $(HELPER_CFLAGS) $(DEFINES) -c -o $@ $<
  15.402 +	$(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
  15.403 +else
  15.404 +op_helper.o: op_helper.c
  15.405 +	$(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
  15.406 +endif
  15.407 +
  15.408 +cpu-exec.o: cpu-exec.c
  15.409 +	$(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
  15.410 +
  15.411 +# Note: this is a workaround. The real fix is to avoid compiling
  15.412 +# cpu_signal_handler() in cpu-exec.c.
  15.413 +signal.o: signal.c
  15.414 +	$(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
  15.415  
  15.416  ifeq ($(TARGET_BASE_ARCH), i386)
  15.417  op.o: op.c opreg_template.h ops_template.h ops_template_mem.h ops_mem.h ops_sse.h
  15.418 @@ -529,19 +581,12 @@ translate.o: translate.c translate_init.
  15.419  endif
  15.420  
  15.421  ifeq ($(TARGET_ARCH), mips)
  15.422 -op.o: op.c op_template.c op_mem.c
  15.423 +op.o: op.c op_template.c fop_template.c op_mem.c
  15.424  op_helper.o: op_helper_mem.c
  15.425  endif
  15.426  
  15.427  loader.o: loader.c elf_ops.h
  15.428  
  15.429 -acpi.o: acpi.c acpi-dsdt.hex
  15.430 -
  15.431 -ifdef BUILD_ACPI_TABLES
  15.432 -$(SRC_PATH)/hw/acpi-dsdt.hex: acpi-dsdt.dsl
  15.433 -	iasl -tc -p $@ $<
  15.434 -endif
  15.435 -
  15.436  ifeq ($(TARGET_ARCH), sh4)
  15.437  op.o: op.c op_mem.c cpu.h
  15.438  op_helper.o: op_helper.c exec.h cpu.h
  15.439 @@ -555,10 +600,10 @@ endif
  15.440  $(OBJS) $(LIBOBJS) $(VL_OBJS): config.h ../config-host.h
  15.441  
  15.442  %.o: %.c
  15.443 -	$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
  15.444 +	$(CC) $(CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
  15.445  
  15.446  %.o: %.S
  15.447 -	$(CC) $(DEFINES) -c -o $@ $<
  15.448 +	$(CC) $(CPPFLAGS) -c -o $@ $<
  15.449  
  15.450  clean:
  15.451  	rm -f *.o  *.a *~ $(PROGS) gen-op.h opc.h op.h nwfpe/*.o slirp/*.o fpu/*.o
    16.1 --- a/tools/ioemu/README.distrib	Wed May 16 10:42:07 2007 -0600
    16.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.3 @@ -1,16 +0,0 @@
    16.4 -Information about the various packages used to build the current qemu
    16.5 -x86 binary distribution:
    16.6 -
    16.7 -* gcc 2.95.2 was used for the build. A glibc 2.1.3 Debian distribution
    16.8 -  was used to get most of the binary packages.
    16.9 -
   16.10 -* wine-20020411 tarball
   16.11 -
   16.12 -  ./configure --prefix=/usr/local/wine-i386
   16.13 -  
   16.14 -  All exe and libs were stripped. Some compile time tools and the
   16.15 -  includes were deleted.
   16.16 -
   16.17 -* ldconfig was launched to build the library links:
   16.18 -
   16.19 -  qemu-i386 /usr/gnemul/qemu-i386/bin/ldconfig-i386 -C /usr/gnemul/qemu-i386/etc/ld.so.cache
    17.1 --- a/tools/ioemu/VERSION	Wed May 16 10:42:07 2007 -0600
    17.2 +++ b/tools/ioemu/VERSION	Wed May 16 10:59:01 2007 -0600
    17.3 @@ -1,1 +1,1 @@
    17.4 -0.8.2
    17.5 \ No newline at end of file
    17.6 +0.9.0
    17.7 \ No newline at end of file
    18.1 --- a/tools/ioemu/audio/.CVS/Entries	Wed May 16 10:42:07 2007 -0600
    18.2 +++ b/tools/ioemu/audio/.CVS/Entries	Wed May 16 10:59:01 2007 -0600
    18.3 @@ -1,20 +1,20 @@
    18.4 -/alsaaudio.c/1.7/Sun Aug  6 01:03:49 2006//Trelease_0_8_2
    18.5 -/audio.c/1.14/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
    18.6 -/audio.h/1.8/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
    18.7 -/audio_int.h/1.10/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
    18.8 -/audio_template.h/1.8/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
    18.9 -/coreaudio.c/1.7/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
   18.10 -/dsound_template.h/1.4/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
   18.11 -/dsoundaudio.c/1.3/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
   18.12 -/fmodaudio.c/1.7/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
   18.13 -/mixeng.c/1.4/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
   18.14 -/mixeng.h/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
   18.15 -/mixeng_template.h/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
   18.16 -/noaudio.c/1.7/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
   18.17 -/ossaudio.c/1.11/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
   18.18 -/rate_template.h/1.3/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
   18.19 -/sdlaudio.c/1.8/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
   18.20 -/sys-queue.h/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
   18.21 -/wavaudio.c/1.8/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
   18.22 -/wavcapture.c/1.5/Sat Jul 22 17:06:44 2006//Trelease_0_8_2
   18.23 +/alsaaudio.c/1.7/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
   18.24 +/audio.c/1.15/Thu May  3 17:17:59 2007//Trelease_0_9_0
   18.25 +/audio.h/1.8/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
   18.26 +/audio_int.h/1.10/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
   18.27 +/audio_template.h/1.8/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
   18.28 +/coreaudio.c/1.7/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
   18.29 +/dsound_template.h/1.4/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
   18.30 +/dsoundaudio.c/1.3/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
   18.31 +/fmodaudio.c/1.7/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
   18.32 +/mixeng.c/1.4/Wed Oct 18 10:11:20 2006//Trelease_0_9_0
   18.33 +/mixeng.h/1.2/Wed Oct 18 10:11:20 2006//Trelease_0_9_0
   18.34 +/mixeng_template.h/1.2/Wed Oct 18 10:11:20 2006//Trelease_0_9_0
   18.35 +/noaudio.c/1.7/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
   18.36 +/ossaudio.c/1.11/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
   18.37 +/rate_template.h/1.3/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
   18.38 +/sdlaudio.c/1.8/Fri Jan  5 14:34:35 2007//Trelease_0_9_0
   18.39 +/sys-queue.h/1.1/Wed Oct 18 10:11:20 2006//Trelease_0_9_0
   18.40 +/wavaudio.c/1.9/Thu May  3 17:17:59 2007//Trelease_0_9_0
   18.41 +/wavcapture.c/1.7/Thu May  3 17:17:59 2007//Trelease_0_9_0
   18.42  D
    19.1 --- a/tools/ioemu/audio/.CVS/Tag	Wed May 16 10:42:07 2007 -0600
    19.2 +++ b/tools/ioemu/audio/.CVS/Tag	Wed May 16 10:59:01 2007 -0600
    19.3 @@ -1,1 +1,1 @@
    19.4 -Nrelease_0_8_2
    19.5 +Nrelease_0_9_0
    20.1 --- a/tools/ioemu/audio/wavaudio.c	Wed May 16 10:42:07 2007 -0600
    20.2 +++ b/tools/ioemu/audio/wavaudio.c	Wed May 16 10:59:01 2007 -0600
    20.3 @@ -151,7 +151,7 @@ static int wav_init_out (HWVoiceOut *hw,
    20.4      le_store (hdr + 28, hw->info.freq << (bits16 + stereo), 4);
    20.5      le_store (hdr + 32, 1 << (bits16 + stereo), 2);
    20.6  
    20.7 -    wav->f = fopen (conf.wav_path, "wb");
    20.8 +    wav->f = qemu_fopen (conf.wav_path, "wb");
    20.9      if (!wav->f) {
   20.10          dolog ("Failed to open wave file `%s'\nReason: %s\n",
   20.11                 conf.wav_path, strerror (errno));
   20.12 @@ -185,7 +185,7 @@ static void wav_fini_out (HWVoiceOut *hw
   20.13      qemu_fseek (wav->f, 32, SEEK_CUR);
   20.14      qemu_put_buffer (wav->f, dlen, 4);
   20.15  
   20.16 -    fclose (wav->f);
   20.17 +    qemu_fclose (wav->f);
   20.18      wav->f = NULL;
   20.19  
   20.20      qemu_free (wav->pcm_buf);
    21.1 --- a/tools/ioemu/audio/wavcapture.c	Wed May 16 10:42:07 2007 -0600
    21.2 +++ b/tools/ioemu/audio/wavcapture.c	Wed May 16 10:59:01 2007 -0600
    21.3 @@ -34,22 +34,19 @@ static void wav_destroy (void *opaque)
    21.4      uint32_t datalen = wav->bytes;
    21.5      uint32_t rifflen = datalen + 36;
    21.6  
    21.7 -    if (!wav->f) {
    21.8 -        return;
    21.9 +    if (wav->f) {
   21.10 +        le_store (rlen, rifflen, 4);
   21.11 +        le_store (dlen, datalen, 4);
   21.12 +        
   21.13 +        qemu_fseek (wav->f, 4, SEEK_SET);
   21.14 +        qemu_put_buffer (wav->f, rlen, 4);
   21.15 +        
   21.16 +        qemu_fseek (wav->f, 32, SEEK_CUR);
   21.17 +        qemu_put_buffer (wav->f, dlen, 4);
   21.18 +        qemu_fclose (wav->f);
   21.19      }
   21.20 -
   21.21 -    le_store (rlen, rifflen, 4);
   21.22 -    le_store (dlen, datalen, 4);
   21.23 -
   21.24 -    qemu_fseek (wav->f, 4, SEEK_SET);
   21.25 -    qemu_put_buffer (wav->f, rlen, 4);
   21.26 -
   21.27 -    qemu_fseek (wav->f, 32, SEEK_CUR);
   21.28 -    qemu_put_buffer (wav->f, dlen, 4);
   21.29 -    fclose (wav->f);
   21.30 -    if (wav->path) {
   21.31 -        qemu_free (wav->path);
   21.32 -    }
   21.33 +    
   21.34 +    qemu_free (wav->path);
   21.35  }
   21.36  
   21.37  static void wav_capture (void *opaque, void *buf, int size)
   21.38 @@ -135,7 +132,7 @@ int wav_start_capture (CaptureState *s, 
   21.39      le_store (hdr + 28, freq << shift, 4);
   21.40      le_store (hdr + 32, 1 << shift, 2);
   21.41  
   21.42 -    wav->f = fopen (path, "wb");
   21.43 +    wav->f = qemu_fopen (path, "wb");
   21.44      if (!wav->f) {
   21.45          term_printf ("Failed to open wave file `%s'\nReason: %s\n",
   21.46                       path, strerror (errno));
   21.47 @@ -153,6 +150,8 @@ int wav_start_capture (CaptureState *s, 
   21.48      cap = AUD_add_capture (NULL, &as, &ops, wav);
   21.49      if (!cap) {
   21.50          term_printf ("Failed to add audio capture\n");
   21.51 +        qemu_free (wav->path);
   21.52 +        qemu_fclose (wav->f);
   21.53          qemu_free (wav);
   21.54          return -1;
   21.55      }
    22.1 --- a/tools/ioemu/block-bochs.c	Wed May 16 10:42:07 2007 -0600
    22.2 +++ b/tools/ioemu/block-bochs.c	Wed May 16 10:59:01 2007 -0600
    22.3 @@ -28,7 +28,8 @@
    22.4  /**************************************************************/
    22.5  
    22.6  #define HEADER_MAGIC "Bochs Virtual HD Image"
    22.7 -#define HEADER_VERSION 0x00010000
    22.8 +#define HEADER_VERSION 0x00020000
    22.9 +#define HEADER_V1 0x00010000
   22.10  #define HEADER_SIZE 512
   22.11  
   22.12  #define REDOLOG_TYPE "Redolog"
   22.13 @@ -37,6 +38,26 @@
   22.14  // not allocated: 0xffffffff
   22.15  
   22.16  // always little-endian
   22.17 +struct bochs_header_v1 {
   22.18 +    char magic[32]; // "Bochs Virtual HD Image"
   22.19 +    char type[16]; // "Redolog"
   22.20 +    char subtype[16]; // "Undoable" / "Volatile" / "Growing"
   22.21 +    uint32_t version;
   22.22 +    uint32_t header; // size of header
   22.23 +    
   22.24 +    union {
   22.25 +	struct {
   22.26 +	    uint32_t catalog; // num of entries
   22.27 +	    uint32_t bitmap; // bitmap size
   22.28 +	    uint32_t extent; // extent size
   22.29 +	    uint64_t disk; // disk size
   22.30 +	    char padding[HEADER_SIZE - 64 - 8 - 20];
   22.31 +	} redolog;
   22.32 +	char padding[HEADER_SIZE - 64 - 8];
   22.33 +    } extra;
   22.34 +};
   22.35 +
   22.36 +// always little-endian
   22.37  struct bochs_header {
   22.38      char magic[32]; // "Bochs Virtual HD Image"
   22.39      char type[16]; // "Redolog"
   22.40 @@ -49,8 +70,9 @@ struct bochs_header {
   22.41  	    uint32_t catalog; // num of entries
   22.42  	    uint32_t bitmap; // bitmap size
   22.43  	    uint32_t extent; // extent size
   22.44 +	    uint32_t reserved; // for ???
   22.45  	    uint64_t disk; // disk size
   22.46 -	    char padding[HEADER_SIZE - 64 - 8 - 20];
   22.47 +	    char padding[HEADER_SIZE - 64 - 8 - 24];
   22.48  	} redolog;
   22.49  	char padding[HEADER_SIZE - 64 - 8];
   22.50      } extra;
   22.51 @@ -79,21 +101,23 @@ static int bochs_probe(const uint8_t *bu
   22.52      if (!strcmp(bochs->magic, HEADER_MAGIC) &&
   22.53  	!strcmp(bochs->type, REDOLOG_TYPE) &&
   22.54  	!strcmp(bochs->subtype, GROWING_TYPE) &&
   22.55 -	(le32_to_cpu(bochs->version) == HEADER_VERSION))
   22.56 +	((le32_to_cpu(bochs->version) == HEADER_VERSION) ||
   22.57 +	(le32_to_cpu(bochs->version) == HEADER_V1)))
   22.58  	return 100;
   22.59  
   22.60      return 0;
   22.61  }
   22.62  
   22.63 -static int bochs_open(BlockDriverState *bs, const char *filename)
   22.64 +static int bochs_open(BlockDriverState *bs, const char *filename, int flags)
   22.65  {
   22.66      BDRVBochsState *s = bs->opaque;
   22.67      int fd, i;
   22.68      struct bochs_header bochs;
   22.69 +    struct bochs_header_v1 header_v1;
   22.70  
   22.71 -    fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
   22.72 +    fd = open(filename, O_RDWR | O_BINARY);
   22.73      if (fd < 0) {
   22.74 -        fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
   22.75 +        fd = open(filename, O_RDONLY | O_BINARY);
   22.76          if (fd < 0)
   22.77              return -1;
   22.78      }
   22.79 @@ -109,11 +133,17 @@ static int bochs_open(BlockDriverState *
   22.80      if (strcmp(bochs.magic, HEADER_MAGIC) ||
   22.81          strcmp(bochs.type, REDOLOG_TYPE) ||
   22.82          strcmp(bochs.subtype, GROWING_TYPE) ||
   22.83 -	(le32_to_cpu(bochs.version) != HEADER_VERSION)) {
   22.84 +	((le32_to_cpu(bochs.version) != HEADER_VERSION) &&
   22.85 +	(le32_to_cpu(bochs.version) != HEADER_V1))) {
   22.86          goto fail;
   22.87      }
   22.88  
   22.89 -    bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512;
   22.90 +    if (le32_to_cpu(bochs.version) == HEADER_V1) {
   22.91 +      memcpy(&header_v1, &bochs, sizeof(bochs));
   22.92 +      bs->total_sectors = le64_to_cpu(header_v1.extra.redolog.disk) / 512;
   22.93 +    } else {
   22.94 +      bs->total_sectors = le64_to_cpu(bochs.extra.redolog.disk) / 512;
   22.95 +    }
   22.96  
   22.97      lseek(s->fd, le32_to_cpu(bochs.header), SEEK_SET);
   22.98  
    23.1 --- a/tools/ioemu/block-cloop.c	Wed May 16 10:42:07 2007 -0600
    23.2 +++ b/tools/ioemu/block-cloop.c	Wed May 16 10:59:01 2007 -0600
    23.3 @@ -50,14 +50,14 @@ static int cloop_probe(const uint8_t *bu
    23.4      return 0;
    23.5  }
    23.6  
    23.7 -static int cloop_open(BlockDriverState *bs, const char *filename)
    23.8 +static int cloop_open(BlockDriverState *bs, const char *filename, int flags)
    23.9  {
   23.10      BDRVCloopState *s = bs->opaque;
   23.11      uint32_t offsets_size,max_compressed_block_size=1,i;
   23.12  
   23.13 -    s->fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
   23.14 +    s->fd = open(filename, O_RDONLY | O_BINARY);
   23.15      if (s->fd < 0)
   23.16 -        return -1;
   23.17 +        return -errno;
   23.18      bs->read_only = 1;
   23.19  
   23.20      /* read header */
    24.1 --- a/tools/ioemu/block-cow.c	Wed May 16 10:42:07 2007 -0600
    24.2 +++ b/tools/ioemu/block-cow.c	Wed May 16 10:59:01 2007 -0600
    24.3 @@ -62,7 +62,7 @@ static int cow_probe(const uint8_t *buf,
    24.4          return 0;
    24.5  }
    24.6  
    24.7 -static int cow_open(BlockDriverState *bs, const char *filename)
    24.8 +static int cow_open(BlockDriverState *bs, const char *filename, int flags)
    24.9  {
   24.10      BDRVCowState *s = bs->opaque;
   24.11      int fd;
   24.12 @@ -93,22 +93,6 @@ static int cow_open(BlockDriverState *bs
   24.13      pstrcpy(bs->backing_file, sizeof(bs->backing_file), 
   24.14              cow_header.backing_file);
   24.15      
   24.16 -#if 0
   24.17 -    if (cow_header.backing_file[0] != '\0') {
   24.18 -        if (stat(cow_header.backing_file, &st) != 0) {
   24.19 -            fprintf(stderr, "%s: could not find original disk image '%s'\n", filename, cow_header.backing_file);
   24.20 -            goto fail;
   24.21 -        }
   24.22 -        if (st.st_mtime != be32_to_cpu(cow_header.mtime)) {
   24.23 -            fprintf(stderr, "%s: original raw disk image '%s' does not match saved timestamp\n", filename, cow_header.backing_file);
   24.24 -            goto fail;
   24.25 -            }
   24.26 -        fd = open(cow_header.backing_file, O_RDONLY | O_LARGEFILE);
   24.27 -        if (fd < 0)
   24.28 -            goto fail;
   24.29 -        bs->fd = fd;
   24.30 -    }
   24.31 -#endif
   24.32      /* mmap the bitmap */
   24.33      s->cow_bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
   24.34      s->cow_bitmap_addr = mmap(get_mmap_addr(s->cow_bitmap_size), 
   24.35 @@ -179,8 +163,15 @@ static int cow_read(BlockDriverState *bs
   24.36              if (ret != n * 512) 
   24.37                  return -1;
   24.38          } else {
   24.39 +            if (bs->backing_hd) {
   24.40 +                /* read from the base image */
   24.41 +                ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
   24.42 +                if (ret < 0)
   24.43 +                    return -1;
   24.44 +            } else {
   24.45              memset(buf, 0, n * 512);
   24.46          }
   24.47 +        }
   24.48          nb_sectors -= n;
   24.49          sector_num += n;
   24.50          buf += n * 512;
   24.51 @@ -220,7 +211,7 @@ static int cow_create(const char *filena
   24.52      if (flags)
   24.53          return -ENOTSUP;
   24.54  
   24.55 -    cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 
   24.56 +    cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 
   24.57                0644);
   24.58      if (cow_fd < 0)
   24.59          return -1;
   24.60 @@ -228,18 +219,23 @@ static int cow_create(const char *filena
   24.61      cow_header.magic = cpu_to_be32(COW_MAGIC);
   24.62      cow_header.version = cpu_to_be32(COW_VERSION);
   24.63      if (image_filename) {
   24.64 +        /* Note: if no file, we put a dummy mtime */
   24.65 +        cow_header.mtime = cpu_to_be32(0);
   24.66 +
   24.67          fd = open(image_filename, O_RDONLY | O_BINARY);
   24.68          if (fd < 0) {
   24.69              close(cow_fd);
   24.70 -            return -1;
   24.71 +            goto mtime_fail;
   24.72          }
   24.73          if (fstat(fd, &st) != 0) {
   24.74              close(fd);
   24.75 -            return -1;
   24.76 +            goto mtime_fail;
   24.77          }
   24.78          close(fd);
   24.79          cow_header.mtime = cpu_to_be32(st.st_mtime);
   24.80 -        realpath(image_filename, cow_header.backing_file);
   24.81 +    mtime_fail:
   24.82 +        pstrcpy(cow_header.backing_file, sizeof(cow_header.backing_file),
   24.83 +                image_filename);
   24.84      }
   24.85      cow_header.sectorsize = cpu_to_be32(512);
   24.86      cow_header.size = cpu_to_be64(image_sectors * 512);
    25.1 --- a/tools/ioemu/block-dmg.c	Wed May 16 10:42:07 2007 -0600
    25.2 +++ b/tools/ioemu/block-dmg.c	Wed May 16 10:59:01 2007 -0600
    25.3 @@ -73,16 +73,16 @@ static off_t read_uint32(int fd)
    25.4  	return be32_to_cpu(buffer);
    25.5  }
    25.6  
    25.7 -static int dmg_open(BlockDriverState *bs, const char *filename)
    25.8 +static int dmg_open(BlockDriverState *bs, const char *filename, int flags)
    25.9  {
   25.10      BDRVDMGState *s = bs->opaque;
   25.11      off_t info_begin,info_end,last_in_offset,last_out_offset;
   25.12      uint32_t count;
   25.13      uint32_t max_compressed_size=1,max_sectors_per_chunk=1,i;
   25.14  
   25.15 -    s->fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
   25.16 +    s->fd = open(filename, O_RDONLY | O_BINARY);
   25.17      if (s->fd < 0)
   25.18 -        return -1;
   25.19 +        return -errno;
   25.20      bs->read_only = 1;
   25.21      s->n_chunks = 0;
   25.22      s->offsets = s->lengths = s->sectors = s->sectorcounts = 0;
   25.23 @@ -93,7 +93,7 @@ dmg_close:
   25.24  	close(s->fd);
   25.25  	/* open raw instead */
   25.26  	bs->drv=&bdrv_raw;
   25.27 -	return bs->drv->bdrv_open(bs,filename);
   25.28 +	return bs->drv->bdrv_open(bs, filename, flags);
   25.29      }
   25.30      info_begin=read_off(s->fd);
   25.31      if(info_begin==0)
    26.1 --- a/tools/ioemu/block-qcow.c	Wed May 16 10:42:07 2007 -0600
    26.2 +++ b/tools/ioemu/block-qcow.c	Wed May 16 10:59:01 2007 -0600
    26.3 @@ -1,7 +1,7 @@
    26.4  /*
    26.5   * Block driver for the QCOW format
    26.6   * 
    26.7 - * Copyright (c) 2004 Fabrice Bellard
    26.8 + * Copyright (c) 2004-2006 Fabrice Bellard
    26.9   * 
   26.10   * Permission is hereby granted, free of charge, to any person obtaining a copy
   26.11   * of this software and associated documentation files (the "Software"), to deal
   26.12 @@ -53,7 +53,7 @@ typedef struct QCowHeader {
   26.13  #define L2_CACHE_SIZE 16
   26.14  
   26.15  typedef struct BDRVQcowState {
   26.16 -    int fd;
   26.17 +    BlockDriverState *hd;
   26.18      int cluster_bits;
   26.19      int cluster_size;
   26.20      int cluster_sectors;
   26.21 @@ -89,20 +89,16 @@ static int qcow_probe(const uint8_t *buf
   26.22          return 0;
   26.23  }
   26.24  
   26.25 -static int qcow_open(BlockDriverState *bs, const char *filename)
   26.26 +static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
   26.27  {
   26.28      BDRVQcowState *s = bs->opaque;
   26.29 -    int fd, len, i, shift;
   26.30 +    int len, i, shift, ret;
   26.31      QCowHeader header;
   26.32 -    
   26.33 -    fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
   26.34 -    if (fd < 0) {
   26.35 -        fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
   26.36 -        if (fd < 0)
   26.37 -            return -1;
   26.38 -    }
   26.39 -    s->fd = fd;
   26.40 -    if (read(fd, &header, sizeof(header)) != sizeof(header))
   26.41 +
   26.42 +    ret = bdrv_file_open(&s->hd, filename, flags);
   26.43 +    if (ret < 0)
   26.44 +        return ret;
   26.45 +    if (bdrv_pread(s->hd, 0, &header, sizeof(header)) != sizeof(header))
   26.46          goto fail;
   26.47      be32_to_cpus(&header.magic);
   26.48      be32_to_cpus(&header.version);
   26.49 @@ -138,8 +134,7 @@ static int qcow_open(BlockDriverState *b
   26.50      s->l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t));
   26.51      if (!s->l1_table)
   26.52          goto fail;
   26.53 -    lseek(fd, s->l1_table_offset, SEEK_SET);
   26.54 -    if (read(fd, s->l1_table, s->l1_size * sizeof(uint64_t)) != 
   26.55 +    if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, s->l1_size * sizeof(uint64_t)) != 
   26.56          s->l1_size * sizeof(uint64_t))
   26.57          goto fail;
   26.58      for(i = 0;i < s->l1_size; i++) {
   26.59 @@ -162,8 +157,7 @@ static int qcow_open(BlockDriverState *b
   26.60          len = header.backing_file_size;
   26.61          if (len > 1023)
   26.62              len = 1023;
   26.63 -        lseek(fd, header.backing_file_offset, SEEK_SET);
   26.64 -        if (read(fd, bs->backing_file, len) != len)
   26.65 +        if (bdrv_pread(s->hd, header.backing_file_offset, bs->backing_file, len) != len)
   26.66              goto fail;
   26.67          bs->backing_file[len] = '\0';
   26.68      }
   26.69 @@ -174,7 +168,7 @@ static int qcow_open(BlockDriverState *b
   26.70      qemu_free(s->l2_cache);
   26.71      qemu_free(s->cluster_cache);
   26.72      qemu_free(s->cluster_data);
   26.73 -    close(fd);
   26.74 +    bdrv_delete(s->hd);
   26.75      return -1;
   26.76  }
   26.77  
   26.78 @@ -276,14 +270,14 @@ static uint64_t get_cluster_offset(Block
   26.79          if (!allocate)
   26.80              return 0;
   26.81          /* allocate a new l2 entry */
   26.82 -        l2_offset = lseek(s->fd, 0, SEEK_END);
   26.83 +        l2_offset = bdrv_getlength(s->hd);
   26.84          /* round to cluster size */
   26.85          l2_offset = (l2_offset + s->cluster_size - 1) & ~(s->cluster_size - 1);
   26.86          /* update the L1 entry */
   26.87          s->l1_table[l1_index] = l2_offset;
   26.88          tmp = cpu_to_be64(l2_offset);
   26.89 -        lseek(s->fd, s->l1_table_offset + l1_index * sizeof(tmp), SEEK_SET);
   26.90 -        if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))
   26.91 +        if (bdrv_pwrite(s->hd, s->l1_table_offset + l1_index * sizeof(tmp), 
   26.92 +                        &tmp, sizeof(tmp)) != sizeof(tmp))
   26.93              return 0;
   26.94          new_l2_table = 1;
   26.95      }
   26.96 @@ -309,14 +303,13 @@ static uint64_t get_cluster_offset(Block
   26.97          }
   26.98      }
   26.99      l2_table = s->l2_cache + (min_index << s->l2_bits);
  26.100 -    lseek(s->fd, l2_offset, SEEK_SET);
  26.101      if (new_l2_table) {
  26.102          memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
  26.103 -        if (write(s->fd, l2_table, s->l2_size * sizeof(uint64_t)) !=
  26.104 +        if (bdrv_pwrite(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
  26.105              s->l2_size * sizeof(uint64_t))
  26.106              return 0;
  26.107      } else {
  26.108 -        if (read(s->fd, l2_table, s->l2_size * sizeof(uint64_t)) != 
  26.109 +        if (bdrv_pread(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) != 
  26.110              s->l2_size * sizeof(uint64_t))
  26.111              return 0;
  26.112      }
  26.113 @@ -337,36 +330,35 @@ static uint64_t get_cluster_offset(Block
  26.114                 overwritten */
  26.115              if (decompress_cluster(s, cluster_offset) < 0)
  26.116                  return 0;
  26.117 -            cluster_offset = lseek(s->fd, 0, SEEK_END);
  26.118 +            cluster_offset = bdrv_getlength(s->hd);
  26.119              cluster_offset = (cluster_offset + s->cluster_size - 1) & 
  26.120                  ~(s->cluster_size - 1);
  26.121              /* write the cluster content */
  26.122 -            lseek(s->fd, cluster_offset, SEEK_SET);
  26.123 -            if (write(s->fd, s->cluster_cache, s->cluster_size) != 
  26.124 +            if (bdrv_pwrite(s->hd, cluster_offset, s->cluster_cache, s->cluster_size) != 
  26.125                  s->cluster_size)
  26.126                  return -1;
  26.127          } else {
  26.128 -            cluster_offset = lseek(s->fd, 0, SEEK_END);
  26.129 +            cluster_offset = bdrv_getlength(s->hd);
  26.130              if (allocate == 1) {
  26.131                  /* round to cluster size */
  26.132                  cluster_offset = (cluster_offset + s->cluster_size - 1) & 
  26.133                      ~(s->cluster_size - 1);
  26.134 -                ftruncate(s->fd, cluster_offset + s->cluster_size);
  26.135 +                bdrv_truncate(s->hd, cluster_offset + s->cluster_size);
  26.136                  /* if encrypted, we must initialize the cluster
  26.137                     content which won't be written */
  26.138                  if (s->crypt_method && 
  26.139                      (n_end - n_start) < s->cluster_sectors) {
  26.140                      uint64_t start_sect;
  26.141                      start_sect = (offset & ~(s->cluster_size - 1)) >> 9;
  26.142 -                    memset(s->cluster_data + 512, 0xaa, 512);
  26.143 +                    memset(s->cluster_data + 512, 0x00, 512);
  26.144                      for(i = 0; i < s->cluster_sectors; i++) {
  26.145                          if (i < n_start || i >= n_end) {
  26.146                              encrypt_sectors(s, start_sect + i, 
  26.147                                              s->cluster_data, 
  26.148                                              s->cluster_data + 512, 1, 1,
  26.149                                              &s->aes_encrypt_key);
  26.150 -                            lseek(s->fd, cluster_offset + i * 512, SEEK_SET);
  26.151 -                            if (write(s->fd, s->cluster_data, 512) != 512)
  26.152 +                            if (bdrv_pwrite(s->hd, cluster_offset + i * 512, 
  26.153 +                                            s->cluster_data, 512) != 512)
  26.154                                  return -1;
  26.155                          }
  26.156                      }
  26.157 @@ -379,8 +371,8 @@ static uint64_t get_cluster_offset(Block
  26.158          /* update L2 table */
  26.159          tmp = cpu_to_be64(cluster_offset);
  26.160          l2_table[l2_index] = tmp;
  26.161 -        lseek(s->fd, l2_offset + l2_index * sizeof(tmp), SEEK_SET);
  26.162 -        if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))
  26.163 +        if (bdrv_pwrite(s->hd, 
  26.164 +                        l2_offset + l2_index * sizeof(tmp), &tmp, sizeof(tmp)) != sizeof(tmp))
  26.165              return 0;
  26.166      }
  26.167      return cluster_offset;
  26.168 @@ -438,8 +430,7 @@ static int decompress_cluster(BDRVQcowSt
  26.169      if (s->cluster_cache_offset != coffset) {
  26.170          csize = cluster_offset >> (63 - s->cluster_bits);
  26.171          csize &= (s->cluster_size - 1);
  26.172 -        lseek(s->fd, coffset, SEEK_SET);
  26.173 -        ret = read(s->fd, s->cluster_data, csize);
  26.174 +        ret = bdrv_pread(s->hd, coffset, s->cluster_data, csize);
  26.175          if (ret != csize) 
  26.176              return -1;
  26.177          if (decompress_buffer(s->cluster_cache, s->cluster_size,
  26.178 @@ -451,6 +442,8 @@ static int decompress_cluster(BDRVQcowSt
  26.179      return 0;
  26.180  }
  26.181  
  26.182 +#if 0
  26.183 +
  26.184  static int qcow_read(BlockDriverState *bs, int64_t sector_num, 
  26.185                       uint8_t *buf, int nb_sectors)
  26.186  {
  26.187 @@ -465,14 +458,20 @@ static int qcow_read(BlockDriverState *b
  26.188          if (n > nb_sectors)
  26.189              n = nb_sectors;
  26.190          if (!cluster_offset) {
  26.191 -            memset(buf, 0, 512 * n);
  26.192 +            if (bs->backing_hd) {
  26.193 +                /* read from the base image */
  26.194 +                ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
  26.195 +                if (ret < 0)
  26.196 +                    return -1;
  26.197 +            } else {
  26.198 +                memset(buf, 0, 512 * n);
  26.199 +            }
  26.200          } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
  26.201              if (decompress_cluster(s, cluster_offset) < 0)
  26.202                  return -1;
  26.203              memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n);
  26.204          } else {
  26.205 -            lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
  26.206 -            ret = read(s->fd, buf, n * 512);
  26.207 +            ret = bdrv_pread(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);
  26.208              if (ret != n * 512) 
  26.209                  return -1;
  26.210              if (s->crypt_method) {
  26.211 @@ -486,6 +485,7 @@ static int qcow_read(BlockDriverState *b
  26.212      }
  26.213      return 0;
  26.214  }
  26.215 +#endif
  26.216  
  26.217  static int qcow_write(BlockDriverState *bs, int64_t sector_num, 
  26.218                       const uint8_t *buf, int nb_sectors)
  26.219 @@ -504,13 +504,13 @@ static int qcow_write(BlockDriverState *
  26.220                                              index_in_cluster + n);
  26.221          if (!cluster_offset)
  26.222              return -1;
  26.223 -        lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
  26.224          if (s->crypt_method) {
  26.225              encrypt_sectors(s, sector_num, s->cluster_data, buf, n, 1,
  26.226                              &s->aes_encrypt_key);
  26.227 -            ret = write(s->fd, s->cluster_data, n * 512);
  26.228 +            ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512, 
  26.229 +                              s->cluster_data, n * 512);
  26.230          } else {
  26.231 -            ret = write(s->fd, buf, n * 512);
  26.232 +            ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);
  26.233          }
  26.234          if (ret != n * 512) 
  26.235              return -1;
  26.236 @@ -522,6 +522,209 @@ static int qcow_write(BlockDriverState *
  26.237      return 0;
  26.238  }
  26.239  
  26.240 +typedef struct QCowAIOCB {
  26.241 +    BlockDriverAIOCB common;
  26.242 +    int64_t sector_num;
  26.243 +    uint8_t *buf;
  26.244 +    int nb_sectors;
  26.245 +    int n;
  26.246 +    uint64_t cluster_offset;
  26.247 +    uint8_t *cluster_data; 
  26.248 +    BlockDriverAIOCB *hd_aiocb;
  26.249 +} QCowAIOCB;
  26.250 +
  26.251 +static void qcow_aio_read_cb(void *opaque, int ret)
  26.252 +{
  26.253 +    QCowAIOCB *acb = opaque;
  26.254 +    BlockDriverState *bs = acb->common.bs;
  26.255 +    BDRVQcowState *s = bs->opaque;
  26.256 +    int index_in_cluster;
  26.257 +
  26.258 +    acb->hd_aiocb = NULL;
  26.259 +    if (ret < 0) {
  26.260 +    fail:
  26.261 +        acb->common.cb(acb->common.opaque, ret);
  26.262 +        qemu_aio_release(acb);
  26.263 +        return;
  26.264 +    }
  26.265 +
  26.266 + redo:
  26.267 +    /* post process the read buffer */
  26.268 +    if (!acb->cluster_offset) {
  26.269 +        /* nothing to do */
  26.270 +    } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
  26.271 +        /* nothing to do */
  26.272 +    } else {
  26.273 +        if (s->crypt_method) {
  26.274 +            encrypt_sectors(s, acb->sector_num, acb->buf, acb->buf, 
  26.275 +                            acb->n, 0, 
  26.276 +                            &s->aes_decrypt_key);
  26.277 +        }
  26.278 +    }
  26.279 +
  26.280 +    acb->nb_sectors -= acb->n;
  26.281 +    acb->sector_num += acb->n;
  26.282 +    acb->buf += acb->n * 512;
  26.283 +
  26.284 +    if (acb->nb_sectors == 0) {
  26.285 +        /* request completed */
  26.286 +        acb->common.cb(acb->common.opaque, 0);
  26.287 +        qemu_aio_release(acb);
  26.288 +        return;
  26.289 +    }
  26.290 +    
  26.291 +    /* prepare next AIO request */
  26.292 +    acb->cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, 
  26.293 +                                             0, 0, 0, 0);
  26.294 +    index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
  26.295 +    acb->n = s->cluster_sectors - index_in_cluster;
  26.296 +    if (acb->n > acb->nb_sectors)
  26.297 +        acb->n = acb->nb_sectors;
  26.298 +
  26.299 +    if (!acb->cluster_offset) {
  26.300 +        if (bs->backing_hd) {
  26.301 +            /* read from the base image */
  26.302 +            acb->hd_aiocb = bdrv_aio_read(bs->backing_hd,
  26.303 +                acb->sector_num, acb->buf, acb->n, qcow_aio_read_cb, acb);
  26.304 +            if (acb->hd_aiocb == NULL)
  26.305 +                goto fail;
  26.306 +        } else {
  26.307 +            /* Note: in this case, no need to wait */
  26.308 +            memset(acb->buf, 0, 512 * acb->n);
  26.309 +            goto redo;
  26.310 +        }
  26.311 +    } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
  26.312 +        /* add AIO support for compressed blocks ? */
  26.313 +        if (decompress_cluster(s, acb->cluster_offset) < 0)
  26.314 +            goto fail;
  26.315 +        memcpy(acb->buf, 
  26.316 +               s->cluster_cache + index_in_cluster * 512, 512 * acb->n);
  26.317 +        goto redo;
  26.318 +    } else {
  26.319 +        if ((acb->cluster_offset & 511) != 0) {
  26.320 +            ret = -EIO;
  26.321 +            goto fail;
  26.322 +        }
  26.323 +        acb->hd_aiocb = bdrv_aio_read(s->hd,
  26.324 +                            (acb->cluster_offset >> 9) + index_in_cluster, 
  26.325 +                            acb->buf, acb->n, qcow_aio_read_cb, acb);
  26.326 +        if (acb->hd_aiocb == NULL)
  26.327 +            goto fail;
  26.328 +    }
  26.329 +}
  26.330 +
  26.331 +static BlockDriverAIOCB *qcow_aio_read(BlockDriverState *bs,
  26.332 +        int64_t sector_num, uint8_t *buf, int nb_sectors,
  26.333 +        BlockDriverCompletionFunc *cb, void *opaque)
  26.334 +{
  26.335 +    QCowAIOCB *acb;
  26.336 +
  26.337 +    acb = qemu_aio_get(bs, cb, opaque);
  26.338 +    if (!acb)
  26.339 +        return NULL;
  26.340 +    acb->hd_aiocb = NULL;
  26.341 +    acb->sector_num = sector_num;
  26.342 +    acb->buf = buf;
  26.343 +    acb->nb_sectors = nb_sectors;
  26.344 +    acb->n = 0;
  26.345 +    acb->cluster_offset = 0;    
  26.346 +
  26.347 +    qcow_aio_read_cb(acb, 0);
  26.348 +    return &acb->common;
  26.349 +}
  26.350 +
  26.351 +static void qcow_aio_write_cb(void *opaque, int ret)
  26.352 +{
  26.353 +    QCowAIOCB *acb = opaque;
  26.354 +    BlockDriverState *bs = acb->common.bs;
  26.355 +    BDRVQcowState *s = bs->opaque;
  26.356 +    int index_in_cluster;
  26.357 +    uint64_t cluster_offset;
  26.358 +    const uint8_t *src_buf;
  26.359 +
  26.360 +    acb->hd_aiocb = NULL;
  26.361 +
  26.362 +    if (ret < 0) {
  26.363 +    fail:
  26.364 +        acb->common.cb(acb->common.opaque, ret);
  26.365 +        qemu_aio_release(acb);
  26.366 +        return;
  26.367 +    }
  26.368 +
  26.369 +    acb->nb_sectors -= acb->n;
  26.370 +    acb->sector_num += acb->n;
  26.371 +    acb->buf += acb->n * 512;
  26.372 +
  26.373 +    if (acb->nb_sectors == 0) {
  26.374 +        /* request completed */
  26.375 +        acb->common.cb(acb->common.opaque, 0);
  26.376 +        qemu_aio_release(acb);
  26.377 +        return;
  26.378 +    }
  26.379 +    
  26.380 +    index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
  26.381 +    acb->n = s->cluster_sectors - index_in_cluster;
  26.382 +    if (acb->n > acb->nb_sectors)
  26.383 +        acb->n = acb->nb_sectors;
  26.384 +    cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, 1, 0, 
  26.385 +                                        index_in_cluster, 
  26.386 +                                        index_in_cluster + acb->n);
  26.387 +    if (!cluster_offset || (cluster_offset & 511) != 0) {
  26.388 +        ret = -EIO;
  26.389 +        goto fail;
  26.390 +    }
  26.391 +    if (s->crypt_method) {
  26.392 +        if (!acb->cluster_data) {
  26.393 +            acb->cluster_data = qemu_mallocz(s->cluster_size);
  26.394 +            if (!acb->cluster_data) {
  26.395 +                ret = -ENOMEM;
  26.396 +                goto fail;
  26.397 +            }
  26.398 +        }
  26.399 +        encrypt_sectors(s, acb->sector_num, acb->cluster_data, acb->buf, 
  26.400 +                        acb->n, 1, &s->aes_encrypt_key);
  26.401 +        src_buf = acb->cluster_data;
  26.402 +    } else {
  26.403 +        src_buf = acb->buf;
  26.404 +    }
  26.405 +    acb->hd_aiocb = bdrv_aio_write(s->hd,
  26.406 +                                   (cluster_offset >> 9) + index_in_cluster, 
  26.407 +                                   src_buf, acb->n, 
  26.408 +                                   qcow_aio_write_cb, acb);
  26.409 +    if (acb->hd_aiocb == NULL)
  26.410 +        goto fail;
  26.411 +}
  26.412 +
  26.413 +static BlockDriverAIOCB *qcow_aio_write(BlockDriverState *bs,
  26.414 +        int64_t sector_num, const uint8_t *buf, int nb_sectors,
  26.415 +        BlockDriverCompletionFunc *cb, void *opaque)
  26.416 +{
  26.417 +    BDRVQcowState *s = bs->opaque;
  26.418 +    QCowAIOCB *acb;
  26.419 +    
  26.420 +    s->cluster_cache_offset = -1; /* disable compressed cache */
  26.421 +
  26.422 +    acb = qemu_aio_get(bs, cb, opaque);
  26.423 +    if (!acb)
  26.424 +        return NULL;
  26.425 +    acb->hd_aiocb = NULL;
  26.426 +    acb->sector_num = sector_num;
  26.427 +    acb->buf = (uint8_t *)buf;
  26.428 +    acb->nb_sectors = nb_sectors;
  26.429 +    acb->n = 0;
  26.430 +    
  26.431 +    qcow_aio_write_cb(acb, 0);
  26.432 +    return &acb->common;
  26.433 +}
  26.434 +
  26.435 +static void qcow_aio_cancel(BlockDriverAIOCB *blockacb)
  26.436 +{
  26.437 +    QCowAIOCB *acb = (QCowAIOCB *)blockacb;
  26.438 +    if (acb->hd_aiocb)
  26.439 +        bdrv_aio_cancel(acb->hd_aiocb);
  26.440 +    qemu_aio_release(acb);
  26.441 +}
  26.442 +
  26.443  static void qcow_close(BlockDriverState *bs)
  26.444  {
  26.445      BDRVQcowState *s = bs->opaque;
  26.446 @@ -529,7 +732,7 @@ static void qcow_close(BlockDriverState 
  26.447      qemu_free(s->l2_cache);
  26.448      qemu_free(s->cluster_cache);
  26.449      qemu_free(s->cluster_data);
  26.450 -    close(s->fd);
  26.451 +    bdrv_delete(s->hd);
  26.452  }
  26.453  
  26.454  static int qcow_create(const char *filename, int64_t total_size,
  26.455 @@ -537,12 +740,9 @@ static int qcow_create(const char *filen
  26.456  {
  26.457      int fd, header_size, backing_filename_len, l1_size, i, shift;
  26.458      QCowHeader header;
  26.459 -    char backing_filename[1024];
  26.460      uint64_t tmp;
  26.461 -    struct stat st;
  26.462  
  26.463 -    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 
  26.464 -              0644);
  26.465 +    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
  26.466      if (fd < 0)
  26.467          return -1;
  26.468      memset(&header, 0, sizeof(header));
  26.469 @@ -552,28 +752,11 @@ static int qcow_create(const char *filen
  26.470      header_size = sizeof(header);
  26.471      backing_filename_len = 0;
  26.472      if (backing_file) {
  26.473 -	if (strcmp(backing_file, "fat:")) {
  26.474 -	    const char *p;
  26.475 -	    /* XXX: this is a hack: we do not attempt to check for URL
  26.476 -	       like syntax */
  26.477 -	    p = strchr(backing_file, ':');
  26.478 -	    if (p && (p - backing_file) >= 2) {
  26.479 -		/* URL like but exclude "c:" like filenames */
  26.480 -		pstrcpy(backing_filename, sizeof(backing_filename),
  26.481 -			backing_file);
  26.482 -	    } else {
  26.483 -		realpath(backing_file, backing_filename);
  26.484 -		if (stat(backing_filename, &st) != 0) {
  26.485 -		    return -1;
  26.486 -		}
  26.487 -	    }
  26.488 -	    header.backing_file_offset = cpu_to_be64(header_size);
  26.489 -	    backing_filename_len = strlen(backing_filename);
  26.490 -	    header.backing_file_size = cpu_to_be32(backing_filename_len);
  26.491 -	    header_size += backing_filename_len;
  26.492 -	} else
  26.493 -	    backing_file = NULL;
  26.494 -        header.mtime = cpu_to_be32(st.st_mtime);
  26.495 +        header.backing_file_offset = cpu_to_be64(header_size);
  26.496 +        backing_filename_len = strlen(backing_file);
  26.497 +        header.backing_file_size = cpu_to_be32(backing_filename_len);
  26.498 +        header_size += backing_filename_len;
  26.499 +        header.mtime = cpu_to_be32(0);
  26.500          header.cluster_bits = 9; /* 512 byte cluster to avoid copying
  26.501                                      unmodifyed sectors */
  26.502          header.l2_bits = 12; /* 32 KB L2 tables */
  26.503 @@ -595,7 +778,7 @@ static int qcow_create(const char *filen
  26.504      /* write all the data */
  26.505      write(fd, &header, sizeof(header));
  26.506      if (backing_file) {
  26.507 -        write(fd, backing_filename, backing_filename_len);
  26.508 +        write(fd, backing_file, backing_filename_len);
  26.509      }
  26.510      lseek(fd, header_size, SEEK_SET);
  26.511      tmp = 0;
  26.512 @@ -606,16 +789,18 @@ static int qcow_create(const char *filen
  26.513      return 0;
  26.514  }
  26.515  
  26.516 -int qcow_make_empty(BlockDriverState *bs)
  26.517 +static int qcow_make_empty(BlockDriverState *bs)
  26.518  {
  26.519      BDRVQcowState *s = bs->opaque;
  26.520      uint32_t l1_length = s->l1_size * sizeof(uint64_t);
  26.521 +    int ret;
  26.522  
  26.523      memset(s->l1_table, 0, l1_length);
  26.524 -    lseek(s->fd, s->l1_table_offset, SEEK_SET);
  26.525 -    if (write(s->fd, s->l1_table, l1_length) < 0)
  26.526 +    if (bdrv_pwrite(s->hd, s->l1_table_offset, s->l1_table, l1_length) < 0)
  26.527  	return -1;
  26.528 -    ftruncate(s->fd, s->l1_table_offset + l1_length);
  26.529 +    ret = bdrv_truncate(s->hd, s->l1_table_offset + l1_length);
  26.530 +    if (ret < 0)
  26.531 +        return ret;
  26.532  
  26.533      memset(s->l2_cache, 0, s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t));
  26.534      memset(s->l2_cache_offsets, 0, L2_CACHE_SIZE * sizeof(uint64_t));
  26.535 @@ -624,18 +809,10 @@ int qcow_make_empty(BlockDriverState *bs
  26.536      return 0;
  26.537  }
  26.538  
  26.539 -int qcow_get_cluster_size(BlockDriverState *bs)
  26.540 -{
  26.541 -    BDRVQcowState *s = bs->opaque;
  26.542 -    if (bs->drv != &bdrv_qcow)
  26.543 -        return -1;
  26.544 -    return s->cluster_size;
  26.545 -}
  26.546 -
  26.547  /* XXX: put compressed sectors first, then all the cluster aligned
  26.548     tables to avoid losing bytes in alignment */
  26.549 -int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num, 
  26.550 -                          const uint8_t *buf)
  26.551 +static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num, 
  26.552 +                                 const uint8_t *buf, int nb_sectors)
  26.553  {
  26.554      BDRVQcowState *s = bs->opaque;
  26.555      z_stream strm;
  26.556 @@ -643,8 +820,8 @@ int qcow_compress_cluster(BlockDriverSta
  26.557      uint8_t *out_buf;
  26.558      uint64_t cluster_offset;
  26.559  
  26.560 -    if (bs->drv != &bdrv_qcow)
  26.561 -        return -1;
  26.562 +    if (nb_sectors != s->cluster_sectors)
  26.563 +        return -EINVAL;
  26.564  
  26.565      out_buf = qemu_malloc(s->cluster_size + (s->cluster_size / 1000) + 128);
  26.566      if (!out_buf)
  26.567 @@ -682,8 +859,7 @@ int qcow_compress_cluster(BlockDriverSta
  26.568          cluster_offset = get_cluster_offset(bs, sector_num << 9, 2, 
  26.569                                              out_len, 0, 0);
  26.570          cluster_offset &= s->cluster_offset_mask;
  26.571 -        lseek(s->fd, cluster_offset, SEEK_SET);
  26.572 -        if (write(s->fd, out_buf, out_len) != out_len) {
  26.573 +        if (bdrv_pwrite(s->hd, cluster_offset, out_buf, out_len) != out_len) {
  26.574              qemu_free(out_buf);
  26.575              return -1;
  26.576          }
  26.577 @@ -696,7 +872,14 @@ int qcow_compress_cluster(BlockDriverSta
  26.578  static void qcow_flush(BlockDriverState *bs)
  26.579  {
  26.580      BDRVQcowState *s = bs->opaque;
  26.581 -    fsync(s->fd);
  26.582 +    bdrv_flush(s->hd);
  26.583 +}
  26.584 +
  26.585 +static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
  26.586 +{
  26.587 +    BDRVQcowState *s = bs->opaque;
  26.588 +    bdi->cluster_size = s->cluster_size;
  26.589 +    return 0;
  26.590  }
  26.591  
  26.592  BlockDriver bdrv_qcow = {
  26.593 @@ -704,14 +887,19 @@ BlockDriver bdrv_qcow = {
  26.594      sizeof(BDRVQcowState),
  26.595      qcow_probe,
  26.596      qcow_open,
  26.597 -    qcow_read,
  26.598 -    qcow_write,
  26.599 +    NULL,
  26.600 +    NULL,
  26.601      qcow_close,
  26.602      qcow_create,
  26.603      qcow_flush,
  26.604      qcow_is_allocated,
  26.605      qcow_set_key,
  26.606 -    qcow_make_empty
  26.607 +    qcow_make_empty,
  26.608 +
  26.609 +    .bdrv_aio_read = qcow_aio_read,
  26.610 +    .bdrv_aio_write = qcow_aio_write,
  26.611 +    .bdrv_aio_cancel = qcow_aio_cancel,
  26.612 +    .aiocb_size = sizeof(QCowAIOCB),
  26.613 +    .bdrv_write_compressed = qcow_write_compressed,
  26.614 +    .bdrv_get_info = qcow_get_info,
  26.615  };
  26.616 -
  26.617 -
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/tools/ioemu/block-qcow2.c	Wed May 16 10:59:01 2007 -0600
    27.3 @@ -0,0 +1,2246 @@
    27.4 +/*
    27.5 + * Block driver for the QCOW version 2 format
    27.6 + * 
    27.7 + * Copyright (c) 2004-2006 Fabrice Bellard
    27.8 + * 
    27.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   27.10 + * of this software and associated documentation files (the "Software"), to deal
   27.11 + * in the Software without restriction, including without limitation the rights
   27.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   27.13 + * copies of the Software, and to permit persons to whom the Software is
   27.14 + * furnished to do so, subject to the following conditions:
   27.15 + *
   27.16 + * The above copyright notice and this permission notice shall be included in
   27.17 + * all copies or substantial portions of the Software.
   27.18 + *
   27.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   27.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   27.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   27.22 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   27.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   27.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   27.25 + * THE SOFTWARE.
   27.26 + */
   27.27 +#include "vl.h"
   27.28 +#include "block_int.h"
   27.29 +#include <zlib.h>
   27.30 +#include "aes.h"
   27.31 +#include <assert.h>
   27.32 +
   27.33 +/*
   27.34 +  Differences with QCOW:
   27.35 +
   27.36 +  - Support for multiple incremental snapshots.
   27.37 +  - Memory management by reference counts.
   27.38 +  - Clusters which have a reference count of one have the bit
   27.39 +    QCOW_OFLAG_COPIED to optimize write performance.
   27.40 +  - Size of compressed clusters is stored in sectors to reduce bit usage 
   27.41 +    in the cluster offsets.
   27.42 +  - Support for storing additional data (such as the VM state) in the
   27.43 +    snapshots.  
   27.44 +  - If a backing store is used, the cluster size is not constrained
   27.45 +    (could be backported to QCOW).
   27.46 +  - L2 tables have always a size of one cluster.
   27.47 +*/
   27.48 +
   27.49 +//#define DEBUG_ALLOC
   27.50 +//#define DEBUG_ALLOC2
   27.51 + 
   27.52 +#define QCOW_MAGIC (('Q' << 24) | ('F' << 16) | ('I' << 8) | 0xfb)
   27.53 +#define QCOW_VERSION 2
   27.54 +
   27.55 +#define QCOW_CRYPT_NONE 0
   27.56 +#define QCOW_CRYPT_AES  1
   27.57 +
   27.58 +/* indicate that the refcount of the referenced cluster is exactly one. */
   27.59 +#define QCOW_OFLAG_COPIED     (1LL << 63)
   27.60 +/* indicate that the cluster is compressed (they never have the copied flag) */
   27.61 +#define QCOW_OFLAG_COMPRESSED (1LL << 62)
   27.62 +
   27.63 +#define REFCOUNT_SHIFT 1 /* refcount size is 2 bytes */
   27.64 +
   27.65 +#ifndef offsetof
   27.66 +#define offsetof(type, field) ((size_t) &((type *)0)->field)
   27.67 +#endif
   27.68 +
   27.69 +typedef struct QCowHeader {
   27.70 +    uint32_t magic;
   27.71 +    uint32_t version;
   27.72 +    uint64_t backing_file_offset;
   27.73 +    uint32_t backing_file_size;
   27.74 +    uint32_t cluster_bits;
   27.75 +    uint64_t size; /* in bytes */
   27.76 +    uint32_t crypt_method;
   27.77 +    uint32_t l1_size; /* XXX: save number of clusters instead ? */
   27.78 +    uint64_t l1_table_offset;
   27.79 +    uint64_t refcount_table_offset;
   27.80 +    uint32_t refcount_table_clusters;
   27.81 +    uint32_t nb_snapshots;
   27.82 +    uint64_t snapshots_offset;
   27.83 +} QCowHeader;
   27.84 +
   27.85 +typedef struct __attribute__((packed)) QCowSnapshotHeader {
   27.86 +    /* header is 8 byte aligned */
   27.87 +    uint64_t l1_table_offset;
   27.88 +
   27.89 +    uint32_t l1_size;
   27.90 +    uint16_t id_str_size;
   27.91 +    uint16_t name_size;
   27.92 +
   27.93 +    uint32_t date_sec;
   27.94 +    uint32_t date_nsec;
   27.95 +
   27.96 +    uint64_t vm_clock_nsec;
   27.97 +
   27.98 +    uint32_t vm_state_size;
   27.99 +    uint32_t extra_data_size; /* for extension */
  27.100 +    /* extra data follows */
  27.101 +    /* id_str follows */
  27.102 +    /* name follows  */
  27.103 +} QCowSnapshotHeader;
  27.104 +
  27.105 +#define L2_CACHE_SIZE 16
  27.106 +
  27.107 +typedef struct QCowSnapshot {
  27.108 +    uint64_t l1_table_offset;
  27.109 +    uint32_t l1_size;
  27.110 +    char *id_str;
  27.111 +    char *name;
  27.112 +    uint32_t vm_state_size;
  27.113 +    uint32_t date_sec;
  27.114 +    uint32_t date_nsec;
  27.115 +    uint64_t vm_clock_nsec;
  27.116 +} QCowSnapshot;
  27.117 +
  27.118 +typedef struct BDRVQcowState {
  27.119 +    BlockDriverState *hd;
  27.120 +    int cluster_bits;
  27.121 +    int cluster_size;
  27.122 +    int cluster_sectors;
  27.123 +    int l2_bits;
  27.124 +    int l2_size;
  27.125 +    int l1_size;
  27.126 +    int l1_vm_state_index;
  27.127 +    int csize_shift;
  27.128 +    int csize_mask;
  27.129 +    uint64_t cluster_offset_mask;
  27.130 +    uint64_t l1_table_offset;
  27.131 +    uint64_t *l1_table;
  27.132 +    uint64_t *l2_cache;
  27.133 +    uint64_t l2_cache_offsets[L2_CACHE_SIZE];
  27.134 +    uint32_t l2_cache_counts[L2_CACHE_SIZE];
  27.135 +    uint8_t *cluster_cache;
  27.136 +    uint8_t *cluster_data;
  27.137 +    uint64_t cluster_cache_offset;
  27.138 +
  27.139 +    uint64_t *refcount_table;
  27.140 +    uint64_t refcount_table_offset;
  27.141 +    uint32_t refcount_table_size;
  27.142 +    uint64_t refcount_block_cache_offset;
  27.143 +    uint16_t *refcount_block_cache;
  27.144 +    int64_t free_cluster_index;
  27.145 +    int64_t free_byte_offset;
  27.146 +
  27.147 +    uint32_t crypt_method; /* current crypt method, 0 if no key yet */
  27.148 +    uint32_t crypt_method_header;
  27.149 +    AES_KEY aes_encrypt_key;
  27.150 +    AES_KEY aes_decrypt_key;
  27.151 +    uint64_t snapshots_offset;
  27.152 +    int snapshots_size;
  27.153 +    int nb_snapshots;
  27.154 +    QCowSnapshot *snapshots;
  27.155 +} BDRVQcowState;
  27.156 +
  27.157 +static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset);
  27.158 +static int qcow_read(BlockDriverState *bs, int64_t sector_num, 
  27.159 +                     uint8_t *buf, int nb_sectors);
  27.160 +static int qcow_read_snapshots(BlockDriverState *bs);
  27.161 +static void qcow_free_snapshots(BlockDriverState *bs);
  27.162 +static int refcount_init(BlockDriverState *bs);
  27.163 +static void refcount_close(BlockDriverState *bs);
  27.164 +static int get_refcount(BlockDriverState *bs, int64_t cluster_index);
  27.165 +static int update_cluster_refcount(BlockDriverState *bs, 
  27.166 +                                   int64_t cluster_index,
  27.167 +                                   int addend);
  27.168 +static void update_refcount(BlockDriverState *bs, 
  27.169 +                            int64_t offset, int64_t length, 
  27.170 +                            int addend);
  27.171 +static int64_t alloc_clusters(BlockDriverState *bs, int64_t size);
  27.172 +static int64_t alloc_bytes(BlockDriverState *bs, int size);
  27.173 +static void free_clusters(BlockDriverState *bs, 
  27.174 +                          int64_t offset, int64_t size);
  27.175 +#ifdef DEBUG_ALLOC
  27.176 +static void check_refcounts(BlockDriverState *bs);
  27.177 +#endif
  27.178 +
  27.179 +static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
  27.180 +{
  27.181 +    const QCowHeader *cow_header = (const void *)buf;
  27.182 +    
  27.183 +    if (buf_size >= sizeof(QCowHeader) &&
  27.184 +        be32_to_cpu(cow_header->magic) == QCOW_MAGIC &&
  27.185 +        be32_to_cpu(cow_header->version) == QCOW_VERSION) 
  27.186 +        return 100;
  27.187 +    else
  27.188 +        return 0;
  27.189 +}
  27.190 +
  27.191 +static int qcow_open(BlockDriverState *bs, const char *filename, int flags)
  27.192 +{
  27.193 +    BDRVQcowState *s = bs->opaque;
  27.194 +    int len, i, shift, ret;
  27.195 +    QCowHeader header;
  27.196 +
  27.197 +    ret = bdrv_file_open(&s->hd, filename, flags);
  27.198 +    if (ret < 0)
  27.199 +        return ret;
  27.200 +    if (bdrv_pread(s->hd, 0, &header, sizeof(header)) != sizeof(header))
  27.201 +        goto fail;
  27.202 +    be32_to_cpus(&header.magic);
  27.203 +    be32_to_cpus(&header.version);
  27.204 +    be64_to_cpus(&header.backing_file_offset);
  27.205 +    be32_to_cpus(&header.backing_file_size);
  27.206 +    be64_to_cpus(&header.size);
  27.207 +    be32_to_cpus(&header.cluster_bits);
  27.208 +    be32_to_cpus(&header.crypt_method);
  27.209 +    be64_to_cpus(&header.l1_table_offset);
  27.210 +    be32_to_cpus(&header.l1_size);
  27.211 +    be64_to_cpus(&header.refcount_table_offset);
  27.212 +    be32_to_cpus(&header.refcount_table_clusters);
  27.213 +    be64_to_cpus(&header.snapshots_offset);
  27.214 +    be32_to_cpus(&header.nb_snapshots);
  27.215 +    
  27.216 +    if (header.magic != QCOW_MAGIC || header.version != QCOW_VERSION)
  27.217 +        goto fail;
  27.218 +    if (header.size <= 1 || 
  27.219 +        header.cluster_bits < 9 || 
  27.220 +        header.cluster_bits > 16)
  27.221 +        goto fail;
  27.222 +    if (header.crypt_method > QCOW_CRYPT_AES)
  27.223 +        goto fail;
  27.224 +    s->crypt_method_header = header.crypt_method;
  27.225 +    if (s->crypt_method_header)
  27.226 +        bs->encrypted = 1;
  27.227 +    s->cluster_bits = header.cluster_bits;
  27.228 +    s->cluster_size = 1 << s->cluster_bits;
  27.229 +    s->cluster_sectors = 1 << (s->cluster_bits - 9);
  27.230 +    s->l2_bits = s->cluster_bits - 3; /* L2 is always one cluster */
  27.231 +    s->l2_size = 1 << s->l2_bits;
  27.232 +    bs->total_sectors = header.size / 512;
  27.233 +    s->csize_shift = (62 - (s->cluster_bits - 8));
  27.234 +    s->csize_mask = (1 << (s->cluster_bits - 8)) - 1;
  27.235 +    s->cluster_offset_mask = (1LL << s->csize_shift) - 1;
  27.236 +    s->refcount_table_offset = header.refcount_table_offset;
  27.237 +    s->refcount_table_size = 
  27.238 +        header.refcount_table_clusters << (s->cluster_bits - 3);
  27.239 +
  27.240 +    s->snapshots_offset = header.snapshots_offset;
  27.241 +    s->nb_snapshots = header.nb_snapshots;
  27.242 +
  27.243 +    /* read the level 1 table */
  27.244 +    s->l1_size = header.l1_size;
  27.245 +    shift = s->cluster_bits + s->l2_bits;
  27.246 +    s->l1_vm_state_index = (header.size + (1LL << shift) - 1) >> shift;
  27.247 +    /* the L1 table must contain at least enough entries to put
  27.248 +       header.size bytes */
  27.249 +    if (s->l1_size < s->l1_vm_state_index)
  27.250 +        goto fail;
  27.251 +    s->l1_table_offset = header.l1_table_offset;
  27.252 +    s->l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t));
  27.253 +    if (!s->l1_table)
  27.254 +        goto fail;
  27.255 +    if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, s->l1_size * sizeof(uint64_t)) != 
  27.256 +        s->l1_size * sizeof(uint64_t))
  27.257 +        goto fail;
  27.258 +    for(i = 0;i < s->l1_size; i++) {
  27.259 +        be64_to_cpus(&s->l1_table[i]);
  27.260 +    }
  27.261 +    /* alloc L2 cache */
  27.262 +    s->l2_cache = qemu_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t));
  27.263 +    if (!s->l2_cache)
  27.264 +        goto fail;
  27.265 +    s->cluster_cache = qemu_malloc(s->cluster_size);
  27.266 +    if (!s->cluster_cache)
  27.267 +        goto fail;
  27.268 +    /* one more sector for decompressed data alignment */
  27.269 +    s->cluster_data = qemu_malloc(s->cluster_size + 512);
  27.270 +    if (!s->cluster_data)
  27.271 +        goto fail;
  27.272 +    s->cluster_cache_offset = -1;
  27.273 +    
  27.274 +    if (refcount_init(bs) < 0)
  27.275 +        goto fail;
  27.276 +
  27.277 +    /* read the backing file name */
  27.278 +    if (header.backing_file_offset != 0) {
  27.279 +        len = header.backing_file_size;
  27.280 +        if (len > 1023)
  27.281 +            len = 1023;
  27.282 +        if (bdrv_pread(s->hd, header.backing_file_offset, bs->backing_file, len) != len)
  27.283 +            goto fail;
  27.284 +        bs->backing_file[len] = '\0';
  27.285 +    }
  27.286 +    if (qcow_read_snapshots(bs) < 0)
  27.287 +        goto fail;
  27.288 +
  27.289 +#ifdef DEBUG_ALLOC
  27.290 +    check_refcounts(bs);
  27.291 +#endif
  27.292 +    return 0;
  27.293 +
  27.294 + fail:
  27.295 +    qcow_free_snapshots(bs);
  27.296 +    refcount_close(bs);
  27.297 +    qemu_free(s->l1_table);
  27.298 +    qemu_free(s->l2_cache);
  27.299 +    qemu_free(s->cluster_cache);
  27.300 +    qemu_free(s->cluster_data);
  27.301 +    bdrv_delete(s->hd);
  27.302 +    return -1;
  27.303 +}
  27.304 +
  27.305 +static int qcow_set_key(BlockDriverState *bs, const char *key)
  27.306 +{
  27.307 +    BDRVQcowState *s = bs->opaque;
  27.308 +    uint8_t keybuf[16];
  27.309 +    int len, i;
  27.310 +    
  27.311 +    memset(keybuf, 0, 16);
  27.312 +    len = strlen(key);
  27.313 +    if (len > 16)
  27.314 +        len = 16;
  27.315 +    /* XXX: we could compress the chars to 7 bits to increase
  27.316 +       entropy */
  27.317 +    for(i = 0;i < len;i++) {
  27.318 +        keybuf[i] = key[i];
  27.319 +    }
  27.320 +    s->crypt_method = s->crypt_method_header;
  27.321 +
  27.322 +    if (AES_set_encrypt_key(keybuf, 128, &s->aes_encrypt_key) != 0)
  27.323 +        return -1;
  27.324 +    if (AES_set_decrypt_key(keybuf, 128, &s->aes_decrypt_key) != 0)
  27.325 +        return -1;
  27.326 +#if 0
  27.327 +    /* test */
  27.328 +    {
  27.329 +        uint8_t in[16];
  27.330 +        uint8_t out[16];
  27.331 +        uint8_t tmp[16];
  27.332 +        for(i=0;i<16;i++)
  27.333 +            in[i] = i;
  27.334 +        AES_encrypt(in, tmp, &s->aes_encrypt_key);
  27.335 +        AES_decrypt(tmp, out, &s->aes_decrypt_key);
  27.336 +        for(i = 0; i < 16; i++)
  27.337 +            printf(" %02x", tmp[i]);
  27.338 +        printf("\n");
  27.339 +        for(i = 0; i < 16; i++)
  27.340 +            printf(" %02x", out[i]);
  27.341 +        printf("\n");
  27.342 +    }
  27.343 +#endif
  27.344 +    return 0;
  27.345 +}
  27.346 +
  27.347 +/* The crypt function is compatible with the linux cryptoloop
  27.348 +   algorithm for < 4 GB images. NOTE: out_buf == in_buf is
  27.349 +   supported */
  27.350 +static void encrypt_sectors(BDRVQcowState *s, int64_t sector_num,
  27.351 +                            uint8_t *out_buf, const uint8_t *in_buf,
  27.352 +                            int nb_sectors, int enc,
  27.353 +                            const AES_KEY *key)
  27.354 +{
  27.355 +    union {
  27.356 +        uint64_t ll[2];
  27.357 +        uint8_t b[16];
  27.358 +    } ivec;
  27.359 +    int i;
  27.360 +
  27.361 +    for(i = 0; i < nb_sectors; i++) {
  27.362 +        ivec.ll[0] = cpu_to_le64(sector_num);
  27.363 +        ivec.ll[1] = 0;
  27.364 +        AES_cbc_encrypt(in_buf, out_buf, 512, key, 
  27.365 +                        ivec.b, enc);
  27.366 +        sector_num++;
  27.367 +        in_buf += 512;
  27.368 +        out_buf += 512;
  27.369 +    }
  27.370 +}
  27.371 +
  27.372 +static int copy_sectors(BlockDriverState *bs, uint64_t start_sect,
  27.373 +                        uint64_t cluster_offset, int n_start, int n_end)
  27.374 +{
  27.375 +    BDRVQcowState *s = bs->opaque;
  27.376 +    int n, ret;
  27.377 +
  27.378 +    n = n_end - n_start;
  27.379 +    if (n <= 0)
  27.380 +        return 0;
  27.381 +    ret = qcow_read(bs, start_sect + n_start, s->cluster_data, n);
  27.382 +    if (ret < 0)
  27.383 +        return ret;
  27.384 +    if (s->crypt_method) {
  27.385 +        encrypt_sectors(s, start_sect + n_start, 
  27.386 +                        s->cluster_data, 
  27.387 +                        s->cluster_data, n, 1,
  27.388 +                        &s->aes_encrypt_key);
  27.389 +    }
  27.390 +    ret = bdrv_write(s->hd, (cluster_offset >> 9) + n_start, 
  27.391 +                     s->cluster_data, n);
  27.392 +    if (ret < 0)
  27.393 +        return ret;
  27.394 +    return 0;
  27.395 +}
  27.396 +
  27.397 +static void l2_cache_reset(BlockDriverState *bs)
  27.398 +{
  27.399 +    BDRVQcowState *s = bs->opaque;
  27.400 +
  27.401 +    memset(s->l2_cache, 0, s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t));
  27.402 +    memset(s->l2_cache_offsets, 0, L2_CACHE_SIZE * sizeof(uint64_t));
  27.403 +    memset(s->l2_cache_counts, 0, L2_CACHE_SIZE * sizeof(uint32_t));
  27.404 +}
  27.405 +
  27.406 +static inline int l2_cache_new_entry(BlockDriverState *bs)
  27.407 +{
  27.408 +    BDRVQcowState *s = bs->opaque;
  27.409 +    uint32_t min_count;
  27.410 +    int min_index, i;
  27.411 +
  27.412 +    /* find a new entry in the least used one */
  27.413 +    min_index = 0;
  27.414 +    min_count = 0xffffffff;
  27.415 +    for(i = 0; i < L2_CACHE_SIZE; i++) {
  27.416 +        if (s->l2_cache_counts[i] < min_count) {
  27.417 +            min_count = s->l2_cache_counts[i];
  27.418 +            min_index = i;
  27.419 +        }
  27.420 +    }
  27.421 +    return min_index;
  27.422 +}
  27.423 +
  27.424 +static int64_t align_offset(int64_t offset, int n)
  27.425 +{
  27.426 +    offset = (offset + n - 1) & ~(n - 1);
  27.427 +    return offset;
  27.428 +}
  27.429 +
  27.430 +static int grow_l1_table(BlockDriverState *bs, int min_size)
  27.431 +{
  27.432 +    BDRVQcowState *s = bs->opaque;
  27.433 +    int new_l1_size, new_l1_size2, ret, i;
  27.434 +    uint64_t *new_l1_table;
  27.435 +    uint64_t new_l1_table_offset;
  27.436 +    uint64_t data64;
  27.437 +    uint32_t data32;
  27.438 +
  27.439 +    new_l1_size = s->l1_size;
  27.440 +    if (min_size <= new_l1_size)
  27.441 +        return 0;
  27.442 +    while (min_size > new_l1_size) {
  27.443 +        new_l1_size = (new_l1_size * 3 + 1) / 2;
  27.444 +    }
  27.445 +#ifdef DEBUG_ALLOC2
  27.446 +    printf("grow l1_table from %d to %d\n", s->l1_size, new_l1_size);
  27.447 +#endif
  27.448 +
  27.449 +    new_l1_size2 = sizeof(uint64_t) * new_l1_size;
  27.450 +    new_l1_table = qemu_mallocz(new_l1_size2);
  27.451 +    if (!new_l1_table)
  27.452 +        return -ENOMEM;
  27.453 +    memcpy(new_l1_table, s->l1_table, s->l1_size * sizeof(uint64_t));
  27.454 +
  27.455 +    /* write new table (align to cluster) */
  27.456 +    new_l1_table_offset = alloc_clusters(bs, new_l1_size2);
  27.457 +    
  27.458 +    for(i = 0; i < s->l1_size; i++)
  27.459 +        new_l1_table[i] = cpu_to_be64(new_l1_table[i]);
  27.460 +    ret = bdrv_pwrite(s->hd, new_l1_table_offset, new_l1_table, new_l1_size2);
  27.461 +    if (ret != new_l1_size2)
  27.462 +        goto fail;
  27.463 +    for(i = 0; i < s->l1_size; i++)
  27.464 +        new_l1_table[i] = be64_to_cpu(new_l1_table[i]);
  27.465 +    
  27.466 +    /* set new table */
  27.467 +    data64 = cpu_to_be64(new_l1_table_offset);
  27.468 +    if (bdrv_pwrite(s->hd, offsetof(QCowHeader, l1_table_offset),
  27.469 +                    &data64, sizeof(data64)) != sizeof(data64))
  27.470 +        goto fail;
  27.471 +    data32 = cpu_to_be32(new_l1_size);
  27.472 +    if (bdrv_pwrite(s->hd, offsetof(QCowHeader, l1_size),
  27.473 +                    &data32, sizeof(data32)) != sizeof(data32))
  27.474 +        goto fail;
  27.475 +    qemu_free(s->l1_table);
  27.476 +    free_clusters(bs, s->l1_table_offset, s->l1_size * sizeof(uint64_t));
  27.477 +    s->l1_table_offset = new_l1_table_offset;
  27.478 +    s->l1_table = new_l1_table;
  27.479 +    s->l1_size = new_l1_size;
  27.480 +    return 0;
  27.481 + fail:
  27.482 +    qemu_free(s->l1_table);
  27.483 +    return -EIO;
  27.484 +}
  27.485 +
  27.486 +/* 'allocate' is:
  27.487 + *
  27.488 + * 0 not to allocate.
  27.489 + *
  27.490 + * 1 to allocate a normal cluster (for sector indexes 'n_start' to
  27.491 + * 'n_end')
  27.492 + *
  27.493 + * 2 to allocate a compressed cluster of size
  27.494 + * 'compressed_size'. 'compressed_size' must be > 0 and <
  27.495 + * cluster_size 
  27.496 + *
  27.497 + * return 0 if not allocated.
  27.498 + */
  27.499 +static uint64_t get_cluster_offset(BlockDriverState *bs,
  27.500 +                                   uint64_t offset, int allocate,
  27.501 +                                   int compressed_size,
  27.502 +                                   int n_start, int n_end)
  27.503 +{
  27.504 +    BDRVQcowState *s = bs->opaque;
  27.505 +    int min_index, i, j, l1_index, l2_index, ret;
  27.506 +    uint64_t l2_offset, *l2_table, cluster_offset, tmp, old_l2_offset;
  27.507 +    
  27.508 +    l1_index = offset >> (s->l2_bits + s->cluster_bits);
  27.509 +    if (l1_index >= s->l1_size) {
  27.510 +        /* outside l1 table is allowed: we grow the table if needed */
  27.511 +        if (!allocate)
  27.512 +            return 0;
  27.513 +        if (grow_l1_table(bs, l1_index + 1) < 0)
  27.514 +            return 0;
  27.515 +    }
  27.516 +    l2_offset = s->l1_table[l1_index];
  27.517 +    if (!l2_offset) {
  27.518 +        if (!allocate)
  27.519 +            return 0;
  27.520 +    l2_allocate:
  27.521 +        old_l2_offset = l2_offset;
  27.522 +        /* allocate a new l2 entry */
  27.523 +        l2_offset = alloc_clusters(bs, s->l2_size * sizeof(uint64_t));
  27.524 +        /* update the L1 entry */
  27.525 +        s->l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED;
  27.526 +        tmp = cpu_to_be64(l2_offset | QCOW_OFLAG_COPIED);
  27.527 +        if (bdrv_pwrite(s->hd, s->l1_table_offset + l1_index * sizeof(tmp), 
  27.528 +                        &tmp, sizeof(tmp)) != sizeof(tmp))
  27.529 +            return 0;
  27.530 +        min_index = l2_cache_new_entry(bs);
  27.531 +        l2_table = s->l2_cache + (min_index << s->l2_bits);
  27.532 +
  27.533 +        if (old_l2_offset == 0) {
  27.534 +            memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
  27.535 +        } else {
  27.536 +            if (bdrv_pread(s->hd, old_l2_offset, 
  27.537 +                           l2_table, s->l2_size * sizeof(uint64_t)) !=
  27.538 +                s->l2_size * sizeof(uint64_t))
  27.539 +                return 0;
  27.540 +        }
  27.541 +        if (bdrv_pwrite(s->hd, l2_offset, 
  27.542 +                        l2_table, s->l2_size * sizeof(uint64_t)) !=
  27.543 +            s->l2_size * sizeof(uint64_t))
  27.544 +            return 0;
  27.545 +    } else {
  27.546 +        if (!(l2_offset & QCOW_OFLAG_COPIED)) {
  27.547 +            if (allocate) {
  27.548 +                free_clusters(bs, l2_offset, s->l2_size * sizeof(uint64_t));
  27.549 +                goto l2_allocate;
  27.550 +            }
  27.551 +        } else {
  27.552 +            l2_offset &= ~QCOW_OFLAG_COPIED;
  27.553 +        }
  27.554 +        for(i = 0; i < L2_CACHE_SIZE; i++) {
  27.555 +            if (l2_offset == s->l2_cache_offsets[i]) {
  27.556 +                /* increment the hit count */
  27.557 +                if (++s->l2_cache_counts[i] == 0xffffffff) {
  27.558 +                    for(j = 0; j < L2_CACHE_SIZE; j++) {
  27.559 +                        s->l2_cache_counts[j] >>= 1;
  27.560 +                    }
  27.561 +                }
  27.562 +                l2_table = s->l2_cache + (i << s->l2_bits);
  27.563 +                goto found;
  27.564 +            }
  27.565 +        }
  27.566 +        /* not found: load a new entry in the least used one */
  27.567 +        min_index = l2_cache_new_entry(bs);
  27.568 +        l2_table = s->l2_cache + (min_index << s->l2_bits);
  27.569 +        if (bdrv_pread(s->hd, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) != 
  27.570 +            s->l2_size * sizeof(uint64_t))
  27.571 +            return 0;
  27.572 +    }
  27.573 +    s->l2_cache_offsets[min_index] = l2_offset;
  27.574 +    s->l2_cache_counts[min_index] = 1;
  27.575 + found:
  27.576 +    l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
  27.577 +    cluster_offset = be64_to_cpu(l2_table[l2_index]);
  27.578 +    if (!cluster_offset) {
  27.579 +        if (!allocate)
  27.580 +            return cluster_offset;
  27.581 +    } else if (!(cluster_offset & QCOW_OFLAG_COPIED)) {
  27.582 +        if (!allocate)
  27.583 +            return cluster_offset;
  27.584 +        /* free the cluster */
  27.585 +        if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
  27.586 +            int nb_csectors;
  27.587 +            nb_csectors = ((cluster_offset >> s->csize_shift) & 
  27.588 +                           s->csize_mask) + 1;
  27.589 +            free_clusters(bs, (cluster_offset & s->cluster_offset_mask) & ~511,
  27.590 +                          nb_csectors * 512);
  27.591 +        } else {
  27.592 +            free_clusters(bs, cluster_offset, s->cluster_size);
  27.593 +        }
  27.594 +    } else {
  27.595 +        cluster_offset &= ~QCOW_OFLAG_COPIED;
  27.596 +        return cluster_offset;
  27.597 +    }
  27.598 +    if (allocate == 1) {
  27.599 +        /* allocate a new cluster */
  27.600 +        cluster_offset = alloc_clusters(bs, s->cluster_size);
  27.601 +
  27.602 +        /* we must initialize the cluster content which won't be
  27.603 +           written */
  27.604 +        if ((n_end - n_start) < s->cluster_sectors) {
  27.605 +            uint64_t start_sect;
  27.606 +            
  27.607 +            start_sect = (offset & ~(s->cluster_size - 1)) >> 9;
  27.608 +            ret = copy_sectors(bs, start_sect,
  27.609 +                               cluster_offset, 0, n_start);
  27.610 +            if (ret < 0)
  27.611 +                return 0;
  27.612 +            ret = copy_sectors(bs, start_sect,
  27.613 +                               cluster_offset, n_end, s->cluster_sectors);
  27.614 +            if (ret < 0)
  27.615 +                return 0;
  27.616 +        }
  27.617 +        tmp = cpu_to_be64(cluster_offset | QCOW_OFLAG_COPIED);
  27.618 +    } else {
  27.619 +        int nb_csectors;
  27.620 +        cluster_offset = alloc_bytes(bs, compressed_size);
  27.621 +        nb_csectors = ((cluster_offset + compressed_size - 1) >> 9) - 
  27.622 +            (cluster_offset >> 9);
  27.623 +        cluster_offset |= QCOW_OFLAG_COMPRESSED | 
  27.624 +            ((uint64_t)nb_csectors << s->csize_shift);
  27.625 +        /* compressed clusters never have the copied flag */
  27.626 +        tmp = cpu_to_be64(cluster_offset);
  27.627 +    }
  27.628 +    /* update L2 table */
  27.629 +    l2_table[l2_index] = tmp;
  27.630 +    if (bdrv_pwrite(s->hd, 
  27.631 +                    l2_offset + l2_index * sizeof(tmp), &tmp, sizeof(tmp)) != sizeof(tmp))
  27.632 +        return 0;
  27.633 +    return cluster_offset;
  27.634 +}
  27.635 +
  27.636 +static int qcow_is_allocated(BlockDriverState *bs, int64_t sector_num, 
  27.637 +                             int nb_sectors, int *pnum)
  27.638 +{
  27.639 +    BDRVQcowState *s = bs->opaque;
  27.640 +    int index_in_cluster, n;
  27.641 +    uint64_t cluster_offset;
  27.642 +
  27.643 +    cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0);
  27.644 +    index_in_cluster = sector_num & (s->cluster_sectors - 1);
  27.645 +    n = s->cluster_sectors - index_in_cluster;
  27.646 +    if (n > nb_sectors)
  27.647 +        n = nb_sectors;
  27.648 +    *pnum = n;
  27.649 +    return (cluster_offset != 0);
  27.650 +}
  27.651 +
  27.652 +static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
  27.653 +                             const uint8_t *buf, int buf_size)
  27.654 +{
  27.655 +    z_stream strm1, *strm = &strm1;
  27.656 +    int ret, out_len;
  27.657 +
  27.658 +    memset(strm, 0, sizeof(*strm));
  27.659 +
  27.660 +    strm->next_in = (uint8_t *)buf;
  27.661 +    strm->avail_in = buf_size;
  27.662 +    strm->next_out = out_buf;
  27.663 +    strm->avail_out = out_buf_size;
  27.664 +
  27.665 +    ret = inflateInit2(strm, -12);
  27.666 +    if (ret != Z_OK)
  27.667 +        return -1;
  27.668 +    ret = inflate(strm, Z_FINISH);
  27.669 +    out_len = strm->next_out - out_buf;
  27.670 +    if ((ret != Z_STREAM_END && ret != Z_BUF_ERROR) ||
  27.671 +        out_len != out_buf_size) {
  27.672 +        inflateEnd(strm);
  27.673 +        return -1;
  27.674 +    }
  27.675 +    inflateEnd(strm);
  27.676 +    return 0;
  27.677 +}
  27.678 +                              
  27.679 +static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
  27.680 +{
  27.681 +    int ret, csize, nb_csectors, sector_offset;
  27.682 +    uint64_t coffset;
  27.683 +
  27.684 +    coffset = cluster_offset & s->cluster_offset_mask;
  27.685 +    if (s->cluster_cache_offset != coffset) {
  27.686 +        nb_csectors = ((cluster_offset >> s->csize_shift) & s->csize_mask) + 1;
  27.687 +        sector_offset = coffset & 511;
  27.688 +        csize = nb_csectors * 512 - sector_offset;
  27.689 +        ret = bdrv_read(s->hd, coffset >> 9, s->cluster_data, nb_csectors);
  27.690 +        if (ret < 0) {
  27.691 +            return -1;
  27.692 +        }
  27.693 +        if (decompress_buffer(s->cluster_cache, s->cluster_size,
  27.694 +                              s->cluster_data + sector_offset, csize) < 0) {
  27.695 +            return -1;
  27.696 +        }
  27.697 +        s->cluster_cache_offset = coffset;
  27.698 +    }
  27.699 +    return 0;
  27.700 +}
  27.701 +
  27.702 +/* handle reading after the end of the backing file */
  27.703 +static int backing_read1(BlockDriverState *bs, 
  27.704 +                         int64_t sector_num, uint8_t *buf, int nb_sectors)
  27.705 +{
  27.706 +    int n1;
  27.707 +    if ((sector_num + nb_sectors) <= bs->total_sectors)
  27.708 +        return nb_sectors;
  27.709 +    if (sector_num >= bs->total_sectors)
  27.710 +        n1 = 0;
  27.711 +    else
  27.712 +        n1 = bs->total_sectors - sector_num;
  27.713 +    memset(buf + n1 * 512, 0, 512 * (nb_sectors - n1));
  27.714 +    return n1;
  27.715 +}
  27.716 +
  27.717 +static int qcow_read(BlockDriverState *bs, int64_t sector_num, 
  27.718 +                     uint8_t *buf, int nb_sectors)
  27.719 +{
  27.720 +    BDRVQcowState *s = bs->opaque;
  27.721 +    int ret, index_in_cluster, n, n1;
  27.722 +    uint64_t cluster_offset;
  27.723 +    
  27.724 +    while (nb_sectors > 0) {
  27.725 +        cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0);
  27.726 +        index_in_cluster = sector_num & (s->cluster_sectors - 1);
  27.727 +        n = s->cluster_sectors - index_in_cluster;
  27.728 +        if (n > nb_sectors)
  27.729 +            n = nb_sectors;
  27.730 +        if (!cluster_offset) {
  27.731 +            if (bs->backing_hd) {
  27.732 +                /* read from the base image */
  27.733 +                n1 = backing_read1(bs->backing_hd, sector_num, buf, n);
  27.734 +                if (n1 > 0) {
  27.735 +                    ret = bdrv_read(bs->backing_hd, sector_num, buf, n1);
  27.736 +                    if (ret < 0)
  27.737 +                        return -1;
  27.738 +                }
  27.739 +            } else {
  27.740 +                memset(buf, 0, 512 * n);
  27.741 +            }
  27.742 +        } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
  27.743 +            if (decompress_cluster(s, cluster_offset) < 0)
  27.744 +                return -1;
  27.745 +            memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n);
  27.746 +        } else {
  27.747 +            ret = bdrv_pread(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);
  27.748 +            if (ret != n * 512) 
  27.749 +                return -1;
  27.750 +            if (s->crypt_method) {
  27.751 +                encrypt_sectors(s, sector_num, buf, buf, n, 0, 
  27.752 +                                &s->aes_decrypt_key);
  27.753 +            }
  27.754 +        }
  27.755 +        nb_sectors -= n;
  27.756 +        sector_num += n;
  27.757 +        buf += n * 512;
  27.758 +    }
  27.759 +    return 0;
  27.760 +}
  27.761 +
  27.762 +static int qcow_write(BlockDriverState *bs, int64_t sector_num, 
  27.763 +                     const uint8_t *buf, int nb_sectors)
  27.764 +{
  27.765 +    BDRVQcowState *s = bs->opaque;
  27.766 +    int ret, index_in_cluster, n;
  27.767 +    uint64_t cluster_offset;
  27.768 +    
  27.769 +    while (nb_sectors > 0) {
  27.770 +        index_in_cluster = sector_num & (s->cluster_sectors - 1);
  27.771 +        n = s->cluster_sectors - index_in_cluster;
  27.772 +        if (n > nb_sectors)
  27.773 +            n = nb_sectors;
  27.774 +        cluster_offset = get_cluster_offset(bs, sector_num << 9, 1, 0, 
  27.775 +                                            index_in_cluster, 
  27.776 +                                            index_in_cluster + n);
  27.777 +        if (!cluster_offset)
  27.778 +            return -1;
  27.779 +        if (s->crypt_method) {
  27.780 +            encrypt_sectors(s, sector_num, s->cluster_data, buf, n, 1,
  27.781 +                            &s->aes_encrypt_key);
  27.782 +            ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512, 
  27.783 +                              s->cluster_data, n * 512);
  27.784 +        } else {
  27.785 +            ret = bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512);
  27.786 +        }
  27.787 +        if (ret != n * 512) 
  27.788 +            return -1;
  27.789 +        nb_sectors -= n;
  27.790 +        sector_num += n;
  27.791 +        buf += n * 512;
  27.792 +    }
  27.793 +    s->cluster_cache_offset = -1; /* disable compressed cache */
  27.794 +    return 0;
  27.795 +}
  27.796 +
  27.797 +typedef struct QCowAIOCB {
  27.798 +    BlockDriverAIOCB common;
  27.799 +    int64_t sector_num;
  27.800 +    uint8_t *buf;
  27.801 +    int nb_sectors;
  27.802 +    int n;
  27.803 +    uint64_t cluster_offset;
  27.804 +    uint8_t *cluster_data; 
  27.805 +    BlockDriverAIOCB *hd_aiocb;
  27.806 +} QCowAIOCB;
  27.807 +
  27.808 +static void qcow_aio_read_cb(void *opaque, int ret)
  27.809 +{
  27.810 +    QCowAIOCB *acb = opaque;
  27.811 +    BlockDriverState *bs = acb->common.bs;
  27.812 +    BDRVQcowState *s = bs->opaque;
  27.813 +    int index_in_cluster, n1;
  27.814 +
  27.815 +    acb->hd_aiocb = NULL;
  27.816 +    if (ret < 0) {
  27.817 +    fail:
  27.818 +        acb->common.cb(acb->common.opaque, ret);
  27.819 +        qemu_aio_release(acb);
  27.820 +        return;
  27.821 +    }
  27.822 +
  27.823 + redo:
  27.824 +    /* post process the read buffer */
  27.825 +    if (!acb->cluster_offset) {
  27.826 +        /* nothing to do */
  27.827 +    } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
  27.828 +        /* nothing to do */
  27.829 +    } else {
  27.830 +        if (s->crypt_method) {
  27.831 +            encrypt_sectors(s, acb->sector_num, acb->buf, acb->buf, 
  27.832 +                            acb->n, 0, 
  27.833 +                            &s->aes_decrypt_key);
  27.834 +        }
  27.835 +    }
  27.836 +
  27.837 +    acb->nb_sectors -= acb->n;
  27.838 +    acb->sector_num += acb->n;
  27.839 +    acb->buf += acb->n * 512;
  27.840 +
  27.841 +    if (acb->nb_sectors == 0) {
  27.842 +        /* request completed */
  27.843 +        acb->common.cb(acb->common.opaque, 0);
  27.844 +        qemu_aio_release(acb);
  27.845 +        return;
  27.846 +    }
  27.847 +    
  27.848 +    /* prepare next AIO request */
  27.849 +    acb->cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, 
  27.850 +                                             0, 0, 0, 0);
  27.851 +    index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
  27.852 +    acb->n = s->cluster_sectors - index_in_cluster;
  27.853 +    if (acb->n > acb->nb_sectors)
  27.854 +        acb->n = acb->nb_sectors;
  27.855 +
  27.856 +    if (!acb->cluster_offset) {
  27.857 +        if (bs->backing_hd) {
  27.858 +            /* read from the base image */
  27.859 +            n1 = backing_read1(bs->backing_hd, acb->sector_num, 
  27.860 +                               acb->buf, acb->n);
  27.861 +            if (n1 > 0) {
  27.862 +                acb->hd_aiocb = bdrv_aio_read(bs->backing_hd, acb->sector_num, 
  27.863 +                                    acb->buf, acb->n, qcow_aio_read_cb, acb);
  27.864 +                if (acb->hd_aiocb == NULL)
  27.865 +                    goto fail;
  27.866 +            } else {
  27.867 +                goto redo;
  27.868 +            }
  27.869 +        } else {
  27.870 +            /* Note: in this case, no need to wait */
  27.871 +            memset(acb->buf, 0, 512 * acb->n);
  27.872 +            goto redo;
  27.873 +        }
  27.874 +    } else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
  27.875 +        /* add AIO support for compressed blocks ? */
  27.876 +        if (decompress_cluster(s, acb->cluster_offset) < 0)
  27.877 +            goto fail;
  27.878 +        memcpy(acb->buf, 
  27.879 +               s->cluster_cache + index_in_cluster * 512, 512 * acb->n);
  27.880 +        goto redo;
  27.881 +    } else {
  27.882 +        if ((acb->cluster_offset & 511) != 0) {
  27.883 +            ret = -EIO;
  27.884 +            goto fail;
  27.885 +        }
  27.886 +        acb->hd_aiocb = bdrv_aio_read(s->hd,
  27.887 +                            (acb->cluster_offset >> 9) + index_in_cluster, 
  27.888 +                            acb->buf, acb->n, qcow_aio_read_cb, acb);
  27.889 +        if (acb->hd_aiocb == NULL)
  27.890 +            goto fail;
  27.891 +    }
  27.892 +}
  27.893 +
  27.894 +static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs,
  27.895 +        int64_t sector_num, uint8_t *buf, int nb_sectors,
  27.896 +        BlockDriverCompletionFunc *cb, void *opaque)
  27.897 +{
  27.898 +    QCowAIOCB *acb;
  27.899 +
  27.900 +    acb = qemu_aio_get(bs, cb, opaque);
  27.901 +    if (!acb)
  27.902 +        return NULL;
  27.903 +    acb->hd_aiocb = NULL;
  27.904 +    acb->sector_num = sector_num;
  27.905 +    acb->buf = buf;
  27.906 +    acb->nb_sectors = nb_sectors;
  27.907 +    acb->n = 0;
  27.908 +    acb->cluster_offset = 0;
  27.909 +    return acb;
  27.910 +}
  27.911 +
  27.912 +static BlockDriverAIOCB *qcow_aio_read(BlockDriverState *bs,
  27.913 +        int64_t sector_num, uint8_t *buf, int nb_sectors,
  27.914 +        BlockDriverCompletionFunc *cb, void *opaque)
  27.915 +{
  27.916 +    QCowAIOCB *acb;
  27.917 +
  27.918 +    acb = qcow_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
  27.919 +    if (!acb)
  27.920 +        return NULL;
  27.921 +
  27.922 +    qcow_aio_read_cb(acb, 0);
  27.923 +    return &acb->common;
  27.924 +}
  27.925 +
  27.926 +static void qcow_aio_write_cb(void *opaque, int ret)
  27.927 +{
  27.928 +    QCowAIOCB *acb = opaque;
  27.929 +    BlockDriverState *bs = acb->common.bs;
  27.930 +    BDRVQcowState *s = bs->opaque;
  27.931 +    int index_in_cluster;
  27.932 +    uint64_t cluster_offset;
  27.933 +    const uint8_t *src_buf;
  27.934 +
  27.935 +    acb->hd_aiocb = NULL;
  27.936 +
  27.937 +    if (ret < 0) {
  27.938 +    fail:
  27.939 +        acb->common.cb(acb->common.opaque, ret);
  27.940 +        qemu_aio_release(acb);
  27.941 +        return;
  27.942 +    }
  27.943 +
  27.944 +    acb->nb_sectors -= acb->n;
  27.945 +    acb->sector_num += acb->n;
  27.946 +    acb->buf += acb->n * 512;
  27.947 +
  27.948 +    if (acb->nb_sectors == 0) {
  27.949 +        /* request completed */
  27.950 +        acb->common.cb(acb->common.opaque, 0);
  27.951 +        qemu_aio_release(acb);
  27.952 +        return;
  27.953 +    }
  27.954 +    
  27.955 +    index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
  27.956 +    acb->n = s->cluster_sectors - index_in_cluster;
  27.957 +    if (acb->n > acb->nb_sectors)
  27.958 +        acb->n = acb->nb_sectors;
  27.959 +    cluster_offset = get_cluster_offset(bs, acb->sector_num << 9, 1, 0, 
  27.960 +                                        index_in_cluster, 
  27.961 +                                        index_in_cluster + acb->n);
  27.962 +    if (!cluster_offset || (cluster_offset & 511) != 0) {
  27.963 +        ret = -EIO;
  27.964 +        goto fail;
  27.965 +    }
  27.966 +    if (s->crypt_method) {
  27.967 +        if (!acb->cluster_data) {
  27.968 +            acb->cluster_data = qemu_mallocz(s->cluster_size);
  27.969 +            if (!acb->cluster_data) {
  27.970 +                ret = -ENOMEM;
  27.971 +                goto fail;
  27.972 +            }
  27.973 +        }
  27.974 +        encrypt_sectors(s, acb->sector_num, acb->cluster_data, acb->buf, 
  27.975 +                        acb->n, 1, &s->aes_encrypt_key);
  27.976 +        src_buf = acb->cluster_data;
  27.977 +    } else {
  27.978 +        src_buf = acb->buf;
  27.979 +    }
  27.980 +    acb->hd_aiocb = bdrv_aio_write(s->hd,
  27.981 +                                   (cluster_offset >> 9) + index_in_cluster, 
  27.982 +                                   src_buf, acb->n, 
  27.983 +                                   qcow_aio_write_cb, acb);
  27.984 +    if (acb->hd_aiocb == NULL)
  27.985 +        goto fail;
  27.986 +}
  27.987 +
  27.988 +static BlockDriverAIOCB *qcow_aio_write(BlockDriverState *bs,
  27.989 +        int64_t sector_num, const uint8_t *buf, int nb_sectors,
  27.990 +        BlockDriverCompletionFunc *cb, void *opaque)
  27.991 +{
  27.992 +    BDRVQcowState *s = bs->opaque;
  27.993 +    QCowAIOCB *acb;
  27.994 +    
  27.995 +    s->cluster_cache_offset = -1; /* disable compressed cache */
  27.996 +
  27.997 +    acb = qcow_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);
  27.998 +    if (!acb)
  27.999 +        return NULL;
 27.1000 +    
 27.1001 +    qcow_aio_write_cb(acb, 0);
 27.1002 +    return &acb->common;
 27.1003 +}
 27.1004 +
 27.1005 +static void qcow_aio_cancel(BlockDriverAIOCB *blockacb)
 27.1006 +{
 27.1007 +    QCowAIOCB *acb = (QCowAIOCB *)blockacb;
 27.1008 +    if (acb->hd_aiocb)
 27.1009 +        bdrv_aio_cancel(acb->hd_aiocb);
 27.1010 +    qemu_aio_release(acb);
 27.1011 +}
 27.1012 +
 27.1013 +static void qcow_close(BlockDriverState *bs)
 27.1014 +{
 27.1015 +    BDRVQcowState *s = bs->opaque;
 27.1016 +    qemu_free(s->l1_table);
 27.1017 +    qemu_free(s->l2_cache);
 27.1018 +    qemu_free(s->cluster_cache);
 27.1019 +    qemu_free(s->cluster_data);
 27.1020 +    refcount_close(bs);
 27.1021 +    bdrv_delete(s->hd);
 27.1022 +}
 27.1023 +
 27.1024 +/* XXX: use std qcow open function ? */
 27.1025 +typedef struct QCowCreateState {
 27.1026 +    int cluster_size;
 27.1027 +    int cluster_bits;
 27.1028 +    uint16_t *refcount_block;
 27.1029 +    uint64_t *refcount_table;
 27.1030 +    int64_t l1_table_offset;
 27.1031 +    int64_t refcount_table_offset;
 27.1032 +    int64_t refcount_block_offset;
 27.1033 +} QCowCreateState;
 27.1034 +
 27.1035 +static void create_refcount_update(QCowCreateState *s,
 27.1036 +                                   int64_t offset, int64_t size)
 27.1037 +{
 27.1038 +    int refcount;
 27.1039 +    int64_t start, last, cluster_offset;
 27.1040 +    uint16_t *p;
 27.1041 +
 27.1042 +    start = offset & ~(s->cluster_size - 1);
 27.1043 +    last = (offset + size - 1)  & ~(s->cluster_size - 1);
 27.1044 +    for(cluster_offset = start; cluster_offset <= last; 
 27.1045 +        cluster_offset += s->cluster_size) {
 27.1046 +        p = &s->refcount_block[cluster_offset >> s->cluster_bits];
 27.1047 +        refcount = be16_to_cpu(*p);
 27.1048 +        refcount++;
 27.1049 +        *p = cpu_to_be16(refcount);
 27.1050 +    }
 27.1051 +}
 27.1052 +
 27.1053 +static int qcow_create(const char *filename, int64_t total_size,
 27.1054 +                      const char *backing_file, int flags)
 27.1055 +{
 27.1056 +    int fd, header_size, backing_filename_len, l1_size, i, shift, l2_bits;
 27.1057 +    QCowHeader header;
 27.1058 +    uint64_t tmp, offset;
 27.1059 +    QCowCreateState s1, *s = &s1;
 27.1060 +    
 27.1061 +    memset(s, 0, sizeof(*s));
 27.1062 +
 27.1063 +    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
 27.1064 +    if (fd < 0)
 27.1065 +        return -1;
 27.1066 +    memset(&header, 0, sizeof(header));
 27.1067 +    header.magic = cpu_to_be32(QCOW_MAGIC);
 27.1068 +    header.version = cpu_to_be32(QCOW_VERSION);
 27.1069 +    header.size = cpu_to_be64(total_size * 512);
 27.1070 +    header_size = sizeof(header);
 27.1071 +    backing_filename_len = 0;
 27.1072 +    if (backing_file) {
 27.1073 +        header.backing_file_offset = cpu_to_be64(header_size);
 27.1074 +        backing_filename_len = strlen(backing_file);
 27.1075 +        header.backing_file_size = cpu_to_be32(backing_filename_len);
 27.1076 +        header_size += backing_filename_len;
 27.1077 +    }
 27.1078 +    s->cluster_bits = 12;  /* 4 KB clusters */
 27.1079 +    s->cluster_size = 1 << s->cluster_bits;
 27.1080 +    header.cluster_bits = cpu_to_be32(s->cluster_bits);
 27.1081 +    header_size = (header_size + 7) & ~7;
 27.1082 +    if (flags) {
 27.1083 +        header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
 27.1084 +    } else {
 27.1085 +        header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);
 27.1086 +    }
 27.1087 +    l2_bits = s->cluster_bits - 3;
 27.1088 +    shift = s->cluster_bits + l2_bits;
 27.1089 +    l1_size = (((total_size * 512) + (1LL << shift) - 1) >> shift);
 27.1090 +    offset = align_offset(header_size, s->cluster_size);
 27.1091 +    s->l1_table_offset = offset;
 27.1092 +    header.l1_table_offset = cpu_to_be64(s->l1_table_offset);
 27.1093 +    header.l1_size = cpu_to_be32(l1_size);
 27.1094 +    offset += align_offset(l1_size * sizeof(uint64_t), s->cluster_size);
 27.1095 +
 27.1096 +    s->refcount_table = qemu_mallocz(s->cluster_size);
 27.1097 +    if (!s->refcount_table)
 27.1098 +        goto fail;
 27.1099 +    s->refcount_block = qemu_mallocz(s->cluster_size);
 27.1100 +    if (!s->refcount_block)
 27.1101 +        goto fail;
 27.1102 +    
 27.1103 +    s->refcount_table_offset = offset;
 27.1104 +    header.refcount_table_offset = cpu_to_be64(offset);
 27.1105 +    header.refcount_table_clusters = cpu_to_be32(1);
 27.1106 +    offset += s->cluster_size;
 27.1107 +
 27.1108 +    s->refcount_table[0] = cpu_to_be64(offset);
 27.1109 +    s->refcount_block_offset = offset;
 27.1110 +    offset += s->cluster_size;
 27.1111 +
 27.1112 +    /* update refcounts */
 27.1113 +    create_refcount_update(s, 0, header_size);
 27.1114 +    create_refcount_update(s, s->l1_table_offset, l1_size * sizeof(uint64_t));
 27.1115 +    create_refcount_update(s, s->refcount_table_offset, s->cluster_size);
 27.1116 +    create_refcount_update(s, s->refcount_block_offset, s->cluster_size);
 27.1117 +    
 27.1118 +    /* write all the data */
 27.1119 +    write(fd, &header, sizeof(header));
 27.1120 +    if (backing_file) {
 27.1121 +        write(fd, backing_file, backing_filename_len);
 27.1122 +    }
 27.1123 +    lseek(fd, s->l1_table_offset, SEEK_SET);
 27.1124 +    tmp = 0;
 27.1125 +    for(i = 0;i < l1_size; i++) {
 27.1126 +        write(fd, &tmp, sizeof(tmp));
 27.1127 +    }
 27.1128 +    lseek(fd, s->refcount_table_offset, SEEK_SET);
 27.1129 +    write(fd, s->refcount_table, s->cluster_size);
 27.1130 +    
 27.1131 +    lseek(fd, s->refcount_block_offset, SEEK_SET);
 27.1132 +    write(fd, s->refcount_block, s->cluster_size);
 27.1133 +
 27.1134 +    qemu_free(s->refcount_table);
 27.1135 +    qemu_free(s->refcount_block);
 27.1136 +    close(fd);
 27.1137 +    return 0;
 27.1138 + fail:
 27.1139 +    qemu_free(s->refcount_table);
 27.1140 +    qemu_free(s->refcount_block);
 27.1141 +    close(fd);
 27.1142 +    return -ENOMEM;
 27.1143 +}
 27.1144 +
 27.1145 +static int qcow_make_empty(BlockDriverState *bs)
 27.1146 +{
 27.1147 +#if 0
 27.1148 +    /* XXX: not correct */
 27.1149 +    BDRVQcowState *s = bs->opaque;
 27.1150 +    uint32_t l1_length = s->l1_size * sizeof(uint64_t);
 27.1151 +    int ret;
 27.1152 +
 27.1153 +    memset(s->l1_table, 0, l1_length);
 27.1154 +    if (bdrv_pwrite(s->hd, s->l1_table_offset, s->l1_table, l1_length) < 0)
 27.1155 +	return -1;
 27.1156 +    ret = bdrv_truncate(s->hd, s->l1_table_offset + l1_length);
 27.1157 +    if (ret < 0)
 27.1158 +        return ret;
 27.1159 +    
 27.1160 +    l2_cache_reset(bs);
 27.1161 +#endif
 27.1162 +    return 0;
 27.1163 +}
 27.1164 +
 27.1165 +/* XXX: put compressed sectors first, then all the cluster aligned
 27.1166 +   tables to avoid losing bytes in alignment */
 27.1167 +static int qcow_write_compressed(BlockDriverState *bs, int64_t sector_num, 
 27.1168 +                                 const uint8_t *buf, int nb_sectors)
 27.1169 +{
 27.1170 +    BDRVQcowState *s = bs->opaque;
 27.1171 +    z_stream strm;
 27.1172 +    int ret, out_len;
 27.1173 +    uint8_t *out_buf;
 27.1174 +    uint64_t cluster_offset;
 27.1175 +
 27.1176 +    if (nb_sectors == 0) {
 27.1177 +        /* align end of file to a sector boundary to ease reading with
 27.1178 +           sector based I/Os */
 27.1179 +        cluster_offset = bdrv_getlength(s->hd);
 27.1180 +        cluster_offset = (cluster_offset + 511) & ~511;
 27.1181 +        bdrv_truncate(s->hd, cluster_offset);
 27.1182 +        return 0;
 27.1183 +    }
 27.1184 +
 27.1185 +    if (nb_sectors != s->cluster_sectors)
 27.1186 +        return -EINVAL;
 27.1187 +
 27.1188 +    out_buf = qemu_malloc(s->cluster_size + (s->cluster_size / 1000) + 128);
 27.1189 +    if (!out_buf)
 27.1190 +        return -ENOMEM;
 27.1191 +
 27.1192 +    /* best compression, small window, no zlib header */
 27.1193 +    memset(&strm, 0, sizeof(strm));
 27.1194 +    ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION,
 27.1195 +                       Z_DEFLATED, -12, 
 27.1196 +                       9, Z_DEFAULT_STRATEGY);
 27.1197 +    if (ret != 0) {
 27.1198 +        qemu_free(out_buf);
 27.1199 +        return -1;
 27.1200 +    }
 27.1201 +
 27.1202 +    strm.avail_in = s->cluster_size;
 27.1203 +    strm.next_in = (uint8_t *)buf;
 27.1204 +    strm.avail_out = s->cluster_size;
 27.1205 +    strm.next_out = out_buf;
 27.1206 +
 27.1207 +    ret = deflate(&strm, Z_FINISH);
 27.1208 +    if (ret != Z_STREAM_END && ret != Z_OK) {
 27.1209 +        qemu_free(out_buf);
 27.1210 +        deflateEnd(&strm);
 27.1211 +        return -1;
 27.1212 +    }
 27.1213 +    out_len = strm.next_out - out_buf;
 27.1214 +
 27.1215 +    deflateEnd(&strm);
 27.1216 +
 27.1217 +    if (ret != Z_STREAM_END || out_len >= s->cluster_size) {
 27.1218 +        /* could not compress: write normal cluster */
 27.1219 +        qcow_write(bs, sector_num, buf, s->cluster_sectors);
 27.1220 +    } else {
 27.1221 +        cluster_offset = get_cluster_offset(bs, sector_num << 9, 2, 
 27.1222 +                                            out_len, 0, 0);
 27.1223 +        cluster_offset &= s->cluster_offset_mask;
 27.1224 +        if (bdrv_pwrite(s->hd, cluster_offset, out_buf, out_len) != out_len) {
 27.1225 +            qemu_free(out_buf);
 27.1226 +            return -1;
 27.1227 +        }
 27.1228 +    }
 27.1229 +    
 27.1230 +    qemu_free(out_buf);
 27.1231 +    return 0;
 27.1232 +}
 27.1233 +
 27.1234 +static void qcow_flush(BlockDriverState *bs)
 27.1235 +{
 27.1236 +    BDRVQcowState *s = bs->opaque;
 27.1237 +    bdrv_flush(s->hd);
 27.1238 +}
 27.1239 +
 27.1240 +static int qcow_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
 27.1241 +{
 27.1242 +    BDRVQcowState *s = bs->opaque;
 27.1243 +    bdi->cluster_size = s->cluster_size;
 27.1244 +    bdi->vm_state_offset = (int64_t)s->l1_vm_state_index << 
 27.1245 +        (s->cluster_bits + s->l2_bits);
 27.1246 +    return 0;
 27.1247 +}
 27.1248 +
 27.1249 +/*********************************************************/
 27.1250 +/* snapshot support */
 27.1251 +
 27.1252 +/* update the refcounts of snapshots and the copied flag */
 27.1253 +static int update_snapshot_refcount(BlockDriverState *bs, 
 27.1254 +                                    int64_t l1_table_offset,
 27.1255 +                                    int l1_size,
 27.1256 +                                    int addend)
 27.1257 +{
 27.1258 +    BDRVQcowState *s = bs->opaque;
 27.1259 +    uint64_t *l1_table, *l2_table, l2_offset, offset, l1_size2, l1_allocated;
 27.1260 +    int64_t old_offset, old_l2_offset;
 27.1261 +    int l2_size, i, j, l1_modified, l2_modified, nb_csectors, refcount;
 27.1262 +    
 27.1263 +    l2_cache_reset(bs);
 27.1264 +
 27.1265 +    l2_table = NULL;
 27.1266 +    l1_table = NULL;
 27.1267 +    l1_size2 = l1_size * sizeof(uint64_t);
 27.1268 +    l1_allocated = 0;
 27.1269 +    if (l1_table_offset != s->l1_table_offset) {
 27.1270 +        l1_table = qemu_malloc(l1_size2);
 27.1271 +        if (!l1_table)
 27.1272 +            goto fail;
 27.1273 +        l1_allocated = 1;
 27.1274 +        if (bdrv_pread(s->hd, l1_table_offset, 
 27.1275 +                       l1_table, l1_size2) != l1_size2)
 27.1276 +            goto fail;
 27.1277 +        for(i = 0;i < l1_size; i++)
 27.1278 +            be64_to_cpus(&l1_table[i]);
 27.1279 +    } else {
 27.1280 +        assert(l1_size == s->l1_size);
 27.1281 +        l1_table = s->l1_table;
 27.1282 +        l1_allocated = 0;
 27.1283 +    }
 27.1284 +    
 27.1285 +    l2_size = s->l2_size * sizeof(uint64_t);
 27.1286 +    l2_table = qemu_malloc(l2_size);
 27.1287 +    if (!l2_table)
 27.1288 +        goto fail;
 27.1289 +    l1_modified = 0;
 27.1290 +    for(i = 0; i < l1_size; i++) {
 27.1291 +        l2_offset = l1_table[i];
 27.1292 +        if (l2_offset) {
 27.1293 +            old_l2_offset = l2_offset;
 27.1294 +            l2_offset &= ~QCOW_OFLAG_COPIED;
 27.1295 +            l2_modified = 0;
 27.1296 +            if (bdrv_pread(s->hd, l2_offset, l2_table, l2_size) != l2_size)
 27.1297 +                goto fail;
 27.1298 +            for(j = 0; j < s->l2_size; j++) {
 27.1299 +                offset = be64_to_cpu(l2_table[j]);
 27.1300 +                if (offset != 0) {
 27.1301 +                    old_offset = offset;
 27.1302 +                    offset &= ~QCOW_OFLAG_COPIED;
 27.1303 +                    if (offset & QCOW_OFLAG_COMPRESSED) {
 27.1304 +                        nb_csectors = ((offset >> s->csize_shift) & 
 27.1305 +                                       s->csize_mask) + 1;
 27.1306 +                        if (addend != 0)
 27.1307 +                            update_refcount(bs, (offset & s->cluster_offset_mask) & ~511,
 27.1308 +                                            nb_csectors * 512, addend);
 27.1309 +                        /* compressed clusters are never modified */
 27.1310 +                        refcount = 2; 
 27.1311 +                    } else {
 27.1312 +                        if (addend != 0) {
 27.1313 +                            refcount = update_cluster_refcount(bs, offset >> s->cluster_bits, addend);
 27.1314 +                        } else {
 27.1315 +                            refcount = get_refcount(bs, offset >> s->cluster_bits);
 27.1316 +                        }
 27.1317 +                    }
 27.1318 +
 27.1319 +                    if (refcount == 1) {
 27.1320 +                        offset |= QCOW_OFLAG_COPIED;
 27.1321 +                    }
 27.1322 +                    if (offset != old_offset) {
 27.1323 +                        l2_table[j] = cpu_to_be64(offset);
 27.1324 +                        l2_modified = 1;
 27.1325 +                    }
 27.1326 +                }
 27.1327 +            }
 27.1328 +            if (l2_modified) {
 27.1329 +                if (bdrv_pwrite(s->hd, 
 27.1330 +                                l2_offset, l2_table, l2_size) != l2_size)
 27.1331 +                    goto fail;
 27.1332 +            }
 27.1333 +
 27.1334 +            if (addend != 0) {
 27.1335 +                refcount = update_cluster_refcount(bs, l2_offset >> s->cluster_bits, addend);
 27.1336 +            } else {
 27.1337 +                refcount = get_refcount(bs, l2_offset >> s->cluster_bits);
 27.1338 +            }
 27.1339 +            if (refcount == 1) {
 27.1340 +                l2_offset |= QCOW_OFLAG_COPIED;
 27.1341 +            }
 27.1342 +            if (l2_offset != old_l2_offset) {
 27.1343 +                l1_table[i] = l2_offset;
 27.1344 +                l1_modified = 1;
 27.1345 +            }
 27.1346 +        }
 27.1347 +    }
 27.1348 +    if (l1_modified) {
 27.1349 +        for(i = 0; i < l1_size; i++)
 27.1350 +            cpu_to_be64s(&l1_table[i]);
 27.1351 +        if (bdrv_pwrite(s->hd, l1_table_offset, l1_table, 
 27.1352 +                        l1_size2) != l1_size2)
 27.1353 +            goto fail;
 27.1354 +        for(i = 0; i < l1_size; i++)
 27.1355 +            be64_to_cpus(&l1_table[i]);
 27.1356 +    }
 27.1357 +    if (l1_allocated)
 27.1358 +        qemu_free(l1_table);
 27.1359 +    qemu_free(l2_table);
 27.1360 +    return 0;
 27.1361 + fail:
 27.1362 +    if (l1_allocated)
 27.1363 +        qemu_free(l1_table);
 27.1364 +    qemu_free(l2_table);
 27.1365 +    return -EIO;
 27.1366 +}
 27.1367 +
 27.1368 +static void qcow_free_snapshots(BlockDriverState *bs)
 27.1369 +{
 27.1370 +    BDRVQcowState *s = bs->opaque;
 27.1371 +    int i;
 27.1372 +
 27.1373 +    for(i = 0; i < s->nb_snapshots; i++) {
 27.1374 +        qemu_free(s->snapshots[i].name);
 27.1375 +        qemu_free(s->snapshots[i].id_str);
 27.1376 +    }
 27.1377 +    qemu_free(s->snapshots);
 27.1378 +    s->snapshots = NULL;
 27.1379 +    s->nb_snapshots = 0;
 27.1380 +}
 27.1381 +
 27.1382 +static int qcow_read_snapshots(BlockDriverState *bs)
 27.1383 +{
 27.1384 +    BDRVQcowState *s = bs->opaque;
 27.1385 +    QCowSnapshotHeader h;
 27.1386 +    QCowSnapshot *sn;
 27.1387 +    int i, id_str_size, name_size;
 27.1388 +    int64_t offset;
 27.1389 +    uint32_t extra_data_size;
 27.1390 +
 27.1391 +    offset = s->snapshots_offset;
 27.1392 +    s->snapshots = qemu_mallocz(s->nb_snapshots * sizeof(QCowSnapshot));
 27.1393 +    if (!s->snapshots)
 27.1394 +        goto fail;
 27.1395 +    for(i = 0; i < s->nb_snapshots; i++) {
 27.1396 +        offset = align_offset(offset, 8);
 27.1397 +        if (bdrv_pread(s->hd, offset, &h, sizeof(h)) != sizeof(h))
 27.1398 +            goto fail;
 27.1399 +        offset += sizeof(h);
 27.1400 +        sn = s->snapshots + i;
 27.1401 +        sn->l1_table_offset = be64_to_cpu(h.l1_table_offset);
 27.1402 +        sn->l1_size = be32_to_cpu(h.l1_size);
 27.1403 +        sn->vm_state_size = be32_to_cpu(h.vm_state_size);
 27.1404 +        sn->date_sec = be32_to_cpu(h.date_sec);
 27.1405 +        sn->date_nsec = be32_to_cpu(h.date_nsec);
 27.1406 +        sn->vm_clock_nsec = be64_to_cpu(h.vm_clock_nsec);
 27.1407 +        extra_data_size = be32_to_cpu(h.extra_data_size);
 27.1408 +
 27.1409 +        id_str_size = be16_to_cpu(h.id_str_size);
 27.1410 +        name_size = be16_to_cpu(h.name_size);
 27.1411 +
 27.1412 +        offset += extra_data_size;
 27.1413 +
 27.1414 +        sn->id_str = qemu_malloc(id_str_size + 1);
 27.1415 +        if (!sn->id_str)
 27.1416 +            goto fail;
 27.1417 +        if (bdrv_pread(s->hd, offset, sn->id_str, id_str_size) != id_str_size)
 27.1418 +            goto fail;
 27.1419 +        offset += id_str_size;
 27.1420 +        sn->id_str[id_str_size] = '\0';
 27.1421 +
 27.1422 +        sn->name = qemu_malloc(name_size + 1);
 27.1423 +        if (!sn->name)
 27.1424 +            goto fail;
 27.1425 +        if (bdrv_pread(s->hd, offset, sn->name, name_size) != name_size)
 27.1426 +            goto fail;
 27.1427 +        offset += name_size;
 27.1428 +        sn->name[name_size] = '\0';
 27.1429 +    }
 27.1430 +    s->snapshots_size = offset - s->snapshots_offset;
 27.1431 +    return 0;
 27.1432 + fail:
 27.1433 +    qcow_free_snapshots(bs);
 27.1434 +    return -1;
 27.1435 +}
 27.1436 +
 27.1437 +/* add at the end of the file a new list of snapshots */
 27.1438 +static int qcow_write_snapshots(BlockDriverState *bs)
 27.1439 +{
 27.1440 +    BDRVQcowState *s = bs->opaque;
 27.1441 +    QCowSnapshot *sn;
 27.1442 +    QCowSnapshotHeader h;
 27.1443 +    int i, name_size, id_str_size, snapshots_size;
 27.1444 +    uint64_t data64;
 27.1445 +    uint32_t data32;
 27.1446 +    int64_t offset, snapshots_offset;
 27.1447 +
 27.1448 +    /* compute the size of the snapshots */
 27.1449 +    offset = 0;
 27.1450 +    for(i = 0; i < s->nb_snapshots; i++) {
 27.1451 +        sn = s->snapshots + i;
 27.1452 +        offset = align_offset(offset, 8);
 27.1453 +        offset += sizeof(h);
 27.1454 +        offset += strlen(sn->id_str);
 27.1455 +        offset += strlen(sn->name);
 27.1456 +    }
 27.1457 +    snapshots_size = offset;
 27.1458 +
 27.1459 +    snapshots_offset = alloc_clusters(bs, snapshots_size);
 27.1460 +    offset = snapshots_offset;
 27.1461 +    
 27.1462 +    for(i = 0; i < s->nb_snapshots; i++) {
 27.1463 +        sn = s->snapshots + i;
 27.1464 +        memset(&h, 0, sizeof(h));
 27.1465 +        h.l1_table_offset = cpu_to_be64(sn->l1_table_offset);
 27.1466 +        h.l1_size = cpu_to_be32(sn->l1_size);
 27.1467 +        h.vm_state_size = cpu_to_be32(sn->vm_state_size);
 27.1468 +        h.date_sec = cpu_to_be32(sn->date_sec);
 27.1469 +        h.date_nsec = cpu_to_be32(sn->date_nsec);
 27.1470 +        h.vm_clock_nsec = cpu_to_be64(sn->vm_clock_nsec);
 27.1471 +        
 27.1472 +        id_str_size = strlen(sn->id_str);
 27.1473 +        name_size = strlen(sn->name);
 27.1474 +        h.id_str_size = cpu_to_be16(id_str_size);
 27.1475 +        h.name_size = cpu_to_be16(name_size);
 27.1476 +        offset = align_offset(offset, 8);
 27.1477 +        if (bdrv_pwrite(s->hd, offset, &h, sizeof(h)) != sizeof(h))
 27.1478 +            goto fail;
 27.1479 +        offset += sizeof(h);
 27.1480 +        if (bdrv_pwrite(s->hd, offset, sn->id_str, id_str_size) != id_str_size)
 27.1481 +            goto fail;
 27.1482 +        offset += id_str_size;
 27.1483 +        if (bdrv_pwrite(s->hd, offset, sn->name, name_size) != name_size)
 27.1484 +            goto fail;
 27.1485 +        offset += name_size;
 27.1486 +    }
 27.1487 +
 27.1488 +    /* update the various header fields */
 27.1489 +    data64 = cpu_to_be64(snapshots_offset);
 27.1490 +    if (bdrv_pwrite(s->hd, offsetof(QCowHeader, snapshots_offset),
 27.1491 +                    &data64, sizeof(data64)) != sizeof(data64))
 27.1492 +        goto fail;
 27.1493 +    data32 = cpu_to_be32(s->nb_snapshots);
 27.1494 +    if (bdrv_pwrite(s->hd, offsetof(QCowHeader, nb_snapshots),
 27.1495 +                    &data32, sizeof(data32)) != sizeof(data32))
 27.1496 +        goto fail;
 27.1497 +
 27.1498 +    /* free the old snapshot table */
 27.1499 +    free_clusters(bs, s->snapshots_offset, s->snapshots_size);
 27.1500 +    s->snapshots_offset = snapshots_offset;
 27.1501 +    s->snapshots_size = snapshots_size;
 27.1502 +    return 0;
 27.1503 + fail:
 27.1504 +    return -1;
 27.1505 +}
 27.1506 +
 27.1507 +static void find_new_snapshot_id(BlockDriverState *bs,
 27.1508 +                                 char *id_str, int id_str_size)
 27.1509 +{
 27.1510 +    BDRVQcowState *s = bs->opaque;
 27.1511 +    QCowSnapshot *sn;
 27.1512 +    int i, id, id_max = 0;
 27.1513 +
 27.1514 +    for(i = 0; i < s->nb_snapshots; i++) {
 27.1515 +        sn = s->snapshots + i;
 27.1516 +        id = strtoul(sn->id_str, NULL, 10);
 27.1517 +        if (id > id_max)
 27.1518 +            id_max = id;
 27.1519 +    }
 27.1520 +    snprintf(id_str, id_str_size, "%d", id_max + 1);
 27.1521 +}
 27.1522 +
 27.1523 +static int find_snapshot_by_id(BlockDriverState *bs, const char *id_str)
 27.1524 +{
 27.1525 +    BDRVQcowState *s = bs->opaque;
 27.1526 +    int i;
 27.1527 +
 27.1528 +    for(i = 0; i < s->nb_snapshots; i++) {
 27.1529 +        if (!strcmp(s->snapshots[i].id_str, id_str))
 27.1530 +            return i;
 27.1531 +    }
 27.1532 +    return -1;
 27.1533 +}
 27.1534 +
 27.1535 +static int find_snapshot_by_id_or_name(BlockDriverState *bs, const char *name)
 27.1536 +{
 27.1537 +    BDRVQcowState *s = bs->opaque;
 27.1538 +    int i, ret;
 27.1539 +    
 27.1540 +    ret = find_snapshot_by_id(bs, name);
 27.1541 +    if (ret >= 0)
 27.1542 +        return ret;
 27.1543 +    for(i = 0; i < s->nb_snapshots; i++) {
 27.1544 +        if (!strcmp(s->snapshots[i].name, name))
 27.1545 +            return i;
 27.1546 +    }
 27.1547 +    return -1;
 27.1548 +}
 27.1549 +
 27.1550 +/* if no id is provided, a new one is constructed */
 27.1551 +static int qcow_snapshot_create(BlockDriverState *bs, 
 27.1552 +                                QEMUSnapshotInfo *sn_info)
 27.1553 +{
 27.1554 +    BDRVQcowState *s = bs->opaque;
 27.1555 +    QCowSnapshot *snapshots1, sn1, *sn = &sn1;
 27.1556 +    int i, ret;
 27.1557 +    uint64_t *l1_table = NULL;
 27.1558 +    
 27.1559 +    memset(sn, 0, sizeof(*sn));
 27.1560 +
 27.1561 +    if (sn_info->id_str[0] == '\0') {
 27.1562 +        /* compute a new id */
 27.1563 +        find_new_snapshot_id(bs, sn_info->id_str, sizeof(sn_info->id_str));
 27.1564 +    }
 27.1565 +
 27.1566 +    /* check that the ID is unique */
 27.1567 +    if (find_snapshot_by_id(bs, sn_info->id_str) >= 0)
 27.1568 +        return -ENOENT;
 27.1569 +
 27.1570 +    sn->id_str = qemu_strdup(sn_info->id_str);
 27.1571 +    if (!sn->id_str)
 27.1572 +        goto fail;
 27.1573 +    sn->name = qemu_strdup(sn_info->name);
 27.1574 +    if (!sn->name)
 27.1575 +        goto fail;
 27.1576 +    sn->vm_state_size = sn_info->vm_state_size;
 27.1577 +    sn->date_sec = sn_info->date_sec;
 27.1578 +    sn->date_nsec = sn_info->date_nsec;
 27.1579 +    sn->vm_clock_nsec = sn_info->vm_clock_nsec;
 27.1580 +
 27.1581 +    ret = update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 1);
 27.1582 +    if (ret < 0)
 27.1583 +        goto fail;
 27.1584 +
 27.1585 +    /* create the L1 table of the snapshot */
 27.1586 +    sn->l1_table_offset = alloc_clusters(bs, s->l1_size * sizeof(uint64_t));
 27.1587 +    sn->l1_size = s->l1_size;
 27.1588 +
 27.1589 +    l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t));
 27.1590 +    if (!l1_table)
 27.1591 +        goto fail;
 27.1592 +    for(i = 0; i < s->l1_size; i++) {
 27.1593 +        l1_table[i] = cpu_to_be64(s->l1_table[i]);
 27.1594 +    }
 27.1595 +    if (bdrv_pwrite(s->hd, sn->l1_table_offset,
 27.1596 +                    l1_table, s->l1_size * sizeof(uint64_t)) != 
 27.1597 +        (s->l1_size * sizeof(uint64_t)))
 27.1598 +        goto fail;
 27.1599 +    qemu_free(l1_table);
 27.1600 +    l1_table = NULL;
 27.1601 +
 27.1602 +    snapshots1 = qemu_malloc((s->nb_snapshots + 1) * sizeof(QCowSnapshot));
 27.1603 +    if (!snapshots1)
 27.1604 +        goto fail;
 27.1605 +    memcpy(snapshots1, s->snapshots, s->nb_snapshots * sizeof(QCowSnapshot));
 27.1606 +    s->snapshots = snapshots1;
 27.1607 +    s->snapshots[s->nb_snapshots++] = *sn;
 27.1608 +
 27.1609 +    if (qcow_write_snapshots(bs) < 0)
 27.1610 +        goto fail;
 27.1611 +#ifdef DEBUG_ALLOC
 27.1612 +    check_refcounts(bs);
 27.1613 +#endif
 27.1614 +    return 0;
 27.1615 + fail:
 27.1616 +    qemu_free(sn->name);
 27.1617 +    qemu_free(l1_table);
 27.1618 +    return -1;
 27.1619 +}
 27.1620 +
 27.1621 +/* copy the snapshot 'snapshot_name' into the current disk image */
 27.1622 +static int qcow_snapshot_goto(BlockDriverState *bs, 
 27.1623 +                              const char *snapshot_id)
 27.1624 +{
 27.1625 +    BDRVQcowState *s = bs->opaque;
 27.1626 +    QCowSnapshot *sn;
 27.1627 +    int i, snapshot_index, l1_size2;
 27.1628 +
 27.1629 +    snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_id);
 27.1630 +    if (snapshot_index < 0)
 27.1631 +        return -ENOENT;
 27.1632 +    sn = &s->snapshots[snapshot_index];
 27.1633 +
 27.1634 +    if (update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, -1) < 0)
 27.1635 +        goto fail;
 27.1636 +
 27.1637 +    if (grow_l1_table(bs, sn->l1_size) < 0)
 27.1638 +        goto fail;
 27.1639 +
 27.1640 +    s->l1_size = sn->l1_size;
 27.1641 +    l1_size2 = s->l1_size * sizeof(uint64_t);
 27.1642 +    /* copy the snapshot l1 table to the current l1 table */
 27.1643 +    if (bdrv_pread(s->hd, sn->l1_table_offset, 
 27.1644 +                   s->l1_table, l1_size2) != l1_size2)
 27.1645 +        goto fail;
 27.1646 +    if (bdrv_pwrite(s->hd, s->l1_table_offset,
 27.1647 +                    s->l1_table, l1_size2) != l1_size2)
 27.1648 +        goto fail;
 27.1649 +    for(i = 0;i < s->l1_size; i++) {
 27.1650 +        be64_to_cpus(&s->l1_table[i]);
 27.1651 +    }
 27.1652 +
 27.1653 +    if (update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 1) < 0)
 27.1654 +        goto fail;
 27.1655 +
 27.1656 +#ifdef DEBUG_ALLOC
 27.1657 +    check_refcounts(bs);
 27.1658 +#endif
 27.1659 +    return 0;
 27.1660 + fail:
 27.1661 +    return -EIO;
 27.1662 +}
 27.1663 +
 27.1664 +static int qcow_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
 27.1665 +{
 27.1666 +    BDRVQcowState *s = bs->opaque;
 27.1667 +    QCowSnapshot *sn;
 27.1668 +    int snapshot_index, ret;
 27.1669 +    
 27.1670 +    snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_id);
 27.1671 +    if (snapshot_index < 0)
 27.1672 +        return -ENOENT;
 27.1673 +    sn = &s->snapshots[snapshot_index];
 27.1674 +
 27.1675 +    ret = update_snapshot_refcount(bs, sn->l1_table_offset, sn->l1_size, -1);
 27.1676 +    if (ret < 0)
 27.1677 +        return ret;
 27.1678 +    /* must update the copied flag on the current cluster offsets */
 27.1679 +    ret = update_snapshot_refcount(bs, s->l1_table_offset, s->l1_size, 0);
 27.1680 +    if (ret < 0)
 27.1681 +        return ret;
 27.1682 +    free_clusters(bs, sn->l1_table_offset, sn->l1_size * sizeof(uint64_t));
 27.1683 +
 27.1684 +    qemu_free(sn->id_str);
 27.1685 +    qemu_free(sn->name);
 27.1686 +    memmove(sn, sn + 1, (s->nb_snapshots - snapshot_index - 1) * sizeof(*sn));
 27.1687 +    s->nb_snapshots--;
 27.1688 +    ret = qcow_write_snapshots(bs);
 27.1689 +    if (ret < 0) {
 27.1690 +        /* XXX: restore snapshot if error ? */
 27.1691 +        return ret;
 27.1692 +    }
 27.1693 +#ifdef DEBUG_ALLOC
 27.1694 +    check_refcounts(bs);
 27.1695 +#endif
 27.1696 +    return 0;
 27.1697 +}
 27.1698 +
 27.1699 +static int qcow_snapshot_list(BlockDriverState *bs, 
 27.1700 +                              QEMUSnapshotInfo **psn_tab)
 27.1701 +{
 27.1702 +    BDRVQcowState *s = bs->opaque;
 27.1703 +    QEMUSnapshotInfo *sn_tab, *sn_info;
 27.1704 +    QCowSnapshot *sn;
 27.1705 +    int i;
 27.1706 +
 27.1707 +    sn_tab = qemu_mallocz(s->nb_snapshots * sizeof(QEMUSnapshotInfo));
 27.1708 +    if (!sn_tab)
 27.1709 +        goto fail;
 27.1710 +    for(i = 0; i < s->nb_snapshots; i++) {
 27.1711 +        sn_info = sn_tab + i;
 27.1712 +        sn = s->snapshots + i;
 27.1713 +        pstrcpy(sn_info->id_str, sizeof(sn_info->id_str),
 27.1714 +                sn->id_str);
 27.1715 +        pstrcpy(sn_info->name, sizeof(sn_info->name),
 27.1716 +                sn->name);
 27.1717 +        sn_info->vm_state_size = sn->vm_state_size;
 27.1718 +        sn_info->date_sec = sn->date_sec;
 27.1719 +        sn_info->date_nsec = sn->date_nsec;
 27.1720 +        sn_info->vm_clock_nsec = sn->vm_clock_nsec;
 27.1721 +    }
 27.1722 +    *psn_tab = sn_tab;
 27.1723 +    return s->nb_snapshots;
 27.1724 + fail:
 27.1725 +    qemu_free(sn_tab);
 27.1726 +    *psn_tab = NULL;
 27.1727 +    return -ENOMEM;
 27.1728 +}
 27.1729 +
 27.1730 +/*********************************************************/
 27.1731 +/* refcount handling */
 27.1732 +
 27.1733 +static int refcount_init(BlockDriverState *bs)
 27.1734 +{
 27.1735 +    BDRVQcowState *s = bs->opaque;
 27.1736 +    int ret, refcount_table_size2, i;
 27.1737 +    
 27.1738 +    s->refcount_block_cache = qemu_malloc(s->cluster_size);
 27.1739 +    if (!s->refcount_block_cache)
 27.1740 +        goto fail;
 27.1741 +    refcount_table_size2 = s->refcount_table_size * sizeof(uint64_t);
 27.1742 +    s->refcount_table = qemu_malloc(refcount_table_size2);
 27.1743 +    if (!s->refcount_table)
 27.1744 +        goto fail;
 27.1745 +    if (s->refcount_table_size > 0) {
 27.1746 +        ret = bdrv_pread(s->hd, s->refcount_table_offset,
 27.1747 +                         s->refcount_table, refcount_table_size2);
 27.1748 +        if (ret != refcount_table_size2)
 27.1749 +            goto fail;
 27.1750 +        for(i = 0; i < s->refcount_table_size; i++)
 27.1751 +            be64_to_cpus(&s->refcount_table[i]);
 27.1752 +    }
 27.1753 +    return 0;
 27.1754 + fail:
 27.1755 +    return -ENOMEM;
 27.1756 +}
 27.1757 +
 27.1758 +static void refcount_close(BlockDriverState *bs)
 27.1759 +{
 27.1760 +    BDRVQcowState *s = bs->opaque;
 27.1761 +    qemu_free(s->refcount_block_cache);
 27.1762 +    qemu_free(s->refcount_table);
 27.1763 +}
 27.1764 +
 27.1765 +
 27.1766 +static int load_refcount_block(BlockDriverState *bs, 
 27.1767 +                               int64_t refcount_block_offset)
 27.1768 +{
 27.1769 +    BDRVQcowState *s = bs->opaque;
 27.1770 +    int ret;
 27.1771 +    ret = bdrv_pread(s->hd, refcount_block_offset, s->refcount_block_cache, 
 27.1772 +                     s->cluster_size);
 27.1773 +    if (ret != s->cluster_size)
 27.1774 +        return -EIO;
 27.1775 +    s->refcount_block_cache_offset = refcount_block_offset;
 27.1776 +    return 0;
 27.1777 +}
 27.1778 +
 27.1779 +static int get_refcount(BlockDriverState *bs, int64_t cluster_index)
 27.1780 +{
 27.1781 +    BDRVQcowState *s = bs->opaque;
 27.1782 +    int refcount_table_index, block_index;
 27.1783 +    int64_t refcount_block_offset;
 27.1784 +
 27.1785 +    refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT);
 27.1786 +    if (refcount_table_index >= s->refcount_table_size)
 27.1787 +        return 0;
 27.1788 +    refcount_block_offset = s->refcount_table[refcount_table_index];
 27.1789 +    if (!refcount_block_offset)
 27.1790 +        return 0;
 27.1791 +    if (refcount_block_offset != s->refcount_block_cache_offset) {
 27.1792 +        /* better than nothing: return allocated if read error */
 27.1793 +        if (load_refcount_block(bs, refcount_block_offset) < 0)
 27.1794 +            return 1;
 27.1795 +    }
 27.1796 +    block_index = cluster_index & 
 27.1797 +        ((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1);
 27.1798 +    return be16_to_cpu(s->refcount_block_cache[block_index]);
 27.1799 +}
 27.1800 +
 27.1801 +/* return < 0 if error */
 27.1802 +static int64_t alloc_clusters_noref(BlockDriverState *bs, int64_t size)
 27.1803 +{
 27.1804 +    BDRVQcowState *s = bs->opaque;
 27.1805 +    int i, nb_clusters;
 27.1806 +
 27.1807 +    nb_clusters = (size + s->cluster_size - 1) >> s->cluster_bits;
 27.1808 +    for(;;) {
 27.1809 +        if (get_refcount(bs, s->free_cluster_index) == 0) {
 27.1810 +            s->free_cluster_index++;
 27.1811 +            for(i = 1; i < nb_clusters; i++) {
 27.1812 +                if (get_refcount(bs, s->free_cluster_index) != 0)
 27.1813 +                    goto not_found;
 27.1814 +                s->free_cluster_index++;
 27.1815 +            }
 27.1816 +#ifdef DEBUG_ALLOC2
 27.1817 +            printf("alloc_clusters: size=%lld -> %lld\n",
 27.1818 +                   size, 
 27.1819 +                   (s->free_cluster_index - nb_clusters) << s->cluster_bits);
 27.1820 +#endif
 27.1821 +            return (s->free_cluster_index - nb_clusters) << s->cluster_bits;
 27.1822 +        } else {
 27.1823 +        not_found:
 27.1824 +            s->free_cluster_index++;
 27.1825 +        }
 27.1826 +    }
 27.1827 +}
 27.1828 +
 27.1829 +static int64_t alloc_clusters(BlockDriverState *bs, int64_t size)
 27.1830 +{
 27.1831 +    int64_t offset;
 27.1832 +
 27.1833 +    offset = alloc_clusters_noref(bs, size);
 27.1834 +    update_refcount(bs, offset, size, 1);
 27.1835 +    return offset;
 27.1836 +}
 27.1837 +
 27.1838 +/* only used to allocate compressed sectors. We try to allocate
 27.1839 +   contiguous sectors. size must be <= cluster_size */
 27.1840 +static int64_t alloc_bytes(BlockDriverState *bs, int size)
 27.1841 +{
 27.1842 +    BDRVQcowState *s = bs->opaque;
 27.1843 +    int64_t offset, cluster_offset;
 27.1844 +    int free_in_cluster;
 27.1845 +    
 27.1846 +    assert(size > 0 && size <= s->cluster_size);
 27.1847 +    if (s->free_byte_offset == 0) {
 27.1848 +        s->free_byte_offset = alloc_clusters(bs, s->cluster_size);
 27.1849 +    }
 27.1850 + redo:
 27.1851 +    free_in_cluster = s->cluster_size - 
 27.1852 +        (s->free_byte_offset & (s->cluster_size - 1));
 27.1853 +    if (size <= free_in_cluster) {
 27.1854 +        /* enough space in current cluster */
 27.1855 +        offset = s->free_byte_offset;
 27.1856 +        s->free_byte_offset += size;
 27.1857 +        free_in_cluster -= size;
 27.1858 +        if (free_in_cluster == 0)
 27.1859 +            s->free_byte_offset = 0;
 27.1860 +        if ((offset & (s->cluster_size - 1)) != 0)
 27.1861 +            update_cluster_refcount(bs, offset >> s->cluster_bits, 1);
 27.1862 +    } else {
 27.1863 +        offset = alloc_clusters(bs, s->cluster_size);
 27.1864 +        cluster_offset = s->free_byte_offset & ~(s->cluster_size - 1);
 27.1865 +        if ((cluster_offset + s->cluster_size) == offset) {
 27.1866 +            /* we are lucky: contiguous data */
 27.1867 +            offset = s->free_byte_offset;
 27.1868 +            update_cluster_refcount(bs, offset >> s->cluster_bits, 1);
 27.1869 +            s->free_byte_offset += size;
 27.1870 +        } else {
 27.1871 +            s->free_byte_offset = offset;
 27.1872 +            goto redo;
 27.1873 +        }
 27.1874 +    }
 27.1875 +    return offset;
 27.1876 +}
 27.1877 +
 27.1878 +static void free_clusters(BlockDriverState *bs, 
 27.1879 +                          int64_t offset, int64_t size)
 27.1880 +{
 27.1881 +    update_refcount(bs, offset, size, -1);
 27.1882 +}
 27.1883 +
 27.1884 +static int grow_refcount_table(BlockDriverState *bs, int min_size)
 27.1885 +{
 27.1886 +    BDRVQcowState *s = bs->opaque;
 27.1887 +    int new_table_size, new_table_size2, refcount_table_clusters, i, ret;
 27.1888 +    uint64_t *new_table;
 27.1889 +    int64_t table_offset;
 27.1890 +    uint64_t data64;
 27.1891 +    uint32_t data32;
 27.1892 +
 27.1893 +    if (min_size <= s->refcount_table_size)
 27.1894 +        return 0;
 27.1895 +    /* compute new table size */
 27.1896 +    refcount_table_clusters = s->refcount_table_size >> (s->cluster_bits - 3);
 27.1897 +    for(;;) {
 27.1898 +        if (refcount_table_clusters == 0) {
 27.1899 +            refcount_table_clusters = 1;
 27.1900 +        } else {
 27.1901 +            refcount_table_clusters = (refcount_table_clusters * 3 + 1) / 2;
 27.1902 +        }
 27.1903 +        new_table_size = refcount_table_clusters << (s->cluster_bits - 3);
 27.1904 +        if (min_size <= new_table_size)
 27.1905 +            break;
 27.1906 +    }
 27.1907 +#ifdef DEBUG_ALLOC2
 27.1908 +    printf("grow_refcount_table from %d to %d\n",
 27.1909 +           s->refcount_table_size,
 27.1910 +           new_table_size);
 27.1911 +#endif
 27.1912 +    new_table_size2 = new_table_size * sizeof(uint64_t);
 27.1913 +    new_table = qemu_mallocz(new_table_size2);
 27.1914 +    if (!new_table)
 27.1915 +        return -ENOMEM;
 27.1916 +    memcpy(new_table, s->refcount_table, 
 27.1917 +           s->refcount_table_size * sizeof(uint64_t));
 27.1918 +    for(i = 0; i < s->refcount_table_size; i++)
 27.1919 +        cpu_to_be64s(&new_table[i]);
 27.1920 +    /* Note: we cannot update the refcount now to avoid recursion */
 27.1921 +    table_offset = alloc_clusters_noref(bs, new_table_size2);
 27.1922 +    ret = bdrv_pwrite(s->hd, table_offset, new_table, new_table_size2);
 27.1923 +    if (ret != new_table_size2) 
 27.1924 +        goto fail;
 27.1925 +    for(i = 0; i < s->refcount_table_size; i++)
 27.1926 +        be64_to_cpus(&new_table[i]);
 27.1927 +
 27.1928 +    data64 = cpu_to_be64(table_offset);
 27.1929 +    if (bdrv_pwrite(s->hd, offsetof(QCowHeader, refcount_table_offset),
 27.1930 +                    &data64, sizeof(data64)) != sizeof(data64))
 27.1931 +        goto fail;
 27.1932 +    data32 = cpu_to_be32(refcount_table_clusters);
 27.1933 +    if (bdrv_pwrite(s->hd, offsetof(QCowHeader, refcount_table_clusters),
 27.1934 +                    &data32, sizeof(data32)) != sizeof(data32))
 27.1935 +        goto fail;
 27.1936 +    qemu_free(s->refcount_table);
 27.1937 +    s->refcount_table = new_table;
 27.1938 +    s->refcount_table_size = new_table_size;
 27.1939 +
 27.1940 +    update_refcount(bs, table_offset, new_table_size2, 1);
 27.1941 +    return 0;
 27.1942 + fail:
 27.1943 +    free_clusters(bs, table_offset, new_table_size2);
 27.1944 +    qemu_free(new_table);
 27.1945 +    return -EIO;
 27.1946 +}
 27.1947 +
 27.1948 +/* addend must be 1 or -1 */
 27.1949 +/* XXX: cache several refcount block clusters ? */
 27.1950 +static int update_cluster_refcount(BlockDriverState *bs, 
 27.1951 +                                   int64_t cluster_index,
 27.1952 +                                   int addend)
 27.1953 +{
 27.1954 +    BDRVQcowState *s = bs->opaque;
 27.1955 +    int64_t offset, refcount_block_offset;
 27.1956 +    int ret, refcount_table_index, block_index, refcount;
 27.1957 +    uint64_t data64;
 27.1958 +
 27.1959 +    refcount_table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT);
 27.1960 +    if (refcount_table_index >= s->refcount_table_size) {
 27.1961 +        if (addend < 0)
 27.1962 +            return -EINVAL;
 27.1963 +        ret = grow_refcount_table(bs, refcount_table_index + 1);
 27.1964 +        if (ret < 0)
 27.1965 +            return ret;
 27.1966 +    }
 27.1967 +    refcount_block_offset = s->refcount_table[refcount_table_index];
 27.1968 +    if (!refcount_block_offset) {
 27.1969 +        if (addend < 0)
 27.1970 +            return -EINVAL;
 27.1971 +        /* create a new refcount block */
 27.1972 +        /* Note: we cannot update the refcount now to avoid recursion */
 27.1973 +        offset = alloc_clusters_noref(bs, s->cluster_size);
 27.1974 +        memset(s->refcount_block_cache, 0, s->cluster_size);
 27.1975 +        ret = bdrv_pwrite(s->hd, offset, s->refcount_block_cache, s->cluster_size);
 27.1976 +        if (ret != s->cluster_size)
 27.1977 +            return -EINVAL;
 27.1978 +        s->refcount_table[refcount_table_index] = offset;
 27.1979 +        data64 = cpu_to_be64(offset);
 27.1980 +        ret = bdrv_pwrite(s->hd, s->refcount_table_offset + 
 27.1981 +                          refcount_table_index * sizeof(uint64_t), 
 27.1982 +                          &data64, sizeof(data64));
 27.1983 +        if (ret != sizeof(data64))
 27.1984 +            return -EINVAL;
 27.1985 +
 27.1986 +        refcount_block_offset = offset;
 27.1987 +        s->refcount_block_cache_offset = offset;
 27.1988 +        update_refcount(bs, offset, s->cluster_size, 1);
 27.1989 +    } else {
 27.1990 +        if (refcount_block_offset != s->refcount_block_cache_offset) {
 27.1991 +            if (load_refcount_block(bs, refcount_block_offset) < 0)
 27.1992 +                return -EIO;
 27.1993 +        }
 27.1994 +    }
 27.1995 +    /* we can update the count and save it */
 27.1996 +    block_index = cluster_index & 
 27.1997 +        ((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1);
 27.1998 +    refcount = be16_to_cpu(s->refcount_block_cache[block_index]);
 27.1999 +    refcount += addend;
 27.2000 +    if (refcount < 0 || refcount > 0xffff)
 27.2001 +        return -EINVAL;
 27.2002 +    if (refcount == 0 && cluster_index < s->free_cluster_index) {
 27.2003 +        s->free_cluster_index = cluster_index;
 27.2004 +    }
 27.2005 +    s->refcount_block_cache[block_index] = cpu_to_be16(refcount);
 27.2006 +    if (bdrv_pwrite(s->hd, 
 27.2007 +                    refcount_block_offset + (block_index << REFCOUNT_SHIFT), 
 27.2008 +                    &s->refcount_block_cache[block_index], 2) != 2)
 27.2009 +        return -EIO;
 27.2010 +    return refcount;
 27.2011 +}
 27.2012 +
 27.2013 +static void update_refcount(BlockDriverState *bs, 
 27.2014 +                            int64_t offset, int64_t length, 
 27.2015 +                            int addend)
 27.2016 +{
 27.2017 +    BDRVQcowState *s = bs->opaque;
 27.2018 +    int64_t start, last, cluster_offset;
 27.2019 +
 27.2020 +#ifdef DEBUG_ALLOC2
 27.2021 +    printf("update_refcount: offset=%lld size=%lld addend=%d\n", 
 27.2022 +           offset, length, addend);
 27.2023 +#endif
 27.2024 +    if (length <= 0)
 27.2025 +        return;
 27.2026 +    start = offset & ~(s->cluster_size - 1);
 27.2027 +    last = (offset + length - 1) & ~(s->cluster_size - 1);
 27.2028 +    for(cluster_offset = start; cluster_offset <= last; 
 27.2029 +        cluster_offset += s->cluster_size) {
 27.2030 +        update_cluster_refcount(bs, cluster_offset >> s->cluster_bits, addend);
 27.2031 +    }
 27.2032 +}
 27.2033 +
 27.2034 +#ifdef DEBUG_ALLOC
 27.2035 +static void inc_refcounts(BlockDriverState *bs, 
 27.2036 +                          uint16_t *refcount_table, 
 27.2037 +                          int refcount_table_size,
 27.2038 +                          int64_t offset, int64_t size)
 27.2039 +{
 27.2040 +    BDRVQcowState *s = bs->opaque;
 27.2041 +    int64_t start, last, cluster_offset;
 27.2042 +    int k;
 27.2043 +    
 27.2044 +    if (size <= 0)
 27.2045 +        return;
 27.2046 +
 27.2047 +    start = offset & ~(s->cluster_size - 1);
 27.2048 +    last = (offset + size - 1) & ~(s->cluster_size - 1);
 27.2049 +    for(cluster_offset = start; cluster_offset <= last; 
 27.2050 +        cluster_offset += s->cluster_size) {
 27.2051 +        k = cluster_offset >> s->cluster_bits;
 27.2052 +        if (k < 0 || k >= refcount_table_size) {
 27.2053 +            printf("ERROR: invalid cluster offset=0x%llx\n", cluster_offset);
 27.2054 +        } else {
 27.2055 +            if (++refcount_table[k] == 0) {
 27.2056 +                printf("ERROR: overflow cluster offset=0x%llx\n", cluster_offset);
 27.2057 +            }
 27.2058 +        }
 27.2059 +    }
 27.2060 +}
 27.2061 +
 27.2062 +static int check_refcounts_l1(BlockDriverState *bs, 
 27.2063 +                              uint16_t *refcount_table, 
 27.2064 +                              int refcount_table_size,
 27.2065 +                              int64_t l1_table_offset, int l1_size,
 27.2066 +                              int check_copied)
 27.2067 +{
 27.2068 +    BDRVQcowState *s = bs->opaque;
 27.2069 +    uint64_t *l1_table, *l2_table, l2_offset, offset, l1_size2;
 27.2070 +    int l2_size, i, j, nb_csectors, refcount;
 27.2071 +
 27.2072 +    l2_table = NULL;
 27.2073 +    l1_size2 = l1_size * sizeof(uint64_t);
 27.2074 +
 27.2075 +    inc_refcounts(bs, refcount_table, refcount_table_size,
 27.2076 +                  l1_table_offset, l1_size2);
 27.2077 +
 27.2078 +    l1_table = qemu_malloc(l1_size2);
 27.2079 +    if (!l1_table)
 27.2080 +        goto fail;
 27.2081 +    if (bdrv_pread(s->hd, l1_table_offset, 
 27.2082 +                   l1_table, l1_size2) != l1_size2)
 27.2083 +        goto fail;
 27.2084 +    for(i = 0;i < l1_size; i++)
 27.2085 +        be64_to_cpus(&l1_table[i]);
 27.2086 +    
 27.2087 +    l2_size = s->l2_size * sizeof(uint64_t);
 27.2088 +    l2_table = qemu_malloc(l2_size);
 27.2089 +    if (!l2_table)
 27.2090 +        goto fail;
 27.2091 +    for(i = 0; i < l1_size; i++) {
 27.2092 +        l2_offset = l1_table[i];
 27.2093 +        if (l2_offset) {
 27.2094 +            if (check_copied) {
 27.2095 +                refcount = get_refcount(bs, (l2_offset & ~QCOW_OFLAG_COPIED) >> s->cluster_bits);
 27.2096 +                if ((refcount == 1) != ((l2_offset & QCOW_OFLAG_COPIED) != 0)) {
 27.2097 +                    printf("ERROR OFLAG_COPIED: l2_offset=%llx refcount=%d\n",
 27.2098 +                           l2_offset, refcount);
 27.2099 +                }
 27.2100 +            }
 27.2101 +            l2_offset &= ~QCOW_OFLAG_COPIED;
 27.2102 +            if (bdrv_pread(s->hd, l2_offset, l2_table, l2_size) != l2_size)
 27.2103 +                goto fail;
 27.2104 +            for(j = 0; j < s->l2_size; j++) {
 27.2105 +                offset = be64_to_cpu(l2_table[j]);
 27.2106 +                if (offset != 0) {
 27.2107 +                    if (offset & QCOW_OFLAG_COMPRESSED) {
 27.2108 +                        if (offset & QCOW_OFLAG_COPIED) {
 27.2109 +                            printf("ERROR: cluster %lld: copied flag must never be set for compressed clusters\n",
 27.2110 +                                   offset >> s->cluster_bits);
 27.2111 +                            offset &= ~QCOW_OFLAG_COPIED;
 27.2112 +                        }
 27.2113 +                        nb_csectors = ((offset >> s->csize_shift) & 
 27.2114 +                                       s->csize_mask) + 1;
 27.2115 +                        offset &= s->cluster_offset_mask;
 27.2116 +                        inc_refcounts(bs, refcount_table, 
 27.2117 +                                      refcount_table_size,
 27.2118 +                                      offset & ~511, nb_csectors * 512);
 27.2119 +                    } else {
 27.2120 +                        if (check_copied) {
 27.2121 +                            refcount = get_refcount(bs, (offset & ~QCOW_OFLAG_COPIED) >> s->cluster_bits);
 27.2122 +                            if ((refcount == 1) != ((offset & QCOW_OFLAG_COPIED) != 0)) {
 27.2123 +                                printf("ERROR OFLAG_COPIED: offset=%llx refcount=%d\n",
 27.2124 +                                       offset, refcount);
 27.2125 +                            }
 27.2126 +                        }
 27.2127 +                        offset &= ~QCOW_OFLAG_COPIED;
 27.2128 +                        inc_refcounts(bs, refcount_table, 
 27.2129 +                                      refcount_table_size,
 27.2130 +                                      offset, s->cluster_size);
 27.2131 +                    }
 27.2132 +                }
 27.2133 +            }
 27.2134 +            inc_refcounts(bs, refcount_table, 
 27.2135 +                          refcount_table_size,
 27.2136 +                          l2_offset,
 27.2137 +                          s->cluster_size);
 27.2138 +        }
 27.2139 +    }
 27.2140 +    qemu_free(l1_table);
 27.2141 +    qemu_free(l2_table);
 27.2142 +    return 0;
 27.2143 + fail:
 27.2144 +    printf("ERROR: I/O error in check_refcounts_l1\n");
 27.2145 +    qemu_free(l1_table);
 27.2146 +    qemu_free(l2_table);
 27.2147 +    return -EIO;
 27.2148 +}
 27.2149 +
 27.2150 +static void check_refcounts(BlockDriverState *bs)
 27.2151 +{
 27.2152 +    BDRVQcowState *s = bs->opaque;
 27.2153 +    int64_t size;
 27.2154 +    int nb_clusters, refcount1, refcount2, i;
 27.2155 +    QCowSnapshot *sn;
 27.2156 +    uint16_t *refcount_table;
 27.2157 +
 27.2158 +    size = bdrv_getlength(s->hd);
 27.2159 +    nb_clusters = (size + s->cluster_size - 1) >> s->cluster_bits;
 27.2160 +    refcount_table = qemu_mallocz(nb_clusters * sizeof(uint16_t));
 27.2161 +
 27.2162 +    /* header */
 27.2163 +    inc_refcounts(bs, refcount_table, nb_clusters,
 27.2164 +                  0, s->cluster_size);
 27.2165 +    
 27.2166 +    check_refcounts_l1(bs, refcount_table, nb_clusters,
 27.2167 +                       s->l1_table_offset, s->l1_size, 1);
 27.2168 +
 27.2169 +    /* snapshots */
 27.2170 +    for(i = 0; i < s->nb_snapshots; i++) {
 27.2171 +        sn = s->snapshots + i;
 27.2172 +        check_refcounts_l1(bs, refcount_table, nb_clusters,
 27.2173 +                           sn->l1_table_offset, sn->l1_size, 0);
 27.2174 +    }
 27.2175 +    inc_refcounts(bs, refcount_table, nb_clusters,
 27.2176 +                  s->snapshots_offset, s->snapshots_size);
 27.2177 +
 27.2178 +    /* refcount data */
 27.2179 +    inc_refcounts(bs, refcount_table, nb_clusters,
 27.2180 +                  s->refcount_table_offset, 
 27.2181 +                  s->refcount_table_size * sizeof(uint64_t));
 27.2182 +    for(i = 0; i < s->refcount_table_size; i++) {
 27.2183 +        int64_t offset;
 27.2184 +        offset = s->refcount_table[i];
 27.2185 +        if (offset != 0) {
 27.2186 +            inc_refcounts(bs, refcount_table, nb_clusters,
 27.2187 +                          offset, s->cluster_size);
 27.2188 +        }
 27.2189 +    }
 27.2190 +
 27.2191 +    /* compare ref counts */
 27.2192 +    for(i = 0; i < nb_clusters; i++) {
 27.2193 +        refcount1 = get_refcount(bs, i);
 27.2194 +        refcount2 = refcount_table[i];
 27.2195 +        if (refcount1 != refcount2)
 27.2196 +            printf("ERROR cluster %d refcount=%d reference=%d\n",
 27.2197 +                   i, refcount1, refcount2);
 27.2198 +    }
 27.2199 +
 27.2200 +    qemu_free(refcount_table);
 27.2201 +}
 27.2202 +
 27.2203 +#if 0
 27.2204 +static void dump_refcounts(BlockDriverState *bs)
 27.2205 +{
 27.2206 +    BDRVQcowState *s = bs->opaque;
 27.2207 +    int64_t nb_clusters, k, k1, size;
 27.2208 +    int refcount;
 27.2209 +
 27.2210 +    size = bdrv_getlength(s->hd);
 27.2211 +    nb_clusters = (size + s->cluster_size - 1) >> s->cluster_bits;
 27.2212 +    for(k = 0; k < nb_clusters;) {
 27.2213 +        k1 = k;
 27.2214 +        refcount = get_refcount(bs, k);
 27.2215 +        k++;
 27.2216 +        while (k < nb_clusters && get_refcount(bs, k) == refcount)
 27.2217 +            k++;
 27.2218 +        printf("%lld: refcount=%d nb=%lld\n", k, refcount, k - k1);
 27.2219 +    }
 27.2220 +}
 27.2221 +#endif
 27.2222 +#endif
 27.2223 +
 27.2224 +BlockDriver bdrv_qcow2 = {
 27.2225 +    "qcow2",
 27.2226 +    sizeof(BDRVQcowState),
 27.2227 +    qcow_probe,
 27.2228 +    qcow_open,
 27.2229 +    NULL,
 27.2230 +    NULL,
 27.2231 +    qcow_close,
 27.2232 +    qcow_create,
 27.2233 +    qcow_flush,
 27.2234 +    qcow_is_allocated,
 27.2235 +    qcow_set_key,
 27.2236 +    qcow_make_empty,
 27.2237 +
 27.2238 +    .bdrv_aio_read = qcow_aio_read,
 27.2239 +    .bdrv_aio_write = qcow_aio_write,
 27.2240 +    .bdrv_aio_cancel = qcow_aio_cancel,
 27.2241 +    .aiocb_size = sizeof(QCowAIOCB),
 27.2242 +    .bdrv_write_compressed = qcow_write_compressed,
 27.2243 +
 27.2244 +    .bdrv_snapshot_create = qcow_snapshot_create,
 27.2245 +    .bdrv_snapshot_goto = qcow_snapshot_goto,
 27.2246 +    .bdrv_snapshot_delete = qcow_snapshot_delete,
 27.2247 +    .bdrv_snapshot_list = qcow_snapshot_list,
 27.2248 +    .bdrv_get_info = qcow_get_info,
 27.2249 +};
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/tools/ioemu/block-raw.c	Wed May 16 10:59:01 2007 -0600
    28.3 @@ -0,0 +1,1353 @@
    28.4 +/*
    28.5 + * Block driver for RAW files
    28.6 + * 
    28.7 + * Copyright (c) 2006 Fabrice Bellard
    28.8 + * 
    28.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   28.10 + * of this software and associated documentation files (the "Software"), to deal
   28.11 + * in the Software without restriction, including without limitation the rights
   28.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   28.13 + * copies of the Software, and to permit persons to whom the Software is
   28.14 + * furnished to do so, subject to the following conditions:
   28.15 + *
   28.16 + * The above copyright notice and this permission notice shall be included in
   28.17 + * all copies or substantial portions of the Software.
   28.18 + *
   28.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   28.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   28.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   28.22 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   28.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   28.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   28.25 + * THE SOFTWARE.
   28.26 + */
   28.27 +#include "vl.h"
   28.28 +#include "block_int.h"
   28.29 +#include <assert.h>
   28.30 +#ifndef _WIN32
   28.31 +#include <aio.h>
   28.32 +
   28.33 +#ifndef QEMU_TOOL
   28.34 +#include "exec-all.h"
   28.35 +#endif
   28.36 +
   28.37 +#ifdef CONFIG_COCOA
   28.38 +#include <paths.h>
   28.39 +#include <sys/param.h>
   28.40 +#include <IOKit/IOKitLib.h>
   28.41 +#include <IOKit/IOBSD.h>
   28.42 +#include <IOKit/storage/IOMediaBSDClient.h>
   28.43 +#include <IOKit/storage/IOMedia.h>
   28.44 +#include <IOKit/storage/IOCDMedia.h>
   28.45 +//#include <IOKit/storage/IOCDTypes.h>
   28.46 +#include <CoreFoundation/CoreFoundation.h>
   28.47 +#endif
   28.48 +
   28.49 +#ifdef __sun__
   28.50 +#define _POSIX_PTHREAD_SEMANTICS 1
   28.51 +#include <signal.h>
   28.52 +#include <sys/dkio.h>
   28.53 +#endif
   28.54 +#ifdef __linux__
   28.55 +#include <sys/ioctl.h>
   28.56 +#include <linux/cdrom.h>
   28.57 +#include <linux/fd.h>
   28.58 +#endif
   28.59 +#ifdef __FreeBSD__
   28.60 +#include <sys/disk.h>
   28.61 +#endif
   28.62 +
   28.63 +//#define DEBUG_FLOPPY
   28.64 +
   28.65 +#define FTYPE_FILE   0
   28.66 +#define FTYPE_CD     1
   28.67 +#define FTYPE_FD     2
   28.68 +
   28.69 +/* if the FD is not accessed during that time (in ms), we try to
   28.70 +   reopen it to see if the disk has been changed */
   28.71 +#define FD_OPEN_TIMEOUT 1000
   28.72 +
   28.73 +typedef struct BDRVRawState {
   28.74 +    int fd;
   28.75 +    int type;
   28.76 +#if defined(__linux__)
   28.77 +    /* linux floppy specific */
   28.78 +    int fd_open_flags;
   28.79 +    int64_t fd_open_time;
   28.80 +    int64_t fd_error_time;
   28.81 +    int fd_got_error;
   28.82 +    int fd_media_changed;
   28.83 +#endif
   28.84 +} BDRVRawState;
   28.85 +
   28.86 +static int fd_open(BlockDriverState *bs);
   28.87 +
   28.88 +static int raw_open(BlockDriverState *bs, const char *filename, int flags)
   28.89 +{
   28.90 +    BDRVRawState *s = bs->opaque;
   28.91 +    int fd, open_flags, ret;
   28.92 +
   28.93 +    open_flags = O_BINARY;
   28.94 +    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
   28.95 +        open_flags |= O_RDWR;
   28.96 +    } else {
   28.97 +        open_flags |= O_RDONLY;
   28.98 +        bs->read_only = 1;
   28.99 +    }
  28.100 +    if (flags & BDRV_O_CREAT)
  28.101 +        open_flags |= O_CREAT | O_TRUNC;
  28.102 +
  28.103 +    s->type = FTYPE_FILE;
  28.104 +
  28.105 +    fd = open(filename, open_flags, 0644);
  28.106 +    if (fd < 0) {
  28.107 +        ret = -errno;
  28.108 +        if (ret == -EROFS)
  28.109 +            ret = -EACCES;
  28.110 +        return ret;
  28.111 +    }
  28.112 +    s->fd = fd;
  28.113 +    return 0;
  28.114 +}
  28.115 +
  28.116 +/* XXX: use host sector size if necessary with:
  28.117 +#ifdef DIOCGSECTORSIZE
  28.118 +        {
  28.119 +            unsigned int sectorsize = 512;
  28.120 +            if (!ioctl(fd, DIOCGSECTORSIZE, &sectorsize) &&
  28.121 +                sectorsize > bufsize)
  28.122 +                bufsize = sectorsize;
  28.123 +        }
  28.124 +#endif
  28.125 +#ifdef CONFIG_COCOA
  28.126 +        u_int32_t   blockSize = 512;
  28.127 +        if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
  28.128 +            bufsize = blockSize;
  28.129 +        }
  28.130 +#endif
  28.131 +*/
  28.132 +
  28.133 +static int raw_pread(BlockDriverState *bs, int64_t offset, 
  28.134 +                     uint8_t *buf, int count)
  28.135 +{
  28.136 +    BDRVRawState *s = bs->opaque;
  28.137 +    int ret;
  28.138 +    
  28.139 +    ret = fd_open(bs);
  28.140 +    if (ret < 0)
  28.141 +        return ret;
  28.142 +
  28.143 +    lseek(s->fd, offset, SEEK_SET);
  28.144 +    ret = read(s->fd, buf, count);
  28.145 +    return ret;
  28.146 +}
  28.147 +
  28.148 +static int raw_pwrite(BlockDriverState *bs, int64_t offset, 
  28.149 +                      const uint8_t *buf, int count)
  28.150 +{
  28.151 +    BDRVRawState *s = bs->opaque;
  28.152 +    int ret;
  28.153 +    
  28.154 +    ret = fd_open(bs);
  28.155 +    if (ret < 0)
  28.156 +        return ret;
  28.157 +
  28.158 +    lseek(s->fd, offset, SEEK_SET);
  28.159 +    ret = write(s->fd, buf, count);
  28.160 +    return ret;
  28.161 +}
  28.162 +
  28.163 +/***********************************************************/
  28.164 +/* Unix AIO using POSIX AIO */
  28.165 +
  28.166 +typedef struct RawAIOCB {
  28.167 +    BlockDriverAIOCB common;
  28.168 +    struct aiocb aiocb;
  28.169 +    struct RawAIOCB *next;
  28.170 +} RawAIOCB;
  28.171 +
  28.172 +static int aio_sig_num = SIGUSR2;
  28.173 +static RawAIOCB *first_aio; /* AIO issued */
  28.174 +static int aio_initialized = 0;
  28.175 +
  28.176 +static void aio_signal_handler(int signum)
  28.177 +{
  28.178 +#ifndef QEMU_TOOL
  28.179 +    CPUState *env = cpu_single_env;
  28.180 +    if (env) {
  28.181 +        /* stop the currently executing cpu because a timer occured */
  28.182 +        cpu_interrupt(env, CPU_INTERRUPT_EXIT);
  28.183 +#ifdef USE_KQEMU
  28.184 +        if (env->kqemu_enabled) {
  28.185 +            kqemu_cpu_interrupt(env);
  28.186 +        }
  28.187 +#endif
  28.188 +    }
  28.189 +#endif
  28.190 +}
  28.191 +
  28.192 +void qemu_aio_init(void)
  28.193 +{
  28.194 +    struct sigaction act;
  28.195 +
  28.196 +    aio_initialized = 1;
  28.197 +    
  28.198 +    sigfillset(&act.sa_mask);
  28.199 +    act.sa_flags = 0; /* do not restart syscalls to interrupt select() */
  28.200 +    act.sa_handler = aio_signal_handler;
  28.201 +    sigaction(aio_sig_num, &act, NULL);
  28.202 +
  28.203 +#if defined(__GLIBC__) && defined(__linux__)
  28.204 +    {
  28.205 +        /* XXX: aio thread exit seems to hang on RedHat 9 and this init
  28.206 +           seems to fix the problem. */
  28.207 +        struct aioinit ai;
  28.208 +        memset(&ai, 0, sizeof(ai));
  28.209 +        ai.aio_threads = 1;
  28.210 +        ai.aio_num = 1;
  28.211 +        ai.aio_idle_time = 365 * 100000;
  28.212 +        aio_init(&ai);
  28.213 +    }
  28.214 +#endif
  28.215 +}
  28.216 +
  28.217 +void qemu_aio_poll(void)
  28.218 +{
  28.219 +    RawAIOCB *acb, **pacb;
  28.220 +    int ret;
  28.221 +
  28.222 +    for(;;) {
  28.223 +        pacb = &first_aio;
  28.224 +        for(;;) {
  28.225 +            acb = *pacb;
  28.226 +            if (!acb)
  28.227 +                goto the_end;
  28.228 +            ret = aio_error(&acb->aiocb);
  28.229 +            if (ret == ECANCELED) {
  28.230 +                /* remove the request */
  28.231 +                *pacb = acb->next;
  28.232 +                qemu_aio_release(acb);
  28.233 +            } else if (ret != EINPROGRESS) {
  28.234 +                /* end of aio */
  28.235 +                if (ret == 0) {
  28.236 +                    ret = aio_return(&acb->aiocb);
  28.237 +                    if (ret == acb->aiocb.aio_nbytes)
  28.238 +                        ret = 0;
  28.239 +                    else
  28.240 +                        ret = -EINVAL;
  28.241 +                } else {
  28.242 +                    ret = -ret;
  28.243 +                }
  28.244 +                /* remove the request */
  28.245 +                *pacb = acb->next;
  28.246 +                /* call the callback */
  28.247 +                acb->common.cb(acb->common.opaque, ret);
  28.248 +                qemu_aio_release(acb);
  28.249 +                break;
  28.250 +            } else {
  28.251 +                pacb = &acb->next;
  28.252 +            }
  28.253 +        }
  28.254 +    }
  28.255 + the_end: ;
  28.256 +}
  28.257 +
  28.258 +/* Wait for all IO requests to complete.  */
  28.259 +void qemu_aio_flush(void)
  28.260 +{
  28.261 +    qemu_aio_wait_start();
  28.262 +    qemu_aio_poll();
  28.263 +    while (first_aio) {
  28.264 +        qemu_aio_wait();
  28.265 +    }
  28.266 +    qemu_aio_wait_end();
  28.267 +}
  28.268 +
  28.269 +/* wait until at least one AIO was handled */
  28.270 +static sigset_t wait_oset;
  28.271 +
  28.272 +void qemu_aio_wait_start(void)
  28.273 +{
  28.274 +    sigset_t set;
  28.275 +
  28.276 +    if (!aio_initialized)
  28.277 +        qemu_aio_init();
  28.278 +    sigemptyset(&set);
  28.279 +    sigaddset(&set, aio_sig_num);
  28.280 +    sigprocmask(SIG_BLOCK, &set, &wait_oset);
  28.281 +}
  28.282 +
  28.283 +void qemu_aio_wait(void)
  28.284 +{
  28.285 +    sigset_t set;
  28.286 +    int nb_sigs;
  28.287 +
  28.288 +#ifndef QEMU_TOOL
  28.289 +    if (qemu_bh_poll())
  28.290 +        return;
  28.291 +#endif
  28.292 +    sigemptyset(&set);
  28.293 +    sigaddset(&set, aio_sig_num);
  28.294 +    sigwait(&set, &nb_sigs);
  28.295 +    qemu_aio_poll();
  28.296 +}
  28.297 +
  28.298 +void qemu_aio_wait_end(void)
  28.299 +{
  28.300 +    sigprocmask(SIG_SETMASK, &wait_oset, NULL);
  28.301 +}
  28.302 +
  28.303 +static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
  28.304 +        int64_t sector_num, uint8_t *buf, int nb_sectors,
  28.305 +        BlockDriverCompletionFunc *cb, void *opaque)
  28.306 +{
  28.307 +    BDRVRawState *s = bs->opaque;
  28.308 +    RawAIOCB *acb;
  28.309 +
  28.310 +    if (fd_open(bs) < 0)
  28.311 +        return NULL;
  28.312 +
  28.313 +    acb = qemu_aio_get(bs, cb, opaque);
  28.314 +    if (!acb)
  28.315 +        return NULL;
  28.316 +    acb->aiocb.aio_fildes = s->fd;
  28.317 +    acb->aiocb.aio_sigevent.sigev_signo = aio_sig_num;
  28.318 +    acb->aiocb.aio_sigevent.sigev_notify = SIGEV_SIGNAL;
  28.319 +    acb->aiocb.aio_buf = buf;
  28.320 +    acb->aiocb.aio_nbytes = nb_sectors * 512;
  28.321 +    acb->aiocb.aio_offset = sector_num * 512;
  28.322 +    acb->next = first_aio;
  28.323 +    first_aio = acb;
  28.324 +    return acb;
  28.325 +}
  28.326 +
  28.327 +static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
  28.328 +        int64_t sector_num, uint8_t *buf, int nb_sectors,
  28.329 +        BlockDriverCompletionFunc *cb, void *opaque)
  28.330 +{
  28.331 +    RawAIOCB *acb;
  28.332 +
  28.333 +    acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
  28.334 +    if (!acb)
  28.335 +        return NULL;
  28.336 +    if (aio_read(&acb->aiocb) < 0) {
  28.337 +        qemu_aio_release(acb);
  28.338 +        return NULL;
  28.339 +    } 
  28.340 +    return &acb->common;
  28.341 +}
  28.342 +
  28.343 +static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
  28.344 +        int64_t sector_num, const uint8_t *buf, int nb_sectors,
  28.345 +        BlockDriverCompletionFunc *cb, void *opaque)
  28.346 +{
  28.347 +    RawAIOCB *acb;
  28.348 +
  28.349 +    acb = raw_aio_setup(bs, sector_num, (uint8_t*)buf, nb_sectors, cb, opaque);
  28.350 +    if (!acb)
  28.351 +        return NULL;
  28.352 +    if (aio_write(&acb->aiocb) < 0) {
  28.353 +        qemu_aio_release(acb);
  28.354 +        return NULL;
  28.355 +    } 
  28.356 +    return &acb->common;
  28.357 +}
  28.358 +
  28.359 +static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
  28.360 +{
  28.361 +    int ret;
  28.362 +    RawAIOCB *acb = (RawAIOCB *)blockacb;
  28.363 +    RawAIOCB **pacb;
  28.364 +
  28.365 +    ret = aio_cancel(acb->aiocb.aio_fildes, &acb->aiocb);
  28.366 +    if (ret == AIO_NOTCANCELED) {
  28.367 +        /* fail safe: if the aio could not be canceled, we wait for
  28.368 +           it */
  28.369 +        while (aio_error(&acb->aiocb) == EINPROGRESS);
  28.370 +    }
  28.371 +
  28.372 +    /* remove the callback from the queue */
  28.373 +    pacb = &first_aio;
  28.374 +    for(;;) {
  28.375 +        if (*pacb == NULL) {
  28.376 +            break;
  28.377 +        } else if (*pacb == acb) {
  28.378 +            *pacb = acb->next;
  28.379 +            qemu_aio_release(acb);
  28.380 +            break;
  28.381 +        }
  28.382 +        pacb = &acb->next;
  28.383 +    }
  28.384 +}
  28.385 +
  28.386 +static void raw_close(BlockDriverState *bs)
  28.387 +{
  28.388 +    BDRVRawState *s = bs->opaque;
  28.389 +    bs->total_sectors = 0;
  28.390 +    if (s->fd >= 0) {
  28.391 +        close(s->fd);
  28.392 +        s->fd = -1;
  28.393 +    }
  28.394 +}
  28.395 +
  28.396 +static int raw_truncate(BlockDriverState *bs, int64_t offset)
  28.397 +{
  28.398 +    BDRVRawState *s = bs->opaque;
  28.399 +    if (s->type != FTYPE_FILE)
  28.400 +        return -ENOTSUP;
  28.401 +    if (ftruncate(s->fd, offset) < 0)
  28.402 +        return -errno;
  28.403 +    return 0;
  28.404 +}
  28.405 +
  28.406 +static int64_t  raw_getlength(BlockDriverState *bs)
  28.407 +{
  28.408 +    BDRVRawState *s = bs->opaque;
  28.409 +    int fd = s->fd;
  28.410 +    int64_t size;
  28.411 +#ifdef _BSD
  28.412 +    struct stat sb;
  28.413 +#endif
  28.414 +#ifdef __sun__
  28.415 +    struct dk_minfo minfo;
  28.416 +    int rv;
  28.417 +#endif
  28.418 +    int ret;
  28.419 +
  28.420 +    ret = fd_open(bs);
  28.421 +    if (ret < 0)
  28.422 +        return ret;
  28.423 +
  28.424 +#ifdef _BSD
  28.425 +    if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
  28.426 +#ifdef DIOCGMEDIASIZE
  28.427 +	if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
  28.428 +#endif
  28.429 +#ifdef CONFIG_COCOA
  28.430 +        size = LONG_LONG_MAX;
  28.431 +#else
  28.432 +        size = lseek(fd, 0LL, SEEK_END);
  28.433 +#endif
  28.434 +    } else
  28.435 +#endif
  28.436 +#ifdef __sun__
  28.437 +    /*
  28.438 +     * use the DKIOCGMEDIAINFO ioctl to read the size.
  28.439 +     */
  28.440 +    rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo );
  28.441 +    if ( rv != -1 ) {
  28.442 +        size = minfo.dki_lbsize * minfo.dki_capacity;
  28.443 +    } else /* there are reports that lseek on some devices
  28.444 +              fails, but irc discussion said that contingency
  28.445 +              on contingency was overkill */
  28.446 +#endif
  28.447 +    {
  28.448 +        size = lseek(fd, 0, SEEK_END);
  28.449 +    }
  28.450 +    return size;
  28.451 +}
  28.452 +
  28.453 +static int raw_create(const char *filename, int64_t total_size,
  28.454 +                      const char *backing_file, int flags)
  28.455 +{
  28.456 +    int fd;
  28.457 +
  28.458 +    if (flags || backing_file)
  28.459 +        return -ENOTSUP;
  28.460 +
  28.461 +    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 
  28.462 +              0644);
  28.463 +    if (fd < 0)
  28.464 +        return -EIO;
  28.465 +    ftruncate(fd, total_size * 512);
  28.466 +    close(fd);
  28.467 +    return 0;
  28.468 +}
  28.469 +
  28.470 +static void raw_flush(BlockDriverState *bs)
  28.471 +{
  28.472 +    BDRVRawState *s = bs->opaque;
  28.473 +    fsync(s->fd);
  28.474 +}
  28.475 +
  28.476 +BlockDriver bdrv_raw = {
  28.477 +    "raw",
  28.478 +    sizeof(BDRVRawState),
  28.479 +    NULL, /* no probe for protocols */
  28.480 +    raw_open,
  28.481 +    NULL,
  28.482 +    NULL,
  28.483 +    raw_close,
  28.484 +    raw_create,
  28.485 +    raw_flush,
  28.486 +    
  28.487 +    .bdrv_aio_read = raw_aio_read,
  28.488 +    .bdrv_aio_write = raw_aio_write,
  28.489 +    .bdrv_aio_cancel = raw_aio_cancel,
  28.490 +    .aiocb_size = sizeof(RawAIOCB),
  28.491 +    .protocol_name = "file",
  28.492 +    .bdrv_pread = raw_pread,
  28.493 +    .bdrv_pwrite = raw_pwrite,
  28.494 +    .bdrv_truncate = raw_truncate,
  28.495 +    .bdrv_getlength = raw_getlength,
  28.496 +};
  28.497 +
  28.498 +/***********************************************/
  28.499 +/* host device */
  28.500 +
  28.501 +#ifdef CONFIG_COCOA
  28.502 +static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
  28.503 +static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
  28.504 +
  28.505 +kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
  28.506 +{
  28.507 +    kern_return_t       kernResult; 
  28.508 +    mach_port_t     masterPort;
  28.509 +    CFMutableDictionaryRef  classesToMatch;
  28.510 +
  28.511 +    kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
  28.512 +    if ( KERN_SUCCESS != kernResult ) {
  28.513 +        printf( "IOMasterPort returned %d\n", kernResult );
  28.514 +    }
  28.515 +    
  28.516 +    classesToMatch = IOServiceMatching( kIOCDMediaClass ); 
  28.517 +    if ( classesToMatch == NULL ) {
  28.518 +        printf( "IOServiceMatching returned a NULL dictionary.\n" );
  28.519 +    } else {
  28.520 +    CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
  28.521 +    }
  28.522 +    kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
  28.523 +    if ( KERN_SUCCESS != kernResult )
  28.524 +    {
  28.525 +        printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
  28.526 +    }
  28.527 +    
  28.528 +    return kernResult;
  28.529 +}
  28.530 +
  28.531 +kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
  28.532 +{
  28.533 +    io_object_t     nextMedia;
  28.534 +    kern_return_t   kernResult = KERN_FAILURE;
  28.535 +    *bsdPath = '\0';
  28.536 +    nextMedia = IOIteratorNext( mediaIterator );
  28.537 +    if ( nextMedia )
  28.538 +    {
  28.539 +        CFTypeRef   bsdPathAsCFString;
  28.540 +    bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
  28.541 +        if ( bsdPathAsCFString ) {
  28.542 +            size_t devPathLength;
  28.543 +            strcpy( bsdPath, _PATH_DEV );
  28.544 +            strcat( bsdPath, "r" );
  28.545 +            devPathLength = strlen( bsdPath );
  28.546 +            if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
  28.547 +                kernResult = KERN_SUCCESS;
  28.548 +            }
  28.549 +            CFRelease( bsdPathAsCFString );
  28.550 +        }
  28.551 +        IOObjectRelease( nextMedia );
  28.552 +    }
  28.553 +    
  28.554 +    return kernResult;
  28.555 +}
  28.556 +
  28.557 +#endif
  28.558 +
  28.559 +static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
  28.560 +{
  28.561 +    BDRVRawState *s = bs->opaque;
  28.562 +    int fd, open_flags, ret;
  28.563 +
  28.564 +#ifdef CONFIG_COCOA
  28.565 +    if (strstart(filename, "/dev/cdrom", NULL)) {
  28.566 +        kern_return_t kernResult;
  28.567 +        io_iterator_t mediaIterator;
  28.568 +        char bsdPath[ MAXPATHLEN ];
  28.569 +        int fd;
  28.570 + 
  28.571 +        kernResult = FindEjectableCDMedia( &mediaIterator );
  28.572 +        kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
  28.573 +    
  28.574 +        if ( bsdPath[ 0 ] != '\0' ) {
  28.575 +            strcat(bsdPath,"s0");
  28.576 +            /* some CDs don't have a partition 0 */
  28.577 +            fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
  28.578 +            if (fd < 0) {
  28.579 +                bsdPath[strlen(bsdPath)-1] = '1';
  28.580 +            } else {
  28.581 +                close(fd);
  28.582 +            }
  28.583 +            filename = bsdPath;
  28.584 +        }
  28.585 +        
  28.586 +        if ( mediaIterator )
  28.587 +            IOObjectRelease( mediaIterator );
  28.588 +    }
  28.589 +#endif
  28.590 +    open_flags = O_BINARY;
  28.591 +    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
  28.592 +        open_flags |= O_RDWR;
  28.593 +    } else {
  28.594 +        open_flags |= O_RDONLY;
  28.595 +        bs->read_only = 1;
  28.596 +    }
  28.597 +
  28.598 +    s->type = FTYPE_FILE;
  28.599 +#if defined(__linux__)
  28.600 +    if (strstart(filename, "/dev/cd", NULL)) {
  28.601 +        /* open will not fail even if no CD is inserted */
  28.602 +        open_flags |= O_NONBLOCK;
  28.603 +        s->type = FTYPE_CD;
  28.604 +    } else if (strstart(filename, "/dev/fd", NULL)) {
  28.605 +        s->type = FTYPE_FD;
  28.606 +        s->fd_open_flags = open_flags;
  28.607 +        /* open will not fail even if no floppy is inserted */
  28.608 +        open_flags |= O_NONBLOCK;
  28.609 +    }
  28.610 +#endif
  28.611 +    fd = open(filename, open_flags, 0644);
  28.612 +    if (fd < 0) {
  28.613 +        ret = -errno;
  28.614 +        if (ret == -EROFS)
  28.615 +            ret = -EACCES;
  28.616 +        return ret;
  28.617 +    }
  28.618 +    s->fd = fd;
  28.619 +#if defined(__linux__)
  28.620 +    /* close fd so that we can reopen it as needed */
  28.621 +    if (s->type == FTYPE_FD) {
  28.622 +        close(s->fd);
  28.623 +        s->fd = -1;
  28.624 +        s->fd_media_changed = 1;
  28.625 +    }
  28.626 +#endif
  28.627 +    return 0;
  28.628 +}
  28.629 +
  28.630 +#if defined(__linux__) && !defined(QEMU_TOOL)
  28.631 +
  28.632 +/* Note: we do not have a reliable method to detect if the floppy is
  28.633 +   present. The current method is to try to open the floppy at every
  28.634 +   I/O and to keep it opened during a few hundreds of ms. */
  28.635 +static int fd_open(BlockDriverState *bs)
  28.636 +{
  28.637 +    BDRVRawState *s = bs->opaque;
  28.638 +    int last_media_present;
  28.639 +
  28.640 +    if (s->type != FTYPE_FD)
  28.641 +        return 0;
  28.642 +    last_media_present = (s->fd >= 0);
  28.643 +    if (s->fd >= 0 && 
  28.644 +        (qemu_get_clock(rt_clock) - s->fd_open_time) >= FD_OPEN_TIMEOUT) {
  28.645 +        close(s->fd);
  28.646 +        s->fd = -1;
  28.647 +#ifdef DEBUG_FLOPPY
  28.648 +        printf("Floppy closed\n");
  28.649 +#endif
  28.650 +    }
  28.651 +    if (s->fd < 0) {
  28.652 +        if (s->fd_got_error && 
  28.653 +            (qemu_get_clock(rt_clock) - s->fd_error_time) < FD_OPEN_TIMEOUT) {
  28.654 +#ifdef DEBUG_FLOPPY
  28.655 +            printf("No floppy (open delayed)\n");
  28.656 +#endif
  28.657 +            return -EIO;
  28.658 +        }
  28.659 +        s->fd = open(bs->filename, s->fd_open_flags);
  28.660 +        if (s->fd < 0) {
  28.661 +            s->fd_error_time = qemu_get_clock(rt_clock);
  28.662 +            s->fd_got_error = 1;
  28.663 +            if (last_media_present)
  28.664 +                s->fd_media_changed = 1;
  28.665 +#ifdef DEBUG_FLOPPY
  28.666 +            printf("No floppy\n");
  28.667 +#endif
  28.668 +            return -EIO;
  28.669 +        }
  28.670 +#ifdef DEBUG_FLOPPY
  28.671 +        printf("Floppy opened\n");
  28.672 +#endif
  28.673 +    }
  28.674 +    if (!last_media_present)
  28.675 +        s->fd_media_changed = 1;
  28.676 +    s->fd_open_time = qemu_get_clock(rt_clock);
  28.677 +    s->fd_got_error = 0;
  28.678 +    return 0;
  28.679 +}
  28.680 +#else
  28.681 +static int fd_open(BlockDriverState *bs)
  28.682 +{
  28.683 +    return 0;
  28.684 +}
  28.685 +#endif
  28.686 +
  28.687 +#if defined(__linux__)
  28.688 +
  28.689 +static int raw_is_inserted(BlockDriverState *bs)
  28.690 +{
  28.691 +    BDRVRawState *s = bs->opaque;
  28.692 +    int ret;
  28.693 +
  28.694 +    switch(s->type) {
  28.695 +    case FTYPE_CD:
  28.696 +        ret = ioctl(s->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
  28.697 +        if (ret == CDS_DISC_OK)
  28.698 +            return 1;
  28.699 +        else
  28.700 +            return 0;
  28.701 +        break;
  28.702 +    case FTYPE_FD:
  28.703 +        ret = fd_open(bs);
  28.704 +        return (ret >= 0);
  28.705 +    default:
  28.706 +        return 1;
  28.707 +    }
  28.708 +}
  28.709 +
  28.710 +/* currently only used by fdc.c, but a CD version would be good too */
  28.711 +static int raw_media_changed(BlockDriverState *bs)
  28.712 +{
  28.713 +    BDRVRawState *s = bs->opaque;
  28.714 +
  28.715 +    switch(s->type) {
  28.716 +    case FTYPE_FD:
  28.717 +        {
  28.718 +            int ret;
  28.719 +            /* XXX: we do not have a true media changed indication. It
  28.720 +               does not work if the floppy is changed without trying
  28.721 +               to read it */
  28.722 +            fd_open(bs);
  28.723 +            ret = s->fd_media_changed;
  28.724 +            s->fd_media_changed = 0;
  28.725 +#ifdef DEBUG_FLOPPY
  28.726 +            printf("Floppy changed=%d\n", ret);
  28.727 +#endif
  28.728 +            return ret;
  28.729 +        }
  28.730 +    default:
  28.731 +        return -ENOTSUP;
  28.732 +    }
  28.733 +}
  28.734 +
  28.735 +static int raw_eject(BlockDriverState *bs, int eject_flag)
  28.736 +{
  28.737 +    BDRVRawState *s = bs->opaque;
  28.738 +
  28.739 +    switch(s->type) {
  28.740 +    case FTYPE_CD:
  28.741 +        if (eject_flag) {
  28.742 +            if (ioctl (s->fd, CDROMEJECT, NULL) < 0)
  28.743 +                perror("CDROMEJECT");
  28.744 +        } else {
  28.745 +            if (ioctl (s->fd, CDROMCLOSETRAY, NULL) < 0)
  28.746 +                perror("CDROMEJECT");
  28.747 +        }
  28.748 +        break;
  28.749 +    case FTYPE_FD:
  28.750 +        {
  28.751 +            int fd;
  28.752 +            if (s->fd >= 0) {
  28.753 +                close(s->fd);
  28.754 +                s->fd = -1;
  28.755 +            }
  28.756 +            fd = open(bs->filename, s->fd_open_flags | O_NONBLOCK);
  28.757 +            if (fd >= 0) {
  28.758 +                if (ioctl(fd, FDEJECT, 0) < 0)
  28.759 +                    perror("FDEJECT");
  28.760 +                close(fd);
  28.761 +            }
  28.762 +        }
  28.763 +        break;
  28.764 +    default:
  28.765 +        return -ENOTSUP;
  28.766 +    }
  28.767 +    return 0;
  28.768 +}
  28.769 +
  28.770 +static int raw_set_locked(BlockDriverState *bs, int locked)
  28.771 +{
  28.772 +    BDRVRawState *s = bs->opaque;
  28.773 +
  28.774 +    switch(s->type) {
  28.775 +    case FTYPE_CD:
  28.776 +        if (ioctl (s->fd, CDROM_LOCKDOOR, locked) < 0) {
  28.777 +            /* Note: an error can happen if the distribution automatically
  28.778 +               mounts the CD-ROM */
  28.779 +            //        perror("CDROM_LOCKDOOR");
  28.780 +        }
  28.781 +        break;
  28.782 +    default:
  28.783 +        return -ENOTSUP;
  28.784 +    }
  28.785 +    return 0;
  28.786 +}
  28.787 +
  28.788 +#else
  28.789 +
  28.790 +static int raw_is_inserted(BlockDriverState *bs)
  28.791 +{
  28.792 +    return 1;
  28.793 +}
  28.794 +
  28.795 +static int raw_media_changed(BlockDriverState *bs)
  28.796 +{
  28.797 +    return -ENOTSUP;
  28.798 +}
  28.799 +
  28.800 +static int raw_eject(BlockDriverState *bs, int eject_flag)
  28.801 +{
  28.802 +    return -ENOTSUP;
  28.803 +}
  28.804 +
  28.805 +static int raw_set_locked(BlockDriverState *bs, int locked)
  28.806 +{
  28.807 +    return -ENOTSUP;
  28.808 +}
  28.809 +
  28.810 +#endif /* !linux */
  28.811 +
  28.812 +BlockDriver bdrv_host_device = {
  28.813 +    "host_device",
  28.814 +    sizeof(BDRVRawState),
  28.815 +    NULL, /* no probe for protocols */
  28.816 +    hdev_open,
  28.817 +    NULL,
  28.818 +    NULL,
  28.819 +    raw_close,
  28.820 +    NULL,
  28.821 +    raw_flush,
  28.822 +    
  28.823 +    .bdrv_aio_read = raw_aio_read,
  28.824 +    .bdrv_aio_write = raw_aio_write,
  28.825 +    .bdrv_aio_cancel = raw_aio_cancel,
  28.826 +    .aiocb_size = sizeof(RawAIOCB),
  28.827 +    .bdrv_pread = raw_pread,
  28.828 +    .bdrv_pwrite = raw_pwrite,
  28.829 +    .bdrv_getlength = raw_getlength,
  28.830 +
  28.831 +    /* removable device support */
  28.832 +    .bdrv_is_inserted = raw_is_inserted,
  28.833 +    .bdrv_media_changed = raw_media_changed,
  28.834 +    .bdrv_eject = raw_eject,
  28.835 +    .bdrv_set_locked = raw_set_locked,
  28.836 +};
  28.837 +
  28.838 +#else /* _WIN32 */
  28.839 +
  28.840 +/* XXX: use another file ? */
  28.841 +#include <winioctl.h>
  28.842 +
  28.843 +#define FTYPE_FILE 0
  28.844 +#define FTYPE_CD     1
  28.845 +#define FTYPE_HARDDISK 2
  28.846 +
  28.847 +typedef struct BDRVRawState {
  28.848 +    HANDLE hfile;
  28.849 +    int type;
  28.850 +    char drive_path[16]; /* format: "d:\" */
  28.851 +} BDRVRawState;
  28.852 +
  28.853 +typedef struct RawAIOCB {
  28.854 +    BlockDriverAIOCB common;
  28.855 +    HANDLE hEvent;
  28.856 +    OVERLAPPED ov;
  28.857 +    int count;
  28.858 +} RawAIOCB;
  28.859 +
  28.860 +int qemu_ftruncate64(int fd, int64_t length)
  28.861 +{
  28.862 +    LARGE_INTEGER li;
  28.863 +    LONG high;
  28.864 +    HANDLE h;
  28.865 +    BOOL res;
  28.866 +
  28.867 +    if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0)
  28.868 +	return -1;
  28.869 +
  28.870 +    h = (HANDLE)_get_osfhandle(fd);
  28.871 +
  28.872 +    /* get current position, ftruncate do not change position */
  28.873 +    li.HighPart = 0;
  28.874 +    li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT);
  28.875 +    if (li.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
  28.876 +	return -1;
  28.877 +
  28.878 +    high = length >> 32;
  28.879 +    if (!SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN))
  28.880 +	return -1;
  28.881 +    res = SetEndOfFile(h);
  28.882 +
  28.883 +    /* back to old position */
  28.884 +    SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN);
  28.885 +    return res ? 0 : -1;
  28.886 +}
  28.887 +
  28.888 +static int set_sparse(int fd)
  28.889 +{
  28.890 +    DWORD returned;
  28.891 +    return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE,
  28.892 +				 NULL, 0, NULL, 0, &returned, NULL);
  28.893 +}
  28.894 +
  28.895 +static int raw_open(BlockDriverState *bs, const char *filename, int flags)
  28.896 +{
  28.897 +    BDRVRawState *s = bs->opaque;
  28.898 +    int access_flags, create_flags;
  28.899 +    DWORD overlapped;
  28.900 +
  28.901 +    s->type = FTYPE_FILE;
  28.902 +
  28.903 +    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
  28.904 +        access_flags = GENERIC_READ | GENERIC_WRITE;
  28.905 +    } else {
  28.906 +        access_flags = GENERIC_READ;
  28.907 +    }
  28.908 +    if (flags & BDRV_O_CREAT) {
  28.909 +        create_flags = CREATE_ALWAYS;
  28.910 +    } else {
  28.911 +        create_flags = OPEN_EXISTING;
  28.912 +    }
  28.913 +#ifdef QEMU_TOOL
  28.914 +    overlapped = FILE_ATTRIBUTE_NORMAL;
  28.915 +#else
  28.916 +    overlapped = FILE_FLAG_OVERLAPPED;
  28.917 +#endif
  28.918 +    s->hfile = CreateFile(filename, access_flags, 
  28.919 +                          FILE_SHARE_READ, NULL,
  28.920 +                          create_flags, overlapped, NULL);
  28.921 +    if (s->hfile == INVALID_HANDLE_VALUE) {
  28.922 +        int err = GetLastError();
  28.923 +
  28.924 +        if (err == ERROR_ACCESS_DENIED)
  28.925 +            return -EACCES;
  28.926 +        return -1;
  28.927 +    }
  28.928 +    return 0;
  28.929 +}
  28.930 +
  28.931 +static int raw_pread(BlockDriverState *bs, int64_t offset, 
  28.932 +                     uint8_t *buf, int count)
  28.933 +{
  28.934 +    BDRVRawState *s = bs->opaque;
  28.935 +    OVERLAPPED ov;
  28.936 +    DWORD ret_count;
  28.937 +    int ret;
  28.938 +    
  28.939 +    memset(&ov, 0, sizeof(ov));
  28.940 +    ov.Offset = offset;
  28.941 +    ov.OffsetHigh = offset >> 32;
  28.942 +    ret = ReadFile(s->hfile, buf, count, &ret_count, &ov);
  28.943 +    if (!ret) {
  28.944 +        ret = GetOverlappedResult(s->hfile, &ov, &ret_count, TRUE);
  28.945 +        if (!ret)
  28.946 +            return -EIO;
  28.947 +        else
  28.948 +            return ret_count;
  28.949 +    }
  28.950 +    return ret_count;
  28.951 +}
  28.952 +
  28.953 +static int raw_pwrite(BlockDriverState *bs, int64_t offset, 
  28.954 +                      const uint8_t *buf, int count)
  28.955 +{
  28.956 +    BDRVRawState *s = bs->opaque;
  28.957 +    OVERLAPPED ov;
  28.958 +    DWORD ret_count;
  28.959 +    int ret;
  28.960 +    
  28.961 +    memset(&ov, 0, sizeof(ov));
  28.962 +    ov.Offset = offset;
  28.963 +    ov.OffsetHigh = offset >> 32;
  28.964 +    ret = WriteFile(s->hfile, buf, count, &ret_count, &ov);
  28.965 +    if (!ret) {
  28.966 +        ret = GetOverlappedResult(s->hfile, &ov, &ret_count, TRUE);
  28.967 +        if (!ret)
  28.968 +            return -EIO;
  28.969 +        else
  28.970 +            return ret_count;
  28.971 +    }
  28.972 +    return ret_count;
  28.973 +}
  28.974 +
  28.975 +#if 0
  28.976 +#ifndef QEMU_TOOL
  28.977 +static void raw_aio_cb(void *opaque)
  28.978 +{
  28.979 +    RawAIOCB *acb = opaque;
  28.980 +    BlockDriverState *bs = acb->common.bs;
  28.981 +    BDRVRawState *s = bs->opaque;
  28.982 +    DWORD ret_count;
  28.983 +    int ret;
  28.984 +
  28.985 +    ret = GetOverlappedResult(s->hfile, &acb->ov, &ret_count, TRUE);
  28.986 +    if (!ret || ret_count != acb->count) {
  28.987 +        acb->common.cb(acb->common.opaque, -EIO);
  28.988 +    } else {
  28.989 +        acb->common.cb(acb->common.opaque, 0);
  28.990 +    }
  28.991 +}
  28.992 +#endif
  28.993 +
  28.994 +static RawAIOCB *raw_aio_setup(BlockDriverState *bs,
  28.995 +        int64_t sector_num, uint8_t *buf, int nb_sectors,
  28.996 +        BlockDriverCompletionFunc *cb, void *opaque)
  28.997 +{
  28.998 +    RawAIOCB *acb;
  28.999 +    int64_t offset;
 28.1000 +
 28.1001 +    acb = qemu_aio_get(bs, cb, opaque);
 28.1002 +    if (acb->hEvent) {
 28.1003 +        acb->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
 28.1004 +        if (!acb->hEvent) {
 28.1005 +            qemu_aio_release(acb);
 28.1006 +            return NULL;
 28.1007 +        }
 28.1008 +    }
 28.1009 +    memset(&acb->ov, 0, sizeof(acb->ov));
 28.1010 +    offset = sector_num * 512;
 28.1011 +    acb->ov.Offset = offset;
 28.1012 +    acb->ov.OffsetHigh = offset >> 32;
 28.1013 +    acb->ov.hEvent = acb->hEvent;
 28.1014 +    acb->count = nb_sectors * 512;
 28.1015 +#ifndef QEMU_TOOL
 28.1016 +    qemu_add_wait_object(acb->ov.hEvent, raw_aio_cb, acb);
 28.1017 +#endif
 28.1018 +    return acb;
 28.1019 +}
 28.1020 +
 28.1021 +static BlockDriverAIOCB *raw_aio_read(BlockDriverState *bs,
 28.1022 +        int64_t sector_num, uint8_t *buf, int nb_sectors,
 28.1023 +        BlockDriverCompletionFunc *cb, void *opaque)
 28.1024 +{
 28.1025 +    BDRVRawState *s = bs->opaque;
 28.1026 +    RawAIOCB *acb;
 28.1027 +    int ret;
 28.1028 +
 28.1029 +    acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
 28.1030 +    if (!acb)
 28.1031 +        return NULL;
 28.1032 +    ret = ReadFile(s->hfile, buf, acb->count, NULL, &acb->ov);
 28.1033 +    if (!ret) {
 28.1034 +        qemu_aio_release(acb);
 28.1035 +        return NULL;
 28.1036 +    }
 28.1037 +#ifdef QEMU_TOOL
 28.1038 +    qemu_aio_release(acb);
 28.1039 +#endif
 28.1040 +    return (BlockDriverAIOCB *)acb;
 28.1041 +}
 28.1042 +
 28.1043 +static BlockDriverAIOCB *raw_aio_write(BlockDriverState *bs,
 28.1044 +        int64_t sector_num, uint8_t *buf, int nb_sectors,
 28.1045 +        BlockDriverCompletionFunc *cb, void *opaque)
 28.1046 +{
 28.1047 +    BDRVRawState *s = bs->opaque;
 28.1048 +    RawAIOCB *acb;
 28.1049 +    int ret;
 28.1050 +
 28.1051 +    acb = raw_aio_setup(bs, sector_num, buf, nb_sectors, cb, opaque);
 28.1052 +    if (!acb)
 28.1053 +        return NULL;
 28.1054 +    ret = WriteFile(s->hfile, buf, acb->count, NULL, &acb->ov);
 28.1055 +    if (!ret) {
 28.1056 +        qemu_aio_release(acb);
 28.1057 +        return NULL;
 28.1058 +    }
 28.1059 +#ifdef QEMU_TOOL
 28.1060 +    qemu_aio_release(acb);
 28.1061 +#endif
 28.1062 +    return (BlockDriverAIOCB *)acb;
 28.1063 +}
 28.1064 +
 28.1065 +static void raw_aio_cancel(BlockDriverAIOCB *blockacb)
 28.1066 +{
 28.1067 +#ifndef QEMU_TOOL
 28.1068 +    RawAIOCB *acb = (RawAIOCB *)blockacb;
 28.1069 +    BlockDriverState *bs = acb->common.bs;
 28.1070 +    BDRVRawState *s = bs->opaque;
 28.1071 +
 28.1072 +    qemu_del_wait_object(acb->ov.hEvent, raw_aio_cb, acb);
 28.1073 +    /* XXX: if more than one async I/O it is not correct */
 28.1074 +    CancelIo(s->hfile);
 28.1075 +    qemu_aio_release(acb);
 28.1076 +#endif
 28.1077 +}
 28.1078 +#endif /* #if 0 */
 28.1079 +
 28.1080 +static void raw_flush(BlockDriverState *bs)
 28.1081 +{
 28.1082 +    BDRVRawState *s = bs->opaque;
 28.1083 +    FlushFileBuffers(s->hfile);
 28.1084 +}
 28.1085 +
 28.1086 +static void raw_close(BlockDriverState *bs)
 28.1087 +{
 28.1088 +    BDRVRawState *s = bs->opaque;
 28.1089 +    CloseHandle(s->hfile);
 28.1090 +}
 28.1091 +
 28.1092 +static int raw_truncate(BlockDriverState *bs, int64_t offset)
 28.1093 +{
 28.1094 +    BDRVRawState *s = bs->opaque;
 28.1095 +    DWORD low, high;
 28.1096 +
 28.1097 +    low = offset;
 28.1098 +    high = offset >> 32;
 28.1099 +    if (!SetFilePointer(s->hfile, low, &high, FILE_BEGIN))
 28.1100 +	return -EIO;
 28.1101 +    if (!SetEndOfFile(s->hfile))
 28.1102 +        return -EIO;
 28.1103 +    return 0;
 28.1104 +}
 28.1105 +
 28.1106 +static int64_t raw_getlength(BlockDriverState *bs)
 28.1107 +{
 28.1108 +    BDRVRawState *s = bs->opaque;
 28.1109 +    LARGE_INTEGER l;
 28.1110 +    ULARGE_INTEGER available, total, total_free; 
 28.1111 +    DISK_GEOMETRY dg;
 28.1112 +    DWORD count;
 28.1113 +    BOOL status;
 28.1114 +
 28.1115 +    switch(s->type) {
 28.1116 +    case FTYPE_FILE:
 28.1117 +        l.LowPart = GetFileSize(s->hfile, &l.HighPart);
 28.1118 +        if (l.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
 28.1119 +            return -EIO;
 28.1120 +        break;
 28.1121 +    case FTYPE_CD:
 28.1122 +        if (!GetDiskFreeSpaceEx(s->drive_path, &available, &total, &total_free))
 28.1123 +            return -EIO;
 28.1124 +        l.QuadPart = total.QuadPart;
 28.1125 +        break;
 28.1126 +    case FTYPE_HARDDISK:
 28.1127 +        status = DeviceIoControl(s->hfile, IOCTL_DISK_GET_DRIVE_GEOMETRY,
 28.1128 +                                 NULL, 0, &dg, sizeof(dg), &count, NULL);
 28.1129 +        if (status != FALSE) {
 28.1130 +            l.QuadPart = dg.Cylinders.QuadPart * dg.TracksPerCylinder
 28.1131 +                * dg.SectorsPerTrack * dg.BytesPerSector;
 28.1132 +        }
 28.1133 +        break;
 28.1134 +    default:
 28.1135 +        return -EIO;
 28.1136 +    }
 28.1137 +    return l.QuadPart;
 28.1138 +}
 28.1139 +
 28.1140 +static int raw_create(const char *filename, int64_t total_size,
 28.1141 +                      const char *backing_file, int flags)
 28.1142 +{
 28.1143 +    int fd;
 28.1144 +
 28.1145 +    if (flags || backing_file)
 28.1146 +        return -ENOTSUP;
 28.1147 +
 28.1148 +    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 
 28.1149 +              0644);
 28.1150 +    if (fd < 0)
 28.1151 +        return -EIO;
 28.1152 +    set_sparse(fd);
 28.1153 +    ftruncate(fd, total_size * 512);
 28.1154 +    close(fd);
 28.1155 +    return 0;
 28.1156 +}
 28.1157 +
 28.1158 +void qemu_aio_init(void)
 28.1159 +{
 28.1160 +}
 28.1161 +
 28.1162 +void qemu_aio_poll(void)
 28.1163 +{
 28.1164 +}
 28.1165 +
 28.1166 +void qemu_aio_flush(void)
 28.1167 +{
 28.1168 +}
 28.1169 +
 28.1170 +void qemu_aio_wait_start(void)
 28.1171 +{
 28.1172 +}
 28.1173 +
 28.1174 +void qemu_aio_wait(void)
 28.1175 +{
 28.1176 +#ifndef QEMU_TOOL
 28.1177 +    qemu_bh_poll();
 28.1178 +#endif
 28.1179 +}
 28.1180 +
 28.1181 +void qemu_aio_wait_end(void)
 28.1182 +{
 28.1183 +}
 28.1184 +
 28.1185 +BlockDriver bdrv_raw = {
 28.1186 +    "raw",
 28.1187 +    sizeof(BDRVRawState),
 28.1188 +    NULL, /* no probe for protocols */
 28.1189 +    raw_open,
 28.1190 +    NULL,
 28.1191 +    NULL,
 28.1192 +    raw_close,
 28.1193 +    raw_create,
 28.1194 +    raw_flush,
 28.1195 +    
 28.1196 +#if 0
 28.1197 +    .bdrv_aio_read = raw_aio_read,
 28.1198 +    .bdrv_aio_write = raw_aio_write,
 28.1199 +    .bdrv_aio_cancel = raw_aio_cancel,
 28.1200 +    .aiocb_size = sizeof(RawAIOCB);
 28.1201 +#endif
 28.1202 +    .protocol_name = "file",
 28.1203 +    .bdrv_pread = raw_pread,
 28.1204 +    .bdrv_pwrite = raw_pwrite,
 28.1205 +    .bdrv_truncate = raw_truncate,
 28.1206 +    .bdrv_getlength = raw_getlength,
 28.1207 +};
 28.1208 +
 28.1209 +/***********************************************/
 28.1210 +/* host device */
 28.1211 +
 28.1212 +static int find_cdrom(char *cdrom_name, int cdrom_name_size)
 28.1213 +{
 28.1214 +    char drives[256], *pdrv = drives;
 28.1215 +    UINT type;
 28.1216 +
 28.1217 +    memset(drives, 0, sizeof(drives));
 28.1218 +    GetLogicalDriveStrings(sizeof(drives), drives);
 28.1219 +    while(pdrv[0] != '\0') {
 28.1220 +        type = GetDriveType(pdrv);
 28.1221 +        switch(type) {
 28.1222 +        case DRIVE_CDROM:
 28.1223 +            snprintf(cdrom_name, cdrom_name_size, "\\\\.\\%c:", pdrv[0]);
 28.1224 +            return 0;
 28.1225 +            break;
 28.1226 +        }
 28.1227 +        pdrv += lstrlen(pdrv) + 1;
 28.1228 +    }
 28.1229 +    return -1;
 28.1230 +}
 28.1231 +
 28.1232 +static int find_device_type(BlockDriverState *bs, const char *filename)
 28.1233 +{
 28.1234 +    BDRVRawState *s = bs->opaque;
 28.1235 +    UINT type;
 28.1236 +    const char *p;
 28.1237 +
 28.1238 +    if (strstart(filename, "\\\\.\\", &p) ||
 28.1239 +        strstart(filename, "//./", &p)) {
 28.1240 +        if (stristart(p, "PhysicalDrive", NULL))
 28.1241 +            return FTYPE_HARDDISK;
 28.1242 +        snprintf(s->drive_path, sizeof(s->drive_path), "%c:\\", p[0]);
 28.1243 +        type = GetDriveType(s->drive_path);
 28.1244 +        if (type == DRIVE_CDROM)
 28.1245 +            return FTYPE_CD;
 28.1246 +        else
 28.1247 +            return FTYPE_FILE;
 28.1248 +    } else {
 28.1249 +        return FTYPE_FILE;
 28.1250 +    }
 28.1251 +}
 28.1252 +
 28.1253 +static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
 28.1254 +{
 28.1255 +    BDRVRawState *s = bs->opaque;
 28.1256 +    int access_flags, create_flags;
 28.1257 +    DWORD overlapped;
 28.1258 +    char device_name[64];
 28.1259 +
 28.1260 +    if (strstart(filename, "/dev/cdrom", NULL)) {
 28.1261 +        if (find_cdrom(device_name, sizeof(device_name)) < 0)
 28.1262 +            return -ENOENT;
 28.1263 +        filename = device_name;
 28.1264 +    } else {
 28.1265 +        /* transform drive letters into device name */
 28.1266 +        if (((filename[0] >= 'a' && filename[0] <= 'z') ||
 28.1267 +             (filename[0] >= 'A' && filename[0] <= 'Z')) &&
 28.1268 +            filename[1] == ':' && filename[2] == '\0') {
 28.1269 +            snprintf(device_name, sizeof(device_name), "\\\\.\\%c:", filename[0]);
 28.1270 +            filename = device_name;
 28.1271 +        }
 28.1272 +    }
 28.1273 +    s->type = find_device_type(bs, filename);
 28.1274 +    
 28.1275 +    if ((flags & BDRV_O_ACCESS) == O_RDWR) {
 28.1276 +        access_flags = GENERIC_READ | GENERIC_WRITE;
 28.1277 +    } else {
 28.1278 +        access_flags = GENERIC_READ;
 28.1279 +    }
 28.1280 +    create_flags = OPEN_EXISTING;
 28.1281 +
 28.1282 +#ifdef QEMU_TOOL
 28.1283 +    overlapped = FILE_ATTRIBUTE_NORMAL;
 28.1284 +#else
 28.1285 +    overlapped = FILE_FLAG_OVERLAPPED;
 28.1286 +#endif
 28.1287 +    s->hfile = CreateFile(filename, access_flags, 
 28.1288 +                          FILE_SHARE_READ, NULL,
 28.1289 +                          create_flags, overlapped, NULL);
 28.1290 +    if (s->hfile == INVALID_HANDLE_VALUE) {
 28.1291 +        int err = GetLastError();
 28.1292 +
 28.1293 +        if (err == ERROR_ACCESS_DENIED)
 28.1294 +            return -EACCES;
 28.1295 +        return -1;
 28.1296 +    }
 28.1297 +    return 0;
 28.1298 +}
 28.1299 +
 28.1300 +#if 0
 28.1301 +/***********************************************/
 28.1302 +/* removable device additionnal commands */
 28.1303 +
 28.1304 +static int raw_is_inserted(BlockDriverState *bs)
 28.1305 +{
 28.1306 +    return 1;
 28.1307 +}
 28.1308 +
 28.1309 +static int raw_media_changed(BlockDriverState *bs)
 28.1310 +{
 28.1311 +    return -ENOTSUP;
 28.1312 +}
 28.1313 +
 28.1314 +static int raw_eject(BlockDriverState *bs, int eject_flag)
 28.1315 +{
 28.1316 +    DWORD ret_count;
 28.1317 +
 28.1318 +    if (s->type == FTYPE_FILE)
 28.1319 +        return -ENOTSUP;
 28.1320 +    if (eject_flag) {
 28.1321 +        DeviceIoControl(s->hfile, IOCTL_STORAGE_EJECT_MEDIA, 
 28.1322 +                        NULL, 0, NULL, 0, &lpBytesReturned, NULL);
 28.1323 +    } else {
 28.1324 +        DeviceIoControl(s->hfile, IOCTL_STORAGE_LOAD_MEDIA, 
 28.1325 +                        NULL, 0, NULL, 0, &lpBytesReturned, NULL);
 28.1326 +    }
 28.1327 +}
 28.1328 +
 28.1329 +static int raw_set_locked(BlockDriverState *bs, int locked)
 28.1330 +{
 28.1331 +    return -ENOTSUP;
 28.1332 +}
 28.1333 +#endif
 28.1334 +
 28.1335 +BlockDriver bdrv_host_device = {
 28.1336 +    "host_device",
 28.1337 +    sizeof(BDRVRawState),
 28.1338 +    NULL, /* no probe for protocols */
 28.1339 +    hdev_open,
 28.1340 +    NULL,
 28.1341 +    NULL,
 28.1342 +    raw_close,
 28.1343 +    NULL,
 28.1344 +    raw_flush,
 28.1345 +    
 28.1346 +#if 0
 28.1347 +    .bdrv_aio_read = raw_aio_read,
 28.1348 +    .bdrv_aio_write = raw_aio_write,
 28.1349 +    .bdrv_aio_cancel = raw_aio_cancel,
 28.1350 +    .aiocb_size = sizeof(RawAIOCB);
 28.1351 +#endif
 28.1352 +    .bdrv_pread = raw_pread,
 28.1353 +    .bdrv_pwrite = raw_pwrite,
 28.1354 +    .bdrv_getlength = raw_getlength,
 28.1355 +};
 28.1356 +#endif /* _WIN32 */
    29.1 --- a/tools/ioemu/block-vmdk.c	Wed May 16 10:42:07 2007 -0600
    29.2 +++ b/tools/ioemu/block-vmdk.c	Wed May 16 10:59:01 2007 -0600
    29.3 @@ -22,6 +22,7 @@
    29.4   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    29.5   * THE SOFTWARE.
    29.6   */
    29.7 +
    29.8  #include "vl.h"
    29.9  #include "block_int.h"
   29.10  
   29.11 @@ -59,7 +60,7 @@ typedef struct {
   29.12  #define L2_CACHE_SIZE 16
   29.13  
   29.14  typedef struct BDRVVmdkState {
   29.15 -    int fd;
   29.16 +    BlockDriverState *hd;
   29.17      int64_t l1_table_offset;
   29.18      int64_t l1_backup_table_offset;
   29.19      uint32_t *l1_table;
   29.20 @@ -73,6 +74,7 @@ typedef struct BDRVVmdkState {
   29.21      uint32_t l2_cache_counts[L2_CACHE_SIZE];
   29.22  
   29.23      unsigned int cluster_sectors;
   29.24 +    uint32_t parent_cid;
   29.25  } BDRVVmdkState;
   29.26  
   29.27  static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
   29.28 @@ -89,27 +91,278 @@ static int vmdk_probe(const uint8_t *buf
   29.29          return 0;
   29.30  }
   29.31  
   29.32 -static int vmdk_open(BlockDriverState *bs, const char *filename)
   29.33 +#define CHECK_CID 1
   29.34 +
   29.35 +#define SECTOR_SIZE 512				
   29.36 +#define DESC_SIZE 20*SECTOR_SIZE	// 20 sectors of 512 bytes each
   29.37 +#define HEADER_SIZE 512   			// first sector of 512 bytes 
   29.38 +
   29.39 +static uint32_t vmdk_read_cid(BlockDriverState *bs, int parent)
   29.40 +{
   29.41 +    BDRVVmdkState *s = bs->opaque;
   29.42 +    char desc[DESC_SIZE];
   29.43 +    uint32_t cid;
   29.44 +    char *p_name, *cid_str; 
   29.45 +    size_t cid_str_size;
   29.46 +
   29.47 +    /* the descriptor offset = 0x200 */
   29.48 +    if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
   29.49 +        return 0;
   29.50 +
   29.51 +    if (parent) {
   29.52 +        cid_str = "parentCID";
   29.53 +        cid_str_size = sizeof("parentCID");
   29.54 +    } else {
   29.55 +        cid_str = "CID";
   29.56 +        cid_str_size = sizeof("CID");
   29.57 +    }
   29.58 +
   29.59 +    if ((p_name = strstr(desc,cid_str)) != 0) {
   29.60 +        p_name += cid_str_size;
   29.61 +        sscanf(p_name,"%x",&cid);
   29.62 +    }
   29.63 +
   29.64 +    return cid;
   29.65 +}
   29.66 +
   29.67 +static int vmdk_write_cid(BlockDriverState *bs, uint32_t cid)
   29.68  {
   29.69      BDRVVmdkState *s = bs->opaque;
   29.70 -    int fd, i;
   29.71 -    uint32_t magic;
   29.72 -    int l1_size;
   29.73 +    char desc[DESC_SIZE], tmp_desc[DESC_SIZE];
   29.74 +    char *p_name, *tmp_str;
   29.75 +
   29.76 +    /* the descriptor offset = 0x200 */
   29.77 +    if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
   29.78 +        return -1;
   29.79 +
   29.80 +    tmp_str = strstr(desc,"parentCID");
   29.81 +    strcpy(tmp_desc, tmp_str);
   29.82 +    if ((p_name = strstr(desc,"CID")) != 0) {
   29.83 +        p_name += sizeof("CID");
   29.84 +        sprintf(p_name,"%x\n",cid);
   29.85 +        strcat(desc,tmp_desc);
   29.86 +    }
   29.87 +
   29.88 +    if (bdrv_pwrite(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
   29.89 +        return -1;
   29.90 +    return 0;
   29.91 +}
   29.92 +
   29.93 +static int vmdk_is_cid_valid(BlockDriverState *bs)
   29.94 +{
   29.95 +#ifdef CHECK_CID
   29.96 +    BDRVVmdkState *s = bs->opaque;
   29.97 +    BlockDriverState *p_bs = s->hd->backing_hd;
   29.98 +    uint32_t cur_pcid;
   29.99 +
  29.100 +    if (p_bs) {
  29.101 +        cur_pcid = vmdk_read_cid(p_bs,0);
  29.102 +        if (s->parent_cid != cur_pcid)
  29.103 +            // CID not valid
  29.104 +            return 0;
  29.105 +    }
  29.106 +#endif
  29.107 +    // CID valid
  29.108 +    return 1;
  29.109 +}
  29.110 +
  29.111 +static int vmdk_snapshot_create(const char *filename, const char *backing_file)
  29.112 +{
  29.113 +    int snp_fd, p_fd;
  29.114 +    uint32_t p_cid;
  29.115 +    char *p_name, *gd_buf, *rgd_buf; 
  29.116 +    const char *real_filename, *temp_str;
  29.117 +    VMDK4Header header;
  29.118 +    uint32_t gde_entries, gd_size;
  29.119 +    int64_t gd_offset, rgd_offset, capacity, gt_size;
  29.120 +    char p_desc[DESC_SIZE], s_desc[DESC_SIZE], hdr[HEADER_SIZE];
  29.121 +    char *desc_template =
  29.122 +    "# Disk DescriptorFile\n"
  29.123 +    "version=1\n"
  29.124 +    "CID=%x\n"
  29.125 +    "parentCID=%x\n"
  29.126 +    "createType=\"monolithicSparse\"\n"
  29.127 +    "parentFileNameHint=\"%s\"\n"
  29.128 +    "\n"
  29.129 +    "# Extent description\n"
  29.130 +    "RW %lu SPARSE \"%s\"\n"
  29.131 +    "\n"
  29.132 +    "# The Disk Data Base \n"
  29.133 +    "#DDB\n"
  29.134 +    "\n";
  29.135 +
  29.136 +    snp_fd = open(filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 0644);
  29.137 +    if (snp_fd < 0)
  29.138 +        return -1;
  29.139 +    p_fd = open(backing_file, O_RDONLY | O_BINARY | O_LARGEFILE);
  29.140 +    if (p_fd < 0) {
  29.141 +        close(snp_fd);
  29.142 +        return -1;
  29.143 +    }
  29.144 +
  29.145 +    /* read the header */
  29.146 +    if (lseek(p_fd, 0x0, SEEK_SET) == -1)
  29.147 +        goto fail;
  29.148 +    if (read(p_fd, hdr, HEADER_SIZE) != HEADER_SIZE)
  29.149 +        goto fail;
  29.150 +
  29.151 +    /* write the header */
  29.152 +    if (lseek(snp_fd, 0x0, SEEK_SET) == -1)
  29.153 +        goto fail;
  29.154 +    if (write(snp_fd, hdr, HEADER_SIZE) == -1)
  29.155 +        goto fail;
  29.156 +
  29.157 +    memset(&header, 0, sizeof(header));
  29.158 +    memcpy(&header,&hdr[4], sizeof(header)); // skip the VMDK4_MAGIC
  29.159 +
  29.160 +    ftruncate(snp_fd, header.grain_offset << 9);
  29.161 +    /* the descriptor offset = 0x200 */
  29.162 +    if (lseek(p_fd, 0x200, SEEK_SET) == -1)
  29.163 +        goto fail;
  29.164 +    if (read(p_fd, p_desc, DESC_SIZE) != DESC_SIZE)
  29.165 +        goto fail;
  29.166 +
  29.167 +    if ((p_name = strstr(p_desc,"CID")) != 0) {
  29.168 +        p_name += sizeof("CID");
  29.169 +        sscanf(p_name,"%x",&p_cid);
  29.170 +    }
  29.171 +
  29.172 +    real_filename = filename;
  29.173 +    if ((temp_str = strrchr(real_filename, '\\')) != NULL)
  29.174 +        real_filename = temp_str + 1;
  29.175 +    if ((temp_str = strrchr(real_filename, '/')) != NULL)
  29.176 +        real_filename = temp_str + 1;
  29.177 +    if ((temp_str = strrchr(real_filename, ':')) != NULL)
  29.178 +        real_filename = temp_str + 1;
  29.179 +
  29.180 +    sprintf(s_desc, desc_template, p_cid, p_cid, backing_file
  29.181 +            , (uint32_t)header.capacity, real_filename);
  29.182  
  29.183 -    fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
  29.184 -    if (fd < 0) {
  29.185 -        fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
  29.186 -        if (fd < 0)
  29.187 +    /* write the descriptor */
  29.188 +    if (lseek(snp_fd, 0x200, SEEK_SET) == -1)
  29.189 +        goto fail;
  29.190 +    if (write(snp_fd, s_desc, strlen(s_desc)) == -1)
  29.191 +        goto fail;
  29.192 +
  29.193 +    gd_offset = header.gd_offset * SECTOR_SIZE;     // offset of GD table
  29.194 +    rgd_offset = header.rgd_offset * SECTOR_SIZE;   // offset of RGD table
  29.195 +    capacity = header.capacity * SECTOR_SIZE;       // Extent size
  29.196 +    /*
  29.197 +     * Each GDE span 32M disk, means:
  29.198 +     * 512 GTE per GT, each GTE points to grain
  29.199 +     */
  29.200 +    gt_size = (int64_t)header.num_gtes_per_gte * header.granularity * SECTOR_SIZE;
  29.201 +    if (!gt_size)
  29.202 +        goto fail;
  29.203 +    gde_entries = (uint32_t)(capacity / gt_size);  // number of gde/rgde 
  29.204 +    gd_size = gde_entries * sizeof(uint32_t);
  29.205 +
  29.206 +    /* write RGD */
  29.207 +    rgd_buf = qemu_malloc(gd_size);
  29.208 +    if (!rgd_buf)
  29.209 +        goto fail;
  29.210 +    if (lseek(p_fd, rgd_offset, SEEK_SET) == -1)
  29.211 +        goto fail_rgd;
  29.212 +    if (read(p_fd, rgd_buf, gd_size) != gd_size)
  29.213 +        goto fail_rgd;
  29.214 +    if (lseek(snp_fd, rgd_offset, SEEK_SET) == -1)
  29.215 +        goto fail_rgd;
  29.216 +    if (write(snp_fd, rgd_buf, gd_size) == -1)
  29.217 +        goto fail_rgd;
  29.218 +    qemu_free(rgd_buf);
  29.219 +
  29.220 +    /* write GD */
  29.221 +    gd_buf = qemu_malloc(gd_size);
  29.222 +    if (!gd_buf)
  29.223 +        goto fail_rgd;
  29.224 +    if (lseek(p_fd, gd_offset, SEEK_SET) == -1)
  29.225 +        goto fail_gd;
  29.226 +    if (read(p_fd, gd_buf, gd_size) != gd_size)
  29.227 +        goto fail_gd;
  29.228 +    if (lseek(snp_fd, gd_offset, SEEK_SET) == -1)
  29.229 +        goto fail_gd;
  29.230 +    if (write(snp_fd, gd_buf, gd_size) == -1)
  29.231 +        goto fail_gd;
  29.232 +    qemu_free(gd_buf);
  29.233 +
  29.234 +    close(p_fd);
  29.235 +    close(snp_fd);
  29.236 +    return 0;
  29.237 +
  29.238 +    fail_gd:
  29.239 +    qemu_free(gd_buf);
  29.240 +    fail_rgd:   
  29.241 +    qemu_free(rgd_buf);
  29.242 +    fail:
  29.243 +    close(p_fd);
  29.244 +    close(snp_fd);
  29.245 +    return -1;
  29.246 +}
  29.247 +
  29.248 +static void vmdk_parent_close(BlockDriverState *bs)
  29.249 +{
  29.250 +    if (bs->backing_hd)
  29.251 +        bdrv_close(bs->backing_hd);
  29.252 +}
  29.253 +
  29.254 +
  29.255 +static int vmdk_parent_open(BlockDriverState *bs, const char * filename)
  29.256 +{
  29.257 +    BDRVVmdkState *s = bs->opaque;
  29.258 +    char *p_name; 
  29.259 +    char desc[DESC_SIZE];
  29.260 +    char parent_img_name[1024];
  29.261 +
  29.262 +    /* the descriptor offset = 0x200 */
  29.263 +    if (bdrv_pread(s->hd, 0x200, desc, DESC_SIZE) != DESC_SIZE)
  29.264 +        return -1;
  29.265 +
  29.266 +    if ((p_name = strstr(desc,"parentFileNameHint")) != 0) {
  29.267 +        char *end_name;
  29.268 +        struct stat file_buf;
  29.269 +
  29.270 +        p_name += sizeof("parentFileNameHint") + 1;
  29.271 +        if ((end_name = strchr(p_name,'\"')) == 0)
  29.272              return -1;
  29.273 -        bs->read_only = 1;
  29.274 +                
  29.275 +        strncpy(s->hd->backing_file, p_name, end_name - p_name);
  29.276 +        if (stat(s->hd->backing_file, &file_buf) != 0) {
  29.277 +            path_combine(parent_img_name, sizeof(parent_img_name),
  29.278 +                         filename, s->hd->backing_file);
  29.279 +        } else {
  29.280 +            strcpy(parent_img_name, s->hd->backing_file);
  29.281 +        }
  29.282 +
  29.283 +        s->hd->backing_hd = bdrv_new("");
  29.284 +        if (!s->hd->backing_hd) {
  29.285 +            failure:
  29.286 +            bdrv_close(s->hd);
  29.287 +            return -1;
  29.288 +        }
  29.289 +        if (bdrv_open(s->hd->backing_hd, parent_img_name, 0) < 0)
  29.290 +            goto failure;
  29.291      }
  29.292 -    if (read(fd, &magic, sizeof(magic)) != sizeof(magic))
  29.293 +
  29.294 +    return 0;
  29.295 +}
  29.296 +
  29.297 +static int vmdk_open(BlockDriverState *bs, const char *filename, int flags)
  29.298 +{
  29.299 +    BDRVVmdkState *s = bs->opaque;
  29.300 +    uint32_t magic;
  29.301 +    int l1_size, i, ret;
  29.302 +
  29.303 +    ret = bdrv_file_open(&s->hd, filename, flags);
  29.304 +    if (ret < 0)
  29.305 +        return ret;
  29.306 +    if (bdrv_pread(s->hd, 0, &magic, sizeof(magic)) != sizeof(magic))
  29.307          goto fail;
  29.308 +
  29.309      magic = be32_to_cpu(magic);
  29.310      if (magic == VMDK3_MAGIC) {
  29.311          VMDK3Header header;
  29.312 -        if (read(fd, &header, sizeof(header)) != 
  29.313 -            sizeof(header))
  29.314 +
  29.315 +        if (bdrv_pread(s->hd, sizeof(magic), &header, sizeof(header)) != sizeof(header))
  29.316              goto fail;
  29.317          s->cluster_sectors = le32_to_cpu(header.granularity);
  29.318          s->l2_size = 1 << 9;
  29.319 @@ -120,8 +373,8 @@ static int vmdk_open(BlockDriverState *b
  29.320          s->l1_entry_sectors = s->l2_size * s->cluster_sectors;
  29.321      } else if (magic == VMDK4_MAGIC) {
  29.322          VMDK4Header header;
  29.323 -        
  29.324 -        if (read(fd, &header, sizeof(header)) != sizeof(header))
  29.325 +
  29.326 +        if (bdrv_pread(s->hd, sizeof(magic), &header, sizeof(header)) != sizeof(header))
  29.327              goto fail;
  29.328          bs->total_sectors = le64_to_cpu(header.capacity);
  29.329          s->cluster_sectors = le64_to_cpu(header.granularity);
  29.330 @@ -133,17 +386,22 @@ static int vmdk_open(BlockDriverState *b
  29.331              / s->l1_entry_sectors;
  29.332          s->l1_table_offset = le64_to_cpu(header.rgd_offset) << 9;
  29.333          s->l1_backup_table_offset = le64_to_cpu(header.gd_offset) << 9;
  29.334 +
  29.335 +        // try to open parent images, if exist
  29.336 +        if (vmdk_parent_open(bs, filename) != 0)
  29.337 +            goto fail;
  29.338 +        // write the CID once after the image creation
  29.339 +        s->parent_cid = vmdk_read_cid(bs,1);
  29.340      } else {
  29.341          goto fail;
  29.342      }
  29.343 +
  29.344      /* read the L1 table */
  29.345      l1_size = s->l1_size * sizeof(uint32_t);
  29.346      s->l1_table = qemu_malloc(l1_size);
  29.347      if (!s->l1_table)
  29.348          goto fail;
  29.349 -    if (lseek(fd, s->l1_table_offset, SEEK_SET) == -1)
  29.350 -        goto fail;
  29.351 -    if (read(fd, s->l1_table, l1_size) != l1_size)
  29.352 +    if (bdrv_pread(s->hd, s->l1_table_offset, s->l1_table, l1_size) != l1_size)
  29.353          goto fail;
  29.354      for(i = 0; i < s->l1_size; i++) {
  29.355          le32_to_cpus(&s->l1_table[i]);
  29.356 @@ -153,9 +411,7 @@ static int vmdk_open(BlockDriverState *b
  29.357          s->l1_backup_table = qemu_malloc(l1_size);
  29.358          if (!s->l1_backup_table)
  29.359              goto fail;
  29.360 -        if (lseek(fd, s->l1_backup_table_offset, SEEK_SET) == -1)
  29.361 -            goto fail;
  29.362 -        if (read(fd, s->l1_backup_table, l1_size) != l1_size)
  29.363 +        if (bdrv_pread(s->hd, s->l1_backup_table_offset, s->l1_backup_table, l1_size) != l1_size)
  29.364              goto fail;
  29.365          for(i = 0; i < s->l1_size; i++) {
  29.366              le32_to_cpus(&s->l1_backup_table[i]);
  29.367 @@ -165,16 +421,43 @@ static int vmdk_open(BlockDriverState *b
  29.368      s->l2_cache = qemu_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint32_t));
  29.369      if (!s->l2_cache)
  29.370          goto fail;
  29.371 -    s->fd = fd;
  29.372      return 0;
  29.373   fail:
  29.374      qemu_free(s->l1_backup_table);
  29.375      qemu_free(s->l1_table);
  29.376      qemu_free(s->l2_cache);
  29.377 -    close(fd);
  29.378 +    bdrv_delete(s->hd);
  29.379      return -1;
  29.380  }
  29.381  
  29.382 +static uint64_t get_cluster_offset(BlockDriverState *bs, uint64_t offset, int allocate);
  29.383 +
  29.384 +static int get_whole_cluster(BlockDriverState *bs, uint64_t cluster_offset,
  29.385 +                             uint64_t offset, int allocate)
  29.386 +{
  29.387 +    uint64_t parent_cluster_offset;
  29.388 +    BDRVVmdkState *s = bs->opaque;
  29.389 +    uint8_t  whole_grain[s->cluster_sectors*512];        // 128 sectors * 512 bytes each = grain size 64KB
  29.390 +
  29.391 +    // we will be here if it's first write on non-exist grain(cluster).
  29.392 +    // try to read from parent image, if exist
  29.393 +    if (s->hd->backing_hd) {
  29.394 +        BDRVVmdkState *ps = s->hd->backing_hd->opaque;
  29.395 +
  29.396 +        if (!vmdk_is_cid_valid(bs))
  29.397 +            return -1;
  29.398 +        parent_cluster_offset = get_cluster_offset(s->hd->backing_hd, offset, allocate);
  29.399 +        if (bdrv_pread(ps->hd, parent_cluster_offset, whole_grain, ps->cluster_sectors*512) != 
  29.400 +                                                                            ps->cluster_sectors*512)
  29.401 +            return -1;
  29.402 +
  29.403 +        if (bdrv_pwrite(s->hd, cluster_offset << 9, whole_grain, sizeof(whole_grain)) != 
  29.404 +                                                                            sizeof(whole_grain))
  29.405 +            return -1;
  29.406 +    }
  29.407 +    return 0;
  29.408 +}
  29.409 +
  29.410  static uint64_t get_cluster_offset(BlockDriverState *bs,
  29.411                                     uint64_t offset, int allocate)
  29.412  {
  29.413 @@ -212,34 +495,41 @@ static uint64_t get_cluster_offset(Block
  29.414          }
  29.415      }
  29.416      l2_table = s->l2_cache + (min_index * s->l2_size);
  29.417 -    lseek(s->fd, (int64_t)l2_offset * 512, SEEK_SET);
  29.418 -    if (read(s->fd, l2_table, s->l2_size * sizeof(uint32_t)) != 
  29.419 -        s->l2_size * sizeof(uint32_t))
  29.420 +    if (bdrv_pread(s->hd, (int64_t)l2_offset * 512, l2_table, s->l2_size * sizeof(uint32_t)) != 
  29.421 +                                                                        s->l2_size * sizeof(uint32_t))
  29.422          return 0;
  29.423 +
  29.424      s->l2_cache_offsets[min_index] = l2_offset;
  29.425      s->l2_cache_counts[min_index] = 1;
  29.426   found:
  29.427      l2_index = ((offset >> 9) / s->cluster_sectors) % s->l2_size;
  29.428      cluster_offset = le32_to_cpu(l2_table[l2_index]);
  29.429      if (!cluster_offset) {
  29.430 +        struct stat file_buf;
  29.431 +
  29.432          if (!allocate)
  29.433              return 0;
  29.434 -        cluster_offset = lseek(s->fd, 0, SEEK_END);
  29.435 -        ftruncate(s->fd, cluster_offset + (s->cluster_sectors << 9));
  29.436 +        stat(s->hd->filename, &file_buf);
  29.437 +        cluster_offset = file_buf.st_size;
  29.438 +        bdrv_truncate(s->hd, cluster_offset + (s->cluster_sectors << 9));
  29.439 +
  29.440          cluster_offset >>= 9;
  29.441          /* update L2 table */
  29.442          tmp = cpu_to_le32(cluster_offset);
  29.443          l2_table[l2_index] = tmp;
  29.444 -        lseek(s->fd, ((int64_t)l2_offset * 512) + (l2_index * sizeof(tmp)), SEEK_SET);
  29.445 -        if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))
  29.446 +        if (bdrv_pwrite(s->hd, ((int64_t)l2_offset * 512) + (l2_index * sizeof(tmp)), 
  29.447 +                        &tmp, sizeof(tmp)) != sizeof(tmp))
  29.448              return 0;
  29.449          /* update backup L2 table */
  29.450          if (s->l1_backup_table_offset != 0) {
  29.451              l2_offset = s->l1_backup_table[l1_index];
  29.452 -            lseek(s->fd, ((int64_t)l2_offset * 512) + (l2_index * sizeof(tmp)), SEEK_SET);
  29.453 -            if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))
  29.454 +            if (bdrv_pwrite(s->hd, ((int64_t)l2_offset * 512) + (l2_index * sizeof(tmp)), 
  29.455 +                            &tmp, sizeof(tmp)) != sizeof(tmp))
  29.456                  return 0;
  29.457          }
  29.458 +
  29.459 +        if (get_whole_cluster(bs, cluster_offset, offset, allocate) == -1)
  29.460 +            return 0;
  29.461      }
  29.462      cluster_offset <<= 9;
  29.463      return cluster_offset;
  29.464 @@ -265,9 +555,9 @@ static int vmdk_read(BlockDriverState *b
  29.465                      uint8_t *buf, int nb_sectors)
  29.466  {
  29.467      BDRVVmdkState *s = bs->opaque;
  29.468 -    int ret, index_in_cluster, n;
  29.469 +    int index_in_cluster, n, ret;
  29.470      uint64_t cluster_offset;
  29.471 -    
  29.472 +
  29.473      while (nb_sectors > 0) {
  29.474          cluster_offset = get_cluster_offset(bs, sector_num << 9, 0);
  29.475          index_in_cluster = sector_num % s->cluster_sectors;
  29.476 @@ -275,11 +565,18 @@ static int vmdk_read(BlockDriverState *b
  29.477          if (n > nb_sectors)
  29.478              n = nb_sectors;
  29.479          if (!cluster_offset) {
  29.480 -            memset(buf, 0, 512 * n);
  29.481 +            // try to read from parent image, if exist
  29.482 +            if (s->hd->backing_hd) {
  29.483 +                if (!vmdk_is_cid_valid(bs))
  29.484 +                    return -1;
  29.485 +                ret = bdrv_read(s->hd->backing_hd, sector_num, buf, n);
  29.486 +                if (ret < 0)
  29.487 +                    return -1;
  29.488 +            } else {
  29.489 +                memset(buf, 0, 512 * n);
  29.490 +            }
  29.491          } else {
  29.492 -            lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
  29.493 -            ret = read(s->fd, buf, n * 512);
  29.494 -            if (ret != n * 512) 
  29.495 +            if(bdrv_pread(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512) != n * 512)
  29.496                  return -1;
  29.497          }
  29.498          nb_sectors -= n;
  29.499 @@ -293,8 +590,9 @@ static int vmdk_write(BlockDriverState *
  29.500                       const uint8_t *buf, int nb_sectors)
  29.501  {
  29.502      BDRVVmdkState *s = bs->opaque;
  29.503 -    int ret, index_in_cluster, n;
  29.504 +    int index_in_cluster, n;
  29.505      uint64_t cluster_offset;
  29.506 +    static int cid_update = 0;
  29.507  
  29.508      while (nb_sectors > 0) {
  29.509          index_in_cluster = sector_num & (s->cluster_sectors - 1);
  29.510 @@ -304,13 +602,17 @@ static int vmdk_write(BlockDriverState *
  29.511          cluster_offset = get_cluster_offset(bs, sector_num << 9, 1);
  29.512          if (!cluster_offset)
  29.513              return -1;
  29.514 -        lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
  29.515 -        ret = write(s->fd, buf, n * 512);
  29.516 -        if (ret != n * 512)
  29.517 +        if (bdrv_pwrite(s->hd, cluster_offset + index_in_cluster * 512, buf, n * 512) != n * 512)
  29.518              return -1;
  29.519          nb_sectors -= n;
  29.520          sector_num += n;
  29.521          buf += n * 512;
  29.522 +
  29.523 +        // update CID on the first write every time the virtual disk is opened
  29.524 +        if (!cid_update) {
  29.525 +            vmdk_write_cid(bs, time(NULL));
  29.526 +            cid_update++;
  29.527 +        }
  29.528      }
  29.529      return 0;
  29.530  }
  29.531 @@ -334,7 +636,7 @@ static int vmdk_create(const char *filen
  29.532          "# The Disk Data Base \n"
  29.533          "#DDB\n"
  29.534          "\n"
  29.535 -        "ddb.virtualHWVersion = \"3\"\n"
  29.536 +        "ddb.virtualHWVersion = \"4\"\n"
  29.537          "ddb.geometry.cylinders = \"%lu\"\n"
  29.538          "ddb.geometry.heads = \"16\"\n"
  29.539          "ddb.geometry.sectors = \"63\"\n"
  29.540 @@ -343,6 +645,9 @@ static int vmdk_create(const char *filen
  29.541      const char *real_filename, *temp_str;
  29.542  
  29.543      /* XXX: add support for backing file */
  29.544 +    if (backing_file) {
  29.545 +        return vmdk_snapshot_create(filename, backing_file);
  29.546 +    }
  29.547  
  29.548      fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
  29.549                0644);
  29.550 @@ -421,15 +726,18 @@ static int vmdk_create(const char *filen
  29.551  static void vmdk_close(BlockDriverState *bs)
  29.552  {
  29.553      BDRVVmdkState *s = bs->opaque;
  29.554 +
  29.555      qemu_free(s->l1_table);
  29.556      qemu_free(s->l2_cache);
  29.557 -    close(s->fd);
  29.558 +    bdrv_delete(s->hd);
  29.559 +    // try to close parent image, if exist
  29.560 +    vmdk_parent_close(s->hd);
  29.561  }
  29.562  
  29.563  static void vmdk_flush(BlockDriverState *bs)
  29.564  {
  29.565      BDRVVmdkState *s = bs->opaque;
  29.566 -    fsync(s->fd);
  29.567 +    bdrv_flush(s->hd);
  29.568  }
  29.569  
  29.570  BlockDriver bdrv_vmdk = {
    30.1 --- a/tools/ioemu/block-vpc.c	Wed May 16 10:42:07 2007 -0600
    30.2 +++ b/tools/ioemu/block-vpc.c	Wed May 16 10:59:01 2007 -0600
    30.3 @@ -86,19 +86,16 @@ static int vpc_probe(const uint8_t *buf,
    30.4      return 0;
    30.5  }
    30.6  
    30.7 -static int vpc_open(BlockDriverState *bs, const char *filename)
    30.8 +static int vpc_open(BlockDriverState *bs, const char *filename, int flags)
    30.9  {
   30.10      BDRVVPCState *s = bs->opaque;
   30.11      int fd, i;
   30.12      struct vpc_subheader header;
   30.13  
   30.14 -    fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
   30.15 -    if (fd < 0) {
   30.16 -        fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
   30.17 -        if (fd < 0)
   30.18 -            return -1;
   30.19 -    }
   30.20 -    
   30.21 +    fd = open(filename, O_RDONLY | O_BINARY);
   30.22 +    if (fd < 0)
   30.23 +        return -1;
   30.24 +
   30.25      bs->read_only = 1; // no write support yet
   30.26      
   30.27      s->fd = fd;
    31.1 --- a/tools/ioemu/block-vvfat.c	Wed May 16 10:42:07 2007 -0600
    31.2 +++ b/tools/ioemu/block-vvfat.c	Wed May 16 10:59:01 2007 -0600
    31.3 @@ -61,7 +61,7 @@ void nonono(const char* file, int line, 
    31.4      exit(-5);
    31.5  }
    31.6  #undef assert
    31.7 -#define assert(a) if (!(a)) nonono(__FILE__, __LINE__, #a)
    31.8 +#define assert(a) do {if (!(a)) nonono(__FILE__, __LINE__, #a);}while(0)
    31.9  #endif
   31.10  
   31.11  #else
   31.12 @@ -351,13 +351,6 @@ typedef struct BDRVVVFATState {
   31.13  } BDRVVVFATState;
   31.14  
   31.15  
   31.16 -static int vvfat_probe(const uint8_t *buf, int buf_size, const char *filename)
   31.17 -{
   31.18 -    if (strstart(filename, "fat:", NULL))
   31.19 -	return 100;
   31.20 -    return 0;
   31.21 -}
   31.22 -
   31.23  static void init_mbr(BDRVVVFATState* s)
   31.24  {
   31.25      /* TODO: if the files mbr.img and bootsect.img exist, use them */
   31.26 @@ -954,18 +947,22 @@ static int init_directories(BDRVVVFATSta
   31.27      return 0;
   31.28  }
   31.29  
   31.30 +#ifdef DEBUG
   31.31  static BDRVVVFATState *vvv = NULL;
   31.32 +#endif
   31.33  
   31.34  static int enable_write_target(BDRVVVFATState *s);
   31.35  static int is_consistent(BDRVVVFATState *s);
   31.36  
   31.37 -static int vvfat_open(BlockDriverState *bs, const char* dirname)
   31.38 +static int vvfat_open(BlockDriverState *bs, const char* dirname, int flags)
   31.39  {
   31.40      BDRVVVFATState *s = bs->opaque;
   31.41      int floppy = 0;
   31.42      int i;
   31.43  
   31.44 +#ifdef DEBUG
   31.45      vvv = s;
   31.46 +#endif
   31.47  
   31.48  DLOG(if (stderr == NULL) {
   31.49      stderr = fopen("vvfat.log", "a");
   31.50 @@ -1040,7 +1037,6 @@ DLOG(if (stderr == NULL) {
   31.51  	bs->heads = bs->cyls = bs->secs = 0;
   31.52  
   31.53      //    assert(is_consistent(s));
   31.54 -
   31.55      return 0;
   31.56  }
   31.57  
   31.58 @@ -2178,7 +2174,7 @@ static int commit_one_file(BDRVVVFATStat
   31.59      for (i = s->cluster_size; i < offset; i += s->cluster_size)
   31.60  	c = modified_fat_get(s, c);
   31.61  
   31.62 -    fd = open(mapping->path, O_RDWR | O_CREAT, 0666);
   31.63 +    fd = open(mapping->path, O_RDWR | O_CREAT | O_BINARY, 0666);
   31.64      if (fd < 0) {
   31.65  	fprintf(stderr, "Could not open %s... (%s, %d)\n", mapping->path,
   31.66  		strerror(errno), errno);
   31.67 @@ -2732,8 +2728,7 @@ static int enable_write_target(BDRVVVFAT
   31.68      array_init(&(s->commits), sizeof(commit_t));
   31.69  
   31.70      s->qcow_filename = malloc(1024);
   31.71 -    strcpy(s->qcow_filename, "/tmp/vl.XXXXXX");
   31.72 -    get_tmp_filename(s->qcow_filename, strlen(s->qcow_filename) + 1);
   31.73 +    get_tmp_filename(s->qcow_filename, 1024);
   31.74      if (bdrv_create(&bdrv_qcow,
   31.75  		s->qcow_filename, s->sector_count, "fat:", 0) < 0)
   31.76  	return -1;
   31.77 @@ -2767,14 +2762,15 @@ static void vvfat_close(BlockDriverState
   31.78  BlockDriver bdrv_vvfat = {
   31.79      "vvfat",
   31.80      sizeof(BDRVVVFATState),
   31.81 -    vvfat_probe,
   31.82 +    NULL, /* no probe for protocols */
   31.83      vvfat_open,
   31.84      vvfat_read,
   31.85      vvfat_write,
   31.86      vvfat_close,
   31.87      NULL, /* ??? Not sure if we can do any meaningful flushing.  */
   31.88      NULL,
   31.89 -    vvfat_is_allocated
   31.90 +    vvfat_is_allocated,
   31.91 +    .protocol_name = "fat",
   31.92  };
   31.93  
   31.94  #ifdef DEBUG
    32.1 --- a/tools/ioemu/block.c	Wed May 16 10:42:07 2007 -0600
    32.2 +++ b/tools/ioemu/block.c	Wed May 16 10:59:01 2007 -0600
    32.3 @@ -32,85 +32,108 @@
    32.4  #include <sys/disk.h>
    32.5  #endif
    32.6  
    32.7 -#ifdef CONFIG_COCOA
    32.8 -#include <paths.h>
    32.9 -#include <sys/param.h>
   32.10 -#include <IOKit/IOKitLib.h>
   32.11 -#include <IOKit/IOBSD.h>
   32.12 -#include <IOKit/storage/IOMediaBSDClient.h>
   32.13 -#include <IOKit/storage/IOMedia.h>
   32.14 -#include <IOKit/storage/IOCDMedia.h>
   32.15 -//#include <IOKit/storage/IOCDTypes.h>
   32.16 -#include <CoreFoundation/CoreFoundation.h>
   32.17 -#endif
   32.18 +#define SECTOR_BITS 9
   32.19 +#define SECTOR_SIZE (1 << SECTOR_BITS)
   32.20 +
   32.21 +typedef struct BlockDriverAIOCBSync {
   32.22 +    BlockDriverAIOCB common;
   32.23 +    QEMUBH *bh;
   32.24 +    int ret;
   32.25 +} BlockDriverAIOCBSync;
   32.26  
   32.27 -#ifdef __sun__
   32.28 -#include <sys/dkio.h>
   32.29 -#endif
   32.30 +static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
   32.31 +        int64_t sector_num, uint8_t *buf, int nb_sectors,
   32.32 +        BlockDriverCompletionFunc *cb, void *opaque);
   32.33 +static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
   32.34 +        int64_t sector_num, const uint8_t *buf, int nb_sectors,
   32.35 +        BlockDriverCompletionFunc *cb, void *opaque);
   32.36 +static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb);
   32.37 +static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num, 
   32.38 +                        uint8_t *buf, int nb_sectors);
   32.39 +static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
   32.40 +                         const uint8_t *buf, int nb_sectors);
   32.41  
   32.42  static BlockDriverState *bdrv_first;
   32.43  static BlockDriver *first_drv;
   32.44  
   32.45 -#ifdef CONFIG_COCOA
   32.46 -static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator );
   32.47 -static kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize );
   32.48 -
   32.49 -kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator )
   32.50 +int path_is_absolute(const char *path)
   32.51  {
   32.52 -    kern_return_t       kernResult; 
   32.53 -    mach_port_t     masterPort;
   32.54 -    CFMutableDictionaryRef  classesToMatch;
   32.55 -
   32.56 -    kernResult = IOMasterPort( MACH_PORT_NULL, &masterPort );
   32.57 -    if ( KERN_SUCCESS != kernResult ) {
   32.58 -        printf( "IOMasterPort returned %d\n", kernResult );
   32.59 -    }
   32.60 -    
   32.61 -    classesToMatch = IOServiceMatching( kIOCDMediaClass ); 
   32.62 -    if ( classesToMatch == NULL ) {
   32.63 -        printf( "IOServiceMatching returned a NULL dictionary.\n" );
   32.64 -    } else {
   32.65 -    CFDictionarySetValue( classesToMatch, CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
   32.66 -    }
   32.67 -    kernResult = IOServiceGetMatchingServices( masterPort, classesToMatch, mediaIterator );
   32.68 -    if ( KERN_SUCCESS != kernResult )
   32.69 -    {
   32.70 -        printf( "IOServiceGetMatchingServices returned %d\n", kernResult );
   32.71 -    }
   32.72 -    
   32.73 -    return kernResult;
   32.74 +    const char *p;
   32.75 +#ifdef _WIN32
   32.76 +    /* specific case for names like: "\\.\d:" */
   32.77 +    if (*path == '/' || *path == '\\')
   32.78 +        return 1;
   32.79 +#endif
   32.80 +    p = strchr(path, ':');
   32.81 +    if (p)
   32.82 +        p++;
   32.83 +    else
   32.84 +        p = path;
   32.85 +#ifdef _WIN32
   32.86 +    return (*p == '/' || *p == '\\');
   32.87 +#else
   32.88 +    return (*p == '/');
   32.89 +#endif
   32.90  }
   32.91  
   32.92 -kern_return_t GetBSDPath( io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize )
   32.93 +/* if filename is absolute, just copy it to dest. Otherwise, build a
   32.94 +   path to it by considering it is relative to base_path. URL are
   32.95 +   supported. */
   32.96 +void path_combine(char *dest, int dest_size,
   32.97 +                  const char *base_path,
   32.98 +                  const char *filename)
   32.99  {
  32.100 -    io_object_t     nextMedia;
  32.101 -    kern_return_t   kernResult = KERN_FAILURE;
  32.102 -    *bsdPath = '\0';
  32.103 -    nextMedia = IOIteratorNext( mediaIterator );
  32.104 -    if ( nextMedia )
  32.105 -    {
  32.106 -        CFTypeRef   bsdPathAsCFString;
  32.107 -    bsdPathAsCFString = IORegistryEntryCreateCFProperty( nextMedia, CFSTR( kIOBSDNameKey ), kCFAllocatorDefault, 0 );
  32.108 -        if ( bsdPathAsCFString ) {
  32.109 -            size_t devPathLength;
  32.110 -            strcpy( bsdPath, _PATH_DEV );
  32.111 -            strcat( bsdPath, "r" );
  32.112 -            devPathLength = strlen( bsdPath );
  32.113 -            if ( CFStringGetCString( bsdPathAsCFString, bsdPath + devPathLength, maxPathSize - devPathLength, kCFStringEncodingASCII ) ) {
  32.114 -                kernResult = KERN_SUCCESS;
  32.115 -            }
  32.116 -            CFRelease( bsdPathAsCFString );
  32.117 +    const char *p, *p1;
  32.118 +    int len;
  32.119 +
  32.120 +    if (dest_size <= 0)
  32.121 +        return;
  32.122 +    if (path_is_absolute(filename)) {
  32.123 +        pstrcpy(dest, dest_size, filename);
  32.124 +    } else {
  32.125 +        p = strchr(base_path, ':');
  32.126 +        if (p)
  32.127 +            p++;
  32.128 +        else
  32.129 +            p = base_path;
  32.130 +        p1 = strrchr(base_path, '/');
  32.131 +#ifdef _WIN32
  32.132 +        {
  32.133 +            const char *p2;
  32.134 +            p2 = strrchr(base_path, '\\');
  32.135 +            if (!p1 || p2 > p1)
  32.136 +                p1 = p2;
  32.137          }
  32.138 -        IOObjectRelease( nextMedia );
  32.139 +#endif
  32.140 +        if (p1)
  32.141 +            p1++;
  32.142 +        else
  32.143 +            p1 = base_path;
  32.144 +        if (p1 > p)
  32.145 +            p = p1;
  32.146 +        len = p - base_path;
  32.147 +        if (len > dest_size - 1)
  32.148 +            len = dest_size - 1;
  32.149 +        memcpy(dest, base_path, len);
  32.150 +        dest[len] = '\0';
  32.151 +        pstrcat(dest, dest_size, filename);
  32.152      }
  32.153 -    
  32.154 -    return kernResult;
  32.155  }
  32.156  
  32.157 -#endif
  32.158  
  32.159  void bdrv_register(BlockDriver *bdrv)
  32.160  {
  32.161 +    if (!bdrv->bdrv_aio_read) {
  32.162 +        /* add AIO emulation layer */
  32.163 +        bdrv->bdrv_aio_read = bdrv_aio_read_em;
  32.164 +        bdrv->bdrv_aio_write = bdrv_aio_write_em;
  32.165 +        bdrv->bdrv_aio_cancel = bdrv_aio_cancel_em;
  32.166 +        bdrv->aiocb_size = sizeof(BlockDriverAIOCBSync);
  32.167 +    } else if (!bdrv->bdrv_read && !bdrv->bdrv_pread) {
  32.168 +        /* add synchronous IO emulation layer */
  32.169 +        bdrv->bdrv_read = bdrv_read_em;
  32.170 +        bdrv->bdrv_write = bdrv_write_em;
  32.171 +    }
  32.172      bdrv->next = first_drv;
  32.173      first_drv = bdrv;
  32.174  }
  32.175 @@ -156,14 +179,10 @@ int bdrv_create(BlockDriver *drv,
  32.176  #ifdef _WIN32
  32.177  void get_tmp_filename(char *filename, int size)
  32.178  {
  32.179 -    char* p = strrchr(filename, '/');
  32.180 -
  32.181 -    if (p == NULL)
  32.182 -	return;
  32.183 -
  32.184 -    /* XXX: find a better function */
  32.185 -    tmpnam(p);
  32.186 -    *p = '/';
  32.187 +    char temp_dir[MAX_PATH];
  32.188 +    
  32.189 +    GetTempPath(MAX_PATH, temp_dir);
  32.190 +    GetTempFileName(temp_dir, "qem", 0, filename);
  32.191  }
  32.192  #else
  32.193  void get_tmp_filename(char *filename, int size)
  32.194 @@ -176,101 +195,141 @@ void get_tmp_filename(char *filename, in
  32.195  }
  32.196  #endif
  32.197  
  32.198 +#ifdef _WIN32
  32.199 +static int is_windows_drive_prefix(const char *filename)
  32.200 +{
  32.201 +    return (((filename[0] >= 'a' && filename[0] <= 'z') ||
  32.202 +             (filename[0] >= 'A' && filename[0] <= 'Z')) &&
  32.203 +            filename[1] == ':');
  32.204 +}
  32.205 +    
  32.206 +static int is_windows_drive(const char *filename)
  32.207 +{
  32.208 +    if (is_windows_drive_prefix(filename) && 
  32.209 +        filename[2] == '\0')
  32.210 +        return 1;
  32.211 +    if (strstart(filename, "\\\\.\\", NULL) ||
  32.212 +        strstart(filename, "//./", NULL))
  32.213 +        return 1;
  32.214 +    return 0;
  32.215 +}
  32.216 +#endif
  32.217 +
  32.218 +static BlockDriver *find_protocol(const char *filename)
  32.219 +{
  32.220 +    BlockDriver *drv1;
  32.221 +    char protocol[128];
  32.222 +    int len;
  32.223 +    const char *p;
  32.224 +
  32.225 +#ifdef _WIN32
  32.226 +    if (is_windows_drive(filename) ||
  32.227 +        is_windows_drive_prefix(filename))
  32.228 +        return &bdrv_raw;
  32.229 +#endif
  32.230 +    p = strchr(filename, ':');
  32.231 +    if (!p)
  32.232 +        return &bdrv_raw;
  32.233 +    len = p - filename;
  32.234 +    if (len > sizeof(protocol) - 1)
  32.235 +        len = sizeof(protocol) - 1;
  32.236 +    memcpy(protocol, filename, len);
  32.237 +    protocol[len] = '\0';
  32.238 +    for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
  32.239 +        if (drv1->protocol_name && 
  32.240 +            !strcmp(drv1->protocol_name, protocol))
  32.241 +            return drv1;
  32.242 +    }
  32.243 +    return NULL;
  32.244 +}
  32.245 +
  32.246  /* XXX: force raw format if block or character device ? It would
  32.247     simplify the BSD case */
  32.248  static BlockDriver *find_image_format(const char *filename)
  32.249  {
  32.250 -    int fd, ret, score, score_max;
  32.251 +    int ret, score, score_max;
  32.252      BlockDriver *drv1, *drv;
  32.253 -    uint8_t *buf;
  32.254 -    size_t bufsize = 1024;
  32.255 -
  32.256 -    fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
  32.257 -    if (fd < 0) {
  32.258 -        buf = NULL;
  32.259 -        ret = 0;
  32.260 -    } else {
  32.261 -#ifdef DIOCGSECTORSIZE
  32.262 -        {
  32.263 -            unsigned int sectorsize = 512;
  32.264 -            if (!ioctl(fd, DIOCGSECTORSIZE, &sectorsize) &&
  32.265 -                sectorsize > bufsize)
  32.266 -                bufsize = sectorsize;
  32.267 +    uint8_t buf[2048];
  32.268 +    BlockDriverState *bs;
  32.269 +    
  32.270 +    /* detect host devices. By convention, /dev/cdrom[N] is always
  32.271 +       recognized as a host CDROM */
  32.272 +    if (strstart(filename, "/dev/cdrom", NULL))
  32.273 +        return &bdrv_host_device;
  32.274 +#ifdef _WIN32
  32.275 +    if (is_windows_drive(filename))
  32.276 +        return &bdrv_host_device;
  32.277 +#else
  32.278 +    {
  32.279 +        struct stat st;
  32.280 +        if (stat(filename, &st) >= 0 && 
  32.281 +            (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode))) {
  32.282 +            return &bdrv_host_device;
  32.283          }
  32.284 +    }
  32.285  #endif
  32.286 -#ifdef CONFIG_COCOA
  32.287 -        u_int32_t   blockSize = 512;
  32.288 -        if ( !ioctl( fd, DKIOCGETBLOCKSIZE, &blockSize ) && blockSize > bufsize) {
  32.289 -            bufsize = blockSize;
  32.290 -        }
  32.291 -#endif
  32.292 -        buf = qemu_malloc(bufsize);
  32.293 -        if (!buf)
  32.294 -            return NULL;
  32.295 -        ret = read(fd, buf, bufsize);
  32.296 -        if (ret < 0) {
  32.297 -            close(fd);
  32.298 -            qemu_free(buf);
  32.299 -            return NULL;
  32.300 -        }
  32.301 -        close(fd);
  32.302 +    
  32.303 +    drv = find_protocol(filename);
  32.304 +    /* no need to test disk image formats for vvfat */
  32.305 +    if (drv == &bdrv_vvfat)
  32.306 +        return drv;
  32.307 +
  32.308 +    ret = bdrv_file_open(&bs, filename, BDRV_O_RDONLY);
  32.309 +    if (ret < 0)
  32.310 +        return NULL;
  32.311 +    ret = bdrv_pread(bs, 0, buf, sizeof(buf));
  32.312 +    bdrv_delete(bs);
  32.313 +    if (ret < 0) {
  32.314 +        return NULL;
  32.315      }
  32.316 -    
  32.317 -    drv = NULL;
  32.318 +
  32.319      score_max = 0;
  32.320      for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
  32.321 -        score = drv1->bdrv_probe(buf, ret, filename);
  32.322 -        if (score > score_max) {
  32.323 -            score_max = score;
  32.324 -            drv = drv1;
  32.325 +        if (drv1->bdrv_probe) {
  32.326 +            score = drv1->bdrv_probe(buf, ret, filename);
  32.327 +            if (score > score_max) {
  32.328 +                score_max = score;
  32.329 +                drv = drv1;
  32.330 +            }
  32.331          }
  32.332      }
  32.333 -    qemu_free(buf);
  32.334      return drv;
  32.335  }
  32.336  
  32.337 -int bdrv_open(BlockDriverState *bs, const char *filename, int snapshot)
  32.338 +int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
  32.339  {
  32.340 -#ifdef CONFIG_COCOA
  32.341 -    if ( strncmp( filename, "/dev/cdrom", 10 ) == 0 ) {
  32.342 -        kern_return_t kernResult;
  32.343 -        io_iterator_t mediaIterator;
  32.344 -        char bsdPath[ MAXPATHLEN ];
  32.345 -        int fd;
  32.346 - 
  32.347 -        kernResult = FindEjectableCDMedia( &mediaIterator );
  32.348 -        kernResult = GetBSDPath( mediaIterator, bsdPath, sizeof( bsdPath ) );
  32.349 -    
  32.350 -        if ( bsdPath[ 0 ] != '\0' ) {
  32.351 -            strcat(bsdPath,"s0");
  32.352 -            /* some CDs don't have a partition 0 */
  32.353 -            fd = open(bsdPath, O_RDONLY | O_BINARY | O_LARGEFILE);
  32.354 -            if (fd < 0) {
  32.355 -                bsdPath[strlen(bsdPath)-1] = '1';
  32.356 -            } else {
  32.357 -                close(fd);
  32.358 -            }
  32.359 -            filename = bsdPath;
  32.360 -        }
  32.361 -        
  32.362 -        if ( mediaIterator )
  32.363 -            IOObjectRelease( mediaIterator );
  32.364 +    BlockDriverState *bs;
  32.365 +    int ret;
  32.366 +
  32.367 +    bs = bdrv_new("");
  32.368 +    if (!bs)
  32.369 +        return -ENOMEM;
  32.370 +    ret = bdrv_open2(bs, filename, flags | BDRV_O_FILE, NULL);
  32.371 +    if (ret < 0) {
  32.372 +        bdrv_delete(bs);
  32.373 +        return ret;
  32.374      }
  32.375 -#endif
  32.376 -    return bdrv_open2(bs, filename, snapshot, NULL);
  32.377 +    *pbs = bs;
  32.378 +    return 0;
  32.379  }
  32.380  
  32.381 -int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot,
  32.382 +int bdrv_open(BlockDriverState *bs, const char *filename, int flags)
  32.383 +{
  32.384 +    return bdrv_open2(bs, filename, flags, NULL);
  32.385 +}
  32.386 +
  32.387 +int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
  32.388                 BlockDriver *drv)
  32.389  {
  32.390 -    int ret;
  32.391 +    int ret, open_flags;
  32.392      char tmp_filename[1024];
  32.393 +    char backing_filename[1024];
  32.394      
  32.395      bs->read_only = 0;
  32.396      bs->is_temporary = 0;
  32.397      bs->encrypted = 0;
  32.398  
  32.399 -    if (snapshot) {
  32.400 +    if (flags & BDRV_O_SNAPSHOT) {
  32.401          BlockDriverState *bs1;
  32.402          int64_t total_size;
  32.403          
  32.404 @@ -280,19 +339,19 @@ int bdrv_open2(BlockDriverState *bs, con
  32.405          /* if there is a backing file, use it */
  32.406          bs1 = bdrv_new("");
  32.407          if (!bs1) {
  32.408 -            return -1;
  32.409 +            return -ENOMEM;
  32.410          }
  32.411          if (bdrv_open(bs1, filename, 0) < 0) {
  32.412              bdrv_delete(bs1);
  32.413              return -1;
  32.414          }
  32.415 -        total_size = bs1->total_sectors;
  32.416 +        total_size = bdrv_getlength(bs1) >> SECTOR_BITS;
  32.417          bdrv_delete(bs1);
  32.418          
  32.419          get_tmp_filename(tmp_filename, sizeof(tmp_filename));
  32.420 -        /* XXX: use cow for linux as it is more efficient ? */
  32.421 -        if (bdrv_create(&bdrv_qcow, tmp_filename, 
  32.422 -                        total_size, filename, 0) < 0) {
  32.423 +        realpath(filename, backing_filename);
  32.424 +        if (bdrv_create(&bdrv_qcow2, tmp_filename, 
  32.425 +                        total_size, backing_filename, 0) < 0) {
  32.426              return -1;
  32.427          }
  32.428          filename = tmp_filename;
  32.429 @@ -300,41 +359,62 @@ int bdrv_open2(BlockDriverState *bs, con
  32.430      }
  32.431  
  32.432      pstrcpy(bs->filename, sizeof(bs->filename), filename);
  32.433 -    if (!drv) {
  32.434 -        drv = find_image_format(filename);
  32.435 +    if (flags & BDRV_O_FILE) {
  32.436 +        drv = find_protocol(filename);
  32.437          if (!drv)
  32.438 -            return -1;
  32.439 +            return -ENOENT;
  32.440 +    } else {
  32.441 +        if (!drv) {
  32.442 +            drv = find_image_format(filename);
  32.443 +            if (!drv)
  32.444 +                return -1;
  32.445 +        }
  32.446      }
  32.447      bs->drv = drv;
  32.448      bs->opaque = qemu_mallocz(drv->instance_size);
  32.449      if (bs->opaque == NULL && drv->instance_size > 0)
  32.450          return -1;
  32.451 -    
  32.452 -    ret = drv->bdrv_open(bs, filename);
  32.453 +    /* Note: for compatibility, we open disk image files as RDWR, and
  32.454 +       RDONLY as fallback */
  32.455 +    if (!(flags & BDRV_O_FILE))
  32.456 +        open_flags = BDRV_O_RDWR;
  32.457 +    else
  32.458 +        open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT);
  32.459 +    ret = drv->bdrv_open(bs, filename, open_flags);
  32.460 +    if (ret == -EACCES && !(flags & BDRV_O_FILE)) {
  32.461 +        ret = drv->bdrv_open(bs, filename, BDRV_O_RDONLY);
  32.462 +        bs->read_only = 1;
  32.463 +    }
  32.464      if (ret < 0) {
  32.465          qemu_free(bs->opaque);
  32.466 -        return -1;
  32.467 +        bs->opaque = NULL;
  32.468 +        bs->drv = NULL;
  32.469 +        return ret;
  32.470 +    }
  32.471 +    if (drv->bdrv_getlength) {
  32.472 +        bs->total_sectors = bdrv_getlength(bs) >> SECTOR_BITS;
  32.473      }
  32.474  #ifndef _WIN32
  32.475      if (bs->is_temporary) {
  32.476          unlink(filename);
  32.477      }
  32.478  #endif
  32.479 -    if (bs->backing_file[0] != '\0' && drv->bdrv_is_allocated) {
  32.480 +    if (bs->backing_file[0] != '\0') {
  32.481          /* if there is a backing file, use it */
  32.482          bs->backing_hd = bdrv_new("");
  32.483          if (!bs->backing_hd) {
  32.484          fail:
  32.485              bdrv_close(bs);
  32.486 -            return -1;
  32.487 +            return -ENOMEM;
  32.488          }
  32.489 -        if (bdrv_open(bs->backing_hd, bs->backing_file, 0) < 0)
  32.490 +        path_combine(backing_filename, sizeof(backing_filename),
  32.491 +                     filename, bs->backing_file);
  32.492 +        if (bdrv_open(bs->backing_hd, backing_filename, 0) < 0)
  32.493              goto fail;
  32.494      }
  32.495  
  32.496 -    bs->inserted = 1;
  32.497 -
  32.498      /* call the change callback */
  32.499 +    bs->media_changed = 1;
  32.500      if (bs->change_cb)
  32.501          bs->change_cb(bs->change_opaque);
  32.502  
  32.503 @@ -343,7 +423,7 @@ int bdrv_open2(BlockDriverState *bs, con
  32.504  
  32.505  void bdrv_close(BlockDriverState *bs)
  32.506  {
  32.507 -    if (bs->inserted) {
  32.508 +    if (bs->drv) {
  32.509          if (bs->backing_hd)
  32.510              bdrv_delete(bs->backing_hd);
  32.511          bs->drv->bdrv_close(bs);
  32.512 @@ -355,9 +435,9 @@ void bdrv_close(BlockDriverState *bs)
  32.513  #endif
  32.514          bs->opaque = NULL;
  32.515          bs->drv = NULL;
  32.516 -        bs->inserted = 0;
  32.517  
  32.518          /* call the change callback */
  32.519 +        bs->media_changed = 1;
  32.520          if (bs->change_cb)
  32.521              bs->change_cb(bs->change_opaque);
  32.522      }
  32.523 @@ -373,12 +453,13 @@ void bdrv_delete(BlockDriverState *bs)
  32.524  /* commit COW file into the raw image */
  32.525  int bdrv_commit(BlockDriverState *bs)
  32.526  {
  32.527 -    int64_t i;
  32.528 +    BlockDriver *drv = bs->drv;
  32.529 +    int64_t i, total_sectors;
  32.530      int n, j;
  32.531      unsigned char sector[512];
  32.532  
  32.533 -    if (!bs->inserted)
  32.534 -        return -ENOENT;
  32.535 +    if (!drv)
  32.536 +        return -ENOMEDIUM;
  32.537  
  32.538      if (bs->read_only) {
  32.539  	return -EACCES;
  32.540 @@ -388,8 +469,9 @@ int bdrv_commit(BlockDriverState *bs)
  32.541  	return -ENOTSUP;
  32.542      }
  32.543  
  32.544 -    for (i = 0; i < bs->total_sectors;) {
  32.545 -        if (bs->drv->bdrv_is_allocated(bs, i, 65536, &n)) {
  32.546 +    total_sectors = bdrv_getlength(bs) >> SECTOR_BITS;
  32.547 +    for (i = 0; i < total_sectors;) {
  32.548 +        if (drv->bdrv_is_allocated(bs, i, 65536, &n)) {
  32.549              for(j = 0; j < n; j++) {
  32.550                  if (bdrv_read(bs, i, sector, 1) != 0) {
  32.551                      return -EIO;
  32.552 @@ -405,72 +487,241 @@ int bdrv_commit(BlockDriverState *bs)
  32.553          }
  32.554      }
  32.555  
  32.556 -    if (bs->drv->bdrv_make_empty)
  32.557 -	return bs->drv->bdrv_make_empty(bs);
  32.558 +    if (drv->bdrv_make_empty)
  32.559 +	return drv->bdrv_make_empty(bs);
  32.560  
  32.561      return 0;
  32.562  }
  32.563  
  32.564 -/* return -1 if error */
  32.565 +/* return < 0 if error. See bdrv_write() for the return codes */
  32.566  int bdrv_read(BlockDriverState *bs, int64_t sector_num, 
  32.567                uint8_t *buf, int nb_sectors)
  32.568  {
  32.569 -    int ret, n;
  32.570      BlockDriver *drv = bs->drv;
  32.571  
  32.572 -    if (!bs->inserted)
  32.573 -        return -1;
  32.574 +    if (!drv)
  32.575 +        return -ENOMEDIUM;
  32.576 +
  32.577      if (sector_num < 0)
  32.578 -	return -1;
  32.579 +	return -EINVAL;
  32.580  
  32.581 -    while (nb_sectors > 0) {
  32.582 -        if (sector_num == 0 && bs->boot_sector_enabled) {
  32.583 +    if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
  32.584              memcpy(buf, bs->boot_sector_data, 512);
  32.585 -            n = 1;
  32.586 -        } else if (bs->backing_hd) {
  32.587 -            if (drv->bdrv_is_allocated(bs, sector_num, nb_sectors, &n)) {
  32.588 -                ret = drv->bdrv_read(bs, sector_num, buf, n);
  32.589 -                if (ret < 0)
  32.590 -                    return -1;
  32.591 -            } else {
  32.592 -                /* read from the base image */
  32.593 -                ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
  32.594 -                if (ret < 0)
  32.595 -                    return -1;
  32.596 -            }
  32.597 -        } else {
  32.598 -            ret = drv->bdrv_read(bs, sector_num, buf, nb_sectors);
  32.599 -            if (ret < 0)
  32.600 -                return -1;
  32.601 -            /* no need to loop */
  32.602 -            break;
  32.603 -        }
  32.604 -        nb_sectors -= n;
  32.605 -        sector_num += n;
  32.606 -        buf += n * 512;
  32.607 +        sector_num++;
  32.608 +        nb_sectors--;
  32.609 +        buf += 512;
  32.610 +        if (nb_sectors == 0)
  32.611 +            return 0;
  32.612      }
  32.613 -    return 0;
  32.614 +    if (drv->bdrv_pread) {
  32.615 +        int ret, len;
  32.616 +        len = nb_sectors * 512;
  32.617 +        ret = drv->bdrv_pread(bs, sector_num * 512, buf, len);
  32.618 +        if (ret < 0)
  32.619 +            return ret;
  32.620 +        else if (ret != len)
  32.621 +            return -EINVAL;
  32.622 +        else
  32.623 +            return 0;
  32.624 +    } else {
  32.625 +        return drv->bdrv_read(bs, sector_num, buf, nb_sectors);
  32.626 +    }
  32.627  }
  32.628  
  32.629 -/* return -1 if error */
  32.630 +/* Return < 0 if error. Important errors are: 
  32.631 +  -EIO         generic I/O error (may happen for all errors)
  32.632 +  -ENOMEDIUM   No media inserted.
  32.633 +  -EINVAL      Invalid sector number or nb_sectors
  32.634 +  -EACCES      Trying to write a read-only device
  32.635 +*/
  32.636  int bdrv_write(BlockDriverState *bs, int64_t sector_num, 
  32.637                 const uint8_t *buf, int nb_sectors)
  32.638  {
  32.639 -    if (!bs->inserted)
  32.640 -        return -1;
  32.641 +    BlockDriver *drv = bs->drv;
  32.642 +    if (!bs->drv)
  32.643 +        return -ENOMEDIUM;
  32.644      if (bs->read_only)
  32.645 -        return -1;
  32.646 +        return -EACCES;
  32.647      if (sector_num < 0)
  32.648 -	return -1;
  32.649 +	return -EINVAL;
  32.650      if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
  32.651          memcpy(bs->boot_sector_data, buf, 512);   
  32.652      }
  32.653 -    return bs->drv->bdrv_write(bs, sector_num, buf, nb_sectors);
  32.654 +    if (drv->bdrv_pwrite) {
  32.655 +        int ret, len;
  32.656 +        len = nb_sectors * 512;
  32.657 +        ret = drv->bdrv_pwrite(bs, sector_num * 512, buf, len);
  32.658 +        if (ret < 0)
  32.659 +            return ret;
  32.660 +        else if (ret != len)
  32.661 +            return -EIO;
  32.662 +        else
  32.663 +            return 0;
  32.664 +    } else {
  32.665 +        return drv->bdrv_write(bs, sector_num, buf, nb_sectors);
  32.666 +    }
  32.667 +}
  32.668 +
  32.669 +static int bdrv_pread_em(BlockDriverState *bs, int64_t offset, 
  32.670 +                         uint8_t *buf, int count1)
  32.671 +{
  32.672 +    uint8_t tmp_buf[SECTOR_SIZE];
  32.673 +    int len, nb_sectors, count;
  32.674 +    int64_t sector_num;
  32.675 +
  32.676 +    count = count1;
  32.677 +    /* first read to align to sector start */
  32.678 +    len = (SECTOR_SIZE - offset) & (SECTOR_SIZE - 1);
  32.679 +    if (len > count)
  32.680 +        len = count;
  32.681 +    sector_num = offset >> SECTOR_BITS;
  32.682 +    if (len > 0) {
  32.683 +        if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
  32.684 +            return -EIO;
  32.685 +        memcpy(buf, tmp_buf + (offset & (SECTOR_SIZE - 1)), len);
  32.686 +        count -= len;
  32.687 +        if (count == 0)
  32.688 +            return count1;
  32.689 +        sector_num++;
  32.690 +        buf += len;
  32.691 +    }
  32.692 +
  32.693 +    /* read the sectors "in place" */
  32.694 +    nb_sectors = count >> SECTOR_BITS;
  32.695 +    if (nb_sectors > 0) {
  32.696 +        if (bdrv_read(bs, sector_num, buf, nb_sectors) < 0)
  32.697 +            return -EIO;
  32.698 +        sector_num += nb_sectors;
  32.699 +        len = nb_sectors << SECTOR_BITS;
  32.700 +        buf += len;
  32.701 +        count -= len;
  32.702 +    }
  32.703 +
  32.704 +    /* add data from the last sector */
  32.705 +    if (count > 0) {
  32.706 +        if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
  32.707 +            return -EIO;
  32.708 +        memcpy(buf, tmp_buf, count);
  32.709 +    }
  32.710 +    return count1;
  32.711  }
  32.712  
  32.713 +static int bdrv_pwrite_em(BlockDriverState *bs, int64_t offset, 
  32.714 +                          const uint8_t *buf, int count1)
  32.715 +{
  32.716 +    uint8_t tmp_buf[SECTOR_SIZE];
  32.717 +    int len, nb_sectors, count;
  32.718 +    int64_t sector_num;
  32.719 +
  32.720 +    count = count1;
  32.721 +    /* first write to align to sector start */
  32.722 +    len = (SECTOR_SIZE - offset) & (SECTOR_SIZE - 1);
  32.723 +    if (len > count)
  32.724 +        len = count;
  32.725 +    sector_num = offset >> SECTOR_BITS;
  32.726 +    if (len > 0) {
  32.727 +        if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
  32.728 +            return -EIO;
  32.729 +        memcpy(tmp_buf + (offset & (SECTOR_SIZE - 1)), buf, len);
  32.730 +        if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)
  32.731 +            return -EIO;
  32.732 +        count -= len;
  32.733 +        if (count == 0)
  32.734 +            return count1;
  32.735 +        sector_num++;
  32.736 +        buf += len;
  32.737 +    }
  32.738 +
  32.739 +    /* write the sectors "in place" */
  32.740 +    nb_sectors = count >> SECTOR_BITS;
  32.741 +    if (nb_sectors > 0) {
  32.742 +        if (bdrv_write(bs, sector_num, buf, nb_sectors) < 0)
  32.743 +            return -EIO;
  32.744 +        sector_num += nb_sectors;
  32.745 +        len = nb_sectors << SECTOR_BITS;
  32.746 +        buf += len;
  32.747 +        count -= len;
  32.748 +    }
  32.749 +
  32.750 +    /* add data from the last sector */
  32.751 +    if (count > 0) {
  32.752 +        if (bdrv_read(bs, sector_num, tmp_buf, 1) < 0)
  32.753 +            return -EIO;
  32.754 +        memcpy(tmp_buf, buf, count);
  32.755 +        if (bdrv_write(bs, sector_num, tmp_buf, 1) < 0)
  32.756 +            return -EIO;
  32.757 +    }
  32.758 +    return count1;
  32.759 +}
  32.760 +
  32.761 +/**
  32.762 + * Read with byte offsets (needed only for file protocols) 
  32.763 + */
  32.764 +int bdrv_pread(BlockDriverState *bs, int64_t offset, 
  32.765 +               void *buf1, int count1)
  32.766 +{
  32.767 +    BlockDriver *drv = bs->drv;
  32.768 +
  32.769 +    if (!drv)
  32.770 +        return -ENOMEDIUM;
  32.771 +    if (!drv->bdrv_pread)
  32.772 +        return bdrv_pread_em(bs, offset, buf1, count1);
  32.773 +    return drv->bdrv_pread(bs, offset, buf1, count1);
  32.774 +}
  32.775 +
  32.776 +/** 
  32.777 + * Write with byte offsets (needed only for file protocols) 
  32.778 + */
  32.779 +int bdrv_pwrite(BlockDriverState *bs, int64_t offset, 
  32.780 +                const void *buf1, int count1)
  32.781 +{
  32.782 +    BlockDriver *drv = bs->drv;
  32.783 +
  32.784 +    if (!drv)
  32.785 +        return -ENOMEDIUM;
  32.786 +    if (!drv->bdrv_pwrite)
  32.787 +        return bdrv_pwrite_em(bs, offset, buf1, count1);
  32.788 +    return drv->bdrv_pwrite(bs, offset, buf1, count1);
  32.789 +}
  32.790 +
  32.791 +/**
  32.792 + * Truncate file to 'offset' bytes (needed only for file protocols)
  32.793 + */
  32.794 +int bdrv_truncate(BlockDriverState *bs, int64_t offset)
  32.795 +{
  32.796 +    BlockDriver *drv = bs->drv;
  32.797 +    if (!drv)
  32.798 +        return -ENOMEDIUM;
  32.799 +    if (!drv->bdrv_truncate)
  32.800 +        return -ENOTSUP;
  32.801 +    return drv->bdrv_truncate(bs, offset);
  32.802 +}
  32.803 +
  32.804 +/**
  32.805 + * Length of a file in bytes. Return < 0 if error or unknown.
  32.806 + */
  32.807 +int64_t bdrv_getlength(BlockDriverState *bs)
  32.808 +{
  32.809 +    BlockDriver *drv = bs->drv;
  32.810 +    if (!drv)
  32.811 +        return -ENOMEDIUM;
  32.812 +    if (!drv->bdrv_getlength) {
  32.813 +        /* legacy mode */
  32.814 +        return bs->total_sectors * SECTOR_SIZE;
  32.815 +    }
  32.816 +    return drv->bdrv_getlength(bs);
  32.817 +}
  32.818 +
  32.819 +/* return 0 as number of sectors if no device present or error */
  32.820  void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr)
  32.821  {
  32.822 -    *nb_sectors_ptr = bs->total_sectors;
  32.823 +    int64_t length;
  32.824 +    length = bdrv_getlength(bs);
  32.825 +    if (length < 0)
  32.826 +        length = 0;
  32.827 +    else
  32.828 +        length = length >> SECTOR_BITS;
  32.829 +    *nb_sectors_ptr = length;
  32.830  }
  32.831  
  32.832  /* force a given boot sector. */
  32.833 @@ -531,21 +782,7 @@ int bdrv_is_read_only(BlockDriverState *
  32.834      return bs->read_only;
  32.835  }
  32.836  
  32.837 -int bdrv_is_inserted(BlockDriverState *bs)
  32.838 -{
  32.839 -    return bs->inserted;
  32.840 -}
  32.841 -
  32.842 -int bdrv_is_locked(BlockDriverState *bs)
  32.843 -{
  32.844 -    return bs->locked;
  32.845 -}
  32.846 -
  32.847 -void bdrv_set_locked(BlockDriverState *bs, int locked)
  32.848 -{
  32.849 -    bs->locked = locked;
  32.850 -}
  32.851 -
  32.852 +/* XXX: no longer used */
  32.853  void bdrv_set_change_cb(BlockDriverState *bs, 
  32.854                          void (*change_cb)(void *opaque), void *opaque)
  32.855  {
  32.856 @@ -577,7 +814,7 @@ int bdrv_set_key(BlockDriverState *bs, c
  32.857  
  32.858  void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
  32.859  {
  32.860 -    if (!bs->inserted || !bs->drv) {
  32.861 +    if (!bs->drv) {
  32.862          buf[0] = '\0';
  32.863      } else {
  32.864          pstrcpy(buf, buf_size, bs->drv->format_name);
  32.865 @@ -649,10 +886,13 @@ void bdrv_info(void)
  32.866          if (bs->removable) {
  32.867              term_printf(" locked=%d", bs->locked);
  32.868          }
  32.869 -        if (bs->inserted) {
  32.870 -            term_printf(" file=%s", bs->filename);
  32.871 -            if (bs->backing_file[0] != '\0')
  32.872 -                term_printf(" backing_file=%s", bs->backing_file);
  32.873 +        if (bs->drv) {
  32.874 +            term_printf(" file=");
  32.875 +	    term_print_filename(bs->filename);
  32.876 +            if (bs->backing_file[0] != '\0') {
  32.877 +                term_printf(" backing_file=");
  32.878 +		term_print_filename(bs->backing_file);
  32.879 +	    }
  32.880              term_printf(" ro=%d", bs->read_only);
  32.881              term_printf(" drv=%s", bs->drv->format_name);
  32.882              if (bs->encrypted)
  32.883 @@ -664,192 +904,337 @@ void bdrv_info(void)
  32.884      }
  32.885  }
  32.886  
  32.887 -/**************************************************************/
  32.888 -/* RAW block driver */
  32.889 +void bdrv_get_backing_filename(BlockDriverState *bs, 
  32.890 +                               char *filename, int filename_size)
  32.891 +{
  32.892 +    if (!bs->backing_hd) {
  32.893 +        pstrcpy(filename, filename_size, "");
  32.894 +    } else {
  32.895 +        pstrcpy(filename, filename_size, bs->backing_file);
  32.896 +    }
  32.897 +}
  32.898 +
  32.899 +int bdrv_write_compressed(BlockDriverState *bs, int64_t sector_num, 
  32.900 +                          const uint8_t *buf, int nb_sectors)
  32.901 +{
  32.902 +    BlockDriver *drv = bs->drv;
  32.903 +    if (!drv)
  32.904 +        return -ENOMEDIUM;
  32.905 +    if (!drv->bdrv_write_compressed)
  32.906 +        return -ENOTSUP;
  32.907 +    return drv->bdrv_write_compressed(bs, sector_num, buf, nb_sectors);
  32.908 +}
  32.909 +    
  32.910 +int bdrv_get_info(BlockDriverState *bs, BlockDriverInfo *bdi)
  32.911 +{
  32.912 +    BlockDriver *drv = bs->drv;
  32.913 +    if (!drv)
  32.914 +        return -ENOMEDIUM;
  32.915 +    if (!drv->bdrv_get_info)
  32.916 +        return -ENOTSUP;
  32.917 +    memset(bdi, 0, sizeof(*bdi));
  32.918 +    return drv->bdrv_get_info(bs, bdi);
  32.919 +}
  32.920  
  32.921 -typedef struct BDRVRawState {
  32.922 -    int fd;
  32.923 -} BDRVRawState;
  32.924 +/**************************************************************/
  32.925 +/* handling of snapshots */
  32.926 +
  32.927 +int bdrv_snapshot_create(BlockDriverState *bs, 
  32.928 +                         QEMUSnapshotInfo *sn_info)
  32.929 +{
  32.930 +    BlockDriver *drv = bs->drv;
  32.931 +    if (!drv)
  32.932 +        return -ENOMEDIUM;
  32.933 +    if (!drv->bdrv_snapshot_create)
  32.934 +        return -ENOTSUP;
  32.935 +    return drv->bdrv_snapshot_create(bs, sn_info);
  32.936 +}
  32.937  
  32.938 -static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
  32.939 +int bdrv_snapshot_goto(BlockDriverState *bs, 
  32.940 +                       const char *snapshot_id)
  32.941  {
  32.942 -    return 1; /* maybe */
  32.943 +    BlockDriver *drv = bs->drv;
  32.944 +    if (!drv)
  32.945 +        return -ENOMEDIUM;
  32.946 +    if (!drv->bdrv_snapshot_goto)
  32.947 +        return -ENOTSUP;
  32.948 +    return drv->bdrv_snapshot_goto(bs, snapshot_id);
  32.949 +}
  32.950 +
  32.951 +int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
  32.952 +{
  32.953 +    BlockDriver *drv = bs->drv;
  32.954 +    if (!drv)
  32.955 +        return -ENOMEDIUM;
  32.956 +    if (!drv->bdrv_snapshot_delete)
  32.957 +        return -ENOTSUP;
  32.958 +    return drv->bdrv_snapshot_delete(bs, snapshot_id);
  32.959  }
  32.960  
  32.961 -static int raw_open(BlockDriverState *bs, const char *filename)
  32.962 +int bdrv_snapshot_list(BlockDriverState *bs, 
  32.963 +                       QEMUSnapshotInfo **psn_info)
  32.964 +{
  32.965 +    BlockDriver *drv = bs->drv;
  32.966 +    if (!drv)
  32.967 +        return -ENOMEDIUM;
  32.968 +    if (!drv->bdrv_snapshot_list)
  32.969 +        return -ENOTSUP;
  32.970 +    return drv->bdrv_snapshot_list(bs, psn_info);
  32.971 +}
  32.972 +
  32.973 +#define NB_SUFFIXES 4
  32.974 +
  32.975 +char *get_human_readable_size(char *buf, int buf_size, int64_t size)
  32.976  {
  32.977 -    BDRVRawState *s = bs->opaque;
  32.978 -    int fd;
  32.979 -    int64_t size;
  32.980 -#ifdef _BSD
  32.981 -    struct stat sb;
  32.982 -#endif
  32.983 -#ifdef __sun__
  32.984 -    struct dk_minfo minfo;
  32.985 -    int rv;
  32.986 -#endif
  32.987 +    static const char suffixes[NB_SUFFIXES] = "KMGT";
  32.988 +    int64_t base;
  32.989 +    int i;
  32.990  
  32.991 -    fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
  32.992 -    if (fd < 0) {
  32.993 -        fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
  32.994 -        if (fd < 0)
  32.995 -            return -1;
  32.996 -        bs->read_only = 1;
  32.997 +    if (size <= 999) {
  32.998 +        snprintf(buf, buf_size, "%" PRId64, size);
  32.999 +    } else {
 32.1000 +        base = 1024;
 32.1001 +        for(i = 0; i < NB_SUFFIXES; i++) {
 32.1002 +            if (size < (10 * base)) {
 32.1003 +                snprintf(buf, buf_size, "%0.1f%c", 
 32.1004 +                         (double)size / base,
 32.1005 +                         suffixes[i]);
 32.1006 +                break;
 32.1007 +            } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) {
 32.1008 +                snprintf(buf, buf_size, "%" PRId64 "%c", 
 32.1009 +                         ((size + (base >> 1)) / base),
 32.1010 +                         suffixes[i]);
 32.1011 +                break;
 32.1012 +            }
 32.1013 +            base = base * 1024;
 32.1014 +        }
 32.1015      }
 32.1016 -#ifdef _BSD
 32.1017 -    if (!fstat(fd, &sb) && (S_IFCHR & sb.st_mode)) {
 32.1018 -#ifdef DIOCGMEDIASIZE
 32.1019 -	if (ioctl(fd, DIOCGMEDIASIZE, (off_t *)&size))
 32.1020 -#endif
 32.1021 -#ifdef CONFIG_COCOA
 32.1022 -        size = LONG_LONG_MAX;
 32.1023 -#else
 32.1024 -        size = lseek(fd, 0LL, SEEK_END);
 32.1025 -#endif
 32.1026 -    } else
 32.1027 -#endif
 32.1028 -#ifdef __sun__
 32.1029 -    /*
 32.1030 -     * use the DKIOCGMEDIAINFO ioctl to read the size.
 32.1031 -     */
 32.1032 -    rv = ioctl ( fd, DKIOCGMEDIAINFO, &minfo );
 32.1033 -    if ( rv != -1 ) {
 32.1034 -        size = minfo.dki_lbsize * minfo.dki_capacity;
 32.1035 -    } else /* there are reports that lseek on some devices
 32.1036 -              fails, but irc discussion said that contingency
 32.1037 -              on contingency was overkill */
 32.1038 -#endif
 32.1039 -    {
 32.1040 -        size = lseek(fd, 0, SEEK_END);
 32.1041 -    }
 32.1042 -#ifdef _WIN32
 32.1043 -    /* On Windows hosts it can happen that we're unable to get file size
 32.1044 -       for CD-ROM raw device (it's inherent limitation of the CDFS driver). */
 32.1045 -    if (size == -1)
 32.1046 -        size = LONG_LONG_MAX;
 32.1047 -#endif
 32.1048 -    bs->total_sectors = size / 512;
 32.1049 -    s->fd = fd;
 32.1050 -    return 0;
 32.1051 +    return buf;
 32.1052  }
 32.1053  
 32.1054 -static int raw_read(BlockDriverState *bs, int64_t sector_num, 
 32.1055 -                    uint8_t *buf, int nb_sectors)
 32.1056 +char *bdrv_snapshot_dump(char *buf, int buf_size, QEMUSnapshotInfo *sn)
 32.1057  {
 32.1058 -    BDRVRawState *s = bs->opaque;
 32.1059 -    int ret;
 32.1060 -    
 32.1061 -    lseek(s->fd, sector_num * 512, SEEK_SET);
 32.1062 -    ret = read(s->fd, buf, nb_sectors * 512);
 32.1063 -    if (ret != nb_sectors * 512) 
 32.1064 -        return -1;
 32.1065 -    return 0;
 32.1066 +    char buf1[128], date_buf[128], clock_buf[128];
 32.1067 +#ifdef _WIN32
 32.1068 +    struct tm *ptm;
 32.1069 +#else
 32.1070 +    struct tm tm;
 32.1071 +#endif
 32.1072 +    time_t ti;
 32.1073 +    int64_t secs;
 32.1074 +
 32.1075 +    if (!sn) {
 32.1076 +        snprintf(buf, buf_size, 
 32.1077 +                 "%-10s%-20s%7s%20s%15s", 
 32.1078 +                 "ID", "TAG", "VM SIZE", "DATE", "VM CLOCK");
 32.1079 +    } else {
 32.1080 +        ti = sn->date_sec;
 32.1081 +#ifdef _WIN32
 32.1082 +        ptm = localtime(&ti);
 32.1083 +        strftime(date_buf, sizeof(date_buf),
 32.1084 +                 "%Y-%m-%d %H:%M:%S", ptm);
 32.1085 +#else
 32.1086 +        localtime_r(&ti, &tm);
 32.1087 +        strftime(date_buf, sizeof(date_buf),
 32.1088 +                 "%Y-%m-%d %H:%M:%S", &tm);
 32.1089 +#endif
 32.1090 +        secs = sn->vm_clock_nsec / 1000000000;
 32.1091 +        snprintf(clock_buf, sizeof(clock_buf),
 32.1092 +                 "%02d:%02d:%02d.%03d",
 32.1093 +                 (int)(secs / 3600),
 32.1094 +                 (int)((secs / 60) % 60),
 32.1095 +                 (int)(secs % 60), 
 32.1096 +                 (int)((sn->vm_clock_nsec / 1000000) % 1000));
 32.1097 +        snprintf(buf, buf_size,
 32.1098 +                 "%-10s%-20s%7s%20s%15s", 
 32.1099 +                 sn->id_str, sn->name,
 32.1100 +                 get_human_readable_size(buf1, sizeof(buf1), sn->vm_state_size),
 32.1101 +                 date_buf,
 32.1102 +                 clock_buf);
 32.1103 +    }
 32.1104 +    return buf;
 32.1105  }
 32.1106  
 32.1107 -static int raw_write(BlockDriverState *bs, int64_t sector_num, 
 32.1108 -                     const uint8_t *buf, int nb_sectors)
 32.1109 +
 32.1110 +/**************************************************************/
 32.1111 +/* async I/Os */
 32.1112 +
 32.1113 +BlockDriverAIOCB *bdrv_aio_read(BlockDriverState *bs, int64_t sector_num,
 32.1114 +                                uint8_t *buf, int nb_sectors,
 32.1115 +                                BlockDriverCompletionFunc *cb, void *opaque)
 32.1116  {
 32.1117 -    BDRVRawState *s = bs->opaque;
 32.1118 -    int ret;
 32.1119 +    BlockDriver *drv = bs->drv;
 32.1120 +
 32.1121 +    if (!drv)
 32.1122 +        return NULL;
 32.1123      
 32.1124 -    lseek(s->fd, sector_num * 512, SEEK_SET);
 32.1125 -    ret = write(s->fd, buf, nb_sectors * 512);
 32.1126 -    if (ret != nb_sectors * 512) 
 32.1127 -        return -1;
 32.1128 -    return 0;
 32.1129 +    /* XXX: we assume that nb_sectors == 0 is suppored by the async read */
 32.1130 +    if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
 32.1131 +        memcpy(buf, bs->boot_sector_data, 512);
 32.1132 +        sector_num++;
 32.1133 +        nb_sectors--;
 32.1134 +        buf += 512;
 32.1135 +    }
 32.1136 +
 32.1137 +    return drv->bdrv_aio_read(bs, sector_num, buf, nb_sectors, cb, opaque);
 32.1138 +}
 32.1139 +
 32.1140 +BlockDriverAIOCB *bdrv_aio_write(BlockDriverState *bs, int64_t sector_num,
 32.1141 +                                 const uint8_t *buf, int nb_sectors,
 32.1142 +                                 BlockDriverCompletionFunc *cb, void *opaque)
 32.1143 +{
 32.1144 +    BlockDriver *drv = bs->drv;
 32.1145 +
 32.1146 +    if (!drv)
 32.1147 +        return NULL;
 32.1148 +    if (bs->read_only)
 32.1149 +        return NULL;
 32.1150 +    if (sector_num == 0 && bs->boot_sector_enabled && nb_sectors > 0) {
 32.1151 +        memcpy(bs->boot_sector_data, buf, 512);   
 32.1152 +    }
 32.1153 +
 32.1154 +    return drv->bdrv_aio_write(bs, sector_num, buf, nb_sectors, cb, opaque);
 32.1155  }
 32.1156  
 32.1157 -static void raw_close(BlockDriverState *bs)
 32.1158 +void bdrv_aio_cancel(BlockDriverAIOCB *acb)
 32.1159 +{
 32.1160 +    BlockDriver *drv = acb->bs->drv;
 32.1161 +
 32.1162 +    drv->bdrv_aio_cancel(acb);
 32.1163 +}
 32.1164 +
 32.1165 +
 32.1166 +/**************************************************************/
 32.1167 +/* async block device emulation */
 32.1168 +
 32.1169 +#ifdef QEMU_TOOL
 32.1170 +static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
 32.1171 +        int64_t sector_num, uint8_t *buf, int nb_sectors,
 32.1172 +        BlockDriverCompletionFunc *cb, void *opaque)
 32.1173  {
 32.1174 -    BDRVRawState *s = bs->opaque;
 32.1175 -    bs->total_sectors = 0;
 32.1176 -    close(s->fd);
 32.1177 +    int ret;
 32.1178 +    ret = bdrv_read(bs, sector_num, buf, nb_sectors);
 32.1179 +    cb(opaque, ret);
 32.1180 +    return NULL;
 32.1181 +}
 32.1182 +
 32.1183 +static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
 32.1184 +        int64_t sector_num, const uint8_t *buf, int nb_sectors,
 32.1185 +        BlockDriverCompletionFunc *cb, void *opaque)
 32.1186 +{
 32.1187 +    int ret;
 32.1188 +    ret = bdrv_write(bs, sector_num, buf, nb_sectors);
 32.1189 +    cb(opaque, ret);
 32.1190 +    return NULL;
 32.1191 +}
 32.1192 +
 32.1193 +static void bdrv_aio_cancel_em(BlockDriverAIOCB *acb)
 32.1194 +{
 32.1195 +}
 32.1196 +#else
 32.1197 +static void bdrv_aio_bh_cb(void *opaque)
 32.1198 +{
 32.1199 +    BlockDriverAIOCBSync *acb = opaque;
 32.1200 +    acb->common.cb(acb->common.opaque, acb->ret);
 32.1201 +    qemu_aio_release(acb);
 32.1202  }
 32.1203  
 32.1204 -#ifdef _WIN32
 32.1205 -#include <windows.h>
 32.1206 -#include <winioctl.h>
 32.1207 -
 32.1208 -int qemu_ftruncate64(int fd, int64_t length)
 32.1209 +static BlockDriverAIOCB *bdrv_aio_read_em(BlockDriverState *bs,
 32.1210 +        int64_t sector_num, uint8_t *buf, int nb_sectors,
 32.1211 +        BlockDriverCompletionFunc *cb, void *opaque)
 32.1212  {
 32.1213 -    LARGE_INTEGER li;
 32.1214 -    LONG high;
 32.1215 -    HANDLE h;
 32.1216 -    BOOL res;
 32.1217 -
 32.1218 -    if ((GetVersion() & 0x80000000UL) && (length >> 32) != 0)
 32.1219 -	return -1;
 32.1220 +    BlockDriverAIOCBSync *acb;
 32.1221 +    int ret;
 32.1222  
 32.1223 -    h = (HANDLE)_get_osfhandle(fd);
 32.1224 -
 32.1225 -    /* get current position, ftruncate do not change position */
 32.1226 -    li.HighPart = 0;
 32.1227 -    li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_CURRENT);
 32.1228 -    if (li.LowPart == 0xffffffffUL && GetLastError() != NO_ERROR)
 32.1229 -	return -1;
 32.1230 +    acb = qemu_aio_get(bs, cb, opaque);
 32.1231 +    if (!acb->bh)
 32.1232 +        acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
 32.1233 +    ret = bdrv_read(bs, sector_num, buf, nb_sectors);
 32.1234 +    acb->ret = ret;
 32.1235 +    qemu_bh_schedule(acb->bh);
 32.1236 +    return &acb->common;
 32.1237 +}
 32.1238  
 32.1239 -    high = length >> 32;
 32.1240 -    if (!SetFilePointer(h, (DWORD) length, &high, FILE_BEGIN))
 32.1241 -	return -1;
 32.1242 -    res = SetEndOfFile(h);
 32.1243 +static BlockDriverAIOCB *bdrv_aio_write_em(BlockDriverState *bs,
 32.1244 +        int64_t sector_num, const uint8_t *buf, int nb_sectors,
 32.1245 +        BlockDriverCompletionFunc *cb, void *opaque)
 32.1246 +{
 32.1247 +    BlockDriverAIOCBSync *acb;
 32.1248 +    int ret;
 32.1249  
 32.1250 -    /* back to old position */
 32.1251 -    SetFilePointer(h, li.LowPart, &li.HighPart, FILE_BEGIN);
 32.1252 -    return res ? 0 : -1;
 32.1253 +    acb = qemu_aio_get(bs, cb, opaque);
 32.1254 +    if (!acb->bh)
 32.1255 +        acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
 32.1256 +    ret = bdrv_write(bs, sector_num, buf, nb_sectors);
 32.1257 +    acb->ret = ret;
 32.1258 +    qemu_bh_schedule(acb->bh);
 32.1259 +    return &acb->common;
 32.1260  }
 32.1261  
 32.1262 -static int set_sparse(int fd)
 32.1263 +static void bdrv_aio_cancel_em(BlockDriverAIOCB *blockacb)
 32.1264  {
 32.1265 -    DWORD returned;
 32.1266 -    return (int) DeviceIoControl((HANDLE)_get_osfhandle(fd), FSCTL_SET_SPARSE,
 32.1267 -				 NULL, 0, NULL, 0, &returned, NULL);
 32.1268 +    BlockDriverAIOCBSync *acb = (BlockDriverAIOCBSync *)blockacb;
 32.1269 +    qemu_bh_cancel(acb->bh);
 32.1270 +    qemu_aio_release(acb);
 32.1271  }
 32.1272 -#else
 32.1273 -static inline int set_sparse(int fd)
 32.1274 -{
 32.1275 -    return 1;
 32.1276 -}
 32.1277 -#endif
 32.1278 +#endif /* !QEMU_TOOL */
 32.1279  
 32.1280 -static int raw_create(const char *filename, int64_t total_size,
 32.1281 -                      const char *backing_file, int flags)
 32.1282 -{
 32.1283 -    int fd;
 32.1284 -
 32.1285 -    if (flags || backing_file)
 32.1286 -        return -ENOTSUP;
 32.1287 +/**************************************************************/
 32.1288 +/* sync block device emulation */
 32.1289  
 32.1290 -    fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE, 
 32.1291 -              0644);
 32.1292 -    if (fd < 0)
 32.1293 -        return -EIO;
 32.1294 -    set_sparse(fd);
 32.1295 -    ftruncate(fd, total_size * 512);
 32.1296 -    close(fd);
 32.1297 -    return 0;
 32.1298 +static void bdrv_rw_em_cb(void *opaque, int ret)
 32.1299 +{
 32.1300 +    *(int *)opaque = ret;
 32.1301  }
 32.1302  
 32.1303 -static void raw_flush(BlockDriverState *bs)
 32.1304 +#define NOT_DONE 0x7fffffff
 32.1305 +
 32.1306 +static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num, 
 32.1307 +                        uint8_t *buf, int nb_sectors)
 32.1308  {
 32.1309 -    BDRVRawState *s = bs->opaque;
 32.1310 -    fsync(s->fd);
 32.1311 +    int async_ret;
 32.1312 +    BlockDriverAIOCB *acb;
 32.1313 +
 32.1314 +    async_ret = NOT_DONE;
 32.1315 +    qemu_aio_wait_start();
 32.1316 +    acb = bdrv_aio_read(bs, sector_num, buf, nb_sectors, 
 32.1317 +                        bdrv_rw_em_cb, &async_ret);
 32.1318 +    if (acb == NULL) {
 32.1319 +        qemu_aio_wait_end();
 32.1320 +        return -1;
 32.1321 +    }
 32.1322 +    while (async_ret == NOT_DONE) {
 32.1323 +        qemu_aio_wait();
 32.1324 +    }
 32.1325 +    qemu_aio_wait_end();
 32.1326 +    return async_ret;
 32.1327  }
 32.1328  
 32.1329 -BlockDriver bdrv_raw = {
 32.1330 -    "raw",
 32.1331 -    sizeof(BDRVRawState),
 32.1332 -    raw_probe,
 32.1333 -    raw_open,
 32.1334 -    raw_read,
 32.1335 -    raw_write,
 32.1336 -    raw_close,
 32.1337 -    raw_create,
 32.1338 -    raw_flush,
 32.1339 -};
 32.1340 +static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
 32.1341 +                         const uint8_t *buf, int nb_sectors)
 32.1342 +{
 32.1343 +    int async_ret;
 32.1344 +    BlockDriverAIOCB *acb;
 32.1345 +
 32.1346 +    async_ret = NOT_DONE;
 32.1347 +    qemu_aio_wait_start();
 32.1348 +    acb = bdrv_aio_write(bs, sector_num, buf, nb_sectors, 
 32.1349 +                         bdrv_rw_em_cb, &async_ret);
 32.1350 +    if (acb == NULL) {
 32.1351 +        qemu_aio_wait_end();
 32.1352 +        return -1;
 32.1353 +    }
 32.1354 +    while (async_ret == NOT_DONE) {
 32.1355 +        qemu_aio_wait();
 32.1356 +    }
 32.1357 +    qemu_aio_wait_end();
 32.1358 +    return async_ret;
 32.1359 +}
 32.1360  
 32.1361  void bdrv_init(void)
 32.1362  {
 32.1363      bdrv_register(&bdrv_raw);
 32.1364 +    bdrv_register(&bdrv_host_device);
 32.1365  #ifndef _WIN32
 32.1366      bdrv_register(&bdrv_cow);
 32.1367  #endif
 32.1368 @@ -860,4 +1245,109 @@ void bdrv_init(void)
 32.1369      bdrv_register(&bdrv_bochs);
 32.1370      bdrv_register(&bdrv_vpc);
 32.1371      bdrv_register(&bdrv_vvfat);
 32.1372 +    bdrv_register(&bdrv_qcow2);
 32.1373  }
 32.1374 +
 32.1375 +void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb,
 32.1376 +                   void *opaque)
 32.1377 +{
 32.1378 +    BlockDriver *drv;
 32.1379 +    BlockDriverAIOCB *acb;
 32.1380 +
 32.1381 +    drv = bs->drv;
 32.1382 +    if (drv->free_aiocb) {
 32.1383 +        acb = drv->free_aiocb;
 32.1384 +        drv->free_aiocb = acb->next;
 32.1385 +    } else {
 32.1386 +        acb = qemu_mallocz(drv->aiocb_size);
 32.1387 +        if (!acb)
 32.1388 +            return NULL;
 32.1389 +    }
 32.1390 +    acb->bs = bs;
 32.1391 +    acb->cb = cb;
 32.1392 +    acb->opaque = opaque;
 32.1393 +    return acb;
 32.1394 +}
 32.1395 +
 32.1396 +void qemu_aio_release(void *p)
 32.1397 +{
 32.1398 +    BlockDriverAIOCB *acb = p;
 32.1399 +    BlockDriver *drv = acb->bs->drv;
 32.1400 +    acb->next = drv->free_aiocb;
 32.1401 +    drv->free_aiocb = acb;
 32.1402 +}
 32.1403 +
 32.1404 +/**************************************************************/
 32.1405 +/* removable device support */
 32.1406 +
 32.1407 +/**
 32.1408 + * Return TRUE if the media is present
 32.1409 + */
 32.1410 +int bdrv_is_inserted(BlockDriverState *bs)
 32.1411 +{
 32.1412 +    BlockDriver *drv = bs->drv;
 32.1413 +    int ret;
 32.1414 +    if (!drv)
 32.1415 +        return 0;
 32.1416 +    if (!drv->bdrv_is_inserted)
 32.1417 +        return 1;
 32.1418 +    ret = drv->bdrv_is_inserted(bs);
 32.1419 +    return ret;
 32.1420 +}
 32.1421 +
 32.1422 +/**
 32.1423 + * Return TRUE if the media changed since the last call to this
 32.1424 + * function. It is currently only used for floppy disks 
 32.1425 + */
 32.1426 +int bdrv_media_changed(BlockDriverState *bs)
 32.1427 +{
 32.1428 +    BlockDriver *drv = bs->drv;
 32.1429 +    int ret;
 32.1430 +
 32.1431 +    if (!drv || !drv->bdrv_media_changed)
 32.1432 +        ret = -ENOTSUP;
 32.1433 +    else
 32.1434 +        ret = drv->bdrv_media_changed(bs);
 32.1435 +    if (ret == -ENOTSUP)
 32.1436 +        ret = bs->media_changed;
 32.1437 +    bs->media_changed = 0;
 32.1438 +    return ret;
 32.1439 +}
 32.1440 +
 32.1441 +/**
 32.1442 + * If eject_flag is TRUE, eject the media. Otherwise, close the tray
 32.1443 + */
 32.1444 +void bdrv_eject(BlockDriverState *bs, int eject_flag)
 32.1445 +{
 32.1446 +    BlockDriver *drv = bs->drv;
 32.1447 +    int ret;
 32.1448 +
 32.1449 +    if (!drv || !drv->bdrv_eject) {
 32.1450 +        ret = -ENOTSUP;
 32.1451 +    } else {
 32.1452 +        ret = drv->bdrv_eject(bs, eject_flag);
 32.1453 +    }
 32.1454 +    if (ret == -ENOTSUP) {
 32.1455 +        if (eject_flag)
 32.1456 +            bdrv_close(bs);
 32.1457 +    }
 32.1458 +}
 32.1459 +
 32.1460 +int bdrv_is_locked(BlockDriverState *bs)
 32.1461 +{
 32.1462 +    return bs->locked;
 32.1463 +}
 32.1464 +
 32.1465 +/**
 32.1466 + * Lock or unlock the media (if it is locked, the user won't be able
 32.1467 + * to eject it manually).
 32.1468 + */
 32.1469 +void bdrv_set_locked(BlockDriverState *bs, int locked)
 32.1470 +{
 32.1471 +    BlockDriver *drv = bs->drv;
 32.1472 +
 32.1473 +    bs->locked = locked;
 32.1474 +    if (drv && drv->bdrv_set_locked) {
 32.1475 +        drv->bdrv_set_locked(bs, locked);
 32.1476 +    }
 32.1477 +}
    33.1 --- a/tools/ioemu/block_int.h	Wed May 16 10:42:07 2007 -0600
    33.2 +++ b/tools/ioemu/block_int.h	Wed May 16 10:59:01 2007 -0600
    33.3 @@ -28,7 +28,7 @@ struct BlockDriver {
    33.4      const char *format_name;
    33.5      int instance_size;
    33.6      int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename);
    33.7 -    int (*bdrv_open)(BlockDriverState *bs, const char *filename);
    33.8 +    int (*bdrv_open)(BlockDriverState *bs, const char *filename, int flags);
    33.9      int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num, 
   33.10                       uint8_t *buf, int nb_sectors);
   33.11      int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num, 
   33.12 @@ -41,13 +41,49 @@ struct BlockDriver {
   33.13                               int nb_sectors, int *pnum);
   33.14      int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
   33.15      int (*bdrv_make_empty)(BlockDriverState *bs);
   33.16 +    /* aio */
   33.17 +    BlockDriverAIOCB *(*bdrv_aio_read)(BlockDriverState *bs,
   33.18 +        int64_t sector_num, uint8_t *buf, int nb_sectors,
   33.19 +        BlockDriverCompletionFunc *cb, void *opaque);
   33.20 +    BlockDriverAIOCB *(*bdrv_aio_write)(BlockDriverState *bs,
   33.21 +        int64_t sector_num, const uint8_t *buf, int nb_sectors,
   33.22 +        BlockDriverCompletionFunc *cb, void *opaque);
   33.23 +    void (*bdrv_aio_cancel)(BlockDriverAIOCB *acb);
   33.24 +    int aiocb_size;
   33.25 +
   33.26 +    const char *protocol_name;
   33.27 +    int (*bdrv_pread)(BlockDriverState *bs, int64_t offset, 
   33.28 +                      uint8_t *buf, int count);
   33.29 +    int (*bdrv_pwrite)(BlockDriverState *bs, int64_t offset, 
   33.30 +                       const uint8_t *buf, int count);
   33.31 +    int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset);
   33.32 +    int64_t (*bdrv_getlength)(BlockDriverState *bs);
   33.33 +    int (*bdrv_write_compressed)(BlockDriverState *bs, int64_t sector_num, 
   33.34 +                                 const uint8_t *buf, int nb_sectors);
   33.35 +
   33.36 +    int (*bdrv_snapshot_create)(BlockDriverState *bs, 
   33.37 +                                QEMUSnapshotInfo *sn_info);
   33.38 +    int (*bdrv_snapshot_goto)(BlockDriverState *bs, 
   33.39 +                              const char *snapshot_id);
   33.40 +    int (*bdrv_snapshot_delete)(BlockDriverState *bs, const char *snapshot_id);
   33.41 +    int (*bdrv_snapshot_list)(BlockDriverState *bs, 
   33.42 +                              QEMUSnapshotInfo **psn_info);
   33.43 +    int (*bdrv_get_info)(BlockDriverState *bs, BlockDriverInfo *bdi);
   33.44 +
   33.45 +    /* removable device specific */
   33.46 +    int (*bdrv_is_inserted)(BlockDriverState *bs);
   33.47 +    int (*bdrv_media_changed)(BlockDriverState *bs);
   33.48 +    int (*bdrv_eject)(BlockDriverState *bs, int eject_flag);
   33.49 +    int (*bdrv_set_locked)(BlockDriverState *bs, int locked);
   33.50 +    
   33.51 +    BlockDriverAIOCB *free_aiocb;
   33.52      struct BlockDriver *next;
   33.53  };
   33.54  
   33.55  struct BlockDriverState {
   33.56 -    int64_t total_sectors;
   33.57 +    int64_t total_sectors; /* if we are reading a disk image, give its
   33.58 +                              size in sectors */
   33.59      int read_only; /* if true, the media is read only */
   33.60 -    int inserted; /* if true, the media is present */
   33.61      int removable; /* if true, the media can be removed */
   33.62      int locked;    /* if true, the media cannot temporarily be ejected */
   33.63      int encrypted; /* if true, the media is encrypted */
   33.64 @@ -55,7 +91,7 @@ struct BlockDriverState {
   33.65      void (*change_cb)(void *opaque);
   33.66      void *change_opaque;
   33.67  
   33.68 -    BlockDriver *drv;
   33.69 +    BlockDriver *drv; /* NULL means no media */
   33.70      void *opaque;
   33.71  
   33.72      int boot_sector_enabled;
   33.73 @@ -65,8 +101,12 @@ struct BlockDriverState {
   33.74      char backing_file[1024]; /* if non zero, the image is a diff of
   33.75                                  this file image */
   33.76      int is_temporary;
   33.77 -    
   33.78 +    int media_changed;
   33.79 +
   33.80      BlockDriverState *backing_hd;
   33.81 +    /* async read/write emulation */
   33.82 +
   33.83 +    void *sync_aiocb;
   33.84      
   33.85      /* NOTE: the following infos are only hints for real hardware
   33.86         drivers. They are not used by the block driver */
   33.87 @@ -76,6 +116,17 @@ struct BlockDriverState {
   33.88      BlockDriverState *next;
   33.89  };
   33.90  
   33.91 +struct BlockDriverAIOCB {
   33.92 +    BlockDriverState *bs;
   33.93 +    BlockDriverCompletionFunc *cb;
   33.94 +    void *opaque;
   33.95 +    BlockDriverAIOCB *next;
   33.96 +};
   33.97 +
   33.98  void get_tmp_filename(char *filename, int size);
   33.99  
  33.100 +void *qemu_aio_get(BlockDriverState *bs, BlockDriverCompletionFunc *cb,
  33.101 +                   void *opaque);
  33.102 +void qemu_aio_release(void *p);
  33.103 +
  33.104  #endif /* BLOCK_INT_H */
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/tools/ioemu/check_ops.sh	Wed May 16 10:59:01 2007 -0600
    34.3 @@ -0,0 +1,47 @@
    34.4 +#! /bin/sh
    34.5 +# Script to check for duplicate function prologues in op.o
    34.6 +# Typically this indicates missing FORCE_RET();
    34.7 +# This script does not detect other errors that may be present.
    34.8 +
    34.9 +# Usage: check_ops.sh [-m machine] [op.o]
   34.10 +#   machine and op.o are guessed if not specified.
   34.11 +
   34.12 +if [ "x$1" = "x-m" ]; then
   34.13 +  machine=$2
   34.14 +  shift 2
   34.15 +else
   34.16 +  machine=`uname -m`
   34.17 +fi
   34.18 +if [ -z "$1" ]; then
   34.19 +  for f in `find . -name op.o`; do
   34.20 +    /bin/sh "$0" -m $machine $f
   34.21 +  done
   34.22 +  exit 0
   34.23 +fi
   34.24 +
   34.25 +case $machine in
   34.26 +  i?86)
   34.27 +    ret='\tret'
   34.28 +    ;;
   34.29 +  x86_64)
   34.30 +    ret='\tretq'
   34.31 +    ;;
   34.32 +  arm)
   34.33 +    ret='\tldm.*pc'
   34.34 +    ;;
   34.35 +  ppc* | powerpc*)
   34.36 +    ret='\tblr'
   34.37 +    ;;
   34.38 +  mips*)
   34.39 +    ret='\tjr.*ra'
   34.40 +    ;;
   34.41 +  *)
   34.42 +    echo "Unknown machine `uname -m`"
   34.43 +    ;;
   34.44 +esac
   34.45 +echo $1
   34.46 +# op_exit_tb causes false positives on some hosts.
   34.47 +${CROSS}objdump -dr $1  | \
   34.48 +  sed -e '/>:$\|'"$ret"'/!d' -e 's/.*<\(.*\)>:/~\1:/' -e 's/.*'"$ret"'.*/!/' | \
   34.49 +  sed -e ':1;N;s/\n//;t1' | sed -e 's/~/\n/g' | grep -v '^op_exit_tb' | \
   34.50 +  grep '^op_.*!!'
    35.1 --- a/tools/ioemu/configure	Wed May 16 10:42:07 2007 -0600
    35.2 +++ b/tools/ioemu/configure	Wed May 16 10:59:01 2007 -0600
    35.3 @@ -22,6 +22,8 @@ static="no"
    35.4  libdir="lib"
    35.5  cross_prefix=""
    35.6  cc="gcc"
    35.7 +gcc3_search="yes"
    35.8 +gcc3_list="gcc-3.4 gcc34 gcc-3.3 gcc33 gcc-3.2 gcc32"
    35.9  host_cc="gcc"
   35.10  ar="ar"
   35.11  make="make"
   35.12 @@ -89,14 +91,13 @@ bsd="no"
   35.13  linux="no"
   35.14  kqemu="no"
   35.15  profiler="no"
   35.16 -kernel_path=""
   35.17  cocoa="no"
   35.18  check_gfx="yes"
   35.19  check_gcc="no"
   35.20  softmmu="yes"
   35.21 -user="no"
   35.22 +linux_user="no"
   35.23 +darwin_user="no"
   35.24  build_docs="no"
   35.25 -build_acpi_tables="no"
   35.26  uname_release=""
   35.27  
   35.28  # OS specific
   35.29 @@ -104,7 +105,7 @@ targetos=`uname -s`
   35.30  case $targetos in
   35.31  CYGWIN*)
   35.32  mingw32="yes"
   35.33 -CFLAGS="-O2 -mno-cygwin"
   35.34 +OS_CFLAGS="-mno-cygwin"
   35.35  ;;
   35.36  MINGW32*)
   35.37  mingw32="yes"
   35.38 @@ -127,6 +128,10 @@ oss="yes"
   35.39  Darwin)
   35.40  bsd="yes"
   35.41  darwin="yes"
   35.42 +darwin_user="yes"
   35.43 +cocoa="yes"
   35.44 +coreaudio="yes"
   35.45 +OS_CFLAGS="-mdynamic-no-pic"
   35.46  ;;
   35.47  SunOS)
   35.48  solaris="yes"
   35.49 @@ -134,7 +139,7 @@ solaris="yes"
   35.50  *)
   35.51  oss="yes"
   35.52  linux="yes"
   35.53 -user="yes"
   35.54 +linux_user="yes"
   35.55  if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
   35.56      kqemu="yes"
   35.57  fi
   35.58 @@ -151,6 +156,11 @@ if [ "$solaris" = "yes" ] ; then
   35.59      make="gmake"
   35.60      install="ginstall"
   35.61      solarisrev=`uname -r | cut -f2 -d.`
   35.62 +    if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
   35.63 +        if test "$solarisrev" -gt 10 ; then
   35.64 +            kqemu="yes"
   35.65 +        fi
   35.66 +    fi
   35.67  fi
   35.68  
   35.69  # find source path
   35.70 @@ -181,6 +191,7 @@ for opt do
   35.71    --cross-prefix=*) cross_prefix="$optarg"
   35.72    ;;
   35.73    --cc=*) cc="$optarg"
   35.74 +  gcc3_search="no"
   35.75    ;;
   35.76    --host-cc=*) host_cc="$optarg"
   35.77    ;;
   35.78 @@ -224,8 +235,6 @@ for opt do
   35.79    ;;
   35.80    --enable-profiler) profiler="yes"
   35.81    ;;
   35.82 -  --kernel-path=*) kernel_path="$optarg"
   35.83 -  ;;
   35.84    --enable-cocoa) cocoa="yes" ; coreaudio="yes" ; sdl="no"
   35.85    ;;
   35.86    --disable-gcc-check) check_gcc="no"
   35.87 @@ -234,21 +243,22 @@ for opt do
   35.88    ;;
   35.89    --enable-system) softmmu="yes"
   35.90    ;;
   35.91 -  --disable-user) user="no"
   35.92 +  --disable-linux-user) linux_user="no"
   35.93 +  ;;
   35.94 +  --enable-linux-user) linux_user="yes"
   35.95    ;;
   35.96 -  --enable-user) user="yes"
   35.97 +  --disable-darwin-user) darwin_user="no"
   35.98 +  ;;
   35.99 +  --enable-darwin-user) darwin_user="yes"
  35.100    ;;
  35.101    --enable-uname-release=*) uname_release="$optarg"
  35.102    ;;
  35.103 -  --enable-iasl) build_acpi_tables="yes"
  35.104 -  ;;
  35.105    esac
  35.106  done
  35.107  
  35.108 -# Checking for CFLAGS
  35.109 -if test -z "$CFLAGS"; then
  35.110 -    CFLAGS="-O2"
  35.111 -fi
  35.112 +# default flags for all hosts
  35.113 +CFLAGS="$CFLAGS -Wall -O2 -g -fno-strict-aliasing"
  35.114 +LDFLAGS="$LDFLAGS -g"
  35.115  
  35.116  if test x"$show_help" = x"yes" ; then
  35.117  cat << EOF
  35.118 @@ -266,7 +276,6 @@ echo "  --target-list=LIST       set tar
  35.119  echo ""
  35.120  echo "kqemu kernel acceleration support:"
  35.121  echo "  --disable-kqemu          disable kqemu support"
  35.122 -echo "  --kernel-path=PATH       set the kernel path (configure probes it)"
  35.123  echo ""
  35.124  echo "Advanced options (experts only):"
  35.125  echo "  --source-path=PATH       path of source code [$source_path]"
  35.126 @@ -285,14 +294,15 @@ echo "  --enable-fmod            enable 
  35.127  echo "  --enabled-dsound         enable DirectSound audio driver"
  35.128  echo "  --enable-system          enable all system emulation targets"
  35.129  echo "  --disable-system         disable all system emulation targets"
  35.130 -echo "  --enable-user            enable all linux usermode emulation targets"
  35.131 -echo "  --disable-user           disable all linux usermode emulation targets"
  35.132 +echo "  --enable-linux-user      enable all linux usermode emulation targets"
  35.133 +echo "  --disable-linux-user     disable all linux usermode emulation targets"
  35.134 +echo "  --enable-darwin-user     enable all darwin usermode emulation targets"
  35.135 +echo "  --disable-darwin-user    disable all darwin usermode emulation targets"
  35.136  echo "  --fmod-lib               path to FMOD library"
  35.137  echo "  --fmod-inc               path to FMOD includes"
  35.138  echo "  --enable-uname-release=R Return R for uname -r in usermode emulation"
  35.139 -echo "  --enable-iasl            compilation of ACPI tables with the IASL compiler"
  35.140  echo ""
  35.141 -echo "NOTE: The object files are build at the place where configure is launched"
  35.142 +echo "NOTE: The object files are built at the place where configure is launched"
  35.143  exit 1
  35.144  fi
  35.145  
  35.146 @@ -321,6 +331,45 @@ if test "$mingw32" = "yes" ; then
  35.147      fi
  35.148  fi
  35.149  
  35.150 +# Check for gcc4, error if pre-gcc4 
  35.151 +if test "$check_gcc" = "yes" ; then
  35.152 +    cat > $TMPC <<EOF
  35.153 +#if __GNUC__ < 4
  35.154 +#error gcc3
  35.155 +#endif
  35.156 +int main(){return 0;}
  35.157 +EOF
  35.158 +    check_cc() {
  35.159 +	which "$1" >&/dev/null
  35.160 +	return $?
  35.161 +    }
  35.162 +
  35.163 +    if "$cc" -o $TMPE $TMPC 2>/dev/null ; then
  35.164 +	echo "WARNING: \"$cc\" looks like gcc 4.x"
  35.165 +	found_compat_cc="no"
  35.166 +	if test "$gcc3_search" = "yes" ; then
  35.167 +	    echo "Looking for gcc 3.x"
  35.168 +	    for compat_cc in $gcc3_list ; do
  35.169 +		if check_cc "$compat_cc" ; then
  35.170 +		    echo "Found \"$compat_cc\""
  35.171 +		    cc="$compat_cc"
  35.172 +		    found_compat_cc="yes"
  35.173 +		    break
  35.174 +		fi
  35.175 +	    done
  35.176 +	    if test "$found_compat_cc" = "no" ; then
  35.177 +		echo "gcc 3.x not found!"
  35.178 +	    fi
  35.179 +	fi
  35.180 +	if test "$found_compat_cc" = "no" ; then
  35.181 +	    echo "QEMU is known to have problems when compiled with gcc 4.x"
  35.182 +	    echo "It is recommended that you use gcc 3.x to build QEMU"
  35.183 +	    echo "To use this compiler anyway, configure with --disable-gcc-check"
  35.184 +	    exit 1;
  35.185 +	fi
  35.186 +    fi
  35.187 +fi
  35.188 +
  35.189  #
  35.190  # Solaris specific configure tool chain decisions
  35.191  #
  35.192 @@ -368,8 +417,12 @@ if test -z "$target_list" ; then
  35.193          target_list="i386-softmmu ppc-softmmu sparc-softmmu x86_64-softmmu mips-softmmu mipsel-softmmu arm-softmmu"
  35.194      fi
  35.195  # the following are Linux specific
  35.196 -    if [ "$user" = "yes" ] ; then
  35.197 -        target_list="i386-user arm-user armeb-user sparc-user ppc-user mips-user mipsel-user $target_list"
  35.198 +    if [ "$linux_user" = "yes" ] ; then
  35.199 +        target_list="i386-linux-user arm-linux-user armeb-linux-user sparc-linux-user ppc-linux-user mips-linux-user mipsel-linux-user m68k-linux-user $target_list"
  35.200 +    fi
  35.201 +# the following are Darwin specific
  35.202 +    if [ "$darwin_user" = "yes" ] ; then
  35.203 +        target_list="i386-darwin-user ppc-darwin-user $target_list"
  35.204      fi
  35.205  # the i386-dm target
  35.206      target_list="i386-dm"
  35.207 @@ -427,23 +480,6 @@ if $cc -fno-reorder-blocks -fno-optimize
  35.208     have_gcc3_options="yes"
  35.209  fi
  35.210  
  35.211 -# Check for gcc4, error if pre-gcc4 
  35.212 -if test "$check_gcc" = "yes" ; then
  35.213 -    cat > $TMPC <<EOF
  35.214 -#if __GNUC__ < 4
  35.215 -#error gcc3
  35.216 -#endif
  35.217 -int main(){return 0;}
  35.218 -EOF
  35.219 -    if $cc -o $TMPO $TMPC 2>/dev/null ; then
  35.220 -        echo "ERROR: \"$cc\" looks like gcc 4.x"
  35.221 -        echo "QEMU is known to have problems when compiled with gcc 4.x"
  35.222 -        echo "It is recommended that you use gcc 3.x to build QEMU"
  35.223 -        echo "To use this compiler anyway, configure with --disable-gcc-check"
  35.224 -        exit 1;
  35.225 -    fi
  35.226 -fi
  35.227 -
  35.228  ##########################################
  35.229  # SDL probe
  35.230  
  35.231 @@ -472,7 +508,9 @@ if $cc -o $TMPE `$sdl_config --cflags 2>
  35.232  if test "$_sdlversion" -lt 121 ; then
  35.233  sdl_too_old=yes
  35.234  else
  35.235 -sdl=yes
  35.236 + if test "$cocoa" = "no" ; then
  35.237 +   sdl=yes
  35.238 + fi
  35.239  fi
  35.240  
  35.241  # static link with sdl ?
  35.242 @@ -493,8 +531,34 @@ fi # static link
  35.243  fi # sdl compile test
  35.244  
  35.245  fi # cross compilation
  35.246 +
  35.247 +else
  35.248 + # Make sure to disable cocoa if sdl was set
  35.249 + if test "$sdl" = "yes" ; then
  35.250 +   cocoa="no"
  35.251 +   coreaudio="no"
  35.252 + fi
  35.253  fi # -z $sdl
  35.254  
  35.255 +##########################################
  35.256 +# alsa sound support libraries
  35.257 +
  35.258 +if test "$alsa" = "yes" ; then
  35.259 +  cat > $TMPC << EOF
  35.260 +#include <alsa/asoundlib.h>
  35.261 +int main(void) { snd_pcm_t **handle; return snd_pcm_close(*handle); }
  35.262 +EOF
  35.263 +  if $cc -o $TMPE $TMPC -lasound 2> /dev/null ; then
  35.264 +    :
  35.265 +  else
  35.266 +    echo
  35.267 +    echo "Error: Could not find alsa"
  35.268 +    echo "Make sure to have the alsa libs and headers installed."
  35.269 +    echo
  35.270 +    exit 1
  35.271 +  fi
  35.272 +fi
  35.273 +
  35.274  # Check if tools are available to build documentation.
  35.275  if [ -x "`which texi2html`" ] && [ -x "`which pod2man`" ]; then
  35.276    build_docs="yes"
  35.277 @@ -600,6 +664,7 @@ fi
  35.278  echo "HOST_CC=$host_cc" >> $config_mak
  35.279  echo "AR=$ar" >> $config_mak
  35.280  echo "STRIP=$strip -s -R .comment -R .note" >> $config_mak
  35.281 +echo "OS_CFLAGS=$OS_CFLAGS" >> $config_mak
  35.282  echo "CFLAGS=$CFLAGS" >> $config_mak
  35.283  echo "LDFLAGS=$LDFLAGS" >> $config_mak
  35.284  echo "EXESUF=$EXESUF" >> $config_mak
  35.285 @@ -719,9 +784,6 @@ echo "TARGET_DIRS=$target_list" >> $conf
  35.286  if [ "$build_docs" = "yes" ] ; then
  35.287    echo "BUILD_DOCS=yes" >> $config_mak
  35.288  fi
  35.289 -if [ "$build_acpi_tables" = "yes" ] ; then
  35.290 -  echo "BUILD_ACPI_TABLES=yes" >> $config_mak
  35.291 -fi
  35.292  
  35.293  # XXX: suppress that
  35.294  if [ "$bsd" = "yes" ] ; then
  35.295 @@ -745,6 +807,7 @@ target_bigendian="no"
  35.296  [ "$target_cpu" = "ppc64" ] && target_bigendian=yes
  35.297  [ "$target_cpu" = "mips" ] && target_bigendian=yes
  35.298  [ "$target_cpu" = "sh4eb" ] && target_bigendian=yes
  35.299 +[ "$target_cpu" = "m68k" ] && target_bigendian=yes
  35.300  target_softmmu="no"
  35.301  if expr $target : '.*-softmmu' > /dev/null ; then
  35.302    target_softmmu="yes"
  35.303 @@ -756,11 +819,21 @@ if expr $target : '.*-user' > /dev/null 
  35.304    target_user_only="yes"
  35.305  fi
  35.306  
  35.307 +target_linux_user="no"
  35.308 +if expr $target : '.*-linux-user' > /dev/null ; then
  35.309 +  target_linux_user="yes"
  35.310 +fi
  35.311 +
  35.312 +target_darwin_user="no"
  35.313 +if expr $target : '.*-darwin-user' > /dev/null ; then
  35.314 +  target_darwin_user="yes"
  35.315 +fi
  35.316 +
  35.317  #echo "Creating $config_mak, $config_h and $target_dir/Makefile"
  35.318  
  35.319  mkdir -p $target_dir
  35.320  mkdir -p $target_dir/fpu
  35.321 -if test "$target" = "arm-user" -o "$target" = "armeb-user" ; then
  35.322 +if test "$target" = "arm-linux-user" -o "$target" = "armeb-linux-user" ; then
  35.323    mkdir -p $target_dir/nwfpe
  35.324  fi
  35.325  if test "$target_user_only" = "no" ; then
  35.326 @@ -840,6 +913,11 @@ elif test "$target_cpu" = "sh4" -o "$tar
  35.327    echo "#define TARGET_ARCH \"sh4\"" >> $config_h
  35.328    echo "#define TARGET_SH4 1" >> $config_h
  35.329    bflt="yes"
  35.330 +elif test "$target_cpu" = "m68k" ; then
  35.331 +  echo "TARGET_ARCH=m68k" >> $config_mak
  35.332 +  echo "#define TARGET_ARCH \"m68k\"" >> $config_h
  35.333 +  echo "#define TARGET_M68K 1" >> $config_h
  35.334 +  bflt="yes"
  35.335  else
  35.336    echo "Unsupported target CPU"
  35.337    exit 1
  35.338 @@ -856,12 +934,19 @@ if test "$target_user_only" = "yes" ; th
  35.339    echo "CONFIG_USER_ONLY=yes" >> $config_mak
  35.340    echo "#define CONFIG_USER_ONLY 1" >> $config_h
  35.341  fi
  35.342 -
  35.343 +if test "$target_linux_user" = "yes" ; then
  35.344 +  echo "CONFIG_LINUX_USER=yes" >> $config_mak
  35.345 +  echo "#define CONFIG_LINUX_USER 1" >> $config_h
  35.346 +fi
  35.347 +if test "$target_darwin_user" = "yes" ; then
  35.348 +  echo "CONFIG_DARWIN_USER=yes" >> $config_mak
  35.349 +  echo "#define CONFIG_DARWIN_USER 1" >> $config_h
  35.350 +fi
  35.351  if expr $target : '.*-dm' > /dev/null ; then
  35.352    echo "#define CONFIG_DM 1" >> $config_h
  35.353  fi
  35.354  
  35.355 -if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64"; then
  35.356 +if test "$target_cpu" = "arm" -o "$target_cpu" = "armeb" -o "$target_cpu" = "sparc" -o "$target_cpu" = "sparc64" -o "$target_cpu" = "m68k"; then
  35.357    echo "CONFIG_SOFTFLOAT=yes" >> $config_mak
  35.358    echo "#define CONFIG_SOFTFLOAT 1" >> $config_h
  35.359  fi
    36.1 --- a/tools/ioemu/console.c	Wed May 16 10:42:07 2007 -0600
    36.2 +++ b/tools/ioemu/console.c	Wed May 16 10:59:01 2007 -0600
    36.3 @@ -121,6 +121,7 @@ struct TextConsole {
    36.4      int total_height;
    36.5      int backscroll_height;
    36.6      int x, y;
    36.7 +    int x_saved, y_saved;
    36.8      int y_displayed;
    36.9      int y_base;
   36.10      TextAttributes t_attrib_default; /* default text attributes */
   36.11 @@ -131,10 +132,7 @@ struct TextConsole {
   36.12      int esc_params[MAX_ESC_PARAMS];
   36.13      int nb_esc_params;
   36.14  
   36.15 -    /* kbd read handler */
   36.16 -    IOCanRWHandler *fd_can_read; 
   36.17 -    IOReadHandler *fd_read;
   36.18 -    void *fd_opaque;
   36.19 +    CharDriverState *chr;
   36.20      /* fifo for key pressed */
   36.21      QEMUFIFO out_fifo;
   36.22      uint8_t out_fifo_buf[16];
   36.23 @@ -147,7 +145,7 @@ static int nb_consoles = 0;
   36.24  
   36.25  void vga_hw_update(void)
   36.26  {
   36.27 -    if (active_console->hw_update)
   36.28 +    if (active_console && active_console->hw_update)
   36.29          active_console->hw_update(active_console->hw);
   36.30  }
   36.31  
   36.32 @@ -659,10 +657,6 @@ static void console_handle_escape(TextCo
   36.33  {
   36.34      int i;
   36.35  
   36.36 -    if (s->nb_esc_params == 0) { /* ESC[m sets all attributes to default */
   36.37 -        s->t_attrib = s->t_attrib_default;
   36.38 -        return;
   36.39 -    }
   36.40      for (i=0; i<s->nb_esc_params; i++) {
   36.41          switch (s->esc_params[i]) {
   36.42              case 0: /* reset all console attributes to default */
   36.43 @@ -752,10 +746,21 @@ static void console_handle_escape(TextCo
   36.44      }
   36.45  }
   36.46  
   36.47 +static void console_clear_xy(TextConsole *s, int x, int y)
   36.48 +{
   36.49 +    int y1 = (s->y_base + y) % s->total_height;
   36.50 +    TextCell *c = &s->cells[y1 * s->width + x];
   36.51 +    c->ch = ' ';
   36.52 +    c->t_attrib = s->t_attrib_default;
   36.53 +    c++;
   36.54 +    update_xy(s, x, y);
   36.55 +}
   36.56 +
   36.57  static void console_putchar(TextConsole *s, int ch)
   36.58  {
   36.59      TextCell *c;
   36.60 -    int y1, i, x;
   36.61 +    int y1, i;
   36.62 +    int x, y;
   36.63  
   36.64      switch(s->state) {
   36.65      case TTY_STATE_NORM:
   36.66 @@ -781,20 +786,31 @@ static void console_putchar(TextConsole 
   36.67          case '\a':  /* alert aka. bell */
   36.68              /* TODO: has to be implemented */
   36.69              break;
   36.70 +        case 14:
   36.71 +            /* SI (shift in), character set 0 (ignored) */
   36.72 +            break;
   36.73 +        case 15:
   36.74 +            /* SO (shift out), character set 1 (ignored) */
   36.75 +            break;
   36.76          case 27:    /* esc (introducing an escape sequence) */
   36.77              s->state = TTY_STATE_ESC;
   36.78              break;
   36.79          default:
   36.80 +            if (s->x >= s->width - 1) {
   36.81 +                break;
   36.82 +            }
   36.83              y1 = (s->y_base + s->y) % s->total_height;
   36.84              c = &s->cells[y1 * s->width + s->x];
   36.85              c->ch = ch;
   36.86              c->t_attrib = s->t_attrib;
   36.87              update_xy(s, s->x, s->y);
   36.88              s->x++;
   36.89 +#if 0 /* line wrap disabled */
   36.90              if (s->x >= s->width) {
   36.91                  s->x = 0;
   36.92                  console_put_lf(s);
   36.93              }
   36.94 +#endif
   36.95              break;
   36.96          }
   36.97          break;
   36.98 @@ -818,32 +834,150 @@ static void console_putchar(TextConsole 
   36.99              s->nb_esc_params++;
  36.100              if (ch == ';')
  36.101                  break;
  36.102 +#ifdef DEBUG_CONSOLE
  36.103 +            fprintf(stderr, "escape sequence CSI%d;%d%c, %d parameters\n",
  36.104 +                    s->esc_params[0], s->esc_params[1], ch, s->nb_esc_params);
  36.105 +#endif
  36.106              s->state = TTY_STATE_NORM;
  36.107              switch(ch) {
  36.108 -            case 'D':
  36.109 -                if (s->x > 0)
  36.110 -                    s->x--;
  36.111 +            case 'A':
  36.112 +                /* move cursor up */
  36.113 +                if (s->esc_params[0] == 0) {
  36.114 +                    s->esc_params[0] = 1;
  36.115 +                }
  36.116 +                s->y -= s->esc_params[0];
  36.117 +                if (s->y < 0) {
  36.118 +                    s->y = 0;
  36.119 +                }
  36.120 +                break;
  36.121 +            case 'B':
  36.122 +                /* move cursor down */
  36.123 +                if (s->esc_params[0] == 0) {
  36.124 +                    s->esc_params[0] = 1;
  36.125 +                }
  36.126 +                s->y += s->esc_params[0];
  36.127 +                if (s->y >= s->height) {
  36.128 +                    s->y = s->height - 1;
  36.129 +                }
  36.130                  break;
  36.131              case 'C':
  36.132 -                if (s->x < (s->width - 1))
  36.133 -                    s->x++;
  36.134 +                /* move cursor right */
  36.135 +                if (s->esc_params[0] == 0) {
  36.136 +                    s->esc_params[0] = 1;
  36.137 +                }
  36.138 +                s->x += s->esc_params[0];
  36.139 +                if (s->x >= s->width) {
  36.140 +                    s->x = s->width - 1;
  36.141 +                }
  36.142                  break;
  36.143 -            case 'K':
  36.144 -                /* clear to eol */
  36.145 -                y1 = (s->y_base + s->y) % s->total_height;
  36.146 -                for(x = s->x; x < s->width; x++) {
  36.147 -                    c = &s->cells[y1 * s->width + x];
  36.148 -                    c->ch = ' ';
  36.149 -                    c->t_attrib = s->t_attrib_default;
  36.150 -                    c++;
  36.151 -                    update_xy(s, x, s->y);
  36.152 +            case 'D':
  36.153 +                /* move cursor left */
  36.154 +                if (s->esc_params[0] == 0) {
  36.155 +                    s->esc_params[0] = 1;
  36.156 +                }
  36.157 +                s->x -= s->esc_params[0];
  36.158 +                if (s->x < 0) {
  36.159 +                    s->x = 0;
  36.160 +                }
  36.161 +                break;
  36.162 +            case 'G':
  36.163 +                /* move cursor to column */
  36.164 +                s->x = s->esc_params[0] - 1;
  36.165 +                if (s->x < 0) {
  36.166 +                    s->x = 0;
  36.167 +                }
  36.168 +                break;
  36.169 +            case 'f':
  36.170 +            case 'H':
  36.171 +                /* move cursor to row, column */
  36.172 +                s->x = s->esc_params[1] - 1;
  36.173 +                if (s->x < 0) {
  36.174 +                    s->x = 0;
  36.175 +                }
  36.176 +                s->y = s->esc_params[0] - 1;
  36.177 +                if (s->y < 0) {
  36.178 +                    s->y = 0;
  36.179                  }
  36.180                  break;
  36.181 -            default:
  36.182 +            case 'J':
  36.183 +                switch (s->esc_params[0]) {
  36.184 +                case 0:
  36.185 +                    /* clear to end of screen */
  36.186 +                    for (y = s->y; y < s->height; y++) {
  36.187 +                        for (x = 0; x < s->width; x++) {
  36.188 +                            if (y == s->y && x < s->x) {
  36.189 +                                continue;
  36.190 +                            }
  36.191 +                            console_clear_xy(s, x, y);
  36.192 +                        }
  36.193 +                    }
  36.194 +                    break;
  36.195 +                case 1:
  36.196 +                    /* clear from beginning of screen */
  36.197 +                    for (y = 0; y <= s->y; y++) {
  36.198 +                        for (x = 0; x < s->width; x++) {
  36.199 +                            if (y == s->y && x > s->x) {
  36.200 +                                break;
  36.201 +                            }
  36.202 +                            console_clear_xy(s, x, y);
  36.203 +                        }
  36.204 +                    }
  36.205 +                    break;
  36.206 +                case 2:
  36.207 +                    /* clear entire screen */
  36.208 +                    for (y = 0; y <= s->height; y++) {
  36.209 +                        for (x = 0; x < s->width; x++) {
  36.210 +                            console_clear_xy(s, x, y);
  36.211 +                        }
  36.212 +                    }
  36.213 +                break;
  36.214 +                }
  36.215 +            case 'K':
  36.216 +                switch (s->esc_params[0]) {
  36.217 +                case 0:
  36.218 +                /* clear to eol */
  36.219 +                for(x = s->x; x < s->width; x++) {
  36.220 +                        console_clear_xy(s, x, s->y);
  36.221 +                }
  36.222 +                break;
  36.223 +                case 1:
  36.224 +                    /* clear from beginning of line */
  36.225 +                    for (x = 0; x <= s->x; x++) {
  36.226 +                        console_clear_xy(s, x, s->y);
  36.227 +                    }
  36.228 +                    break;
  36.229 +                case 2:
  36.230 +                    /* clear entire line */
  36.231 +                    for(x = 0; x < s->width; x++) {
  36.232 +                        console_clear_xy(s, x, s->y);
  36.233 +                    }
  36.234                  break;
  36.235              }
  36.236 +                break;
  36.237 +            case 'm':
  36.238              console_handle_escape(s);
  36.239              break;
  36.240 +            case 'n':
  36.241 +                /* report cursor position */
  36.242 +                /* TODO: send ESC[row;colR */
  36.243 +                break;
  36.244 +            case 's':
  36.245 +                /* save cursor position */
  36.246 +                s->x_saved = s->x;
  36.247 +                s->y_saved = s->y;
  36.248 +                break;
  36.249 +            case 'u':
  36.250 +                /* restore cursor position */
  36.251 +                s->x = s->x_saved;
  36.252 +                s->y = s->y_saved;
  36.253 +                break;
  36.254 +            default:
  36.255 +#ifdef DEBUG_CONSOLE
  36.256 +                fprintf(stderr, "unhandled escape character '%c'\n", ch);
  36.257 +#endif
  36.258 +                break;
  36.259 +            }
  36.260 +            break;
  36.261          }
  36.262      }
  36.263  }
  36.264 @@ -884,16 +1018,6 @@ static int console_puts(CharDriverState 
  36.265      return len;
  36.266  }
  36.267  
  36.268 -static void console_chr_add_read_handler(CharDriverState *chr, 
  36.269 -                                         IOCanRWHandler *fd_can_read, 
  36.270 -                                         IOReadHandler *fd_read, void *opaque)
  36.271 -{
  36.272 -    TextConsole *s = chr->opaque;
  36.273 -    s->fd_can_read = fd_can_read;
  36.274 -    s->fd_read = fd_read;
  36.275 -    s->fd_opaque = opaque;
  36.276 -}
  36.277 -
  36.278  static void console_send_event(CharDriverState *chr, int event)
  36.279  {
  36.280      TextConsole *s = chr->opaque;
  36.281 @@ -915,14 +1039,14 @@ static void kbd_send_chars(void *opaque)
  36.282      int len;
  36.283      uint8_t buf[16];
  36.284      
  36.285 -    len = s->fd_can_read(s->fd_opaque);
  36.286 +    len = qemu_chr_can_read(s->chr);
  36.287      if (len > s->out_fifo.count)
  36.288          len = s->out_fifo.count;
  36.289      if (len > 0) {
  36.290          if (len > sizeof(buf))
  36.291              len = sizeof(buf);
  36.292          qemu_fifo_read(&s->out_fifo, buf, len);
  36.293 -        s->fd_read(s->fd_opaque, buf, len);
  36.294 +        qemu_chr_read(s->chr, buf, len);
  36.295      }
  36.296      /* characters are pending: we send them a bit later (XXX:
  36.297         horrible, should change char device API) */
  36.298 @@ -973,7 +1097,7 @@ void kbd_put_keysym(int keysym)
  36.299          } else {
  36.300                  *q++ = keysym;
  36.301          }
  36.302 -        if (s->fd_read) {
  36.303 +        if (s->chr->chr_read) {
  36.304              qemu_fifo_write(&s->out_fifo, buf, q - buf);
  36.305              kbd_send_chars(s);
  36.306          }
  36.307 @@ -1059,9 +1183,9 @@ CharDriverState *text_console_init(Displ
  36.308      }
  36.309      chr->opaque = s;
  36.310      chr->chr_write = console_puts;
  36.311 -    chr->chr_add_read_handler = console_chr_add_read_handler;
  36.312      chr->chr_send_event = console_send_event;
  36.313  
  36.314 +    s->chr = chr;
  36.315      s->out_fifo.buf = s->out_fifo_buf;
  36.316      s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
  36.317      s->kbd_timer = qemu_new_timer(rt_clock, kbd_send_chars, s);
  36.318 @@ -1091,5 +1215,7 @@ CharDriverState *text_console_init(Displ
  36.319      s->t_attrib = s->t_attrib_default;
  36.320      text_console_resize(s);
  36.321  
  36.322 +    qemu_chr_reset(chr);
  36.323 +
  36.324      return chr;
  36.325  }
    37.1 --- a/tools/ioemu/cpu-all.h	Wed May 16 10:42:07 2007 -0600
    37.2 +++ b/tools/ioemu/cpu-all.h	Wed May 16 10:59:01 2007 -0600
    37.3 @@ -727,6 +727,13 @@ void page_unprotect_range(target_ulong d
    37.4  #define cpu_gen_code cpu_ppc_gen_code
    37.5  #define cpu_signal_handler cpu_ppc_signal_handler
    37.6  
    37.7 +#elif defined(TARGET_M68K)
    37.8 +#define CPUState CPUM68KState
    37.9 +#define cpu_init cpu_m68k_init
   37.10 +#define cpu_exec cpu_m68k_exec
   37.11 +#define cpu_gen_code cpu_m68k_gen_code
   37.12 +#define cpu_signal_handler cpu_m68k_signal_handler
   37.13 +
   37.14  #elif defined(TARGET_MIPS)
   37.15  #define CPUState CPUMIPSState
   37.16  #define cpu_init cpu_mips_init
   37.17 @@ -770,6 +777,7 @@ extern int code_copy_enabled;
   37.18  #define CPU_INTERRUPT_TIMER  0x08 /* internal timer exception pending */
   37.19  #define CPU_INTERRUPT_FIQ    0x10 /* Fast interrupt pending.  */
   37.20  #define CPU_INTERRUPT_HALT   0x20 /* CPU halt wanted */
   37.21 +#define CPU_INTERRUPT_SMI    0x40 /* (x86 only) SMI interrupt pending */
   37.22  
   37.23  void cpu_interrupt(CPUState *s, int mask);
   37.24  void cpu_reset_interrupt(CPUState *env, int mask);
   37.25 @@ -820,48 +828,6 @@ int cpu_inw(CPUState *env, int addr);
   37.26  int cpu_inl(CPUState *env, int addr);
   37.27  #endif
   37.28  
   37.29 -#if defined(__i386__) || defined(__x86_64__)
   37.30 -static __inline__ void atomic_set_bit(long nr, volatile void *addr)
   37.31 -{
   37.32 -        __asm__ __volatile__(
   37.33 -                "lock ; bts %1,%0"
   37.34 -                :"=m" (*(volatile long *)addr)
   37.35 -                :"dIr" (nr));
   37.36 -}
   37.37 -static __inline__ void atomic_clear_bit(long nr, volatile void *addr)
   37.38 -{
   37.39 -        __asm__ __volatile__(
   37.40 -                "lock ; btr %1,%0"
   37.41 -                :"=m" (*(volatile long *)addr)
   37.42 -                :"dIr" (nr));
   37.43 -}
   37.44 -#elif defined(__ia64__)
   37.45 -#include "ia64_intrinsic.h"
   37.46 -#define atomic_set_bit(nr, addr) ({					\
   37.47 -	typeof(*addr) bit, old, new;					\
   37.48 -	volatile typeof(*addr) *m;					\
   37.49 -									\
   37.50 -	m = (volatile typeof(*addr)*)(addr + nr / (8*sizeof(*addr)));	\
   37.51 -	bit = 1 << (nr % (8*sizeof(*addr)));				\
   37.52 -	do {								\
   37.53 -		old = *m;						\
   37.54 -		new = old | bit;					\
   37.55 -	} while (cmpxchg_acq(m, old, new) != old);			\
   37.56 -})
   37.57 -
   37.58 -#define atomic_clear_bit(nr, addr) ({					\
   37.59 -	typeof(*addr) bit, old, new;					\
   37.60 -	volatile typeof(*addr) *m;					\
   37.61 -									\
   37.62 -	m = (volatile typeof(*addr)*)(addr + nr / (8*sizeof(*addr)));	\
   37.63 -	bit = ~(1 << (nr % (8*sizeof(*addr))));				\
   37.64 -	do {								\
   37.65 -		old = *m;						\
   37.66 -		new = old & bit;					\
   37.67 -	} while (cmpxchg_acq(m, old, new) != old);			\
   37.68 -})
   37.69 -#endif
   37.70 -
   37.71  /* memory API */
   37.72  
   37.73  extern uint64_t phys_ram_size;
   37.74 @@ -889,6 +855,7 @@ typedef uint32_t CPUReadMemoryFunc(void 
   37.75  void cpu_register_physical_memory(target_phys_addr_t start_addr, 
   37.76                                    unsigned long size,
   37.77                                    unsigned long phys_offset);
   37.78 +uint32_t cpu_get_physical_page_desc(target_phys_addr_t addr);
   37.79  int cpu_register_io_memory(int io_index,
   37.80                             CPUReadMemoryFunc **mem_read,
   37.81                             CPUWriteMemoryFunc **mem_write,
   37.82 @@ -1042,6 +1009,15 @@ static inline int64_t cpu_get_real_ticks
   37.83          return rval.i64;
   37.84  #endif
   37.85  }
   37.86 +#else
   37.87 +/* The host CPU doesn't have an easily accessible cycle counter.
   37.88 +   Just return a monotonically increasing vlue.  This will be totally wrong,
   37.89 +   but hopefully better than nothing.  */
   37.90 +static inline int64_t cpu_get_real_ticks (void)
   37.91 +{
   37.92 +    static int64_t ticks = 0;
   37.93 +    return ticks++;
   37.94 +}
   37.95  #endif
   37.96  
   37.97  /* profiling */
    38.1 --- a/tools/ioemu/cpu-defs.h	Wed May 16 10:42:07 2007 -0600
    38.2 +++ b/tools/ioemu/cpu-defs.h	Wed May 16 10:59:01 2007 -0600
    38.3 @@ -80,6 +80,14 @@ typedef unsigned long ram_addr_t;
    38.4  #define TB_JMP_CACHE_BITS 12
    38.5  #define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS)
    38.6  
    38.7 +/* Only the bottom TB_JMP_PAGE_BITS of the jump cache hash bits vary for
    38.8 +   addresses on the same page.  The top bits are the same.  This allows
    38.9 +   TLB invalidation to quickly clear a subset of the hash table.  */
   38.10 +#define TB_JMP_PAGE_BITS (TB_JMP_CACHE_BITS / 2)
   38.11 +#define TB_JMP_PAGE_SIZE (1 << TB_JMP_PAGE_BITS)
   38.12 +#define TB_JMP_ADDR_MASK (TB_JMP_PAGE_SIZE - 1)
   38.13 +#define TB_JMP_PAGE_MASK (TB_JMP_CACHE_SIZE - TB_JMP_PAGE_SIZE)
   38.14 +
   38.15  #define CPU_TLB_BITS 8
   38.16  #define CPU_TLB_SIZE (1 << CPU_TLB_BITS)
   38.17  
    39.1 --- a/tools/ioemu/cpu-exec.c	Wed May 16 10:42:07 2007 -0600
    39.2 +++ b/tools/ioemu/cpu-exec.c	Wed May 16 10:59:01 2007 -0600
    39.3 @@ -40,14 +40,14 @@ int tb_invalidated_flag;
    39.4  //#define DEBUG_EXEC
    39.5  //#define DEBUG_SIGNAL
    39.6  
    39.7 -#if defined(TARGET_ARM) || defined(TARGET_SPARC)
    39.8 +#if defined(TARGET_ARM) || defined(TARGET_SPARC) || defined(TARGET_M68K)
    39.9  /* XXX: unify with i386 target */
   39.10  void cpu_loop_exit(void)
   39.11  {
   39.12      longjmp(env->jmp_env, 1);
   39.13  }
   39.14  #endif
   39.15 -#if !(defined(TARGET_SPARC) || defined(TARGET_SH4))
   39.16 +#if !(defined(TARGET_SPARC) || defined(TARGET_SH4) || defined(TARGET_M68K))
   39.17  #define reg_T2
   39.18  #endif
   39.19  
   39.20 @@ -194,6 +194,10 @@ static inline TranslationBlock *tb_find_
   39.21      flags = env->hflags & (MIPS_HFLAG_TMASK | MIPS_HFLAG_BMASK);
   39.22      cs_base = 0;
   39.23      pc = env->PC;
   39.24 +#elif defined(TARGET_M68K)
   39.25 +    flags = env->fpcr & M68K_FPCR_PREC;
   39.26 +    cs_base = 0;
   39.27 +    pc = env->pc;
   39.28  #elif defined(TARGET_SH4)
   39.29      flags = env->sr & (SR_MD | SR_RB);
   39.30      cs_base = 0;         /* XXXXX */
   39.31 @@ -222,43 +226,16 @@ static inline TranslationBlock *tb_find_
   39.32  
   39.33  int cpu_exec(CPUState *env1)
   39.34  {
   39.35 -    int saved_T0, saved_T1;
   39.36 -#if defined(reg_T2)
   39.37 -    int saved_T2;
   39.38 -#endif
   39.39 -    CPUState *saved_env;
   39.40 -#if defined(TARGET_I386)
   39.41 -#ifdef reg_EAX
   39.42 -    int saved_EAX;
   39.43 -#endif
   39.44 -#ifdef reg_ECX
   39.45 -    int saved_ECX;
   39.46 -#endif
   39.47 -#ifdef reg_EDX
   39.48 -    int saved_EDX;
   39.49 -#endif
   39.50 -#ifdef reg_EBX
   39.51 -    int saved_EBX;
   39.52 -#endif
   39.53 -#ifdef reg_ESP
   39.54 -    int saved_ESP;
   39.55 -#endif
   39.56 -#ifdef reg_EBP
   39.57 -    int saved_EBP;
   39.58 -#endif
   39.59 -#ifdef reg_ESI
   39.60 -    int saved_ESI;
   39.61 -#endif
   39.62 -#ifdef reg_EDI
   39.63 -    int saved_EDI;
   39.64 -#endif
   39.65 -#elif defined(TARGET_SPARC)
   39.66 +#define DECLARE_HOST_REGS 1
   39.67 +#include "hostregs_helper.h"
   39.68 +#if defined(TARGET_SPARC)
   39.69  #if defined(reg_REGWPTR)
   39.70      uint32_t *saved_regwptr;
   39.71  #endif
   39.72  #endif
   39.73  #if defined(__sparc__) && !defined(HOST_SOLARIS)
   39.74 -    int saved_i7, tmp_T0;
   39.75 +    int saved_i7;
   39.76 +    target_ulong tmp_T0;
   39.77  #endif
   39.78      int ret, interrupt_request;
   39.79      void (*gen_func)(void);
   39.80 @@ -320,44 +297,15 @@ int cpu_exec(CPUState *env1)
   39.81      cpu_single_env = env1; 
   39.82  
   39.83      /* first we save global registers */
   39.84 -    saved_env = env;
   39.85 +#define SAVE_HOST_REGS 1
   39.86 +#include "hostregs_helper.h"
   39.87      env = env1;
   39.88 -    saved_T0 = T0;
   39.89 -    saved_T1 = T1;
   39.90 -#if defined(reg_T2)
   39.91 -    saved_T2 = T2;
   39.92 -#endif
   39.93  #if defined(__sparc__) && !defined(HOST_SOLARIS)
   39.94      /* we also save i7 because longjmp may not restore it */
   39.95      asm volatile ("mov %%i7, %0" : "=r" (saved_i7));
   39.96  #endif
   39.97  
   39.98  #if defined(TARGET_I386)
   39.99 -#ifdef reg_EAX
  39.100 -    saved_EAX = EAX;
  39.101 -#endif
  39.102 -#ifdef reg_ECX
  39.103 -    saved_ECX = ECX;
  39.104 -#endif
  39.105 -#ifdef reg_EDX
  39.106 -    saved_EDX = EDX;
  39.107 -#endif
  39.108 -#ifdef reg_EBX
  39.109 -    saved_EBX = EBX;
  39.110 -#endif
  39.111 -#ifdef reg_ESP
  39.112 -    saved_ESP = ESP;
  39.113 -#endif
  39.114 -#ifdef reg_EBP
  39.115 -    saved_EBP = EBP;
  39.116 -#endif
  39.117 -#ifdef reg_ESI
  39.118 -    saved_ESI = ESI;
  39.119 -#endif
  39.120 -#ifdef reg_EDI
  39.121 -    saved_EDI = EDI;
  39.122 -#endif
  39.123 -
  39.124      env_to_regs();
  39.125      /* put eflags in CPU temporary format */
  39.126      CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
  39.127 @@ -370,6 +318,10 @@ int cpu_exec(CPUState *env1)
  39.128      saved_regwptr = REGWPTR;
  39.129  #endif
  39.130  #elif defined(TARGET_PPC)
  39.131 +#elif defined(TARGET_M68K)
  39.132 +    env->cc_op = CC_OP_FLAGS;
  39.133 +    env->cc_dest = env->sr & 0xf;
  39.134 +    env->cc_x = (env->sr >> 4) & 1;
  39.135  #elif defined(TARGET_MIPS)
  39.136  #elif defined(TARGET_SH4)
  39.137      /* XXXXX */
  39.138 @@ -390,7 +342,7 @@ int cpu_exec(CPUState *env1)
  39.139                      break;
  39.140                  } else if (env->user_mode_only) {
  39.141                      /* if user mode only, we simulate a fake exception
  39.142 -                       which will be hanlded outside the cpu execution
  39.143 +                       which will be handled outside the cpu execution
  39.144                         loop */
  39.145  #if defined(TARGET_I386)
  39.146                      do_interrupt_user(env->exception_index, 
  39.147 @@ -458,8 +410,16 @@ int cpu_exec(CPUState *env1)
  39.148                  interrupt_request = env->interrupt_request;
  39.149                  if (__builtin_expect(interrupt_request, 0)) {
  39.150  #if defined(TARGET_I386)
  39.151 -                    /* if hardware interrupt pending, we execute it */
  39.152 -                    if ((interrupt_request & CPU_INTERRUPT_HARD) &&
  39.153 +                    if ((interrupt_request & CPU_INTERRUPT_SMI) &&
  39.154 +                        !(env->hflags & HF_SMM_MASK)) {
  39.155 +                        env->interrupt_request &= ~CPU_INTERRUPT_SMI;
  39.156 +                        do_smm_enter();
  39.157 +#if defined(__sparc__) && !defined(HOST_SOLARIS)
  39.158 +                        tmp_T0 = 0;
  39.159 +#else
  39.160 +                        T0 = 0;
  39.161 +#endif
  39.162 +                    } else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
  39.163                          (env->eflags & IF_MASK) && 
  39.164                          !(env->hflags & HF_INHIBIT_IRQ_MASK)) {
  39.165                          int intno;
  39.166 @@ -519,7 +479,6 @@ int cpu_exec(CPUState *env1)
  39.167                          env->exception_index = EXCP_EXT_INTERRUPT;
  39.168                          env->error_code = 0;
  39.169                          do_interrupt(env);
  39.170 -                        env->interrupt_request &= ~CPU_INTERRUPT_HARD;
  39.171  #if defined(__sparc__) && !defined(HOST_SOLARIS)
  39.172                          tmp_T0 = 0;
  39.173  #else
  39.174 @@ -548,8 +507,10 @@ int cpu_exec(CPUState *env1)
  39.175  			//do_interrupt(0, 0, 0, 0, 0);
  39.176  			env->interrupt_request &= ~CPU_INTERRUPT_TIMER;
  39.177  		    } else if (interrupt_request & CPU_INTERRUPT_HALT) {
  39.178 -                        env1->halted = 1;
  39.179 -                        return EXCP_HALTED;
  39.180 +			env->interrupt_request &= ~CPU_INTERRUPT_HALT;
  39.181 +			env->halted = 1;
  39.182 +			env->exception_index = EXCP_HLT;
  39.183 +			cpu_loop_exit();
  39.184                      }
  39.185  #elif defined(TARGET_ARM)
  39.186                      if (interrupt_request & CPU_INTERRUPT_FIQ
  39.187 @@ -622,6 +583,12 @@ int cpu_exec(CPUState *env1)
  39.188                      cpu_dump_state(env, logfile, fprintf, 0);
  39.189  #elif defined(TARGET_PPC)
  39.190                      cpu_dump_state(env, logfile, fprintf, 0);
  39.191 +#elif defined(TARGET_M68K)
  39.192 +                    cpu_m68k_flush_flags(env, env->cc_op);
  39.193 +                    env->cc_op = CC_OP_FLAGS;
  39.194 +                    env->sr = (env->sr & 0xffe0)
  39.195 +                              | env->cc_dest | (env->cc_x << 4);
  39.196 +                    cpu_dump_state(env, logfile, fprintf, 0);
  39.197  #elif defined(TARGET_MIPS)
  39.198                      cpu_dump_state(env, logfile, fprintf, 0);
  39.199  #elif defined(TARGET_SH4)
  39.200 @@ -803,32 +770,6 @@ int cpu_exec(CPUState *env1)
  39.201  #endif
  39.202      /* restore flags in standard format */
  39.203      env->eflags = env->eflags | cc_table[CC_OP].compute_all() | (DF & DF_MASK);
  39.204 -
  39.205 -    /* restore global registers */
  39.206 -#ifdef reg_EAX
  39.207 -    EAX = saved_EAX;
  39.208 -#endif
  39.209 -#ifdef reg_ECX
  39.210 -    ECX = saved_ECX;
  39.211 -#endif
  39.212 -#ifdef reg_EDX
  39.213 -    EDX = saved_EDX;
  39.214 -#endif
  39.215 -#ifdef reg_EBX
  39.216 -    EBX = saved_EBX;
  39.217 -#endif
  39.218 -#ifdef reg_ESP
  39.219 -    ESP = saved_ESP;
  39.220 -#endif
  39.221 -#ifdef reg_EBP
  39.222 -    EBP = saved_EBP;
  39.223 -#endif
  39.224 -#ifdef reg_ESI
  39.225 -    ESI = saved_ESI;
  39.226 -#endif
  39.227 -#ifdef reg_EDI
  39.228 -    EDI = saved_EDI;
  39.229 -#endif
  39.230  #elif defined(TARGET_ARM)
  39.231      /* XXX: Save/restore host fpu exception state?.  */
  39.232  #elif defined(TARGET_SPARC)
  39.233 @@ -836,21 +777,24 @@ int cpu_exec(CPUState *env1)
  39.234      REGWPTR = saved_regwptr;
  39.235  #endif
  39.236  #elif defined(TARGET_PPC)
  39.237 +#elif defined(TARGET_M68K)
  39.238 +    cpu_m68k_flush_flags(env, env->cc_op);
  39.239 +    env->cc_op = CC_OP_FLAGS;
  39.240 +    env->sr = (env->sr & 0xffe0)
  39.241 +              | env->cc_dest | (env->cc_x << 4);
  39.242  #elif defined(TARGET_MIPS)
  39.243  #elif defined(TARGET_SH4)
  39.244      /* XXXXX */
  39.245  #else
  39.246  #error unsupported target CPU
  39.247  #endif
  39.248 +
  39.249 +    /* restore global registers */
  39.250  #if defined(__sparc__) && !defined(HOST_SOLARIS)
  39.251      asm volatile ("mov %0, %%i7" : : "r" (saved_i7));
  39.252  #endif
  39.253 -    T0 = saved_T0;
  39.254 -    T1 = saved_T1;
  39.255 -#if defined(reg_T2)
  39.256 -    T2 = saved_T2;
  39.257 -#endif
  39.258 -    env = saved_env;
  39.259 +#include "hostregs_helper.h"
  39.260 +
  39.261      /* fail safe : never use cpu_single_env outside cpu_exec() */
  39.262      cpu_single_env = NULL; 
  39.263      return ret;
  39.264 @@ -1093,6 +1037,45 @@ static inline int handle_cpu_signal(unsi
  39.265      return 1;
  39.266  }
  39.267  
  39.268 +#elif defined(TARGET_M68K)
  39.269 +static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
  39.270 +                                    int is_write, sigset_t *old_set,
  39.271 +                                    void *puc)
  39.272 +{
  39.273 +    TranslationBlock *tb;
  39.274 +    int ret;
  39.275 +
  39.276 +    if (cpu_single_env)
  39.277 +        env = cpu_single_env; /* XXX: find a correct solution for multithread */
  39.278 +#if defined(DEBUG_SIGNAL)
  39.279 +    printf("qemu: SIGSEGV pc=0x%08lx address=%08lx w=%d oldset=0x%08lx\n", 
  39.280 +           pc, address, is_write, *(unsigned long *)old_set);
  39.281 +#endif
  39.282 +    /* XXX: locking issue */
  39.283 +    if (is_write && page_unprotect(address, pc, puc)) {
  39.284 +        return 1;
  39.285 +    }
  39.286 +    /* see if it is an MMU fault */
  39.287 +    ret = cpu_m68k_handle_mmu_fault(env, address, is_write, 1, 0);
  39.288 +    if (ret < 0)
  39.289 +        return 0; /* not an MMU fault */
  39.290 +    if (ret == 0)
  39.291 +        return 1; /* the MMU fault was handled without causing real CPU fault */
  39.292 +    /* now we have a real cpu fault */
  39.293 +    tb = tb_find_pc(pc);
  39.294 +    if (tb) {
  39.295 +        /* the PC is inside the translated code. It means that we have
  39.296 +           a virtual CPU fault */
  39.297 +        cpu_restore_state(tb, env, pc, puc);
  39.298 +    }
  39.299 +    /* we restore the process signal mask as the sigreturn should
  39.300 +       do it (XXX: use sigsetjmp) */
  39.301 +    sigprocmask(SIG_SETMASK, old_set, NULL);
  39.302 +    cpu_loop_exit();
  39.303 +    /* never comes here */
  39.304 +    return 1;
  39.305 +}
  39.306 +
  39.307  #elif defined (TARGET_MIPS)
  39.308  static inline int handle_cpu_signal(unsigned long pc, unsigned long address,
  39.309                                      int is_write, sigset_t *old_set,
  39.310 @@ -1193,6 +1176,18 @@ static inline int handle_cpu_signal(unsi
  39.311  
  39.312  #if defined(__i386__)
  39.313  
  39.314 +#if defined(__APPLE__)
  39.315 +# include <sys/ucontext.h>
  39.316 +
  39.317 +# define EIP_sig(context)  (*((unsigned long*)&(context)->uc_mcontext->ss.eip))
  39.318 +# define TRAP_sig(context)    ((context)->uc_mcontext->es.trapno)
  39.319 +# define ERROR_sig(context)   ((context)->uc_mcontext->es.err)
  39.320 +#else
  39.321 +# define EIP_sig(context)     ((context)->uc_mcontext.gregs[REG_EIP])
  39.322 +# define TRAP_sig(context)    ((context)->uc_mcontext.gregs[REG_TRAPNO])
  39.323 +# define ERROR_sig(context)   ((context)->uc_mcontext.gregs[REG_ERR])
  39.324 +#endif
  39.325 +
  39.326  #if defined(USE_CODE_COPY)
  39.327  static void cpu_send_trap(unsigned long pc, int trap, 
  39.328                            struct ucontext *uc)
  39.329 @@ -1213,9 +1208,10 @@ static void cpu_send_trap(unsigned long 
  39.330  }
  39.331  #endif
  39.332  
  39.333 -int cpu_signal_handler(int host_signum, struct siginfo *info, 
  39.334 +int cpu_signal_handler(int host_signum, void *pinfo, 
  39.335                         void *puc)
  39.336  {
  39.337 +    siginfo_t *info = pinfo;
  39.338      struct ucontext *uc = puc;
  39.339      unsigned long pc;
  39.340      int trapno;
  39.341 @@ -1226,8 +1222,8 @@ int cpu_signal_handler(int host_signum, 
  39.342  #define REG_ERR    ERR
  39.343  #define REG_TRAPNO TRAPNO
  39.344  #endif
  39.345 -    pc = uc->uc_mcontext.gregs[REG_EIP];
  39.346 -    trapno = uc->uc_mcontext.gregs[REG_TRAPNO];
  39.347 +    pc = EIP_sig(uc);
  39.348 +    trapno = TRAP_sig(uc);
  39.349  #if defined(TARGET_I386) && defined(USE_CODE_COPY)
  39.350      if (trapno == 0x00 || trapno == 0x05) {
  39.351          /* send division by zero or bound exception */
  39.352 @@ -1237,15 +1233,16 @@ int cpu_signal_handler(int host_signum, 
  39.353  #endif
  39.354          return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
  39.355                                   trapno == 0xe ? 
  39.356 -                                 (uc->uc_mcontext.gregs[REG_ERR] >> 1) & 1 : 0,
  39.357 +                                 (ERROR_sig(uc) >> 1) & 1 : 0,
  39.358                                   &uc->uc_sigmask, puc);
  39.359  }
  39.360  
  39.361  #elif defined(__x86_64__)
  39.362  
  39.363 -int cpu_signal_handler(int host_signum, struct siginfo *info,
  39.364 +int cpu_signal_handler(int host_signum, void *pinfo,
  39.365                         void *puc)
  39.366  {
  39.367 +    siginfo_t *info = pinfo;
  39.368      struct ucontext *uc = puc;
  39.369      unsigned long pc;
  39.370  
  39.371 @@ -1307,9 +1304,10 @@ typedef struct ucontext SIGCONTEXT;
  39.372  # define TRAP_sig(context)			EXCEPREG_sig(exception, context) /* number of powerpc exception taken */
  39.373  #endif /* __APPLE__ */
  39.374  
  39.375 -int cpu_signal_handler(int host_signum, struct siginfo *info, 
  39.376 +int cpu_signal_handler(int host_signum, void *pinfo, 
  39.377                         void *puc)
  39.378  {
  39.379 +    siginfo_t *info = pinfo;
  39.380      struct ucontext *uc = puc;
  39.381      unsigned long pc;
  39.382      int is_write;
  39.383 @@ -1330,9 +1328,10 @@ int cpu_signal_handler(int host_signum, 
  39.384  
  39.385  #elif defined(__alpha__)
  39.386  
  39.387 -int cpu_signal_handler(int host_signum, struct siginfo *info, 
  39.388 +int cpu_signal_handler(int host_signum, void *pinfo, 
  39.389                             void *puc)
  39.390  {
  39.391 +    siginfo_t *info = pinfo;
  39.392      struct ucontext *uc = puc;
  39.393      uint32_t *pc = uc->uc_mcontext.sc_pc;
  39.394      uint32_t insn = *pc;
  39.395 @@ -1359,9 +1358,10 @@ int cpu_signal_handler(int host_signum, 
  39.396  }
  39.397  #elif defined(__sparc__)
  39.398  
  39.399 -int cpu_signal_handler(int host_signum, struct siginfo *info, 
  39.400 +int cpu_signal_handler(int host_signum, void *pinfo, 
  39.401                         void *puc)
  39.402  {
  39.403 +    siginfo_t *info = pinfo;
  39.404      uint32_t *regs = (uint32_t *)(info + 1);
  39.405      void *sigmask = (regs + 20);
  39.406      unsigned long pc;
  39.407 @@ -1392,9 +1392,10 @@ int cpu_signal_handler(int host_signum, 
  39.408  
  39.409  #elif defined(__arm__)
  39.410  
  39.411 -int cpu_signal_handler(int host_signum, struct siginfo *info, 
  39.412 +int cpu_signal_handler(int host_signum, void *pinfo, 
  39.413                         void *puc)
  39.414  {
  39.415 +    siginfo_t *info = pinfo;
  39.416      struct ucontext *uc = puc;
  39.417      unsigned long pc;
  39.418      int is_write;
  39.419 @@ -1404,14 +1405,15 @@ int cpu_signal_handler(int host_signum, 
  39.420      is_write = 0;
  39.421      return handle_cpu_signal(pc, (unsigned long)info->si_addr, 
  39.422                               is_write,
  39.423 -                             &uc->uc_sigmask);
  39.424 +                             &uc->uc_sigmask, puc);
  39.425  }
  39.426  
  39.427  #elif defined(__mc68000)
  39.428  
  39.429 -int cpu_signal_handler(int host_signum, struct siginfo *info, 
  39.430 +int cpu_signal_handler(int host_signum, void *pinfo, 
  39.431                         void *puc)
  39.432  {
  39.433 +    siginfo_t *info = pinfo;
  39.434      struct ucontext *uc = puc;
  39.435      unsigned long pc;
  39.436      int is_write;
  39.437 @@ -1431,8 +1433,9 @@ int cpu_signal_handler(int host_signum, 
  39.438  # define __ISR_VALID	1
  39.439  #endif
  39.440  
  39.441 -int cpu_signal_handler(int host_signum, struct siginfo *info, void *puc)
  39.442 +int cpu_signal_handler(int host_signum, void *pinfo, void *puc)
  39.443  {
  39.444 +    siginfo_t *info = pinfo;
  39.445      struct ucontext *uc = puc;
  39.446      unsigned long ip;
  39.447      int is_write = 0;
  39.448 @@ -1459,9 +1462,10 @@ int cpu_signal_handler(int host_signum, 
  39.449  
  39.450  #elif defined(__s390__)
  39.451  
  39.452 -int cpu_signal_handler(int host_signum, struct siginfo *info, 
  39.453 +int cpu_signal_handler(int host_signum, void *pinfo, 
  39.454                         void *puc)
  39.455  {
  39.456 +    siginfo_t *info = pinfo;
  39.457      struct ucontext *uc = puc;
  39.458      unsigned long pc;
  39.459      int is_write;
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/tools/ioemu/cutils.c	Wed May 16 10:59:01 2007 -0600
    40.3 @@ -0,0 +1,83 @@
    40.4 +/*
    40.5 + * Simple C functions to supplement the C library
    40.6 + * 
    40.7 + * Copyright (c) 2006 Fabrice Bellard
    40.8 + *
    40.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   40.10 + * of this software and associated documentation files (the "Software"), to deal
   40.11 + * in the Software without restriction, including without limitation the rights
   40.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   40.13 + * copies of the Software, and to permit persons to whom the Software is
   40.14 + * furnished to do so, subject to the following conditions:
   40.15 + *
   40.16 + * The above copyright notice and this permission notice shall be included in
   40.17 + * all copies or substantial portions of the Software.
   40.18 + *
   40.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   40.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   40.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   40.22 + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   40.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   40.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   40.25 + * THE SOFTWARE.
   40.26 + */
   40.27 +#include "vl.h"
   40.28 +
   40.29 +void pstrcpy(char *buf, int buf_size, const char *str)
   40.30 +{
   40.31 +    int c;
   40.32 +    char *q = buf;
   40.33 +
   40.34 +    if (buf_size <= 0)
   40.35 +        return;
   40.36 +
   40.37 +    for(;;) {
   40.38 +        c = *str++;
   40.39 +        if (c == 0 || q >= buf + buf_size - 1)
   40.40 +            break;
   40.41 +        *q++ = c;
   40.42 +    }
   40.43 +    *q = '\0';
   40.44 +}
   40.45 +
   40.46 +/* strcat and truncate. */
   40.47 +char *pstrcat(char *buf, int buf_size, const char *s)
   40.48 +{
   40.49 +    int len;
   40.50 +    len = strlen(buf);
   40.51 +    if (len < buf_size) 
   40.52 +        pstrcpy(buf + len, buf_size - len, s);
   40.53 +    return buf;
   40.54 +}
   40.55 +
   40.56 +int strstart(const char *str, const char *val, const char **ptr)
   40.57 +{
   40.58 +    const char *p, *q;
   40.59 +    p = str;
   40.60 +    q = val;
   40.61 +    while (*q != '\0') {
   40.62 +        if (*p != *q)
   40.63 +            return 0;
   40.64 +        p++;
   40.65 +        q++;
   40.66 +    }
   40.67 +    if (ptr)
   40.68 +        *ptr = p;
   40.69 +    return 1;
   40.70 +}
   40.71 +
   40.72 +int stristart(const char *str, const char *val, const char **ptr)
   40.73 +{
   40.74 +    const char *p, *q;
   40.75 +    p = str;
   40.76 +    q = val;
   40.77 +    while (*q != '\0') {
   40.78 +        if (toupper(*p) != toupper(*q))
   40.79 +            return 0;
   40.80 +        p++;
   40.81 +        q++;
   40.82 +    }
   40.83 +    if (ptr)
   40.84 +        *ptr = p;
   40.85 +    return 1;
   40.86 +}
    41.1 --- a/tools/ioemu/disas.c	Wed May 16 10:42:07 2007 -0600
    41.2 +++ b/tools/ioemu/disas.c	Wed May 16 10:59:01 2007 -0600
    41.3 @@ -186,14 +186,14 @@ void target_disas(FILE *out, target_ulon
    41.4      disasm_info.mach = bfd_mach_ppc;
    41.5  #endif
    41.6      print_insn = print_insn_ppc;
    41.7 +#elif defined(TARGET_M68K)
    41.8 +    print_insn = print_insn_m68k;
    41.9  #elif defined(TARGET_MIPS)
   41.10  #ifdef TARGET_WORDS_BIGENDIAN
   41.11      print_insn = print_insn_big_mips;
   41.12  #else
   41.13      print_insn = print_insn_little_mips;
   41.14  #endif
   41.15 -#elif defined(TARGET_M68K)
   41.16 -    print_insn = print_insn_m68k;
   41.17  #elif defined(TARGET_SH4)
   41.18      disasm_info.mach = bfd_mach_sh4;
   41.19      print_insn = print_insn_sh;
   41.20 @@ -271,11 +271,9 @@ void disas(FILE *out, void *code, unsign
   41.21      for (pc = (unsigned long)code; pc < (unsigned long)code + size; pc += count) {
   41.22  	fprintf(out, "0x%08lx:  ", pc);
   41.23  #ifdef __arm__
   41.24 -        /* since data are included in the code, it is better to
   41.25 +        /* since data is included in the code, it is better to
   41.26             display code data too */
   41.27 -        if (is_host) {
   41.28 -            fprintf(out, "%08x  ", (int)bfd_getl32((const bfd_byte *)pc));
   41.29 -        }
   41.30 +        fprintf(out, "%08x  ", (int)bfd_getl32((const bfd_byte *)pc));
   41.31  #endif
   41.32  	count = print_insn(pc, &disasm_info);
   41.33  	fprintf(out, "\n");
   41.34 @@ -387,14 +385,14 @@ void monitor_disas(CPUState *env,
   41.35      disasm_info.mach = bfd_mach_ppc;
   41.36  #endif
   41.37      print_insn = print_insn_ppc;
   41.38 +#elif defined(TARGET_M68K)
   41.39 +    print_insn = print_insn_m68k;
   41.40  #elif defined(TARGET_MIPS)
   41.41  #ifdef TARGET_WORDS_BIGENDIAN
   41.42      print_insn = print_insn_big_mips;
   41.43  #else
   41.44      print_insn = print_insn_little_mips;
   41.45  #endif
   41.46 -#elif defined(TARGET_M68K)
   41.47 -    print_insn = print_insn_m68k;
   41.48  #else
   41.49      term_printf("0x" TARGET_FMT_lx
   41.50  		": Asm output not supported on this arch\n", pc);
    42.1 --- a/tools/ioemu/dyngen-exec.h	Wed May 16 10:42:07 2007 -0600
    42.2 +++ b/tools/ioemu/dyngen-exec.h	Wed May 16 10:59:01 2007 -0600
    42.3 @@ -62,6 +62,9 @@ typedef signed long long int64_t;
    42.4  #endif
    42.5  #endif
    42.6  
    42.7 +/* XXX: This may be wrong for 64-bit ILP32 hosts.  */
    42.8 +typedef void * host_reg_t;
    42.9 +
   42.10  #define INT8_MIN		(-128)
   42.11  #define INT16_MIN		(-32767-1)
   42.12  #define INT32_MIN		(-2147483647-1)
   42.13 @@ -188,7 +191,7 @@ extern int printf(const char *, ...);
   42.14  #endif
   42.15  
   42.16  /* force GCC to generate only one epilog at the end of the function */
   42.17 -#define FORCE_RET() asm volatile ("");
   42.18 +#define FORCE_RET() __asm__ __volatile__("" : : : "memory");
   42.19  
   42.20  #ifndef OPPROTO
   42.21  #define OPPROTO
    43.1 --- a/tools/ioemu/dyngen.c	Wed May 16 10:42:07 2007 -0600
    43.2 +++ b/tools/ioemu/dyngen.c	Wed May 16 10:59:01 2007 -0600
    43.3 @@ -127,10 +127,12 @@
    43.4  typedef int32_t host_long;
    43.5  typedef uint32_t host_ulong;
    43.6  #define swabls(x) swab32s(x)
    43.7 +#define swablss(x) swab32ss(x)
    43.8  #else
    43.9  typedef int64_t host_long;
   43.10  typedef uint64_t host_ulong;
   43.11  #define swabls(x) swab64s(x)
   43.12 +#define swablss(x) swab64ss(x)
   43.13  #endif
   43.14  
   43.15  #ifdef ELF_USES_RELOCA
   43.16 @@ -284,11 +286,21 @@ void swab32s(uint32_t *p)
   43.17      *p = bswap32(*p);
   43.18  }
   43.19  
   43.20 +void swab32ss(int32_t *p)
   43.21 +{
   43.22 +    *p = bswap32(*p);
   43.23 +}
   43.24 +
   43.25  void swab64s(uint64_t *p)
   43.26  {
   43.27      *p = bswap64(*p);
   43.28  }
   43.29  
   43.30 +void swab64ss(int64_t *p)
   43.31 +{
   43.32 +    *p = bswap64(*p);
   43.33 +}
   43.34 +
   43.35  uint16_t get16(uint16_t *p)
   43.36  {
   43.37      uint16_t val;
   43.38 @@ -397,7 +409,7 @@ void elf_swap_rel(ELF_RELOC *rel)
   43.39      swabls(&rel->r_offset);
   43.40      swabls(&rel->r_info);
   43.41  #ifdef ELF_USES_RELOCA
   43.42 -    swabls(&rel->r_addend);
   43.43 +    swablss(&rel->r_addend);
   43.44  #endif
   43.45  }
   43.46  
   43.47 @@ -505,7 +517,7 @@ int load_object(const char *filename)
   43.48      }
   43.49  
   43.50      sec = &shdr[ehdr.e_shstrndx];
   43.51 -    shstr = sdata[ehdr.e_shstrndx];
   43.52 +    shstr = (char *)sdata[ehdr.e_shstrndx];
   43.53  
   43.54      /* swap relocations */
   43.55      for(i = 0; i < ehdr.e_shnum; i++) {
   43.56 @@ -541,7 +553,7 @@ int load_object(const char *filename)
   43.57      strtab_sec = &shdr[symtab_sec->sh_link];
   43.58  
   43.59      symtab = (ElfW(Sym) *)sdata[symtab_sec - shdr];
   43.60 -    strtab = sdata[symtab_sec->sh_link];
   43.61 +    strtab = (char *)sdata[symtab_sec->sh_link];
   43.62      
   43.63      nb_syms = symtab_sec->sh_size / sizeof(ElfW(Sym));
   43.64      if (do_swap) {
   43.65 @@ -1255,90 +1267,149 @@ int arm_emit_ldr_info(const char *name, 
   43.66  {
   43.67      uint8_t *p;
   43.68      uint32_t insn;
   43.69 -    int offset, min_offset, pc_offset, data_size;
   43.70 +    int offset, min_offset, pc_offset, data_size, spare, max_pool;
   43.71      uint8_t data_allocated[1024];
   43.72      unsigned int data_index;
   43.73 +    int type;
   43.74      
   43.75      memset(data_allocated, 0, sizeof(data_allocated));
   43.76      
   43.77      p = p_start;
   43.78      min_offset = p_end - p_start;
   43.79 +    spare = 0x7fffffff;
   43.80      while (p < p_start + min_offset) {
   43.81          insn = get32((uint32_t *)p);
   43.82 +        /* TODO: Armv5e ldrd.  */
   43.83 +        /* TODO: VFP load.  */
   43.84          if ((insn & 0x0d5f0000) == 0x051f0000) {
   43.85              /* ldr reg, [pc, #im] */
   43.86              offset = insn & 0xfff;
   43.87              if (!(insn & 0x00800000))
   43.88 -                        offset = -offset;
   43.89 +                offset = -offset;
   43.90 +            max_pool = 4096;
   43.91 +            type = 0;
   43.92 +        } else if ((insn & 0x0e5f0f00) == 0x0c1f0100) {
   43.93 +            /* FPA ldf.  */
   43.94 +            offset = (insn & 0xff) << 2;
   43.95 +            if (!(insn & 0x00800000))
   43.96 +                offset = -offset;
   43.97 +            max_pool = 1024;
   43.98 +            type = 1;
   43.99 +        } else if ((insn & 0x0fff0000) == 0x028f0000) {
  43.100 +            /* Some gcc load a doubleword immediate with
  43.101 +               add regN, pc, #imm
  43.102 +               ldmia regN, {regN, regM}
  43.103 +               Hope and pray the compiler never generates somethin like
  43.104 +               add reg, pc, #imm1; ldr reg, [reg, #-imm2]; */
  43.105 +            int r;
  43.106 +
  43.107 +            r = (insn & 0xf00) >> 7;
  43.108 +            offset = ((insn & 0xff) >> r) | ((insn & 0xff) << (32 - r));
  43.109 +            max_pool = 1024;
  43.110 +            type = 2;
  43.111 +        } else {
  43.112 +            max_pool = 0;
  43.113 +            type = -1;
  43.114 +        }
  43.115 +        if (type >= 0) {
  43.116 +            /* PC-relative load needs fixing up.  */
  43.117 +            if (spare > max_pool - offset)
  43.118 +                spare = max_pool - offset;
  43.119              if ((offset & 3) !=0)
  43.120 -                error("%s:%04x: ldr pc offset must be 32 bit aligned", 
  43.121 +                error("%s:%04x: pc offset must be 32 bit aligned", 
  43.122 +                      name, start_offset + p - p_start);
  43.123 +            if (offset < 0)
  43.124 +                error("%s:%04x: Embedded literal value",
  43.125                        name, start_offset + p - p_start);
  43.126              pc_offset = p - p_start + offset + 8;
  43.127              if (pc_offset <= (p - p_start) || 
  43.128                  pc_offset >= (p_end - p_start))
  43.129 -                error("%s:%04x: ldr pc offset must point inside the function code", 
  43.130 +                error("%s:%04x: pc offset must point inside the function code", 
  43.131                        name, start_offset + p - p_start);
  43.132              if (pc_offset < min_offset)
  43.133                  min_offset = pc_offset;
  43.134              if (outfile) {
  43.135 -                /* ldr position */
  43.136 +                /* The intruction position */
  43.137                  fprintf(outfile, "    arm_ldr_ptr->ptr = gen_code_ptr + %d;\n", 
  43.138                          p - p_start);
  43.139 -                /* ldr data index */
  43.140 -                data_index = ((p_end - p_start) - pc_offset - 4) >> 2;
  43.141 -                fprintf(outfile, "    arm_ldr_ptr->data_ptr = arm_data_ptr + %d;\n", 
  43.142 +                /* The position of the constant pool data.  */
  43.143 +                data_index = ((p_end - p_start) - pc_offset) >> 2;
  43.144 +                fprintf(outfile, "    arm_ldr_ptr->data_ptr = arm_data_ptr - %d;\n", 
  43.145                          data_index);
  43.146 +                fprintf(outfile, "    arm_ldr_ptr->type = %d;\n", type);
  43.147                  fprintf(outfile, "    arm_ldr_ptr++;\n");
  43.148 -                if (data_index >= sizeof(data_allocated))
  43.149 -                    error("%s: too many data", name);
  43.150 -                if (!data_allocated[data_index]) {
  43.151 -                    ELF_RELOC *rel;
  43.152 -                    int i, addend, type;
  43.153 -                    const char *sym_name, *p;
  43.154 -                    char relname[1024];
  43.155 -
  43.156 -                    data_allocated[data_index] = 1;
  43.157 -
  43.158 -                    /* data value */
  43.159 -                    addend = get32((uint32_t *)(p_start + pc_offset));
  43.160 -                    relname[0] = '\0';
  43.161 -                    for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
  43.162 -                        if (rel->r_offset == (pc_offset + start_offset)) {
  43.163 -                            sym_name = get_rel_sym_name(rel);
  43.164 -                            /* the compiler leave some unnecessary references to the code */
  43.165 -                            get_reloc_expr(relname, sizeof(relname), sym_name);
  43.166 -                            type = ELF32_R_TYPE(rel->r_info);
  43.167 -                            if (type != R_ARM_ABS32)
  43.168 -                                error("%s: unsupported data relocation", name);
  43.169 -                            break;
  43.170 -                        }
  43.171 -                    }
  43.172 -                    fprintf(outfile, "    arm_data_ptr[%d] = 0x%x",
  43.173 -                            data_index, addend);
  43.174 -                    if (relname[0] != '\0')
  43.175 -                        fprintf(outfile, " + %s", relname);
  43.176 -                    fprintf(outfile, ";\n");
  43.177 -                }
  43.178              }
  43.179          }
  43.180          p += 4;
  43.181      }
  43.182 +
  43.183 +    /* Copy and relocate the constant pool data.  */
  43.184      data_size = (p_end - p_start) - min_offset;
  43.185      if (data_size > 0 && outfile) {
  43.186 -        fprintf(outfile, "    arm_data_ptr += %d;\n", data_size >> 2);
  43.187 +        spare += min_offset;
  43.188 +        fprintf(outfile, "    arm_data_ptr -= %d;\n", data_size >> 2);
  43.189 +        fprintf(outfile, "    arm_pool_ptr -= %d;\n", data_size);
  43.190 +        fprintf(outfile, "    if (arm_pool_ptr > gen_code_ptr + %d)\n"
  43.191 +                         "        arm_pool_ptr = gen_code_ptr + %d;\n",
  43.192 +                         spare, spare);
  43.193 +
  43.194 +        data_index = 0;
  43.195 +        for (pc_offset = min_offset;
  43.196 +             pc_offset < p_end - p_start;
  43.197 +             pc_offset += 4) {
  43.198 +
  43.199 +            ELF_RELOC *rel;
  43.200 +            int i, addend, type;
  43.201 +            const char *sym_name;
  43.202 +            char relname[1024];
  43.203 +
  43.204 +            /* data value */
  43.205 +            addend = get32((uint32_t *)(p_start + pc_offset));
  43.206 +            relname[0] = '\0';
  43.207 +            for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
  43.208 +                if (rel->r_offset == (pc_offset + start_offset)) {
  43.209 +                    sym_name = get_rel_sym_name(rel);
  43.210 +                    /* the compiler leave some unnecessary references to the code */
  43.211 +                    get_reloc_expr(relname, sizeof(relname), sym_name);
  43.212 +                    type = ELF32_R_TYPE(rel->r_info);
  43.213 +                    if (type != R_ARM_ABS32)
  43.214 +                        error("%s: unsupported data relocation", name);
  43.215 +                    break;
  43.216 +                }
  43.217 +            }
  43.218 +            fprintf(outfile, "    arm_data_ptr[%d] = 0x%x",
  43.219 +                    data_index, addend);
  43.220 +            if (relname[0] != '\0')
  43.221 +                fprintf(outfile, " + %s", relname);
  43.222 +            fprintf(outfile, ";\n");
  43.223 +
  43.224 +            data_index++;
  43.225 +        }
  43.226      }
  43.227  
  43.228 -    /* the last instruction must be a mov pc, lr */
  43.229      if (p == p_start)
  43.230          goto arm_ret_error;
  43.231      p -= 4;
  43.232      insn = get32((uint32_t *)p);
  43.233 -    if ((insn & 0xffff0000) != 0xe91b0000) {
  43.234 +    /* The last instruction must be an ldm instruction.  There are several
  43.235 +       forms generated by gcc:
  43.236 +        ldmib sp, {..., pc}  (implies a sp adjustment of +4)
  43.237 +        ldmia sp, {..., pc}
  43.238 +        ldmea fp, {..., pc} */
  43.239 +    if ((insn & 0xffff8000) == 0xe99d8000) {
  43.240 +        if (outfile) {
  43.241 +            fprintf(outfile,
  43.242 +                    "    *(uint32_t *)(gen_code_ptr + %d) = 0xe28dd004;\n",
  43.243 +                    p - p_start);
  43.244 +        }
  43.245 +        p += 4;
  43.246 +    } else if ((insn & 0xffff8000) != 0xe89d8000
  43.247 +        && (insn & 0xffff8000) != 0xe91b8000) {
  43.248      arm_ret_error:
  43.249          if (!outfile)
  43.250              printf("%s: invalid epilog\n", name);
  43.251      }
  43.252 -    return p - p_start;	    
  43.253 +    return p - p_start;
  43.254  }
  43.255  #endif
  43.256  
  43.257 @@ -1537,6 +1608,8 @@ void gen_code(const char *name, host_ulo
  43.258      }
  43.259  #elif defined(HOST_ARM)
  43.260      {
  43.261 +        uint32_t insn;
  43.262 +
  43.263          if ((p_end - p_start) <= 16)
  43.264              error("%s: function too small", name);
  43.265          if (get32((uint32_t *)p_start) != 0xe1a0c00d ||
  43.266 @@ -1545,6 +1618,12 @@ void gen_code(const char *name, host_ulo
  43.267              error("%s: invalid prolog", name);
  43.268          p_start += 12;
  43.269          start_offset += 12;
  43.270 +        insn = get32((uint32_t *)p_start);
  43.271 +        if ((insn & 0xffffff00) == 0xe24dd000) {
  43.272 +            /* Stack adjustment.  Assume op uses the frame pointer.  */
  43.273 +            p_start -= 4;
  43.274 +            start_offset -= 4;
  43.275 +        }
  43.276          copy_size = arm_emit_ldr_info(name, start_offset, NULL, p_start, p_end, 
  43.277                                        relocs, nb_relocs);
  43.278      }
  43.279 @@ -2282,7 +2361,37 @@ void gen_code(const char *name, host_ulo
  43.280                  int type;
  43.281                  int addend;
  43.282                  int reloc_offset;
  43.283 +                uint32_t insn;
  43.284  
  43.285 +                insn = get32((uint32_t *)(p_start + 4));
  43.286 +                /* If prologue ends in sub sp, sp, #const then assume
  43.287 +                   op has a stack frame and needs the frame pointer.  */
  43.288 +                if ((insn & 0xffffff00) == 0xe24dd000) {
  43.289 +                    int i;
  43.290 +                    uint32_t opcode;
  43.291 +                    opcode = 0xe28db000; /* add fp, sp, #0.  */
  43.292 +#if 0
  43.293 +/* ??? Need to undo the extra stack adjustment at the end of the op.
  43.294 +   For now just leave the stack misaligned and hope it doesn't break anything
  43.295 +   too important.  */
  43.296 +                    if ((insn & 4) != 0) {
  43.297 +                        /* Preserve doubleword stack alignment.  */
  43.298 +                        fprintf(outfile,
  43.299 +                                "    *(uint32_t *)(gen_code_ptr + 4)= 0x%x;\n",
  43.300 +                                insn + 4);
  43.301 +                        opcode -= 4;
  43.302 +                    }
  43.303 +#endif
  43.304 +                    insn = get32((uint32_t *)(p_start - 4));
  43.305 +                    /* Calculate the size of the saved registers,
  43.306 +                       excluding pc.  */
  43.307 +                    for (i = 0; i < 15; i++) {
  43.308 +                        if (insn & (1 << i))
  43.309 +                            opcode += 4;
  43.310 +                    }
  43.311 +                    fprintf(outfile,
  43.312 +                            "    *(uint32_t *)gen_code_ptr = 0x%x;\n", opcode);
  43.313 +                }
  43.314                  arm_emit_ldr_info(name, start_offset, outfile, p_start, p_end,
  43.315                                    relocs, nb_relocs);
  43.316  
  43.317 @@ -2303,6 +2412,8 @@ void gen_code(const char *name, host_ulo
  43.318                                  reloc_offset, name, addend);
  43.319                          break;
  43.320                      case R_ARM_PC24:
  43.321 +                    case R_ARM_JUMP24:
  43.322 +                    case R_ARM_CALL:
  43.323                          fprintf(outfile, "    arm_reloc_pc24((uint32_t *)(gen_code_ptr + %d), 0x%x, %s);\n", 
  43.324                                  reloc_offset, addend, name);
  43.325                          break;
  43.326 @@ -2407,6 +2518,28 @@ int gen_file(FILE *outfile, int out_type
  43.327          
  43.328      } else {
  43.329          /* generate big code generation switch */
  43.330 +
  43.331 +#ifdef HOST_ARM
  43.332 +        /* We need to know the size of all the ops so we can figure out when
  43.333 +           to emit constant pools.  This must be consistent with opc.h.  */
  43.334 +fprintf(outfile,
  43.335 +"static const uint32_t arm_opc_size[] = {\n"
  43.336 +"  0,\n" /* end */
  43.337 +"  0,\n" /* nop */
  43.338 +"  0,\n" /* nop1 */
  43.339 +"  0,\n" /* nop2 */
  43.340 +"  0,\n"); /* nop3 */
  43.341 +        for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
  43.342 +            const char *name;
  43.343 +            name = get_sym_name(sym);
  43.344 +            if (strstart(name, OP_PREFIX, NULL)) {
  43.345 +                fprintf(outfile, "  %d,\n", sym->st_size);
  43.346 +            }
  43.347 +	}
  43.348 +fprintf(outfile,
  43.349 +"};\n");
  43.350 +#endif
  43.351 +
  43.352  fprintf(outfile,
  43.353  "int dyngen_code(uint8_t *gen_code_buf,\n"
  43.354  "                uint16_t *label_offsets, uint16_t *jmp_offsets,\n"
  43.355 @@ -2417,10 +2550,36 @@ fprintf(outfile,
  43.356  "    const uint32_t *opparam_ptr;\n");
  43.357  
  43.358  #ifdef HOST_ARM
  43.359 +/* Arm is tricky because it uses constant pools for loading immediate values.
  43.360 +   We assume (and require) each function is code followed by a constant pool.
  43.361 +   All the ops are small so this should be ok.  For each op we figure
  43.362 +   out how much "spare" range we have in the load instructions.  This allows
  43.363 +   us to insert subsequent ops in between the op and the constant pool,
  43.364 +   eliminating the neeed to jump around the pool.
  43.365 +
  43.366 +   We currently generate:
  43.367 +   
  43.368 +   [ For this example we assume merging would move op1_pool out of range.
  43.369 +     In practice we should be able to combine many ops before the offset
  43.370 +     limits are reached. ]
  43.371 +   op1_code;
  43.372 +   op2_code;
  43.373 +   goto op3;
  43.374 +   op2_pool;
  43.375 +   op1_pool;
  43.376 +op3:
  43.377 +   op3_code;
  43.378 +   ret;
  43.379 +   op3_pool;
  43.380 +
  43.381 +   Ideally we'd put op1_pool before op2_pool, but that requires two passes.
  43.382 + */
  43.383  fprintf(outfile,
  43.384  "    uint8_t *last_gen_code_ptr = gen_code_buf;\n"
  43.385  "    LDREntry *arm_ldr_ptr = arm_ldr_table;\n"
  43.386 -"    uint32_t *arm_data_ptr = arm_data_table;\n");
  43.387 +"    uint32_t *arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
  43.388 +/* Initialise the parmissible pool offset to an arbitary large value.  */
  43.389 +"    uint8_t *arm_pool_ptr = gen_code_buf + 0x1000000;\n");
  43.390  #endif
  43.391  #ifdef HOST_IA64
  43.392      {
  43.393 @@ -2489,9 +2648,23 @@ fprintf(outfile,
  43.394  	/* Generate prologue, if needed. */ 
  43.395  
  43.396  fprintf(outfile,
  43.397 -"    for(;;) {\n"
  43.398 -"        switch(*opc_ptr++) {\n"
  43.399 -);
  43.400 +"    for(;;) {\n");
  43.401 +
  43.402 +#ifdef HOST_ARM
  43.403 +/* Generate constant pool if needed */
  43.404 +fprintf(outfile,
  43.405 +"            if (gen_code_ptr + arm_opc_size[*opc_ptr] >= arm_pool_ptr) {\n"
  43.406 +"                gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
  43.407 +"arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 1);\n"
  43.408 +"                last_gen_code_ptr = gen_code_ptr;\n"
  43.409 +"                arm_ldr_ptr = arm_ldr_table;\n"
  43.410 +"                arm_data_ptr = arm_data_table + ARM_LDR_TABLE_SIZE;\n"
  43.411 +"                arm_pool_ptr = gen_code_ptr + 0x1000000;\n"
  43.412 +"            }\n");
  43.413 +#endif
  43.414 +
  43.415 +fprintf(outfile,
  43.416 +"        switch(*opc_ptr++) {\n");
  43.417  
  43.418          for(i = 0, sym = symtab; i < nb_syms; i++, sym++) {
  43.419              const char *name;
  43.420 @@ -2525,17 +2698,6 @@ fprintf(outfile,
  43.421  "            goto the_end;\n"
  43.422  "        }\n");
  43.423  
  43.424 -#ifdef HOST_ARM
  43.425 -/* generate constant table if needed */
  43.426 -fprintf(outfile,
  43.427 -"        if ((gen_code_ptr - last_gen_code_ptr) >= (MAX_FRAG_SIZE - MAX_OP_SIZE)) {\n"
  43.428 -"            gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, arm_ldr_ptr, arm_data_table, arm_data_ptr, 1);\n"
  43.429 -"            last_gen_code_ptr = gen_code_ptr;\n"
  43.430 -"            arm_ldr_ptr = arm_ldr_table;\n"
  43.431 -"            arm_data_ptr = arm_data_table;\n"
  43.432 -"        }\n");         
  43.433 -#endif
  43.434 -
  43.435  
  43.436  fprintf(outfile,
  43.437  "    }\n"
  43.438 @@ -2553,7 +2715,10 @@ fprintf(outfile,
  43.439  
  43.440  /* generate some code patching */ 
  43.441  #ifdef HOST_ARM
  43.442 -fprintf(outfile, "gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, arm_ldr_ptr, arm_data_table, arm_data_ptr, 0);\n");
  43.443 +fprintf(outfile,
  43.444 +"if (arm_data_ptr != arm_data_table + ARM_LDR_TABLE_SIZE)\n"
  43.445 +"    gen_code_ptr = arm_flush_ldr(gen_code_ptr, arm_ldr_table, "
  43.446 +"arm_ldr_ptr, arm_data_ptr, arm_data_table + ARM_LDR_TABLE_SIZE, 0);\n");
  43.447  #endif
  43.448      /* flush instruction cache */
  43.449      fprintf(outfile, "flush_icache_range((unsigned long)gen_code_buf, (unsigned long)gen_code_ptr);\n");
    44.1 --- a/tools/ioemu/dyngen.h	Wed May 16 10:42:07 2007 -0600
    44.2 +++ b/tools/ioemu/dyngen.h	Wed May 16 10:59:01 2007 -0600
    44.3 @@ -19,7 +19,7 @@
    44.4   */
    44.5  
    44.6  int __op_param1, __op_param2, __op_param3;
    44.7 -#ifdef __sparc__
    44.8 +#if defined(__sparc__) || defined(__arm__)
    44.9    void __op_gen_label1(){}
   44.10    void __op_gen_label2(){}
   44.11    void __op_gen_label3(){}
   44.12 @@ -145,18 +145,16 @@ void fix_bsr(void *p, int offset) {
   44.13  
   44.14  #ifdef __arm__
   44.15  
   44.16 -#define MAX_OP_SIZE    (128 * 4) /* in bytes */
   44.17 -/* max size of the code that can be generated without calling arm_flush_ldr */
   44.18 -#define MAX_FRAG_SIZE  (1024 * 4) 
   44.19 -//#define MAX_FRAG_SIZE  (135 * 4) /* for testing */ 
   44.20 +#define ARM_LDR_TABLE_SIZE 1024
   44.21  
   44.22  typedef struct LDREntry {
   44.23      uint8_t *ptr;
   44.24      uint32_t *data_ptr;
   44.25 +    unsigned type:2;
   44.26  } LDREntry;
   44.27  
   44.28  static LDREntry arm_ldr_table[1024];
   44.29 -static uint32_t arm_data_table[1024];
   44.30 +static uint32_t arm_data_table[ARM_LDR_TABLE_SIZE];
   44.31  
   44.32  extern char exec_loop;
   44.33  
   44.34 @@ -175,8 +173,9 @@ static uint8_t *arm_flush_ldr(uint8_t *g
   44.35      int offset, data_size, target;
   44.36      uint8_t *data_ptr;
   44.37      uint32_t insn;
   44.38 +    uint32_t mask;
   44.39   
   44.40 -    data_size = (uint8_t *)data_end - (uint8_t *)data_start;
   44.41 +    data_size = (data_end - data_start) << 2;
   44.42  
   44.43      if (gen_jmp) {
   44.44          /* generate branch to skip the data */
   44.45 @@ -198,17 +197,48 @@ static uint8_t *arm_flush_ldr(uint8_t *g
   44.46          offset = ((unsigned long)(le->data_ptr) - (unsigned long)data_start) + 
   44.47              (unsigned long)data_ptr - 
   44.48              (unsigned long)ptr - 8;
   44.49 -        insn = *ptr & ~(0xfff | 0x00800000);
   44.50          if (offset < 0) {
   44.51 -            offset = - offset;
   44.52 -        } else {
   44.53 -            insn |= 0x00800000;
   44.54 -        }
   44.55 -        if (offset > 0xfff) {
   44.56 -            fprintf(stderr, "Error ldr offset\n");
   44.57 +            fprintf(stderr, "Negative constant pool offset\n");
   44.58              abort();
   44.59          }
   44.60 -        insn |= offset;
   44.61 +        switch (le->type) {
   44.62 +          case 0: /* ldr */
   44.63 +            mask = ~0x00800fff;
   44.64 +            if (offset >= 4096) {
   44.65 +                fprintf(stderr, "Bad ldr offset\n");
   44.66 +                abort();
   44.67 +            }
   44.68 +            break;
   44.69 +          case 1: /* ldc */
   44.70 +            mask = ~0x008000ff;
   44.71 +            if (offset >= 1024 ) {
   44.72 +                fprintf(stderr, "Bad ldc offset\n");
   44.73 +                abort();
   44.74 +            }
   44.75 +            break;
   44.76 +          case 2: /* add */
   44.77 +            mask = ~0xfff;
   44.78 +            if (offset >= 1024 ) {
   44.79 +                fprintf(stderr, "Bad add offset\n");
   44.80 +                abort();
   44.81 +            }
   44.82 +            break;
   44.83 +          default:
   44.84 +            fprintf(stderr, "Bad pc relative fixup\n");
   44.85 +            abort();
   44.86 +          }
   44.87 +        insn = *ptr & mask;
   44.88 +        switch (le->type) {
   44.89 +          case 0: /* ldr */
   44.90 +            insn |= offset | 0x00800000;
   44.91 +            break;
   44.92 +          case 1: /* ldc */
   44.93 +            insn |= (offset >> 2) | 0x00800000;
   44.94 +            break;
   44.95 +          case 2: /* add */
   44.96 +            insn |= (offset >> 2) | 0xf00;
   44.97 +            break;
   44.98 +          }
   44.99          *ptr = insn;
  44.100      }
  44.101      return gen_code_ptr;
    45.1 --- a/tools/ioemu/elf.h	Wed May 16 10:42:07 2007 -0600
    45.2 +++ b/tools/ioemu/elf.h	Wed May 16 10:59:01 2007 -0600
    45.3 @@ -502,6 +502,8 @@ typedef struct {
    45.4  #define R_ARM_GOTPC		25	/* 32 bit PC relative offset to GOT */
    45.5  #define R_ARM_GOT32		26	/* 32 bit GOT entry */
    45.6  #define R_ARM_PLT32		27	/* 32 bit PLT address */
    45.7 +#define R_ARM_CALL              28
    45.8 +#define R_ARM_JUMP24            29
    45.9  #define R_ARM_GNU_VTENTRY	100
   45.10  #define R_ARM_GNU_VTINHERIT	101
   45.11  #define R_ARM_THM_PC11		102	/* thumb unconditional branch */
    46.1 --- a/tools/ioemu/elf_ops.h	Wed May 16 10:42:07 2007 -0600
    46.2 +++ b/tools/ioemu/elf_ops.h	Wed May 16 10:59:01 2007 -0600
    46.3 @@ -153,6 +153,9 @@ int glue(load_elf, SZ)(int fd, int64_t v
    46.4          glue(bswap_ehdr, SZ)(&ehdr);
    46.5      }
    46.6  
    46.7 +    if (ELF_MACHINE != ehdr.e_machine)
    46.8 +        goto fail;
    46.9 +
   46.10      if (pentry)
   46.11     	*pentry = (uint64_t)ehdr.e_entry;
   46.12  
   46.13 @@ -202,4 +205,3 @@ int glue(load_elf, SZ)(int fd, int64_t v
   46.14      qemu_free(phdr);
   46.15      return -1;
   46.16  }
   46.17 -
    47.1 --- a/tools/ioemu/exec-all.h	Wed May 16 10:42:07 2007 -0600
    47.2 +++ b/tools/ioemu/exec-all.h	Wed May 16 10:59:01 2007 -0600
    47.3 @@ -196,9 +196,19 @@ typedef struct TranslationBlock {
    47.4      struct TranslationBlock *jmp_first;
    47.5  } TranslationBlock;
    47.6  
    47.7 +static inline unsigned int tb_jmp_cache_hash_page(target_ulong pc)
    47.8 +{
    47.9 +    target_ulong tmp;
   47.10 +    tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS));
   47.11 +    return (tmp >> TB_JMP_PAGE_BITS) & TB_JMP_PAGE_MASK;
   47.12 +}
   47.13 +
   47.14  static inline unsigned int tb_jmp_cache_hash_func(target_ulong pc)
   47.15  {
   47.16 -    return (pc ^ (pc >> TB_JMP_CACHE_BITS)) & (TB_JMP_CACHE_SIZE - 1);
   47.17 +    target_ulong tmp;
   47.18 +    tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS));
   47.19 +    return (((tmp >> TB_JMP_PAGE_BITS) & TB_JMP_PAGE_MASK) |
   47.20 +	    (tmp & TB_JMP_ADDR_MASK));
   47.21  }
   47.22  
   47.23  static inline unsigned int tb_phys_hash_func(unsigned long pc)
   47.24 @@ -462,13 +472,12 @@ static inline int testandset (int *p)
   47.25  }
   47.26  #endif
   47.27  
   47.28 -#ifdef __ia64__
   47.29 -#include "ia64_intrinsic.h"
   47.30 +#ifdef __ia64
   47.31 +#include <ia64intrin.h>
   47.32  
   47.33  static inline int testandset (int *p)
   47.34  {
   47.35 -    uint32_t o = 0, n = 1;
   47.36 -    return (int)cmpxchg_acq(p, o, n);
   47.37 +    return __sync_lock_test_and_set (p, 1);
   47.38  }
   47.39  #endif
   47.40  
    48.1 --- a/tools/ioemu/exec.c	Wed May 16 10:42:07 2007 -0600
    48.2 +++ b/tools/ioemu/exec.c	Wed May 16 10:59:01 2007 -0600
    48.3 @@ -41,6 +41,7 @@
    48.4  //#define DEBUG_TB_INVALIDATE
    48.5  //#define DEBUG_FLUSH
    48.6  //#define DEBUG_TLB
    48.7 +//#define DEBUG_UNASSIGNED
    48.8  
    48.9  /* make various TB consistency checks */
   48.10  //#define DEBUG_TB_CHECK 
   48.11 @@ -1288,14 +1289,13 @@ void tlb_flush_page(CPUState *env, targe
   48.12      tlb_flush_entry(&env->tlb_table[0][i], addr);
   48.13      tlb_flush_entry(&env->tlb_table[1][i], addr);
   48.14  
   48.15 -    for(i = 0; i < TB_JMP_CACHE_SIZE; i++) {
   48.16 -        tb = env->tb_jmp_cache[i];
   48.17 -        if (tb && 
   48.18 -            ((tb->pc & TARGET_PAGE_MASK) == addr ||
   48.19 -             ((tb->pc + tb->size - 1) & TARGET_PAGE_MASK) == addr)) {
   48.20 -            env->tb_jmp_cache[i] = NULL;
   48.21 -        }
   48.22 -    }
   48.23 +    /* Discard jump cache entries for any tb which might potentially
   48.24 +       overlap the flushed page.  */
   48.25 +    i = tb_jmp_cache_hash_page(addr - TARGET_PAGE_SIZE);
   48.26 +    memset (&env->tb_jmp_cache[i], 0, TB_JMP_PAGE_SIZE * sizeof(tb));
   48.27 +
   48.28 +    i = tb_jmp_cache_hash_page(addr);
   48.29 +    memset (&env->tb_jmp_cache[i], 0, TB_JMP_PAGE_SIZE * sizeof(tb));
   48.30  
   48.31  #if !defined(CONFIG_SOFTMMU)
   48.32      if (addr < MMAP_AREA_END)
   48.33 @@ -1801,13 +1801,30 @@ void cpu_register_physical_memory(target
   48.34      }
   48.35  }
   48.36  
   48.37 +/* XXX: temporary until new memory mapping API */
   48.38 +uint32_t cpu_get_physical_page_desc(target_phys_addr_t addr)
   48.39 +{
   48.40 +    PhysPageDesc *p;
   48.41 +
   48.42 +    p = phys_page_find(addr >> TARGET_PAGE_BITS);
   48.43 +    if (!p)
   48.44 +        return IO_MEM_UNASSIGNED;
   48.45 +    return p->phys_offset;
   48.46 +}
   48.47 +
   48.48  static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
   48.49  {
   48.50 +#ifdef DEBUG_UNASSIGNED
   48.51 +    printf("Unassigned mem read  0x%08x\n", (int)addr);
   48.52 +#endif
   48.53      return 0;
   48.54  }
   48.55  
   48.56  static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
   48.57  {
   48.58 +#ifdef DEBUG_UNASSIGNED
   48.59 +    printf("Unassigned mem write 0x%08x = 0x%x\n", (int)addr, val);
   48.60 +#endif
   48.61  }
   48.62  
   48.63  static CPUReadMemoryFunc *unassigned_mem_read[3] = {
    49.1 --- a/tools/ioemu/fpu/.CVS/Entries	Wed May 16 10:42:07 2007 -0600
    49.2 +++ b/tools/ioemu/fpu/.CVS/Entries	Wed May 16 10:59:01 2007 -0600
    49.3 @@ -1,7 +1,7 @@
    49.4 -/softfloat-macros.h/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
    49.5 -/softfloat-native.c/1.4/Sun Aug  6 01:03:50 2006//Trelease_0_8_2
    49.6 -/softfloat-native.h/1.6/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
    49.7 -/softfloat-specialize.h/1.1/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
    49.8 -/softfloat.c/1.2/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
    49.9 -/softfloat.h/1.3/Fri Jul 14 12:43:45 2006//Trelease_0_8_2
   49.10 +/softfloat-macros.h/1.1/Wed Oct 18 10:11:20 2006//Trelease_0_9_0
   49.11 +/softfloat-native.c/1.6/Thu May  3 17:18:00 2007//Trelease_0_9_0
   49.12 +/softfloat-native.h/1.8/Thu May  3 17:18:00 2007//Trelease_0_9_0
   49.13 +/softfloat-specialize.h/1.2/Thu May  3 17:18:00 2007//Trelease_0_9_0
   49.14 +/softfloat.c/1.4/Thu May  3 17:18:00 2007//Trelease_0_9_0
   49.15 +/softfloat.h/1.5/Thu May  3 17:18:00 2007//Trelease_0_9_0
   49.16  D
    50.1 --- a/tools/ioemu/fpu/.CVS/Tag	Wed May 16 10:42:07 2007 -0600
    50.2 +++ b/tools/ioemu/fpu/.CVS/Tag	Wed May 16 10:59:01 2007 -0600
    50.3 @@ -1,1 +1,1 @@
    50.4 -Nrelease_0_8_2
    50.5 +Nrelease_0_9_0
    51.1 --- a/tools/ioemu/fpu/softfloat-native.c	Wed May 16 10:42:07 2007 -0600
    51.2 +++ b/tools/ioemu/fpu/softfloat-native.c	Wed May 16 10:59:01 2007 -0600
    51.3 @@ -149,7 +149,7 @@ float32 float32_sqrt( float32 a STATUS_P
    51.4  {
    51.5      return sqrtf(a);
    51.6  }
    51.7 -char float32_compare( float32 a, float32 b STATUS_PARAM )
    51.8 +int float32_compare( float32 a, float32 b STATUS_PARAM )
    51.9  {
   51.10      if (a < b) {
   51.11          return -1;
   51.12 @@ -161,7 +161,7 @@ char float32_compare( float32 a, float32
   51.13          return 2;
   51.14      }
   51.15  }
   51.16 -char float32_compare_quiet( float32 a, float32 b STATUS_PARAM )
   51.17 +int float32_compare_quiet( float32 a, float32 b STATUS_PARAM )
   51.18  {
   51.19      if (isless(a, b)) {
   51.20          return -1;
   51.21 @@ -173,7 +173,7 @@ char float32_compare_quiet( float32 a, f
   51.22          return 2;
   51.23      }
   51.24  }
   51.25 -char float32_is_signaling_nan( float32 a1)
   51.26 +int float32_is_signaling_nan( float32 a1)
   51.27  {
   51.28      float32u u;
   51.29      uint32_t a;
   51.30 @@ -221,6 +221,11 @@ float128 float64_to_float128( float64 a 
   51.31  /*----------------------------------------------------------------------------
   51.32  | Software IEC/IEEE double-precision operations.
   51.33  *----------------------------------------------------------------------------*/
   51.34 +float64 float64_trunc_to_int( float64 a STATUS_PARAM )
   51.35 +{
   51.36 +    return trunc(a);
   51.37 +}
   51.38 +
   51.39  float64 float64_round_to_int( float64 a STATUS_PARAM )
   51.40  {
   51.41  #if defined(__arm__)
   51.42 @@ -253,7 +258,7 @@ float64 float64_sqrt( float64 a STATUS_P
   51.43  {
   51.44      return sqrt(a);
   51.45  }
   51.46 -char float64_compare( float64 a, float64 b STATUS_PARAM )
   51.47 +int float64_compare( float64 a, float64 b STATUS_PARAM )
   51.48  {
   51.49      if (a < b) {
   51.50          return -1;
   51.51 @@ -265,7 +270,7 @@ char float64_compare( float64 a, float64
   51.52          return 2;
   51.53      }
   51.54  }
   51.55 -char float64_compare_quiet( float64 a, float64 b STATUS_PARAM )
   51.56 +int float64_compare_quiet( float64 a, float64 b STATUS_PARAM )
   51.57  {
   51.58      if (isless(a, b)) {
   51.59          return -1;
   51.60 @@ -277,7 +282,7 @@ char float64_compare_quiet( float64 a, f
   51.61          return 2;
   51.62      }
   51.63  }
   51.64 -char float64_is_signaling_nan( float64 a1)
   51.65 +int float64_is_signaling_nan( float64 a1)
   51.66  {
   51.67      float64u u;
   51.68      uint64_t a;
   51.69 @@ -289,6 +294,17 @@ char float64_is_signaling_nan( float64 a
   51.70  
   51.71  }
   51.72  
   51.73 +int float64_is_nan( float64 a1 )
   51.74 +{
   51.75 +    float64u u;
   51.76 +    uint64_t a;
   51.77 +    u.f = a1;
   51.78 +    a = u.i;
   51.79 +
   51.80 +    return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
   51.81 +
   51.82 +}
   51.83 +