diff options
Diffstat (limited to 'hw/block')
-rw-r--r-- | hw/block/block.c | 48 | ||||
-rw-r--r-- | hw/block/pflash_cfi01.c | 15 | ||||
-rw-r--r-- | hw/block/pflash_cfi02.c | 13 |
3 files changed, 53 insertions, 23 deletions
diff --git a/hw/block/block.c b/hw/block/block.c index cf0eb826f1..bf56c7612b 100644 --- a/hw/block/block.c +++ b/hw/block/block.c @@ -13,7 +13,53 @@ #include "hw/block/block.h" #include "qapi/error.h" #include "qapi/qapi-types-block.h" -#include "qemu/error-report.h" + +/* + * Read the entire contents of @blk into @buf. + * @blk's contents must be @size bytes, and @size must be at most + * BDRV_REQUEST_MAX_BYTES. + * On success, return true. + * On failure, store an error through @errp and return false. + * Note that the error messages do not identify the block backend. + * TODO Since callers don't either, this can result in confusing + * errors. + * This function not intended for actual block devices, which read on + * demand. It's for things like memory devices that (ab)use a block + * backend to provide persistence. + */ +bool blk_check_size_and_read_all(BlockBackend *blk, void *buf, hwaddr size, + Error **errp) +{ + int64_t blk_len; + int ret; + + blk_len = blk_getlength(blk); + if (blk_len < 0) { + error_setg_errno(errp, -blk_len, + "can't get size of block backend"); + return false; + } + if (blk_len != size) { + error_setg(errp, "device requires %" HWADDR_PRIu " bytes, " + "block backend provides %" PRIu64 " bytes", + size, blk_len); + return false; + } + + /* + * We could loop for @size > BDRV_REQUEST_MAX_BYTES, but if we + * ever get to the point we want to read *gigabytes* here, we + * should probably rework the device to be more like an actual + * block device and read only on demand. + */ + assert(size <= BDRV_REQUEST_MAX_BYTES); + ret = blk_pread(blk, 0, buf, size); + if (ret < 0) { + error_setg_errno(errp, -ret, "can't read block backend"); + return false; + } + return true; +} void blkconf_blocksizes(BlockConf *conf) { diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c index 125f70b8e4..16dfae14b8 100644 --- a/hw/block/pflash_cfi01.c +++ b/hw/block/pflash_cfi01.c @@ -38,6 +38,7 @@ #include "qemu/osdep.h" #include "hw/hw.h" +#include "hw/block/block.h" #include "hw/block/flash.h" #include "sysemu/block-backend.h" #include "qapi/error.h" @@ -730,13 +731,6 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp) } device_len = sector_len_per_device * blocks_per_device; - /* XXX: to be fixed */ -#if 0 - if (total_len != (8 * 1024 * 1024) && total_len != (16 * 1024 * 1024) && - total_len != (32 * 1024 * 1024) && total_len != (64 * 1024 * 1024)) - return NULL; -#endif - memory_region_init_rom_device( &pfl->mem, OBJECT(dev), &pflash_cfi01_ops, @@ -763,12 +757,9 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp) } if (pfl->blk) { - /* read the initial flash content */ - ret = blk_pread(pfl->blk, 0, pfl->storage, total_len); - - if (ret < 0) { + if (!blk_check_size_and_read_all(pfl->blk, pfl->storage, total_len, + errp)) { vmstate_unregister_ram(&pfl->mem, DEVICE(pfl)); - error_setg(errp, "failed to read the initial flash content"); return; } } diff --git a/hw/block/pflash_cfi02.c b/hw/block/pflash_cfi02.c index c9db430611..f2c6201f81 100644 --- a/hw/block/pflash_cfi02.c +++ b/hw/block/pflash_cfi02.c @@ -37,6 +37,7 @@ #include "qemu/osdep.h" #include "hw/hw.h" +#include "hw/block/block.h" #include "hw/block/flash.h" #include "qapi/error.h" #include "qemu/timer.h" @@ -550,12 +551,6 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp) } chip_len = pfl->sector_len * pfl->nb_blocs; - /* XXX: to be fixed */ -#if 0 - if (total_len != (8 * 1024 * 1024) && total_len != (16 * 1024 * 1024) && - total_len != (32 * 1024 * 1024) && total_len != (64 * 1024 * 1024)) - return NULL; -#endif memory_region_init_rom_device(&pfl->orig_mem, OBJECT(pfl), pfl->be ? &pflash_cfi02_ops_be : &pflash_cfi02_ops_le, @@ -581,11 +576,9 @@ static void pflash_cfi02_realize(DeviceState *dev, Error **errp) } if (pfl->blk) { - /* read the initial flash content */ - ret = blk_pread(pfl->blk, 0, pfl->storage, chip_len); - if (ret < 0) { + if (!blk_check_size_and_read_all(pfl->blk, pfl->storage, chip_len, + errp)) { vmstate_unregister_ram(&pfl->orig_mem, DEVICE(pfl)); - error_setg(errp, "failed to read the initial flash content"); return; } } |