1243327Sgrehan/*- 2243327Sgrehan * Copyright (c) 2012 NetApp, Inc. 3243327Sgrehan * All rights reserved. 4243327Sgrehan * 5243327Sgrehan * Redistribution and use in source and binary forms, with or without 6243327Sgrehan * modification, are permitted provided that the following conditions 7243327Sgrehan * are met: 8243327Sgrehan * 1. Redistributions of source code must retain the above copyright 9243327Sgrehan * notice, this list of conditions and the following disclaimer. 10243327Sgrehan * 2. Redistributions in binary form must reproduce the above copyright 11243327Sgrehan * notice, this list of conditions and the following disclaimer in the 12243327Sgrehan * documentation and/or other materials provided with the distribution. 13243327Sgrehan * 14243327Sgrehan * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 15243327Sgrehan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16243327Sgrehan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17243327Sgrehan * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 18243327Sgrehan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19243327Sgrehan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20243327Sgrehan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21243327Sgrehan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22243327Sgrehan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23243327Sgrehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24243327Sgrehan * SUCH DAMAGE. 25243327Sgrehan * 26243327Sgrehan * $FreeBSD: releng/11.0/usr.sbin/bhyve/acpi.c 287927 2015-09-17 18:11:26Z delphij $ 27243327Sgrehan */ 28243327Sgrehan 29243327Sgrehan/* 30243327Sgrehan * bhyve ACPI table generator. 31243327Sgrehan * 32243327Sgrehan * Create the minimal set of ACPI tables required to boot FreeBSD (and 33243327Sgrehan * hopefully other o/s's) by writing out ASL template files for each of 34243327Sgrehan * the tables and the compiling them to AML with the Intel iasl compiler. 35243327Sgrehan * The AML files are then read into guest memory. 36243327Sgrehan * 37243327Sgrehan * The tables are placed in the guest's ROM area just below 1MB physical, 38243327Sgrehan * above the MPTable. 39243327Sgrehan * 40243327Sgrehan * Layout 41243327Sgrehan * ------ 42262744Stychon * RSDP -> 0xf2400 (36 bytes fixed) 43269700Sneel * RSDT -> 0xf2440 (36 bytes + 4*7 table addrs, 4 used) 44269700Sneel * XSDT -> 0xf2480 (36 bytes + 8*7 table addrs, 4 used) 45262744Stychon * MADT -> 0xf2500 (depends on #CPUs) 46262744Stychon * FADT -> 0xf2600 (268 bytes) 47262744Stychon * HPET -> 0xf2740 (56 bytes) 48269700Sneel * MCFG -> 0xf2780 (60 bytes) 49269700Sneel * FACS -> 0xf27C0 (64 bytes) 50262744Stychon * DSDT -> 0xf2800 (variable - can go up to 0x100000) 51243327Sgrehan */ 52243327Sgrehan 53243327Sgrehan#include <sys/cdefs.h> 54243327Sgrehan__FBSDID("$FreeBSD: releng/11.0/usr.sbin/bhyve/acpi.c 287927 2015-09-17 18:11:26Z delphij $"); 55243327Sgrehan 56243327Sgrehan#include <sys/param.h> 57243327Sgrehan#include <sys/errno.h> 58243327Sgrehan#include <sys/stat.h> 59243327Sgrehan 60243327Sgrehan#include <paths.h> 61260206Sjhb#include <stdarg.h> 62243327Sgrehan#include <stdio.h> 63243327Sgrehan#include <stdlib.h> 64243327Sgrehan#include <string.h> 65243327Sgrehan#include <unistd.h> 66243327Sgrehan 67258579Sneel#include <machine/vmm.h> 68258579Sneel#include <vmmapi.h> 69258579Sneel 70244167Sgrehan#include "bhyverun.h" 71243327Sgrehan#include "acpi.h" 72260206Sjhb#include "pci_emul.h" 73243327Sgrehan 74243327Sgrehan/* 75243327Sgrehan * Define the base address of the ACPI tables, and the offsets to 76243327Sgrehan * the individual tables 77243327Sgrehan */ 78262744Stychon#define BHYVE_ACPI_BASE 0xf2400 79243327Sgrehan#define RSDT_OFFSET 0x040 80243704Sgrehan#define XSDT_OFFSET 0x080 81243704Sgrehan#define MADT_OFFSET 0x100 82243327Sgrehan#define FADT_OFFSET 0x200 83258579Sneel#define HPET_OFFSET 0x340 84269700Sneel#define MCFG_OFFSET 0x380 85269700Sneel#define FACS_OFFSET 0x3C0 86243327Sgrehan#define DSDT_OFFSET 0x400 87243327Sgrehan 88243327Sgrehan#define BHYVE_ASL_TEMPLATE "bhyve.XXXXXXX" 89243327Sgrehan#define BHYVE_ASL_SUFFIX ".aml" 90243327Sgrehan#define BHYVE_ASL_COMPILER "/usr/sbin/iasl" 91243327Sgrehan 92243327Sgrehanstatic int basl_keep_temps; 93243327Sgrehanstatic int basl_verbose_iasl; 94243327Sgrehanstatic int basl_ncpu; 95243327Sgrehanstatic uint32_t basl_acpi_base = BHYVE_ACPI_BASE; 96258579Sneelstatic uint32_t hpet_capabilities; 97243327Sgrehan 98243327Sgrehan/* 99243327Sgrehan * Contains the full pathname of the template to be passed 100243327Sgrehan * to mkstemp/mktemps(3) 101243327Sgrehan */ 102243327Sgrehanstatic char basl_template[MAXPATHLEN]; 103243327Sgrehanstatic char basl_stemplate[MAXPATHLEN]; 104243327Sgrehan 105260206Sjhb/* 106260206Sjhb * State for dsdt_line(), dsdt_indent(), and dsdt_unindent(). 107260206Sjhb */ 108260206Sjhbstatic FILE *dsdt_fp; 109260206Sjhbstatic int dsdt_indent_level; 110260206Sjhbstatic int dsdt_error; 111260206Sjhb 112243327Sgrehanstruct basl_fio { 113243327Sgrehan int fd; 114243327Sgrehan FILE *fp; 115243327Sgrehan char f_name[MAXPATHLEN]; 116243327Sgrehan}; 117243327Sgrehan 118243327Sgrehan#define EFPRINTF(...) \ 119243327Sgrehan err = fprintf(__VA_ARGS__); if (err < 0) goto err_exit; 120243327Sgrehan 121243327Sgrehan#define EFFLUSH(x) \ 122243327Sgrehan err = fflush(x); if (err != 0) goto err_exit; 123243327Sgrehan 124243327Sgrehanstatic int 125243327Sgrehanbasl_fwrite_rsdp(FILE *fp) 126243327Sgrehan{ 127243327Sgrehan int err; 128243327Sgrehan 129243327Sgrehan err = 0; 130243327Sgrehan 131243327Sgrehan EFPRINTF(fp, "/*\n"); 132243327Sgrehan EFPRINTF(fp, " * bhyve RSDP template\n"); 133243327Sgrehan EFPRINTF(fp, " */\n"); 134243327Sgrehan EFPRINTF(fp, "[0008]\t\tSignature : \"RSD PTR \"\n"); 135243327Sgrehan EFPRINTF(fp, "[0001]\t\tChecksum : 43\n"); 136243327Sgrehan EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n"); 137243327Sgrehan EFPRINTF(fp, "[0001]\t\tRevision : 02\n"); 138243327Sgrehan EFPRINTF(fp, "[0004]\t\tRSDT Address : %08X\n", 139243327Sgrehan basl_acpi_base + RSDT_OFFSET); 140243327Sgrehan EFPRINTF(fp, "[0004]\t\tLength : 00000024\n"); 141243704Sgrehan EFPRINTF(fp, "[0008]\t\tXSDT Address : 00000000%08X\n", 142243704Sgrehan basl_acpi_base + XSDT_OFFSET); 143243327Sgrehan EFPRINTF(fp, "[0001]\t\tExtended Checksum : 00\n"); 144243327Sgrehan EFPRINTF(fp, "[0003]\t\tReserved : 000000\n"); 145243327Sgrehan 146243327Sgrehan EFFLUSH(fp); 147243327Sgrehan 148243327Sgrehan return (0); 149243327Sgrehan 150243327Sgrehanerr_exit: 151243327Sgrehan return (errno); 152243327Sgrehan} 153243327Sgrehan 154243327Sgrehanstatic int 155243327Sgrehanbasl_fwrite_rsdt(FILE *fp) 156243327Sgrehan{ 157243327Sgrehan int err; 158243327Sgrehan 159243327Sgrehan err = 0; 160243327Sgrehan 161243327Sgrehan EFPRINTF(fp, "/*\n"); 162243327Sgrehan EFPRINTF(fp, " * bhyve RSDT template\n"); 163243327Sgrehan EFPRINTF(fp, " */\n"); 164243327Sgrehan EFPRINTF(fp, "[0004]\t\tSignature : \"RSDT\"\n"); 165243327Sgrehan EFPRINTF(fp, "[0004]\t\tTable Length : 00000000\n"); 166243327Sgrehan EFPRINTF(fp, "[0001]\t\tRevision : 01\n"); 167243327Sgrehan EFPRINTF(fp, "[0001]\t\tChecksum : 00\n"); 168243327Sgrehan EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n"); 169243327Sgrehan EFPRINTF(fp, "[0008]\t\tOem Table ID : \"BVRSDT \"\n"); 170243327Sgrehan EFPRINTF(fp, "[0004]\t\tOem Revision : 00000001\n"); 171243327Sgrehan /* iasl will fill in the compiler ID/revision fields */ 172243327Sgrehan EFPRINTF(fp, "[0004]\t\tAsl Compiler ID : \"xxxx\"\n"); 173243327Sgrehan EFPRINTF(fp, "[0004]\t\tAsl Compiler Revision : 00000000\n"); 174243327Sgrehan EFPRINTF(fp, "\n"); 175243327Sgrehan 176258579Sneel /* Add in pointers to the MADT, FADT and HPET */ 177243327Sgrehan EFPRINTF(fp, "[0004]\t\tACPI Table Address 0 : %08X\n", 178243327Sgrehan basl_acpi_base + MADT_OFFSET); 179243327Sgrehan EFPRINTF(fp, "[0004]\t\tACPI Table Address 1 : %08X\n", 180243327Sgrehan basl_acpi_base + FADT_OFFSET); 181258579Sneel EFPRINTF(fp, "[0004]\t\tACPI Table Address 2 : %08X\n", 182258579Sneel basl_acpi_base + HPET_OFFSET); 183269700Sneel EFPRINTF(fp, "[0004]\t\tACPI Table Address 3 : %08X\n", 184269700Sneel basl_acpi_base + MCFG_OFFSET); 185243327Sgrehan 186243327Sgrehan EFFLUSH(fp); 187243327Sgrehan 188243327Sgrehan return (0); 189243327Sgrehan 190243327Sgrehanerr_exit: 191243327Sgrehan return (errno); 192243327Sgrehan} 193243327Sgrehan 194243327Sgrehanstatic int 195243704Sgrehanbasl_fwrite_xsdt(FILE *fp) 196243704Sgrehan{ 197243704Sgrehan int err; 198243704Sgrehan 199243704Sgrehan err = 0; 200243704Sgrehan 201243704Sgrehan EFPRINTF(fp, "/*\n"); 202243704Sgrehan EFPRINTF(fp, " * bhyve XSDT template\n"); 203243704Sgrehan EFPRINTF(fp, " */\n"); 204243704Sgrehan EFPRINTF(fp, "[0004]\t\tSignature : \"XSDT\"\n"); 205243704Sgrehan EFPRINTF(fp, "[0004]\t\tTable Length : 00000000\n"); 206243704Sgrehan EFPRINTF(fp, "[0001]\t\tRevision : 01\n"); 207243704Sgrehan EFPRINTF(fp, "[0001]\t\tChecksum : 00\n"); 208243704Sgrehan EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n"); 209243704Sgrehan EFPRINTF(fp, "[0008]\t\tOem Table ID : \"BVXSDT \"\n"); 210243704Sgrehan EFPRINTF(fp, "[0004]\t\tOem Revision : 00000001\n"); 211243704Sgrehan /* iasl will fill in the compiler ID/revision fields */ 212243704Sgrehan EFPRINTF(fp, "[0004]\t\tAsl Compiler ID : \"xxxx\"\n"); 213243704Sgrehan EFPRINTF(fp, "[0004]\t\tAsl Compiler Revision : 00000000\n"); 214243704Sgrehan EFPRINTF(fp, "\n"); 215243704Sgrehan 216258579Sneel /* Add in pointers to the MADT, FADT and HPET */ 217243704Sgrehan EFPRINTF(fp, "[0004]\t\tACPI Table Address 0 : 00000000%08X\n", 218243704Sgrehan basl_acpi_base + MADT_OFFSET); 219243704Sgrehan EFPRINTF(fp, "[0004]\t\tACPI Table Address 1 : 00000000%08X\n", 220243704Sgrehan basl_acpi_base + FADT_OFFSET); 221258579Sneel EFPRINTF(fp, "[0004]\t\tACPI Table Address 2 : 00000000%08X\n", 222258579Sneel basl_acpi_base + HPET_OFFSET); 223269700Sneel EFPRINTF(fp, "[0004]\t\tACPI Table Address 3 : 00000000%08X\n", 224269700Sneel basl_acpi_base + MCFG_OFFSET); 225243704Sgrehan 226243704Sgrehan EFFLUSH(fp); 227243704Sgrehan 228243704Sgrehan return (0); 229243704Sgrehan 230243704Sgrehanerr_exit: 231243704Sgrehan return (errno); 232243704Sgrehan} 233243704Sgrehan 234243704Sgrehanstatic int 235243327Sgrehanbasl_fwrite_madt(FILE *fp) 236243327Sgrehan{ 237243327Sgrehan int err; 238243327Sgrehan int i; 239243327Sgrehan 240243327Sgrehan err = 0; 241243327Sgrehan 242243327Sgrehan EFPRINTF(fp, "/*\n"); 243243327Sgrehan EFPRINTF(fp, " * bhyve MADT template\n"); 244243327Sgrehan EFPRINTF(fp, " */\n"); 245243327Sgrehan EFPRINTF(fp, "[0004]\t\tSignature : \"APIC\"\n"); 246243327Sgrehan EFPRINTF(fp, "[0004]\t\tTable Length : 00000000\n"); 247243327Sgrehan EFPRINTF(fp, "[0001]\t\tRevision : 01\n"); 248243327Sgrehan EFPRINTF(fp, "[0001]\t\tChecksum : 00\n"); 249243327Sgrehan EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n"); 250243327Sgrehan EFPRINTF(fp, "[0008]\t\tOem Table ID : \"BVMADT \"\n"); 251243327Sgrehan EFPRINTF(fp, "[0004]\t\tOem Revision : 00000001\n"); 252243327Sgrehan 253243327Sgrehan /* iasl will fill in the compiler ID/revision fields */ 254243327Sgrehan EFPRINTF(fp, "[0004]\t\tAsl Compiler ID : \"xxxx\"\n"); 255243327Sgrehan EFPRINTF(fp, "[0004]\t\tAsl Compiler Revision : 00000000\n"); 256243327Sgrehan EFPRINTF(fp, "\n"); 257243327Sgrehan 258243327Sgrehan EFPRINTF(fp, "[0004]\t\tLocal Apic Address : FEE00000\n"); 259243327Sgrehan EFPRINTF(fp, "[0004]\t\tFlags (decoded below) : 00000001\n"); 260243327Sgrehan EFPRINTF(fp, "\t\t\tPC-AT Compatibility : 1\n"); 261243327Sgrehan EFPRINTF(fp, "\n"); 262243327Sgrehan 263243327Sgrehan /* Add a Processor Local APIC entry for each CPU */ 264243327Sgrehan for (i = 0; i < basl_ncpu; i++) { 265243327Sgrehan EFPRINTF(fp, "[0001]\t\tSubtable Type : 00\n"); 266243327Sgrehan EFPRINTF(fp, "[0001]\t\tLength : 08\n"); 267255438Sgrehan /* iasl expects hex values for the proc and apic id's */ 268255438Sgrehan EFPRINTF(fp, "[0001]\t\tProcessor ID : %02x\n", i); 269255438Sgrehan EFPRINTF(fp, "[0001]\t\tLocal Apic ID : %02x\n", i); 270243327Sgrehan EFPRINTF(fp, "[0004]\t\tFlags (decoded below) : 00000001\n"); 271243327Sgrehan EFPRINTF(fp, "\t\t\tProcessor Enabled : 1\n"); 272243327Sgrehan EFPRINTF(fp, "\n"); 273243327Sgrehan } 274243327Sgrehan 275258699Sneel /* Always a single IOAPIC entry, with ID 0 */ 276243327Sgrehan EFPRINTF(fp, "[0001]\t\tSubtable Type : 01\n"); 277243327Sgrehan EFPRINTF(fp, "[0001]\t\tLength : 0C\n"); 278255438Sgrehan /* iasl expects a hex value for the i/o apic id */ 279258609Sneel EFPRINTF(fp, "[0001]\t\tI/O Apic ID : %02x\n", 0); 280243327Sgrehan EFPRINTF(fp, "[0001]\t\tReserved : 00\n"); 281243327Sgrehan EFPRINTF(fp, "[0004]\t\tAddress : fec00000\n"); 282243327Sgrehan EFPRINTF(fp, "[0004]\t\tInterrupt : 00000000\n"); 283243327Sgrehan EFPRINTF(fp, "\n"); 284243327Sgrehan 285257933Sneel /* Legacy IRQ0 is connected to pin 2 of the IOAPIC */ 286243327Sgrehan EFPRINTF(fp, "[0001]\t\tSubtable Type : 02\n"); 287243327Sgrehan EFPRINTF(fp, "[0001]\t\tLength : 0A\n"); 288243327Sgrehan EFPRINTF(fp, "[0001]\t\tBus : 00\n"); 289257933Sneel EFPRINTF(fp, "[0001]\t\tSource : 00\n"); 290257933Sneel EFPRINTF(fp, "[0004]\t\tInterrupt : 00000002\n"); 291257933Sneel EFPRINTF(fp, "[0002]\t\tFlags (decoded below) : 0005\n"); 292257933Sneel EFPRINTF(fp, "\t\t\tPolarity : 1\n"); 293257933Sneel EFPRINTF(fp, "\t\t\tTrigger Mode : 1\n"); 294257933Sneel EFPRINTF(fp, "\n"); 295257933Sneel 296257933Sneel EFPRINTF(fp, "[0001]\t\tSubtable Type : 02\n"); 297257933Sneel EFPRINTF(fp, "[0001]\t\tLength : 0A\n"); 298257933Sneel EFPRINTF(fp, "[0001]\t\tBus : 00\n"); 299259998Sjhb EFPRINTF(fp, "[0001]\t\tSource : %02X\n", SCI_INT); 300259998Sjhb EFPRINTF(fp, "[0004]\t\tInterrupt : %08X\n", SCI_INT); 301243327Sgrehan EFPRINTF(fp, "[0002]\t\tFlags (decoded below) : 0000\n"); 302259998Sjhb EFPRINTF(fp, "\t\t\tPolarity : 3\n"); 303259998Sjhb EFPRINTF(fp, "\t\t\tTrigger Mode : 3\n"); 304243327Sgrehan EFPRINTF(fp, "\n"); 305243327Sgrehan 306259779Sjhb /* Local APIC NMI is connected to LINT 1 on all CPUs */ 307259779Sjhb EFPRINTF(fp, "[0001]\t\tSubtable Type : 04\n"); 308259779Sjhb EFPRINTF(fp, "[0001]\t\tLength : 06\n"); 309259779Sjhb EFPRINTF(fp, "[0001]\t\tProcessorId : FF\n"); 310259779Sjhb EFPRINTF(fp, "[0002]\t\tFlags (decoded below) : 0005\n"); 311259779Sjhb EFPRINTF(fp, "\t\t\tPolarity : 1\n"); 312259779Sjhb EFPRINTF(fp, "\t\t\tTrigger Mode : 1\n"); 313259779Sjhb EFPRINTF(fp, "[0001]\t\tInterrupt : 01\n"); 314259779Sjhb EFPRINTF(fp, "\n"); 315259779Sjhb 316243327Sgrehan EFFLUSH(fp); 317243327Sgrehan 318243327Sgrehan return (0); 319243327Sgrehan 320243327Sgrehanerr_exit: 321243327Sgrehan return (errno); 322243327Sgrehan} 323243327Sgrehan 324243327Sgrehanstatic int 325243327Sgrehanbasl_fwrite_fadt(FILE *fp) 326243327Sgrehan{ 327243327Sgrehan int err; 328243327Sgrehan 329243327Sgrehan err = 0; 330243327Sgrehan 331243327Sgrehan EFPRINTF(fp, "/*\n"); 332243327Sgrehan EFPRINTF(fp, " * bhyve FADT template\n"); 333243327Sgrehan EFPRINTF(fp, " */\n"); 334243327Sgrehan EFPRINTF(fp, "[0004]\t\tSignature : \"FACP\"\n"); 335243327Sgrehan EFPRINTF(fp, "[0004]\t\tTable Length : 0000010C\n"); 336243327Sgrehan EFPRINTF(fp, "[0001]\t\tRevision : 05\n"); 337243327Sgrehan EFPRINTF(fp, "[0001]\t\tChecksum : 00\n"); 338243327Sgrehan EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n"); 339243327Sgrehan EFPRINTF(fp, "[0008]\t\tOem Table ID : \"BVFACP \"\n"); 340243327Sgrehan EFPRINTF(fp, "[0004]\t\tOem Revision : 00000001\n"); 341243327Sgrehan /* iasl will fill in the compiler ID/revision fields */ 342243327Sgrehan EFPRINTF(fp, "[0004]\t\tAsl Compiler ID : \"xxxx\"\n"); 343243327Sgrehan EFPRINTF(fp, "[0004]\t\tAsl Compiler Revision : 00000000\n"); 344243327Sgrehan EFPRINTF(fp, "\n"); 345243327Sgrehan 346243327Sgrehan EFPRINTF(fp, "[0004]\t\tFACS Address : %08X\n", 347243327Sgrehan basl_acpi_base + FACS_OFFSET); 348243327Sgrehan EFPRINTF(fp, "[0004]\t\tDSDT Address : %08X\n", 349243327Sgrehan basl_acpi_base + DSDT_OFFSET); 350259998Sjhb EFPRINTF(fp, "[0001]\t\tModel : 01\n"); 351243327Sgrehan EFPRINTF(fp, "[0001]\t\tPM Profile : 00 [Unspecified]\n"); 352259998Sjhb EFPRINTF(fp, "[0002]\t\tSCI Interrupt : %04X\n", 353259998Sjhb SCI_INT); 354259998Sjhb EFPRINTF(fp, "[0004]\t\tSMI Command Port : %08X\n", 355259998Sjhb SMI_CMD); 356259998Sjhb EFPRINTF(fp, "[0001]\t\tACPI Enable Value : %02X\n", 357259998Sjhb BHYVE_ACPI_ENABLE); 358259998Sjhb EFPRINTF(fp, "[0001]\t\tACPI Disable Value : %02X\n", 359259998Sjhb BHYVE_ACPI_DISABLE); 360243327Sgrehan EFPRINTF(fp, "[0001]\t\tS4BIOS Command : 00\n"); 361243327Sgrehan EFPRINTF(fp, "[0001]\t\tP-State Control : 00\n"); 362259826Sjhb EFPRINTF(fp, "[0004]\t\tPM1A Event Block Address : %08X\n", 363259998Sjhb PM1A_EVT_ADDR); 364243327Sgrehan EFPRINTF(fp, "[0004]\t\tPM1B Event Block Address : 00000000\n"); 365259826Sjhb EFPRINTF(fp, "[0004]\t\tPM1A Control Block Address : %08X\n", 366259998Sjhb PM1A_CNT_ADDR); 367243327Sgrehan EFPRINTF(fp, "[0004]\t\tPM1B Control Block Address : 00000000\n"); 368243327Sgrehan EFPRINTF(fp, "[0004]\t\tPM2 Control Block Address : 00000000\n"); 369243327Sgrehan EFPRINTF(fp, "[0004]\t\tPM Timer Block Address : %08X\n", 370259998Sjhb IO_PMTMR); 371243327Sgrehan EFPRINTF(fp, "[0004]\t\tGPE0 Block Address : 00000000\n"); 372243327Sgrehan EFPRINTF(fp, "[0004]\t\tGPE1 Block Address : 00000000\n"); 373243327Sgrehan EFPRINTF(fp, "[0001]\t\tPM1 Event Block Length : 04\n"); 374243327Sgrehan EFPRINTF(fp, "[0001]\t\tPM1 Control Block Length : 02\n"); 375243327Sgrehan EFPRINTF(fp, "[0001]\t\tPM2 Control Block Length : 00\n"); 376243327Sgrehan EFPRINTF(fp, "[0001]\t\tPM Timer Block Length : 04\n"); 377243327Sgrehan EFPRINTF(fp, "[0001]\t\tGPE0 Block Length : 00\n"); 378243327Sgrehan EFPRINTF(fp, "[0001]\t\tGPE1 Block Length : 00\n"); 379243327Sgrehan EFPRINTF(fp, "[0001]\t\tGPE1 Base Offset : 00\n"); 380243327Sgrehan EFPRINTF(fp, "[0001]\t\t_CST Support : 00\n"); 381243327Sgrehan EFPRINTF(fp, "[0002]\t\tC2 Latency : 0000\n"); 382243327Sgrehan EFPRINTF(fp, "[0002]\t\tC3 Latency : 0000\n"); 383243327Sgrehan EFPRINTF(fp, "[0002]\t\tCPU Cache Size : 0000\n"); 384243327Sgrehan EFPRINTF(fp, "[0002]\t\tCache Flush Stride : 0000\n"); 385243327Sgrehan EFPRINTF(fp, "[0001]\t\tDuty Cycle Offset : 00\n"); 386243327Sgrehan EFPRINTF(fp, "[0001]\t\tDuty Cycle Width : 00\n"); 387243327Sgrehan EFPRINTF(fp, "[0001]\t\tRTC Day Alarm Index : 00\n"); 388243327Sgrehan EFPRINTF(fp, "[0001]\t\tRTC Month Alarm Index : 00\n"); 389282206Sneel EFPRINTF(fp, "[0001]\t\tRTC Century Index : 32\n"); 390243327Sgrehan EFPRINTF(fp, "[0002]\t\tBoot Flags (decoded below) : 0000\n"); 391243327Sgrehan EFPRINTF(fp, "\t\t\tLegacy Devices Supported (V2) : 0\n"); 392243327Sgrehan EFPRINTF(fp, "\t\t\t8042 Present on ports 60/64 (V2) : 0\n"); 393243327Sgrehan EFPRINTF(fp, "\t\t\tVGA Not Present (V4) : 1\n"); 394243327Sgrehan EFPRINTF(fp, "\t\t\tMSI Not Supported (V4) : 0\n"); 395243327Sgrehan EFPRINTF(fp, "\t\t\tPCIe ASPM Not Supported (V4) : 1\n"); 396243327Sgrehan EFPRINTF(fp, "\t\t\tCMOS RTC Not Present (V5) : 0\n"); 397243327Sgrehan EFPRINTF(fp, "[0001]\t\tReserved : 00\n"); 398243327Sgrehan EFPRINTF(fp, "[0004]\t\tFlags (decoded below) : 00000000\n"); 399243327Sgrehan EFPRINTF(fp, "\t\t\tWBINVD instruction is operational (V1) : 1\n"); 400243327Sgrehan EFPRINTF(fp, "\t\t\tWBINVD flushes all caches (V1) : 0\n"); 401259826Sjhb EFPRINTF(fp, "\t\t\tAll CPUs support C1 (V1) : 1\n"); 402243327Sgrehan EFPRINTF(fp, "\t\t\tC2 works on MP system (V1) : 0\n"); 403259998Sjhb EFPRINTF(fp, "\t\t\tControl Method Power Button (V1) : 0\n"); 404243327Sgrehan EFPRINTF(fp, "\t\t\tControl Method Sleep Button (V1) : 1\n"); 405243327Sgrehan EFPRINTF(fp, "\t\t\tRTC wake not in fixed reg space (V1) : 0\n"); 406243327Sgrehan EFPRINTF(fp, "\t\t\tRTC can wake system from S4 (V1) : 0\n"); 407243327Sgrehan EFPRINTF(fp, "\t\t\t32-bit PM Timer (V1) : 1\n"); 408243327Sgrehan EFPRINTF(fp, "\t\t\tDocking Supported (V1) : 0\n"); 409259826Sjhb EFPRINTF(fp, "\t\t\tReset Register Supported (V2) : 1\n"); 410243327Sgrehan EFPRINTF(fp, "\t\t\tSealed Case (V3) : 0\n"); 411243327Sgrehan EFPRINTF(fp, "\t\t\tHeadless - No Video (V3) : 1\n"); 412243327Sgrehan EFPRINTF(fp, "\t\t\tUse native instr after SLP_TYPx (V3) : 0\n"); 413243327Sgrehan EFPRINTF(fp, "\t\t\tPCIEXP_WAK Bits Supported (V4) : 0\n"); 414243327Sgrehan EFPRINTF(fp, "\t\t\tUse Platform Timer (V4) : 0\n"); 415243327Sgrehan EFPRINTF(fp, "\t\t\tRTC_STS valid on S4 wake (V4) : 0\n"); 416243327Sgrehan EFPRINTF(fp, "\t\t\tRemote Power-on capable (V4) : 0\n"); 417243327Sgrehan EFPRINTF(fp, "\t\t\tUse APIC Cluster Model (V4) : 0\n"); 418243327Sgrehan EFPRINTF(fp, "\t\t\tUse APIC Physical Destination Mode (V4) : 1\n"); 419243327Sgrehan EFPRINTF(fp, "\t\t\tHardware Reduced (V5) : 0\n"); 420243327Sgrehan EFPRINTF(fp, "\t\t\tLow Power S0 Idle (V5) : 0\n"); 421243327Sgrehan EFPRINTF(fp, "\n"); 422243327Sgrehan 423243327Sgrehan EFPRINTF(fp, 424243327Sgrehan "[0012]\t\tReset Register : [Generic Address Structure]\n"); 425243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 426243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 08\n"); 427243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 428243327Sgrehan EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 01 [Byte Access:8]\n"); 429259826Sjhb EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000CF9\n"); 430243327Sgrehan EFPRINTF(fp, "\n"); 431243327Sgrehan 432259826Sjhb EFPRINTF(fp, "[0001]\t\tValue to cause reset : 06\n"); 433272481Sgrehan EFPRINTF(fp, "[0002]\t\tARM Flags (decoded below): 0000\n"); 434272481Sgrehan EFPRINTF(fp, "\t\t\tPSCI Compliant : 0\n"); 435272481Sgrehan EFPRINTF(fp, "\t\t\tMust use HVC for PSCI : 0\n"); 436272481Sgrehan EFPRINTF(fp, "[0001]\t\tFADT Minor Revision : 01\n"); 437243327Sgrehan EFPRINTF(fp, "[0008]\t\tFACS Address : 00000000%08X\n", 438243327Sgrehan basl_acpi_base + FACS_OFFSET); 439243327Sgrehan EFPRINTF(fp, "[0008]\t\tDSDT Address : 00000000%08X\n", 440243327Sgrehan basl_acpi_base + DSDT_OFFSET); 441243327Sgrehan EFPRINTF(fp, 442243327Sgrehan "[0012]\t\tPM1A Event Block : [Generic Address Structure]\n"); 443243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 444243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 20\n"); 445243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 446243327Sgrehan EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 02 [Word Access:16]\n"); 447259826Sjhb EFPRINTF(fp, "[0008]\t\tAddress : 00000000%08X\n", 448259998Sjhb PM1A_EVT_ADDR); 449243327Sgrehan EFPRINTF(fp, "\n"); 450243327Sgrehan 451243327Sgrehan EFPRINTF(fp, 452243327Sgrehan "[0012]\t\tPM1B Event Block : [Generic Address Structure]\n"); 453243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 454243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 00\n"); 455243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 456243327Sgrehan EFPRINTF(fp, 457243327Sgrehan "[0001]\t\tEncoded Access Width : 00 [Undefined/Legacy]\n"); 458243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n"); 459243327Sgrehan EFPRINTF(fp, "\n"); 460243327Sgrehan 461243327Sgrehan EFPRINTF(fp, 462243327Sgrehan "[0012]\t\tPM1A Control Block : [Generic Address Structure]\n"); 463243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 464243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 10\n"); 465243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 466243327Sgrehan EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 02 [Word Access:16]\n"); 467259826Sjhb EFPRINTF(fp, "[0008]\t\tAddress : 00000000%08X\n", 468259998Sjhb PM1A_CNT_ADDR); 469243327Sgrehan EFPRINTF(fp, "\n"); 470243327Sgrehan 471243327Sgrehan EFPRINTF(fp, 472243327Sgrehan "[0012]\t\tPM1B Control Block : [Generic Address Structure]\n"); 473243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 474243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 00\n"); 475243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 476243327Sgrehan EFPRINTF(fp, 477243327Sgrehan "[0001]\t\tEncoded Access Width : 00 [Undefined/Legacy]\n"); 478243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n"); 479243327Sgrehan EFPRINTF(fp, "\n"); 480243327Sgrehan 481243327Sgrehan EFPRINTF(fp, 482243327Sgrehan "[0012]\t\tPM2 Control Block : [Generic Address Structure]\n"); 483243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 484243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 08\n"); 485243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 486243327Sgrehan EFPRINTF(fp, 487243327Sgrehan "[0001]\t\tEncoded Access Width : 00 [Undefined/Legacy]\n"); 488243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n"); 489243327Sgrehan EFPRINTF(fp, "\n"); 490243327Sgrehan 491243327Sgrehan /* Valid for bhyve */ 492243327Sgrehan EFPRINTF(fp, 493243327Sgrehan "[0012]\t\tPM Timer Block : [Generic Address Structure]\n"); 494243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 495272838Sneel EFPRINTF(fp, "[0001]\t\tBit Width : 20\n"); 496243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 497243327Sgrehan EFPRINTF(fp, 498243327Sgrehan "[0001]\t\tEncoded Access Width : 03 [DWord Access:32]\n"); 499243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 00000000%08X\n", 500259998Sjhb IO_PMTMR); 501243327Sgrehan EFPRINTF(fp, "\n"); 502243327Sgrehan 503243327Sgrehan EFPRINTF(fp, "[0012]\t\tGPE0 Block : [Generic Address Structure]\n"); 504243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 505272838Sneel EFPRINTF(fp, "[0001]\t\tBit Width : 00\n"); 506243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 507243327Sgrehan EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 01 [Byte Access:8]\n"); 508243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n"); 509243327Sgrehan EFPRINTF(fp, "\n"); 510243327Sgrehan 511243327Sgrehan EFPRINTF(fp, "[0012]\t\tGPE1 Block : [Generic Address Structure]\n"); 512243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 513243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 00\n"); 514243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 515243327Sgrehan EFPRINTF(fp, 516243327Sgrehan "[0001]\t\tEncoded Access Width : 00 [Undefined/Legacy]\n"); 517243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n"); 518243327Sgrehan EFPRINTF(fp, "\n"); 519243327Sgrehan 520243327Sgrehan EFPRINTF(fp, 521243327Sgrehan "[0012]\t\tSleep Control Register : [Generic Address Structure]\n"); 522243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 523243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 08\n"); 524243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 525243327Sgrehan EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 01 [Byte Access:8]\n"); 526243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n"); 527243327Sgrehan EFPRINTF(fp, "\n"); 528243327Sgrehan 529243327Sgrehan EFPRINTF(fp, 530243327Sgrehan "[0012]\t\tSleep Status Register : [Generic Address Structure]\n"); 531243327Sgrehan EFPRINTF(fp, "[0001]\t\tSpace ID : 01 [SystemIO]\n"); 532243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Width : 08\n"); 533243327Sgrehan EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 534243327Sgrehan EFPRINTF(fp, "[0001]\t\tEncoded Access Width : 01 [Byte Access:8]\n"); 535243327Sgrehan EFPRINTF(fp, "[0008]\t\tAddress : 0000000000000000\n"); 536243327Sgrehan 537243327Sgrehan EFFLUSH(fp); 538243327Sgrehan 539243327Sgrehan return (0); 540243327Sgrehan 541243327Sgrehanerr_exit: 542243327Sgrehan return (errno); 543243327Sgrehan} 544243327Sgrehan 545243327Sgrehanstatic int 546258579Sneelbasl_fwrite_hpet(FILE *fp) 547258579Sneel{ 548258579Sneel int err; 549258579Sneel 550258579Sneel err = 0; 551258579Sneel 552258579Sneel EFPRINTF(fp, "/*\n"); 553258579Sneel EFPRINTF(fp, " * bhyve HPET template\n"); 554258579Sneel EFPRINTF(fp, " */\n"); 555258579Sneel EFPRINTF(fp, "[0004]\t\tSignature : \"HPET\"\n"); 556258579Sneel EFPRINTF(fp, "[0004]\t\tTable Length : 00000000\n"); 557258579Sneel EFPRINTF(fp, "[0001]\t\tRevision : 01\n"); 558258579Sneel EFPRINTF(fp, "[0001]\t\tChecksum : 00\n"); 559258579Sneel EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n"); 560258579Sneel EFPRINTF(fp, "[0008]\t\tOem Table ID : \"BVHPET \"\n"); 561258579Sneel EFPRINTF(fp, "[0004]\t\tOem Revision : 00000001\n"); 562258579Sneel 563258579Sneel /* iasl will fill in the compiler ID/revision fields */ 564258579Sneel EFPRINTF(fp, "[0004]\t\tAsl Compiler ID : \"xxxx\"\n"); 565258579Sneel EFPRINTF(fp, "[0004]\t\tAsl Compiler Revision : 00000000\n"); 566258579Sneel EFPRINTF(fp, "\n"); 567258579Sneel 568258579Sneel EFPRINTF(fp, "[0004]\t\tTimer Block ID : %08X\n", hpet_capabilities); 569258579Sneel EFPRINTF(fp, 570258579Sneel "[0012]\t\tTimer Block Register : [Generic Address Structure]\n"); 571258579Sneel EFPRINTF(fp, "[0001]\t\tSpace ID : 00 [SystemMemory]\n"); 572258579Sneel EFPRINTF(fp, "[0001]\t\tBit Width : 00\n"); 573258579Sneel EFPRINTF(fp, "[0001]\t\tBit Offset : 00\n"); 574258579Sneel EFPRINTF(fp, 575258579Sneel "[0001]\t\tEncoded Access Width : 00 [Undefined/Legacy]\n"); 576258579Sneel EFPRINTF(fp, "[0008]\t\tAddress : 00000000FED00000\n"); 577258579Sneel EFPRINTF(fp, "\n"); 578258579Sneel 579258579Sneel EFPRINTF(fp, "[0001]\t\tHPET Number : 00\n"); 580258579Sneel EFPRINTF(fp, "[0002]\t\tMinimum Clock Ticks : 0000\n"); 581258579Sneel EFPRINTF(fp, "[0004]\t\tFlags (decoded below) : 00000001\n"); 582258579Sneel EFPRINTF(fp, "\t\t\t4K Page Protect : 1\n"); 583258579Sneel EFPRINTF(fp, "\t\t\t64K Page Protect : 0\n"); 584258579Sneel EFPRINTF(fp, "\n"); 585258579Sneel 586258579Sneel EFFLUSH(fp); 587258579Sneel 588258579Sneel return (0); 589258579Sneel 590258579Sneelerr_exit: 591258579Sneel return (errno); 592258579Sneel} 593258579Sneel 594258579Sneelstatic int 595269700Sneelbasl_fwrite_mcfg(FILE *fp) 596269700Sneel{ 597269700Sneel int err = 0; 598269700Sneel 599269700Sneel EFPRINTF(fp, "/*\n"); 600269700Sneel EFPRINTF(fp, " * bhyve MCFG template\n"); 601269700Sneel EFPRINTF(fp, " */\n"); 602269700Sneel EFPRINTF(fp, "[0004]\t\tSignature : \"MCFG\"\n"); 603269700Sneel EFPRINTF(fp, "[0004]\t\tTable Length : 00000000\n"); 604269700Sneel EFPRINTF(fp, "[0001]\t\tRevision : 01\n"); 605269700Sneel EFPRINTF(fp, "[0001]\t\tChecksum : 00\n"); 606269700Sneel EFPRINTF(fp, "[0006]\t\tOem ID : \"BHYVE \"\n"); 607269700Sneel EFPRINTF(fp, "[0008]\t\tOem Table ID : \"BVMCFG \"\n"); 608269700Sneel EFPRINTF(fp, "[0004]\t\tOem Revision : 00000001\n"); 609269700Sneel 610269700Sneel /* iasl will fill in the compiler ID/revision fields */ 611269700Sneel EFPRINTF(fp, "[0004]\t\tAsl Compiler ID : \"xxxx\"\n"); 612269700Sneel EFPRINTF(fp, "[0004]\t\tAsl Compiler Revision : 00000000\n"); 613269700Sneel EFPRINTF(fp, "[0008]\t\tReserved : 0\n"); 614269700Sneel EFPRINTF(fp, "\n"); 615269700Sneel 616269700Sneel EFPRINTF(fp, "[0008]\t\tBase Address : %016lX\n", pci_ecfg_base()); 617269700Sneel EFPRINTF(fp, "[0002]\t\tSegment Group: 0000\n"); 618269700Sneel EFPRINTF(fp, "[0001]\t\tStart Bus: 00\n"); 619269700Sneel EFPRINTF(fp, "[0001]\t\tEnd Bus: FF\n"); 620269700Sneel EFPRINTF(fp, "[0004]\t\tReserved : 0\n"); 621269700Sneel EFFLUSH(fp); 622269700Sneel return (0); 623269700Sneelerr_exit: 624269700Sneel return (errno); 625269700Sneel} 626269700Sneel 627269700Sneelstatic int 628243327Sgrehanbasl_fwrite_facs(FILE *fp) 629243327Sgrehan{ 630243327Sgrehan int err; 631243327Sgrehan 632243327Sgrehan err = 0; 633243327Sgrehan 634243327Sgrehan EFPRINTF(fp, "/*\n"); 635243327Sgrehan EFPRINTF(fp, " * bhyve FACS template\n"); 636243327Sgrehan EFPRINTF(fp, " */\n"); 637243327Sgrehan EFPRINTF(fp, "[0004]\t\tSignature : \"FACS\"\n"); 638243327Sgrehan EFPRINTF(fp, "[0004]\t\tLength : 00000040\n"); 639243327Sgrehan EFPRINTF(fp, "[0004]\t\tHardware Signature : 00000000\n"); 640243327Sgrehan EFPRINTF(fp, "[0004]\t\t32 Firmware Waking Vector : 00000000\n"); 641243327Sgrehan EFPRINTF(fp, "[0004]\t\tGlobal Lock : 00000000\n"); 642243327Sgrehan EFPRINTF(fp, "[0004]\t\tFlags (decoded below) : 00000000\n"); 643243327Sgrehan EFPRINTF(fp, "\t\t\tS4BIOS Support Present : 0\n"); 644243327Sgrehan EFPRINTF(fp, "\t\t\t64-bit Wake Supported (V2) : 0\n"); 645243327Sgrehan EFPRINTF(fp, 646243327Sgrehan "[0008]\t\t64 Firmware Waking Vector : 0000000000000000\n"); 647243327Sgrehan EFPRINTF(fp, "[0001]\t\tVersion : 02\n"); 648243327Sgrehan EFPRINTF(fp, "[0003]\t\tReserved : 000000\n"); 649243327Sgrehan EFPRINTF(fp, "[0004]\t\tOspmFlags (decoded below) : 00000000\n"); 650243327Sgrehan EFPRINTF(fp, "\t\t\t64-bit Wake Env Required (V2) : 0\n"); 651243327Sgrehan 652243327Sgrehan EFFLUSH(fp); 653243327Sgrehan 654243327Sgrehan return (0); 655243327Sgrehan 656243327Sgrehanerr_exit: 657243327Sgrehan return (errno); 658243327Sgrehan} 659243327Sgrehan 660260206Sjhb/* 661260206Sjhb * Helper routines for writing to the DSDT from other modules. 662260206Sjhb */ 663260206Sjhbvoid 664260206Sjhbdsdt_line(const char *fmt, ...) 665260206Sjhb{ 666260206Sjhb va_list ap; 667260206Sjhb int err; 668260206Sjhb 669260206Sjhb if (dsdt_error != 0) 670260206Sjhb return; 671260206Sjhb 672260206Sjhb if (strcmp(fmt, "") != 0) { 673260206Sjhb if (dsdt_indent_level != 0) 674260206Sjhb EFPRINTF(dsdt_fp, "%*c", dsdt_indent_level * 2, ' '); 675260206Sjhb va_start(ap, fmt); 676260206Sjhb if (vfprintf(dsdt_fp, fmt, ap) < 0) 677260206Sjhb goto err_exit; 678260206Sjhb va_end(ap); 679260206Sjhb } 680260206Sjhb EFPRINTF(dsdt_fp, "\n"); 681260206Sjhb return; 682260206Sjhb 683260206Sjhberr_exit: 684260206Sjhb dsdt_error = errno; 685260206Sjhb} 686260206Sjhb 687260206Sjhbvoid 688260206Sjhbdsdt_indent(int levels) 689260206Sjhb{ 690260206Sjhb 691260206Sjhb dsdt_indent_level += levels; 692260206Sjhb assert(dsdt_indent_level >= 0); 693260206Sjhb} 694260206Sjhb 695260206Sjhbvoid 696260206Sjhbdsdt_unindent(int levels) 697260206Sjhb{ 698260206Sjhb 699260206Sjhb assert(dsdt_indent_level >= levels); 700260206Sjhb dsdt_indent_level -= levels; 701260206Sjhb} 702260206Sjhb 703260206Sjhbvoid 704260206Sjhbdsdt_fixed_ioport(uint16_t iobase, uint16_t length) 705260206Sjhb{ 706260206Sjhb 707260206Sjhb dsdt_line("IO (Decode16,"); 708260206Sjhb dsdt_line(" 0x%04X, // Range Minimum", iobase); 709260206Sjhb dsdt_line(" 0x%04X, // Range Maximum", iobase); 710260206Sjhb dsdt_line(" 0x01, // Alignment"); 711260206Sjhb dsdt_line(" 0x%02X, // Length", length); 712260206Sjhb dsdt_line(" )"); 713260206Sjhb} 714260206Sjhb 715260206Sjhbvoid 716260206Sjhbdsdt_fixed_irq(uint8_t irq) 717260206Sjhb{ 718260206Sjhb 719260206Sjhb dsdt_line("IRQNoFlags ()"); 720260206Sjhb dsdt_line(" {%d}", irq); 721260206Sjhb} 722260206Sjhb 723260206Sjhbvoid 724260206Sjhbdsdt_fixed_mem32(uint32_t base, uint32_t length) 725260206Sjhb{ 726260206Sjhb 727260206Sjhb dsdt_line("Memory32Fixed (ReadWrite,"); 728260206Sjhb dsdt_line(" 0x%08X, // Address Base", base); 729260206Sjhb dsdt_line(" 0x%08X, // Address Length", length); 730260206Sjhb dsdt_line(" )"); 731260206Sjhb} 732260206Sjhb 733243327Sgrehanstatic int 734243327Sgrehanbasl_fwrite_dsdt(FILE *fp) 735243327Sgrehan{ 736243327Sgrehan int err; 737243327Sgrehan 738243327Sgrehan err = 0; 739260206Sjhb dsdt_fp = fp; 740260206Sjhb dsdt_error = 0; 741260206Sjhb dsdt_indent_level = 0; 742243327Sgrehan 743260206Sjhb dsdt_line("/*"); 744260206Sjhb dsdt_line(" * bhyve DSDT template"); 745260206Sjhb dsdt_line(" */"); 746260206Sjhb dsdt_line("DefinitionBlock (\"bhyve_dsdt.aml\", \"DSDT\", 2," 747260206Sjhb "\"BHYVE \", \"BVDSDT \", 0x00000001)"); 748260206Sjhb dsdt_line("{"); 749266125Sjhb dsdt_line(" Name (_S5, Package ()"); 750260206Sjhb dsdt_line(" {"); 751260206Sjhb dsdt_line(" 0x05,"); 752260206Sjhb dsdt_line(" Zero,"); 753260206Sjhb dsdt_line(" })"); 754258579Sneel 755260206Sjhb pci_write_dsdt(); 756258579Sneel 757260206Sjhb dsdt_line(""); 758261904Sneel dsdt_line(" Scope (_SB.PC00)"); 759260206Sjhb dsdt_line(" {"); 760260206Sjhb dsdt_line(" Device (HPET)"); 761260206Sjhb dsdt_line(" {"); 762260206Sjhb dsdt_line(" Name (_HID, EISAID(\"PNP0103\"))"); 763260206Sjhb dsdt_line(" Name (_UID, 0)"); 764260206Sjhb dsdt_line(" Name (_CRS, ResourceTemplate ()"); 765260206Sjhb dsdt_line(" {"); 766260206Sjhb dsdt_indent(4); 767260206Sjhb dsdt_fixed_mem32(0xFED00000, 0x400); 768260206Sjhb dsdt_unindent(4); 769260206Sjhb dsdt_line(" })"); 770260206Sjhb dsdt_line(" }"); 771260206Sjhb dsdt_line(" }"); 772260206Sjhb dsdt_line("}"); 773243327Sgrehan 774260206Sjhb if (dsdt_error != 0) 775260206Sjhb return (dsdt_error); 776260206Sjhb 777243327Sgrehan EFFLUSH(fp); 778243327Sgrehan 779243327Sgrehan return (0); 780243327Sgrehan 781243327Sgrehanerr_exit: 782243327Sgrehan return (errno); 783243327Sgrehan} 784243327Sgrehan 785243327Sgrehanstatic int 786243327Sgrehanbasl_open(struct basl_fio *bf, int suffix) 787243327Sgrehan{ 788243327Sgrehan int err; 789243327Sgrehan 790243327Sgrehan err = 0; 791243327Sgrehan 792243327Sgrehan if (suffix) { 793287927Sdelphij strlcpy(bf->f_name, basl_stemplate, MAXPATHLEN); 794243327Sgrehan bf->fd = mkstemps(bf->f_name, strlen(BHYVE_ASL_SUFFIX)); 795243327Sgrehan } else { 796287927Sdelphij strlcpy(bf->f_name, basl_template, MAXPATHLEN); 797243327Sgrehan bf->fd = mkstemp(bf->f_name); 798243327Sgrehan } 799243327Sgrehan 800243327Sgrehan if (bf->fd > 0) { 801243327Sgrehan bf->fp = fdopen(bf->fd, "w+"); 802243327Sgrehan if (bf->fp == NULL) { 803243327Sgrehan unlink(bf->f_name); 804243327Sgrehan close(bf->fd); 805243327Sgrehan } 806243327Sgrehan } else { 807243327Sgrehan err = 1; 808243327Sgrehan } 809243327Sgrehan 810243327Sgrehan return (err); 811243327Sgrehan} 812243327Sgrehan 813243327Sgrehanstatic void 814243327Sgrehanbasl_close(struct basl_fio *bf) 815243327Sgrehan{ 816243327Sgrehan 817243327Sgrehan if (!basl_keep_temps) 818243327Sgrehan unlink(bf->f_name); 819243327Sgrehan fclose(bf->fp); 820243327Sgrehan} 821243327Sgrehan 822243327Sgrehanstatic int 823243327Sgrehanbasl_start(struct basl_fio *in, struct basl_fio *out) 824243327Sgrehan{ 825243327Sgrehan int err; 826243327Sgrehan 827243327Sgrehan err = basl_open(in, 0); 828243327Sgrehan if (!err) { 829243327Sgrehan err = basl_open(out, 1); 830243327Sgrehan if (err) { 831243327Sgrehan basl_close(in); 832243327Sgrehan } 833243327Sgrehan } 834243327Sgrehan 835243327Sgrehan return (err); 836243327Sgrehan} 837243327Sgrehan 838243327Sgrehanstatic void 839243327Sgrehanbasl_end(struct basl_fio *in, struct basl_fio *out) 840243327Sgrehan{ 841243327Sgrehan 842243327Sgrehan basl_close(in); 843243327Sgrehan basl_close(out); 844243327Sgrehan} 845243327Sgrehan 846243327Sgrehanstatic int 847248477Sneelbasl_load(struct vmctx *ctx, int fd, uint64_t off) 848243327Sgrehan{ 849248477Sneel struct stat sb; 850247523Sneel void *gaddr; 851243327Sgrehan 852248477Sneel if (fstat(fd, &sb) < 0) 853248477Sneel return (errno); 854248477Sneel 855248477Sneel gaddr = paddr_guest2host(ctx, basl_acpi_base + off, sb.st_size); 856248477Sneel if (gaddr == NULL) 857248477Sneel return (EFAULT); 858243327Sgrehan 859248477Sneel if (read(fd, gaddr, sb.st_size) < 0) 860248477Sneel return (errno); 861248477Sneel 862248477Sneel return (0); 863243327Sgrehan} 864243327Sgrehan 865243327Sgrehanstatic int 866248477Sneelbasl_compile(struct vmctx *ctx, int (*fwrite_section)(FILE *), uint64_t offset) 867243327Sgrehan{ 868243327Sgrehan struct basl_fio io[2]; 869243327Sgrehan static char iaslbuf[3*MAXPATHLEN + 10]; 870243327Sgrehan char *fmt; 871243327Sgrehan int err; 872243327Sgrehan 873243327Sgrehan err = basl_start(&io[0], &io[1]); 874243327Sgrehan if (!err) { 875243327Sgrehan err = (*fwrite_section)(io[0].fp); 876243327Sgrehan 877243327Sgrehan if (!err) { 878243327Sgrehan /* 879243327Sgrehan * iasl sends the results of the compilation to 880243327Sgrehan * stdout. Shut this down by using the shell to 881243327Sgrehan * redirect stdout to /dev/null, unless the user 882243327Sgrehan * has requested verbose output for debugging 883243327Sgrehan * purposes 884243327Sgrehan */ 885243327Sgrehan fmt = basl_verbose_iasl ? 886243327Sgrehan "%s -p %s %s" : 887243327Sgrehan "/bin/sh -c \"%s -p %s %s\" 1> /dev/null"; 888243327Sgrehan 889243327Sgrehan snprintf(iaslbuf, sizeof(iaslbuf), 890243327Sgrehan fmt, 891243327Sgrehan BHYVE_ASL_COMPILER, 892243327Sgrehan io[1].f_name, io[0].f_name); 893243327Sgrehan err = system(iaslbuf); 894243327Sgrehan 895243327Sgrehan if (!err) { 896243327Sgrehan /* 897243327Sgrehan * Copy the aml output file into guest 898243327Sgrehan * memory at the specified location 899243327Sgrehan */ 900248477Sneel err = basl_load(ctx, io[1].fd, offset); 901243327Sgrehan } 902243327Sgrehan } 903243327Sgrehan basl_end(&io[0], &io[1]); 904243327Sgrehan } 905243327Sgrehan 906243327Sgrehan return (err); 907243327Sgrehan} 908243327Sgrehan 909243327Sgrehanstatic int 910243327Sgrehanbasl_make_templates(void) 911243327Sgrehan{ 912243327Sgrehan const char *tmpdir; 913243327Sgrehan int err; 914243327Sgrehan int len; 915243327Sgrehan 916243327Sgrehan err = 0; 917243327Sgrehan 918243327Sgrehan /* 919243327Sgrehan * 920243327Sgrehan */ 921243327Sgrehan if ((tmpdir = getenv("BHYVE_TMPDIR")) == NULL || *tmpdir == '\0' || 922243327Sgrehan (tmpdir = getenv("TMPDIR")) == NULL || *tmpdir == '\0') { 923243327Sgrehan tmpdir = _PATH_TMP; 924243327Sgrehan } 925243327Sgrehan 926243327Sgrehan len = strlen(tmpdir); 927243327Sgrehan 928243327Sgrehan if ((len + sizeof(BHYVE_ASL_TEMPLATE) + 1) < MAXPATHLEN) { 929243327Sgrehan strcpy(basl_template, tmpdir); 930243327Sgrehan while (len > 0 && basl_template[len - 1] == '/') 931243327Sgrehan len--; 932243327Sgrehan basl_template[len] = '/'; 933243327Sgrehan strcpy(&basl_template[len + 1], BHYVE_ASL_TEMPLATE); 934243327Sgrehan } else 935243327Sgrehan err = E2BIG; 936243327Sgrehan 937243327Sgrehan if (!err) { 938243327Sgrehan /* 939243327Sgrehan * len has been intialized (and maybe adjusted) above 940243327Sgrehan */ 941243327Sgrehan if ((len + sizeof(BHYVE_ASL_TEMPLATE) + 1 + 942243327Sgrehan sizeof(BHYVE_ASL_SUFFIX)) < MAXPATHLEN) { 943243327Sgrehan strcpy(basl_stemplate, tmpdir); 944243327Sgrehan basl_stemplate[len] = '/'; 945243327Sgrehan strcpy(&basl_stemplate[len + 1], BHYVE_ASL_TEMPLATE); 946243327Sgrehan len = strlen(basl_stemplate); 947243327Sgrehan strcpy(&basl_stemplate[len], BHYVE_ASL_SUFFIX); 948243327Sgrehan } else 949243327Sgrehan err = E2BIG; 950243327Sgrehan } 951243327Sgrehan 952243327Sgrehan return (err); 953243327Sgrehan} 954243327Sgrehan 955243327Sgrehanstatic struct { 956243327Sgrehan int (*wsect)(FILE *fp); 957243327Sgrehan uint64_t offset; 958243327Sgrehan} basl_ftables[] = 959243327Sgrehan{ 960243327Sgrehan { basl_fwrite_rsdp, 0}, 961243327Sgrehan { basl_fwrite_rsdt, RSDT_OFFSET }, 962243704Sgrehan { basl_fwrite_xsdt, XSDT_OFFSET }, 963243327Sgrehan { basl_fwrite_madt, MADT_OFFSET }, 964243327Sgrehan { basl_fwrite_fadt, FADT_OFFSET }, 965258579Sneel { basl_fwrite_hpet, HPET_OFFSET }, 966269700Sneel { basl_fwrite_mcfg, MCFG_OFFSET }, 967243327Sgrehan { basl_fwrite_facs, FACS_OFFSET }, 968243327Sgrehan { basl_fwrite_dsdt, DSDT_OFFSET }, 969243327Sgrehan { NULL } 970243327Sgrehan}; 971243327Sgrehan 972243327Sgrehanint 973257423Sneelacpi_build(struct vmctx *ctx, int ncpu) 974243327Sgrehan{ 975243327Sgrehan int err; 976243327Sgrehan int i; 977243327Sgrehan 978243327Sgrehan basl_ncpu = ncpu; 979243327Sgrehan 980258579Sneel err = vm_get_hpet_capabilities(ctx, &hpet_capabilities); 981258579Sneel if (err != 0) 982258579Sneel return (err); 983258579Sneel 984243327Sgrehan /* 985243327Sgrehan * For debug, allow the user to have iasl compiler output sent 986243327Sgrehan * to stdout rather than /dev/null 987243327Sgrehan */ 988243327Sgrehan if (getenv("BHYVE_ACPI_VERBOSE_IASL")) 989243327Sgrehan basl_verbose_iasl = 1; 990243327Sgrehan 991243327Sgrehan /* 992243327Sgrehan * Allow the user to keep the generated ASL files for debugging 993243327Sgrehan * instead of deleting them following use 994243327Sgrehan */ 995243327Sgrehan if (getenv("BHYVE_ACPI_KEEPTMPS")) 996243327Sgrehan basl_keep_temps = 1; 997243327Sgrehan 998243327Sgrehan i = 0; 999243327Sgrehan err = basl_make_templates(); 1000243327Sgrehan 1001243327Sgrehan /* 1002243327Sgrehan * Run through all the ASL files, compiling them and 1003243327Sgrehan * copying them into guest memory 1004243327Sgrehan */ 1005243327Sgrehan while (!err && basl_ftables[i].wsect != NULL) { 1006248477Sneel err = basl_compile(ctx, basl_ftables[i].wsect, 1007243327Sgrehan basl_ftables[i].offset); 1008243327Sgrehan i++; 1009243327Sgrehan } 1010243327Sgrehan 1011243327Sgrehan return (err); 1012243327Sgrehan} 1013