All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Gabriel L. Somlo" <somlo@cmu.edu>
To: qemu-devel@nongnu.org
Cc: matt.fleming@intel.com, rjones@redhat.com,
	jordan.l.justen@intel.com, gleb@cloudius-systems.com,
	mdroth@linux.vnet.ibm.com, gsomlo@gmail.com, kraxel@redhat.com,
	pbonzini@redhat.com, lersek@redhat.com
Subject: [Qemu-devel] [PATCH 6/6] qga: RFC: guest-side retrieval of fw_cfg file
Date: Mon, 16 Mar 2015 10:15:05 -0400	[thread overview]
Message-ID: <1426515305-17766-7-git-send-email-somlo@cmu.edu> (raw)
In-Reply-To: <1426515305-17766-1-git-send-email-somlo@cmu.edu>

Add -g (--get-fwcfg) client-mode option to qemu-ga, causing
the named fw_cfg file to be retrieved and written to stdout.

Signed-off-by: Gabriel Somlo <somlo@cmu.edu>
---

First off, I have NOT forgotten the suggestion to make this a
standalone binary, and will do so when I submit it "for real".
It's just more comfortable this way for quick-n-dirty testing :)

Two main issues I need help with before this would be ready to
go upstream:

  1. I can't for the life of me figure out how to stop gcc -O2
     from assuming the if() test below is ALWAYS FALSE, and thus
     optimizing it out completely. For now I've forced -O0 on
     the entire function, but for some reason fw_cfg_read(&fcfile, ...)
     does not appear to count as potentially modifying fcfile...

  2. I'm toying with the idea of writing a kernel driver for fw_cfg
     and thus having all this functionality reduced to
     "cat /sys/firmware/fw_cfg/<filename> | grep <something>" :)

     Of course, I have no idea how that would work on Windows, so maybe
     a binary spitting out a file is still the more portable way to go.
     (not to mention that most of the code for that is already written
     below).

Thanks much for any additional clue...
  Gabriel

 qga/Makefile.objs      |  1 +
 qga/get-fwcfg.c        | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++
 qga/guest-agent-core.h |  2 ++
 qga/main.c             |  6 +++-
 4 files changed, 100 insertions(+), 1 deletion(-)
 create mode 100644 qga/get-fwcfg.c

diff --git a/qga/Makefile.objs b/qga/Makefile.objs
index 1c5986c..ef53841 100644
--- a/qga/Makefile.objs
+++ b/qga/Makefile.objs
@@ -4,5 +4,6 @@ qga-obj-$(CONFIG_WIN32) += commands-win32.o channel-win32.o service-win32.o
 qga-obj-$(CONFIG_WIN32) += vss-win32.o
 qga-obj-y += qapi-generated/qga-qapi-types.o qapi-generated/qga-qapi-visit.o
 qga-obj-y += qapi-generated/qga-qmp-marshal.o
+qga-obj-y += get-fwcfg.o
 
 qga-vss-dll-obj-$(CONFIG_QGA_VSS) += vss-win32/
