示例#1
0
bool TWPartition::Wipe_MTD() {
	if (!UnMount(true))
		return false;

	ui_print("MTD Formatting \"%s\"\n", MTD_Name.c_str());

    mtd_scan_partitions();
    const MtdPartition* mtd = mtd_find_partition_by_name(MTD_Name.c_str());
    if (mtd == NULL) {
        LOGE("No mtd partition named '%s'", MTD_Name.c_str());
        return false;
    }

    MtdWriteContext* ctx = mtd_write_partition(mtd);
    if (ctx == NULL) {
        LOGE("Can't write '%s', failed to format.", MTD_Name.c_str());
        return false;
    }
    if (mtd_erase_blocks(ctx, -1) == -1) {
        mtd_write_close(ctx);
        LOGE("Failed to format '%s'", MTD_Name.c_str());
        return false;
    }
    if (mtd_write_close(ctx) != 0) {
        LOGE("Failed to close '%s'", MTD_Name.c_str());
        return false;
    }
	Recreate_AndSec_Folder();
	ui_print("Done.\n");
    return true;
}
示例#2
0
int format_volume(const char* volume) {
    Volume* v = volume_for_path(volume);
    char value[PROPERTY_VALUE_MAX];

    if (v == NULL) {
        LOGE("unknown volume \"%s\"\n", volume);
        return -1;
    }
    if (strcmp(v->fs_type, "ramdisk") == 0) {
        // you can't format the ramdisk.
        LOGE("can't format_volume \"%s\"", volume);
        return -1;
    }
    if (strcmp(v->mount_point, volume) != 0) {
        LOGE("can't give path \"%s\" to format_volume\n", volume);
        return -1;
    }

    if (ensure_path_unmounted(volume) != 0) {
        LOGE("format_volume failed to unmount \"%s\"\n", v->mount_point);
        return -1;
    }

    if (strcmp(v->fs_type, "yaffs2") == 0 || strcmp(v->fs_type, "mtd") == 0) {
        mtd_scan_partitions();
        const MtdPartition* partition = mtd_find_partition_by_name(v->device);
        if (partition == NULL) {
            LOGE("format_volume: no MTD partition \"%s\"\n", v->device);
            return -1;
        }

        MtdWriteContext *write = mtd_write_partition(partition);
        if (write == NULL) {
            LOGE("format_volume: can't open MTD \"%s\"\n", v->device);
            return -1;
        } else if (mtd_erase_blocks(write, -1) == (off_t) -1) {
            LOGE("format_volume: can't erase MTD \"%s\"\n", v->device);
            mtd_write_close(write);
            return -1;
        } else if (mtd_write_close(write)) {
            LOGE("format_volume: can't close MTD \"%s\"\n", v->device);
            return -1;
        }
        return 0;
    }

    if (strcmp(v->fs_type, "ext4") == 0) {
        int result = make_ext4fs(v->device, v->length, volume, NULL);
        if (result != 0) {
            // If v->length is <= 0 the fs is not created by make_ext4fs.
            LOGE("format_volume: make_extf4fs failed on %s\n", v->device);
            return -1;
        }
        return 0;
    }

    LOGE("format_volume: fs_type \"%s\" unsupported\n", v->fs_type);
    return -1;
}
static int
set_bootloader_message_mtd (const struct bootloader_message *in,
			    const Volume * v)
{
  size_t write_size;

  mtd_scan_partitions ();
  const MtdPartition *part = mtd_find_partition_by_name (v->device);

  if (part == NULL || mtd_partition_info (part, NULL, NULL, &write_size))
	  {
	    LOGE ("Can't find %s\n", v->device);
	    return -1;
	  }

  MtdReadContext *read = mtd_read_partition (part);

  if (read == NULL)
	  {
	    LOGE ("Can't open %s\n(%s)\n", v->device, strerror (errno));
	    return -1;
	  }

  ssize_t size = write_size * MISC_PAGES;
  char data[size];
  ssize_t r = mtd_read_data (read, data, size);

  if (r != size)
    LOGE ("Can't read %s\n(%s)\n", v->device, strerror (errno));
  mtd_read_close (read);
  if (r != size)
    return -1;

  memcpy (&data[write_size * MISC_COMMAND_PAGE], in, sizeof (*in));

  MtdWriteContext *write = mtd_write_partition (part);

  if (write == NULL)
	  {
	    LOGE ("Can't open %s\n(%s)\n", v->device, strerror (errno));
	    return -1;
	  }
  if (mtd_write_data (write, data, size) != size)
	  {
	    LOGE ("Can't write %s\n(%s)\n", v->device, strerror (errno));
	    mtd_write_close (write);
	    return -1;
	  }
  if (mtd_write_close (write))
	  {
	    LOGE ("Can't finish %s\n(%s)\n", v->device, strerror (errno));
	    return -1;
	  }

  LOGI ("Set boot command \"%s\"\n",
	in->command[0] != 255 ? in->command : "");
  return 0;
}
示例#4
0
// Write a memory buffer to target_mtd partition, a string of the form
// "MTD:<partition>[:...]".  Return 0 on success.
int WriteToMTDPartition(unsigned char* data, size_t len,
                        const char* target_mtd) {
  char* partition = strchr(target_mtd, ':');
  if (partition == NULL) {
    fprintf(stderr, "bad MTD target name \"%s\"\n", target_mtd);
    return -1;
  }
  ++partition;
  // Trim off anything after a colon, eg "MTD:boot:blah:blah:blah...".
  // We want just the partition name "boot".
  partition = strdup(partition);
  char* end = strchr(partition, ':');
  if (end != NULL)
    *end = '\0';

  if (!mtd_partitions_scanned) {
    mtd_scan_partitions();
    mtd_partitions_scanned = 1;
  }

  const MtdPartition* mtd = mtd_find_partition_by_name(partition);
  if (mtd == NULL) {
    fprintf(stderr, "mtd partition \"%s\" not found for writing\n", partition);
    return -1;
  }

  MtdWriteContext* ctx = mtd_write_partition(mtd);
  if (ctx == NULL) {
    fprintf(stderr, "failed to init mtd partition \"%s\" for writing\n",
            partition);
    return -1;
  }

  size_t written = mtd_write_data(ctx, (char*)data, len);
  if (written != len) {
    fprintf(stderr, "only wrote %d of %d bytes to MTD %s\n",
            written, len, partition);
    mtd_write_close(ctx);
    return -1;
  }

  if (mtd_erase_blocks(ctx, -1) < 0) {
    fprintf(stderr, "error finishing mtd write of %s\n", partition);
    mtd_write_close(ctx);
    return -1;
  }

  if (mtd_write_close(ctx)) {
    fprintf(stderr, "error closing mtd write of %s\n", partition);
    return -1;
  }

  free(partition);
  return 0;
}
// FOTA cookie indicates that an android or modem image package
// is available for delta update
int set_fota_cookie_mtd(void)
{
    size_t write_size;

    mtd_scan_partitions();
    const MtdPartition *part = mtd_find_partition_by_name("FOTA");

    if (part == NULL || mtd_partition_info(part, NULL, NULL, &write_size)) {
        LOGE("Can't find FOTA\n");
        return -1;
    }

    MtdReadContext *read = mtd_read_partition(part);
    if (read == NULL) {
        LOGE("Can't open FOTA\n(%s)\n", strerror(errno));
        return -1;
    }

    ssize_t size = write_size; //writing 1 page is enough
    char data[size];
    ssize_t r = mtd_read_data(read, data, size);
    if (r != size) LOGE("Can't read FOTA\n(%s)\n", strerror(errno));
    mtd_read_close(read);
    if (r != size) return -1;

    //setting FOTA cookie value, 0x64645343
    memset(data, 0x0, sizeof(data));
    data[0] = 0x43;
    data[1] = 0x53;
    data[2] = 0x64;
    data[3] = 0x64;

    MtdWriteContext *write = mtd_write_partition(part);
    if (write == NULL) {
        LOGE("Can't open FOTA\n(%s)\n", strerror(errno));
        return -1;
    }
    if (mtd_write_data(write, data, size) != size) {
        LOGE("Can't write FOTA\n(%s)\n", strerror(errno));
        mtd_write_close(write);
        return -1;
    }
    if (mtd_write_close(write)) {
        LOGE("Can't finish FOTA\n(%s)\n", strerror(errno));
        return -1;
    }

    LOGI("Set FOTA cookie done.\n");
    return 0;
}
int set_bootloader_message(const struct bootloader_message *in) {
    size_t write_size;
    const MtdPartition *part = get_root_mtd_partition(MISC_NAME);
    if (part == NULL || mtd_partition_info(part, NULL, NULL, &write_size)) {
        LOGE("Can't find %s\n", MISC_NAME);
        return -1;
    }

    MtdReadContext *read = mtd_read_partition(part);
    if (read == NULL) {
        LOGE("Can't open %s\n(%s)\n", MISC_NAME, strerror(errno));
        return -1;
    }

    ssize_t size = write_size * MISC_PAGES;
    char data[size];
    ssize_t r = mtd_read_data(read, data, size);
    if (r != size) LOGE("Can't read %s\n(%s)\n", MISC_NAME, strerror(errno));
    mtd_read_close(read);
    if (r != size) return -1;

    memcpy(&data[write_size * MISC_COMMAND_PAGE], in, sizeof(*in));

#ifdef LOG_VERBOSE
    printf("\n--- set_bootloader_message ---\n");
    dump_data(data, size);
    printf("\n");
#endif

    MtdWriteContext *write = mtd_write_partition(part);
    if (write == NULL) {
        LOGE("Can't open %s\n(%s)\n", MISC_NAME, strerror(errno));
        return -1;
    }
    if (mtd_write_data(write, data, size) != size) {
        LOGE("Can't write %s\n(%s)\n", MISC_NAME, strerror(errno));
        mtd_write_close(write);
        return -1;
    }
    if (mtd_write_close(write)) {
        LOGE("Can't finish %s\n(%s)\n", MISC_NAME, strerror(errno));
        return -1;
    }

    LOGI("Set boot command \"%s\"\n", in->command[0] != 255 ? in->command : "");
    return 0;
}
示例#7
0
int
cmd_mtd_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;
}
示例#8
0
static int phx_format_mtd(const char* device)
{
    char* location = (char*) device;

    Volume* v = volume_for_device(device);
    if (v)
    {
        // We may not have the right "name" for it... Let's flip it
        location = v->device;
    }

    LOGI("%s: Formatting \"%s\"\n", __FUNCTION__, location);

    mtd_scan_partitions();
    const MtdPartition* mtd = mtd_find_partition_by_name(location);
    if (mtd == NULL) {
        LOGE("%s: no mtd partition named \"%s\"", __FUNCTION__, location);
        return -1;
    }

    MtdWriteContext* ctx = mtd_write_partition(mtd);
    if (ctx == NULL) {
        LOGE("%s: can't write \"%s\"", __FUNCTION__, location);
        return -1;
    }
    if (mtd_erase_blocks(ctx, -1) == -1) {
        mtd_write_close(ctx);
        LOGE("%s: failed to erase \"%s\"", __FUNCTION__, location);
        return -1;
    }
    if (mtd_write_close(ctx) != 0) {
        LOGE("%s: failed to close \"%s\"", __FUNCTION__, location);
        return -1;
    }
    return 0;
}
示例#9
0
int cmd_mtd_restore_raw_partition(const char *partition_name, const char *filename)
{
    const MtdPartition *ptn;
    MtdWriteContext *write;
    void *data;

    FILE* f = fopen(filename, "rb");
    if (f == NULL) {
        fprintf(stderr, "error opening %s", filename);
        return -1;
    }

    if (mtd_scan_partitions() <= 0)
    {
        fprintf(stderr, "error scanning partitions");
        return -1;
    }
    const MtdPartition *mtd = mtd_find_partition_by_name(partition_name);
    if (mtd == NULL)
    {
        fprintf(stderr, "can't find %s partition", partition_name);
        return -1;
    }

    int fd = open(filename, O_RDONLY);
    if (fd < 0)
    {
        printf("error opening %s", filename);
        return -1;
    }
    
    MtdWriteContext* ctx = mtd_write_partition(mtd);
    if (ctx == NULL) {
        printf("error writing %s", partition_name);
        return -1;
    }

    int success = 1;
    char* buffer = malloc(BUFSIZ);
    int read;
    while (success && (read = fread(buffer, 1, BUFSIZ, f)) > 0) {
        int wrote = mtd_write_data(ctx, buffer, read);
        success = success && (wrote == read);
    }
    free(buffer);
    fclose(f);

    if (!success) {
        fprintf(stderr, "error writing %s", partition_name);
        return -1;
    }

    if (mtd_erase_blocks(ctx, -1) == -1) {
        fprintf(stderr, "error erasing blocks of %s\n", partition_name);
    }
    if (mtd_write_close(ctx) != 0) {
        fprintf(stderr, "error closing write of %s\n", partition_name);
    }
    printf("%s %s partition\n", success ? "wrote" : "failed to write", partition_name);
    return 0;
}
// write_raw_image(filename_or_blob, partition)
Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) {
    char* result = NULL;

    Value* partition_value;
    Value* contents;
    if (ReadValueArgs(state, argv, 2, &contents, &partition_value) < 0) {
        return NULL;
    }

    char* partition = NULL;
    if (partition_value->type != VAL_STRING) {
        ErrorAbort(state, "partition argument to %s must be string", name);
        goto done;
    }
    partition = partition_value->data;
    if (strlen(partition) == 0) {
        ErrorAbort(state, "partition argument to %s can't be empty", name);
        goto done;
    }
    if (contents->type == VAL_STRING && strlen((char*) contents->data) == 0) {
        ErrorAbort(state, "file argument to %s can't be empty", name);
        goto done;
    }

    mtd_scan_partitions();
    const MtdPartition* mtd = mtd_find_partition_by_name(partition);
    if (mtd == NULL) {
        fprintf(stderr, "%s: no mtd partition named \"%s\"\n", name, partition);
        result = strdup("");
        goto done;
    }

    MtdWriteContext* ctx = mtd_write_partition(mtd);
    if (ctx == NULL) {
        fprintf(stderr, "%s: can't write mtd partition \"%s\"\n",
                name, partition);
        result = strdup("");
        goto done;
    }

    bool success;

    if (contents->type == VAL_STRING) {
        // we're given a filename as the contents
        char* filename = contents->data;
        FILE* f = fopen(filename, "rb");
        if (f == NULL) {
            fprintf(stderr, "%s: can't open %s: %s\n",
                    name, filename, strerror(errno));
            result = strdup("");
            goto done;
        }

        success = true;
        char* buffer = malloc(BUFSIZ);
        int read;
        while (success && (read = fread(buffer, 1, BUFSIZ, f)) > 0) {
            int wrote = mtd_write_data(ctx, buffer, read);
            success = success && (wrote == read);
        }
        free(buffer);
        fclose(f);
    } else {
        // we're given a blob as the contents
        ssize_t wrote = mtd_write_data(ctx, contents->data, contents->size);
        success = (wrote == contents->size);
    }
    if (!success) {
        fprintf(stderr, "mtd_write_data to %s failed: %s\n",
                partition, strerror(errno));
    }

    if (mtd_erase_blocks(ctx, -1) == -1) {
        fprintf(stderr, "%s: error erasing blocks of %s\n", name, partition);
    }
    if (mtd_write_close(ctx) != 0) {
        fprintf(stderr, "%s: error closing write of %s\n", name, partition);
    }

    printf("%s %s partition\n",
           success ? "wrote" : "failed to write", partition);

    result = success ? partition : strdup("");

done:
    if (result != partition) FreeValue(partition_value);
    FreeValue(contents);
    return StringValue(result);
}
示例#11
0
int format_volume(const char* volume) {
    Volume* v = volume_for_path(volume);
    if (v == NULL) {
        LOGE("unknown volume \"%s\"\n", volume);
        return -1;
    }
    if (strcmp(v->fs_type, "ramdisk") == 0) {
        // you can't format the ramdisk.
        LOGE("can't format_volume \"%s\"", volume);
        return -1;
    }
    if (strcmp(v->mount_point, volume) != 0) {
        LOGE("can't give path \"%s\" to format_volume\n", volume);
        return -1;
    }

    if (ensure_path_unmounted(volume) != 0) {
        LOGE("format_volume failed to unmount \"%s\"\n", v->mount_point);
        return -1;
    }
    if(!strcmp(v->fs_type, "ubifs"))
    {
    const MtdPartition *partition;
	mtd_scan_partitions();
    if(strcmp(v->mount_point, "/data"))
        partition = mtd_find_partition_by_name(&v->mount_point[1]);
    else
        partition = mtd_find_partition_by_name("userdata");
        if (partition == NULL) {
            LOGE("format_volume: %s cat't find mtd partition\n", v->mount_point);
            return -1;
	        }else{
	        if (strcmp(v->mount_point, "/system") == 0 ||
	            strcmp(v->mount_point, "/cache") == 0 ||
	            strcmp(v->mount_point, "/data") == 0 ){
	            
	           char cmd_line[128];
	            int  ubi_vol = 1;
	//            bool b_org_mounted = false;
	            int status;

	            ui_print("format partition: %s \n", v->mount_point);
#if 1      
	            if (strcmp(v->mount_point, "/system") == 0){
	                ubi_vol = 1;
	            }else if (strcmp(v->mount_point, "/data") == 0){
	            	ubi_vol = 2;
	            }else if(strcmp(v->mount_point, "/cache") == 0){
	                ubi_vol = 3;
	            }else{
	            	ubi_vol = 4; //perm partition
	            }
#endif

				//vapor : it is not properly, so we mask it.
	            //if (ensure_path_mounted(v->mount_point) == 0)  
	            {
	                fprintf(stderr,"umount /%s\r\n", v->mount_point);
	                umount(v->mount_point);
	            }
	            
	            memset(cmd_line, 0, 128);
	            sprintf(cmd_line, "/format.sh %d %d %s", partition->device_index, ubi_vol, partition->name);
                format_ubifs(cmd_line);
	            ui_print("format partition: %s complete\n", v->device);
	        	return 0;
	   		 }
	    	}
		}
	    else if (strcmp(v->fs_type, "yaffs2") == 0 || strcmp(v->fs_type, "mtd") == 0) {
	        mtd_scan_partitions();
	        const MtdPartition* partition = mtd_find_partition_by_name(v->device);
	        if (partition == NULL) {
	            LOGE("format_volume: no MTD partition \"%s\"\n", v->device);
	            return -1;
	        }

	        MtdWriteContext *write = mtd_write_partition(partition);
	        if (write == NULL) {
	            LOGW("format_volume: can't open MTD \"%s\"\n", v->device);
	            return -1;
	        } else if (mtd_erase_blocks(write, -1) == (off_t) -1) {
	            LOGW("format_volume: can't erase MTD \"%s\"\n", v->device);
	            mtd_write_close(write);
	            return -1;
	        } else if (mtd_write_close(write)) {
	            LOGW("format_volume: can't close MTD \"%s\"\n", v->device);
	            return -1;
	        }
	        return 0;
	    }
#if 0
	    else if (strcmp(v->fs_type, "ext4") == 0) {
	        int result = make_ext4fs(v->device, v->length);
	        if (result != 0) {
	            LOGE("format_volume: make_extf4fs failed on %s\n", v->device);
	            return -1;
	        }
	        return 0;
	    }
#endif
    LOGE("format_volume: fs_type \"%s\" unsupported\n", v->fs_type);
    return -1;
}
示例#12
0
// write_raw_image(file, partition)
Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) {
    char* result = NULL;

    char* partition;
    char* filename;
    if (ReadArgs(state, argv, 2, &filename, &partition) < 0) {
        return NULL;
    }

    if (strlen(partition) == 0) {
        ErrorAbort(state, "partition argument to %s can't be empty", name);
        goto done;
    }
    if (strlen(filename) == 0) {
        ErrorAbort(state, "file argument to %s can't be empty", name);
        goto done;
    }

#ifdef BOARD_USES_BMLUTILS
    if (0 == write_raw_image(name, filename)) {
        result = partition;
    }
    result = strdup("Failure");
#else
    mtd_scan_partitions();
    const MtdPartition* mtd = mtd_find_partition_by_name(partition);
    if (mtd == NULL) {
        fprintf(stderr, "%s: no mtd partition named \"%s\"\n", name, partition);
        result = strdup("");
        goto MMC;
    }

    MtdWriteContext* ctx = mtd_write_partition(mtd);
    if (ctx == NULL) {
        fprintf(stderr, "%s: can't write mtd partition \"%s\"\n",
                name, partition);
        result = strdup("");
        goto done;
    }

    bool success;

    FILE* f = fopen(filename, "rb");
    if (f == NULL) {
        fprintf(stderr, "%s: can't open %s: %s\n",
                name, filename, strerror(errno));
        result = strdup("");
        goto done;
    }

    success = true;
    char* buffer = malloc(BUFSIZ);
    int read;
    while (success && (read = fread(buffer, 1, BUFSIZ, f)) > 0) {
        int wrote = mtd_write_data(ctx, buffer, read);
        success = success && (wrote == read);
        if (!success) {
            fprintf(stderr, "mtd_write_data to %s failed: %s\n",
                    partition, strerror(errno));
        }
    }
    free(buffer);
    fclose(f);

    if (mtd_erase_blocks(ctx, -1) == -1) {
        fprintf(stderr, "%s: error erasing blocks of %s\n", name, partition);
    }
    if (mtd_write_close(ctx) != 0) {
        fprintf(stderr, "%s: error closing write of %s\n", name, partition);
    }

    printf("%s %s partition from %s\n",
           success ? "wrote" : "failed to write", partition, filename);

    result = success ? partition : strdup("");
    goto done;

MMC:
    mmc_scan_partitions();
    const MmcPartition* mmc = mmc_find_partition_by_name(partition);
    if (mmc == NULL) {
        fprintf(stderr, "%s: no mmc partition named \"%s\"\n", name, partition);
        result = strdup("");
        goto done;
    }
    if (mmc_raw_copy(mmc, filename)) {
        fprintf(stderr, "%s: error erasing mmc partition named \"%s\"\n", name, partition);
        result = strdup("");
        goto done;
    }
    result = partition;
#endif

done:
    if (result != partition) free(partition);
    free(filename);
    return StringValue(result);
}
// Write a memory buffer to 'target' partition, a string of the form
// "MTD:<partition>[:...]" or "EMMC:<partition_device>:".  Return 0 on
// success.
int WriteToPartition(unsigned char* data, size_t len,
                        const char* target) {
    char* copy = strdup(target);
    const char* magic = strtok(copy, ":");

    enum PartitionType type;
    if (strcmp(magic, "MTD") == 0) {
        type = MTD;
    } else if (strcmp(magic, "EMMC") == 0) {
        type = EMMC;
    } else {
        printf("WriteToPartition called with bad target (%s)\n", target);
        return -1;
    }
    const char* partition = strtok(NULL, ":");

    if (partition == NULL) {
        printf("bad partition target name \"%s\"\n", target);
        return -1;
    }

    switch (type) {
        case MTD:
            if (!mtd_partitions_scanned) {
                mtd_scan_partitions();
                mtd_partitions_scanned = 1;
            }

            const MtdPartition* mtd = mtd_find_partition_by_name(partition);
            if (mtd == NULL) {
                printf("mtd partition \"%s\" not found for writing\n",
                       partition);
                return -1;
            }

            MtdWriteContext* ctx = mtd_write_partition(mtd);
            if (ctx == NULL) {
                printf("failed to init mtd partition \"%s\" for writing\n",
                       partition);
                return -1;
            }

            size_t written = mtd_write_data(ctx, (char*)data, len);
            if (written != len) {
                printf("only wrote %zu of %zu bytes to MTD %s\n",
                       written, len, partition);
                mtd_write_close(ctx);
                return -1;
            }

            if (mtd_erase_blocks(ctx, -1) < 0) {
                printf("error finishing mtd write of %s\n", partition);
                mtd_write_close(ctx);
                return -1;
            }

            if (mtd_write_close(ctx)) {
                printf("error closing mtd write of %s\n", partition);
                return -1;
            }
            break;

        case EMMC:
        {
            size_t start = 0;
            int success = 0;
            int fd = open(partition, O_RDWR);
            if (fd < 0) {
                printf("failed to open %s: %s\n", partition, strerror(errno));
                return -1;
            }
            int attempt;

            for (attempt = 0; attempt < 2; ++attempt) {
                lseek(fd, start, SEEK_SET);
                while (start < len) {
                    size_t to_write = len - start;
                    if (to_write > 1<<20) to_write = 1<<20;

                    ssize_t written = write(fd, data+start, to_write);
                    if (written < 0) {
                        if (errno == EINTR) {
                            written = 0;
                        } else {
                            printf("failed write writing to %s (%s)\n",
                                   partition, strerror(errno));
                            return -1;
                        }
                    }
                    start += written;
                }
                fsync(fd);

                // drop caches so our subsequent verification read
                // won't just be reading the cache.
                sync();
                int dc = open("/proc/sys/vm/drop_caches", O_WRONLY);
                write(dc, "3\n", 2);
                close(dc);
                sleep(1);
                printf("  caches dropped\n");

                // verify
                lseek(fd, 0, SEEK_SET);
                unsigned char buffer[4096];
                start = len;
                size_t p;
                for (p = 0; p < len; p += sizeof(buffer)) {
                    size_t to_read = len - p;
                    if (to_read > sizeof(buffer)) to_read = sizeof(buffer);

                    size_t so_far = 0;
                    while (so_far < to_read) {
                        ssize_t read_count = read(fd, buffer+so_far, to_read-so_far);
                        if (read_count < 0) {
                            if (errno == EINTR) {
                                read_count = 0;
                            } else {
                                printf("verify read error %s at %zu: %s\n",
                                       partition, p, strerror(errno));
                                return -1;
                            }
                        }
                        if ((size_t)read_count < to_read) {
                            printf("short verify read %s at %zu: %zd %zu %s\n",
                                   partition, p, read_count, to_read, strerror(errno));
                        }
                        so_far += read_count;
                    }

                    if (memcmp(buffer, data+p, to_read)) {
                        printf("verification failed starting at %zu\n", p);
                        start = p;
                        break;
                    }
                }

                if (start == len) {
                    printf("verification read succeeded (attempt %d)\n", attempt+1);
                    success = true;
                    break;
                }
            }

            if (!success) {
                printf("failed to verify after all attempts\n");
                return -1;
            }

            if (close(fd) != 0) {
                printf("error closing %s (%s)\n", partition, strerror(errno));
                return -1;
            }
            sync();
            break;
        }
    }

    free(copy);
    return 0;
}
示例#14
0
// Write a memory buffer to 'target' partition, a string of the form
// "MTD:<partition>[:...]" or "EMMC:<partition_device>:".  Return 0 on
// success.
int WriteToPartition(unsigned char* data, size_t len,
                        const char* target) {
    char* copy = strdup(target);
    const char* magic = strtok(copy, ":");

    enum PartitionType type;

#if 0 //wschen 2012-05-24
    if (strcmp(magic, "MTD") == 0) {
        type = MTD;
    } else if (strcmp(magic, "EMMC") == 0) {
        type = EMMC;
    } else {
        printf("WriteToPartition called with bad target (%s)\n", target);
        free(copy);
        return -1;
    }
#else
    switch (phone_type()) {
        case NAND_TYPE:
            type = MTD;
            break;
        case EMMC_TYPE:
            type = EMMC;
            break;
        default:
            printf("WriteToPartition called with bad target (%s)\n", target);
            free(copy);
            return -1;
    }
#endif

    const char* partition = strtok(NULL, ":");

    if (partition == NULL) {
        printf("bad partition target name \"%s\"\n", target);
        free(copy);
        return -1;
    }

    switch (type) {
        case MTD:
            if (!mtd_partitions_scanned) {
                mtd_scan_partitions();
                mtd_partitions_scanned = 1;
            }

            const MtdPartition* mtd = mtd_find_partition_by_name(partition);
            if (mtd == NULL) {
                printf("mtd partition \"%s\" not found for writing\n",
                       partition);
                free(copy);
                return -1;
            }

            MtdWriteContext* ctx = mtd_write_partition(mtd);
            if (ctx == NULL) {
                printf("failed to init mtd partition \"%s\" for writing\n",
                       partition);
                free(copy);
                return -1;
            }

            size_t written = mtd_write_data(ctx, (char*)data, len);
            if (written != len) {
                printf("only wrote %d of %d bytes to MTD %s\n",
                       written, len, partition);
                mtd_write_close(ctx);
                free(copy);
                return -1;
            }

            if (mtd_erase_blocks(ctx, -1) < 0) {
                printf("error finishing mtd write of %s\n", partition);
                mtd_write_close(ctx);
                free(copy);
                return -1;
            }

            if (mtd_write_close(ctx)) {
                printf("error closing mtd write of %s\n", partition);
                free(copy);
                return -1;
            }
            break;

        case EMMC:
            ;
#if 0 //wschen 2011-11-29
            FILE* f = fopen(partition, "wb");
            if (fwrite(data, 1, len, f) != len) {
                printf("short write writing to %s (%s)\n",
                       partition, strerror(errno));
                free(copy);
                return -1;
            }
            if (fclose(f) != 0) {
                printf("error closing %s (%s)\n", partition, strerror(errno));
                free(copy);
                return -1;
            }
#else
            int dev;
            if (!strcmp(partition, "boot")) {
                dev = open("/dev/bootimg", O_RDWR | O_SYNC);
                if (dev == -1) {
                    printf("failed to open emmc partition \"/dev/bootimg\": %s\n", strerror(errno));
                    free(copy);
                    return -1;
                }
            } else {
                char dev_name[32];

                snprintf(dev_name, sizeof(dev_name), "/dev/%s", partition);
                dev = open(dev_name, O_RDWR | O_SYNC);
                if (dev == -1) {
                    printf("failed to open emmc partition \"%s\": %s\n", dev_name, strerror(errno));
                    free(copy);
                    return -1;
                }
            }

            if (write(dev, data, len) != len) {
                printf("short write writing to %s (%s)\n", partition, strerror(errno));
                close(dev);
                free(copy);
                return -1;
            }
            close(dev);
            sync();
#endif
            break;
    }

    free(copy);
    return 0;
}
示例#15
0
int format_volume(const char* volume) {
	if (PartitionManager.Wipe_By_Path(volume))
		return 0;
	else
		return -1;
    Volume* v = volume_for_path(volume);
    if (v == NULL) {
        LOGE("unknown volume \"%s\"\n", volume);
        return -1;
    }
    if (strcmp(v->fs_type, "ramdisk") == 0) {
        // you can't format the ramdisk.
        LOGE("can't format_volume \"%s\"", volume);
        return -1;
    }
    if (strcmp(v->mount_point, volume) != 0) {
        LOGE("can't give path \"%s\" to format_volume\n", volume);
        return -1;
    }

    if (ensure_path_unmounted(volume) != 0) {
        LOGE("format_volume failed to unmount \"%s\"\n", v->mount_point);
        return -1;
    }

    if (strcmp(v->fs_type, "yaffs2") == 0 || strcmp(v->fs_type, "mtd") == 0) {
        mtd_scan_partitions();
        const MtdPartition* partition = mtd_find_partition_by_name(v->device);
        if (partition == NULL) {
            LOGE("format_volume: no MTD partition \"%s\"\n", v->device);
            return -1;
        }

        MtdWriteContext *write = mtd_write_partition(partition);
        if (write == NULL) {
            LOGW("format_volume: can't open MTD \"%s\"\n", v->device);
            return -1;
        } else if (mtd_erase_blocks(write, -1) == (off_t) -1) {
            LOGW("format_volume: can't erase MTD \"%s\"\n", v->device);
            mtd_write_close(write);
            return -1;
        } else if (mtd_write_close(write)) {
            LOGW("format_volume: can't close MTD \"%s\"\n", v->device);
            return -1;
        }
        return 0;
    }

    if (strcmp(v->fs_type, "ext4") == 0) {
#ifdef USE_EXT4
/*
        int result = make_ext4fs(v->device, v->length, volume, sehandle);
*/
        int result = 0;
#else
        int result = 0;
#endif
        if (result != 0) {
            LOGE("format_volume: make_extf4fs failed on %s\n", v->device);
            return -1;
        }
        return 0;
    }

    LOGE("format_volume: fs_type \"%s\" unsupported\n", v->fs_type);
    return -1;
}
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;
}
示例#17
0
// Write a memory buffer to 'target' partition, a string of the form
// "MTD:<partition>[:...]" or "EMMC:<partition_device>:".  Return 0 on
// success.
int WriteToPartition(unsigned char* data, size_t len,
                        const char* target) {
    char* copy = strdup(target);
    const char* magic = strtok(copy, ":");

    enum PartitionType type;
    if (strcmp(magic, "MTD") == 0) {
        type = MTD;
    } else if (strcmp(magic, "EMMC") == 0) {
        type = EMMC;
    } else {
        printf("WriteToPartition called with bad target (%s)\n", target);
        return -1;
    }
    const char* partition = strtok(NULL, ":");

    if (partition == NULL) {
        printf("bad partition target name \"%s\"\n", target);
        return -1;
    }

    switch (type) {
        case MTD:
            if (!mtd_partitions_scanned) {
                mtd_scan_partitions();
                mtd_partitions_scanned = 1;
            }

            const MtdPartition* mtd = mtd_find_partition_by_name(partition);
            if (mtd == NULL) {
                printf("mtd partition \"%s\" not found for writing\n",
                       partition);
                return -1;
            }

            MtdWriteContext* ctx = mtd_write_partition(mtd);
            if (ctx == NULL) {
                printf("failed to init mtd partition \"%s\" for writing\n",
                       partition);
                return -1;
            }

            size_t written = mtd_write_data(ctx, (char*)data, len);
            if (written != len) {
                printf("only wrote %d of %d bytes to MTD %s\n",
                       written, len, partition);
                mtd_write_close(ctx);
                return -1;
            }

            if (mtd_erase_blocks(ctx, -1) < 0) {
                printf("error finishing mtd write of %s\n", partition);
                mtd_write_close(ctx);
                return -1;
            }

            if (mtd_write_close(ctx)) {
                printf("error closing mtd write of %s\n", partition);
                return -1;
            }
            break;

        case EMMC:
            ;
            FILE* f = fopen(partition, "wb");
            if (fwrite(data, 1, len, f) != len) {
                printf("short write writing to %s (%s)\n",
                       partition, strerror(errno));
                return -1;
            }
            if (fclose(f) != 0) {
                printf("error closing %s (%s)\n", partition, strerror(errno));
                return -1;
            }
            break;
    }

    free(copy);
    return 0;
}
示例#18
0
int set_bootloader_message(const struct bootloader_message *in) {
//	INFO("Enter set_bootloader_message\n");
    if(in->command[0] != 0)
    {
    	LOGI("command:\n%s\n", in->command);
    	LOGI("status:\n%s\n", in->status);
    	LOGI("recovery:\n%s\n", in->recovery);
    }
    else
    	LOGI("bootloader_message is empty\n");
    	
    size_t write_size;
    const MtdPartition *part = get_root_mtd_partition(MISC_NAME);
    if (part == NULL || mtd_partition_info(part, NULL, NULL, &write_size)) {
        LOGE("Can't find %s\n", MISC_NAME);
        return -1;
    }

    MtdReadContext *read = mtd_read_partition(part);
    if (read == NULL) {
        LOGE("Can't open %s\n(%s)\n", MISC_NAME, strerror(errno));
        return -1;
    }
//cmy: 以sector为单位
    ssize_t size = write_size * MISC_PAGES;
    char data[size<<9];//cmy
    ssize_t r = mtd_read_data(read, data, size);
    if (r != size) LOGE("Can't read %s\n(%s)\n", MISC_NAME, strerror(errno));
    mtd_read_close(read);
    if (r != size) return -1;

    memcpy(&data[(write_size<<9) * MISC_COMMAND_PAGE], in, sizeof(*in));
	
#ifdef LOG_VERBOSE
    printf("\n--- set_bootloader_message ---\n");
    dump_data(data, size<<9);
    printf("\n");
#endif
//    INFO("\n--- set_bootloader_message ---\n");
//    dump_data(data, size);
//    INFO("\n");

// CMY:由于底层写数据时会自动执行擦除操作,因些我们可以直接写数据而不考虑擦除动作
#if 1
    MtdWriteContext *write = mtd_write_partition(part);
    if (write == NULL) {
        LOGE("Can't open %s\n(%s)\n", MISC_NAME, strerror(errno));
        return -1;
    }
	LOGI("Write bootloader message\n");
    if (mtd_write_data(write, data, size) != size) {
        LOGE("Can't write %s\n(%s)\n", MISC_NAME, strerror(errno));
        mtd_write_close(write);
        return -1;
    }
    if (mtd_write_close(write)) {
        LOGE("Can't finish %s\n(%s)\n", MISC_NAME, strerror(errno));
        return -1;
    }
#endif

    LOGI("Set boot command \"%s\"\n", in->command[0] != 255 ? in->command : "");
    return 0;
}
示例#19
0
// format(type, location)
//
//    type="MTD"  location=partition
Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
    char* result = NULL;
    if (argc != 2) {
        return ErrorAbort(state, "%s() expects 2 args, got %d", name, argc);
    }
    char* type;
    char* location;
    if (ReadArgs(state, argv, 2, &type, &location) < 0) {
        return NULL;
    }

    if (strlen(type) == 0) {
        ErrorAbort(state, "type argument to %s() can't be empty", name);
        goto done;
    }
    if (strlen(location) == 0) {
        ErrorAbort(state, "location argument to %s() can't be empty", name);
        goto done;
    }

    if (strcmp(type, "MTD") == 0) {
#if 0 // 0: rk
        mtd_scan_partitions();
        const MtdPartition* mtd = mtd_find_partition_by_name(location);
        if (mtd == NULL) {
            fprintf(stderr, "%s: no mtd partition named \"%s\"",
                    name, location);
            result = strdup("");
            goto done;
        }
        MtdWriteContext* ctx = mtd_write_partition(mtd);
        if (ctx == NULL) {
            fprintf(stderr, "%s: can't write \"%s\"", name, location);
            result = strdup("");
            goto done;
        }
        if (mtd_erase_blocks(ctx, -1) == -1) {
            mtd_write_close(ctx);
            fprintf(stderr, "%s: failed to erase \"%s\"", name, location);
            result = strdup("");
            goto done;
        }
        if (mtd_write_close(ctx) != 0) {
            fprintf(stderr, "%s: failed to close \"%s\"", name, location);
            result = strdup("");
            goto done;
        }
        result = location;
#else
        mtd_scan_partitions();
        const MtdPartition* mtd = mtd_find_partition_by_name(location);
        if (mtd == NULL) {
            fprintf(stderr, "%s: no mtd partition named \"%s\"",
                    name, location);
            result = strdup("");
            goto done;
        }
        // ext3
        int status = mtd_format_partition(mtd, 0, NULL);
        if (status != 0) {
            fprintf(stderr, "%s: mtd_format_partition failed (%d) on %s",
                    name, status, location);
            result = strdup("");
            goto done;
        }
        result = location;
#endif
    } else {
        fprintf(stderr, "%s: unsupported type \"%s\"", name, type);
    }

