Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F107746609
D38338.id121571.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D38338.id121571.diff
View Options
diff --git a/usr.sbin/bhyve/bhyve.8 b/usr.sbin/bhyve/bhyve.8
--- a/usr.sbin/bhyve/bhyve.8
+++ b/usr.sbin/bhyve/bhyve.8
@@ -45,6 +45,15 @@
.Op Cm ,threads= Ar n
.Oc
.Sm on
+.Oo Fl f
+.Sm off
+.Ar name Cm \&,
+.Oo
+.Cm string No | Cm file
+.Oc
+.Cm \&= Ar data
+.Sm on
+.Oc
.Oo
.Sm off
.Fl G\~
@@ -145,6 +154,16 @@
.Nm
to exit when a guest issues an access to an I/O port that is not emulated.
This is intended for debug purposes.
+.It Fl f Ar name Ns Cm \&, Ns Oo Cm string Ns No | Ns Cm file Ns Oc Ns Cm \&= Ns Ar data
+Add a fw_cfg file
+.Ar name
+to the fw_cfg interface.
+If a
+.Cm string
+is specified, the fw_cfg file contains the string as data.
+If a
+.Cm file
+is specified, bhyve reads the file and adds the file content as fw_cfg data.
.It Fl G Xo
.Sm off
.Oo Ar w Oc
diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c
--- a/usr.sbin/bhyve/bhyverun.c
+++ b/usr.sbin/bhyve/bhyverun.c
@@ -1259,9 +1259,9 @@
progname = basename(argv[0]);
#ifdef BHYVE_SNAPSHOT
- optstr = "aehuwxACDHIPSWYk:o:p:G:c:s:m:l:K:U:r:";
+ optstr = "aehuwxACDHIPSWYk:f:o:p:G:c:s:m:l:K:U:r:";
#else
- optstr = "aehuwxACDHIPSWYk:o:p:G:c:s:m:l:K:U:";
+ optstr = "aehuwxACDHIPSWYk:f:o:p:G:c:s:m:l:K:U:";
#endif
while ((c = getopt(argc, argv, optstr)) != -1) {
switch (c) {
@@ -1289,6 +1289,11 @@
case 'C':
set_config_bool("memory.guest_in_core", true);
break;
+ case 'f':
+ if (qemu_fwcfg_parse_cmdline_arg(optarg) != 0) {
+ exit(1);
+ }
+ break;
case 'G':
parse_gdb_options(optarg);
break;
diff --git a/usr.sbin/bhyve/qemu_fwcfg.h b/usr.sbin/bhyve/qemu_fwcfg.h
--- a/usr.sbin/bhyve/qemu_fwcfg.h
+++ b/usr.sbin/bhyve/qemu_fwcfg.h
@@ -23,3 +23,4 @@
int qemu_fwcfg_add_file(const char *name,
const uint32_t size, void *const data);
int qemu_fwcfg_init(struct vmctx *const ctx);
+int qemu_fwcfg_parse_cmdline_arg(const char *opt);
diff --git a/usr.sbin/bhyve/qemu_fwcfg.c b/usr.sbin/bhyve/qemu_fwcfg.c
--- a/usr.sbin/bhyve/qemu_fwcfg.c
+++ b/usr.sbin/bhyve/qemu_fwcfg.c
@@ -7,13 +7,18 @@
#include <sys/param.h>
#include <sys/endian.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
#include <machine/vmm.h>
#include <err.h>
#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include "acpi_device.h"
#include "bhyverun.h"
@@ -98,6 +103,15 @@
static struct qemu_fwcfg_softc fwcfg_sc;
+struct qemu_fwcfg_user_file {
+ STAILQ_ENTRY(qemu_fwcfg_user_file) chain;
+ uint8_t name[QEMU_FWCFG_MAX_NAME];
+ uint32_t size;
+ void *data;
+};
+static STAILQ_HEAD(qemu_fwcfg_user_file_list,
+ qemu_fwcfg_user_file) user_files = STAILQ_HEAD_INITIALIZER(user_files);
+
static int
qemu_fwcfg_selector_port_handler(struct vmctx *const ctx __unused, const int in,
const int port __unused, const int bytes, uint32_t *const eax,
@@ -384,6 +398,22 @@
return (0);
}
+static int
+qemu_fwcfg_add_user_files(void)
+{
+ const struct qemu_fwcfg_user_file *fwcfg_file;
+ int error;
+
+ STAILQ_FOREACH(fwcfg_file, &user_files, chain) {
+ error = qemu_fwcfg_add_file(fwcfg_file->name, fwcfg_file->size,
+ fwcfg_file->data);
+ if (error)
+ return (error);
+ }
+
+ return (0);
+}
+
static const struct acpi_device_emul qemu_fwcfg_acpi_device_emul = {
.name = QEMU_FWCFG_ACPI_DEVICE_NAME,
.hid = QEMU_FWCFG_ACPI_HARDWARE_ID,
@@ -458,6 +488,11 @@
}
if ((error = qemu_fwcfg_add_item_file_dir()) != 0) {
warnx("%s: Unable to add file_dir item", __func__);
+ }
+
+ /* add user defined fwcfg files */
+ if ((error = qemu_fwcfg_add_user_files()) != 0) {
+ warnx("%s: Unable to add user files", __func__);
goto done;
}
@@ -468,3 +503,112 @@
return (error);
}
+
+static void
+qemu_fwcfg_usage(const char *opt)
+{
+ warnx("Invalid fw_cfg option \"%s\"", opt);
+ warnx("-f [name=]<name>,(string|file)=<value>");
+}
+
+/*
+ * Parses the cmdline argument for user defined fw_cfg items. The cmdline
+ * argument has the format:
+ * "-f [name=]<name>,(string|file)=<value>"
+ *
+ * E.g.: "-f opt/com.page/example,string=Hello"
+ */
+int
+qemu_fwcfg_parse_cmdline_arg(const char *opt)
+{
+ struct qemu_fwcfg_user_file *fwcfg_file;
+ struct stat sb;
+ const char *opt_ptr, *opt_end;
+ int fd;
+
+ fwcfg_file = malloc(sizeof(*fwcfg_file));
+ if (fwcfg_file == NULL) {
+ warnx("Unable to allocate fw_cfg_user_file");
+ return (ENOMEM);
+ }
+
+ /* get pointer to <name> */
+ opt_ptr = opt;
+ /* If [name=] is specified, skip it */
+ if (strncmp(opt_ptr, "name=", sizeof("name=") - 1) == 0) {
+ opt_ptr += sizeof("name=") - 1;
+ }
+
+ /* get the end of <name> */
+ opt_end = strchr(opt_ptr, ',');
+ if (opt_end == NULL) {
+ qemu_fwcfg_usage(opt);
+ return (EINVAL);
+ }
+
+ /* check if <name> is too long */
+ if (opt_end - opt_ptr >= QEMU_FWCFG_MAX_NAME) {
+ warnx("fw_cfg name too long: \"%s\"", opt);
+ return (EINVAL);
+ }
+
+ /* save <name> */
+ strncpy(fwcfg_file->name, opt_ptr, opt_end - opt_ptr);
+ fwcfg_file->name[opt_end - opt_ptr] = '\0';
+
+ /* set opt_ptr and opt_end to <value> */
+ opt_ptr = opt_end + 1;
+ opt_end = opt_ptr + strlen(opt_ptr);
+
+ if (strncmp(opt_ptr, "string=", sizeof("string=") - 1) == 0) {
+ opt_ptr += sizeof("string=") - 1;
+ fwcfg_file->data = strdup(opt_ptr);
+ if (fwcfg_file->data == NULL) {
+ warnx(" Can't duplicate fw_cfg_user_file string \"%s\"",
+ opt_ptr);
+ return (ENOMEM);
+ }
+ fwcfg_file->size = strlen(opt_ptr) + 1;
+ } else if (strncmp(opt_ptr, "file=", sizeof("file=") - 1) == 0) {
+ opt_ptr += sizeof("file=") - 1;
+
+ fd = open(opt_ptr, O_RDONLY);
+ if (fd < 0) {
+ warnx("Can't open fw_cfg_user_file file \"%s\"",
+ opt_ptr);
+ return (EINVAL);
+ }
+
+ if (fstat(fd, &sb) < 0) {
+ warnx("Unable to get size of file \"%s\"", opt_ptr);
+ close(fd);
+ return (errno);
+ }
+
+ fwcfg_file->data = malloc(sb.st_size);
+ if (fwcfg_file->data == NULL) {
+ warnx(
+ "Can't allocate fw_cfg_user_file file \"%s\" (size: 0x%16lx)",
+ opt_ptr, sb.st_size);
+ close(fd);
+ return (ENOMEM);
+ }
+ fwcfg_file->size = read(fd, fwcfg_file->data, sb.st_size);
+ if (fwcfg_file->size != sb.st_size) {
+ warnx("Unable to read file \"%s\"", opt_ptr);
+ free(fwcfg_file->data);
+ close(fd);
+ return (errno);
+ }
+
+ close(fd);
+
+ } else {
+ qemu_fwcfg_usage(opt);
+ return (EINVAL);
+ }
+
+ STAILQ_INSERT_TAIL(&user_files, fwcfg_file, chain);
+
+ return (0);
+}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Jan 18, 10:43 PM (20 h, 59 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15900829
Default Alt Text
D38338.id121571.diff (6 KB)
Attached To
Mode
D38338: bhyve: add cmdline option for user defined fw_cfg items
Attached
Detach File
Event Timeline
Log In to Comment