Add new -sdcard2 <file> option.
Add support for FreeBSD in the standalone build system.
diff --git a/CHANGES.TXT b/CHANGES.TXT
index 35a519b..08099f0 100644
--- a/CHANGES.TXT
+++ b/CHANGES.TXT
@@ -31,6 +31,9 @@
   The minor number will now be stuck to 0 since each official emulator
   release is supposed to match a corresponding SDK Tools release.
 
+- Added a new option -sdcard2 <file> to be able to use two SD Card images
+  at once. Note that this requires an updated emulator-specific kernel
+  and system image. It will thus be ignored by older emulated platforms.
 
 OTHER:
 
diff --git a/Makefile.android b/Makefile.android
index da06cc6..a9939c1 100644
--- a/Makefile.android
+++ b/Makefile.android
@@ -567,6 +567,10 @@
   LOCAL_LDLIBS += -mno-cygwin -mwindows -mconsole
 endif
 
+ifeq ($(HOST_OS),freebsd)
+    LOCAL_LDLIBS += -L/usr/local/lib -lpthread -lX11 -lutil
+endif
+
 LOCAL_SRC_FILES += $(VL_SOURCES)
 
 ifeq ($(HOST_OS),linux)
diff --git a/android-configure.sh b/android-configure.sh
index 26ea251..742fe21 100755
--- a/android-configure.sh
+++ b/android-configure.sh
@@ -212,6 +212,12 @@
 EXTRA_CFLAGS="$SDL_CFLAGS"
 EXTRA_LDFLAGS="$SDL_LIBS"
 
+case "$OS" in
+    freebsd-*)
+    EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lm -lpthread"
+    ;;
+esac
+
 cat > $TMPC << EOF
 #include <SDL.h>
 #undef main
@@ -278,6 +284,8 @@
     ;;
     linux-*) PROBE_ALSA=yes; PROBE_OSS=yes; PROBE_ESD=yes;
     ;;
+    freebsd-*) PROBE_OSS=yes;
+    ;;
     windows) PROBE_WINAUDIO=yes
     ;;
 esac
@@ -427,6 +435,9 @@
     darwin-*) CONFIG_OS=DARWIN
               BSD=1
     ;;
+    freebsd-*) CONFIG_OS=FREEBSD
+              BSD=1
+    ;;
     windows*) CONFIG_OS=WIN32
     ;;
     *) CONFIG_OS=$OS
diff --git a/android/avd/info.c b/android/avd/info.c
index e738065..6766c96 100644
--- a/android/avd/info.c
+++ b/android/avd/info.c
@@ -92,6 +92,12 @@
  */
 #define  SDCARD_PATH     "sdcard.path"
 
+/* the config.ini key that is used to indicate the absolute path
+ * to the second SD Card image file, if you don't want to place it in
+ * the content directory.
+ */
+#define  SDCARD2_PATH     "sdcard2.path"
+
 /* certain disk image files are mounted read/write by the emulator
  * to ensure that several emulators referencing the same files
  * do not corrupt these files, we need to lock them and respond
@@ -675,7 +681,26 @@
     return l->pPath[0];
 }
 
+static void _sdcardLoadImages(ImageLoader* l, AvdInfo* i, AvdInfoParams* params, AvdImageType sdcardImage)
+{
+    imageLoader_set(l, sdcardImage);
+    imageLoader_load(l, IMAGE_OPTIONAL |
+                        IMAGE_IGNORE_IF_LOCKED);
 
+    /* if the file was not found, ignore it */
+    if (l->pPath[0] && !path_exists(l->pPath[0]))
+    {
+        D("ignoring non-existing %s at %s: %s",
+          l->imageText, l->pPath[0], strerror(errno));
+
+        /* if the user provided the SD Card path by hand,
+         * warn him. */
+        if (params->forcePaths[sdcardImage] != NULL)
+            dwarning("ignoring non-existing SD Card image");
+
+        imageLoader_setPath(l, NULL);
+    }
+}
 
 /* find the correct path of all image files we're going to need
  * and lock the files that need it.
@@ -772,23 +797,8 @@
      * already used, we must ignore it.
      */
     if (!noSdCard) {
-        imageLoader_set (l, AVD_IMAGE_SDCARD);
-        imageLoader_load(l, IMAGE_OPTIONAL |
-                            IMAGE_IGNORE_IF_LOCKED);
-
-        /* if the file was not found, ignore it */
-        if (l->pPath[0] && !path_exists(l->pPath[0])) 
-        {
-            D("ignoring non-existing %s at %s: %s",
-              l->imageText, l->pPath[0], strerror(errno));
-
-            /* if the user provided the SD Card path by hand,
-             * warn him. */
-            if (params->forcePaths[AVD_IMAGE_SDCARD] != NULL)
-                dwarning("ignoring non-existing SD Card image");
-
-            imageLoader_setPath(l, NULL);
-        }
+        _sdcardLoadImages(l, i, params, AVD_IMAGE_SDCARD);
+        _sdcardLoadImages(l, i, params, AVD_IMAGE_SDCARD2);
     }
 
     return 0;
