fw_cfg: add API for file transfer.
This patch adds a file transfer interface to fw_cfg. Intended to be used for passing non-pci option roms and vgabios to seabios. Namespace is modeled after the existing cbfs filesystem support in seabios. Reading the new FW_CFG_FILE_DIR entry returns a file list. Fields there are in network byte order (aka bigendian). aliguori: fix fw_cfg.h for multiboot.bin, add proper fw_cfg.h declarations, quiet fprintf() in fw_cfg.c Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
c2b5bda43a
commit
abe147e0ce
43
hw/fw_cfg.c
43
hw/fw_cfg.c
@ -47,6 +47,7 @@ typedef struct _FWCfgEntry {
|
|||||||
|
|
||||||
struct _FWCfgState {
|
struct _FWCfgState {
|
||||||
FWCfgEntry entries[2][FW_CFG_MAX_ENTRY];
|
FWCfgEntry entries[2][FW_CFG_MAX_ENTRY];
|
||||||
|
FWCfgFiles *files;
|
||||||
uint16_t cur_entry;
|
uint16_t cur_entry;
|
||||||
uint32_t cur_offset;
|
uint32_t cur_offset;
|
||||||
};
|
};
|
||||||
@ -273,6 +274,48 @@ int fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
|
||||||
target_phys_addr_t ctl_addr, target_phys_addr_t data_addr)
|
target_phys_addr_t ctl_addr, target_phys_addr_t data_addr)
|
||||||
{
|
{
|
||||||
|
21
hw/fw_cfg.h
21
hw/fw_cfg.h
@ -26,7 +26,11 @@
|
|||||||
#define FW_CFG_SETUP_ADDR 0x16
|
#define FW_CFG_SETUP_ADDR 0x16
|
||||||
#define FW_CFG_SETUP_SIZE 0x17
|
#define FW_CFG_SETUP_SIZE 0x17
|
||||||
#define FW_CFG_SETUP_DATA 0x18
|
#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_WRITE_CHANNEL 0x4000
|
||||||
#define FW_CFG_ARCH_LOCAL 0x8000
|
#define FW_CFG_ARCH_LOCAL 0x8000
|
||||||
@ -35,6 +39,18 @@
|
|||||||
#define FW_CFG_INVALID 0xffff
|
#define FW_CFG_INVALID 0xffff
|
||||||
|
|
||||||
#ifndef NO_QEMU_PROTOS
|
#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);
|
typedef void (*FWCfgCallback)(void *opaque, uint8_t *data);
|
||||||
|
|
||||||
typedef struct _FWCfgState FWCfgState;
|
typedef struct _FWCfgState FWCfgState;
|
||||||
@ -44,7 +60,8 @@ 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_i64(FWCfgState *s, uint16_t key, uint64_t value);
|
||||||
int fw_cfg_add_callback(FWCfgState *s, 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);
|
void *callback_opaque, uint8_t *data, size_t len);
|
||||||
int fw_cfg_add_file(FWCfgState *s, uint8_t type, uint8_t *data, uint32_t len);
|
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,
|
FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
|
||||||
target_phys_addr_t crl_addr, target_phys_addr_t data_addr);
|
target_phys_addr_t crl_addr, target_phys_addr_t data_addr);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user