Page MenuHomeFreeBSD

D57516.id181761.diff
No OneTemporary

D57516.id181761.diff

diff --git a/usr.sbin/bhyve/bhyve_config.5 b/usr.sbin/bhyve/bhyve_config.5
--- a/usr.sbin/bhyve/bhyve_config.5
+++ b/usr.sbin/bhyve/bhyve_config.5
@@ -226,6 +226,9 @@
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
--- a/usr.sbin/bhyve/smbiostbl.c
+++ b/usr.sbin/bhyve/smbiostbl.c
@@ -29,10 +29,14 @@
#include <sys/param.h>
#include <assert.h>
+#include <ctype.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 +65,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 +255,13 @@
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 +491,15 @@
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 +603,9 @@
{ (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 +774,171 @@
return (0);
}
+/*
+ * Gather oemstring values from oemstring node of config kvlist
+ *
+ * 1) Create a new kvlist, valid, to save off valid keys and values
+ * 2) Determine storage for any numerically missing keys
+ * 3) Create storage, make pointer array
+ *
+ * Returns: pointer to a char ** array of strings
+ * name, and value pointers
+ *
+ * Notes: The keys must be numeric and greater than zero. if not,
+ * they are ignored
+ *
+ * Any missing number keys will be added with a value
+ * of "N/A"
+ *
+ * There is a storage after the pointers in strings for
+ * all of the keys and values.
+ *
+ * The maximum number of strings allowed is 255
+ */
+
+static struct smbios_string *
+smbios_gather_type11_strings(void)
+{
+ char value[256], numberkey[6];
+ const char *na = "N/A";
+ char *np, *sp;
+ struct smbios_string* strings;
+ const char *name;
+ void *cookie = NULL;
+ nvlist_t *node;
+ nvlist_t *valid = NULL;
+ long maxnumber = 0;
+ long number;
+ int stringtotal = 0;
+ int fromconfig = 0;
+ int i, type;
+
+ /* find any oemstrings */
+ node = find_config_node("oemstring");
+ /* nothing to do if none */
+ if (!node)
+ return NULL;
+
+ /* add valid keys to nvlist: valid */
+ while ((name = nvlist_next(node, &type, &cookie)) != NULL) {
+ bool numbersonly = 1;
+ if (valid == NULL) {
+ valid = nvlist_create(0);
+ if (valid == NULL)
+ err(4, "Failed to create valid oemstring nvlist");
+ }
+
+ /* verify name is all numbers */
+ for (i = 0; name[i]; i++) {
+ if (!isdigit((int)name[i])) {
+ numbersonly = 0;
+ break;
+ }
+ }
+ if (!numbersonly)
+ errx(EX_USAGE, "Invalid format: %s should only contain digits", name);
+
+ /* get integer value of current name */
+ number = strtol(name, &np, 0);
+ if (number == 0 || number > SMBIOS_TYPE11_MAX_COUNT)
+ errx(EX_USAGE, "Invalid range: %s should be in 0-%d", name, SMBIOS_TYPE11_MAX_COUNT);
+
+ snprintf(numberkey, sizeof(numberkey), "%05d", (int)number);
+ if (number > maxnumber)
+ maxnumber = number;
+
+ /* add this string */
+ switch (type) {
+ case NV_TYPE_NUMBER:
+ snprintf(value, sizeof(value), "%ju", (uintmax_t)nvlist_get_number(node, name));
+ break;
+ case NV_TYPE_STRING:
+ snprintf(value, sizeof(value), "%s", nvlist_get_string(node, name));
+ break;
+ default:
+ /* errx(1, "Unexpected type '%d'", type); */
+ strcpy(value, na);
+ break;
+ }
+ nvlist_add_string(valid, numberkey, value);
+ /* add strings lengths plus trailing nulls */
+ stringtotal += (strlen(numberkey) + strlen(value) + 2);
+ fromconfig++;
+ }
+
+ /* add any storage required for missing values */
+ stringtotal += ((strlen(numberkey) + strlen(na) + 2) * (maxnumber - fromconfig));
+
+ /*
+ * create storage for the number of pairs plus NULL pair at end
+ * we also will store the key and value strings after the pointers
+ *
+ * storage layout is:
+ *
+ * j<node/value> pair(s) including a null pair
+ * followed by all strings
+ */
+ i = (sizeof(struct smbios_string) * (maxnumber + 1)) + stringtotal;
+ strings = malloc(i);
+ if (strings == NULL)
+ err(4, "oemstring allocation failed");
+
+ memset(strings, 0, i);
+ /* initialize sp to the first byte past the string descriptors */
+ sp = (char *)(strings + (maxnumber + 1));
+ maxnumber++;
+
+ /* populate the descriptors and save off the strings */
+ for (i=1; i < maxnumber; i++) {
+ const char *vp;
+ /* store number */
+ snprintf(numberkey, sizeof(numberkey), "%05d", i);
+ strcpy(sp, numberkey);
+ strings[i - 1].node = sp;
+ sp += strlen(numberkey) + 1;
+ /* store value or "N/A" */
+ if (nvlist_exists(valid, numberkey))
+ vp = nvlist_get_string(valid, numberkey);
+ else
+ vp = na;
+ strcpy(sp, vp);
+ strings[i - 1].value = sp;
+ sp += strlen(vp) + 1;
+ }
+
+ /* remove nvlist */
+ nvlist_destroy(valid);
+
+ /* return data */
+ return (strings);
+}
+
+static int
+smbios_type11_initializer(const struct smbios_structure *template_entry,
+ const struct smbios_string *template_strings, 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();
+ template_strings = type11_strings;
+
+ smbios_generic_initializer(template_entry, template_strings,
+ curaddr, endaddr, n);
+
+ if (template_strings != NULL) {
+ /* count up strings */
+ type11 = (struct smbios_table_type11 *)curaddr;
+ for (i = 0; template_strings[i].node != NULL; i++)
+ ;
+ 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,

File Metadata

Mime Type
text/plain
Expires
Sat, Oct 10, 5:23 AM (3 h, 28 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40526590
Default Alt Text
D57516.id181761.diff (7 KB)

Event Timeline