xref: /illumos-gate/usr/src/cmd/bhyve/smbiostbl.c (revision bf21cd93)
1*bf21cd93STycho Nightingale /*-
2*bf21cd93STycho Nightingale  * Copyright (c) 2014 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
3*bf21cd93STycho Nightingale  * All rights reserved.
4*bf21cd93STycho Nightingale  *
5*bf21cd93STycho Nightingale  * Redistribution and use in source and binary forms, with or without
6*bf21cd93STycho Nightingale  * modification, are permitted provided that the following conditions
7*bf21cd93STycho Nightingale  * are met:
8*bf21cd93STycho Nightingale  * 1. Redistributions of source code must retain the above copyright
9*bf21cd93STycho Nightingale  *    notice, this list of conditions and the following disclaimer.
10*bf21cd93STycho Nightingale  * 2. Redistributions in binary form must reproduce the above copyright
11*bf21cd93STycho Nightingale  *    notice, this list of conditions and the following disclaimer in the
12*bf21cd93STycho Nightingale  *    documentation and/or other materials provided with the distribution.
13*bf21cd93STycho Nightingale  *
14*bf21cd93STycho Nightingale  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
15*bf21cd93STycho Nightingale  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*bf21cd93STycho Nightingale  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*bf21cd93STycho Nightingale  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*bf21cd93STycho Nightingale  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*bf21cd93STycho Nightingale  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*bf21cd93STycho Nightingale  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*bf21cd93STycho Nightingale  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*bf21cd93STycho Nightingale  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*bf21cd93STycho Nightingale  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*bf21cd93STycho Nightingale  * SUCH DAMAGE.
25*bf21cd93STycho Nightingale  */
26*bf21cd93STycho Nightingale 
27*bf21cd93STycho Nightingale #include <sys/cdefs.h>
28*bf21cd93STycho Nightingale __FBSDID("$FreeBSD: head/usr.sbin/bhyve/smbiostbl.c 272007 2014-09-23 01:17:22Z grehan $");
29*bf21cd93STycho Nightingale 
30*bf21cd93STycho Nightingale #include <sys/param.h>
31*bf21cd93STycho Nightingale 
32*bf21cd93STycho Nightingale #include <assert.h>
33*bf21cd93STycho Nightingale #include <errno.h>
34*bf21cd93STycho Nightingale #include <md5.h>
35*bf21cd93STycho Nightingale #include <stdio.h>
36*bf21cd93STycho Nightingale #include <string.h>
37*bf21cd93STycho Nightingale #include <unistd.h>
38*bf21cd93STycho Nightingale #include <uuid.h>
39*bf21cd93STycho Nightingale 
40*bf21cd93STycho Nightingale #include <machine/vmm.h>
41*bf21cd93STycho Nightingale #include <vmmapi.h>
42*bf21cd93STycho Nightingale 
43*bf21cd93STycho Nightingale #include "bhyverun.h"
44*bf21cd93STycho Nightingale #include "smbiostbl.h"
45*bf21cd93STycho Nightingale 
46*bf21cd93STycho Nightingale #define	MB			(1024*1024)
47*bf21cd93STycho Nightingale #define	GB			(1024ULL*1024*1024)
48*bf21cd93STycho Nightingale 
49*bf21cd93STycho Nightingale #define SMBIOS_BASE		0xF1000
50*bf21cd93STycho Nightingale 
51*bf21cd93STycho Nightingale /* BHYVE_ACPI_BASE - SMBIOS_BASE) */
52*bf21cd93STycho Nightingale #define	SMBIOS_MAX_LENGTH	(0xF2400 - 0xF1000)
53*bf21cd93STycho Nightingale 
54*bf21cd93STycho Nightingale #define	SMBIOS_TYPE_BIOS	0
55*bf21cd93STycho Nightingale #define	SMBIOS_TYPE_SYSTEM	1
56*bf21cd93STycho Nightingale #define	SMBIOS_TYPE_CHASSIS	3
57*bf21cd93STycho Nightingale #define	SMBIOS_TYPE_PROCESSOR	4
58*bf21cd93STycho Nightingale #define	SMBIOS_TYPE_MEMARRAY	16
59*bf21cd93STycho Nightingale #define	SMBIOS_TYPE_MEMDEVICE	17
60*bf21cd93STycho Nightingale #define	SMBIOS_TYPE_MEMARRAYMAP	19
61*bf21cd93STycho Nightingale #define	SMBIOS_TYPE_BOOT	32
62*bf21cd93STycho Nightingale #define	SMBIOS_TYPE_EOT		127
63*bf21cd93STycho Nightingale 
64*bf21cd93STycho Nightingale struct smbios_structure {
65*bf21cd93STycho Nightingale 	uint8_t		type;
66*bf21cd93STycho Nightingale 	uint8_t		length;
67*bf21cd93STycho Nightingale 	uint16_t	handle;
68*bf21cd93STycho Nightingale } __packed;
69*bf21cd93STycho Nightingale 
70*bf21cd93STycho Nightingale typedef int (*initializer_func_t)(struct smbios_structure *template_entry,
71*bf21cd93STycho Nightingale     const char **template_strings, char *curaddr, char **endaddr,
72*bf21cd93STycho Nightingale     uint16_t *n, uint16_t *size);
73*bf21cd93STycho Nightingale 
74*bf21cd93STycho Nightingale struct smbios_template_entry {
75*bf21cd93STycho Nightingale 	struct smbios_structure	*entry;
76*bf21cd93STycho Nightingale 	const char		**strings;
77*bf21cd93STycho Nightingale 	initializer_func_t	initializer;
78*bf21cd93STycho Nightingale };
79*bf21cd93STycho Nightingale 
80*bf21cd93STycho Nightingale /*
81*bf21cd93STycho Nightingale  * SMBIOS Structure Table Entry Point
82*bf21cd93STycho Nightingale  */
83*bf21cd93STycho Nightingale #define	SMBIOS_ENTRY_EANCHOR	"_SM_"
84*bf21cd93STycho Nightingale #define	SMBIOS_ENTRY_EANCHORLEN	4
85*bf21cd93STycho Nightingale #define	SMBIOS_ENTRY_IANCHOR	"_DMI_"
86*bf21cd93STycho Nightingale #define	SMBIOS_ENTRY_IANCHORLEN	5
87*bf21cd93STycho Nightingale 
88*bf21cd93STycho Nightingale struct smbios_entry_point {
89*bf21cd93STycho Nightingale 	char		eanchor[4];	/* anchor tag */
90*bf21cd93STycho Nightingale 	uint8_t		echecksum;	/* checksum of entry point structure */
91*bf21cd93STycho Nightingale 	uint8_t		eplen;		/* length in bytes of entry point */
92*bf21cd93STycho Nightingale 	uint8_t		major;		/* major version of the SMBIOS spec */
93*bf21cd93STycho Nightingale 	uint8_t		minor;		/* minor version of the SMBIOS spec */
94*bf21cd93STycho Nightingale 	uint16_t	maxssize;	/* maximum size in bytes of a struct */
95*bf21cd93STycho Nightingale 	uint8_t		revision;	/* entry point structure revision */
96*bf21cd93STycho Nightingale 	uint8_t		format[5];	/* entry point rev-specific data */
97*bf21cd93STycho Nightingale 	char		ianchor[5];	/* intermediate anchor tag */
98*bf21cd93STycho Nightingale 	uint8_t		ichecksum;	/* intermediate checksum */
99*bf21cd93STycho Nightingale 	uint16_t	stlen;		/* len in bytes of structure table */
100*bf21cd93STycho Nightingale 	uint32_t	staddr;		/* physical addr of structure table */
101*bf21cd93STycho Nightingale 	uint16_t	stnum;		/* number of structure table entries */
102*bf21cd93STycho Nightingale 	uint8_t		bcdrev;		/* BCD value representing DMI ver */
103*bf21cd93STycho Nightingale } __packed;
104*bf21cd93STycho Nightingale 
105*bf21cd93STycho Nightingale /*
106*bf21cd93STycho Nightingale  * BIOS Information
107*bf21cd93STycho Nightingale  */
108*bf21cd93STycho Nightingale #define	SMBIOS_FL_ISA		0x00000010	/* ISA is supported */
109*bf21cd93STycho Nightingale #define	SMBIOS_FL_PCI		0x00000080	/* PCI is supported */
110*bf21cd93STycho Nightingale #define	SMBIOS_FL_SHADOW	0x00001000	/* BIOS shadowing is allowed */
111*bf21cd93STycho Nightingale #define	SMBIOS_FL_CDBOOT	0x00008000	/* Boot from CD is supported */
112*bf21cd93STycho Nightingale #define	SMBIOS_FL_SELBOOT	0x00010000	/* Selectable Boot supported */
113*bf21cd93STycho Nightingale #define	SMBIOS_FL_EDD		0x00080000	/* EDD Spec is supported */
114*bf21cd93STycho Nightingale 
115*bf21cd93STycho Nightingale #define	SMBIOS_XB1_FL_ACPI	0x00000001	/* ACPI is supported */
116*bf21cd93STycho Nightingale 
117*bf21cd93STycho Nightingale #define	SMBIOS_XB2_FL_BBS	0x00000001	/* BIOS Boot Specification */
118*bf21cd93STycho Nightingale #define	SMBIOS_XB2_FL_VM	0x00000010	/* Virtual Machine */
119*bf21cd93STycho Nightingale 
120*bf21cd93STycho Nightingale struct smbios_table_type0 {
121*bf21cd93STycho Nightingale 	struct smbios_structure	header;
122*bf21cd93STycho Nightingale 	uint8_t			vendor;		/* vendor string */
123*bf21cd93STycho Nightingale 	uint8_t			version;	/* version string */
124*bf21cd93STycho Nightingale 	uint16_t		segment;	/* address segment location */
125*bf21cd93STycho Nightingale 	uint8_t			rel_date;	/* release date */
126*bf21cd93STycho Nightingale 	uint8_t			size;		/* rom size */
127*bf21cd93STycho Nightingale 	uint64_t		cflags;		/* characteristics */
128*bf21cd93STycho Nightingale 	uint8_t			xc_bytes[2];	/* characteristics ext bytes */
129*bf21cd93STycho Nightingale 	uint8_t			sb_major_rel;	/* system bios version */
130*bf21cd93STycho Nightingale 	uint8_t			sb_minor_rele;
131*bf21cd93STycho Nightingale 	uint8_t			ecfw_major_rel;	/* embedded ctrl fw version */
132*bf21cd93STycho Nightingale 	uint8_t			ecfw_minor_rel;
133*bf21cd93STycho Nightingale } __packed;
134*bf21cd93STycho Nightingale 
135*bf21cd93STycho Nightingale /*
136*bf21cd93STycho Nightingale  * System Information
137*bf21cd93STycho Nightingale  */
138*bf21cd93STycho Nightingale #define	SMBIOS_WAKEUP_SWITCH	0x06	/* power switch */
139*bf21cd93STycho Nightingale 
140*bf21cd93STycho Nightingale struct smbios_table_type1 {
141*bf21cd93STycho Nightingale 	struct smbios_structure	header;
142*bf21cd93STycho Nightingale 	uint8_t			manufacturer;	/* manufacturer string */
143*bf21cd93STycho Nightingale 	uint8_t			product;	/* product name string */
144*bf21cd93STycho Nightingale 	uint8_t			version;	/* version string */
145*bf21cd93STycho Nightingale 	uint8_t			serial;		/* serial number string */
146*bf21cd93STycho Nightingale 	uint8_t			uuid[16];	/* uuid byte array */
147*bf21cd93STycho Nightingale 	uint8_t			wakeup;		/* wake-up event */
148*bf21cd93STycho Nightingale 	uint8_t			sku;		/* sku number string */
149*bf21cd93STycho Nightingale 	uint8_t			family;		/* family name string */
150*bf21cd93STycho Nightingale } __packed;
151*bf21cd93STycho Nightingale 
152*bf21cd93STycho Nightingale /*
153*bf21cd93STycho Nightingale  * System Enclosure or Chassis
154*bf21cd93STycho Nightingale  */
155*bf21cd93STycho Nightingale #define	SMBIOS_CHT_UNKNOWN	0x02	/* unknown */
156*bf21cd93STycho Nightingale 
157*bf21cd93STycho Nightingale #define	SMBIOS_CHST_SAFE	0x03	/* safe */
158*bf21cd93STycho Nightingale 
159*bf21cd93STycho Nightingale #define	SMBIOS_CHSC_NONE	0x03	/* none */
160*bf21cd93STycho Nightingale 
161*bf21cd93STycho Nightingale struct smbios_table_type3 {
162*bf21cd93STycho Nightingale 	struct smbios_structure	header;
163*bf21cd93STycho Nightingale 	uint8_t			manufacturer;	/* manufacturer string */
164*bf21cd93STycho Nightingale 	uint8_t			type;		/* type */
165*bf21cd93STycho Nightingale 	uint8_t			version;	/* version string */
166*bf21cd93STycho Nightingale 	uint8_t			serial;		/* serial number string */
167*bf21cd93STycho Nightingale 	uint8_t			asset;		/* asset tag string */
168*bf21cd93STycho Nightingale 	uint8_t			bustate;	/* boot-up state */
169*bf21cd93STycho Nightingale 	uint8_t			psstate;	/* power supply state */
170*bf21cd93STycho Nightingale 	uint8_t			tstate;		/* thermal state */
171*bf21cd93STycho Nightingale 	uint8_t			security;	/* security status */
172*bf21cd93STycho Nightingale 	uint8_t			uheight;	/* height in 'u's */
173*bf21cd93STycho Nightingale 	uint8_t			cords;		/* number of power cords */
174*bf21cd93STycho Nightingale 	uint8_t			elems;		/* number of element records */
175*bf21cd93STycho Nightingale 	uint8_t			elemlen;	/* length of records */
176*bf21cd93STycho Nightingale 	uint8_t			sku;		/* sku number string */
177*bf21cd93STycho Nightingale } __packed;
178*bf21cd93STycho Nightingale 
179*bf21cd93STycho Nightingale /*
180*bf21cd93STycho Nightingale  * Processor Information
181*bf21cd93STycho Nightingale  */
182*bf21cd93STycho Nightingale #define	SMBIOS_PRT_CENTRAL	0x03	/* central processor */
183*bf21cd93STycho Nightingale 
184*bf21cd93STycho Nightingale #define	SMBIOS_PRF_OTHER	0x01	/* other */
185*bf21cd93STycho Nightingale 
186*bf21cd93STycho Nightingale #define	SMBIOS_PRS_PRESENT	0x40	/* socket is populated */
187*bf21cd93STycho Nightingale #define	SMBIOS_PRS_ENABLED	0x1	/* enabled */
188*bf21cd93STycho Nightingale 
189*bf21cd93STycho Nightingale #define	SMBIOS_PRU_NONE		0x06	/* none */
190*bf21cd93STycho Nightingale 
191*bf21cd93STycho Nightingale #define	SMBIOS_PFL_64B	0x04	/* 64-bit capable */
192*bf21cd93STycho Nightingale 
193*bf21cd93STycho Nightingale struct smbios_table_type4 {
194*bf21cd93STycho Nightingale 	struct smbios_structure	header;
195*bf21cd93STycho Nightingale 	uint8_t			socket;		/* socket designation string */
196*bf21cd93STycho Nightingale 	uint8_t			type;		/* processor type */
197*bf21cd93STycho Nightingale 	uint8_t			family;		/* processor family */
198*bf21cd93STycho Nightingale 	uint8_t			manufacturer;	/* manufacturer string */
199*bf21cd93STycho Nightingale 	uint64_t		cpuid;		/* processor cpuid */
200*bf21cd93STycho Nightingale 	uint8_t			version;	/* version string */
201*bf21cd93STycho Nightingale 	uint8_t			voltage;	/* voltage */
202*bf21cd93STycho Nightingale 	uint16_t		clkspeed;	/* ext clock speed in mhz */
203*bf21cd93STycho Nightingale 	uint16_t		maxspeed;	/* maximum speed in mhz */
204*bf21cd93STycho Nightingale 	uint16_t		curspeed;	/* current speed in mhz */
205*bf21cd93STycho Nightingale 	uint8_t			status;		/* status */
206*bf21cd93STycho Nightingale 	uint8_t			upgrade;	/* upgrade */
207*bf21cd93STycho Nightingale 	uint16_t		l1handle;	/* l1 cache handle */
208*bf21cd93STycho Nightingale 	uint16_t		l2handle;	/* l2 cache handle */
209*bf21cd93STycho Nightingale 	uint16_t		l3handle;	/* l3 cache handle */
210*bf21cd93STycho Nightingale 	uint8_t			serial;		/* serial number string */
211*bf21cd93STycho Nightingale 	uint8_t			asset;		/* asset tag string */
212*bf21cd93STycho Nightingale 	uint8_t			part;		/* part number string */
213*bf21cd93STycho Nightingale 	uint8_t			cores;		/* cores per socket */
214*bf21cd93STycho Nightingale 	uint8_t			ecores;		/* enabled cores */
215*bf21cd93STycho Nightingale 	uint8_t			threads;	/* threads per socket */
216*bf21cd93STycho Nightingale 	uint16_t		cflags;		/* processor characteristics */
217*bf21cd93STycho Nightingale 	uint16_t		family2;	/* processor family 2 */
218*bf21cd93STycho Nightingale } __packed;
219*bf21cd93STycho Nightingale 
220*bf21cd93STycho Nightingale /*
221*bf21cd93STycho Nightingale  * Physical Memory Array
222*bf21cd93STycho Nightingale  */
223*bf21cd93STycho Nightingale #define	SMBIOS_MAL_SYSMB	0x03	/* system board or motherboard */
224*bf21cd93STycho Nightingale 
225*bf21cd93STycho Nightingale #define	SMBIOS_MAU_SYSTEM	0x03	/* system memory */
226*bf21cd93STycho Nightingale 
227*bf21cd93STycho Nightingale #define	SMBIOS_MAE_NONE		0x03	/* none */
228*bf21cd93STycho Nightingale 
229*bf21cd93STycho Nightingale struct smbios_table_type16 {
230*bf21cd93STycho Nightingale 	struct smbios_structure	header;
231*bf21cd93STycho Nightingale 	uint8_t			location;	/* physical device location */
232*bf21cd93STycho Nightingale 	uint8_t			use;		/* device functional purpose */
233*bf21cd93STycho Nightingale 	uint8_t			ecc;		/* err detect/correct method */
234*bf21cd93STycho Nightingale 	uint32_t		size;		/* max mem capacity in kb */
235*bf21cd93STycho Nightingale 	uint16_t		errhand;	/* handle of error (if any) */
236*bf21cd93STycho Nightingale 	uint16_t		ndevs;		/* num of slots or sockets */
237*bf21cd93STycho Nightingale 	uint64_t		xsize;		/* max mem capacity in bytes */
238*bf21cd93STycho Nightingale } __packed;
239*bf21cd93STycho Nightingale 
240*bf21cd93STycho Nightingale /*
241*bf21cd93STycho Nightingale  * Memory Device
242*bf21cd93STycho Nightingale  */
243*bf21cd93STycho Nightingale #define	SMBIOS_MDFF_UNKNOWN	0x02	/* unknown */
244*bf21cd93STycho Nightingale 
245*bf21cd93STycho Nightingale #define	SMBIOS_MDT_UNKNOWN	0x02	/* unknown */
246*bf21cd93STycho Nightingale 
247*bf21cd93STycho Nightingale #define	SMBIOS_MDF_UNKNOWN	0x0004	/* unknown */
248*bf21cd93STycho Nightingale 
249*bf21cd93STycho Nightingale struct smbios_table_type17 {
250*bf21cd93STycho Nightingale 	struct smbios_structure	header;
251*bf21cd93STycho Nightingale 	uint16_t		arrayhand;	/* handle of physl mem array */
252*bf21cd93STycho Nightingale 	uint16_t		errhand;	/* handle of mem error data */
253*bf21cd93STycho Nightingale 	uint16_t		twidth;		/* total width in bits */
254*bf21cd93STycho Nightingale 	uint16_t		dwidth;		/* data width in bits */
255*bf21cd93STycho Nightingale 	uint16_t		size;		/* size in bytes */
256*bf21cd93STycho Nightingale 	uint8_t			form;		/* form factor */
257*bf21cd93STycho Nightingale 	uint8_t			set;		/* set */
258*bf21cd93STycho Nightingale 	uint8_t			dloc;		/* device locator string */
259*bf21cd93STycho Nightingale 	uint8_t			bloc;		/* phys bank locator string */
260*bf21cd93STycho Nightingale 	uint8_t			type;		/* memory type */
261*bf21cd93STycho Nightingale 	uint16_t		flags;		/* memory characteristics */
262*bf21cd93STycho Nightingale 	uint16_t		maxspeed;	/* maximum speed in mhz */
263*bf21cd93STycho Nightingale 	uint8_t			manufacturer;	/* manufacturer string */
264*bf21cd93STycho Nightingale 	uint8_t			serial;		/* serial number string */
265*bf21cd93STycho Nightingale 	uint8_t			asset;		/* asset tag string */
266*bf21cd93STycho Nightingale 	uint8_t			part;		/* part number string */
267*bf21cd93STycho Nightingale 	uint8_t			attributes;	/* attributes */
268*bf21cd93STycho Nightingale 	uint32_t		xsize;		/* extended size in mbs */
269*bf21cd93STycho Nightingale 	uint16_t		curspeed;	/* current speed in mhz */
270*bf21cd93STycho Nightingale 	uint16_t		minvoltage;	/* minimum voltage */
271*bf21cd93STycho Nightingale 	uint16_t		maxvoltage;	/* maximum voltage */
272*bf21cd93STycho Nightingale 	uint16_t		curvoltage;	/* configured voltage */
273*bf21cd93STycho Nightingale } __packed;
274*bf21cd93STycho Nightingale 
275*bf21cd93STycho Nightingale /*
276*bf21cd93STycho Nightingale  * Memory Array Mapped Address
277*bf21cd93STycho Nightingale  */
278*bf21cd93STycho Nightingale struct smbios_table_type19 {
279*bf21cd93STycho Nightingale 	struct smbios_structure	header;
280*bf21cd93STycho Nightingale 	uint32_t		saddr;		/* start phys addr in kb */
281*bf21cd93STycho Nightingale 	uint32_t		eaddr;		/* end phys addr in kb */
282*bf21cd93STycho Nightingale 	uint16_t		arrayhand;	/* physical mem array handle */
283*bf21cd93STycho Nightingale 	uint8_t			width;		/* num of dev in row */
284*bf21cd93STycho Nightingale 	uint64_t		xsaddr;		/* start phys addr in bytes */
285*bf21cd93STycho Nightingale 	uint64_t		xeaddr;		/* end phys addr in bytes */
286*bf21cd93STycho Nightingale } __packed;
287*bf21cd93STycho Nightingale 
288*bf21cd93STycho Nightingale /*
289*bf21cd93STycho Nightingale  * System Boot Information
290*bf21cd93STycho Nightingale  */
291*bf21cd93STycho Nightingale #define	SMBIOS_BOOT_NORMAL	0	/* no errors detected */
292*bf21cd93STycho Nightingale 
293*bf21cd93STycho Nightingale struct smbios_table_type32 {
294*bf21cd93STycho Nightingale 	struct smbios_structure	header;
295*bf21cd93STycho Nightingale 	uint8_t			reserved[6];
296*bf21cd93STycho Nightingale 	uint8_t			status;		/* boot status */
297*bf21cd93STycho Nightingale } __packed;
298*bf21cd93STycho Nightingale 
299*bf21cd93STycho Nightingale /*
300*bf21cd93STycho Nightingale  * End-of-Table
301*bf21cd93STycho Nightingale  */
302*bf21cd93STycho Nightingale struct smbios_table_type127 {
303*bf21cd93STycho Nightingale 	struct smbios_structure	header;
304*bf21cd93STycho Nightingale } __packed;
305*bf21cd93STycho Nightingale 
306*bf21cd93STycho Nightingale struct smbios_table_type0 smbios_type0_template = {
307*bf21cd93STycho Nightingale 	{ SMBIOS_TYPE_BIOS, sizeof (struct smbios_table_type0), 0 },
308*bf21cd93STycho Nightingale 	1,	/* bios vendor string */
309*bf21cd93STycho Nightingale 	2,	/* bios version string */
310*bf21cd93STycho Nightingale 	0xF000,	/* bios address segment location */
311*bf21cd93STycho Nightingale 	3,	/* bios release date */
312*bf21cd93STycho Nightingale 	0x0,	/* bios size (64k * (n + 1) is the size in bytes) */
313*bf21cd93STycho Nightingale 	SMBIOS_FL_ISA | SMBIOS_FL_PCI | SMBIOS_FL_SHADOW |
314*bf21cd93STycho Nightingale 	    SMBIOS_FL_CDBOOT | SMBIOS_FL_EDD,
315*bf21cd93STycho Nightingale 	{ SMBIOS_XB1_FL_ACPI, SMBIOS_XB2_FL_BBS | SMBIOS_XB2_FL_VM },
316*bf21cd93STycho Nightingale 	0x0,	/* bios major release */
317*bf21cd93STycho Nightingale 	0x0,	/* bios minor release */
318*bf21cd93STycho Nightingale 	0xff,	/* embedded controller firmware major release */
319*bf21cd93STycho Nightingale 	0xff	/* embedded controller firmware minor release */
320*bf21cd93STycho Nightingale };
321*bf21cd93STycho Nightingale 
322*bf21cd93STycho Nightingale const char *smbios_type0_strings[] = {
323*bf21cd93STycho Nightingale 	"BHYVE",	/* vendor string */
324*bf21cd93STycho Nightingale 	__TIME__,	/* bios version string */
325*bf21cd93STycho Nightingale 	__DATE__,	/* bios release date string */
326*bf21cd93STycho Nightingale 	NULL
327*bf21cd93STycho Nightingale };
328*bf21cd93STycho Nightingale 
329*bf21cd93STycho Nightingale struct smbios_table_type1 smbios_type1_template = {
330*bf21cd93STycho Nightingale 	{ SMBIOS_TYPE_SYSTEM, sizeof (struct smbios_table_type1), 0 },
331*bf21cd93STycho Nightingale 	1,		/* manufacturer string */
332*bf21cd93STycho Nightingale 	2,		/* product string */
333*bf21cd93STycho Nightingale 	3,		/* version string */
334*bf21cd93STycho Nightingale 	4,		/* serial number string */
335*bf21cd93STycho Nightingale 	{ 0 },
336*bf21cd93STycho Nightingale 	SMBIOS_WAKEUP_SWITCH,
337*bf21cd93STycho Nightingale 	5,		/* sku string */
338*bf21cd93STycho Nightingale 	6		/* family string */
339*bf21cd93STycho Nightingale };
340*bf21cd93STycho Nightingale 
341*bf21cd93STycho Nightingale static int smbios_type1_initializer(struct smbios_structure *template_entry,
342*bf21cd93STycho Nightingale     const char **template_strings, char *curaddr, char **endaddr,
343*bf21cd93STycho Nightingale     uint16_t *n, uint16_t *size);
344*bf21cd93STycho Nightingale 
345*bf21cd93STycho Nightingale const char *smbios_type1_strings[] = {
346*bf21cd93STycho Nightingale 	" ",		/* manufacturer string */
347*bf21cd93STycho Nightingale 	"BHYVE",	/* product name string */
348*bf21cd93STycho Nightingale 	"1.0",		/* version string */
349*bf21cd93STycho Nightingale 	"None",		/* serial number string */
350*bf21cd93STycho Nightingale 	"None",		/* sku string */
351*bf21cd93STycho Nightingale 	" ",		/* family name string */
352*bf21cd93STycho Nightingale 	NULL
353*bf21cd93STycho Nightingale };
354*bf21cd93STycho Nightingale 
355*bf21cd93STycho Nightingale struct smbios_table_type3 smbios_type3_template = {
356*bf21cd93STycho Nightingale 	{ SMBIOS_TYPE_CHASSIS, sizeof (struct smbios_table_type3), 0 },
357*bf21cd93STycho Nightingale 	1,		/* manufacturer string */
358*bf21cd93STycho Nightingale 	SMBIOS_CHT_UNKNOWN,
359*bf21cd93STycho Nightingale 	2,		/* version string */
360*bf21cd93STycho Nightingale 	3,		/* serial number string */
361*bf21cd93STycho Nightingale 	4,		/* asset tag string */
362*bf21cd93STycho Nightingale 	SMBIOS_CHST_SAFE,
363*bf21cd93STycho Nightingale 	SMBIOS_CHST_SAFE,
364*bf21cd93STycho Nightingale 	SMBIOS_CHST_SAFE,
365*bf21cd93STycho Nightingale 	SMBIOS_CHSC_NONE,
366*bf21cd93STycho Nightingale 	0,		/* height in 'u's (0=enclosure height unspecified) */
367*bf21cd93STycho Nightingale 	0,		/* number of power cords (0=number unspecified) */
368*bf21cd93STycho Nightingale 	0,		/* number of contained element records */
369*bf21cd93STycho Nightingale 	0,		/* length of records */
370*bf21cd93STycho Nightingale 	5		/* sku number string */
371*bf21cd93STycho Nightingale };
372*bf21cd93STycho Nightingale 
373*bf21cd93STycho Nightingale const char *smbios_type3_strings[] = {
374*bf21cd93STycho Nightingale 	" ",		/* manufacturer string */
375*bf21cd93STycho Nightingale 	"1.0",		/* version string */
376*bf21cd93STycho Nightingale 	"None",		/* serial number string */
377*bf21cd93STycho Nightingale 	"None",		/* asset tag string */
378*bf21cd93STycho Nightingale 	"None",		/* sku number string */
379*bf21cd93STycho Nightingale 	NULL
380*bf21cd93STycho Nightingale };
381*bf21cd93STycho Nightingale 
382*bf21cd93STycho Nightingale struct smbios_table_type4 smbios_type4_template = {
383*bf21cd93STycho Nightingale 	{ SMBIOS_TYPE_PROCESSOR, sizeof (struct smbios_table_type4), 0 },
384*bf21cd93STycho Nightingale 	1,		/* socket designation string */
385*bf21cd93STycho Nightingale 	SMBIOS_PRT_CENTRAL,
386*bf21cd93STycho Nightingale 	SMBIOS_PRF_OTHER,
387*bf21cd93STycho Nightingale 	2,		/* manufacturer string */
388*bf21cd93STycho Nightingale 	0,		/* cpuid */
389*bf21cd93STycho Nightingale 	3,		/* version string */
390*bf21cd93STycho Nightingale 	0,		/* voltage */
391*bf21cd93STycho Nightingale 	0,		/* external clock frequency in mhz (0=unknown) */
392*bf21cd93STycho Nightingale 	0,		/* maximum frequency in mhz (0=unknown) */
393*bf21cd93STycho Nightingale 	0,		/* current frequency in mhz (0=unknown) */
394*bf21cd93STycho Nightingale 	SMBIOS_PRS_PRESENT | SMBIOS_PRS_ENABLED,
395*bf21cd93STycho Nightingale 	SMBIOS_PRU_NONE,
396*bf21cd93STycho Nightingale 	-1,		/* l1 cache handle */
397*bf21cd93STycho Nightingale 	-1,		/* l2 cache handle */
398*bf21cd93STycho Nightingale 	-1,		/* l3 cache handle */
399*bf21cd93STycho Nightingale 	4,		/* serial number string */
400*bf21cd93STycho Nightingale 	5,		/* asset tag string */
401*bf21cd93STycho Nightingale 	6,		/* part number string */
402*bf21cd93STycho Nightingale 	0,		/* cores per socket (0=unknown) */
403*bf21cd93STycho Nightingale 	0,		/* enabled cores per socket (0=unknown) */
404*bf21cd93STycho Nightingale 	0,		/* threads per socket (0=unknown) */
405*bf21cd93STycho Nightingale 	SMBIOS_PFL_64B,
406*bf21cd93STycho Nightingale 	SMBIOS_PRF_OTHER
407*bf21cd93STycho Nightingale };
408*bf21cd93STycho Nightingale 
409*bf21cd93STycho Nightingale const char *smbios_type4_strings[] = {
410*bf21cd93STycho Nightingale 	" ",		/* socket designation string */
411*bf21cd93STycho Nightingale 	" ",		/* manufacturer string */
412*bf21cd93STycho Nightingale 	" ",		/* version string */
413*bf21cd93STycho Nightingale 	"None",		/* serial number string */
414*bf21cd93STycho Nightingale 	"None",		/* asset tag string */
415*bf21cd93STycho Nightingale 	"None",		/* part number string */
416*bf21cd93STycho Nightingale 	NULL
417*bf21cd93STycho Nightingale };
418*bf21cd93STycho Nightingale 
419*bf21cd93STycho Nightingale static int smbios_type4_initializer(struct smbios_structure *template_entry,
420*bf21cd93STycho Nightingale     const char **template_strings, char *curaddr, char **endaddr,
421*bf21cd93STycho Nightingale     uint16_t *n, uint16_t *size);
422*bf21cd93STycho Nightingale 
423*bf21cd93STycho Nightingale struct smbios_table_type16 smbios_type16_template = {
424*bf21cd93STycho Nightingale 	{ SMBIOS_TYPE_MEMARRAY, sizeof (struct smbios_table_type16),  0 },
425*bf21cd93STycho Nightingale 	SMBIOS_MAL_SYSMB,
426*bf21cd93STycho Nightingale 	SMBIOS_MAU_SYSTEM,
427*bf21cd93STycho Nightingale 	SMBIOS_MAE_NONE,
428*bf21cd93STycho Nightingale 	0x80000000,	/* max mem capacity in kb (0x80000000=use extended) */
429*bf21cd93STycho Nightingale 	-1,		/* handle of error (if any) */
430*bf21cd93STycho Nightingale 	0,		/* number of slots or sockets (TBD) */
431*bf21cd93STycho Nightingale 	0		/* extended maximum memory capacity in bytes (TBD) */
432*bf21cd93STycho Nightingale };
433*bf21cd93STycho Nightingale 
434*bf21cd93STycho Nightingale static int smbios_type16_initializer(struct smbios_structure *template_entry,
435*bf21cd93STycho Nightingale     const char **template_strings, char *curaddr, char **endaddr,
436*bf21cd93STycho Nightingale     uint16_t *n, uint16_t *size);
437*bf21cd93STycho Nightingale 
438*bf21cd93STycho Nightingale struct smbios_table_type17 smbios_type17_template = {
439*bf21cd93STycho Nightingale 	{ SMBIOS_TYPE_MEMDEVICE, sizeof (struct smbios_table_type17),  0 },
440*bf21cd93STycho Nightingale 	-1,		/* handle of physical memory array */
441*bf21cd93STycho Nightingale 	-1,		/* handle of memory error data */
442*bf21cd93STycho Nightingale 	64,		/* total width in bits including ecc */
443*bf21cd93STycho Nightingale 	64,		/* data width in bits */
444*bf21cd93STycho Nightingale 	0x7fff,		/* size in bytes (0x7fff=use extended)*/
445*bf21cd93STycho Nightingale 	SMBIOS_MDFF_UNKNOWN,
446*bf21cd93STycho Nightingale 	0,		/* set (0x00=none, 0xff=unknown) */
447*bf21cd93STycho Nightingale 	1,		/* device locator string */
448*bf21cd93STycho Nightingale 	2,		/* physical bank locator string */
449*bf21cd93STycho Nightingale 	SMBIOS_MDT_UNKNOWN,
450*bf21cd93STycho Nightingale 	SMBIOS_MDF_UNKNOWN,
451*bf21cd93STycho Nightingale 	0,		/* maximum memory speed in mhz (0=unknown) */
452*bf21cd93STycho Nightingale 	3,		/* manufacturer string */
453*bf21cd93STycho Nightingale 	4,		/* serial number string */
454*bf21cd93STycho Nightingale 	5,		/* asset tag string */
455*bf21cd93STycho Nightingale 	6,		/* part number string */
456*bf21cd93STycho Nightingale 	0,		/* attributes (0=unknown rank information) */
457*bf21cd93STycho Nightingale 	0,		/* extended size in mb (TBD) */
458*bf21cd93STycho Nightingale 	0,		/* current speed in mhz (0=unknown) */
459*bf21cd93STycho Nightingale 	0,		/* minimum voltage in mv (0=unknown) */
460*bf21cd93STycho Nightingale 	0,		/* maximum voltage in mv (0=unknown) */
461*bf21cd93STycho Nightingale 	0		/* configured voltage in mv (0=unknown) */
462*bf21cd93STycho Nightingale };
463*bf21cd93STycho Nightingale 
464*bf21cd93STycho Nightingale const char *smbios_type17_strings[] = {
465*bf21cd93STycho Nightingale 	" ",		/* device locator string */
466*bf21cd93STycho Nightingale 	" ",		/* physical bank locator string */
467*bf21cd93STycho Nightingale 	" ",		/* manufacturer string */
468*bf21cd93STycho Nightingale 	"None",		/* serial number string */
469*bf21cd93STycho Nightingale 	"None",		/* asset tag string */
470*bf21cd93STycho Nightingale 	"None",		/* part number string */
471*bf21cd93STycho Nightingale 	NULL
472*bf21cd93STycho Nightingale };
473*bf21cd93STycho Nightingale 
474*bf21cd93STycho Nightingale static int smbios_type17_initializer(struct smbios_structure *template_entry,
475*bf21cd93STycho Nightingale     const char **template_strings, char *curaddr, char **endaddr,
476*bf21cd93STycho Nightingale     uint16_t *n, uint16_t *size);
477*bf21cd93STycho Nightingale 
478*bf21cd93STycho Nightingale struct smbios_table_type19 smbios_type19_template = {
479*bf21cd93STycho Nightingale 	{ SMBIOS_TYPE_MEMARRAYMAP, sizeof (struct smbios_table_type19),  0 },
480*bf21cd93STycho Nightingale 	0xffffffff,	/* starting phys addr in kb (0xffffffff=use ext) */
481*bf21cd93STycho Nightingale 	0xffffffff,	/* ending phys addr in kb (0xffffffff=use ext) */
482*bf21cd93STycho Nightingale 	-1,		/* physical memory array handle */
483*bf21cd93STycho Nightingale 	1,		/* number of devices that form a row */
484*bf21cd93STycho Nightingale 	0,		/* extended starting phys addr in bytes (TDB) */
485*bf21cd93STycho Nightingale 	0		/* extended ending phys addr in bytes (TDB) */
486*bf21cd93STycho Nightingale };
487*bf21cd93STycho Nightingale 
488*bf21cd93STycho Nightingale static int smbios_type19_initializer(struct smbios_structure *template_entry,
489*bf21cd93STycho Nightingale     const char **template_strings, char *curaddr, char **endaddr,
490*bf21cd93STycho Nightingale     uint16_t *n, uint16_t *size);
491*bf21cd93STycho Nightingale 
492*bf21cd93STycho Nightingale struct smbios_table_type32 smbios_type32_template = {
493*bf21cd93STycho Nightingale 	{ SMBIOS_TYPE_BOOT, sizeof (struct smbios_table_type32),  0 },
494*bf21cd93STycho Nightingale 	{ 0, 0, 0, 0, 0, 0 },
495*bf21cd93STycho Nightingale 	SMBIOS_BOOT_NORMAL
496*bf21cd93STycho Nightingale };
497*bf21cd93STycho Nightingale 
498*bf21cd93STycho Nightingale struct smbios_table_type127 smbios_type127_template = {
499*bf21cd93STycho Nightingale 	{ SMBIOS_TYPE_EOT, sizeof (struct smbios_table_type127),  0 }
500*bf21cd93STycho Nightingale };
501*bf21cd93STycho Nightingale 
502*bf21cd93STycho Nightingale static int smbios_generic_initializer(struct smbios_structure *template_entry,
503*bf21cd93STycho Nightingale     const char **template_strings, char *curaddr, char **endaddr,
504*bf21cd93STycho Nightingale     uint16_t *n, uint16_t *size);
505*bf21cd93STycho Nightingale 
506*bf21cd93STycho Nightingale static struct smbios_template_entry smbios_template[] = {
507*bf21cd93STycho Nightingale 	{ (struct smbios_structure *)&smbios_type0_template,
508*bf21cd93STycho Nightingale 	  smbios_type0_strings,
509*bf21cd93STycho Nightingale 	  smbios_generic_initializer },
510*bf21cd93STycho Nightingale 	{ (struct smbios_structure *)&smbios_type1_template,
511*bf21cd93STycho Nightingale 	  smbios_type1_strings,
512*bf21cd93STycho Nightingale 	  smbios_type1_initializer },
513*bf21cd93STycho Nightingale 	{ (struct smbios_structure *)&smbios_type3_template,
514*bf21cd93STycho Nightingale 	  smbios_type3_strings,
515*bf21cd93STycho Nightingale 	  smbios_generic_initializer },
516*bf21cd93STycho Nightingale 	{ (struct smbios_structure *)&smbios_type4_template,
517*bf21cd93STycho Nightingale 	  smbios_type4_strings,
518*bf21cd93STycho Nightingale 	  smbios_type4_initializer },
519*bf21cd93STycho Nightingale 	{ (struct smbios_structure *)&smbios_type16_template,
520*bf21cd93STycho Nightingale 	  NULL,
521*bf21cd93STycho Nightingale 	  smbios_type16_initializer },
522*bf21cd93STycho Nightingale 	{ (struct smbios_structure *)&smbios_type17_template,
523*bf21cd93STycho Nightingale 	  smbios_type17_strings,
524*bf21cd93STycho Nightingale 	  smbios_type17_initializer },
525*bf21cd93STycho Nightingale 	{ (struct smbios_structure *)&smbios_type19_template,
526*bf21cd93STycho Nightingale 	  NULL,
527*bf21cd93STycho Nightingale 	  smbios_type19_initializer },
528*bf21cd93STycho Nightingale 	{ (struct smbios_structure *)&smbios_type32_template,
529*bf21cd93STycho Nightingale 	  NULL,
530*bf21cd93STycho Nightingale 	  smbios_generic_initializer },
531*bf21cd93STycho Nightingale 	{ (struct smbios_structure *)&smbios_type127_template,
532*bf21cd93STycho Nightingale 	  NULL,
533*bf21cd93STycho Nightingale 	  smbios_generic_initializer },
534*bf21cd93STycho Nightingale 	{ NULL,NULL, NULL }
535*bf21cd93STycho Nightingale };
536*bf21cd93STycho Nightingale 
537*bf21cd93STycho Nightingale static uint64_t guest_lomem, guest_himem;
538*bf21cd93STycho Nightingale static uint16_t type16_handle;
539*bf21cd93STycho Nightingale 
540*bf21cd93STycho Nightingale static int
541*bf21cd93STycho Nightingale smbios_generic_initializer(struct smbios_structure *template_entry,
542*bf21cd93STycho Nightingale     const char **template_strings, char *curaddr, char **endaddr,
543*bf21cd93STycho Nightingale     uint16_t *n, uint16_t *size)
544*bf21cd93STycho Nightingale {
545*bf21cd93STycho Nightingale 	struct smbios_structure *entry;
546*bf21cd93STycho Nightingale 
547*bf21cd93STycho Nightingale 	memcpy(curaddr, template_entry, template_entry->length);
548*bf21cd93STycho Nightingale 	entry = (struct smbios_structure *)curaddr;
549*bf21cd93STycho Nightingale 	entry->handle = *n + 1;
550*bf21cd93STycho Nightingale 	curaddr += entry->length;
551*bf21cd93STycho Nightingale 	if (template_strings != NULL) {
552*bf21cd93STycho Nightingale 		int	i;
553*bf21cd93STycho Nightingale 
554*bf21cd93STycho Nightingale 		for (i = 0; template_strings[i] != NULL; i++) {
555*bf21cd93STycho Nightingale 			const char *string;
556*bf21cd93STycho Nightingale 			int len;
557*bf21cd93STycho Nightingale 
558*bf21cd93STycho Nightingale 			string = template_strings[i];
559*bf21cd93STycho Nightingale 			len = strlen(string) + 1;
560*bf21cd93STycho Nightingale 			memcpy(curaddr, string, len);
561*bf21cd93STycho Nightingale 			curaddr += len;
562*bf21cd93STycho Nightingale 		}
563*bf21cd93STycho Nightingale 		*curaddr = '\0';
564*bf21cd93STycho Nightingale 		curaddr++;
565*bf21cd93STycho Nightingale 	} else {
566*bf21cd93STycho Nightingale 		/* Minimum string section is double nul */
567*bf21cd93STycho Nightingale 		*curaddr = '\0';
568*bf21cd93STycho Nightingale 		curaddr++;
569*bf21cd93STycho Nightingale 		*curaddr = '\0';
570*bf21cd93STycho Nightingale 		curaddr++;
571*bf21cd93STycho Nightingale 	}
572*bf21cd93STycho Nightingale 	(*n)++;
573*bf21cd93STycho Nightingale 	*endaddr = curaddr;
574*bf21cd93STycho Nightingale 
575*bf21cd93STycho Nightingale 	return (0);
576*bf21cd93STycho Nightingale }
577*bf21cd93STycho Nightingale 
578*bf21cd93STycho Nightingale static int
579*bf21cd93STycho Nightingale smbios_type1_initializer(struct smbios_structure *template_entry,
580*bf21cd93STycho Nightingale     const char **template_strings, char *curaddr, char **endaddr,
581*bf21cd93STycho Nightingale     uint16_t *n, uint16_t *size)
582*bf21cd93STycho Nightingale {
583*bf21cd93STycho Nightingale 	struct smbios_table_type1 *type1;
584*bf21cd93STycho Nightingale 
585*bf21cd93STycho Nightingale 	smbios_generic_initializer(template_entry, template_strings,
586*bf21cd93STycho Nightingale 	    curaddr, endaddr, n, size);
587*bf21cd93STycho Nightingale 	type1 = (struct smbios_table_type1 *)curaddr;
588*bf21cd93STycho Nightingale 
589*bf21cd93STycho Nightingale 	if (guest_uuid_str != NULL) {
590*bf21cd93STycho Nightingale 		uuid_t		uuid;
591*bf21cd93STycho Nightingale 		uint32_t	status;
592*bf21cd93STycho Nightingale 
593*bf21cd93STycho Nightingale 		uuid_from_string(guest_uuid_str, &uuid, &status);
594*bf21cd93STycho Nightingale 		if (status != uuid_s_ok)
595*bf21cd93STycho Nightingale 			return (-1);
596*bf21cd93STycho Nightingale 
597*bf21cd93STycho Nightingale 		uuid_enc_le(&type1->uuid, &uuid);
598*bf21cd93STycho Nightingale 	} else {
599*bf21cd93STycho Nightingale 		MD5_CTX		mdctx;
600*bf21cd93STycho Nightingale 		u_char		digest[16];
601*bf21cd93STycho Nightingale 		char		hostname[MAXHOSTNAMELEN];
602*bf21cd93STycho Nightingale 
603*bf21cd93STycho Nightingale 		/*
604*bf21cd93STycho Nightingale 		 * Universally unique and yet reproducible are an
605*bf21cd93STycho Nightingale 		 * oxymoron, however reproducible is desirable in
606*bf21cd93STycho Nightingale 		 * this case.
607*bf21cd93STycho Nightingale 		 */
608*bf21cd93STycho Nightingale 		if (gethostname(hostname, sizeof(hostname)))
609*bf21cd93STycho Nightingale 			return (-1);
610*bf21cd93STycho Nightingale 
611*bf21cd93STycho Nightingale 		MD5Init(&mdctx);
612*bf21cd93STycho Nightingale 		MD5Update(&mdctx, vmname, strlen(vmname));
613*bf21cd93STycho Nightingale 		MD5Update(&mdctx, hostname, sizeof(hostname));
614*bf21cd93STycho Nightingale 		MD5Final(digest, &mdctx);
615*bf21cd93STycho Nightingale 
616*bf21cd93STycho Nightingale 		/*
617*bf21cd93STycho Nightingale 		 * Set the variant and version number.
618*bf21cd93STycho Nightingale 		 */
619*bf21cd93STycho Nightingale 		digest[6] &= 0x0F;
620*bf21cd93STycho Nightingale 		digest[6] |= 0x30;	/* version 3 */
621*bf21cd93STycho Nightingale 		digest[8] &= 0x3F;
622*bf21cd93STycho Nightingale 		digest[8] |= 0x80;
623*bf21cd93STycho Nightingale 
624*bf21cd93STycho Nightingale 		memcpy(&type1->uuid, digest, sizeof (digest));
625*bf21cd93STycho Nightingale 	}
626*bf21cd93STycho Nightingale 
627*bf21cd93STycho Nightingale 	return (0);
628*bf21cd93STycho Nightingale }
629*bf21cd93STycho Nightingale 
630*bf21cd93STycho Nightingale static int
631*bf21cd93STycho Nightingale smbios_type4_initializer(struct smbios_structure *template_entry,
632*bf21cd93STycho Nightingale     const char **template_strings, char *curaddr, char **endaddr,
633*bf21cd93STycho Nightingale     uint16_t *n, uint16_t *size)
634*bf21cd93STycho Nightingale {
635*bf21cd93STycho Nightingale 	int i;
636*bf21cd93STycho Nightingale 
637*bf21cd93STycho Nightingale 	for (i = 0; i < guest_ncpus; i++) {
638*bf21cd93STycho Nightingale 		struct smbios_table_type4 *type4;
639*bf21cd93STycho Nightingale 		char *p;
640*bf21cd93STycho Nightingale 		int nstrings, len;
641*bf21cd93STycho Nightingale 
642*bf21cd93STycho Nightingale 		smbios_generic_initializer(template_entry, template_strings,
643*bf21cd93STycho Nightingale 		    curaddr, endaddr, n, size);
644*bf21cd93STycho Nightingale 		type4 = (struct smbios_table_type4 *)curaddr;
645*bf21cd93STycho Nightingale 		p = curaddr + sizeof (struct smbios_table_type4);
646*bf21cd93STycho Nightingale 		nstrings = 0;
647*bf21cd93STycho Nightingale 		while (p < *endaddr - 1) {
648*bf21cd93STycho Nightingale 			if (*p++ == '\0')
649*bf21cd93STycho Nightingale 				nstrings++;
650*bf21cd93STycho Nightingale 		}
651*bf21cd93STycho Nightingale 		len = sprintf(*endaddr - 1, "CPU #%d", i) + 1;
652*bf21cd93STycho Nightingale 		*endaddr += len - 1;
653*bf21cd93STycho Nightingale 		*(*endaddr) = '\0';
654*bf21cd93STycho Nightingale 		(*endaddr)++;
655*bf21cd93STycho Nightingale 		type4->socket = nstrings + 1;
656*bf21cd93STycho Nightingale 		curaddr = *endaddr;
657*bf21cd93STycho Nightingale 	}
658*bf21cd93STycho Nightingale 
659*bf21cd93STycho Nightingale 	return (0);
660*bf21cd93STycho Nightingale }
661*bf21cd93STycho Nightingale 
662*bf21cd93STycho Nightingale static int
663*bf21cd93STycho Nightingale smbios_type16_initializer(struct smbios_structure *template_entry,
664*bf21cd93STycho Nightingale     const char **template_strings, char *curaddr, char **endaddr,
665*bf21cd93STycho Nightingale     uint16_t *n, uint16_t *size)
666*bf21cd93STycho Nightingale {
667*bf21cd93STycho Nightingale 	struct smbios_table_type16 *type16;
668*bf21cd93STycho Nightingale 
669*bf21cd93STycho Nightingale 	type16_handle = *n;
670*bf21cd93STycho Nightingale 	smbios_generic_initializer(template_entry, template_strings,
671*bf21cd93STycho Nightingale 	    curaddr, endaddr, n, size);
672*bf21cd93STycho Nightingale 	type16 = (struct smbios_table_type16 *)curaddr;
673*bf21cd93STycho Nightingale 	type16->xsize = guest_lomem + guest_himem;
674*bf21cd93STycho Nightingale 	type16->ndevs = guest_himem > 0 ? 2 : 1;
675*bf21cd93STycho Nightingale 
676*bf21cd93STycho Nightingale 	return (0);
677*bf21cd93STycho Nightingale }
678*bf21cd93STycho Nightingale 
679*bf21cd93STycho Nightingale static int
680*bf21cd93STycho Nightingale smbios_type17_initializer(struct smbios_structure *template_entry,
681*bf21cd93STycho Nightingale     const char **template_strings, char *curaddr, char **endaddr,
682*bf21cd93STycho Nightingale     uint16_t *n, uint16_t *size)
683*bf21cd93STycho Nightingale {
684*bf21cd93STycho Nightingale 	struct smbios_table_type17 *type17;
685*bf21cd93STycho Nightingale 
686*bf21cd93STycho Nightingale 	smbios_generic_initializer(template_entry, template_strings,
687*bf21cd93STycho Nightingale 	    curaddr, endaddr, n, size);
688*bf21cd93STycho Nightingale 	type17 = (struct smbios_table_type17 *)curaddr;
689*bf21cd93STycho Nightingale 	type17->arrayhand = type16_handle;
690*bf21cd93STycho Nightingale 	type17->xsize = guest_lomem;
691*bf21cd93STycho Nightingale 
692*bf21cd93STycho Nightingale 	if (guest_himem > 0) {
693*bf21cd93STycho Nightingale 		curaddr = *endaddr;
694*bf21cd93STycho Nightingale 		smbios_generic_initializer(template_entry, template_strings,
695*bf21cd93STycho Nightingale 		    curaddr, endaddr, n, size);
696*bf21cd93STycho Nightingale 		type17 = (struct smbios_table_type17 *)curaddr;
697*bf21cd93STycho Nightingale 		type17->arrayhand = type16_handle;
698*bf21cd93STycho Nightingale 		type17->xsize = guest_himem;
699*bf21cd93STycho Nightingale 	}
700*bf21cd93STycho Nightingale 
701*bf21cd93STycho Nightingale 	return (0);
702*bf21cd93STycho Nightingale }
703*bf21cd93STycho Nightingale 
704*bf21cd93STycho Nightingale static int
705*bf21cd93STycho Nightingale smbios_type19_initializer(struct smbios_structure *template_entry,
706*bf21cd93STycho Nightingale     const char **template_strings, char *curaddr, char **endaddr,
707*bf21cd93STycho Nightingale     uint16_t *n, uint16_t *size)
708*bf21cd93STycho Nightingale {
709*bf21cd93STycho Nightingale 	struct smbios_table_type19 *type19;
710*bf21cd93STycho Nightingale 
711*bf21cd93STycho Nightingale 	smbios_generic_initializer(template_entry, template_strings,
712*bf21cd93STycho Nightingale 	    curaddr, endaddr, n, size);
713*bf21cd93STycho Nightingale 	type19 = (struct smbios_table_type19 *)curaddr;
714*bf21cd93STycho Nightingale 	type19->arrayhand = type16_handle;
715*bf21cd93STycho Nightingale 	type19->xsaddr = 0;
716*bf21cd93STycho Nightingale 	type19->xeaddr = guest_lomem;
717*bf21cd93STycho Nightingale 
718*bf21cd93STycho Nightingale 	if (guest_himem > 0) {
719*bf21cd93STycho Nightingale 		curaddr = *endaddr;
720*bf21cd93STycho Nightingale 		smbios_generic_initializer(template_entry, template_strings,
721*bf21cd93STycho Nightingale 		    curaddr, endaddr, n, size);
722*bf21cd93STycho Nightingale 		type19 = (struct smbios_table_type19 *)curaddr;
723*bf21cd93STycho Nightingale 		type19->arrayhand = type16_handle;
724*bf21cd93STycho Nightingale 		type19->xsaddr = 4*GB;
725*bf21cd93STycho Nightingale 		type19->xeaddr = guest_himem;
726*bf21cd93STycho Nightingale 	}
727*bf21cd93STycho Nightingale 
728*bf21cd93STycho Nightingale 	return (0);
729*bf21cd93STycho Nightingale }
730*bf21cd93STycho Nightingale 
731*bf21cd93STycho Nightingale static void
732*bf21cd93STycho Nightingale smbios_ep_initializer(struct smbios_entry_point *smbios_ep, uint32_t staddr)
733*bf21cd93STycho Nightingale {
734*bf21cd93STycho Nightingale 	memset(smbios_ep, 0, sizeof(*smbios_ep));
735*bf21cd93STycho Nightingale 	memcpy(smbios_ep->eanchor, SMBIOS_ENTRY_EANCHOR,
736*bf21cd93STycho Nightingale 	    SMBIOS_ENTRY_EANCHORLEN);
737*bf21cd93STycho Nightingale 	smbios_ep->eplen = 0x1F;
738*bf21cd93STycho Nightingale 	assert(sizeof (struct smbios_entry_point) == smbios_ep->eplen);
739*bf21cd93STycho Nightingale 	smbios_ep->major = 2;
740*bf21cd93STycho Nightingale 	smbios_ep->minor = 6;
741*bf21cd93STycho Nightingale 	smbios_ep->revision = 0;
742*bf21cd93STycho Nightingale 	memcpy(smbios_ep->ianchor, SMBIOS_ENTRY_IANCHOR,
743*bf21cd93STycho Nightingale 	    SMBIOS_ENTRY_IANCHORLEN);
744*bf21cd93STycho Nightingale 	smbios_ep->staddr = staddr;
745*bf21cd93STycho Nightingale 	smbios_ep->bcdrev = 0x24;
746*bf21cd93STycho Nightingale }
747*bf21cd93STycho Nightingale 
748*bf21cd93STycho Nightingale static void
749*bf21cd93STycho Nightingale smbios_ep_finalizer(struct smbios_entry_point *smbios_ep, uint16_t len,
750*bf21cd93STycho Nightingale     uint16_t num, uint16_t maxssize)
751*bf21cd93STycho Nightingale {
752*bf21cd93STycho Nightingale 	uint8_t	checksum;
753*bf21cd93STycho Nightingale 	int	i;
754*bf21cd93STycho Nightingale 
755*bf21cd93STycho Nightingale 	smbios_ep->maxssize = maxssize;
756*bf21cd93STycho Nightingale 	smbios_ep->stlen = len;
757*bf21cd93STycho Nightingale 	smbios_ep->stnum = num;
758*bf21cd93STycho Nightingale 
759*bf21cd93STycho Nightingale 	checksum = 0;
760*bf21cd93STycho Nightingale 	for (i = 0x10; i < 0x1f; i++) {
761*bf21cd93STycho Nightingale 		checksum -= ((uint8_t *)smbios_ep)[i];
762*bf21cd93STycho Nightingale 	}
763*bf21cd93STycho Nightingale 	smbios_ep->ichecksum = checksum;
764*bf21cd93STycho Nightingale 
765*bf21cd93STycho Nightingale 	checksum = 0;
766*bf21cd93STycho Nightingale 	for (i = 0; i < 0x1f; i++) {
767*bf21cd93STycho Nightingale 		checksum -= ((uint8_t *)smbios_ep)[i];
768*bf21cd93STycho Nightingale 	}
769*bf21cd93STycho Nightingale 	smbios_ep->echecksum = checksum;
770*bf21cd93STycho Nightingale }
771*bf21cd93STycho Nightingale 
772*bf21cd93STycho Nightingale int
773*bf21cd93STycho Nightingale smbios_build(struct vmctx *ctx)
774*bf21cd93STycho Nightingale {
775*bf21cd93STycho Nightingale 	struct smbios_entry_point	*smbios_ep;
776*bf21cd93STycho Nightingale 	uint16_t			n;
777*bf21cd93STycho Nightingale 	uint16_t			maxssize;
778*bf21cd93STycho Nightingale 	char				*curaddr, *startaddr, *ststartaddr;
779*bf21cd93STycho Nightingale 	int				i;
780*bf21cd93STycho Nightingale 	int				err;
781*bf21cd93STycho Nightingale 
782*bf21cd93STycho Nightingale 	guest_lomem = vm_get_lowmem_size(ctx);
783*bf21cd93STycho Nightingale 	guest_himem = vm_get_highmem_size(ctx);
784*bf21cd93STycho Nightingale 
785*bf21cd93STycho Nightingale 	startaddr = paddr_guest2host(ctx, SMBIOS_BASE, SMBIOS_MAX_LENGTH);
786*bf21cd93STycho Nightingale 	if (startaddr == NULL) {
787*bf21cd93STycho Nightingale 		fprintf(stderr, "smbios table requires mapped mem\n");
788*bf21cd93STycho Nightingale 		return (ENOMEM);
789*bf21cd93STycho Nightingale 	}
790*bf21cd93STycho Nightingale 
791*bf21cd93STycho Nightingale 	curaddr = startaddr;
792*bf21cd93STycho Nightingale 
793*bf21cd93STycho Nightingale 	smbios_ep = (struct smbios_entry_point *)curaddr;
794*bf21cd93STycho Nightingale 	smbios_ep_initializer(smbios_ep, SMBIOS_BASE +
795*bf21cd93STycho Nightingale 	    sizeof(struct smbios_entry_point));
796*bf21cd93STycho Nightingale 	curaddr += sizeof(struct smbios_entry_point);
797*bf21cd93STycho Nightingale 	ststartaddr = curaddr;
798*bf21cd93STycho Nightingale 
799*bf21cd93STycho Nightingale 	n = 0;
800*bf21cd93STycho Nightingale 	maxssize = 0;
801*bf21cd93STycho Nightingale 	for (i = 0; smbios_template[i].entry != NULL; i++) {
802*bf21cd93STycho Nightingale 		struct smbios_structure	*entry;
803*bf21cd93STycho Nightingale 		const char		**strings;
804*bf21cd93STycho Nightingale 		initializer_func_t      initializer;
805*bf21cd93STycho Nightingale 		char			*endaddr;
806*bf21cd93STycho Nightingale 		uint16_t		size;
807*bf21cd93STycho Nightingale 
808*bf21cd93STycho Nightingale 		entry = smbios_template[i].entry;
809*bf21cd93STycho Nightingale 		strings = smbios_template[i].strings;
810*bf21cd93STycho Nightingale 		initializer = smbios_template[i].initializer;
811*bf21cd93STycho Nightingale 
812*bf21cd93STycho Nightingale 		err = (*initializer)(entry, strings, curaddr, &endaddr,
813*bf21cd93STycho Nightingale 		    &n, &size);
814*bf21cd93STycho Nightingale 		if (err != 0)
815*bf21cd93STycho Nightingale 			return (err);
816*bf21cd93STycho Nightingale 
817*bf21cd93STycho Nightingale 		if (size > maxssize)
818*bf21cd93STycho Nightingale 			maxssize = size;
819*bf21cd93STycho Nightingale 
820*bf21cd93STycho Nightingale 		curaddr = endaddr;
821*bf21cd93STycho Nightingale 	}
822*bf21cd93STycho Nightingale 
823*bf21cd93STycho Nightingale 	assert(curaddr - startaddr < SMBIOS_MAX_LENGTH);
824*bf21cd93STycho Nightingale 	smbios_ep_finalizer(smbios_ep, curaddr - ststartaddr, n, maxssize);
825*bf21cd93STycho Nightingale 
826*bf21cd93STycho Nightingale 	return (0);
827*bf21cd93STycho Nightingale }
828