]> xenbits.xensource.com Git - seabios.git/commitdiff
QEMU DMA: Add DMA write capability
authorBen Warren <ben@skyportsystems.com>
Tue, 21 Feb 2017 03:56:15 +0000 (19:56 -0800)
committerGerd Hoffmann <kraxel@redhat.com>
Fri, 24 Feb 2017 14:01:20 +0000 (15:01 +0100)
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>
(cherry picked from commit f991822f24adbeea519495dd8fe2d8ca7ed47291)

src/fw/paravirt.c
src/fw/paravirt.h

index 6de70f611e046ddf41d24765825490e968130303..4618647f49f6173709b56060428358ac126a6e00 100644 (file)
@@ -252,6 +252,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)
 {
@@ -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)
 {
index d8eb7c45bacf505a72f234b07a3c2a31f1281906..fb220d87ff1f37e5d54f158dd0619a92964d43ba 100644 (file)
@@ -3,6 +3,7 @@
 
 #include "config.h" // CONFIG_*
 #include "biosvar.h" // GET_GLOBAL
+#include "romfile.h" // struct romfile_s
 
 // Types of paravirtualized platforms.
 #define PF_QEMU     (1<<0)
@@ -43,6 +44,7 @@ static inline int runningOnKVM(void) {
 #define QEMU_CFG_DMA_CTL_READ    0x02
 #define QEMU_CFG_DMA_CTL_SKIP    0x04
 #define QEMU_CFG_DMA_CTL_SELECT  0x08
+#define QEMU_CFG_DMA_CTL_WRITE   0x10
 
 // QEMU_CFG_DMA ID bit
 #define QEMU_CFG_VERSION_DMA    2
@@ -53,5 +55,6 @@ void qemu_platform_setup(void);
 void qemu_cfg_init(void);
 
 u16 qemu_get_present_cpus_count(void);
+int qemu_cfg_write_file(void *src, struct romfile_s *file, u32 offset, u32 len);
 
 #endif