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