done:
    free(type);
    if (result != location) free(location);
    return StringValue(result);
}
示例#20
0
int format_volume(const char* volume) {
    Volume* v = volume_for_path(volume);
    if (v == NULL) {
        // silent failure for sd-ext
        if (strcmp(volume, "/sd-ext") == 0)
            return -1;
        LOGE("unknown volume \"%s\"\n", volume);
        return -1;
    }
    if (is_data_media_volume_path(volume)) {
        return format_unknown_device(NULL, volume, NULL);
    }
    // check to see if /data is being formatted, and if it is /data/media
    // Note: the /sdcard check is redundant probably, just being safe.
    if (strstr(volume, "/data") == volume && is_data_media() && !handle_data_media) {
        return format_unknown_device(NULL, volume, NULL);
    }
    if (strcmp(v->fs_type, "ramdisk") == 0) {
        // you can't format the ramdisk.
        LOGE("can't format_volume \"%s\"", volume);
        return -1;
    }
    if (strcmp(v->mount_point, volume) != 0) {
#if 0
        LOGE("can't give path \"%s\" to format_volume\n", volume);
        return -1;
#endif
        return format_unknown_device(v->device, volume, NULL);
    }

    if (ensure_path_unmounted(volume) != 0) {
        LOGE("format_volume failed to unmount \"%s\"\n", v->mount_point);
        return -1;
    }

    if (strcmp(v->fs_type, "yaffs2") == 0 || strcmp(v->fs_type, "mtd") == 0) {
        mtd_scan_partitions();
        const MtdPartition* partition = mtd_find_partition_by_name(v->device);
        if (partition == NULL) {
            LOGE("format_volume: no MTD partition \"%s\"\n", v->device);
            return -1;
        }

        MtdWriteContext *write = mtd_write_partition(partition);
        if (write == NULL) {
            LOGW("format_volume: can't open MTD \"%s\"\n", v->device);
            return -1;
        } else if (mtd_erase_blocks(write, -1) == (off_t) -1) {
            LOGW("format_volume: can't erase MTD \"%s\"\n", v->device);
            mtd_write_close(write);
            return -1;
        } else if (mtd_write_close(write)) {
            LOGW("format_volume: can't close MTD \"%s\"\n", v->device);
            return -1;
        }
        return 0;
    }

    if (strcmp(v->fs_type, "ext4") == 0) {
        int result = make_ext4fs(v->device, v->length, volume, sehandle);
        if (result != 0) {
            LOGE("format_volume: make_extf4fs failed on %s\n", v->device);
            return -1;
        }
        return 0;
    }

#if 0
    LOGE("format_volume: fs_type \"%s\" unsupported\n", v->fs_type);
    return -1;
#endif
    return format_unknown_device(v->device, volume, v->fs_type);
}
示例#21
0
int format_volume(const char* volume) {
    Volume* v = volume_for_path(volume);
    if (v == NULL) {
        LOGE("unknown volume \"%s\"\n", volume);
        return -1;
    }
    if (strcmp(v->fs_type, "ramdisk") == 0) {
        // you can't format the ramdisk.
        LOGE("can't format_volume \"%s\"", volume);
        return -1;
    }
    if (strcmp(v->mount_point, volume) != 0) {
        LOGE("can't give path \"%s\" to format_volume\n", volume);
        return -1;
    }

    if (ensure_path_unmounted(volume) != 0) {
        LOGE("format_volume failed to unmount \"%s\"\n", v->mount_point);
        return -1;
    }

    if (strcmp(v->fs_type, "yaffs2") == 0 || strcmp(v->fs_type, "mtd") == 0) {
        mtd_scan_partitions();
        const MtdPartition* partition = mtd_find_partition_by_name(v->blk_device);
        if (partition == NULL) {
            LOGE("format_volume: no MTD partition \"%s\"\n", v->blk_device);
            return -1;
        }

        MtdWriteContext *write = mtd_write_partition(partition);
        if (write == NULL) {
            LOGW("format_volume: can't open MTD \"%s\"\n", v->blk_device);
            return -1;
        } else if (mtd_erase_blocks(write, -1) == (off_t) -1) {
            LOGW("format_volume: can't erase MTD \"%s\"\n", v->blk_device);
            mtd_write_close(write);
            return -1;
        } else if (mtd_write_close(write)) {
            LOGW("format_volume: can't close MTD \"%s\"\n", v->blk_device);
            return -1;
        }
        return 0;
    }

    if (strcmp(v->fs_type, "ext4") == 0 || strcmp(v->fs_type, "f2fs") == 0) {
        // if there's a key_loc that looks like a path, it should be a
        // block device for storing encryption metadata.  wipe it too.
        if (v->key_loc != NULL && v->key_loc[0] == '/') {
            LOGI("wiping %s\n", v->key_loc);
            int fd = open(v->key_loc, O_WRONLY | O_CREAT, 0644);
            if (fd < 0) {
                LOGE("format_volume: failed to open %s\n", v->key_loc);
                return -1;
            }
            wipe_block_device(fd, get_file_size(fd));
            close(fd);
        }

        ssize_t length = 0;
        if (v->length != 0) {
            length = v->length;
        } else if (v->key_loc != NULL && strcmp(v->key_loc, "footer") == 0) {
            length = -CRYPT_FOOTER_OFFSET;
        }
        int result;
        if (strcmp(v->fs_type, "ext4") == 0) {
            result = make_ext4fs(v->blk_device, length, volume, sehandle);
        } else {   /* Has to be f2fs because we checked earlier. */
            if (v->key_loc != NULL && strcmp(v->key_loc, "footer") == 0 && length < 0) {
                LOGE("format_volume: crypt footer + negative length (%zd) not supported on %s\n", length, v->fs_type);
                return -1;
            }
            if (length < 0) {
                LOGE("format_volume: negative length (%zd) not supported on %s\n", length, v->fs_type);
                return -1;
            }
            char *num_sectors;
            if (asprintf(&num_sectors, "%zd", length / 512) <= 0) {
                LOGE("format_volume: failed to create %s command for %s\n", v->fs_type, v->blk_device);
                return -1;
            }
            const char *f2fs_path = "/sbin/mkfs.f2fs";
            const char* const f2fs_argv[] = {"mkfs.f2fs", "-t", "-d1", v->blk_device, num_sectors, NULL};

            result = exec_cmd(f2fs_path, (char* const*)f2fs_argv);
            free(num_sectors);
        }
        if (result != 0) {
            LOGE("format_volume: make %s failed on %s with %d(%s)\n", v->fs_type, v->blk_device, result, strerror(errno));
            return -1;
        }
        return 0;
    }

    LOGE("format_volume: fs_type \"%s\" unsupported\n", v->fs_type);
    return -1;
}
void wipe_data(int confirm) {
    if (confirm) {
        static char** title_headers = NULL;

        if (title_headers == NULL) {
            char* headers[] = { "Confirm wipe of all user data?",
                                "  THIS CAN NOT BE UNDONE.",
                                "",
                                NULL };
            title_headers = prepend_title((const char**)headers);
        }

        char* items[] = { " No",
#if TARGET_BOOTLOADER_BOARD_NAME == otter
                          " Yes -- delete all user data",   // [1]
#else
                          " No",
                          " No",
                          " No",
                          " No",
                          " No",
                          " No",
                          " Yes -- delete all user data",   // [7]
                          " No",
                          " No",
                          " No",
#endif
                          NULL };

        int chosen_item = get_menu_selection(title_headers, items, 1, 0);
#if TARGET_BOOTLOADER_BOARD_NAME == otter
        if (chosen_item != 1) {
#else
        if (chosen_itme != 7) {
#endif
            return;
        }
    }

    ui_print("\n-- Wiping data...\n");
    device_wipe_data();
    erase_volume("/data");
    erase_volume("/cache");
    if (has_datadata()) {
        erase_volume("/datadata");
    }
#if TARGET_BOOTLOADER_BOARD_NAME != otter	// ToDo: make this check for the partition rather then the device
    erase_volume("/sd-ext");
#endif
    erase_volume("/sdcard/.android_secure");
    ui_print("%s\n", datawipecomplete);
}

void erase_cache(int orscallback) {
    if(orscallback) {
	if(orswipeprompt && !confirm_selection("Confirm wipe?","Yes - Wipe Cache")) {
	    ui_print("Skipping cache wipe...\n");
	    return;
	}
    } else if (!confirm_selection("Confirm wipe?", "Yes - Wipe Cache")) {
	return;
    }
    ui_print("\n-- Wiping cache...\n");
    erase_volume("/cache");
    ui_print("%s\n", cachewipecomplete);
    if (!ui_text_visible()) return;
}

void erase_dalvik_cache(int orscallback) {
    if(orscallback) {
	if(orswipeprompt && !confirm_selection("Confirm wipe?", "Yes - Wipe Dalvik Cache")) {
	    ui_print("Skipping dalvik cache wipe...\n");
	    return;
	}
    } else if (!confirm_selection( "Confirm wipe?", "Yes - Wipe Dalvik Cache")) {
	return;
    }
    if (0 != ensure_path_mounted("/data")) {
	return;
    }
#if TARGET_BOOTLOADER_BOARD_NAME != otter
    ensure_path_mounted("/sd-ext");
#endif
    ensure_path_mounted("/cache");
    
    __system("rm -r /data/dalvik-cache");
    __system("rm -r /cache/dalvik-cache");
#if TARGET_BOOTLOADER_BOARD_NAME != otter
    __system("rm -r /sd-ext/dalvik-cache");
#endif
    ui_print("Dalvik Cache wiped.\n");
    
    ensure_path_unmounted("/data");
}

void wipe_all(int orscallback) {
    if(orscallback) {
	if(orswipeprompt && !confirm_selection("Confirm wipe all?", "Yes - Wipe All")) {
	    ui_print("Skipping full wipe...\n");
	    return;
	}
    } else if (!confirm_selection("Confirm wipe all?", "Yes - Wipe All")) {
	return;
    }
    ui_print("\n-- Wiping system, data, cache...\n");
    erase_volume("/system");
    erase_volume("/data");
    erase_volume("/cache");
    ui_print("\nFull wipe complete!\n");
    if (!ui_text_visible()) return;
}

int format_device(const char *device, const char *path, const char *fs_type) {
    Volume* v = volume_for_path(path);
    if (v == NULL) {
        // no /sdcard? let's assume /data/media
        if (strstr(path, "/sdcard") == path && is_data_media()) {
            return format_unknown_device(NULL, path, NULL);
        }
        // silent failure for sd-ext
        if (strcmp(path, "/sd-ext") == 0)
            return -1;
        LOGE("unknown volume \"%s\"\n", path);
        return -1;
    }
    if (strcmp(fs_type, "ramdisk") == 0) {
        // you can't format the ramdisk.
        LOGE("can't format_volume \"%s\"", path);
        return -1;
    }

    if (strcmp(fs_type, "rfs") == 0) {
        if (ensure_path_unmounted(path) != 0) {
            LOGE("format_volume failed to unmount \"%s\"\n", v->mount_point);
            return -1;
        }
        if (0 != format_rfs_device(device, path)) {
            LOGE("format_volume: format_rfs_device failed on %s\n", device);
            return -1;
        }
        return 0;
    }

    if (strcmp(v->mount_point, path) != 0) {
        return format_unknown_device(v->device, path, NULL);
    }

    if (ensure_path_unmounted(path) != 0) {
        LOGE("format_volume failed to unmount \"%s\"\n", v->mount_point);
        return -1;
    }

    if (strcmp(fs_type, "yaffs2") == 0 || strcmp(fs_type, "mtd") == 0) {
        mtd_scan_partitions();
        const MtdPartition* partition = mtd_find_partition_by_name(device);
        if (partition == NULL) {
            LOGE("format_volume: no MTD partition \"%s\"\n", device);
            return -1;
        }

        MtdWriteContext *write = mtd_write_partition(partition);
        if (write == NULL) {
            LOGW("format_volume: can't open MTD \"%s\"\n", device);
            return -1;
        } else if (mtd_erase_blocks(write, -1) == (off_t) -1) {
            LOGW("format_volume: can't erase MTD \"%s\"\n", device);
            mtd_write_close(write);
            return -1;
        } else if (mtd_write_close(write)) {
            LOGW("format_volume: can't close MTD \"%s\"\n",device);
            return -1;
        }
        return 0;
    }

    if (strcmp(fs_type, "ext4") == 0) {
        int length = 0;
        if (strcmp(v->fs_type, "ext4") == 0) {
            // Our desired filesystem matches the one in fstab, respect v->length
            length = v->length;
        }
        reset_ext4fs_info();
        int result = make_ext4fs(device, length, v->mount_point, sehandle);
        if (result != 0) {
            LOGE("format_volume: make_extf4fs failed on %s\n", device);
            return -1;
        }
        return 0;
    }

    return format_unknown_device(device, path, fs_type);
}
示例#23
0
int format_root_device(const char *root)
{
    /* See if this root is already mounted. */
    const MountedVolume *volume;
    char *filesystem;
    char *device;
    int ret = scan_mounted_volumes();
    if (ret < 0)
    {
        LOGD(TAG "format_root_device: load mount info fail\n", root);
        return false;
    }
    
    volume = find_mounted_volume_by_mount_point(root);
    if (volume == NULL)
    {
        LOGD(TAG "The path %s is unmounted\n", root);
        return 0;
    }
    filesystem = strdup(volume->filesystem);
    device = strdup(volume->device);
    ret = unmount_mounted_volume(volume);
    if (ret < 0) 
    {
        LOGD(TAG "format_root_device: can't unmount \"%s\"\n", root);
        return false;
    }
    LOGD(TAG "format_root_device : unmount %s scucess, type is %s\n", root, filesystem);

    if (!strcmp(filesystem, "yaffs2"))
    {
        LOGD(TAG "format yaffs2 partitions\n", root);
    /* Format the device. */
    mtd_scan_partitions();
    const MtdPartition *partition = NULL;

    if(!strcmp(root, DATA_PARTITION))
    {
        LOGD(TAG "find the partition name is %s", root);
        partition = mtd_find_partition_by_name("userdata");
    }
    
    if (partition == NULL) 
    {
        LOGD(TAG "format_root_device: can't find mtd partition \"%s\"\n", root);
        return false;
    }
    
    MtdWriteContext *write = mtd_write_partition(partition);
    
    if (write == NULL) 
    {
        LOGD(TAG "format_root_device: can't open \"%s\"\n", root);
        return false;
        } else if (mtd_erase_blocks(write, -1) == (off_t) - 1)
    {
        LOGD(TAG "format_root_device: can't erase \"%s\"\n", root);
        mtd_write_close(write);
        return false;
        } else if (mtd_write_close(write))
        {
            LOGD(TAG "format_root_device: can't close \"%s\"\n", root);
            return false;
        } else
        {
            ret= true;
        }
    } else
    {
        if (!strcmp(filesystem, "ubifs"))
        {
            int ubi_num = -1, ubi_dev;
            int mtd_num = -1;
            char path[128];
            char mtd_dev_name[128];
            const char *binary_path = "/system/bin/ubiformat";

            sscanf(device, "/dev/ubi%d_0", &ubi_num);
            if (ubi_num >= 0 && ubi_num <= 32)
            {
                LOGD(TAG "format_root_device: detach ubi device /dev/ubi%d_0\n", ubi_num);
            } else
            {
                LOGD(TAG "Can not find parse ubi num :%s\n", device);
                return false;
            }
            sprintf(path, "/sys/class/ubi/ubi%d/mtd_num", ubi_num);
            ubi_dev = open(path, O_RDONLY);
            if (ubi_dev != -1)
            {
                ret = read(ubi_dev, path, sizeof(path));
                close(ubi_dev);
                if (ret > 0)
                {
                    mtd_num = atoi(path);
                    LOGD(TAG "  %s mtd_num is %d \n", device, mtd_num);
                    sprintf(mtd_dev_name, "/dev/mtd/mtd%d", mtd_num);
                } else
                {
                    LOGD(TAG " read %s fail! \n", path);
                    return false;
                }
            } else
            {
                LOGD(TAG " open %s fail! \n", path);
                return false;
            }

            ret = ubi_detach_dev(ubi_num);
            if (ret != 0)
            {
                LOGD(TAG "format_root_device: detach ubi device /dev/ubi%d_0 fail!ret=%d\n", ubi_num, ret);
                return false;
            }
            //int check;
            //check = chmod(binary_path, 0777);
            //printf("chmod = %d\n", check);

            const char **args = (const char **)malloc(sizeof(char *) * 3);
            args[0] = binary_path;
            args[1] = mtd_dev_name;
            args[2] = NULL;

            pid_t pid = fork();
            if (pid == 0)
            {
                execv(binary_path, (char *const *)args);
                fprintf(stdout, "E:Can't run %s (%s)\n", binary_path, strerror(errno));
                _exit(-1);
    }

            int status;
            waitpid(pid, &status, 0);

            if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
    {
                LOGE("Error in ubiformat\n(Status %d)\n", WEXITSTATUS(status));
        return false;
    }

           ret=true;

        } else
    {
            LOGD(TAG "format_root_device : unsupport filesystem %s\n", filesystem);
            return false;
    }    
    
    }
    free(filesystem);
    free(device);    
    return ret;
}
示例#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;
}
示例#25
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;
}
示例#26
0
int format_volume(const char* volume) {
    Volume* v = volume_for_path(volume);
    if (v == NULL) {
        // no /sdcard? let's assume /data/media
        if (strstr(volume, "/sdcard") == volume && is_data_media()) {
            return format_unknown_device(NULL, volume, NULL);
        }
        // silent failure for sd-ext
        if (strcmp(volume, "/sd-ext") == 0)
            return -1;
        LOGE("unknown volume \"%s\"\n", volume);
        return -1;
    }
    if (strcmp(v->fs_type, "ramdisk") == 0) {
        // you can't format the ramdisk.
        LOGE("can't format_volume \"%s\"", volume);
        return -1;
    }
    if (strcmp(v->mount_point, volume) != 0) {
#if 0
        LOGE("can't give path \"%s\" to format_volume\n", volume);
        return -1;
#endif
        return format_unknown_device(v->device, volume, NULL);
    }

    if (ensure_path_unmounted(volume) != 0) {
        LOGE("format_volume failed to unmount \"%s\"\n", v->mount_point);
        return -1;
    }

    if (strcmp(v->fs_type, "yaffs2") == 0 || strcmp(v->fs_type, "mtd") == 0) {
        mtd_scan_partitions();
        const MtdPartition* partition = mtd_find_partition_by_name(v->device);
        if (partition == NULL) {
            LOGE("format_volume: no MTD partition \"%s\"\n", v->device);
            return -1;
        }

        MtdWriteContext *write = mtd_write_partition(partition);
//        MtdWriteContext *write = mtd_write_partition(v->device);
        if (write == NULL) {
            LOGW("format_volume: can't open MTD \"%s\"\n", v->device);
            return -1;
        } else if (mtd_erase_blocks(write, -1) == (off_t) -1) {
            LOGW("format_volume: can't erase MTD \"%s\"\n", v->device);
            mtd_write_close(write);
            return -1;
        } else if (mtd_write_close(write)) {
            LOGW("format_volume: can't close MTD \"%s\"\n", v->device);
            return -1;
        }
        return 0;
    }

    if (strcmp(v->fs_type, "ext4") == 0) {
        reset_ext4fs_info();
        int result = make_ext4fs(v->device, NULL, NULL, 0, 0, 0);
        if (result != 0) {
            LOGE("format_volume: make_extf4fs failed on %s\n", v->device);
            return -1;
        }
        return 0;
    }

#if 0
    LOGE("format_volume: fs_type \"%s\" unsupported\n", v->fs_type);
    return -1;
#endif
    return format_unknown_device(v->device, volume, v->fs_type);
}
示例#27
0
// format(fs_type, partition_type, location, fs_size, mount_point)
//
//    fs_type="yaffs2" partition_type="MTD"     location=partition fs_size=<bytes> mount_point=<location>
//    fs_type="ext4"   partition_type="EMMC"    location=device    fs_size=<bytes> mount_point=<location>
//    if fs_size == 0, then make_ext4fs uses the entire partition.
//    if fs_size > 0, that is the size to use
//    if fs_size < 0, then reserve that many bytes at the end of the partition
Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
    char* result = NULL;
    if (argc != 5) {
        return ErrorAbort(state, "%s() expects 5 args, got %d", name, argc);
    }
    char* fs_type;
    char* partition_type;
    char* location;
    char* fs_size;
    char* mount_point;

    if (ReadArgs(state, argv, 5, &fs_type, &partition_type, &location, &fs_size, &mount_point) < 0) {
        return NULL;
    }

    if (strlen(fs_type) == 0) {
        ErrorAbort(state, "fs_type argument to %s() can't be empty", name);
        goto done;
    }
    if (strlen(partition_type) == 0) {
        ErrorAbort(state, "partition_type argument to %s() can't be empty",
                   name);
        goto done;
    }
    if (strlen(location) == 0) {
        ErrorAbort(state, "location argument to %s() can't be empty", name);
        goto done;
    }

    if (strlen(mount_point) == 0) {
        ErrorAbort(state, "mount_point argument to %s() can't be empty", name);
        goto done;
    }

    if (strcmp(partition_type, "MTD") == 0) {
        mtd_scan_partitions();
        const MtdPartition* mtd = mtd_find_partition_by_name(location);
        if (mtd == NULL) {
            fprintf(stderr, "%s: no mtd partition named \"%s\"",
                    name, location);
            result = strdup("");
            goto done;
        }
        MtdWriteContext* ctx = mtd_write_partition(mtd);
        if (ctx == NULL) {
            fprintf(stderr, "%s: can't write \"%s\"", name, location);
            result = strdup("");
            goto done;
        }
        if (mtd_erase_blocks(ctx, -1) == -1) {
            mtd_write_close(ctx);
            fprintf(stderr, "%s: failed to erase \"%s\"", name, location);
            result = strdup("");
            goto done;
        }
        if (mtd_write_close(ctx) != 0) {
            fprintf(stderr, "%s: failed to close \"%s\"", name, location);
            result = strdup("");
            goto done;
        }
        result = location;
#ifdef USE_EXT4
    } else if (strcmp(fs_type, "ext4") == 0) {
        int status = make_ext4fs(location, atoll(fs_size), mount_point, sehandle);
        if (status != 0) {
            fprintf(stderr, "%s: make_ext4fs failed (%d) on %s",
                    name, status, location);
            result = strdup("");
            goto done;
        }
        result = location;
#endif
    } else {
        fprintf(stderr, "%s: unsupported fs_type \"%s\" partition_type \"%s\"",
                name, fs_type, partition_type);
    }

