int format_root_device(const char *root)
{
    /* Don't try to format a mounted device. */
    int ret = ensure_root_path_unmounted(root);  
    if (ret < 0) {
        LOGD(LOG_TAG "format_root_device: can't unmount \"%s\"\n", root);
        return -1;
    }

    if (!strcmp(root, "/data")) {
	  int result = make_ext4fs("/emmc@usrdata", 0);
	  if (result != 0) {	
		LOGE("format_volume: make_extf4fs failed on /emmc@usrdata\n");
	    	return -1;
    	  }
    }	else if (!strcmp(root, "/cache")) {
    	
	   int  result = make_ext4fs("/emmc@cache", 0);
	   if (result != 0) {	
			LOGE("format_volume: make_extf4fs failed on /emmc@cache\n");
	    		return -1;
    	   }

    }

    return 0;
}
Esempio n. 2
0
void root_menu(int confirm) {
    if (confirm) {
        static char** title_headers = NULL;

        if (title_headers == NULL) {
            char* headers[] = { "ROOT installed ROM?",
								" ",
                                "Rooting without the superuser app installed",
                                "does nothing. Please install the superuser app",
								"from the market! (by ChainsDD)",
								" ",
                                NULL };
            title_headers = prepend_title(headers);
        }

        char* items[] = { " No",
                          " OK, give me root!",
                          NULL };

        int chosen_item = get_menu_selection(title_headers, items, 1, 0);
        if (chosen_item != 1) {
            return;
        }
    }
	char* argv[] = { "/sbin/actroot",
	NULL };

    char* envp[] = { NULL };
	
	ensure_root_path_mounted("SYSTEM:");
	remove("/system/recovery-from-boot.p");
    int status = runve("/sbin/actroot",argv,envp,1);
	ensure_root_path_unmounted("SYSTEM:");
	return;
}
int format_non_mtd_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))
        {
            ui_print("No app2sd partition found. Skipping format of /sd-ext.\n");
            return 0;
        }
    }

    char path[PATH_MAX];
    translate_root_path(root, path, PATH_MAX);
    if (0 != ensure_root_path_mounted(root))
    {
        ui_print("Error mounting %s!\n", path);
        ui_print("Skipping format...\n");
        return 0;
    }

    static char tmp[PATH_MAX];
    sprintf(tmp, "rm -rf %s/*", path);
    __system(tmp);
    sprintf(tmp, "rm -rf %s/.*", path);
    __system(tmp);
    
    ensure_root_path_unmounted(root);
    return 0;
}
Esempio n. 4
0
/* Image backup functions
 */
