Date: Sat, 18 Jul 2026 22:10:44 +0000 From: Chuck Tuffli <chuck@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Cc: John De Boskey <jwd@freebsd.org> Subject: git: cbd442efe85d - main - bhyve: add configurable SMBIOS OEM Strings Message-ID: <6a5bf9e4.24f79.6babb116@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by chuck: URL: https://cgit.FreeBSD.org/src/commit/?id=cbd442efe85d9ae371581565670dfc0287afbf8e commit cbd442efe85d9ae371581565670dfc0287afbf8e Author: John De Boskey <jwd@freebsd.org> AuthorDate: 2026-07-18 21:39:33 +0000 Commit: Chuck Tuffli <chuck@FreeBSD.org> CommitDate: 2026-07-18 22:07:07 +0000 bhyve: add configurable SMBIOS OEM Strings Add the option "oemstring" to allow setting the DMI type 11 ("OEM Strings") SMBIOS structure. These are free-form strings, available for any purpose, but can be especially useful to pass configuration, secrets, and credential information into a Linux guest and consumed by systemd. MFC after: 1 month Relnotes: yes Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D57516 --- usr.sbin/bhyve/bhyve_config.5 | 3 + usr.sbin/bhyve/smbiostbl.c | 124 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+) diff --git a/usr.sbin/bhyve/bhyve_config.5 b/usr.sbin/bhyve/bhyve_config.5 index dd82bea61d20..ae84aba1fe57 100644 --- a/usr.sbin/bhyve/bhyve_config.5 +++ b/usr.sbin/bhyve/bhyve_config.5 @@ -226,6 +226,9 @@ This value is used for the guest's System Management BIOS System Information str Stock keeping unit of the chassis. It's also called product ID or purchase order number. This value is used for the guest's System Management BIOS System Information structure. +.It Va oemstring.N Ta string Ta none Ta +This value is returned for the guest's Nth System Management BIOS System Information OEM Strings structure. +Configuration can specify up to 255 strings. .It Va rundir Ta String Ta Pa /var/run/bhyve/ Ta Path to the runtime directory for .Xr bhyve 8 diff --git a/usr.sbin/bhyve/smbiostbl.c b/usr.sbin/bhyve/smbiostbl.c index e09fbc95fc9e..8bb2415318bb 100644 --- a/usr.sbin/bhyve/smbiostbl.c +++ b/usr.sbin/bhyve/smbiostbl.c @@ -29,10 +29,13 @@ #include <sys/param.h> #include <assert.h> +#include <err.h> #include <errno.h> #include <md5.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> +#include <sysexits.h> #include <unistd.h> #include <uuid.h> @@ -61,6 +64,7 @@ #define SMBIOS_TYPE_BOARD 2 #define SMBIOS_TYPE_CHASSIS 3 #define SMBIOS_TYPE_PROCESSOR 4 +#define SMBIOS_TYPE_OEM 11 #define SMBIOS_TYPE_MEMARRAY 16 #define SMBIOS_TYPE_MEMDEVICE 17 #define SMBIOS_TYPE_MEMARRAYMAP 19 @@ -250,6 +254,13 @@ struct smbios_table_type4 { uint16_t family2; /* processor family 2 */ } __packed; +#define SMBIOS_TYPE11_MAX_COUNT 255 + +struct smbios_table_type11 { + struct smbios_structure header; + uint8_t nstrings; /* number of oem strings to follow */ +} __packed; + /* * Physical Memory Array */ @@ -479,6 +490,15 @@ static int smbios_type4_initializer( const struct smbios_string *template_strings, char *curaddr, char **endaddr, uint16_t *n); +static const struct smbios_table_type11 smbios_type11_template = { + { SMBIOS_TYPE_OEM, sizeof(struct smbios_table_type11), 0 }, + 0 /* first string */ +}; + +static int smbios_type11_initializer(const struct smbios_structure *template_entry, + const struct smbios_string *template_strings, char *curaddr, char **endaddr, + uint16_t *n); + static const struct smbios_table_type16 smbios_type16_template = { { SMBIOS_TYPE_MEMARRAY, sizeof (struct smbios_table_type16), 0 }, SMBIOS_MAL_SYSMB, @@ -582,6 +602,9 @@ static struct smbios_template_entry smbios_template[] = { { (const struct smbios_structure *)&smbios_type4_template, smbios_type4_strings, smbios_type4_initializer }, + { (const struct smbios_structure *)&smbios_type11_template, + NULL, + smbios_type11_initializer }, { (const struct smbios_structure *)&smbios_type16_template, NULL, smbios_type16_initializer }, @@ -750,6 +773,107 @@ smbios_type4_initializer(const struct smbios_structure *template_entry, return (0); } +/* + * Gather oemstring values from oemstring node of config kvlist + * + * Notes: The keys must be numeric and greater than zero. + * + * Any missing number keys will be added with a value + * of "N/A" + * + * The maximum number of strings allowed is 255 + */ + +static struct smbios_string * +smbios_gather_type11_strings(void) +{ + const char *na = "N/A"; + struct smbios_string *strings; + const char *name; + char *np; + void *cookie = NULL; + nvlist_t *node; + long maxnumber = 0; + long number; + char keystr[4]; /* SMBIOS_TYPE11_MAX_COUNT is a 3 digit number */ + char canonical[4]; + int key, type; + + /* find any oemstrings */ + node = find_config_node("oemstring"); + /* nothing to do if none */ + if (!node) + return NULL; + + while ((name = nvlist_next(node, &type, &cookie)) != NULL) { + if (type != NV_TYPE_STRING) + errx(BHYVE_EXIT_ERROR, "Unexpected entry type for %s", name); + + errno = 0; + number = strtol(name, &np, 10); + if ((*np != '\0') || (errno == EINVAL)) + errx(BHYVE_EXIT_ERROR, "Invalid format: %s should be a decimal number", name); + if (number <= 0 || number > SMBIOS_TYPE11_MAX_COUNT) + errx(BHYVE_EXIT_ERROR, "Invalid range: %s should be in 1-%d", name, + SMBIOS_TYPE11_MAX_COUNT); + /* strtol accepts leading zeros and signed values which will break search */ + snprintf(canonical, sizeof(canonical), "%ld", number); + if (strcmp(name, canonical) != 0) + errx(BHYVE_EXIT_ERROR, "Invalid format: %s should be %s", name, canonical); + if (number > maxnumber) + maxnumber = number; + } + strings = calloc(maxnumber + 1, sizeof(struct smbios_string)); + if (strings == NULL) + err(BHYVE_EXIT_ERROR, "oemstring allocation failed"); + + /* + * The returned smbios_string should leave the node field as NULL to + * avoid creating a new node in the config tree. + */ + for (key = 1; key <= maxnumber; key++) { + const char *vp; + + snprintf(keystr, sizeof(keystr), "%d", key); + if (nvlist_exists(node, keystr)) + vp = nvlist_get_string(node, keystr); + else + vp = na; + strings[key - 1].value = strdup(vp); + if (strings[key - 1].value == NULL) + err(BHYVE_EXIT_ERROR, "oemstring value allocation failed"); + } + + /* return data */ + return (strings); +} + +static int +smbios_type11_initializer(const struct smbios_structure *template_entry, + const struct smbios_string *template_strings __unused, char *curaddr, + char **endaddr, uint16_t *n) +{ + struct smbios_table_type11 *type11; + struct smbios_string *type11_strings; + int i = 0; + + type11_strings = smbios_gather_type11_strings(); + + smbios_generic_initializer(template_entry, type11_strings, curaddr, + endaddr, n); + + if (type11_strings != NULL) { + /* count up strings */ + type11 = (struct smbios_table_type11 *)curaddr; + for (i = 0; type11_strings[i].value != NULL; i++) { + free(__DECONST(char *, type11_strings[i].value)); + } + type11->nstrings = i; + } + free(type11_strings); + return (0); +} + static int smbios_type16_initializer(const struct smbios_structure *template_entry, const struct smbios_string *template_strings, char *curaddr, char **endaddr,home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a5bf9e4.24f79.6babb116>