done:
    free(fs_type);
    free(partition_type);
    if (result != location) free(location);
    return StringValue(result);
}
/* Read an image file and write it to a flash partition. */
int main(int argc, char **argv) {
    const MtdPartition *ptn;
    MtdWriteContext *write;
    void *data;
    unsigned sz;
    int i;
    char *partitionName = NULL, *imageFile = NULL;
    int deleteImage = 0;

    if (argc < 3) {
		printUsage(argv[0]);
        return 2;
    }

	partitionName = argv[1];
	imageFile = argv[2];

	if (partitionName == NULL || imageFile == NULL) {
		printUsage(argv[0]);
		return 2;
	}



    if (mtd_scan_partitions() <= 0) die("error scanning partitions");
    const MtdPartition *partition = mtd_find_partition_by_name(partitionName);
    if (partition == NULL) die("can't find %s partition", partitionName);

    // If the first part of the file matches the partition, skip writing

    int fd = open(imageFile, O_RDONLY);
    if (fd < 0) die("error opening %s", imageFile);

    char header[HEADER_SIZE];
    int headerlen = read(fd, header, sizeof(header));
    if (headerlen <= 0) die("error reading %s header", imageFile);

    MtdReadContext *in = mtd_read_partition(partition);
    if (in == NULL) {
        LOGW("error opening %s: %s\n", partitionName, 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) {
            LOGW("error reading %s: %s\n", partitionName, strerror(errno));
            // just assume it needs re-writing
        } else if (checklen == headerlen && !memcmp(header, check, headerlen)) {
            LOGI("header is the same, not flashing %s\n", argv[1]);
            if (deleteImage)
				unlink(imageFile);
            return 0;
        }
        mtd_read_close(in);
    }

    // Skip the header (we'll come back to it), write everything else
    LOGI("flashing %s from %s\n", partitionName, imageFile);

    MtdWriteContext *out = mtd_write_partition(partition);
    if (out == NULL) die("error writing %s", partitionName);

    char buf[HEADER_SIZE];
    memset(buf, 0, headerlen);
    int wrote = mtd_write_data(out, buf, headerlen);
    if (wrote != headerlen) die("error writing %s", partitionName);

    int len;
    while ((len = read(fd, buf, sizeof(buf))) > 0) {
        wrote = mtd_write_data(out, buf, len);
        if (wrote != len) die("error writing %s", partitionName);
    }
    if (len < 0) die("error reading %s", imageFile);

    if (mtd_write_close(out)) die("error closing %s", partitionName);

    // Now come back and write the header last

    out = mtd_write_partition(partition);
    if (out == NULL) die("error re-opening %s", partitionName);

    wrote = mtd_write_data(out, header, headerlen);
    if (wrote != headerlen) die("error re-writing %s", partitionName);

    // 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))
        die("error getting %s block size", partitionName);

    if (lseek(fd, headerlen, SEEK_SET) != headerlen)
        die("error rewinding %s", imageFile);

    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) die("error reading %s", imageFile);
        if (mtd_write_data(out, buf, len) != len)
            die("error writing %s", partitionName);
        left -= len;
    }

    if (mtd_write_close(out)) die("error closing %s", partitionName);

	if (deleteImage)
		unlink(imageFile);

    return 0;
}
int format_device(const char *device, const char *path, const char *fs_type) {
    Volume* v = volume_for_path(path);
    if (v == NULL) {
        // silent failure for sd-ext
        if (strcmp(path, "/sd-ext") == 0)
            return -1;
        LOGE("unknown volume \"%s\"\n", path);
        return -1;
    }
    if (is_data_media_volume_path(path)) {
        return format_unknown_device(NULL, path, NULL);
    }
    if (strstr(path, "/data") == path && is_data_media()) {
        return format_unknown_device(NULL, path, NULL);
    }
    if (strcmp(fs_type, "ramdisk") == 0) {
        // you can't format the ramdisk.
        LOGE("can't format_volume \"%s\"", path);
        return -1;
    }

    if (strcmp(fs_type, "rfs") == 0) {
        if (ensure_path_unmounted(path) != 0) {
            LOGE("format_volume failed to unmount \"%s\"\n", v->mount_point);
            return -1;
        }
        if (0 != format_rfs_device(device, path)) {
            LOGE("format_volume: format_rfs_device failed on %s\n", device);
            return -1;
        }
        return 0;
    }
 
    if (strcmp(v->mount_point, path) != 0) {
        return format_unknown_device(v->device, path, NULL);
    }

    if (ensure_path_unmounted(path) != 0) {
        LOGE("format_volume failed to unmount \"%s\"\n", v->mount_point);
        return -1;
    }

    if (strcmp(fs_type, "yaffs2") == 0 || strcmp(fs_type, "mtd") == 0) {
        mtd_scan_partitions();
        const MtdPartition* partition = mtd_find_partition_by_name(device);
        if (partition == NULL) {
            LOGE("format_volume: no MTD partition \"%s\"\n", device);
            return -1;
        }

        MtdWriteContext *write = mtd_write_partition(partition);
        if (write == NULL) {
            LOGW("format_volume: can't open MTD \"%s\"\n", device);
            return -1;
        } else if (mtd_erase_blocks(write, -1) == (off_t) -1) {
            LOGW("format_volume: can't erase MTD \"%s\"\n", device);
            mtd_write_close(write);
            return -1;
        } else if (mtd_write_close(write)) {
            LOGW("format_volume: can't close MTD \"%s\"\n",device);
            return -1;
        }
        return 0;
    }

    if (strcmp(fs_type, "ext4") == 0) {
        int length = 0;
        if (strcmp(v->fs_type, "ext4") == 0) {
            // Our desired filesystem matches the one in fstab, respect v->length
            length = v->length;
        }
        reset_ext4fs_info();
        int result = make_ext4fs(device, length, v->mount_point, sehandle);
        if (result != 0) {
            LOGE("format_volume: make_extf4fs failed on %s\n", device);
            return -1;
        }
        return 0;
    }

    return format_unknown_device(device, path, fs_type);
}
示例#30
0
int
cmd_mtd_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;
}