@@ -1043,22 +1053,24 @@
 }
 
 /* If the user didn't explicitely provide an SD Card path,
- * check the SDCARD_PATH key in config.ini and use that if
+ * check the specfied key in config.ini and use that if
  * available.
  */
 static void
-_getSDCardPath( AvdInfo*  i, AvdInfoParams*  params )
+_getSDCardPath(AvdInfo*  i, AvdInfoParams*  params, AvdImageType sdcardImage,
+               const char* iniKey )
 {
     const char*  path;
 
-    if (params->forcePaths[AVD_IMAGE_SDCARD] != NULL)
+    if (params->forcePaths[sdcardImage] != NULL) {
         return;
+    }
 
-    path = iniFile_getString(i->configIni, SDCARD_PATH);
+    path = iniFile_getString(i->configIni, iniKey);
     if (path == NULL)
         return;
 
-    params->forcePaths[AVD_IMAGE_SDCARD] = path;
+    params->forcePaths[sdcardImage] = path;
 }
 
 AvdInfo*
@@ -1087,7 +1099,8 @@
      * obsolete SDKs.
      */
     _getSearchPaths(i);
-    _getSDCardPath(i, params);
+    _getSDCardPath(i, params, AVD_IMAGE_SDCARD, SDCARD_PATH);
+    _getSDCardPath(i, params, AVD_IMAGE_SDCARD2, SDCARD2_PATH);
 
     /* don't need this anymore */
     iniFile_free(i->rootIni);
@@ -1255,6 +1268,9 @@
     if (!noSdCard) {
         imageLoader_set (l, AVD_IMAGE_SDCARD);
         imageLoader_load(l, IMAGE_OPTIONAL | IMAGE_IGNORE_IF_LOCKED);
+
+        imageLoader_set (l, AVD_IMAGE_SDCARD2);
+        imageLoader_load(l, IMAGE_OPTIONAL | IMAGE_IGNORE_IF_LOCKED);
     }
 
     return 0;
diff --git a/android/avd/info.h b/android/avd/info.h
index 19df807..75dab89 100644
--- a/android/avd/info.h
+++ b/android/avd/info.h
@@ -58,6 +58,7 @@
     _AVD_IMG(USERDATA,"userdata-qemu.img", "user data") \
     _AVD_IMG(CACHE,"cache.img","cache") \
     _AVD_IMG(SDCARD,"sdcard.img","SD Card") \
+    _AVD_IMG(SDCARD2,"sdcard2.img","SD Card 2") \
 
 /* define the enumared values corresponding to each AVD image type
  * examples are: AVD_IMAGE_KERNEL, AVD_IMAGE_SYSTEM, etc..
diff --git a/android/build/common.sh b/android/build/common.sh
index 3f2c642..93ffba7 100644
--- a/android/build/common.sh
+++ b/android/build/common.sh
@@ -88,6 +88,9 @@
     Linux)
         # note that building  32-bit binaries on x86_64 is handled later
         OS=linux-$CPU
+	;;
+    FreeBSD)
+        OS=freebsd-$CPU
         ;;
     CYGWIN*|*_NT-*)
         OS=windows
@@ -123,6 +126,8 @@
     ;;
     darwin-*) HOST_OS=darwin
     ;;
+    freebsd-*) HOST_OS=freebsd
+    ;;
     *) HOST_OS=$OS
 esac
 
@@ -161,6 +166,7 @@
         case $OS in
             linux-x86_64) OS=linux-x86 ;;
             darwin-x86_64) OS=darwin-x86 ;;
+	    freebsd-x86_64) OS=freebsd-x86 ;;
         esac
         HOST_ARCH=x86
         CPU=x86
diff --git a/android/cmdline-options.h b/android/cmdline-options.h
index 6a4e7ff..fabac5c 100644
--- a/android/cmdline-options.h
+++ b/android/cmdline-options.h
@@ -76,6 +76,7 @@
 CFG_FLAG ( no_cache, "disable the cache partition" )
 CFG_FLAG ( nocache,  "same as -no-cache" )
 OPT_PARAM( sdcard, "<file>", "SD card image (default <system>/sdcard.img")
+OPT_PARAM( sdcard2, "<file>", "SD card 2 image (default <system>/sdcard2.img")
 OPT_FLAG ( wipe_data, "reset the use data image (copy it from initdata)" )
 CFG_PARAM( avd, "<name>", "use a specific android virtual device" )
 CFG_PARAM( skindir, "<dir>", "search skins in <dir> (default <system>/skins)" )
diff --git a/android/config/freebsd-x86/config-host.h b/android/config/freebsd-x86/config-host.h
new file mode 100644
index 0000000..8a08339
--- /dev/null
+++ b/android/config/freebsd-x86/config-host.h
@@ -0,0 +1,13 @@
+/* Automatically generated by configure - do not modify */
+#define CONFIG_QEMU_SHAREDIR "/usr/local/share/qemu"
+#define HOST_I386 1
+#define HOST_LONG_BITS 32
+#define CONFIG_GDBSTUB 1
+#define CONFIG_SLIRP 1
+#define CONFIG_OSS 1
+#define QEMU_VERSION "0.8.2"
+#define O_LARGEFILE 0
+#define MAP_ANONYMOUS MAP_ANON
+#define _BSD 1
+#define CONFIG_UNAME_RELEASE ""
+#define CONFIG_SKINS 1
diff --git a/android/console.c b/android/console.c
index ab32213..45da8aa 100644
--- a/android/console.c
+++ b/android/console.c
@@ -31,6 +31,8 @@
 #include "hw/power_supply.h"
 #include "shaper.h"
 #include "modem_driver.h"
