On Mon, Feb 20, 2017 at 07:56:19PM -0800, ben(a)skyportsystems.com wrote:
From: Ben Warren <ben(a)skyportsystems.com>
Any pointers to BIOS-allocated memory that were written back to QEMU
fw_cfg files are replayed when resuming from S3 sleep.
Signed-off-by: Ben Warren <ben(a)skyportsystems.com>
Reviewed-by: Laszlo Ersek <lersek(a)redhat.com>
---
src/fw/romfile_loader.c | 33 +++++++++++++++++++++++++++++++++
src/fw/romfile_loader.h | 2 ++
src/resume.c | 4 ++++
3 files changed, 39 insertions(+)
diff --git a/src/fw/romfile_loader.c b/src/fw/romfile_loader.c
index 30e7b58..14bc908 100644
--- a/src/fw/romfile_loader.c
+++ b/src/fw/romfile_loader.c
@@ -4,6 +4,7 @@
#include "string.h" // strcmp
#include "romfile.h" // struct romfile_s
#include "malloc.h" // Zone*, _malloc
+#include "list.h" // struct hlist_node
#include "output.h" // warn_*
#include "paravirt.h" // qemu_cfg_write_file
@@ -16,6 +17,16 @@ struct romfile_loader_files {
struct romfile_loader_file files[];
};
+// Data structures for storing "write pointer" entries for possible replay
+struct romfile_wr_pointer_entry {
+ u64 pointer;
+ u32 offset;
+ u16 key;
+ u8 ptr_size;
+ struct hlist_node node;
+};
+static struct hlist_head romfile_pointer_list;
+
static struct romfile_loader_file *
romfile_loader_find(const char *name,
struct romfile_loader_files *files)
@@ -29,6 +40,19 @@ romfile_loader_find(const char *name,
return NULL;
}
+// Replay "write pointer" entries back to QEMU
+void romfile_fw_cfg_resume(void)
+{
+ if (!CONFIG_QEMU)
+ return;
+
+ struct romfile_wr_pointer_entry *entry;
+ hlist_for_each_entry(entry, &romfile_pointer_list, node) {
+ qemu_cfg_write_file_simple(&entry->pointer, entry->key,
+ entry->offset, entry->ptr_size);
+ }
+}
+
static void romfile_loader_allocate(struct romfile_loader_entry_s *entry,
struct romfile_loader_files *files)
{
@@ -163,6 +187,15 @@ static void romfile_loader_write_pointer(struct
romfile_loader_entry_s *entry,
entry->wr_pointer.size) != entry->wr_pointer.size) {
goto err;
}
+
+ /* Store the info so it can replayed later if necessary */
+ struct romfile_wr_pointer_entry *store = malloc_high(sizeof(*store));
+ store->pointer = pointer;
I missed this in my earlier review - it's necessary to always check
the return of malloc() in seabios. (Writing to NULL changes memory at
address 0 which is shared with the 16bit interrupt table.) I fixed it
upon commit.
-Kevin