diff --git a/block/cloop.c b/block/cloop.c index 775f8a98e1..7570eb8e74 100644 --- a/block/cloop.c +++ b/block/cloop.c @@ -30,7 +30,7 @@ typedef struct BDRVCloopState { CoMutex lock; uint32_t block_size; uint32_t n_blocks; - uint64_t* offsets; + uint64_t *offsets; uint32_t sectors_per_block; uint32_t current_block; uint8_t *compressed_block; @@ -40,21 +40,23 @@ typedef struct BDRVCloopState { static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename) { - const char* magic_version_2_0="#!/bin/sh\n" - "#V2.0 Format\n" - "modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n"; - int length=strlen(magic_version_2_0); - if(length>buf_size) - length=buf_size; - if(!memcmp(magic_version_2_0,buf,length)) - return 2; + const char *magic_version_2_0 = "#!/bin/sh\n" + "#V2.0 Format\n" + "modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n"; + int length = strlen(magic_version_2_0); + if (length > buf_size) { + length = buf_size; + } + if (!memcmp(magic_version_2_0, buf, length)) { + return 2; + } return 0; } static int cloop_open(BlockDriverState *bs, int flags) { BDRVCloopState *s = bs->opaque; - uint32_t offsets_size,max_compressed_block_size=1,i; + uint32_t offsets_size, max_compressed_block_size = 1, i; bs->read_only = 1; @@ -74,26 +76,28 @@ static int cloop_open(BlockDriverState *bs, int flags) s->offsets = g_malloc(offsets_size); if (bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size) < offsets_size) { - goto cloop_close; + goto cloop_close; } for(i=0;in_blocks;i++) { - s->offsets[i]=be64_to_cpu(s->offsets[i]); - if(i>0) { - uint32_t size=s->offsets[i]-s->offsets[i-1]; - if(size>max_compressed_block_size) - max_compressed_block_size=size; - } + s->offsets[i] = be64_to_cpu(s->offsets[i]); + if (i > 0) { + uint32_t size = s->offsets[i] - s->offsets[i - 1]; + if (size > max_compressed_block_size) { + max_compressed_block_size = size; + } + } } /* initialize zlib engine */ - s->compressed_block = g_malloc(max_compressed_block_size+1); + s->compressed_block = g_malloc(max_compressed_block_size + 1); s->uncompressed_block = g_malloc(s->block_size); - if(inflateInit(&s->zstream) != Z_OK) - goto cloop_close; - s->current_block=s->n_blocks; + if (inflateInit(&s->zstream) != Z_OK) { + goto cloop_close; + } + s->current_block = s->n_blocks; s->sectors_per_block = s->block_size/512; - bs->total_sectors = s->n_blocks*s->sectors_per_block; + bs->total_sectors = s->n_blocks * s->sectors_per_block; qemu_co_mutex_init(&s->lock); return 0; @@ -105,27 +109,30 @@ static inline int cloop_read_block(BlockDriverState *bs, int block_num) { BDRVCloopState *s = bs->opaque; - if(s->current_block != block_num) { - int ret; - uint32_t bytes = s->offsets[block_num+1]-s->offsets[block_num]; + if (s->current_block != block_num) { + int ret; + uint32_t bytes = s->offsets[block_num + 1] - s->offsets[block_num]; ret = bdrv_pread(bs->file, s->offsets[block_num], s->compressed_block, bytes); - if (ret != bytes) + if (ret != bytes) { return -1; + } - s->zstream.next_in = s->compressed_block; - s->zstream.avail_in = bytes; - s->zstream.next_out = s->uncompressed_block; - s->zstream.avail_out = s->block_size; - ret = inflateReset(&s->zstream); - if(ret != Z_OK) - return -1; - ret = inflate(&s->zstream, Z_FINISH); - if(ret != Z_STREAM_END || s->zstream.total_out != s->block_size) - return -1; + s->zstream.next_in = s->compressed_block; + s->zstream.avail_in = bytes; + s->zstream.next_out = s->uncompressed_block; + s->zstream.avail_out = s->block_size; + ret = inflateReset(&s->zstream); + if (ret != Z_OK) { + return -1; + } + ret = inflate(&s->zstream, Z_FINISH); + if (ret != Z_STREAM_END || s->zstream.total_out != s->block_size) { + return -1; + } - s->current_block = block_num; + s->current_block = block_num; } return 0; } @@ -136,12 +143,15 @@ static int cloop_read(BlockDriverState *bs, int64_t sector_num, BDRVCloopState *s = bs->opaque; int i; - for(i=0;isectors_per_block), - block_num=(sector_num+i)/s->sectors_per_block; - if(cloop_read_block(bs, block_num) != 0) - return -1; - memcpy(buf+i*512,s->uncompressed_block+sector_offset_in_block*512,512); + for (i = 0; i < nb_sectors; i++) { + uint32_t sector_offset_in_block = + ((sector_num + i) % s->sectors_per_block), + block_num = (sector_num + i) / s->sectors_per_block; + if (cloop_read_block(bs, block_num) != 0) { + return -1; + } + memcpy(buf + i * 512, + s->uncompressed_block + sector_offset_in_block * 512, 512); } return 0; } @@ -160,20 +170,21 @@ static coroutine_fn int cloop_co_read(BlockDriverState *bs, int64_t sector_num, static void cloop_close(BlockDriverState *bs) { BDRVCloopState *s = bs->opaque; - if(s->n_blocks>0) - free(s->offsets); - free(s->compressed_block); - free(s->uncompressed_block); + if (s->n_blocks > 0) { + g_free(s->offsets); + } + g_free(s->compressed_block); + g_free(s->uncompressed_block); inflateEnd(&s->zstream); } static BlockDriver bdrv_cloop = { - .format_name = "cloop", - .instance_size = sizeof(BDRVCloopState), - .bdrv_probe = cloop_probe, - .bdrv_open = cloop_open, - .bdrv_read = cloop_co_read, - .bdrv_close = cloop_close, + .format_name = "cloop", + .instance_size = sizeof(BDRVCloopState), + .bdrv_probe = cloop_probe, + .bdrv_open = cloop_open, + .bdrv_read = cloop_co_read, + .bdrv_close = cloop_close, }; static void bdrv_cloop_init(void) diff --git a/block/vvfat.c b/block/vvfat.c index e1fcdbc45b..8511fe523c 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -799,6 +799,7 @@ static int read_directory(BDRVVVFATState* s, int mapping_index) /* root directory */ int cur = s->directory.next; array_ensure_allocated(&(s->directory), ROOT_ENTRIES - 1); + s->directory.next = ROOT_ENTRIES; memset(array_get(&(s->directory), cur), 0, (ROOT_ENTRIES - cur) * sizeof(direntry_t)); } @@ -915,11 +916,8 @@ static int init_directories(BDRVVVFATState* s, cluster = mapping->end; if(cluster > s->cluster_count) { - fprintf(stderr,"Directory does not fit in FAT%d (capacity %s)\n", - s->fat_type, - s->fat_type == 12 ? s->sector_count == 2880 ? "1.44 MB" - : "2.88 MB" - : "504MB"); + fprintf(stderr,"Directory does not fit in FAT%d (capacity %.2f MB)\n", + s->fat_type, s->sector_count / 2000.0); return -EINVAL; } @@ -953,7 +951,7 @@ static int init_directories(BDRVVVFATState* s, bootsector->number_of_fats=0x2; /* number of FATs */ bootsector->root_entries=cpu_to_le16(s->sectors_of_root_directory*0x10); bootsector->total_sectors16=s->sector_count>0xffff?0:cpu_to_le16(s->sector_count); - bootsector->media_type=(s->fat_type!=12?0xf8:s->sector_count==5760?0xf9:0xf8); /* media descriptor */ + bootsector->media_type=(s->first_sectors_number>1?0xf8:0xf0); /* media descriptor (f8=hd, f0=3.5 fd)*/ s->fat.pointer[0] = bootsector->media_type; bootsector->sectors_per_fat=cpu_to_le16(s->sectors_per_fat); bootsector->sectors_per_track=cpu_to_le16(s->bs->secs); @@ -962,7 +960,7 @@ static int init_directories(BDRVVVFATState* s, bootsector->total_sectors=cpu_to_le32(s->sector_count>0xffff?s->sector_count:0); /* LATER TODO: if FAT32, this is wrong */ - bootsector->u.fat16.drive_number=s->fat_type==12?0:0x80; /* assume this is hda (TODO) */ + bootsector->u.fat16.drive_number=s->first_sectors_number==1?0:0x80; /* fda=0, hda=0x80 */ bootsector->u.fat16.current_head=0; bootsector->u.fat16.signature=0x29; bootsector->u.fat16.id=cpu_to_le32(0xfabe1afd); @@ -984,7 +982,6 @@ static int is_consistent(BDRVVVFATState *s); static int vvfat_open(BlockDriverState *bs, const char* dirname, int flags) { BDRVVVFATState *s = bs->opaque; - int floppy = 0; int i; #ifdef DEBUG @@ -998,11 +995,8 @@ DLOG(if (stderr == NULL) { s->bs = bs; - s->fat_type=16; /* LATER TODO: if FAT32, adjust */ s->sectors_per_cluster=0x10; - /* 504MB disk*/ - bs->cyls=1024; bs->heads=16; bs->secs=63; s->current_cluster=0xffffffff; @@ -1017,16 +1011,6 @@ DLOG(if (stderr == NULL) { if (!strstart(dirname, "fat:", NULL)) return -1; - if (strstr(dirname, ":floppy:")) { - floppy = 1; - s->fat_type = 12; - s->first_sectors_number = 1; - s->sectors_per_cluster=2; - bs->cyls = 80; bs->heads = 2; bs->secs = 36; - } - - s->sector_count=bs->cyls*bs->heads*bs->secs; - if (strstr(dirname, ":32:")) { fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. You are welcome to do so!\n"); s->fat_type = 32; @@ -1034,9 +1018,31 @@ DLOG(if (stderr == NULL) { s->fat_type = 16; } else if (strstr(dirname, ":12:")) { s->fat_type = 12; - s->sector_count=2880; } + if (strstr(dirname, ":floppy:")) { + /* 1.44MB or 2.88MB floppy. 2.88MB can be FAT12 (default) or FAT16. */ + if (!s->fat_type) { + s->fat_type = 12; + bs->secs = 36; + s->sectors_per_cluster=2; + } else { + bs->secs=(s->fat_type == 12 ? 18 : 36); + s->sectors_per_cluster=1; + } + s->first_sectors_number = 1; + bs->cyls=80; bs->heads=2; + } else { + /* 32MB or 504MB disk*/ + if (!s->fat_type) { + s->fat_type = 16; + } + bs->cyls=(s->fat_type == 12 ? 64 : 1024); + bs->heads=16; bs->secs=63; + } + + s->sector_count=bs->cyls*bs->heads*bs->secs-(s->first_sectors_number-1); + if (strstr(dirname, ":rw:")) { if (enable_write_target(s)) return -1; @@ -1060,10 +1066,10 @@ DLOG(if (stderr == NULL) { if(s->first_sectors_number==0x40) init_mbr(s); - - /* for some reason or other, MS-DOS does not like to know about CHS... */ - if (floppy) + else { + /* MS-DOS does not like to know about CHS (?). */ bs->heads = bs->cyls = bs->secs = 0; + } // assert(is_consistent(s)); qemu_co_mutex_init(&s->lock); @@ -1244,7 +1250,7 @@ static int vvfat_read(BlockDriverState *bs, int64_t sector_num, int i; for(i=0;i= s->sector_count) + if (sector_num >= bs->total_sectors) return -1; if (s->qcow) { int n; @@ -1270,7 +1276,7 @@ DLOG(fprintf(stderr, "sector %d not allocated\n", (int)sector_num)); uint32_t sector=sector_num-s->faked_sectors, sector_offset_in_cluster=(sector%s->sectors_per_cluster), cluster_num=sector/s->sectors_per_cluster; - if(read_cluster(s, cluster_num) != 0) { + if(cluster_num > s->cluster_count || read_cluster(s, cluster_num) != 0) { /* LATER TODO: strict: return -1; */ memset(buf+i*0x200,0,0x200); continue; diff --git a/hw/dma.c b/hw/dma.c index 8a7302a42f..0a9322daa3 100644 --- a/hw/dma.c +++ b/hw/dma.c @@ -358,6 +358,14 @@ static void DMA_run (void) struct dma_cont *d; int icont, ichan; int rearm = 0; + static int running = 0; + + if (running) { + rearm = 1; + goto out; + } else { + running = 1; + } d = dma_controllers; @@ -374,6 +382,8 @@ static void DMA_run (void) } } + running = 0; +out: if (rearm) qemu_bh_schedule_idle(dma_bh); } diff --git a/qemu-io.c b/qemu-io.c index 5af887e057..de26422fcf 100644 --- a/qemu-io.c +++ b/qemu-io.c @@ -596,6 +596,9 @@ static int readv_f(int argc, char **argv) nr_iov = argc - optind; buf = create_iovec(&qiov, &argv[optind], nr_iov, 0xab); + if (buf == NULL) { + return 0; + } gettimeofday(&t1, NULL); cnt = do_aio_readv(&qiov, offset, &total); @@ -850,6 +853,9 @@ static int writev_f(int argc, char **argv) nr_iov = argc - optind; buf = create_iovec(&qiov, &argv[optind], nr_iov, pattern); + if (buf == NULL) { + return 0; + } gettimeofday(&t1, NULL); cnt = do_aio_writev(&qiov, offset, &total); @@ -950,25 +956,25 @@ static int multiwrite_f(int argc, char **argv) } } - reqs = g_malloc(nr_reqs * sizeof(*reqs)); - buf = g_malloc(nr_reqs * sizeof(*buf)); + reqs = g_malloc0(nr_reqs * sizeof(*reqs)); + buf = g_malloc0(nr_reqs * sizeof(*buf)); qiovs = g_malloc(nr_reqs * sizeof(*qiovs)); - for (i = 0; i < nr_reqs; i++) { + for (i = 0; i < nr_reqs && optind < argc; i++) { int j; /* Read the offset of the request */ offset = cvtnum(argv[optind]); if (offset < 0) { printf("non-numeric offset argument -- %s\n", argv[optind]); - return 0; + goto out; } optind++; if (offset & 0x1ff) { printf("offset %lld is not sector aligned\n", (long long)offset); - return 0; + goto out; } if (i == 0) { @@ -985,8 +991,12 @@ static int multiwrite_f(int argc, char **argv) nr_iov = j - optind; /* Build request */ + buf[i] = create_iovec(&qiovs[i], &argv[optind], nr_iov, pattern); + if (buf[i] == NULL) { + goto out; + } + reqs[i].qiov = &qiovs[i]; - buf[i] = create_iovec(reqs[i].qiov, &argv[optind], nr_iov, pattern); reqs[i].sector = offset >> 9; reqs[i].nb_sectors = reqs[i].qiov->size >> 9; @@ -995,6 +1005,9 @@ static int multiwrite_f(int argc, char **argv) pattern++; } + /* If there were empty requests at the end, ignore them */ + nr_reqs = i; + gettimeofday(&t1, NULL); cnt = do_aio_multiwrite(reqs, nr_reqs, &total); gettimeofday(&t2, NULL); @@ -1014,7 +1027,9 @@ static int multiwrite_f(int argc, char **argv) out: for (i = 0; i < nr_reqs; i++) { qemu_io_free(buf[i]); - qemu_iovec_destroy(&qiovs[i]); + if (reqs[i].qiov != NULL) { + qemu_iovec_destroy(&qiovs[i]); + } } g_free(buf); g_free(reqs); @@ -1185,6 +1200,10 @@ static int aio_read_f(int argc, char **argv) nr_iov = argc - optind; ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, 0xab); + if (ctx->buf == NULL) { + free(ctx); + return 0; + } gettimeofday(&ctx->t1, NULL); acb = bdrv_aio_readv(bs, ctx->offset >> 9, &ctx->qiov, @@ -1280,6 +1299,10 @@ static int aio_write_f(int argc, char **argv) nr_iov = argc - optind; ctx->buf = create_iovec(&ctx->qiov, &argv[optind], nr_iov, pattern); + if (ctx->buf == NULL) { + free(ctx); + return 0; + } gettimeofday(&ctx->t1, NULL); acb = bdrv_aio_writev(bs, ctx->offset >> 9, &ctx->qiov,