Refactor recovery's block device handling to work across variant hardware in a cleaner fashion.

Re add firmware update

Change-Id: I699ad22390ed14e597d17a7bcb32ad1b1af00b4b

support mmc misc

Change-Id: Iff02f8d03db6835f501d052140cebeefee521305

fix compile errors

Change-Id: I032edbd157a8a15f561bb83330c715ebaa008d18

fix compile errors

Change-Id: Idff3449be3376f22fceefc2c35637527f8df8f3f

Initial work to clean up the block devices.

Change-Id: I4be20ac124864a281be9cd116e211a2618404a27

all done

Change-Id: I0338f62f6a045556ebe90b0200685be113178319

fix up nandroid

Change-Id: I886f00271183e6d2921c080b0939341f2cf12a4d
diff --git a/Android.mk b/Android.mk
index 4786c79..817bef8 100644
--- a/Android.mk
+++ b/Android.mk
@@ -8,6 +8,7 @@
 # LOCAL_CPP_EXTENSION := .c
 
 LOCAL_SRC_FILES := \
+    mounts.c \
 	extendedcommands.c \
 	nandroid.c \
 	legacy.c \
@@ -49,94 +50,13 @@
 RECOVERY_API_VERSION := 2
 LOCAL_CFLAGS += -DRECOVERY_API_VERSION=$(RECOVERY_API_VERSION)
 
-ifeq ($(BOARD_HAS_NO_SELECT_BUTTON),true)
-  LOCAL_CFLAGS += -DKEY_POWER_IS_SELECT_ITEM
-endif
+BOARD_RECOVERY_DEFINES := BOARD_HAS_NO_SELECT_BUTTON BOARD_SDCARD_DEVICE_PRIMARY BOARD_SDCARD_DEVICE_SECONDARY BOARD_SDEXT_DEVICE BOARD_SDEXT_FILESYSTEM BOARD_DATA_DEVICE BOARD_DATA_FILESYSTEM BOARD_DATADATA_DEVICE BOARD_DATADATA_FILESYSTEM BOARD_CACHE_DEVICE BOARD_CACHE_FILESYSTEM BOARD_SYSTEM_DEVICE BOARD_SYSTEM_FILESYSTEM BOARD_HAS_DATADATA BOARD_DATA_FILESYSTEM_OPTIONS BOARD_DATADATA_FILESYSTEM_OPTIONS BOARD_CACHE_FILESYSTEM_OPTIONS BOARD_SYSTEM_FILESYSTEM_OPTIONS BOARD_HAS_MTD_CACHE BOARD_USES_BMLUTILS BOARD_USES_MMCUTILS BOARD_HAS_SMALL_RECOVERY
 
