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 {
|
||||
FWCfgEntry entries[2][FW_CFG_MAX_ENTRY];
|
||||
FWCfgFiles *files;
|
||||
uint16_t cur_entry;
|
||||
uint32_t cur_offset;
|
||||
};
|
||||
@ -273,6 +274,48 @@ int fw_cfg_add_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback,
|
||||
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,
|
||||
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_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,6 +39,18 @@
|
||||
#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);
|
||||
|
||||
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_callback(FWCfgState *s, uint16_t key, FWCfgCallback callback,
|
||||
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,
|
||||
target_phys_addr_t crl_addr, target_phys_addr_t data_addr);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user