int nandroid_backup_partition_extended(const char* backup_path, char* root, int umount_when_finished) {
    int ret = 0;
    char mount_point[PATH_MAX];
    translate_root_path(root, mount_point, PATH_MAX);
    char* name = basename(mount_point);

    struct stat file_info;
    mkyaffs2image_callback callback = NULL;
    if (0 != stat("/sdcard/ebrecovery/.hidenandroidprogress", &file_info)) {
        callback = yaffs_callback;
    }
    
    ui_print("Backing up %s...\n", name);
    if (0 != (ret = ensure_root_path_mounted(root) != 0)) {
        ui_print("Can't mount %s!\n", mount_point);
        return ret;
    }
    compute_directory_stats(mount_point);
    char tmp[PATH_MAX];
    sprintf(tmp, "%s/%s.img", backup_path, name);
    ret = mkyaffs2image(mount_point, tmp, 0, callback);
    if (umount_when_finished) {
        ensure_root_path_unmounted(root);
    }
    if (0 != ret) {
        ui_print("Error while making a yaffs2 image of %s!\n", mount_point);
        return ret;
    }
    return 0;
}
void wipe_battery_stats()
{
    ui_print("Wiping battery stats...\n");
    ensure_root_path_mounted("DATA:");
    remove("/data/system/batterystats.bin");
    ensure_root_path_unmounted("DATA:");
    ui_print("Done.\n");
}
Esempio n. 6
0
void disable_OTA() {
	ui_print("\nDisabling OTA updates in ROM...");
	ensure_root_path_mounted("SYSTEM:");
	remove("/system/etc/security/otacerts.zip");
	remove("/cache/signed-*.*");
	ui_print("\nOTA-updates disabled.\n");
	ensure_root_path_unmounted("SYSTEM:");
	return;
}	
Esempio n. 7
0
int tarbackup_restore_partition_extended(const char* backup_path, const char* root, int umount_when_finished) {
    int ret;
    char mount_point[PATH_MAX];
    translate_root_path(root, mount_point, PATH_MAX);
    char* name = basename(mount_point);

    char tmp[PATH_MAX];
    sprintf(tmp, "%s/%s.tar", backup_path, name);
    struct stat file_info;
    if (0 != (ret = statfs(tmp, &file_info))) {
        ui_print("%s.tar not found. Skipping restore of %s.\n", name, mount_point);
        return 0;
    }

    ensure_directory(mount_point);

    ui_print("Restoring %s...\n", name);
    if (0 != (ret = ensure_root_path_unmounted(root))) {
        ui_print("Can't unmount %s!\n", mount_point);
        return ret;
    }

    if (0 != (ret = format_root_device(root))) {
        ui_print("Error while formatting %s!\n", root);
        return ret;
    }

    if (0 != (ret = ensure_root_path_mounted(root))) {
        ui_print("Can't mount %s!\n", mount_point);
        return ret;
    }

    sprintf(tmp, "tar -x -f %s/%s.tar", backup_path, name);
    if (0 != __system(tmp)) {
        ui_print("Error while restoring %s!\n", mount_point);
        return ret;
    }

    if (umount_when_finished) {
        ensure_root_path_unmounted(root);
    }

    return 0;
}
Esempio n. 8
0
int detect_internal_fs(const char *root_path)
{
    RootInfo *info = get_root_info_for_path(root_path);
    if (info == NULL || info->device == NULL) {
        LOGW("detect_internal_fs: can't resolve \"%s\"\n", root_path);
        return -1;
    }

    /* Don't try to unmount a mounted device.
     */
    int ret = ensure_root_path_unmounted(root_path);
    if (ret < 0) {
    	LOGW("detect_internal_fs: can't unmount \"%s\"\n", root_path);
    	return ret;
    }

    /* Consistently try to mount for different types of file systems.
     */
    int i;
    for (i=0; i<NUM_FSYSTEMS; i++) {
    	LOGW("detect_internal_fs: Try to mount: %s as %s (%s) - ", root_path, g_fs_options[i].filesystem, g_fs_options[i].filesystem_options);
    	if (mount_internal(info->device, info->mount_point, g_fs_options[i].filesystem, g_fs_options[i].filesystem_options) == 0) {
    		LOGW("success\n");
    		/* success
    		 * set type of fs & options for root_path
    		 */
    		info->filesystem = g_fs_options[i].filesystem;
    		info->filesystem_options = g_fs_options[i].filesystem_options;

    		// unmount partition
    		ensure_root_path_unmounted(root_path);
    		return 0;
    	}
    }
    // can't determine
    return -1;
}
Esempio n. 9
0
int nandroid_restore_partition_extended(const char* backup_path, const char* root, int umount_when_finished) {
    int ret;
    char mount_point[PATH_MAX];
    translate_root_path(root, mount_point, PATH_MAX);
    char* name = basename(mount_point);
    
    char tmp[PATH_MAX];
    sprintf(tmp, "%s/%s.img", backup_path, name);
    struct stat file_info;
    if (0 != (ret = statfs(tmp, &file_info))) {
        ui_print("%s.img not found. Skipping restore of %s.\n", name, mount_point);
        return 0;
    }

    ensure_directory(mount_point);

    unyaffs_callback callback = NULL;
    if (0 != stat("/sdcard/ebrecovery/.hidenandroidprogress", &file_info)) {
        callback = yaffs_callback;
    }

    ui_print("Restoring %s...\n", name);
    /*
    if (0 != (ret = ensure_root_path_unmounted(root))) {
        ui_print("Can't unmount %s!\n", mount_point);
        return ret;
    }
    */
    if (0 != (ret = format_root_device(root))) {
        ui_print("Error while formatting %s!\n", root);
        return ret;
    }
    
    if (0 != (ret = ensure_root_path_mounted(root))) {
        ui_print("Can't mount %s!\n", mount_point);
        return ret;
    }
    
    if (0 != (ret = unyaffs(tmp, mount_point, callback))) {
        ui_print("Error while restoring %s!\n", mount_point);
        return ret;
    }

    if (umount_when_finished) {
        ensure_root_path_unmounted(root);
    }
    
    return 0;
}
Esempio n. 10
0
int format_root_device(const char *root)
{
    /* Don't try to format a mounted device. */
    int ret = ensure_root_path_unmounted(root);  
    if (ret < 0) 
    {
        LOGD(TAG "format_root_device: can't unmount \"%s\"\n", root);
        return false;
    }
#if 1
        int fd;
        struct msdc_ioctl msdc_io;

        fd = open("/dev/misc-sd", O_RDONLY);
        if (fd < 0) {
            LOGE("open: /dev/misc-sd failed\n");
            return -1;
        }
        
        msdc_io.opcode = MSDC_ERASE_PARTITION;
        if (!strcmp(root, "/cache")) {
            msdc_io.buffer = (unsigned int*) "cache";
            msdc_io.total_size = 6;
        } else if (!strcmp(root, "/data")) {
            msdc_io.buffer = (unsigned int*) "usrdata";
            msdc_io.total_size = 8;
        }

        ioctl(fd, 0, &msdc_io);
        close(fd);
#endif
    if (!strcmp(root, "/data")) {
	    int result = make_ext4fs("/emmc@usrdata", 0, 0, 0);
	    if (result != 0) {	
		LOGE("format_volume: make_extf4fs failed on /emmc@usrdata\n");
	    	return -1;
    	    }
    }	

    return 0;
}
Esempio n. 11
0
/* TAR backup functions
 */