-ifdef BOARD_SDCARD_DEVICE_PRIMARY
-  LOCAL_CFLAGS += -DSDCARD_DEVICE_PRIMARY=\"$(BOARD_SDCARD_DEVICE_PRIMARY)\"
-endif
-
-ifdef BOARD_SDCARD_DEVICE_SECONDARY
-  LOCAL_CFLAGS += -DSDCARD_DEVICE_SECONDARY=\"$(BOARD_SDCARD_DEVICE_SECONDARY)\"
-endif
-
-ifdef BOARD_SDEXT_DEVICE
-  LOCAL_CFLAGS += -DSDEXT_DEVICE=\"$(BOARD_SDEXT_DEVICE)\"
-endif
-
-ifdef BOARD_SDEXT_FILESYSTEM
-  LOCAL_CFLAGS += -DSDEXT_FILESYSTEM=\"$(BOARD_SDEXT_FILESYSTEM)\"
-endif
-
-ifdef BOARD_DATA_DEVICE
-  LOCAL_CFLAGS += -DDATA_DEVICE=\"$(BOARD_DATA_DEVICE)\"
-endif
-
-ifdef BOARD_DATA_FILESYSTEM
-  LOCAL_CFLAGS += -DDATA_FILESYSTEM=\"$(BOARD_DATA_FILESYSTEM)\"
-endif
-
-ifdef BOARD_DATADATA_DEVICE
-  LOCAL_CFLAGS += -DDATADATA_DEVICE=\"$(BOARD_DATADATA_DEVICE)\"
-endif
-
-ifdef BOARD_DATADATA_FILESYSTEM
-  LOCAL_CFLAGS += -DDATADATA_FILESYSTEM=\"$(BOARD_DATADATA_FILESYSTEM)\"
-endif
-
-ifdef BOARD_CACHE_DEVICE
-  LOCAL_CFLAGS += -DCACHE_DEVICE=\"$(BOARD_CACHE_DEVICE)\"
-endif
-
-ifdef BOARD_CACHE_FILESYSTEM
-  LOCAL_CFLAGS += -DCACHE_FILESYSTEM=\"$(BOARD_CACHE_FILESYSTEM)\"
-endif
-
-ifdef BOARD_SYSTEM_DEVICE
-  LOCAL_CFLAGS += -DSYSTEM_DEVICE=\"$(BOARD_SYSTEM_DEVICE)\"
-endif
-
-ifdef BOARD_SYSTEM_FILESYSTEM
-  LOCAL_CFLAGS += -DSYSTEM_FILESYSTEM=\"$(BOARD_SYSTEM_FILESYSTEM)\"
-endif
-
-ifdef BOARD_HAS_DATADATA
-  LOCAL_CFLAGS += -DHAS_DATADATA
-endif
-
-ifdef BOARD_DATA_FILESYSTEM_OPTIONS
-  LOCAL_CFLAGS += -DDATA_FILESYSTEM_OPTIONS=\"$(BOARD_DATA_FILESYSTEM_OPTIONS)\"
-endif
-
-ifdef BOARD_DATADATA_FILESYSTEM_OPTIONS
-  LOCAL_CFLAGS += -DDATADATA_FILESYSTEM_OPTIONS=\"$(BOARD_DATADATA_FILESYSTEM_OPTIONS)\"
-endif
-
-ifdef BOARD_CACHE_FILESYSTEM_OPTIONS
-  LOCAL_CFLAGS += -DCACHE_FILESYSTEM_OPTIONS=\"$(BOARD_CACHE_FILESYSTEM_OPTIONS)\"
-endif
-
-ifdef BOARD_SYSTEM_FILESYSTEM_OPTIONS
-  LOCAL_CFLAGS += -DSYSTEM_FILESYSTEM_OPTIONS=\"$(BOARD_SYSTEM_FILESYSTEM_OPTIONS)\"
-endif
-
-ifdef BOARD_HAS_MTD_CACHE
-  LOCAL_CFLAGS += -DBOARD_HAS_MTD_CACHE
-endif
-
-ifdef BOARD_USES_BMLUTILS
-  LOCAL_CFLAGS += -DBOARD_USES_BMLUTILS
-  LOCAL_STATIC_LIBRARIES += libbmlutils
-endif
-
-ifdef BOARD_USES_MMCUTILS
-  LOCAL_CFLAGS += -DBOARD_USES_MMCUTILS
-endif
-
-ifdef BOARD_HAS_SMALL_RECOVERY
-  LOCAL_CFLAGS += -DBOARD_HAS_SMALL_RECOVERY
-endif
+$(foreach board_define,$(BOARD_RECOVERY_DEFINES), \
+  $(if $($(board_define)), \
+    $(eval LOCAL_CFLAGS += -D$(board_define)=\"$($(board_define))\") \
+  ) \
+  )
 
 # This binary is in the recovery ramdisk, which is otherwise a copy of root.
 # It gets copied there in config/Makefile.  LOCAL_MODULE_TAGS suppresses
@@ -151,9 +71,20 @@
 else
   LOCAL_SRC_FILES += $(BOARD_CUSTOM_RECOVERY_KEYMAPPING)
 endif
-LOCAL_STATIC_LIBRARIES += libbusybox libclearsilverregex libmkyaffs2image libunyaffs liberase_image libdump_image libflash_image libmtdutils
+LOCAL_STATIC_LIBRARIES += libbusybox libclearsilverregex libmkyaffs2image libunyaffs liberase_image libdump_image libflash_image
+
+ifdef BOARD_USES_BMLUTILS
+	BOARD_FLASH_LIBRARY := libbmlutils
+else ifdef BOARD_USES_MMCUTILS
+	BOARD_FLASH_LIBRARY := libmmcutils
+else
+	BOARD_FLASH_LIBRARY := libmtdutils
+endif
+
+LOCAL_STATIC_LIBRARIES += $(BOARD_FLASH_LIBRARY)
+
 LOCAL_STATIC_LIBRARIES += libamend
-LOCAL_STATIC_LIBRARIES += libminzip libunz libmtdutils libmmcutils libmincrypt
+LOCAL_STATIC_LIBRARIES += libminzip libunz libmincrypt
 LOCAL_STATIC_LIBRARIES += libminui libpixelflinger_static libpng libcutils
 LOCAL_STATIC_LIBRARIES += libstdc++ libc
 
@@ -217,6 +148,7 @@
 
 include $(commands_recovery_local_path)/amend/Android.mk
 include $(commands_recovery_local_path)/bmlutils/Android.mk
+include $(commands_recovery_local_path)/flashutils/Android.mk
 include $(commands_recovery_local_path)/minui/Android.mk
 include $(commands_recovery_local_path)/minzip/Android.mk
 include $(commands_recovery_local_path)/mtdutils/Android.mk
diff --git a/commands.c b/commands.c
index 8db0aba..c7e4fd7 100644
--- a/commands.c
+++ b/commands.c
@@ -145,7 +145,7 @@
         LOGE("Can't format %s\n", root);
         return 1;
     }
-#ifdef HAS_DATADATA
+#ifdef BOARD_HAS_DATADATA
     if (0 == strcmp(root, "DATA:")) {
         ret = format_root_device("DATADATA:");
         if (ret != 0) {
@@ -653,6 +653,7 @@
 cmd_write_raw_image(const char *name, void *cookie,
         int argc, const char *argv[], PermissionRequestList *permissions)
 {
+#ifdef BOARD_USES_MTDUTILS
     UNUSED(cookie);
     CHECK_WORDS();
 //xxx permissions
@@ -738,6 +739,10 @@
         return -1;
     }
     return 0;
+#else
+    LOGE("Board does not support mtd utils.");
+    return -1;
+#endif
 }
 
 /* mark <resource> dirty|clean
diff --git a/extendedcommands.c b/extendedcommands.c
index cc7fb01..801f4a8 100644
--- a/extendedcommands.c
+++ b/extendedcommands.c
@@ -33,9 +33,6 @@
 #include "commands.h"
 #include "amend/amend.h"
 
-#include "mtdutils/mtdutils.h"
-#include "mmcutils/mmcutils.h"
-#include "mtdutils/dump_image.h"
 #include "../../external/yaffs2/yaffs2/utils/mkyaffs2image.h"
 #include "../../external/yaffs2/yaffs2/utils/unyaffs.h"
 
@@ -395,7 +392,7 @@
 void show_mount_usb_storage_menu()
 {
     char command[PATH_MAX];
-    sprintf(command, "echo %s > /sys/devices/platform/usb_mass_storage/lun0/file", SDCARD_DEVICE_PRIMARY);
+    sprintf(command, "echo %s > /sys/devices/platform/usb_mass_storage/lun0/file", BOARD_SDCARD_DEVICE_PRIMARY);
     __system(command);
     static char* headers[] = {  "USB Mass Storage device",
                                 "Leaving this menu unmount",
@@ -441,13 +438,13 @@
     return chosen_item == 7;
 }
 
-int format_non_mtd_device(const char* root)
+int format_unknown_device(const char* root)
 {
     // if this is SDEXT:, don't worry about it.
     if (0 == strcmp(root, "SDEXT:"))
     {
         struct stat st;
-        if (0 != stat(SDEXT_DEVICE, &st))
+        if (0 != stat(BOARD_SDEXT_DEVICE, &st))
         {
             ui_print("No app2sd partition found. Skipping format of /sd-ext.\n");
             return 0;
@@ -569,7 +566,7 @@
             if (!confirm_selection(confirm_format, confirm))
                 continue;
             ui_print("Formatting %s...\n", mmcs[chosen_item][1]);
-            if (0 != format_non_mtd_device(mmcs[chosen_item][1]))
+            if (0 != format_unknown_device(mmcs[chosen_item][1]))
                 ui_print("Error formatting %s!\n", mmcs[chosen_item][1]);
             else
                 ui_print("Done.\n");
@@ -918,22 +915,15 @@
         LOGW("Unable to get root info for %s during fstab generation!", root_path);
         return;
     }
-    MtdPartition *mtd = get_root_mtd_partition(root_path);
-    if (mtd != NULL)
+    char device[PATH_MAX];
+    int ret = get_root_partition_device(root_path, device);
+    if (ret == 0)
     {
-        fprintf(file, "/dev/block/mtdblock%d ", mtd->device_index);
+        fprintf(file, "%s ", device);
     }
     else
     {
-        MmcPartition *mmc = get_root_mmc_partition(root_path);
-        if (mmc != NULL)
-        {
-            fprintf(file, "%s ", mmc->device_index);
-        }
-        else
-        {
-            fprintf(file, "%s ", info->device);
-        }
+        fprintf(file, "%s ", info->device);
     }
     
     fprintf(file, "%s ", info->mount_point);
@@ -950,7 +940,7 @@
     }
     write_fstab_root("CACHE:", file);
     write_fstab_root("DATA:", file);
-#ifdef HAS_DATADATA
+#ifdef BOARD_HAS_DATADATA
     write_fstab_root("DATADATA:", file);
 #endif
     write_fstab_root("SYSTEM:", file);
diff --git a/extendedcommands.h b/extendedcommands.h
index 9d38116..650a519 100644
--- a/extendedcommands.h
+++ b/extendedcommands.h
@@ -38,7 +38,7 @@
 show_advanced_menu();
 
 int
-format_non_mtd_device(const char* root);
+format_unknown_device(const char* root);
 
 void
 wipe_battery_stats();
diff --git a/flashutils/Android.mk b/flashutils/Android.mk
new file mode 100644
index 0000000..5742af3
--- /dev/null
+++ b/flashutils/Android.mk
@@ -0,0 +1,84 @@
+LOCAL_PATH := $(call my-dir)
+
+ifneq ($(TARGET_SIMULATOR),true)
+ifeq ($(TARGET_ARCH),arm)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := flash_image.c
+LOCAL_MODULE := flash_image
+LOCAL_MODULE_TAGS := eng
+LOCAL_STATIC_LIBRARIES := $(BOARD_FLASH_LIBRARY)
+LOCAL_SHARED_LIBRARIES := libcutils libc
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := dump_image.c
+LOCAL_MODULE := dump_image
+LOCAL_MODULE_TAGS := eng
+LOCAL_STATIC_LIBRARIES := $(BOARD_FLASH_LIBRARY)
+LOCAL_SHARED_LIBRARIES := libcutils libc
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := erase_image.c
+LOCAL_MODULE := erase_image
+LOCAL_MODULE_TAGS := eng
+LOCAL_STATIC_LIBRARIES := $(BOARD_FLASH_LIBRARY)
+LOCAL_SHARED_LIBRARIES := libcutils libc
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := flash_image.c
+LOCAL_MODULE := libflash_image
+LOCAL_CFLAGS += -Dmain=flash_image_main
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := dump_image.c
+LOCAL_MODULE := libdump_image
+LOCAL_CFLAGS += -Dmain=dump_image_main
+include $(BUILD_STATIC_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := erase_image.c
+LOCAL_MODULE := liberase_image
+LOCAL_CFLAGS += -Dmain=erase_image_main
+include $(BUILD_STATIC_LIBRARY)
+
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := dump_image.c
+LOCAL_MODULE := utility_dump_image
+LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities
+LOCAL_UNSTRIPPED_PATH := $(PRODUCT_OUT)/symbols/utilities
+LOCAL_MODULE_STEM := dump_image
+LOCAL_STATIC_LIBRARIES := $(BOARD_FLASH_LIBRARY) libcutils libc
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := flash_image.c
+LOCAL_MODULE := utility_flash_image
+LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities
+LOCAL_UNSTRIPPED_PATH := $(PRODUCT_OUT)/symbols/utilities
+LOCAL_MODULE_STEM := flash_image
+LOCAL_STATIC_LIBRARIES := $(BOARD_FLASH_LIBRARY) libcutils libc
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES := erase_image.c
+LOCAL_MODULE := utility_erase_image
+LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities
+LOCAL_UNSTRIPPED_PATH := $(PRODUCT_OUT)/symbols/utilities
+LOCAL_MODULE_STEM := erase_image
+LOCAL_STATIC_LIBRARIES := $(BOARD_FLASH_LIBRARY) libcutils libc
+LOCAL_FORCE_STATIC_EXECUTABLE := true
+include $(BUILD_EXECUTABLE)
+
+
+endif	# TARGET_ARCH == arm
+endif	# !TARGET_SIMULATOR
diff --git a/mtdutils/dump_image.c b/flashutils/dump_image.c
similarity index 93%
rename from mtdutils/dump_image.c
rename to flashutils/dump_image.c
index 8b0a896..4db1f74 100644
--- a/mtdutils/dump_image.c
+++ b/flashutils/dump_image.c
@@ -23,13 +23,14 @@
 #include <sys/ioctl.h>
 
 #include "cutils/log.h"
-#include "mtdutils.h"
-#include "dump_image.h"
+#include "flashutils.h"
 
 #ifdef LOG_TAG
 #undef LOG_TAG
 #endif
 
+#if 0
+
 #define LOG_TAG "dump_image"
 
 #define BLOCK_SIZE    2048
@@ -135,3 +136,15 @@
 
     return dump_image(argv[1], argv[2], NULL);
 }
+
+#endif
+
+int main(int argc, char **argv)
+{
+    if (argc != 3) {
+        fprintf(stderr, "usage: %s partition file.img\n", argv[0]);
+        return 2;
+    }
+
+    return backup_raw_partition(argv[1], argv[2]);
+}
diff --git a/mtdutils/erase_image.c b/flashutils/erase_image.c
similarity index 90%
rename from mtdutils/erase_image.c
rename to flashutils/erase_image.c
index 37623b8..c495255 100644
--- a/mtdutils/erase_image.c
+++ b/flashutils/erase_image.c
@@ -23,15 +23,17 @@
 #include <unistd.h>
 
 #include <fcntl.h>
-#include <mtd/mtd-user.h>
 
 #include "cutils/log.h"
-#include "mtdutils.h"
+#include "flashutils.h"
+
+#if 0
 
 #ifdef LOG_TAG
 #undef LOG_TAG
 #endif
 
+
 #define LOG_TAG "erase_image"
 
 static int die(const char *msg, ...) {
@@ -86,3 +88,16 @@
     
     return erase_image(argv[1]);
 }
+
+#endif
+
+
+int main(int argc, char **argv)
+{
+    if (argc != 2) {
+        fprintf(stderr, "usage: %s partition\n", argv[0]);
+        return 2;
+    }
+
+    return erase_raw_partition(argv[1]);
+}
diff --git a/mtdutils/flash_image.c b/flashutils/flash_image.c
similarity index 95%
rename from mtdutils/flash_image.c
rename to flashutils/flash_image.c
index c776876..560370c 100644
--- a/mtdutils/flash_image.c
+++ b/flashutils/flash_image.c
@@ -22,8 +22,8 @@
 #include <unistd.h>
 
 #include "cutils/log.h"
-#include "mtdutils.h"
 
+#if 0
 #define LOG_TAG "flash_image"
 
 #define HEADER_SIZE 2048  // size of header to compare for equality
@@ -138,3 +138,14 @@
     if (mtd_write_close(out)) die("error closing %s", argv[1]);
     return 0;
 }
+#endif
+
+int main(int argc, char **argv)
+{
+    if (argc != 3) {
+        fprintf(stderr, "usage: %s partition file.img\n", argv[0]);
+        return 2;
+    }
+
+    return restore_raw_partition(argv[1], argv[2]);
+}
diff --git a/flashutils/flashutils.h b/flashutils/flashutils.h
new file mode 100644
index 0000000..f4466f0
--- /dev/null
+++ b/flashutils/flashutils.h
@@ -0,0 +1,6 @@
+int restore_raw_partition(const char *partition, const char *filename);
+int backup_raw_partition(const char *partition, const char *filename);
+int erase_raw_partition(const char *partition);
+int erase_partition(const char *partition, const char *filesystem);
+int mount_partition(const char *partition, const char *mount_point, const char *filesystem, int read_only);
+int get_partition_device(const char *partition, char *device);
\ No newline at end of file
diff --git a/install.c b/install.c
index 8e778f8..8b319a0 100644
--- a/install.c
+++ b/install.c
@@ -28,7 +28,7 @@
 #include "minui/minui.h"
 #include "minzip/SysUtil.h"
 #include "minzip/Zip.h"
-#include "mtdutils/mounts.h"
+#include "mounts.h"
 #include "mtdutils/mtdutils.h"
 #include "roots.h"
 #include "verifier.h"
@@ -182,6 +182,9 @@
     }
     close(pipefd[1]);
 
+    char* firmware_type = NULL;
+    char* firmware_filename = NULL;
+
     char buffer[1024];
     FILE* from_child = fdopen(pipefd[0], "r");
     while (fgets(buffer, sizeof(buffer), from_child) != NULL) {
@@ -201,6 +204,18 @@
             char* fraction_s = strtok(NULL, " \n");
             float fraction = strtof(fraction_s, NULL);
             ui_set_progress(fraction);
+        } else if (strcmp(command, "firmware") == 0) {
+            char* type = strtok(NULL, " \n");
+            char* filename = strtok(NULL, " \n");
+
+            if (type != NULL && filename != NULL) {
+                if (firmware_type != NULL) {
+                    LOGE("ignoring attempt to do multiple firmware updates");
+                } else {
+                    firmware_type = strdup(type);
+                    firmware_filename = strdup(filename);
+                }
+            }
         } else if (strcmp(command, "ui_print") == 0) {
             char* str = strtok(NULL, "\n");
             if (str) {
@@ -221,6 +236,11 @@
         return INSTALL_ERROR;
     }
 
+    if (firmware_type != NULL) {
+        return handle_firmware_update(firmware_type, firmware_filename, zip);
+    } else {
+        return INSTALL_SUCCESS;
+    }
     return INSTALL_SUCCESS;
 }
 
diff --git a/legacy.c b/legacy.c
index 88c620e..bb6f194 100644
--- a/legacy.c
+++ b/legacy.c
@@ -28,7 +28,6 @@
 #include "minui/minui.h"
 #include "minzip/SysUtil.h"
 #include "minzip/Zip.h"
-#include "mtdutils/mounts.h"
 #include "mtdutils/mtdutils.h"
 #include "roots.h"
 #include "verifier.h"
@@ -41,7 +40,7 @@
 #include "minui/minui.h"
 #include "minzip/SysUtil.h"
 #include "minzip/Zip.h"
-#include "mtdutils/mounts.h"
+#include "mounts.h"
 #include "mtdutils/mtdutils.h"
 #include "roots.h"
 #include "verifier.h"
diff --git a/mmcutils/mmcutils.c b/mmcutils/mmcutils.c
index f7df95d..f0cdf8c 100644
--- a/mmcutils/mmcutils.c
+++ b/mmcutils/mmcutils.c
@@ -47,6 +47,16 @@
 unsigned vfat_count = 0;
 char *vfat_partitions[] = {"modem", "NONE"};
 
+struct MmcPartition {
+    char *device_index;
+    char *filesystem;
+    char *name;
+    unsigned dstatus;
+    unsigned dtype ;
+    unsigned dfirstsec;
+    unsigned dsize;
+};
+
 typedef struct {
     MmcPartition *partitions;
     int partitions_allocd;
@@ -408,6 +418,7 @@
 }
 
 
+// TODO: refactor this to not be a giant copy paste mess
 int
 mmc_raw_dump (const MmcPartition *partition, char *out_file) {
     int ch;
@@ -459,3 +470,121 @@
 
 }
 
+
+int
+mmc_raw_read (const MmcPartition *partition, char *data, int data_size) {
+    int ch;
+    FILE *in;
+    int val = 0;
+    char buf[512];
+    unsigned sz = 0;
+    unsigned i;
+    int ret = -1;
+    char *in_file = partition->device_index;
+
+    in  = fopen ( in_file,  "r" );
+    if (in == NULL)
+        goto ERROR3;
+
+    fseek(in, 0L, SEEK_END);
+    sz = ftell(in);
+    fseek(in, 0L, SEEK_SET);
+
+    fread(data, data_size, 1, in);
+
+    ret = 0;
+ERROR1:
+ERROR2:
+    fclose ( in );
+ERROR3:
+    return ret;
+
+}
+
+int
+mmc_raw_write (const MmcPartition *partition, char *data, int data_size) {
+    int ch;
+    FILE *out;
+    int val = 0;
+    char buf[512];
+    unsigned sz = 0;
+    unsigned i;
+    int ret = -1;
+    char *out_file = partition->device_index;
+
+    out  = fopen ( out_file,  "w" );
+    if (out == NULL)
+        goto ERROR3;
+
+    fwrite(data, data_size, 1, out);
+
+    ret = 0;
+ERROR1:
+ERROR2:
+    fclose ( out );
+ERROR3:
+    return ret;
+
+}
+
+int restore_raw_partition(const char *partition, const char *filename)
+{
+    mmc_scan_partitions();
+    const MmcPartition *p;
+    p = mmc_find_partition_by_name(partition);
+    if (p == NULL)
+        return -1;
+    return mmc_raw_copy(p, filename);
+}
+
+int backup_raw_partition(const char *partition, const char *filename)
+{
+    mmc_scan_partitions();
+    const MmcPartition *p;
+    p = mmc_find_partition_by_name(partition);
+    if (p == NULL)
+        return -1;
+    return mmc_raw_dump(p, filename);
+}
+
+int erase_raw_partition(const char *partition)
+{
+    mmc_scan_partitions();
+    const MmcPartition *p;
+    p = mmc_find_partition_by_name(partition);
+    if (p == NULL)
+        return -1;
+        
+    // TODO: implement raw wipe
+    return 0;
+}
+
+int erase_partition(const char *partition, const char *filesystem)
+{
+    mmc_scan_partitions();
+    const MmcPartition *p;
+    p = mmc_find_partition_by_name(partition);
+    if (p == NULL)
+        return -1;
+    return mmc_format_ext3 (p);
+}
+
+int mount_partition(const char *partition, const char *mount_point, const char *filesystem, int read_only)
+{
+    mmc_scan_partitions();
+    const MmcPartition *p;
+    p = mmc_find_partition_by_name(partition);
+    if (p == NULL)
+        return -1;
+    return mmc_mount_partition(p, mount_point, read_only);
+}
+
+const char* get_partition_device(const char *partition)
+{
+    mmc_scan_partitions();
+    const MmcPartition *p;
+    p = mmc_find_partition_by_name(partition);
+    if (p == NULL)
+        return NULL;
+    return p->device_index;
+}
diff --git a/mmcutils/mmcutils.h b/mmcutils/mmcutils.h
index 6a3070d..64e5813 100644
--- a/mmcutils/mmcutils.h
+++ b/mmcutils/mmcutils.h
@@ -71,15 +71,7 @@
 #define MMC_BOOT_TYPE 0x48
 #define MMC_EXT3_TYPE 0x83
 #define MMC_VFAT_TYPE 0xC
-typedef struct MmcPartition {
-    char *device_index;
-    char *filesystem;
-    char *name;
-    unsigned dstatus;
-    unsigned dtype ;
-    unsigned dfirstsec;
-    unsigned dsize;
-} MmcPartition;
+typedef struct MmcPartition MmcPartition;
 
 /* Functions */
 int mmc_scan_partitions();
@@ -88,7 +80,8 @@
 int mmc_mount_partition(const MmcPartition *partition, const char *mount_point, \
                         int read_only);
 int mmc_raw_copy (const MmcPartition *partition, char *in_file);
-int mmc_raw_dump (const MmcPartition *partition, char *out_file);
+int mmc_raw_read (const MmcPartition *partition, char *data, int data_size);
+int mmc_raw_write (const MmcPartition *partition, char *data, int data_size);
 
 #endif  // MMCUTILS_H_
 
diff --git a/mtdutils/mounts.c b/mounts.c
similarity index 100%
rename from mtdutils/mounts.c
rename to mounts.c
diff --git a/mtdutils/mounts.h b/mounts.h
similarity index 100%
rename from mtdutils/mounts.h
rename to mounts.h
diff --git a/mtdutils/Android.mk b/mtdutils/Android.mk
index 6dedcfb..90e97fd 100644
--- a/mtdutils/Android.mk
+++ b/mtdutils/Android.mk
@@ -5,88 +5,12 @@
 include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := \
-	mtdutils.c \
-	mounts.c
+	mtdutils.c
 
 LOCAL_MODULE := libmtdutils
 
 include $(BUILD_STATIC_LIBRARY)
 
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := flash_image.c
-LOCAL_MODULE := flash_image
-LOCAL_MODULE_TAGS := eng
-LOCAL_STATIC_LIBRARIES := libmtdutils
-LOCAL_SHARED_LIBRARIES := libcutils libc
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := dump_image.c
-LOCAL_MODULE := dump_image
-LOCAL_MODULE_TAGS := eng
-LOCAL_STATIC_LIBRARIES := libmtdutils
-LOCAL_SHARED_LIBRARIES := libcutils libc
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := erase_image.c
-LOCAL_MODULE := erase_image
-LOCAL_MODULE_TAGS := eng
-LOCAL_STATIC_LIBRARIES := libmtdutils
-LOCAL_SHARED_LIBRARIES := libcutils libc
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := flash_image.c
-LOCAL_MODULE := libflash_image
-LOCAL_CFLAGS += -Dmain=flash_image_main
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := dump_image.c
-LOCAL_MODULE := libdump_image
-LOCAL_CFLAGS += -Dmain=dump_image_main
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := erase_image.c
-LOCAL_MODULE := liberase_image
-LOCAL_CFLAGS += -Dmain=erase_image_main
-include $(BUILD_STATIC_LIBRARY)
-
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := dump_image.c
-LOCAL_MODULE := utility_dump_image
-LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES
-LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities
-LOCAL_UNSTRIPPED_PATH := $(PRODUCT_OUT)/symbols/utilities
-LOCAL_MODULE_STEM := dump_image
-LOCAL_STATIC_LIBRARIES := libmtdutils libcutils libc
-LOCAL_FORCE_STATIC_EXECUTABLE := true
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := flash_image.c
-LOCAL_MODULE := utility_flash_image
-LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES
-LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities
-LOCAL_UNSTRIPPED_PATH := $(PRODUCT_OUT)/symbols/utilities
-LOCAL_MODULE_STEM := flash_image
-LOCAL_STATIC_LIBRARIES := libmtdutils libcutils libc
-LOCAL_FORCE_STATIC_EXECUTABLE := true
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := erase_image.c
-LOCAL_MODULE := utility_erase_image
-LOCAL_MODULE_CLASS := UTILITY_EXECUTABLES
-LOCAL_MODULE_PATH := $(PRODUCT_OUT)/utilities
-LOCAL_UNSTRIPPED_PATH := $(PRODUCT_OUT)/symbols/utilities
-LOCAL_MODULE_STEM := erase_image
-LOCAL_STATIC_LIBRARIES := libmtdutils libcutils libc
-LOCAL_FORCE_STATIC_EXECUTABLE := true
-include $(BUILD_EXECUTABLE)
 
 endif	# TARGET_ARCH == arm
 endif	# !TARGET_SIMULATOR
diff --git a/mtdutils/driver.c b/mtdutils/driver.c
deleted file mode 100644
index 351181f..0000000
--- a/mtdutils/driver.c
+++ /dev/null
@@ -1,17 +0,0 @@
-#undef main
-
-#include <stdio.h>
-#include <stdlib.h>
-
-int main(int argc, char** argv)
-{
-    if (strstr(argv[0], "flash_image") != NULL)
-        return flash_image_main(argc, argv);
-    if (strstr(argv[0], "dump_image") != NULL)
-        return dump_image_main(argc, argv);
-    if (strstr(argv[0], "mkyaffs2image") != NULL)
-        return mkyaffs2image_main(argc, argv);
-    if (strstr(argv[0], "unyaffs") != NULL)
-        return unyaffs_main(argc, argv);
-    return 0;
-}
\ No newline at end of file
diff --git a/mtdutils/dump_image.h b/mtdutils/dump_image.h
deleted file mode 100644
index 6198322..0000000
--- a/mtdutils/dump_image.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef DUMP_IMAGE_H
-#define DUMP_IMAGE_H
-
-typedef void (*dump_image_callback) (int partition_dumped, int partition_size);
-
-int dump_image(char* partition_name, char* filename, dump_image_callback callback);
-
-#endif
diff --git a/mtdutils/mtdutils.c b/mtdutils/mtdutils.c
index 8069c3f..8b71867 100644
--- a/mtdutils/mtdutils.c
+++ b/mtdutils/mtdutils.c
@@ -557,3 +557,295 @@
     }
     return pos;
 }
+
+#define BLOCK_SIZE    2048
+#define SPARE_SIZE    (BLOCK_SIZE >> 5)
+#define HEADER_SIZE 2048
+
+int restore_raw_partition(const char *partition_name, const char *filename)
+{
+    const MtdPartition *ptn;
+    MtdWriteContext *write;
+    void *data;
+    unsigned sz;
+
+    if (mtd_scan_partitions() <= 0)
+    {
+        printf("error scanning partitions");
+        return -1;
+    }
+    const MtdPartition *partition = mtd_find_partition_by_name(partition_name);
+    if (partition == NULL)
+    {
+        printf("can't find %s partition", partition_name);  
+        return -1;
+    } 
+
+    // If the first part of the file matches the partition, skip writing
+
+    int fd = open(filename, O_RDONLY);
+    if (fd < 0)
+    {
+        printf("error opening %s", filename);
+        return -1;
+    } 
+
+    char header[HEADER_SIZE];
+    int headerlen = read(fd, header, sizeof(header));
+    if (headerlen <= 0) 
+    {
+        printf("error reading %s header", filename);
+        return -1;
+    }
+
+    MtdReadContext *in = mtd_read_partition(partition);
+    if (in == NULL) {
+        printf("error opening %s: %s\n", partition, strerror(errno));
+        // just assume it needs re-writing
+    } else {
+        char check[HEADER_SIZE];
+        int checklen = mtd_read_data(in, check, sizeof(check));
+        if (checklen <= 0) {
+            printf("error reading %s: %s\n", partition_name, strerror(errno));
+            // just assume it needs re-writing
+        } else if (checklen == headerlen && !memcmp(header, check, headerlen)) {
+            printf("header is the same, not flashing %s\n", partition_name);
+            return 0;
+        }
+        mtd_read_close(in);
+    }
+
+    // Skip the header (we'll come back to it), write everything else
+    printf("flashing %s from %s\n", partition_name, filename);
+
+    MtdWriteContext *out = mtd_write_partition(partition);
+    if (out == NULL) 
+    {
+       printf("error writing %s", partition_name);
+       return -1;
+    }
+
+    char buf[HEADER_SIZE];
+    memset(buf, 0, headerlen);
+    int wrote = mtd_write_data(out, buf, headerlen);
+    if (wrote != headerlen) 
+    {
+        printf("error writing %s", partition_name);
+        return -1;
+    }
+
+    int len;
+    while ((len = read(fd, buf, sizeof(buf))) > 0) {
+        wrote = mtd_write_data(out, buf, len);
+        if (wrote != len)
+        {
+            printf("error writing %s", partition_name);
+            return -1;
+        }
+    }
+    if (len < 0) 
+    {
+       printf("error reading %s", filename);
+       return -1;
+    }
+
+    if (mtd_write_close(out)) 
+    {
+        printf("error closing %s", partition_name);
+        return -1;
+    }
+
+    // Now come back and write the header last
+
+    out = mtd_write_partition(partition);
+    if (out == NULL)
+    {
+        printf("error re-opening %s", partition_name);
+        return -1;
+    } 
+
+    wrote = mtd_write_data(out, header, headerlen);
+    if (wrote != headerlen)
+    {
+        printf("error re-writing %s", partition_name);
+        return -1;
+    } 
+
+    // Need to write a complete block, so write the rest of the first block
+    size_t block_size;
+    if (mtd_partition_info(partition, NULL, &block_size, NULL))
+    {
+        printf("error getting %s block size", partition_name);
+        return -1;
+    }
+
+    if (lseek(fd, headerlen, SEEK_SET) != headerlen)
+    {
+        printf("error rewinding %s", filename);
+        return -1;
+    }
+
+    int left = block_size - headerlen;
+    while (left < 0) left += block_size;
+    while (left > 0) {
+        len = read(fd, buf, left > (int)sizeof(buf) ? (int)sizeof(buf) : left);
+        if (len <= 0){
+            printf("error reading %s", filename);
+            return -1;
+        }
+        if (mtd_write_data(out, buf, len) != len)
+        {
+            printf("error writing %s", partition_name);
+            return -1;
+        }
+            
+        left -= len;
+    }
+
+    if (mtd_write_close(out)) 
+    {
+        printf("error closing %s", partition_name);
+        return -1;
+    }
+    return 0;
+}
+
+
+int backup_raw_partition(const char *partition_name, const char *filename)
+{
+    MtdReadContext *in;
+    const MtdPartition *partition;
+    char buf[BLOCK_SIZE + SPARE_SIZE];
+    size_t partition_size;
+    size_t read_size;
+    size_t total;
+    int fd;
+    int wrote;
+    int len;
+    
+    if (mtd_scan_partitions() <= 0)
+    {
+        printf("error scanning partitions");    
+        return -1;
+    }
+
+    partition = mtd_find_partition_by_name(partition_name);
+    if (partition == NULL)
+    {
+        printf("can't find %s partition", partition_name);
+        return -1;
+    }
+
+    if (mtd_partition_info(partition, &partition_size, NULL, NULL)) {
+        printf("can't get info of partition %s", partition_name);
+        return -1;
+    }
+
+    if (!strcmp(filename, "-")) {
+        fd = fileno(stdout);
+    } 
+    else {
+        fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0666);
+    }
+
+    if (fd < 0)
+    {
+       printf("error opening %s", filename);
+       return -1;
+    }
+
+    in = mtd_read_partition(partition);
+    if (in == NULL) {
+        close(fd);
+        unlink(filename);
+        printf("error opening %s: %s\n", partition_name, strerror(errno));
+        return -1;
+    }
+
+    total = 0;
+    while ((len = mtd_read_data(in, buf, BLOCK_SIZE)) > 0) {
+        wrote = write(fd, buf, len);
+        if (wrote != len) {
+            close(fd);
+            unlink(filename);
+            printf("error writing %s", filename);
+            return -1;
+        }
+        total += BLOCK_SIZE;
+    }
+
+    mtd_read_close(in);
+
+    if (close(fd)) {
+        unlink(filename);
+        printf("error closing %s", filename);
+        return -1;
+    }
+    return 0;
+}
+
+int erase_raw_partition(const char *partition_name)
+{
+    MtdWriteContext *out;
+    size_t erased;
+    size_t total_size;
+    size_t erase_size;
+
+    if (mtd_scan_partitions() <= 0)
+    {
+        printf("error scanning partitions");
+        return -1;
+    }
+    const MtdPartition *p = mtd_find_partition_by_name(partition_name);
+    if (p == NULL)
+    {
+        printf("can't find %s partition", partition_name);   
+        return -1;
+    }
+
+    out = mtd_write_partition(p);
+    if (out == NULL)
+    {
+        printf("could not estabilish write context for %s", partition_name);   
+        return -1;
+    }
+
+    // do the actual erase, -1 = full partition erase
+    erased = mtd_erase_blocks(out, -1);
+
+    // erased = bytes erased, if zero, something borked
+    if (!erased)
+    {
+        printf("error erasing %s", partition_name);
+        return -1;
+    }
+
+    return 0;
+}
+
+int erase_partition(const char *partition, const char *filesystem)
+{
+    return erase_raw_partition(partition);
+}
+
+
+int mount_partition(const char *partition, const char *mount_point, const char *filesystem, int read_only)
+{
+    mtd_scan_partitions();
+    const MtdPartition *p;
+    p = mtd_find_partition_by_name(partition);
+    if (p == NULL) {
+        return -1;
+    }
+    return mtd_mount_partition(p, mount_point, filesystem, read_only);
+}
+
+int get_partition_device(const char *partition, char *device)
+{
+    mtd_scan_partitions();
+    MtdPartition *p = mtd_find_partition_by_name(partition);
+    if (p == NULL)
+        return -1;
+    sprintf(device, "/dev/block/mtdblock%d", p->device_index);
+    return 0;
+}
diff --git a/nandroid.c b/nandroid.c
index dae3713..0b38294 100644
--- a/nandroid.c
+++ b/nandroid.c
@@ -33,8 +33,6 @@
 #include "commands.h"
 #include "amend/amend.h"
 
