diff mbox series

[1/1] hw/arm/aspeed: Automatically zero-extend flash images

Message ID 20221114190823.1888691-2-peter@pjd.dev (mailing list archive)
State New, archived
Headers show
Series hw/arm/aspeed: Automatically zero-extend flash images | expand

Commit Message

Peter Delevoryas Nov. 14, 2022, 7:08 p.m. UTC
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 <peter@pjd.dev>
---
 hw/arm/aspeed.c | 40 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 39 insertions(+), 1 deletion(-)
diff mbox series

Patch

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);