2008-09-18 20:27:29 +02:00
|
|
|
#ifndef FW_CFG_H
|
|
|
|
#define FW_CFG_H
|
|
|
|
|
2013-04-26 05:24:43 +02:00
|
|
|
#include "exec/hwaddr.h"
|
2016-03-10 14:09:58 +01:00
|
|
|
#include "hw/nvram/fw_cfg_keys.h"
|
2013-04-26 05:24:43 +02:00
|
|
|
|
2009-12-18 12:01:10 +01:00
|
|
|
typedef struct FWCfgFile {
|
|
|
|
uint32_t size; /* file size */
|
|
|
|
uint16_t select; /* write this to 0x510 to read it */
|
|
|
|
uint16_t reserved;
|
2013-07-24 17:56:05 +02:00
|
|
|
char name[FW_CFG_MAX_FILE_PATH];
|
2009-12-18 12:01:10 +01:00
|
|
|
} FWCfgFile;
|
|
|
|
|
2016-04-07 16:12:58 +02:00
|
|
|
#define FW_CFG_ORDER_OVERRIDE_VGA 70
|
|
|
|
#define FW_CFG_ORDER_OVERRIDE_NIC 80
|
|
|
|
#define FW_CFG_ORDER_OVERRIDE_USER 100
|
|
|
|
#define FW_CFG_ORDER_OVERRIDE_DEVICE 110
|
|
|
|
|
|
|
|
void fw_cfg_set_order_override(FWCfgState *fw_cfg, int order);
|
|
|
|
void fw_cfg_reset_order_override(FWCfgState *fw_cfg);
|
|
|
|
|
2009-12-18 12:01:10 +01:00
|
|
|
typedef struct FWCfgFiles {
|
|
|
|
uint32_t count;
|
|
|
|
FWCfgFile f[];
|
|
|
|
} FWCfgFiles;
|
|
|
|
|
2015-10-08 17:02:55 +02:00
|
|
|
/* Control as first field allows for different structures selected by this
|
|
|
|
* field, which might be useful in the future
|
|
|
|
*/
|
|
|
|
typedef struct FWCfgDmaAccess {
|
|
|
|
uint32_t control;
|
|
|
|
uint32_t length;
|
|
|
|
uint64_t address;
|
|
|
|
} QEMU_PACKED FWCfgDmaAccess;
|
|
|
|
|
2015-11-05 15:32:49 +01:00
|
|
|
typedef void (*FWCfgReadCallback)(void *opaque);
|
2008-09-18 20:27:29 +02:00
|
|
|
|
2015-11-05 15:32:47 +01:00
|
|
|
/**
|
|
|
|
* fw_cfg_add_bytes:
|
|
|
|
* @s: fw_cfg device being modified
|
|
|
|
* @key: selector key value for new fw_cfg item
|
|
|
|
* @data: pointer to start of item data
|
|
|
|
* @len: size of item data
|
|
|
|
*
|
|
|
|
* Add a new fw_cfg item, available by selecting the given key, as a raw
|
|
|
|
* "blob" of the given size. The data referenced by the starting pointer
|
|
|
|
* is only linked, NOT copied, into the data structure of the fw_cfg device.
|
|
|
|
*/
|
2013-01-16 14:50:28 +01:00
|
|
|
void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len);
|
2015-11-05 15:32:47 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* fw_cfg_add_string:
|
|
|
|
* @s: fw_cfg device being modified
|
|
|
|
* @key: selector key value for new fw_cfg item
|
|
|
|
* @value: NUL-terminated ascii string
|
|
|
|
*
|
|
|
|
* Add a new fw_cfg item, available by selecting the given key. The item
|
|
|
|
* data will consist of a dynamically allocated copy of the provided string,
|
|
|
|
* including its NUL terminator.
|
|
|
|
*/
|
2013-01-16 14:50:24 +01:00
|
|
|
void fw_cfg_add_string(FWCfgState *s, uint16_t key, const char *value);
|
2015-11-05 15:32:47 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* fw_cfg_add_i16:
|
|
|
|
* @s: fw_cfg device being modified
|
|
|
|
* @key: selector key value for new fw_cfg item
|
|
|
|
* @value: 16-bit integer
|
|
|
|
*
|
|
|
|
* Add a new fw_cfg item, available by selecting the given key. The item
|
|
|
|
* data will consist of a dynamically allocated copy of the given 16-bit
|
|
|
|
* value, converted to little-endian representation.
|
|
|
|
*/
|
2013-01-16 14:50:23 +01:00
|
|
|
void fw_cfg_add_i16(FWCfgState *s, uint16_t key, uint16_t value);
|
2015-11-05 15:32:47 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* fw_cfg_modify_i16:
|
|
|
|
* @s: fw_cfg device being modified
|
|
|
|
* @key: selector key value for new fw_cfg item
|
|
|
|
* @value: 16-bit integer
|
|
|
|
*
|
|
|
|
* Replace the fw_cfg item available by selecting the given key. The new
|
|
|
|
* data will consist of a dynamically allocated copy of the given 16-bit
|
|
|
|
* value, converted to little-endian representation. The data being replaced,
|
|
|
|
* assumed to have been dynamically allocated during an earlier call to
|
|
|
|
* either fw_cfg_add_i16() or fw_cfg_modify_i16(), is freed before returning.
|
|
|
|
*/
|
2015-06-08 20:10:44 +02:00
|
|
|
void fw_cfg_modify_i16(FWCfgState *s, uint16_t key, uint16_t value);
|
2015-11-05 15:32:47 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* fw_cfg_add_i32:
|
|
|
|
* @s: fw_cfg device being modified
|
|
|
|
* @key: selector key value for new fw_cfg item
|
|
|
|
* @value: 32-bit integer
|
|
|
|
*
|
|
|
|
* Add a new fw_cfg item, available by selecting the given key. The item
|
|
|
|
* data will consist of a dynamically allocated copy of the given 32-bit
|
|
|
|
* value, converted to little-endian representation.
|
|
|
|
*/
|
2013-01-16 14:50:23 +01:00
|
|
|
void fw_cfg_add_i32(FWCfgState *s, uint16_t key, uint32_t value);
|
2015-11-05 15:32:47 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* fw_cfg_add_i64:
|
|
|
|
* @s: fw_cfg device being modified
|
|
|
|
* @key: selector key value for new fw_cfg item
|
|
|
|
* @value: 64-bit integer
|
|
|
|
*
|
|
|
|
* Add a new fw_cfg item, available by selecting the given key. The item
|
|
|
|
* data will consist of a dynamically allocated copy of the given 64-bit
|
|
|
|
* value, converted to little-endian representation.
|
|
|
|
*/
|
2013-01-16 14:50:23 +01:00
|
|
|
void fw_cfg_add_i64(FWCfgState *s, uint16_t key, uint64_t value);
|
2015-11-05 15:32:47 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* fw_cfg_add_file:
|
|
|
|
* @s: fw_cfg device being modified
|
|
|
|
* @filename: name of new fw_cfg file item
|
|
|
|
* @data: pointer to start of item data
|
|
|
|
* @len: size of item data
|
|
|
|
*
|
|
|
|
* Add a new NAMED fw_cfg item as a raw "blob" of the given size. The data
|
|
|
|
* referenced by the starting pointer is only linked, NOT copied, into the
|
|
|
|
* data structure of the fw_cfg device.
|
|
|
|
* The next available (unused) selector key starting at FW_CFG_FILE_FIRST
|
|
|
|
* will be used; also, a new entry will be added to the file directory
|
|
|
|
* structure residing at key value FW_CFG_FILE_DIR, containing the item name,
|
|
|
|
* data size, and assigned selector key value.
|
|
|
|
*/
|
2013-01-16 14:50:28 +01:00
|
|
|
void fw_cfg_add_file(FWCfgState *s, const char *filename, void *data,
|
|
|
|
size_t len);
|
2015-11-05 15:32:47 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* fw_cfg_add_file_callback:
|
|
|
|
* @s: fw_cfg device being modified
|
|
|
|
* @filename: name of new fw_cfg file item
|
|
|
|
* @callback: callback function
|
|
|
|
* @callback_opaque: argument to be passed into callback function
|
|
|
|
* @data: pointer to start of item data
|
|
|
|
* @len: size of item data
|
|
|
|
*
|
|
|
|
* Add a new NAMED fw_cfg item as a raw "blob" of the given size. The data
|
|
|
|
* referenced by the starting pointer is only linked, NOT copied, into the
|
|
|
|
* data structure of the fw_cfg device.
|
|
|
|
* The next available (unused) selector key starting at FW_CFG_FILE_FIRST
|
|
|
|
* will be used; also, a new entry will be added to the file directory
|
|
|
|
* 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
|
fw_cfg: amend callback behavior spec to once per select
Currently, the fw_cfg internal API specifies that if an item was set up
with a read callback, the callback must be run each time a byte is read
from the item. This behavior is both wasteful (most items do not have a
read callback set), and impractical for bulk transfers (e.g., DMA read).
At the time of this writing, the only items configured with a callback
are "/etc/table-loader", "/etc/acpi/tables", and "/etc/acpi/rsdp". They
all share the same callback functions: virt_acpi_build_update() on ARM
(in hw/arm/virt-acpi-build.c), and acpi_build_update() on i386 (in
hw/i386/acpi.c). Both of these callbacks are one-shot (i.e. they return
without doing anything at all after the first time they are invoked with
a given build_state; since build_state is also shared across all three
items mentioned above, the callback only ever runs *once*, the first
time either of the listed items is read).
This patch amends the specification for fw_cfg_add_file_callback() to
state that any available read callback will only be invoked once each
time the item is selected. This change has no practical effect on the
current behavior of QEMU, and it enables us to significantly optimize
the behavior of fw_cfg reads during guest firmware setup, eliminating
a large amount of redundant callback checks and invocations.
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Marc Marí <markmb@redhat.com>
Signed-off-by: Gabriel Somlo <somlo@cmu.edu>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Message-id: 1446733972-1602-3-git-send-email-somlo@cmu.edu
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
2015-11-05 15:32:48 +01:00
|
|
|
* 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).
|
2015-11-05 15:32:47 +01:00
|
|
|
*/
|
2013-09-01 16:56:20 +02:00
|
|
|
void fw_cfg_add_file_callback(FWCfgState *s, const char *filename,
|
|
|
|
FWCfgReadCallback callback, void *callback_opaque,
|
|
|
|
void *data, size_t len);
|
2015-11-05 15:32:47 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* fw_cfg_modify_file:
|
|
|
|
* @s: fw_cfg device being modified
|
|
|
|
* @filename: name of new fw_cfg file item
|
|
|
|
* @data: pointer to start of item data
|
|
|
|
* @len: size of item data
|
|
|
|
*
|
|
|
|
* Replace a NAMED fw_cfg item. If an existing item is found, its callback
|
|
|
|
* information will be cleared, and a pointer to its data will be returned
|
|
|
|
* to the caller, so that it may be freed if necessary. If an existing item
|
|
|
|
* is not found, this call defaults to fw_cfg_add_file(), and NULL is
|
|
|
|
* returned to the caller.
|
|
|
|
* In either case, the new item data is only linked, NOT copied, into the
|
|
|
|
* data structure of the fw_cfg device.
|
|
|
|
*
|
|
|
|
* Returns: pointer to old item's data, or NULL if old item does not exist.
|
|
|
|
*/
|
2014-10-07 10:00:08 +02:00
|
|
|
void *fw_cfg_modify_file(FWCfgState *s, const char *filename, void *data,
|
|
|
|
size_t len);
|
2015-11-05 15:32:47 +01:00
|
|
|
|
2015-10-08 17:02:55 +02:00
|
|
|
FWCfgState *fw_cfg_init_io_dma(uint32_t iobase, uint32_t dma_iobase,
|
|
|
|
AddressSpace *dma_as);
|
2014-12-22 13:11:35 +01:00
|
|
|
FWCfgState *fw_cfg_init_io(uint32_t iobase);
|
|
|
|
FWCfgState *fw_cfg_init_mem(hwaddr ctl_addr, hwaddr data_addr);
|
2015-10-08 17:02:55 +02:00
|
|
|
FWCfgState *fw_cfg_init_mem_wide(hwaddr ctl_addr,
|
|
|
|
hwaddr data_addr, uint32_t data_width,
|
|
|
|
hwaddr dma_addr, AddressSpace *dma_as);
|
2008-09-18 20:27:29 +02:00
|
|
|
|
2013-05-30 15:07:58 +02:00
|
|
|
FWCfgState *fw_cfg_find(void);
|
2016-05-23 20:11:33 +02:00
|
|
|
bool fw_cfg_dma_enabled(void *opaque);
|
2013-05-30 15:07:58 +02:00
|
|
|
|
2008-09-18 20:27:29 +02:00
|
|
|
#endif
|