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