1bf21cd93STycho Nightingale /*-
2*32640292SAndy Fiddaman * SPDX-License-Identifier: BSD-2-Clause
34c87aefeSPatrick Mooney *
4bf21cd93STycho Nightingale * Copyright (c) 2014 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
5bf21cd93STycho Nightingale * All rights reserved.
6bf21cd93STycho Nightingale *
7bf21cd93STycho Nightingale * Redistribution and use in source and binary forms, with or without
8bf21cd93STycho Nightingale * modification, are permitted provided that the following conditions
9bf21cd93STycho Nightingale * are met:
10bf21cd93STycho Nightingale * 1. Redistributions of source code must retain the above copyright
11bf21cd93STycho Nightingale * notice, this list of conditions and the following disclaimer.
12bf21cd93STycho Nightingale * 2. Redistributions in binary form must reproduce the above copyright
13bf21cd93STycho Nightingale * notice, this list of conditions and the following disclaimer in the
14bf21cd93STycho Nightingale * documentation and/or other materials provided with the distribution.
15bf21cd93STycho Nightingale *
16bf21cd93STycho Nightingale * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
17bf21cd93STycho Nightingale * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18bf21cd93STycho Nightingale * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19bf21cd93STycho Nightingale * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20bf21cd93STycho Nightingale * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21bf21cd93STycho Nightingale * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22bf21cd93STycho Nightingale * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23bf21cd93STycho Nightingale * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24bf21cd93STycho Nightingale * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25bf21cd93STycho Nightingale * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26bf21cd93STycho Nightingale * SUCH DAMAGE.
27bf21cd93STycho Nightingale */
28bf21cd93STycho Nightingale
29bf21cd93STycho Nightingale #include <sys/cdefs.h>
30bf21cd93STycho Nightingale
31bf21cd93STycho Nightingale #include <sys/param.h>
32bf21cd93STycho Nightingale
33bf21cd93STycho Nightingale #include <assert.h>
34bf21cd93STycho Nightingale #include <errno.h>
35bf21cd93STycho Nightingale #include <md5.h>
36bf21cd93STycho Nightingale #include <stdio.h>
374c87aefeSPatrick Mooney #include <stdlib.h>
38bf21cd93STycho Nightingale #include <string.h>
39bf21cd93STycho Nightingale #include <unistd.h>
40bf21cd93STycho Nightingale #include <uuid.h>
41bf21cd93STycho Nightingale
42bf21cd93STycho Nightingale #include <machine/vmm.h>
43bf21cd93STycho Nightingale #include <vmmapi.h>
44bf21cd93STycho Nightingale
454f3f3e9aSAndy Fiddaman #ifndef __FreeBSD__
464f3f3e9aSAndy Fiddaman #include <sys/sysmacros.h>
474f3f3e9aSAndy Fiddaman #endif
484f3f3e9aSAndy Fiddaman
49bf21cd93STycho Nightingale #include "bhyverun.h"
502b948146SAndy Fiddaman #include "config.h"
51154972afSPatrick Mooney #include "debug.h"
52bf21cd93STycho Nightingale #include "smbiostbl.h"
53bf21cd93STycho Nightingale
54bf21cd93STycho Nightingale #define MB (1024*1024)
55bf21cd93STycho Nightingale #define GB (1024ULL*1024*1024)
56bf21cd93STycho Nightingale
57bf21cd93STycho Nightingale #define SMBIOS_BASE 0xF1000
58bf21cd93STycho Nightingale
596dc98349SAndy Fiddaman #define FIRMWARE_VERSION "14.0"
606960cd89SAndy Fiddaman /* The SMBIOS specification defines the date format to be mm/dd/yyyy */
616dc98349SAndy Fiddaman #define FIRMWARE_RELEASE_DATE "10/10/2021"
626960cd89SAndy Fiddaman
63bf21cd93STycho Nightingale /* BHYVE_ACPI_BASE - SMBIOS_BASE) */
64bf21cd93STycho Nightingale #define SMBIOS_MAX_LENGTH (0xF2400 - 0xF1000)
65bf21cd93STycho Nightingale
66bf21cd93STycho Nightingale #define SMBIOS_TYPE_BIOS 0
67bf21cd93STycho Nightingale #define SMBIOS_TYPE_SYSTEM 1
68b0de25cbSAndy Fiddaman #define SMBIOS_TYPE_BOARD 2
69bf21cd93STycho Nightingale #define SMBIOS_TYPE_CHASSIS 3
70bf21cd93STycho Nightingale #define SMBIOS_TYPE_PROCESSOR 4
71bf21cd93STycho Nightingale #define SMBIOS_TYPE_MEMARRAY 16
72bf21cd93STycho Nightingale #define SMBIOS_TYPE_MEMDEVICE 17
73bf21cd93STycho Nightingale #define SMBIOS_TYPE_MEMARRAYMAP 19
74bf21cd93STycho Nightingale #define SMBIOS_TYPE_BOOT 32
75bf21cd93STycho Nightingale #define SMBIOS_TYPE_EOT 127
76bf21cd93STycho Nightingale
77bf21cd93STycho Nightingale struct smbios_structure {
78bf21cd93STycho Nightingale uint8_t type;
79bf21cd93STycho Nightingale uint8_t length;
80bf21cd93STycho Nightingale uint16_t handle;
81bf21cd93STycho Nightingale } __packed;
82bf21cd93STycho Nightingale
834f3f3e9aSAndy Fiddaman struct smbios_string {
844f3f3e9aSAndy Fiddaman const char *node;
854f3f3e9aSAndy Fiddaman const char *value;
864f3f3e9aSAndy Fiddaman };
874f3f3e9aSAndy Fiddaman
8859d65d31SAndy Fiddaman typedef int (*initializer_func_t)(const struct smbios_structure *template_entry,
8959d65d31SAndy Fiddaman const struct smbios_string *template_strings, char *curaddr, char **endaddr,
9059d65d31SAndy Fiddaman uint16_t *n);
91bf21cd93STycho Nightingale
92bf21cd93STycho Nightingale struct smbios_template_entry {
9359d65d31SAndy Fiddaman const struct smbios_structure *entry;
9459d65d31SAndy Fiddaman const struct smbios_string *strings;
9559d65d31SAndy Fiddaman initializer_func_t initializer;
96bf21cd93STycho Nightingale };
97bf21cd93STycho Nightingale
98bf21cd93STycho Nightingale /*
99bf21cd93STycho Nightingale * SMBIOS Structure Table Entry Point
100bf21cd93STycho Nightingale */
101bf21cd93STycho Nightingale #define SMBIOS_ENTRY_EANCHOR "_SM_"
102bf21cd93STycho Nightingale #define SMBIOS_ENTRY_EANCHORLEN 4
103bf21cd93STycho Nightingale #define SMBIOS_ENTRY_IANCHOR "_DMI_"
104bf21cd93STycho Nightingale #define SMBIOS_ENTRY_IANCHORLEN 5
105bf21cd93STycho Nightingale
106bf21cd93STycho Nightingale struct smbios_entry_point {
107bf21cd93STycho Nightingale char eanchor[4]; /* anchor tag */
108bf21cd93STycho Nightingale uint8_t echecksum; /* checksum of entry point structure */
109bf21cd93STycho Nightingale uint8_t eplen; /* length in bytes of entry point */
110bf21cd93STycho Nightingale uint8_t major; /* major version of the SMBIOS spec */
111bf21cd93STycho Nightingale uint8_t minor; /* minor version of the SMBIOS spec */
112bf21cd93STycho Nightingale uint16_t maxssize; /* maximum size in bytes of a struct */
113bf21cd93STycho Nightingale uint8_t revision; /* entry point structure revision */
114bf21cd93STycho Nightingale uint8_t format[5]; /* entry point rev-specific data */
115bf21cd93STycho Nightingale char ianchor[5]; /* intermediate anchor tag */
116bf21cd93STycho Nightingale uint8_t ichecksum; /* intermediate checksum */
117bf21cd93STycho Nightingale uint16_t stlen; /* len in bytes of structure table */
118bf21cd93STycho Nightingale uint32_t staddr; /* physical addr of structure table */
119bf21cd93STycho Nightingale uint16_t stnum; /* number of structure table entries */
120bf21cd93STycho Nightingale uint8_t bcdrev; /* BCD value representing DMI ver */
121bf21cd93STycho Nightingale } __packed;
122bf21cd93STycho Nightingale
123bf21cd93STycho Nightingale /*
124bf21cd93STycho Nightingale * BIOS Information
125bf21cd93STycho Nightingale */
126bf21cd93STycho Nightingale #define SMBIOS_FL_ISA 0x00000010 /* ISA is supported */
127bf21cd93STycho Nightingale #define SMBIOS_FL_PCI 0x00000080 /* PCI is supported */
128bf21cd93STycho Nightingale #define SMBIOS_FL_SHADOW 0x00001000 /* BIOS shadowing is allowed */
129bf21cd93STycho Nightingale #define SMBIOS_FL_CDBOOT 0x00008000 /* Boot from CD is supported */
130bf21cd93STycho Nightingale #define SMBIOS_FL_SELBOOT 0x00010000 /* Selectable Boot supported */
131bf21cd93STycho Nightingale #define SMBIOS_FL_EDD 0x00080000 /* EDD Spec is supported */
132bf21cd93STycho Nightingale
133bf21cd93STycho Nightingale #define SMBIOS_XB1_FL_ACPI 0x00000001 /* ACPI is supported */
134bf21cd93STycho Nightingale
135bf21cd93STycho Nightingale #define SMBIOS_XB2_FL_BBS 0x00000001 /* BIOS Boot Specification */
136bf21cd93STycho Nightingale #define SMBIOS_XB2_FL_VM 0x00000010 /* Virtual Machine */
137bf21cd93STycho Nightingale
138bf21cd93STycho Nightingale struct smbios_table_type0 {
139bf21cd93STycho Nightingale struct smbios_structure header;
140bf21cd93STycho Nightingale uint8_t vendor; /* vendor string */
141bf21cd93STycho Nightingale uint8_t version; /* version string */
142bf21cd93STycho Nightingale uint16_t segment; /* address segment location */
143bf21cd93STycho Nightingale uint8_t rel_date; /* release date */
144bf21cd93STycho Nightingale uint8_t size; /* rom size */
145bf21cd93STycho Nightingale uint64_t cflags; /* characteristics */
146bf21cd93STycho Nightingale uint8_t xc_bytes[2]; /* characteristics ext bytes */
147bf21cd93STycho Nightingale uint8_t sb_major_rel; /* system bios version */
148bf21cd93STycho Nightingale uint8_t sb_minor_rele;
149bf21cd93STycho Nightingale uint8_t ecfw_major_rel; /* embedded ctrl fw version */
150bf21cd93STycho Nightingale uint8_t ecfw_minor_rel;
151bf21cd93STycho Nightingale } __packed;
152bf21cd93STycho Nightingale
153bf21cd93STycho Nightingale /*
154bf21cd93STycho Nightingale * System Information
155bf21cd93STycho Nightingale */
156bf21cd93STycho Nightingale #define SMBIOS_WAKEUP_SWITCH 0x06 /* power switch */
157bf21cd93STycho Nightingale
158bf21cd93STycho Nightingale struct smbios_table_type1 {
159bf21cd93STycho Nightingale struct smbios_structure header;
160bf21cd93STycho Nightingale uint8_t manufacturer; /* manufacturer string */
161bf21cd93STycho Nightingale uint8_t product; /* product name string */
162bf21cd93STycho Nightingale uint8_t version; /* version string */
163bf21cd93STycho Nightingale uint8_t serial; /* serial number string */
164bf21cd93STycho Nightingale uint8_t uuid[16]; /* uuid byte array */
165bf21cd93STycho Nightingale uint8_t wakeup; /* wake-up event */
166bf21cd93STycho Nightingale uint8_t sku; /* sku number string */
167bf21cd93STycho Nightingale uint8_t family; /* family name string */
168bf21cd93STycho Nightingale } __packed;
169bf21cd93STycho Nightingale
170b0de25cbSAndy Fiddaman /*
171b0de25cbSAndy Fiddaman * Baseboard (or Module) Information
172b0de25cbSAndy Fiddaman */
173b0de25cbSAndy Fiddaman #define SMBIOS_BRF_HOSTING 0x1
174b0de25cbSAndy Fiddaman #define SMBIOS_BRT_MOTHERBOARD 0xa
175b0de25cbSAndy Fiddaman
176b0de25cbSAndy Fiddaman struct smbios_table_type2 {
177b0de25cbSAndy Fiddaman struct smbios_structure header;
178b0de25cbSAndy Fiddaman uint8_t manufacturer; /* manufacturer string */
179b0de25cbSAndy Fiddaman uint8_t product; /* product name string */
180b0de25cbSAndy Fiddaman uint8_t version; /* version string */
181b0de25cbSAndy Fiddaman uint8_t serial; /* serial number string */
182b0de25cbSAndy Fiddaman uint8_t asset; /* asset tag string */
183b0de25cbSAndy Fiddaman uint8_t fflags; /* feature flags */
184b0de25cbSAndy Fiddaman uint8_t location; /* location in chassis */
185b0de25cbSAndy Fiddaman uint16_t chandle; /* chassis handle */
186b0de25cbSAndy Fiddaman uint8_t type; /* board type */
187b0de25cbSAndy Fiddaman uint8_t n_objs; /* number of contained object handles */
188b0de25cbSAndy Fiddaman } __packed;
189b0de25cbSAndy Fiddaman
190bf21cd93STycho Nightingale /*
191bf21cd93STycho Nightingale * System Enclosure or Chassis
192bf21cd93STycho Nightingale */
193bf21cd93STycho Nightingale #define SMBIOS_CHT_UNKNOWN 0x02 /* unknown */
194b0de25cbSAndy Fiddaman #define SMBIOS_CHT_DESKTOP 0x03 /* desktop */
195bf21cd93STycho Nightingale
196bf21cd93STycho Nightingale #define SMBIOS_CHST_SAFE 0x03 /* safe */
197bf21cd93STycho Nightingale
198bf21cd93STycho Nightingale #define SMBIOS_CHSC_NONE 0x03 /* none */
199bf21cd93STycho Nightingale
200bf21cd93STycho Nightingale struct smbios_table_type3 {
201bf21cd93STycho Nightingale struct smbios_structure header;
202bf21cd93STycho Nightingale uint8_t manufacturer; /* manufacturer string */
203bf21cd93STycho Nightingale uint8_t type; /* type */
204bf21cd93STycho Nightingale uint8_t version; /* version string */
205bf21cd93STycho Nightingale uint8_t serial; /* serial number string */
206bf21cd93STycho Nightingale uint8_t asset; /* asset tag string */
207bf21cd93STycho Nightingale uint8_t bustate; /* boot-up state */
208bf21cd93STycho Nightingale uint8_t psstate; /* power supply state */
209bf21cd93STycho Nightingale uint8_t tstate; /* thermal state */
210bf21cd93STycho Nightingale uint8_t security; /* security status */
211058c1d46SRobert Mustacchi uint32_t oemdata; /* OEM-specific data */
212bf21cd93STycho Nightingale uint8_t uheight; /* height in 'u's */
213bf21cd93STycho Nightingale uint8_t cords; /* number of power cords */
214bf21cd93STycho Nightingale uint8_t elems; /* number of element records */
215bf21cd93STycho Nightingale uint8_t elemlen; /* length of records */
216bf21cd93STycho Nightingale uint8_t sku; /* sku number string */
217bf21cd93STycho Nightingale } __packed;
218bf21cd93STycho Nightingale
219bf21cd93STycho Nightingale /*
220bf21cd93STycho Nightingale * Processor Information
221bf21cd93STycho Nightingale */
222bf21cd93STycho Nightingale #define SMBIOS_PRT_CENTRAL 0x03 /* central processor */
223bf21cd93STycho Nightingale
224bf21cd93STycho Nightingale #define SMBIOS_PRF_OTHER 0x01 /* other */
225bf21cd93STycho Nightingale
226bf21cd93STycho Nightingale #define SMBIOS_PRS_PRESENT 0x40 /* socket is populated */
227bf21cd93STycho Nightingale #define SMBIOS_PRS_ENABLED 0x1 /* enabled */
228bf21cd93STycho Nightingale
229bf21cd93STycho Nightingale #define SMBIOS_PRU_NONE 0x06 /* none */
230bf21cd93STycho Nightingale
231bf21cd93STycho Nightingale #define SMBIOS_PFL_64B 0x04 /* 64-bit capable */
232bf21cd93STycho Nightingale
233bf21cd93STycho Nightingale struct smbios_table_type4 {
234bf21cd93STycho Nightingale struct smbios_structure header;
235bf21cd93STycho Nightingale uint8_t socket; /* socket designation string */
236bf21cd93STycho Nightingale uint8_t type; /* processor type */
237bf21cd93STycho Nightingale uint8_t family; /* processor family */
238bf21cd93STycho Nightingale uint8_t manufacturer; /* manufacturer string */
239bf21cd93STycho Nightingale uint64_t cpuid; /* processor cpuid */
240bf21cd93STycho Nightingale uint8_t version; /* version string */
241bf21cd93STycho Nightingale uint8_t voltage; /* voltage */
242bf21cd93STycho Nightingale uint16_t clkspeed; /* ext clock speed in mhz */
243bf21cd93STycho Nightingale uint16_t maxspeed; /* maximum speed in mhz */
244bf21cd93STycho Nightingale uint16_t curspeed; /* current speed in mhz */
245bf21cd93STycho Nightingale uint8_t status; /* status */
246bf21cd93STycho Nightingale uint8_t upgrade; /* upgrade */
247bf21cd93STycho Nightingale uint16_t l1handle; /* l1 cache handle */
248bf21cd93STycho Nightingale uint16_t l2handle; /* l2 cache handle */
249bf21cd93STycho Nightingale uint16_t l3handle; /* l3 cache handle */
250bf21cd93STycho Nightingale uint8_t serial; /* serial number string */
251bf21cd93STycho Nightingale uint8_t asset; /* asset tag string */
252bf21cd93STycho Nightingale uint8_t part; /* part number string */
253bf21cd93STycho Nightingale uint8_t cores; /* cores per socket */
254bf21cd93STycho Nightingale uint8_t ecores; /* enabled cores */
255bf21cd93STycho Nightingale uint8_t threads; /* threads per socket */
256bf21cd93STycho Nightingale uint16_t cflags; /* processor characteristics */
257bf21cd93STycho Nightingale uint16_t family2; /* processor family 2 */
258bf21cd93STycho Nightingale } __packed;
259bf21cd93STycho Nightingale
260bf21cd93STycho Nightingale /*
261bf21cd93STycho Nightingale * Physical Memory Array
262bf21cd93STycho Nightingale */
263bf21cd93STycho Nightingale #define SMBIOS_MAL_SYSMB 0x03 /* system board or motherboard */
264bf21cd93STycho Nightingale
265bf21cd93STycho Nightingale #define SMBIOS_MAU_SYSTEM 0x03 /* system memory */
266bf21cd93STycho Nightingale
267bf21cd93STycho Nightingale #define SMBIOS_MAE_NONE 0x03 /* none */
268bf21cd93STycho Nightingale
269bf21cd93STycho Nightingale struct smbios_table_type16 {
270bf21cd93STycho Nightingale struct smbios_structure header;
271bf21cd93STycho Nightingale uint8_t location; /* physical device location */
272bf21cd93STycho Nightingale uint8_t use; /* device functional purpose */
273bf21cd93STycho Nightingale uint8_t ecc; /* err detect/correct method */
274bf21cd93STycho Nightingale uint32_t size; /* max mem capacity in kb */
275bf21cd93STycho Nightingale uint16_t errhand; /* handle of error (if any) */
276bf21cd93STycho Nightingale uint16_t ndevs; /* num of slots or sockets */
277bf21cd93STycho Nightingale uint64_t xsize; /* max mem capacity in bytes */
278bf21cd93STycho Nightingale } __packed;
279bf21cd93STycho Nightingale
280bf21cd93STycho Nightingale /*
281bf21cd93STycho Nightingale * Memory Device
282bf21cd93STycho Nightingale */
283bf21cd93STycho Nightingale #define SMBIOS_MDFF_UNKNOWN 0x02 /* unknown */
284bf21cd93STycho Nightingale
285bf21cd93STycho Nightingale #define SMBIOS_MDT_UNKNOWN 0x02 /* unknown */
286bf21cd93STycho Nightingale
287bf21cd93STycho Nightingale #define SMBIOS_MDF_UNKNOWN 0x0004 /* unknown */
288bf21cd93STycho Nightingale
289bf21cd93STycho Nightingale struct smbios_table_type17 {
290bf21cd93STycho Nightingale struct smbios_structure header;
291bf21cd93STycho Nightingale uint16_t arrayhand; /* handle of physl mem array */
292bf21cd93STycho Nightingale uint16_t errhand; /* handle of mem error data */
293bf21cd93STycho Nightingale uint16_t twidth; /* total width in bits */
294bf21cd93STycho Nightingale uint16_t dwidth; /* data width in bits */
295154972afSPatrick Mooney uint16_t size; /* size in kb or mb */
296bf21cd93STycho Nightingale uint8_t form; /* form factor */
297bf21cd93STycho Nightingale uint8_t set; /* set */
298bf21cd93STycho Nightingale uint8_t dloc; /* device locator string */
299bf21cd93STycho Nightingale uint8_t bloc; /* phys bank locator string */
300bf21cd93STycho Nightingale uint8_t type; /* memory type */
301bf21cd93STycho Nightingale uint16_t flags; /* memory characteristics */
302bf21cd93STycho Nightingale uint16_t maxspeed; /* maximum speed in mhz */
303bf21cd93STycho Nightingale uint8_t manufacturer; /* manufacturer string */
304bf21cd93STycho Nightingale uint8_t serial; /* serial number string */
305bf21cd93STycho Nightingale uint8_t asset; /* asset tag string */
306bf21cd93STycho Nightingale uint8_t part; /* part number string */
307bf21cd93STycho Nightingale uint8_t attributes; /* attributes */
308154972afSPatrick Mooney uint32_t xsize; /* extended size in mb */
309bf21cd93STycho Nightingale uint16_t curspeed; /* current speed in mhz */
310bf21cd93STycho Nightingale uint16_t minvoltage; /* minimum voltage */
311bf21cd93STycho Nightingale uint16_t maxvoltage; /* maximum voltage */
312bf21cd93STycho Nightingale uint16_t curvoltage; /* configured voltage */
313bf21cd93STycho Nightingale } __packed;
314bf21cd93STycho Nightingale
315bf21cd93STycho Nightingale /*
316bf21cd93STycho Nightingale * Memory Array Mapped Address
317bf21cd93STycho Nightingale */
318bf21cd93STycho Nightingale struct smbios_table_type19 {
319bf21cd93STycho Nightingale struct smbios_structure header;
320bf21cd93STycho Nightingale uint32_t saddr; /* start phys addr in kb */
321bf21cd93STycho Nightingale uint32_t eaddr; /* end phys addr in kb */
322bf21cd93STycho Nightingale uint16_t arrayhand; /* physical mem array handle */
323bf21cd93STycho Nightingale uint8_t width; /* num of dev in row */
324bf21cd93STycho Nightingale uint64_t xsaddr; /* start phys addr in bytes */
325bf21cd93STycho Nightingale uint64_t xeaddr; /* end phys addr in bytes */
326bf21cd93STycho Nightingale } __packed;
327bf21cd93STycho Nightingale
328bf21cd93STycho Nightingale /*
329bf21cd93STycho Nightingale * System Boot Information
330bf21cd93STycho Nightingale */
331bf21cd93STycho Nightingale #define SMBIOS_BOOT_NORMAL 0 /* no errors detected */
332bf21cd93STycho Nightingale
333bf21cd93STycho Nightingale struct smbios_table_type32 {
334bf21cd93STycho Nightingale struct smbios_structure header;
335bf21cd93STycho Nightingale uint8_t reserved[6];
336bf21cd93STycho Nightingale uint8_t status; /* boot status */
337bf21cd93STycho Nightingale } __packed;
338bf21cd93STycho Nightingale
339bf21cd93STycho Nightingale /*
340bf21cd93STycho Nightingale * End-of-Table
341bf21cd93STycho Nightingale */
342bf21cd93STycho Nightingale struct smbios_table_type127 {
343bf21cd93STycho Nightingale struct smbios_structure header;
344bf21cd93STycho Nightingale } __packed;
345bf21cd93STycho Nightingale
34659d65d31SAndy Fiddaman static const struct smbios_table_type0 smbios_type0_template = {
347bf21cd93STycho Nightingale { SMBIOS_TYPE_BIOS, sizeof (struct smbios_table_type0), 0 },
348bf21cd93STycho Nightingale 1, /* bios vendor string */
349bf21cd93STycho Nightingale 2, /* bios version string */
350bf21cd93STycho Nightingale 0xF000, /* bios address segment location */
351bf21cd93STycho Nightingale 3, /* bios release date */
352bf21cd93STycho Nightingale 0x0, /* bios size (64k * (n + 1) is the size in bytes) */
353bf21cd93STycho Nightingale SMBIOS_FL_ISA | SMBIOS_FL_PCI | SMBIOS_FL_SHADOW |
354bf21cd93STycho Nightingale SMBIOS_FL_CDBOOT | SMBIOS_FL_EDD,
355bf21cd93STycho Nightingale { SMBIOS_XB1_FL_ACPI, SMBIOS_XB2_FL_BBS | SMBIOS_XB2_FL_VM },
356bf21cd93STycho Nightingale 0x0, /* bios major release */
357bf21cd93STycho Nightingale 0x0, /* bios minor release */
358bf21cd93STycho Nightingale 0xff, /* embedded controller firmware major release */
359bf21cd93STycho Nightingale 0xff /* embedded controller firmware minor release */
360bf21cd93STycho Nightingale };
361bf21cd93STycho Nightingale
36259d65d31SAndy Fiddaman static const struct smbios_string smbios_type0_strings[] = {
3634f3f3e9aSAndy Fiddaman { "bios.vendor", "BHYVE" }, /* vendor string */
3644f3f3e9aSAndy Fiddaman { "bios.version", FIRMWARE_VERSION }, /* bios version string */
3654f3f3e9aSAndy Fiddaman { "bios.release_date", FIRMWARE_RELEASE_DATE }, /* bios release date string */
3664f3f3e9aSAndy Fiddaman { 0 }
367bf21cd93STycho Nightingale };
368bf21cd93STycho Nightingale
36959d65d31SAndy Fiddaman static const struct smbios_table_type1 smbios_type1_template = {
370bf21cd93STycho Nightingale { SMBIOS_TYPE_SYSTEM, sizeof (struct smbios_table_type1), 0 },
371bf21cd93STycho Nightingale 1, /* manufacturer string */
372bf21cd93STycho Nightingale 2, /* product string */
373bf21cd93STycho Nightingale 3, /* version string */
374bf21cd93STycho Nightingale 4, /* serial number string */
375bf21cd93STycho Nightingale { 0 },
376bf21cd93STycho Nightingale SMBIOS_WAKEUP_SWITCH,
377bf21cd93STycho Nightingale 5, /* sku string */
378bf21cd93STycho Nightingale 6 /* family string */
379bf21cd93STycho Nightingale };
380bf21cd93STycho Nightingale
38159d65d31SAndy Fiddaman static int smbios_type1_initializer(const struct smbios_structure *template_entry,
38259d65d31SAndy Fiddaman const struct smbios_string *template_strings, char *curaddr, char **endaddr,
38359d65d31SAndy Fiddaman uint16_t *n);
384bf21cd93STycho Nightingale
38559d65d31SAndy Fiddaman static const struct smbios_string smbios_type1_strings[] = {
3864f3f3e9aSAndy Fiddaman { "system.manufacturer", "illumos" }, /* manufacturer string */
3874f3f3e9aSAndy Fiddaman { "system.product_name", "BHYVE" }, /* product string */
3884f3f3e9aSAndy Fiddaman { "system.version", "1.0" }, /* version string */
3894f3f3e9aSAndy Fiddaman { "system.serial_number", "None" }, /* serial number string */
3904f3f3e9aSAndy Fiddaman { "system.sku", "None" }, /* sku string */
3914f3f3e9aSAndy Fiddaman { "system.family_name", "Virtual Machine" }, /* family string */
3924f3f3e9aSAndy Fiddaman { 0 }
393bf21cd93STycho Nightingale };
394bf21cd93STycho Nightingale
39559d65d31SAndy Fiddaman static const struct smbios_table_type2 smbios_type2_template = {
396b0de25cbSAndy Fiddaman { SMBIOS_TYPE_BOARD, sizeof (struct smbios_table_type2), 0 },
397b0de25cbSAndy Fiddaman 1, /* manufacturer string */
398b0de25cbSAndy Fiddaman 2, /* product string */
399b0de25cbSAndy Fiddaman 3, /* version string */
400b0de25cbSAndy Fiddaman 4, /* serial number string */
401b0de25cbSAndy Fiddaman 5, /* asset tag string */
402b0de25cbSAndy Fiddaman SMBIOS_BRF_HOSTING, /* feature flags */
403b0de25cbSAndy Fiddaman 6, /* location string */
404b0de25cbSAndy Fiddaman SMBIOS_CHT_DESKTOP, /* chassis handle */
405b0de25cbSAndy Fiddaman SMBIOS_BRT_MOTHERBOARD, /* board type */
406b0de25cbSAndy Fiddaman 0
407b0de25cbSAndy Fiddaman };
408b0de25cbSAndy Fiddaman
40959d65d31SAndy Fiddaman static const struct smbios_string smbios_type2_strings[] = {
4104f3f3e9aSAndy Fiddaman { "board.manufacturer", "illumos" }, /* manufacturer string */
4114f3f3e9aSAndy Fiddaman { "board.product_name", "BHYVE" }, /* product name string */
4124f3f3e9aSAndy Fiddaman { "board.version", "1.0" }, /* version string */
4134f3f3e9aSAndy Fiddaman { "board.serial_number", "None" }, /* serial number string */
4144f3f3e9aSAndy Fiddaman { "board.asset_tag", "None" }, /* asset tag string */
4154f3f3e9aSAndy Fiddaman { "board.location", "None" }, /* location string */
4164f3f3e9aSAndy Fiddaman { 0 }
417b0de25cbSAndy Fiddaman };
418b0de25cbSAndy Fiddaman
41959d65d31SAndy Fiddaman static const struct smbios_table_type3 smbios_type3_template = {
420bf21cd93STycho Nightingale { SMBIOS_TYPE_CHASSIS, sizeof (struct smbios_table_type3), 0 },
421bf21cd93STycho Nightingale 1, /* manufacturer string */
422bf21cd93STycho Nightingale SMBIOS_CHT_UNKNOWN,
423bf21cd93STycho Nightingale 2, /* version string */
424bf21cd93STycho Nightingale 3, /* serial number string */
425bf21cd93STycho Nightingale 4, /* asset tag string */
426bf21cd93STycho Nightingale SMBIOS_CHST_SAFE,
427bf21cd93STycho Nightingale SMBIOS_CHST_SAFE,
428bf21cd93STycho Nightingale SMBIOS_CHST_SAFE,
429bf21cd93STycho Nightingale SMBIOS_CHSC_NONE,
430058c1d46SRobert Mustacchi 0, /* OEM specific data, we have none */
431bf21cd93STycho Nightingale 0, /* height in 'u's (0=enclosure height unspecified) */
432bf21cd93STycho Nightingale 0, /* number of power cords (0=number unspecified) */
433bf21cd93STycho Nightingale 0, /* number of contained element records */
434bf21cd93STycho Nightingale 0, /* length of records */
435bf21cd93STycho Nightingale 5 /* sku number string */
436bf21cd93STycho Nightingale };
437bf21cd93STycho Nightingale
43859d65d31SAndy Fiddaman static const struct smbios_string smbios_type3_strings[] = {
4394f3f3e9aSAndy Fiddaman { "chassis.manufacturer", "illumos" }, /* manufacturer string */
4404f3f3e9aSAndy Fiddaman { "chassis.version", "1.0" }, /* version string */
4414f3f3e9aSAndy Fiddaman { "chassis.serial_number", "None" }, /* serial number string */
4424f3f3e9aSAndy Fiddaman { "chassis.asset_tag", "None" }, /* asset tag string */
4434f3f3e9aSAndy Fiddaman { "chassis.sku", "None" }, /* sku number string */
4444f3f3e9aSAndy Fiddaman { 0 }
445bf21cd93STycho Nightingale };
446bf21cd93STycho Nightingale
44759d65d31SAndy Fiddaman static const struct smbios_table_type4 smbios_type4_template = {
448bf21cd93STycho Nightingale { SMBIOS_TYPE_PROCESSOR, sizeof (struct smbios_table_type4), 0 },
449bf21cd93STycho Nightingale 1, /* socket designation string */
450bf21cd93STycho Nightingale SMBIOS_PRT_CENTRAL,
451bf21cd93STycho Nightingale SMBIOS_PRF_OTHER,
452bf21cd93STycho Nightingale 2, /* manufacturer string */
453bf21cd93STycho Nightingale 0, /* cpuid */
454bf21cd93STycho Nightingale 3, /* version string */
455bf21cd93STycho Nightingale 0, /* voltage */
456bf21cd93STycho Nightingale 0, /* external clock frequency in mhz (0=unknown) */
457bf21cd93STycho Nightingale 0, /* maximum frequency in mhz (0=unknown) */
458bf21cd93STycho Nightingale 0, /* current frequency in mhz (0=unknown) */
459bf21cd93STycho Nightingale SMBIOS_PRS_PRESENT | SMBIOS_PRS_ENABLED,
460bf21cd93STycho Nightingale SMBIOS_PRU_NONE,
461bf21cd93STycho Nightingale -1, /* l1 cache handle */
462bf21cd93STycho Nightingale -1, /* l2 cache handle */
463bf21cd93STycho Nightingale -1, /* l3 cache handle */
464bf21cd93STycho Nightingale 4, /* serial number string */
465bf21cd93STycho Nightingale 5, /* asset tag string */
466bf21cd93STycho Nightingale 6, /* part number string */
467bf21cd93STycho Nightingale 0, /* cores per socket (0=unknown) */
468bf21cd93STycho Nightingale 0, /* enabled cores per socket (0=unknown) */
469bf21cd93STycho Nightingale 0, /* threads per socket (0=unknown) */
470bf21cd93STycho Nightingale SMBIOS_PFL_64B,
471bf21cd93STycho Nightingale SMBIOS_PRF_OTHER
472bf21cd93STycho Nightingale };
473bf21cd93STycho Nightingale
47459d65d31SAndy Fiddaman static const struct smbios_string smbios_type4_strings[] = {
4754f3f3e9aSAndy Fiddaman { NULL, " " }, /* socket designation string */
4764f3f3e9aSAndy Fiddaman { NULL, " " }, /* manufacturer string */
4774f3f3e9aSAndy Fiddaman { NULL, " " }, /* version string */
4784f3f3e9aSAndy Fiddaman { NULL, "None" }, /* serial number string */
4794f3f3e9aSAndy Fiddaman { NULL, "None" }, /* asset tag string */
4804f3f3e9aSAndy Fiddaman { NULL, "None" }, /* part number string */
4814f3f3e9aSAndy Fiddaman { 0 }
482bf21cd93STycho Nightingale };
483bf21cd93STycho Nightingale
48459d65d31SAndy Fiddaman static int smbios_type4_initializer(
48559d65d31SAndy Fiddaman const struct smbios_structure *template_entry,
48659d65d31SAndy Fiddaman const struct smbios_string *template_strings, char *curaddr, char **endaddr,
48759d65d31SAndy Fiddaman uint16_t *n);
488bf21cd93STycho Nightingale
48959d65d31SAndy Fiddaman static const struct smbios_table_type16 smbios_type16_template = {
490bf21cd93STycho Nightingale { SMBIOS_TYPE_MEMARRAY, sizeof (struct smbios_table_type16), 0 },
491bf21cd93STycho Nightingale SMBIOS_MAL_SYSMB,
492bf21cd93STycho Nightingale SMBIOS_MAU_SYSTEM,
493bf21cd93STycho Nightingale SMBIOS_MAE_NONE,
494bf21cd93STycho Nightingale 0x80000000, /* max mem capacity in kb (0x80000000=use extended) */
495bf21cd93STycho Nightingale -1, /* handle of error (if any) */
496bf21cd93STycho Nightingale 0, /* number of slots or sockets (TBD) */
497bf21cd93STycho Nightingale 0 /* extended maximum memory capacity in bytes (TBD) */
498bf21cd93STycho Nightingale };
499bf21cd93STycho Nightingale
50059d65d31SAndy Fiddaman static int smbios_type16_initializer(
50159d65d31SAndy Fiddaman const struct smbios_structure *template_entry,
50259d65d31SAndy Fiddaman const struct smbios_string *template_strings, char *curaddr, char **endaddr,
50359d65d31SAndy Fiddaman uint16_t *n);
504bf21cd93STycho Nightingale
50559d65d31SAndy Fiddaman static const struct smbios_table_type17 smbios_type17_template = {
506bf21cd93STycho Nightingale { SMBIOS_TYPE_MEMDEVICE, sizeof (struct smbios_table_type17), 0 },
507bf21cd93STycho Nightingale -1, /* handle of physical memory array */
508bf21cd93STycho Nightingale -1, /* handle of memory error data */
509bf21cd93STycho Nightingale 64, /* total width in bits including ecc */
510bf21cd93STycho Nightingale 64, /* data width in bits */
511154972afSPatrick Mooney 0, /* size in kb or mb (0x7fff=use extended)*/
512bf21cd93STycho Nightingale SMBIOS_MDFF_UNKNOWN,
513bf21cd93STycho Nightingale 0, /* set (0x00=none, 0xff=unknown) */
514bf21cd93STycho Nightingale 1, /* device locator string */
515bf21cd93STycho Nightingale 2, /* physical bank locator string */
516bf21cd93STycho Nightingale SMBIOS_MDT_UNKNOWN,
517bf21cd93STycho Nightingale SMBIOS_MDF_UNKNOWN,
518bf21cd93STycho Nightingale 0, /* maximum memory speed in mhz (0=unknown) */
519bf21cd93STycho Nightingale 3, /* manufacturer string */
520bf21cd93STycho Nightingale 4, /* serial number string */
521bf21cd93STycho Nightingale 5, /* asset tag string */
522bf21cd93STycho Nightingale 6, /* part number string */
523bf21cd93STycho Nightingale 0, /* attributes (0=unknown rank information) */
524bf21cd93STycho Nightingale 0, /* extended size in mb (TBD) */
525bf21cd93STycho Nightingale 0, /* current speed in mhz (0=unknown) */
526bf21cd93STycho Nightingale 0, /* minimum voltage in mv (0=unknown) */
527bf21cd93STycho Nightingale 0, /* maximum voltage in mv (0=unknown) */
528bf21cd93STycho Nightingale 0 /* configured voltage in mv (0=unknown) */
529bf21cd93STycho Nightingale };
530bf21cd93STycho Nightingale
53159d65d31SAndy Fiddaman static const struct smbios_string smbios_type17_strings[] = {
5324f3f3e9aSAndy Fiddaman { NULL, " " }, /* device locator string */
5334f3f3e9aSAndy Fiddaman { NULL, " " }, /* physical bank locator string */
5344f3f3e9aSAndy Fiddaman { NULL, " " }, /* manufacturer string */
5354f3f3e9aSAndy Fiddaman { NULL, "None" }, /* serial number string */
5364f3f3e9aSAndy Fiddaman { NULL, "None" }, /* asset tag string */
5374f3f3e9aSAndy Fiddaman { NULL, "None" }, /* part number string */
5384f3f3e9aSAndy Fiddaman { 0 }
539bf21cd93STycho Nightingale };
540bf21cd93STycho Nightingale
54159d65d31SAndy Fiddaman static int smbios_type17_initializer(
54259d65d31SAndy Fiddaman const struct smbios_structure *template_entry,
54359d65d31SAndy Fiddaman const struct smbios_string *template_strings, char *curaddr, char **endaddr,
54459d65d31SAndy Fiddaman uint16_t *n);
545bf21cd93STycho Nightingale
54659d65d31SAndy Fiddaman static const struct smbios_table_type19 smbios_type19_template = {
547bf21cd93STycho Nightingale { SMBIOS_TYPE_MEMARRAYMAP, sizeof (struct smbios_table_type19), 0 },
548bf21cd93STycho Nightingale 0xffffffff, /* starting phys addr in kb (0xffffffff=use ext) */
549bf21cd93STycho Nightingale 0xffffffff, /* ending phys addr in kb (0xffffffff=use ext) */
550bf21cd93STycho Nightingale -1, /* physical memory array handle */
551bf21cd93STycho Nightingale 1, /* number of devices that form a row */
552bf21cd93STycho Nightingale 0, /* extended starting phys addr in bytes (TDB) */
553bf21cd93STycho Nightingale 0 /* extended ending phys addr in bytes (TDB) */
554bf21cd93STycho Nightingale };
555bf21cd93STycho Nightingale
55659d65d31SAndy Fiddaman static int smbios_type19_initializer(
55759d65d31SAndy Fiddaman const struct smbios_structure *template_entry,
55859d65d31SAndy Fiddaman const struct smbios_string *template_strings, char *curaddr, char **endaddr,
55959d65d31SAndy Fiddaman uint16_t *n);
560bf21cd93STycho Nightingale
56159d65d31SAndy Fiddaman static struct smbios_table_type32 smbios_type32_template = {
562bf21cd93STycho Nightingale { SMBIOS_TYPE_BOOT, sizeof (struct smbios_table_type32), 0 },
563bf21cd93STycho Nightingale { 0, 0, 0, 0, 0, 0 },
564bf21cd93STycho Nightingale SMBIOS_BOOT_NORMAL
565bf21cd93STycho Nightingale };
566bf21cd93STycho Nightingale
56759d65d31SAndy Fiddaman static const struct smbios_table_type127 smbios_type127_template = {
568bf21cd93STycho Nightingale { SMBIOS_TYPE_EOT, sizeof (struct smbios_table_type127), 0 }
569bf21cd93STycho Nightingale };
570bf21cd93STycho Nightingale
57159d65d31SAndy Fiddaman static int smbios_generic_initializer(
57259d65d31SAndy Fiddaman const struct smbios_structure *template_entry,
57359d65d31SAndy Fiddaman const struct smbios_string *template_strings, char *curaddr, char **endaddr,
57459d65d31SAndy Fiddaman uint16_t *n);
575bf21cd93STycho Nightingale
576bf21cd93STycho Nightingale static struct smbios_template_entry smbios_template[] = {
57759d65d31SAndy Fiddaman { (const struct smbios_structure *)&smbios_type0_template,
578bf21cd93STycho Nightingale smbios_type0_strings,
579bf21cd93STycho Nightingale smbios_generic_initializer },
58059d65d31SAndy Fiddaman { (const struct smbios_structure *)&smbios_type1_template,
581bf21cd93STycho Nightingale smbios_type1_strings,
582bf21cd93STycho Nightingale smbios_type1_initializer },
58359d65d31SAndy Fiddaman { (const struct smbios_structure *)&smbios_type2_template,
584b0de25cbSAndy Fiddaman smbios_type2_strings,
585b0de25cbSAndy Fiddaman smbios_generic_initializer },
58659d65d31SAndy Fiddaman { (const struct smbios_structure *)&smbios_type3_template,
587bf21cd93STycho Nightingale smbios_type3_strings,
588bf21cd93STycho Nightingale smbios_generic_initializer },
58959d65d31SAndy Fiddaman { (const struct smbios_structure *)&smbios_type4_template,
590bf21cd93STycho Nightingale smbios_type4_strings,
591bf21cd93STycho Nightingale smbios_type4_initializer },
59259d65d31SAndy Fiddaman { (const struct smbios_structure *)&smbios_type16_template,
593bf21cd93STycho Nightingale NULL,
594bf21cd93STycho Nightingale smbios_type16_initializer },
59559d65d31SAndy Fiddaman { (const struct smbios_structure *)&smbios_type17_template,
596bf21cd93STycho Nightingale smbios_type17_strings,
597bf21cd93STycho Nightingale smbios_type17_initializer },
59859d65d31SAndy Fiddaman { (const struct smbios_structure *)&smbios_type19_template,
599bf21cd93STycho Nightingale NULL,
600bf21cd93STycho Nightingale smbios_type19_initializer },
60159d65d31SAndy Fiddaman { (const struct smbios_structure *)&smbios_type32_template,
602bf21cd93STycho Nightingale NULL,
603bf21cd93STycho Nightingale smbios_generic_initializer },
60459d65d31SAndy Fiddaman { (const struct smbios_structure *)&smbios_type127_template,
605bf21cd93STycho Nightingale NULL,
606bf21cd93STycho Nightingale smbios_generic_initializer },
607bf21cd93STycho Nightingale { NULL,NULL, NULL }
608bf21cd93STycho Nightingale };
609bf21cd93STycho Nightingale
610bf21cd93STycho Nightingale static uint64_t guest_lomem, guest_himem;
611bf21cd93STycho Nightingale static uint16_t type16_handle;
612bf21cd93STycho Nightingale
613bf21cd93STycho Nightingale static int
smbios_generic_initializer(const struct smbios_structure * template_entry,const struct smbios_string * template_strings,char * curaddr,char ** endaddr,uint16_t * n)61459d65d31SAndy Fiddaman smbios_generic_initializer(const struct smbios_structure *template_entry,
61559d65d31SAndy Fiddaman const struct smbios_string *template_strings, char *curaddr, char **endaddr,
61659d65d31SAndy Fiddaman uint16_t *n)
617bf21cd93STycho Nightingale {
618bf21cd93STycho Nightingale struct smbios_structure *entry;
619bf21cd93STycho Nightingale
620bf21cd93STycho Nightingale memcpy(curaddr, template_entry, template_entry->length);
621bf21cd93STycho Nightingale entry = (struct smbios_structure *)curaddr;
622bf21cd93STycho Nightingale entry->handle = *n + 1;
623bf21cd93STycho Nightingale curaddr += entry->length;
624bf21cd93STycho Nightingale if (template_strings != NULL) {
625bf21cd93STycho Nightingale int i;
626bf21cd93STycho Nightingale
6274f3f3e9aSAndy Fiddaman for (i = 0; template_strings[i].value != NULL; i++) {
628bf21cd93STycho Nightingale const char *string;
629bf21cd93STycho Nightingale int len;
630bf21cd93STycho Nightingale
6314f3f3e9aSAndy Fiddaman if (template_strings[i].node == NULL) {
6324f3f3e9aSAndy Fiddaman string = template_strings[i].value;
6334f3f3e9aSAndy Fiddaman } else {
6344f3f3e9aSAndy Fiddaman set_config_value_if_unset(
6354f3f3e9aSAndy Fiddaman template_strings[i].node,
6364f3f3e9aSAndy Fiddaman template_strings[i].value);
6374f3f3e9aSAndy Fiddaman string = get_config_value(
6384f3f3e9aSAndy Fiddaman template_strings[i].node);
6394f3f3e9aSAndy Fiddaman }
6404f3f3e9aSAndy Fiddaman
641bf21cd93STycho Nightingale len = strlen(string) + 1;
642bf21cd93STycho Nightingale memcpy(curaddr, string, len);
643bf21cd93STycho Nightingale curaddr += len;
644bf21cd93STycho Nightingale }
645bf21cd93STycho Nightingale *curaddr = '\0';
646bf21cd93STycho Nightingale curaddr++;
647bf21cd93STycho Nightingale } else {
648bf21cd93STycho Nightingale /* Minimum string section is double nul */
649bf21cd93STycho Nightingale *curaddr = '\0';
650bf21cd93STycho Nightingale curaddr++;
651bf21cd93STycho Nightingale *curaddr = '\0';
652bf21cd93STycho Nightingale curaddr++;
653bf21cd93STycho Nightingale }
654bf21cd93STycho Nightingale (*n)++;
655bf21cd93STycho Nightingale *endaddr = curaddr;
656bf21cd93STycho Nightingale
657bf21cd93STycho Nightingale return (0);
658bf21cd93STycho Nightingale }
659bf21cd93STycho Nightingale
660bf21cd93STycho Nightingale static int
smbios_type1_initializer(const struct smbios_structure * template_entry,const struct smbios_string * template_strings,char * curaddr,char ** endaddr,uint16_t * n)66159d65d31SAndy Fiddaman smbios_type1_initializer(const struct smbios_structure *template_entry,
66259d65d31SAndy Fiddaman const struct smbios_string *template_strings, char *curaddr, char **endaddr,
66359d65d31SAndy Fiddaman uint16_t *n)
664bf21cd93STycho Nightingale {
665bf21cd93STycho Nightingale struct smbios_table_type1 *type1;
6662b948146SAndy Fiddaman const char *guest_uuid_str;
667bf21cd93STycho Nightingale
668bf21cd93STycho Nightingale smbios_generic_initializer(template_entry, template_strings,
66959d65d31SAndy Fiddaman curaddr, endaddr, n);
670bf21cd93STycho Nightingale type1 = (struct smbios_table_type1 *)curaddr;
671bf21cd93STycho Nightingale
6722b948146SAndy Fiddaman guest_uuid_str = get_config_value("uuid");
673bf21cd93STycho Nightingale if (guest_uuid_str != NULL) {
674bf21cd93STycho Nightingale uuid_t uuid;
675bf21cd93STycho Nightingale uint32_t status;
676bf21cd93STycho Nightingale
677bf21cd93STycho Nightingale uuid_from_string(guest_uuid_str, &uuid, &status);
6784f3f3e9aSAndy Fiddaman if (status != uuid_s_ok) {
6794f3f3e9aSAndy Fiddaman EPRINTLN("Invalid UUID");
680bf21cd93STycho Nightingale return (-1);
6814f3f3e9aSAndy Fiddaman }
682bf21cd93STycho Nightingale
683bf21cd93STycho Nightingale uuid_enc_le(&type1->uuid, &uuid);
684bf21cd93STycho Nightingale } else {
685bf21cd93STycho Nightingale MD5_CTX mdctx;
686bf21cd93STycho Nightingale u_char digest[16];
687bf21cd93STycho Nightingale char hostname[MAXHOSTNAMELEN];
6882b948146SAndy Fiddaman const char *vmname;
689bf21cd93STycho Nightingale
690bf21cd93STycho Nightingale /*
691bf21cd93STycho Nightingale * Universally unique and yet reproducible are an
692bf21cd93STycho Nightingale * oxymoron, however reproducible is desirable in
693bf21cd93STycho Nightingale * this case.
694bf21cd93STycho Nightingale */
695bf21cd93STycho Nightingale if (gethostname(hostname, sizeof(hostname)))
696bf21cd93STycho Nightingale return (-1);
697bf21cd93STycho Nightingale
698bf21cd93STycho Nightingale MD5Init(&mdctx);
6992b948146SAndy Fiddaman vmname = get_config_value("name");
700bf21cd93STycho Nightingale MD5Update(&mdctx, vmname, strlen(vmname));
701bf21cd93STycho Nightingale MD5Update(&mdctx, hostname, sizeof(hostname));
702bf21cd93STycho Nightingale MD5Final(digest, &mdctx);
703bf21cd93STycho Nightingale
704bf21cd93STycho Nightingale /*
705bf21cd93STycho Nightingale * Set the variant and version number.
706bf21cd93STycho Nightingale */
707bf21cd93STycho Nightingale digest[6] &= 0x0F;
708bf21cd93STycho Nightingale digest[6] |= 0x30; /* version 3 */
709bf21cd93STycho Nightingale digest[8] &= 0x3F;
710bf21cd93STycho Nightingale digest[8] |= 0x80;
711bf21cd93STycho Nightingale
712bf21cd93STycho Nightingale memcpy(&type1->uuid, digest, sizeof (digest));
713bf21cd93STycho Nightingale }
714bf21cd93STycho Nightingale
715bf21cd93STycho Nightingale return (0);
716bf21cd93STycho Nightingale }
717bf21cd93STycho Nightingale
718bf21cd93STycho Nightingale static int
smbios_type4_initializer(const struct smbios_structure * template_entry,const struct smbios_string * template_strings,char * curaddr,char ** endaddr,uint16_t * n)71959d65d31SAndy Fiddaman smbios_type4_initializer(const struct smbios_structure *template_entry,
72059d65d31SAndy Fiddaman const struct smbios_string *template_strings, char *curaddr, char **endaddr,
72159d65d31SAndy Fiddaman uint16_t *n)
722bf21cd93STycho Nightingale {
723bf21cd93STycho Nightingale int i;
724bf21cd93STycho Nightingale
72559d65d31SAndy Fiddaman for (i = 0; i < cpu_sockets; i++) {
726bf21cd93STycho Nightingale struct smbios_table_type4 *type4;
727bf21cd93STycho Nightingale char *p;
728bf21cd93STycho Nightingale int nstrings, len;
729bf21cd93STycho Nightingale
730bf21cd93STycho Nightingale smbios_generic_initializer(template_entry, template_strings,
73159d65d31SAndy Fiddaman curaddr, endaddr, n);
732bf21cd93STycho Nightingale type4 = (struct smbios_table_type4 *)curaddr;
733bf21cd93STycho Nightingale p = curaddr + sizeof (struct smbios_table_type4);
734bf21cd93STycho Nightingale nstrings = 0;
735bf21cd93STycho Nightingale while (p < *endaddr - 1) {
736bf21cd93STycho Nightingale if (*p++ == '\0')
737bf21cd93STycho Nightingale nstrings++;
738bf21cd93STycho Nightingale }
739bf21cd93STycho Nightingale len = sprintf(*endaddr - 1, "CPU #%d", i) + 1;
740bf21cd93STycho Nightingale *endaddr += len - 1;
741bf21cd93STycho Nightingale *(*endaddr) = '\0';
742bf21cd93STycho Nightingale (*endaddr)++;
743bf21cd93STycho Nightingale type4->socket = nstrings + 1;
7444c87aefeSPatrick Mooney /* Revise cores and threads after update to smbios 3.0 */
74559d65d31SAndy Fiddaman if (cpu_cores > 254)
7464c87aefeSPatrick Mooney type4->cores = 0;
7474c87aefeSPatrick Mooney else
74859d65d31SAndy Fiddaman type4->cores = cpu_cores;
7494c87aefeSPatrick Mooney /* This threads is total threads in a socket */
75059d65d31SAndy Fiddaman if (cpu_cores * cpu_threads > 254)
7514c87aefeSPatrick Mooney type4->threads = 0;
7524c87aefeSPatrick Mooney else
75359d65d31SAndy Fiddaman type4->threads = cpu_cores * cpu_threads;
754bf21cd93STycho Nightingale curaddr = *endaddr;
755bf21cd93STycho Nightingale }
756bf21cd93STycho Nightingale
757bf21cd93STycho Nightingale return (0);
758bf21cd93STycho Nightingale }
759bf21cd93STycho Nightingale
760bf21cd93STycho Nightingale static int
smbios_type16_initializer(const struct smbios_structure * template_entry,const struct smbios_string * template_strings,char * curaddr,char ** endaddr,uint16_t * n)76159d65d31SAndy Fiddaman smbios_type16_initializer(const struct smbios_structure *template_entry,
76259d65d31SAndy Fiddaman const struct smbios_string *template_strings, char *curaddr, char **endaddr,
76359d65d31SAndy Fiddaman uint16_t *n)
764bf21cd93STycho Nightingale {
765bf21cd93STycho Nightingale struct smbios_table_type16 *type16;
766bf21cd93STycho Nightingale
767bf21cd93STycho Nightingale type16_handle = *n;
768bf21cd93STycho Nightingale smbios_generic_initializer(template_entry, template_strings,
76959d65d31SAndy Fiddaman curaddr, endaddr, n);
770bf21cd93STycho Nightingale type16 = (struct smbios_table_type16 *)curaddr;
771bf21cd93STycho Nightingale type16->xsize = guest_lomem + guest_himem;
772bf21cd93STycho Nightingale type16->ndevs = guest_himem > 0 ? 2 : 1;
773bf21cd93STycho Nightingale
774bf21cd93STycho Nightingale return (0);
775bf21cd93STycho Nightingale }
776bf21cd93STycho Nightingale
777bf21cd93STycho Nightingale static int
smbios_type17_initializer(const struct smbios_structure * template_entry,const struct smbios_string * template_strings,char * curaddr,char ** endaddr,uint16_t * n)77859d65d31SAndy Fiddaman smbios_type17_initializer(const struct smbios_structure *template_entry,
77959d65d31SAndy Fiddaman const struct smbios_string *template_strings, char *curaddr, char **endaddr,
78059d65d31SAndy Fiddaman uint16_t *n)
781bf21cd93STycho Nightingale {
782bf21cd93STycho Nightingale struct smbios_table_type17 *type17;
783154972afSPatrick Mooney uint64_t memsize, size_KB, size_MB;
784bf21cd93STycho Nightingale
785bf21cd93STycho Nightingale smbios_generic_initializer(template_entry, template_strings,
78659d65d31SAndy Fiddaman curaddr, endaddr, n);
787bf21cd93STycho Nightingale type17 = (struct smbios_table_type17 *)curaddr;
788bf21cd93STycho Nightingale type17->arrayhand = type16_handle;
789bf21cd93STycho Nightingale
790154972afSPatrick Mooney memsize = guest_lomem + guest_himem;
791154972afSPatrick Mooney size_KB = memsize / 1024;
792154972afSPatrick Mooney size_MB = memsize / MB;
793154972afSPatrick Mooney
794154972afSPatrick Mooney /* A single Type 17 entry can't represent more than ~2PB RAM */
795154972afSPatrick Mooney if (size_MB > 0x7FFFFFFF) {
796154972afSPatrick Mooney printf("Warning: guest memory too big for SMBIOS Type 17 table: "
797154972afSPatrick Mooney "%luMB greater than max supported 2147483647MB\n", size_MB);
798154972afSPatrick Mooney
799154972afSPatrick Mooney size_MB = 0x7FFFFFFF;
800154972afSPatrick Mooney }
801154972afSPatrick Mooney
802154972afSPatrick Mooney /* See SMBIOS 2.7.0 section 7.18 - Memory Device (Type 17) */
803154972afSPatrick Mooney if (size_KB <= 0x7FFF) {
804154972afSPatrick Mooney /* Can represent up to 32767KB with the top bit set */
805154972afSPatrick Mooney type17->size = size_KB | (1 << 15);
806154972afSPatrick Mooney } else if (size_MB < 0x7FFF) {
807154972afSPatrick Mooney /* Can represent up to 32766MB with the top bit unset */
808154972afSPatrick Mooney type17->size = size_MB & 0x7FFF;
809154972afSPatrick Mooney } else {
810154972afSPatrick Mooney type17->size = 0x7FFF;
811154972afSPatrick Mooney /*
812154972afSPatrick Mooney * Can represent up to 2147483647MB (~2PB)
813154972afSPatrick Mooney * The top bit is reserved
814154972afSPatrick Mooney */
815154972afSPatrick Mooney type17->xsize = size_MB & 0x7FFFFFFF;
816bf21cd93STycho Nightingale }
817bf21cd93STycho Nightingale
818bf21cd93STycho Nightingale return (0);
819bf21cd93STycho Nightingale }
820bf21cd93STycho Nightingale
821bf21cd93STycho Nightingale static int
smbios_type19_initializer(const struct smbios_structure * template_entry,const struct smbios_string * template_strings,char * curaddr,char ** endaddr,uint16_t * n)82259d65d31SAndy Fiddaman smbios_type19_initializer(const struct smbios_structure *template_entry,
82359d65d31SAndy Fiddaman const struct smbios_string *template_strings, char *curaddr, char **endaddr,
82459d65d31SAndy Fiddaman uint16_t *n)
825bf21cd93STycho Nightingale {
826bf21cd93STycho Nightingale struct smbios_table_type19 *type19;
827bf21cd93STycho Nightingale
828bf21cd93STycho Nightingale smbios_generic_initializer(template_entry, template_strings,
82959d65d31SAndy Fiddaman curaddr, endaddr, n);
830bf21cd93STycho Nightingale type19 = (struct smbios_table_type19 *)curaddr;
831bf21cd93STycho Nightingale type19->arrayhand = type16_handle;
832bf21cd93STycho Nightingale type19->xsaddr = 0;
833bf21cd93STycho Nightingale type19->xeaddr = guest_lomem;
834bf21cd93STycho Nightingale
835bf21cd93STycho Nightingale if (guest_himem > 0) {
836bf21cd93STycho Nightingale curaddr = *endaddr;
837bf21cd93STycho Nightingale smbios_generic_initializer(template_entry, template_strings,
83859d65d31SAndy Fiddaman curaddr, endaddr, n);
839bf21cd93STycho Nightingale type19 = (struct smbios_table_type19 *)curaddr;
840bf21cd93STycho Nightingale type19->arrayhand = type16_handle;
841bf21cd93STycho Nightingale type19->xsaddr = 4*GB;
8426960cd89SAndy Fiddaman type19->xeaddr = type19->xsaddr + guest_himem;
843bf21cd93STycho Nightingale }
844bf21cd93STycho Nightingale
845bf21cd93STycho Nightingale return (0);
846bf21cd93STycho Nightingale }
847bf21cd93STycho Nightingale
848bf21cd93STycho Nightingale static void
smbios_ep_initializer(struct smbios_entry_point * smbios_ep,uint32_t staddr)849bf21cd93STycho Nightingale smbios_ep_initializer(struct smbios_entry_point *smbios_ep, uint32_t staddr)
850bf21cd93STycho Nightingale {
851bf21cd93STycho Nightingale memset(smbios_ep, 0, sizeof(*smbios_ep));
852bf21cd93STycho Nightingale memcpy(smbios_ep->eanchor, SMBIOS_ENTRY_EANCHOR,
853bf21cd93STycho Nightingale SMBIOS_ENTRY_EANCHORLEN);
854bf21cd93STycho Nightingale smbios_ep->eplen = 0x1F;
855bf21cd93STycho Nightingale assert(sizeof (struct smbios_entry_point) == smbios_ep->eplen);
856bf21cd93STycho Nightingale smbios_ep->major = 2;
857bf21cd93STycho Nightingale smbios_ep->minor = 6;
858bf21cd93STycho Nightingale smbios_ep->revision = 0;
859bf21cd93STycho Nightingale memcpy(smbios_ep->ianchor, SMBIOS_ENTRY_IANCHOR,
860bf21cd93STycho Nightingale SMBIOS_ENTRY_IANCHORLEN);
861bf21cd93STycho Nightingale smbios_ep->staddr = staddr;
862154972afSPatrick Mooney smbios_ep->bcdrev = (smbios_ep->major & 0xf) << 4 | (smbios_ep->minor & 0xf);
863bf21cd93STycho Nightingale }
864bf21cd93STycho Nightingale
865bf21cd93STycho Nightingale static void
smbios_ep_finalizer(struct smbios_entry_point * smbios_ep,uint16_t len,uint16_t num,uint16_t maxssize)866bf21cd93STycho Nightingale smbios_ep_finalizer(struct smbios_entry_point *smbios_ep, uint16_t len,
867bf21cd93STycho Nightingale uint16_t num, uint16_t maxssize)
868bf21cd93STycho Nightingale {
869bf21cd93STycho Nightingale uint8_t checksum;
870bf21cd93STycho Nightingale int i;
871bf21cd93STycho Nightingale
872bf21cd93STycho Nightingale smbios_ep->maxssize = maxssize;
873bf21cd93STycho Nightingale smbios_ep->stlen = len;
874bf21cd93STycho Nightingale smbios_ep->stnum = num;
875bf21cd93STycho Nightingale
876bf21cd93STycho Nightingale checksum = 0;
877bf21cd93STycho Nightingale for (i = 0x10; i < 0x1f; i++) {
878bf21cd93STycho Nightingale checksum -= ((uint8_t *)smbios_ep)[i];
879bf21cd93STycho Nightingale }
880bf21cd93STycho Nightingale smbios_ep->ichecksum = checksum;
881bf21cd93STycho Nightingale
882bf21cd93STycho Nightingale checksum = 0;
883bf21cd93STycho Nightingale for (i = 0; i < 0x1f; i++) {
884bf21cd93STycho Nightingale checksum -= ((uint8_t *)smbios_ep)[i];
885bf21cd93STycho Nightingale }
886bf21cd93STycho Nightingale smbios_ep->echecksum = checksum;
887bf21cd93STycho Nightingale }
888bf21cd93STycho Nightingale
8894f3f3e9aSAndy Fiddaman #ifndef __FreeBSD__
8904f3f3e9aSAndy Fiddaman /*
8914f3f3e9aSAndy Fiddaman * bhyve on illumos previously used configuration keys starting with 'smbios.'
8924f3f3e9aSAndy Fiddaman * to control type 1 SMBIOS information. Since these may still be present in
8934f3f3e9aSAndy Fiddaman * bhyve configuration files, the following table is used to translate them
8944f3f3e9aSAndy Fiddaman * to their new key names.
8954f3f3e9aSAndy Fiddaman */
8964f3f3e9aSAndy Fiddaman static struct {
8974f3f3e9aSAndy Fiddaman const char *oldkey;
8984f3f3e9aSAndy Fiddaman const char *newkey;
8994f3f3e9aSAndy Fiddaman } smbios_legacy_config_map[] = {
9004f3f3e9aSAndy Fiddaman { "smbios.manufacturer", "system.manufacturer" },
9014f3f3e9aSAndy Fiddaman { "smbios.family", "system.family_name" },
9024f3f3e9aSAndy Fiddaman { "smbios.product", "system.product_name" },
9034f3f3e9aSAndy Fiddaman { "smbios.serial", "system.serial_number" },
9044f3f3e9aSAndy Fiddaman { "smbios.sku", "system.sku" },
9054f3f3e9aSAndy Fiddaman { "smbios.version", "system.version" },
9064f3f3e9aSAndy Fiddaman };
9074f3f3e9aSAndy Fiddaman #endif
9084f3f3e9aSAndy Fiddaman
909bf21cd93STycho Nightingale int
smbios_build(struct vmctx * ctx)910bf21cd93STycho Nightingale smbios_build(struct vmctx *ctx)
911bf21cd93STycho Nightingale {
912bf21cd93STycho Nightingale struct smbios_entry_point *smbios_ep;
913bf21cd93STycho Nightingale uint16_t n;
914bf21cd93STycho Nightingale uint16_t maxssize;
915bf21cd93STycho Nightingale char *curaddr, *startaddr, *ststartaddr;
916bf21cd93STycho Nightingale int i;
917bf21cd93STycho Nightingale int err;
918bf21cd93STycho Nightingale
919bf21cd93STycho Nightingale guest_lomem = vm_get_lowmem_size(ctx);
920bf21cd93STycho Nightingale guest_himem = vm_get_highmem_size(ctx);
921bf21cd93STycho Nightingale
922bf21cd93STycho Nightingale startaddr = paddr_guest2host(ctx, SMBIOS_BASE, SMBIOS_MAX_LENGTH);
923bf21cd93STycho Nightingale if (startaddr == NULL) {
924154972afSPatrick Mooney EPRINTLN("smbios table requires mapped mem");
925bf21cd93STycho Nightingale return (ENOMEM);
926bf21cd93STycho Nightingale }
927bf21cd93STycho Nightingale
9284f3f3e9aSAndy Fiddaman #ifndef __FreeBSD__
9294f3f3e9aSAndy Fiddaman /* Translate legacy illumos configuration keys */
9304f3f3e9aSAndy Fiddaman for (uint_t i = 0; i < ARRAY_SIZE(smbios_legacy_config_map); i++) {
9314f3f3e9aSAndy Fiddaman const char *v;
9324f3f3e9aSAndy Fiddaman
9334f3f3e9aSAndy Fiddaman v = get_config_value(smbios_legacy_config_map[i].oldkey);
9344f3f3e9aSAndy Fiddaman if (v != NULL) {
9354f3f3e9aSAndy Fiddaman set_config_value_if_unset(
9364f3f3e9aSAndy Fiddaman smbios_legacy_config_map[i].newkey, v);
9374f3f3e9aSAndy Fiddaman }
9384f3f3e9aSAndy Fiddaman }
9394f3f3e9aSAndy Fiddaman #endif
9404f3f3e9aSAndy Fiddaman
941bf21cd93STycho Nightingale curaddr = startaddr;
942bf21cd93STycho Nightingale
943bf21cd93STycho Nightingale smbios_ep = (struct smbios_entry_point *)curaddr;
944bf21cd93STycho Nightingale smbios_ep_initializer(smbios_ep, SMBIOS_BASE +
945bf21cd93STycho Nightingale sizeof(struct smbios_entry_point));
946bf21cd93STycho Nightingale curaddr += sizeof(struct smbios_entry_point);
947bf21cd93STycho Nightingale ststartaddr = curaddr;
948bf21cd93STycho Nightingale
949bf21cd93STycho Nightingale n = 0;
950bf21cd93STycho Nightingale maxssize = 0;
951bf21cd93STycho Nightingale for (i = 0; smbios_template[i].entry != NULL; i++) {
95259d65d31SAndy Fiddaman const struct smbios_structure *entry;
95359d65d31SAndy Fiddaman const struct smbios_string *strings;
954bf21cd93STycho Nightingale initializer_func_t initializer;
955bf21cd93STycho Nightingale char *endaddr;
95659d65d31SAndy Fiddaman size_t size;
957bf21cd93STycho Nightingale
958bf21cd93STycho Nightingale entry = smbios_template[i].entry;
959bf21cd93STycho Nightingale strings = smbios_template[i].strings;
960bf21cd93STycho Nightingale initializer = smbios_template[i].initializer;
961bf21cd93STycho Nightingale
96259d65d31SAndy Fiddaman err = (*initializer)(entry, strings, curaddr, &endaddr, &n);
963bf21cd93STycho Nightingale if (err != 0)
964bf21cd93STycho Nightingale return (err);
965bf21cd93STycho Nightingale
96659d65d31SAndy Fiddaman size = endaddr - curaddr;
96759d65d31SAndy Fiddaman assert(size <= UINT16_MAX);
968bf21cd93STycho Nightingale if (size > maxssize)
96959d65d31SAndy Fiddaman maxssize = (uint16_t)size;
970bf21cd93STycho Nightingale curaddr = endaddr;
971bf21cd93STycho Nightingale }
972bf21cd93STycho Nightingale
973bf21cd93STycho Nightingale assert(curaddr - startaddr < SMBIOS_MAX_LENGTH);
974bf21cd93STycho Nightingale smbios_ep_finalizer(smbios_ep, curaddr - ststartaddr, n, maxssize);
975bf21cd93STycho Nightingale
976bf21cd93STycho Nightingale return (0);
977bf21cd93STycho Nightingale }
9784c87aefeSPatrick Mooney
9792b948146SAndy Fiddaman #ifndef __FreeBSD__
9804f3f3e9aSAndy Fiddaman static struct {
9814f3f3e9aSAndy Fiddaman uint_t type;
9822b948146SAndy Fiddaman const char *key;
9834f3f3e9aSAndy Fiddaman char *val;
9844f3f3e9aSAndy Fiddaman } smbios_legacy_map[] = {
9854f3f3e9aSAndy Fiddaman { 1, "product", "product_name" },
9864f3f3e9aSAndy Fiddaman { 1, "serial", "serial_number" },
9874f3f3e9aSAndy Fiddaman { 1, "family", "family_name" },
9882b948146SAndy Fiddaman };
9892b948146SAndy Fiddaman
99059d65d31SAndy Fiddaman static const struct smbios_string *smbios_tbl_map[] = {
9914f3f3e9aSAndy Fiddaman smbios_type0_strings,
9924f3f3e9aSAndy Fiddaman smbios_type1_strings,
9934f3f3e9aSAndy Fiddaman smbios_type2_strings,
9944f3f3e9aSAndy Fiddaman smbios_type3_strings,
9954f3f3e9aSAndy Fiddaman };
9962b948146SAndy Fiddaman
9974f3f3e9aSAndy Fiddaman /*
9984f3f3e9aSAndy Fiddaman * This function accepts an option of the form
9994f3f3e9aSAndy Fiddaman * type,[key=value][,key=value]...
10004f3f3e9aSAndy Fiddaman * and sets smbios data for the given type. Keys for type X are defined in the
10014f3f3e9aSAndy Fiddaman * smbios_typeX_strings tables above, but for type 1 there are also some
10024f3f3e9aSAndy Fiddaman * legacy values which were accepted in earlier versions of bhyve on illumos
10034f3f3e9aSAndy Fiddaman * which need to be mapped.
10044f3f3e9aSAndy Fiddaman */
10054c87aefeSPatrick Mooney int
smbios_parse(const char * opts)10064c87aefeSPatrick Mooney smbios_parse(const char *opts)
10074c87aefeSPatrick Mooney {
10084f3f3e9aSAndy Fiddaman char *buf, *lasts, *token, *typekey = NULL;
10094f3f3e9aSAndy Fiddaman const char *errstr;
101059d65d31SAndy Fiddaman const struct smbios_string *tbl;
10112b948146SAndy Fiddaman nvlist_t *nvl;
10124f3f3e9aSAndy Fiddaman uint_t i;
10134c87aefeSPatrick Mooney long type;
10144c87aefeSPatrick Mooney
10154c87aefeSPatrick Mooney if ((buf = strdup(opts)) == NULL) {
10164c87aefeSPatrick Mooney (void) fprintf(stderr, "out of memory\n");
10174c87aefeSPatrick Mooney return (-1);
10184c87aefeSPatrick Mooney }
10194c87aefeSPatrick Mooney
10204c87aefeSPatrick Mooney if ((token = strtok_r(buf, ",", &lasts)) == NULL) {
10214c87aefeSPatrick Mooney (void) fprintf(stderr, "too few fields\n");
10224c87aefeSPatrick Mooney goto fail;
10234c87aefeSPatrick Mooney }
10244c87aefeSPatrick Mooney
10254f3f3e9aSAndy Fiddaman type = strtonum(token, 0, 3, &errstr);
10264f3f3e9aSAndy Fiddaman if (errstr != NULL) {
10274f3f3e9aSAndy Fiddaman fprintf(stderr, "First token (type) is %s\n", errstr);
10284c87aefeSPatrick Mooney goto fail;
10294c87aefeSPatrick Mooney }
10304c87aefeSPatrick Mooney
10314f3f3e9aSAndy Fiddaman tbl = smbios_tbl_map[type];
10324f3f3e9aSAndy Fiddaman
10334f3f3e9aSAndy Fiddaman /* Extract the config key for this type */
10344f3f3e9aSAndy Fiddaman typekey = strdup(tbl[0].node);
10354f3f3e9aSAndy Fiddaman if (typekey == NULL) {
10364f3f3e9aSAndy Fiddaman (void) fprintf(stderr, "out of memory\n");
10374c87aefeSPatrick Mooney goto fail;
10384c87aefeSPatrick Mooney }
10394c87aefeSPatrick Mooney
10404f3f3e9aSAndy Fiddaman token = strchr(typekey, '.');
10414f3f3e9aSAndy Fiddaman assert(token != NULL);
10424f3f3e9aSAndy Fiddaman *token = '\0';
10434f3f3e9aSAndy Fiddaman
10444f3f3e9aSAndy Fiddaman nvl = create_config_node(typekey);
10452b948146SAndy Fiddaman if (nvl == NULL) {
10462b948146SAndy Fiddaman (void) fprintf(stderr, "out of memory\n");
10474f3f3e9aSAndy Fiddaman goto fail;
10482b948146SAndy Fiddaman }
10492b948146SAndy Fiddaman
10504c87aefeSPatrick Mooney while ((token = strtok_r(NULL, ",", &lasts)) != NULL) {
10514c87aefeSPatrick Mooney char *val;
10524c87aefeSPatrick Mooney
10534f3f3e9aSAndy Fiddaman if ((val = strchr(token, '=')) == NULL || val[1] == '\0') {
10544c87aefeSPatrick Mooney (void) fprintf(stderr, "invalid key=value: '%s'\n",
10554c87aefeSPatrick Mooney token);
10564c87aefeSPatrick Mooney goto fail;
10574c87aefeSPatrick Mooney }
10584f3f3e9aSAndy Fiddaman *val++ = '\0';
10594c87aefeSPatrick Mooney
10604f3f3e9aSAndy Fiddaman /* UUID is a top-level config item, but -U takes priority */
10612b948146SAndy Fiddaman if (strcmp(token, "uuid") == 0) {
10624f3f3e9aSAndy Fiddaman set_config_value_if_unset(token, val);
10632b948146SAndy Fiddaman continue;
10642b948146SAndy Fiddaman }
10652b948146SAndy Fiddaman
10664f3f3e9aSAndy Fiddaman /* Translate legacy keys */
10674f3f3e9aSAndy Fiddaman for (i = 0; i < ARRAY_SIZE(smbios_legacy_map); i++) {
10684f3f3e9aSAndy Fiddaman if (type == smbios_legacy_map[i].type &&
10694f3f3e9aSAndy Fiddaman strcmp(token, smbios_legacy_map[i].key) == 0) {
10704f3f3e9aSAndy Fiddaman token = smbios_legacy_map[i].val;
10714c87aefeSPatrick Mooney break;
10724c87aefeSPatrick Mooney }
10734c87aefeSPatrick Mooney }
10744f3f3e9aSAndy Fiddaman
10754f3f3e9aSAndy Fiddaman for (i = 0; tbl[i].value != NULL; i++) {
10764f3f3e9aSAndy Fiddaman if (strcmp(tbl[i].node + strlen(typekey) + 1,
10774f3f3e9aSAndy Fiddaman token) == 0) {
10784f3f3e9aSAndy Fiddaman /* Found match */
10794f3f3e9aSAndy Fiddaman break;
10804f3f3e9aSAndy Fiddaman }
10814f3f3e9aSAndy Fiddaman }
10824f3f3e9aSAndy Fiddaman
10834f3f3e9aSAndy Fiddaman if (tbl[i].value == NULL) {
10844f3f3e9aSAndy Fiddaman (void) fprintf(stderr,
10854f3f3e9aSAndy Fiddaman "Unknown SMBIOS key %s for type %d\n", token, type);
10864c87aefeSPatrick Mooney goto fail;
10874c87aefeSPatrick Mooney }
10884f3f3e9aSAndy Fiddaman
10892b948146SAndy Fiddaman set_config_value_node(nvl, token, val);
10904c87aefeSPatrick Mooney }
10914c87aefeSPatrick Mooney
10924f3f3e9aSAndy Fiddaman free(typekey);
10934c87aefeSPatrick Mooney return (0);
10944c87aefeSPatrick Mooney
10954c87aefeSPatrick Mooney fail:
10964c87aefeSPatrick Mooney free(buf);
10974f3f3e9aSAndy Fiddaman free(typekey);
10984c87aefeSPatrick Mooney return (-1);
10994c87aefeSPatrick Mooney }
11002b948146SAndy Fiddaman #endif
1101