1bf21cd93STycho Nightingale /*- 24c87aefeSPatrick Mooney * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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> 304c87aefeSPatrick Mooney __FBSDID("$FreeBSD$"); 31bf21cd93STycho Nightingale 32bf21cd93STycho Nightingale #include <sys/param.h> 33bf21cd93STycho Nightingale 34bf21cd93STycho Nightingale #include <assert.h> 35bf21cd93STycho Nightingale #include <errno.h> 36bf21cd93STycho Nightingale #include <md5.h> 37bf21cd93STycho Nightingale #include <stdio.h> 384c87aefeSPatrick Mooney #include <stdlib.h> 39bf21cd93STycho Nightingale #include <string.h> 40bf21cd93STycho Nightingale #include <unistd.h> 41bf21cd93STycho Nightingale #include <uuid.h> 42bf21cd93STycho Nightingale 43bf21cd93STycho Nightingale #include <machine/vmm.h> 44bf21cd93STycho Nightingale #include <vmmapi.h> 45bf21cd93STycho Nightingale 46bf21cd93STycho Nightingale #include "bhyverun.h" 472b948146SAndy Fiddaman #include "config.h" 48154972afSPatrick Mooney #include "debug.h" 49bf21cd93STycho Nightingale #include "smbiostbl.h" 50bf21cd93STycho Nightingale 51bf21cd93STycho Nightingale #define MB (1024*1024) 52bf21cd93STycho Nightingale #define GB (1024ULL*1024*1024) 53bf21cd93STycho Nightingale 54bf21cd93STycho Nightingale #define SMBIOS_BASE 0xF1000 55bf21cd93STycho Nightingale 566960cd89SAndy Fiddaman #define FIRMWARE_VERSION "13.0" 576960cd89SAndy Fiddaman /* The SMBIOS specification defines the date format to be mm/dd/yyyy */ 586960cd89SAndy Fiddaman #define FIRMWARE_RELEASE_DATE "11/10/2020" 596960cd89SAndy Fiddaman 60bf21cd93STycho Nightingale /* BHYVE_ACPI_BASE - SMBIOS_BASE) */ 61bf21cd93STycho Nightingale #define SMBIOS_MAX_LENGTH (0xF2400 - 0xF1000) 62bf21cd93STycho Nightingale 63bf21cd93STycho Nightingale #define SMBIOS_TYPE_BIOS 0 64bf21cd93STycho Nightingale #define SMBIOS_TYPE_SYSTEM 1 65b0de25cbSAndy Fiddaman #define SMBIOS_TYPE_BOARD 2 66bf21cd93STycho Nightingale #define SMBIOS_TYPE_CHASSIS 3 67bf21cd93STycho Nightingale #define SMBIOS_TYPE_PROCESSOR 4 68bf21cd93STycho Nightingale #define SMBIOS_TYPE_MEMARRAY 16 69bf21cd93STycho Nightingale #define SMBIOS_TYPE_MEMDEVICE 17 70bf21cd93STycho Nightingale #define SMBIOS_TYPE_MEMARRAYMAP 19 71bf21cd93STycho Nightingale #define SMBIOS_TYPE_BOOT 32 72bf21cd93STycho Nightingale #define SMBIOS_TYPE_EOT 127 73bf21cd93STycho Nightingale 74bf21cd93STycho Nightingale struct smbios_structure { 75bf21cd93STycho Nightingale uint8_t type; 76bf21cd93STycho Nightingale uint8_t length; 77bf21cd93STycho Nightingale uint16_t handle; 78bf21cd93STycho Nightingale } __packed; 79bf21cd93STycho Nightingale 80bf21cd93STycho Nightingale typedef int (*initializer_func_t)(struct smbios_structure *template_entry, 81bf21cd93STycho Nightingale const char **template_strings, char *curaddr, char **endaddr, 82bf21cd93STycho Nightingale uint16_t *n, uint16_t *size); 83bf21cd93STycho Nightingale 84bf21cd93STycho Nightingale struct smbios_template_entry { 85bf21cd93STycho Nightingale struct smbios_structure *entry; 86bf21cd93STycho Nightingale const char **strings; 87bf21cd93STycho Nightingale initializer_func_t initializer; 88bf21cd93STycho Nightingale }; 89bf21cd93STycho Nightingale 90bf21cd93STycho Nightingale /* 91bf21cd93STycho Nightingale * SMBIOS Structure Table Entry Point 92bf21cd93STycho Nightingale */ 93bf21cd93STycho Nightingale #define SMBIOS_ENTRY_EANCHOR "_SM_" 94bf21cd93STycho Nightingale #define SMBIOS_ENTRY_EANCHORLEN 4 95bf21cd93STycho Nightingale #define SMBIOS_ENTRY_IANCHOR "_DMI_" 96bf21cd93STycho Nightingale #define SMBIOS_ENTRY_IANCHORLEN 5 97bf21cd93STycho Nightingale 98bf21cd93STycho Nightingale struct smbios_entry_point { 99bf21cd93STycho Nightingale char eanchor[4]; /* anchor tag */ 100bf21cd93STycho Nightingale uint8_t echecksum; /* checksum of entry point structure */ 101bf21cd93STycho Nightingale uint8_t eplen; /* length in bytes of entry point */ 102bf21cd93STycho Nightingale uint8_t major; /* major version of the SMBIOS spec */ 103bf21cd93STycho Nightingale uint8_t minor; /* minor version of the SMBIOS spec */ 104bf21cd93STycho Nightingale uint16_t maxssize; /* maximum size in bytes of a struct */ 105bf21cd93STycho Nightingale uint8_t revision; /* entry point structure revision */ 106bf21cd93STycho Nightingale uint8_t format[5]; /* entry point rev-specific data */ 107bf21cd93STycho Nightingale char ianchor[5]; /* intermediate anchor tag */ 108bf21cd93STycho Nightingale uint8_t ichecksum; /* intermediate checksum */ 109bf21cd93STycho Nightingale uint16_t stlen; /* len in bytes of structure table */ 110bf21cd93STycho Nightingale uint32_t staddr; /* physical addr of structure table */ 111bf21cd93STycho Nightingale uint16_t stnum; /* number of structure table entries */ 112bf21cd93STycho Nightingale uint8_t bcdrev; /* BCD value representing DMI ver */ 113bf21cd93STycho Nightingale } __packed; 114bf21cd93STycho Nightingale 115bf21cd93STycho Nightingale /* 116bf21cd93STycho Nightingale * BIOS Information 117bf21cd93STycho Nightingale */ 118bf21cd93STycho Nightingale #define SMBIOS_FL_ISA 0x00000010 /* ISA is supported */ 119bf21cd93STycho Nightingale #define SMBIOS_FL_PCI 0x00000080 /* PCI is supported */ 120bf21cd93STycho Nightingale #define SMBIOS_FL_SHADOW 0x00001000 /* BIOS shadowing is allowed */ 121bf21cd93STycho Nightingale #define SMBIOS_FL_CDBOOT 0x00008000 /* Boot from CD is supported */ 122bf21cd93STycho Nightingale #define SMBIOS_FL_SELBOOT 0x00010000 /* Selectable Boot supported */ 123bf21cd93STycho Nightingale #define SMBIOS_FL_EDD 0x00080000 /* EDD Spec is supported */ 124bf21cd93STycho Nightingale 125bf21cd93STycho Nightingale #define SMBIOS_XB1_FL_ACPI 0x00000001 /* ACPI is supported */ 126bf21cd93STycho Nightingale 127bf21cd93STycho Nightingale #define SMBIOS_XB2_FL_BBS 0x00000001 /* BIOS Boot Specification */ 128bf21cd93STycho Nightingale #define SMBIOS_XB2_FL_VM 0x00000010 /* Virtual Machine */ 129bf21cd93STycho Nightingale 130bf21cd93STycho Nightingale struct smbios_table_type0 { 131bf21cd93STycho Nightingale struct smbios_structure header; 132bf21cd93STycho Nightingale uint8_t vendor; /* vendor string */ 133bf21cd93STycho Nightingale uint8_t version; /* version string */ 134bf21cd93STycho Nightingale uint16_t segment; /* address segment location */ 135bf21cd93STycho Nightingale uint8_t rel_date; /* release date */ 136bf21cd93STycho Nightingale uint8_t size; /* rom size */ 137bf21cd93STycho Nightingale uint64_t cflags; /* characteristics */ 138bf21cd93STycho Nightingale uint8_t xc_bytes[2]; /* characteristics ext bytes */ 139bf21cd93STycho Nightingale uint8_t sb_major_rel; /* system bios version */ 140bf21cd93STycho Nightingale uint8_t sb_minor_rele; 141bf21cd93STycho Nightingale uint8_t ecfw_major_rel; /* embedded ctrl fw version */ 142bf21cd93STycho Nightingale uint8_t ecfw_minor_rel; 143bf21cd93STycho Nightingale } __packed; 144bf21cd93STycho Nightingale 145bf21cd93STycho Nightingale /* 146bf21cd93STycho Nightingale * System Information 147bf21cd93STycho Nightingale */ 148bf21cd93STycho Nightingale #define SMBIOS_WAKEUP_SWITCH 0x06 /* power switch */ 149bf21cd93STycho Nightingale 150bf21cd93STycho Nightingale struct smbios_table_type1 { 151bf21cd93STycho Nightingale struct smbios_structure header; 152bf21cd93STycho Nightingale uint8_t manufacturer; /* manufacturer string */ 153bf21cd93STycho Nightingale uint8_t product; /* product name string */ 154bf21cd93STycho Nightingale uint8_t version; /* version string */ 155bf21cd93STycho Nightingale uint8_t serial; /* serial number string */ 156bf21cd93STycho Nightingale uint8_t uuid[16]; /* uuid byte array */ 157bf21cd93STycho Nightingale uint8_t wakeup; /* wake-up event */ 158bf21cd93STycho Nightingale uint8_t sku; /* sku number string */ 159bf21cd93STycho Nightingale uint8_t family; /* family name string */ 160bf21cd93STycho Nightingale } __packed; 161bf21cd93STycho Nightingale 162b0de25cbSAndy Fiddaman /* 163b0de25cbSAndy Fiddaman * Baseboard (or Module) Information 164b0de25cbSAndy Fiddaman */ 165b0de25cbSAndy Fiddaman #define SMBIOS_BRF_HOSTING 0x1 166b0de25cbSAndy Fiddaman #define SMBIOS_BRT_MOTHERBOARD 0xa 167b0de25cbSAndy Fiddaman 168b0de25cbSAndy Fiddaman struct smbios_table_type2 { 169b0de25cbSAndy Fiddaman struct smbios_structure header; 170b0de25cbSAndy Fiddaman uint8_t manufacturer; /* manufacturer string */ 171b0de25cbSAndy Fiddaman uint8_t product; /* product name string */ 172b0de25cbSAndy Fiddaman uint8_t version; /* version string */ 173b0de25cbSAndy Fiddaman uint8_t serial; /* serial number string */ 174b0de25cbSAndy Fiddaman uint8_t asset; /* asset tag string */ 175b0de25cbSAndy Fiddaman uint8_t fflags; /* feature flags */ 176b0de25cbSAndy Fiddaman uint8_t location; /* location in chassis */ 177b0de25cbSAndy Fiddaman uint16_t chandle; /* chassis handle */ 178b0de25cbSAndy Fiddaman uint8_t type; /* board type */ 179b0de25cbSAndy Fiddaman uint8_t n_objs; /* number of contained object handles */ 180b0de25cbSAndy Fiddaman } __packed; 181b0de25cbSAndy Fiddaman 182bf21cd93STycho Nightingale /* 183bf21cd93STycho Nightingale * System Enclosure or Chassis 184bf21cd93STycho Nightingale */ 185bf21cd93STycho Nightingale #define SMBIOS_CHT_UNKNOWN 0x02 /* unknown */ 186b0de25cbSAndy Fiddaman #define SMBIOS_CHT_DESKTOP 0x03 /* desktop */ 187bf21cd93STycho Nightingale 188bf21cd93STycho Nightingale #define SMBIOS_CHST_SAFE 0x03 /* safe */ 189bf21cd93STycho Nightingale 190bf21cd93STycho Nightingale #define SMBIOS_CHSC_NONE 0x03 /* none */ 191bf21cd93STycho Nightingale 192bf21cd93STycho Nightingale struct smbios_table_type3 { 193bf21cd93STycho Nightingale struct smbios_structure header; 194bf21cd93STycho Nightingale uint8_t manufacturer; /* manufacturer string */ 195bf21cd93STycho Nightingale uint8_t type; /* type */ 196bf21cd93STycho Nightingale uint8_t version; /* version string */ 197bf21cd93STycho Nightingale uint8_t serial; /* serial number string */ 198bf21cd93STycho Nightingale uint8_t asset; /* asset tag string */ 199bf21cd93STycho Nightingale uint8_t bustate; /* boot-up state */ 200bf21cd93STycho Nightingale uint8_t psstate; /* power supply state */ 201bf21cd93STycho Nightingale uint8_t tstate; /* thermal state */ 202bf21cd93STycho Nightingale uint8_t security; /* security status */ 203*058c1d46SRobert Mustacchi uint32_t oemdata; /* OEM-specific data */ 204bf21cd93STycho Nightingale uint8_t uheight; /* height in 'u's */ 205bf21cd93STycho Nightingale uint8_t cords; /* number of power cords */ 206bf21cd93STycho Nightingale uint8_t elems; /* number of element records */ 207bf21cd93STycho Nightingale uint8_t elemlen; /* length of records */ 208bf21cd93STycho Nightingale uint8_t sku; /* sku number string */ 209bf21cd93STycho Nightingale } __packed; 210bf21cd93STycho Nightingale 211bf21cd93STycho Nightingale /* 212bf21cd93STycho Nightingale * Processor Information 213bf21cd93STycho Nightingale */ 214bf21cd93STycho Nightingale #define SMBIOS_PRT_CENTRAL 0x03 /* central processor */ 215bf21cd93STycho Nightingale 216bf21cd93STycho Nightingale #define SMBIOS_PRF_OTHER 0x01 /* other */ 217bf21cd93STycho Nightingale 218bf21cd93STycho Nightingale #define SMBIOS_PRS_PRESENT 0x40 /* socket is populated */ 219bf21cd93STycho Nightingale #define SMBIOS_PRS_ENABLED 0x1 /* enabled */ 220bf21cd93STycho Nightingale 221bf21cd93STycho Nightingale #define SMBIOS_PRU_NONE 0x06 /* none */ 222bf21cd93STycho Nightingale 223bf21cd93STycho Nightingale #define SMBIOS_PFL_64B 0x04 /* 64-bit capable */ 224bf21cd93STycho Nightingale 225bf21cd93STycho Nightingale struct smbios_table_type4 { 226bf21cd93STycho Nightingale struct smbios_structure header; 227bf21cd93STycho Nightingale uint8_t socket; /* socket designation string */ 228bf21cd93STycho Nightingale uint8_t type; /* processor type */ 229bf21cd93STycho Nightingale uint8_t family; /* processor family */ 230bf21cd93STycho Nightingale uint8_t manufacturer; /* manufacturer string */ 231bf21cd93STycho Nightingale uint64_t cpuid; /* processor cpuid */ 232bf21cd93STycho Nightingale uint8_t version; /* version string */ 233bf21cd93STycho Nightingale uint8_t voltage; /* voltage */ 234bf21cd93STycho Nightingale uint16_t clkspeed; /* ext clock speed in mhz */ 235bf21cd93STycho Nightingale uint16_t maxspeed; /* maximum speed in mhz */ 236bf21cd93STycho Nightingale uint16_t curspeed; /* current speed in mhz */ 237bf21cd93STycho Nightingale uint8_t status; /* status */ 238bf21cd93STycho Nightingale uint8_t upgrade; /* upgrade */ 239bf21cd93STycho Nightingale uint16_t l1handle; /* l1 cache handle */ 240bf21cd93STycho Nightingale uint16_t l2handle; /* l2 cache handle */ 241bf21cd93STycho Nightingale uint16_t l3handle; /* l3 cache handle */ 242bf21cd93STycho Nightingale uint8_t serial; /* serial number string */ 243bf21cd93STycho Nightingale uint8_t asset; /* asset tag string */ 244bf21cd93STycho Nightingale uint8_t part; /* part number string */ 245bf21cd93STycho Nightingale uint8_t cores; /* cores per socket */ 246bf21cd93STycho Nightingale uint8_t ecores; /* enabled cores */ 247bf21cd93STycho Nightingale uint8_t threads; /* threads per socket */ 248bf21cd93STycho Nightingale uint16_t cflags; /* processor characteristics */ 249bf21cd93STycho Nightingale uint16_t family2; /* processor family 2 */ 250bf21cd93STycho Nightingale } __packed; 251bf21cd93STycho Nightingale 252bf21cd93STycho Nightingale /* 253bf21cd93STycho Nightingale * Physical Memory Array 254bf21cd93STycho Nightingale */ 255bf21cd93STycho Nightingale #define SMBIOS_MAL_SYSMB 0x03 /* system board or motherboard */ 256bf21cd93STycho Nightingale 257bf21cd93STycho Nightingale #define SMBIOS_MAU_SYSTEM 0x03 /* system memory */ 258bf21cd93STycho Nightingale 259bf21cd93STycho Nightingale #define SMBIOS_MAE_NONE 0x03 /* none */ 260bf21cd93STycho Nightingale 261bf21cd93STycho Nightingale struct smbios_table_type16 { 262bf21cd93STycho Nightingale struct smbios_structure header; 263bf21cd93STycho Nightingale uint8_t location; /* physical device location */ 264bf21cd93STycho Nightingale uint8_t use; /* device functional purpose */ 265bf21cd93STycho Nightingale uint8_t ecc; /* err detect/correct method */ 266bf21cd93STycho Nightingale uint32_t size; /* max mem capacity in kb */ 267bf21cd93STycho Nightingale uint16_t errhand; /* handle of error (if any) */ 268bf21cd93STycho Nightingale uint16_t ndevs; /* num of slots or sockets */ 269bf21cd93STycho Nightingale uint64_t xsize; /* max mem capacity in bytes */ 270bf21cd93STycho Nightingale } __packed; 271bf21cd93STycho Nightingale 272bf21cd93STycho Nightingale /* 273bf21cd93STycho Nightingale * Memory Device 274bf21cd93STycho Nightingale */ 275bf21cd93STycho Nightingale #define SMBIOS_MDFF_UNKNOWN 0x02 /* unknown */ 276bf21cd93STycho Nightingale 277bf21cd93STycho Nightingale #define SMBIOS_MDT_UNKNOWN 0x02 /* unknown */ 278bf21cd93STycho Nightingale 279bf21cd93STycho Nightingale #define SMBIOS_MDF_UNKNOWN 0x0004 /* unknown */ 280bf21cd93STycho Nightingale 281bf21cd93STycho Nightingale struct smbios_table_type17 { 282bf21cd93STycho Nightingale struct smbios_structure header; 283bf21cd93STycho Nightingale uint16_t arrayhand; /* handle of physl mem array */ 284bf21cd93STycho Nightingale uint16_t errhand; /* handle of mem error data */ 285bf21cd93STycho Nightingale uint16_t twidth; /* total width in bits */ 286bf21cd93STycho Nightingale uint16_t dwidth; /* data width in bits */ 287154972afSPatrick Mooney uint16_t size; /* size in kb or mb */ 288bf21cd93STycho Nightingale uint8_t form; /* form factor */ 289bf21cd93STycho Nightingale uint8_t set; /* set */ 290bf21cd93STycho Nightingale uint8_t dloc; /* device locator string */ 291bf21cd93STycho Nightingale uint8_t bloc; /* phys bank locator string */ 292bf21cd93STycho Nightingale uint8_t type; /* memory type */ 293bf21cd93STycho Nightingale uint16_t flags; /* memory characteristics */ 294bf21cd93STycho Nightingale uint16_t maxspeed; /* maximum speed in mhz */ 295bf21cd93STycho Nightingale uint8_t manufacturer; /* manufacturer string */ 296bf21cd93STycho Nightingale uint8_t serial; /* serial number string */ 297bf21cd93STycho Nightingale uint8_t asset; /* asset tag string */ 298bf21cd93STycho Nightingale uint8_t part; /* part number string */ 299bf21cd93STycho Nightingale uint8_t attributes; /* attributes */ 300154972afSPatrick Mooney uint32_t xsize; /* extended size in mb */ 301bf21cd93STycho Nightingale uint16_t curspeed; /* current speed in mhz */ 302bf21cd93STycho Nightingale uint16_t minvoltage; /* minimum voltage */ 303bf21cd93STycho Nightingale uint16_t maxvoltage; /* maximum voltage */ 304bf21cd93STycho Nightingale uint16_t curvoltage; /* configured voltage */ 305bf21cd93STycho Nightingale } __packed; 306bf21cd93STycho Nightingale 307bf21cd93STycho Nightingale /* 308bf21cd93STycho Nightingale * Memory Array Mapped Address 309bf21cd93STycho Nightingale */ 310bf21cd93STycho Nightingale struct smbios_table_type19 { 311bf21cd93STycho Nightingale struct smbios_structure header; 312bf21cd93STycho Nightingale uint32_t saddr; /* start phys addr in kb */ 313bf21cd93STycho Nightingale uint32_t eaddr; /* end phys addr in kb */ 314bf21cd93STycho Nightingale uint16_t arrayhand; /* physical mem array handle */ 315bf21cd93STycho Nightingale uint8_t width; /* num of dev in row */ 316bf21cd93STycho Nightingale uint64_t xsaddr; /* start phys addr in bytes */ 317bf21cd93STycho Nightingale uint64_t xeaddr; /* end phys addr in bytes */ 318bf21cd93STycho Nightingale } __packed; 319bf21cd93STycho Nightingale 320bf21cd93STycho Nightingale /* 321bf21cd93STycho Nightingale * System Boot Information 322bf21cd93STycho Nightingale */ 323bf21cd93STycho Nightingale #define SMBIOS_BOOT_NORMAL 0 /* no errors detected */ 324bf21cd93STycho Nightingale 325bf21cd93STycho Nightingale struct smbios_table_type32 { 326bf21cd93STycho Nightingale struct smbios_structure header; 327bf21cd93STycho Nightingale uint8_t reserved[6]; 328bf21cd93STycho Nightingale uint8_t status; /* boot status */ 329bf21cd93STycho Nightingale } __packed; 330bf21cd93STycho Nightingale 331bf21cd93STycho Nightingale /* 332bf21cd93STycho Nightingale * End-of-Table 333bf21cd93STycho Nightingale */ 334bf21cd93STycho Nightingale struct smbios_table_type127 { 335bf21cd93STycho Nightingale struct smbios_structure header; 336bf21cd93STycho Nightingale } __packed; 337bf21cd93STycho Nightingale 338bf21cd93STycho Nightingale struct smbios_table_type0 smbios_type0_template = { 339bf21cd93STycho Nightingale { SMBIOS_TYPE_BIOS, sizeof (struct smbios_table_type0), 0 }, 340bf21cd93STycho Nightingale 1, /* bios vendor string */ 341bf21cd93STycho Nightingale 2, /* bios version string */ 342bf21cd93STycho Nightingale 0xF000, /* bios address segment location */ 343bf21cd93STycho Nightingale 3, /* bios release date */ 344bf21cd93STycho Nightingale 0x0, /* bios size (64k * (n + 1) is the size in bytes) */ 345bf21cd93STycho Nightingale SMBIOS_FL_ISA | SMBIOS_FL_PCI | SMBIOS_FL_SHADOW | 346bf21cd93STycho Nightingale SMBIOS_FL_CDBOOT | SMBIOS_FL_EDD, 347bf21cd93STycho Nightingale { SMBIOS_XB1_FL_ACPI, SMBIOS_XB2_FL_BBS | SMBIOS_XB2_FL_VM }, 348bf21cd93STycho Nightingale 0x0, /* bios major release */ 349bf21cd93STycho Nightingale 0x0, /* bios minor release */ 350bf21cd93STycho Nightingale 0xff, /* embedded controller firmware major release */ 351bf21cd93STycho Nightingale 0xff /* embedded controller firmware minor release */ 352bf21cd93STycho Nightingale }; 353bf21cd93STycho Nightingale 354bf21cd93STycho Nightingale const char *smbios_type0_strings[] = { 3556960cd89SAndy Fiddaman "BHYVE", /* vendor string */ 3566960cd89SAndy Fiddaman FIRMWARE_VERSION, /* bios version string */ 3576960cd89SAndy Fiddaman FIRMWARE_RELEASE_DATE, /* bios release date string */ 358bf21cd93STycho Nightingale NULL 359bf21cd93STycho Nightingale }; 360bf21cd93STycho Nightingale 361bf21cd93STycho Nightingale struct smbios_table_type1 smbios_type1_template = { 362bf21cd93STycho Nightingale { SMBIOS_TYPE_SYSTEM, sizeof (struct smbios_table_type1), 0 }, 363bf21cd93STycho Nightingale 1, /* manufacturer string */ 364bf21cd93STycho Nightingale 2, /* product string */ 365bf21cd93STycho Nightingale 3, /* version string */ 366bf21cd93STycho Nightingale 4, /* serial number string */ 367bf21cd93STycho Nightingale { 0 }, 368bf21cd93STycho Nightingale SMBIOS_WAKEUP_SWITCH, 369bf21cd93STycho Nightingale 5, /* sku string */ 370bf21cd93STycho Nightingale 6 /* family string */ 371bf21cd93STycho Nightingale }; 372bf21cd93STycho Nightingale 373bf21cd93STycho Nightingale static int smbios_type1_initializer(struct smbios_structure *template_entry, 374bf21cd93STycho Nightingale const char **template_strings, char *curaddr, char **endaddr, 375bf21cd93STycho Nightingale uint16_t *n, uint16_t *size); 376bf21cd93STycho Nightingale 377bf21cd93STycho Nightingale const char *smbios_type1_strings[] = { 3786960cd89SAndy Fiddaman "illumos", /* manufacturer string */ 3796960cd89SAndy Fiddaman "BHYVE", /* product name string */ 3806960cd89SAndy Fiddaman "1.0", /* version string */ 3816960cd89SAndy Fiddaman "None", /* serial number string */ 3826960cd89SAndy Fiddaman "None", /* sku string */ 3836960cd89SAndy Fiddaman "Virtual Machine", /* family name string */ 384bf21cd93STycho Nightingale NULL 385bf21cd93STycho Nightingale }; 386bf21cd93STycho Nightingale 387b0de25cbSAndy Fiddaman struct smbios_table_type2 smbios_type2_template = { 388b0de25cbSAndy Fiddaman { SMBIOS_TYPE_BOARD, sizeof (struct smbios_table_type2), 0 }, 389b0de25cbSAndy Fiddaman 1, /* manufacturer string */ 390b0de25cbSAndy Fiddaman 2, /* product string */ 391b0de25cbSAndy Fiddaman 3, /* version string */ 392b0de25cbSAndy Fiddaman 4, /* serial number string */ 393b0de25cbSAndy Fiddaman 5, /* asset tag string */ 394b0de25cbSAndy Fiddaman SMBIOS_BRF_HOSTING, /* feature flags */ 395b0de25cbSAndy Fiddaman 6, /* location string */ 396b0de25cbSAndy Fiddaman SMBIOS_CHT_DESKTOP, /* chassis handle */ 397b0de25cbSAndy Fiddaman SMBIOS_BRT_MOTHERBOARD, /* board type */ 398b0de25cbSAndy Fiddaman 0 399b0de25cbSAndy Fiddaman }; 400b0de25cbSAndy Fiddaman 401b0de25cbSAndy Fiddaman const char *smbios_type2_strings[] = { 402b0de25cbSAndy Fiddaman "illumos", /* manufacturer string */ 403b0de25cbSAndy Fiddaman "BHYVE", /* product name string */ 404b0de25cbSAndy Fiddaman "1.0", /* version string */ 405b0de25cbSAndy Fiddaman "None", /* serial number string */ 406b0de25cbSAndy Fiddaman "None", /* asset tag string */ 407b0de25cbSAndy Fiddaman "None", /* location string */ 408b0de25cbSAndy Fiddaman NULL 409b0de25cbSAndy Fiddaman }; 410b0de25cbSAndy Fiddaman 411bf21cd93STycho Nightingale struct smbios_table_type3 smbios_type3_template = { 412bf21cd93STycho Nightingale { SMBIOS_TYPE_CHASSIS, sizeof (struct smbios_table_type3), 0 }, 413bf21cd93STycho Nightingale 1, /* manufacturer string */ 414bf21cd93STycho Nightingale SMBIOS_CHT_UNKNOWN, 415bf21cd93STycho Nightingale 2, /* version string */ 416bf21cd93STycho Nightingale 3, /* serial number string */ 417bf21cd93STycho Nightingale 4, /* asset tag string */ 418bf21cd93STycho Nightingale SMBIOS_CHST_SAFE, 419bf21cd93STycho Nightingale SMBIOS_CHST_SAFE, 420bf21cd93STycho Nightingale SMBIOS_CHST_SAFE, 421bf21cd93STycho Nightingale SMBIOS_CHSC_NONE, 422*058c1d46SRobert Mustacchi 0, /* OEM specific data, we have none */ 423bf21cd93STycho Nightingale 0, /* height in 'u's (0=enclosure height unspecified) */ 424bf21cd93STycho Nightingale 0, /* number of power cords (0=number unspecified) */ 425bf21cd93STycho Nightingale 0, /* number of contained element records */ 426bf21cd93STycho Nightingale 0, /* length of records */ 427bf21cd93STycho Nightingale 5 /* sku number string */ 428bf21cd93STycho Nightingale }; 429bf21cd93STycho Nightingale 430bf21cd93STycho Nightingale const char *smbios_type3_strings[] = { 4316960cd89SAndy Fiddaman "illumos", /* manufacturer string */ 432bf21cd93STycho Nightingale "1.0", /* version string */ 433bf21cd93STycho Nightingale "None", /* serial number string */ 434bf21cd93STycho Nightingale "None", /* asset tag string */ 435bf21cd93STycho Nightingale "None", /* sku number string */ 436bf21cd93STycho Nightingale NULL 437bf21cd93STycho Nightingale }; 438bf21cd93STycho Nightingale 439bf21cd93STycho Nightingale struct smbios_table_type4 smbios_type4_template = { 440bf21cd93STycho Nightingale { SMBIOS_TYPE_PROCESSOR, sizeof (struct smbios_table_type4), 0 }, 441bf21cd93STycho Nightingale 1, /* socket designation string */ 442bf21cd93STycho Nightingale SMBIOS_PRT_CENTRAL, 443bf21cd93STycho Nightingale SMBIOS_PRF_OTHER, 444bf21cd93STycho Nightingale 2, /* manufacturer string */ 445bf21cd93STycho Nightingale 0, /* cpuid */ 446bf21cd93STycho Nightingale 3, /* version string */ 447bf21cd93STycho Nightingale 0, /* voltage */ 448bf21cd93STycho Nightingale 0, /* external clock frequency in mhz (0=unknown) */ 449bf21cd93STycho Nightingale 0, /* maximum frequency in mhz (0=unknown) */ 450bf21cd93STycho Nightingale 0, /* current frequency in mhz (0=unknown) */ 451bf21cd93STycho Nightingale SMBIOS_PRS_PRESENT | SMBIOS_PRS_ENABLED, 452bf21cd93STycho Nightingale SMBIOS_PRU_NONE, 453bf21cd93STycho Nightingale -1, /* l1 cache handle */ 454bf21cd93STycho Nightingale -1, /* l2 cache handle */ 455bf21cd93STycho Nightingale -1, /* l3 cache handle */ 456bf21cd93STycho Nightingale 4, /* serial number string */ 457bf21cd93STycho Nightingale 5, /* asset tag string */ 458bf21cd93STycho Nightingale 6, /* part number string */ 459bf21cd93STycho Nightingale 0, /* cores per socket (0=unknown) */ 460bf21cd93STycho Nightingale 0, /* enabled cores per socket (0=unknown) */ 461bf21cd93STycho Nightingale 0, /* threads per socket (0=unknown) */ 462bf21cd93STycho Nightingale SMBIOS_PFL_64B, 463bf21cd93STycho Nightingale SMBIOS_PRF_OTHER 464bf21cd93STycho Nightingale }; 465bf21cd93STycho Nightingale 466bf21cd93STycho Nightingale const char *smbios_type4_strings[] = { 467bf21cd93STycho Nightingale " ", /* socket designation string */ 468bf21cd93STycho Nightingale " ", /* manufacturer string */ 469bf21cd93STycho Nightingale " ", /* version string */ 470bf21cd93STycho Nightingale "None", /* serial number string */ 471bf21cd93STycho Nightingale "None", /* asset tag string */ 472bf21cd93STycho Nightingale "None", /* part number string */ 473bf21cd93STycho Nightingale NULL 474bf21cd93STycho Nightingale }; 475bf21cd93STycho Nightingale 476bf21cd93STycho Nightingale static int smbios_type4_initializer(struct smbios_structure *template_entry, 477bf21cd93STycho Nightingale const char **template_strings, char *curaddr, char **endaddr, 478bf21cd93STycho Nightingale uint16_t *n, uint16_t *size); 479bf21cd93STycho Nightingale 480bf21cd93STycho Nightingale struct smbios_table_type16 smbios_type16_template = { 481bf21cd93STycho Nightingale { SMBIOS_TYPE_MEMARRAY, sizeof (struct smbios_table_type16), 0 }, 482bf21cd93STycho Nightingale SMBIOS_MAL_SYSMB, 483bf21cd93STycho Nightingale SMBIOS_MAU_SYSTEM, 484bf21cd93STycho Nightingale SMBIOS_MAE_NONE, 485bf21cd93STycho Nightingale 0x80000000, /* max mem capacity in kb (0x80000000=use extended) */ 486bf21cd93STycho Nightingale -1, /* handle of error (if any) */ 487bf21cd93STycho Nightingale 0, /* number of slots or sockets (TBD) */ 488bf21cd93STycho Nightingale 0 /* extended maximum memory capacity in bytes (TBD) */ 489bf21cd93STycho Nightingale }; 490bf21cd93STycho Nightingale 491bf21cd93STycho Nightingale static int smbios_type16_initializer(struct smbios_structure *template_entry, 492bf21cd93STycho Nightingale const char **template_strings, char *curaddr, char **endaddr, 493bf21cd93STycho Nightingale uint16_t *n, uint16_t *size); 494bf21cd93STycho Nightingale 495bf21cd93STycho Nightingale struct smbios_table_type17 smbios_type17_template = { 496bf21cd93STycho Nightingale { SMBIOS_TYPE_MEMDEVICE, sizeof (struct smbios_table_type17), 0 }, 497bf21cd93STycho Nightingale -1, /* handle of physical memory array */ 498bf21cd93STycho Nightingale -1, /* handle of memory error data */ 499bf21cd93STycho Nightingale 64, /* total width in bits including ecc */ 500bf21cd93STycho Nightingale 64, /* data width in bits */ 501154972afSPatrick Mooney 0, /* size in kb or mb (0x7fff=use extended)*/ 502bf21cd93STycho Nightingale SMBIOS_MDFF_UNKNOWN, 503bf21cd93STycho Nightingale 0, /* set (0x00=none, 0xff=unknown) */ 504bf21cd93STycho Nightingale 1, /* device locator string */ 505bf21cd93STycho Nightingale 2, /* physical bank locator string */ 506bf21cd93STycho Nightingale SMBIOS_MDT_UNKNOWN, 507bf21cd93STycho Nightingale SMBIOS_MDF_UNKNOWN, 508bf21cd93STycho Nightingale 0, /* maximum memory speed in mhz (0=unknown) */ 509bf21cd93STycho Nightingale 3, /* manufacturer string */ 510bf21cd93STycho Nightingale 4, /* serial number string */ 511bf21cd93STycho Nightingale 5, /* asset tag string */ 512bf21cd93STycho Nightingale 6, /* part number string */ 513bf21cd93STycho Nightingale 0, /* attributes (0=unknown rank information) */ 514bf21cd93STycho Nightingale 0, /* extended size in mb (TBD) */ 515bf21cd93STycho Nightingale 0, /* current speed in mhz (0=unknown) */ 516bf21cd93STycho Nightingale 0, /* minimum voltage in mv (0=unknown) */ 517bf21cd93STycho Nightingale 0, /* maximum voltage in mv (0=unknown) */ 518bf21cd93STycho Nightingale 0 /* configured voltage in mv (0=unknown) */ 519bf21cd93STycho Nightingale }; 520bf21cd93STycho Nightingale 521bf21cd93STycho Nightingale const char *smbios_type17_strings[] = { 522bf21cd93STycho Nightingale " ", /* device locator string */ 523bf21cd93STycho Nightingale " ", /* physical bank locator string */ 524bf21cd93STycho Nightingale " ", /* manufacturer string */ 525bf21cd93STycho Nightingale "None", /* serial number string */ 526bf21cd93STycho Nightingale "None", /* asset tag string */ 527bf21cd93STycho Nightingale "None", /* part number string */ 528bf21cd93STycho Nightingale NULL 529bf21cd93STycho Nightingale }; 530bf21cd93STycho Nightingale 531bf21cd93STycho Nightingale static int smbios_type17_initializer(struct smbios_structure *template_entry, 532bf21cd93STycho Nightingale const char **template_strings, char *curaddr, char **endaddr, 533bf21cd93STycho Nightingale uint16_t *n, uint16_t *size); 534bf21cd93STycho Nightingale 535bf21cd93STycho Nightingale struct smbios_table_type19 smbios_type19_template = { 536bf21cd93STycho Nightingale { SMBIOS_TYPE_MEMARRAYMAP, sizeof (struct smbios_table_type19), 0 }, 537bf21cd93STycho Nightingale 0xffffffff, /* starting phys addr in kb (0xffffffff=use ext) */ 538bf21cd93STycho Nightingale 0xffffffff, /* ending phys addr in kb (0xffffffff=use ext) */ 539bf21cd93STycho Nightingale -1, /* physical memory array handle */ 540bf21cd93STycho Nightingale 1, /* number of devices that form a row */ 541bf21cd93STycho Nightingale 0, /* extended starting phys addr in bytes (TDB) */ 542bf21cd93STycho Nightingale 0 /* extended ending phys addr in bytes (TDB) */ 543bf21cd93STycho Nightingale }; 544bf21cd93STycho Nightingale 545bf21cd93STycho Nightingale static int smbios_type19_initializer(struct smbios_structure *template_entry, 546bf21cd93STycho Nightingale const char **template_strings, char *curaddr, char **endaddr, 547bf21cd93STycho Nightingale uint16_t *n, uint16_t *size); 548bf21cd93STycho Nightingale 549bf21cd93STycho Nightingale struct smbios_table_type32 smbios_type32_template = { 550bf21cd93STycho Nightingale { SMBIOS_TYPE_BOOT, sizeof (struct smbios_table_type32), 0 }, 551bf21cd93STycho Nightingale { 0, 0, 0, 0, 0, 0 }, 552bf21cd93STycho Nightingale SMBIOS_BOOT_NORMAL 553bf21cd93STycho Nightingale }; 554bf21cd93STycho Nightingale 555bf21cd93STycho Nightingale struct smbios_table_type127 smbios_type127_template = { 556bf21cd93STycho Nightingale { SMBIOS_TYPE_EOT, sizeof (struct smbios_table_type127), 0 } 557bf21cd93STycho Nightingale }; 558bf21cd93STycho Nightingale 559bf21cd93STycho Nightingale static int smbios_generic_initializer(struct smbios_structure *template_entry, 560bf21cd93STycho Nightingale const char **template_strings, char *curaddr, char **endaddr, 561bf21cd93STycho Nightingale uint16_t *n, uint16_t *size); 562bf21cd93STycho Nightingale 563bf21cd93STycho Nightingale static struct smbios_template_entry smbios_template[] = { 564bf21cd93STycho Nightingale { (struct smbios_structure *)&smbios_type0_template, 565bf21cd93STycho Nightingale smbios_type0_strings, 566bf21cd93STycho Nightingale smbios_generic_initializer }, 567bf21cd93STycho Nightingale { (struct smbios_structure *)&smbios_type1_template, 568bf21cd93STycho Nightingale smbios_type1_strings, 569bf21cd93STycho Nightingale smbios_type1_initializer }, 570b0de25cbSAndy Fiddaman { (struct smbios_structure *)&smbios_type2_template, 571b0de25cbSAndy Fiddaman smbios_type2_strings, 572b0de25cbSAndy Fiddaman smbios_generic_initializer }, 573bf21cd93STycho Nightingale { (struct smbios_structure *)&smbios_type3_template, 574bf21cd93STycho Nightingale smbios_type3_strings, 575bf21cd93STycho Nightingale smbios_generic_initializer }, 576bf21cd93STycho Nightingale { (struct smbios_structure *)&smbios_type4_template, 577bf21cd93STycho Nightingale smbios_type4_strings, 578bf21cd93STycho Nightingale smbios_type4_initializer }, 579bf21cd93STycho Nightingale { (struct smbios_structure *)&smbios_type16_template, 580bf21cd93STycho Nightingale NULL, 581bf21cd93STycho Nightingale smbios_type16_initializer }, 582bf21cd93STycho Nightingale { (struct smbios_structure *)&smbios_type17_template, 583bf21cd93STycho Nightingale smbios_type17_strings, 584bf21cd93STycho Nightingale smbios_type17_initializer }, 585bf21cd93STycho Nightingale { (struct smbios_structure *)&smbios_type19_template, 586bf21cd93STycho Nightingale NULL, 587bf21cd93STycho Nightingale smbios_type19_initializer }, 588bf21cd93STycho Nightingale { (struct smbios_structure *)&smbios_type32_template, 589bf21cd93STycho Nightingale NULL, 590bf21cd93STycho Nightingale smbios_generic_initializer }, 591bf21cd93STycho Nightingale { (struct smbios_structure *)&smbios_type127_template, 592bf21cd93STycho Nightingale NULL, 593bf21cd93STycho Nightingale smbios_generic_initializer }, 594bf21cd93STycho Nightingale { NULL,NULL, NULL } 595bf21cd93STycho Nightingale }; 596bf21cd93STycho Nightingale 597bf21cd93STycho Nightingale static uint64_t guest_lomem, guest_himem; 598bf21cd93STycho Nightingale static uint16_t type16_handle; 599bf21cd93STycho Nightingale 600bf21cd93STycho Nightingale static int 601bf21cd93STycho Nightingale smbios_generic_initializer(struct smbios_structure *template_entry, 602bf21cd93STycho Nightingale const char **template_strings, char *curaddr, char **endaddr, 603bf21cd93STycho Nightingale uint16_t *n, uint16_t *size) 604bf21cd93STycho Nightingale { 605bf21cd93STycho Nightingale struct smbios_structure *entry; 606bf21cd93STycho Nightingale 607bf21cd93STycho Nightingale memcpy(curaddr, template_entry, template_entry->length); 608bf21cd93STycho Nightingale entry = (struct smbios_structure *)curaddr; 609bf21cd93STycho Nightingale entry->handle = *n + 1; 610bf21cd93STycho Nightingale curaddr += entry->length; 611bf21cd93STycho Nightingale if (template_strings != NULL) { 612bf21cd93STycho Nightingale int i; 613bf21cd93STycho Nightingale 614bf21cd93STycho Nightingale for (i = 0; template_strings[i] != NULL; i++) { 615bf21cd93STycho Nightingale const char *string; 616bf21cd93STycho Nightingale int len; 617bf21cd93STycho Nightingale 618bf21cd93STycho Nightingale string = template_strings[i]; 619bf21cd93STycho Nightingale len = strlen(string) + 1; 620bf21cd93STycho Nightingale memcpy(curaddr, string, len); 621bf21cd93STycho Nightingale curaddr += len; 622bf21cd93STycho Nightingale } 623bf21cd93STycho Nightingale *curaddr = '\0'; 624bf21cd93STycho Nightingale curaddr++; 625bf21cd93STycho Nightingale } else { 626bf21cd93STycho Nightingale /* Minimum string section is double nul */ 627bf21cd93STycho Nightingale *curaddr = '\0'; 628bf21cd93STycho Nightingale curaddr++; 629bf21cd93STycho Nightingale *curaddr = '\0'; 630bf21cd93STycho Nightingale curaddr++; 631bf21cd93STycho Nightingale } 632bf21cd93STycho Nightingale (*n)++; 633bf21cd93STycho Nightingale *endaddr = curaddr; 634bf21cd93STycho Nightingale 635bf21cd93STycho Nightingale return (0); 636bf21cd93STycho Nightingale } 637bf21cd93STycho Nightingale 638bf21cd93STycho Nightingale static int 639bf21cd93STycho Nightingale smbios_type1_initializer(struct smbios_structure *template_entry, 640bf21cd93STycho Nightingale const char **template_strings, char *curaddr, char **endaddr, 641bf21cd93STycho Nightingale uint16_t *n, uint16_t *size) 642bf21cd93STycho Nightingale { 643bf21cd93STycho Nightingale struct smbios_table_type1 *type1; 6442b948146SAndy Fiddaman const char *guest_uuid_str; 645bf21cd93STycho Nightingale 646bf21cd93STycho Nightingale smbios_generic_initializer(template_entry, template_strings, 647bf21cd93STycho Nightingale curaddr, endaddr, n, size); 648bf21cd93STycho Nightingale type1 = (struct smbios_table_type1 *)curaddr; 649bf21cd93STycho Nightingale 6502b948146SAndy Fiddaman guest_uuid_str = get_config_value("uuid"); 651bf21cd93STycho Nightingale if (guest_uuid_str != NULL) { 652bf21cd93STycho Nightingale uuid_t uuid; 653bf21cd93STycho Nightingale uint32_t status; 654bf21cd93STycho Nightingale 655bf21cd93STycho Nightingale uuid_from_string(guest_uuid_str, &uuid, &status); 656bf21cd93STycho Nightingale if (status != uuid_s_ok) 657bf21cd93STycho Nightingale return (-1); 658bf21cd93STycho Nightingale 659bf21cd93STycho Nightingale uuid_enc_le(&type1->uuid, &uuid); 660bf21cd93STycho Nightingale } else { 661bf21cd93STycho Nightingale MD5_CTX mdctx; 662bf21cd93STycho Nightingale u_char digest[16]; 663bf21cd93STycho Nightingale char hostname[MAXHOSTNAMELEN]; 6642b948146SAndy Fiddaman const char *vmname; 665bf21cd93STycho Nightingale 666bf21cd93STycho Nightingale /* 667bf21cd93STycho Nightingale * Universally unique and yet reproducible are an 668bf21cd93STycho Nightingale * oxymoron, however reproducible is desirable in 669bf21cd93STycho Nightingale * this case. 670bf21cd93STycho Nightingale */ 671bf21cd93STycho Nightingale if (gethostname(hostname, sizeof(hostname))) 672bf21cd93STycho Nightingale return (-1); 673bf21cd93STycho Nightingale 674bf21cd93STycho Nightingale MD5Init(&mdctx); 6752b948146SAndy Fiddaman vmname = get_config_value("name"); 676bf21cd93STycho Nightingale MD5Update(&mdctx, vmname, strlen(vmname)); 677bf21cd93STycho Nightingale MD5Update(&mdctx, hostname, sizeof(hostname)); 678bf21cd93STycho Nightingale MD5Final(digest, &mdctx); 679bf21cd93STycho Nightingale 680bf21cd93STycho Nightingale /* 681bf21cd93STycho Nightingale * Set the variant and version number. 682bf21cd93STycho Nightingale */ 683bf21cd93STycho Nightingale digest[6] &= 0x0F; 684bf21cd93STycho Nightingale digest[6] |= 0x30; /* version 3 */ 685bf21cd93STycho Nightingale digest[8] &= 0x3F; 686bf21cd93STycho Nightingale digest[8] |= 0x80; 687bf21cd93STycho Nightingale 688bf21cd93STycho Nightingale memcpy(&type1->uuid, digest, sizeof (digest)); 689bf21cd93STycho Nightingale } 690bf21cd93STycho Nightingale 691bf21cd93STycho Nightingale return (0); 692bf21cd93STycho Nightingale } 693bf21cd93STycho Nightingale 694bf21cd93STycho Nightingale static int 695bf21cd93STycho Nightingale smbios_type4_initializer(struct smbios_structure *template_entry, 696bf21cd93STycho Nightingale const char **template_strings, char *curaddr, char **endaddr, 697bf21cd93STycho Nightingale uint16_t *n, uint16_t *size) 698bf21cd93STycho Nightingale { 699bf21cd93STycho Nightingale int i; 700bf21cd93STycho Nightingale 7014c87aefeSPatrick Mooney for (i = 0; i < sockets; i++) { 702bf21cd93STycho Nightingale struct smbios_table_type4 *type4; 703bf21cd93STycho Nightingale char *p; 704bf21cd93STycho Nightingale int nstrings, len; 705bf21cd93STycho Nightingale 706bf21cd93STycho Nightingale smbios_generic_initializer(template_entry, template_strings, 707bf21cd93STycho Nightingale curaddr, endaddr, n, size); 708bf21cd93STycho Nightingale type4 = (struct smbios_table_type4 *)curaddr; 709bf21cd93STycho Nightingale p = curaddr + sizeof (struct smbios_table_type4); 710bf21cd93STycho Nightingale nstrings = 0; 711bf21cd93STycho Nightingale while (p < *endaddr - 1) { 712bf21cd93STycho Nightingale if (*p++ == '\0') 713bf21cd93STycho Nightingale nstrings++; 714bf21cd93STycho Nightingale } 715bf21cd93STycho Nightingale len = sprintf(*endaddr - 1, "CPU #%d", i) + 1; 716bf21cd93STycho Nightingale *endaddr += len - 1; 717bf21cd93STycho Nightingale *(*endaddr) = '\0'; 718bf21cd93STycho Nightingale (*endaddr)++; 719bf21cd93STycho Nightingale type4->socket = nstrings + 1; 7204c87aefeSPatrick Mooney /* Revise cores and threads after update to smbios 3.0 */ 7214c87aefeSPatrick Mooney if (cores > 254) 7224c87aefeSPatrick Mooney type4->cores = 0; 7234c87aefeSPatrick Mooney else 7244c87aefeSPatrick Mooney type4->cores = cores; 7254c87aefeSPatrick Mooney /* This threads is total threads in a socket */ 7264c87aefeSPatrick Mooney if ((cores * threads) > 254) 7274c87aefeSPatrick Mooney type4->threads = 0; 7284c87aefeSPatrick Mooney else 7294c87aefeSPatrick Mooney type4->threads = (cores * threads); 730bf21cd93STycho Nightingale curaddr = *endaddr; 731bf21cd93STycho Nightingale } 732bf21cd93STycho Nightingale 733bf21cd93STycho Nightingale return (0); 734bf21cd93STycho Nightingale } 735bf21cd93STycho Nightingale 736bf21cd93STycho Nightingale static int 737bf21cd93STycho Nightingale smbios_type16_initializer(struct smbios_structure *template_entry, 738bf21cd93STycho Nightingale const char **template_strings, char *curaddr, char **endaddr, 739bf21cd93STycho Nightingale uint16_t *n, uint16_t *size) 740bf21cd93STycho Nightingale { 741bf21cd93STycho Nightingale struct smbios_table_type16 *type16; 742bf21cd93STycho Nightingale 743bf21cd93STycho Nightingale type16_handle = *n; 744bf21cd93STycho Nightingale smbios_generic_initializer(template_entry, template_strings, 745bf21cd93STycho Nightingale curaddr, endaddr, n, size); 746bf21cd93STycho Nightingale type16 = (struct smbios_table_type16 *)curaddr; 747bf21cd93STycho Nightingale type16->xsize = guest_lomem + guest_himem; 748bf21cd93STycho Nightingale type16->ndevs = guest_himem > 0 ? 2 : 1; 749bf21cd93STycho Nightingale 750bf21cd93STycho Nightingale return (0); 751bf21cd93STycho Nightingale } 752bf21cd93STycho Nightingale 753bf21cd93STycho Nightingale static int 754bf21cd93STycho Nightingale smbios_type17_initializer(struct smbios_structure *template_entry, 755bf21cd93STycho Nightingale const char **template_strings, char *curaddr, char **endaddr, 756bf21cd93STycho Nightingale uint16_t *n, uint16_t *size) 757bf21cd93STycho Nightingale { 758bf21cd93STycho Nightingale struct smbios_table_type17 *type17; 759154972afSPatrick Mooney uint64_t memsize, size_KB, size_MB; 760bf21cd93STycho Nightingale 761bf21cd93STycho Nightingale smbios_generic_initializer(template_entry, template_strings, 762bf21cd93STycho Nightingale curaddr, endaddr, n, size); 763bf21cd93STycho Nightingale type17 = (struct smbios_table_type17 *)curaddr; 764bf21cd93STycho Nightingale type17->arrayhand = type16_handle; 765bf21cd93STycho Nightingale 766154972afSPatrick Mooney memsize = guest_lomem + guest_himem; 767154972afSPatrick Mooney size_KB = memsize / 1024; 768154972afSPatrick Mooney size_MB = memsize / MB; 769154972afSPatrick Mooney 770154972afSPatrick Mooney /* A single Type 17 entry can't represent more than ~2PB RAM */ 771154972afSPatrick Mooney if (size_MB > 0x7FFFFFFF) { 772154972afSPatrick Mooney printf("Warning: guest memory too big for SMBIOS Type 17 table: " 773154972afSPatrick Mooney "%luMB greater than max supported 2147483647MB\n", size_MB); 774154972afSPatrick Mooney 775154972afSPatrick Mooney size_MB = 0x7FFFFFFF; 776154972afSPatrick Mooney } 777154972afSPatrick Mooney 778154972afSPatrick Mooney /* See SMBIOS 2.7.0 section 7.18 - Memory Device (Type 17) */ 779154972afSPatrick Mooney if (size_KB <= 0x7FFF) { 780154972afSPatrick Mooney /* Can represent up to 32767KB with the top bit set */ 781154972afSPatrick Mooney type17->size = size_KB | (1 << 15); 782154972afSPatrick Mooney } else if (size_MB < 0x7FFF) { 783154972afSPatrick Mooney /* Can represent up to 32766MB with the top bit unset */ 784154972afSPatrick Mooney type17->size = size_MB & 0x7FFF; 785154972afSPatrick Mooney } else { 786154972afSPatrick Mooney type17->size = 0x7FFF; 787154972afSPatrick Mooney /* 788154972afSPatrick Mooney * Can represent up to 2147483647MB (~2PB) 789154972afSPatrick Mooney * The top bit is reserved 790154972afSPatrick Mooney */ 791154972afSPatrick Mooney type17->xsize = size_MB & 0x7FFFFFFF; 792bf21cd93STycho Nightingale } 793bf21cd93STycho Nightingale 794bf21cd93STycho Nightingale return (0); 795bf21cd93STycho Nightingale } 796bf21cd93STycho Nightingale 797bf21cd93STycho Nightingale static int 798bf21cd93STycho Nightingale smbios_type19_initializer(struct smbios_structure *template_entry, 799bf21cd93STycho Nightingale const char **template_strings, char *curaddr, char **endaddr, 800bf21cd93STycho Nightingale uint16_t *n, uint16_t *size) 801bf21cd93STycho Nightingale { 802bf21cd93STycho Nightingale struct smbios_table_type19 *type19; 803bf21cd93STycho Nightingale 804bf21cd93STycho Nightingale smbios_generic_initializer(template_entry, template_strings, 805bf21cd93STycho Nightingale curaddr, endaddr, n, size); 806bf21cd93STycho Nightingale type19 = (struct smbios_table_type19 *)curaddr; 807bf21cd93STycho Nightingale type19->arrayhand = type16_handle; 808bf21cd93STycho Nightingale type19->xsaddr = 0; 809bf21cd93STycho Nightingale type19->xeaddr = guest_lomem; 810bf21cd93STycho Nightingale 811bf21cd93STycho Nightingale if (guest_himem > 0) { 812bf21cd93STycho Nightingale curaddr = *endaddr; 813bf21cd93STycho Nightingale smbios_generic_initializer(template_entry, template_strings, 814bf21cd93STycho Nightingale curaddr, endaddr, n, size); 815bf21cd93STycho Nightingale type19 = (struct smbios_table_type19 *)curaddr; 816bf21cd93STycho Nightingale type19->arrayhand = type16_handle; 817bf21cd93STycho Nightingale type19->xsaddr = 4*GB; 8186960cd89SAndy Fiddaman type19->xeaddr = type19->xsaddr + guest_himem; 819bf21cd93STycho Nightingale } 820bf21cd93STycho Nightingale 821bf21cd93STycho Nightingale return (0); 822bf21cd93STycho Nightingale } 823bf21cd93STycho Nightingale 824bf21cd93STycho Nightingale static void 825bf21cd93STycho Nightingale smbios_ep_initializer(struct smbios_entry_point *smbios_ep, uint32_t staddr) 826bf21cd93STycho Nightingale { 827bf21cd93STycho Nightingale memset(smbios_ep, 0, sizeof(*smbios_ep)); 828bf21cd93STycho Nightingale memcpy(smbios_ep->eanchor, SMBIOS_ENTRY_EANCHOR, 829bf21cd93STycho Nightingale SMBIOS_ENTRY_EANCHORLEN); 830bf21cd93STycho Nightingale smbios_ep->eplen = 0x1F; 831bf21cd93STycho Nightingale assert(sizeof (struct smbios_entry_point) == smbios_ep->eplen); 832bf21cd93STycho Nightingale smbios_ep->major = 2; 833bf21cd93STycho Nightingale smbios_ep->minor = 6; 834bf21cd93STycho Nightingale smbios_ep->revision = 0; 835bf21cd93STycho Nightingale memcpy(smbios_ep->ianchor, SMBIOS_ENTRY_IANCHOR, 836bf21cd93STycho Nightingale SMBIOS_ENTRY_IANCHORLEN); 837bf21cd93STycho Nightingale smbios_ep->staddr = staddr; 838154972afSPatrick Mooney smbios_ep->bcdrev = (smbios_ep->major & 0xf) << 4 | (smbios_ep->minor & 0xf); 839bf21cd93STycho Nightingale } 840bf21cd93STycho Nightingale 841bf21cd93STycho Nightingale static void 842bf21cd93STycho Nightingale smbios_ep_finalizer(struct smbios_entry_point *smbios_ep, uint16_t len, 843bf21cd93STycho Nightingale uint16_t num, uint16_t maxssize) 844bf21cd93STycho Nightingale { 845bf21cd93STycho Nightingale uint8_t checksum; 846bf21cd93STycho Nightingale int i; 847bf21cd93STycho Nightingale 848bf21cd93STycho Nightingale smbios_ep->maxssize = maxssize; 849bf21cd93STycho Nightingale smbios_ep->stlen = len; 850bf21cd93STycho Nightingale smbios_ep->stnum = num; 851bf21cd93STycho Nightingale 852bf21cd93STycho Nightingale checksum = 0; 853bf21cd93STycho Nightingale for (i = 0x10; i < 0x1f; i++) { 854bf21cd93STycho Nightingale checksum -= ((uint8_t *)smbios_ep)[i]; 855bf21cd93STycho Nightingale } 856bf21cd93STycho Nightingale smbios_ep->ichecksum = checksum; 857bf21cd93STycho Nightingale 858bf21cd93STycho Nightingale checksum = 0; 859bf21cd93STycho Nightingale for (i = 0; i < 0x1f; i++) { 860bf21cd93STycho Nightingale checksum -= ((uint8_t *)smbios_ep)[i]; 861bf21cd93STycho Nightingale } 862bf21cd93STycho Nightingale smbios_ep->echecksum = checksum; 863bf21cd93STycho Nightingale } 864bf21cd93STycho Nightingale 865bf21cd93STycho Nightingale int 866bf21cd93STycho Nightingale smbios_build(struct vmctx *ctx) 867bf21cd93STycho Nightingale { 868bf21cd93STycho Nightingale struct smbios_entry_point *smbios_ep; 869bf21cd93STycho Nightingale uint16_t n; 870bf21cd93STycho Nightingale uint16_t maxssize; 871bf21cd93STycho Nightingale char *curaddr, *startaddr, *ststartaddr; 872bf21cd93STycho Nightingale int i; 873bf21cd93STycho Nightingale int err; 874bf21cd93STycho Nightingale 875bf21cd93STycho Nightingale guest_lomem = vm_get_lowmem_size(ctx); 876bf21cd93STycho Nightingale guest_himem = vm_get_highmem_size(ctx); 877bf21cd93STycho Nightingale 878bf21cd93STycho Nightingale startaddr = paddr_guest2host(ctx, SMBIOS_BASE, SMBIOS_MAX_LENGTH); 879bf21cd93STycho Nightingale if (startaddr == NULL) { 880154972afSPatrick Mooney EPRINTLN("smbios table requires mapped mem"); 881bf21cd93STycho Nightingale return (ENOMEM); 882bf21cd93STycho Nightingale } 883bf21cd93STycho Nightingale 884bf21cd93STycho Nightingale curaddr = startaddr; 885bf21cd93STycho Nightingale 886bf21cd93STycho Nightingale smbios_ep = (struct smbios_entry_point *)curaddr; 887bf21cd93STycho Nightingale smbios_ep_initializer(smbios_ep, SMBIOS_BASE + 888bf21cd93STycho Nightingale sizeof(struct smbios_entry_point)); 889bf21cd93STycho Nightingale curaddr += sizeof(struct smbios_entry_point); 890bf21cd93STycho Nightingale ststartaddr = curaddr; 891bf21cd93STycho Nightingale 892bf21cd93STycho Nightingale n = 0; 893bf21cd93STycho Nightingale maxssize = 0; 894bf21cd93STycho Nightingale for (i = 0; smbios_template[i].entry != NULL; i++) { 895bf21cd93STycho Nightingale struct smbios_structure *entry; 896bf21cd93STycho Nightingale const char **strings; 897bf21cd93STycho Nightingale initializer_func_t initializer; 898bf21cd93STycho Nightingale char *endaddr; 899bf21cd93STycho Nightingale uint16_t size; 900bf21cd93STycho Nightingale 901bf21cd93STycho Nightingale entry = smbios_template[i].entry; 902bf21cd93STycho Nightingale strings = smbios_template[i].strings; 903bf21cd93STycho Nightingale initializer = smbios_template[i].initializer; 904bf21cd93STycho Nightingale 905bf21cd93STycho Nightingale err = (*initializer)(entry, strings, curaddr, &endaddr, 906bf21cd93STycho Nightingale &n, &size); 907bf21cd93STycho Nightingale if (err != 0) 908bf21cd93STycho Nightingale return (err); 909bf21cd93STycho Nightingale 910bf21cd93STycho Nightingale if (size > maxssize) 911bf21cd93STycho Nightingale maxssize = size; 912bf21cd93STycho Nightingale 913bf21cd93STycho Nightingale curaddr = endaddr; 914bf21cd93STycho Nightingale } 915bf21cd93STycho Nightingale 916bf21cd93STycho Nightingale assert(curaddr - startaddr < SMBIOS_MAX_LENGTH); 917bf21cd93STycho Nightingale smbios_ep_finalizer(smbios_ep, curaddr - ststartaddr, n, maxssize); 918bf21cd93STycho Nightingale 919bf21cd93STycho Nightingale return (0); 920bf21cd93STycho Nightingale } 9214c87aefeSPatrick Mooney 9222b948146SAndy Fiddaman #ifndef __FreeBSD__ 9232b948146SAndy Fiddaman struct { 9242b948146SAndy Fiddaman const char *key; 9252b948146SAndy Fiddaman const char **targetp; 9262b948146SAndy Fiddaman } type1_map[] = { 9272b948146SAndy Fiddaman { "manufacturer", &smbios_type1_strings[0] }, 9282b948146SAndy Fiddaman { "product", &smbios_type1_strings[1] }, 9292b948146SAndy Fiddaman { "version", &smbios_type1_strings[2] }, 9302b948146SAndy Fiddaman { "serial", &smbios_type1_strings[3] }, 9312b948146SAndy Fiddaman { "sku", &smbios_type1_strings[4] }, 9322b948146SAndy Fiddaman { "family", &smbios_type1_strings[5] }, 9332b948146SAndy Fiddaman { 0 } 9342b948146SAndy Fiddaman }; 9352b948146SAndy Fiddaman 9362b948146SAndy Fiddaman void 9372b948146SAndy Fiddaman smbios_apply(void) 9382b948146SAndy Fiddaman { 9392b948146SAndy Fiddaman nvlist_t *nvl; 9402b948146SAndy Fiddaman 9412b948146SAndy Fiddaman nvl = find_config_node("smbios"); 9422b948146SAndy Fiddaman if (nvl == NULL) 9432b948146SAndy Fiddaman return; 9442b948146SAndy Fiddaman 9452b948146SAndy Fiddaman for (uint_t i = 0; type1_map[i].key != NULL; i++) { 9462b948146SAndy Fiddaman const char *value; 9472b948146SAndy Fiddaman 9482b948146SAndy Fiddaman value = get_config_value_node(nvl, type1_map[i].key); 9492b948146SAndy Fiddaman if (value != NULL) 9502b948146SAndy Fiddaman *type1_map[i].targetp = value; 9512b948146SAndy Fiddaman } 9522b948146SAndy Fiddaman } 9532b948146SAndy Fiddaman 9544c87aefeSPatrick Mooney int 9554c87aefeSPatrick Mooney smbios_parse(const char *opts) 9564c87aefeSPatrick Mooney { 9572b948146SAndy Fiddaman char *buf, *lasts, *token, *end; 9582b948146SAndy Fiddaman nvlist_t *nvl; 9594c87aefeSPatrick Mooney long type; 9604c87aefeSPatrick Mooney 9614c87aefeSPatrick Mooney if ((buf = strdup(opts)) == NULL) { 9624c87aefeSPatrick Mooney (void) fprintf(stderr, "out of memory\n"); 9634c87aefeSPatrick Mooney return (-1); 9644c87aefeSPatrick Mooney } 9654c87aefeSPatrick Mooney 9664c87aefeSPatrick Mooney if ((token = strtok_r(buf, ",", &lasts)) == NULL) { 9674c87aefeSPatrick Mooney (void) fprintf(stderr, "too few fields\n"); 9684c87aefeSPatrick Mooney goto fail; 9694c87aefeSPatrick Mooney } 9704c87aefeSPatrick Mooney 9714c87aefeSPatrick Mooney errno = 0; 9724c87aefeSPatrick Mooney type = strtol(token, &end, 10); 9734c87aefeSPatrick Mooney if (errno != 0 || *end != '\0') { 9744c87aefeSPatrick Mooney (void) fprintf(stderr, "first token '%s' is not an integer\n", 9754c87aefeSPatrick Mooney token); 9764c87aefeSPatrick Mooney goto fail; 9774c87aefeSPatrick Mooney } 9784c87aefeSPatrick Mooney 9794c87aefeSPatrick Mooney /* For now, only type 1 is supported. */ 9804c87aefeSPatrick Mooney if (type != 1) { 9814c87aefeSPatrick Mooney (void) fprintf(stderr, "unsupported type %d\n", type); 9824c87aefeSPatrick Mooney goto fail; 9834c87aefeSPatrick Mooney } 9844c87aefeSPatrick Mooney 9852b948146SAndy Fiddaman nvl = create_config_node("smbios"); 9862b948146SAndy Fiddaman if (nvl == NULL) { 9872b948146SAndy Fiddaman (void) fprintf(stderr, "out of memory\n"); 9882b948146SAndy Fiddaman return (-1); 9892b948146SAndy Fiddaman } 9902b948146SAndy Fiddaman 9914c87aefeSPatrick Mooney while ((token = strtok_r(NULL, ",", &lasts)) != NULL) { 9924c87aefeSPatrick Mooney char *val; 9932b948146SAndy Fiddaman uint_t i; 9944c87aefeSPatrick Mooney 9954c87aefeSPatrick Mooney if ((val = strchr(token, '=')) == NULL) { 9964c87aefeSPatrick Mooney (void) fprintf(stderr, "invalid key=value: '%s'\n", 9974c87aefeSPatrick Mooney token); 9984c87aefeSPatrick Mooney goto fail; 9994c87aefeSPatrick Mooney } 10004c87aefeSPatrick Mooney *val = '\0'; 10014c87aefeSPatrick Mooney val++; 10024c87aefeSPatrick Mooney 10032b948146SAndy Fiddaman if (strcmp(token, "uuid") == 0) { 10042b948146SAndy Fiddaman set_config_value_node(nvl, token, val); 10052b948146SAndy Fiddaman continue; 10062b948146SAndy Fiddaman } 10072b948146SAndy Fiddaman 10084c87aefeSPatrick Mooney for (i = 0; type1_map[i].key != NULL; i++) { 10094c87aefeSPatrick Mooney if (strcmp(token, type1_map[i].key) == 0) { 10104c87aefeSPatrick Mooney break; 10114c87aefeSPatrick Mooney } 10124c87aefeSPatrick Mooney } 10134c87aefeSPatrick Mooney if (type1_map[i].key == NULL) { 10144c87aefeSPatrick Mooney (void) fprintf(stderr, "invalid key '%s'\n", token); 10154c87aefeSPatrick Mooney goto fail; 10164c87aefeSPatrick Mooney } 10172b948146SAndy Fiddaman set_config_value_node(nvl, token, val); 10184c87aefeSPatrick Mooney } 10194c87aefeSPatrick Mooney 10204c87aefeSPatrick Mooney return (0); 10214c87aefeSPatrick Mooney 10224c87aefeSPatrick Mooney fail: 10234c87aefeSPatrick Mooney free(buf); 10244c87aefeSPatrick Mooney return (-1); 10254c87aefeSPatrick Mooney } 10262b948146SAndy Fiddaman #endif 1027