int tarbackup_backup_partition_extended(const char* backup_path, char* root, int umount_when_finished) {
	char mount_point[PATH_MAX];
	translate_root_path(root, mount_point, PATH_MAX);
	char* name = basename(mount_point);
    ui_print("Backing up %s...\n", name);

    if (0 != ensure_root_path_mounted(root)) {
    	ui_print("Can't mount partition for backup!\n");
    	return -1;
    }

    char tmp[PATH_MAX];
    sprintf(tmp, "tar -c --exclude=*RFS_LOG.LO* -f %s/%s.tar %s", backup_path, name, get_mount_point_for_root(root)+1);
    int ret = __system(tmp);

    if (umount_when_finished) {
        ensure_root_path_unmounted(root);
    }
    if (0 != ret) {
        ui_print("Error while making image of %s!\n", mount_point);
        return ret;
    }
    return 0;
}
void show_partition_menu()
{
    static char* headers[] = {  "Mounts and Storage Menu",
                                "",
                                NULL 
    };

    typedef char* string;
    string mounts[MOUNTABLE_COUNT][3] = { 
        { "mount /system", "unmount /system", "SYSTEM:" },
        { "mount /data", "unmount /data", "DATA:" },
        { "mount /dbdata", "unmount /dbdata", "DATADATA:" },
        { "mount /cache", "unmount /cache", "CACHE:" },
        { "mount /sdcard", "unmount /sdcard", "SDCARD:" },
        { "mount /sd-ext", "unmount /sd-ext", "SDEXT:" },
        { "", "", "" },
        };
        
    string mtds[MTD_COUNT][2] = {
        { "format system", "SYSTEM:" },
        { "format data", "DATA:" },
        { "format dbdata", "DATADATA:" },
        { "format cache", "CACHE:" },
        { "", "" },
    };
    
    string conv_mtds[MTD_COUNT][3] = {
    	{ "convert system", "SYSTEM:", "**" },
    	{ "convert data", "DATA:", "**" },
    	{ "convert dbdata", "DATADATA:", "**" },
    	{ "convert cache", "CACHE:", "**" },
    	{ "", "", "" },
    };

    string mmcs[MMC_COUNT][3] = {
      { "format sdcard", "SDCARD:" },
      { "format sd-ext", "SDEXT:" },
      { "", "" },
    };
    
    static char* confirm_format  = "Confirm format?";
    static char* confirm = "Yes - Format";
        
    for (;;)
    {
        int ismounted[MOUNTABLE_COUNT];
        int i;
        static string options[MOUNTABLE_COUNT + MTD_COUNT + MTD_COUNT + MMC_COUNT + 1 + 1]; // mountables, format mtds, convet mtds, format mmcs, usb storage, null
        for (i = 0; i < MOUNTABLE_COUNT; i++)
        {
            ismounted[i] = is_root_path_mounted(mounts[i][2]);
            options[i] = ismounted[i] ? mounts[i][1] : mounts[i][0];
        }
        
        for (i = 0; i < MTD_COUNT; i++)
        {
            options[MOUNTABLE_COUNT + i] = mtds[i][0];
        }

        for (i = 0; i < MTD_COUNT; i++)
        {
            options[MOUNTABLE_COUNT + MTD_COUNT + i] = conv_mtds[i][0];
        }

        for (i = 0; i < MMC_COUNT; i++)
        {
            options[MOUNTABLE_COUNT + MTD_COUNT*2 + i] = mmcs[i][0];
        }
    
        options[MOUNTABLE_COUNT + MTD_COUNT*2 + MMC_COUNT] = "mount USB storage";
        options[MOUNTABLE_COUNT + MTD_COUNT*2 + MMC_COUNT + 1] = NULL;
        
        int chosen_item = get_menu_selection(headers, options, 0);
        if (chosen_item == GO_BACK)
            break;
        if (chosen_item == MOUNTABLE_COUNT + MTD_COUNT*2 + MMC_COUNT)
        {
            show_mount_usb_storage_menu();
        }
        else if (chosen_item < MOUNTABLE_COUNT)
        {
            if (ismounted[chosen_item])
            {
                if (0 != ensure_root_path_unmounted(mounts[chosen_item][2]))
                    ui_print("Error unmounting %s!\n", mounts[chosen_item][2]);
            }
            else
            {
                if (0 != ensure_root_path_mounted(mounts[chosen_item][2]))
                    ui_print("Error mounting %s!\n", mounts[chosen_item][2]);
            }
        }
        else if (chosen_item < MOUNTABLE_COUNT + MTD_COUNT)
        {
            chosen_item = chosen_item - MOUNTABLE_COUNT;
            if (!confirm_selection(confirm_format, confirm))
                continue;
            ui_print("Formatting %s...\n", mtds[chosen_item][1]);
            if (0 != format_root_device(mtds[chosen_item][1]))
                ui_print("Error formatting %s!\n", mtds[chosen_item][1]);
            else
                ui_print("Done.\n");
        }
        else if (chosen_item < MOUNTABLE_COUNT + MTD_COUNT*2)
        {
            chosen_item = chosen_item - MOUNTABLE_COUNT - MTD_COUNT;
            if (0 == convert_mtd_device(conv_mtds[chosen_item][1], conv_mtds[chosen_item][2])) {
            	ui_print("Done.\n");
            	detect_root_fs();
            }
            ui_clear_backgroud();
            ui_reset_progress();
        }
        else if (chosen_item < MOUNTABLE_COUNT + MTD_COUNT*2 + MMC_COUNT)
        {
            chosen_item = chosen_item - MOUNTABLE_COUNT - MTD_COUNT*2;
            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]))
                ui_print("Error formatting %s!\n", mmcs[chosen_item][1]);
            else
                ui_print("Done.\n");
        }
    }
}
Esempio n. 13
0
/* write_raw_image <src-image> <dest-root>
 */
