aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2009-12-20 12:40:14 +0200
committerAvi Kivity <avi@redhat.com>2009-12-20 12:40:14 +0200
commitaa55ccbf54b74f3a843afe57ae008ab37a3f1912 (patch)
tree5c85c9648eafd2cb106a94fda4eb66882aa8d25e /hw
parentMerge commit '898829d5c731516c96f9e3cc3cdcbe36cd494fd4' into stable-0.12-merge (diff)
parentroms: use new fw_cfg file xfer support. (diff)
downloadqemu-kvm-aa55ccbf54b74f3a843afe57ae008ab37a3f1912.tar.gz
qemu-kvm-aa55ccbf54b74f3a843afe57ae008ab37a3f1912.tar.bz2
qemu-kvm-aa55ccbf54b74f3a843afe57ae008ab37a3f1912.zip
Merge commit '26bb2a0865ff25f5d26438238a6bcda9c5146335' into stable-0.12-merge
* commit '26bb2a0865ff25f5d26438238a6bcda9c5146335': roms: use new fw_cfg file xfer support. fw_cfg: add API for file transfer. fw_cfg: make calls typesafe Conflicts: hw/pc.c Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/fw_cfg.c69
-rw-r--r--hw/fw_cfg.h35
-rw-r--r--hw/loader.c25
-rw-r--r--hw/loader.h5
-rw-r--r--hw/pc.c2
5 files changed, 109 insertions, 27 deletions
diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c
index b25affff8..fe9c52758 100644
--- a/hw/fw_cfg.c
+++ b/hw/fw_cfg.c
@@ -45,11 +45,12 @@ typedef struct _FWCfgEntry {
FWCfgCallback callback;
} FWCfgEntry;
-typedef struct _FWCfgState {
+struct _FWCfgState {
FWCfgEntry entries[2][FW_CFG_MAX_ENTRY];
+ FWCfgFiles *files;
uint16_t cur_entry;
uint32_t cur_offset;
-} FWCfgState;
+};
static void fw_cfg_write(FWCfgState *s, uint8_t value)
{
@@ -210,9 +211,8 @@ static const VMStateDescription vmstate_fw_cfg = {
}
};
-int fw_cfg_add_bytes(void *opaque, uint16_t key, uint8_t *data, uint32_t len)
+int fw_cfg_add_bytes(FWCfgState *s, uint16_t key, uint8_t *data, uint32_t len)
{
- FWCfgState *s = opaque;
int arch = !!(key & FW_CFG_ARCH_LOCAL);
key &= FW_CFG_ENTRY_MASK;
@@ -226,37 +226,36 @@ int fw_cfg_add_bytes(void *opaque, uint16_t key, uint8_t *data, uint32_t len)
return 1;
}
-int fw_cfg_add_i16(void *opaque, uint16_t key, uint16_t value)
+int fw_cfg_add_i16(FWCfgState *s, uint16_t key, uint16_t value)
{
uint16_t *copy;
copy = qemu_malloc(sizeof(value));
*copy = cpu_to_le16(value);
- return fw_cfg_add_bytes(opaque, key, (uint8_t *)copy, sizeof(value));
+ return fw_cfg_add_bytes(s, key, (uint8_t *)copy, sizeof(value));
}
-int fw_cfg_add_i32(void *opaque, uint16_t key, uint32_t value)
+int fw_cfg_add_i32(FWCfgState *s, uint16_t key, uint32_t value)
{
uint32_t *copy;
copy = qemu_malloc(sizeof(value));
*copy = cpu_to_le32(value);
- return fw_cfg_add_bytes(opaque, key, (uint8_t *)copy, sizeof(value));
+ return fw_cfg_add_bytes(s, key, (uint8_t *)copy, sizeof(value));
}
-int fw_cfg_add_i64(void *opaque, uint16_t key, uint64_t value)
+int fw_cfg_add_i64(FWCfgState *s, uint16_t key, uint64_t value)
{
uint64_t *copy;
copy = qemu_malloc(sizeof(value));
*copy = cpu_to_le64(value);
- return fw_cfg_add_bytes(opaque, key, (uint8_t *)copy, sizeof(value));
+ return fw_cfg_add_bytes(s, key, (uint8_t *)copy, sizeof(value));
}
-int fw_cfg_add_callback(void *opaque, uint16_t key, FWCfgCallback callback,
+int fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback,
void *callback_opaque, uint8_t *data, size_t len)
{
- FWCfgState *s = opaque;
int arch = !!(key & FW_CFG_ARCH_LOCAL);
if (!(key & FW_CFG_WRITE_CHANNEL))
@@ -275,8 +274,50 @@ int fw_cfg_add_callback(void *opaque, uint16_t key, FWCfgCallback callback,
return 1;
}
-void *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
- target_phys_addr_t ctl_addr, target_phys_addr_t data_addr)
+int fw_cfg_add_file(FWCfgState *s, const char *dir, const char *filename,
+ uint8_t *data, uint32_t len)
+{
+ const char *basename;
+ int index;
+
+ if (!s->files) {
+ int dsize = sizeof(uint32_t) + sizeof(FWCfgFile) * FW_CFG_FILE_SLOTS;
+ s->files = qemu_mallocz(dsize);
+ fw_cfg_add_bytes(s, FW_CFG_FILE_DIR, (uint8_t*)s->files, dsize);
+ }
+
+ index = be32_to_cpu(s->files->count);
+ if (index == FW_CFG_FILE_SLOTS) {
+ fprintf(stderr, "fw_cfg: out of file slots\n");
+ return 0;
+ }
+
+ fw_cfg_add_bytes(s, FW_CFG_FILE_FIRST + index, data, len);
+
+ basename = strrchr(filename, '/');
+ if (basename) {
+ basename++;
+ } else {
+ basename = filename;
+ }
+ if (dir) {
+ snprintf(s->files->f[index].name, sizeof(s->files->f[index].name),
+ "%s/%s", dir, basename);
+ } else {
+ snprintf(s->files->f[index].name, sizeof(s->files->f[index].name),
+ "%s", basename);
+ }
+ s->files->f[index].size = cpu_to_be32(len);
+ s->files->f[index].select = cpu_to_be16(FW_CFG_FILE_FIRST + index);
+ FW_CFG_DPRINTF("%s: #%d: %s (%d bytes)\n", __FUNCTION__,
+ index, s->files->f[index].name, len);
+
+ s->files->count = cpu_to_be32(index+1);
+ return 1;
+}
+
+FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
+ target_phys_addr_t ctl_addr, target_phys_addr_t data_addr)
{
FWCfgState *s;
int io_ctl_memory, io_data_memory;
diff --git a/hw/fw_cfg.h b/hw/fw_cfg.h
index 7070c9401..c1019d0b0 100644
--- a/hw/fw_cfg.h
+++ b/hw/fw_cfg.h
@@ -26,7 +26,11 @@
#define FW_CFG_SETUP_ADDR 0x16
#define FW_CFG_SETUP_SIZE 0x17
#define FW_CFG_SETUP_DATA 0x18
-#define FW_CFG_MAX_ENTRY 0x19
+#define FW_CFG_FILE_DIR 0x19
+
+#define FW_CFG_FILE_FIRST 0x20
+#define FW_CFG_FILE_SLOTS 0x10
+#define FW_CFG_MAX_ENTRY (FW_CFG_FILE_FIRST+FW_CFG_FILE_SLOTS)
#define FW_CFG_WRITE_CHANNEL 0x4000
#define FW_CFG_ARCH_LOCAL 0x8000
@@ -35,16 +39,31 @@
#define FW_CFG_INVALID 0xffff
#ifndef NO_QEMU_PROTOS
+typedef struct FWCfgFile {
+ uint32_t size; /* file size */
+ uint16_t select; /* write this to 0x510 to read it */
+ uint16_t reserved;
+ char name[56];
+} FWCfgFile;
+
+typedef struct FWCfgFiles {
+ uint32_t count;
+ FWCfgFile f[];
+} FWCfgFiles;
+
typedef void (*FWCfgCallback)(void *opaque, uint8_t *data);
-int fw_cfg_add_bytes(void *opaque, uint16_t key, uint8_t *data, uint32_t len);
-int fw_cfg_add_i16(void *opaque, uint16_t key, uint16_t value);
-int fw_cfg_add_i32(void *opaque, uint16_t key, uint32_t value);
-int fw_cfg_add_i64(void *opaque, uint16_t key, uint64_t value);
-int fw_cfg_add_callback(void *opaque, uint16_t key, FWCfgCallback callback,
+typedef struct _FWCfgState FWCfgState;
+int fw_cfg_add_bytes(FWCfgState *s, uint16_t key, uint8_t *data, uint32_t len);
+int fw_cfg_add_i16(FWCfgState *s, uint16_t key, uint16_t value);
+int fw_cfg_add_i32(FWCfgState *s, uint16_t key, uint32_t value);
+int fw_cfg_add_i64(FWCfgState *s, uint16_t key, uint64_t value);
+int fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback,
void *callback_opaque, uint8_t *data, size_t len);
-void *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
- target_phys_addr_t crl_addr, target_phys_addr_t data_addr);
+int fw_cfg_add_file(FWCfgState *s, const char *dir, const char *filename,
+ uint8_t *data, uint32_t len);
+FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
+ target_phys_addr_t crl_addr, target_phys_addr_t data_addr);
#endif /* NO_QEMU_PROTOS */
diff --git a/hw/loader.c b/hw/loader.c
index dd4a9a2b1..f5b9ae12c 100644
--- a/hw/loader.c
+++ b/hw/loader.c
@@ -48,6 +48,7 @@
#include "sysemu.h"
#include "uboot_image.h"
#include "loader.h"
+#include "fw_cfg.h"
#include <zlib.h>
@@ -528,6 +529,8 @@ struct Rom {
uint8_t *data;
int align;
int isrom;
+ char *fw_dir;
+ char *fw_file;
target_phys_addr_t min;
target_phys_addr_t max;
@@ -556,7 +559,7 @@ static void rom_insert(Rom *rom)
QTAILQ_INSERT_TAIL(&roms, rom, next);
}
-int rom_add_file(const char *file,
+int rom_add_file(const char *file, const char *fw_dir, const char *fw_file,
target_phys_addr_t min, target_phys_addr_t max, int align)
{
Rom *rom;
@@ -576,6 +579,8 @@ int rom_add_file(const char *file,
goto err;
}
+ rom->fw_dir = fw_dir ? qemu_strdup(fw_dir) : NULL;
+ rom->fw_file = fw_file ? qemu_strdup(fw_file) : NULL;
rom->align = align;
rom->min = min;
rom->max = max;
@@ -623,14 +628,16 @@ int rom_add_vga(const char *file)
{
if (!rom_enable_driver_roms)
return 0;
- return rom_add_file(file, PC_ROM_MIN_VGA, PC_ROM_MAX, PC_ROM_ALIGN);
+ return rom_add_file(file, "vgaroms", file,
+ PC_ROM_MIN_VGA, PC_ROM_MAX, PC_ROM_ALIGN);
}
int rom_add_option(const char *file)
{
if (!rom_enable_driver_roms)
return 0;
- return rom_add_file(file, PC_ROM_MIN_OPTION, PC_ROM_MAX, PC_ROM_ALIGN);
+ return rom_add_file(file, "genroms", file,
+ PC_ROM_MIN_OPTION, PC_ROM_MAX, PC_ROM_ALIGN);
}
static void rom_reset(void *unused)
@@ -692,6 +699,18 @@ int rom_load_all(void)
return 0;
}
+int rom_load_fw(void *fw_cfg)
+{
+ Rom *rom;
+
+ QTAILQ_FOREACH(rom, &roms, next) {
+ if (!rom->fw_file)
+ continue;
+ fw_cfg_add_file(fw_cfg, rom->fw_dir, rom->fw_file, rom->data, rom->romsize);
+ }
+ return 0;
+}
+
static Rom *find_rom(target_phys_addr_t addr)
{
Rom *rom;
diff --git a/hw/loader.h b/hw/loader.h
index b3311a392..634f7d5d0 100644
--- a/hw/loader.h
+++ b/hw/loader.h
@@ -19,17 +19,18 @@ void pstrcpy_targphys(const char *name,
target_phys_addr_t dest, int buf_size,
const char *source);
-int rom_add_file(const char *file,
+int rom_add_file(const char *file, const char *fw_dir, const char *fw_file,
target_phys_addr_t min, target_phys_addr_t max, int align);
int rom_add_blob(const char *name, const void *blob, size_t len,
target_phys_addr_t min, target_phys_addr_t max, int align);
int rom_load_all(void);
+int rom_load_fw(void *fw_cfg);
int rom_copy(uint8_t *dest, target_phys_addr_t addr, size_t size);
void *rom_ptr(target_phys_addr_t addr);
void do_info_roms(Monitor *mon);
#define rom_add_file_fixed(_f, _a) \
- rom_add_file(_f, _a, 0, 0)
+ rom_add_file(_f, NULL, NULL, _a, 0, 0)
#define rom_add_blob_fixed(_f, _b, _l, _a) \
rom_add_blob(_f, _b, _l, _a, 0, 0)
diff --git a/hw/pc.c b/hw/pc.c
index 6a7257c4c..51603f8cf 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1292,6 +1292,8 @@ static void pc_init1(ram_addr_t ram_size,
}
}
+ rom_load_fw(fw_cfg);
+
#ifdef CONFIG_KVM_DEVICE_ASSIGNMENT
if (kvm_enabled()) {
add_assigned_devices(pci_bus, assigned_devices, assigned_devices_index);