diff options
author | Ben Warren <ben@skyportsystems.com> | 2017-02-20 19:56:15 -0800 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2017-02-21 09:30:14 -0500 |
commit | f991822f24adbeea519495dd8fe2d8ca7ed47291 (patch) | |
tree | 1b8357883b8299764f5d4c8e708cd85caa61349c /src/fw/paravirt.c | |
parent | c83e15b60b7c59552a44d71d0582f2d62a6084a7 (diff) | |
download | seabios-f991822f24adbeea519495dd8fe2d8ca7ed47291.tar.gz |
QEMU DMA: Add DMA write capability
This allows BIOS to write data back to QEMU using the DMA interface and
provides a higher-level abstraction to write to a fw_cfg file
Signed-off-by: Ben Warren <ben@skyportsystems.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
Diffstat (limited to 'src/fw/paravirt.c')
-rw-r--r-- | src/fw/paravirt.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/src/fw/paravirt.c b/src/fw/paravirt.c index 6de70f61..4618647f 100644 --- a/src/fw/paravirt.c +++ b/src/fw/paravirt.c @@ -253,6 +253,20 @@ qemu_cfg_read(void *buf, int len) } static void +qemu_cfg_write(void *buf, int len) +{ + if (len == 0) { + return; + } + + if (qemu_cfg_dma_enabled()) { + qemu_cfg_dma_transfer(buf, len, QEMU_CFG_DMA_CTL_WRITE); + } else { + warn_internalerror(); + } +} + +static void qemu_cfg_skip(int len) { if (len == 0) { @@ -280,6 +294,18 @@ qemu_cfg_read_entry(void *buf, int e, int len) } } +static void +qemu_cfg_write_entry(void *buf, int e, int len) +{ + if (qemu_cfg_dma_enabled()) { + u32 control = (e << 16) | QEMU_CFG_DMA_CTL_SELECT + | QEMU_CFG_DMA_CTL_WRITE; + qemu_cfg_dma_transfer(buf, len, control); + } else { + warn_internalerror(); + } +} + struct qemu_romfile_s { struct romfile_s file; int select, skip; @@ -303,6 +329,29 @@ qemu_cfg_read_file(struct romfile_s *file, void *dst, u32 maxlen) return file->size; } +int +qemu_cfg_write_file(void *src, struct romfile_s *file, u32 offset, u32 len) +{ + if ((offset + len) > file->size) + return -1; + + if (!qemu_cfg_dma_enabled() || (file->copy != qemu_cfg_read_file)) { + warn_internalerror(); + return -1; + } + struct qemu_romfile_s *qfile; + qfile = container_of(file, struct qemu_romfile_s, file); + if (offset == 0) { + /* Do it in one transfer */ + qemu_cfg_write_entry(src, qfile->select, len); + } else { + qemu_cfg_select(qfile->select); + qemu_cfg_skip(offset); + qemu_cfg_write(src, len); + } + return len; +} + static void qemu_romfile_add(char *name, int select, int skip, int size) { |