Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 4 Mar 2014 17:12:06 +0000 (UTC)
From:      Tycho Nightingale <tychon@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r262744 - head/usr.sbin/bhyve
Message-ID:  <201403041712.s24HC6Jd012637@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: tychon
Date: Tue Mar  4 17:12:06 2014
New Revision: 262744
URL: http://svnweb.freebsd.org/changeset/base/262744

Log:
  Add SMBIOS support.
  
  A new option, -U, can be used to set the UUID in the System
  Information (Type 1) structure.  Manpage fix to follow.
  
  Approved by:	grehan (co-mentor)

Added:
  head/usr.sbin/bhyve/smbiostbl.c   (contents, props changed)
  head/usr.sbin/bhyve/smbiostbl.h   (contents, props changed)
Modified:
  head/usr.sbin/bhyve/Makefile
  head/usr.sbin/bhyve/acpi.c
  head/usr.sbin/bhyve/bhyverun.c
  head/usr.sbin/bhyve/bhyverun.h

Modified: head/usr.sbin/bhyve/Makefile
==============================================================================
--- head/usr.sbin/bhyve/Makefile	Tue Mar  4 15:14:47 2014	(r262743)
+++ head/usr.sbin/bhyve/Makefile	Tue Mar  4 17:12:06 2014	(r262744)
@@ -34,6 +34,7 @@ SRCS=	\
 	pmtmr.c			\
 	post.c			\
 	rtc.c			\
+	smbiostbl.c		\
 	uart_emul.c		\
 	virtio.c		\
 	xmsr.c			\

Modified: head/usr.sbin/bhyve/acpi.c
==============================================================================
--- head/usr.sbin/bhyve/acpi.c	Tue Mar  4 15:14:47 2014	(r262743)
+++ head/usr.sbin/bhyve/acpi.c	Tue Mar  4 17:12:06 2014	(r262744)
@@ -39,14 +39,14 @@
  *
  *  Layout
  *  ------