diff --git a/qga/get-fwcfg.c b/qga/get-fwcfg.c
new file mode 100644
index 0000000..1928698
--- /dev/null
+++ b/qga/get-fwcfg.c
@@ -0,0 +1,92 @@
+/*
+ * QEMU Guest Agent: retrieve blob from fw_cfg device by name
+ *
+ * Copyright Carnegie Mellon University 2015
+ *
+ * Author:
+ *  Gabriel L. Somlo  <somlo@cmu.edu>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/io.h>
+#include "qemu/bswap.h"
+#include "hw/nvram/fw_cfg.h"
+#include "qga/guest-agent-core.h"
+
+#define PORT_FW_CFG_CTL       0x0510
+#define PORT_FW_CFG_DATA      0x0511
+
+static void
+fw_cfg_select(uint16_t f)
+{
+    outw(f, PORT_FW_CFG_CTL);
+}
+
+static void
+fw_cfg_read(void *buf, int len)
+{
+    insb(PORT_FW_CFG_DATA, buf, len);
+}
+
+static void
+fw_cfg_read_entry(void *buf, int e, int len)
+{
+    fw_cfg_select(e);
+    fw_cfg_read(buf, len);
+}
+
+int
+__attribute__((optimize("O0"))) //FIXME: "gcc -O2" wrongfully optimizes "if"!!!
+ga_get_fwcfg(const char *filename)
+{
+    int i;
+    uint32_t count, len = 0;
+    uint16_t sel;
+    uint8_t sig[] = "QEMU";
+    FWCfgFile fcfile;
+    void *buf;
+
+    /* ensure access to the fw_cfg device */
+    if (ioperm(PORT_FW_CFG_CTL, 2, 1) != 0) {
+        perror("ioperm failed");
+        return EXIT_FAILURE;
+    }
+
+    /* verify presence of fw_cfg device */
+    fw_cfg_select(FW_CFG_SIGNATURE);
+    for (i = 0; i < sizeof(sig) - 1; i++) {
+        sig[i] = inb(PORT_FW_CFG_DATA);
+    }
+    if (memcmp(sig, "QEMU", sizeof(sig)) != 0) {
+        fprintf(stderr, "fw_cfg signature not found!\n");
+        return EXIT_FAILURE;
+    }
+
+    /* read number of fw_cfg entries, then scan for requested entry by name */
+    fw_cfg_read_entry(&count, FW_CFG_FILE_DIR, sizeof(count));
+    count = be32_to_cpu(count);
+    for (i = 0; i < count; i++) {
+        fw_cfg_read(&fcfile, sizeof(fcfile));
+        //FIXME: why does gcc -O2 optimize away the whole if {} block below?!?
+        if (!strcmp(fcfile.name, filename)) {
+            len = be32_to_cpu(fcfile.size);
+            sel = be16_to_cpu(fcfile.select);
+            buf = g_malloc(len);
+            fw_cfg_read_entry(buf, sel, len);
+            if (write(STDOUT_FILENO, buf, len) != len) {
+                fprintf(stderr, "Failed to write %s to stdout\n", filename);
+                return EXIT_FAILURE;
+            }
+            return 0;;
+        }
+    }
+
+    /* requested entry not present in fw_cfg */
+    fprintf(stderr, "File %s not found in fw_cfg!\n", filename);
+    return EXIT_FAILURE;
+}
diff --git a/qga/guest-agent-core.h b/qga/guest-agent-core.h
index e92c6ab..b859e08 100644
--- a/qga/guest-agent-core.h
+++ b/qga/guest-agent-core.h
@@ -41,3 +41,5 @@ int64_t ga_get_fd_handle(GAState *s, Error **errp);
 #ifndef _WIN32
 void reopen_fd_to_null(int fd);
 #endif
+
+int ga_get_fwcfg(const char *file);
diff --git a/qga/main.c b/qga/main.c
index 9939a2b..f9c1ece 100644
--- a/qga/main.c
+++ b/qga/main.c
@@ -215,6 +215,7 @@ static void usage(const char *cmd)
 #endif
 "  -b, --blacklist   comma-separated list of RPCs to disable (no spaces, \"?\"\n"
 "                    to list available RPCs)\n"
+"  -g, --get-fwcfg   dump the content of a given fw_cfg file to stdout\n"
 "  -h, --help        display this help and exit\n"
 "\n"
 "Report bugs to <mdroth@linux.vnet.ibm.com>\n"
