On Tue, Sep 1, 2020 at 8:49 AM Green Wan <green....@sifive.com> wrote: > > Add '-drive' support to OTP device. Allow users to assign a raw file > as OTP image.
Do you mind writing an example command line argument in the commit message? Also, do you have a test case for this? I would like to add it to my CI. > > Signed-off-by: Green Wan <green....@sifive.com> > --- > hw/riscv/sifive_u_otp.c | 50 +++++++++++++++++++++++++++++++++ > include/hw/riscv/sifive_u_otp.h | 2 ++ > 2 files changed, 52 insertions(+) > > diff --git a/hw/riscv/sifive_u_otp.c b/hw/riscv/sifive_u_otp.c > index b8369e9035..477c54c7b8 100644 > --- a/hw/riscv/sifive_u_otp.c > +++ b/hw/riscv/sifive_u_otp.c > @@ -24,6 +24,8 @@ > #include "qemu/log.h" > #include "qemu/module.h" > #include "hw/riscv/sifive_u_otp.h" > +#include "sysemu/blockdev.h" > +#include "sysemu/block-backend.h" > > #define WRITTEN_BIT_ON 0x1 > > @@ -54,6 +56,16 @@ static uint64_t sifive_u_otp_read(void *opaque, hwaddr > addr, unsigned int size) > if ((s->pce & SIFIVE_U_OTP_PCE_EN) && > (s->pdstb & SIFIVE_U_OTP_PDSTB_EN) && > (s->ptrim & SIFIVE_U_OTP_PTRIM_EN)) { > + > + /* read from backend */ > + if (s->blk) { > + int32_t buf; > + > + blk_pread(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD, &buf, > + SIFIVE_U_OTP_FUSE_WORD); > + return buf; > + } > + > return s->fuse[s->pa & SIFIVE_U_OTP_PA_MASK]; > } else { > return 0xff; > @@ -145,6 +157,12 @@ static void sifive_u_otp_write(void *opaque, hwaddr addr, > /* write bit data */ > SET_FUSEARRAY_BIT(s->fuse, s->pa, s->paio, s->pdin); > > + /* write to backend */ > + if (s->blk) { > + blk_pwrite(s->blk, s->pa * SIFIVE_U_OTP_FUSE_WORD, &val32, > + SIFIVE_U_OTP_FUSE_WORD, 0); > + } > + > /* update written bit */ > SET_FUSEARRAY_BIT(s->fuse_wo, s->pa, s->paio, WRITTEN_BIT_ON); > } > @@ -168,16 +186,48 @@ static const MemoryRegionOps sifive_u_otp_ops = { > > static Property sifive_u_otp_properties[] = { > DEFINE_PROP_UINT32("serial", SiFiveUOTPState, serial, 0), > + DEFINE_PROP_DRIVE("drive", SiFiveUOTPState, blk), > DEFINE_PROP_END_OF_LIST(), > }; > > static void sifive_u_otp_realize(DeviceState *dev, Error **errp) > { > SiFiveUOTPState *s = SIFIVE_U_OTP(dev); > + DriveInfo *dinfo; > > memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_u_otp_ops, s, > TYPE_SIFIVE_U_OTP, SIFIVE_U_OTP_REG_SIZE); > sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); > + > + dinfo = drive_get_next(IF_NONE); > + if (dinfo) { > + int ret; > + uint64_t perm; > + int filesize; > + BlockBackend *blk; > + > + blk = blk_by_legacy_dinfo(dinfo); I think this should be: blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL; > + filesize = SIFIVE_U_OTP_NUM_FUSES * SIFIVE_U_OTP_FUSE_WORD; > + if (blk_getlength(blk) < filesize) { > + qemu_log_mask(LOG_GUEST_ERROR, "OTP drive size < 16K\n"); You should probably be setting errp instead. If a user specified a -drive argument, they probably want to error if we aren't going to use it. > + return; > + } > + > + qdev_prop_set_drive(dev, "drive", blk); > + > + perm = BLK_PERM_CONSISTENT_READ | > + (blk_is_read_only(s->blk) ? 0 : BLK_PERM_WRITE); > + ret = blk_set_perm(s->blk, perm, BLK_PERM_ALL, errp); > + if (ret < 0) { > + qemu_log_mask(LOG_GUEST_ERROR, "set perm error."); Is it worth printing the error? > + } > + > + if (blk_pread(s->blk, 0, s->fuse, filesize) != filesize) { > + qemu_log_mask(LOG_GUEST_ERROR, > + "failed to read the initial flash content"); > + return; You don't need a return here. Is this error fatal? Alistair > + } > + } > } > > static void sifive_u_otp_reset(DeviceState *dev) > diff --git a/include/hw/riscv/sifive_u_otp.h b/include/hw/riscv/sifive_u_otp.h > index 4a5a0acf48..9bc781fd4f 100644 > --- a/include/hw/riscv/sifive_u_otp.h > +++ b/include/hw/riscv/sifive_u_otp.h > @@ -45,6 +45,7 @@ > > #define SIFIVE_U_OTP_PA_MASK 0xfff > #define SIFIVE_U_OTP_NUM_FUSES 0x1000 > +#define SIFIVE_U_OTP_FUSE_WORD 4 > #define SIFIVE_U_OTP_SERIAL_ADDR 0xfc > > #define SIFIVE_U_OTP_REG_SIZE 0x1000 > @@ -78,6 +79,7 @@ typedef struct SiFiveUOTPState { > uint32_t fuse_wo[SIFIVE_U_OTP_NUM_FUSES]; > /* config */ > uint32_t serial; > + BlockBackend *blk; > } SiFiveUOTPState; > > #endif /* HW_SIFIVE_U_OTP_H */ > -- > 2.17.1 > >