Message ID | 20230118024214.14413-4-peter@pjd.dev (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | hw/nvram/eeprom_at24c: Cleanup + FRUID EEPROM init example | expand |
On 1/18/23 03:42, Peter Delevoryas wrote: > Allows users to specify binary data to initialize an EEPROM, allowing users to > emulate data programmed at manufacturing time. > > - Added init_rom and init_rom_size attributes to TYPE_AT24C_EE > - Added at24c_eeprom_init_rom helper function to initialize attributes > - If -drive property is provided, it overrides init_rom data > > Signed-off-by: Peter Delevoryas <peter@pjd.dev> > Reviewed-by: Joel Stanley <joel@jms.id.au> Reviewed-by: Cédric Le Goater <clg@kaod.org> Thanks, C. > --- > hw/nvram/eeprom_at24c.c | 37 ++++++++++++++++++++++++++++----- > include/hw/nvram/eeprom_at24c.h | 16 ++++++++++++++ > 2 files changed, 48 insertions(+), 5 deletions(-) > > diff --git a/hw/nvram/eeprom_at24c.c b/hw/nvram/eeprom_at24c.c > index 98857e3626b9..f8d751fa278d 100644 > --- a/hw/nvram/eeprom_at24c.c > +++ b/hw/nvram/eeprom_at24c.c > @@ -50,6 +50,9 @@ struct EEPROMState { > uint8_t *mem; > > BlockBackend *blk; > + > + const uint8_t *init_rom; > + uint32_t init_rom_size; > }; > > static > @@ -131,19 +134,38 @@ int at24c_eeprom_send(I2CSlave *s, uint8_t data) > > I2CSlave *at24c_eeprom_init(I2CBus *bus, uint8_t address, uint32_t rom_size) > { > - I2CSlave *i2c_dev = i2c_slave_new(TYPE_AT24C_EE, address); > - DeviceState *dev = DEVICE(i2c_dev); > + return at24c_eeprom_init_rom(bus, address, rom_size, NULL, 0); > +} > + > +I2CSlave *at24c_eeprom_init_rom(I2CBus *bus, uint8_t address, uint32_t rom_size, > + const uint8_t *init_rom, uint32_t init_rom_size) > +{ > + EEPROMState *s; > + > + s = AT24C_EE(qdev_new(TYPE_AT24C_EE)); > + > + qdev_prop_set_uint8(DEVICE(s), "address", address); > + qdev_prop_set_uint32(DEVICE(s), "rom-size", rom_size); > > - qdev_prop_set_uint32(dev, "rom-size", rom_size); > - i2c_slave_realize_and_unref(i2c_dev, bus, &error_abort); > + /* TODO: Model init_rom with QOM properties. */ > + s->init_rom = init_rom; > + s->init_rom_size = init_rom_size; > > - return i2c_dev; > + i2c_slave_realize_and_unref(I2C_SLAVE(s), bus, &error_abort); > + > + return I2C_SLAVE(s); > } > > static void at24c_eeprom_realize(DeviceState *dev, Error **errp) > { > EEPROMState *ee = AT24C_EE(dev); > > + if (ee->init_rom_size > ee->rsize) { > + error_setg(errp, "%s: init rom is larger than rom: %u > %u", > + TYPE_AT24C_EE, ee->init_rom_size, ee->rsize); > + return; > + } > + > if (ee->blk) { > int64_t len = blk_getlength(ee->blk); > > @@ -163,6 +185,7 @@ static void at24c_eeprom_realize(DeviceState *dev, Error **errp) > } > > ee->mem = g_malloc0(ee->rsize); > + > } > > static > @@ -176,6 +199,10 @@ void at24c_eeprom_reset(DeviceState *state) > > memset(ee->mem, 0, ee->rsize); > > + if (ee->init_rom) { > + memcpy(ee->mem, ee->init_rom, MIN(ee->init_rom_size, ee->rsize)); > + } > + > if (ee->blk) { > int ret = blk_pread(ee->blk, 0, ee->rsize, ee->mem, 0); > > diff --git a/include/hw/nvram/eeprom_at24c.h b/include/hw/nvram/eeprom_at24c.h > index 196db309d451..acb9857b2add 100644 > --- a/include/hw/nvram/eeprom_at24c.h > +++ b/include/hw/nvram/eeprom_at24c.h > @@ -20,4 +20,20 @@ > */ > I2CSlave *at24c_eeprom_init(I2CBus *bus, uint8_t address, uint32_t rom_size); > > + > +/* > + * Create and realize an AT24C EEPROM device on the heap with initial data. > + * @bus: I2C bus to put it on > + * @address: I2C address of the EEPROM slave when put on a bus > + * @rom_size: size of the EEPROM > + * @init_rom: Array of bytes to initialize EEPROM memory with > + * @init_rom_size: Size of @init_rom, must be less than or equal to @rom_size > + * > + * Create the device state structure, initialize it, put it on the specified > + * @bus, and drop the reference to it (the device is realized). Copies the data > + * from @init_rom to the beginning of the EEPROM memory buffer. > + */ > +I2CSlave *at24c_eeprom_init_rom(I2CBus *bus, uint8_t address, uint32_t rom_size, > + const uint8_t *init_rom, uint32_t init_rom_size); > + > #endif
On Wed, Jan 25, 2023 at 04:53:20PM +0000, Ninad S Palsule wrote: > Signed-off-by: Peter Delevoryas peter@pjd.dev<mailto:peter@pjd.dev> > Reviewed-by: Joel Stanley joel@jms.id.au<mailto:joel@jms.id.au> > > Tested-by: Ninad Palsule ninadpalsule@us.ibm.com<mailto:ninadpalsule@us.ibm.com> > > Hi Peter, > I applied your patches and made sure that different EEPROM images can be loaded from > appropriate image files and it is working as expected. Thanks Ninad, this is a good regression test to make sure I didn't break the existing drive proprerty. - Peter > > # Used following command to invoke the qemu. > qemu-system-arm -M rainier-bmc -nographic \ > -kernel fitImage-linux.bin \ > -dtb aspeed-bmc-ibm-rainier.dtb \ > -initrd obmc-phosphor-initramfs.rootfs.cpio.xz \ > -drive file=obmc-phosphor-image.rootfs.wic.qcow2,if=sd,index=2 \ > -append "rootwait console=ttyS4,115200n8 root=PARTLABEL=rofs-a" \ > -device at24c-eeprom,bus=aspeed.i2c.bus.0,address=0x51,drive=a,rom-size=32768 -drive file=tpm.eeprom.bin,format=raw,if=none,id=a \ > -device at24c-eeprom,bus=aspeed.i2c.bus.7,address=0x50,drive=b,rom-size=65536 -drive file=oppanel.eeprom.bin,format=raw,if=none,id=b \ > -device at24c-eeprom,bus=aspeed.i2c.bus.7,address=0x51,drive=c,rom-size=65536 -drive file=lcd.eeprom.bin,format=raw,if=none,id=c \ > -device at24c-eeprom,bus=aspeed.i2c.bus.8,address=0x50,drive=d,rom-size=65536 -drive file=baseboard.eeprom.bin,format=raw,if=none,id=d \ > -device at24c-eeprom,bus=aspeed.i2c.bus.8,address=0x51,drive=e,rom-size=65536 -drive file=bmc.eeprom.bin,format=raw,if=none,id=e \ > -device at24c-eeprom,bus=aspeed.i2c.bus.9,address=0x50,drive=f,rom-size=131072 -drive file=vrm.eeprom.bin,format=raw,if=none,id=f \ > -device at24c-eeprom,bus=aspeed.i2c.bus.10,address=0x50,drive=g,rom-size=131072 -drive file=vrm.eeprom.bin,format=raw,if=none,id=g \ > -device at24c-eeprom,bus=aspeed.i2c.bus.13,address=0x50,drive=h,rom-size=65536 -drive file=nvme.eeprom.bin,format=raw,if=none,id=h \ > -device at24c-eeprom,bus=aspeed.i2c.bus.14,address=0x50,drive=i,rom-size=65536 -drive file=nvme.eeprom.bin,format=raw,if=none,id=i \ > -device at24c-eeprom,bus=aspeed.i2c.bus.15,address=0x50,drive=j,rom-size=65536 -drive file=nvme.eeprom.bin,format=raw,if=none,id=j
On Tue, Jan 17, 2023 at 06:42:12PM -0800, Peter Delevoryas wrote: > Allows users to specify binary data to initialize an EEPROM, allowing users to > emulate data programmed at manufacturing time. > > - Added init_rom and init_rom_size attributes to TYPE_AT24C_EE > - Added at24c_eeprom_init_rom helper function to initialize attributes > - If -drive property is provided, it overrides init_rom data > > Signed-off-by: Peter Delevoryas <peter@pjd.dev> > Reviewed-by: Joel Stanley <joel@jms.id.au> > --- > hw/nvram/eeprom_at24c.c | 37 ++++++++++++++++++++++++++++----- > include/hw/nvram/eeprom_at24c.h | 16 ++++++++++++++ > 2 files changed, 48 insertions(+), 5 deletions(-) > > diff --git a/hw/nvram/eeprom_at24c.c b/hw/nvram/eeprom_at24c.c > index 98857e3626b9..f8d751fa278d 100644 > --- a/hw/nvram/eeprom_at24c.c > +++ b/hw/nvram/eeprom_at24c.c > @@ -50,6 +50,9 @@ struct EEPROMState { > uint8_t *mem; > > BlockBackend *blk; > + > + const uint8_t *init_rom; > + uint32_t init_rom_size; > }; > > static > @@ -131,19 +134,38 @@ int at24c_eeprom_send(I2CSlave *s, uint8_t data) > > I2CSlave *at24c_eeprom_init(I2CBus *bus, uint8_t address, uint32_t rom_size) > { > - I2CSlave *i2c_dev = i2c_slave_new(TYPE_AT24C_EE, address); > - DeviceState *dev = DEVICE(i2c_dev); > + return at24c_eeprom_init_rom(bus, address, rom_size, NULL, 0); > +} > + > +I2CSlave *at24c_eeprom_init_rom(I2CBus *bus, uint8_t address, uint32_t rom_size, > + const uint8_t *init_rom, uint32_t init_rom_size) > +{ > + EEPROMState *s; > + > + s = AT24C_EE(qdev_new(TYPE_AT24C_EE)); > + > + qdev_prop_set_uint8(DEVICE(s), "address", address); Why did you switch from using i2c_slave_new()? Using it is more documentation and future-proofing than convenience. Other than that, looks good to me. Reviewed-by: Corey Minyard <cminyard@mvista.com> > + qdev_prop_set_uint32(DEVICE(s), "rom-size", rom_size); > > - qdev_prop_set_uint32(dev, "rom-size", rom_size); > - i2c_slave_realize_and_unref(i2c_dev, bus, &error_abort); > + /* TODO: Model init_rom with QOM properties. */ > + s->init_rom = init_rom; > + s->init_rom_size = init_rom_size; > > - return i2c_dev; > + i2c_slave_realize_and_unref(I2C_SLAVE(s), bus, &error_abort); > + > + return I2C_SLAVE(s); > } > > static void at24c_eeprom_realize(DeviceState *dev, Error **errp) > { > EEPROMState *ee = AT24C_EE(dev); > > + if (ee->init_rom_size > ee->rsize) { > + error_setg(errp, "%s: init rom is larger than rom: %u > %u", > + TYPE_AT24C_EE, ee->init_rom_size, ee->rsize); > + return; > + } > + > if (ee->blk) { > int64_t len = blk_getlength(ee->blk); > > @@ -163,6 +185,7 @@ static void at24c_eeprom_realize(DeviceState *dev, Error **errp) > } > > ee->mem = g_malloc0(ee->rsize); > + > } > > static > @@ -176,6 +199,10 @@ void at24c_eeprom_reset(DeviceState *state) > > memset(ee->mem, 0, ee->rsize); > > + if (ee->init_rom) { > + memcpy(ee->mem, ee->init_rom, MIN(ee->init_rom_size, ee->rsize)); > + } > + > if (ee->blk) { > int ret = blk_pread(ee->blk, 0, ee->rsize, ee->mem, 0); > > diff --git a/include/hw/nvram/eeprom_at24c.h b/include/hw/nvram/eeprom_at24c.h > index 196db309d451..acb9857b2add 100644 > --- a/include/hw/nvram/eeprom_at24c.h > +++ b/include/hw/nvram/eeprom_at24c.h > @@ -20,4 +20,20 @@ > */ > I2CSlave *at24c_eeprom_init(I2CBus *bus, uint8_t address, uint32_t rom_size); > > + > +/* > + * Create and realize an AT24C EEPROM device on the heap with initial data. > + * @bus: I2C bus to put it on > + * @address: I2C address of the EEPROM slave when put on a bus > + * @rom_size: size of the EEPROM > + * @init_rom: Array of bytes to initialize EEPROM memory with > + * @init_rom_size: Size of @init_rom, must be less than or equal to @rom_size > + * > + * Create the device state structure, initialize it, put it on the specified > + * @bus, and drop the reference to it (the device is realized). Copies the data > + * from @init_rom to the beginning of the EEPROM memory buffer. > + */ > +I2CSlave *at24c_eeprom_init_rom(I2CBus *bus, uint8_t address, uint32_t rom_size, > + const uint8_t *init_rom, uint32_t init_rom_size); > + > #endif > -- > 2.39.0 > >
On Wed, Jan 25, 2023 at 03:36:23PM -0600, Corey Minyard wrote: > On Tue, Jan 17, 2023 at 06:42:12PM -0800, Peter Delevoryas wrote: > > Allows users to specify binary data to initialize an EEPROM, allowing users to > > emulate data programmed at manufacturing time. > > > > - Added init_rom and init_rom_size attributes to TYPE_AT24C_EE > > - Added at24c_eeprom_init_rom helper function to initialize attributes > > - If -drive property is provided, it overrides init_rom data > > > > Signed-off-by: Peter Delevoryas <peter@pjd.dev> > > Reviewed-by: Joel Stanley <joel@jms.id.au> > > --- > > hw/nvram/eeprom_at24c.c | 37 ++++++++++++++++++++++++++++----- > > include/hw/nvram/eeprom_at24c.h | 16 ++++++++++++++ > > 2 files changed, 48 insertions(+), 5 deletions(-) > > > > diff --git a/hw/nvram/eeprom_at24c.c b/hw/nvram/eeprom_at24c.c > > index 98857e3626b9..f8d751fa278d 100644 > > --- a/hw/nvram/eeprom_at24c.c > > +++ b/hw/nvram/eeprom_at24c.c > > @@ -50,6 +50,9 @@ struct EEPROMState { > > uint8_t *mem; > > > > BlockBackend *blk; > > + > > + const uint8_t *init_rom; > > + uint32_t init_rom_size; > > }; > > > > static > > @@ -131,19 +134,38 @@ int at24c_eeprom_send(I2CSlave *s, uint8_t data) > > > > I2CSlave *at24c_eeprom_init(I2CBus *bus, uint8_t address, uint32_t rom_size) > > { > > - I2CSlave *i2c_dev = i2c_slave_new(TYPE_AT24C_EE, address); > > - DeviceState *dev = DEVICE(i2c_dev); > > + return at24c_eeprom_init_rom(bus, address, rom_size, NULL, 0); > > +} > > + > > +I2CSlave *at24c_eeprom_init_rom(I2CBus *bus, uint8_t address, uint32_t rom_size, > > + const uint8_t *init_rom, uint32_t init_rom_size) > > +{ > > + EEPROMState *s; > > + > > + s = AT24C_EE(qdev_new(TYPE_AT24C_EE)); > > + > > + qdev_prop_set_uint8(DEVICE(s), "address", address); > > Why did you switch from using i2c_slave_new()? Using it is more > documentation and future-proofing than convenience. Oh, yeah that's my bad. I was probably doing it so that all the qdev_prop_set calls to the object are in the same place, but I probably should have just kept i2c_slave_new() and initialized only the at24c-eeprom properties here, instead of initializing the I2CSlave ones too. - Peter > > Other than that, looks good to me. > > Reviewed-by: Corey Minyard <cminyard@mvista.com> > > > + qdev_prop_set_uint32(DEVICE(s), "rom-size", rom_size); > > > > - qdev_prop_set_uint32(dev, "rom-size", rom_size); > > - i2c_slave_realize_and_unref(i2c_dev, bus, &error_abort); > > + /* TODO: Model init_rom with QOM properties. */ > > + s->init_rom = init_rom; > > + s->init_rom_size = init_rom_size; > > > > - return i2c_dev; > > + i2c_slave_realize_and_unref(I2C_SLAVE(s), bus, &error_abort); > > + > > + return I2C_SLAVE(s); > > } > > > > static void at24c_eeprom_realize(DeviceState *dev, Error **errp) > > { > > EEPROMState *ee = AT24C_EE(dev); > > > > + if (ee->init_rom_size > ee->rsize) { > > + error_setg(errp, "%s: init rom is larger than rom: %u > %u", > > + TYPE_AT24C_EE, ee->init_rom_size, ee->rsize); > > + return; > > + } > > + > > if (ee->blk) { > > int64_t len = blk_getlength(ee->blk); > > > > @@ -163,6 +185,7 @@ static void at24c_eeprom_realize(DeviceState *dev, Error **errp) > > } > > > > ee->mem = g_malloc0(ee->rsize); > > + > > } > > > > static > > @@ -176,6 +199,10 @@ void at24c_eeprom_reset(DeviceState *state) > > > > memset(ee->mem, 0, ee->rsize); > > > > + if (ee->init_rom) { > > + memcpy(ee->mem, ee->init_rom, MIN(ee->init_rom_size, ee->rsize)); > > + } > > + > > if (ee->blk) { > > int ret = blk_pread(ee->blk, 0, ee->rsize, ee->mem, 0); > > > > diff --git a/include/hw/nvram/eeprom_at24c.h b/include/hw/nvram/eeprom_at24c.h > > index 196db309d451..acb9857b2add 100644 > > --- a/include/hw/nvram/eeprom_at24c.h > > +++ b/include/hw/nvram/eeprom_at24c.h > > @@ -20,4 +20,20 @@ > > */ > > I2CSlave *at24c_eeprom_init(I2CBus *bus, uint8_t address, uint32_t rom_size); > > > > + > > +/* > > + * Create and realize an AT24C EEPROM device on the heap with initial data. > > + * @bus: I2C bus to put it on > > + * @address: I2C address of the EEPROM slave when put on a bus > > + * @rom_size: size of the EEPROM > > + * @init_rom: Array of bytes to initialize EEPROM memory with > > + * @init_rom_size: Size of @init_rom, must be less than or equal to @rom_size > > + * > > + * Create the device state structure, initialize it, put it on the specified > > + * @bus, and drop the reference to it (the device is realized). Copies the data > > + * from @init_rom to the beginning of the EEPROM memory buffer. > > + */ > > +I2CSlave *at24c_eeprom_init_rom(I2CBus *bus, uint8_t address, uint32_t rom_size, > > + const uint8_t *init_rom, uint32_t init_rom_size); > > + > > #endif > > -- > > 2.39.0 > > > >
>>> I2CSlave *at24c_eeprom_init(I2CBus *bus, uint8_t address, uint32_t rom_size) >>> { >>> - I2CSlave *i2c_dev = i2c_slave_new(TYPE_AT24C_EE, address); >>> - DeviceState *dev = DEVICE(i2c_dev); >>> + return at24c_eeprom_init_rom(bus, address, rom_size, NULL, 0); >>> +} >>> + >>> +I2CSlave *at24c_eeprom_init_rom(I2CBus *bus, uint8_t address, uint32_t rom_size, >>> + const uint8_t *init_rom, uint32_t init_rom_size) >>> +{ >>> + EEPROMState *s; >>> + >>> + s = AT24C_EE(qdev_new(TYPE_AT24C_EE)); >>> + >>> + qdev_prop_set_uint8(DEVICE(s), "address", address); >> >> Why did you switch from using i2c_slave_new()? Using it is more >> documentation and future-proofing than convenience. > > Oh, yeah that's my bad. I was probably doing it so that all the qdev_prop_set > calls to the object are in the same place, but I probably should have just kept > i2c_slave_new() and initialized only the at24c-eeprom properties here, instead > of initializing the I2CSlave ones too. Will you send a v5 ? Thanks, C.
On Fri, Jan 27, 2023 at 08:42:40AM +0100, Cédric Le Goater wrote: > > > > I2CSlave *at24c_eeprom_init(I2CBus *bus, uint8_t address, uint32_t rom_size) > > > > { > > > > - I2CSlave *i2c_dev = i2c_slave_new(TYPE_AT24C_EE, address); > > > > - DeviceState *dev = DEVICE(i2c_dev); > > > > + return at24c_eeprom_init_rom(bus, address, rom_size, NULL, 0); > > > > +} > > > > + > > > > +I2CSlave *at24c_eeprom_init_rom(I2CBus *bus, uint8_t address, uint32_t rom_size, > > > > + const uint8_t *init_rom, uint32_t init_rom_size) > > > > +{ > > > > + EEPROMState *s; > > > > + > > > > + s = AT24C_EE(qdev_new(TYPE_AT24C_EE)); > > > > + > > > > + qdev_prop_set_uint8(DEVICE(s), "address", address); > > > > > > Why did you switch from using i2c_slave_new()? Using it is more > > > documentation and future-proofing than convenience. > > > > Oh, yeah that's my bad. I was probably doing it so that all the qdev_prop_set > > calls to the object are in the same place, but I probably should have just kept > > i2c_slave_new() and initialized only the at24c-eeprom properties here, instead > > of initializing the I2CSlave ones too. > > Will you send a v5 ? Oh! Yeah sure: I thought I had already missed the boat because I thought you sent a pull request, but I see that it hasn't been pulled yet. - Peter > > Thanks, > > C.
diff --git a/hw/nvram/eeprom_at24c.c b/hw/nvram/eeprom_at24c.c index 98857e3626b9..f8d751fa278d 100644 --- a/hw/nvram/eeprom_at24c.c +++ b/hw/nvram/eeprom_at24c.c @@ -50,6 +50,9 @@ struct EEPROMState { uint8_t *mem; BlockBackend *blk; + + const uint8_t *init_rom; + uint32_t init_rom_size; }; static @@ -131,19 +134,38 @@ int at24c_eeprom_send(I2CSlave *s, uint8_t data) I2CSlave *at24c_eeprom_init(I2CBus *bus, uint8_t address, uint32_t rom_size) { - I2CSlave *i2c_dev = i2c_slave_new(TYPE_AT24C_EE, address); - DeviceState *dev = DEVICE(i2c_dev); + return at24c_eeprom_init_rom(bus, address, rom_size, NULL, 0); +} + +I2CSlave *at24c_eeprom_init_rom(I2CBus *bus, uint8_t address, uint32_t rom_size, + const uint8_t *init_rom, uint32_t init_rom_size) +{ + EEPROMState *s; + + s = AT24C_EE(qdev_new(TYPE_AT24C_EE)); + + qdev_prop_set_uint8(DEVICE(s), "address", address); + qdev_prop_set_uint32(DEVICE(s), "rom-size", rom_size); - qdev_prop_set_uint32(dev, "rom-size", rom_size); - i2c_slave_realize_and_unref(i2c_dev, bus, &error_abort); + /* TODO: Model init_rom with QOM properties. */ + s->init_rom = init_rom; + s->init_rom_size = init_rom_size; - return i2c_dev; + i2c_slave_realize_and_unref(I2C_SLAVE(s), bus, &error_abort); + + return I2C_SLAVE(s); } static void at24c_eeprom_realize(DeviceState *dev, Error **errp) { EEPROMState *ee = AT24C_EE(dev); + if (ee->init_rom_size > ee->rsize) { + error_setg(errp, "%s: init rom is larger than rom: %u > %u", + TYPE_AT24C_EE, ee->init_rom_size, ee->rsize); + return; + } + if (ee->blk) { int64_t len = blk_getlength(ee->blk); @@ -163,6 +185,7 @@ static void at24c_eeprom_realize(DeviceState *dev, Error **errp) } ee->mem = g_malloc0(ee->rsize); + } static @@ -176,6 +199,10 @@ void at24c_eeprom_reset(DeviceState *state) memset(ee->mem, 0, ee->rsize); + if (ee->init_rom) { + memcpy(ee->mem, ee->init_rom, MIN(ee->init_rom_size, ee->rsize)); + } + if (ee->blk) { int ret = blk_pread(ee->blk, 0, ee->rsize, ee->mem, 0); diff --git a/include/hw/nvram/eeprom_at24c.h b/include/hw/nvram/eeprom_at24c.h index 196db309d451..acb9857b2add 100644 --- a/include/hw/nvram/eeprom_at24c.h +++ b/include/hw/nvram/eeprom_at24c.h @@ -20,4 +20,20 @@ */ I2CSlave *at24c_eeprom_init(I2CBus *bus, uint8_t address, uint32_t rom_size); + +/* + * Create and realize an AT24C EEPROM device on the heap with initial data. + * @bus: I2C bus to put it on + * @address: I2C address of the EEPROM slave when put on a bus + * @rom_size: size of the EEPROM + * @init_rom: Array of bytes to initialize EEPROM memory with + * @init_rom_size: Size of @init_rom, must be less than or equal to @rom_size + * + * Create the device state structure, initialize it, put it on the specified + * @bus, and drop the reference to it (the device is realized). Copies the data + * from @init_rom to the beginning of the EEPROM memory buffer. + */ +I2CSlave *at24c_eeprom_init_rom(I2CBus *bus, uint8_t address, uint32_t rom_size, + const uint8_t *init_rom, uint32_t init_rom_size); + #endif