@@ -923,7 +924,7 @@ static void ga_print_cmd(QmpCommand *cmd, void *opaque)
 
 int main(int argc, char **argv)
 {
-    const char *sopt = "hVvdm:p:l:f:F::b:s:t:";
+    const char *sopt = "hVvdm:p:l:f:F::b:s:t:g:";
     const char *method = NULL, *path = NULL;
     const char *log_filepath = NULL;
     const char *pid_filepath;
@@ -951,6 +952,7 @@ int main(int argc, char **argv)
         { "service", 1, NULL, 's' },
 #endif
         { "statedir", 1, NULL, 't' },
+        { "get-fwcfg", 1, NULL, 'g' },
         { NULL, 0, NULL, 0 }
     };
     int opt_ind = 0, ch, daemonize = 0, i, j, len;
@@ -1042,6 +1044,8 @@ int main(int argc, char **argv)
             }
             break;
 #endif
+        case 'g':
+            return ga_get_fwcfg(optarg);
         case 'h':
             usage(argv[0]);
             return 0;
-- 
2.1.0

  parent reply	other threads:[~2015-03-16 14:15 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-03-16 14:14 [Qemu-devel] [PATCH 0/6] fw-cfg: documentation, cleanup, and proposed feature Gabriel L. Somlo
2015-03-16 14:15 ` [Qemu-devel] [PATCH 1/6] fw_cfg: add documentation file (docs/specs/fw_cfg.txt) Gabriel L. Somlo
2015-03-16 16:30   ` Laszlo Ersek
2015-03-16 14:15 ` [Qemu-devel] [PATCH 2/6] fw_cfg: remove support for guest-side data writes Gabriel L. Somlo
2015-03-16 17:02   ` Laszlo Ersek
2015-03-16 18:41     ` Gabriel L. Somlo
2015-03-17  7:46       ` Gerd Hoffmann
2015-03-16 14:15 ` [Qemu-devel] [PATCH 3/6] fw_cfg: assertion to detect memory leak when adding new data blob Gabriel L. Somlo
2015-03-16 19:12   ` Laszlo Ersek
2015-03-16 14:15 ` [Qemu-devel] [PATCH 4/6] fw_cfg: exit with error when dupe fw_cfg file name inserted Gabriel L. Somlo
2015-03-16 19:26   ` Laszlo Ersek
2015-03-16 14:15 ` [Qemu-devel] [PATCH 5/6] fw_cfg: insert fw_cfg file blobs via qemu cmdline Gabriel L. Somlo
2015-03-17 10:07   ` Gerd Hoffmann
2015-03-17 10:55   ` Matt Fleming
2015-03-17 14:09     ` Gabriel L. Somlo
2015-03-17 11:28   ` Laszlo Ersek
2015-03-17 11:49     ` Gerd Hoffmann
2015-03-18 20:06       ` Gabriel L. Somlo
2015-03-19 10:43         ` Laszlo Ersek
2015-03-18 20:27     ` Gabriel L. Somlo
2015-03-19  7:34       ` Gerd Hoffmann
2015-03-19  8:41       ` [Qemu-devel] How to emit errors with nice location information (was: [PATCH 5/6] fw_cfg: insert fw_cfg file blobs via qemu cmdline) Markus Armbruster
2015-03-16 14:15 ` Gabriel L. Somlo [this message]
2015-03-17 12:38   ` [Qemu-devel] [PATCH 6/6] qga: RFC: guest-side retrieval of fw_cfg file Laszlo Ersek
2015-03-17 14:28     ` Gabriel L. Somlo
2015-03-19 18:27     ` Kevin O'Connor
2015-03-19 18:44       ` Laszlo Ersek
2015-03-16 14:26 ` [Qemu-devel] [PATCH 0/6] fw-cfg: documentation, cleanup, and proposed feature Patchew Tool

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1426515305-17766-7-git-send-email-somlo@cmu.edu \
    --to=somlo@cmu.edu \
    --cc=gleb@cloudius-systems.com \
    --cc=gsomlo@gmail.com \
    --cc=jordan.l.justen@intel.com \
    --cc=kraxel@redhat.com \
    --cc=lersek@redhat.com \
    --cc=matt.fleming@intel.com \
    --cc=mdroth@linux.vnet.ibm.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=rjones@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.