aboutsummaryrefslogtreecommitdiff
path: root/hw/nvram/eeprom_at24c.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/nvram/eeprom_at24c.c')
-rw-r--r--hw/nvram/eeprom_at24c.c58
1 files changed, 47 insertions, 11 deletions
diff --git a/hw/nvram/eeprom_at24c.c b/hw/nvram/eeprom_at24c.c
index 2d4d8b952f..3328c32814 100644
--- a/hw/nvram/eeprom_at24c.c
+++ b/hw/nvram/eeprom_at24c.c
@@ -12,6 +12,7 @@
#include "qapi/error.h"
#include "qemu/module.h"
#include "hw/i2c/i2c.h"
+#include "hw/nvram/eeprom_at24c.h"
#include "hw/qdev-properties.h"
#include "hw/qdev-properties-system.h"
#include "sysemu/block-backend.h"
@@ -49,6 +50,9 @@ struct EEPROMState {
uint8_t *mem;
BlockBackend *blk;
+
+ const uint8_t *init_rom;
+ uint32_t init_rom_size;
};
static
@@ -128,10 +132,39 @@ int at24c_eeprom_send(I2CSlave *s, uint8_t data)
return 0;
}
+I2CSlave *at24c_eeprom_init(I2CBus *bus, uint8_t address, uint32_t rom_size)
+{
+ 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(i2c_slave_new(TYPE_AT24C_EE, address));
+
+ qdev_prop_set_uint32(DEVICE(s), "rom-size", rom_size);
+
+ /* TODO: Model init_rom with QOM properties. */
+ s->init_rom = init_rom;
+ s->init_rom_size = init_rom_size;
+
+ 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);
@@ -151,19 +184,12 @@ static void at24c_eeprom_realize(DeviceState *dev, Error **errp)
}
ee->mem = g_malloc0(ee->rsize);
-}
-
-static
-void at24c_eeprom_reset(DeviceState *state)
-{
- EEPROMState *ee = AT24C_EE(state);
-
- ee->changed = false;
- ee->cur = 0;
- ee->haveaddr = 0;
-
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);
@@ -175,6 +201,16 @@ void at24c_eeprom_reset(DeviceState *state)
}
}
+static
+void at24c_eeprom_reset(DeviceState *state)
+{
+ EEPROMState *ee = AT24C_EE(state);
+
+ ee->changed = false;
+ ee->cur = 0;
+ ee->haveaddr = 0;
+}
+
static Property at24c_eeprom_props[] = {
DEFINE_PROP_UINT32("rom-size", EEPROMState, rsize, 0),
DEFINE_PROP_BOOL("writable", EEPROMState, writable, true),