diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index 73b0a813a7..6e6414b723 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -252,7 +252,8 @@ static void fw_cfg_write(FWCfgState *s, uint8_t value) static int fw_cfg_select(FWCfgState *s, uint16_t key) { - int ret; + int arch, ret; + FWCfgEntry *e; s->cur_offset = 0; if ((key & FW_CFG_ENTRY_MASK) >= FW_CFG_MAX_ENTRY) { @@ -261,6 +262,12 @@ static int fw_cfg_select(FWCfgState *s, uint16_t key) } else { s->cur_entry = key; ret = 1; + /* entry successfully selected, now run callback if present */ + arch = !!(key & FW_CFG_ARCH_LOCAL); + e = &s->entries[arch][key & FW_CFG_ENTRY_MASK]; + if (e->read_callback) { + e->read_callback(e->callback_opaque, s->cur_offset); + } } trace_fw_cfg_select(s, key, ret); @@ -276,9 +283,6 @@ static uint8_t fw_cfg_read(FWCfgState *s) if (s->cur_entry == FW_CFG_INVALID || !e->data || s->cur_offset >= e->len) ret = 0; else { - if (e->read_callback) { - e->read_callback(e->callback_opaque, s->cur_offset); - } ret = e->data[s->cur_offset++]; } @@ -371,10 +375,6 @@ static void fw_cfg_dma_transfer(FWCfgState *s) len = (e->len - s->cur_offset); } - if (e->read_callback) { - e->read_callback(e->callback_opaque, s->cur_offset); - } - /* If the access is not a read access, it will be a skip access, * tested before. */ @@ -513,7 +513,8 @@ static void fw_cfg_reset(DeviceState *d) { FWCfgState *s = FW_CFG(d); - fw_cfg_select(s, 0); + /* we never register a read callback for FW_CFG_SIGNATURE */ + fw_cfg_select(s, FW_CFG_SIGNATURE); } /* Save restore 32 bit int as uint16_t diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h index 4b5e196d17..a1cfaa4a2f 100644 --- a/include/hw/nvram/fw_cfg.h +++ b/include/hw/nvram/fw_cfg.h @@ -183,13 +183,9 @@ void fw_cfg_add_file(FWCfgState *s, const char *filename, void *data, * structure residing at key value FW_CFG_FILE_DIR, containing the item name, * data size, and assigned selector key value. * Additionally, set a callback function (and argument) to be called each - * time a byte is read by the guest from this particular item, or, in the - * case of DMA, each time a read or skip request overlaps with the valid - * offset range of the item. - * NOTE: In addition to the opaque argument set here, the callback function - * takes the current data offset as an additional argument, allowing it the - * option of only acting upon specific offset values (e.g., 0, before the - * first data byte of the selected item is returned to the guest). + * time this item is selected (by having its selector key either written to + * the fw_cfg control register, or passed to QEMU in FWCfgDmaAccess.control + * with FW_CFG_DMA_CTL_SELECT). */ void fw_cfg_add_file_callback(FWCfgState *s, const char *filename, FWCfgReadCallback callback, void *callback_opaque,