- *   RSDP  ->   0xf0400    (36 bytes fixed)
- *     RSDT  ->   0xf0440    (36 bytes + 4*N table addrs, 2 used)
- *     XSDT  ->   0xf0480    (36 bytes + 8*N table addrs, 2 used)
- *       MADT  ->   0xf0500  (depends on #CPUs)
- *       FADT  ->   0xf0600  (268 bytes)
- *       HPET  ->   0xf0740  (56 bytes)
- *         FACS  ->   0xf0780 (64 bytes)
- *         DSDT  ->   0xf0800 (variable - can go up to 0x100000)
+ *   RSDP  ->   0xf2400    (36 bytes fixed)
+ *     RSDT  ->   0xf2440    (36 bytes + 4*N table addrs, 2 used)
+ *     XSDT  ->   0xf2480    (36 bytes + 8*N table addrs, 2 used)
+ *       MADT  ->   0xf2500  (depends on #CPUs)
+ *       FADT  ->   0xf2600  (268 bytes)
+ *       HPET  ->   0xf2740  (56 bytes)
+ *         FACS  ->   0xf2780 (64 bytes)
+ *         DSDT  ->   0xf2800 (variable - can go up to 0x100000)
  */
 
 #include <sys/cdefs.h>
@@ -74,7 +74,7 @@ __FBSDID("$FreeBSD$");
  * Define the base address of the ACPI tables, and the offsets to
  * the individual tables
  */
-#define BHYVE_ACPI_BASE		0xf0400
+#define BHYVE_ACPI_BASE		0xf2400
 #define RSDT_OFFSET		0x040
 #define XSDT_OFFSET		0x080
 #define MADT_OFFSET		0x100

Modified: head/usr.sbin/bhyve/bhyverun.c
==============================================================================
--- head/usr.sbin/bhyve/bhyverun.c	Tue Mar  4 15:14:47 2014	(r262743)
+++ head/usr.sbin/bhyve/bhyverun.c	Tue Mar  4 17:12:06 2014	(r262744)
@@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$");
 #include "mptbl.h"
 #include "pci_emul.h"
 #include "pci_lpc.h"
+#include "smbiostbl.h"
 #include "xmsr.h"
 #include "spinup_ap.h"
 #include "rtc.h"
@@ -82,6 +83,7 @@ typedef int (*vmexit_handler_t)(struct v
 char *vmname;
 
 int guest_ncpus;
+char *guest_uuid_str;
 
 static int pincpu = -1;
 static int guest_vmexit_on_hlt, guest_vmexit_on_pause;
@@ -141,7 +143,8 @@ usage(int code)
 		"       -l: LPC device configuration\n"
 		"       -m: memory size in MB\n"
 		"       -w: ignore unimplemented MSRs\n"
-		"       -x: local apic is in x2APIC mode\n",
+		"       -x: local apic is in x2APIC mode\n"
+		"       -U: uuid\n",
 		progname, (int)strlen(progname), "");
 
 	exit(code);
@@ -599,7 +602,7 @@ main(int argc, char *argv[])
 	guest_ncpus = 1;
 	memsize = 256 * MB;
 
-	while ((c = getopt(argc, argv, "abehwxAHIPWp:g:c:s:m:l:")) != -1) {
+	while ((c = getopt(argc, argv, "abehwxAHIPWp:g:c:s:m:l:U:")) != -1) {
 		switch (c) {
 		case 'a':
 			x2apic_mode = 0;
@@ -653,6 +656,9 @@ main(int argc, char *argv[])
 		case 'e':
 			strictio = 1;
 			break;
+		case 'U':
+			guest_uuid_str = optarg;
+			break;
 		case 'w':
 			strictmsr = 0;
 			break;
@@ -723,6 +729,9 @@ main(int argc, char *argv[])
 	 */
 	mptable_build(ctx, guest_ncpus);
 
+	error = smbios_build(ctx);
+	assert(error == 0);
+
 	if (acpi) {
 		error = acpi_build(ctx, guest_ncpus);
 		assert(error == 0);

Modified: head/usr.sbin/bhyve/bhyverun.h
==============================================================================
--- head/usr.sbin/bhyve/bhyverun.h	Tue Mar  4 15:14:47 2014	(r262743)
+++ head/usr.sbin/bhyve/bhyverun.h	Tue Mar  4 17:12:06 2014	(r262744)
@@ -37,6 +37,7 @@
 
 struct vmctx;
 extern int guest_ncpus;
+extern char *guest_uuid_str;
 extern char *vmname;
 
 void *paddr_guest2host(struct vmctx *ctx, uintptr_t addr, size_t len);

Added: head/usr.sbin/bhyve/smbiostbl.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/usr.sbin/bhyve/smbiostbl.c	Tue Mar  4 17:12:06 2014	(r262744)
@@ -0,0 +1,832 @@
+/*-
+ * Copyright (c) 2014 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <md5.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <uuid.h>
+
+#include <machine/vmm.h>
+#include <vmmapi.h>
+
+#include "bhyverun.h"
+#include "smbiostbl.h"
+
+#define	MB			(1024*1024)
+#define	GB			(1024ULL*1024*1024)
+
+#define SMBIOS_BASE		0xF1000
+
+/* BHYVE_ACPI_BASE - SMBIOS_BASE) */
+#define	SMBIOS_MAX_LENGTH	(0xF2400 - 0xF1000)
+
+#define	SMBIOS_TYPE_BIOS	0
+#define	SMBIOS_TYPE_SYSTEM	1
+#define	SMBIOS_TYPE_CHASSIS	3
+#define	SMBIOS_TYPE_PROCESSOR	4
+#define	SMBIOS_TYPE_MEMARRAY	16
+#define	SMBIOS_TYPE_MEMDEVICE	17
+#define	SMBIOS_TYPE_MEMARRAYMAP	19
+#define	SMBIOS_TYPE_BOOT	32
+#define	SMBIOS_TYPE_EOT		127
+
+struct smbios_structure {
+	uint8_t		type;
+	uint8_t		length;
+	uint16_t	handle;
+} __packed;
+
+typedef int (*initializer_func_t)(struct smbios_structure *template_entry,
+    const char **template_strings, char *curaddr, char **endaddr,
+    uint16_t *n, uint16_t *size);
+
+struct smbios_template_entry {
+	struct smbios_structure	*entry;
+	const char		**strings;
+	initializer_func_t	initializer;
+};
+
+/*
+ * SMBIOS Structure Table Entry Point
+ */
+#define	SMBIOS_ENTRY_EANCHOR	"_SM_"
+#define	SMBIOS_ENTRY_EANCHORLEN	4
+#define	SMBIOS_ENTRY_IANCHOR	"_DMI_"
+#define	SMBIOS_ENTRY_IANCHORLEN	5
+
+struct smbios_entry_point {
+	char		eanchor[4];	/* anchor tag */
+	uint8_t		echecksum;	/* checksum of entry point structure */
+	uint8_t		eplen;		/* length in bytes of entry point */
+	uint8_t		major;		/* major version of the SMBIOS spec */
+	uint8_t		minor;		/* minor version of the SMBIOS spec */
+	uint16_t	maxssize;	/* maximum size in bytes of a struct */
+	uint8_t		revision;	/* entry point structure revision */
+	uint8_t		format[5];	/* entry point rev-specific data */
+	char		ianchor[5];	/* intermediate anchor tag */
+	uint8_t		ichecksum;	/* intermediate checksum */
+	uint16_t	stlen;		/* len in bytes of structure table */
+	uint32_t	staddr;		/* physical addr of structure table */
+	uint16_t	stnum;		/* number of structure table entries */
+	uint8_t		bcdrev;		/* BCD value representing DMI ver */
+} __packed;
+
+/*
+ * BIOS Information
+ */
+#define	SMBIOS_FL_ISA		0x00000010	/* ISA is supported */
+#define	SMBIOS_FL_PCI		0x00000080	/* PCI is supported */
+#define	SMBIOS_FL_SHADOW	0x00001000	/* BIOS shadowing is allowed */
+#define	SMBIOS_FL_CDBOOT	0x00008000	/* Boot from CD is supported */
+#define	SMBIOS_FL_SELBOOT	0x00010000	/* Selectable Boot supported */
+#define	SMBIOS_FL_EDD		0x00080000	/* EDD Spec is supported */
+
+#define	SMBIOS_XB1_FL_ACPI	0x00000001	/* ACPI is supported */
+
+#define	SMBIOS_XB2_FL_BBS	0x00000001	/* BIOS Boot Specification */
+#define	SMBIOS_XB2_FL_VM	0x00000010	/* Virtual Machine */
+
+struct smbios_table_type0 {
+	struct smbios_structure	header;
+	uint8_t			vendor;		/* vendor string */
+	uint8_t			version;	/* version string */
+	uint16_t		segment;	/* address segment location */
+	uint8_t			rel_date;	/* release date */
+	uint8_t			size;		/* rom size */
+	uint64_t		cflags;		/* characteristics */
+	uint8_t			xc_bytes[2];	/* characteristics ext bytes */
+	uint8_t			sb_major_rel;	/* system bios version */
+	uint8_t			sb_minor_rele;
+	uint8_t			ecfw_major_rel;	/* embedded ctrl fw version */
+	uint8_t			ecfw_minor_rel;
+} __packed;
+
+/*
+ * System Information
+ */
+#define	SMBIOS_WAKEUP_SWITCH	0x06	/* power switch */
+
+struct smbios_table_type1 {
+	struct smbios_structure	header;
+	uint8_t			manufacturer;	/* manufacturer string */
+	uint8_t			product;	/* product name string */
+	uint8_t			version;	/* version string */
+	uint8_t			serial;		/* serial number string */
+	uint8_t			uuid[16];	/* uuid byte array */
+	uint8_t			wakeup;		/* wake-up event */
+	uint8_t			sku;		/* sku number string */
+	uint8_t			family;		/* family name string */
+} __packed;
+
+/*
+ * System Enclosure or Chassis
+ */
+#define	SMBIOS_CHT_UNKNOWN	0x02	/* unknown */
+
+#define	SMBIOS_CHST_SAFE	0x03	/* safe */
+
+#define	SMBIOS_CHSC_NONE	0x03	/* none */
+
+struct smbios_table_type3 {
+	struct smbios_structure	header;
+	uint8_t			manufacturer;	/* manufacturer string */
+	uint8_t			type;		/* type */
+	uint8_t			version;	/* version string */
+	uint8_t			serial;		/* serial number string */
+	uint8_t			asset;		/* asset tag string */
+	uint8_t			bustate;	/* boot-up state */
+	uint8_t			psstate;	/* power supply state */
+	uint8_t			tstate;		/* thermal state */
+	uint8_t			security;	/* security status */
+	uint8_t			uheight;	/* height in 'u's */
+	uint8_t			cords;		/* number of power cords */
+	uint8_t			elems;		/* number of element records */
+	uint8_t			elemlen;	/* length of records */
+	uint8_t			sku;		/* sku number string */
+} __packed;
+
+/*
+ * Processor Information
+ */
+#define	SMBIOS_PRT_CENTRAL	0x03	/* central processor */
+
+#define	SMBIOS_PRF_OTHER	0x01	/* other */
+
+#define	SMBIOS_PRS_PRESENT	0x40	/* socket is populated */
+#define	SMBIOS_PRS_ENABLED	0x1	/* enabled */
+
+#define	SMBIOS_PRU_NONE		0x06	/* none */
+
+#define	SMBIOS_PFL_64B	0x04	/* 64-bit capable */
+
+struct smbios_table_type4 {
+	struct smbios_structure	header;
+	uint8_t			socket;		/* socket designation string */
+	uint8_t			type;		/* processor type */
+	uint8_t			family;		/* processor family */
+	uint8_t			manufacturer;	/* manufacturer string */
+	uint64_t		cpuid;		/* processor cpuid */
+	uint8_t			version;	/* version string */
+	uint8_t			voltage;	/* voltage */
+	uint16_t		clkspeed;	/* ext clock speed in mhz */
+	uint16_t		maxspeed;	/* maximum speed in mhz */
+	uint16_t		curspeed;	/* current speed in mhz */
+	uint8_t			status;		/* status */
+	uint8_t			upgrade;	/* upgrade */
+	uint16_t		l1handle;	/* l1 cache handle */
+	uint16_t		l2handle;	/* l2 cache handle */
+	uint16_t		l3handle;	/* l3 cache handle */
+	uint8_t			serial;		/* serial number string */
+	uint8_t			asset;		/* asset tag string */
+	uint8_t			part;		/* part number string */
+	uint8_t			cores;		/* cores per socket */
+	uint8_t			ecores;		/* enabled cores */
+	uint8_t			threads;	/* threads per socket */
+	uint16_t		cflags;		/* processor characteristics */
+	uint16_t		family2;	/* processor family 2 */
+} __packed;
+
+/*
+ * Physical Memory Array
+ */
+#define	SMBIOS_MAL_SYSMB	0x03	/* system board or motherboard */
+
+#define	SMBIOS_MAU_SYSTEM	0x03	/* system memory */
+
+#define	SMBIOS_MAE_NONE		0x03	/* none */
+
+struct smbios_table_type16 {
+	struct smbios_structure	header;
+	uint8_t			location;	/* physical device location */
+	uint8_t			use;		/* device functional purpose */
+	uint8_t			ecc;		/* err detect/correct method */
+	uint32_t		size;		/* max mem capacity in kb */
+	uint16_t		errhand;	/* handle of error (if any) */
+	uint16_t		ndevs;		/* num of slots or sockets */
+	uint64_t		xsize;		/* max mem capacity in bytes */
+} __packed;
+
+/*
+ * Memory Device
+ */
+#define	SMBIOS_MDFF_UNKNOWN	0x02	/* unknown */
+
+#define	SMBIOS_MDT_UNKNOWN	0x02	/* unknown */
+
+#define	SMBIOS_MDF_UNKNOWN	0x0004	/* unknown */
+
+struct smbios_table_type17 {
+	struct smbios_structure	header;
+	uint16_t		arrayhand;	/* handle of physl mem array */
+	uint16_t		errhand;	/* handle of mem error data */
+	uint16_t		twidth;		/* total width in bits */
+	uint16_t		dwidth;		/* data width in bits */
+	uint16_t		size;		/* size in bytes */
+	uint8_t			form;		/* form factor */
+	uint8_t			set;		/* set */
+	uint8_t			dloc;		/* device locator string */
+	uint8_t			bloc;		/* phys bank locator string */
+	uint8_t			type;		/* memory type */
+	uint16_t		flags;		/* memory characteristics */
+	uint16_t		maxspeed;	/* maximum speed in mhz */
+	uint8_t			manufacturer;	/* manufacturer string */
+	uint8_t			serial;		/* serial number string */
+	uint8_t			asset;		/* asset tag string */
+	uint8_t			part;		/* part number string */
+	uint8_t			attributes;	/* attributes */
+	uint32_t		xsize;		/* extended size in mbs */
+	uint16_t		curspeed;	/* current speed in mhz */
+	uint16_t		minvoltage;	/* minimum voltage */
+	uint16_t		maxvoltage;	/* maximum voltage */
+	uint16_t		curvoltage;	/* configured voltage */
+} __packed;
+
+/*
+ * Memory Array Mapped Address
+ */
+struct smbios_table_type19 {
+	struct smbios_structure	header;
+	uint32_t		saddr;		/* start phys addr in kb */
+	uint32_t		eaddr;		/* end phys addr in kb */
+	uint16_t		arrayhand;	/* physical mem array handle */
+	uint8_t			width;		/* num of dev in row */
+	uint64_t		xsaddr;		/* start phys addr in bytes */
+	uint64_t		xeaddr;		/* end phys addr in bytes */
+} __packed;
+
+/*
+ * System Boot Information
+ */
+#define	SMBIOS_BOOT_NORMAL	0	/* no errors detected */
+
+struct smbios_table_type32 {
+	struct smbios_structure	header;
+	uint8_t			reserved[6];
+	uint8_t			status;		/* boot status */
+} __packed;
+
+/*
+ * End-of-Table
+ */
+struct smbios_table_type127 {
+	struct smbios_structure	header;
+} __packed;
+
+struct smbios_table_type0 smbios_type0_template = {
+	{ SMBIOS_TYPE_BIOS, sizeof (struct smbios_table_type0), 0 },
+	1,	/* bios vendor string */
+	2,	/* bios version string */
+	0xF000,	/* bios address segment location */
+	3,	/* bios release date */
+	0x0,	/* bios size (64k * (n + 1) is the size in bytes) */
+	SMBIOS_FL_ISA | SMBIOS_FL_PCI | SMBIOS_FL_SHADOW |
+	    SMBIOS_FL_CDBOOT | SMBIOS_FL_EDD,
+	{ SMBIOS_XB1_FL_ACPI, SMBIOS_XB2_FL_BBS | SMBIOS_XB2_FL_VM },
+	0x0,	/* bios major release */
+	0x0,	/* bios minor release */
+	0xff,	/* embedded controller firmware major release */
+	0xff	/* embedded controller firmware minor release */
+};
+
+const char *smbios_type0_strings[] = {
+	"BHYVE",	/* vendor string */
+	__TIME__,	/* bios version string */
+	__DATE__,	/* bios release date string */
+	NULL
+};
+
+struct smbios_table_type1 smbios_type1_template = {
+	{ SMBIOS_TYPE_SYSTEM, sizeof (struct smbios_table_type1), 0 },
+	1,		/* manufacturer string */
+	2,		/* product string */
+	3,		/* version string */
+	4,		/* serial number string */
+	{ 0 },
+	SMBIOS_WAKEUP_SWITCH,
+	5,		/* sku string */
+	6		/* family string */
+};
+
+static int smbios_type1_initializer(struct smbios_structure *template_entry,
+    const char **template_strings, char *curaddr, char **endaddr,
+    uint16_t *n, uint16_t *size);
+
+const char *smbios_type1_strings[] = {
+	" ",		/* manufacturer string */
+	"BHYVE",	/* product name string */
+	"1.0",		/* version string */
+	"None",		/* serial number string */
+	"None",		/* sku string */
+	" ",		/* family name string */
+	NULL
+};
+
+struct smbios_table_type3 smbios_type3_template = {
+	{ SMBIOS_TYPE_CHASSIS, sizeof (struct smbios_table_type3), 0 },
+	1,		/* manufacturer string */
+	SMBIOS_CHT_UNKNOWN,
+	2,		/* version string */
+	3,		/* serial number string */
+	4,		/* asset tag string */
+	SMBIOS_CHST_SAFE,
+	SMBIOS_CHST_SAFE,
+	SMBIOS_CHST_SAFE,
+	SMBIOS_CHSC_NONE,
+	0,		/* height in 'u's (0=enclosure height unspecified) */
+	0,		/* number of power cords (0=number unspecified) */
+	0,		/* number of contained element records */
+	0,		/* length of records */
+	5		/* sku number string */
+};
+
+const char *smbios_type3_strings[] = {
+	" ",		/* manufacturer string */
+	"1.0",		/* version string */
+	"None",		/* serial number string */
+	"None",		/* asset tag string */
+	"None",		/* sku number string */
+	NULL
+};
+
+struct smbios_table_type4 smbios_type4_template = {
+	{ SMBIOS_TYPE_PROCESSOR, sizeof (struct smbios_table_type4), 0 },
+	1,		/* socket designation string */
+	SMBIOS_PRT_CENTRAL,
+	SMBIOS_PRF_OTHER,
+	2,		/* manufacturer string */
+	0,		/* cpuid */
+	3,		/* version string */
+	0,		/* voltage */
+	0,		/* external clock frequency in mhz (0=unknown) */
+	0,		/* maximum frequency in mhz (0=unknown) */
+	0,		/* current frequency in mhz (0=unknown) */
+	SMBIOS_PRS_PRESENT | SMBIOS_PRS_ENABLED,
+	SMBIOS_PRU_NONE,
+	-1,		/* l1 cache handle */
+	-1,		/* l2 cache handle */
+	-1,		/* l3 cache handle */
+	4,		/* serial number string */
+	5,		/* asset tag string */
+	6,		/* part number string */
+	0,		/* cores per socket (0=unknown) */
+	0,		/* enabled cores per socket (0=unknown) */
+	0,		/* threads per socket (0=unknown) */
+	SMBIOS_PFL_64B,
+	SMBIOS_PRF_OTHER
+};
+
+const char *smbios_type4_strings[] = {
+	" ",		/* socket designation string */
+	" ",		/* manufacturer string */
+	" ",		/* version string */
+	"None",		/* serial number string */
+	"None",		/* asset tag string */
+	"None",		/* part number string */
+	NULL
+};
+
+static int smbios_type4_initializer(struct smbios_structure *template_entry,
+    const char **template_strings, char *curaddr, char **endaddr,
+    uint16_t *n, uint16_t *size);
+
+struct smbios_table_type16 smbios_type16_template = {
+	{ SMBIOS_TYPE_MEMARRAY, sizeof (struct smbios_table_type16),  0 },
+	SMBIOS_MAL_SYSMB,
+	SMBIOS_MAU_SYSTEM,
+	SMBIOS_MAE_NONE,
+	0x80000000,	/* max mem capacity in kb (0x80000000=use extended) */
+	-1,		/* handle of error (if any) */
+	0,		/* number of slots or sockets (TBD) */
+	0		/* extended maximum memory capacity in bytes (TBD) */
+};
+
+static int smbios_type16_initializer(struct smbios_structure *template_entry,
+    const char **template_strings, char *curaddr, char **endaddr,
+    uint16_t *n, uint16_t *size);
+
+struct smbios_table_type17 smbios_type17_template = {
+	{ SMBIOS_TYPE_MEMDEVICE, sizeof (struct smbios_table_type17),  0 },
+	-1,		/* handle of physical memory array */
+	-1,		/* handle of memory error data */
+	64,		/* total width in bits including ecc */
+	64,		/* data width in bits */
+	0x7fff,		/* size in bytes (0x7fff=use extended)*/
+	SMBIOS_MDFF_UNKNOWN,
+	0,		/* set (0x00=none, 0xff=unknown) */
+	1,		/* device locator string */
+	2,		/* physical bank locator string */
+	SMBIOS_MDT_UNKNOWN,
+	SMBIOS_MDF_UNKNOWN,
+	0,		/* maximum memory speed in mhz (0=unknown) */
+	3,		/* manufacturer string */
+	4,		/* serial number string */
+	5,		/* asset tag string */
+	6,		/* part number string */
+	0,		/* attributes (0=unknown rank information) */
+	0,		/* extended size in mb (TBD) */
+	0,		/* current speed in mhz (0=unknown) */
+	0,		/* minimum voltage in mv (0=unknown) */
+	0,		/* maximum voltage in mv (0=unknown) */
+	0		/* configured voltage in mv (0=unknown) */
+};
+
+const char *smbios_type17_strings[] = {
+	" ",		/* device locator string */
+	" ",		/* physical bank locator string */
+	" ",		/* manufacturer string */
+	"None",		/* serial number string */
+	"None",		/* asset tag string */
+	"None",		/* part number string */
+	NULL
+};
+
+static int smbios_type17_initializer(struct smbios_structure *template_entry,
+    const char **template_strings, char *curaddr, char **endaddr,
+    uint16_t *n, uint16_t *size);
+
+struct smbios_table_type19 smbios_type19_template = {
+	{ SMBIOS_TYPE_MEMARRAYMAP, sizeof (struct smbios_table_type19),  0 },
+	0xffffffff,	/* starting phys addr in kb (0xffffffff=use ext) */
+	0xffffffff,	/* ending phys addr in kb (0xffffffff=use ext) */
+	-1,		/* physical memory array handle */
+	1,		/* number of devices that form a row */
+	0,		/* extended starting phys addr in bytes (TDB) */
+	0		/* extended ending phys addr in bytes (TDB) */
+};
+
+static int smbios_type19_initializer(struct smbios_structure *template_entry,
+    const char **template_strings, char *curaddr, char **endaddr,
+    uint16_t *n, uint16_t *size);
+
+struct smbios_table_type32 smbios_type32_template = {
+	{ SMBIOS_TYPE_BOOT, sizeof (struct smbios_table_type32),  0 },
+	{ 0, 0, 0, 0, 0, 0 },
+	SMBIOS_BOOT_NORMAL
+};
+
+struct smbios_table_type127 smbios_type127_template = {
+	{ SMBIOS_TYPE_EOT, sizeof (struct smbios_table_type127),  0 }
+};
+
+static int smbios_generic_initializer(struct smbios_structure *template_entry,
+    const char **template_strings, char *curaddr, char **endaddr,
+    uint16_t *n, uint16_t *size);
+
+static struct smbios_template_entry smbios_template[] = {
+	{ (struct smbios_structure *)&smbios_type0_template,
+	  smbios_type0_strings,
+	  smbios_generic_initializer },
+	{ (struct smbios_structure *)&smbios_type1_template,
+	  smbios_type1_strings,
+	  smbios_type1_initializer },
+	{ (struct smbios_structure *)&smbios_type3_template,
+	  smbios_type3_strings,
+	  smbios_generic_initializer },
+	{ (struct smbios_structure *)&smbios_type4_template,
+	  smbios_type4_strings,
+	  smbios_type4_initializer },
+	{ (struct smbios_structure *)&smbios_type16_template,
+	  NULL,
+	  smbios_type16_initializer },
+	{ (struct smbios_structure *)&smbios_type17_template,
+	  smbios_type17_strings,
+	  smbios_type17_initializer },
+	{ (struct smbios_structure *)&smbios_type19_template,
+	  NULL,
+	  smbios_type19_initializer },
+	{ (struct smbios_structure *)&smbios_type32_template,
+	  NULL,
+	  smbios_generic_initializer },
+	{ (struct smbios_structure *)&smbios_type127_template,
+	  NULL,
+	  smbios_generic_initializer },
+	{ NULL,NULL, NULL }
+};
+
+static uint64_t guest_lomem, guest_himem;
+static uint16_t type16_handle;
+
+static int
+smbios_generic_initializer(struct smbios_structure *template_entry,
+    const char **template_strings, char *curaddr, char **endaddr,
+    uint16_t *n, uint16_t *size)
+{
+	struct smbios_structure *entry;
+
+	memcpy(curaddr, template_entry, template_entry->length);
+	entry = (struct smbios_structure *)curaddr;
+	entry->handle = *n + 1;
+	curaddr += entry->length;
+	if (template_strings != NULL) {
+		int	i;
+
+		for (i = 0; template_strings[i] != NULL; i++) {
+			const char *string;
+			int len;
+
+			string = template_strings[i];
+			len = strlen(string) + 1;
+			memcpy(curaddr, string, len);
+			curaddr += len;
+		}
+		*curaddr = '\0';
+		curaddr++;
+	} else {
+		/* Minimum string section is double nul */
+		*curaddr = '\0';
+		curaddr++;
+		*curaddr = '\0';
+		curaddr++;
+	}
+	(*n)++;
+	*endaddr = curaddr;
+
+	return (0);
+}
+
+static int
+smbios_type1_initializer(struct smbios_structure *template_entry,
+    const char **template_strings, char *curaddr, char **endaddr,
+    uint16_t *n, uint16_t *size)
+{
+	struct smbios_table_type1 *type1;
+
+	smbios_generic_initializer(template_entry, template_strings,
+	    curaddr, endaddr, n, size);
+	type1 = (struct smbios_table_type1 *)curaddr;
+
+	if (guest_uuid_str != NULL) {
+		uuid_t		uuid;
+		uint32_t	status;
+
+		uuid_from_string(guest_uuid_str, &uuid, &status);
+		if (status != uuid_s_ok)
+			return (-1);
+
+		uuid_enc_le(&type1->uuid, &uuid);
+	} else {
+		MD5_CTX		mdctx;
+		u_char		digest[16];
+		char		hostname[MAXHOSTNAMELEN];
+
+		/*
+		 * Universally unique and yet reproducible are an
+		 * oxymoron, however reproducible is desirable in
+		 * this case.
+		 */
+		if (gethostname(hostname, sizeof(hostname)))
+			return (-1);
+
+		MD5Init(&mdctx);
+		MD5Update(&mdctx, vmname, strlen(vmname));
+		MD5Update(&mdctx, hostname, sizeof(hostname));
+		MD5Final(digest, &mdctx);
+
+		/*
+		 * Set the variant and version number.
+		 */
+		digest[6] &= 0x0F;
+		digest[6] |= 0x30;	/* version 3 */
+		digest[8] &= 0x3F;
+		digest[8] |= 0x80;
+
+		memcpy(&type1->uuid, digest, sizeof (digest));
+	}
+
+	return (0);
+}
+
+static int
+smbios_type4_initializer(struct smbios_structure *template_entry,
+    const char **template_strings, char *curaddr, char **endaddr,
+    uint16_t *n, uint16_t *size)
+{
+	int i;
+
+	for (i = 0; i < guest_ncpus; i++) {
+		struct smbios_table_type4 *type4;
+		char *p;
+		int nstrings, len;
+
+		smbios_generic_initializer(template_entry, template_strings,
+		    curaddr, endaddr, n, size);
+		type4 = (struct smbios_table_type4 *)curaddr;
+		p = curaddr + sizeof (struct smbios_table_type4);
+		nstrings = 0;
+		while (p < *endaddr - 1) {
+			if (*p++ == '\0')
+				nstrings++;
+		}
+		len = sprintf(*endaddr - 1, "CPU #%d", i) + 1;
+		*endaddr += len - 1;
+		*(*endaddr) = '\0';
+		(*endaddr)++;
+		type4->socket = nstrings + 1;
+		curaddr = *endaddr;
+	}
+
+	return (0);
+}
+
+static int
+smbios_type16_initializer(struct smbios_structure *template_entry,
+    const char **template_strings, char *curaddr, char **endaddr,
+    uint16_t *n, uint16_t *size)
+{
+	struct smbios_table_type16 *type16;
+
+	type16_handle = *n;
+	smbios_generic_initializer(template_entry, template_strings,
+	    curaddr, endaddr, n, size);
+	type16 = (struct smbios_table_type16 *)curaddr;
+	type16->xsize = guest_lomem + guest_himem;
+	type16->ndevs = guest_himem > 0 ? 2 : 1;
+
+	return (0);
+}
+
+static int
+smbios_type17_initializer(struct smbios_structure *template_entry,
+    const char **template_strings, char *curaddr, char **endaddr,
+    uint16_t *n, uint16_t *size)
+{
+	struct smbios_table_type17 *type17;
+
+	smbios_generic_initializer(template_entry, template_strings,
+	    curaddr, endaddr, n, size);
+	type17 = (struct smbios_table_type17 *)curaddr;
+	type17->arrayhand = type16_handle;
+	type17->xsize = guest_lomem;
+
+	if (guest_himem > 0) {
+		curaddr = *endaddr;
+		smbios_generic_initializer(template_entry, template_strings,
+		    curaddr, endaddr, n, size);
+		type17 = (struct smbios_table_type17 *)curaddr;
+		type17->arrayhand = type16_handle;
+		type17->xsize = guest_himem;
+	}
+
+	return (0);
+}
+
+static int
+smbios_type19_initializer(struct smbios_structure *template_entry,
+    const char **template_strings, char *curaddr, char **endaddr,
+    uint16_t *n, uint16_t *size)
+{
+	struct smbios_table_type19 *type19;
+
+	smbios_generic_initializer(template_entry, template_strings,
+	    curaddr, endaddr, n, size);
+	type19 = (struct smbios_table_type19 *)curaddr;
+	type19->arrayhand = type16_handle;
+	type19->xsaddr = 0;
+	type19->xeaddr = guest_lomem;
+
+	if (guest_himem > 0) {
+		curaddr = *endaddr;
+		smbios_generic_initializer(template_entry, template_strings,
+		    curaddr, endaddr, n, size);
+		type19 = (struct smbios_table_type19 *)curaddr;
+		type19->arrayhand = type16_handle;
+		type19->xsaddr = 4*GB;
+		type19->xeaddr = guest_himem;
+	}
+
+	return (0);
+}
+
+static void
+smbios_ep_initializer(struct smbios_entry_point *smbios_ep, uint32_t staddr)
+{
+	memset(smbios_ep, 0, sizeof(*smbios_ep));
+	memcpy(smbios_ep->eanchor, SMBIOS_ENTRY_EANCHOR,
+	    SMBIOS_ENTRY_EANCHORLEN);
+	smbios_ep->eplen = 0x1F;
+	assert(sizeof (struct smbios_entry_point) == smbios_ep->eplen);
+	smbios_ep->major = 2;
+	smbios_ep->minor = 4;
+	smbios_ep->revision = 0;
+	memcpy(smbios_ep->ianchor, SMBIOS_ENTRY_IANCHOR,
+	    SMBIOS_ENTRY_IANCHORLEN);
+	smbios_ep->staddr = staddr;
+	smbios_ep->bcdrev = 0x24;
+}
+
+static void
+smbios_ep_finalizer(struct smbios_entry_point *smbios_ep, uint16_t len,
+    uint16_t num, uint16_t maxssize)
+{
+	uint8_t	checksum;
+	int	i;
+
+	smbios_ep->maxssize = maxssize;
+	smbios_ep->stlen = len;
+	smbios_ep->stnum = num;
+
+	checksum = 0;
+	for (i = 0x10; i < 0x1f; i++) {
+		checksum -= ((uint8_t *)smbios_ep)[i];
+	}
+	smbios_ep->ichecksum = checksum;
+
+	checksum = 0;
+	for (i = 0; i < 0x1f; i++) {
+		checksum -= ((uint8_t *)smbios_ep)[i];
+	}
+	smbios_ep->echecksum = checksum;
+}
+
+int
+smbios_build(struct vmctx *ctx)
+{
+	struct smbios_entry_point	*smbios_ep;
+	uint16_t			n;
+	uint16_t			maxssize;
+	char				*curaddr, *startaddr, *ststartaddr;
+	int				i;
+	int				err;
+
+	err = vm_get_memory_seg(ctx, 0, &guest_lomem, NULL);
+	if (err != 0)
+		return (err);
+
+	err = vm_get_memory_seg(ctx, 4*GB, &guest_himem, NULL);
+	if (err != 0)
+		return (err);
+
+	startaddr = paddr_guest2host(ctx, SMBIOS_BASE, SMBIOS_MAX_LENGTH);
+	if (startaddr == NULL) {
+		fprintf(stderr, "smbios table requires mapped mem\n");
+		return (ENOMEM);
+	}
+
+	curaddr = startaddr;
+
+	smbios_ep = (struct smbios_entry_point *)curaddr;
+	smbios_ep_initializer(smbios_ep, SMBIOS_BASE +
+	    sizeof(struct smbios_entry_point));
+	curaddr += sizeof(struct smbios_entry_point);
+	ststartaddr = curaddr;
+
+	n = 0;
+	maxssize = 0;
+	for (i = 0; smbios_template[i].entry != NULL; i++) {
+		struct smbios_structure	*entry;
+		const char		**strings;
+		initializer_func_t      initializer;
+		char			*endaddr;
+		uint16_t		size;
+
+		entry = smbios_template[i].entry;
+		strings = smbios_template[i].strings;
+		initializer = smbios_template[i].initializer;
+
+		err = (*initializer)(entry, strings, curaddr, &endaddr,
+		    &n, &size);
+		if (err != 0)
+			return (err);
+
+		if (size > maxssize)
+			maxssize = size;
+
+		curaddr = endaddr;
+	}
+
+	assert(curaddr - startaddr < SMBIOS_MAX_LENGTH);
+	smbios_ep_finalizer(smbios_ep, curaddr - ststartaddr, n, maxssize);
+
+	return (0);
+}

Added: head/usr.sbin/bhyve/smbiostbl.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/usr.sbin/bhyve/smbiostbl.h	Tue Mar  4 17:12:06 2014	(r262744)
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2014 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SMBIOSTBL_H_
+#define _SMBIOSTBL_H_
+
+struct vmctx;
+
+int	smbios_build(struct vmctx *ctx);
+
+#endif /* _SMBIOSTBL_H_ */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201403041712.s24HC6Jd012637>