One thing that's really annoying about the Aspeed machines is that you have to provide a flash image that is the same size as the SPI-NOR flash device the board uses, or something larger. If you don't, you'll get this obscure error message:
qemu-system-aarch64: failed to read the initial flash content Which is just because the file isn't the right size. Zero-extending the file to 128MB (the largest SPI-NOR flash size) fixes this. This commit just performs the zero-extend automatically, so people don't have to maintain bash scripts for it. And if your bash script does this already, it will be a no-op. And, if your firmware image is larger than the SPI-NOR device, then it will not truncate it. Signed-off-by: Peter Delevoryas <pe...@pjd.dev> --- hw/arm/aspeed.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 55f114ef72..26450d90db 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -260,6 +260,30 @@ static void write_boot_rom(DriveInfo *dinfo, hwaddr addr, size_t rom_size, rom_add_blob_fixed("aspeed.boot_rom", storage, rom_size, addr); } +static int zero_extend_block_device(BlockBackend *blk, uint64_t size, + Error **errp) +{ + uint64_t perm, shared_perm; + + blk_get_perm(blk, &perm, &shared_perm); + + if (blk_set_perm(blk, BLK_PERM_ALL, BLK_PERM_ALL, errp)) { + error_append_hint(errp, "Unable to change permissions on block device"); + return -1; + } + if (blk_truncate(blk, size, true, PREALLOC_MODE_OFF, BDRV_REQ_ZERO_WRITE, + errp)) { + error_append_hint(errp, "Unable to zero-extend block device"); + return -1; + } + if (blk_set_perm(blk, perm, shared_perm, errp)) { + error_append_hint(errp, + "Unable to restore permissions on block device"); + /* Ignore error since we successfully extended the device already */ + } + return 0; +} + void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype, unsigned int count, int unit0) { @@ -273,10 +297,24 @@ void aspeed_board_init_flashes(AspeedSMCState *s, const char *flashtype, DriveInfo *dinfo = drive_get(IF_MTD, 0, unit0 + i); qemu_irq cs_line; DeviceState *dev; + AspeedSMCFlash *flash = &s->flashes[i]; + uint64_t flash_size = memory_region_size(&flash->mmio); dev = qdev_new(flashtype); if (dinfo) { - qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo)); + BlockBackend *blk = blk_by_legacy_dinfo(dinfo); + int64_t blk_size = blk_getlength(blk); + + if (blk_size > 0 && blk_size < (int64_t)flash_size) { + Error *err = NULL; + + zero_extend_block_device(blk, flash_size, &err); + if (err) { + warn_reportf_err(err, "Error zero-extending MTD drive[%d] " + "to flash size", i); + } + } + qdev_prop_set_drive(dev, "drive", blk); } qdev_realize_and_unref(dev, BUS(s->spi), &error_fatal); -- 2.38.1