static void goldfish_mmc_do_command(struct goldfish_mmc_state *s, uint32_t cmd, uint32_t arg) { int result; int new_status = MMC_STAT_END_OF_CMD; int opcode = cmd & 63; s->resp[0] = 0; s->resp[1] = 0; s->resp[2] = 0; s->resp[3] = 0; #define SET_R1_CURRENT_STATE(s) ((s << 9) & 0x00001E00) switch (opcode) { case MMC_SEND_CSD: { int64_t sector_count = 0; uint64_t capacity; uint8_t exponent; uint32_t m; bdrv_get_geometry(s->bs, (uint64_t*)§or_count); capacity = sector_count * 512; if (capacity > 2147483648U) { s->is_SDHC = 1; s->resp[3] = 0x400E0032; s->resp[2] = 0x5B590000; s->resp[1] = 0x00007F80; s->resp[0] = 0x0A4040DF; m = (uint32_t)(capacity / (512*1024)) - 1; if (m & 0xFFC00000) { fprintf(stderr, "SD card too big (%lld bytes). Maximum SDHC card size is 128 gigabytes.\n", (long long)capacity); abort(); } s->resp[1] |= ((m & 0x0000FFFF) << 16); s->resp[2] |= (m >> 16); } else { s->is_SDHC = 0; s->resp[3] = 0x00260032; s->resp[2] = 0x5F5A8000; s->resp[1] = 0x3EF84FFF; s->resp[0] = 0x928040CB; exponent = 0; capacity = sector_count * 512; if (capacity > 2147483648U) { fprintf(stderr, "SD card too big (%lld bytes). Maximum SD card size is 2 gigabytes.\n", (long long)capacity); abort(); } capacity >>= 10; while (capacity > 4096) { exponent++; capacity >>= 1; } capacity -= 1; if (exponent < 2) { cpu_abort(cpu_single_env, "SDCard too small, must be at least 9MB\n"); } exponent -= 2; if (exponent > 7) { cpu_abort(cpu_single_env, "SDCard too large.\n"); } s->resp[2] |= (((uint32_t)capacity >> 2) & 0x3FF); s->resp[1] |= (((uint32_t)capacity & 3) << 30); s->resp[1] |= (exponent << (47 - 32)); } break; }
static int img_create(int argc, char **argv) { int c, ret, flags; const char *fmt = "raw"; const char *base_fmt = NULL; const char *filename; const char *base_filename = NULL; BlockDriver *drv; QEMUOptionParameter *param = NULL; char *options = NULL; flags = 0; for(;;) { c = getopt(argc, argv, "F:b:f:he6o:"); if (c == -1) break; switch(c) { case 'h': help(); break; case 'F': base_fmt = optarg; break; case 'b': base_filename = optarg; break; case 'f': fmt = optarg; break; case 'e': flags |= BLOCK_FLAG_ENCRYPT; break; case '6': flags |= BLOCK_FLAG_COMPAT6; break; case 'o': options = optarg; break; } } /* Find driver and parse its options */ drv = bdrv_find_format(fmt); if (!drv) error("Unknown file format '%s'", fmt); if (options && !strcmp(options, "?")) { print_option_help(drv->create_options); return 0; } /* Create parameter list with default values */ param = parse_option_parameters("", drv->create_options, param); set_option_parameter_int(param, BLOCK_OPT_SIZE, -1); /* Parse -o options */ if (options) { param = parse_option_parameters(options, drv->create_options, param); if (param == NULL) { error("Invalid options for file format '%s'.", fmt); } } /* Get the filename */ if (optind >= argc) help(); filename = argv[optind++]; /* Add size to parameters */ if (optind < argc) { set_option_parameter(param, BLOCK_OPT_SIZE, argv[optind++]); } /* Add old-style options to parameters */ add_old_style_options(fmt, param, flags, base_filename, base_fmt); // The size for the image must always be specified, with one exception: // If we are using a backing file, we can obtain the size from there if (get_option_parameter(param, BLOCK_OPT_SIZE)->value.n == -1) { QEMUOptionParameter *backing_file = get_option_parameter(param, BLOCK_OPT_BACKING_FILE); QEMUOptionParameter *backing_fmt = get_option_parameter(param, BLOCK_OPT_BACKING_FMT); if (backing_file && backing_file->value.s) { BlockDriverState *bs; uint64_t size; const char *fmt = NULL; char buf[32]; if (backing_fmt && backing_fmt->value.s) { if (bdrv_find_format(backing_fmt->value.s)) { fmt = backing_fmt->value.s; } else { error("Unknown backing file format '%s'", backing_fmt->value.s); } } bs = bdrv_new_open(backing_file->value.s, fmt, BDRV_O_FLAGS); bdrv_get_geometry(bs, &size); size *= 512; bdrv_delete(bs); snprintf(buf, sizeof(buf), "%" PRId64, size); set_option_parameter(param, BLOCK_OPT_SIZE, buf); } else { error("Image creation needs a size parameter"); } } printf("Formatting '%s', fmt=%s ", filename, fmt); print_option_parameters(param); puts(""); ret = bdrv_create(drv, filename, param); free_option_parameters(param); if (ret < 0) { if (ret == -ENOTSUP) { error("Formatting or formatting option not supported for file format '%s'", fmt); } else if (ret == -EFBIG) { error("The image size is too large for file format '%s'", fmt); } else { error("%s: error while creating %s: %s", filename, fmt, strerror(-ret)); } } return 0; }
void nand_add_dev(const char *arg) { uint64_t dev_size = 0; const char *next_arg; const char *value; size_t arg_len, value_len; nand_dev *new_devs, *dev; char *devname = NULL; size_t devname_len = 0; char *initfilename = NULL; char *rwfilename = NULL; int initfd = -1; int rwfd = -1; int read_only = 0; int pad; ssize_t read_size; uint32_t page_size = 2048; uint32_t extra_size = 64; uint32_t erase_pages = 64; //VERBOSE_PRINT(init, "%s: %s", __FUNCTION__, arg); while(arg) { next_arg = strchr(arg, ','); value = strchr(arg, '='); if(next_arg != NULL) { arg_len = next_arg - arg; next_arg++; if(value >= next_arg) value = NULL; } else arg_len = strlen(arg); if(value != NULL) { size_t new_arg_len = value - arg; value_len = arg_len - new_arg_len - 1; arg_len = new_arg_len; value++; } else value_len = 0; if(devname == NULL) { if(value != NULL) goto bad_arg_and_value; devname_len = arg_len; devname = malloc(arg_len+1); if(devname == NULL) goto out_of_memory; memcpy(devname, arg, arg_len); devname[arg_len] = 0; } else if(value == NULL) { if(arg_match("readonly", arg, arg_len)) { read_only = 1; } else { XLOG("bad arg: %.*s\n", arg_len, arg); exit(1); } } else { if(arg_match("size", arg, arg_len)) { char *ep; dev_size = strtoull(value, &ep, 0); D("Dev size 0x%X came from argument\n", dev_size); if(ep != value + value_len) goto bad_arg_and_value; } else if(arg_match("pagesize", arg, arg_len)) { char *ep; page_size = strtoul(value, &ep, 0); if(ep != value + value_len) goto bad_arg_and_value; } else if(arg_match("extrasize", arg, arg_len)) { char *ep; extra_size = strtoul(value, &ep, 0); if(ep != value + value_len) goto bad_arg_and_value; } else if(arg_match("erasepages", arg, arg_len)) { char *ep; erase_pages = strtoul(value, &ep, 0); if(ep != value + value_len) goto bad_arg_and_value; } else if(arg_match("initfile", arg, arg_len)) { initfilename = malloc(value_len + 1); if(initfilename == NULL) goto out_of_memory; memcpy(initfilename, value, value_len); initfilename[value_len] = '\0'; } else if(arg_match("file", arg, arg_len)) { rwfilename = malloc(value_len + 1); if(rwfilename == NULL) goto out_of_memory; memcpy(rwfilename, value, value_len); rwfilename[value_len] = '\0'; } else { goto bad_arg_and_value; } } arg = next_arg; } if (rwfilename == NULL) { /* we create a temporary file to store everything */ TempFile* tmp = tempfile_create(); if (tmp == NULL) { XLOG("could not create temp file for %.*s NAND disk image: %s\n", devname_len, devname, strerror(errno)); exit(1); } rwfilename = (char*) tempfile_path(tmp); // if (VERBOSE_CHECK(init)) // dprint( "mapping '%.*s' NAND image to %s", devname_len, devname, rwfilename); } if(rwfilename) { rwfd = open(rwfilename, O_BINARY | (read_only ? O_RDONLY : O_RDWR)); if(rwfd < 0) { XLOG("could not open file %s, %s\n", rwfilename, strerror(errno)); exit(1); } /* this could be a writable temporary file. use atexit_close_fd to ensure * that it is properly cleaned up at exit on Win32 */ if (!read_only) atexit_close_fd(rwfd); } if(initfilename) { uint64_t dev_bigger; initfd = open(initfilename, O_BINARY | O_RDONLY); if(initfd < 0) { XLOG("could not open file %s, %s\n", initfilename, strerror(errno)); exit(1); } //if(dev_size == 0) { D("calculating dev_size from lseek of %s\n", initfilename); dev_bigger = do_lseek(initfd, 0, SEEK_END); do_lseek(initfd, 0, SEEK_SET); if (dev_bigger > dev_size) { dev_size = dev_bigger; } } new_devs = realloc(nand_devs, sizeof(nand_devs[0]) * (nand_dev_count + 1)); if(new_devs == NULL) goto out_of_memory; nand_devs = new_devs; dev = &new_devs[nand_dev_count]; dev->page_size = page_size; dev->extra_size = extra_size; dev->erase_size = erase_pages * (page_size + extra_size); dev->data = malloc(dev->erase_size); if(dev->data == NULL) goto out_of_memory; dev->flags = read_only ? NAND_DEV_FLAG_READ_ONLY : 0; #ifdef TARGET_I386 dev->flags |= NAND_DEV_FLAG_BATCH_CAP; #endif if (initfd >= 0) { do { read_size = do_read(initfd, dev->data, dev->erase_size); if(read_size < 0) { XLOG("could not read file %s, %s\n", initfilename, strerror(errno)); exit(1); } if(do_write(rwfd, dev->data, read_size) != read_size) { XLOG("could not write file %s, %s\n", rwfilename, strerror(errno)); exit(1); } } while(read_size == dev->erase_size); close(initfd); } #if defined ANDROID_QCOW close(rwfd); dev->bdrv = bdrv_new(rwfilename); if (0 > bdrv_open(dev->bdrv, rwfilename, BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, NULL)) { //if (0 > bdrv_file_open(&dev->bdrv,rwfilename, BDRV_O_RDWR)) { XLOG("failed to open block driver %s\n", rwfilename); exit(1); } dev_size = 0; //dev_size = bdrv_getlength(dev->bdrv->file); // gets allocated file size // This is how qemu-img gets the virtual disk size: bdrv_get_geometry(dev->bdrv, &dev_size); dev_size *= 512; #else dev->fd = rwfd; #endif pad = dev_size % dev->erase_size; if (pad != 0) { //dev_size += (dev->erase_size - pad); dev_size -= pad; D("rounding devsize up to a full eraseunit, now %llx\n", dev_size); } dev->devname = devname; dev->devname_len = devname_len; dev->max_size = dev_size; D("Dev size of %s is %llx\n", rwfilename, dev_size); nand_dev_count++; return; out_of_memory: XLOG("out of memory\n"); exit(1); bad_arg_and_value: XLOG("bad arg: %.*s=%.*s\n", arg_len, arg, value_len, value); exit(1); }
static int img_convert(int argc, char **argv) { int c, ret = 0, n, n1, bs_n, bs_i, flags, cluster_size, cluster_sectors; const char *fmt, *out_fmt, *out_baseimg, *out_filename; BlockDriver *drv, *proto_drv; BlockDriverState **bs = NULL, *out_bs = NULL; int64_t total_sectors, nb_sectors, sector_num, bs_offset; uint64_t bs_sectors; uint8_t * buf = NULL; const uint8_t *buf1; BlockDriverInfo bdi; QEMUOptionParameter *param = NULL, *create_options = NULL; char *options = NULL; fmt = NULL; out_fmt = "raw"; out_baseimg = NULL; flags = 0; for(;;) { c = getopt(argc, argv, "f:O:B:hce6o:"); if (c == -1) break; switch(c) { case 'h': help(); break; case 'f': fmt = optarg; break; case 'O': out_fmt = optarg; break; case 'B': out_baseimg = optarg; break; case 'c': flags |= BLOCK_FLAG_COMPRESS; break; case 'e': flags |= BLOCK_FLAG_ENCRYPT; break; case '6': flags |= BLOCK_FLAG_COMPAT6; break; case 'o': options = optarg; break; } } bs_n = argc - optind - 1; if (bs_n < 1) help(); out_filename = argv[argc - 1]; if (bs_n > 1 && out_baseimg) { error("-B makes no sense when concatenating multiple input images"); return 1; } bs = calloc(bs_n, sizeof(BlockDriverState *)); if (!bs) { error("Out of memory"); return 1; } total_sectors = 0; for (bs_i = 0; bs_i < bs_n; bs_i++) { bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BDRV_O_FLAGS); if (!bs[bs_i]) { error("Could not open '%s'", argv[optind + bs_i]); ret = -1; goto out; } bdrv_get_geometry(bs[bs_i], &bs_sectors); total_sectors += bs_sectors; } /* Find driver and parse its options */ drv = bdrv_find_format(out_fmt); if (!drv) { error("Unknown file format '%s'", out_fmt); ret = -1; goto out; } proto_drv = bdrv_find_protocol(out_filename); if (!proto_drv) { error("Unknown protocol '%s'", out_filename); ret = -1; goto out; } create_options = append_option_parameters(create_options, drv->create_options); create_options = append_option_parameters(create_options, proto_drv->create_options); if (options && !strcmp(options, "?")) { print_option_help(create_options); goto out; } if (options) { param = parse_option_parameters(options, create_options, param); if (param == NULL) { error("Invalid options for file format '%s'.", out_fmt); ret = -1; goto out; } } else { param = parse_option_parameters("", create_options, param); } set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512); ret = add_old_style_options(out_fmt, param, flags, out_baseimg, NULL); if (ret < 0) { goto out; } /* Check if compression is supported */ if (flags & BLOCK_FLAG_COMPRESS) { QEMUOptionParameter *encryption = get_option_parameter(param, BLOCK_OPT_ENCRYPT); if (!drv->bdrv_write_compressed) { error("Compression not supported for this file format"); ret = -1; goto out; } if (encryption && encryption->value.n) { error("Compression and encryption not supported at the same time"); ret = -1; goto out; } } /* Create the new image */ ret = bdrv_create(drv, out_filename, param); if (ret < 0) { if (ret == -ENOTSUP) { error("Formatting not supported for file format '%s'", out_fmt); } else if (ret == -EFBIG) { error("The image size is too large for file format '%s'", out_fmt); } else { error("%s: error while converting %s: %s", out_filename, out_fmt, strerror(-ret)); } goto out; } out_bs = bdrv_new_open(out_filename, out_fmt, BDRV_O_FLAGS | BDRV_O_RDWR | BDRV_O_NO_FLUSH); if (!out_bs) { ret = -1; goto out; } bs_i = 0; bs_offset = 0; bdrv_get_geometry(bs[0], &bs_sectors); buf = qemu_malloc(IO_BUF_SIZE); if (flags & BLOCK_FLAG_COMPRESS) { ret = bdrv_get_info(out_bs, &bdi); if (ret < 0) { error("could not get block driver info"); goto out; } cluster_size = bdi.cluster_size; if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE) { error("invalid cluster size"); ret = -1; goto out; } cluster_sectors = cluster_size >> 9; sector_num = 0; for(;;) { int64_t bs_num; int remainder; uint8_t *buf2; nb_sectors = total_sectors - sector_num; if (nb_sectors <= 0) break; if (nb_sectors >= cluster_sectors) n = cluster_sectors; else n = nb_sectors; bs_num = sector_num - bs_offset; assert (bs_num >= 0); remainder = n; buf2 = buf; while (remainder > 0) { int nlow; while (bs_num == bs_sectors) { bs_i++; assert (bs_i < bs_n); bs_offset += bs_sectors; bdrv_get_geometry(bs[bs_i], &bs_sectors); bs_num = 0; /* printf("changing part: sector_num=%" PRId64 ", " "bs_i=%d, bs_offset=%" PRId64 ", bs_sectors=%" PRId64 "\n", sector_num, bs_i, bs_offset, bs_sectors); */ } assert (bs_num < bs_sectors); nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder; ret = bdrv_read(bs[bs_i], bs_num, buf2, nlow); if (ret < 0) { error("error while reading"); goto out; } buf2 += nlow * 512; bs_num += nlow; remainder -= nlow; } assert (remainder == 0); if (n < cluster_sectors) memset(buf + n * 512, 0, cluster_size - n * 512); if (is_not_zero(buf, cluster_size)) { ret = bdrv_write_compressed(out_bs, sector_num, buf, cluster_sectors); if (ret != 0) { error("error while compressing sector %" PRId64, sector_num); goto out; } } sector_num += n; } /* signal EOF to align */ bdrv_write_compressed(out_bs, 0, NULL, 0); } else {
/** * bdrv_query_image_info: * @bs: block device to examine * @p_info: location to store image information * @errp: location to store error information * * Store "flat" image information in @p_info. * * "Flat" means it does *not* query backing image information, * i.e. (*pinfo)->has_backing_image will be set to false and * (*pinfo)->backing_image to NULL even when the image does in fact have * a backing image. * * @p_info will be set only on success. On error, store error in @errp. */ void bdrv_query_image_info(BlockDriverState *bs, ImageInfo **p_info, Error **errp) { uint64_t total_sectors; const char *backing_filename; char backing_filename2[1024]; BlockDriverInfo bdi; int ret; Error *err = NULL; ImageInfo *info = g_new0(ImageInfo, 1); bdrv_get_geometry(bs, &total_sectors); info->filename = g_strdup(bs->filename); info->format = g_strdup(bdrv_get_format_name(bs)); info->virtual_size = total_sectors * 512; info->actual_size = bdrv_get_allocated_file_size(bs); info->has_actual_size = info->actual_size >= 0; if (bdrv_is_encrypted(bs)) { info->encrypted = true; info->has_encrypted = true; } if (bdrv_get_info(bs, &bdi) >= 0) { if (bdi.cluster_size != 0) { info->cluster_size = bdi.cluster_size; info->has_cluster_size = true; } info->dirty_flag = bdi.is_dirty; info->has_dirty_flag = true; } info->format_specific = bdrv_get_specific_info(bs); info->has_format_specific = info->format_specific != NULL; backing_filename = bs->backing_file; if (backing_filename[0] != '\0') { info->backing_filename = g_strdup(backing_filename); info->has_backing_filename = true; bdrv_get_full_backing_filename(bs, backing_filename2, sizeof(backing_filename2)); if (strcmp(backing_filename, backing_filename2) != 0) { info->full_backing_filename = g_strdup(backing_filename2); info->has_full_backing_filename = true; } if (bs->backing_format[0]) { info->backing_filename_format = g_strdup(bs->backing_format); info->has_backing_filename_format = true; } } ret = bdrv_query_snapshot_info_list(bs, &info->snapshots, &err); switch (ret) { case 0: if (info->snapshots) { info->has_snapshots = true; } break; /* recoverable error */ case -ENOMEDIUM: case -ENOTSUP: error_free(err); break; default: error_propagate(errp, err); qapi_free_ImageInfo(info); return; } *p_info = info; }
static int img_convert(int argc, char **argv) { int c, ret = 0, n, n1, bs_n, bs_i, compress, cluster_size, cluster_sectors; int progress = 0; const char *fmt, *out_fmt, *out_baseimg, *out_filename; BlockDriver *drv, *proto_drv; BlockDriverState **bs = NULL, *out_bs = NULL; int64_t total_sectors, nb_sectors, sector_num, bs_offset; uint64_t bs_sectors; uint8_t * buf = NULL; const uint8_t *buf1; BlockDriverInfo bdi; QEMUOptionParameter *param = NULL, *create_options = NULL; QEMUOptionParameter *out_baseimg_param; char *options = NULL; const char *snapshot_name = NULL; float local_progress; fmt = NULL; out_fmt = "raw"; out_baseimg = NULL; compress = 0; for(;;) { c = getopt(argc, argv, "f:O:B:s:hce6o:p"); if (c == -1) { break; } switch(c) { case '?': case 'h': help(); break; case 'f': fmt = optarg; break; case 'O': out_fmt = optarg; break; case 'B': out_baseimg = optarg; break; case 'c': compress = 1; break; case 'e': error_report("qemu-img: option -e is deprecated, please use \'-o " "encryption\' instead!"); return 1; case '6': error_report("qemu-img: option -6 is deprecated, please use \'-o " "compat6\' instead!"); return 1; case 'o': options = optarg; break; case 's': snapshot_name = optarg; break; case 'p': progress = 1; break; } } bs_n = argc - optind - 1; if (bs_n < 1) { help(); } out_filename = argv[argc - 1]; if (options && !strcmp(options, "?")) { ret = print_block_option_help(out_filename, out_fmt); goto out; } if (bs_n > 1 && out_baseimg) { error_report("-B makes no sense when concatenating multiple input " "images"); ret = -1; goto out; } qemu_progress_init(progress, 2.0); qemu_progress_print(0, 100); bs = qemu_mallocz(bs_n * sizeof(BlockDriverState *)); total_sectors = 0; for (bs_i = 0; bs_i < bs_n; bs_i++) { bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BDRV_O_FLAGS); if (!bs[bs_i]) { error_report("Could not open '%s'", argv[optind + bs_i]); ret = -1; goto out; } bdrv_get_geometry(bs[bs_i], &bs_sectors); total_sectors += bs_sectors; } if (snapshot_name != NULL) { if (bs_n > 1) { error_report("No support for concatenating multiple snapshot\n"); ret = -1; goto out; } if (bdrv_snapshot_load_tmp(bs[0], snapshot_name) < 0) { error_report("Failed to load snapshot\n"); ret = -1; goto out; } } /* Find driver and parse its options */ drv = bdrv_find_format(out_fmt); if (!drv) { error_report("Unknown file format '%s'", out_fmt); ret = -1; goto out; } proto_drv = bdrv_find_protocol(out_filename); if (!proto_drv) { error_report("Unknown protocol '%s'", out_filename); ret = -1; goto out; } create_options = append_option_parameters(create_options, drv->create_options); create_options = append_option_parameters(create_options, proto_drv->create_options); if (options) { param = parse_option_parameters(options, create_options, param); if (param == NULL) { error_report("Invalid options for file format '%s'.", out_fmt); ret = -1; goto out; } } else { param = parse_option_parameters("", create_options, param); } set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512); ret = add_old_style_options(out_fmt, param, out_baseimg, NULL); if (ret < 0) { goto out; } /* Get backing file name if -o backing_file was used */ out_baseimg_param = get_option_parameter(param, BLOCK_OPT_BACKING_FILE); if (out_baseimg_param) { out_baseimg = out_baseimg_param->value.s; } /* Check if compression is supported */ if (compress) { QEMUOptionParameter *encryption = get_option_parameter(param, BLOCK_OPT_ENCRYPT); if (!drv->bdrv_write_compressed) { error_report("Compression not supported for this file format"); ret = -1; goto out; } if (encryption && encryption->value.n) { error_report("Compression and encryption not supported at " "the same time"); ret = -1; goto out; } } /* Create the new image */ ret = bdrv_create(drv, out_filename, param); if (ret < 0) { if (ret == -ENOTSUP) { error_report("Formatting not supported for file format '%s'", out_fmt); } else if (ret == -EFBIG) { error_report("The image size is too large for file format '%s'", out_fmt); } else { error_report("%s: error while converting %s: %s", out_filename, out_fmt, strerror(-ret)); } goto out; } out_bs = bdrv_new_open(out_filename, out_fmt, BDRV_O_FLAGS | BDRV_O_RDWR | BDRV_O_NO_FLUSH); if (!out_bs) { ret = -1; goto out; } bs_i = 0; bs_offset = 0; bdrv_get_geometry(bs[0], &bs_sectors); buf = qemu_malloc(IO_BUF_SIZE); if (compress) { ret = bdrv_get_info(out_bs, &bdi); if (ret < 0) { error_report("could not get block driver info"); goto out; } cluster_size = bdi.cluster_size; if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE) { error_report("invalid cluster size"); ret = -1; goto out; } cluster_sectors = cluster_size >> 9; sector_num = 0; nb_sectors = total_sectors; local_progress = (float)100 / (nb_sectors / MIN(nb_sectors, (cluster_sectors))); for(;;) { int64_t bs_num; int remainder; uint8_t *buf2; nb_sectors = total_sectors - sector_num; if (nb_sectors <= 0) break; if (nb_sectors >= cluster_sectors) n = cluster_sectors; else n = nb_sectors; bs_num = sector_num - bs_offset; assert (bs_num >= 0); remainder = n; buf2 = buf; while (remainder > 0) { int nlow; while (bs_num == bs_sectors) { bs_i++; assert (bs_i < bs_n); bs_offset += bs_sectors; bdrv_get_geometry(bs[bs_i], &bs_sectors); bs_num = 0; /* printf("changing part: sector_num=%" PRId64 ", " "bs_i=%d, bs_offset=%" PRId64 ", bs_sectors=%" PRId64 "\n", sector_num, bs_i, bs_offset, bs_sectors); */ } assert (bs_num < bs_sectors); nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder; ret = bdrv_read(bs[bs_i], bs_num, buf2, nlow); if (ret < 0) { error_report("error while reading"); goto out; } buf2 += nlow * 512; bs_num += nlow; remainder -= nlow; } assert (remainder == 0); if (n < cluster_sectors) { memset(buf + n * 512, 0, cluster_size - n * 512); } if (is_not_zero(buf, cluster_size)) { ret = bdrv_write_compressed(out_bs, sector_num, buf, cluster_sectors); if (ret != 0) { error_report("error while compressing sector %" PRId64, sector_num); goto out; } } sector_num += n; qemu_progress_print(local_progress, 100); } /* signal EOF to align */ bdrv_write_compressed(out_bs, 0, NULL, 0); } else {
static void goldfish_mmc_do_command(struct goldfish_mmc_state *s, uint32_t cmd, uint32_t arg) { int new_status = MMC_STAT_END_OF_CMD; int opcode = cmd & 63; // fprintf(stderr, "goldfish_mmc_do_command opcode: %s (0x%04X), arg: %d\n", get_command_name(opcode), cmd, arg); int printData = matchMeInPidTid(cpu_single_env); s->resp[0] = 0; s->resp[1] = 0; s->resp[2] = 0; s->resp[3] = 0; #define SET_R1_CURRENT_STATE(s) ((s << 9) & 0x00001E00) /* sx, b (4 bits) */ switch (opcode) { case MMC_SEND_CSD: { int64_t sector_count = 0; uint64_t capacity; uint8_t exponent; uint32_t m; bdrv_get_geometry(s->bs, (uint64_t*)§or_count); capacity = sector_count * 512; if (capacity > 2147483648U) { // if storages is > 2 gig, then emulate SDHC card s->is_SDHC = 1; // CSD bits borrowed from a real SDHC card, with capacity bits zeroed out s->resp[3] = 0x400E0032; s->resp[2] = 0x5B590000; s->resp[1] = 0x00007F80; s->resp[0] = 0x0A4040DF; // stuff in the real capacity // m = UNSTUFF_BITS(resp, 48, 22); m = (uint32_t)(capacity / (512*1024)) - 1; // m must fit into 22 bits if (m & 0xFFC00000) { fprintf(stderr, "SD card too big (%" PRId64 " bytes). " "Maximum SDHC card size is 128 gigabytes.\n", capacity); abort(); } // low 16 bits go in high end of resp[1] s->resp[1] |= ((m & 0x0000FFFF) << 16); // high 6 bits go in low end of resp[2] s->resp[2] |= (m >> 16); } else { // emulate standard SD card s->is_SDHC = 0; // CSD bits borrowed from a real SD card, with capacity bits zeroed out s->resp[3] = 0x00260032; s->resp[2] = 0x5F5A8000; s->resp[1] = 0x3EF84FFF; s->resp[0] = 0x928040CB; // stuff in the real capacity // e = UNSTUFF_BITS(resp, 47, 3); // m = UNSTUFF_BITS(resp, 62, 12); // csd->capacity = (1 + m) << (e + 2); // need to reverse the formula and calculate e and m exponent = 0; capacity = sector_count * 512; if (capacity > 2147483648U) { fprintf(stderr, "SD card too big (%" PRIu64 " bytes). " "Maximum SD card size is 2 gigabytes.\n", capacity); abort(); } capacity >>= 10; // convert to Kbytes while (capacity > 4096) { // (capacity - 1) must fit into 12 bits exponent++; capacity >>= 1; } capacity -= 1; if (exponent < 2) { cpu_abort(cpu_single_env, "SDCard too small, must be at least 9MB\n"); } exponent -= 2; if (exponent > 7) { cpu_abort(cpu_single_env, "SDCard too large.\n"); } s->resp[2] |= (((uint32_t)capacity >> 2) & 0x3FF); // high 10 bits to bottom of resp[2] s->resp[1] |= (((uint32_t)capacity & 3) << 30); // low 2 bits to top of resp[1] s->resp[1] |= (exponent << (47 - 32)); } break; }
int main(int argc, char *argv[]) { int c; const char *filename, *fmt; BlockDriver *drv; BlockDriverState *bs; char fmt_name[128], size_buf[128], dsize_buf[128]; uint64_t total_sectors; int64_t allocated_size; char backing_filename[1024]; char backing_filename2[1024]; BlockDriverInfo bdi; bdrv_init(); fmt = NULL; for(;;) { c = getopt(argc, argv, "f:h"); if (c == -1) break; switch(c) { case 'h': // help(); break; case 'f': fmt = optarg; break; } } if (optind >= argc) help(); filename = argv[optind++]; bs = bdrv_new(""); if (!bs) error("Not enough memory"); if (fmt) { drv = bdrv_find_format(fmt); if (!drv) error("Unknown file format '%s'", fmt); } else { drv = NULL; } if (bdrv_open2(bs, filename, 0, drv) < 0) { error("Could not open '%s'", filename); } bdrv_get_format(bs, fmt_name, sizeof(fmt_name)); bdrv_get_geometry(bs, &total_sectors); get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512); allocated_size = get_allocated_file_size(filename); if (allocated_size < 0) sprintf(dsize_buf, "unavailable"); else get_human_readable_size(dsize_buf, sizeof(dsize_buf), allocated_size); /* if (bdrv_is_encrypted(bs)) fprintf(stderr, "encrypted: yes\n"); if (bdrv_get_info(bs, &bdi) >= 0) { if (bdi.cluster_size != 0) fprintf(stderr, "cluster_size: %d\n", bdi.cluster_size); } */ bdrv_get_info(bs, &bdi); bdrv_get_backing_filename(bs, backing_filename, sizeof(backing_filename)); if (backing_filename[0] != '\0') { path_combine(backing_filename2, sizeof(backing_filename2), filename, backing_filename); /* fprintf(stderr, "backing file: %s (actual path: %s)\n", backing_filename, backing_filename2); */ } fprintf(stdout, "{'filename' : '%s'," " 'format' : '%s'," " 'image_disk_size' : '%s'," " 'allocated_size' : '%s'," " 'total_sectors' : '%"PRId64"'," " 'backing_file' : '%s',}", filename, fmt_name, size_buf, dsize_buf, total_sectors, backing_filename); dump_snapshots(bs); bdrv_delete(bs); return 0; }
static int img_convert(int argc, char **argv) { int c, ret, n, n1, bs_n, bs_i, flags, cluster_size, cluster_sectors; const char *fmt, *out_fmt, *out_baseimg, *out_filename; BlockDriver *drv; BlockDriverState **bs, *out_bs; int64_t total_sectors, nb_sectors, sector_num, bs_offset; uint64_t bs_sectors; uint8_t buf[IO_BUF_SIZE]; const uint8_t *buf1; BlockDriverInfo bdi; fmt = NULL; out_fmt = "raw"; out_baseimg = NULL; flags = 0; for(;;) { c = getopt(argc, argv, "f:O:B:hce6"); if (c == -1) break; switch(c) { case 'h': help(); break; case 'f': fmt = optarg; break; case 'O': out_fmt = optarg; break; case 'B': out_baseimg = optarg; break; case 'c': flags |= BLOCK_FLAG_COMPRESS; break; case 'e': flags |= BLOCK_FLAG_ENCRYPT; break; case '6': flags |= BLOCK_FLAG_COMPAT6; break; } } bs_n = argc - optind - 1; if (bs_n < 1) help(); out_filename = argv[argc - 1]; if (bs_n > 1 && out_baseimg) error("-B makes no sense when concatenating multiple input images"); bs = calloc(bs_n, sizeof(BlockDriverState *)); if (!bs) error("Out of memory"); total_sectors = 0; for (bs_i = 0; bs_i < bs_n; bs_i++) { bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BDRV_O_CACHE_WB|BDRV_O_RDONLY); if (!bs[bs_i]) error("Could not open '%s'", argv[optind + bs_i]); bdrv_get_geometry(bs[bs_i], &bs_sectors); total_sectors += bs_sectors; } drv = bdrv_find_format(out_fmt); if (!drv) error("Unknown file format '%s'", out_fmt); if (flags & BLOCK_FLAG_COMPRESS && drv != &bdrv_qcow && drv != &bdrv_qcow2) error("Compression not supported for this file format"); if (flags & BLOCK_FLAG_ENCRYPT && drv != &bdrv_qcow && drv != &bdrv_qcow2) error("Encryption not supported for this file format"); if (flags & BLOCK_FLAG_COMPAT6 && drv != &bdrv_vmdk) error("Alternative compatibility level not supported for this file format"); if (flags & BLOCK_FLAG_ENCRYPT && flags & BLOCK_FLAG_COMPRESS) error("Compression and encryption not supported at the same time"); ret = bdrv_create(drv, out_filename, total_sectors, out_baseimg, flags); if (ret < 0) { if (ret == -ENOTSUP) { error("Formatting not supported for file format '%s'", fmt); } else { error("Error while formatting '%s'", out_filename); } } out_bs = bdrv_new_open(out_filename, out_fmt, BDRV_O_CACHE_WB|BDRV_O_RDWR); bs_i = 0; bs_offset = 0; bdrv_get_geometry(bs[0], &bs_sectors); if (flags & BLOCK_FLAG_COMPRESS) { if (bdrv_get_info(out_bs, &bdi) < 0) error("could not get block driver info"); cluster_size = bdi.cluster_size; if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE) error("invalid cluster size"); cluster_sectors = cluster_size >> 9; sector_num = 0; for(;;) { int64_t bs_num; int remainder; uint8_t *buf2; nb_sectors = total_sectors - sector_num; if (nb_sectors <= 0) break; if (nb_sectors >= cluster_sectors) n = cluster_sectors; else n = nb_sectors; bs_num = sector_num - bs_offset; assert (bs_num >= 0); remainder = n; buf2 = buf; while (remainder > 0) { int nlow; while (bs_num == bs_sectors) { bs_i++; assert (bs_i < bs_n); bs_offset += bs_sectors; bdrv_get_geometry(bs[bs_i], &bs_sectors); bs_num = 0; /* printf("changing part: sector_num=%lld, " "bs_i=%d, bs_offset=%lld, bs_sectors=%lld\n", sector_num, bs_i, bs_offset, bs_sectors); */ } assert (bs_num < bs_sectors); nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder; if (bdrv_read(bs[bs_i], bs_num, buf2, nlow) < 0) error("error while reading"); buf2 += nlow * 512; bs_num += nlow; remainder -= nlow; } assert (remainder == 0); if (n < cluster_sectors) memset(buf + n * 512, 0, cluster_size - n * 512); if (is_not_zero(buf, cluster_size)) { if (bdrv_write_compressed(out_bs, sector_num, buf, cluster_sectors) != 0) error("error while compressing sector %" PRId64, sector_num); } sector_num += n; } /* signal EOF to align */ bdrv_write_compressed(out_bs, 0, NULL, 0); } else {
static int img_create(int argc, char **argv) { int c, ret, flags; const char *fmt = "raw"; const char *filename; const char *base_filename = NULL; uint64_t size; const char *p; BlockDriver *drv; flags = 0; for(;;) { c = getopt(argc, argv, "b:f:he6"); if (c == -1) break; switch(c) { case 'h': help(); break; case 'b': base_filename = optarg; break; case 'f': fmt = optarg; break; case 'e': flags |= BLOCK_FLAG_ENCRYPT; break; case '6': flags |= BLOCK_FLAG_COMPAT6; break; } } if (optind >= argc) help(); filename = argv[optind++]; size = 0; if (base_filename) { BlockDriverState *bs; bs = bdrv_new_open(base_filename, NULL, BDRV_O_RDWR); bdrv_get_geometry(bs, &size); size *= 512; bdrv_delete(bs); } else { if (optind >= argc) help(); p = argv[optind]; size = strtoul(p, (char **)&p, 0); if (*p == 'M') { size *= 1024 * 1024; } else if (*p == 'G') { size *= 1024 * 1024 * 1024; } else if (*p == 'k' || *p == 'K' || *p == '\0') { size *= 1024; } else { help(); } } drv = bdrv_find_format(fmt); if (!drv) error("Unknown file format '%s'", fmt); printf("Formatting '%s', fmt=%s", filename, fmt); if (flags & BLOCK_FLAG_ENCRYPT) printf(", encrypted"); if (flags & BLOCK_FLAG_COMPAT6) printf(", compatibility level=6"); if (base_filename) { printf(", backing_file=%s", base_filename); } printf(", size=%" PRIu64 " kB\n", size / 1024); ret = bdrv_create(drv, filename, size / 512, base_filename, flags); if (ret < 0) { if (ret == -ENOTSUP) { error("Formatting or formatting option not supported for file format '%s'", fmt); } else { error("Error while formatting"); } } return 0; }
static int img_convert(int argc, char **argv) { int c, ret, n, n1, compress, cluster_size, cluster_sectors, encrypt; const char *filename, *fmt, *out_fmt, *out_filename; BlockDriver *drv; BlockDriverState *bs, *out_bs; int64_t total_sectors, nb_sectors, sector_num; uint8_t buf[IO_BUF_SIZE]; const uint8_t *buf1; BlockDriverInfo bdi; fmt = NULL; out_fmt = "raw"; compress = 0; encrypt = 0; for(;;) { c = getopt(argc, argv, "f:O:hce"); if (c == -1) break; switch(c) { case 'h': help(); break; case 'f': fmt = optarg; break; case 'O': out_fmt = optarg; break; case 'c': compress = 1; break; case 'e': encrypt = 1; break; } } if (optind >= argc) help(); filename = argv[optind++]; if (optind >= argc) help(); out_filename = argv[optind++]; bs = bdrv_new_open(filename, fmt); drv = bdrv_find_format(out_fmt); if (!drv) error("Unknown file format '%s'", fmt); if (compress && drv != &bdrv_qcow && drv != &bdrv_qcow2) error("Compression not supported for this file format"); if (encrypt && drv != &bdrv_qcow && drv != &bdrv_qcow2) error("Encryption not supported for this file format"); if (compress && encrypt) error("Compression and encryption not supported at the same time"); bdrv_get_geometry(bs, &total_sectors); ret = bdrv_create(drv, out_filename, total_sectors, NULL, encrypt); if (ret < 0) { if (ret == -ENOTSUP) { error("Formatting not supported for file format '%s'", fmt); } else { error("Error while formatting '%s'", out_filename); } } out_bs = bdrv_new_open(out_filename, out_fmt); if (compress) { if (bdrv_get_info(out_bs, &bdi) < 0) error("could not get block driver info"); cluster_size = bdi.cluster_size; if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE) error("invalid cluster size"); cluster_sectors = cluster_size >> 9; sector_num = 0; for(;;) { nb_sectors = total_sectors - sector_num; if (nb_sectors <= 0) break; if (nb_sectors >= cluster_sectors) n = cluster_sectors; else n = nb_sectors; if (bdrv_read(bs, sector_num, buf, n) < 0) error("error while reading"); if (n < cluster_sectors) memset(buf + n * 512, 0, cluster_size - n * 512); if (is_not_zero(buf, cluster_size)) { if (bdrv_write_compressed(out_bs, sector_num, buf, cluster_sectors) != 0) error("error while compressing sector %" PRId64, sector_num); } sector_num += n; } /* signal EOF to align */ bdrv_write_compressed(out_bs, 0, NULL, 0); } else {