aboutsummaryrefslogtreecommitdiffstats
path: root/src/fw/paravirt.c
diff options
context:
space:
mode:
authorBen Warren <ben@skyportsystems.com>2017-02-20 19:56:15 -0800
committerKevin O'Connor <kevin@koconnor.net>2017-02-21 09:30:14 -0500
commitf991822f24adbeea519495dd8fe2d8ca7ed47291 (patch)
tree1b8357883b8299764f5d4c8e708cd85caa61349c /src/fw/paravirt.c
parentc83e15b60b7c59552a44d71d0582f2d62a6084a7 (diff)
downloadseabios-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.c49
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)
{