static int
cmd_write_raw_image(const char *name, void *cookie,
        int argc, const char *argv[])
{
    UNUSED(cookie);
    CHECK_WORDS();

    if (argc != 2) {
        LOGE("Command %s requires exactly two arguments\n", name);
        return 1;
    }

    // Use 10% of the progress bar (20% post-verification) by default
    const char *src_root_path = argv[0];
    const char *dst_root_path = argv[1];
    ui_print("Writing %s...\n", dst_root_path);
    if (!gDidShowProgress) ui_show_progress(DEFAULT_IMAGE_PROGRESS_FRACTION, 0);

    /* Find the source image, which is probably in a package.
     */
    if (!is_package_root_path(src_root_path)) {
        LOGE("Command %s: non-package source path \"%s\" not yet supported\n",
                name, src_root_path);
        return 255;
    }

    /* Get the package.
     */
    char srcpathbuf[PATH_MAX];
    const char *src_path;
    const ZipArchive *package;
    src_path = translate_package_root_path(src_root_path,
            srcpathbuf, sizeof(srcpathbuf), &package);
    if (src_path == NULL) {
        LOGE("Command %s: bad source path \"%s\"\n", name, src_root_path);
        return 1;
    }

    /* Get the entry.
     */
    const ZipEntry *entry = mzFindZipEntry(package, src_path);
    if (entry == NULL) {
        LOGE("Missing file %s\n", src_path);
        return 1;
    }

    /* Unmount the destination root if it isn't already.
     */
    int ret = ensure_root_path_unmounted(dst_root_path);
    if (ret < 0) {
        LOGE("Can't unmount %s\n", dst_root_path);
        return 1;
    }

    /* Open the partition for writing.
     */
    const MtdPartition *partition = get_root_mtd_partition(dst_root_path);
    if (partition == NULL) {
        LOGE("Can't find %s\n", dst_root_path);
        return 1;
    }
    MtdWriteContext *context = mtd_write_partition(partition);
    if (context == NULL) {
        LOGE("Can't open %s\n", dst_root_path);
        return 1;
    }

    /* Extract and write the image.
     */
    bool ok = mzProcessZipEntryContents(package, entry,
            write_raw_image_process_fn, context);
    if (!ok) {
        LOGE("Error writing %s\n", dst_root_path);
        mtd_write_close(context);
        return 1;
    }

    if (mtd_erase_blocks(context, -1) == (off_t) -1) {
        LOGE("Error finishing %s\n", dst_root_path);
        mtd_write_close(context);
        return -1;
    }

    if (mtd_write_close(context)) {
        LOGE("Error closing %s\n", dst_root_path);
        return -1;
    }
    return 0;
}
void show_advanced_menu()
{
    static char* headers[] = {  "Advanced and Debugging Menu",
                                "",
                                NULL
    };

    static char* list[] = { "Reboot Recovery",
                            "Wipe Dalvik Cache",
                            "Wipe Battery Stats",
                            "Wipe /data/userinit script",
                            "Report Error",
                            "Key Test",
#ifndef BOARD_HAS_SMALL_RECOVERY
                            "Partition SD Card",
                            "Fix Permissions",
#endif
                            "Create image for Odin",
                            "---Flash Kernel------",
                            "---Flash Recovery----",
                            "Unlock Kernel 4 Flash",
                            "Unlock Recovery 4 Flash",
                            NULL
    };

    for (;;)
    {
        int chosen_item = get_menu_selection(headers, list, 0);
        if (chosen_item == GO_BACK)
            break;
        switch (chosen_item)
        {
            case 0:
                __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, "recovery");
                break;
            case 1:
            {
                if (0 != ensure_root_path_mounted("DATA:"))
                    break;
                ensure_root_path_mounted("SDEXT:");
                ensure_root_path_mounted("CACHE:");
                if (confirm_selection( "Confirm wipe?", "Yes - Wipe Dalvik Cache")) {
                    __system("rm -r /data/dalvik-cache");
                    __system("rm -r /cache/dalvik-cache");
                    __system("rm -r /sd-ext/dalvik-cache");
                }
                ensure_root_path_unmounted("DATA:");
                ui_print("Dalvik Cache wiped.\n");
                break;
            }
            case 2:
            {
                if (confirm_selection( "Confirm wipe?", "Yes - Wipe Battery Stats"))
                    wipe_battery_stats();
                break;
            }
            case 3:
                ui_print("Wiping /data/userinit.sh...\n");
                ensure_root_path_mounted("DATA:");
                remove("/data/userinit.sh");
                ensure_root_path_unmounted("DATA:");
                ui_print("Done.\n");
            	break;
            case 4:
                handle_failure(1);
                break;
            case 5:
            {
                ui_print("Outputting key codes.\n");
                ui_print("Go back to end debugging.\n");
                int key;
                int action;
                do
                {
                    key = ui_wait_key();
                    action = device_handle_key(key, 1);
                    ui_print("Key: %d\n", key);
                }
                while (action != GO_BACK);
                break;
            }
            case 6:
            {
                static char* ext_sizes[] = { "128M",
                                             "256M",
                                             "512M",
                                             "1024M",
                                             "2048M",
                                             "4096M",
                                             "8192M",
                                             "16384M",
                                             NULL };

                static char* swap_sizes[] = { "0M",
                                              "32M",
                                              "64M",
                                              "128M",
                                              "256M",
                                              NULL };

                static char* ext_headers[] = { "Ext Size", "", NULL };
                static char* swap_headers[] = { "Swap Size", "", NULL };

                int ext_size = get_menu_selection(ext_headers, ext_sizes, 0);
                if (ext_size == GO_BACK)
                    continue;
                 
                int swap_size = get_menu_selection(swap_headers, swap_sizes, 0);
                if (swap_size == GO_BACK)
                    continue;

                char sddevice[256];
                const RootInfo *ri = get_root_info_for_path("SDCARD:");
                strcpy(sddevice, ri->device);
                // we only want the mmcblk, not the partition
                sddevice[strlen("/dev/block/mmcblkX")] = NULL;
                char cmd[PATH_MAX];
                setenv("SDPATH", sddevice, 1);
                sprintf(cmd, "sdparted -es %s -ss %s -efs ext3 -s", ext_sizes[ext_size], swap_sizes[swap_size]);
                ui_print("Partitioning SD Card... please wait...\n");
                if (0 == __system(cmd))
                    ui_print("Done!\n");
                else
                    ui_print("An error occured while partitioning your SD Card. Please see /tmp/recovery.log for more details.\n");
                break;
            }
            case 7:
            {
                ensure_root_path_mounted("SYSTEM:");
                ensure_root_path_mounted("DATA:");
                ui_print("Fixing permissions...\n");
                __system("fix_permissions");
                ui_print("Done!\n");
                break;
            }
            case 8:
            {
            	// create image for Odin
            	dump_odin_image();
            	break;
            }
            case 9:
            {
                ui_print("Flashing kernel...\n");
                __system("flash_kernel");
                ui_print("Done!\n");
                break;
            }
            case 10:
            {
                ui_print("Flashing recovery...\n");
                __system("flash_recovery");
                ui_print("Done!\n");
                break;
            }
            case 11:
            {
                ui_print("Unlocking Kernel...\n");
                __system("unlock_kernel");
                ui_print("Done!\n");
                break;
            }
            case 12:
            {
                ui_print("Unlocking Recovery...\n");
                __system("unlock_recovery");
                ui_print("Done!\n");
                break;
            }
        }
    }
}
Esempio n. 15
0
int
install_package(const char *root_path)
{
	recovery_status = 0;
	int status = INSTALL_SUCCESS;
    ui_set_background(BACKGROUND_ICON_INSTALLING);
    ui_print("Finding update package...\n");
    ui_show_indeterminate_progress();

    if (ensure_root_path_mounted(root_path) != 0) {
        ui_print("Can't mount %s\n", root_path);
        status = INSTALL_CORRUPT;
		goto exit;
    }

    char path[PATH_MAX] = "";
    if (translate_root_path(root_path, path, sizeof(path)) == NULL) {
        ui_print("Bad path %s\n", root_path);
        status = INSTALL_CORRUPT;
		goto exit;
    }
	printf("package name = '%s'\t path_len= %d\n",path,strlen(path));
    ui_print("Opening update package...\n");
#if 0
    int numKeys;
    RSAPublicKey* loadedKeys = load_keys(PUBLIC_KEYS_FILE, &numKeys);
    if (loadedKeys == NULL) {
        LOGE("Failed to load keys\n");
        return INSTALL_CORRUPT;
    }
    LOGI("%d key(s) loaded from %s\n", numKeys, PUBLIC_KEYS_FILE);

    // Give verification half the progress bar...
    ui_print("Verifying update package...\n");
    ui_show_progress(
            VERIFICATION_PROGRESS_FRACTION,
            VERIFICATION_PROGRESS_TIME);

    int err;
    err = verify_file(path, loadedKeys, numKeys);
    free(loadedKeys);
    LOGI("verify_file returned %d\n", err);
    if (err != VERIFY_SUCCESS) {
        LOGE("signature verification failed\n");
        return INSTALL_CORRUPT;
    }
#endif

    /* Try to open the package.
     */
    int err;
    ZipArchive zip;
    err = mzOpenZipArchive(path, &zip);
    if (err != 0) {
        ui_print("Can't open %s\n(%s)\n", path, err != -1 ? strerror(err) : "bad");
        status = INSTALL_CORRUPT;
		goto exit;
    }

	/*
	 * Verify hw version 
	 */
	/*
	if (check_hw_version(&zip)) {
		ui_print("HW version doesn't match!!!");
		status = INSTALL_CORRUPT;
    	mzCloseZipArchive(&zip);
		goto exit;
	}
*/
    /* Verify and install the contents of the package.
     */
	ui_print("start update package file\n");
    status = handle_update_package(path, &zip);
	ui_print("install_success!!!\n");
    mzCloseZipArchive(&zip);

exit:
	ensure_root_path_unmounted(root_path);
	if (status != INSTALL_SUCCESS)
		recovery_status = 1;
	else
		recovery_status = 0;

    return status;
}
Esempio n. 16
0
int
format_root_device(const char *root)
{
    /* Be a little safer here; require that "root" is just
     * a device with no relative path after it.
     */
    const char *c = root;
    while (*c != '\0' && *c != ':') {
        c++;
    }
    /*
    if (c[0] != ':' || c[1] != '\0') {
        LOGW("format_root_device: bad root name \"%s\"\n", root);
        return -1;
    }
    */

    const RootInfo *info = get_root_info_for_path(root);
    if (info == NULL || info->device == NULL) {
        LOGW("format_root_device: can't resolve \"%s\"\n", root);
        return -1;
    }
    if (info->mount_point != NULL) {
        /* Don't try to format a mounted device.
         */
        int ret = ensure_root_path_unmounted(root);
        if (ret < 0) {
            LOGW("format_root_device: can't unmount \"%s\"\n", root);
            return ret;
        }
    }

    /* 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;
            }
        }
    }

    //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(mmc_format_ext3(partition))
                LOGE("\n\"%s\" wipe failed!\n", info->partition_name);
        }
    }

    /* Format rfs filesystem
     */
    if (!strcmp(info->filesystem, "rfs")) {
    	LOGW("format_root_device: %s as rfs\n", info->device);
    	char stl_format[32] = "stl.format ";
    	strcat(stl_format, info->device);
    	if (__system(stl_format) != 0) {
    		LOGE("format_root_device: Can't run STL format [%s]\n", strerror(errno));
    		return -1;
    	}
    	return 0;
    }

    /* Format ext file system
     */
    if (!strncmp(info->filesystem, "ext", 3)) {
    	LOGW("format_root_device: %s as %s\n", info->device, info->filesystem);
    	char ext_format[96];
    	sprintf(ext_format, "/sbin/mke2fs -T %s -F -j -q -m 0 -b 4096 %s %s", info->filesystem, (info->filesystem[3]=='2')?"":"-O ^huge_file,extent ", info->device);
    	if (__system(ext_format) != 0) {
    		LOGE("format_root_device: Can't run mke2fs [%s]\n", strerror(errno));
    		return -1;
    	}
    	return 0;
    }

    return format_non_mtd_device(root);
}
void dumping_odin_image(const char* root)
{
	if (strcmp(get_type_internal_fs(root), "rfs")) {
		ui_print("You can use this only for RFS filesystem!\n");
		return -1;
	}

    struct statfs s;
    if (0 != statfs("/sdcard", &s))
        return print_and_error("Unable to stat /sdcard\n");
    uint64_t bavail = s.f_bavail;
    uint64_t bsize = s.f_bsize;
    uint64_t sdcard_free = bavail * bsize;
    uint64_t sdcard_free_mb = sdcard_free / (uint64_t)(1024 * 1024);
    ui_print("SD Card space free: %lluMB\n", sdcard_free_mb);
    if (sdcard_free_mb < 400)
        ui_print("There may not be enough free space to complete dump... continuing...\n");

	int n_odin_ifile=0;
	const char* odin_ifile[3] = { "factoryfs.rfs", "datafs.rfs", "cache.rfs" };
    char backup_path[PATH_MAX], sdev[32], *st;
	if (!strcmp(root, "DATA:")) n_odin_ifile = 1;
	else if (!strcmp(root, "CACHE:")) n_odin_ifile = 2;

    char tar_file[PATH_MAX];
    time_t t = time(NULL);
    struct tm *tmp = localtime(&t);
    if (tmp == NULL)
    {
        struct timeval tp;
        gettimeofday(&tp, NULL);
        sprintf(tar_file, "%d", tp.tv_sec);
    }
    else
    {
        strftime(tar_file, sizeof(tar_file), "%F.%H.%M.%S", tmp);
    }

	ensure_root_path_unmounted(root);

    if (ensure_root_path_mounted("SDCARD:") != 0) {
        LOGE ("Can't mount /sdcard\n");
        return;
    }

    if (0 != __system("mkdir -p /sdcard/ebrecovery/odin/tmp")) {
		ui_print("Can't create tmp folder for backup\n");
		return -1;
	}

    strcpy(sdev, get_dev_for_root(root));
    if (st = strstr(sdev, "stl")) {
    	memcpy(st, "bml", 3);
    }
    else {
    	ui_print("Mistake in device name %s\n", sdev);
    	return -1;
    }

    ui_print("Dumping %s..\n", root);
    sprintf(backup_path, "fdump -t %s /sdcard/ebrecovery/odin/tmp/%s", sdev, odin_ifile[n_odin_ifile]);
    if (0 != __system(backup_path)) {
		ui_print("Can't create odin image [%s]\n", odin_ifile[n_odin_ifile]);
		return -1;
	}

    sprintf(backup_path, "cd /sdcard/ebrecovery/odin/tmp && tar -cf ../%s.tar %s", tar_file, odin_ifile[n_odin_ifile]);
    if (0 != __system(backup_path)) {
		ui_print("Can't create odin image [%s]\n", odin_ifile[n_odin_ifile]);
		return -1;
	}

    __system("rm -r /sdcard/ebrecovery/odin/tmp");

    ui_print("Done\n");
}
Esempio n. 18
0
void show_partition_menu()
{
    static char* headers[] = {  "Mounts and Storage Menu",
                                "",
                                NULL
    };

    typedef char* string;
    string mounts[MOUNTABLE_COUNT][3] = {
        { "mount /system", "unmount /system", "SYSTEM:" },
        { "mount /data", "unmount /data", "DATA:" },
        { "mount /cache", "unmount /cache", "CACHE:" },
        { "mount /sdcard", "unmount /sdcard", "SDCARD:" },
#ifdef BOARD_HAS_SDCARD_INTERNAL
        { "mount /emmc", "unmount /emmc", "SDINTERNAL:" },
#endif
        { "mount /sd-ext", "unmount /sd-ext", "SDEXT:" }
        };

    string mtds[MTD_COUNT][2] = {
        { "format boot", "BOOT:" },
        { "format system", "SYSTEM:" },
        { "format data", "DATA:" },
        { "format cache", "CACHE:" },
    };

    string mmcs[MMC_COUNT][3] = {
      { "format sdcard", "SDCARD:" },
#ifdef BOARD_HAS_SDCARD_INTERNAL
      { "format internal sdcard", "SDINTERNAL:" },
#endif
      { "format sd-ext", "SDEXT:" }
    };

    static char* confirm_format  = "Confirm format?";
    static char* confirm = "Yes - Format";

    for (;;)
    {
        int ismounted[MOUNTABLE_COUNT];
        int i;
        static string options[MOUNTABLE_COUNT + MTD_COUNT + MMC_COUNT + 1 + 1]; // mountables, format mtds, format mmcs, usb storage, null
        for (i = 0; i < MOUNTABLE_COUNT; i++)
        {
            ismounted[i] = is_root_path_mounted(mounts[i][2]);
            options[i] = ismounted[i] ? mounts[i][1] : mounts[i][0];
        }

        for (i = 0; i < MTD_COUNT; i++)
        {
            options[MOUNTABLE_COUNT + i] = mtds[i][0];
        }

        for (i = 0; i < MMC_COUNT; i++)
        {
            options[MOUNTABLE_COUNT + MTD_COUNT + i] = mmcs[i][0];
        }

        options[MOUNTABLE_COUNT + MTD_COUNT + MMC_COUNT] = "mount USB storage";
        options[MOUNTABLE_COUNT + MTD_COUNT + MMC_COUNT + 1] = NULL;

        int chosen_item = get_menu_selection(headers, options, 0);
        if (chosen_item == GO_BACK)
            break;
        if (chosen_item == MOUNTABLE_COUNT + MTD_COUNT + MMC_COUNT)
        {
            show_mount_usb_storage_menu();
        }
        else if (chosen_item < MOUNTABLE_COUNT)
        {
            if (ismounted[chosen_item])
            {
                if (0 != ensure_root_path_unmounted(mounts[chosen_item][2]))
                    ui_print("Error unmounting %s!\n", mounts[chosen_item][2]);
            }
            else
            {
                if (0 != ensure_root_path_mounted(mounts[chosen_item][2]))
                    ui_print("Error mounting %s!\n", mounts[chosen_item][2]);
            }
        }
        else if (chosen_item < MOUNTABLE_COUNT + MTD_COUNT)
        {
            chosen_item = chosen_item - MOUNTABLE_COUNT;
            if (!confirm_selection(confirm_format, confirm))
                continue;
            ui_print("Formatting %s...\n", mtds[chosen_item][1]);
            if (0 != format_root_device(mtds[chosen_item][1]))
                ui_print("Error formatting %s!\n", mtds[chosen_item][1]);
            else
                ui_print("Done.\n");
        }
        else if (chosen_item < MOUNTABLE_COUNT + MTD_COUNT + MMC_COUNT)
        {
            chosen_item = chosen_item - MOUNTABLE_COUNT - MTD_COUNT;
            if (!confirm_selection(confirm_format, confirm))
                continue;
            ui_print("Formatting %s...\n", 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");
        }
    }
}
int write_update_for_bootloader(
        const char *update, int update_length,
        int bitmap_width, int bitmap_height, int bitmap_bpp,
        const char *busy_bitmap, const char *fail_bitmap) {
    if (ensure_root_path_unmounted(CACHE_NAME)) {
        LOGE("Can't unmount %s\n", CACHE_NAME);
        return -1;
    }

    const MtdPartition *part = get_root_mtd_partition(CACHE_NAME);
    if (part == NULL) {
        LOGE("Can't find %s\n", CACHE_NAME);
        return -1;
    }

    MtdWriteContext *write = mtd_write_partition(part);
    if (write == NULL) {
        LOGE("Can't open %s\n(%s)\n", CACHE_NAME, strerror(errno));
        return -1;
    }

    /* Write an invalid (zero) header first, to disable any previous
     * update and any other structured contents (like a filesystem),
     * and as a placeholder for the amount of space required.
     */

    struct update_header header;
    memset(&header, 0, sizeof(header));
    const ssize_t header_size = sizeof(header);
    if (mtd_write_data(write, (char*) &header, header_size) != header_size) {
        LOGE("Can't write header to %s\n(%s)\n", CACHE_NAME, strerror(errno));
        mtd_write_close(write);
        return -1;
    }

    /* Write each section individually block-aligned, so we can write
     * each block independently without complicated buffering.
     */

    memcpy(&header.MAGIC, UPDATE_MAGIC, UPDATE_MAGIC_SIZE);
    header.version = UPDATE_VERSION;
    header.size = header_size;

    off_t image_start_pos = mtd_erase_blocks(write, 0);
    header.image_length = update_length;
    if ((int) header.image_offset == -1 ||
        mtd_write_data(write, update, update_length) != update_length) {
        LOGE("Can't write update to %s\n(%s)\n", CACHE_NAME, strerror(errno));
        mtd_write_close(write);
        return -1;
    }
    off_t busy_start_pos = mtd_erase_blocks(write, 0);
    header.image_offset = mtd_find_write_start(write, image_start_pos);

    header.bitmap_width = bitmap_width;
    header.bitmap_height = bitmap_height;
    header.bitmap_bpp = bitmap_bpp;

    int bitmap_length = (bitmap_bpp + 7) / 8 * bitmap_width * bitmap_height;

    header.busy_bitmap_length = busy_bitmap != NULL ? bitmap_length : 0;
    if ((int) header.busy_bitmap_offset == -1 ||
        mtd_write_data(write, busy_bitmap, bitmap_length) != bitmap_length) {
        LOGE("Can't write bitmap to %s\n(%s)\n", CACHE_NAME, strerror(errno));
        mtd_write_close(write);
        return -1;
    }
    off_t fail_start_pos = mtd_erase_blocks(write, 0);
    header.busy_bitmap_offset = mtd_find_write_start(write, busy_start_pos);

    header.fail_bitmap_length = fail_bitmap != NULL ? bitmap_length : 0;
    if ((int) header.fail_bitmap_offset == -1 ||
        mtd_write_data(write, fail_bitmap, bitmap_length) != bitmap_length) {
        LOGE("Can't write bitmap to %s\n(%s)\n", CACHE_NAME, strerror(errno));
        mtd_write_close(write);
        return -1;
    }
    mtd_erase_blocks(write, 0);
    header.fail_bitmap_offset = mtd_find_write_start(write, fail_start_pos);

    /* Write the header last, after all the blocks it refers to, so that
     * when the magic number is installed everything is valid.
     */

    if (mtd_write_close(write)) {
        LOGE("Can't finish writing %s\n(%s)\n", CACHE_NAME, strerror(errno));
        return -1;
    }

    write = mtd_write_partition(part);
    if (write == NULL) {
        LOGE("Can't reopen %s\n(%s)\n", CACHE_NAME, strerror(errno));
        return -1;
    }

    if (mtd_write_data(write, (char*) &header, header_size) != header_size) {
        LOGE("Can't rewrite header to %s\n(%s)\n", CACHE_NAME, strerror(errno));
        mtd_write_close(write);
        return -1;
    }

    if (mtd_erase_blocks(write, 0) != image_start_pos) {
        LOGE("Misalignment rewriting %s\n(%s)\n", CACHE_NAME, strerror(errno));
        mtd_write_close(write);
        return -1;
    }

    if (mtd_write_close(write)) {
        LOGE("Can't finish header of %s\n(%s)\n", CACHE_NAME, strerror(errno));
        return -1;
    }

    return 0;
}
Esempio n. 20
0
void show_multi_boot_menu()
{
    static char* headers[] = {  "MultiBoot Menu",
                                "",
                                NULL
    };

    static char* list[] = { "~~~> Go Back <~~~",
			    "Switch ROM",
                            "Backup Current ROM",
			    "Switch Kernel",
			    "Backup Data",
			    "Restore Data",
                            NULL
    };

    for (;;)
    {	
	create_rom_dirs();
        int chosen_item = get_menu_selection(headers, list, 0);
	if (chosen_item == GO_BACK)
            break;
        switch (chosen_item)
        {
		case 0:
		{
		return;
		break;
		}
            
		case 1:
                {
		if (ensure_root_path_mounted("SDCARD:") != 0) {
		LOGE ("Can't mount /sdcard\n");
		return;
		}
		
   		static char* advancedheaders1[] = {  "Choose Which ROM to Activate",
                                			NULL
   						 };
  		char* file = choose_file_menu("/sdcard/Android/data/g3mod/roms/", NULL, advancedheaders1);
   		 if (file == NULL)
     		   return;

    		static char* headers[] = {  "Activating ROM",
                           		     "",
                            		    NULL
  					  };

    		static char* confirm_restore  = "Confirm activate?";
       	        if (confirm_selection(confirm_restore, "Yes - Activate ROM"))
		{		
		nandroid_restore_system(file,1);
		
		}
		
		if (0 != ensure_root_path_mounted("DATA:"))
                    break;
                ensure_root_path_mounted("SDEXT:");
                ensure_root_path_mounted("CACHE:");
                    __system("rm -r /data/dalvik-cache");
                    __system("rm -r /cache/dalvik-cache");
                    __system("rm -r /sd-ext/dalvik-cache");
                ensure_root_path_unmounted("DATA:");
                ui_print("Dalvik Cache wiped.\n");

		show_choose_kernel_menu();
		
                break;
	}
            case 2:
            {
                backup_rom();
                break;
            }
	case 3:
                {
		show_choose_kernel_menu();
                break;
	}
	case 4:
                {
		backup_data();
                break;
	}
	case 5:
                {
		if (ensure_root_path_mounted("SDCARD:") != 0) {
		LOGE ("Can't mount /sdcard\n");
		return;
		}
		
   		static char* advancedheaders1[] = {  "Choose Which Data to Restore",
                                			NULL
   						 };
  		char* file = choose_file_menu("/sdcard/Android/data/g3mod/data/", NULL, advancedheaders1);
   		 if (file == NULL)
     		   return;

    		static char* headers[] = {  "Restoring Data",
                           		     "",
                            		    NULL
  					  };

    		static char* confirm_restore  = "Confirm restore?";
       	        if (confirm_selection(confirm_restore, "Yes - Restore Data"))
		{		
			nandroid_restore_data(file,1);
			nandroid_restore_sd(file,1);
			nandroid_restore_androidSecure(file,1);
		}
                break;
	}
        }
    }
}
Esempio n. 21
0
void show_wipe_menu()
{

static char* headers[] = {  "Wipe Menu",
                                "",
                                NULL
    };

 static char* list[] = { "~~~> Go Back <~~~",
                         "Data / Factory Reset",
                         "Cache",
                         "Wipe Dalvik Cache",
                         "Wipe Battery Stats",
                            NULL
};

for (;;)
    {
        int chosen_item = get_menu_selection(headers, list, 0);
	if (chosen_item == GO_BACK)
            break;
	switch (chosen_item)
	{
		case 0:
		{
		return;
		break;
		}
		case 1:
		{
		wipe_data1(ui_text_visible());
                if (!ui_text_visible()) return;
		break;
		}
		case 2:
		{
		  if (confirm_selection("Confirm wipe?", "Yes - Wipe Cache"))
                {
                    ui_print("\n-- Wiping cache...\n");
                    erase_root1("CACHE:");
                    ui_print("Cache wipe complete.\n");
                    if (!ui_text_visible()) return;
                }
		break;
		}
		case 3:
		{
		if (0 != ensure_root_path_mounted("DATA:"))
                    break;
                ensure_root_path_mounted("SDEXT:");
                ensure_root_path_mounted("CACHE:");
                if (confirm_selection( "Confirm wipe?", "Yes - Wipe Dalvik Cache")) {
                    __system("rm -r /data/dalvik-cache");
                    __system("rm -r /cache/dalvik-cache");
                    __system("rm -r /sd-ext/dalvik-cache");
                }
                ensure_root_path_unmounted("DATA:");
                ui_print("Dalvik Cache wiped.\n");
                break;
		}
		case 4:
		{
		if (confirm_selection( "Confirm wipe?", "Yes - Wipe Battery Stats"))
                    wipe_battery_stats();
                break;
		}
	}
     }
}
Esempio n. 22
0
void wipe_battery_stats()
{
    ensure_root_path_mounted("DATA:");
    remove("/data/system/batterystats.bin");
    ensure_root_path_unmounted("DATA:");
}
Esempio n. 23
0
int
format_root_device(const char *root)
{
    /* Be a little safer here; require that "root" is just
     * a device with no relative path after it.
     */
    const char *c = root;
    while (*c != '\0' && *c != ':') {
        c++;
    }
    if (c[0] != ':' || c[1] != '\0') {
        LOGW("format_root_device: bad root name \"%s\"\n", root);
        return -1;
    }

    const RootInfo *info = get_root_info_for_path(root);
    if (info == NULL || info->device == NULL) {
        LOGW("format_root_device: can't resolve \"%s\"\n", root);
        return -1;
    }
    if (info->mount_point != NULL) {
        /* Don't try to format a mounted device.
         */
        int ret = ensure_root_path_unmounted(root);
        if (ret < 0) {
            LOGW("format_root_device: can't unmount \"%s\"\n", root);
            return ret;
        }
    }

    /* 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;
            }
        }
    } 
    else 
    {
	    return format_non_mtd_device(root);
    }

    //TODO: handle other device types (sdcard, etc.)
    LOGW("format_root_device: can't handle non-mtd device \"%s\"\n", root);
    return -1;
}
Esempio n. 24
0
int
format_root_device(const char *root)
{
    /* Be a little safer here; require that "root" is just
     * a device with no relative path after it.
     */
    const char *c = root;
    while (*c != '\0' && *c != ':') {
        c++;
    }
    if (c[0] != ':' || c[1] != '\0') {
        LOGW("format_root_device: bad root name \"%s\"\n", root);
        return -1;
    }

    const RootInfo *info = get_root_info_for_path(root);
    if (info == NULL || info->device == NULL) {
        LOGW("format_root_device: can't resolve \"%s\"\n", root);
        return -1;
    }
    if (info->mount_point != NULL) {
        /* Don't try to format a mounted device.
         */
        int ret = ensure_root_path_unmounted(root);
        if (ret < 0) {
            LOGW("format_root_device: can't unmount \"%s\"\n", root);
            return ret;
        }
    }

    if (info->filesystem != NULL && strcmp(info->filesystem, "ext2")==0) {
	LOGW("format: %s\n", info->device);
        pid_t pid = fork();
        if (pid == 0) {
	    char *args[] = {"/xbin/mke2fs", "-b4096", info->device, NULL};
            execv("/xbin/mke2fs", args);
            fprintf(stderr, "E:Can't run mke2fs format [%s]\n", strerror(errno));
            _exit(-1);
        }

        int status;

        while (waitpid(pid, &status, WNOHANG) == 0) {
            ui_print(".");
            sleep(1);
        }
        ui_print("\n");

        if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) {
            LOGW("format_root_device: can't erase \"%s\"\n", root);
	    return -1;
            ui_print("Error running samdroid backup. Backup not performed.\n\n");
        }
	return 0;
    }

    /* 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;
            }
        }
    }
//TODO: handle other device types (sdcard, etc.)
    LOGW("format_root_device: can't handle non-mtd device \"%s\"\n", root);
    return -1;
}