From nobody Thu May 11 12:20:54 2023 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4QH9wR0CP8z4B9Qm; Thu, 11 May 2023 12:20:55 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4QH9wQ6X28z44vf; Thu, 11 May 2023 12:20:54 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1683807654; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=2O3rvfY9Q06ClVOKsPSkXgmzuabXIznzFtG7fCDm32M=; b=Lhceiuqt3OBHkkpbZsz4IFkPHVWs3094Yoj1R4ohC0FOU2l8UpDgxschPwlFl0LyYZW4ZY 9l034hUrWY/bn3dbI5/PkDj3rH4J4+sI1hFr+UWoQ1kUI/RDFLT59/L9HW3yDisxv777+d aWzwrp0PAIrQBAL8EYfO/oEMxvMrDRLijIbL9mZwgA4lF/jEmnMntSZ3sCe4wSvy4egyxk l2RUXG411BDfDxDdzWoq0fkDhJ5zQhKSAXMgLOmrf35wxJI+GVWQrQKjPwMh71pGKWOubu bhbM7wnoFh9eU86jo0pSqFXYJ1lchd4ZLqjKXjXZ9fTir01bmbIKiF3OJFSBSA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1683807654; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=2O3rvfY9Q06ClVOKsPSkXgmzuabXIznzFtG7fCDm32M=; b=JI/uzbAVQb41xG5x+1rDulOrYUsE9Xnjv1TlxtGlZPCcvrSImNj4gI0lh09jokhzrzFJZu THPyh98qL1pYbRHxgcvJ4uq7xe9AZhClTmsFw91H1y8UB3kJ7kSlbC2HfAyXGZpl760NsR L9rMmkrb2d+MKib0UI5DnbfXcuzJ9rkfD/jiEMF7HEDNSKYG3NAr/8RjlqBYzi2bXNKlH2 z8PwzUMyEPiUZANbvfnL+OCeMMyhzmpyWraUSbGlFhzQMxovXZXpc+dpRZpuX8Mmz9N8Wa a1FqTsxO3flrnYOd3z/qGARuDwtC4306K3x1E9OjzZG44MX3fxZuUwZFknxQBw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1683807654; a=rsa-sha256; cv=none; b=WRWynnREj3clFFw+6lg9hwehjJK9+2FYIODC0s1EyuaKc3NaPRjsIltslgcrhQSiAO3ya8 AcgIlN6+O+bz/W8JA/B5K9Cc15vutXfTObrYx69Bui3IQ7yZt9nFSRq5Gbtw2VNyzw+8YA oPJGe8GkL5J2VuoQWILVekXLPfS6xyu7t9yQ1iuMStt9sk24kaCXul4Ifps87gp02y3psY um8vCKIJmlxTq9pTDBUM/Vfve9SyP9qzvssqsBMi9hNlBdXnQJH+PPGyAxyjE+4tWgSZop hnt2w/X4Fzhf1K3O6UJOum1J9uj3YIJJEbKsCK8KJcMd7utefLLPus0UIZMn9w== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4QH9wQ5Jp4zsc0; Thu, 11 May 2023 12:20:54 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 34BCKs03055499; Thu, 11 May 2023 12:20:54 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 34BCKsg6055498; Thu, 11 May 2023 12:20:54 GMT (envelope-from git) Date: Thu, 11 May 2023 12:20:54 GMT Message-Id: <202305111220.34BCKsg6055498@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: =?utf-8?Q?Corvin=20K=C3=B6hne?= Subject: git: ca14781c8170 - main - bhyve: add cmdline option for user defined fw_cfg items List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: corvink X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: ca14781c8170f3517ae79e198c0c880dbc3142dd Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by corvink: URL: https://cgit.FreeBSD.org/src/commit/?id=ca14781c8170f3517ae79e198c0c880dbc3142dd commit ca14781c8170f3517ae79e198c0c880dbc3142dd Author: Corvin Köhne AuthorDate: 2021-09-08 09:31:21 +0000 Commit: Corvin Köhne CommitDate: 2023-05-11 12:20:32 +0000 bhyve: add cmdline option for user defined fw_cfg items Some guest allow to configure themself by fw_cfg. E.g. Fedora CoreOs can be provisioned by adding a JSON file as fw_cfg item. Reviewed by: jhb MFC after: 1 week Sponsored by: Beckhoff Automation GmbH & Co. KG Differential Revision: https://reviews.freebsd.org/D38338 --- usr.sbin/bhyve/bhyve.8 | 19 ++++++ usr.sbin/bhyve/bhyverun.c | 9 ++- usr.sbin/bhyve/qemu_fwcfg.c | 146 ++++++++++++++++++++++++++++++++++++++++++++ usr.sbin/bhyve/qemu_fwcfg.h | 1 + 4 files changed, 173 insertions(+), 2 deletions(-) diff --git a/usr.sbin/bhyve/bhyve.8 b/usr.sbin/bhyve/bhyve.8 index 321c014395fb..38891ab33c40 100644 --- 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 @@ Force .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 index 627a86d71e0e..5c5d4608b10d 100644 --- a/usr.sbin/bhyve/bhyverun.c +++ b/usr.sbin/bhyve/bhyverun.c @@ -1259,9 +1259,9 @@ main(int argc, char *argv[]) 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 @@ main(int argc, char *argv[]) case 'C': set_config_bool("memory.guest_in_core", true); break; + case 'f': + if (qemu_fwcfg_parse_cmdline_arg(optarg) != 0) { + errx(EX_USAGE, "invalid fwcfg item '%s'", optarg); + } + break; case 'G': parse_gdb_options(optarg); break; diff --git a/usr.sbin/bhyve/qemu_fwcfg.c b/usr.sbin/bhyve/qemu_fwcfg.c index af819dc4a952..73a10e0e61c9 100644 --- a/usr.sbin/bhyve/qemu_fwcfg.c +++ b/usr.sbin/bhyve/qemu_fwcfg.c @@ -7,13 +7,18 @@ #include #include +#include +#include #include #include #include +#include +#include #include #include +#include #include "acpi_device.h" #include "bhyverun.h" @@ -98,6 +103,15 @@ struct qemu_fwcfg_softc { 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 @@ qemu_fwcfg_add_file(const char *name, const uint32_t size, void *const data) 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 @@ qemu_fwcfg_init(struct vmctx *const ctx) } 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,114 @@ done: return (error); } + +static void +qemu_fwcfg_usage(const char *opt) +{ + warnx("Invalid fw_cfg option \"%s\"", opt); + warnx("-f [name=],(string|file)="); +} + +/* + * Parses the cmdline argument for user defined fw_cfg items. The cmdline + * argument has the format: + * "-f [name=],(string|file)=" + * + * 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 */ + 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 */ + opt_end = strchr(opt_ptr, ','); + if (opt_end == NULL) { + qemu_fwcfg_usage(opt); + return (EINVAL); + } + + /* check if is too long */ + if (opt_end - opt_ptr >= QEMU_FWCFG_MAX_NAME) { + warnx("fw_cfg name too long: \"%s\"", opt); + return (EINVAL); + } + + /* save */ + 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 */ + 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) { + warn("Can't open fw_cfg_user_file file \"%s\"", + opt_ptr); + return (EINVAL); + } + + if (fstat(fd, &sb) < 0) { + warn("Unable to get size of file \"%s\"", opt_ptr); + close(fd); + return (-1); + } + + 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 ((ssize_t)fwcfg_file->size < 0) { + warn("Unable to read file \"%s\"", opt_ptr); + free(fwcfg_file->data); + close(fd); + return (-1); + } else if (fwcfg_file->size < sb.st_size) { + warnx("Only read %u bytes of file \"%s\"", + fwcfg_file->size, opt_ptr); + } + + close(fd); + } else { + qemu_fwcfg_usage(opt); + return (EINVAL); + } + + STAILQ_INSERT_TAIL(&user_files, fwcfg_file, chain); + + return (0); +} diff --git a/usr.sbin/bhyve/qemu_fwcfg.h b/usr.sbin/bhyve/qemu_fwcfg.h index d318d0434285..98881b4ab79d 100644 --- a/usr.sbin/bhyve/qemu_fwcfg.h +++ b/usr.sbin/bhyve/qemu_fwcfg.h @@ -23,3 +23,4 @@ struct qemu_fwcfg_item { 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);