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.nighting...@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.nighting...@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_ */
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to