+#include "block.h"
+#include "block_int.h"
 #include "android/gps.h"
 #include "android/globals.h"
 #include "android/utils/bufprint.h"
@@ -2066,6 +2068,135 @@
 /********************************************************************************************/
 /********************************************************************************************/
 /*****                                                                                 ******/
+/*****                       S D C A R D   C O M M A N D S                             ******/
+/*****                                                                                 ******/
+/********************************************************************************************/
+/********************************************************************************************/
+
+static int
+do_sdcard_insert( ControlClient  client, char*  args )
+{
+    char img[255];
+    char *p;
+    int n;
+    int drv_idx;
+
+    if (!args) {
+        control_write( client, "K0: argument missing, try 'sdcard insert <slot #> [imagefile]'\r\n" );
+        return -1;
+    }
+
+    memset(img, 0, sizeof(img));
+
+    n = strtoul(args, &p, 0);
+    if (n > 2) {
+        control_write( client, "K0: argument out of range\r\n" );
+        return -1;
+    }
+
+    if (p) {
+        p++;
+        strncpy(img, p, sizeof(img) -1);
+    }
+
+    if (goldfish_mmc_is_media_inserted(n)) {
+        control_write( client, "K0: Slot %d already has media inserted\r\n", n );
+        return -1;
+    }
+
+    drv_idx = drive_get_index( IF_IDE, 0, n);
+    if (drv_idx >= 0) {
+        if (img[0] != '\0' && strcmp(img, drives_table[drv_idx].bdrv->filename)) {
+            if (drive_swap(drives_table[drv_idx].bdrv, img)) {
+                control_write (client, "K0: Drive swap failed\r\n");
+                return -1;
+            }
+        }
+    } else {
+        drv_idx = drive_hotadd(img, "index=%d,media=disk", n);
+        if (drv_idx < 0) {
+                control_write (client, "K0: Drive hot-add failed\r\n");
+                return -1;
+        }
+    }
+
+    goldfish_mmc_insert(n, drives_table[drv_idx].bdrv);
+
+    return 0;
+}
+
+static int
+do_sdcard_remove( ControlClient  client, char*  args )
+{
+    int n;
+    int ins;
+
+    if (!args) {
+        control_write( client, "K0: argument missing, try 'sdcard remove <slot #>'\r\n" );
+        return -1;
+    }
+
+    n = atoi(args);
+
+    if ((ins = goldfish_mmc_is_media_inserted(n)) < 0) {
+        control_write( client, "K0: Slot %d is invalid\r\n", n );
+    } else if (!ins) {
+        control_write( client, "K0: Slot %d has no media\r\n", n );
+        return -1;
+    }
+
+    goldfish_mmc_remove(n);
+    return 0;
+}
+
+static int
+do_sdcard_status( ControlClient  client, char*  args )
+{
+    int i;
+    control_write( client, "Current SD card status:\r\n" );
+
+    for (i = 0; i < 2; i++) {
+        int drv_idx = drive_get_index( IF_IDE, 0, i);
+
+        control_write( client,
+                       "  Slot %d, image %s, inserted %d\r\n", i,
+                       (drv_idx >=0 ? drives_table[drv_idx].bdrv->filename : "none"),
+                       goldfish_mmc_is_media_inserted(i));
+    }
+    return 0;
+}
+
+static int
+do_sdcard_fail( ControlClient  client, char*  args )
+{
+	return -ENOSYS;
+}
+
+static const CommandDefRec  sdcard_commands[] =
+{
+    { "insert", "hot-insert a virtual sdcard",
+    "'sdcard insert <slot #> [imagefile]'\r\n",
+    NULL, do_sdcard_insert, NULL },
+
+    { "remove", "hot-remove a virtual sdcard",
+    "'sdcard remove <slot #>'\r\n",
+    NULL, do_sdcard_remove, NULL },
+
+    { "status", "query virtual device status",
+    "'sdcard status'\r\n",
+    NULL, do_sdcard_status, NULL },
+
+    { "fail", "simulate an sdcard failure",
+    "'sdcard fail <read|write>'\r\n",
+    NULL, do_sdcard_fail, NULL },
+
+    { NULL, NULL, NULL, NULL, NULL, NULL }
+};
+
+
+/********************************************************************************************/
+/********************************************************************************************/
+/*****                                                                                 ******/
 /*****                           M A I N   C O M M A N D S                             ******/
 /*****                                                                                 ******/
 /********************************************************************************************/
