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" 47*2b948146SAndy 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 65bf21cd93STycho Nightingale #define SMBIOS_TYPE_CHASSIS 3 66bf21cd93STycho Nightingale #define SMBIOS_TYPE_PROCESSOR 4 67bf21cd93STycho Nightingale #define SMBIOS_TYPE_MEMARRAY 16 68bf21cd93STycho Nightingale #define SMBIOS_TYPE_MEMDEVICE 17 69bf21cd93STycho Nightingale #define SMBIOS_TYPE_MEMARRAYMAP 19 70bf21cd93STycho Nightingale #define SMBIOS_TYPE_BOOT 32 71bf21cd93STycho Nightingale #define SMBIOS_TYPE_EOT 127 72bf21cd93STycho Nightingale 73bf21cd93STycho Nightingale struct smbios_structure { 74bf21cd93STycho Nightingale uint8_t type; 75bf21cd93STycho Nightingale uint8_t length; 76bf21cd93STycho Nightingale uint16_t handle; 77bf21cd93STycho Nightingale } __packed; 78bf21cd93STycho Nightingale 79bf21cd93STycho Nightingale typedef int (*initializer_func_t)(struct smbios_structure *template_entry, 80bf21cd93STycho Nightingale const char **template_strings, char *curaddr, char **endaddr, 81bf21cd93STycho Nightingale uint16_t *n, uint16_t *size); 82bf21cd93STycho Nightingale 83bf21cd93STycho Nightingale struct smbios_template_entry { 84bf21cd93STycho Nightingale struct smbios_structure *entry; 85bf21cd93STycho Nightingale const char **strings; 86bf21cd93STycho Nightingale initializer_func_t initializer; 87bf21cd93STycho Nightingale }; 88bf21cd93STycho Nightingale 89bf21cd93STycho Nightingale /* 90bf21cd93STycho Nightingale * SMBIOS Structure Table Entry Point 91bf21cd93STycho Nightingale */ 92bf21cd93STycho Nightingale #define SMBIOS_ENTRY_EANCHOR "_SM_" 93bf21cd93STycho Nightingale #define SMBIOS_ENTRY_EANCHORLEN 4 94bf21cd93STycho Nightingale #define SMBIOS_ENTRY_IANCHOR "_DMI_" 95bf21cd93STycho Nightingale #define SMBIOS_ENTRY_IANCHORLEN 5 96bf21cd93STycho Nightingale 97bf21cd93STycho Nightingale struct smbios_entry_point { 98bf21cd93STycho Nightingale char eanchor[4]; /* anchor tag */ 99bf21cd93STycho Nightingale uint8_t echecksum; /* checksum of entry point structure */ 100bf21cd93STycho Nightingale uint8_t eplen; /* length in bytes of entry point */ 101bf21cd93STycho Nightingale uint8_t major; /* major version of the SMBIOS spec */ 102bf21cd93STycho Nightingale uint8_t minor; /* minor version of the SMBIOS spec */ 103bf21cd93STycho Nightingale uint16_t maxssize; /* maximum size in bytes of a struct */ 104bf21cd93STycho Nightingale uint8_t revision; /* entry point structure revision */ 105bf21cd93STycho Nightingale uint8_t format[5]; /* entry point rev-specific data */ 106bf21cd93STycho Nightingale char ianchor[5]; /* intermediate anchor tag */ 107bf21cd93STycho Nightingale uint8_t ichecksum; /* intermediate checksum */ 108bf21cd93STycho Nightingale uint16_t stlen; /* len in bytes of structure table */ 109bf21cd93STycho Nightingale uint32_t staddr; /* physical addr of structure table */ 110bf21cd93STycho Nightingale uint16_t stnum; /* number of structure table entries */ 111bf21cd93STycho Nightingale uint8_t bcdrev; /* BCD value representing DMI ver */ 112bf21cd93STycho Nightingale } __packed; 113bf21cd93STycho Nightingale 114bf21cd93STycho Nightingale /* 115bf21cd93STycho Nightingale * BIOS Information 116bf21cd93STycho Nightingale */ 117bf21cd93STycho Nightingale #define SMBIOS_FL_ISA 0x00000010 /* ISA is supported */ 118bf21cd93STycho Nightingale #define SMBIOS_FL_PCI 0x00000080 /* PCI is supported */ 119bf21cd93STycho Nightingale #define SMBIOS_FL_SHADOW 0x00001000 /* BIOS shadowing is allowed */ 120bf21cd93STycho Nightingale #define SMBIOS_FL_CDBOOT 0x00008000 /* Boot from CD is supported */ 121bf21cd93STycho Nightingale #define SMBIOS_FL_SELBOOT 0x00010000 /* Selectable Boot supported */ 122bf21cd93STycho Nightingale #define SMBIOS_FL_EDD 0x00080000 /* EDD Spec is supported */ 123bf21cd93STycho Nightingale 124bf21cd93STycho Nightingale #define SMBIOS_XB1_FL_ACPI 0x00000001 /* ACPI is supported */ 125bf21cd93STycho Nightingale 126bf21cd93STycho Nightingale #define SMBIOS_XB2_FL_BBS 0x00000001 /* BIOS Boot Specification */ 127bf21cd93STycho Nightingale #define SMBIOS_XB2_FL_VM 0x00000010 /* Virtual Machine */ 128bf21cd93STycho Nightingale 129bf21cd93STycho Nightingale struct smbios_table_type0 { 130bf21cd93STycho Nightingale struct smbios_structure header; 131bf21cd93STycho Nightingale uint8_t vendor; /* vendor string */ 132bf21cd93STycho Nightingale uint8_t version; /* version string */ 133bf21cd93STycho Nightingale uint16_t segment; /* address segment location */ 134bf21cd93STycho Nightingale uint8_t rel_date; /* release date */ 135bf21cd93STycho Nightingale uint8_t size; /* rom size */ 136bf21cd93STycho Nightingale uint64_t cflags; /* characteristics */ 137bf21cd93STycho Nightingale uint8_t xc_bytes[2]; /* characteristics ext bytes */ 138bf21cd93STycho Nightingale uint8_t sb_major_rel; /* system bios version */ 139bf21cd93STycho Nightingale uint8_t sb_minor_rele; 140bf21cd93STycho Nightingale uint8_t ecfw_major_rel; /* embedded ctrl fw version */ 141bf21cd93STycho Nightingale uint8_t ecfw_minor_rel; 142bf21cd93STycho Nightingale } __packed; 143bf21cd93STycho Nightingale 144bf21cd93STycho Nightingale /* 145bf21cd93STycho Nightingale * System Information 146bf21cd93STycho Nightingale */ 147bf21cd93STycho Nightingale #define SMBIOS_WAKEUP_SWITCH 0x06 /* power switch */ 148bf21cd93STycho Nightingale 149bf21cd93STycho Nightingale struct smbios_table_type1 { 150bf21cd93STycho Nightingale struct smbios_structure header; 151bf21cd93STycho Nightingale uint8_t manufacturer; /* manufacturer string */ 152bf21cd93STycho Nightingale uint8_t product; /* product name string */ 153bf21cd93STycho Nightingale uint8_t version; /* version string */ 154bf21cd93STycho Nightingale uint8_t serial; /* serial number string */ 155bf21cd93STycho Nightingale uint8_t uuid[16]; /* uuid byte array */ 156bf21cd93STycho Nightingale uint8_t wakeup; /* wake-up event */ 157bf21cd93STycho Nightingale uint8_t sku; /* sku number string */ 158bf21cd93STycho Nightingale uint8_t family; /* family name string */ 159bf21cd93STycho Nightingale } __packed; 160bf21cd93STycho Nightingale 161bf21cd93STycho Nightingale /* 162bf21cd93STycho Nightingale * System Enclosure or Chassis 163bf21cd93STycho Nightingale */ 164bf21cd93STycho Nightingale #define SMBIOS_CHT_UNKNOWN 0x02 /* unknown */ 165bf21cd93STycho Nightingale 166bf21cd93STycho Nightingale #define SMBIOS_CHST_SAFE 0x03 /* safe */ 167bf21cd93STycho Nightingale 168bf21cd93STycho Nightingale #define SMBIOS_CHSC_NONE 0x03 /* none */ 169bf21cd93STycho Nightingale 170bf21cd93STycho Nightingale struct smbios_table_type3 { 171bf21cd93STycho Nightingale struct smbios_structure header; 172bf21cd93STycho Nightingale uint8_t manufacturer; /* manufacturer string */ 173bf21cd93STycho Nightingale uint8_t type; /* type */ 174bf21cd93STycho Nightingale uint8_t version; /* version string */ 175bf21cd93STycho Nightingale uint8_t serial; /* serial number string */ 176bf21cd93STycho Nightingale uint8_t asset; /* asset tag string */ 177bf21cd93STycho Nightingale uint8_t bustate; /* boot-up state */ 178bf21cd93STycho Nightingale uint8_t psstate; /* power supply state */ 179bf21cd93STycho Nightingale uint8_t tstate; /* thermal state */ 180bf21cd93STycho Nightingale uint8_t security; /* security status */ 181bf21cd93STycho Nightingale uint8_t uheight; /* height in 'u's */ 182bf21cd93STycho Nightingale uint8_t cords; /* number of power cords */ 183bf21cd93STycho Nightingale uint8_t elems; /* number of element records */ 184bf21cd93STycho Nightingale uint8_t elemlen; /* length of records */ 185bf21cd93STycho Nightingale uint8_t sku; /* sku number string */ 186bf21cd93STycho Nightingale } __packed; 187bf21cd93STycho Nightingale 188bf21cd93STycho Nightingale /* 189bf21cd93STycho Nightingale * Processor Information 190bf21cd93STycho Nightingale */ 191bf21cd93STycho Nightingale #define SMBIOS_PRT_CENTRAL 0x03 /* central processor */ 192bf21cd93STycho Nightingale 193bf21cd93STycho Nightingale #define SMBIOS_PRF_OTHER 0x01 /* other */ 194bf21cd93STycho Nightingale 195bf21cd93STycho Nightingale #define SMBIOS_PRS_PRESENT 0x40 /* socket is populated */ 196bf21cd93STycho Nightingale #define SMBIOS_PRS_ENABLED 0x1 /* enabled */ 197bf21cd93STycho Nightingale 198bf21cd93STycho Nightingale #define SMBIOS_PRU_NONE 0x06 /* none */ 199bf21cd93STycho Nightingale 200bf21cd93STycho Nightingale #define SMBIOS_PFL_64B 0x04 /* 64-bit capable */ 201bf21cd93STycho Nightingale 202bf21cd93STycho Nightingale struct smbios_table_type4 { 203bf21cd93STycho Nightingale struct smbios_structure header; 204bf21cd93STycho Nightingale uint8_t socket; /* socket designation string */ 205bf21cd93STycho Nightingale uint8_t type; /* processor type */ 206bf21cd93STycho Nightingale uint8_t family; /* processor family */ 207bf21cd93STycho Nightingale uint8_t manufacturer; /* manufacturer string */ 208bf21cd93STycho Nightingale uint64_t cpuid; /* processor cpuid */ 209bf21cd93STycho Nightingale uint8_t version; /* version string */ 210bf21cd93STycho Nightingale uint8_t voltage; /* voltage */ 211bf21cd93STycho Nightingale uint16_t clkspeed; /* ext clock speed in mhz */ 212bf21cd93STycho Nightingale uint16_t maxspeed; /* maximum speed in mhz */ 213bf21cd93STycho Nightingale uint16_t curspeed; /* current speed in mhz */ 214bf21cd93STycho Nightingale uint8_t status; /* status */ 215bf21cd93STycho Nightingale uint8_t upgrade; /* upgrade */ 216bf21cd93STycho Nightingale uint16_t l1handle; /* l1 cache handle */ 217bf21cd93STycho Nightingale uint16_t l2handle; /* l2 cache handle */ 218bf21cd93STycho Nightingale uint16_t l3handle; /* l3 cache handle */ 219bf21cd93STycho Nightingale uint8_t serial; /* serial number string */ 220bf21cd93STycho Nightingale uint8_t asset; /* asset tag string */ 221bf21cd93STycho Nightingale uint8_t part; /* part number string */ 222bf21cd93STycho Nightingale uint8_t cores; /* cores per socket */ 223bf21cd93STycho Nightingale uint8_t ecores; /* enabled cores */ 224bf21cd93STycho Nightingale uint8_t threads; /* threads per socket */ 225bf21cd93STycho Nightingale uint16_t cflags; /* processor characteristics */ 226bf21cd93STycho Nightingale uint16_t family2; /* processor family 2 */ 227bf21cd93STycho Nightingale } __packed; 228bf21cd93STycho Nightingale 229bf21cd93STycho Nightingale /* 230bf21cd93STycho Nightingale * Physical Memory Array 231bf21cd93STycho Nightingale */ 232bf21cd93STycho Nightingale #define SMBIOS_MAL_SYSMB 0x03 /* system board or motherboard */ 233bf21cd93STycho Nightingale 234bf21cd93STycho Nightingale #define SMBIOS_MAU_SYSTEM 0x03 /* system memory */ 235bf21cd93STycho Nightingale 236bf21cd93STycho Nightingale #define SMBIOS_MAE_NONE 0x03 /* none */ 237bf21cd93STycho Nightingale 238bf21cd93STycho Nightingale struct smbios_table_type16 { 239bf21cd93STycho Nightingale struct smbios_structure header; 240bf21cd93STycho Nightingale uint8_t location; /* physical device location */ 241bf21cd93STycho Nightingale uint8_t use; /* device functional purpose */ 242bf21cd93STycho Nightingale uint8_t ecc; /* err detect/correct method */ 243bf21cd93STycho Nightingale uint32_t size; /* max mem capacity in kb */ 244bf21cd93STycho Nightingale uint16_t errhand; /* handle of error (if any) */ 245bf21cd93STycho Nightingale uint16_t ndevs; /* num of slots or sockets */ 246bf21cd93STycho Nightingale uint64_t xsize; /* max mem capacity in bytes */ 247bf21cd93STycho Nightingale } __packed; 248bf21cd93STycho Nightingale 249bf21cd93STycho Nightingale /* 250bf21cd93STycho Nightingale * Memory Device 251bf21cd93STycho Nightingale */ 252bf21cd93STycho Nightingale #define SMBIOS_MDFF_UNKNOWN 0x02 /* unknown */ 253bf21cd93STycho Nightingale 254bf21cd93STycho Nightingale #define SMBIOS_MDT_UNKNOWN 0x02 /* unknown */ 255bf21cd93STycho Nightingale 256bf21cd93STycho Nightingale #define SMBIOS_MDF_UNKNOWN 0x0004 /* unknown */ 257bf21cd93STycho Nightingale 258bf21cd93STycho Nightingale struct smbios_table_type17 { 259bf21cd93STycho Nightingale struct smbios_structure header; 260bf21cd93STycho Nightingale uint16_t arrayhand; /* handle of physl mem array */ 261bf21cd93STycho Nightingale uint16_t errhand; /* handle of mem error data */ 262bf21cd93STycho Nightingale uint16_t twidth; /* total width in bits */ 263bf21cd93STycho Nightingale uint16_t dwidth; /* data width in bits */ 264154972afSPatrick Mooney uint16_t size; /* size in kb or mb */ 265bf21cd93STycho Nightingale uint8_t form; /* form factor */ 266bf21cd93STycho Nightingale uint8_t set; /* set */ 267bf21cd93STycho Nightingale uint8_t dloc; /* device locator string */ 268bf21cd93STycho Nightingale uint8_t bloc; /* phys bank locator string */ 269bf21cd93STycho Nightingale uint8_t type; /* memory type */ 270bf21cd93STycho Nightingale uint16_t flags; /* memory characteristics */ 271bf21cd93STycho Nightingale uint16_t maxspeed; /* maximum speed in mhz */ 272bf21cd93STycho Nightingale uint8_t manufacturer; /* manufacturer string */ 273bf21cd93STycho Nightingale uint8_t serial; /* serial number string */ 274bf21cd93STycho Nightingale uint8_t asset; /* asset tag string */ 275bf21cd93STycho Nightingale uint8_t part; /* part number string */ 276bf21cd93STycho Nightingale uint8_t attributes; /* attributes */ 277154972afSPatrick Mooney uint32_t xsize; /* extended size in mb */ 278bf21cd93STycho Nightingale uint16_t curspeed; /* current speed in mhz */ 279bf21cd93STycho Nightingale uint16_t minvoltage; /* minimum voltage */ 280bf21cd93STycho Nightingale uint16_t maxvoltage; /* maximum voltage */ 281bf21cd93STycho Nightingale uint16_t curvoltage; /* configured voltage */ 282bf21cd93STycho Nightingale } __packed; 283bf21cd93STycho Nightingale 284bf21cd93STycho Nightingale /* 285bf21cd93STycho Nightingale * Memory Array Mapped Address 286bf21cd93STycho Nightingale */ 287bf21cd93STycho Nightingale struct smbios_table_type19 { 288bf21cd93STycho Nightingale struct smbios_structure header; 289bf21cd93STycho Nightingale uint32_t saddr; /* start phys addr in kb */ 290bf21cd93STycho Nightingale uint32_t eaddr; /* end phys addr in kb */ 291bf21cd93STycho Nightingale uint16_t arrayhand; /* physical mem array handle */ 292bf21cd93STycho Nightingale uint8_t width; /* num of dev in row */ 293bf21cd93STycho Nightingale uint64_t xsaddr; /* start phys addr in bytes */ 294bf21cd93STycho Nightingale uint64_t xeaddr; /* end phys addr in bytes */ 295bf21cd93STycho Nightingale } __packed; 296bf21cd93STycho Nightingale 297bf21cd93STycho Nightingale /* 298bf21cd93STycho Nightingale * System Boot Information 299bf21cd93STycho Nightingale */ 300bf21cd93STycho Nightingale #define SMBIOS_BOOT_NORMAL 0 /* no errors detected */ 301bf21cd93STycho Nightingale 302bf21cd93STycho Nightingale struct smbios_table_type32 { 303bf21cd93STycho Nightingale struct smbios_structure header; 304bf21cd93STycho Nightingale uint8_t reserved[6]; 305bf21cd93STycho Nightingale uint8_t status; /* boot status */ 306bf21cd93STycho Nightingale } __packed; 307bf21cd93STycho Nightingale 308bf21cd93STycho Nightingale /* 309bf21cd93STycho Nightingale * End-of-Table 310bf21cd93STycho Nightingale */ 311bf21cd93STycho Nightingale struct smbios_table_type127 { 312bf21cd93STycho Nightingale struct smbios_structure header; 313bf21cd93STycho Nightingale } __packed; 314bf21cd93STycho Nightingale 315bf21cd93STycho Nightingale struct smbios_table_type0 smbios_type0_template = { 316bf21cd93STycho Nightingale { SMBIOS_TYPE_BIOS, sizeof (struct smbios_table_type0), 0 }, 317bf21cd93STycho Nightingale 1, /* bios vendor string */ 318bf21cd93STycho Nightingale 2, /* bios version string */ 319bf21cd93STycho Nightingale 0xF000, /* bios address segment location */ 320bf21cd93STycho Nightingale 3, /* bios release date */ 321bf21cd93STycho Nightingale 0x0, /* bios size (64k * (n + 1) is the size in bytes) */ 322bf21cd93STycho Nightingale SMBIOS_FL_ISA | SMBIOS_FL_PCI | SMBIOS_FL_SHADOW | 323bf21cd93STycho Nightingale SMBIOS_FL_CDBOOT | SMBIOS_FL_EDD, 324bf21cd93STycho Nightingale { SMBIOS_XB1_FL_ACPI, SMBIOS_XB2_FL_BBS | SMBIOS_XB2_FL_VM }, 325bf21cd93STycho Nightingale 0x0, /* bios major release */ 326bf21cd93STycho Nightingale 0x0, /* bios minor release */ 327bf21cd93STycho Nightingale 0xff, /* embedded controller firmware major release */ 328bf21cd93STycho Nightingale 0xff /* embedded controller firmware minor release */ 329bf21cd93STycho Nightingale }; 330bf21cd93STycho Nightingale 331bf21cd93STycho Nightingale const char *smbios_type0_strings[] = { 3326960cd89SAndy Fiddaman "BHYVE", /* vendor string */ 3336960cd89SAndy Fiddaman FIRMWARE_VERSION, /* bios version string */ 3346960cd89SAndy Fiddaman FIRMWARE_RELEASE_DATE, /* bios release date string */ 335bf21cd93STycho Nightingale NULL 336bf21cd93STycho Nightingale }; 337bf21cd93STycho Nightingale 338bf21cd93STycho Nightingale struct smbios_table_type1 smbios_type1_template = { 339bf21cd93STycho Nightingale { SMBIOS_TYPE_SYSTEM, sizeof (struct smbios_table_type1), 0 }, 340bf21cd93STycho Nightingale 1, /* manufacturer string */ 341bf21cd93STycho Nightingale 2, /* product string */ 342bf21cd93STycho Nightingale 3, /* version string */ 343bf21cd93STycho Nightingale 4, /* serial number string */ 344bf21cd93STycho Nightingale { 0 }, 345bf21cd93STycho Nightingale SMBIOS_WAKEUP_SWITCH, 346bf21cd93STycho Nightingale 5, /* sku string */ 347bf21cd93STycho Nightingale 6 /* family string */ 348bf21cd93STycho Nightingale }; 349bf21cd93STycho Nightingale 350bf21cd93STycho Nightingale static int smbios_type1_initializer(struct smbios_structure *template_entry, 351bf21cd93STycho Nightingale const char **template_strings, char *curaddr, char **endaddr, 352bf21cd93STycho Nightingale uint16_t *n, uint16_t *size); 353bf21cd93STycho Nightingale 354bf21cd93STycho Nightingale const char *smbios_type1_strings[] = { 3556960cd89SAndy Fiddaman "illumos", /* manufacturer string */ 3566960cd89SAndy Fiddaman "BHYVE", /* product name string */ 3576960cd89SAndy Fiddaman "1.0", /* version string */ 3586960cd89SAndy Fiddaman "None", /* serial number string */ 3596960cd89SAndy Fiddaman "None", /* sku string */ 3606960cd89SAndy Fiddaman "Virtual Machine", /* family name string */ 361bf21cd93STycho Nightingale NULL 362bf21cd93STycho Nightingale }; 363bf21cd93STycho Nightingale 364bf21cd93STycho Nightingale struct smbios_table_type3 smbios_type3_template = { 365bf21cd93STycho Nightingale { SMBIOS_TYPE_CHASSIS, sizeof (struct smbios_table_type3), 0 }, 366bf21cd93STycho Nightingale 1, /* manufacturer string */ 367bf21cd93STycho Nightingale SMBIOS_CHT_UNKNOWN, 368bf21cd93STycho Nightingale 2, /* version string */ 369bf21cd93STycho Nightingale 3, /* serial number string */ 370bf21cd93STycho Nightingale 4, /* asset tag string */ 371bf21cd93STycho Nightingale SMBIOS_CHST_SAFE, 372bf21cd93STycho Nightingale SMBIOS_CHST_SAFE, 373bf21cd93STycho Nightingale SMBIOS_CHST_SAFE, 374bf21cd93STycho Nightingale SMBIOS_CHSC_NONE, 375bf21cd93STycho Nightingale 0, /* height in 'u's (0=enclosure height unspecified) */ 376bf21cd93STycho Nightingale 0, /* number of power cords (0=number unspecified) */ 377bf21cd93STycho Nightingale 0, /* number of contained element records */ 378bf21cd93STycho Nightingale 0, /* length of records */ 379bf21cd93STycho Nightingale 5 /* sku number string */ 380bf21cd93STycho Nightingale }; 381bf21cd93STycho Nightingale 382bf21cd93STycho Nightingale const char *smbios_type3_strings[] = { 3836960cd89SAndy Fiddaman "illumos", /* manufacturer string */ 384bf21cd93STycho Nightingale "1.0", /* version string */ 385bf21cd93STycho Nightingale "None", /* serial number string */ 386bf21cd93STycho Nightingale "None", /* asset tag string */ 387bf21cd93STycho Nightingale "None", /* sku number string */ 388bf21cd93STycho Nightingale NULL 389bf21cd93STycho Nightingale }; 390bf21cd93STycho Nightingale 391bf21cd93STycho Nightingale struct smbios_table_type4 smbios_type4_template = { 392bf21cd93STycho Nightingale { SMBIOS_TYPE_PROCESSOR, sizeof (struct smbios_table_type4), 0 }, 393bf21cd93STycho Nightingale 1, /* socket designation string */ 394bf21cd93STycho Nightingale SMBIOS_PRT_CENTRAL, 395bf21cd93STycho Nightingale SMBIOS_PRF_OTHER, 396bf21cd93STycho Nightingale 2, /* manufacturer string */ 397bf21cd93STycho Nightingale 0, /* cpuid */ 398bf21cd93STycho Nightingale 3, /* version string */ 399bf21cd93STycho Nightingale 0, /* voltage */ 400bf21cd93STycho Nightingale 0, /* external clock frequency in mhz (0=unknown) */ 401bf21cd93STycho Nightingale 0, /* maximum frequency in mhz (0=unknown) */ 402bf21cd93STycho Nightingale 0, /* current frequency in mhz (0=unknown) */ 403bf21cd93STycho Nightingale SMBIOS_PRS_PRESENT | SMBIOS_PRS_ENABLED, 404bf21cd93STycho Nightingale SMBIOS_PRU_NONE, 405bf21cd93STycho Nightingale -1, /* l1 cache handle */ 406bf21cd93STycho Nightingale -1, /* l2 cache handle */ 407bf21cd93STycho Nightingale -1, /* l3 cache handle */ 408bf21cd93STycho Nightingale 4, /* serial number string */ 409bf21cd93STycho Nightingale 5, /* asset tag string */ 410bf21cd93STycho Nightingale 6, /* part number string */ 411bf21cd93STycho Nightingale 0, /* cores per socket (0=unknown) */ 412bf21cd93STycho Nightingale 0, /* enabled cores per socket (0=unknown) */ 413bf21cd93STycho Nightingale 0, /* threads per socket (0=unknown) */ 414bf21cd93STycho Nightingale SMBIOS_PFL_64B, 415bf21cd93STycho Nightingale SMBIOS_PRF_OTHER 416bf21cd93STycho Nightingale }; 417bf21cd93STycho Nightingale 418bf21cd93STycho Nightingale const char *smbios_type4_strings[] = { 419bf21cd93STycho Nightingale " ", /* socket designation string */ 420bf21cd93STycho Nightingale " ", /* manufacturer string */ 421bf21cd93STycho Nightingale " ", /* version string */ 422bf21cd93STycho Nightingale "None", /* serial number string */ 423bf21cd93STycho Nightingale "None", /* asset tag string */ 424bf21cd93STycho Nightingale "None", /* part number string */ 425bf21cd93STycho Nightingale NULL 426bf21cd93STycho Nightingale }; 427bf21cd93STycho Nightingale 428bf21cd93STycho Nightingale static int smbios_type4_initializer(struct smbios_structure *template_entry, 429bf21cd93STycho Nightingale const char **template_strings, char *curaddr, char **endaddr, 430bf21cd93STycho Nightingale uint16_t *n, uint16_t *size); 431bf21cd93STycho Nightingale 432bf21cd93STycho Nightingale struct smbios_table_type16 smbios_type16_template = { 433bf21cd93STycho Nightingale { SMBIOS_TYPE_MEMARRAY, sizeof (struct smbios_table_type16), 0 }, 434bf21cd93STycho Nightingale SMBIOS_MAL_SYSMB, 435bf21cd93STycho Nightingale SMBIOS_MAU_SYSTEM, 436bf21cd93STycho Nightingale SMBIOS_MAE_NONE, 437bf21cd93STycho Nightingale 0x80000000, /* max mem capacity in kb (0x80000000=use extended) */ 438bf21cd93STycho Nightingale -1, /* handle of error (if any) */ 439bf21cd93STycho Nightingale 0, /* number of slots or sockets (TBD) */ 440bf21cd93STycho Nightingale 0 /* extended maximum memory capacity in bytes (TBD) */ 441bf21cd93STycho Nightingale }; 442bf21cd93STycho Nightingale 443bf21cd93STycho Nightingale static int smbios_type16_initializer(struct smbios_structure *template_entry, 444bf21cd93STycho Nightingale const char **template_strings, char *curaddr, char **endaddr, 445bf21cd93STycho Nightingale uint16_t *n, uint16_t *size); 446bf21cd93STycho Nightingale 447bf21cd93STycho Nightingale struct smbios_table_type17 smbios_type17_template = { 448bf21cd93STycho Nightingale { SMBIOS_TYPE_MEMDEVICE, sizeof (struct smbios_table_type17), 0 }, 449bf21cd93STycho Nightingale -1, /* handle of physical memory array */ 450bf21cd93STycho Nightingale -1, /* handle of memory error data */ 451bf21cd93STycho Nightingale 64, /* total width in bits including ecc */ 452bf21cd93STycho Nightingale 64, /* data width in bits */ 453154972afSPatrick Mooney 0, /* size in kb or mb (0x7fff=use extended)*/ 454bf21cd93STycho Nightingale SMBIOS_MDFF_UNKNOWN, 455bf21cd93STycho Nightingale 0, /* set (0x00=none, 0xff=unknown) */ 456bf21cd93STycho Nightingale 1, /* device locator string */ 457bf21cd93STycho Nightingale 2, /* physical bank locator string */ 458bf21cd93STycho Nightingale SMBIOS_MDT_UNKNOWN, 459bf21cd93STycho Nightingale SMBIOS_MDF_UNKNOWN, 460bf21cd93STycho Nightingale 0, /* maximum memory speed in mhz (0=unknown) */ 461bf21cd93STycho Nightingale 3, /* manufacturer string */ 462bf21cd93STycho Nightingale 4, /* serial number string */ 463bf21cd93STycho Nightingale 5, /* asset tag string */ 464bf21cd93STycho Nightingale 6, /* part number string */ 465bf21cd93STycho Nightingale 0, /* attributes (0=unknown rank information) */ 466bf21cd93STycho Nightingale 0, /* extended size in mb (TBD) */ 467bf21cd93STycho Nightingale 0, /* current speed in mhz (0=unknown) */ 468bf21cd93STycho Nightingale 0, /* minimum voltage in mv (0=unknown) */ 469bf21cd93STycho Nightingale 0, /* maximum voltage in mv (0=unknown) */ 470bf21cd93STycho Nightingale 0 /* configured voltage in mv (0=unknown) */ 471bf21cd93STycho Nightingale }; 472bf21cd93STycho Nightingale 473bf21cd93STycho Nightingale const char *smbios_type17_strings[] = { 474bf21cd93STycho Nightingale " ", /* device locator string */ 475bf21cd93STycho Nightingale " ", /* physical bank locator string */ 476bf21cd93STycho Nightingale " ", /* manufacturer string */ 477bf21cd93STycho Nightingale "None", /* serial number string */ 478bf21cd93STycho Nightingale "None", /* asset tag string */ 479bf21cd93STycho Nightingale "None", /* part number string */ 480bf21cd93STycho Nightingale NULL 481bf21cd93STycho Nightingale }; 482bf21cd93STycho Nightingale 483bf21cd93STycho Nightingale static int smbios_type17_initializer(struct smbios_structure *template_entry, 484bf21cd93STycho Nightingale const char **template_strings, char *curaddr, char **endaddr, 485bf21cd93STycho Nightingale uint16_t *n, uint16_t *size); 486bf21cd93STycho Nightingale 487bf21cd93STycho Nightingale struct smbios_table_type19 smbios_type19_template = { 488bf21cd93STycho Nightingale { SMBIOS_TYPE_MEMARRAYMAP, sizeof (struct smbios_table_type19), 0 }, 489bf21cd93STycho Nightingale 0xffffffff, /* starting phys addr in kb (0xffffffff=use ext) */ 490bf21cd93STycho Nightingale 0xffffffff, /* ending phys addr in kb (0xffffffff=use ext) */ 491bf21cd93STycho Nightingale -1, /* physical memory array handle */ 492bf21cd93STycho Nightingale 1, /* number of devices that form a row */ 493bf21cd93STycho Nightingale 0, /* extended starting phys addr in bytes (TDB) */ 494bf21cd93STycho Nightingale 0 /* extended ending phys addr in bytes (TDB) */ 495bf21cd93STycho Nightingale }; 496bf21cd93STycho Nightingale 497bf21cd93STycho Nightingale static int smbios_type19_initializer(struct smbios_structure *template_entry, 498bf21cd93STycho Nightingale const char **template_strings, char *curaddr, char **endaddr, 499bf21cd93STycho Nightingale uint16_t *n, uint16_t *size); 500bf21cd93STycho Nightingale 501bf21cd93STycho Nightingale struct smbios_table_type32 smbios_type32_template = { 502bf21cd93STycho Nightingale { SMBIOS_TYPE_BOOT, sizeof (struct smbios_table_type32), 0 }, 503bf21cd93STycho Nightingale { 0, 0, 0, 0, 0, 0 }, 504bf21cd93STycho Nightingale SMBIOS_BOOT_NORMAL 505bf21cd93STycho Nightingale }; 506bf21cd93STycho Nightingale 507bf21cd93STycho Nightingale struct smbios_table_type127 smbios_type127_template = { 508bf21cd93STycho Nightingale { SMBIOS_TYPE_EOT, sizeof (struct smbios_table_type127), 0 } 509bf21cd93STycho Nightingale }; 510bf21cd93STycho Nightingale 511bf21cd93STycho Nightingale static int smbios_generic_initializer(struct smbios_structure *template_entry, 512bf21cd93STycho Nightingale const char **template_strings, char *curaddr, char **endaddr, 513bf21cd93STycho Nightingale uint16_t *n, uint16_t *size); 514bf21cd93STycho Nightingale 515bf21cd93STycho Nightingale static struct smbios_template_entry smbios_template[] = { 516bf21cd93STycho Nightingale { (struct smbios_structure *)&smbios_type0_template, 517bf21cd93STycho Nightingale smbios_type0_strings, 518bf21cd93STycho Nightingale smbios_generic_initializer }, 519bf21cd93STycho Nightingale { (struct smbios_structure *)&smbios_type1_template, 520bf21cd93STycho Nightingale smbios_type1_strings, 521bf21cd93STycho Nightingale smbios_type1_initializer }, 522bf21cd93STycho Nightingale { (struct smbios_structure *)&smbios_type3_template, 523bf21cd93STycho Nightingale smbios_type3_strings, 524bf21cd93STycho Nightingale smbios_generic_initializer }, 525bf21cd93STycho Nightingale { (struct smbios_structure *)&smbios_type4_template, 526bf21cd93STycho Nightingale smbios_type4_strings, 527bf21cd93STycho Nightingale smbios_type4_initializer }, 528bf21cd93STycho Nightingale { (struct smbios_structure *)&smbios_type16_template, 529bf21cd93STycho Nightingale NULL, 530bf21cd93STycho Nightingale smbios_type16_initializer }, 531bf21cd93STycho Nightingale { (struct smbios_structure *)&smbios_type17_template, 532bf21cd93STycho Nightingale smbios_type17_strings, 533bf21cd93STycho Nightingale smbios_type17_initializer }, 534bf21cd93STycho Nightingale { (struct smbios_structure *)&smbios_type19_template, 535bf21cd93STycho Nightingale NULL, 536bf21cd93STycho Nightingale smbios_type19_initializer }, 537bf21cd93STycho Nightingale { (struct smbios_structure *)&smbios_type32_template, 538bf21cd93STycho Nightingale NULL, 539bf21cd93STycho Nightingale smbios_generic_initializer }, 540bf21cd93STycho Nightingale { (struct smbios_structure *)&smbios_type127_template, 541bf21cd93STycho Nightingale NULL, 542bf21cd93STycho Nightingale smbios_generic_initializer }, 543bf21cd93STycho Nightingale { NULL,NULL, NULL } 544bf21cd93STycho Nightingale }; 545bf21cd93STycho Nightingale 546bf21cd93STycho Nightingale static uint64_t guest_lomem, guest_himem; 547bf21cd93STycho Nightingale static uint16_t type16_handle; 548bf21cd93STycho Nightingale 549bf21cd93STycho Nightingale static int 550bf21cd93STycho Nightingale smbios_generic_initializer(struct smbios_structure *template_entry, 551bf21cd93STycho Nightingale const char **template_strings, char *curaddr, char **endaddr, 552bf21cd93STycho Nightingale uint16_t *n, uint16_t *size) 553bf21cd93STycho Nightingale { 554bf21cd93STycho Nightingale struct smbios_structure *entry; 555bf21cd93STycho Nightingale 556bf21cd93STycho Nightingale memcpy(curaddr, template_entry, template_entry->length); 557bf21cd93STycho Nightingale entry = (struct smbios_structure *)curaddr; 558bf21cd93STycho Nightingale entry->handle = *n + 1; 559bf21cd93STycho Nightingale curaddr += entry->length; 560bf21cd93STycho Nightingale if (template_strings != NULL) { 561bf21cd93STycho Nightingale int i; 562bf21cd93STycho Nightingale 563bf21cd93STycho Nightingale for (i = 0; template_strings[i] != NULL; i++) { 564bf21cd93STycho Nightingale const char *string; 565bf21cd93STycho Nightingale int len; 566bf21cd93STycho Nightingale 567bf21cd93STycho Nightingale string = template_strings[i]; 568bf21cd93STycho Nightingale len = strlen(string) + 1; 569bf21cd93STycho Nightingale memcpy(curaddr, string, len); 570bf21cd93STycho Nightingale curaddr += len; 571bf21cd93STycho Nightingale } 572bf21cd93STycho Nightingale *curaddr = '\0'; 573bf21cd93STycho Nightingale curaddr++; 574bf21cd93STycho Nightingale } else { 575bf21cd93STycho Nightingale /* Minimum string section is double nul */ 576bf21cd93STycho Nightingale *curaddr = '\0'; 577bf21cd93STycho Nightingale curaddr++; 578bf21cd93STycho Nightingale *curaddr = '\0'; 579bf21cd93STycho Nightingale curaddr++; 580bf21cd93STycho Nightingale } 581bf21cd93STycho Nightingale (*n)++; 582bf21cd93STycho Nightingale *endaddr = curaddr; 583bf21cd93STycho Nightingale 584bf21cd93STycho Nightingale return (0); 585bf21cd93STycho Nightingale } 586bf21cd93STycho Nightingale 587bf21cd93STycho Nightingale static int 588bf21cd93STycho Nightingale smbios_type1_initializer(struct smbios_structure *template_entry, 589bf21cd93STycho Nightingale const char **template_strings, char *curaddr, char **endaddr, 590bf21cd93STycho Nightingale uint16_t *n, uint16_t *size) 591bf21cd93STycho Nightingale { 592bf21cd93STycho Nightingale struct smbios_table_type1 *type1; 593*2b948146SAndy Fiddaman const char *guest_uuid_str; 594bf21cd93STycho Nightingale 595bf21cd93STycho Nightingale smbios_generic_initializer(template_entry, template_strings, 596bf21cd93STycho Nightingale curaddr, endaddr, n, size); 597bf21cd93STycho Nightingale type1 = (struct smbios_table_type1 *)curaddr; 598bf21cd93STycho Nightingale 599*2b948146SAndy Fiddaman guest_uuid_str = get_config_value("uuid"); 600bf21cd93STycho Nightingale if (guest_uuid_str != NULL) { 601bf21cd93STycho Nightingale uuid_t uuid; 602bf21cd93STycho Nightingale uint32_t status; 603bf21cd93STycho Nightingale 604bf21cd93STycho Nightingale uuid_from_string(guest_uuid_str, &uuid, &status); 605bf21cd93STycho Nightingale if (status != uuid_s_ok) 606bf21cd93STycho Nightingale return (-1); 607bf21cd93STycho Nightingale 608bf21cd93STycho Nightingale uuid_enc_le(&type1->uuid, &uuid); 609bf21cd93STycho Nightingale } else { 610bf21cd93STycho Nightingale MD5_CTX mdctx; 611bf21cd93STycho Nightingale u_char digest[16]; 612bf21cd93STycho Nightingale char hostname[MAXHOSTNAMELEN]; 613*2b948146SAndy Fiddaman const char *vmname; 614bf21cd93STycho Nightingale 615bf21cd93STycho Nightingale /* 616bf21cd93STycho Nightingale * Universally unique and yet reproducible are an 617bf21cd93STycho Nightingale * oxymoron, however reproducible is desirable in 618bf21cd93STycho Nightingale * this case. 619bf21cd93STycho Nightingale */ 620bf21cd93STycho Nightingale if (gethostname(hostname, sizeof(hostname))) 621bf21cd93STycho Nightingale return (-1); 622bf21cd93STycho Nightingale 623bf21cd93STycho Nightingale MD5Init(&mdctx); 624*2b948146SAndy Fiddaman vmname = get_config_value("name"); 625bf21cd93STycho Nightingale MD5Update(&mdctx, vmname, strlen(vmname)); 626bf21cd93STycho Nightingale MD5Update(&mdctx, hostname, sizeof(hostname)); 627bf21cd93STycho Nightingale MD5Final(digest, &mdctx); 628bf21cd93STycho Nightingale 629bf21cd93STycho Nightingale /* 630bf21cd93STycho Nightingale * Set the variant and version number. 631bf21cd93STycho Nightingale */ 632bf21cd93STycho Nightingale digest[6] &= 0x0F; 633bf21cd93STycho Nightingale digest[6] |= 0x30; /* version 3 */ 634bf21cd93STycho Nightingale digest[8] &= 0x3F; 635bf21cd93STycho Nightingale digest[8] |= 0x80; 636bf21cd93STycho Nightingale 637bf21cd93STycho Nightingale memcpy(&type1->uuid, digest, sizeof (digest)); 638bf21cd93STycho Nightingale } 639bf21cd93STycho Nightingale 640bf21cd93STycho Nightingale return (0); 641bf21cd93STycho Nightingale } 642bf21cd93STycho Nightingale 643bf21cd93STycho Nightingale static int 644bf21cd93STycho Nightingale smbios_type4_initializer(struct smbios_structure *template_entry, 645bf21cd93STycho Nightingale const char **template_strings, char *curaddr, char **endaddr, 646bf21cd93STycho Nightingale uint16_t *n, uint16_t *size) 647bf21cd93STycho Nightingale { 648bf21cd93STycho Nightingale int i; 649bf21cd93STycho Nightingale 6504c87aefeSPatrick Mooney for (i = 0; i < sockets; i++) { 651bf21cd93STycho Nightingale struct smbios_table_type4 *type4; 652bf21cd93STycho Nightingale char *p; 653bf21cd93STycho Nightingale int nstrings, len; 654bf21cd93STycho Nightingale 655bf21cd93STycho Nightingale smbios_generic_initializer(template_entry, template_strings, 656bf21cd93STycho Nightingale curaddr, endaddr, n, size); 657bf21cd93STycho Nightingale type4 = (struct smbios_table_type4 *)curaddr; 658bf21cd93STycho Nightingale p = curaddr + sizeof (struct smbios_table_type4); 659bf21cd93STycho Nightingale nstrings = 0; 660bf21cd93STycho Nightingale while (p < *endaddr - 1) { 661bf21cd93STycho Nightingale if (*p++ == '\0') 662bf21cd93STycho Nightingale nstrings++; 663bf21cd93STycho Nightingale } 664bf21cd93STycho Nightingale len = sprintf(*endaddr - 1, "CPU #%d", i) + 1; 665bf21cd93STycho Nightingale *endaddr += len - 1; 666bf21cd93STycho Nightingale *(*endaddr) = '\0'; 667bf21cd93STycho Nightingale (*endaddr)++; 668bf21cd93STycho Nightingale type4->socket = nstrings + 1; 6694c87aefeSPatrick Mooney /* Revise cores and threads after update to smbios 3.0 */ 6704c87aefeSPatrick Mooney if (cores > 254) 6714c87aefeSPatrick Mooney type4->cores = 0; 6724c87aefeSPatrick Mooney else 6734c87aefeSPatrick Mooney type4->cores = cores; 6744c87aefeSPatrick Mooney /* This threads is total threads in a socket */ 6754c87aefeSPatrick Mooney if ((cores * threads) > 254) 6764c87aefeSPatrick Mooney type4->threads = 0; 6774c87aefeSPatrick Mooney else 6784c87aefeSPatrick Mooney type4->threads = (cores * threads); 679bf21cd93STycho Nightingale curaddr = *endaddr; 680bf21cd93STycho Nightingale } 681bf21cd93STycho Nightingale 682bf21cd93STycho Nightingale return (0); 683bf21cd93STycho Nightingale } 684bf21cd93STycho Nightingale 685bf21cd93STycho Nightingale static int 686bf21cd93STycho Nightingale smbios_type16_initializer(struct smbios_structure *template_entry, 687bf21cd93STycho Nightingale const char **template_strings, char *curaddr, char **endaddr, 688bf21cd93STycho Nightingale uint16_t *n, uint16_t *size) 689bf21cd93STycho Nightingale { 690bf21cd93STycho Nightingale struct smbios_table_type16 *type16; 691bf21cd93STycho Nightingale 692bf21cd93STycho Nightingale type16_handle = *n; 693bf21cd93STycho Nightingale smbios_generic_initializer(template_entry, template_strings, 694bf21cd93STycho Nightingale curaddr, endaddr, n, size); 695bf21cd93STycho Nightingale type16 = (struct smbios_table_type16 *)curaddr; 696bf21cd93STycho Nightingale type16->xsize = guest_lomem + guest_himem; 697bf21cd93STycho Nightingale type16->ndevs = guest_himem > 0 ? 2 : 1; 698bf21cd93STycho Nightingale 699bf21cd93STycho Nightingale return (0); 700bf21cd93STycho Nightingale } 701bf21cd93STycho Nightingale 702bf21cd93STycho Nightingale static int 703bf21cd93STycho Nightingale smbios_type17_initializer(struct smbios_structure *template_entry, 704bf21cd93STycho Nightingale const char **template_strings, char *curaddr, char **endaddr, 705bf21cd93STycho Nightingale uint16_t *n, uint16_t *size) 706bf21cd93STycho Nightingale { 707bf21cd93STycho Nightingale struct smbios_table_type17 *type17; 708154972afSPatrick Mooney uint64_t memsize, size_KB, size_MB; 709bf21cd93STycho Nightingale 710bf21cd93STycho Nightingale smbios_generic_initializer(template_entry, template_strings, 711bf21cd93STycho Nightingale curaddr, endaddr, n, size); 712bf21cd93STycho Nightingale type17 = (struct smbios_table_type17 *)curaddr; 713bf21cd93STycho Nightingale type17->arrayhand = type16_handle; 714bf21cd93STycho Nightingale 715154972afSPatrick Mooney memsize = guest_lomem + guest_himem; 716154972afSPatrick Mooney size_KB = memsize / 1024; 717154972afSPatrick Mooney size_MB = memsize / MB; 718154972afSPatrick Mooney 719154972afSPatrick Mooney /* A single Type 17 entry can't represent more than ~2PB RAM */ 720154972afSPatrick Mooney if (size_MB > 0x7FFFFFFF) { 721154972afSPatrick Mooney printf("Warning: guest memory too big for SMBIOS Type 17 table: " 722154972afSPatrick Mooney "%luMB greater than max supported 2147483647MB\n", size_MB); 723154972afSPatrick Mooney 724154972afSPatrick Mooney size_MB = 0x7FFFFFFF; 725154972afSPatrick Mooney } 726154972afSPatrick Mooney 727154972afSPatrick Mooney /* See SMBIOS 2.7.0 section 7.18 - Memory Device (Type 17) */ 728154972afSPatrick Mooney if (size_KB <= 0x7FFF) { 729154972afSPatrick Mooney /* Can represent up to 32767KB with the top bit set */ 730154972afSPatrick Mooney type17->size = size_KB | (1 << 15); 731154972afSPatrick Mooney } else if (size_MB < 0x7FFF) { 732154972afSPatrick Mooney /* Can represent up to 32766MB with the top bit unset */ 733154972afSPatrick Mooney type17->size = size_MB & 0x7FFF; 734154972afSPatrick Mooney } else { 735154972afSPatrick Mooney type17->size = 0x7FFF; 736154972afSPatrick Mooney /* 737154972afSPatrick Mooney * Can represent up to 2147483647MB (~2PB) 738154972afSPatrick Mooney * The top bit is reserved 739154972afSPatrick Mooney */ 740154972afSPatrick Mooney type17->xsize = size_MB & 0x7FFFFFFF; 741bf21cd93STycho Nightingale } 742bf21cd93STycho Nightingale 743bf21cd93STycho Nightingale return (0); 744bf21cd93STycho Nightingale } 745bf21cd93STycho Nightingale 746bf21cd93STycho Nightingale static int 747bf21cd93STycho Nightingale smbios_type19_initializer(struct smbios_structure *template_entry, 748bf21cd93STycho Nightingale const char **template_strings, char *curaddr, char **endaddr, 749bf21cd93STycho Nightingale uint16_t *n, uint16_t *size) 750bf21cd93STycho Nightingale { 751bf21cd93STycho Nightingale struct smbios_table_type19 *type19; 752bf21cd93STycho Nightingale 753bf21cd93STycho Nightingale smbios_generic_initializer(template_entry, template_strings, 754bf21cd93STycho Nightingale curaddr, endaddr, n, size); 755bf21cd93STycho Nightingale type19 = (struct smbios_table_type19 *)curaddr; 756bf21cd93STycho Nightingale type19->arrayhand = type16_handle; 757bf21cd93STycho Nightingale type19->xsaddr = 0; 758bf21cd93STycho Nightingale type19->xeaddr = guest_lomem; 759bf21cd93STycho Nightingale 760bf21cd93STycho Nightingale if (guest_himem > 0) { 761bf21cd93STycho Nightingale curaddr = *endaddr; 762bf21cd93STycho Nightingale smbios_generic_initializer(template_entry, template_strings, 763bf21cd93STycho Nightingale curaddr, endaddr, n, size); 764bf21cd93STycho Nightingale type19 = (struct smbios_table_type19 *)curaddr; 765bf21cd93STycho Nightingale type19->arrayhand = type16_handle; 766bf21cd93STycho Nightingale type19->xsaddr = 4*GB; 7676960cd89SAndy Fiddaman type19->xeaddr = type19->xsaddr + guest_himem; 768bf21cd93STycho Nightingale } 769bf21cd93STycho Nightingale 770bf21cd93STycho Nightingale return (0); 771bf21cd93STycho Nightingale } 772bf21cd93STycho Nightingale 773bf21cd93STycho Nightingale static void 774bf21cd93STycho Nightingale smbios_ep_initializer(struct smbios_entry_point *smbios_ep, uint32_t staddr) 775bf21cd93STycho Nightingale { 776bf21cd93STycho Nightingale memset(smbios_ep, 0, sizeof(*smbios_ep)); 777bf21cd93STycho Nightingale memcpy(smbios_ep->eanchor, SMBIOS_ENTRY_EANCHOR, 778bf21cd93STycho Nightingale SMBIOS_ENTRY_EANCHORLEN); 779bf21cd93STycho Nightingale smbios_ep->eplen = 0x1F; 780bf21cd93STycho Nightingale assert(sizeof (struct smbios_entry_point) == smbios_ep->eplen); 781bf21cd93STycho Nightingale smbios_ep->major = 2; 782bf21cd93STycho Nightingale smbios_ep->minor = 6; 783bf21cd93STycho Nightingale smbios_ep->revision = 0; 784bf21cd93STycho Nightingale memcpy(smbios_ep->ianchor, SMBIOS_ENTRY_IANCHOR, 785bf21cd93STycho Nightingale SMBIOS_ENTRY_IANCHORLEN); 786bf21cd93STycho Nightingale smbios_ep->staddr = staddr; 787154972afSPatrick Mooney smbios_ep->bcdrev = (smbios_ep->major & 0xf) << 4 | (smbios_ep->minor & 0xf); 788bf21cd93STycho Nightingale } 789bf21cd93STycho Nightingale 790bf21cd93STycho Nightingale static void 791bf21cd93STycho Nightingale smbios_ep_finalizer(struct smbios_entry_point *smbios_ep, uint16_t len, 792bf21cd93STycho Nightingale uint16_t num, uint16_t maxssize) 793bf21cd93STycho Nightingale { 794bf21cd93STycho Nightingale uint8_t checksum; 795bf21cd93STycho Nightingale int i; 796bf21cd93STycho Nightingale 797bf21cd93STycho Nightingale smbios_ep->maxssize = maxssize; 798bf21cd93STycho Nightingale smbios_ep->stlen = len; 799bf21cd93STycho Nightingale smbios_ep->stnum = num; 800bf21cd93STycho Nightingale 801bf21cd93STycho Nightingale checksum = 0; 802bf21cd93STycho Nightingale for (i = 0x10; i < 0x1f; i++) { 803bf21cd93STycho Nightingale checksum -= ((uint8_t *)smbios_ep)[i]; 804bf21cd93STycho Nightingale } 805bf21cd93STycho Nightingale smbios_ep->ichecksum = checksum; 806bf21cd93STycho Nightingale 807bf21cd93STycho Nightingale checksum = 0; 808bf21cd93STycho Nightingale for (i = 0; i < 0x1f; i++) { 809bf21cd93STycho Nightingale checksum -= ((uint8_t *)smbios_ep)[i]; 810bf21cd93STycho Nightingale } 811bf21cd93STycho Nightingale smbios_ep->echecksum = checksum; 812bf21cd93STycho Nightingale } 813bf21cd93STycho Nightingale 814bf21cd93STycho Nightingale int 815bf21cd93STycho Nightingale smbios_build(struct vmctx *ctx) 816bf21cd93STycho Nightingale { 817bf21cd93STycho Nightingale struct smbios_entry_point *smbios_ep; 818bf21cd93STycho Nightingale uint16_t n; 819bf21cd93STycho Nightingale uint16_t maxssize; 820bf21cd93STycho Nightingale char *curaddr, *startaddr, *ststartaddr; 821bf21cd93STycho Nightingale int i; 822bf21cd93STycho Nightingale int err; 823bf21cd93STycho Nightingale 824bf21cd93STycho Nightingale guest_lomem = vm_get_lowmem_size(ctx); 825bf21cd93STycho Nightingale guest_himem = vm_get_highmem_size(ctx); 826bf21cd93STycho Nightingale 827bf21cd93STycho Nightingale startaddr = paddr_guest2host(ctx, SMBIOS_BASE, SMBIOS_MAX_LENGTH); 828bf21cd93STycho Nightingale if (startaddr == NULL) { 829154972afSPatrick Mooney EPRINTLN("smbios table requires mapped mem"); 830bf21cd93STycho Nightingale return (ENOMEM); 831bf21cd93STycho Nightingale } 832bf21cd93STycho Nightingale 833bf21cd93STycho Nightingale curaddr = startaddr; 834bf21cd93STycho Nightingale 835bf21cd93STycho Nightingale smbios_ep = (struct smbios_entry_point *)curaddr; 836bf21cd93STycho Nightingale smbios_ep_initializer(smbios_ep, SMBIOS_BASE + 837bf21cd93STycho Nightingale sizeof(struct smbios_entry_point)); 838bf21cd93STycho Nightingale curaddr += sizeof(struct smbios_entry_point); 839bf21cd93STycho Nightingale ststartaddr = curaddr; 840bf21cd93STycho Nightingale 841bf21cd93STycho Nightingale n = 0; 842bf21cd93STycho Nightingale maxssize = 0; 843bf21cd93STycho Nightingale for (i = 0; smbios_template[i].entry != NULL; i++) { 844bf21cd93STycho Nightingale struct smbios_structure *entry; 845bf21cd93STycho Nightingale const char **strings; 846bf21cd93STycho Nightingale initializer_func_t initializer; 847bf21cd93STycho Nightingale char *endaddr; 848bf21cd93STycho Nightingale uint16_t size; 849bf21cd93STycho Nightingale 850bf21cd93STycho Nightingale entry = smbios_template[i].entry; 851bf21cd93STycho Nightingale strings = smbios_template[i].strings; 852bf21cd93STycho Nightingale initializer = smbios_template[i].initializer; 853bf21cd93STycho Nightingale 854bf21cd93STycho Nightingale err = (*initializer)(entry, strings, curaddr, &endaddr, 855bf21cd93STycho Nightingale &n, &size); 856bf21cd93STycho Nightingale if (err != 0) 857bf21cd93STycho Nightingale return (err); 858bf21cd93STycho Nightingale 859bf21cd93STycho Nightingale if (size > maxssize) 860bf21cd93STycho Nightingale maxssize = size; 861bf21cd93STycho Nightingale 862bf21cd93STycho Nightingale curaddr = endaddr; 863bf21cd93STycho Nightingale } 864bf21cd93STycho Nightingale 865bf21cd93STycho Nightingale assert(curaddr - startaddr < SMBIOS_MAX_LENGTH); 866bf21cd93STycho Nightingale smbios_ep_finalizer(smbios_ep, curaddr - ststartaddr, n, maxssize); 867bf21cd93STycho Nightingale 868bf21cd93STycho Nightingale return (0); 869bf21cd93STycho Nightingale } 8704c87aefeSPatrick Mooney 871*2b948146SAndy Fiddaman #ifndef __FreeBSD__ 872*2b948146SAndy Fiddaman struct { 873*2b948146SAndy Fiddaman const char *key; 874*2b948146SAndy Fiddaman const char **targetp; 875*2b948146SAndy Fiddaman } type1_map[] = { 876*2b948146SAndy Fiddaman { "manufacturer", &smbios_type1_strings[0] }, 877*2b948146SAndy Fiddaman { "product", &smbios_type1_strings[1] }, 878*2b948146SAndy Fiddaman { "version", &smbios_type1_strings[2] }, 879*2b948146SAndy Fiddaman { "serial", &smbios_type1_strings[3] }, 880*2b948146SAndy Fiddaman { "sku", &smbios_type1_strings[4] }, 881*2b948146SAndy Fiddaman { "family", &smbios_type1_strings[5] }, 882*2b948146SAndy Fiddaman { 0 } 883*2b948146SAndy Fiddaman }; 884*2b948146SAndy Fiddaman 885*2b948146SAndy Fiddaman void 886*2b948146SAndy Fiddaman smbios_apply(void) 887*2b948146SAndy Fiddaman { 888*2b948146SAndy Fiddaman nvlist_t *nvl; 889*2b948146SAndy Fiddaman 890*2b948146SAndy Fiddaman nvl = find_config_node("smbios"); 891*2b948146SAndy Fiddaman if (nvl == NULL) 892*2b948146SAndy Fiddaman return; 893*2b948146SAndy Fiddaman 894*2b948146SAndy Fiddaman for (uint_t i = 0; type1_map[i].key != NULL; i++) { 895*2b948146SAndy Fiddaman const char *value; 896*2b948146SAndy Fiddaman 897*2b948146SAndy Fiddaman value = get_config_value_node(nvl, type1_map[i].key); 898*2b948146SAndy Fiddaman if (value != NULL) 899*2b948146SAndy Fiddaman *type1_map[i].targetp = value; 900*2b948146SAndy Fiddaman } 901*2b948146SAndy Fiddaman } 902*2b948146SAndy Fiddaman 9034c87aefeSPatrick Mooney int 9044c87aefeSPatrick Mooney smbios_parse(const char *opts) 9054c87aefeSPatrick Mooney { 906*2b948146SAndy Fiddaman char *buf, *lasts, *token, *end; 907*2b948146SAndy Fiddaman nvlist_t *nvl; 9084c87aefeSPatrick Mooney long type; 9094c87aefeSPatrick Mooney 9104c87aefeSPatrick Mooney if ((buf = strdup(opts)) == NULL) { 9114c87aefeSPatrick Mooney (void) fprintf(stderr, "out of memory\n"); 9124c87aefeSPatrick Mooney return (-1); 9134c87aefeSPatrick Mooney } 9144c87aefeSPatrick Mooney 9154c87aefeSPatrick Mooney if ((token = strtok_r(buf, ",", &lasts)) == NULL) { 9164c87aefeSPatrick Mooney (void) fprintf(stderr, "too few fields\n"); 9174c87aefeSPatrick Mooney goto fail; 9184c87aefeSPatrick Mooney } 9194c87aefeSPatrick Mooney 9204c87aefeSPatrick Mooney errno = 0; 9214c87aefeSPatrick Mooney type = strtol(token, &end, 10); 9224c87aefeSPatrick Mooney if (errno != 0 || *end != '\0') { 9234c87aefeSPatrick Mooney (void) fprintf(stderr, "first token '%s' is not an integer\n", 9244c87aefeSPatrick Mooney token); 9254c87aefeSPatrick Mooney goto fail; 9264c87aefeSPatrick Mooney } 9274c87aefeSPatrick Mooney 9284c87aefeSPatrick Mooney /* For now, only type 1 is supported. */ 9294c87aefeSPatrick Mooney if (type != 1) { 9304c87aefeSPatrick Mooney (void) fprintf(stderr, "unsupported type %d\n", type); 9314c87aefeSPatrick Mooney goto fail; 9324c87aefeSPatrick Mooney } 9334c87aefeSPatrick Mooney 934*2b948146SAndy Fiddaman nvl = create_config_node("smbios"); 935*2b948146SAndy Fiddaman if (nvl == NULL) { 936*2b948146SAndy Fiddaman (void) fprintf(stderr, "out of memory\n"); 937*2b948146SAndy Fiddaman return (-1); 938*2b948146SAndy Fiddaman } 939*2b948146SAndy Fiddaman 9404c87aefeSPatrick Mooney while ((token = strtok_r(NULL, ",", &lasts)) != NULL) { 9414c87aefeSPatrick Mooney char *val; 942*2b948146SAndy Fiddaman uint_t i; 9434c87aefeSPatrick Mooney 9444c87aefeSPatrick Mooney if ((val = strchr(token, '=')) == NULL) { 9454c87aefeSPatrick Mooney (void) fprintf(stderr, "invalid key=value: '%s'\n", 9464c87aefeSPatrick Mooney token); 9474c87aefeSPatrick Mooney goto fail; 9484c87aefeSPatrick Mooney } 9494c87aefeSPatrick Mooney *val = '\0'; 9504c87aefeSPatrick Mooney val++; 9514c87aefeSPatrick Mooney 952*2b948146SAndy Fiddaman if (strcmp(token, "uuid") == 0) { 953*2b948146SAndy Fiddaman set_config_value_node(nvl, token, val); 954*2b948146SAndy Fiddaman continue; 955*2b948146SAndy Fiddaman } 956*2b948146SAndy Fiddaman 9574c87aefeSPatrick Mooney for (i = 0; type1_map[i].key != NULL; i++) { 9584c87aefeSPatrick Mooney if (strcmp(token, type1_map[i].key) == 0) { 9594c87aefeSPatrick Mooney break; 9604c87aefeSPatrick Mooney } 9614c87aefeSPatrick Mooney } 9624c87aefeSPatrick Mooney if (type1_map[i].key == NULL) { 9634c87aefeSPatrick Mooney (void) fprintf(stderr, "invalid key '%s'\n", token); 9644c87aefeSPatrick Mooney goto fail; 9654c87aefeSPatrick Mooney } 966*2b948146SAndy Fiddaman set_config_value_node(nvl, token, val); 9674c87aefeSPatrick Mooney } 9684c87aefeSPatrick Mooney 9694c87aefeSPatrick Mooney return (0); 9704c87aefeSPatrick Mooney 9714c87aefeSPatrick Mooney fail: 9724c87aefeSPatrick Mooney free(buf); 9734c87aefeSPatrick Mooney return (-1); 9744c87aefeSPatrick Mooney } 975*2b948146SAndy Fiddaman #endif 976