-#include "mtdutils/dump_image.h"
-#include "mmcutils/mmcutils.h"
 #include "../../external/yaffs2/yaffs2/utils/mkyaffs2image.h"
 #include "../../external/yaffs2/yaffs2/utils/unyaffs.h"
 
@@ -43,33 +41,6 @@
 #include "extendedcommands.h"
 #include "nandroid.h"
 
-#ifdef BOARD_USES_BMLUTILS
-#elif BOARD_USES_MMCUTILS
-int write_raw_image(const char* partition, const char* filename) {
-    mmc_scan_partitions();
-    const MmcPartition *p;
-    p = mmc_find_partition_by_name(partition);
-    return mmc_raw_copy (p, filename);
-}
-
-int read_raw_image(const char* partition, const char* filename) {
-    mmc_scan_partitions();
-    const MmcPartition *p;
-    p = mmc_find_partition_by_name(partition);
-    return mmc_raw_dump (p, filename);
-}
-#else
-int write_raw_image(const char* partition, const char* filename) {
-    char tmp[PATH_MAX];
-    sprintf(tmp, "flash_image boot %s", filename);
-    return __system(tmp);
-}
-
-int read_raw_image(const char* partition, const char* filename) {
-    return dump_image(partition, filename, NULL);
-}
-#endif
-
 int print_and_error(char* message) {
     ui_print(message);
     return 1;
@@ -164,13 +135,13 @@
 #ifndef BOARD_RECOVERY_IGNORE_BOOTABLES
     ui_print("Backing up boot...\n");
     sprintf(tmp, "%s/%s", backup_path, "boot.img");
-    ret = read_raw_image("boot", tmp);
+    ret = backup_raw_partition("boot", tmp);
     if (0 != ret)
         return print_and_error("Error while dumping boot image!\n");
 
     ui_print("Backing up recovery...\n");
     sprintf(tmp, "%s/%s", backup_path, "recovery.img");
-    ret = read_raw_image("recovery", tmp);
+    ret = backup_raw_partition("recovery", tmp);
     if (0 != ret)
         return print_and_error("Error while dumping recovery image!\n");
 #endif
@@ -181,7 +152,7 @@
     if (0 != (ret = nandroid_backup_partition(backup_path, "DATA:")))
         return ret;
 
-#ifdef HAS_DATADATA
+#ifdef BOARD_HAS_DATADATA
     if (0 != (ret = nandroid_backup_partition(backup_path, "DATADATA:")))
         return ret;
 #endif
@@ -200,7 +171,7 @@
     if (0 != (ret = nandroid_backup_partition_extended(backup_path, "CACHE:", 0)))
         return ret;
 
-    if (0 != stat(SDEXT_DEVICE, &st))
+    if (0 != stat(BOARD_SDEXT_DEVICE, &st))
     {
         ui_print("No sd-ext found. Skipping backup of sd-ext.\n");
     }
@@ -313,7 +284,7 @@
             return print_and_error("Error while formatting BOOT:!\n");
         sprintf(tmp, "%s/boot.img", backup_path);
         ui_print("Restoring boot image...\n");
-        if (0 != (ret = write_raw_image("boot", tmp))) {
+        if (0 != (ret = restore_raw_partition("boot", tmp))) {
             ui_print("Error while flashing boot image!");
             return ret;
         }
@@ -326,7 +297,7 @@
     if (restore_data && 0 != (ret = nandroid_restore_partition(backup_path, "DATA:")))
         return ret;
         
-#ifdef HAS_DATADATA
+#ifdef BOARD_HAS_DATADATA
     if (restore_data && 0 != (ret = nandroid_restore_partition(backup_path, "DATADATA:")))
         return ret;
 #endif
diff --git a/recovery.c b/recovery.c
index 53241ac..bda808c 100644
--- a/recovery.c
+++ b/recovery.c
@@ -444,7 +444,7 @@
     ui_print("\n-- Wiping data...\n");
     device_wipe_data();
     erase_root("DATA:");
-#ifdef HAS_DATADATA
+#ifdef BOARD_HAS_DATADATA
     erase_root("DATADATA:");
 #endif
     erase_root("CACHE:");
diff --git a/roots.c b/roots.c
index 92b89a4..39179e9 100644
--- a/roots.c
+++ b/roots.c
@@ -24,37 +24,35 @@
 
 #include <limits.h>
 
-#include "mtdutils/mtdutils.h"
-#include "mtdutils/mounts.h"
-#include "mmcutils/mmcutils.h"
+#include "flashutils/flashutils.h"
 #include "minzip/Zip.h"
 #include "roots.h"
 #include "common.h"
 
+#include "mounts.h"
 #include "extendedcommands.h"
 
 /* Canonical pointers.
 xxx may just want to use enums
  */
-static const char g_mtd_device[] = "@\0g_mtd_device";
-static const char g_mmc_device[] = "@\0g_mmc_device";
+static const char g_default_device[] = "@\0g_default_device";
 static const char g_raw[] = "@\0g_raw";
 static const char g_package_file[] = "@\0g_package_file";
 
 static RootInfo g_roots[] = {
-    { "BOOT:", DEFAULT_DEVICE, NULL, "boot", NULL, g_raw, NULL },
-    { "CACHE:", CACHE_DEVICE, NULL, "cache", "/cache", CACHE_FILESYSTEM, CACHE_FILESYSTEM_OPTIONS },
-    { "DATA:", DATA_DEVICE, NULL, "userdata", "/data", DATA_FILESYSTEM, DATA_FILESYSTEM_OPTIONS },
-#ifdef HAS_DATADATA
-    { "DATADATA:", DATADATA_DEVICE, NULL, "datadata", "/datadata", DATADATA_FILESYSTEM, DATADATA_FILESYSTEM_OPTIONS },
+    { "BOOT:", g_default_device, NULL, "boot", NULL, g_raw, NULL },
+    { "CACHE:", BOARD_CACHE_DEVICE, NULL, "cache", "/cache", BOARD_CACHE_FILESYSTEM, BOARD_CACHE_FILESYSTEM_OPTIONS },
+    { "DATA:", BOARD_DATA_DEVICE, NULL, "userdata", "/data", BOARD_DATA_FILESYSTEM, BOARD_DATA_FILESYSTEM_OPTIONS },
+#ifdef BOARD_HAS_DATADATA
+    { "DATADATA:", BOARD_DATADATA_DEVICE, NULL, "datadata", "/datadata", BOARD_DATADATA_FILESYSTEM, BOARD_DATADATA_FILESYSTEM_OPTIONS },
 #endif
-    { "MISC:", DEFAULT_DEVICE, NULL, "misc", NULL, g_raw, NULL },
+    { "MISC:", g_default_device, NULL, "misc", NULL, g_raw, NULL },
     { "PACKAGE:", NULL, NULL, NULL, NULL, g_package_file, NULL },
-    { "RECOVERY:", DEFAULT_DEVICE, NULL, "recovery", "/", g_raw, NULL },
-    { "SDCARD:", SDCARD_DEVICE_PRIMARY, SDCARD_DEVICE_SECONDARY, NULL, "/sdcard", "vfat", NULL },
-    { "SDEXT:", SDEXT_DEVICE, NULL, NULL, "/sd-ext", SDEXT_FILESYSTEM, NULL },
-    { "SYSTEM:", SYSTEM_DEVICE, NULL, "system", "/system", SYSTEM_FILESYSTEM, SYSTEM_FILESYSTEM_OPTIONS },
-    { "MBM:", DEFAULT_DEVICE, NULL, "mbm", NULL, g_raw, NULL },
+    { "RECOVERY:", g_default_device, NULL, "recovery", "/", g_raw, NULL },
+    { "SDCARD:", BOARD_SDCARD_DEVICE_PRIMARY, BOARD_SDCARD_DEVICE_SECONDARY, NULL, "/sdcard", "vfat", NULL },
+    { "SDEXT:", BOARD_SDEXT_DEVICE, NULL, NULL, "/sd-ext", BOARD_SDEXT_FILESYSTEM, NULL },
+    { "SYSTEM:", BOARD_SYSTEM_DEVICE, NULL, "system", "/system", BOARD_SYSTEM_FILESYSTEM, BOARD_SYSTEM_FILESYSTEM_OPTIONS },
+    { "MBM:", g_default_device, NULL, "mbm", NULL, g_raw, NULL },
     { "TMP:", NULL, NULL, NULL, "/tmp", NULL, NULL },
 };
 #define NUM_ROOTS (sizeof(g_roots) / sizeof(g_roots[0]))
@@ -240,35 +238,6 @@
 
     /* It's not mounted.
      */
-    if (info->device == g_mtd_device) {
-        if (info->partition_name == NULL) {
-            return -1;
-        }
-//TODO: make the mtd stuff scan once when it needs to
-        mtd_scan_partitions();
-        const MtdPartition *partition;
-        partition = mtd_find_partition_by_name(info->partition_name);
-        if (partition == NULL) {
-            return -1;
-        }
-        return mtd_mount_partition(partition, info->mount_point,
-                info->filesystem, 0);
-    }
-
-    if (info->device == g_mmc_device) {
-        if (info->partition_name == NULL) {
-            return -1;
-        }
-//TODO: make the mtd stuff scan once when it needs to
-        mmc_scan_partitions();
-        const MmcPartition *partition;
-        partition = mmc_find_partition_by_name(info->partition_name);
-        if (partition == NULL) {
-            return -1;
-        }
-        return mmc_mount_partition(partition, info->mount_point, 0);
-    }
-
     if (info->device == NULL || info->mount_point == NULL ||
         info->filesystem == NULL ||
         info->filesystem == g_raw ||
@@ -276,6 +245,13 @@
         return -1;
     }
 
+    if (info->device == g_default_device) {
+        if (info->partition_name == NULL) {
+            return -1;
+        }
+        return mount_partition(info->partition_name, info->mount_point, info->filesystem, 0);
+    }
+
     mkdir(info->mount_point, 0755);  // in case it doesn't already exist
     if (mount_internal(info->device, info->mount_point, info->filesystem, info->filesystem_options)) {
         if (info->device2 == NULL) {
@@ -322,11 +298,24 @@
     return unmount_mounted_volume(volume);
 }
 
+int
+get_root_partition_device(const char *root_path, char *device)
+{
+    const RootInfo *info = get_root_info_for_path(root_path);
+    if (info == NULL || info->device != g_default_device ||
+            info->partition_name == NULL)
+    {
+        return NULL;
+    }
+    return get_partition_device(info->partition_name, device);
+}
+
+#ifndef BOARD_HAS_NO_MISC_PARTITION
 const MtdPartition *
 get_root_mtd_partition(const char *root_path)
 {
     const RootInfo *info = get_root_info_for_path(root_path);
-    if (info == NULL || info->device != g_mtd_device ||
+    if (info == NULL || info->device != g_default_device ||
             info->partition_name == NULL)
     {
 #ifdef BOARD_HAS_MTD_CACHE
@@ -339,19 +328,7 @@
     mtd_scan_partitions();
     return mtd_find_partition_by_name(info->partition_name);
 }
-
-const MmcPartition *
-get_root_mmc_partition(const char *root_path)
-{
-    const RootInfo *info = get_root_info_for_path(root_path);
-    if (info == NULL || info->device != g_mmc_device ||
-            info->partition_name == NULL)
-    {
-        return NULL;
-    }
-    mmc_scan_partitions();
-    return mmc_find_partition_by_name(info->partition_name);
-}
+#endif
 
 int
 format_root_device(const char *root)
@@ -375,7 +352,8 @@
         LOGW("format_root_device: can't resolve \"%s\"\n", root);
         return -1;
     }
-    if (info->mount_point != NULL && (info->device == g_mtd_device || info->device == g_mmc_device)) {
+
+    if (info->mount_point != NULL && info->device == g_default_device) {
         /* Don't try to format a mounted device.
          */
         int ret = ensure_root_path_unmounted(root);
@@ -387,52 +365,17 @@
 
     /* Format the device.
      */
-    if (info->device == g_mtd_device) {
-        mtd_scan_partitions();
-        const MtdPartition *partition;
-        partition = mtd_find_partition_by_name(info->partition_name);
-        if (partition == NULL) {
-            LOGW("format_root_device: can't find mtd partition \"%s\"\n",
-                    info->partition_name);
-            return -1;
-        }
-        if (info->filesystem == g_raw || !strcmp(info->filesystem, "yaffs2")) {
-            MtdWriteContext *write = mtd_write_partition(partition);
-            if (write == NULL) {
-                LOGW("format_root_device: can't open \"%s\"\n", root);
-                return -1;
-            } else if (mtd_erase_blocks(write, -1) == (off_t) -1) {
-                LOGW("format_root_device: can't erase \"%s\"\n", root);
-                mtd_write_close(write);
-                return -1;
-            } else if (mtd_write_close(write)) {
-                LOGW("format_root_device: can't close \"%s\"\n", root);
-                return -1;
-            } else {
-                return 0;
-            }
-        }
+    if (info->device == g_default_device) {
+        int ret = 0;
+        if (info->filesystem == g_raw)
+            ret = erase_raw_partition(info->partition_name);
+        else
+            ret = erase_partition(info->partition_name, info->filesystem);
+        
+        if (ret != 0)
+            LOGE("Error erasing device %s\n", info->device);
+        return ret;
     }
 
-    //Handle MMC device types
-    if(info->device == g_mmc_device) {
-        mmc_scan_partitions();
-        const MmcPartition *partition;
-        partition = mmc_find_partition_by_name(info->partition_name);
-        if (partition == NULL) {
-            LOGE("format_root_device: can't find mmc partition \"%s\"\n",
-                    info->partition_name);
-            return -1;
-        }
-        if (!strcmp(info->filesystem, "ext3")) {
-            if(0 == mmc_format_ext3(partition))
-                return 0;
-            LOGE("\n\"%s\" wipe failed!\n", info->partition_name);
-            return -1;
-        }
-        LOGW("\n\"%s\" wipe skipped!\n", info->partition_name);
-        return 0;
-    }
-
-    return format_non_mtd_device(root);
+    return format_unknown_device(root);
 }
diff --git a/roots.h b/roots.h
index ee78363..e10663d 100644
--- a/roots.h
+++ b/roots.h
@@ -23,75 +23,73 @@
 #include "mmcutils/mmcutils.h"
 
 #ifndef BOARD_USES_MMCUTILS
-#define DEFAULT_DEVICE g_mtd_device
 #define DEFAULT_FILESYSTEM "yaffs2"
 #else
-#define DEFAULT_DEVICE g_mmc_device
 #define DEFAULT_FILESYSTEM "ext3"
 #endif
 
-#ifndef SDCARD_DEVICE_PRIMARY
-#define SDCARD_DEVICE_PRIMARY "/dev/block/mmcblk0p1"
+#ifndef BOARD_SDCARD_DEVICE_PRIMARY
+#define BOARD_SDCARD_DEVICE_PRIMARY "/dev/block/mmcblk0p1"
 #endif
 
-#ifndef SDCARD_DEVICE_SECONDARY
-#define SDCARD_DEVICE_SECONDARY "/dev/block/mmcblk0"
+#ifndef BOARD_SDCARD_DEVICE_SECONDARY
+#define BOARD_SDCARD_DEVICE_SECONDARY "/dev/block/mmcblk0"
 #endif
 
-#ifndef SDEXT_DEVICE
-#define SDEXT_DEVICE "/dev/block/mmcblk0p2"
+#ifndef BOARD_SDEXT_DEVICE
+#define BOARD_SDEXT_DEVICE "/dev/block/mmcblk0p2"
 #endif
 
-#ifndef SDEXT_FILESYSTEM
-#define SDEXT_FILESYSTEM "auto"
+#ifndef BOARD_SDEXT_FILESYSTEM
+#define BOARD_SDEXT_FILESYSTEM "auto"
 #endif
 
-#ifndef DATA_DEVICE
-#define DATA_DEVICE DEFAULT_DEVICE
+#ifndef BOARD_DATA_DEVICE
+#define BOARD_DATA_DEVICE g_default_device
 #endif
 
-#ifndef DATA_FILESYSTEM
-#define DATA_FILESYSTEM DEFAULT_FILESYSTEM
+#ifndef BOARD_DATA_FILESYSTEM
+#define BOARD_DATA_FILESYSTEM DEFAULT_FILESYSTEM
 #endif
 
-#ifndef DATADATA_DEVICE
-#define DATADATA_DEVICE DEFAULT_DEVICE
+#ifndef BOARD_DATADATA_DEVICE
+#define BOARD_DATADATA_DEVICE g_default_device
 #endif
 
-#ifndef DATADATA_FILESYSTEM
-#define DATADATA_FILESYSTEM DEFAULT_FILESYSTEM
+#ifndef BOARD_DATADATA_FILESYSTEM
+#define BOARD_DATADATA_FILESYSTEM DEFAULT_FILESYSTEM
 #endif
 
-#ifndef CACHE_DEVICE
-#define CACHE_DEVICE DEFAULT_DEVICE
+#ifndef BOARD_CACHE_DEVICE
+#define BOARD_CACHE_DEVICE g_default_device
 #endif
 
-#ifndef CACHE_FILESYSTEM
-#define CACHE_FILESYSTEM DEFAULT_FILESYSTEM
+#ifndef BOARD_CACHE_FILESYSTEM
+#define BOARD_CACHE_FILESYSTEM DEFAULT_FILESYSTEM
 #endif
 
-#ifndef SYSTEM_DEVICE
-#define SYSTEM_DEVICE DEFAULT_DEVICE
+#ifndef BOARD_SYSTEM_DEVICE
+#define BOARD_SYSTEM_DEVICE g_default_device
 #endif
 
-#ifndef SYSTEM_FILESYSTEM
-#define SYSTEM_FILESYSTEM DEFAULT_FILESYSTEM
+#ifndef BOARD_SYSTEM_FILESYSTEM
+#define BOARD_SYSTEM_FILESYSTEM DEFAULT_FILESYSTEM
 #endif
 
-#ifndef DATA_FILESYSTEM_OPTIONS
-#define DATA_FILESYSTEM_OPTIONS NULL
+#ifndef BOARD_DATA_FILESYSTEM_OPTIONS
+#define BOARD_DATA_FILESYSTEM_OPTIONS NULL
 #endif
 
-#ifndef CACHE_FILESYSTEM_OPTIONS
-#define CACHE_FILESYSTEM_OPTIONS NULL
+#ifndef BOARD_CACHE_FILESYSTEM_OPTIONS
+#define BOARD_CACHE_FILESYSTEM_OPTIONS NULL
 #endif
 
-#ifndef DATADATA_FILESYSTEM_OPTIONS
-#define DATADATA_FILESYSTEM_OPTIONS NULL
+#ifndef BOARD_DATADATA_FILESYSTEM_OPTIONS
+#define BOARD_DATADATA_FILESYSTEM_OPTIONS NULL
 #endif
 
-#ifndef SYSTEM_FILESYSTEM_OPTIONS
-#define SYSTEM_FILESYSTEM_OPTIONS NULL
+#ifndef BOARD_SYSTEM_FILESYSTEM_OPTIONS
+#define BOARD_SYSTEM_FILESYSTEM_OPTIONS NULL
 #endif
 
 
@@ -129,7 +127,7 @@
 int ensure_root_path_unmounted(const char *root_path);
 
 const MtdPartition *get_root_mtd_partition(const char *root_path);
-const MmcPartition *get_root_mmc_partition(const char *root_path);
+int get_root_partition_device(const char *root_path, char *device);
 
 /* "root" must be the exact name of the root; no relative path is permitted.
  * If the named root is mounted, this will attempt to unmount it first.
diff --git a/updater/install.c b/updater/install.c
index 000b525..82cddb1 100644
--- a/updater/install.c
+++ b/updater/install.c
@@ -660,8 +660,6 @@
     return false;
 }
 
-int write_raw_image(const char* partition, const char* filename);
-
 // write_raw_image(file, partition)
 Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) {
     char* result = NULL;