@@ -2176,6 +2307,10 @@
     "allows you to modify the emulator window\r\n", NULL,
     NULL, window_commands },
 
+    { "sdcard", "manage emulator sdcards",
+    "allows you to modify the emulator sdcard configuration\r\n", NULL,
+    NULL, sdcard_commands },
+
     { NULL, NULL, NULL, NULL, NULL, NULL }
 };
 
diff --git a/android/help.c b/android/help.c
index a142f9d..cbca332 100644
--- a/android/help.c
+++ b/android/help.c
@@ -120,8 +120,8 @@
 
     "  You can use the -sysdir, -system, -kernel, -ramdisk, -datadir, -data options\n"
     "  to specify different search directories or specific image files. You can\n"
-    "  also use the -cache and -sdcard options to indicate specific cache partition\n"
-    "  and SD Card image files.\n\n"
+    "  also use the -cache, -sdcard, and -sdcard2 options to indicate specific \n"
+    "  cache partition and SD Card image files.\n\n"
 
     "  For more details, see the corresponding -help-<option> section.\n\n"
 
@@ -166,6 +166,7 @@
     "    system-qemu.img    an *optional* persistent system image\n"
     "    cache.img          an *optional* cache partition image\n"
     "    sdcard.img         an *optional* SD Card partition image\n\n"
+    "    sdcard2.img        an *optional* second SD Card partition image\n\n"
 
     "  If you use a virtual device, its content directory should store\n"
     "  all writable images, and read-only ones will be found from the\n"
@@ -181,7 +182,7 @@
     "  can still run the emulator by explicitely providing the paths to\n"
     "  *all* required disk images through a combination of the following\n"
     "  options: -sysdir, -datadir, -kernel, -ramdisk, -system, -data, -cache\n"
-    "  and -sdcard\n\n"
+    "  -sdcard, and -sdcard2\n\n"
 
     "  The actual logic being that the emulator should be able to find all\n"
     "  images from the options you give it.\n\n"
@@ -621,6 +622,21 @@
 }
 
 static void
+help_sdcard2(stralloc_t*  out)
+{
+    PRINTF(
+    "  use '-sdcard2 <file>' to specify a second SD Card image file that will be attached\n"
+    "  to the emulator. By default, the 'sdcard.img' file is searched in the data\n"
+    "  directory.\n\n"
+
+    "  if the file does not exist, the emulator will still start, but without a\n"
+    "  second SD Card attached.\n\n"
+
+    "  see '-help-disk-images' for more information about disk image files\n\n"
+    );
+}
+
+static void
 help_skindir(stralloc_t*  out)
 {
     PRINTF(
diff --git a/android/main.c b/android/main.c
index e791efe..de048b9 100644
--- a/android/main.c
+++ b/android/main.c
@@ -1795,6 +1795,7 @@
     int    n;
     char*  opt;
     int    use_sdcard_img = 0;
+    int    use_sdcard2_img = 0;
     int    serial = 0;
     int    gps_serial = 0;
     int    radio_serial = 0;
@@ -2059,6 +2060,14 @@
                 D("autoconfig: -sdcard %s", opts->sdcard);
             }
         }
