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