+
+        if (!opts->sdcard2 && opts->datadir) {
+            bufprint(tmp, tmpend, "%s/sdcard2.img", opts->datadir);
+            if (path_exists(tmp)) {
+                opts->sdcard2 = qemu_strdup(tmp);
+                D("autoconfig: -sdcard2 %s", opts->sdcard2);
+            }
+        }
     }
 
     /* setup the virtual device parameters from our options
@@ -2079,6 +2088,7 @@
     _forceAvdImagePath(AVD_IMAGE_USERDATA,   opts->data,   "user data", 0);
     _forceAvdImagePath(AVD_IMAGE_CACHE,      opts->cache,  "cache", 0);
     _forceAvdImagePath(AVD_IMAGE_SDCARD,     opts->sdcard, "SD Card", 0);
+    _forceAvdImagePath(AVD_IMAGE_SDCARD2,    opts->sdcard2, "SD Card 2", 0);
 
     /* we don't accept -skindir without -skin now
      * to simplify the autoconfig stuff with virtual devices
@@ -2471,11 +2481,14 @@
         args[n++] = strdup(tmp);
     }
 
-    if (hw->hw_sdCard != 0)
+    if (hw->hw_sdCard != 0) {
         opts->sdcard = (char*) avdInfo_getImageFile(avd, AVD_IMAGE_SDCARD);
-    else if (opts->sdcard) {
+        opts->sdcard2 = (char*) avdInfo_getImageFile(avd, AVD_IMAGE_SDCARD2);
+
+    } else if (opts->sdcard || opts->sdcard2) {
         dwarning( "Emulated hardware doesn't support SD Cards" );
         opts->sdcard = NULL;
+        opts->sdcard2 = NULL;
     }
 
     if(opts->sdcard) {
@@ -2497,6 +2510,25 @@
         }
     }
 
+    if(opts->sdcard2) {
+        uint64_t  size;
+        if (path_get_size(opts->sdcard2, &size) == 0) {
+            /* see if we have an sdcard image.  get its size if it exists */
+            /* due to what looks like limitations of the MMC protocol, one has
+             * to use an SD Card image that is equal or larger than 9 MB
+             */
+            if (size < 9*1024*1024ULL) {
+                fprintf(stderr, "### WARNING: SD Card files must be at least 9MB, ignoring '%s'\n", opts->sdcard2);
+            } else {
+                args[n++] = "-hdb";
+                args[n++] = opts->sdcard2;
+                use_sdcard2_img = 1;
+            }
+        } else {
+            D("no SD Card image at '%s'", opts->sdcard2);
+        }
+    }
+
     if (!opts->logcat || opts->logcat[0] == 0) {
         opts->logcat = getenv("ANDROID_LOG_TAGS");
         if (opts->logcat && opts->logcat[0] == 0)
diff --git a/android/utils/timezone.c b/android/utils/timezone.c
index b5588a3..f4b78db 100644
--- a/android/utils/timezone.c
+++ b/android/utils/timezone.c
@@ -96,7 +96,7 @@
 /* on OS X, the timezone directory is always /usr/share/zoneinfo
  * this makes things easy.
  */
-#ifdef __APPLE__
+#if defined(__APPLE__)
 
 #include <unistd.h>
 #include <limits.h>
@@ -149,7 +149,7 @@
  * the original timezone file. the only way to know which zoneinfo name to retrieve is to compare
  * it with all files in $TZDIR (at least those that match Area/Location or Area/Location/SubLocation
  */
-#ifdef __linux__
+#if defined(__linux__) || defined (__FreeBSD__)
 
 #include <unistd.h>
 #include <limits.h>
diff --git a/distrib/sdl-1.2.12/android/build/freebsd-x86/SDL_config.h b/distrib/sdl-1.2.12/android/build/freebsd-x86/SDL_config.h
new file mode 100644
index 0000000..302a22a
--- /dev/null
+++ b/distrib/sdl-1.2.12/android/build/freebsd-x86/SDL_config.h
@@ -0,0 +1,126 @@
+/* This file was autogenerated by 'android-configure.sh' - do not edit */
+#ifndef _SDL_config_h
+#define _SDL_config_h
+
+#include "SDL_platform.h"
+
+#define SDL_HAS_64BIT_TYPE 1
+#define SDL_BYTEORDER 1234
+
+#define HAVE_LIBC 1
+#if HAVE_LIBC
+
+/* Useful headers */
+/* #undef HAVE_ALLOCA_H */
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_STDIO_H 1
+#define STDC_HEADERS  1
+#define HAVE_STDLIB_H 1
+#define HAVE_STDARG_H 1
+/* #undef HAVE_MALLOC_H */
+#define HAVE_MEMORY_H 1
+#define HAVE_STRING_H 1
+#define HAVE_STRINGS_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_CTYPE_H 1
+#define HAVE_MATH_H 1
+/* #undef HAVE_ICONV_H */
+#define HAVE_SIGNAL_H 1
+/* #undef HAVE_ALTIVEC_H */
+/* C library functions */
+#define HAVE_MALLOC 1
+#define HAVE_CALLOC 1
+#define HAVE_REALLOC 1
+#define HAVE_FREE 1
+/* #undef HAVE_ALLOC */
+#ifndef _WIN32 /* Don't use on Windows */
+#define HAVE_GETENV 1
+#define HAVE_PUTENV 1
+#define HAVE_UNSETENV 1
+#endif
+#define HAVE_QSORT 1
+#define HAVE_ABS 1
+#define HAVE_BCOPY 1
+#define HAVE_MEMSET 1
+#define HAVE_MEMCPY 1
+#define HAVE_MEMMOVE 1
+#define HAVE_MEMCMP 1
+#define HAVE_STRLEN 1
+#define HAVE_STRLCPY 1
+#define HAVE_STRLCAT 1
+#define HAVE_STRDUP 1
+/* #undef HAVE__STRREV */
+/* #undef HAVE__STRUPR */
+/* #undef HAVE__STRLWR */
+#define HAVE_INDEX 1
+#define HAVE_RINDEX 1
+#define HAVE_STRCHR 1
+#define HAVE_STRRCHR 1
+/* #undef HAVE_ITOA */
+/* #undef HAVE__LTOA */
+/* #undef HAVE__UITOA */
+/* #undef HAVE__ULTOA */
+#define HAVE_STRTOL 1
+#define HAVE_STRTOUL 1
+/* #undef HAVE__I64TOA */
+/* #undef HAVE__UI64TOA */
+#define HAVE_STRTOLL 1
+#define HAVE_STRTOULL 1
+#define HAVE_STRTOD 1
+#define HAVE_ATOI 1
+#define HAVE_ATOF 1
+#define HAVE_STRCMP 1
+#define HAVE_STRNCMP 1
+/* #undef HAVE__STRICMP */
+#define HAVE_STRCASECMP 1
+/* #undef HAVE__STRNICMP */
+#define HAVE_VSNPRINTF 1
+/* #undef HAVE_ICONV */
+#define HAVE_SIGACTION 1
+#define HAVE_SETJMP 1
+#define HAVE_NANOSLEEP 1
+#define HAVE_CLOCK_GETTIME 1
+/* #undef HAVE_DLVSYM */
+#define HAVE_GETPAGESIZE 1
+#else
+/* We may need some replacement for stdarg.h here */
+#include <stdarg.h>
+#endif /* HAVE_LIBC */
+
+/* Allow disabling of core subsystems */
+/* #undef SDL_AUDIO_DISABLED */
+#define SDL_CDROM_DISABLED 1
+/* #undef SDL_CPUINFO_DISABLED */
+/* #undef SDL_EVENTS_DISABLED */
+#define SDL_FILE_DISABLED 1
+#define SDL_JOYSTICK_DISABLED 1
+/* #undef SDL_LOADSO_DISABLED */
+/* #undef SDL_THREADS_DISABLED */
+/* #undef SDL_TIMERS_DISABLED */
+/* #undef SDL_VIDEO_DISABLED */
+
+/* Enable various audio drivers */
+#define SDL_AUDIO_DRIVER_OSS 1
+
+/* Enable various shared object loading systems */
+#define SDL_LOADSO_DLOPEN 1
+
+/* Enable various threading systems */
+#define SDL_THREAD_PTHREAD 1
+#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1
+
+/* Enable various timer systems */
+#define SDL_TIMER_UNIX 1
+
+/* Enable various video drivers */
+#define SDL_VIDEO_DRIVER_X11 1
+#define SDL_VIDEO_DRIVER_X11_DPMS 1
+#define SDL_VIDEO_DRIVER_X11_XINERAMA 1
+#define SDL_VIDEO_DRIVER_X11_XME 1
+#define SDL_MAIN_DUMMY 1
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC "libX11.so.6"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT "libXext.so.6"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR "libXrandr.so.2"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XRENDER "libXrender.so.1"
+#endif /* _SDL_config_h */
diff --git a/hw/android_arm.c b/hw/android_arm.c
index 32f6925..4ef4a10 100644
--- a/hw/android_arm.c
+++ b/hw/android_arm.c
@@ -42,7 +42,18 @@
 
 /* Board init.  */
 
-#define TEST_SWITCH 1
+static void goldfish_sdcard_init(int n, unsigned base)
+{
+    int idx = drive_get_index( IF_IDE, 0, n );
+
+    goldfish_mmc_init(base, n);
+
+    if (idx >= 0) {
+        goldfish_mmc_insert(n, drives_table[idx].bdrv);
+    }
+}
+
+// #define TEST_SWITCH 1
 #if TEST_SWITCH
 uint32_t switch_test_write(void *opaque, uint32_t state)
 {
@@ -113,11 +124,9 @@
 #ifdef HAS_AUDIO
     goldfish_audio_init(0xff004000, 0, audio_input_source);
 #endif
-    {
-        int  idx = drive_get_index( IF_IDE, 0, 0 );
-        if (idx >= 0)
-            goldfish_mmc_init(0xff005000, 0, drives_table[idx].bdrv);
-    }
+
+    goldfish_sdcard_init(0, 0xff005000);
+    goldfish_sdcard_init(1, 0xff007000);
 
     goldfish_memlog_init(0xff006000);
 
diff --git a/hw/goldfish_device.h b/hw/goldfish_device.h
index d04a166..d0739b7 100644
--- a/hw/goldfish_device.h
+++ b/hw/goldfish_device.h
@@ -46,7 +46,12 @@
 void goldfish_battery_init();
 void goldfish_battery_set_prop(int ac, int property, int value);
 void goldfish_battery_display(void (* callback)(void *data, const char* string), void *data);
-void goldfish_mmc_init(uint32_t base, int id, BlockDriverState* bs);
+
+void goldfish_mmc_init(uint32_t base, int id);
+void goldfish_mmc_insert(int id, BlockDriverState* bs);
+void goldfish_mmc_remove(int id);
+int goldfish_mmc_is_media_inserted(int id);
+
 void *goldfish_switch_add(char *name, uint32_t (*writefn)(void *opaque, uint32_t state), void *writeopaque, int id);
 void goldfish_switch_set_state(void *opaque, uint32_t state);
 
diff --git a/hw/goldfish_mmc.c b/hw/goldfish_mmc.c
index 3824db9..8b5c137 100644
--- a/hw/goldfish_mmc.c
+++ b/hw/goldfish_mmc.c
@@ -52,6 +52,7 @@
     MMC_STAT_END_OF_CMD     = 1U << 0,
     MMC_STAT_END_OF_DATA    = 1U << 1,
     MMC_STAT_STATE_CHANGE   = 1U << 2,
+    MMC_STAT_CMD_TIMEOUT    = 1U << 3,
 
     /* MMC_STATE bits */
     MMC_STATE_INSERTED     = 1U << 0,
@@ -82,6 +83,9 @@
     uint8_t* buf;
 };
 
+#define GOLDFISH_MMC_MAX 2
+static struct goldfish_mmc_state *gDrvState[GOLDFISH_MMC_MAX];
+
 #define  GOLDFISH_MMC_SAVE_VERSION  2
 #define  QFIELD_STRUCT  struct goldfish_mmc_state
 QFIELD_BEGIN(goldfish_mmc_fields)
@@ -218,13 +222,24 @@
     int new_status = MMC_STAT_END_OF_CMD;
     int opcode = cmd & 63;
 
-// fprintf(stderr, "goldfish_mmc_do_command opcode: %s (0x%04X), arg: %d\n", get_command_name(opcode), cmd, arg);
-
+ //fprintf(stderr, "goldfish_mmc_do_command opcode: %s (0x%04X), arg: %d\n", get_command_name(opcode), cmd, arg);
     s->resp[0] = 0;
     s->resp[1] = 0;
     s->resp[2] = 0;
     s->resp[3] = 0;
 
+    if (!s->bs) {
+        /*
+         * No backing store available. Signal a command timeout
+         * to the host. If the command timeout irq enable is set
+         * then also set the status bit - otherwise we're assuming
+         * a legacy driver which doesnt support timeouts.
+         */
+        if (s->int_enable & MMC_STAT_CMD_TIMEOUT)
+            new_status |= MMC_STAT_CMD_TIMEOUT;
+        goto skip;
+    }
+
 #define SET_R1_CURRENT_STATE(s)    ((s << 9) & 0x00001E00) /* sx, b (4 bits) */
 
     switch (opcode) {
@@ -405,6 +420,7 @@
             break;
      }
 
+ skip:
     s->int_status |= new_status;
 
     if ((s->int_status & s->int_enable)) {
@@ -414,7 +430,7 @@
 
 static uint32_t goldfish_mmc_read(void *opaque, target_phys_addr_t offset)
 {
-    uint32_t ret;
+    uint32_t ret = 0;
     struct goldfish_mmc_state *s = opaque;
 
     switch(offset) {
@@ -430,9 +446,11 @@
         case MMC_RESP_3:
             return s->resp[3];
         case MMC_STATE: {
-            ret = MMC_STATE_INSERTED;
-            if (bdrv_is_read_only(s->bs)) {
-                ret |= MMC_STATE_READ_ONLY;
+            if (s->bs) {
+                ret = MMC_STATE_INSERTED;
+                if (bdrv_is_read_only(s->bs)) {
+                    ret |= MMC_STATE_READ_ONLY;
+                }
             }
             return ret;
         }
@@ -499,22 +517,71 @@
    goldfish_mmc_write
 };
 
-void goldfish_mmc_init(uint32_t base, int id, BlockDriverState* bs)
+void goldfish_mmc_init(uint32_t base, int id)
 {
     struct goldfish_mmc_state *s;
 
+    if (id >= GOLDFISH_MMC_MAX) {
+        fprintf(stderr, "mmc controller %d out of range\n", id);
+        return;
+    }
+
     s = (struct goldfish_mmc_state *)qemu_mallocz(sizeof(*s));
     s->dev.name = "goldfish_mmc";
     s->dev.id = id;
     s->dev.base = base;
     s->dev.size = 0x1000;
     s->dev.irq_count = 1;
-    s->bs = bs;
+    s->bs = NULL;
     s->buf = qemu_memalign(512,512);
 
+    gDrvState[id] = s;
+
     goldfish_device_add(&s->dev, goldfish_mmc_readfn, goldfish_mmc_writefn, s);
 
-    register_savevm( "goldfish_mmc", 0, GOLDFISH_MMC_SAVE_VERSION,
+    register_savevm( (!id ? "goldfish_mmc0" : "goldfish_mmc1"),
+                     id, GOLDFISH_MMC_SAVE_VERSION,
                      goldfish_mmc_save, goldfish_mmc_load, s);
 }
 
+static void goldfish_mmc_setbs(struct goldfish_mmc_state* s, BlockDriverState* bs)
+{
+    s->bs = bs;
+    s->int_status |= MMC_STAT_STATE_CHANGE;
+
+    /*
+     * Legacy - only send state change irq if
+     * the driver has the CMD_TIMEOUT irq enabled.
+     */
+    if (s->int_enable & MMC_STAT_CMD_TIMEOUT)
+        goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable));
+}
+
+void goldfish_mmc_insert(int id, BlockDriverState* bs)
+{
+    if (id >= GOLDFISH_MMC_MAX) {
+        return -1;
+    }
+
+    goldfish_mmc_setbs(gDrvState[id], bs);
+}
+
+int goldfish_mmc_is_media_inserted(int id)
+{
+    if (id > GOLDFISH_MMC_MAX) {
+        return -1;
+    }
+
+    return (gDrvState[id]->bs != NULL);
+}
+
+void goldfish_mmc_remove(int id)
+{
+    if (id >= GOLDFISH_MMC_MAX) {
+        return -1;
+    }
+
+    goldfish_mmc_setbs(gDrvState[id], NULL);
+}
+
+
diff --git a/sysemu.h b/sysemu.h
index fe24415..7959197 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -173,6 +173,7 @@
 extern DriveInfo drives_table[MAX_DRIVES+1];
 
 extern int drive_get_index(BlockInterfaceType type, int bus, int unit);
+extern int drive_get_index_by_bdrv(BlockDriverState *bdrv);
 extern int drive_get_max_bus(BlockInterfaceType type);
 extern void drive_uninit(BlockDriverState *bdrv);
 extern void drive_remove(int index);
@@ -192,6 +193,8 @@
 
 extern int drive_add(const char *file, const char *fmt, ...);
 extern int drive_init(struct drive_opt *arg, int snapshot, void *machine);
+extern int drive_swap(struct BlockDriverState *bdrv, const char *file);
+extern int drive_hotadd(const char *file, const char *fmt, ...);
 
 /* acpi */
 void qemu_system_hot_add_init(void);
diff --git a/vl-android.c b/vl-android.c
index d6feced..5d234a2 100644
--- a/vl-android.c
+++ b/vl-android.c
@@ -2223,6 +2223,41 @@
     return -1;
 }
 
+int drive_swap(BlockDriverState *bdrv, const char *file)
+{
+    int index = drive_get_index_by_bdrv(bdrv);
+    int unit = drives_table[index].unit;
+    int opt_idx;
+
+    bdrv_close(bdrv);
+    drive_uninit(bdrv);
+    bdrv_delete(bdrv);
+
+    opt_idx = drive_add(file, HD_ALIAS, unit);
+    return drive_init(&drives_opt[opt_idx], 0, current_machine);
+}
+
+int drive_hotadd(const char *file, const char *fmt, ...)
+{
+    va_list ap;
+    int index = drive_opt_get_free_idx();
+
+    if (nb_drives_opt >= MAX_DRIVES || index == -1) {
+        fprintf(stderr, "qemu: too many drives\n");
+        return -1;
+    }
+
+    drives_opt[index].file = file;
+    va_start(ap, fmt);
+    vsnprintf(drives_opt[index].opt,
+              sizeof(drives_opt[0].opt), fmt, ap);
+    va_end(ap);
+    nb_drives_opt++;
+    if (drive_init(&drives_opt[index], 0, current_machine) < 0)
+        return -1;
+    return index;
+}
+
 int drive_add(const char *file, const char *fmt, ...)
 {
     va_list ap;
@@ -2238,7 +2273,6 @@
     vsnprintf(drives_opt[index].opt,
               sizeof(drives_opt[0].opt), fmt, ap);
     va_end(ap);
-
     nb_drives_opt++;
     return index;
 }
@@ -2249,6 +2283,15 @@
     nb_drives_opt--;
 }
 
+int drive_get_index_by_bdrv(BlockDriverState *bdrv)
+{
+    int index;
+
+    for (index = 0; index < MAX_DRIVES; index++)
+        if (drives_table[index].bdrv == bdrv)
+            return index;
+    return -1;
+}
 int drive_get_index(BlockInterfaceType type, int bus, int unit)
 {
     int index;